From eeb37cebe961b4fce344d50f2bfa4e0e9f08b88a Mon Sep 17 00:00:00 2001 From: Max-shipper <257223904+Max-shipper@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:26:42 -0500 Subject: [PATCH] fix: handle array content, add model aliases, increase subprocess timeout Co-Authored-By: Claude Sonnet 4.6 --- src/adapter/openai-to-cli.ts | 35 ++++++++++++++++++++++++++++++----- src/subprocess/manager.ts | 4 +++- src/types/openai.ts | 7 ++++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/adapter/openai-to-cli.ts b/src/adapter/openai-to-cli.ts index c8ecaa1..4b4e770 100644 --- a/src/adapter/openai-to-cli.ts +++ b/src/adapter/openai-to-cli.ts @@ -2,9 +2,9 @@ * Converts OpenAI chat request format to Claude CLI input */ -import type { OpenAIChatRequest } from "../types/openai.js"; +import type { OpenAIChatRequest, OpenAIContentBlock } from "../types/openai.js"; -export type ClaudeModel = "opus" | "sonnet" | "haiku"; +export type ClaudeModel = "opus" | "sonnet" | "haiku" | "claude-sonnet-4-6"; export interface CliInput { prompt: string; @@ -15,11 +15,15 @@ export interface CliInput { const MODEL_MAP: Record = { // Direct model names "claude-opus-4": "opus", + "claude-opus-4-6": "opus", "claude-sonnet-4": "sonnet", + "claude-sonnet-4-6": "claude-sonnet-4-6", "claude-haiku-4": "haiku", // With provider prefix "claude-code-cli/claude-opus-4": "opus", + "claude-code-cli/claude-opus-4-6": "opus", "claude-code-cli/claude-sonnet-4": "sonnet", + "claude-code-cli/claude-sonnet-4-6": "claude-sonnet-4-6", "claude-code-cli/claude-haiku-4": "haiku", // Aliases "opus": "opus", @@ -27,6 +31,26 @@ const MODEL_MAP: Record = { "haiku": "haiku", }; +/** + * Extract text from OpenAI content field, which can be: + * - a plain string + * - an array of content blocks [{type: "text", text: "..."}, ...] + * - null/undefined + */ +function extractContentText(content: string | OpenAIContentBlock[] | null | undefined): string { + if (typeof content === "string") return content; + if (Array.isArray(content)) { + return content + .filter((b): b is OpenAIContentBlock & { type: "text"; text: string } => + b != null && typeof b === "object" && b.type === "text" && typeof b.text === "string" + ) + .map((b) => b.text) + .join("\n"); + } + if (content == null) return ""; + return String(content); +} + /** * Extract Claude model alias from request model string */ @@ -56,20 +80,21 @@ export function messagesToPrompt(messages: OpenAIChatRequest["messages"]): strin const parts: string[] = []; for (const msg of messages) { + const text = extractContentText(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/subprocess/manager.ts b/src/subprocess/manager.ts index 6551a81..de30315 100644 --- a/src/subprocess/manager.ts +++ b/src/subprocess/manager.ts @@ -34,7 +34,9 @@ export interface SubprocessEvents { raw: (line: string) => void; } -const DEFAULT_TIMEOUT = 300000; // 5 minutes +// 15 minutes — agentic/research tasks with multiple tool calls (web search, +// multi-step reasoning) routinely exceed 5 minutes; a short timeout kills them mid-run. +const DEFAULT_TIMEOUT = 900000; export class ClaudeSubprocess extends EventEmitter { private process: ChildProcess | null = null; diff --git a/src/types/openai.ts b/src/types/openai.ts index c116658..0921a63 100644 --- a/src/types/openai.ts +++ b/src/types/openai.ts @@ -3,9 +3,14 @@ * Used for Clawdbot integration */ +export interface OpenAIContentBlock { + type: string; + text?: string; +} + export interface OpenAIChatMessage { role: "system" | "user" | "assistant"; - content: string; + content: string | OpenAIContentBlock[] | null; } export interface OpenAIChatRequest {