diff --git a/src/adapter/openai-to-cli.ts b/src/adapter/openai-to-cli.ts
index c8ecaa1..41af8a3 100644
--- a/src/adapter/openai-to-cli.ts
+++ b/src/adapter/openai-to-cli.ts
@@ -2,7 +2,10 @@
* Converts OpenAI chat request format to Claude CLI input
*/
-import type { OpenAIChatRequest } from "../types/openai.js";
+import type {
+ OpenAIChatRequest,
+ OpenAIContentPart,
+} from "../types/openai.js";
export type ClaudeModel = "opus" | "sonnet" | "haiku";
@@ -46,6 +49,32 @@ export function extractModel(model: string): ClaudeModel {
return "opus";
}
+/**
+ * Extract text from message content.
+ *
+ * OpenAI API allows content to be either a plain string or an array of
+ * content parts (e.g. [{type: "text", text: "..."}]). This function
+ * normalises both forms into a single string.
+ */
+export function extractContent(
+ content: string | OpenAIContentPart[],
+): string {
+ if (typeof content === "string") return content;
+
+ if (Array.isArray(content)) {
+ return content
+ .map((part) => {
+ if (typeof part === "string") return part;
+ if (part && typeof part === "object") return part.text ?? "";
+ return "";
+ })
+ .filter(Boolean)
+ .join("\n");
+ }
+
+ return String(content ?? "");
+}
+
/**
* Convert OpenAI messages array to a single prompt string for Claude CLI
*
@@ -56,20 +85,22 @@ export function messagesToPrompt(messages: OpenAIChatRequest["messages"]): strin
const parts: string[] = [];
for (const msg of messages) {
+ const text = extractContent(msg.content);
+
switch (msg.role) {
case "system":
// System messages become context instructions
- parts.push(`\n${msg.content}\n\n`);
+ parts.push(`\n${text}\n\n`);
break;
case "user":
// User messages are the main prompt
- parts.push(msg.content);
+ parts.push(text);
break;
case "assistant":
// Previous assistant responses for context
- parts.push(`\n${msg.content}\n\n`);
+ parts.push(`\n${text}\n\n`);
break;
}
}
diff --git a/src/types/openai.ts b/src/types/openai.ts
index c116658..706ef62 100644
--- a/src/types/openai.ts
+++ b/src/types/openai.ts
@@ -3,9 +3,19 @@
* Used for Clawdbot integration
*/
+/**
+ * A single content part in a multi-part message.
+ * See: https://platform.openai.com/docs/api-reference/chat/create#chat-create-messages
+ */
+export interface OpenAIContentPart {
+ type: "text" | "image_url";
+ text?: string;
+ image_url?: { url: string; detail?: string };
+}
+
export interface OpenAIChatMessage {
role: "system" | "user" | "assistant";
- content: string;
+ content: string | OpenAIContentPart[];
}
export interface OpenAIChatRequest {