Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 42 additions & 18 deletions packages/pi/src/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ function sanitize(text: string): string {
return text.replace(/[\uD800-\uDFFF]/g, '\uFFFD')
}

function sanitizeToolId(id: string): string {
if (!id) return 'tool_call_unknown'
const sanitized = id.replace(/[^a-zA-Z0-9_-]/g, '_')
if (!sanitized) return 'tool_call_unknown'
return sanitized.slice(0, 256)
}

function toClaudeCodeToolName(name: string): string {
return CLAUDE_CODE_TOOLS.get(name.toLowerCase()) ?? name
}
Expand All @@ -70,19 +77,22 @@ function convertTextAndImages(
.join('\n')
}

const blocks = content.map((item) => {
if (item.type === 'text') {
return { type: 'text', text: sanitize(item.text) }
}
return {
type: 'image',
source: {
type: 'base64',
media_type: item.mimeType,
data: item.data,
},
}
})
const blocks = content
.map((item) => {
if (item.type === 'text') {
return { type: 'text', text: sanitize(item.text) }
}
if (!item.data) return null
return {
type: 'image',
source: {
type: 'base64',
media_type: item.mimeType,
data: item.data,
},
}
})
.filter((block): block is NonNullable<typeof block> => block !== null)

if (!blocks.some((block) => block.type === 'text')) {
blocks.unshift({ type: 'text', text: '(see attached image)' })
Expand Down Expand Up @@ -134,7 +144,7 @@ function convertMessages(
} else if (block.type === 'toolCall') {
blocks.push({
type: 'tool_use',
id: block.id,
id: sanitizeToolId(block.id),
name: toClaudeCodeToolName(block.name),
input: block.arguments,
})
Expand All @@ -147,10 +157,17 @@ function convertMessages(
if (message.role === 'toolResult') {
const toolResult = message as ToolResultMessage
const toolResults: Array<Record<string, unknown>> = []
const firstContent = convertTextAndImages(toolResult.content)
const firstContentArr = Array.isArray(firstContent)
? firstContent
: [{ type: 'text', text: firstContent }]
if (toolResult.isError && firstContentArr.length === 0) {
firstContentArr.push({ type: 'text', text: 'Error' })
}
toolResults.push({
type: 'tool_result',
tool_use_id: toolResult.toolCallId,
content: convertTextAndImages(toolResult.content),
tool_use_id: sanitizeToolId(toolResult.toolCallId),
content: firstContentArr,
is_error: toolResult.isError,
})

Expand All @@ -160,10 +177,17 @@ function convertMessages(
messages[nextIndex]?.role === 'toolResult'
) {
const next = messages[nextIndex] as ToolResultMessage
const nextContent = convertTextAndImages(next.content)
const nextContentArr = Array.isArray(nextContent)
? nextContent
: [{ type: 'text', text: nextContent }]
if (next.isError && nextContentArr.length === 0) {
nextContentArr.push({ type: 'text', text: 'Error' })
}
toolResults.push({
type: 'tool_result',
tool_use_id: next.toolCallId,
content: convertTextAndImages(next.content),
tool_use_id: sanitizeToolId(next.toolCallId),
content: nextContentArr,
is_error: next.isError,
})
nextIndex += 1
Expand Down