@omnicross/core 0.1.0 → 0.1.1

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 (139) hide show
  1. package/dist/ApiConverter.cjs +799 -0
  2. package/dist/ApiConverter.d.cts +82 -0
  3. package/dist/ApiConverter.d.ts +82 -0
  4. package/dist/ApiConverter.js +763 -0
  5. package/dist/BuiltinToolExecutor-BluWyeob.d.ts +81 -0
  6. package/dist/BuiltinToolExecutor-CS2WpXhM.d.cts +81 -0
  7. package/dist/CompletionService-7fCmKAP3.d.ts +212 -0
  8. package/dist/CompletionService-DtOF_War.d.cts +212 -0
  9. package/dist/{ProviderProxy-f_8ziIhW.d.cts → ProviderProxy-C-xqrkKi.d.ts} +7 -2
  10. package/dist/{ProviderProxy-vjt8sQQk.d.ts → ProviderProxy-CnMQYN59.d.cts} +7 -2
  11. package/dist/completion/BuiltinToolExecutor.cjs +327 -0
  12. package/dist/completion/BuiltinToolExecutor.d.cts +4 -0
  13. package/dist/completion/BuiltinToolExecutor.d.ts +4 -0
  14. package/dist/completion/BuiltinToolExecutor.js +296 -0
  15. package/dist/completion/CompletionService.cjs +3487 -0
  16. package/dist/completion/CompletionService.d.cts +21 -0
  17. package/dist/completion/CompletionService.d.ts +21 -0
  18. package/dist/completion/CompletionService.js +3461 -0
  19. package/dist/completion/NativeSearchInjector.cjs +196 -0
  20. package/dist/completion/NativeSearchInjector.d.cts +42 -0
  21. package/dist/completion/NativeSearchInjector.d.ts +42 -0
  22. package/dist/completion/NativeSearchInjector.js +167 -0
  23. package/dist/completion/ProviderSearchInjector.cjs +87 -0
  24. package/dist/completion/ProviderSearchInjector.d.cts +47 -0
  25. package/dist/completion/ProviderSearchInjector.d.ts +47 -0
  26. package/dist/completion/ProviderSearchInjector.js +60 -0
  27. package/dist/completion/native-search-types.cjs +67 -0
  28. package/dist/completion/native-search-types.d.cts +3 -0
  29. package/dist/completion/native-search-types.d.ts +3 -0
  30. package/dist/completion/native-search-types.js +38 -0
  31. package/dist/completion/openrouter-headers.cjs +72 -0
  32. package/dist/completion/openrouter-headers.d.cts +44 -0
  33. package/dist/completion/openrouter-headers.d.ts +44 -0
  34. package/dist/completion/openrouter-headers.js +42 -0
  35. package/dist/completion/openrouter-models.cjs +86 -0
  36. package/dist/completion/openrouter-models.d.cts +27 -0
  37. package/dist/completion/openrouter-models.d.ts +27 -0
  38. package/dist/completion/openrouter-models.js +59 -0
  39. package/dist/completion/types.cjs +18 -0
  40. package/dist/completion/types.d.cts +3 -0
  41. package/dist/completion/types.d.ts +3 -0
  42. package/dist/completion/types.js +0 -0
  43. package/dist/completion/url-builder.cjs +138 -0
  44. package/dist/completion/url-builder.d.cts +87 -0
  45. package/dist/completion/url-builder.d.ts +87 -0
  46. package/dist/completion/url-builder.js +104 -0
  47. package/dist/completion.d.cts +148 -7
  48. package/dist/completion.d.ts +148 -7
  49. package/dist/index.cjs +1 -0
  50. package/dist/index.d.cts +27 -90
  51. package/dist/index.d.ts +27 -90
  52. package/dist/index.js +1 -0
  53. package/dist/outbound-api/routeResolver.cjs +221 -0
  54. package/dist/outbound-api/routeResolver.d.cts +18 -0
  55. package/dist/outbound-api/routeResolver.d.ts +18 -0
  56. package/dist/outbound-api/routeResolver.js +192 -0
  57. package/dist/outbound-api/subscriptionRegistryPort.d.cts +5 -2
  58. package/dist/outbound-api/subscriptionRegistryPort.d.ts +5 -2
  59. package/dist/outbound-api/types.cjs +18 -0
  60. package/dist/{types-CbCN2NQP.d.ts → outbound-api/types.d.cts} +17 -3
  61. package/dist/{types-CGGrKqC_.d.cts → outbound-api/types.d.ts} +17 -3
  62. package/dist/outbound-api/types.js +0 -0
  63. package/dist/outbound-api.cjs +1 -0
  64. package/dist/outbound-api.d.cts +14 -87
  65. package/dist/outbound-api.d.ts +14 -87
  66. package/dist/outbound-api.js +1 -0
  67. package/dist/pipeline/AuthSource.cjs +18 -0
  68. package/dist/pipeline/AuthSource.d.cts +101 -0
  69. package/dist/pipeline/AuthSource.d.ts +101 -0
  70. package/dist/pipeline/AuthSource.js +0 -0
  71. package/dist/pipeline/LlmConfigProviderAuth.cjs +169 -0
  72. package/dist/pipeline/LlmConfigProviderAuth.d.cts +86 -0
  73. package/dist/pipeline/LlmConfigProviderAuth.d.ts +86 -0
  74. package/dist/pipeline/LlmConfigProviderAuth.js +142 -0
  75. package/dist/pipeline/SubscriptionAuthSource.d.cts +165 -3
  76. package/dist/pipeline/SubscriptionAuthSource.d.ts +165 -3
  77. package/dist/pipeline/executeProviderCall.cjs +70 -0
  78. package/dist/pipeline/executeProviderCall.d.cts +149 -0
  79. package/dist/pipeline/executeProviderCall.d.ts +149 -0
  80. package/dist/pipeline/executeProviderCall.js +45 -0
  81. package/dist/pipeline/resolveProviderChain.cjs +47 -0
  82. package/dist/pipeline/resolveProviderChain.d.cts +58 -0
  83. package/dist/pipeline/resolveProviderChain.d.ts +58 -0
  84. package/dist/pipeline/resolveProviderChain.js +22 -0
  85. package/dist/pipeline/resolveSubscriptionChain.cjs +68 -0
  86. package/dist/pipeline/resolveSubscriptionChain.d.cts +68 -0
  87. package/dist/pipeline/resolveSubscriptionChain.d.ts +68 -0
  88. package/dist/pipeline/resolveSubscriptionChain.js +43 -0
  89. package/dist/ports/provider-config-source.cjs +18 -0
  90. package/dist/ports/provider-config-source.d.cts +51 -0
  91. package/dist/ports/provider-config-source.d.ts +51 -0
  92. package/dist/ports/provider-config-source.js +0 -0
  93. package/dist/ports/web-search-backend.cjs +18 -0
  94. package/dist/ports/web-search-backend.d.cts +29 -0
  95. package/dist/ports/web-search-backend.d.ts +29 -0
  96. package/dist/ports/web-search-backend.js +0 -0
  97. package/dist/ports.d.cts +10 -7
  98. package/dist/ports.d.ts +10 -7
  99. package/dist/provider-proxy/ProviderProxy.cjs +4643 -0
  100. package/dist/provider-proxy/ProviderProxy.d.cts +16 -0
  101. package/dist/provider-proxy/ProviderProxy.d.ts +16 -0
  102. package/dist/provider-proxy/ProviderProxy.js +4618 -0
  103. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +5 -2
  104. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +5 -2
  105. package/dist/provider-proxy/types.d.cts +406 -8
  106. package/dist/provider-proxy/types.d.ts +406 -8
  107. package/dist/provider-proxy.cjs +1 -0
  108. package/dist/provider-proxy.d.cts +8 -5
  109. package/dist/provider-proxy.d.ts +8 -5
  110. package/dist/provider-proxy.js +1 -0
  111. package/dist/routeResolver-BrbK6ja9.d.cts +88 -0
  112. package/dist/routeResolver-HE-ZO0fO.d.ts +88 -0
  113. package/dist/transformer/anthropicBetaInject.cjs +51 -0
  114. package/dist/transformer/anthropicBetaInject.d.cts +20 -0
  115. package/dist/transformer/anthropicBetaInject.d.ts +20 -0
  116. package/dist/transformer/anthropicBetaInject.js +25 -0
  117. package/dist/transformer/transformers/AnthropicTransformer.cjs +1017 -0
  118. package/dist/transformer/transformers/AnthropicTransformer.d.cts +148 -0
  119. package/dist/transformer/transformers/AnthropicTransformer.d.ts +148 -0
  120. package/dist/transformer/transformers/AnthropicTransformer.js +990 -0
  121. package/dist/transformer/transformers/ReasoningTransformer.cjs +273 -0
  122. package/dist/transformer/transformers/ReasoningTransformer.d.cts +47 -0
  123. package/dist/transformer/transformers/ReasoningTransformer.d.ts +47 -0
  124. package/dist/transformer/transformers/ReasoningTransformer.js +253 -0
  125. package/dist/transformer/transformers.cjs +3206 -0
  126. package/dist/transformer/transformers.d.cts +100 -0
  127. package/dist/transformer/transformers.d.ts +100 -0
  128. package/dist/transformer/transformers.js +3174 -0
  129. package/dist/transformer.d.cts +8 -31
  130. package/dist/transformer.d.ts +8 -31
  131. package/dist/types-BScIHmPr.d.cts +153 -0
  132. package/dist/types-BScIHmPr.d.ts +153 -0
  133. package/package.json +3 -3
  134. package/dist/SubscriptionAuthSource-Cr4fVEYY.d.cts +0 -264
  135. package/dist/SubscriptionAuthSource-D89zmiSS.d.ts +0 -264
  136. package/dist/index-BTSmc9Sm.d.ts +0 -645
  137. package/dist/index-DXazdTzZ.d.cts +0 -645
  138. package/dist/types-DCzHkhJt.d.ts +0 -467
  139. package/dist/types-DZIQbgp0.d.cts +0 -467
@@ -0,0 +1,81 @@
1
+ import { MCPCallToolResponse, MCPTool } from '@omnicross/contracts/mcp-types';
2
+ import { WebSearchBackend } from './ports/web-search-backend.js';
3
+
4
+ /**
5
+ * Core-owned tool-shape types.
6
+ *
7
+ * The structural tool definitions (`OpenAITool`, `AnthropicTool`,
8
+ * `GeminiTools`) are pure data shapes with no host dependency — hoisted here
9
+ * (verbatim from the host `tools/mcp-users/ToolsLoader.ts`) so the serving core
10
+ * names no host module. The host `ToolsLoader.ts` re-exports these from
11
+ * `@omnicross/core`, keeping every existing host consumer unchanged.
12
+ *
13
+ * `McpToolProvider` is the narrow structural port for the single `callTool`
14
+ * method the completion tool-loop consumes from the host's concrete
15
+ * `McpService`. The concrete `McpService` instance is injected at the existing
16
+ * seam and satisfies this port structurally (type-only — no runtime coupling).
17
+ */
18
+
19
+ /**
20
+ * OpenAI-compatible tool definition
21
+ */
22
+ interface OpenAITool {
23
+ type: 'function';
24
+ function: {
25
+ name: string;
26
+ description: string;
27
+ parameters: Record<string, any>;
28
+ };
29
+ }
30
+ /**
31
+ * Anthropic tool definition
32
+ */
33
+ interface AnthropicTool {
34
+ name: string;
35
+ description: string;
36
+ input_schema: Record<string, any>;
37
+ }
38
+ /**
39
+ * Google Gemini tool definition
40
+ * Gemini REST API expects tools wrapped in functionDeclarations
41
+ */
42
+ type GeminiTools = Array<{
43
+ functionDeclarations: Array<{
44
+ name: string;
45
+ description: string;
46
+ parameters: Record<string, any>;
47
+ }>;
48
+ }>;
49
+ /**
50
+ * Narrow structural port for the host MCP tool provider — only the `callTool`
51
+ * method the serving-core tool-loop dispatches to. The host's concrete
52
+ * `McpService` satisfies this structurally.
53
+ */
54
+ interface McpToolProvider {
55
+ callTool(serverId: string, toolName: string, args: unknown, callId: string): Promise<MCPCallToolResponse>;
56
+ }
57
+
58
+ /**
59
+ * BuiltinToolExecutor — Executes built-in tools (web_search, web_fetch)
60
+ * for the non-agent chat pipeline.
61
+ *
62
+ * Built-in tools use `serverId: 'builtin'` in MCPTool metadata and are
63
+ * dispatched here instead of going through McpService.callTool().
64
+ */
65
+
66
+ declare class BuiltinToolExecutor {
67
+ private webSearch;
68
+ constructor(webSearch: WebSearchBackend);
69
+ execute(toolName: string, args: Record<string, unknown>): Promise<MCPCallToolResponse>;
70
+ private executeWebSearch;
71
+ private resolveProviderChain;
72
+ private executeWebFetch;
73
+ }
74
+ /** Get the built-in MCPTool definitions for web search tools. */
75
+ declare function getBuiltinSearchTools(): MCPTool[];
76
+ /** Convert built-in tools to OpenAI function format. */
77
+ declare function convertBuiltinToolsToOpenAI(tools: MCPTool[]): OpenAITool[];
78
+ /** Convert built-in tools to Anthropic format. */
79
+ declare function convertBuiltinToolsToAnthropic(tools: MCPTool[]): AnthropicTool[];
80
+
81
+ export { type AnthropicTool as A, BuiltinToolExecutor as B, type GeminiTools as G, type McpToolProvider as M, type OpenAITool as O, convertBuiltinToolsToOpenAI as a, convertBuiltinToolsToAnthropic as c, getBuiltinSearchTools as g };
@@ -0,0 +1,81 @@
1
+ import { MCPCallToolResponse, MCPTool } from '@omnicross/contracts/mcp-types';
2
+ import { WebSearchBackend } from './ports/web-search-backend.cjs';
3
+
4
+ /**
5
+ * Core-owned tool-shape types.
6
+ *
7
+ * The structural tool definitions (`OpenAITool`, `AnthropicTool`,
8
+ * `GeminiTools`) are pure data shapes with no host dependency — hoisted here
9
+ * (verbatim from the host `tools/mcp-users/ToolsLoader.ts`) so the serving core
10
+ * names no host module. The host `ToolsLoader.ts` re-exports these from
11
+ * `@omnicross/core`, keeping every existing host consumer unchanged.
12
+ *
13
+ * `McpToolProvider` is the narrow structural port for the single `callTool`
14
+ * method the completion tool-loop consumes from the host's concrete
15
+ * `McpService`. The concrete `McpService` instance is injected at the existing
16
+ * seam and satisfies this port structurally (type-only — no runtime coupling).
17
+ */
18
+
19
+ /**
20
+ * OpenAI-compatible tool definition
21
+ */
22
+ interface OpenAITool {
23
+ type: 'function';
24
+ function: {
25
+ name: string;
26
+ description: string;
27
+ parameters: Record<string, any>;
28
+ };
29
+ }
30
+ /**
31
+ * Anthropic tool definition
32
+ */
33
+ interface AnthropicTool {
34
+ name: string;
35
+ description: string;
36
+ input_schema: Record<string, any>;
37
+ }
38
+ /**
39
+ * Google Gemini tool definition
40
+ * Gemini REST API expects tools wrapped in functionDeclarations
41
+ */
42
+ type GeminiTools = Array<{
43
+ functionDeclarations: Array<{
44
+ name: string;
45
+ description: string;
46
+ parameters: Record<string, any>;
47
+ }>;
48
+ }>;
49
+ /**
50
+ * Narrow structural port for the host MCP tool provider — only the `callTool`
51
+ * method the serving-core tool-loop dispatches to. The host's concrete
52
+ * `McpService` satisfies this structurally.
53
+ */
54
+ interface McpToolProvider {
55
+ callTool(serverId: string, toolName: string, args: unknown, callId: string): Promise<MCPCallToolResponse>;
56
+ }
57
+
58
+ /**
59
+ * BuiltinToolExecutor — Executes built-in tools (web_search, web_fetch)
60
+ * for the non-agent chat pipeline.
61
+ *
62
+ * Built-in tools use `serverId: 'builtin'` in MCPTool metadata and are
63
+ * dispatched here instead of going through McpService.callTool().
64
+ */
65
+
66
+ declare class BuiltinToolExecutor {
67
+ private webSearch;
68
+ constructor(webSearch: WebSearchBackend);
69
+ execute(toolName: string, args: Record<string, unknown>): Promise<MCPCallToolResponse>;
70
+ private executeWebSearch;
71
+ private resolveProviderChain;
72
+ private executeWebFetch;
73
+ }
74
+ /** Get the built-in MCPTool definitions for web search tools. */
75
+ declare function getBuiltinSearchTools(): MCPTool[];
76
+ /** Convert built-in tools to OpenAI function format. */
77
+ declare function convertBuiltinToolsToOpenAI(tools: MCPTool[]): OpenAITool[];
78
+ /** Convert built-in tools to Anthropic format. */
79
+ declare function convertBuiltinToolsToAnthropic(tools: MCPTool[]): AnthropicTool[];
80
+
81
+ export { type AnthropicTool as A, BuiltinToolExecutor as B, type GeminiTools as G, type McpToolProvider as M, type OpenAITool as O, convertBuiltinToolsToOpenAI as a, convertBuiltinToolsToAnthropic as c, getBuiltinSearchTools as g };
@@ -0,0 +1,212 @@
1
+ import { ThinkLevel } from '@omnicross/contracts/completion-types';
2
+ import { LLMProvider } from '@omnicross/contracts/llm-config';
3
+ import { C as CorePaths, U as UsageEventSink } from './usage-event-sink-BX7FE1NL.js';
4
+ import { L as Logger, A as ApiKeyPoolService } from './ApiKeyPoolService-BmMkau07.js';
5
+ import { ProviderConfigSource } from './ports/provider-config-source.js';
6
+ import { UsageRecorderImport } from './provider-proxy/types.js';
7
+ import { O as OpenAITool, A as AnthropicTool, G as GeminiTools, M as McpToolProvider, B as BuiltinToolExecutor } from './BuiltinToolExecutor-BluWyeob.js';
8
+ import { C as CompletionOptions, S as StreamCallbacks, a as CompletionResult } from './types-BScIHmPr.js';
9
+ import { MCPTool } from '@omnicross/contracts/mcp-types';
10
+
11
+ /**
12
+ * VisionFallbackProvider — serving-core port for image-to-text fallback.
13
+ *
14
+ * When the active completion model lacks vision capability but a message
15
+ * carries images, `CompletionService.applyVisionFallback` delegates to this
16
+ * port to turn the images into a text description (which is then appended to
17
+ * the message content) before stripping the image attachments.
18
+ *
19
+ * The concrete implementation is built ON TOP OF CompletionService, so it
20
+ * lives in the embedding host and is injected DOWN into the serving core via
21
+ * `setVisionFallbackProvider` at bootstrap (instead of the core importing
22
+ * upward).
23
+ *
24
+ * @module completion/VisionFallbackProvider
25
+ */
26
+ /**
27
+ * Describe a batch of images as text using an auxiliary vision-capable model.
28
+ *
29
+ * @param images Image data URLs to describe (`{ data: 'data:<mime>;base64,…' }`).
30
+ * @param context Free-form context (the surrounding user message content).
31
+ * @param model The resolved vision aux ModelRef (`"providerId,modelId"`).
32
+ * @returns A textual description, or an empty / sentinel string when
33
+ * unavailable. Callers MUST tolerate `''` and
34
+ * `'[Image description unavailable]'`.
35
+ */
36
+ interface VisionFallbackProvider {
37
+ describeImages(images: {
38
+ data: string;
39
+ }[], context: string, model: string): Promise<string>;
40
+ }
41
+
42
+ /**
43
+ * ToolHandler - Handles streaming completion with MCP tool support
44
+ *
45
+ * Extracted from CompletionService to isolate the agentic loop logic
46
+ * that handles tool calls: LLM -> execute tools -> LLM again until done.
47
+ */
48
+
49
+ /** Extended options for tool-based completion */
50
+ interface StreamWithToolsOptions extends CompletionOptions {
51
+ tools: OpenAITool[] | AnthropicTool[] | GeminiTools;
52
+ mcpTools?: MCPTool[];
53
+ }
54
+ /** Extended callbacks for tool-based completion */
55
+ interface StreamWithToolsCallbacks extends StreamCallbacks {
56
+ onToolCall?: (toolCall: {
57
+ id: string;
58
+ name: string;
59
+ args: unknown;
60
+ }) => void;
61
+ onToolResult?: (toolId: string, result: unknown) => void;
62
+ }
63
+
64
+ /**
65
+ * CompletionService - Handles completion API calls
66
+ *
67
+ * This service provides a unified interface for making completion API calls
68
+ * to different providers, handling format conversion as needed.
69
+ * Supports transformer chains for advanced request/response transformation.
70
+ *
71
+ * This is a thin facade that delegates to domain-specific handlers:
72
+ * - DirectApiHandler: Non-streaming API calls (OpenAI, Anthropic, Gemini)
73
+ * - StreamHandler: SSE-based streaming (OpenAI, Anthropic, Gemini)
74
+ * - TransformerHandler: Transformer chain-based completion
75
+ * - ToolHandler: Agentic tool-calling loop
76
+ * - ThinkingResolver: Thinking budget and max tokens resolution
77
+ */
78
+
79
+ declare class CompletionService {
80
+ private paths;
81
+ private llmConfig;
82
+ private logger;
83
+ private apiKeyPool;
84
+ private usageRecorder;
85
+ private usageEventSink;
86
+ private visionFallbackProvider;
87
+ constructor(paths: CorePaths, llmConfig: ProviderConfigSource, logger: Logger);
88
+ /**
89
+ * Set the API key pool service for multi-key load balancing.
90
+ * When set, keys are resolved via the pool instead of directly from the provider.
91
+ */
92
+ setApiKeyPool(pool: ApiKeyPoolService): void;
93
+ /**
94
+ * Set the usage recorder so completion paths can persist token/cost stats.
95
+ * Optional — when unset, all calls succeed but nothing is recorded.
96
+ */
97
+ setUsageRecorder(recorder: UsageRecorderImport): void;
98
+ /**
99
+ * Set the usage-event sink so completion paths can push live usage events
100
+ * (context-meter, aggregate recorder) into the in-process hub. Injected DOWN
101
+ * at bootstrap with `getUsageEventHub()` immediately after construction, so
102
+ * emission is unconditional in production. Optional — when unset (unit-test
103
+ * constructors), the emit calls no-op, identical to `usageRecorder`.
104
+ */
105
+ setUsageEventSink(sink: UsageEventSink): void;
106
+ /**
107
+ * Set the vision-fallback provider used by `applyVisionFallback` to describe
108
+ * images for non-vision models. Injected DOWN by the host at bootstrap
109
+ * (the host's impl is built on top of CompletionService).
110
+ * Optional — when unset, `applyVisionFallback` strips images instead.
111
+ */
112
+ setVisionFallbackProvider(provider: VisionFallbackProvider): void;
113
+ /**
114
+ * Get provider by ID
115
+ * Delegates to the `ProviderConfigSource` which maintains its own in-memory cache.
116
+ */
117
+ getProvider(providerId: string): Promise<LLMProvider | null>;
118
+ /**
119
+ * Send a completion request
120
+ */
121
+ complete(options: CompletionOptions): Promise<CompletionResult>;
122
+ /**
123
+ * Send a streaming completion request
124
+ */
125
+ completeStream(options: CompletionOptions, callbacks: StreamCallbacks): Promise<void>;
126
+ /**
127
+ * Get available models for a provider
128
+ */
129
+ getAvailableModels(providerId: string): Promise<string[]>;
130
+ /**
131
+ * Test provider connection with a specific model.
132
+ * Sends "Hello" and returns the AI response, duration, etc.
133
+ */
134
+ testModel(providerId: string, modelId: string): Promise<{
135
+ success: boolean;
136
+ message: string;
137
+ response?: string;
138
+ model: string;
139
+ durationMs?: number;
140
+ }>;
141
+ /**
142
+ * Check if any messages contain images and the model lacks vision capability.
143
+ * If so, use the auxiliary vision model to describe images as text and remove
144
+ * the image attachments from the messages.
145
+ *
146
+ * Mutates options.messages in-place.
147
+ */
148
+ private applyVisionFallback;
149
+ /**
150
+ * Resolve API key for a request with priority:
151
+ * 1. Coding Plan override (if enabled)
152
+ * 2. API key pool (session-affinity weighted round-robin)
153
+ * 3. Legacy single key from provider config
154
+ */
155
+ private resolveApiKeyForRequest;
156
+ /**
157
+ * Extract HTTP status code from error messages like "API error (429): ..."
158
+ */
159
+ private extractHttpStatus;
160
+ /**
161
+ * Dispatch a non-streaming completion to the appropriate handler.
162
+ */
163
+ private callDirectHandler;
164
+ /**
165
+ * Dispatch a streaming completion to the appropriate handler.
166
+ */
167
+ private callStreamHandler;
168
+ /**
169
+ * Resolve API key (handle environment variable references)
170
+ */
171
+ resolveApiKey(apiKey: string): string;
172
+ /**
173
+ * Resolve effective max_tokens value with priority:
174
+ * 1. Session settings (if provided)
175
+ * 2. Global model parameters (if enabled)
176
+ * 3. Model's maxTokens from provider config
177
+ * 4. Discovered models cache (from API)
178
+ * 5. undefined - let API use its default
179
+ */
180
+ resolveEffectiveMaxTokens(providerId: string, modelId: string, sessionMaxTokens?: number): Promise<number | undefined>;
181
+ /**
182
+ * Get required max_tokens for providers that need it (e.g., Anthropic)
183
+ * Falls back to DEFAULT_MAX_TOKENS if no value is configured
184
+ */
185
+ getRequiredMaxTokens(providerId: string, modelId: string, sessionMaxTokens?: number): Promise<number>;
186
+ /**
187
+ * Calculate thinking budget and adjust max_tokens for the provider
188
+ */
189
+ resolveThinkingBudget(providerId: string, modelId: string, maxTokens: number, thinkLevel: ThinkLevel): Promise<{
190
+ adjustedMaxTokens: number;
191
+ thinkingBudget: number | undefined;
192
+ thinkingConfig: {
193
+ type?: 'enabled' | 'disabled';
194
+ budget_tokens?: number;
195
+ } | undefined;
196
+ }>;
197
+ /**
198
+ * Send a completion request using transformer chain
199
+ */
200
+ completeWithTransformers(options: CompletionOptions): Promise<CompletionResult>;
201
+ /**
202
+ * Send a streaming completion request using transformer chain
203
+ */
204
+ completeStreamWithTransformers(options: CompletionOptions, callbacks: StreamCallbacks): Promise<void>;
205
+ /**
206
+ * Stream completion with MCP tools support (direct API call)
207
+ * Implements agentic loop: calls LLM -> executes tools -> calls LLM again until done
208
+ */
209
+ streamWithTools(options: StreamWithToolsOptions, callbacks: StreamWithToolsCallbacks, mcpService?: McpToolProvider, builtinExecutor?: BuiltinToolExecutor): Promise<void>;
210
+ }
211
+
212
+ export { CompletionService as C, type VisionFallbackProvider as V };
@@ -0,0 +1,212 @@
1
+ import { ThinkLevel } from '@omnicross/contracts/completion-types';
2
+ import { LLMProvider } from '@omnicross/contracts/llm-config';
3
+ import { C as CorePaths, U as UsageEventSink } from './usage-event-sink-BX7FE1NL.cjs';
4
+ import { L as Logger, A as ApiKeyPoolService } from './ApiKeyPoolService-BmMkau07.cjs';
5
+ import { ProviderConfigSource } from './ports/provider-config-source.cjs';
6
+ import { UsageRecorderImport } from './provider-proxy/types.cjs';
7
+ import { O as OpenAITool, A as AnthropicTool, G as GeminiTools, M as McpToolProvider, B as BuiltinToolExecutor } from './BuiltinToolExecutor-CS2WpXhM.cjs';
8
+ import { C as CompletionOptions, S as StreamCallbacks, a as CompletionResult } from './types-BScIHmPr.cjs';
9
+ import { MCPTool } from '@omnicross/contracts/mcp-types';
10
+
11
+ /**
12
+ * VisionFallbackProvider — serving-core port for image-to-text fallback.
13
+ *
14
+ * When the active completion model lacks vision capability but a message
15
+ * carries images, `CompletionService.applyVisionFallback` delegates to this
16
+ * port to turn the images into a text description (which is then appended to
17
+ * the message content) before stripping the image attachments.
18
+ *
19
+ * The concrete implementation is built ON TOP OF CompletionService, so it
20
+ * lives in the embedding host and is injected DOWN into the serving core via
21
+ * `setVisionFallbackProvider` at bootstrap (instead of the core importing
22
+ * upward).
23
+ *
24
+ * @module completion/VisionFallbackProvider
25
+ */
26
+ /**
27
+ * Describe a batch of images as text using an auxiliary vision-capable model.
28
+ *
29
+ * @param images Image data URLs to describe (`{ data: 'data:<mime>;base64,…' }`).
30
+ * @param context Free-form context (the surrounding user message content).
31
+ * @param model The resolved vision aux ModelRef (`"providerId,modelId"`).
32
+ * @returns A textual description, or an empty / sentinel string when
33
+ * unavailable. Callers MUST tolerate `''` and
34
+ * `'[Image description unavailable]'`.
35
+ */
36
+ interface VisionFallbackProvider {
37
+ describeImages(images: {
38
+ data: string;
39
+ }[], context: string, model: string): Promise<string>;
40
+ }
41
+
42
+ /**
43
+ * ToolHandler - Handles streaming completion with MCP tool support
44
+ *
45
+ * Extracted from CompletionService to isolate the agentic loop logic
46
+ * that handles tool calls: LLM -> execute tools -> LLM again until done.
47
+ */
48
+
49
+ /** Extended options for tool-based completion */
50
+ interface StreamWithToolsOptions extends CompletionOptions {
51
+ tools: OpenAITool[] | AnthropicTool[] | GeminiTools;
52
+ mcpTools?: MCPTool[];
53
+ }
54
+ /** Extended callbacks for tool-based completion */
55
+ interface StreamWithToolsCallbacks extends StreamCallbacks {
56
+ onToolCall?: (toolCall: {
57
+ id: string;
58
+ name: string;
59
+ args: unknown;
60
+ }) => void;
61
+ onToolResult?: (toolId: string, result: unknown) => void;
62
+ }
63
+
64
+ /**
65
+ * CompletionService - Handles completion API calls
66
+ *
67
+ * This service provides a unified interface for making completion API calls
68
+ * to different providers, handling format conversion as needed.
69
+ * Supports transformer chains for advanced request/response transformation.
70
+ *
71
+ * This is a thin facade that delegates to domain-specific handlers:
72
+ * - DirectApiHandler: Non-streaming API calls (OpenAI, Anthropic, Gemini)
73
+ * - StreamHandler: SSE-based streaming (OpenAI, Anthropic, Gemini)
74
+ * - TransformerHandler: Transformer chain-based completion
75
+ * - ToolHandler: Agentic tool-calling loop
76
+ * - ThinkingResolver: Thinking budget and max tokens resolution
77
+ */
78
+
79
+ declare class CompletionService {
80
+ private paths;
81
+ private llmConfig;
82
+ private logger;
83
+ private apiKeyPool;
84
+ private usageRecorder;
85
+ private usageEventSink;
86
+ private visionFallbackProvider;
87
+ constructor(paths: CorePaths, llmConfig: ProviderConfigSource, logger: Logger);
88
+ /**
89
+ * Set the API key pool service for multi-key load balancing.
90
+ * When set, keys are resolved via the pool instead of directly from the provider.
91
+ */
92
+ setApiKeyPool(pool: ApiKeyPoolService): void;
93
+ /**
94
+ * Set the usage recorder so completion paths can persist token/cost stats.
95
+ * Optional — when unset, all calls succeed but nothing is recorded.
96
+ */
97
+ setUsageRecorder(recorder: UsageRecorderImport): void;
98
+ /**
99
+ * Set the usage-event sink so completion paths can push live usage events
100
+ * (context-meter, aggregate recorder) into the in-process hub. Injected DOWN
101
+ * at bootstrap with `getUsageEventHub()` immediately after construction, so
102
+ * emission is unconditional in production. Optional — when unset (unit-test
103
+ * constructors), the emit calls no-op, identical to `usageRecorder`.
104
+ */
105
+ setUsageEventSink(sink: UsageEventSink): void;
106
+ /**
107
+ * Set the vision-fallback provider used by `applyVisionFallback` to describe
108
+ * images for non-vision models. Injected DOWN by the host at bootstrap
109
+ * (the host's impl is built on top of CompletionService).
110
+ * Optional — when unset, `applyVisionFallback` strips images instead.
111
+ */
112
+ setVisionFallbackProvider(provider: VisionFallbackProvider): void;
113
+ /**
114
+ * Get provider by ID
115
+ * Delegates to the `ProviderConfigSource` which maintains its own in-memory cache.
116
+ */
117
+ getProvider(providerId: string): Promise<LLMProvider | null>;
118
+ /**
119
+ * Send a completion request
120
+ */
121
+ complete(options: CompletionOptions): Promise<CompletionResult>;
122
+ /**
123
+ * Send a streaming completion request
124
+ */
125
+ completeStream(options: CompletionOptions, callbacks: StreamCallbacks): Promise<void>;
126
+ /**
127
+ * Get available models for a provider
128
+ */
129
+ getAvailableModels(providerId: string): Promise<string[]>;
130
+ /**
131
+ * Test provider connection with a specific model.
132
+ * Sends "Hello" and returns the AI response, duration, etc.
133
+ */
134
+ testModel(providerId: string, modelId: string): Promise<{
135
+ success: boolean;
136
+ message: string;
137
+ response?: string;
138
+ model: string;
139
+ durationMs?: number;
140
+ }>;
141
+ /**
142
+ * Check if any messages contain images and the model lacks vision capability.
143
+ * If so, use the auxiliary vision model to describe images as text and remove
144
+ * the image attachments from the messages.
145
+ *
146
+ * Mutates options.messages in-place.
147
+ */
148
+ private applyVisionFallback;
149
+ /**
150
+ * Resolve API key for a request with priority:
151
+ * 1. Coding Plan override (if enabled)
152
+ * 2. API key pool (session-affinity weighted round-robin)
153
+ * 3. Legacy single key from provider config
154
+ */
155
+ private resolveApiKeyForRequest;
156
+ /**
157
+ * Extract HTTP status code from error messages like "API error (429): ..."
158
+ */
159
+ private extractHttpStatus;
160
+ /**
161
+ * Dispatch a non-streaming completion to the appropriate handler.
162
+ */
163
+ private callDirectHandler;
164
+ /**
165
+ * Dispatch a streaming completion to the appropriate handler.
166
+ */
167
+ private callStreamHandler;
168
+ /**
169
+ * Resolve API key (handle environment variable references)
170
+ */
171
+ resolveApiKey(apiKey: string): string;
172
+ /**
173
+ * Resolve effective max_tokens value with priority:
174
+ * 1. Session settings (if provided)
175
+ * 2. Global model parameters (if enabled)
176
+ * 3. Model's maxTokens from provider config
177
+ * 4. Discovered models cache (from API)
178
+ * 5. undefined - let API use its default
179
+ */
180
+ resolveEffectiveMaxTokens(providerId: string, modelId: string, sessionMaxTokens?: number): Promise<number | undefined>;
181
+ /**
182
+ * Get required max_tokens for providers that need it (e.g., Anthropic)
183
+ * Falls back to DEFAULT_MAX_TOKENS if no value is configured
184
+ */
185
+ getRequiredMaxTokens(providerId: string, modelId: string, sessionMaxTokens?: number): Promise<number>;
186
+ /**
187
+ * Calculate thinking budget and adjust max_tokens for the provider
188
+ */
189
+ resolveThinkingBudget(providerId: string, modelId: string, maxTokens: number, thinkLevel: ThinkLevel): Promise<{
190
+ adjustedMaxTokens: number;
191
+ thinkingBudget: number | undefined;
192
+ thinkingConfig: {
193
+ type?: 'enabled' | 'disabled';
194
+ budget_tokens?: number;
195
+ } | undefined;
196
+ }>;
197
+ /**
198
+ * Send a completion request using transformer chain
199
+ */
200
+ completeWithTransformers(options: CompletionOptions): Promise<CompletionResult>;
201
+ /**
202
+ * Send a streaming completion request using transformer chain
203
+ */
204
+ completeStreamWithTransformers(options: CompletionOptions, callbacks: StreamCallbacks): Promise<void>;
205
+ /**
206
+ * Stream completion with MCP tools support (direct API call)
207
+ * Implements agentic loop: calls LLM -> executes tools -> calls LLM again until done
208
+ */
209
+ streamWithTools(options: StreamWithToolsOptions, callbacks: StreamWithToolsCallbacks, mcpService?: McpToolProvider, builtinExecutor?: BuiltinToolExecutor): Promise<void>;
210
+ }
211
+
212
+ export { CompletionService as C, type VisionFallbackProvider as V };
@@ -1,4 +1,4 @@
1
- import { g as RouteContext, a as ProviderProxyDeps } from './types-DZIQbgp0.cjs';
1
+ import { RouteContext, ProviderProxyDeps } from './provider-proxy/types.js';
2
2
 
3
3
  /**
4
4
  * ProviderProxyRouteMap — the per-run `Map<token, RouteContext>` with crypto
@@ -82,6 +82,11 @@ declare class ProviderProxyRouteMap {
82
82
  * @module provider-proxy/ProviderProxy
83
83
  */
84
84
 
85
+ /**
86
+ * True for IPv4/IPv6 loopback peer addresses. Exported so the isolation gate
87
+ * ("the listener refuses non-loopback origins") can be unit-asserted.
88
+ */
89
+ declare function isLoopbackAddress(addr: string | undefined): boolean;
85
90
  declare class ProviderProxy {
86
91
  private readonly deps;
87
92
  private server;
@@ -117,4 +122,4 @@ declare class ProviderProxy {
117
122
  routeCount(): number;
118
123
  }
119
124
 
120
- export { DEFAULT_ROUTE_IDLE_MS as D, ProviderProxy as P, ProviderProxyRouteMap as a };
125
+ export { DEFAULT_ROUTE_IDLE_MS as D, ProviderProxy as P, ProviderProxyRouteMap as a, isLoopbackAddress as i };
@@ -1,4 +1,4 @@
1
- import { g as RouteContext, a as ProviderProxyDeps } from './types-DCzHkhJt.js';
1
+ import { RouteContext, ProviderProxyDeps } from './provider-proxy/types.cjs';
2
2
 
3
3
  /**
4
4
  * ProviderProxyRouteMap — the per-run `Map<token, RouteContext>` with crypto
@@ -82,6 +82,11 @@ declare class ProviderProxyRouteMap {
82
82
  * @module provider-proxy/ProviderProxy
83
83
  */
84
84
 
85
+ /**
86
+ * True for IPv4/IPv6 loopback peer addresses. Exported so the isolation gate
87
+ * ("the listener refuses non-loopback origins") can be unit-asserted.
88
+ */
89
+ declare function isLoopbackAddress(addr: string | undefined): boolean;
85
90
  declare class ProviderProxy {
86
91
  private readonly deps;
87
92
  private server;
@@ -117,4 +122,4 @@ declare class ProviderProxy {
117
122
  routeCount(): number;
118
123
  }
119
124
 
120
- export { DEFAULT_ROUTE_IDLE_MS as D, ProviderProxy as P, ProviderProxyRouteMap as a };
125
+ export { DEFAULT_ROUTE_IDLE_MS as D, ProviderProxy as P, ProviderProxyRouteMap as a, isLoopbackAddress as i };