@jini-ai/agent-runtime 0.1.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.
- package/LICENSE +201 -0
- package/README.md +43 -0
- package/dist/acp-model-probe.d.ts +48 -0
- package/dist/acp-model-probe.d.ts.map +1 -0
- package/dist/acp-model-probe.js +15 -0
- package/dist/acp-model-probe.js.map +1 -0
- package/dist/agent-protocol/acp/account-failure.d.ts +54 -0
- package/dist/agent-protocol/acp/account-failure.d.ts.map +1 -0
- package/dist/agent-protocol/acp/account-failure.js +37 -0
- package/dist/agent-protocol/acp/account-failure.js.map +1 -0
- package/dist/agent-protocol/acp/constants.d.ts +26 -0
- package/dist/agent-protocol/acp/constants.d.ts.map +1 -0
- package/dist/agent-protocol/acp/constants.js +39 -0
- package/dist/agent-protocol/acp/constants.js.map +1 -0
- package/dist/agent-protocol/acp/index.d.ts +14 -0
- package/dist/agent-protocol/acp/index.d.ts.map +1 -0
- package/dist/agent-protocol/acp/index.js +14 -0
- package/dist/agent-protocol/acp/index.js.map +1 -0
- package/dist/agent-protocol/acp/json.d.ts +82 -0
- package/dist/agent-protocol/acp/json.d.ts.map +1 -0
- package/dist/agent-protocol/acp/json.js +144 -0
- package/dist/agent-protocol/acp/json.js.map +1 -0
- package/dist/agent-protocol/acp/models.d.ts +112 -0
- package/dist/agent-protocol/acp/models.d.ts.map +1 -0
- package/dist/agent-protocol/acp/models.js +293 -0
- package/dist/agent-protocol/acp/models.js.map +1 -0
- package/dist/agent-protocol/acp/rpc.d.ts +107 -0
- package/dist/agent-protocol/acp/rpc.d.ts.map +1 -0
- package/dist/agent-protocol/acp/rpc.js +162 -0
- package/dist/agent-protocol/acp/rpc.js.map +1 -0
- package/dist/agent-protocol/acp/session-params.d.ts +55 -0
- package/dist/agent-protocol/acp/session-params.d.ts.map +1 -0
- package/dist/agent-protocol/acp/session-params.js +81 -0
- package/dist/agent-protocol/acp/session-params.js.map +1 -0
- package/dist/agent-protocol/acp/session.d.ts +101 -0
- package/dist/agent-protocol/acp/session.d.ts.map +1 -0
- package/dist/agent-protocol/acp/session.js +832 -0
- package/dist/agent-protocol/acp/session.js.map +1 -0
- package/dist/agent-protocol/acp/text-suppression.d.ts +73 -0
- package/dist/agent-protocol/acp/text-suppression.d.ts.map +1 -0
- package/dist/agent-protocol/acp/text-suppression.js +229 -0
- package/dist/agent-protocol/acp/text-suppression.js.map +1 -0
- package/dist/agent-protocol/acp/types.d.ts +27 -0
- package/dist/agent-protocol/acp/types.d.ts.map +1 -0
- package/dist/agent-protocol/acp/types.js +2 -0
- package/dist/agent-protocol/acp/types.js.map +1 -0
- package/dist/agent-protocol/acp/updates.d.ts +166 -0
- package/dist/agent-protocol/acp/updates.d.ts.map +1 -0
- package/dist/agent-protocol/acp/updates.js +268 -0
- package/dist/agent-protocol/acp/updates.js.map +1 -0
- package/dist/agent-protocol/core/index.d.ts +6 -0
- package/dist/agent-protocol/core/index.d.ts.map +1 -0
- package/dist/agent-protocol/core/index.js +6 -0
- package/dist/agent-protocol/core/index.js.map +1 -0
- package/dist/agent-protocol/core/json-line-stream.d.ts +42 -0
- package/dist/agent-protocol/core/json-line-stream.d.ts.map +1 -0
- package/dist/agent-protocol/core/json-line-stream.js +333 -0
- package/dist/agent-protocol/core/json-line-stream.js.map +1 -0
- package/dist/agent-protocol/index.d.ts +8 -0
- package/dist/agent-protocol/index.d.ts.map +1 -0
- package/dist/agent-protocol/index.js +8 -0
- package/dist/agent-protocol/index.js.map +1 -0
- package/dist/agent-protocol/pi-rpc/events.d.ts +26 -0
- package/dist/agent-protocol/pi-rpc/events.d.ts.map +1 -0
- package/dist/agent-protocol/pi-rpc/events.js +167 -0
- package/dist/agent-protocol/pi-rpc/events.js.map +1 -0
- package/dist/agent-protocol/pi-rpc/index.d.ts +11 -0
- package/dist/agent-protocol/pi-rpc/index.d.ts.map +1 -0
- package/dist/agent-protocol/pi-rpc/index.js +11 -0
- package/dist/agent-protocol/pi-rpc/index.js.map +1 -0
- package/dist/agent-protocol/pi-rpc/internal.d.ts +45 -0
- package/dist/agent-protocol/pi-rpc/internal.d.ts.map +1 -0
- package/dist/agent-protocol/pi-rpc/internal.js +41 -0
- package/dist/agent-protocol/pi-rpc/internal.js.map +1 -0
- package/dist/agent-protocol/pi-rpc/models.d.ts +21 -0
- package/dist/agent-protocol/pi-rpc/models.d.ts.map +1 -0
- package/dist/agent-protocol/pi-rpc/models.js +48 -0
- package/dist/agent-protocol/pi-rpc/models.js.map +1 -0
- package/dist/agent-protocol/pi-rpc/session.d.ts +106 -0
- package/dist/agent-protocol/pi-rpc/session.d.ts.map +1 -0
- package/dist/agent-protocol/pi-rpc/session.js +371 -0
- package/dist/agent-protocol/pi-rpc/session.js.map +1 -0
- package/dist/amr-model-cache.d.ts +40 -0
- package/dist/amr-model-cache.d.ts.map +1 -0
- package/dist/amr-model-cache.js +79 -0
- package/dist/amr-model-cache.js.map +1 -0
- package/dist/amr-profile-resolver.d.ts +21 -0
- package/dist/amr-profile-resolver.d.ts.map +1 -0
- package/dist/amr-profile-resolver.js +4 -0
- package/dist/amr-profile-resolver.js.map +1 -0
- package/dist/artifact-taxonomy.d.ts +27 -0
- package/dist/artifact-taxonomy.d.ts.map +1 -0
- package/dist/artifact-taxonomy.js +5 -0
- package/dist/artifact-taxonomy.js.map +1 -0
- package/dist/auth.d.ts +25 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +332 -0
- package/dist/auth.js.map +1 -0
- package/dist/capabilities.d.ts +9 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +2 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/claude-stream.d.ts +37 -0
- package/dist/claude-stream.d.ts.map +1 -0
- package/dist/claude-stream.js +660 -0
- package/dist/claude-stream.js.map +1 -0
- package/dist/copilot-stream.d.ts +37 -0
- package/dist/copilot-stream.d.ts.map +1 -0
- package/dist/copilot-stream.js +136 -0
- package/dist/copilot-stream.js.map +1 -0
- package/dist/defs/aider.d.ts +13 -0
- package/dist/defs/aider.d.ts.map +1 -0
- package/dist/defs/aider.js +63 -0
- package/dist/defs/aider.js.map +1 -0
- package/dist/defs/amp.d.ts +12 -0
- package/dist/defs/amp.d.ts.map +1 -0
- package/dist/defs/amp.js +56 -0
- package/dist/defs/amp.js.map +1 -0
- package/dist/defs/amr.d.ts +37 -0
- package/dist/defs/amr.d.ts.map +1 -0
- package/dist/defs/amr.js +303 -0
- package/dist/defs/amr.js.map +1 -0
- package/dist/defs/antigravity.d.ts +25 -0
- package/dist/defs/antigravity.d.ts.map +1 -0
- package/dist/defs/antigravity.js +213 -0
- package/dist/defs/antigravity.js.map +1 -0
- package/dist/defs/claude.d.ts +30 -0
- package/dist/defs/claude.d.ts.map +1 -0
- package/dist/defs/claude.js +130 -0
- package/dist/defs/claude.js.map +1 -0
- package/dist/defs/codebuddy.d.ts +26 -0
- package/dist/defs/codebuddy.d.ts.map +1 -0
- package/dist/defs/codebuddy.js +124 -0
- package/dist/defs/codebuddy.js.map +1 -0
- package/dist/defs/codex.d.ts +30 -0
- package/dist/defs/codex.d.ts.map +1 -0
- package/dist/defs/codex.js +196 -0
- package/dist/defs/codex.js.map +1 -0
- package/dist/defs/copilot.d.ts +12 -0
- package/dist/defs/copilot.d.ts.map +1 -0
- package/dist/defs/copilot.js +88 -0
- package/dist/defs/copilot.js.map +1 -0
- package/dist/defs/cursor-agent.d.ts +27 -0
- package/dist/defs/cursor-agent.d.ts.map +1 -0
- package/dist/defs/cursor-agent.js +93 -0
- package/dist/defs/cursor-agent.js.map +1 -0
- package/dist/defs/deepseek.d.ts +12 -0
- package/dist/defs/deepseek.d.ts.map +1 -0
- package/dist/defs/deepseek.js +53 -0
- package/dist/defs/deepseek.js.map +1 -0
- package/dist/defs/devin.d.ts +12 -0
- package/dist/defs/devin.d.ts.map +1 -0
- package/dist/defs/devin.js +45 -0
- package/dist/defs/devin.js.map +1 -0
- package/dist/defs/grok-build.d.ts +26 -0
- package/dist/defs/grok-build.d.ts.map +1 -0
- package/dist/defs/grok-build.js +105 -0
- package/dist/defs/grok-build.js.map +1 -0
- package/dist/defs/hermes.d.ts +13 -0
- package/dist/defs/hermes.d.ts.map +1 -0
- package/dist/defs/hermes.js +51 -0
- package/dist/defs/hermes.js.map +1 -0
- package/dist/defs/index.d.ts +33 -0
- package/dist/defs/index.d.ts.map +1 -0
- package/dist/defs/index.js +33 -0
- package/dist/defs/index.js.map +1 -0
- package/dist/defs/kilo.d.ts +12 -0
- package/dist/defs/kilo.d.ts.map +1 -0
- package/dist/defs/kilo.js +20 -0
- package/dist/defs/kilo.js.map +1 -0
- package/dist/defs/kimi.d.ts +13 -0
- package/dist/defs/kimi.d.ts.map +1 -0
- package/dist/defs/kimi.js +26 -0
- package/dist/defs/kimi.js.map +1 -0
- package/dist/defs/kiro.d.ts +12 -0
- package/dist/defs/kiro.d.ts.map +1 -0
- package/dist/defs/kiro.js +20 -0
- package/dist/defs/kiro.js.map +1 -0
- package/dist/defs/mimo.d.ts +13 -0
- package/dist/defs/mimo.d.ts.map +1 -0
- package/dist/defs/mimo.js +26 -0
- package/dist/defs/mimo.js.map +1 -0
- package/dist/defs/opencode.d.ts +27 -0
- package/dist/defs/opencode.d.ts.map +1 -0
- package/dist/defs/opencode.js +89 -0
- package/dist/defs/opencode.js.map +1 -0
- package/dist/defs/pi.d.ts +18 -0
- package/dist/defs/pi.d.ts.map +1 -0
- package/dist/defs/pi.js +94 -0
- package/dist/defs/pi.js.map +1 -0
- package/dist/defs/qoder.d.ts +11 -0
- package/dist/defs/qoder.d.ts.map +1 -0
- package/dist/defs/qoder.js +50 -0
- package/dist/defs/qoder.js.map +1 -0
- package/dist/defs/qwen.d.ts +11 -0
- package/dist/defs/qwen.d.ts.map +1 -0
- package/dist/defs/qwen.js +28 -0
- package/dist/defs/qwen.js.map +1 -0
- package/dist/defs/reasonix.d.ts +20 -0
- package/dist/defs/reasonix.d.ts.map +1 -0
- package/dist/defs/reasonix.js +60 -0
- package/dist/defs/reasonix.js.map +1 -0
- package/dist/defs/shared.d.ts +23 -0
- package/dist/defs/shared.d.ts.map +1 -0
- package/dist/defs/shared.js +58 -0
- package/dist/defs/shared.js.map +1 -0
- package/dist/defs/trae-cli.d.ts +14 -0
- package/dist/defs/trae-cli.d.ts.map +1 -0
- package/dist/defs/trae-cli.js +22 -0
- package/dist/defs/trae-cli.js.map +1 -0
- package/dist/defs/vibe.d.ts +12 -0
- package/dist/defs/vibe.d.ts.map +1 -0
- package/dist/defs/vibe.js +20 -0
- package/dist/defs/vibe.js.map +1 -0
- package/dist/detection.d.ts +14 -0
- package/dist/detection.d.ts.map +1 -0
- package/dist/detection.js +266 -0
- package/dist/detection.js.map +1 -0
- package/dist/diagnostics.d.ts +8 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +95 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/env.d.ts +19 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +95 -0
- package/dist/env.js.map +1 -0
- package/dist/executables.d.ts +24 -0
- package/dist/executables.d.ts.map +1 -0
- package/dist/executables.js +349 -0
- package/dist/executables.js.map +1 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +102 -0
- package/dist/index.js.map +1 -0
- package/dist/invocation.d.ts +6 -0
- package/dist/invocation.d.ts.map +1 -0
- package/dist/invocation.js +47 -0
- package/dist/invocation.js.map +1 -0
- package/dist/json-event-stream.d.ts +9 -0
- package/dist/json-event-stream.d.ts.map +1 -0
- package/dist/json-event-stream.js +856 -0
- package/dist/json-event-stream.js.map +1 -0
- package/dist/launch.d.ts +12 -0
- package/dist/launch.d.ts.map +1 -0
- package/dist/launch.js +221 -0
- package/dist/launch.js.map +1 -0
- package/dist/mcp.d.ts +44 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +12 -0
- package/dist/mcp.js.map +1 -0
- package/dist/metadata.d.ts +24 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +100 -0
- package/dist/metadata.js.map +1 -0
- package/dist/mmd-routes.d.ts +12 -0
- package/dist/mmd-routes.d.ts.map +1 -0
- package/dist/mmd-routes.js +146 -0
- package/dist/mmd-routes.js.map +1 -0
- package/dist/model-registry.d.ts +120 -0
- package/dist/model-registry.d.ts.map +1 -0
- package/dist/model-registry.js +77 -0
- package/dist/model-registry.js.map +1 -0
- package/dist/models.d.ts +16 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +93 -0
- package/dist/models.js.map +1 -0
- package/dist/opencode-log.d.ts +16 -0
- package/dist/opencode-log.d.ts.map +1 -0
- package/dist/opencode-log.js +163 -0
- package/dist/opencode-log.js.map +1 -0
- package/dist/paths.d.ts +3 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +29 -0
- package/dist/paths.js.map +1 -0
- package/dist/pi-models.d.ts +13 -0
- package/dist/pi-models.d.ts.map +1 -0
- package/dist/pi-models.js +36 -0
- package/dist/pi-models.js.map +1 -0
- package/dist/prompt-augmenter.d.ts +60 -0
- package/dist/prompt-augmenter.d.ts.map +1 -0
- package/dist/prompt-augmenter.js +26 -0
- package/dist/prompt-augmenter.js.map +1 -0
- package/dist/prompt-budget.d.ts +20 -0
- package/dist/prompt-budget.d.ts.map +1 -0
- package/dist/prompt-budget.js +226 -0
- package/dist/prompt-budget.js.map +1 -0
- package/dist/prompt-file.d.ts +7 -0
- package/dist/prompt-file.d.ts.map +1 -0
- package/dist/prompt-file.js +27 -0
- package/dist/prompt-file.js.map +1 -0
- package/dist/providers/aihubmix.d.ts +99 -0
- package/dist/providers/aihubmix.d.ts.map +1 -0
- package/dist/providers/aihubmix.js +239 -0
- package/dist/providers/aihubmix.js.map +1 -0
- package/dist/providers/anthropic-messages.d.ts +116 -0
- package/dist/providers/anthropic-messages.d.ts.map +1 -0
- package/dist/providers/anthropic-messages.js +313 -0
- package/dist/providers/anthropic-messages.js.map +1 -0
- package/dist/providers/azure-chat.d.ts +99 -0
- package/dist/providers/azure-chat.d.ts.map +1 -0
- package/dist/providers/azure-chat.js +164 -0
- package/dist/providers/azure-chat.js.map +1 -0
- package/dist/providers/connection-guard.d.ts +67 -0
- package/dist/providers/connection-guard.d.ts.map +1 -0
- package/dist/providers/connection-guard.js +211 -0
- package/dist/providers/connection-guard.js.map +1 -0
- package/dist/providers/elevenlabs.d.ts +28 -0
- package/dist/providers/elevenlabs.d.ts.map +1 -0
- package/dist/providers/elevenlabs.js +138 -0
- package/dist/providers/elevenlabs.js.map +1 -0
- package/dist/providers/google-messages.d.ts +108 -0
- package/dist/providers/google-messages.d.ts.map +1 -0
- package/dist/providers/google-messages.js +284 -0
- package/dist/providers/google-messages.js.map +1 -0
- package/dist/providers/google.d.ts +20 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +42 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/index.d.ts +39 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +39 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/model-catalog.d.ts +32 -0
- package/dist/providers/model-catalog.d.ts.map +1 -0
- package/dist/providers/model-catalog.js +394 -0
- package/dist/providers/model-catalog.js.map +1 -0
- package/dist/providers/oauth-callback-server.d.ts +35 -0
- package/dist/providers/oauth-callback-server.d.ts.map +1 -0
- package/dist/providers/oauth-callback-server.js +217 -0
- package/dist/providers/oauth-callback-server.js.map +1 -0
- package/dist/providers/oauth-credentials.d.ts +29 -0
- package/dist/providers/oauth-credentials.d.ts.map +1 -0
- package/dist/providers/oauth-credentials.js +70 -0
- package/dist/providers/oauth-credentials.js.map +1 -0
- package/dist/providers/oauth-provider.d.ts +95 -0
- package/dist/providers/oauth-provider.d.ts.map +1 -0
- package/dist/providers/oauth-provider.js +130 -0
- package/dist/providers/oauth-provider.js.map +1 -0
- package/dist/providers/oauth-tokens.d.ts +35 -0
- package/dist/providers/oauth-tokens.d.ts.map +1 -0
- package/dist/providers/oauth-tokens.js +136 -0
- package/dist/providers/oauth-tokens.js.map +1 -0
- package/dist/providers/ollama-chat.d.ts +106 -0
- package/dist/providers/ollama-chat.d.ts.map +1 -0
- package/dist/providers/ollama-chat.js +292 -0
- package/dist/providers/ollama-chat.js.map +1 -0
- package/dist/providers/openai-chat.d.ts +147 -0
- package/dist/providers/openai-chat.d.ts.map +1 -0
- package/dist/providers/openai-chat.js +302 -0
- package/dist/providers/openai-chat.js.map +1 -0
- package/dist/providers/pkce.d.ts +81 -0
- package/dist/providers/pkce.d.ts.map +1 -0
- package/dist/providers/pkce.js +176 -0
- package/dist/providers/pkce.js.map +1 -0
- package/dist/providers/sse-decode.d.ts +47 -0
- package/dist/providers/sse-decode.d.ts.map +1 -0
- package/dist/providers/sse-decode.js +109 -0
- package/dist/providers/sse-decode.js.map +1 -0
- package/dist/providers/token-params.d.ts +29 -0
- package/dist/providers/token-params.d.ts.map +1 -0
- package/dist/providers/token-params.js +41 -0
- package/dist/providers/token-params.js.map +1 -0
- package/dist/providers/turn-end-guard.d.ts +37 -0
- package/dist/providers/turn-end-guard.d.ts.map +1 -0
- package/dist/providers/turn-end-guard.js +42 -0
- package/dist/providers/turn-end-guard.js.map +1 -0
- package/dist/providers/types.d.ts +36 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +13 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/qoder-stream.d.ts +19 -0
- package/dist/qoder-stream.d.ts.map +1 -0
- package/dist/qoder-stream.js +167 -0
- package/dist/qoder-stream.js.map +1 -0
- package/dist/registry.d.ts +5 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +58 -0
- package/dist/registry.js.map +1 -0
- package/dist/resolution.d.ts +2 -0
- package/dist/resolution.d.ts.map +1 -0
- package/dist/resolution.js +19 -0
- package/dist/resolution.js.map +1 -0
- package/dist/role-marker-guard.d.ts +53 -0
- package/dist/role-marker-guard.d.ts.map +1 -0
- package/dist/role-marker-guard.js +280 -0
- package/dist/role-marker-guard.js.map +1 -0
- package/dist/telemetry-sink.d.ts +35 -0
- package/dist/telemetry-sink.d.ts.map +1 -0
- package/dist/telemetry-sink.js +5 -0
- package/dist/telemetry-sink.js.map +1 -0
- package/dist/terminal-launch.d.ts +11 -0
- package/dist/terminal-launch.d.ts.map +1 -0
- package/dist/terminal-launch.js +123 -0
- package/dist/terminal-launch.js.map +1 -0
- package/dist/types.d.ts +185 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { type TurnEndReason } from './turn-end-guard.js';
|
|
2
|
+
export interface OllamaFunctionToolDef {
|
|
3
|
+
readonly type: 'function';
|
|
4
|
+
readonly function: {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly description?: string;
|
|
7
|
+
readonly parameters: Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Ollama's native `/api/chat` tool-call shape — genuinely different from the
|
|
12
|
+
* OpenAI-compatible one this file's types were originally copied from:
|
|
13
|
+
* `arguments` is a native JSON object (not a stringified blob), and there is
|
|
14
|
+
* no `id`/`type` field at all (confirmed against Ollama's own documented
|
|
15
|
+
* "Chat request (No streaming, with tools)" example,
|
|
16
|
+
* `github.com/ollama/ollama/blob/main/docs/api.md`). Round-4 external audit
|
|
17
|
+
* (`AUD-R4-002`) found the first port had kept the OpenAI shape here, which
|
|
18
|
+
* a strict Ollama server can reject. Synthetic per-call `id`s are still
|
|
19
|
+
* generated (see `runSingleOllamaRequest`) but stay purely internal to this
|
|
20
|
+
* module's own event stream — they are never put on the wire.
|
|
21
|
+
*/
|
|
22
|
+
export interface OllamaToolCallParam {
|
|
23
|
+
readonly function: {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly arguments: unknown;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface OllamaMessageParam {
|
|
29
|
+
readonly role: 'system' | 'user' | 'assistant' | 'tool';
|
|
30
|
+
readonly content: string | null;
|
|
31
|
+
readonly tool_calls?: readonly OllamaToolCallParam[];
|
|
32
|
+
/** Ollama's native tool-result association field — NOT `tool_call_id` (that's the OpenAI shape; Ollama has no call-id concept on the wire). */
|
|
33
|
+
readonly tool_name?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface OllamaToolCall {
|
|
36
|
+
readonly id: string;
|
|
37
|
+
readonly name: string;
|
|
38
|
+
readonly input: unknown;
|
|
39
|
+
}
|
|
40
|
+
export interface OllamaToolResult {
|
|
41
|
+
readonly content: string;
|
|
42
|
+
}
|
|
43
|
+
/** Host-owned tool execution — same "the collaborator is always supplied" convention as `anthropic-messages.ts#AnthropicToolExecutor`. */
|
|
44
|
+
export type OllamaToolExecutor = (call: OllamaToolCall) => Promise<OllamaToolResult>;
|
|
45
|
+
export type OllamaTurnEndReason = TurnEndReason;
|
|
46
|
+
export type OllamaTurnEvent = {
|
|
47
|
+
readonly type: 'status';
|
|
48
|
+
readonly label: string;
|
|
49
|
+
} | {
|
|
50
|
+
readonly type: 'text_delta';
|
|
51
|
+
readonly delta: string;
|
|
52
|
+
} | {
|
|
53
|
+
readonly type: 'tool_use';
|
|
54
|
+
readonly id: string;
|
|
55
|
+
readonly name: string;
|
|
56
|
+
readonly input: unknown;
|
|
57
|
+
} | {
|
|
58
|
+
readonly type: 'tool_result';
|
|
59
|
+
readonly toolUseId: string;
|
|
60
|
+
readonly content: string;
|
|
61
|
+
readonly isError: boolean;
|
|
62
|
+
} | {
|
|
63
|
+
readonly type: 'usage';
|
|
64
|
+
readonly usage: Record<string, unknown> | null;
|
|
65
|
+
} | {
|
|
66
|
+
readonly type: 'fabricated_role_marker';
|
|
67
|
+
readonly marker: string;
|
|
68
|
+
readonly messageId: string;
|
|
69
|
+
} | {
|
|
70
|
+
readonly type: 'error';
|
|
71
|
+
readonly message: string;
|
|
72
|
+
readonly code?: string;
|
|
73
|
+
} | {
|
|
74
|
+
readonly type: 'end';
|
|
75
|
+
readonly reason: OllamaTurnEndReason;
|
|
76
|
+
};
|
|
77
|
+
export interface OllamaTurnOptions {
|
|
78
|
+
/** Required — see module doc (OD's real handler rejects a request with no apiKey). */
|
|
79
|
+
readonly apiKey: string;
|
|
80
|
+
/** Defaults to `https://ollama.com` (Ollama Cloud) — see module doc. Pass a local address explicitly to target a local install. */
|
|
81
|
+
readonly baseUrl?: string;
|
|
82
|
+
readonly model: string;
|
|
83
|
+
readonly messages: readonly OllamaMessageParam[];
|
|
84
|
+
readonly tools?: readonly OllamaFunctionToolDef[];
|
|
85
|
+
readonly temperature?: number;
|
|
86
|
+
readonly maxTokens?: number;
|
|
87
|
+
/** Same bound and rationale as `AnthropicTurnOptions.maxToolTurns`. Defaults to 8. */
|
|
88
|
+
readonly maxToolTurns?: number;
|
|
89
|
+
readonly executeTool?: OllamaToolExecutor;
|
|
90
|
+
readonly onEvent: (event: OllamaTurnEvent) => void;
|
|
91
|
+
readonly signal?: AbortSignal;
|
|
92
|
+
/** Caller-supplied extra headers — see `anthropic-messages.ts#AnthropicTurnOptions.extraHeaders`'s doc for why this exists and what it fixes. */
|
|
93
|
+
readonly extraHeaders?: Record<string, string>;
|
|
94
|
+
}
|
|
95
|
+
export interface OllamaTurnResult {
|
|
96
|
+
readonly finishReason: string | null;
|
|
97
|
+
readonly toolTurns: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Runs a full Ollama native `/api/chat` turn, including the tool-execution
|
|
101
|
+
* loop when `options.executeTool` is supplied and the model requests a
|
|
102
|
+
* function call. See `anthropic-messages.ts#runAnthropicToolTurn`'s doc for
|
|
103
|
+
* the shared event-stream/`ended`-flag contract this mirrors exactly.
|
|
104
|
+
*/
|
|
105
|
+
export declare function runOllamaToolTurn(options: OllamaTurnOptions): Promise<OllamaTurnResult>;
|
|
106
|
+
//# sourceMappingURL=ollama-chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama-chat.d.ts","sourceRoot":"","sources":["../../src/providers/ollama-chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module providers/ollama-chat
|
|
3
|
+
*
|
|
4
|
+
* Ollama native Chat API wire adapter + tool-loop turn-runner. Sibling of
|
|
5
|
+
* `anthropic-messages.ts`/`openai-chat.ts`/`azure-chat.ts` — see those
|
|
6
|
+
* modules' headers for the shared design rationale.
|
|
7
|
+
*
|
|
8
|
+
* **Corrected to match Open Design's real behavior** (an earlier version of
|
|
9
|
+
* this module targeted Ollama's OpenAI-compatible `/v1/chat/completions`
|
|
10
|
+
* surface instead — found wrong by a live side-by-side comparison against a
|
|
11
|
+
* running OD daemon, `apps/daemon/src/routes/chat.ts:1298`'s real
|
|
12
|
+
* `/api/proxy/ollama/stream` handler):
|
|
13
|
+
*
|
|
14
|
+
* - **Endpoint**: `{baseUrl}/api/chat` — Ollama's own native chat API, not
|
|
15
|
+
* the OpenAI-compatible shim. `baseUrl` has any trailing `/api` stripped
|
|
16
|
+
* before appending, matching OD's `.replace(/\/api\/?$/, '')`.
|
|
17
|
+
* - **Wire format**: newline-delimited JSON (NDJSON), one JSON object per
|
|
18
|
+
* line, terminated by a line with `"done": true` — NOT Server-Sent
|
|
19
|
+
* Events. `text_delta`s come from `message.content`; the terminal line's
|
|
20
|
+
* `done: true` ends the stream (see `runSingleOllamaRequest` below).
|
|
21
|
+
* - **`apiKey` is required**, like every other provider — OD's real handler
|
|
22
|
+
* rejects a request with no `apiKey` (`if (!apiKey || !model)`), because
|
|
23
|
+
* its default target is Ollama Cloud (see next point), not a bare local
|
|
24
|
+
* install.
|
|
25
|
+
* - **Default `baseUrl` is `https://ollama.com`** (Ollama Cloud), matching
|
|
26
|
+
* OD's `effectiveBaseUrl = baseUrl || 'https://ollama.com'` — not a local
|
|
27
|
+
* loopback address. A caller running a real local Ollama install still
|
|
28
|
+
* just passes `baseUrl: 'http://localhost:11434'` explicitly; the
|
|
29
|
+
* loopback carve-out in `connection-guard.ts` (documented there as
|
|
30
|
+
* existing "for local LLM servers like Ollama") still applies when they
|
|
31
|
+
* do.
|
|
32
|
+
* - **Token limit**: `options.num_predict` (Ollama's native token-limit
|
|
33
|
+
* field), sent only when `maxTokens` is a positive number — matches OD's
|
|
34
|
+
* `if (typeof maxTokens === 'number' && maxTokens > 0) payload.options = {
|
|
35
|
+
* num_predict: maxTokens }`.
|
|
36
|
+
*
|
|
37
|
+
* **Round-4 external audit fix (`AUD-R4-002`)**: the first port of this
|
|
38
|
+
* module's tool-call loop kept the OpenAI-compatible wire shape for both the
|
|
39
|
+
* emitted lifecycle event and the continuation request — `tool_use` was
|
|
40
|
+
* never emitted, and the assistant/tool continuation messages used a
|
|
41
|
+
* stringified `arguments` blob with `id`/`type`/`tool_call_id` fields that
|
|
42
|
+
* don't exist in Ollama's native tool-call schema. Fixed: `tool_use` now
|
|
43
|
+
* fires for every resolved call as soon as the stream ends (see
|
|
44
|
+
* `runSingleOllamaRequest`), and `OllamaToolCallParam`/`OllamaMessageParam`
|
|
45
|
+
* now match Ollama's own documented shape (`arguments` as a native object,
|
|
46
|
+
* `tool_name` instead of `tool_call_id` — see those interfaces' docs).
|
|
47
|
+
*
|
|
48
|
+
* **Deliberate extension beyond OD's own scope, not a parity gap**: OD's
|
|
49
|
+
* ollama handler never builds a `tools` field into its request and never
|
|
50
|
+
* reads `message.tool_calls` from the response — its own ollama proxy has
|
|
51
|
+
* no tool-calling support at all. Ollama's real native `/api/chat` API does
|
|
52
|
+
* support tool calling (a `tools` array in the same OpenAI
|
|
53
|
+
* function-declaration shape on the request, `message.tool_calls: [{id?,
|
|
54
|
+
* function: {name, arguments}}]` on a non-streaming-final response chunk —
|
|
55
|
+
* see `github.com/ollama/ollama/blob/main/docs/api.md#chat-request-with-
|
|
56
|
+
* tools`). This module keeps that capability (as the original, pre-parity-
|
|
57
|
+
* fix version of this file already did) rather than removing working
|
|
58
|
+
* functionality just to match a gap in OD's own product scope — matching
|
|
59
|
+
* this repo's established practice elsewhere (e.g. `xai.ts` deliberately
|
|
60
|
+
* generalizing OD's OAuth-connect *shape* while dropping its OD-specific
|
|
61
|
+
* SuperGrok billing gate).
|
|
62
|
+
*/
|
|
63
|
+
import { createRoleMarkerGuard } from '../role-marker-guard.js';
|
|
64
|
+
import { defaultDnsLookup, redactSecrets, validateBaseUrlResolved } from './connection-guard.js';
|
|
65
|
+
import { createTurnEndGuard } from './turn-end-guard.js';
|
|
66
|
+
const DEFAULT_OLLAMA_BASE_URL = 'https://ollama.com';
|
|
67
|
+
const DEFAULT_MAX_TOOL_TURNS = 8;
|
|
68
|
+
function isRecord(value) {
|
|
69
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
70
|
+
}
|
|
71
|
+
/** Strips a trailing `/api` (with or without a trailing slash) before appending `/api/chat` — matches OD's `.replace(/\/+$/, '').replace(/\/api\/?$/, '')` so a caller-supplied `baseUrl` ending in `/api` doesn't produce `/api/api/chat`. */
|
|
72
|
+
function ollamaRequestUrl(baseUrl) {
|
|
73
|
+
const trimmed = (baseUrl ?? DEFAULT_OLLAMA_BASE_URL).replace(/\/+$/, '').replace(/\/api\/?$/, '');
|
|
74
|
+
return `${trimmed}/api/chat`;
|
|
75
|
+
}
|
|
76
|
+
function ollamaHeaders(options) {
|
|
77
|
+
return {
|
|
78
|
+
'content-type': 'application/json',
|
|
79
|
+
authorization: `Bearer ${options.apiKey}`,
|
|
80
|
+
...(options.extraHeaders ?? {}),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function ollamaRequestBody(options, messages) {
|
|
84
|
+
const modelOptions = {};
|
|
85
|
+
if (options.temperature !== undefined)
|
|
86
|
+
modelOptions.temperature = options.temperature;
|
|
87
|
+
if (typeof options.maxTokens === 'number' && options.maxTokens > 0)
|
|
88
|
+
modelOptions.num_predict = options.maxTokens;
|
|
89
|
+
return {
|
|
90
|
+
model: options.model,
|
|
91
|
+
stream: true,
|
|
92
|
+
messages,
|
|
93
|
+
...(Object.keys(modelOptions).length > 0 ? { options: modelOptions } : {}),
|
|
94
|
+
...(options.tools && options.tools.length > 0 ? { tools: options.tools } : {}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function extractOllamaErrorDetail(rawText) {
|
|
98
|
+
try {
|
|
99
|
+
const parsed = JSON.parse(rawText);
|
|
100
|
+
if (isRecord(parsed) && typeof parsed.error === 'string')
|
|
101
|
+
return parsed.error;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// fall through to raw text
|
|
105
|
+
}
|
|
106
|
+
return rawText.slice(0, 500);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Reads a `fetch` response body as newline-delimited JSON, yielding one
|
|
110
|
+
* parsed line at a time. Buffers partial lines across chunk boundaries — an
|
|
111
|
+
* NDJSON line is not guaranteed to arrive in a single chunk. A trailing,
|
|
112
|
+
* unterminated final line (no closing newline) is still yielded once the
|
|
113
|
+
* stream ends, matching `sse-decode.ts#decodeSseStream`'s equivalent
|
|
114
|
+
* tolerance for the SSE case.
|
|
115
|
+
*/
|
|
116
|
+
async function* decodeNdjsonStream(body) {
|
|
117
|
+
const decoder = new TextDecoder();
|
|
118
|
+
let buffer = '';
|
|
119
|
+
for await (const chunk of body) {
|
|
120
|
+
buffer += typeof chunk === 'string' ? chunk : decoder.decode(chunk, { stream: true });
|
|
121
|
+
let newlineIndex;
|
|
122
|
+
while ((newlineIndex = buffer.indexOf('\n')) >= 0) {
|
|
123
|
+
const line = buffer.slice(0, newlineIndex).trim();
|
|
124
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
125
|
+
if (!line)
|
|
126
|
+
continue;
|
|
127
|
+
try {
|
|
128
|
+
yield JSON.parse(line);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
continue; // tolerate a malformed/empty keep-alive line
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const trailing = buffer.trim();
|
|
136
|
+
if (trailing) {
|
|
137
|
+
try {
|
|
138
|
+
yield JSON.parse(trailing);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// final partial line was never completed — nothing usable to yield
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** Runs exactly one Ollama `/api/chat` NDJSON streaming request and reduces it into a single outcome. Mirrors `anthropic-messages.ts#runSingleAnthropicRequest`'s `emitEnd` contract — see that function's doc. */
|
|
146
|
+
async function runSingleOllamaRequest(options, messages, emitEnd) {
|
|
147
|
+
const { onEvent } = options;
|
|
148
|
+
const baseUrlCheck = await validateBaseUrlResolved(options.baseUrl ?? DEFAULT_OLLAMA_BASE_URL, defaultDnsLookup);
|
|
149
|
+
if (baseUrlCheck.error) {
|
|
150
|
+
onEvent({ type: 'error', message: baseUrlCheck.error });
|
|
151
|
+
emitEnd('error');
|
|
152
|
+
return { finishReason: null, toolCalls: [], text: '' };
|
|
153
|
+
}
|
|
154
|
+
let response;
|
|
155
|
+
try {
|
|
156
|
+
response = (await fetch(ollamaRequestUrl(options.baseUrl), {
|
|
157
|
+
method: 'POST',
|
|
158
|
+
headers: ollamaHeaders(options),
|
|
159
|
+
body: JSON.stringify(ollamaRequestBody(options, messages)),
|
|
160
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
165
|
+
onEvent({ type: 'error', message: redactSecrets(message, [options.apiKey]) });
|
|
166
|
+
emitEnd('error');
|
|
167
|
+
return { finishReason: null, toolCalls: [], text: '' };
|
|
168
|
+
}
|
|
169
|
+
if (!response.ok) {
|
|
170
|
+
const rawText = await response.text();
|
|
171
|
+
onEvent({
|
|
172
|
+
type: 'error',
|
|
173
|
+
message: redactSecrets(extractOllamaErrorDetail(rawText), [options.apiKey]),
|
|
174
|
+
code: String(response.status),
|
|
175
|
+
});
|
|
176
|
+
emitEnd('error');
|
|
177
|
+
return { finishReason: null, toolCalls: [], text: '' };
|
|
178
|
+
}
|
|
179
|
+
if (!response.body) {
|
|
180
|
+
onEvent({ type: 'error', message: 'Ollama response had no body' });
|
|
181
|
+
emitEnd('error');
|
|
182
|
+
return { finishReason: null, toolCalls: [], text: '' };
|
|
183
|
+
}
|
|
184
|
+
onEvent({ type: 'status', label: 'requesting' });
|
|
185
|
+
const guard = createRoleMarkerGuard('ollama-turn');
|
|
186
|
+
let fullText = '';
|
|
187
|
+
const toolCalls = [];
|
|
188
|
+
let finishReason = null;
|
|
189
|
+
for await (const line of decodeNdjsonStream(response.body)) {
|
|
190
|
+
if (!isRecord(line))
|
|
191
|
+
continue;
|
|
192
|
+
const message = isRecord(line.message) ? line.message : null;
|
|
193
|
+
if (message && typeof message.content === 'string' && message.content.length > 0) {
|
|
194
|
+
const safe = guard.feedText(message.content);
|
|
195
|
+
if (safe.length > 0) {
|
|
196
|
+
fullText += safe;
|
|
197
|
+
onEvent({ type: 'text_delta', delta: safe });
|
|
198
|
+
}
|
|
199
|
+
if (guard.contaminated) {
|
|
200
|
+
const warn = guard.warningEvent();
|
|
201
|
+
if (warn)
|
|
202
|
+
onEvent(warn);
|
|
203
|
+
finishReason = 'contaminated';
|
|
204
|
+
emitEnd('contaminated');
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (message && Array.isArray(message.tool_calls)) {
|
|
209
|
+
for (const rawCall of message.tool_calls) {
|
|
210
|
+
if (!isRecord(rawCall) || !isRecord(rawCall.function))
|
|
211
|
+
continue;
|
|
212
|
+
const name = typeof rawCall.function.name === 'string' ? rawCall.function.name : '';
|
|
213
|
+
if (!name)
|
|
214
|
+
continue;
|
|
215
|
+
const args = rawCall.function.arguments;
|
|
216
|
+
const input = typeof args === 'string' ? (() => { try {
|
|
217
|
+
return JSON.parse(args);
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return args;
|
|
221
|
+
} })() : args;
|
|
222
|
+
const id = typeof rawCall.id === 'string' && rawCall.id ? rawCall.id : `ollama-tool-${toolCalls.length}`;
|
|
223
|
+
toolCalls.push({ id, name, input });
|
|
224
|
+
}
|
|
225
|
+
if (toolCalls.length > 0)
|
|
226
|
+
finishReason = 'tool_calls';
|
|
227
|
+
}
|
|
228
|
+
if (line.done === true) {
|
|
229
|
+
if (finishReason !== 'contaminated' && finishReason !== 'tool_calls')
|
|
230
|
+
finishReason = 'stop';
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Emitted for every resolved call as soon as the stream ends, independent of whether the
|
|
235
|
+
// caller actually supplied an `executeTool` — matches `openai-chat.ts#runOpenAiCompatibleRequest`'s
|
|
236
|
+
// identical unconditional-on-resolution emission (see AUD-R4-002 fix note in the module doc).
|
|
237
|
+
if (finishReason === 'tool_calls') {
|
|
238
|
+
for (const call of toolCalls) {
|
|
239
|
+
onEvent({ type: 'tool_use', id: call.id, name: call.name, input: call.input });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return { finishReason, toolCalls, text: fullText };
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Runs a full Ollama native `/api/chat` turn, including the tool-execution
|
|
246
|
+
* loop when `options.executeTool` is supplied and the model requests a
|
|
247
|
+
* function call. See `anthropic-messages.ts#runAnthropicToolTurn`'s doc for
|
|
248
|
+
* the shared event-stream/`ended`-flag contract this mirrors exactly.
|
|
249
|
+
*/
|
|
250
|
+
export async function runOllamaToolTurn(options) {
|
|
251
|
+
const maxToolTurns = options.maxToolTurns ?? DEFAULT_MAX_TOOL_TURNS;
|
|
252
|
+
const endGuard = createTurnEndGuard(options.onEvent, (reason) => ({ type: 'end', reason }));
|
|
253
|
+
const emitEnd = endGuard.emitEnd;
|
|
254
|
+
let messages = options.messages.slice();
|
|
255
|
+
let toolTurns = 0;
|
|
256
|
+
let lastFinishReason = null;
|
|
257
|
+
while (true) {
|
|
258
|
+
const outcome = await runSingleOllamaRequest(options, messages, emitEnd);
|
|
259
|
+
lastFinishReason = outcome.finishReason;
|
|
260
|
+
if (endGuard.hasEnded())
|
|
261
|
+
break;
|
|
262
|
+
if (outcome.finishReason !== 'tool_calls' || outcome.toolCalls.length === 0) {
|
|
263
|
+
emitEnd('stop');
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
if (!options.executeTool) {
|
|
267
|
+
emitEnd('stop');
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
if (toolTurns >= maxToolTurns) {
|
|
271
|
+
emitEnd('max_tool_turns');
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
toolTurns += 1;
|
|
275
|
+
const assistantToolCalls = outcome.toolCalls.map((call) => ({
|
|
276
|
+
function: { name: call.name, arguments: call.input },
|
|
277
|
+
}));
|
|
278
|
+
const toolResultMessages = [];
|
|
279
|
+
for (const call of outcome.toolCalls) {
|
|
280
|
+
const result = await options.executeTool(call);
|
|
281
|
+
options.onEvent({ type: 'tool_result', toolUseId: call.id, content: result.content, isError: false });
|
|
282
|
+
toolResultMessages.push({ role: 'tool', content: result.content, tool_name: call.name });
|
|
283
|
+
}
|
|
284
|
+
messages = [
|
|
285
|
+
...messages,
|
|
286
|
+
{ role: 'assistant', content: outcome.text || null, tool_calls: assistantToolCalls },
|
|
287
|
+
...toolResultMessages,
|
|
288
|
+
];
|
|
289
|
+
}
|
|
290
|
+
return { finishReason: lastFinishReason, toolTurns };
|
|
291
|
+
}
|
|
292
|
+
//# sourceMappingURL=ollama-chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama-chat.js","sourceRoot":"","sources":["../../src/providers/ollama-chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { type TurnEndReason } from './turn-end-guard.js';
|
|
2
|
+
export interface OpenAiFunctionToolDef {
|
|
3
|
+
readonly type: 'function';
|
|
4
|
+
readonly function: {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly description?: string;
|
|
7
|
+
readonly parameters: Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export interface OpenAiToolCallParam {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly type: 'function';
|
|
13
|
+
readonly function: {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly arguments: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface OpenAiMessageParam {
|
|
19
|
+
readonly role: 'system' | 'user' | 'assistant' | 'tool';
|
|
20
|
+
readonly content: string | null;
|
|
21
|
+
readonly tool_calls?: readonly OpenAiToolCallParam[];
|
|
22
|
+
readonly tool_call_id?: string;
|
|
23
|
+
readonly name?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface OpenAiToolCall {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly input: unknown;
|
|
29
|
+
}
|
|
30
|
+
export interface OpenAiToolResult {
|
|
31
|
+
readonly content: string;
|
|
32
|
+
}
|
|
33
|
+
/** Host-owned tool execution — same "the collaborator is always supplied" convention as `anthropic-messages.ts#AnthropicToolExecutor`. */
|
|
34
|
+
export type OpenAiToolExecutor = (call: OpenAiToolCall) => Promise<OpenAiToolResult>;
|
|
35
|
+
export type OpenAiTurnEndReason = TurnEndReason;
|
|
36
|
+
export type OpenAiTurnEvent = {
|
|
37
|
+
readonly type: 'status';
|
|
38
|
+
readonly label: string;
|
|
39
|
+
} | {
|
|
40
|
+
readonly type: 'text_delta';
|
|
41
|
+
readonly delta: string;
|
|
42
|
+
} | {
|
|
43
|
+
readonly type: 'tool_use';
|
|
44
|
+
readonly id: string;
|
|
45
|
+
readonly name: string;
|
|
46
|
+
readonly input: unknown;
|
|
47
|
+
} | {
|
|
48
|
+
readonly type: 'tool_result';
|
|
49
|
+
readonly toolUseId: string;
|
|
50
|
+
readonly content: string;
|
|
51
|
+
readonly isError: boolean;
|
|
52
|
+
} | {
|
|
53
|
+
readonly type: 'usage';
|
|
54
|
+
readonly usage: Record<string, unknown> | null;
|
|
55
|
+
} | {
|
|
56
|
+
readonly type: 'fabricated_role_marker';
|
|
57
|
+
readonly marker: string;
|
|
58
|
+
readonly messageId: string;
|
|
59
|
+
} | {
|
|
60
|
+
readonly type: 'error';
|
|
61
|
+
readonly message: string;
|
|
62
|
+
readonly code?: string;
|
|
63
|
+
} | {
|
|
64
|
+
readonly type: 'end';
|
|
65
|
+
readonly reason: OpenAiTurnEndReason;
|
|
66
|
+
};
|
|
67
|
+
export interface OpenAiTurnOptions {
|
|
68
|
+
readonly apiKey: string;
|
|
69
|
+
/** Defaults to `https://api.openai.com`. Overridable for OpenAI-compatible gateways (matching `providers/model-catalog.ts`'s `openai`-protocol `baseUrl` convention). */
|
|
70
|
+
readonly baseUrl?: string;
|
|
71
|
+
readonly model: string;
|
|
72
|
+
readonly messages: readonly OpenAiMessageParam[];
|
|
73
|
+
readonly tools?: readonly OpenAiFunctionToolDef[];
|
|
74
|
+
readonly temperature?: number;
|
|
75
|
+
/** Defaults to {@link DEFAULT_OPENAI_MAX_TOKENS} (8192) when omitted or not a positive number — a token limit is always sent, matching OD's real behavior (see module doc). */
|
|
76
|
+
readonly maxTokens?: number;
|
|
77
|
+
/** Same bound and rationale as `AnthropicTurnOptions.maxToolTurns`. Defaults to 8. */
|
|
78
|
+
readonly maxToolTurns?: number;
|
|
79
|
+
readonly executeTool?: OpenAiToolExecutor;
|
|
80
|
+
readonly onEvent: (event: OpenAiTurnEvent) => void;
|
|
81
|
+
readonly signal?: AbortSignal;
|
|
82
|
+
/** Caller-supplied extra headers — see `anthropic-messages.ts#AnthropicTurnOptions.extraHeaders`'s doc for why this exists and what it fixes. */
|
|
83
|
+
readonly extraHeaders?: Record<string, string>;
|
|
84
|
+
}
|
|
85
|
+
export interface OpenAiTurnResult {
|
|
86
|
+
readonly finishReason: string | null;
|
|
87
|
+
readonly toolTurns: number;
|
|
88
|
+
}
|
|
89
|
+
/** Matches OD's own default (`apps/daemon/src/routes/chat.ts`'s openai/azure handlers both fall back to this when the caller doesn't supply one) — a real, explicit bound is always sent, never an unbounded request. */
|
|
90
|
+
export declare const DEFAULT_OPENAI_MAX_TOKENS = 8192;
|
|
91
|
+
/** Shared return shape for one reduced OpenAI-compatible streaming request — exported so every OpenAI-compatible provider turn-runner (`azure-chat.ts`, `ollama-chat.ts`) can type its own internal single-request helper against it without re-declaring an identical interface. */
|
|
92
|
+
export interface OpenAiCompatibleRequestOutcome {
|
|
93
|
+
readonly finishReason: string | null;
|
|
94
|
+
readonly toolCalls: readonly OpenAiToolCall[];
|
|
95
|
+
readonly text: string;
|
|
96
|
+
}
|
|
97
|
+
/** Injected parameters for {@link runOpenAiCompatibleRequest}. Every OpenAI-compatible provider builds its own URL/headers/body (its own auth scheme, its own base-URL default and SSRF validation) and hands the finished request to this shared reducer — see that function's doc for why. */
|
|
98
|
+
export interface OpenAiCompatibleRequestInit {
|
|
99
|
+
readonly url: string;
|
|
100
|
+
readonly headers: Record<string, string>;
|
|
101
|
+
readonly body: Record<string, unknown>;
|
|
102
|
+
readonly signal?: AbortSignal;
|
|
103
|
+
/** Secrets to strip out of any error message surfaced to the caller (e.g. the request's API key) — forwarded verbatim to `redactSecrets`'s `exactSecrets` parameter. */
|
|
104
|
+
readonly redactSecretsList: ReadonlyArray<string | undefined | null>;
|
|
105
|
+
/** Role-marker guard message id — distinguishes each provider's stream in guard telemetry (`'openai-turn'`, `'azure-turn'`, `'ollama-turn'`). */
|
|
106
|
+
readonly guardMessageId: string;
|
|
107
|
+
/** Human-readable provider name used in the "response had no body" fallback error message (e.g. `'OpenAI'`, `'Azure OpenAI'`, `'Ollama'`). */
|
|
108
|
+
readonly providerLabel: string;
|
|
109
|
+
readonly onEvent: (event: OpenAiTurnEvent) => void;
|
|
110
|
+
readonly emitEnd: (reason: OpenAiTurnEndReason) => void;
|
|
111
|
+
readonly hasEnded: () => boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Optional single-retry hook: called with the HTTP status and raw error
|
|
114
|
+
* body text on a non-ok response, before the error is treated as
|
|
115
|
+
* terminal. Return a replacement request body to retry once with, or
|
|
116
|
+
* `null`/`undefined` to fall through to the normal error path. Matches
|
|
117
|
+
* OD's real `[proxy:azure]` handler, which retries a 400
|
|
118
|
+
* `isUnsupportedMaxTokensError` response with `max_completion_tokens`
|
|
119
|
+
* (see `azure-chat.ts`). Cleared on the retried call so a second failure
|
|
120
|
+
* cannot retry again.
|
|
121
|
+
*/
|
|
122
|
+
readonly retryableBody?: (status: number, rawErrorText: string) => Record<string, unknown> | null | undefined;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Runs exactly one OpenAI-compatible (Chat Completions JSON wire format)
|
|
126
|
+
* streaming HTTP request and reduces its SSE events into a single outcome.
|
|
127
|
+
* Extracted so this ~150-line SSE-reduction loop has exactly one
|
|
128
|
+
* implementation shared by every OpenAI-compatible provider turn-runner in
|
|
129
|
+
* this package: `runOpenAiToolTurn` itself (below), plus
|
|
130
|
+
* `azure-chat.ts#runAzureToolTurn` and `ollama-chat.ts#runOllamaToolTurn` —
|
|
131
|
+
* both target byte-identical chat-completions JSON, differing only in URL
|
|
132
|
+
* and auth. Callers own their own base-URL SSRF validation
|
|
133
|
+
* (`validateBaseUrl`) and URL/header/body construction *before* calling
|
|
134
|
+
* this function — it only knows how to run *a* request against whatever
|
|
135
|
+
* URL/headers/body it is handed, and has no opinion on any provider's
|
|
136
|
+
* defaults. Mirrors `anthropic-messages.ts#runSingleAnthropicRequest`'s
|
|
137
|
+
* `emitEnd` contract — see that function's doc.
|
|
138
|
+
*/
|
|
139
|
+
export declare function runOpenAiCompatibleRequest(init: OpenAiCompatibleRequestInit): Promise<OpenAiCompatibleRequestOutcome>;
|
|
140
|
+
/**
|
|
141
|
+
* Runs a full OpenAI Chat Completions turn, including the tool-execution
|
|
142
|
+
* loop when `options.executeTool` is supplied and the model requests a
|
|
143
|
+
* function call. See `anthropic-messages.ts#runAnthropicToolTurn`'s doc for
|
|
144
|
+
* the shared event-stream/`ended`-flag contract this mirrors exactly.
|
|
145
|
+
*/
|
|
146
|
+
export declare function runOpenAiToolTurn(options: OpenAiTurnOptions): Promise<OpenAiTurnResult>;
|
|
147
|
+
//# sourceMappingURL=openai-chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-chat.d.ts","sourceRoot":"","sources":["../../src/providers/openai-chat.ts"],"names":[],"mappings":"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"}
|