noumen 0.2.0 → 0.3.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 (83) hide show
  1. package/README.md +95 -16
  2. package/dist/a2a/index.d.ts +5 -5
  3. package/dist/a2a/index.js +3 -3
  4. package/dist/a2a/index.js.map +1 -1
  5. package/dist/acp/index.d.ts +5 -5
  6. package/dist/acp/index.js +4 -4
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/{agent-BrkbZyOT.d.ts → agent-1nFVUP9E.d.ts} +319 -15
  9. package/dist/{cache-DVqaCX8v.d.ts → cache-DsRqxx6v.d.ts} +1 -1
  10. package/dist/{chunk-BGG2E6JD.js → chunk-3HEYCV26.js} +1 -1
  11. package/dist/chunk-3SK5GCI6.js +75 -0
  12. package/dist/chunk-3SK5GCI6.js.map +1 -0
  13. package/dist/{chunk-NBDFQYUZ.js → chunk-4HW6LN6D.js} +4784 -2411
  14. package/dist/chunk-4HW6LN6D.js.map +1 -0
  15. package/dist/{chunk-7ZMN7XJE.js → chunk-5JN4SPI7.js} +6 -6
  16. package/dist/chunk-5JN4SPI7.js.map +1 -0
  17. package/dist/{chunk-CPFHEPW4.js → chunk-CS6WNDCF.js} +73 -41
  18. package/dist/chunk-CS6WNDCF.js.map +1 -0
  19. package/dist/chunk-EKOGVTBT.js +472 -0
  20. package/dist/chunk-EKOGVTBT.js.map +1 -0
  21. package/dist/{chunk-KY6ZPWHO.js → chunk-HEQQQGK5.js} +47 -28
  22. package/dist/chunk-HEQQQGK5.js.map +1 -0
  23. package/dist/{chunk-QTJ7VTJY.js → chunk-HL6JCRZJ.js} +1599 -481
  24. package/dist/chunk-HL6JCRZJ.js.map +1 -0
  25. package/dist/chunk-L3L3FG5T.js +16 -0
  26. package/dist/chunk-L3L3FG5T.js.map +1 -0
  27. package/dist/cli/index.js +36 -30
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/client/index.d.ts +2 -2
  30. package/dist/{headless-Q7XHHZIW.js → headless-FFU2DESQ.js} +3 -4
  31. package/dist/headless-FFU2DESQ.js.map +1 -0
  32. package/dist/index.d.ts +218 -68
  33. package/dist/index.js +37 -23
  34. package/dist/lsp/index.d.ts +4 -4
  35. package/dist/mcp/index.d.ts +5 -5
  36. package/dist/mcp/index.js +2 -1
  37. package/dist/mcp/index.js.map +1 -1
  38. package/dist/{provider-factory-34MSWJZ3.js → provider-factory-KCLIF34X.js} +2 -2
  39. package/dist/providers/anthropic.d.ts +2 -2
  40. package/dist/providers/anthropic.js +5 -3
  41. package/dist/providers/anthropic.js.map +1 -1
  42. package/dist/providers/bedrock.d.ts +2 -2
  43. package/dist/providers/bedrock.js +5 -3
  44. package/dist/providers/bedrock.js.map +1 -1
  45. package/dist/providers/gemini.d.ts +2 -1
  46. package/dist/providers/gemini.js +133 -95
  47. package/dist/providers/gemini.js.map +1 -1
  48. package/dist/providers/ollama.d.ts +13 -0
  49. package/dist/{ollama-YNXAYP3R.js → providers/ollama.js} +6 -4
  50. package/dist/providers/ollama.js.map +1 -0
  51. package/dist/providers/openai.d.ts +4 -1
  52. package/dist/providers/openai.js +2 -1
  53. package/dist/providers/openrouter.d.ts +1 -1
  54. package/dist/providers/openrouter.js +2 -1
  55. package/dist/providers/openrouter.js.map +1 -1
  56. package/dist/providers/vertex.d.ts +4 -2
  57. package/dist/providers/vertex.js +6 -3
  58. package/dist/providers/vertex.js.map +1 -1
  59. package/dist/{resolve-XM52G7YE.js → resolve-4JA2BBDA.js} +2 -2
  60. package/dist/server/index.d.ts +35 -20
  61. package/dist/server/index.js +276 -207
  62. package/dist/server/index.js.map +1 -1
  63. package/dist/{server-Cg1yWGaV.d.ts → server-CHMxuWKq.d.ts} +1 -1
  64. package/dist/{types-DwdzmXfs.d.ts → types-CD0rUKKT.d.ts} +2 -0
  65. package/dist/{types-3c88cRKH.d.ts → types-LrU4LRmX.d.ts} +28 -0
  66. package/dist/{types-CwKKucOF.d.ts → types-RPKUTu1k.d.ts} +27 -2
  67. package/dist/uuid-RVN2T26F.js +8 -0
  68. package/dist/uuid-RVN2T26F.js.map +1 -0
  69. package/dist/zod-7YXKWYMC.js +12 -0
  70. package/dist/zod-7YXKWYMC.js.map +1 -0
  71. package/package.json +19 -13
  72. package/dist/chunk-2ZTGQLYK.js +0 -356
  73. package/dist/chunk-2ZTGQLYK.js.map +0 -1
  74. package/dist/chunk-7ZMN7XJE.js.map +0 -1
  75. package/dist/chunk-CPFHEPW4.js.map +0 -1
  76. package/dist/chunk-KY6ZPWHO.js.map +0 -1
  77. package/dist/chunk-NBDFQYUZ.js.map +0 -1
  78. package/dist/chunk-QTJ7VTJY.js.map +0 -1
  79. package/dist/headless-Q7XHHZIW.js.map +0 -1
  80. package/dist/ollama-YNXAYP3R.js.map +0 -1
  81. /package/dist/{chunk-BGG2E6JD.js.map → chunk-3HEYCV26.js.map} +0 -0
  82. /package/dist/{provider-factory-34MSWJZ3.js.map → provider-factory-KCLIF34X.js.map} +0 -0
  83. /package/dist/{resolve-XM52G7YE.js.map → resolve-4JA2BBDA.js.map} +0 -0
package/dist/index.js CHANGED
@@ -3,7 +3,6 @@ import {
3
3
  CLEARED_PLACEHOLDER,
4
4
  COMPACTABLE_TOOLS,
5
5
  CannotRetryError,
6
- ChatStreamError,
7
6
  CostTracker,
8
7
  DEFAULT_PRICING,
9
8
  DEFAULT_RETRY_CONFIG,
@@ -14,11 +13,14 @@ import {
14
13
  E2BComputer,
15
14
  E2BFs,
16
15
  E2BSandbox,
17
- FallbackTriggeredError,
18
16
  FileCheckpointManager,
19
17
  FileMemoryProvider,
20
18
  FileStateCache,
19
+ FreestyleComputer,
20
+ FreestyleFs,
21
+ FreestyleSandbox,
21
22
  InProcessBackend,
23
+ InvariantViolation,
22
24
  LocalComputer,
23
25
  LocalFs,
24
26
  LocalSandbox,
@@ -26,7 +28,6 @@ import {
26
28
  NoopSpan,
27
29
  NoopTracer,
28
30
  OTelTracer,
29
- RULE_SOURCE_PRECEDENCE,
30
31
  STRUCTURED_OUTPUT_TOOL_NAME,
31
32
  SandboxedLocalComputer,
32
33
  SpanStatusCode,
@@ -45,6 +46,7 @@ import {
45
46
  applyPermissionUpdate,
46
47
  applyPermissionUpdates,
47
48
  applyPersistedReplacements,
49
+ assertValidMessageSequence,
48
50
  buildExtractionPrompt,
49
51
  buildMemorySystemPromptSection,
50
52
  buildProjectContextSection,
@@ -52,10 +54,8 @@ import {
52
54
  calculateCost,
53
55
  canAutoCompact,
54
56
  classifyError,
55
- classifyPermission,
56
57
  codingAgent,
57
58
  compactConversation,
58
- contentMatchesRule,
59
59
  createAutoCompactConfig,
60
60
  createAutoCompactTracking,
61
61
  createBudgetState,
@@ -86,17 +86,15 @@ import {
86
86
  generateMissingToolResults,
87
87
  getActiveSkills,
88
88
  getLastCacheSafeParams,
89
- getMatchingRules,
90
89
  getRetryDelay,
91
90
  getWorktreeChanges,
92
91
  groupMessagesByTurn,
93
- isPathInWorkingDirectories,
94
92
  isRetryable,
95
93
  listWorktrees,
96
94
  loadProjectContext,
97
95
  loadSkills,
98
- matchSimpleGlob,
99
96
  microcompactMessages,
97
+ normalizeMessagesForAPI,
100
98
  parseAllowedTools,
101
99
  parseFrontmatter,
102
100
  parsePaths,
@@ -107,7 +105,6 @@ import {
107
105
  recordAutoCompactFailure,
108
106
  recordAutoCompactSuccess,
109
107
  removeWorktree,
110
- resolvePermission,
111
108
  restoreSession,
112
109
  reviewAgent,
113
110
  runNotificationHooks,
@@ -124,19 +121,23 @@ import {
124
121
  taskListTool,
125
122
  taskUpdateTool,
126
123
  tokenCountWithEstimation,
127
- toolMatchesRule,
128
124
  truncateHeadForPTLRetry,
129
125
  truncateIndex,
130
126
  tryReactiveCompact,
131
127
  webSearchToolPlaceholder,
132
128
  withRetry
133
- } from "./chunk-NBDFQYUZ.js";
129
+ } from "./chunk-4HW6LN6D.js";
130
+ import {
131
+ applySnipRemovals,
132
+ projectSnippedView,
133
+ snipMessagesByUuids
134
+ } from "./chunk-42PHHZUA.js";
134
135
  import {
135
136
  DEFAULT_MODELS,
136
137
  SUPPORTED_PROVIDERS,
137
138
  detectProvider,
138
139
  resolveProvider
139
- } from "./chunk-7ZMN7XJE.js";
140
+ } from "./chunk-5JN4SPI7.js";
140
141
  import {
141
142
  getAutoCompactThreshold,
142
143
  getContextWindowForModel,
@@ -144,20 +145,21 @@ import {
144
145
  getMessageCacheBreakpointIndex,
145
146
  registerContextWindows,
146
147
  sortToolDefinitionsForCache
147
- } from "./chunk-KY6ZPWHO.js";
148
+ } from "./chunk-HEQQQGK5.js";
148
149
  import {
149
- applySnipRemovals,
150
- projectSnippedView,
151
- snipMessagesByUuids
152
- } from "./chunk-42PHHZUA.js";
153
- import "./chunk-BGG2E6JD.js";
150
+ ChatStreamError
151
+ } from "./chunk-L3L3FG5T.js";
152
+ import "./chunk-3HEYCV26.js";
154
153
  import {
154
+ RULE_SOURCE_PRECEDENCE,
155
155
  TOOL_SEARCH_NAME,
156
156
  ToolRegistry,
157
157
  askUserTool,
158
158
  bashTool,
159
159
  classifyCommand,
160
+ classifyPermission,
160
161
  commandWritesGitInternals,
162
+ contentMatchesRule,
161
163
  countOccurrences,
162
164
  createToolSearchTool,
163
165
  detectGitOperations,
@@ -165,25 +167,32 @@ import {
165
167
  extractCommandName,
166
168
  findActualString,
167
169
  formatDeferredToolLine,
168
- formatZodValidationError,
170
+ getMatchingRules,
169
171
  globTool,
170
172
  grepTool,
171
173
  hasGitIndexLockError,
172
174
  isDeferredTool,
173
175
  isGitInternalPath,
176
+ isPathInWorkingDirectories,
174
177
  looksLikeBareRepo,
178
+ matchSimpleGlob,
175
179
  normalizeQuotes,
176
180
  notebookEditTool,
177
181
  preserveQuoteStyle,
178
182
  readFileTool,
179
- registerZodToJsonSchema,
183
+ resolvePermission,
180
184
  resolveToolFlag,
181
185
  searchToolsWithKeywords,
182
186
  stripTrailingWhitespace,
187
+ toolMatchesRule,
183
188
  webFetchTool,
184
- writeFileTool,
189
+ writeFileTool
190
+ } from "./chunk-HL6JCRZJ.js";
191
+ import {
192
+ formatZodValidationError,
193
+ registerZodToJsonSchema,
185
194
  zodToJsonSchema
186
- } from "./chunk-QTJ7VTJY.js";
195
+ } from "./chunk-3SK5GCI6.js";
187
196
  import {
188
197
  API_IMAGE_MAX_BASE64_SIZE,
189
198
  IMAGE_EXTENSIONS,
@@ -225,14 +234,17 @@ export {
225
234
  E2BComputer,
226
235
  E2BFs,
227
236
  E2BSandbox,
228
- FallbackTriggeredError,
229
237
  FileCheckpointManager,
230
238
  FileMemoryProvider,
231
239
  FileStateCache,
240
+ FreestyleComputer,
241
+ FreestyleFs,
242
+ FreestyleSandbox,
232
243
  IMAGE_EXTENSIONS,
233
244
  IMAGE_MAX_HEIGHT,
234
245
  IMAGE_MAX_WIDTH,
235
246
  InProcessBackend,
247
+ InvariantViolation,
236
248
  LocalComputer,
237
249
  LocalFs,
238
250
  LocalSandbox,
@@ -264,6 +276,7 @@ export {
264
276
  applyPersistedReplacements,
265
277
  applySnipRemovals,
266
278
  askUserTool,
279
+ assertValidMessageSequence,
267
280
  bashTool,
268
281
  buildExtractionPrompt,
269
282
  buildMcpToolName,
@@ -347,6 +360,7 @@ export {
347
360
  maybeResizeAndDownsampleImageBuffer,
348
361
  microcompactMessages,
349
362
  normalizeContent,
363
+ normalizeMessagesForAPI,
350
364
  normalizeNameForMCP,
351
365
  normalizeQuotes,
352
366
  notebookEditTool,
@@ -1,7 +1,7 @@
1
- import { L as LspServerConfig, a as LspServerState, b as LspDiagnostic, T as Tool } from '../types-CwKKucOF.js';
2
- export { D as DiagnosticRegistry, c as LspLocation, d as LspOperation, e as LspServerManager, f as LspSymbol } from '../types-CwKKucOF.js';
3
- import '../types-3c88cRKH.js';
4
- import '../types-DwdzmXfs.js';
1
+ import { L as LspServerConfig, a as LspServerState, b as LspDiagnostic, T as Tool } from '../types-RPKUTu1k.js';
2
+ export { D as DiagnosticRegistry, c as LspLocation, d as LspOperation, e as LspServerManager, f as LspSymbol } from '../types-RPKUTu1k.js';
3
+ import '../types-LrU4LRmX.js';
4
+ import '../types-CD0rUKKT.js';
5
5
 
6
6
  interface ServerCapabilities {
7
7
  definitionProvider?: boolean;
@@ -1,15 +1,15 @@
1
- import { M as McpClientManager } from '../server-Cg1yWGaV.js';
2
- export { a as McpClientManagerOptions, b as McpServerOptions, c as buildMcpToolName, d as createMcpServer, g as getMcpPrefix, n as normalizeNameForMCP, p as parseMcpToolName } from '../server-Cg1yWGaV.js';
1
+ import { M as McpClientManager } from '../server-CHMxuWKq.js';
2
+ export { a as McpClientManagerOptions, b as McpServerOptions, c as buildMcpToolName, d as createMcpServer, g as getMcpPrefix, n as normalizeNameForMCP, p as parseMcpToolName } from '../server-CHMxuWKq.js';
3
3
  import { T as TokenStorage, O as OAuthTokenData, a as OAuthProviderOptions } from '../types-2kTLUCnD.js';
4
4
  export { b as McpConfig, c as McpConnection, d as McpHttpServerConfig, e as McpOAuthConfig, M as McpServerConfig, f as McpSseServerConfig, g as McpStdioServerConfig, h as McpToolInfo, i as McpWebSocketServerConfig } from '../types-2kTLUCnD.js';
5
5
  import { OAuthClientProvider, OAuthDiscoveryState } from '@modelcontextprotocol/sdk/client/auth.js';
6
6
  export { OAuthClientProvider, OAuthDiscoveryState } from '@modelcontextprotocol/sdk/client/auth.js';
7
7
  import { OAuthClientMetadata, OAuthClientInformationMixed, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
8
8
  export { OAuthClientInformation, OAuthClientInformationFull, OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
9
- import { T as Tool } from '../types-CwKKucOF.js';
9
+ import { T as Tool } from '../types-RPKUTu1k.js';
10
10
  import '@modelcontextprotocol/sdk/client/index.js';
11
- import '../types-3c88cRKH.js';
12
- import '../types-DwdzmXfs.js';
11
+ import '../types-LrU4LRmX.js';
12
+ import '../types-CD0rUKKT.js';
13
13
 
14
14
  /**
15
15
  * In-memory token storage. Suitable for tests, short-lived processes,
package/dist/mcp/index.js CHANGED
@@ -11,7 +11,8 @@ import {
11
11
  } from "../chunk-BZSFUEWM.js";
12
12
  import {
13
13
  ToolRegistry
14
- } from "../chunk-QTJ7VTJY.js";
14
+ } from "../chunk-HL6JCRZJ.js";
15
+ import "../chunk-3SK5GCI6.js";
15
16
  import "../chunk-5GEX6ZSB.js";
16
17
  import {
17
18
  buildMcpToolName,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/mcp/server.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n type CallToolResult,\n type ListToolsResult,\n type Tool as McpSdkTool,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Tool, ToolContext } from \"../tools/types.js\";\nimport { ToolRegistry } from \"../tools/registry.js\";\nimport { contentToString } from \"../utils/content.js\";\n\nexport interface McpServerOptions {\n /** Additional tools beyond the 6 built-ins */\n tools?: Tool[];\n /** Context passed to tool.call() for all invocations */\n toolContext: ToolContext;\n /** Server name reported to clients */\n name?: string;\n /** Server version reported to clients */\n version?: string;\n}\n\n/**\n * Start an MCP server over stdio that exposes noumen's tools.\n * This is the entry point for `noumen mcp` or similar CLI integrations.\n */\nexport async function createMcpServer(opts: McpServerOptions): Promise<void> {\n const registry = new ToolRegistry(opts.tools);\n\n const server = new Server(\n { name: opts.name ?? \"noumen\", version: opts.version ?? \"0.1.0\" },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(\n ListToolsRequestSchema,\n async (): Promise<ListToolsResult> => {\n const tools = registry.listTools();\n return {\n tools: tools.map(\n (tool): McpSdkTool => ({\n name: tool.name,\n description: tool.description,\n inputSchema: {\n type: \"object\" as const,\n properties: tool.parameters.properties as Record<string, object>,\n ...(tool.parameters.required\n ? { required: tool.parameters.required }\n : {}),\n },\n }),\n ),\n };\n },\n );\n\n server.setRequestHandler(\n CallToolRequestSchema,\n async ({ params: { name, arguments: args } }): Promise<CallToolResult> => {\n const tool = registry.get(name);\n if (!tool) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Unknown tool: ${name}` }],\n };\n }\n\n try {\n const result = await tool.call(\n (args as Record<string, unknown>) ?? {},\n opts.toolContext,\n );\n return {\n isError: result.isError,\n content: [{ type: \"text\", text: contentToString(result.content) }],\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: message }],\n };\n }\n },\n );\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAoBP,eAAsB,gBAAgB,MAAuC;AAC3E,QAAM,WAAW,IAAI,aAAa,KAAK,KAAK;AAE5C,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,KAAK,QAAQ,UAAU,SAAS,KAAK,WAAW,QAAQ;AAAA,IAChE,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EAChC;AAEA,SAAO;AAAA,IACL;AAAA,IACA,YAAsC;AACpC,YAAM,QAAQ,SAAS,UAAU;AACjC,aAAO;AAAA,QACL,OAAO,MAAM;AAAA,UACX,CAAC,UAAsB;AAAA,YACrB,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB,aAAa;AAAA,cACX,MAAM;AAAA,cACN,YAAY,KAAK,WAAW;AAAA,cAC5B,GAAI,KAAK,WAAW,WAChB,EAAE,UAAU,KAAK,WAAW,SAAS,IACrC,CAAC;AAAA,YACP;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,KAAK,EAAE,MAA+B;AACxE,YAAM,OAAO,SAAS,IAAI,IAAI;AAC9B,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,GAAG,CAAC;AAAA,QAC3D;AAAA,MACF;AAEA,UAAI;AACF,cAAM,SAAS,MAAM,KAAK;AAAA,UACvB,QAAoC,CAAC;AAAA,UACtC,KAAK;AAAA,QACP;AACA,eAAO;AAAA,UACL,SAAS,OAAO;AAAA,UAChB,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,gBAAgB,OAAO,OAAO,EAAE,CAAC;AAAA,QACnE;AAAA,MACF,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;","names":[]}
1
+ {"version":3,"sources":["../../src/mcp/server.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n type CallToolResult,\n type ListToolsResult,\n type Tool as McpSdkTool,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Tool, ToolContext } from \"../tools/types.js\";\nimport { ToolRegistry } from \"../tools/registry.js\";\nimport { contentToString } from \"../utils/content.js\";\n\nexport interface McpServerOptions {\n /** Additional tools beyond the 6 built-ins */\n tools?: Tool[];\n /** Context passed to tool.call() for all invocations */\n toolContext: ToolContext;\n /** Server name reported to clients */\n name?: string;\n /** Server version reported to clients */\n version?: string;\n}\n\n/**\n * Start an MCP server over stdio that exposes noumen's tools.\n * This is the entry point for `noumen mcp` or similar CLI integrations.\n */\nexport async function createMcpServer(opts: McpServerOptions): Promise<void> {\n const registry = new ToolRegistry(opts.tools);\n\n const server = new Server(\n { name: opts.name ?? \"noumen\", version: opts.version ?? \"0.1.0\" },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(\n ListToolsRequestSchema,\n async (): Promise<ListToolsResult> => {\n const tools = registry.listTools();\n return {\n tools: tools.map(\n (tool): McpSdkTool => ({\n name: tool.name,\n description: tool.description,\n inputSchema: {\n type: \"object\" as const,\n properties: tool.parameters.properties as Record<string, object>,\n ...(tool.parameters.required\n ? { required: tool.parameters.required }\n : {}),\n },\n }),\n ),\n };\n },\n );\n\n server.setRequestHandler(\n CallToolRequestSchema,\n async ({ params: { name, arguments: args } }): Promise<CallToolResult> => {\n const tool = registry.get(name);\n if (!tool) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Unknown tool: ${name}` }],\n };\n }\n\n try {\n const result = await tool.call(\n (args as Record<string, unknown>) ?? {},\n opts.toolContext,\n );\n return {\n isError: result.isError,\n content: [{ type: \"text\", text: contentToString(result.content) }],\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: message }],\n };\n }\n },\n );\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAoBP,eAAsB,gBAAgB,MAAuC;AAC3E,QAAM,WAAW,IAAI,aAAa,KAAK,KAAK;AAE5C,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,KAAK,QAAQ,UAAU,SAAS,KAAK,WAAW,QAAQ;AAAA,IAChE,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EAChC;AAEA,SAAO;AAAA,IACL;AAAA,IACA,YAAsC;AACpC,YAAM,QAAQ,SAAS,UAAU;AACjC,aAAO;AAAA,QACL,OAAO,MAAM;AAAA,UACX,CAAC,UAAsB;AAAA,YACrB,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB,aAAa;AAAA,cACX,MAAM;AAAA,cACN,YAAY,KAAK,WAAW;AAAA,cAC5B,GAAI,KAAK,WAAW,WAChB,EAAE,UAAU,KAAK,WAAW,SAAS,IACrC,CAAC;AAAA,YACP;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,KAAK,EAAE,MAA+B;AACxE,YAAM,OAAO,SAAS,IAAI,IAAI;AAC9B,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,GAAG,CAAC;AAAA,QAC3D;AAAA,MACF;AAEA,UAAI;AACF,cAAM,SAAS,MAAM,KAAK;AAAA,UACvB,QAAoC,CAAC;AAAA,UACtC,KAAK;AAAA,QACP;AACA,eAAO;AAAA,UACL,SAAS,OAAO;AAAA,UAChB,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,gBAAgB,OAAO,OAAO,EAAE,CAAC;AAAA,QACnE;AAAA,MACF,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;","names":[]}
@@ -7,7 +7,7 @@ import {
7
7
  SUPPORTED_PROVIDERS,
8
8
  detectProvider,
9
9
  resolveProvider
10
- } from "./chunk-7ZMN7XJE.js";
10
+ } from "./chunk-5JN4SPI7.js";
11
11
  import "./chunk-DGUM43GV.js";
12
12
  export {
13
13
  DEFAULT_MODELS,
@@ -17,4 +17,4 @@ export {
17
17
  isOllamaRunning,
18
18
  ollamaBaseURL
19
19
  };
20
- //# sourceMappingURL=provider-factory-34MSWJZ3.js.map
20
+ //# sourceMappingURL=provider-factory-KCLIF34X.js.map
@@ -1,5 +1,5 @@
1
- import { A as AIProvider, C as ChatParams, a as ChatStreamChunk } from '../types-3c88cRKH.js';
2
- import { C as CacheControlConfig } from '../cache-DVqaCX8v.js';
1
+ import { A as AIProvider, C as ChatParams, a as ChatStreamChunk } from '../types-LrU4LRmX.js';
2
+ import { C as CacheControlConfig } from '../cache-DsRqxx6v.js';
3
3
 
4
4
  interface AnthropicProviderOptions {
5
5
  apiKey: string;
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  streamAnthropicChat
3
- } from "../chunk-2ZTGQLYK.js";
4
- import "../chunk-KY6ZPWHO.js";
3
+ } from "../chunk-EKOGVTBT.js";
4
+ import "../chunk-HEQQQGK5.js";
5
+ import "../chunk-L3L3FG5T.js";
5
6
  import "../chunk-DGUM43GV.js";
6
7
 
7
8
  // src/providers/anthropic.ts
@@ -13,7 +14,8 @@ var AnthropicProvider = class {
13
14
  constructor(opts) {
14
15
  this.client = new Anthropic({
15
16
  apiKey: opts.apiKey,
16
- baseURL: opts.baseURL
17
+ baseURL: opts.baseURL,
18
+ maxRetries: 0
17
19
  });
18
20
  this.defaultModel = opts.model ?? "claude-opus-4.6";
19
21
  this.cacheConfig = opts.cacheControl;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/anthropic.ts"],"sourcesContent":["import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n AIProvider,\n ChatParams,\n ChatStreamChunk,\n} from \"./types.js\";\nimport type { CacheControlConfig } from \"./cache.js\";\nimport { streamAnthropicChat, type AnthropicStreamClient } from \"./anthropic-shared.js\";\n\nexport interface AnthropicProviderOptions {\n apiKey: string;\n baseURL?: string;\n model?: string;\n /** When enabled, injects cache_control markers on system prompt, tools, and messages. */\n cacheControl?: CacheControlConfig;\n}\n\nexport class AnthropicProvider implements AIProvider {\n private client: Anthropic;\n private defaultModel: string;\n private cacheConfig: CacheControlConfig | undefined;\n\n constructor(opts: AnthropicProviderOptions) {\n this.client = new Anthropic({\n apiKey: opts.apiKey,\n baseURL: opts.baseURL,\n });\n this.defaultModel = opts.model ?? \"claude-opus-4.6\";\n this.cacheConfig = opts.cacheControl;\n }\n\n async *chat(params: ChatParams): AsyncIterable<ChatStreamChunk> {\n yield* streamAnthropicChat(\n this.client as unknown as AnthropicStreamClient,\n params,\n this.defaultModel,\n this.cacheConfig,\n );\n }\n}\n"],"mappings":";;;;;;;AAAA,OAAO,eAAe;AAiBf,IAAM,oBAAN,MAA8C;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,MAAgC;AAC1C,SAAK,SAAS,IAAI,UAAU;AAAA,MAC1B,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,IAChB,CAAC;AACD,SAAK,eAAe,KAAK,SAAS;AAClC,SAAK,cAAc,KAAK;AAAA,EAC1B;AAAA,EAEA,OAAO,KAAK,QAAoD;AAC9D,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/providers/anthropic.ts"],"sourcesContent":["import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n AIProvider,\n ChatParams,\n ChatStreamChunk,\n} from \"./types.js\";\nimport type { CacheControlConfig } from \"./cache.js\";\nimport { streamAnthropicChat, type AnthropicStreamClient } from \"./anthropic-shared.js\";\n\nexport interface AnthropicProviderOptions {\n apiKey: string;\n baseURL?: string;\n model?: string;\n /** When enabled, injects cache_control markers on system prompt, tools, and messages. */\n cacheControl?: CacheControlConfig;\n}\n\nexport class AnthropicProvider implements AIProvider {\n private client: Anthropic;\n private defaultModel: string;\n private cacheConfig: CacheControlConfig | undefined;\n\n constructor(opts: AnthropicProviderOptions) {\n this.client = new Anthropic({\n apiKey: opts.apiKey,\n baseURL: opts.baseURL,\n maxRetries: 0,\n });\n this.defaultModel = opts.model ?? \"claude-opus-4.6\";\n this.cacheConfig = opts.cacheControl;\n }\n\n async *chat(params: ChatParams): AsyncIterable<ChatStreamChunk> {\n yield* streamAnthropicChat(\n this.client as unknown as AnthropicStreamClient,\n params,\n this.defaultModel,\n this.cacheConfig,\n );\n }\n}\n"],"mappings":";;;;;;;;AAAA,OAAO,eAAe;AAiBf,IAAM,oBAAN,MAA8C;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,MAAgC;AAC1C,SAAK,SAAS,IAAI,UAAU;AAAA,MAC1B,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,YAAY;AAAA,IACd,CAAC;AACD,SAAK,eAAe,KAAK,SAAS;AAClC,SAAK,cAAc,KAAK;AAAA,EAC1B;AAAA,EAEA,OAAO,KAAK,QAAoD;AAC9D,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AACF;","names":[]}
@@ -1,5 +1,5 @@
1
- import { A as AIProvider, C as ChatParams, a as ChatStreamChunk } from '../types-3c88cRKH.js';
2
- import { C as CacheControlConfig } from '../cache-DVqaCX8v.js';
1
+ import { A as AIProvider, C as ChatParams, a as ChatStreamChunk } from '../types-LrU4LRmX.js';
2
+ import { C as CacheControlConfig } from '../cache-DsRqxx6v.js';
3
3
 
4
4
  interface BedrockAnthropicProviderOptions {
5
5
  /** AWS region (default: us-east-1). */
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  streamAnthropicChat
3
- } from "../chunk-2ZTGQLYK.js";
4
- import "../chunk-KY6ZPWHO.js";
3
+ } from "../chunk-EKOGVTBT.js";
4
+ import "../chunk-HEQQQGK5.js";
5
+ import "../chunk-L3L3FG5T.js";
5
6
  import {
6
7
  __require
7
8
  } from "../chunk-DGUM43GV.js";
@@ -24,7 +25,8 @@ var BedrockAnthropicProvider = class {
24
25
  );
25
26
  }
26
27
  const args = {
27
- awsRegion: opts.region ?? "us-east-1"
28
+ awsRegion: opts.region ?? "us-east-1",
29
+ maxRetries: 0
28
30
  };
29
31
  if (opts.baseURL) args.baseURL = opts.baseURL;
30
32
  if (opts.credentials) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/bedrock.ts"],"sourcesContent":["import type {\n AIProvider,\n ChatParams,\n ChatStreamChunk,\n} from \"./types.js\";\nimport type { CacheControlConfig } from \"./cache.js\";\nimport { streamAnthropicChat, type AnthropicStreamClient } from \"./anthropic-shared.js\";\n\nexport interface BedrockAnthropicProviderOptions {\n /** AWS region (default: us-east-1). */\n region?: string;\n /** Explicit AWS credentials. If omitted, the SDK uses the default credential chain. */\n credentials?: {\n accessKeyId: string;\n secretAccessKey: string;\n sessionToken?: string;\n };\n /** Model ID in Bedrock format (default: us.anthropic.claude-opus-4.6-v1:0). */\n model?: string;\n /** Custom base URL for a Bedrock-compatible endpoint. */\n baseURL?: string;\n /** Cache control config (same as AnthropicProvider). */\n cacheControl?: CacheControlConfig;\n /**\n * Pre-constructed AnthropicBedrock client. When provided, all other\n * connection options are ignored. Useful for testing or advanced setups.\n */\n client?: unknown;\n}\n\n/**\n * Anthropic provider routed through AWS Bedrock.\n *\n * Requires `@anthropic-ai/bedrock-sdk` as an optional peer dependency.\n * Install it with: `pnpm add @anthropic-ai/bedrock-sdk`\n */\nexport class BedrockAnthropicProvider implements AIProvider {\n private client: AnthropicStreamClient;\n private defaultModel: string;\n private cacheConfig: CacheControlConfig | undefined;\n\n constructor(opts: BedrockAnthropicProviderOptions) {\n if (opts.client) {\n this.client = opts.client as AnthropicStreamClient;\n } else {\n let AnthropicBedrock: new (args: Record<string, unknown>) => unknown;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n AnthropicBedrock = require(\"@anthropic-ai/bedrock-sdk\").AnthropicBedrock;\n } catch {\n throw new Error(\n \"BedrockAnthropicProvider requires @anthropic-ai/bedrock-sdk. \" +\n \"Install it with: pnpm add @anthropic-ai/bedrock-sdk\",\n );\n }\n\n const args: Record<string, unknown> = {\n awsRegion: opts.region ?? \"us-east-1\",\n };\n if (opts.baseURL) args.baseURL = opts.baseURL;\n if (opts.credentials) {\n args.awsAccessKey = opts.credentials.accessKeyId;\n args.awsSecretKey = opts.credentials.secretAccessKey;\n if (opts.credentials.sessionToken) {\n args.awsSessionToken = opts.credentials.sessionToken;\n }\n }\n\n this.client = new AnthropicBedrock(args) as unknown as AnthropicStreamClient;\n }\n\n this.defaultModel =\n opts.model ?? \"us.anthropic.claude-opus-4.6-v1:0\";\n this.cacheConfig = opts.cacheControl;\n }\n\n async *chat(params: ChatParams): AsyncIterable<ChatStreamChunk> {\n yield* streamAnthropicChat(\n this.client,\n params,\n this.defaultModel,\n this.cacheConfig,\n );\n }\n}\n"],"mappings":";;;;;;;;;AAoCO,IAAM,2BAAN,MAAqD;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,MAAuC;AACjD,QAAI,KAAK,QAAQ;AACf,WAAK,SAAS,KAAK;AAAA,IACrB,OAAO;AACL,UAAI;AACJ,UAAI;AAEF,2BAAmB,UAAQ,2BAA2B,EAAE;AAAA,MAC1D,QAAQ;AACN,cAAM,IAAI;AAAA,UACR;AAAA,QAEF;AAAA,MACF;AAEA,YAAM,OAAgC;AAAA,QACpC,WAAW,KAAK,UAAU;AAAA,MAC5B;AACA,UAAI,KAAK,QAAS,MAAK,UAAU,KAAK;AACtC,UAAI,KAAK,aAAa;AACpB,aAAK,eAAe,KAAK,YAAY;AACrC,aAAK,eAAe,KAAK,YAAY;AACrC,YAAI,KAAK,YAAY,cAAc;AACjC,eAAK,kBAAkB,KAAK,YAAY;AAAA,QAC1C;AAAA,MACF;AAEA,WAAK,SAAS,IAAI,iBAAiB,IAAI;AAAA,IACzC;AAEA,SAAK,eACH,KAAK,SAAS;AAChB,SAAK,cAAc,KAAK;AAAA,EAC1B;AAAA,EAEA,OAAO,KAAK,QAAoD;AAC9D,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/providers/bedrock.ts"],"sourcesContent":["import type {\n AIProvider,\n ChatParams,\n ChatStreamChunk,\n} from \"./types.js\";\nimport type { CacheControlConfig } from \"./cache.js\";\nimport { streamAnthropicChat, type AnthropicStreamClient } from \"./anthropic-shared.js\";\n\nexport interface BedrockAnthropicProviderOptions {\n /** AWS region (default: us-east-1). */\n region?: string;\n /** Explicit AWS credentials. If omitted, the SDK uses the default credential chain. */\n credentials?: {\n accessKeyId: string;\n secretAccessKey: string;\n sessionToken?: string;\n };\n /** Model ID in Bedrock format (default: us.anthropic.claude-opus-4.6-v1:0). */\n model?: string;\n /** Custom base URL for a Bedrock-compatible endpoint. */\n baseURL?: string;\n /** Cache control config (same as AnthropicProvider). */\n cacheControl?: CacheControlConfig;\n /**\n * Pre-constructed AnthropicBedrock client. When provided, all other\n * connection options are ignored. Useful for testing or advanced setups.\n */\n client?: unknown;\n}\n\n/**\n * Anthropic provider routed through AWS Bedrock.\n *\n * Requires `@anthropic-ai/bedrock-sdk` as an optional peer dependency.\n * Install it with: `pnpm add @anthropic-ai/bedrock-sdk`\n */\nexport class BedrockAnthropicProvider implements AIProvider {\n private client: AnthropicStreamClient;\n private defaultModel: string;\n private cacheConfig: CacheControlConfig | undefined;\n\n constructor(opts: BedrockAnthropicProviderOptions) {\n if (opts.client) {\n this.client = opts.client as AnthropicStreamClient;\n } else {\n let AnthropicBedrock: new (args: Record<string, unknown>) => unknown;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n AnthropicBedrock = require(\"@anthropic-ai/bedrock-sdk\").AnthropicBedrock;\n } catch {\n throw new Error(\n \"BedrockAnthropicProvider requires @anthropic-ai/bedrock-sdk. \" +\n \"Install it with: pnpm add @anthropic-ai/bedrock-sdk\",\n );\n }\n\n const args: Record<string, unknown> = {\n awsRegion: opts.region ?? \"us-east-1\",\n maxRetries: 0,\n };\n if (opts.baseURL) args.baseURL = opts.baseURL;\n if (opts.credentials) {\n args.awsAccessKey = opts.credentials.accessKeyId;\n args.awsSecretKey = opts.credentials.secretAccessKey;\n if (opts.credentials.sessionToken) {\n args.awsSessionToken = opts.credentials.sessionToken;\n }\n }\n\n this.client = new AnthropicBedrock(args) as unknown as AnthropicStreamClient;\n }\n\n this.defaultModel =\n opts.model ?? \"us.anthropic.claude-opus-4.6-v1:0\";\n this.cacheConfig = opts.cacheControl;\n }\n\n async *chat(params: ChatParams): AsyncIterable<ChatStreamChunk> {\n yield* streamAnthropicChat(\n this.client,\n params,\n this.defaultModel,\n this.cacheConfig,\n );\n }\n}\n"],"mappings":";;;;;;;;;;AAoCO,IAAM,2BAAN,MAAqD;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,MAAuC;AACjD,QAAI,KAAK,QAAQ;AACf,WAAK,SAAS,KAAK;AAAA,IACrB,OAAO;AACL,UAAI;AACJ,UAAI;AAEF,2BAAmB,UAAQ,2BAA2B,EAAE;AAAA,MAC1D,QAAQ;AACN,cAAM,IAAI;AAAA,UACR;AAAA,QAEF;AAAA,MACF;AAEA,YAAM,OAAgC;AAAA,QACpC,WAAW,KAAK,UAAU;AAAA,QAC1B,YAAY;AAAA,MACd;AACA,UAAI,KAAK,QAAS,MAAK,UAAU,KAAK;AACtC,UAAI,KAAK,aAAa;AACpB,aAAK,eAAe,KAAK,YAAY;AACrC,aAAK,eAAe,KAAK,YAAY;AACrC,YAAI,KAAK,YAAY,cAAc;AACjC,eAAK,kBAAkB,KAAK,YAAY;AAAA,QAC1C;AAAA,MACF;AAEA,WAAK,SAAS,IAAI,iBAAiB,IAAI;AAAA,IACzC;AAEA,SAAK,eACH,KAAK,SAAS;AAChB,SAAK,cAAc,KAAK;AAAA,EAC1B;AAAA,EAEA,OAAO,KAAK,QAAoD;AAC9D,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AACF;","names":[]}
@@ -1,8 +1,9 @@
1
- import { A as AIProvider, C as ChatParams, a as ChatStreamChunk } from '../types-3c88cRKH.js';
1
+ import { A as AIProvider, C as ChatParams, a as ChatStreamChunk } from '../types-LrU4LRmX.js';
2
2
 
3
3
  interface GeminiProviderOptions {
4
4
  apiKey: string;
5
5
  model?: string;
6
+ baseURL?: string;
6
7
  }
7
8
  declare class GeminiProvider implements AIProvider {
8
9
  private client;
@@ -1,3 +1,6 @@
1
+ import {
2
+ ChatStreamError
3
+ } from "../chunk-L3L3FG5T.js";
1
4
  import "../chunk-DGUM43GV.js";
2
5
 
3
6
  // src/providers/gemini.ts
@@ -6,7 +9,9 @@ var GeminiProvider = class _GeminiProvider {
6
9
  client;
7
10
  defaultModel;
8
11
  constructor(opts) {
9
- this.client = new GoogleGenAI({ apiKey: opts.apiKey });
12
+ const clientOpts = { apiKey: opts.apiKey };
13
+ if (opts.baseURL) clientOpts.httpOptions = { baseUrl: opts.baseURL };
14
+ this.client = new GoogleGenAI(clientOpts);
10
15
  this.defaultModel = opts.model ?? "gemini-2.5-flash";
11
16
  }
12
17
  async *chat(params) {
@@ -40,108 +45,137 @@ var GeminiProvider = class _GeminiProvider {
40
45
  } else if (params.outputFormat?.type === "json_object") {
41
46
  config.responseMimeType = "application/json";
42
47
  }
43
- const stream = await this.client.models.generateContentStream({
44
- model: params.model ?? this.defaultModel,
45
- contents,
46
- config
47
- });
48
- let chunkIndex = 0;
49
- let toolCallIndex = 0;
50
- let lastUsage;
51
- for await (const chunk of stream) {
52
- const chunkId = `gemini-${chunkIndex++}`;
53
- const model = params.model ?? this.defaultModel;
54
- const meta = chunk.usageMetadata;
55
- if (meta) {
56
- const prompt = meta.promptTokenCount ?? 0;
57
- const completion = meta.candidatesTokenCount ?? 0;
58
- lastUsage = {
59
- prompt_tokens: prompt,
60
- completion_tokens: completion,
61
- total_tokens: meta.totalTokenCount ?? prompt + completion,
62
- thinking_tokens: meta.thoughtsTokenCount || void 0
63
- };
64
- }
65
- const candidates = chunk.candidates;
66
- if (!candidates || candidates.length === 0) continue;
67
- const parts = candidates[0].content?.parts;
68
- if (!parts) continue;
69
- for (const part of parts) {
70
- if (part.thought && part.text !== void 0 && part.text !== null) {
71
- yield {
72
- id: chunkId,
73
- model,
74
- choices: [
75
- {
76
- index: 0,
77
- delta: { thinking_content: part.text },
78
- finish_reason: null
79
- }
80
- ]
48
+ if (params.signal) {
49
+ config.httpOptions = {
50
+ ...config.httpOptions ?? {},
51
+ signal: params.signal
52
+ };
53
+ }
54
+ try {
55
+ const stream = await this.client.models.generateContentStream({
56
+ model: params.model ?? this.defaultModel,
57
+ contents,
58
+ config
59
+ });
60
+ let chunkIndex = 0;
61
+ let toolCallIndex = 0;
62
+ let responseHasToolCalls = false;
63
+ let finishReasonSeen = false;
64
+ let lastUsage;
65
+ for await (const chunk of stream) {
66
+ const chunkId = `gemini-${chunkIndex++}`;
67
+ const model = params.model ?? this.defaultModel;
68
+ const meta = chunk.usageMetadata;
69
+ if (meta) {
70
+ const prompt = meta.promptTokenCount ?? 0;
71
+ const completion = meta.candidatesTokenCount ?? 0;
72
+ lastUsage = {
73
+ prompt_tokens: prompt,
74
+ completion_tokens: completion,
75
+ total_tokens: meta.totalTokenCount ?? prompt + completion,
76
+ thinking_tokens: meta.thoughtsTokenCount || void 0
81
77
  };
82
- continue;
83
78
  }
84
- if (part.text !== void 0 && part.text !== null) {
85
- yield {
86
- id: chunkId,
87
- model,
88
- choices: [
89
- {
90
- index: 0,
91
- delta: { content: part.text },
92
- finish_reason: null
93
- }
94
- ]
95
- };
79
+ const candidates = chunk.candidates;
80
+ if (!candidates || candidates.length === 0) continue;
81
+ const parts = candidates[0].content?.parts;
82
+ if (parts) {
83
+ for (const part of parts) {
84
+ if (part.thought && part.text !== void 0 && part.text !== null) {
85
+ yield {
86
+ id: chunkId,
87
+ model,
88
+ choices: [
89
+ {
90
+ index: 0,
91
+ delta: { thinking_content: part.text },
92
+ finish_reason: null
93
+ }
94
+ ]
95
+ };
96
+ continue;
97
+ }
98
+ if (part.text !== void 0 && part.text !== null) {
99
+ yield {
100
+ id: chunkId,
101
+ model,
102
+ choices: [
103
+ {
104
+ index: 0,
105
+ delta: { content: part.text },
106
+ finish_reason: null
107
+ }
108
+ ]
109
+ };
110
+ }
111
+ if (part.functionCall) {
112
+ const fc = part.functionCall;
113
+ const tcId = `gemini-tc-${toolCallIndex}`;
114
+ const idx = toolCallIndex++;
115
+ responseHasToolCalls = true;
116
+ yield {
117
+ id: chunkId,
118
+ model,
119
+ choices: [
120
+ {
121
+ index: 0,
122
+ delta: {
123
+ tool_calls: [
124
+ {
125
+ index: idx,
126
+ id: tcId,
127
+ type: "function",
128
+ function: {
129
+ name: fc.name,
130
+ arguments: JSON.stringify(fc.args ?? {})
131
+ }
132
+ }
133
+ ]
134
+ },
135
+ finish_reason: null
136
+ }
137
+ ]
138
+ };
139
+ }
140
+ }
96
141
  }
97
- if (part.functionCall) {
98
- const fc = part.functionCall;
99
- const tcId = `gemini-tc-${toolCallIndex}`;
100
- const idx = toolCallIndex++;
142
+ const finishReason = candidates[0].finishReason;
143
+ if (finishReason && finishReason !== "FINISH_REASON_UNSPECIFIED") {
144
+ let mapped;
145
+ if (finishReason === "STOP") {
146
+ mapped = responseHasToolCalls ? "tool_calls" : "stop";
147
+ } else if (finishReason === "MAX_TOKENS") {
148
+ mapped = "length";
149
+ } else if (finishReason === "SAFETY" || finishReason === "RECITATION" || finishReason === "BLOCKLIST" || finishReason === "PROHIBITED_CONTENT" || finishReason === "SPII" || finishReason === "MALFORMED_FUNCTION_CALL") {
150
+ mapped = "content_filter";
151
+ } else {
152
+ mapped = "stop";
153
+ }
154
+ finishReasonSeen = true;
101
155
  yield {
102
156
  id: chunkId,
103
157
  model,
104
- choices: [
105
- {
106
- index: 0,
107
- delta: {
108
- tool_calls: [
109
- {
110
- index: idx,
111
- id: tcId,
112
- type: "function",
113
- function: {
114
- name: fc.name,
115
- arguments: JSON.stringify(fc.args ?? {})
116
- }
117
- }
118
- ]
119
- },
120
- finish_reason: null
121
- }
122
- ]
158
+ choices: [{ index: 0, delta: {}, finish_reason: mapped }],
159
+ usage: lastUsage
123
160
  };
124
161
  }
125
162
  }
126
- const finishReason = candidates[0].finishReason;
127
- if (finishReason && finishReason !== "FINISH_REASON_UNSPECIFIED") {
128
- let mapped;
129
- if (finishReason === "STOP") {
130
- mapped = toolCallIndex > 0 ? "tool_calls" : "stop";
131
- } else if (finishReason === "MAX_TOKENS") {
132
- mapped = "length";
133
- } else if (finishReason === "SAFETY" || finishReason === "RECITATION") {
134
- mapped = "content_filter";
135
- } else {
136
- mapped = "stop";
137
- }
138
- yield {
139
- id: chunkId,
140
- model,
141
- choices: [{ index: 0, delta: {}, finish_reason: mapped }],
142
- usage: lastUsage
143
- };
163
+ if (!finishReasonSeen && chunkIndex > 0) {
164
+ throw new ChatStreamError("Gemini stream ended without finish reason", {
165
+ cause: new Error("incomplete_stream")
166
+ });
144
167
  }
168
+ } catch (err) {
169
+ if (err instanceof ChatStreamError) throw err;
170
+ const apiErr = err;
171
+ const status = apiErr.status ?? apiErr.statusCode ?? apiErr.code;
172
+ throw new ChatStreamError(
173
+ err instanceof Error ? err.message : String(err),
174
+ {
175
+ status: typeof status === "number" ? status : void 0,
176
+ cause: err
177
+ }
178
+ );
145
179
  }
146
180
  }
147
181
  static contentPartsToGemini(parts) {
@@ -183,6 +217,9 @@ var GeminiProvider = class _GeminiProvider {
183
217
  }
184
218
  } else if (msg.role === "assistant") {
185
219
  const parts = [];
220
+ if (msg.thinking_content) {
221
+ parts.push({ text: msg.thinking_content, thought: true });
222
+ }
186
223
  if (msg.content) {
187
224
  parts.push({ text: msg.content });
188
225
  }
@@ -198,9 +235,10 @@ var GeminiProvider = class _GeminiProvider {
198
235
  });
199
236
  }
200
237
  }
201
- if (parts.length > 0) {
202
- contents.push({ role: "model", parts });
238
+ if (parts.length === 0) {
239
+ parts.push({ text: "" });
203
240
  }
241
+ contents.push({ role: "model", parts });
204
242
  } else if (msg.role === "tool") {
205
243
  const fnName = toolCallIdToName.get(msg.tool_call_id) ?? msg.tool_call_id;
206
244
  const resultValue = Array.isArray(msg.content) ? msg.content.filter((p) => p.type === "text").map((p) => p.text).join("") : msg.content;