@posthog/agent 2.3.216 → 2.3.256

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,6 +40,6 @@ declare function hydrateSessionJsonl(params: {
40
40
  permissionMode?: string;
41
41
  posthogAPI: PostHogAPIClient;
42
42
  log: HydrationLog;
43
- }): Promise<void>;
43
+ }): Promise<boolean>;
44
44
 
45
45
  export { conversationTurnsToJsonlEntries, getSessionJsonlPath, hydrateSessionJsonl, rebuildConversation, selectRecentTurns };
@@ -386,18 +386,18 @@ async function hydrateSessionJsonl(params) {
386
386
  log.info("Local JSONL exists, skipping S3 hydration", {
387
387
  sessionId: params.sessionId
388
388
  });
389
- return;
389
+ return true;
390
390
  } catch {
391
391
  }
392
392
  const taskRun = await posthogAPI.getTaskRun(params.taskId, params.runId);
393
393
  if (!taskRun.log_url) {
394
394
  log.info("No log URL, skipping JSONL hydration");
395
- return;
395
+ return false;
396
396
  }
397
397
  const entries = await posthogAPI.fetchTaskRunLogs(taskRun);
398
398
  if (entries.length === 0) {
399
399
  log.info("No S3 log entries, skipping JSONL hydration");
400
- return;
400
+ return false;
401
401
  }
402
402
  const entryCounts = {};
403
403
  for (const entry of entries) {
@@ -414,7 +414,7 @@ async function hydrateSessionJsonl(params) {
414
414
  const allTurns = rebuildConversation(entries);
415
415
  if (allTurns.length === 0) {
416
416
  log.info("No conversation in S3 logs, skipping JSONL hydration");
417
- return;
417
+ return false;
418
418
  }
419
419
  const maxTokens = supports1MContext(params.model ?? "") ? LARGE_CONTEXT_MAX_TOKENS : DEFAULT_MAX_TOKENS;
420
420
  const conversation = selectRecentTurns(allTurns, maxTokens);
@@ -440,11 +440,13 @@ async function hydrateSessionJsonl(params) {
440
440
  turns: conversation.length,
441
441
  lines: jsonlLines.length
442
442
  });
443
+ return true;
443
444
  } catch (err) {
444
445
  log.warn("Failed to hydrate session JSONL, continuing", {
445
446
  sessionId: params.sessionId,
446
447
  error: err instanceof Error ? err.message : String(err)
447
448
  });
449
+ return false;
448
450
  }
449
451
  }
450
452
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/adapters/claude/session/jsonl-hydration.ts","../../../../src/adapters/claude/session/models.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ContentBlock } from \"@agentclientprotocol/sdk\";\nimport type { PostHogAPIClient } from \"../../../posthog-api\";\nimport type { StoredEntry } from \"../../../types\";\nimport { supports1MContext } from \"./models\";\n\ninterface ConversationTurn {\n role: \"user\" | \"assistant\";\n content: ContentBlock[];\n toolCalls?: ToolCallInfo[];\n}\n\ninterface ToolCallInfo {\n toolCallId: string;\n toolName: string;\n input: unknown;\n result?: unknown;\n}\n\ninterface JsonlConfig {\n sessionId: string;\n cwd: string;\n model?: string;\n version?: string;\n gitBranch?: string;\n slug?: string;\n permissionMode?: string;\n}\n\ninterface ClaudeCodeMeta {\n toolCallId?: string;\n toolName?: string;\n toolInput?: unknown;\n toolResponse?: unknown;\n}\n\ninterface SessionUpdate {\n sessionUpdate: string;\n content?: ContentBlock | ContentBlock[];\n _meta?: { claudeCode?: ClaudeCodeMeta };\n}\n\nconst MAX_PROJECT_KEY_LENGTH = 200;\n\nfunction hashString(s: string): string {\n let hash = 0;\n for (let i = 0; i < s.length; i++) {\n hash = (hash << 5) - hash + s.charCodeAt(i);\n hash |= 0;\n }\n return Math.abs(hash).toString(36);\n}\n\nexport function getSessionJsonlPath(sessionId: string, cwd: string): string {\n const configDir =\n process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), \".claude\");\n let projectKey = cwd.replace(/[^a-zA-Z0-9]/g, \"-\");\n if (projectKey.length > MAX_PROJECT_KEY_LENGTH) {\n projectKey = `${projectKey.slice(0, MAX_PROJECT_KEY_LENGTH)}-${hashString(cwd)}`;\n }\n return path.join(configDir, \"projects\", projectKey, `${sessionId}.jsonl`);\n}\n\nexport function rebuildConversation(\n entries: StoredEntry[],\n): ConversationTurn[] {\n const turns: ConversationTurn[] = [];\n let currentAssistantContent: ContentBlock[] = [];\n let currentToolCalls: ToolCallInfo[] = [];\n\n for (const entry of entries) {\n const method = entry.notification?.method;\n const params = entry.notification?.params as Record<string, unknown>;\n\n if (method === \"session/update\" && params?.update) {\n const update = params.update as SessionUpdate;\n\n switch (update.sessionUpdate) {\n case \"user_message\":\n case \"user_message_chunk\": {\n if (\n currentAssistantContent.length > 0 ||\n currentToolCalls.length > 0\n ) {\n turns.push({\n role: \"assistant\",\n content: currentAssistantContent,\n toolCalls:\n currentToolCalls.length > 0 ? currentToolCalls : undefined,\n });\n currentAssistantContent = [];\n currentToolCalls = [];\n }\n\n const content = update.content;\n const contentArray = Array.isArray(content)\n ? content\n : content\n ? [content]\n : [];\n\n const lastTurn = turns[turns.length - 1];\n if (lastTurn?.role === \"user\") {\n lastTurn.content.push(...contentArray);\n } else {\n turns.push({ role: \"user\", content: contentArray });\n }\n break;\n }\n\n case \"agent_message\":\n case \"agent_message_chunk\":\n case \"agent_thought_chunk\": {\n const content = update.content;\n if (content && !Array.isArray(content)) {\n if (\n content.type === \"text\" &&\n currentAssistantContent.length > 0 &&\n currentAssistantContent[currentAssistantContent.length - 1]\n .type === \"text\"\n ) {\n const lastBlock = currentAssistantContent[\n currentAssistantContent.length - 1\n ] as { type: \"text\"; text: string };\n lastBlock.text += (\n content as { type: \"text\"; text: string }\n ).text;\n } else {\n currentAssistantContent.push(content);\n }\n }\n break;\n }\n\n case \"tool_call\":\n case \"tool_call_update\": {\n const meta = update._meta?.claudeCode;\n if (meta) {\n const { toolCallId, toolName, toolInput, toolResponse } = meta;\n\n if (toolCallId && toolName) {\n let toolCall = currentToolCalls.find(\n (tc) => tc.toolCallId === toolCallId,\n );\n if (!toolCall) {\n toolCall = { toolCallId, toolName, input: toolInput };\n currentToolCalls.push(toolCall);\n }\n if (toolResponse !== undefined) {\n toolCall.result = toolResponse;\n }\n }\n }\n break;\n }\n\n case \"tool_result\": {\n const meta = update._meta?.claudeCode;\n if (meta) {\n const { toolCallId, toolResponse } = meta;\n if (toolCallId) {\n const toolCall = currentToolCalls.find(\n (tc) => tc.toolCallId === toolCallId,\n );\n if (toolCall && toolResponse !== undefined) {\n toolCall.result = toolResponse;\n }\n }\n }\n break;\n }\n }\n }\n }\n\n if (currentAssistantContent.length > 0 || currentToolCalls.length > 0) {\n turns.push({\n role: \"assistant\",\n content: currentAssistantContent,\n toolCalls: currentToolCalls.length > 0 ? currentToolCalls : undefined,\n });\n }\n\n return turns;\n}\n\nconst CHARS_PER_TOKEN = 4;\nconst DEFAULT_MAX_TOKENS = 150_000;\nconst LARGE_CONTEXT_MAX_TOKENS = 800_000;\n\nfunction estimateTurnTokens(turn: ConversationTurn): number {\n let chars = 0;\n for (const block of turn.content) {\n if (\"text\" in block && typeof block.text === \"string\") {\n chars += block.text.length;\n }\n }\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n chars += JSON.stringify(tc.input ?? \"\").length;\n if (tc.result !== undefined) {\n chars +=\n typeof tc.result === \"string\"\n ? tc.result.length\n : JSON.stringify(tc.result).length;\n }\n }\n }\n return Math.ceil(chars / CHARS_PER_TOKEN);\n}\n\nexport function selectRecentTurns(\n turns: ConversationTurn[],\n maxTokens = DEFAULT_MAX_TOKENS,\n): ConversationTurn[] {\n let budget = maxTokens;\n let startIndex = turns.length;\n\n for (let i = turns.length - 1; i >= 0; i--) {\n const cost = estimateTurnTokens(turns[i]);\n if (cost > budget) break;\n budget -= cost;\n startIndex = i;\n }\n\n // Ensure we start on a user turn so the conversation is well-formed\n while (startIndex < turns.length && turns[startIndex].role !== \"user\") {\n startIndex++;\n }\n\n return turns.slice(startIndex);\n}\n\nconst BASE62 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\nfunction generateMessageId(): string {\n const bytes = new Uint8Array(24);\n crypto.getRandomValues(bytes);\n let id = \"msg_01\";\n for (const b of bytes) {\n id += BASE62[b % 62];\n }\n return id;\n}\n\nconst ADJECTIVES = [\n \"bright\",\n \"calm\",\n \"daring\",\n \"eager\",\n \"fair\",\n \"gentle\",\n \"happy\",\n \"keen\",\n \"lively\",\n \"merry\",\n \"noble\",\n \"polite\",\n \"quick\",\n \"sharp\",\n \"warm\",\n \"witty\",\n];\nconst VERBS = [\n \"blazing\",\n \"crafting\",\n \"dashing\",\n \"flowing\",\n \"gliding\",\n \"humming\",\n \"jumping\",\n \"linking\",\n \"melting\",\n \"nesting\",\n \"pacing\",\n \"roaming\",\n \"sailing\",\n \"turning\",\n \"waving\",\n \"zoning\",\n];\nconst NOUNS = [\n \"aurora\",\n \"breeze\",\n \"cedar\",\n \"delta\",\n \"ember\",\n \"frost\",\n \"grove\",\n \"haven\",\n \"inlet\",\n \"jewel\",\n \"knoll\",\n \"lotus\",\n \"maple\",\n \"nexus\",\n \"oasis\",\n \"prism\",\n];\n\nfunction generateSlug(): string {\n const pick = (arr: string[]) => arr[Math.floor(Math.random() * arr.length)];\n return `${pick(ADJECTIVES)}-${pick(VERBS)}-${pick(NOUNS)}`;\n}\n\nexport function conversationTurnsToJsonlEntries(\n turns: ConversationTurn[],\n config: JsonlConfig,\n): string[] {\n const lines: string[] = [];\n let parentUuid: string | null = null;\n const model = config.model ?? \"claude-opus-4-6\";\n const version = config.version ?? \"2.1.63\";\n const gitBranch = config.gitBranch ?? \"\";\n const slug = config.slug ?? generateSlug();\n const permissionMode = config.permissionMode ?? \"default\";\n const baseTime = Date.now() - turns.length * 3000;\n let turnIndex = 0;\n\n for (const turn of turns) {\n const timestamp = new Date(baseTime + turnIndex * 3000).toISOString();\n turnIndex++;\n if (turn.role === \"user\") {\n lines.push(\n JSON.stringify({\n type: \"queue-operation\",\n operation: \"enqueue\",\n timestamp,\n sessionId: config.sessionId,\n }),\n );\n lines.push(\n JSON.stringify({\n type: \"queue-operation\",\n operation: \"dequeue\",\n timestamp,\n sessionId: config.sessionId,\n }),\n );\n\n const uuid = randomUUID();\n const textParts = turn.content\n .filter(\n (block) =>\n \"text\" in block && typeof block.text === \"string\" && block.text,\n )\n .map((block) => (block as { text: string }).text);\n\n const userText = textParts.length > 0 ? textParts.join(\"\") : \" \";\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"user\",\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: userText }],\n },\n uuid,\n timestamp,\n permissionMode,\n }),\n );\n parentUuid = uuid;\n } else {\n const allBlocks: unknown[] = [];\n\n for (const block of turn.content) {\n const blockType = (block as { type: string }).type;\n if (blockType === \"thinking\" || blockType === \"text\") {\n allBlocks.push(block);\n }\n }\n\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n allBlocks.push({\n type: \"tool_use\",\n id: tc.toolCallId,\n name: tc.toolName,\n input: tc.input,\n });\n }\n }\n\n const msgId = generateMessageId();\n const hasToolUse = allBlocks.some(\n (b) => (b as { type: string }).type === \"tool_use\",\n );\n const lastStopReason = hasToolUse ? \"tool_use\" : \"end_turn\";\n\n for (let i = 0; i < allBlocks.length; i++) {\n const block = allBlocks[i];\n const isLast = i === allBlocks.length - 1;\n const uuid = randomUUID();\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"assistant\",\n message: {\n model,\n id: msgId,\n type: \"message\",\n role: \"assistant\",\n content: [block],\n stop_reason: isLast ? lastStopReason : null,\n stop_sequence: null,\n usage: {\n input_tokens: 0,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n output_tokens: 0,\n },\n },\n uuid,\n timestamp,\n }),\n );\n parentUuid = uuid;\n }\n\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n if (tc.result === undefined) continue;\n\n const uuid = randomUUID();\n const resultText =\n typeof tc.result === \"string\"\n ? tc.result\n : JSON.stringify(tc.result);\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"user\",\n message: {\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: tc.toolCallId,\n content: resultText,\n },\n ],\n },\n uuid,\n timestamp,\n }),\n );\n parentUuid = uuid;\n }\n }\n }\n }\n\n return lines;\n}\n\ninterface HydrationLog {\n info: (msg: string, data?: unknown) => void;\n warn: (msg: string, data?: unknown) => void;\n}\n\nexport async function hydrateSessionJsonl(params: {\n sessionId: string;\n cwd: string;\n taskId: string;\n runId: string;\n model?: string;\n gitBranch?: string;\n permissionMode?: string;\n posthogAPI: PostHogAPIClient;\n log: HydrationLog;\n}): Promise<void> {\n const { posthogAPI, log } = params;\n\n try {\n const jsonlPath = getSessionJsonlPath(params.sessionId, params.cwd);\n try {\n await fs.access(jsonlPath);\n log.info(\"Local JSONL exists, skipping S3 hydration\", {\n sessionId: params.sessionId,\n });\n return;\n } catch {\n // File doesn't exist, proceed with hydration\n }\n\n const taskRun = await posthogAPI.getTaskRun(params.taskId, params.runId);\n if (!taskRun.log_url) {\n log.info(\"No log URL, skipping JSONL hydration\");\n return;\n }\n\n const entries = await posthogAPI.fetchTaskRunLogs(taskRun);\n if (entries.length === 0) {\n log.info(\"No S3 log entries, skipping JSONL hydration\");\n return;\n }\n\n const entryCounts: Record<string, number> = {};\n for (const entry of entries) {\n const method = entry.notification?.method ?? \"unknown\";\n const entryParams = entry.notification?.params as\n | Record<string, unknown>\n | undefined;\n const update = entryParams?.update as\n | { sessionUpdate?: string }\n | undefined;\n const key = update?.sessionUpdate\n ? `${method}:${update.sessionUpdate}`\n : method;\n entryCounts[key] = (entryCounts[key] ?? 0) + 1;\n }\n log.info(\"S3 log entry breakdown\", {\n totalEntries: entries.length,\n types: entryCounts,\n });\n\n const allTurns = rebuildConversation(entries);\n if (allTurns.length === 0) {\n log.info(\"No conversation in S3 logs, skipping JSONL hydration\");\n return;\n }\n\n const maxTokens = supports1MContext(params.model ?? \"\")\n ? LARGE_CONTEXT_MAX_TOKENS\n : DEFAULT_MAX_TOKENS;\n const conversation = selectRecentTurns(allTurns, maxTokens);\n log.info(\"Selected recent turns for hydration\", {\n totalTurns: allTurns.length,\n selectedTurns: conversation.length,\n turnRoles: conversation.map((t) => t.role),\n });\n\n const jsonlLines = conversationTurnsToJsonlEntries(conversation, {\n sessionId: params.sessionId,\n cwd: params.cwd,\n model: params.model,\n gitBranch: params.gitBranch,\n permissionMode: params.permissionMode,\n });\n\n await fs.mkdir(path.dirname(jsonlPath), { recursive: true });\n\n const tmpPath = `${jsonlPath}.tmp.${Date.now()}`;\n await fs.writeFile(tmpPath, `${jsonlLines.join(\"\\n\")}\\n`);\n await fs.rename(tmpPath, jsonlPath);\n\n log.info(\"Hydrated session JSONL from S3\", {\n sessionId: params.sessionId,\n turns: conversation.length,\n lines: jsonlLines.length,\n });\n } catch (err) {\n log.warn(\"Failed to hydrate session JSONL, continuing\", {\n sessionId: params.sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n","export const DEFAULT_MODEL = \"opus\";\n\nconst GATEWAY_TO_SDK_MODEL: Record<string, string> = {\n \"claude-opus-4-5\": \"opus\",\n \"claude-opus-4-6\": \"opus\",\n \"claude-sonnet-4-5\": \"sonnet\",\n \"claude-sonnet-4-6\": \"sonnet\",\n \"claude-haiku-4-5\": \"haiku\",\n};\n\nexport function toSdkModelId(modelId: string): string {\n return GATEWAY_TO_SDK_MODEL[modelId] ?? modelId;\n}\n\nconst MODELS_WITH_1M_CONTEXT = new Set([\n \"claude-opus-4-6\",\n \"claude-sonnet-4-6\",\n]);\n\nexport function supports1MContext(modelId: string): boolean {\n return MODELS_WITH_1M_CONTEXT.has(modelId);\n}\n\nconst MODELS_WITH_EFFORT = new Set([\n \"claude-opus-4-5\",\n \"claude-opus-4-6\",\n \"claude-sonnet-4-6\",\n]);\n\nconst MODELS_WITH_MAX_EFFORT = new Set([\"claude-opus-4-6\"]);\n\nexport function supportsEffort(modelId: string): boolean {\n return MODELS_WITH_EFFORT.has(modelId);\n}\n\nexport function supportsMaxEffort(modelId: string): boolean {\n return MODELS_WITH_MAX_EFFORT.has(modelId);\n}\n\nconst MODELS_TO_EXCLUDE_MCP_TOOLS = new Set([\"claude-haiku-4-5\"]);\n\nexport function supportsMcpInjection(modelId: string): boolean {\n return !MODELS_TO_EXCLUDE_MCP_TOOLS.has(modelId);\n}\n\ninterface EffortOption {\n value: string;\n name: string;\n}\n\nexport function getEffortOptions(modelId: string): EffortOption[] | null {\n if (!supportsEffort(modelId)) return null;\n\n const options: EffortOption[] = [\n { value: \"low\", name: \"Low\" },\n { value: \"medium\", name: \"Medium\" },\n { value: \"high\", name: \"High\" },\n ];\n\n if (supportsMaxEffort(modelId)) {\n options.push({ value: \"max\", name: \"Max\" });\n }\n\n return options;\n}\n\n// Model alias resolution — lets callers use human-friendly aliases like\n// \"opus\" or \"sonnet\" instead of full model IDs like \"claude-opus-4-6\".\n\nconst MODEL_CONTEXT_HINT_PATTERN = /\\[(\\d+m)\\]$/i;\n\nfunction tokenizeModelPreference(model: string): {\n tokens: string[];\n contextHint?: string;\n} {\n const lower = model.trim().toLowerCase();\n const contextHint = lower\n .match(MODEL_CONTEXT_HINT_PATTERN)?.[1]\n ?.toLowerCase();\n\n const normalized = lower.replace(MODEL_CONTEXT_HINT_PATTERN, \" $1 \");\n const rawTokens = normalized.split(/[^a-z0-9]+/).filter(Boolean);\n const tokens = rawTokens\n .map((token) => {\n if (token === \"opusplan\") return \"opus\";\n if (token === \"best\" || token === \"default\") return \"\";\n return token;\n })\n .filter((token) => token && token !== \"claude\")\n .filter((token) => /[a-z]/.test(token) || token.endsWith(\"m\"));\n\n return { tokens, contextHint };\n}\n\ninterface ModelOption {\n value: string;\n name?: string;\n description?: string;\n}\n\nfunction scoreModelMatch(\n model: ModelOption,\n tokens: string[],\n contextHint?: string,\n): number {\n const haystack = `${model.value} ${model.name ?? \"\"}`.toLowerCase();\n let score = 0;\n for (const token of tokens) {\n if (haystack.includes(token)) {\n score += token === contextHint ? 3 : 1;\n }\n }\n return score;\n}\n\nexport function resolveModelPreference(\n preference: string,\n options: ModelOption[],\n): string | null {\n const trimmed = preference.trim();\n if (!trimmed) return null;\n\n const lower = trimmed.toLowerCase();\n\n // Exact match on value or display name\n const directMatch = options.find(\n (o) =>\n o.value === trimmed ||\n o.value.toLowerCase() === lower ||\n (o.name && o.name.toLowerCase() === lower),\n );\n if (directMatch) return directMatch.value;\n\n // Substring match\n const includesMatch = options.find((o) => {\n const value = o.value.toLowerCase();\n const display = (o.name ?? \"\").toLowerCase();\n return (\n value.includes(lower) || display.includes(lower) || lower.includes(value)\n );\n });\n if (includesMatch) return includesMatch.value;\n\n // Tokenized matching for aliases like \"opus[1m]\"\n const { tokens, contextHint } = tokenizeModelPreference(trimmed);\n if (tokens.length === 0) return null;\n\n let bestMatch: ModelOption | null = null;\n let bestScore = 0;\n for (const model of options) {\n const score = scoreModelMatch(model, tokens, contextHint);\n if (0 < score && (!bestMatch || bestScore < score)) {\n bestMatch = model;\n bestScore = score;\n }\n }\n\n return bestMatch?.value ?? null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/adapters/claude/session/jsonl-hydration.ts","../../../../src/adapters/claude/session/models.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ContentBlock } from \"@agentclientprotocol/sdk\";\nimport type { PostHogAPIClient } from \"../../../posthog-api\";\nimport type { StoredEntry } from \"../../../types\";\nimport { supports1MContext } from \"./models\";\n\ninterface ConversationTurn {\n role: \"user\" | \"assistant\";\n content: ContentBlock[];\n toolCalls?: ToolCallInfo[];\n}\n\ninterface ToolCallInfo {\n toolCallId: string;\n toolName: string;\n input: unknown;\n result?: unknown;\n}\n\ninterface JsonlConfig {\n sessionId: string;\n cwd: string;\n model?: string;\n version?: string;\n gitBranch?: string;\n slug?: string;\n permissionMode?: string;\n}\n\ninterface ClaudeCodeMeta {\n toolCallId?: string;\n toolName?: string;\n toolInput?: unknown;\n toolResponse?: unknown;\n}\n\ninterface SessionUpdate {\n sessionUpdate: string;\n content?: ContentBlock | ContentBlock[];\n _meta?: { claudeCode?: ClaudeCodeMeta };\n}\n\nconst MAX_PROJECT_KEY_LENGTH = 200;\n\nfunction hashString(s: string): string {\n let hash = 0;\n for (let i = 0; i < s.length; i++) {\n hash = (hash << 5) - hash + s.charCodeAt(i);\n hash |= 0;\n }\n return Math.abs(hash).toString(36);\n}\n\nexport function getSessionJsonlPath(sessionId: string, cwd: string): string {\n const configDir =\n process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), \".claude\");\n let projectKey = cwd.replace(/[^a-zA-Z0-9]/g, \"-\");\n if (projectKey.length > MAX_PROJECT_KEY_LENGTH) {\n projectKey = `${projectKey.slice(0, MAX_PROJECT_KEY_LENGTH)}-${hashString(cwd)}`;\n }\n return path.join(configDir, \"projects\", projectKey, `${sessionId}.jsonl`);\n}\n\nexport function rebuildConversation(\n entries: StoredEntry[],\n): ConversationTurn[] {\n const turns: ConversationTurn[] = [];\n let currentAssistantContent: ContentBlock[] = [];\n let currentToolCalls: ToolCallInfo[] = [];\n\n for (const entry of entries) {\n const method = entry.notification?.method;\n const params = entry.notification?.params as Record<string, unknown>;\n\n if (method === \"session/update\" && params?.update) {\n const update = params.update as SessionUpdate;\n\n switch (update.sessionUpdate) {\n case \"user_message\":\n case \"user_message_chunk\": {\n if (\n currentAssistantContent.length > 0 ||\n currentToolCalls.length > 0\n ) {\n turns.push({\n role: \"assistant\",\n content: currentAssistantContent,\n toolCalls:\n currentToolCalls.length > 0 ? currentToolCalls : undefined,\n });\n currentAssistantContent = [];\n currentToolCalls = [];\n }\n\n const content = update.content;\n const contentArray = Array.isArray(content)\n ? content\n : content\n ? [content]\n : [];\n\n const lastTurn = turns[turns.length - 1];\n if (lastTurn?.role === \"user\") {\n lastTurn.content.push(...contentArray);\n } else {\n turns.push({ role: \"user\", content: contentArray });\n }\n break;\n }\n\n case \"agent_message\":\n case \"agent_message_chunk\":\n case \"agent_thought_chunk\": {\n const content = update.content;\n if (content && !Array.isArray(content)) {\n if (\n content.type === \"text\" &&\n currentAssistantContent.length > 0 &&\n currentAssistantContent[currentAssistantContent.length - 1]\n .type === \"text\"\n ) {\n const lastBlock = currentAssistantContent[\n currentAssistantContent.length - 1\n ] as { type: \"text\"; text: string };\n lastBlock.text += (\n content as { type: \"text\"; text: string }\n ).text;\n } else {\n currentAssistantContent.push(content);\n }\n }\n break;\n }\n\n case \"tool_call\":\n case \"tool_call_update\": {\n const meta = update._meta?.claudeCode;\n if (meta) {\n const { toolCallId, toolName, toolInput, toolResponse } = meta;\n\n if (toolCallId && toolName) {\n let toolCall = currentToolCalls.find(\n (tc) => tc.toolCallId === toolCallId,\n );\n if (!toolCall) {\n toolCall = { toolCallId, toolName, input: toolInput };\n currentToolCalls.push(toolCall);\n }\n if (toolResponse !== undefined) {\n toolCall.result = toolResponse;\n }\n }\n }\n break;\n }\n\n case \"tool_result\": {\n const meta = update._meta?.claudeCode;\n if (meta) {\n const { toolCallId, toolResponse } = meta;\n if (toolCallId) {\n const toolCall = currentToolCalls.find(\n (tc) => tc.toolCallId === toolCallId,\n );\n if (toolCall && toolResponse !== undefined) {\n toolCall.result = toolResponse;\n }\n }\n }\n break;\n }\n }\n }\n }\n\n if (currentAssistantContent.length > 0 || currentToolCalls.length > 0) {\n turns.push({\n role: \"assistant\",\n content: currentAssistantContent,\n toolCalls: currentToolCalls.length > 0 ? currentToolCalls : undefined,\n });\n }\n\n return turns;\n}\n\nconst CHARS_PER_TOKEN = 4;\nconst DEFAULT_MAX_TOKENS = 150_000;\nconst LARGE_CONTEXT_MAX_TOKENS = 800_000;\n\nfunction estimateTurnTokens(turn: ConversationTurn): number {\n let chars = 0;\n for (const block of turn.content) {\n if (\"text\" in block && typeof block.text === \"string\") {\n chars += block.text.length;\n }\n }\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n chars += JSON.stringify(tc.input ?? \"\").length;\n if (tc.result !== undefined) {\n chars +=\n typeof tc.result === \"string\"\n ? tc.result.length\n : JSON.stringify(tc.result).length;\n }\n }\n }\n return Math.ceil(chars / CHARS_PER_TOKEN);\n}\n\nexport function selectRecentTurns(\n turns: ConversationTurn[],\n maxTokens = DEFAULT_MAX_TOKENS,\n): ConversationTurn[] {\n let budget = maxTokens;\n let startIndex = turns.length;\n\n for (let i = turns.length - 1; i >= 0; i--) {\n const cost = estimateTurnTokens(turns[i]);\n if (cost > budget) break;\n budget -= cost;\n startIndex = i;\n }\n\n // Ensure we start on a user turn so the conversation is well-formed\n while (startIndex < turns.length && turns[startIndex].role !== \"user\") {\n startIndex++;\n }\n\n return turns.slice(startIndex);\n}\n\nconst BASE62 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\nfunction generateMessageId(): string {\n const bytes = new Uint8Array(24);\n crypto.getRandomValues(bytes);\n let id = \"msg_01\";\n for (const b of bytes) {\n id += BASE62[b % 62];\n }\n return id;\n}\n\nconst ADJECTIVES = [\n \"bright\",\n \"calm\",\n \"daring\",\n \"eager\",\n \"fair\",\n \"gentle\",\n \"happy\",\n \"keen\",\n \"lively\",\n \"merry\",\n \"noble\",\n \"polite\",\n \"quick\",\n \"sharp\",\n \"warm\",\n \"witty\",\n];\nconst VERBS = [\n \"blazing\",\n \"crafting\",\n \"dashing\",\n \"flowing\",\n \"gliding\",\n \"humming\",\n \"jumping\",\n \"linking\",\n \"melting\",\n \"nesting\",\n \"pacing\",\n \"roaming\",\n \"sailing\",\n \"turning\",\n \"waving\",\n \"zoning\",\n];\nconst NOUNS = [\n \"aurora\",\n \"breeze\",\n \"cedar\",\n \"delta\",\n \"ember\",\n \"frost\",\n \"grove\",\n \"haven\",\n \"inlet\",\n \"jewel\",\n \"knoll\",\n \"lotus\",\n \"maple\",\n \"nexus\",\n \"oasis\",\n \"prism\",\n];\n\nfunction generateSlug(): string {\n const pick = (arr: string[]) => arr[Math.floor(Math.random() * arr.length)];\n return `${pick(ADJECTIVES)}-${pick(VERBS)}-${pick(NOUNS)}`;\n}\n\nexport function conversationTurnsToJsonlEntries(\n turns: ConversationTurn[],\n config: JsonlConfig,\n): string[] {\n const lines: string[] = [];\n let parentUuid: string | null = null;\n const model = config.model ?? \"claude-opus-4-6\";\n const version = config.version ?? \"2.1.63\";\n const gitBranch = config.gitBranch ?? \"\";\n const slug = config.slug ?? generateSlug();\n const permissionMode = config.permissionMode ?? \"default\";\n const baseTime = Date.now() - turns.length * 3000;\n let turnIndex = 0;\n\n for (const turn of turns) {\n const timestamp = new Date(baseTime + turnIndex * 3000).toISOString();\n turnIndex++;\n if (turn.role === \"user\") {\n lines.push(\n JSON.stringify({\n type: \"queue-operation\",\n operation: \"enqueue\",\n timestamp,\n sessionId: config.sessionId,\n }),\n );\n lines.push(\n JSON.stringify({\n type: \"queue-operation\",\n operation: \"dequeue\",\n timestamp,\n sessionId: config.sessionId,\n }),\n );\n\n const uuid = randomUUID();\n const textParts = turn.content\n .filter(\n (block) =>\n \"text\" in block && typeof block.text === \"string\" && block.text,\n )\n .map((block) => (block as { text: string }).text);\n\n const userText = textParts.length > 0 ? textParts.join(\"\") : \" \";\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"user\",\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: userText }],\n },\n uuid,\n timestamp,\n permissionMode,\n }),\n );\n parentUuid = uuid;\n } else {\n const allBlocks: unknown[] = [];\n\n for (const block of turn.content) {\n const blockType = (block as { type: string }).type;\n if (blockType === \"thinking\" || blockType === \"text\") {\n allBlocks.push(block);\n }\n }\n\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n allBlocks.push({\n type: \"tool_use\",\n id: tc.toolCallId,\n name: tc.toolName,\n input: tc.input,\n });\n }\n }\n\n const msgId = generateMessageId();\n const hasToolUse = allBlocks.some(\n (b) => (b as { type: string }).type === \"tool_use\",\n );\n const lastStopReason = hasToolUse ? \"tool_use\" : \"end_turn\";\n\n for (let i = 0; i < allBlocks.length; i++) {\n const block = allBlocks[i];\n const isLast = i === allBlocks.length - 1;\n const uuid = randomUUID();\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"assistant\",\n message: {\n model,\n id: msgId,\n type: \"message\",\n role: \"assistant\",\n content: [block],\n stop_reason: isLast ? lastStopReason : null,\n stop_sequence: null,\n usage: {\n input_tokens: 0,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n output_tokens: 0,\n },\n },\n uuid,\n timestamp,\n }),\n );\n parentUuid = uuid;\n }\n\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n if (tc.result === undefined) continue;\n\n const uuid = randomUUID();\n const resultText =\n typeof tc.result === \"string\"\n ? tc.result\n : JSON.stringify(tc.result);\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"user\",\n message: {\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: tc.toolCallId,\n content: resultText,\n },\n ],\n },\n uuid,\n timestamp,\n }),\n );\n parentUuid = uuid;\n }\n }\n }\n }\n\n return lines;\n}\n\ninterface HydrationLog {\n info: (msg: string, data?: unknown) => void;\n warn: (msg: string, data?: unknown) => void;\n}\n\nexport async function hydrateSessionJsonl(params: {\n sessionId: string;\n cwd: string;\n taskId: string;\n runId: string;\n model?: string;\n gitBranch?: string;\n permissionMode?: string;\n posthogAPI: PostHogAPIClient;\n log: HydrationLog;\n}): Promise<boolean> {\n const { posthogAPI, log } = params;\n\n try {\n const jsonlPath = getSessionJsonlPath(params.sessionId, params.cwd);\n try {\n await fs.access(jsonlPath);\n log.info(\"Local JSONL exists, skipping S3 hydration\", {\n sessionId: params.sessionId,\n });\n return true;\n } catch {\n // File doesn't exist, proceed with hydration\n }\n\n const taskRun = await posthogAPI.getTaskRun(params.taskId, params.runId);\n if (!taskRun.log_url) {\n log.info(\"No log URL, skipping JSONL hydration\");\n return false;\n }\n\n const entries = await posthogAPI.fetchTaskRunLogs(taskRun);\n if (entries.length === 0) {\n log.info(\"No S3 log entries, skipping JSONL hydration\");\n return false;\n }\n\n const entryCounts: Record<string, number> = {};\n for (const entry of entries) {\n const method = entry.notification?.method ?? \"unknown\";\n const entryParams = entry.notification?.params as\n | Record<string, unknown>\n | undefined;\n const update = entryParams?.update as\n | { sessionUpdate?: string }\n | undefined;\n const key = update?.sessionUpdate\n ? `${method}:${update.sessionUpdate}`\n : method;\n entryCounts[key] = (entryCounts[key] ?? 0) + 1;\n }\n log.info(\"S3 log entry breakdown\", {\n totalEntries: entries.length,\n types: entryCounts,\n });\n\n const allTurns = rebuildConversation(entries);\n if (allTurns.length === 0) {\n log.info(\"No conversation in S3 logs, skipping JSONL hydration\");\n return false;\n }\n\n const maxTokens = supports1MContext(params.model ?? \"\")\n ? LARGE_CONTEXT_MAX_TOKENS\n : DEFAULT_MAX_TOKENS;\n const conversation = selectRecentTurns(allTurns, maxTokens);\n log.info(\"Selected recent turns for hydration\", {\n totalTurns: allTurns.length,\n selectedTurns: conversation.length,\n turnRoles: conversation.map((t) => t.role),\n });\n\n const jsonlLines = conversationTurnsToJsonlEntries(conversation, {\n sessionId: params.sessionId,\n cwd: params.cwd,\n model: params.model,\n gitBranch: params.gitBranch,\n permissionMode: params.permissionMode,\n });\n\n await fs.mkdir(path.dirname(jsonlPath), { recursive: true });\n\n const tmpPath = `${jsonlPath}.tmp.${Date.now()}`;\n await fs.writeFile(tmpPath, `${jsonlLines.join(\"\\n\")}\\n`);\n await fs.rename(tmpPath, jsonlPath);\n\n log.info(\"Hydrated session JSONL from S3\", {\n sessionId: params.sessionId,\n turns: conversation.length,\n lines: jsonlLines.length,\n });\n return true;\n } catch (err) {\n log.warn(\"Failed to hydrate session JSONL, continuing\", {\n sessionId: params.sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n return false;\n }\n}\n","export const DEFAULT_MODEL = \"opus\";\n\nconst GATEWAY_TO_SDK_MODEL: Record<string, string> = {\n \"claude-opus-4-5\": \"opus\",\n \"claude-opus-4-6\": \"opus\",\n \"claude-sonnet-4-5\": \"sonnet\",\n \"claude-sonnet-4-6\": \"sonnet\",\n \"claude-haiku-4-5\": \"haiku\",\n};\n\nexport function toSdkModelId(modelId: string): string {\n return GATEWAY_TO_SDK_MODEL[modelId] ?? modelId;\n}\n\nconst MODELS_WITH_1M_CONTEXT = new Set([\n \"claude-opus-4-6\",\n \"claude-sonnet-4-6\",\n]);\n\nexport function supports1MContext(modelId: string): boolean {\n return MODELS_WITH_1M_CONTEXT.has(modelId);\n}\n\nconst MODELS_WITH_EFFORT = new Set([\n \"claude-opus-4-5\",\n \"claude-opus-4-6\",\n \"claude-sonnet-4-6\",\n]);\n\nconst MODELS_WITH_MAX_EFFORT = new Set([\"claude-opus-4-6\"]);\n\nexport function supportsEffort(modelId: string): boolean {\n return MODELS_WITH_EFFORT.has(modelId);\n}\n\nexport function supportsMaxEffort(modelId: string): boolean {\n return MODELS_WITH_MAX_EFFORT.has(modelId);\n}\n\nconst MODELS_TO_EXCLUDE_MCP_TOOLS = new Set([\"claude-haiku-4-5\"]);\n\nexport function supportsMcpInjection(modelId: string): boolean {\n return !MODELS_TO_EXCLUDE_MCP_TOOLS.has(modelId);\n}\n\ninterface EffortOption {\n value: string;\n name: string;\n}\n\nexport function getEffortOptions(modelId: string): EffortOption[] | null {\n if (!supportsEffort(modelId)) return null;\n\n const options: EffortOption[] = [\n { value: \"low\", name: \"Low\" },\n { value: \"medium\", name: \"Medium\" },\n { value: \"high\", name: \"High\" },\n ];\n\n if (supportsMaxEffort(modelId)) {\n options.push({ value: \"max\", name: \"Max\" });\n }\n\n return options;\n}\n\n// Model alias resolution — lets callers use human-friendly aliases like\n// \"opus\" or \"sonnet\" instead of full model IDs like \"claude-opus-4-6\".\n\nconst MODEL_CONTEXT_HINT_PATTERN = /\\[(\\d+m)\\]$/i;\n\nfunction tokenizeModelPreference(model: string): {\n tokens: string[];\n contextHint?: string;\n} {\n const lower = model.trim().toLowerCase();\n const contextHint = lower\n .match(MODEL_CONTEXT_HINT_PATTERN)?.[1]\n ?.toLowerCase();\n\n const normalized = lower.replace(MODEL_CONTEXT_HINT_PATTERN, \" $1 \");\n const rawTokens = normalized.split(/[^a-z0-9]+/).filter(Boolean);\n const tokens = rawTokens\n .map((token) => {\n if (token === \"opusplan\") return \"opus\";\n if (token === \"best\" || token === \"default\") return \"\";\n return token;\n })\n .filter((token) => token && token !== \"claude\")\n .filter((token) => /[a-z]/.test(token) || token.endsWith(\"m\"));\n\n return { tokens, contextHint };\n}\n\ninterface ModelOption {\n value: string;\n name?: string;\n description?: string;\n}\n\nfunction scoreModelMatch(\n model: ModelOption,\n tokens: string[],\n contextHint?: string,\n): number {\n const haystack = `${model.value} ${model.name ?? \"\"}`.toLowerCase();\n let score = 0;\n for (const token of tokens) {\n if (haystack.includes(token)) {\n score += token === contextHint ? 3 : 1;\n }\n }\n return score;\n}\n\nexport function resolveModelPreference(\n preference: string,\n options: ModelOption[],\n): string | null {\n const trimmed = preference.trim();\n if (!trimmed) return null;\n\n const lower = trimmed.toLowerCase();\n\n // Exact match on value or display name\n const directMatch = options.find(\n (o) =>\n o.value === trimmed ||\n o.value.toLowerCase() === lower ||\n (o.name && o.name.toLowerCase() === lower),\n );\n if (directMatch) return directMatch.value;\n\n // Substring match\n const includesMatch = options.find((o) => {\n const value = o.value.toLowerCase();\n const display = (o.name ?? \"\").toLowerCase();\n return (\n value.includes(lower) || display.includes(lower) || lower.includes(value)\n );\n });\n if (includesMatch) return includesMatch.value;\n\n // Tokenized matching for aliases like \"opus[1m]\"\n const { tokens, contextHint } = tokenizeModelPreference(trimmed);\n if (tokens.length === 0) return null;\n\n let bestMatch: ModelOption | null = null;\n let bestScore = 0;\n for (const model of options) {\n const score = scoreModelMatch(model, tokens, contextHint);\n if (0 < score && (!bestMatch || bestScore < score)) {\n bestMatch = model;\n bestScore = score;\n }\n }\n\n return bestMatch?.value ?? null;\n}\n"],"mappings":"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","names":[]}
package/dist/agent.js CHANGED
@@ -245,7 +245,7 @@ import { v7 as uuidv7 } from "uuid";
245
245
  // package.json
246
246
  var package_default = {
247
247
  name: "@posthog/agent",
248
- version: "2.3.216",
248
+ version: "2.3.256",
249
249
  repository: "https://github.com/PostHog/code",
250
250
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
251
251
  exports: {
@@ -4342,28 +4342,23 @@ import * as os5 from "os";
4342
4342
  import * as path7 from "path";
4343
4343
  var CodexSettingsManager = class {
4344
4344
  cwd;
4345
- settings = {};
4346
- initialized = false;
4345
+ settings = { mcpServerNames: [] };
4347
4346
  constructor(cwd) {
4348
4347
  this.cwd = cwd;
4348
+ this.loadSettings();
4349
4349
  }
4350
4350
  async initialize() {
4351
- if (this.initialized) {
4352
- return;
4353
- }
4354
- await this.loadSettings();
4355
- this.initialized = true;
4356
4351
  }
4357
4352
  getConfigPath() {
4358
4353
  return path7.join(os5.homedir(), ".codex", "config.toml");
4359
4354
  }
4360
- async loadSettings() {
4355
+ loadSettings() {
4361
4356
  const configPath = this.getConfigPath();
4362
4357
  try {
4363
- const content = await fs5.promises.readFile(configPath, "utf-8");
4358
+ const content = fs5.readFileSync(configPath, "utf-8");
4364
4359
  this.settings = parseCodexToml(content, this.cwd);
4365
4360
  } catch {
4366
- this.settings = {};
4361
+ this.settings = { mcpServerNames: [] };
4367
4362
  }
4368
4363
  }
4369
4364
  getSettings() {
@@ -4373,20 +4368,16 @@ var CodexSettingsManager = class {
4373
4368
  return this.cwd;
4374
4369
  }
4375
4370
  async setCwd(cwd) {
4376
- if (this.cwd === cwd) {
4377
- return;
4378
- }
4379
- this.dispose();
4371
+ if (this.cwd === cwd) return;
4380
4372
  this.cwd = cwd;
4381
- this.initialized = false;
4382
- await this.initialize();
4373
+ this.loadSettings();
4383
4374
  }
4384
4375
  dispose() {
4385
- this.initialized = false;
4386
4376
  }
4387
4377
  };
4388
4378
  function parseCodexToml(content, cwd) {
4389
- const settings = {};
4379
+ const settings = { mcpServerNames: [] };
4380
+ const mcpServerNames = /* @__PURE__ */ new Set();
4390
4381
  let currentSection = "";
4391
4382
  for (const line of content.split("\n")) {
4392
4383
  const trimmed = line.trim();
@@ -4394,6 +4385,9 @@ function parseCodexToml(content, cwd) {
4394
4385
  const sectionMatch = trimmed.match(/^\[(.+)\]$/);
4395
4386
  if (sectionMatch) {
4396
4387
  currentSection = sectionMatch[1] ?? "";
4388
+ if (currentSection.startsWith("mcp_servers.")) {
4389
+ mcpServerNames.add(currentSection.slice("mcp_servers.".length));
4390
+ }
4397
4391
  continue;
4398
4392
  }
4399
4393
  const kvMatch = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
@@ -4412,6 +4406,7 @@ function parseCodexToml(content, cwd) {
4412
4406
  if (key === "trust_level") settings.trustLevel = value;
4413
4407
  }
4414
4408
  }
4409
+ settings.mcpServerNames = Array.from(mcpServerNames);
4415
4410
  return settings;
4416
4411
  }
4417
4412
 
@@ -4422,6 +4417,9 @@ import { delimiter, dirname } from "path";
4422
4417
  function buildConfigArgs(options) {
4423
4418
  const args = [];
4424
4419
  args.push("-c", `features.remote_models=false`);
4420
+ for (const name of options.settings?.mcpServerNames ?? []) {
4421
+ args.push("-c", `mcp_servers.${name}.enabled=false`);
4422
+ }
4425
4423
  if (options.apiBaseUrl) {
4426
4424
  args.push("-c", `model_provider="posthog"`);
4427
4425
  args.push("-c", `model_providers.posthog.name="PostHog Gateway"`);
@@ -4536,16 +4534,17 @@ var CodexAcpAgent = class extends BaseAcpAgent {
4536
4534
  constructor(client, options) {
4537
4535
  super(client);
4538
4536
  this.logger = new Logger({ debug: true, prefix: "[CodexAcpAgent]" });
4537
+ const cwd = options.codexProcessOptions.cwd ?? process.cwd();
4538
+ const settingsManager = new CodexSettingsManager(cwd);
4539
4539
  this.codexProcess = spawnCodexProcess({
4540
4540
  ...options.codexProcessOptions,
4541
+ settings: settingsManager.getSettings(),
4541
4542
  logger: this.logger,
4542
4543
  processCallbacks: options.processCallbacks
4543
4544
  });
4544
4545
  const codexReadable = nodeReadableToWebReadable(this.codexProcess.stdout);
4545
4546
  const codexWritable = nodeWritableToWebWritable(this.codexProcess.stdin);
4546
4547
  const codexStream = ndJsonStream(codexWritable, codexReadable);
4547
- const cwd = options.codexProcessOptions.cwd ?? process.cwd();
4548
- const settingsManager = new CodexSettingsManager(cwd);
4549
4548
  const abortController = new AbortController();
4550
4549
  this.session = {
4551
4550
  abortController,