noumen 0.6.0 → 0.8.0

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.
Files changed (137) hide show
  1. package/README.md +237 -93
  2. package/dist/a2a/index.d.ts +5 -7
  3. package/dist/a2a/index.js +3 -4
  4. package/dist/a2a/index.js.map +1 -1
  5. package/dist/acp/index.d.ts +5 -7
  6. package/dist/acp/index.js +0 -1
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/{agent-DWE4_P5X.d.ts → agent-D0gl-qYi.d.ts} +89 -34
  9. package/dist/{chunk-6MMYCGJQ.js → chunk-5HY4IYNT.js} +1529 -2321
  10. package/dist/chunk-5HY4IYNT.js.map +1 -0
  11. package/dist/chunk-BC5BLWBC.js +21 -0
  12. package/dist/chunk-BC5BLWBC.js.map +1 -0
  13. package/dist/{chunk-XZN4QZLK.js → chunk-CX4BL6PC.js} +25 -15
  14. package/dist/chunk-CX4BL6PC.js.map +1 -0
  15. package/dist/{chunk-5GEX6ZSB.js → chunk-HQISH4D7.js} +60 -1
  16. package/dist/chunk-HQISH4D7.js.map +1 -0
  17. package/dist/{chunk-Y45R3PQL.js → chunk-NUCJXOUV.js} +32 -18
  18. package/dist/{chunk-Y45R3PQL.js.map → chunk-NUCJXOUV.js.map} +1 -1
  19. package/dist/chunk-OPFFLQZL.js +40 -0
  20. package/dist/chunk-OPFFLQZL.js.map +1 -0
  21. package/dist/chunk-PDEAJ272.js +660 -0
  22. package/dist/chunk-PDEAJ272.js.map +1 -0
  23. package/dist/chunk-PKHLGGEC.js +115 -0
  24. package/dist/chunk-PKHLGGEC.js.map +1 -0
  25. package/dist/chunk-XQTNXRE7.js +176 -0
  26. package/dist/chunk-XQTNXRE7.js.map +1 -0
  27. package/dist/chunk-XZPAA5TO.js +817 -0
  28. package/dist/chunk-XZPAA5TO.js.map +1 -0
  29. package/dist/cli/index.js +77 -42
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/client/index.d.ts +1 -2
  32. package/dist/client/index.js +0 -2
  33. package/dist/client/index.js.map +1 -1
  34. package/dist/client-JJFLE6RT.js +9 -0
  35. package/dist/{computer-BPdxSo6X.d.ts → computer-DzMR92tK.d.ts} +1 -1
  36. package/dist/docker.d.ts +2 -2
  37. package/dist/docker.js +0 -1
  38. package/dist/docker.js.map +1 -1
  39. package/dist/e2b.d.ts +2 -2
  40. package/dist/e2b.js +0 -1
  41. package/dist/e2b.js.map +1 -1
  42. package/dist/freestyle.d.ts +2 -2
  43. package/dist/freestyle.js +0 -1
  44. package/dist/freestyle.js.map +1 -1
  45. package/dist/{headless-FFU2DESQ.js → headless-25DU4MJQ.js} +1 -3
  46. package/dist/{headless-FFU2DESQ.js.map → headless-25DU4MJQ.js.map} +1 -1
  47. package/dist/{history-snip-64GYP4ZL.js → history-snip-HAWNAYKY.js} +1 -2
  48. package/dist/index.d.ts +351 -72
  49. package/dist/index.js +54 -55
  50. package/dist/jsonrpc/index.js +0 -1
  51. package/dist/local.d.ts +168 -0
  52. package/dist/local.js +40 -0
  53. package/dist/local.js.map +1 -0
  54. package/dist/lsp/index.d.ts +4 -5
  55. package/dist/lsp/index.js +0 -1
  56. package/dist/{lsp-PS3BWIHC.js → lsp-3APWNKB2.js} +1 -2
  57. package/dist/{manager-DLXK63XC.js → manager-Z5EQ7YYV.js} +1 -2
  58. package/dist/mcp/index.d.ts +16 -8
  59. package/dist/mcp/index.js +5 -6
  60. package/dist/mcp/index.js.map +1 -1
  61. package/dist/{mcp-auth-AEI2R4ZC.js → mcp-auth-NOIQPF7W.js} +1 -2
  62. package/dist/{provider-factory-TUHU3DIG.js → provider-factory-KNBSHXJ6.js} +3 -3
  63. package/dist/{render-GRN4ZSSW.js → render-4VEODRK7.js} +1 -2
  64. package/dist/{resolve-6KUZNEYW.js → resolve-AGQZFMKD.js} +3 -3
  65. package/dist/sandbox-DAqQo0Tj.d.ts +49 -0
  66. package/dist/sandbox-index-ODNREIFA.js +32 -0
  67. package/dist/sandbox-index-ODNREIFA.js.map +1 -0
  68. package/dist/server/index.d.ts +18 -7
  69. package/dist/server/index.js +9 -5
  70. package/dist/server/index.js.map +1 -1
  71. package/dist/{server-BzNGKTP6.d.ts → server-DFXdlqyX.d.ts} +1 -1
  72. package/dist/{spinner-OJNR6NFO.js → spinner-72JEISPK.js} +1 -2
  73. package/dist/sprites.d.ts +2 -2
  74. package/dist/sprites.js +0 -1
  75. package/dist/sprites.js.map +1 -1
  76. package/dist/ssh.d.ts +2 -2
  77. package/dist/ssh.js +0 -1
  78. package/dist/ssh.js.map +1 -1
  79. package/dist/{types-DhXwOQwD.d.ts → types-BX4ALqoN.d.ts} +76 -4
  80. package/dist/{types-kiGBF35b.d.ts → types-DLZNyF5t.d.ts} +125 -1
  81. package/dist/unsandboxed.d.ts +59 -0
  82. package/dist/unsandboxed.js +32 -0
  83. package/dist/unsandboxed.js.map +1 -0
  84. package/dist/{uuid-RVN2T26F.js → uuid-CVTNAPEB.js} +1 -2
  85. package/dist/{zod-7YXKWYMC.js → zod-VKURGPRT.js} +1 -2
  86. package/package.json +35 -50
  87. package/dist/cache-BlBwXXPS.d.ts +0 -38
  88. package/dist/chunk-5GEX6ZSB.js.map +0 -1
  89. package/dist/chunk-6MMYCGJQ.js.map +0 -1
  90. package/dist/chunk-7IQCQI2G.js +0 -94
  91. package/dist/chunk-7IQCQI2G.js.map +0 -1
  92. package/dist/chunk-CCM2AXZG.js +0 -16
  93. package/dist/chunk-CCM2AXZG.js.map +0 -1
  94. package/dist/chunk-DGUM43GV.js +0 -11
  95. package/dist/chunk-HEQQQGK5.js +0 -131
  96. package/dist/chunk-HEQQQGK5.js.map +0 -1
  97. package/dist/chunk-I3JTUFPK.js +0 -171
  98. package/dist/chunk-I3JTUFPK.js.map +0 -1
  99. package/dist/chunk-XZN4QZLK.js.map +0 -1
  100. package/dist/chunk-ZXSDKBYB.js +0 -474
  101. package/dist/chunk-ZXSDKBYB.js.map +0 -1
  102. package/dist/client-CRRO2376.js +0 -10
  103. package/dist/providers/anthropic.d.ts +0 -19
  104. package/dist/providers/anthropic.js +0 -36
  105. package/dist/providers/anthropic.js.map +0 -1
  106. package/dist/providers/bedrock.d.ts +0 -39
  107. package/dist/providers/bedrock.js +0 -56
  108. package/dist/providers/bedrock.js.map +0 -1
  109. package/dist/providers/gemini.d.ts +0 -17
  110. package/dist/providers/gemini.js +0 -262
  111. package/dist/providers/gemini.js.map +0 -1
  112. package/dist/providers/ollama.d.ts +0 -13
  113. package/dist/providers/ollama.js +0 -20
  114. package/dist/providers/ollama.js.map +0 -1
  115. package/dist/providers/openai.d.ts +0 -21
  116. package/dist/providers/openai.js +0 -9
  117. package/dist/providers/openrouter.d.ts +0 -16
  118. package/dist/providers/openrouter.js +0 -24
  119. package/dist/providers/openrouter.js.map +0 -1
  120. package/dist/providers/vertex.d.ts +0 -42
  121. package/dist/providers/vertex.js +0 -68
  122. package/dist/providers/vertex.js.map +0 -1
  123. package/dist/sandbox-9qeMTNrD.d.ts +0 -126
  124. package/dist/types-CD0rUKKT.d.ts +0 -109
  125. package/dist/uuid-RVN2T26F.js.map +0 -1
  126. package/dist/zod-7YXKWYMC.js.map +0 -1
  127. /package/dist/{chunk-DGUM43GV.js.map → client-JJFLE6RT.js.map} +0 -0
  128. /package/dist/{client-CRRO2376.js.map → history-snip-HAWNAYKY.js.map} +0 -0
  129. /package/dist/{history-snip-64GYP4ZL.js.map → lsp-3APWNKB2.js.map} +0 -0
  130. /package/dist/{lsp-PS3BWIHC.js.map → manager-Z5EQ7YYV.js.map} +0 -0
  131. /package/dist/{manager-DLXK63XC.js.map → mcp-auth-NOIQPF7W.js.map} +0 -0
  132. /package/dist/{mcp-auth-AEI2R4ZC.js.map → provider-factory-KNBSHXJ6.js.map} +0 -0
  133. /package/dist/{provider-factory-TUHU3DIG.js.map → render-4VEODRK7.js.map} +0 -0
  134. /package/dist/{providers/openai.js.map → resolve-AGQZFMKD.js.map} +0 -0
  135. /package/dist/{render-GRN4ZSSW.js.map → spinner-72JEISPK.js.map} +0 -0
  136. /package/dist/{resolve-6KUZNEYW.js.map → uuid-CVTNAPEB.js.map} +0 -0
  137. /package/dist/{spinner-OJNR6NFO.js.map → zod-VKURGPRT.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/ai-sdk/errors.ts","../src/providers/ai-sdk/compat/schema.ts","../src/providers/ai-sdk/request.ts","../src/providers/ai-sdk/compat/json-repair.ts","../src/providers/ai-sdk/stream.ts","../src/providers/ai-sdk/provider-family.ts","../src/providers/ai-sdk/provider.ts","../src/providers/resolve.ts"],"sourcesContent":["/**\n * Maps AI SDK `APICallError` (and similar provider errors) onto noumen's\n * `ChatStreamError`, preserving the HTTP status code and `Retry-After`\n * header so the existing retry engine (`pipeline/provider-round.ts`) can\n * make backoff decisions without knowing about `@ai-sdk/provider`.\n */\n\nimport { ChatStreamError } from \"../types.js\";\n\n// We duck-type the error instead of `instanceof APICallError` so noumen\n// doesn't pay the cost of importing `@ai-sdk/provider` at runtime when it\n// isn't needed. The shape is part of the public AI SDK contract.\ninterface ApiCallErrorLike {\n statusCode?: number;\n responseHeaders?: Record<string, string>;\n isRetryable?: boolean;\n message: string;\n}\n\nfunction isApiCallErrorLike(err: unknown): err is ApiCallErrorLike {\n if (!err || typeof err !== \"object\") return false;\n // APICallError extends AISDKError which exposes a brand via `name`.\n const name = (err as { name?: unknown }).name;\n if (name !== \"AI_APICallError\" && name !== \"APICallError\") return false;\n return typeof (err as { message?: unknown }).message === \"string\";\n}\n\nexport function mapApiCallError(err: unknown): ChatStreamError {\n if (err instanceof ChatStreamError) return err;\n\n if (isApiCallErrorLike(err)) {\n return new ChatStreamError(err.message, {\n status: err.statusCode,\n retryAfter: err.responseHeaders?.[\"retry-after\"],\n cause: err,\n });\n }\n\n const message = err instanceof Error ? err.message : String(err);\n return new ChatStreamError(message, { cause: err });\n}\n","/**\n * JSON Schema shims for AI SDK provider compatibility.\n *\n * Ported from mastra (`packages/core/src/stream/aisdk/v5/compat/prepare-tools.ts`).\n * Zod v4 `z.any()` serializes to a schema with no `type` field, which OpenAI\n * and other providers reject. `fixTypelessProperties` walks the schema and\n * injects a permissive type union wherever a property omits `type`, `$ref`,\n * `anyOf`, `oneOf`, and `allOf`.\n */\n\nconst PERMISSIVE_TYPES = [\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"object\",\n \"null\",\n] as const;\n\nexport function fixTypelessProperties(\n schema: Record<string, unknown>,\n): Record<string, unknown> {\n if (typeof schema !== \"object\" || schema === null) return schema;\n\n const result: Record<string, unknown> = { ...schema };\n\n if (\n result.properties &&\n typeof result.properties === \"object\" &&\n !Array.isArray(result.properties)\n ) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties as Record<string, unknown>).map(([key, value]) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return [key, value];\n }\n\n const propSchema = value as Record<string, unknown>;\n const hasType = \"type\" in propSchema;\n const hasRef = \"$ref\" in propSchema;\n const hasAnyOf = \"anyOf\" in propSchema;\n const hasOneOf = \"oneOf\" in propSchema;\n const hasAllOf = \"allOf\" in propSchema;\n\n if (!hasType && !hasRef && !hasAnyOf && !hasOneOf && !hasAllOf) {\n const { items: _items, ...rest } = propSchema;\n return [key, { ...rest, type: [...PERMISSIVE_TYPES] }];\n }\n\n return [key, fixTypelessProperties(propSchema)];\n }),\n );\n }\n\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = (result.items as Record<string, unknown>[]).map((item) =>\n fixTypelessProperties(item),\n );\n } else if (typeof result.items === \"object\") {\n result.items = fixTypelessProperties(result.items as Record<string, unknown>);\n }\n }\n\n return result;\n}\n","/**\n * `ChatParams` -> `LanguageModelV3CallOptions` translation.\n *\n * Handles:\n * - OpenAI-shaped `ChatMessage`s -> AI SDK `LanguageModelV3Prompt`\n * - Anthropic thinking signature / redacted thinking round-tripping via\n * `providerOptions.anthropic` on reasoning parts\n * - Anthropic cache breakpoints on tools + messages (honors `skipCacheWrite`)\n * - `thinking` / `reasoningEffort` mapped to the right\n * `providerOptions.{anthropic,openai,google}` shape per provider family\n * - Tool definitions with `fixTypelessProperties` to satisfy OpenAI's\n * strict JSON Schema validator\n */\n\nimport type { ChatMessage, ContentPart } from \"../../session/types.js\";\nimport type { ChatParams, ToolDefinition } from \"../types.js\";\nimport type { CacheControlConfig } from \"../cache.js\";\nimport { getMessageCacheBreakpointIndex } from \"../cache.js\";\nimport { fixTypelessProperties } from \"./compat/schema.js\";\nimport type { ProviderFamily } from \"./provider-family.js\";\n\n/**\n * Minimal subset of `LanguageModelV3CallOptions` that we produce. We avoid\n * importing `@ai-sdk/provider` types at the module level so mock language\n * models in tests don't need to ship the full generic type surface; the\n * returned object is structurally compatible.\n */\nexport interface TranslatedCallOptions {\n prompt: AiSdkMessage[];\n maxOutputTokens?: number;\n temperature?: number;\n abortSignal?: AbortSignal;\n tools?: AiSdkTool[];\n toolChoice?: { type: \"auto\" };\n responseFormat?:\n | { type: \"text\" }\n | { type: \"json\"; schema?: Record<string, unknown>; name?: string };\n providerOptions?: Record<string, Record<string, unknown>>;\n}\n\nexport type AiSdkMessage =\n | { role: \"system\"; content: string; providerOptions?: Record<string, Record<string, unknown>> }\n | {\n role: \"user\";\n content: Array<AiSdkTextPart | AiSdkFilePart>;\n providerOptions?: Record<string, Record<string, unknown>>;\n }\n | {\n role: \"assistant\";\n content: Array<AiSdkTextPart | AiSdkReasoningPart | AiSdkToolCallPart>;\n providerOptions?: Record<string, Record<string, unknown>>;\n }\n | {\n role: \"tool\";\n content: AiSdkToolResultPart[];\n providerOptions?: Record<string, Record<string, unknown>>;\n };\n\nexport interface AiSdkTextPart {\n type: \"text\";\n text: string;\n providerOptions?: Record<string, Record<string, unknown>>;\n}\n\nexport interface AiSdkFilePart {\n type: \"file\";\n data: string | Uint8Array | URL;\n mediaType: string;\n filename?: string;\n providerOptions?: Record<string, Record<string, unknown>>;\n}\n\nexport interface AiSdkReasoningPart {\n type: \"reasoning\";\n text: string;\n providerOptions?: Record<string, Record<string, unknown>>;\n}\n\nexport interface AiSdkToolCallPart {\n type: \"tool-call\";\n toolCallId: string;\n toolName: string;\n input: unknown;\n providerOptions?: Record<string, Record<string, unknown>>;\n}\n\nexport interface AiSdkToolResultPart {\n type: \"tool-result\";\n toolCallId: string;\n toolName: string;\n output:\n | { type: \"text\"; value: string }\n | { type: \"json\"; value: unknown }\n | { type: \"error-text\"; value: string }\n | {\n type: \"content\";\n value: Array<\n | { type: \"text\"; text: string }\n | { type: \"image-data\"; data: string; mediaType: string }\n | { type: \"image-url\"; url: string }\n >;\n };\n providerOptions?: Record<string, Record<string, unknown>>;\n}\n\nexport interface AiSdkTool {\n type: \"function\";\n name: string;\n description?: string;\n inputSchema: Record<string, unknown>;\n providerOptions?: Record<string, Record<string, unknown>>;\n}\n\n// ---------------------------------------------------------------------------\n// Top-level entry point\n// ---------------------------------------------------------------------------\n\nexport interface TranslateRequestOptions {\n providerFamily: ProviderFamily;\n /** Opt-in prompt caching config. Only applied when family is `anthropic`. */\n cacheConfig?: CacheControlConfig;\n}\n\nexport function translateRequest(\n params: ChatParams,\n opts: TranslateRequestOptions,\n): TranslatedCallOptions {\n const { providerFamily } = opts;\n const useAnthropicCache =\n providerFamily === \"anthropic\" && opts.cacheConfig?.enabled === true;\n\n const prompt = buildPrompt(params, {\n providerFamily,\n cacheConfig: useAnthropicCache ? opts.cacheConfig : undefined,\n skipCacheWrite: params.skipCacheWrite,\n });\n\n const tools = buildTools(params.tools, {\n providerFamily,\n cacheConfig: useAnthropicCache ? opts.cacheConfig : undefined,\n });\n\n const call: TranslatedCallOptions = {\n prompt,\n maxOutputTokens: params.max_tokens,\n };\n\n if (params.signal) call.abortSignal = params.signal;\n if (tools && tools.length > 0) call.tools = tools;\n\n const thinkingEnabled =\n params.thinking?.type === \"enabled\" &&\n (params.thinking as { budgetTokens: number }).budgetTokens > 0;\n\n // Anthropic rejects non-default temperature when thinking is on; replicate\n // the guard from the legacy provider so behavior is identical.\n if (providerFamily === \"anthropic\") {\n if (!thinkingEnabled && params.temperature !== undefined) {\n call.temperature = params.temperature;\n }\n } else if (params.temperature !== undefined) {\n // OpenAI reasoning models also reject non-default temperature, but the\n // AI SDK's OpenAI provider silently drops it with a warning, so we pass\n // it through and let the SDK decide.\n call.temperature = params.temperature;\n }\n\n if (params.outputFormat?.type === \"json_schema\") {\n call.responseFormat = {\n type: \"json\",\n schema: params.outputFormat.schema,\n name: params.outputFormat.name,\n };\n } else if (params.outputFormat?.type === \"json_object\") {\n call.responseFormat = { type: \"json\" };\n }\n\n const providerOptions = buildProviderOptions(params, providerFamily);\n if (providerOptions) call.providerOptions = providerOptions;\n\n return call;\n}\n\n// ---------------------------------------------------------------------------\n// Provider-specific option mapping\n// ---------------------------------------------------------------------------\n\nfunction buildProviderOptions(\n params: ChatParams,\n family: ProviderFamily,\n): Record<string, Record<string, unknown>> | undefined {\n const thinking = params.thinking;\n const thinkingEnabled =\n thinking?.type === \"enabled\" &&\n (thinking as { budgetTokens: number }).budgetTokens > 0;\n\n switch (family) {\n case \"anthropic\": {\n if (!thinkingEnabled) {\n // `thinking: { type: \"disabled\" }` -> omit; Anthropic rejects an\n // explicit disabled object on models that don't support the knob.\n return undefined;\n }\n const { budgetTokens } = thinking as { type: \"enabled\"; budgetTokens: number };\n const maxOutput = params.max_tokens;\n const clampedBudget =\n typeof maxOutput === \"number\" && maxOutput > 0\n ? Math.min(budgetTokens, maxOutput - 1)\n : budgetTokens;\n return {\n anthropic: {\n thinking: {\n type: \"enabled\",\n budgetTokens: clampedBudget,\n },\n },\n };\n }\n\n case \"openai\": {\n const effort =\n params.reasoningEffort ??\n (thinkingEnabled ? \"high\" : thinking?.type === \"disabled\" ? \"minimal\" : undefined);\n if (!effort) return undefined;\n return { openai: { reasoningEffort: effort } };\n }\n\n case \"google\": {\n if (thinkingEnabled) {\n const { budgetTokens } = thinking as { type: \"enabled\"; budgetTokens: number };\n return { google: { thinkingConfig: { thinkingBudget: budgetTokens } } };\n }\n if (thinking?.type === \"disabled\") {\n // Gemini 2.5-flash enables thinking by default and eats the output\n // budget. Pin to 0 to disable. Matches the legacy GeminiProvider.\n return { google: { thinkingConfig: { thinkingBudget: 0 } } };\n }\n return undefined;\n }\n\n default:\n return undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prompt construction\n// ---------------------------------------------------------------------------\n\ninterface BuildPromptOptions {\n providerFamily: ProviderFamily;\n cacheConfig?: CacheControlConfig;\n skipCacheWrite?: boolean;\n}\n\nfunction buildPrompt(\n params: ChatParams,\n opts: BuildPromptOptions,\n): AiSdkMessage[] {\n const result: AiSdkMessage[] = [];\n\n // Conversation-level filter: drop noumen-internal system messages; the\n // top-level system prompt lives in params.system for historical reasons.\n const convo = params.messages.filter((m) => m.role !== \"system\");\n\n const cacheEnabled = opts.cacheConfig?.enabled === true;\n const cacheBreakpoint = cacheEnabled\n ? getMessageCacheBreakpointIndex(convo, opts.skipCacheWrite)\n : -1;\n\n if (params.system) {\n const sys: AiSdkMessage = { role: \"system\", content: params.system };\n if (cacheEnabled) {\n sys.providerOptions = {\n anthropic: { cacheControl: buildCacheControl(opts.cacheConfig!) },\n };\n }\n result.push(sys);\n }\n\n for (let i = 0; i < convo.length; i++) {\n const msg = convo[i];\n const addCache = cacheEnabled && i === cacheBreakpoint;\n\n if (msg.role === \"user\") {\n result.push(convertUserMessage(msg, addCache ? opts.cacheConfig : undefined));\n } else if (msg.role === \"assistant\") {\n result.push(\n convertAssistantMessage(msg, {\n addCache,\n cacheConfig: opts.cacheConfig,\n providerFamily: opts.providerFamily,\n }),\n );\n } else if (msg.role === \"tool\") {\n result.push(\n convertToolMessage(msg, addCache ? opts.cacheConfig : undefined),\n );\n }\n }\n\n return result;\n}\n\nfunction convertUserMessage(\n msg: Extract<ChatMessage, { role: \"user\" }>,\n cacheConfig: CacheControlConfig | undefined,\n): AiSdkMessage {\n const parts: Array<AiSdkTextPart | AiSdkFilePart> = Array.isArray(msg.content)\n ? contentPartsToAiSdk(msg.content)\n : [{ type: \"text\", text: msg.content }];\n\n if (cacheConfig?.enabled && parts.length > 0) {\n const last = parts[parts.length - 1];\n last.providerOptions = {\n ...(last.providerOptions ?? {}),\n anthropic: { cacheControl: buildCacheControl(cacheConfig) },\n };\n }\n\n return { role: \"user\", content: parts };\n}\n\ninterface AssistantConvertOptions {\n addCache: boolean;\n cacheConfig?: CacheControlConfig;\n providerFamily: ProviderFamily;\n}\n\nfunction convertAssistantMessage(\n msg: Extract<ChatMessage, { role: \"assistant\" }>,\n opts: AssistantConvertOptions,\n): AiSdkMessage {\n const content: Array<AiSdkTextPart | AiSdkReasoningPart | AiSdkToolCallPart> = [];\n\n // Anthropic requires the thinking block back verbatim (including\n // signature) for cache continuity. Other providers ignore it — the\n // AI SDK forwards reasoning parts only when the provider knows how to\n // handle them.\n if (msg.thinking_content && opts.providerFamily === \"anthropic\") {\n const reasoning: AiSdkReasoningPart = {\n type: \"reasoning\",\n text: msg.thinking_content,\n };\n if (msg.thinking_signature) {\n reasoning.providerOptions = {\n anthropic: { signature: msg.thinking_signature },\n };\n }\n content.push(reasoning);\n }\n\n if (msg.redacted_thinking_data && opts.providerFamily === \"anthropic\") {\n // AI SDK models redacted thinking as a reasoning part with\n // `redactedData` in providerOptions. The text is empty because the\n // provider only needs the opaque payload to reconstruct the block.\n content.push({\n type: \"reasoning\",\n text: \"\",\n providerOptions: {\n anthropic: { redactedData: msg.redacted_thinking_data },\n },\n });\n }\n\n if (typeof msg.content === \"string\" && msg.content !== \"\") {\n content.push({ type: \"text\", text: msg.content });\n } else if (\n msg.content != null &&\n typeof msg.content !== \"string\" &&\n Array.isArray(msg.content)\n ) {\n for (const part of msg.content as ContentPart[]) {\n if (part.type === \"text\") content.push({ type: \"text\", text: part.text });\n }\n }\n\n if (msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n let input: unknown = {};\n if (tc.function.arguments) {\n try {\n input = JSON.parse(tc.function.arguments);\n } catch {\n // Truncated / malformed — send empty object so providers accept\n // the turn; the error will already have surfaced via the stream.\n input = {};\n }\n }\n content.push({\n type: \"tool-call\",\n toolCallId: tc.id,\n toolName: tc.function.name,\n input,\n });\n }\n }\n\n if (content.length === 0) {\n content.push({ type: \"text\", text: \"\" });\n }\n\n if (opts.addCache && opts.cacheConfig?.enabled) {\n for (let i = content.length - 1; i >= 0; i--) {\n const block = content[i];\n if (block.type === \"reasoning\") continue;\n block.providerOptions = {\n ...(block.providerOptions ?? {}),\n anthropic: { cacheControl: buildCacheControl(opts.cacheConfig) },\n };\n break;\n }\n }\n\n return { role: \"assistant\", content };\n}\n\nfunction convertToolMessage(\n msg: Extract<ChatMessage, { role: \"tool\" }>,\n cacheConfig: CacheControlConfig | undefined,\n): AiSdkMessage {\n const output: AiSdkToolResultPart[\"output\"] = Array.isArray(msg.content)\n ? toolContentToOutput(msg.content as ContentPart[], msg.isError)\n : msg.isError\n ? { type: \"error-text\", value: msg.content }\n : { type: \"text\", value: msg.content };\n\n const part: AiSdkToolResultPart = {\n type: \"tool-result\",\n toolCallId: msg.tool_call_id,\n toolName: \"tool\",\n output,\n };\n\n if (cacheConfig?.enabled) {\n part.providerOptions = {\n anthropic: { cacheControl: buildCacheControl(cacheConfig) },\n };\n }\n\n return { role: \"tool\", content: [part] };\n}\n\n// ---------------------------------------------------------------------------\n// Content part conversion\n// ---------------------------------------------------------------------------\n\nfunction contentPartsToAiSdk(parts: ContentPart[]): Array<AiSdkTextPart | AiSdkFilePart> {\n return parts.map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\", text: part.text } as AiSdkTextPart;\n }\n if (part.type === \"image\") {\n return {\n type: \"file\",\n mediaType: part.media_type,\n data: part.data,\n } as AiSdkFilePart;\n }\n return {\n type: \"file\",\n mediaType: \"image/*\",\n data: new URL(part.url),\n } as AiSdkFilePart;\n });\n}\n\nfunction toolContentToOutput(\n parts: ContentPart[],\n isError: boolean | undefined,\n): AiSdkToolResultPart[\"output\"] {\n const contentValue: Array<\n | { type: \"text\"; text: string }\n | { type: \"image-data\"; data: string; mediaType: string }\n | { type: \"image-url\"; url: string }\n > = parts.map((p) => {\n if (p.type === \"text\") return { type: \"text\", text: p.text };\n if (p.type === \"image\") {\n return { type: \"image-data\", data: p.data, mediaType: p.media_type };\n }\n return { type: \"image-url\", url: p.url };\n });\n\n if (isError) {\n const textOnly = contentValue\n .filter((v): v is { type: \"text\"; text: string } => v.type === \"text\")\n .map((v) => v.text)\n .join(\"\\n\");\n return { type: \"error-text\", value: textOnly };\n }\n\n return { type: \"content\", value: contentValue };\n}\n\n// ---------------------------------------------------------------------------\n// Tools\n// ---------------------------------------------------------------------------\n\ninterface BuildToolsOptions {\n providerFamily: ProviderFamily;\n cacheConfig?: CacheControlConfig;\n}\n\nfunction buildTools(\n tools: ToolDefinition[] | undefined,\n opts: BuildToolsOptions,\n): AiSdkTool[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n\n const cacheEnabled =\n opts.providerFamily === \"anthropic\" && opts.cacheConfig?.enabled === true;\n\n return tools.map((t, idx) => {\n const schema = fixTypelessProperties(\n t.function.parameters as unknown as Record<string, unknown>,\n );\n const tool: AiSdkTool = {\n type: \"function\",\n name: t.function.name,\n description: t.function.description,\n inputSchema: schema,\n };\n\n // Anthropic places the cache breakpoint on the *last* tool.\n if (cacheEnabled && idx === tools.length - 1) {\n tool.providerOptions = {\n anthropic: { cacheControl: buildCacheControl(opts.cacheConfig!) },\n };\n }\n\n return tool;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Cache control helper\n// ---------------------------------------------------------------------------\n\nfunction buildCacheControl(config: CacheControlConfig): Record<string, unknown> {\n const cc: Record<string, unknown> = { type: \"ephemeral\" };\n if (config.ttl) cc.ttl = config.ttl;\n if (config.scope) cc.scope = config.scope;\n return cc;\n}\n","/**\n * JSON repair helpers for LLM-emitted tool-call arguments.\n *\n * Ported from mastra (`packages/core/src/stream/aisdk/v5/transform.ts`) so\n * every AI SDK provider noumen talks to goes through the same robust parsing\n * path. Upstream tests live in mastra; vectors are mirrored in our own\n * `ai-sdk-adversarial.test.ts` so regressions surface locally.\n */\n\n/**\n * Sanitizes tool-call input strings for safe JSON parsing.\n *\n * Some LLMs append internal tokens like `<|call|>`, `<|endoftext|>`, or\n * `<|end|>` to otherwise valid JSON in streamed tool-call arguments, causing\n * `JSON.parse` to fail. This function first tries `JSON.parse` on the\n * original input — if parsing succeeds, the input is returned unchanged so\n * legitimate `<|...|>` patterns inside JSON string values are preserved.\n * Only when the original input is not valid JSON does the function fall\n * back to stripping `<|...|>` token patterns and surrounding whitespace.\n */\nexport function sanitizeToolCallInput(input: string): string {\n try {\n JSON.parse(input);\n return input;\n } catch {\n return input.replace(/[\\s]*<\\|[^|]*\\|>[\\s]*/g, \"\").trim();\n }\n}\n\n/**\n * Attempts to repair common JSON malformations produced by LLM providers.\n *\n * Repairs applied in order:\n * 1. Missing quote before property name: `{\"a\":\"b\",c\":\"d\"}` -> `{\"a\":\"b\",\"c\":\"d\"}`\n * 2. Unquoted property names: `{command:\"value\"}` -> `{\"command\":\"value\"}`\n * 3. Single quotes -> double quotes\n * 4. Trailing commas: `{\"a\":1,}` -> `{\"a\":1}`\n * 5. Unquoted ISO dates/datetimes\n *\n * @returns The parsed object if repair succeeds, or `null` if unrecoverable.\n */\nexport function tryRepairJson(input: string): Record<string, unknown> | null {\n let repaired = input.trim();\n\n // Fix 1: Missing quote before property name after `,` or `{`.\n repaired = repaired.replace(\n /([{,]\\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\"/g,\n (match, prefix, name) => {\n if (prefix.trimEnd().endsWith('\"')) return match;\n return `${prefix}\"${name}\"`;\n },\n );\n\n // Fix 2: Unquoted property names.\n repaired = repaired.replace(\n /([{,]\\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*:/g,\n '$1\"$2\":',\n );\n\n // Fix 3: Single quotes -> double quotes.\n repaired = repaired.replace(/'/g, '\"');\n\n // Fix 4: Trailing commas before closing braces/brackets.\n repaired = repaired.replace(/,(\\s*[}\\]])/g, \"$1\");\n\n // Fix 5: Unquoted ISO date/datetime values.\n repaired = repaired.replace(\n /:\\s*(\\d{4}-\\d{2}-\\d{2}(?:T[\\d:]+)?)\\s*([,}])/g,\n ': \"$1\"$2',\n );\n\n try {\n return JSON.parse(repaired) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/**\n * Parse tool-call JSON the same way mastra does, with sanitize + repair\n * fallback. Returns `undefined` if the string is empty; returns `null`\n * when the JSON is unrecoverable (callers typically drop the tool call).\n */\nexport function parseToolCallJson(input: string): Record<string, unknown> | null | undefined {\n if (!input) return undefined;\n const sanitized = sanitizeToolCallInput(input);\n if (!sanitized) return undefined;\n try {\n return JSON.parse(sanitized) as Record<string, unknown>;\n } catch {\n return tryRepairJson(sanitized);\n }\n}\n","/**\n * AI SDK v3 stream -> noumen `ChatStreamChunk` translation.\n *\n * Consumes a `ReadableStream<LanguageModelV3StreamPart>` produced by any\n * Vercel AI SDK provider and yields OpenAI-shaped chunks compatible with\n * the existing noumen pipeline:\n *\n * text-delta -> choices[0].delta.content\n * reasoning-delta -> choices[0].delta.thinking_content\n * reasoning-end -> choices[0].delta.{thinking_signature,redacted_thinking_data}\n * (reads Anthropic providerMetadata)\n * tool-input-* -> choices[0].delta.tool_calls[].function.arguments (streamed)\n * tool-call -> finalizes the tool-call (applies sanitize + repair)\n * finish -> terminal chunk with finish_reason + usage\n * error -> throws ChatStreamError via mapApiCallError\n */\n\nimport type { ChatStreamChunk } from \"../types.js\";\nimport { ChatStreamError } from \"../types.js\";\nimport { parseToolCallJson } from \"./compat/json-repair.js\";\nimport { mapApiCallError } from \"./errors.js\";\n\ntype Json = unknown;\n\ninterface StreamPartBase {\n type: string;\n providerMetadata?: Record<string, Record<string, Json>>;\n id?: string;\n}\n\n// We accept a loose shape because we support both v2 and v3 streams. The\n// stream parts have the same discriminator values across both versions for\n// the events we care about.\nexport type AiSdkStreamPart =\n | { type: \"stream-start\"; warnings?: unknown }\n | { type: \"response-metadata\"; id?: string; modelId?: string; timestamp?: Date }\n | { type: \"text-start\"; id: string; providerMetadata?: Record<string, Record<string, Json>> }\n | {\n type: \"text-delta\";\n id: string;\n delta: string;\n providerMetadata?: Record<string, Record<string, Json>>;\n }\n | { type: \"text-end\"; id: string; providerMetadata?: Record<string, Record<string, Json>> }\n | {\n type: \"reasoning-start\";\n id: string;\n providerMetadata?: Record<string, Record<string, Json>>;\n }\n | {\n type: \"reasoning-delta\";\n id: string;\n delta: string;\n providerMetadata?: Record<string, Record<string, Json>>;\n }\n | {\n type: \"reasoning-end\";\n id: string;\n providerMetadata?: Record<string, Record<string, Json>>;\n }\n | {\n type: \"tool-input-start\";\n id: string;\n toolName: string;\n providerMetadata?: Record<string, Record<string, Json>>;\n providerExecuted?: boolean;\n dynamic?: boolean;\n }\n | {\n type: \"tool-input-delta\";\n id: string;\n delta: string;\n providerMetadata?: Record<string, Record<string, Json>>;\n }\n | { type: \"tool-input-end\"; id: string; providerMetadata?: Record<string, Record<string, Json>> }\n | {\n type: \"tool-call\";\n toolCallId: string;\n toolName: string;\n input: string;\n providerExecuted?: boolean;\n providerMetadata?: Record<string, Record<string, Json>>;\n }\n | {\n type: \"tool-result\";\n toolCallId: string;\n toolName: string;\n result: Json;\n isError?: boolean;\n providerMetadata?: Record<string, Record<string, Json>>;\n }\n | {\n type: \"finish\";\n finishReason: string | { unified: string; raw?: string };\n usage: AiSdkUsage;\n providerMetadata?: Record<string, Record<string, Json>>;\n }\n | { type: \"error\"; error: unknown }\n | (StreamPartBase & { [k: string]: unknown });\n\n/** Unified usage shape covering both V2 (flat) and V3 (nested). */\nexport type AiSdkUsage = {\n // V2 flat\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n reasoningTokens?: number;\n cachedInputTokens?: number;\n} | {\n // V3 nested\n inputTokens: {\n total?: number;\n noCache?: number;\n cacheRead?: number;\n cacheWrite?: number;\n };\n outputTokens: {\n total?: number;\n text?: number;\n reasoning?: number;\n };\n raw?: Record<string, Json>;\n};\n\n// ---------------------------------------------------------------------------\n// Primary translator\n// ---------------------------------------------------------------------------\n\n/**\n * Transform an AI SDK stream into noumen's chunk protocol.\n *\n * @param stream the `LanguageModelV3StreamResult['stream']`\n * @param model model id to stamp on each emitted chunk (matches legacy behavior)\n * @param signal optional abort signal; terminates iteration cleanly on abort\n */\nexport async function* translateStream(\n stream: ReadableStream<AiSdkStreamPart>,\n model: string,\n signal?: AbortSignal,\n): AsyncIterable<ChatStreamChunk> {\n const reader = stream.getReader();\n const state = createState();\n\n try {\n while (true) {\n if (signal?.aborted) {\n try { await reader.cancel(); } catch { /* ignore */ }\n throw new ChatStreamError(\"aborted\", { cause: signal.reason });\n }\n\n const { done, value: part } = await reader.read();\n if (done) break;\n\n for (const chunk of processStreamPart(part, state, model)) {\n yield chunk;\n }\n\n if (state.terminated) break;\n }\n } catch (err) {\n if (err instanceof ChatStreamError) throw err;\n throw mapApiCallError(err);\n } finally {\n try { reader.releaseLock(); } catch { /* ignore */ }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Reducer\n// ---------------------------------------------------------------------------\n\ninterface State {\n chunkIndex: number;\n toolIndexMap: Map<string, number>;\n toolNames: Map<string, string>;\n nextToolIndex: number;\n terminated: boolean;\n}\n\nfunction createState(): State {\n return {\n chunkIndex: 0,\n toolIndexMap: new Map(),\n toolNames: new Map(),\n nextToolIndex: 0,\n terminated: false,\n };\n}\n\nexport function processStreamPart(\n part: AiSdkStreamPart,\n state: State,\n model: string,\n): ChatStreamChunk[] {\n if (!part || typeof part !== \"object\") return [];\n const chunkId = `chatcmpl-${state.chunkIndex++}`;\n\n switch (part.type) {\n case \"text-delta\": {\n const delta = (part as { delta?: string }).delta;\n if (!delta) return [];\n return [makeChunk(chunkId, model, { content: delta })];\n }\n\n case \"reasoning-delta\": {\n const delta = (part as { delta?: string }).delta;\n if (!delta) return [];\n return [makeChunk(chunkId, model, { thinking_content: delta })];\n }\n\n case \"reasoning-end\": {\n // Anthropic packs the thinking signature (and redacted data) into\n // providerMetadata on the closing reasoning-end event; we lift both\n // onto the delta so the stored AssistantMessage round-trips.\n const meta = (part as {\n providerMetadata?: Record<string, Record<string, unknown>>;\n }).providerMetadata;\n const anthropicMeta = meta?.anthropic;\n if (!anthropicMeta) return [];\n\n const delta: Record<string, unknown> = {};\n if (typeof anthropicMeta.signature === \"string\") {\n delta.thinking_signature = anthropicMeta.signature;\n }\n if (typeof anthropicMeta.redactedData === \"string\") {\n delta.redacted_thinking_data = anthropicMeta.redactedData;\n }\n if (Object.keys(delta).length === 0) return [];\n return [makeChunk(chunkId, model, delta)];\n }\n\n case \"tool-input-start\": {\n const p = part as {\n id: string;\n toolName: string;\n };\n if (!p.id || !p.toolName) return [];\n if (state.toolIndexMap.has(p.id)) return [];\n const idx = state.nextToolIndex++;\n state.toolIndexMap.set(p.id, idx);\n state.toolNames.set(p.id, p.toolName);\n return [\n makeChunk(chunkId, model, {\n tool_calls: [\n {\n index: idx,\n id: p.id,\n type: \"function\",\n function: { name: p.toolName, arguments: \"\" },\n },\n ],\n }),\n ];\n }\n\n case \"tool-input-delta\": {\n const p = part as { id: string; delta: string };\n if (!p.delta) return [];\n let idx = state.toolIndexMap.get(p.id);\n if (idx === undefined) {\n // Some providers emit `tool-input-delta` without a prior `tool-input-start`.\n idx = state.nextToolIndex++;\n state.toolIndexMap.set(p.id, idx);\n }\n return [\n makeChunk(chunkId, model, {\n tool_calls: [\n {\n index: idx,\n function: { arguments: p.delta },\n },\n ],\n }),\n ];\n }\n\n case \"tool-call\": {\n // Terminal tool-call chunk. AI SDK providers emit this whether or not\n // a streaming `tool-input-*` sequence preceded it. The `input` here\n // is the canonical JSON string. If we already streamed deltas with\n // the raw JSON, we must NOT re-emit — downstream accumulators would\n // double-count. Check if we have seen this id stream; if so, skip.\n const p = part as {\n toolCallId: string;\n toolName: string;\n input: string;\n };\n if (state.toolIndexMap.has(p.toolCallId)) {\n // Already streamed; parse to validate but emit nothing. We rely on\n // the stream deltas to have carried the full JSON.\n return [];\n }\n\n // Non-streamed tool call — emit the whole thing in one go. Apply\n // the sanitize + repair pipeline before re-serializing so the\n // downstream accumulator gets valid JSON.\n const idx = state.nextToolIndex++;\n state.toolIndexMap.set(p.toolCallId, idx);\n state.toolNames.set(p.toolCallId, p.toolName);\n const parsed = parseToolCallJson(p.input);\n const argsString =\n parsed === null || parsed === undefined\n ? p.input ?? \"\"\n : JSON.stringify(parsed);\n\n return [\n makeChunk(chunkId, model, {\n tool_calls: [\n {\n index: idx,\n id: p.toolCallId,\n type: \"function\",\n function: { name: p.toolName, arguments: argsString },\n },\n ],\n }),\n ];\n }\n\n case \"finish\": {\n state.terminated = true;\n const p = part as {\n finishReason: string | { unified: string; raw?: string };\n usage: AiSdkUsage;\n providerMetadata?: Record<string, Record<string, unknown>>;\n };\n const finishReason = mapFinishReason(\n p.finishReason,\n state.toolIndexMap.size > 0,\n );\n const usage = mapUsage(p.usage, p.providerMetadata);\n return [\n {\n id: chunkId,\n model,\n choices: [\n {\n index: 0,\n delta: {},\n finish_reason: finishReason,\n },\n ],\n usage,\n },\n ];\n }\n\n case \"error\": {\n state.terminated = true;\n throw mapApiCallError((part as { error: unknown }).error);\n }\n\n // No-op events we simply drop. These still advance chunkIndex for\n // deterministic ids, matching mastra's approach.\n case \"stream-start\":\n case \"response-metadata\":\n case \"text-start\":\n case \"text-end\":\n case \"reasoning-start\":\n case \"tool-input-end\":\n case \"tool-result\":\n case \"tool-approval-request\":\n case \"file\":\n case \"source\":\n case \"raw\":\n return [];\n\n default:\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Finish reason + usage mapping\n// ---------------------------------------------------------------------------\n\nfunction mapFinishReason(\n reason: string | { unified: string; raw?: string } | undefined,\n hasToolCalls: boolean,\n): string {\n const unified =\n typeof reason === \"object\" && reason !== null && \"unified\" in reason\n ? reason.unified\n : reason ?? \"other\";\n\n switch (unified) {\n case \"stop\": return hasToolCalls ? \"tool_calls\" : \"stop\";\n case \"length\": return \"length\";\n case \"content-filter\": return \"content_filter\";\n case \"tool-calls\": return \"tool_calls\";\n case \"error\": return \"error\";\n case \"other\":\n case \"unknown\":\n default: return hasToolCalls ? \"tool_calls\" : \"stop\";\n }\n}\n\nfunction mapUsage(\n usage: AiSdkUsage | undefined,\n providerMetadata: Record<string, Record<string, unknown>> | undefined,\n): ChatStreamChunk[\"usage\"] {\n if (!usage) return undefined;\n\n let prompt = 0;\n let completion = 0;\n let cacheRead: number | undefined;\n let cacheCreation: number | undefined;\n let thinking: number | undefined;\n\n const nested =\n typeof (usage as { inputTokens?: unknown }).inputTokens === \"object\";\n\n if (nested) {\n const u = usage as Extract<AiSdkUsage, { inputTokens: { total?: number } }>;\n prompt = u.inputTokens.total ?? 0;\n completion = u.outputTokens.total ?? 0;\n cacheRead = u.inputTokens.cacheRead;\n cacheCreation = u.inputTokens.cacheWrite;\n thinking = u.outputTokens.reasoning;\n } else {\n const u = usage as Extract<AiSdkUsage, { inputTokens?: number }>;\n prompt = u.inputTokens ?? 0;\n completion = u.outputTokens ?? 0;\n thinking = u.reasoningTokens;\n cacheRead = u.cachedInputTokens;\n }\n\n // Anthropic sometimes only surfaces cache numbers via providerMetadata.\n if (providerMetadata) {\n const anth = providerMetadata.anthropic;\n if (anth) {\n if (cacheRead === undefined && typeof anth.cacheReadInputTokens === \"number\") {\n cacheRead = anth.cacheReadInputTokens;\n }\n if (\n cacheCreation === undefined &&\n typeof anth.cacheCreationInputTokens === \"number\"\n ) {\n cacheCreation = anth.cacheCreationInputTokens;\n }\n }\n const openai = providerMetadata.openai;\n if (openai && cacheRead === undefined && typeof openai.cachedPromptTokens === \"number\") {\n cacheRead = openai.cachedPromptTokens;\n }\n }\n\n return {\n prompt_tokens: prompt,\n completion_tokens: completion,\n total_tokens: prompt + completion,\n cache_read_tokens: cacheRead,\n cache_creation_tokens: cacheCreation,\n thinking_tokens: thinking,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Chunk builder (kept local so the module is self-contained)\n// ---------------------------------------------------------------------------\n\nfunction makeChunk(\n id: string,\n model: string,\n delta: Record<string, unknown>,\n): ChatStreamChunk {\n return {\n id,\n model,\n choices: [\n {\n index: 0,\n delta: delta as ChatStreamChunk[\"choices\"][0][\"delta\"],\n finish_reason: null,\n },\n ],\n };\n}\n","/**\n * Classification of an AI SDK `LanguageModelV3` by its vendor / wire format.\n *\n * We derive the family from the model's `provider` string. Providers\n * downstream plug additional provider-specific knobs onto\n * `providerOptions` in different shapes; the request translator uses the\n * family to decide whether `thinking` becomes Anthropic's\n * `thinking: { type: \"enabled\" }`, OpenAI's `reasoningEffort`, or\n * Gemini-native `thinkingConfig`.\n */\nexport type ProviderFamily =\n /** Anthropic messages API — native or via Bedrock / Vertex / OpenRouter passthrough. */\n | \"anthropic\"\n /** OpenAI chat/completions or Responses; also `google` when routed through a chat/completions proxy. */\n | \"openai\"\n /** Google Generative AI native (`@ai-sdk/google`). */\n | \"google\"\n /** Unknown vendor — provider-specific options are dropped. */\n | \"unknown\";\n\n/**\n * Heuristic classifier. Call sites can override by passing an explicit\n * `providerFamily` to `AiSdkProvider`.\n *\n * Examples of provider strings in the wild:\n * - `@ai-sdk/openai` v3 -> `\"openai.chat\"` / `\"openai.responses\"`\n * - `@ai-sdk/anthropic` v3 -> `\"anthropic.messages\"`\n * - `@ai-sdk/google` v3 -> `\"google.generative-ai\"`\n * - `@ai-sdk/amazon-bedrock` with Claude -> `\"amazon-bedrock\"` (Anthropic wire format)\n * - `@ai-sdk/google-vertex` with Claude -> `\"google-vertex.anthropic\"`\n * - `@openrouter/ai-sdk-provider` -> `\"openrouter.chat\"` (OpenAI-compat wire format)\n * - `ollama-ai-provider-v2` -> `\"ollama.chat\"` (OpenAI-compat wire format)\n */\nexport function inferProviderFamily(providerString: string): ProviderFamily {\n const p = providerString.toLowerCase();\n\n if (p.includes(\"anthropic\")) return \"anthropic\";\n if (p.startsWith(\"amazon-bedrock\") || p.startsWith(\"bedrock\")) {\n return \"anthropic\";\n }\n\n // `@ai-sdk/google` native Gemini\n if (p.startsWith(\"google.\") || p === \"google\" || p.startsWith(\"google-generative-ai\")) {\n return \"google\";\n }\n\n // Everything else that speaks OpenAI wire format:\n // `openai.*`, `openrouter.*`, `ollama.*`, custom `*.chat`, etc.\n if (\n p.startsWith(\"openai\") ||\n p.startsWith(\"openrouter\") ||\n p.startsWith(\"ollama\") ||\n p.endsWith(\".chat\") ||\n p.endsWith(\".responses\")\n ) {\n return \"openai\";\n }\n\n return \"unknown\";\n}\n","/**\n * `AiSdkProvider` — single noumen `AIProvider` implementation that wraps\n * any Vercel AI SDK `LanguageModelV3` (`@ai-sdk/openai`, `@ai-sdk/anthropic`,\n * `@ai-sdk/google`, `@openrouter/ai-sdk-provider`, `@ai-sdk/amazon-bedrock`,\n * `@ai-sdk/google-vertex`, `ollama-ai-provider-v2`, ...).\n *\n * Callers construct the vendor SDK model (often via pocketuniverse's metered\n * `createProvider(...)` factory so traffic flows through `/api/ai/*` with\n * JWT auth + credit metering) and hand it to `new AiSdkProvider({ model })`.\n * The noumen pipeline then keeps talking to one uniform `chat()` surface.\n *\n * See `/Users/a/mastra/packages/core/src/llm/model/aisdk/v5/model.ts` for\n * the reference wrapper; we intentionally strip out mastra-specific event\n * plumbing and keep the surface area to just `AIProvider.chat`.\n */\n\nimport type { AIProvider, ChatParams, ChatStreamChunk } from \"../types.js\";\nimport type { CacheControlConfig } from \"../cache.js\";\nimport { mapApiCallError } from \"./errors.js\";\nimport { translateRequest, type TranslatedCallOptions } from \"./request.js\";\nimport { translateStream, type AiSdkStreamPart } from \"./stream.js\";\nimport {\n inferProviderFamily,\n type ProviderFamily,\n} from \"./provider-family.js\";\n\n/**\n * Minimal subset of `LanguageModelV3` we require. Using a structural type\n * means tests can pass lightweight mocks and we don't have a hard import\n * dependency on `@ai-sdk/provider` types (peer-only).\n */\nexport interface AiSdkLanguageModel {\n readonly specificationVersion: \"v2\" | \"v3\";\n readonly provider: string;\n readonly modelId: string;\n doStream(options: TranslatedCallOptions): Promise<{\n stream: ReadableStream<AiSdkStreamPart>;\n }>;\n}\n\nexport interface AiSdkProviderOptions {\n /** The AI SDK language model instance (any v2 or v3 provider). */\n model: AiSdkLanguageModel;\n /**\n * Fallback model id reported by `AIProvider.defaultModel`. When omitted\n * we use `model.modelId`. `ChatParams.model`, when provided, always\n * wins at call time because the AI SDK model is already bound to its\n * id — this field is purely informational for consumers that ask for\n * a default without wiring in a resolver.\n */\n defaultModel?: string;\n /**\n * Override the provider family classifier. Use this if you know the\n * model's vendor more precisely than the string-based heuristic (e.g.\n * a custom base URL forwards Anthropic traffic but reports\n * `provider: \"openai.chat\"`).\n */\n providerFamily?: ProviderFamily;\n /**\n * Anthropic prompt-cache configuration. No-op when `providerFamily` is\n * not Anthropic. When enabled, noumen inserts a single cache breakpoint\n * on the appropriate message position (respects `ChatParams.skipCacheWrite`).\n */\n cacheConfig?: CacheControlConfig;\n}\n\nexport class AiSdkProvider implements AIProvider {\n readonly defaultModel: string;\n readonly providerFamily: ProviderFamily;\n private readonly model: AiSdkLanguageModel;\n private readonly cacheConfig?: CacheControlConfig;\n\n constructor(opts: AiSdkProviderOptions) {\n this.model = opts.model;\n this.defaultModel = opts.defaultModel ?? opts.model.modelId;\n this.providerFamily =\n opts.providerFamily ?? inferProviderFamily(opts.model.provider);\n this.cacheConfig = opts.cacheConfig;\n }\n\n async *chat(params: ChatParams): AsyncIterable<ChatStreamChunk> {\n const call = translateRequest(params, {\n providerFamily: this.providerFamily,\n cacheConfig: this.cacheConfig,\n });\n\n let result: { stream: ReadableStream<AiSdkStreamPart> };\n try {\n result = await this.model.doStream(call);\n } catch (err) {\n throw mapApiCallError(err);\n }\n\n const modelId = params.model ?? this.defaultModel;\n yield* translateStream(result.stream, modelId, params.signal);\n }\n}\n","/**\n * CLI-facing provider resolver.\n *\n * Builds an `AiSdkProvider` wrapping any Vercel AI SDK `LanguageModelV3`.\n * Each vendor SDK is dynamically imported so CLI users only need to install\n * the packages for the providers they actually use.\n *\n * Programmatic callers should prefer constructing `AiSdkProvider` directly\n * with their own language model — that path supports metering proxies,\n * bespoke auth, and any other knob the AI SDK exposes. This resolver exists\n * so `noumen <provider>` still works out of the box.\n */\n\nimport type { AIProvider } from \"./types.js\";\nimport type { AiSdkLanguageModel } from \"./ai-sdk/provider.js\";\nimport { AiSdkProvider } from \"./ai-sdk/provider.js\";\n\nexport type ProviderName =\n | \"openai\"\n | \"anthropic\"\n | \"gemini\"\n | \"openrouter\"\n | \"bedrock\"\n | \"vertex\"\n | \"ollama\";\n\nconst ENV_KEY_MAP: Record<string, string> = {\n openai: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n gemini: \"GEMINI_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n};\n\nexport const DEFAULT_MODELS: Record<string, string> = {\n openai: \"gpt-5.4\",\n anthropic: \"claude-opus-4.6\",\n gemini: \"gemini-2.5-flash\",\n openrouter: \"anthropic/claude-opus-4.6\",\n bedrock: \"us.anthropic.claude-opus-4.6-v1:0\",\n vertex: \"claude-opus-4.6\",\n ollama: \"qwen2.5-coder:32b\",\n};\n\nexport const SUPPORTED_PROVIDERS: ProviderName[] = Object.keys(DEFAULT_MODELS) as ProviderName[];\n\nfunction getProviderEnvKey(name: string): string | undefined {\n const envVar = ENV_KEY_MAP[name];\n return envVar ? process.env[envVar] : undefined;\n}\n\nexport interface ResolveProviderOptions {\n apiKey?: string;\n model?: string;\n baseURL?: string;\n}\n\nfunction cannotFindVendor(provider: string, pkg: string, err: unknown): never {\n const hint =\n err instanceof Error && err.message.includes(\"Cannot find\")\n ? ` Install it with \\`pnpm add ${pkg}\\`.`\n : \"\";\n throw new Error(\n `noumen provider \"${provider}\" requires the \"${pkg}\" package.${hint}`,\n { cause: err },\n );\n}\n\nasync function loadModule<T = unknown>(\n provider: string,\n pkg: string,\n): Promise<T> {\n try {\n return (await import(pkg)) as T;\n } catch (err) {\n cannotFindVendor(provider, pkg, err);\n }\n}\n\n/**\n * Resolve a provider from a name string or pass through an AIProvider instance.\n *\n * API key resolution order:\n * 1. Explicit `apiKey` option\n * 2. Provider-specific env var (`OPENAI_API_KEY`, etc.)\n * 3. `NOUMEN_API_KEY` generic env var\n */\nexport async function resolveProvider(\n input: AIProvider | ProviderName,\n opts?: ResolveProviderOptions,\n): Promise<AIProvider> {\n if (typeof input !== \"string\") return input;\n\n const name = input;\n if (!SUPPORTED_PROVIDERS.includes(name)) {\n throw new Error(\n `Unknown provider \"${name}\". Supported: ${SUPPORTED_PROVIDERS.join(\", \")}`,\n );\n }\n\n const apiKey =\n opts?.apiKey ??\n getProviderEnvKey(name) ??\n process.env.NOUMEN_API_KEY;\n\n const modelId = opts?.model ?? DEFAULT_MODELS[name];\n\n switch (name) {\n case \"openai\": {\n if (!apiKey) {\n throw new Error(\"OpenAI requires an API key. Set OPENAI_API_KEY or pass apiKey.\");\n }\n const mod = await loadModule<{\n createOpenAI: (o: Record<string, unknown>) => ((id: string) => AiSdkLanguageModel) & {\n chat(id: string): AiSdkLanguageModel;\n };\n }>(name, \"@ai-sdk/openai\");\n const openai = mod.createOpenAI({ apiKey, baseURL: opts?.baseURL });\n // Pin to chat/completions — it's the lowest-common-denominator endpoint\n // and matches what the legacy OpenAIProvider used.\n return new AiSdkProvider({ model: openai.chat(modelId) });\n }\n\n case \"anthropic\": {\n if (!apiKey) {\n throw new Error(\"Anthropic requires an API key. Set ANTHROPIC_API_KEY or pass apiKey.\");\n }\n const mod = await loadModule<{\n createAnthropic: (o: Record<string, unknown>) => (id: string) => AiSdkLanguageModel;\n }>(name, \"@ai-sdk/anthropic\");\n const anthropic = mod.createAnthropic({ apiKey, baseURL: opts?.baseURL });\n return new AiSdkProvider({\n model: anthropic(modelId),\n providerFamily: \"anthropic\",\n cacheConfig: { enabled: true },\n });\n }\n\n case \"gemini\": {\n if (!apiKey) {\n throw new Error(\"Gemini requires an API key. Set GEMINI_API_KEY or pass apiKey.\");\n }\n const mod = await loadModule<{\n createGoogleGenerativeAI: (o: Record<string, unknown>) => (id: string) => AiSdkLanguageModel;\n }>(name, \"@ai-sdk/google\");\n const google = mod.createGoogleGenerativeAI({ apiKey, baseURL: opts?.baseURL });\n return new AiSdkProvider({ model: google(modelId), providerFamily: \"google\" });\n }\n\n case \"openrouter\": {\n if (!apiKey) {\n throw new Error(\"OpenRouter requires an API key. Set OPENROUTER_API_KEY or pass apiKey.\");\n }\n const mod = await loadModule<{\n createOpenRouter: (o: Record<string, unknown>) => {\n chat(id: string): AiSdkLanguageModel;\n };\n }>(name, \"@openrouter/ai-sdk-provider\");\n const openrouter = mod.createOpenRouter({ apiKey });\n return new AiSdkProvider({ model: openrouter.chat(modelId) });\n }\n\n case \"bedrock\": {\n const mod = await loadModule<{\n createAmazonBedrock: (o: Record<string, unknown>) => (id: string) => AiSdkLanguageModel;\n }>(name, \"@ai-sdk/amazon-bedrock\");\n const bedrock = mod.createAmazonBedrock({\n region: process.env.AWS_REGION,\n baseURL: opts?.baseURL,\n });\n return new AiSdkProvider({ model: bedrock(modelId), providerFamily: \"anthropic\" });\n }\n\n case \"vertex\": {\n const mod = await loadModule<{\n createVertex: (o: Record<string, unknown>) => {\n anthropic(id: string): AiSdkLanguageModel;\n } & ((id: string) => AiSdkLanguageModel);\n }>(name, \"@ai-sdk/google-vertex\");\n const vertex = mod.createVertex({\n project: process.env.GCLOUD_PROJECT ?? process.env.GOOGLE_CLOUD_PROJECT,\n location: process.env.GOOGLE_CLOUD_LOCATION ?? \"us-central1\",\n baseURL: opts?.baseURL,\n });\n // Default vertex usage is Claude via Anthropic-on-Vertex; the\n // DEFAULT_MODELS[vertex] id is a Claude id. If the caller passed a\n // Gemini model we route through the native Vertex Gemini entry.\n const isClaude = modelId.toLowerCase().includes(\"claude\");\n const model = isClaude ? vertex.anthropic(modelId) : vertex(modelId);\n return new AiSdkProvider({\n model,\n providerFamily: isClaude ? \"anthropic\" : \"google\",\n });\n }\n\n case \"ollama\": {\n const mod = await loadModule<{\n createOllama: (o: Record<string, unknown>) => (id: string) => AiSdkLanguageModel;\n }>(name, \"ollama-ai-provider-v2\");\n const base =\n opts?.baseURL ??\n (process.env.OLLAMA_HOST\n ? `${process.env.OLLAMA_HOST.replace(/\\/+$/, \"\")}/api`\n : undefined);\n const ollama = mod.createOllama(base ? { baseURL: base } : {});\n return new AiSdkProvider({ model: ollama(modelId) });\n }\n\n default:\n throw new Error(`Unhandled provider: ${name satisfies never}`);\n }\n}\n\n/**\n * Auto-detect provider from available environment variables.\n */\nexport async function detectProvider(): Promise<ProviderName | undefined> {\n if (process.env.ANTHROPIC_API_KEY) return \"anthropic\";\n if (process.env.OPENAI_API_KEY) return \"openai\";\n if (process.env.GEMINI_API_KEY) return \"gemini\";\n if (process.env.OPENROUTER_API_KEY) return \"openrouter\";\n if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_PROFILE) return \"bedrock\";\n if (process.env.GOOGLE_APPLICATION_CREDENTIALS || process.env.GCLOUD_PROJECT) return \"vertex\";\n if (process.env.OLLAMA_HOST) return \"ollama\";\n\n try {\n const host = process.env.OLLAMA_HOST ?? \"http://localhost:11434\";\n const res = await fetch(`${host.replace(/\\/+$/, \"\")}/api/tags`, {\n signal: AbortSignal.timeout(500),\n });\n if (res.ok) return \"ollama\";\n } catch { /* not running */ }\n\n return undefined;\n}\n"],"mappings":"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","names":[]}
package/dist/cli/index.js CHANGED
@@ -12,27 +12,34 @@ import {
12
12
  import {
13
13
  startSpinner
14
14
  } from "../chunk-KXDB56YW.js";
15
- import {
16
- Agent,
17
- LocalSandbox,
18
- UnsandboxedLocal
19
- } from "../chunk-6MMYCGJQ.js";
15
+ import "../chunk-PDEAJ272.js";
20
16
  import {
21
17
  DEFAULT_MODELS,
22
18
  SUPPORTED_PROVIDERS,
23
19
  detectProvider,
24
20
  resolveProvider
25
- } from "../chunk-7IQCQI2G.js";
26
- import "../chunk-42PHHZUA.js";
27
- import "../chunk-XZN4QZLK.js";
28
- import "../chunk-5GEX6ZSB.js";
21
+ } from "../chunk-XZPAA5TO.js";
29
22
  import "../chunk-4SQA2UCV.js";
30
- import "../chunk-3SK5GCI6.js";
31
- import "../chunk-HEQQQGK5.js";
32
- import "../chunk-CCM2AXZG.js";
23
+ import {
24
+ LocalSandbox
25
+ } from "../chunk-PKHLGGEC.js";
26
+ import {
27
+ UnsandboxedLocal
28
+ } from "../chunk-BC5BLWBC.js";
29
+ import "../chunk-XQTNXRE7.js";
30
+ import {
31
+ Agent
32
+ } from "../chunk-5HY4IYNT.js";
33
+ import "../chunk-42PHHZUA.js";
34
+ import "../chunk-OPFFLQZL.js";
33
35
  import "../chunk-3HEYCV26.js";
36
+ import "../chunk-CX4BL6PC.js";
37
+ import "../chunk-3SK5GCI6.js";
38
+ import {
39
+ DEFAULT_DOT_DIRS,
40
+ createDotDirResolver
41
+ } from "../chunk-HQISH4D7.js";
34
42
  import "../chunk-JACGEMTF.js";
35
- import "../chunk-DGUM43GV.js";
36
43
 
37
44
  // src/cli/index.ts
38
45
  import { Command } from "commander";
@@ -42,25 +49,33 @@ import chalk3 from "chalk";
42
49
  import * as fs from "fs";
43
50
  import * as path from "path";
44
51
  import * as os from "os";
45
- function loadGlobalConfig() {
46
- const globalPath = path.join(os.homedir(), ".noumen", "config.json");
47
- try {
48
- const raw = fs.readFileSync(globalPath, "utf-8");
49
- return JSON.parse(raw);
50
- } catch {
51
- return {};
52
- }
53
- }
54
- function loadProjectConfig(cwd) {
55
- let dir = path.resolve(cwd);
56
- const root = path.parse(dir).root;
57
- while (true) {
58
- const candidate = path.join(dir, ".noumen", "config.json");
52
+ function readFirstJson(resolver, base, rel) {
53
+ for (const candidate of resolver.joinRead(base, rel)) {
59
54
  try {
60
55
  const raw = fs.readFileSync(candidate, "utf-8");
61
56
  return JSON.parse(raw);
62
57
  } catch {
63
58
  }
59
+ }
60
+ return null;
61
+ }
62
+ function resolverFromConfigs(...configs) {
63
+ for (const cfg of configs) {
64
+ if (cfg.dotDirs) return createDotDirResolver(cfg.dotDirs);
65
+ }
66
+ return createDotDirResolver(DEFAULT_DOT_DIRS);
67
+ }
68
+ function loadGlobalConfig(resolver) {
69
+ const r = resolver ?? createDotDirResolver(DEFAULT_DOT_DIRS);
70
+ return readFirstJson(r, os.homedir(), "config.json") ?? {};
71
+ }
72
+ function loadProjectConfig(cwd, resolver) {
73
+ const r = resolver ?? createDotDirResolver(DEFAULT_DOT_DIRS);
74
+ let dir = path.resolve(cwd);
75
+ const root = path.parse(dir).root;
76
+ while (true) {
77
+ const hit = readFirstJson(r, dir, "config.json");
78
+ if (hit) return hit;
64
79
  const parent = path.dirname(dir);
65
80
  if (parent === dir || dir === root) break;
66
81
  dir = parent;
@@ -68,9 +83,20 @@ function loadProjectConfig(cwd) {
68
83
  return {};
69
84
  }
70
85
  function loadCliConfig(cwd) {
71
- const global = loadGlobalConfig();
72
- const project = loadProjectConfig(cwd);
73
- return { ...global, ...project };
86
+ const bootstrapResolver = createDotDirResolver(DEFAULT_DOT_DIRS);
87
+ const globalBootstrap = loadGlobalConfig(bootstrapResolver);
88
+ const projectBootstrap = loadProjectConfig(cwd, bootstrapResolver);
89
+ const override = projectBootstrap.dotDirs ?? globalBootstrap.dotDirs;
90
+ if (override) {
91
+ const resolver = createDotDirResolver(override);
92
+ const global = loadGlobalConfig(resolver);
93
+ const project = loadProjectConfig(cwd, resolver);
94
+ return { ...global, ...project };
95
+ }
96
+ return { ...globalBootstrap, ...projectBootstrap };
97
+ }
98
+ function resolveCliDotDirs(config) {
99
+ return resolverFromConfigs(config);
74
100
  }
75
101
  function mergeConfig(config, flags) {
76
102
  const cwd = flags.cwd ?? process.cwd();
@@ -370,7 +396,9 @@ async function runInit() {
370
396
  const config = { provider };
371
397
  if (model !== defaultModel) config.model = model;
372
398
  if (permissions !== "default") config.permissions = permissions;
373
- const dir = path2.join(process.cwd(), ".noumen");
399
+ const existing = loadCliConfig(process.cwd());
400
+ const resolver = resolveCliDotDirs(existing);
401
+ const dir = resolver.writePath(process.cwd());
374
402
  fs2.mkdirSync(dir, { recursive: true });
375
403
  const configPath = path2.join(dir, "config.json");
376
404
  fs2.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
@@ -532,7 +560,7 @@ async function runAgent(config) {
532
560
  const { createInterface: createInterface3 } = await import("readline/promises");
533
561
  const rl = createInterface3({ input: process.stdin, output: process.stderr, terminal: true });
534
562
  try {
535
- const { SUPPORTED_PROVIDERS: SUPPORTED_PROVIDERS2, isOllamaRunning: isOllamaRunning2, ollamaBaseURL: ollamaBaseURL2 } = await import("../provider-factory-TUHU3DIG.js");
563
+ const { SUPPORTED_PROVIDERS: SUPPORTED_PROVIDERS2, isOllamaRunning: isOllamaRunning2, ollamaBaseURL: ollamaBaseURL2 } = await import("../provider-factory-KNBSHXJ6.js");
536
564
  const providerAnswer = await rl.question(
537
565
  ` Provider (${SUPPORTED_PROVIDERS2.join(", ")}) [${chalk3.bold("ollama")}]: `
538
566
  );
@@ -589,9 +617,9 @@ async function runAgent(config) {
589
617
  return runAgent(config);
590
618
  }
591
619
  if (!config.model) {
592
- const { DEFAULT_MODELS: DEFAULT_MODELS2 } = await import("../provider-factory-TUHU3DIG.js");
620
+ const { DEFAULT_MODELS: DEFAULT_MODELS2 } = await import("../provider-factory-KNBSHXJ6.js");
593
621
  if (providerName === "ollama") {
594
- const { ollamaBaseURL: ollamaBaseURL2 } = await import("../provider-factory-TUHU3DIG.js");
622
+ const { ollamaBaseURL: ollamaBaseURL2 } = await import("../provider-factory-KNBSHXJ6.js");
595
623
  const models = await listLocalOllamaModels(ollamaBaseURL2());
596
624
  const preferred = DEFAULT_MODELS2[providerName];
597
625
  config.model = models.includes(preferred) ? preferred : models[0] ?? preferred;
@@ -626,14 +654,15 @@ async function runAgent(config) {
626
654
  lsp: config.lsp,
627
655
  hooks: config.hooks,
628
656
  webSearch: config.webSearch,
629
- sessionDir: config.sessionDir ?? ".noumen/sessions",
657
+ ...config.sessionDir ? { sessionDir: config.sessionDir } : {},
658
+ ...config.dotDirs ? { dotDirs: config.dotDirs } : {},
630
659
  projectContext: { cwd: config.cwd, homeDir: os2.homedir() },
631
660
  costTracking: { enabled: true },
632
661
  retry: true
633
662
  }
634
663
  });
635
664
  if (config.headless) {
636
- const { runHeadless } = await import("../headless-FFU2DESQ.js");
665
+ const { runHeadless } = await import("../headless-25DU4MJQ.js");
637
666
  await runHeadless(agent, config);
638
667
  return;
639
668
  }
@@ -655,8 +684,8 @@ async function runAgent(config) {
655
684
  }
656
685
  }
657
686
  async function runOneShot(agent, config) {
658
- const { startSpinner: startSpinner2 } = await import("../spinner-OJNR6NFO.js");
659
- const { isVisibleEvent: isVisibleEvent2 } = await import("../render-GRN4ZSSW.js");
687
+ const { startSpinner: startSpinner2 } = await import("../spinner-72JEISPK.js");
688
+ const { isVisibleEvent: isVisibleEvent2 } = await import("../render-4VEODRK7.js");
660
689
  const thread = await agent.createThread();
661
690
  const state = createRenderState();
662
691
  const runOpts = config.maxTurns ? { maxTurns: config.maxTurns } : void 0;
@@ -698,7 +727,11 @@ async function listSessions() {
698
727
  const agent = new Agent({
699
728
  provider,
700
729
  sandbox: UnsandboxedLocal({ cwd }),
701
- options: { cwd, sessionDir: merged.sessionDir ?? ".noumen/sessions" }
730
+ options: {
731
+ cwd,
732
+ ...merged.sessionDir ? { sessionDir: merged.sessionDir } : {},
733
+ ...merged.dotDirs ? { dotDirs: merged.dotDirs } : {}
734
+ }
702
735
  });
703
736
  const sessions = await agent.listSessions();
704
737
  if (sessions.length === 0) {
@@ -744,7 +777,8 @@ async function resumeSession(sessionId) {
744
777
  mcpServers: merged.mcpServers,
745
778
  lsp: merged.lsp,
746
779
  hooks: merged.hooks,
747
- sessionDir: merged.sessionDir ?? ".noumen/sessions",
780
+ ...merged.sessionDir ? { sessionDir: merged.sessionDir } : {},
781
+ ...merged.dotDirs ? { dotDirs: merged.dotDirs } : {},
748
782
  projectContext: { cwd, homeDir: os2.homedir() },
749
783
  costTracking: { enabled: true },
750
784
  retry: true
@@ -768,7 +802,7 @@ async function resumeSession(sessionId) {
768
802
  const { createInterface: createInterface3 } = await import("readline/promises");
769
803
  const rl = createInterface3({ input: process.stdin, output: process.stderr, terminal: true });
770
804
  const thread = await agent.resumeThread(match.sessionId);
771
- const { renderEvent: render, createRenderState: makeState } = await import("../render-GRN4ZSSW.js");
805
+ const { renderEvent: render, createRenderState: makeState } = await import("../render-4VEODRK7.js");
772
806
  process.stderr.write(chalk3.dim("Session resumed. Type a message to continue.\n\n"));
773
807
  try {
774
808
  while (true) {
@@ -815,7 +849,8 @@ async function runDoctor() {
815
849
  model: merged.model,
816
850
  mcpServers: merged.mcpServers,
817
851
  lsp: merged.lsp,
818
- sessionDir: merged.sessionDir ?? ".noumen/sessions"
852
+ ...merged.sessionDir ? { sessionDir: merged.sessionDir } : {},
853
+ ...merged.dotDirs ? { dotDirs: merged.dotDirs } : {}
819
854
  }
820
855
  });
821
856
  await agent.init();