@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,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module providers/model-catalog
|
|
3
|
+
*
|
|
4
|
+
* Live model-catalog discovery for BYOK providers (OpenAI-compatible,
|
|
5
|
+
* Anthropic, Google, AIHubMix, SenseAudio, plus static seeds for Bedrock and
|
|
6
|
+
* an explicit "unsupported" response for Azure). Ported from OD's
|
|
7
|
+
* `integrations/provider-models.ts` (`listProviderModels`) with its
|
|
8
|
+
* upstream contracts-package type imports repointed at this package's own
|
|
9
|
+
* vendored `types.ts`, and its `../connectionTest.js` SSRF-guard /
|
|
10
|
+
* secret-redaction imports repointed at this package's own vendored
|
|
11
|
+
* `connection-guard.ts` (see that module's doc comment for what was and
|
|
12
|
+
* wasn't pulled from the 2,600-line origin file). Logic is otherwise
|
|
13
|
+
* unchanged — product-neutral as found (a bare BYOK-protocol model lister,
|
|
14
|
+
* no OD-branded strings).
|
|
15
|
+
*/
|
|
16
|
+
import { defaultDnsLookup, redactSecrets, validateBaseUrlResolved } from './connection-guard.js';
|
|
17
|
+
import { aihubmixCatalogUrl, aihubmixHeaders, parseAIHubMixCatalog } from './aihubmix.js';
|
|
18
|
+
import { googleProviderModelsUrl, normalizeGoogleModelId } from './google.js';
|
|
19
|
+
const PROVIDER_MODELS_TIMEOUT_MS = 12_000;
|
|
20
|
+
const BEDROCK_MODEL_OPTIONS = [
|
|
21
|
+
{ id: 'anthropic.claude-3-5-sonnet-20241022-v2:0', label: 'Claude 3.5 Sonnet v2' },
|
|
22
|
+
{ id: 'anthropic.claude-3-5-haiku-20241022-v1:0', label: 'Claude 3.5 Haiku' },
|
|
23
|
+
{ id: 'anthropic.claude-3-haiku-20240307-v1:0', label: 'Claude 3 Haiku' },
|
|
24
|
+
{ id: 'amazon.nova-pro-v1:0', label: 'Amazon Nova Pro' },
|
|
25
|
+
{ id: 'amazon.nova-lite-v1:0', label: 'Amazon Nova Lite' },
|
|
26
|
+
{ id: 'amazon.nova-micro-v1:0', label: 'Amazon Nova Micro' },
|
|
27
|
+
];
|
|
28
|
+
function appendVersionedApiPath(baseUrl, suffix) {
|
|
29
|
+
const url = new URL(baseUrl);
|
|
30
|
+
const pathname = url.pathname.replace(/\/+$/, '');
|
|
31
|
+
url.pathname = /\/v\d+(\/|$)/.test(pathname)
|
|
32
|
+
? `${pathname}${suffix}`
|
|
33
|
+
: `${pathname}/v1${suffix}`;
|
|
34
|
+
return url.toString();
|
|
35
|
+
}
|
|
36
|
+
function statusToKind(status) {
|
|
37
|
+
if (status === 401)
|
|
38
|
+
return 'auth_failed';
|
|
39
|
+
if (status === 403)
|
|
40
|
+
return 'forbidden';
|
|
41
|
+
if (status === 404)
|
|
42
|
+
return 'invalid_base_url';
|
|
43
|
+
if (status === 429)
|
|
44
|
+
return 'rate_limited';
|
|
45
|
+
if (status >= 500)
|
|
46
|
+
return 'upstream_unavailable';
|
|
47
|
+
return 'unknown';
|
|
48
|
+
}
|
|
49
|
+
function extractProviderErrorDetail(data, rawText) {
|
|
50
|
+
const obj = data && typeof data === 'object' ? data : null;
|
|
51
|
+
const error = obj ? obj.error : null;
|
|
52
|
+
if (typeof error === 'string')
|
|
53
|
+
return error;
|
|
54
|
+
if (error && typeof error === 'object') {
|
|
55
|
+
const message = error.message;
|
|
56
|
+
if (typeof message === 'string' && message.trim())
|
|
57
|
+
return message;
|
|
58
|
+
}
|
|
59
|
+
const message = obj ? obj.message : null;
|
|
60
|
+
if (typeof message === 'string' && message.trim())
|
|
61
|
+
return message;
|
|
62
|
+
return rawText.trim().slice(0, 240);
|
|
63
|
+
}
|
|
64
|
+
function networkErrorToKind(err) {
|
|
65
|
+
if (err instanceof Error) {
|
|
66
|
+
if (err.name === 'AbortError')
|
|
67
|
+
return 'timeout';
|
|
68
|
+
const cause = err.cause;
|
|
69
|
+
const code = cause?.code;
|
|
70
|
+
if (code === 'ENOTFOUND' ||
|
|
71
|
+
code === 'EAI_AGAIN' ||
|
|
72
|
+
code === 'ECONNREFUSED' ||
|
|
73
|
+
code === 'ECONNRESET' ||
|
|
74
|
+
code === 'ETIMEDOUT' ||
|
|
75
|
+
code === 'EHOSTUNREACH' ||
|
|
76
|
+
code === 'ENETUNREACH' ||
|
|
77
|
+
code === 'CERT_HAS_EXPIRED' ||
|
|
78
|
+
code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE') {
|
|
79
|
+
return 'invalid_base_url';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return 'unknown';
|
|
83
|
+
}
|
|
84
|
+
function uniqueModels(models) {
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const model of models) {
|
|
88
|
+
const id = model.id.trim();
|
|
89
|
+
if (!id || seen.has(id))
|
|
90
|
+
continue;
|
|
91
|
+
seen.add(id);
|
|
92
|
+
out.push({ id, label: model.label.trim() || id });
|
|
93
|
+
}
|
|
94
|
+
return out.sort((a, b) => a.id.localeCompare(b.id));
|
|
95
|
+
}
|
|
96
|
+
function isOpenAiChatModelId(id) {
|
|
97
|
+
const normalized = id.trim().toLowerCase();
|
|
98
|
+
if (!normalized)
|
|
99
|
+
return false;
|
|
100
|
+
if (normalized.includes('embedding') ||
|
|
101
|
+
normalized.includes('moderation') ||
|
|
102
|
+
normalized.includes('rerank') ||
|
|
103
|
+
normalized.includes('whisper') ||
|
|
104
|
+
normalized.includes('tts') ||
|
|
105
|
+
normalized.includes('transcribe') ||
|
|
106
|
+
normalized.includes('speech') ||
|
|
107
|
+
normalized.includes('image') ||
|
|
108
|
+
normalized.includes('video') ||
|
|
109
|
+
normalized.includes('dall-e') ||
|
|
110
|
+
normalized.includes('stable-diffusion') ||
|
|
111
|
+
normalized.includes('flux') ||
|
|
112
|
+
(normalized.includes('wan') &&
|
|
113
|
+
/(?:^|[-_.:])(?:t2v|i2v|v2v)(?:[-_.:]|$)/u.test(normalized))) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
return !/(?:^|[-_.:])(?:t2i|i2i|t2v|i2v|v2v|tts|asr|ocr)(?:[-_.:]|$)/u.test(normalized);
|
|
117
|
+
}
|
|
118
|
+
function extractOpenAiModels(data) {
|
|
119
|
+
const items = data.data;
|
|
120
|
+
if (!Array.isArray(items))
|
|
121
|
+
return [];
|
|
122
|
+
return uniqueModels(items
|
|
123
|
+
.map((item) => item?.id)
|
|
124
|
+
.filter((id) => typeof id === 'string' && id.length > 0)
|
|
125
|
+
.filter(isOpenAiChatModelId)
|
|
126
|
+
.map((id) => ({ id, label: id })));
|
|
127
|
+
}
|
|
128
|
+
function extractAnthropicModels(data) {
|
|
129
|
+
const items = data.data;
|
|
130
|
+
if (!Array.isArray(items))
|
|
131
|
+
return [];
|
|
132
|
+
return uniqueModels(items
|
|
133
|
+
.map((item) => {
|
|
134
|
+
const obj = item && typeof item === 'object'
|
|
135
|
+
? item
|
|
136
|
+
: null;
|
|
137
|
+
const id = typeof obj?.id === 'string' ? obj.id : '';
|
|
138
|
+
const label = typeof obj?.display_name === 'string'
|
|
139
|
+
? obj.display_name
|
|
140
|
+
: typeof obj?.displayName === 'string'
|
|
141
|
+
? obj.displayName
|
|
142
|
+
: id;
|
|
143
|
+
return id ? { id, label } : null;
|
|
144
|
+
})
|
|
145
|
+
.filter((item) => item != null));
|
|
146
|
+
}
|
|
147
|
+
function googleModelId(rawName, rawBaseModelId) {
|
|
148
|
+
if (typeof rawBaseModelId === 'string' && rawBaseModelId.trim()) {
|
|
149
|
+
return normalizeGoogleModelId(rawBaseModelId);
|
|
150
|
+
}
|
|
151
|
+
if (typeof rawName !== 'string')
|
|
152
|
+
return '';
|
|
153
|
+
return normalizeGoogleModelId(rawName);
|
|
154
|
+
}
|
|
155
|
+
function supportsGoogleGenerateContent(item) {
|
|
156
|
+
const methods = item
|
|
157
|
+
?.supportedGenerationMethods
|
|
158
|
+
?? item?.supported_actions;
|
|
159
|
+
return Array.isArray(methods) && methods.includes('generateContent');
|
|
160
|
+
}
|
|
161
|
+
function extractGoogleModels(data) {
|
|
162
|
+
const items = data.models;
|
|
163
|
+
if (!Array.isArray(items))
|
|
164
|
+
return [];
|
|
165
|
+
return uniqueModels(items
|
|
166
|
+
// supportsGoogleGenerateContent only returns true for an item whose
|
|
167
|
+
// (optionally-chained) supportedGenerationMethods/supported_actions
|
|
168
|
+
// resolves to an array — a non-object item can never satisfy that, so
|
|
169
|
+
// every item reaching .map() below is already known to be an object.
|
|
170
|
+
// No redundant `typeof item === 'object'` re-check here.
|
|
171
|
+
.filter(supportsGoogleGenerateContent)
|
|
172
|
+
.map((item) => {
|
|
173
|
+
const obj = item;
|
|
174
|
+
const id = googleModelId(obj.name, obj.baseModelId);
|
|
175
|
+
const label = typeof obj.displayName === 'string' && obj.displayName.trim()
|
|
176
|
+
? obj.displayName
|
|
177
|
+
: id;
|
|
178
|
+
return id ? { id, label } : null;
|
|
179
|
+
})
|
|
180
|
+
.filter((item) => item != null));
|
|
181
|
+
}
|
|
182
|
+
function providerModelsUrl(protocol, baseUrl, apiKey) {
|
|
183
|
+
if (protocol === 'aihubmix') {
|
|
184
|
+
// AIHubMix exposes its chat catalogue on a dedicated endpoint
|
|
185
|
+
// (GET /api/v1/models?type=llm), not the OpenAI /v1/models route.
|
|
186
|
+
return aihubmixCatalogUrl(baseUrl, 'llm');
|
|
187
|
+
}
|
|
188
|
+
if (protocol === 'openai' || protocol === 'senseaudio') {
|
|
189
|
+
return appendVersionedApiPath(baseUrl, '/models');
|
|
190
|
+
}
|
|
191
|
+
if (protocol === 'anthropic') {
|
|
192
|
+
const url = new URL(appendVersionedApiPath(baseUrl, '/models'));
|
|
193
|
+
url.searchParams.set('limit', '1000');
|
|
194
|
+
return url.toString();
|
|
195
|
+
}
|
|
196
|
+
if (protocol === 'google') {
|
|
197
|
+
return googleProviderModelsUrl(baseUrl, apiKey);
|
|
198
|
+
}
|
|
199
|
+
throw new Error(`Unsupported protocol: ${protocol}`);
|
|
200
|
+
}
|
|
201
|
+
function providerModelsHeaders(protocol, apiKey) {
|
|
202
|
+
if (protocol === 'openai' || protocol === 'senseaudio') {
|
|
203
|
+
return { authorization: `Bearer ${apiKey}` };
|
|
204
|
+
}
|
|
205
|
+
if (protocol === 'aihubmix') {
|
|
206
|
+
// The catalogue is public — only attach Bearer auth (+ APP-Code) when the
|
|
207
|
+
// caller actually supplied a key. An empty `Bearer ` would be rejected by
|
|
208
|
+
// some gateways, so send no headers when the key is blank.
|
|
209
|
+
return apiKey.trim() ? aihubmixHeaders(apiKey) : {};
|
|
210
|
+
}
|
|
211
|
+
if (protocol === 'anthropic') {
|
|
212
|
+
return {
|
|
213
|
+
'x-api-key': apiKey,
|
|
214
|
+
'anthropic-version': '2023-06-01',
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return {};
|
|
218
|
+
}
|
|
219
|
+
function extractModels(protocol, data) {
|
|
220
|
+
// SenseAudio's /v1/models response follows the OpenAI envelope
|
|
221
|
+
// (`{ data: [{ id, ... }] }`), so the same extractor handles both.
|
|
222
|
+
// Chat picker: drop media-generation rows. AIHubMix's `?type=llm` matches any
|
|
223
|
+
// model whose `types` merely contains `llm`, so dual-tagged image models
|
|
224
|
+
// (e.g. gpt-image-2 -> "image_generation,llm") would otherwise leak in. Those
|
|
225
|
+
// belong to the dedicated image/video/audio pickers.
|
|
226
|
+
if (protocol === 'aihubmix')
|
|
227
|
+
return parseAIHubMixCatalog(data, { chatOnly: true });
|
|
228
|
+
if (protocol === 'openai' || protocol === 'senseaudio')
|
|
229
|
+
return extractOpenAiModels(data);
|
|
230
|
+
if (protocol === 'anthropic')
|
|
231
|
+
return extractAnthropicModels(data);
|
|
232
|
+
return extractGoogleModels(data);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Fetches the live model catalog for a BYOK provider connection. Validates
|
|
236
|
+
* the base URL (sync + DNS-resolved SSRF guard) before issuing any request,
|
|
237
|
+
* dispatches per-protocol (a static seed for Bedrock, an explicit
|
|
238
|
+
* "unsupported" response for Azure), and normalizes every provider's
|
|
239
|
+
* response envelope into a de-duplicated, alphabetized `{ id, label }[]`.
|
|
240
|
+
*/
|
|
241
|
+
export async function listProviderModels(input) {
|
|
242
|
+
const start = Date.now();
|
|
243
|
+
if (input.protocol === 'azure') {
|
|
244
|
+
return {
|
|
245
|
+
ok: false,
|
|
246
|
+
kind: 'unsupported_protocol',
|
|
247
|
+
latencyMs: Date.now() - start,
|
|
248
|
+
detail: 'Azure OpenAI deployment discovery is not supported from the inference endpoint.',
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
const validated = await validateBaseUrlResolved(input.baseUrl, input.dnsLookup ?? defaultDnsLookup);
|
|
252
|
+
if (validated.error || !validated.parsed) {
|
|
253
|
+
return {
|
|
254
|
+
ok: false,
|
|
255
|
+
kind: validated.forbidden ? 'forbidden' : 'invalid_base_url',
|
|
256
|
+
latencyMs: Date.now() - start,
|
|
257
|
+
// Non-null assertion, not a runtime guard: every BaseUrlValidationResult
|
|
258
|
+
// this branch's guard condition can produce sets `error` alongside a
|
|
259
|
+
// missing `parsed` (connection-guard.ts never returns neither/both) —
|
|
260
|
+
// `?? ''` would satisfy the `detail: string` type too, but per this
|
|
261
|
+
// package's coverage-loop policy an assertion is more honest about
|
|
262
|
+
// "TS requires an `undefined` guard here that can't actually occur".
|
|
263
|
+
detail: validated.error,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
if (input.protocol === 'bedrock') {
|
|
267
|
+
return {
|
|
268
|
+
ok: true,
|
|
269
|
+
kind: 'success',
|
|
270
|
+
latencyMs: Date.now() - start,
|
|
271
|
+
models: BEDROCK_MODEL_OPTIONS,
|
|
272
|
+
detail: 'AWS Bedrock uses a static seed until AWS credential-backed discovery is available.',
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
let url;
|
|
276
|
+
try {
|
|
277
|
+
url = providerModelsUrl(input.protocol, input.baseUrl, input.apiKey);
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
return {
|
|
281
|
+
ok: false,
|
|
282
|
+
kind: 'unsupported_protocol',
|
|
283
|
+
latencyMs: Date.now() - start,
|
|
284
|
+
// `providerModelsUrl`'s only throw site is `throw new Error(...)`; the
|
|
285
|
+
// cast (rather than an `instanceof` guard) documents that the
|
|
286
|
+
// non-Error case can't occur here without adding an untestable branch.
|
|
287
|
+
detail: err.message,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
const controller = new AbortController();
|
|
291
|
+
const abortFromParent = () => controller.abort();
|
|
292
|
+
if (input.signal?.aborted) {
|
|
293
|
+
controller.abort();
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
input.signal?.addEventListener('abort', abortFromParent, { once: true });
|
|
297
|
+
}
|
|
298
|
+
const timer = setTimeout(() => controller.abort(), PROVIDER_MODELS_TIMEOUT_MS);
|
|
299
|
+
// `result` + a trailing `return result;` after the try/catch/finally,
|
|
300
|
+
// rather than returning directly from inside `catch` (every return inside
|
|
301
|
+
// `try` stays a direct early return): a v8/istanbul coverage-instrumentation
|
|
302
|
+
// artifact, re-derived empirically for this exact shape (a minimal
|
|
303
|
+
// `try { return A } catch { return B } finally {}` repro reproduces an
|
|
304
|
+
// uncoverable phantom branch at the `finally` clause's own opening brace,
|
|
305
|
+
// regardless of which/how many try/catch paths a test exercises — verified
|
|
306
|
+
// with `success`, `try-throws-then-caught`, and `throw-from-inside-catch`
|
|
307
|
+
// scenarios, all leaving the same phantom branch at 0). Only `catch`
|
|
308
|
+
// needed to change: with `try`'s own returns direct and only `catch`
|
|
309
|
+
// falling through, the phantom branch doesn't appear (also re-derived).
|
|
310
|
+
// TypeScript accepts `result` as definitely assigned at the trailing
|
|
311
|
+
// `return` because every real path through `try` above already returns or
|
|
312
|
+
// throws — the only way to fall through to it is via `catch`, which
|
|
313
|
+
// assigns unconditionally.
|
|
314
|
+
let result;
|
|
315
|
+
try {
|
|
316
|
+
const response = await fetch(url, {
|
|
317
|
+
method: 'GET',
|
|
318
|
+
headers: providerModelsHeaders(input.protocol, input.apiKey),
|
|
319
|
+
...input.requestInit,
|
|
320
|
+
signal: controller.signal,
|
|
321
|
+
redirect: 'error',
|
|
322
|
+
});
|
|
323
|
+
const latencyMs = Date.now() - start;
|
|
324
|
+
const rawText = await response.text();
|
|
325
|
+
let data = {};
|
|
326
|
+
let parseError;
|
|
327
|
+
try {
|
|
328
|
+
data = rawText ? JSON.parse(rawText) : {};
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
// JSON.parse only ever throws a SyntaxError (an Error); the cast
|
|
332
|
+
// documents that rather than adding an untestable non-Error branch.
|
|
333
|
+
parseError = err.message;
|
|
334
|
+
}
|
|
335
|
+
if (!response.ok) {
|
|
336
|
+
const detail = parseError
|
|
337
|
+
? rawText.trim().slice(0, 240) || parseError
|
|
338
|
+
: extractProviderErrorDetail(data, rawText);
|
|
339
|
+
return {
|
|
340
|
+
ok: false,
|
|
341
|
+
kind: statusToKind(response.status),
|
|
342
|
+
latencyMs,
|
|
343
|
+
status: response.status,
|
|
344
|
+
detail: redactSecrets(detail, [input.apiKey]),
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
if (parseError) {
|
|
348
|
+
return {
|
|
349
|
+
ok: false,
|
|
350
|
+
kind: 'unknown',
|
|
351
|
+
latencyMs,
|
|
352
|
+
status: response.status,
|
|
353
|
+
detail: redactSecrets(parseError, [input.apiKey]),
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
// Safe: `url` above only resolves for the five protocols
|
|
357
|
+
// `ModelListProtocol` covers (providerModelsUrl throws for every other
|
|
358
|
+
// ConnectionTestProtocol, and azure/bedrock already returned above).
|
|
359
|
+
const models = extractModels(input.protocol, data);
|
|
360
|
+
if (models.length === 0) {
|
|
361
|
+
return {
|
|
362
|
+
ok: false,
|
|
363
|
+
kind: 'no_models',
|
|
364
|
+
latencyMs,
|
|
365
|
+
status: response.status,
|
|
366
|
+
detail: 'Provider returned no usable text-generation models.',
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
ok: true,
|
|
371
|
+
kind: 'success',
|
|
372
|
+
latencyMs,
|
|
373
|
+
status: response.status,
|
|
374
|
+
models,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
catch (err) {
|
|
378
|
+
const latencyMs = Date.now() - start;
|
|
379
|
+
const kind = networkErrorToKind(err);
|
|
380
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
381
|
+
result = {
|
|
382
|
+
ok: false,
|
|
383
|
+
kind,
|
|
384
|
+
latencyMs,
|
|
385
|
+
detail: redactSecrets(message, [input.apiKey]),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
finally {
|
|
389
|
+
clearTimeout(timer);
|
|
390
|
+
input.signal?.removeEventListener('abort', abortFromParent);
|
|
391
|
+
}
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=model-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-catalog.js","sourceRoot":"","sources":["../../src/providers/model-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type OAuthCallbackOutcome = {
|
|
2
|
+
kind: 'ok';
|
|
3
|
+
code: string;
|
|
4
|
+
state: string;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'error';
|
|
7
|
+
error: string;
|
|
8
|
+
state?: string;
|
|
9
|
+
};
|
|
10
|
+
export interface StartOAuthCallbackListenerInput {
|
|
11
|
+
host: string;
|
|
12
|
+
port: number;
|
|
13
|
+
path: string;
|
|
14
|
+
expectedState: string;
|
|
15
|
+
onCallback: (outcome: OAuthCallbackOutcome) => Promise<void> | void;
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface OAuthCallbackListener {
|
|
19
|
+
/** Where the listener is actually bound (informational, esp. for tests). */
|
|
20
|
+
readonly address: {
|
|
21
|
+
host: string;
|
|
22
|
+
port: number;
|
|
23
|
+
};
|
|
24
|
+
/** Stops the listener early (e.g. the user cancelled OAuth in the UI). */
|
|
25
|
+
stop(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Opens a one-shot HTTP listener for an OAuth redirect callback.
|
|
29
|
+
*
|
|
30
|
+
* Resolves once the listener is bound; callback handling is asynchronous
|
|
31
|
+
* via `onCallback`. The listener self-closes after the first matching
|
|
32
|
+
* callback OR after `timeoutMs` (default 30 min), whichever comes first.
|
|
33
|
+
*/
|
|
34
|
+
export declare function startOAuthCallbackListener(input: StartOAuthCallbackListenerInput): Promise<OAuthCallbackListener>;
|
|
35
|
+
//# sourceMappingURL=oauth-callback-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-callback-server.d.ts","sourceRoot":"","sources":["../../src/providers/oauth-callback-server.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,0EAA0E;IAC1E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,+BAA+B,GACrC,OAAO,CAAC,qBAAqB,CAAC,CAyKhC"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module providers/oauth-callback-server
|
|
3
|
+
*
|
|
4
|
+
* One-shot HTTP listener for an OAuth PKCE redirect callback — opens a
|
|
5
|
+
* loopback listener, accepts a single `GET <path>?code=...&state=...`,
|
|
6
|
+
* validates `state` against the in-flight dance, invokes `onCallback`, then
|
|
7
|
+
* closes itself (or times out after a configurable window).
|
|
8
|
+
*
|
|
9
|
+
* Ported from OD's `integrations/xai-oauth-server.ts`, de-branded: the
|
|
10
|
+
* origin hardcoded xAI's fixed callback port/host/path as module constants
|
|
11
|
+
* and had the origin product's own name baked into the result-page HTML
|
|
12
|
+
* (see `source-map.md` for the exact original strings). Both are now
|
|
13
|
+
* caller-supplied — `host`/`port`/
|
|
14
|
+
* `path` are required input fields instead of defaulted constants (a
|
|
15
|
+
* provider whose OAuth client_id is locked to a specific redirect URI, like
|
|
16
|
+
* xAI's, supplies that provider's fixed port via
|
|
17
|
+
* `oauth-provider.ts`'s preset), and the result page uses generic "the host
|
|
18
|
+
* application" copy with no product name. Listener mechanics are otherwise
|
|
19
|
+
* unchanged.
|
|
20
|
+
*/
|
|
21
|
+
import http from 'node:http';
|
|
22
|
+
const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 min
|
|
23
|
+
/**
|
|
24
|
+
* Opens a one-shot HTTP listener for an OAuth redirect callback.
|
|
25
|
+
*
|
|
26
|
+
* Resolves once the listener is bound; callback handling is asynchronous
|
|
27
|
+
* via `onCallback`. The listener self-closes after the first matching
|
|
28
|
+
* callback OR after `timeoutMs` (default 30 min), whichever comes first.
|
|
29
|
+
*/
|
|
30
|
+
export async function startOAuthCallbackListener(input) {
|
|
31
|
+
const { host, port, path: callbackPath } = input;
|
|
32
|
+
const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
33
|
+
let consumed = false;
|
|
34
|
+
let stopped = false;
|
|
35
|
+
let serverRef = null;
|
|
36
|
+
let timer = null;
|
|
37
|
+
const closeServer = () => new Promise((resolve) => {
|
|
38
|
+
// Non-null: `stop()` (this function's only caller) guards on `stopped`
|
|
39
|
+
// before ever reaching here, so this runs at most once — after
|
|
40
|
+
// `serverRef` was unconditionally set at listener-startup, before this
|
|
41
|
+
// closure's `stop`/`address` are ever handed to a caller.
|
|
42
|
+
const s = serverRef;
|
|
43
|
+
serverRef = null;
|
|
44
|
+
if (timer) {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
timer = null;
|
|
47
|
+
}
|
|
48
|
+
s.close(() => resolve());
|
|
49
|
+
// Force close after a short grace period so lingering keep-alive
|
|
50
|
+
// sockets don't keep the event loop alive in tests.
|
|
51
|
+
const reaper = setTimeout(() => {
|
|
52
|
+
try {
|
|
53
|
+
s.closeAllConnections?.();
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Best-effort cleanup only: node:http's closeAllConnections()
|
|
57
|
+
// doesn't document a throwing case in the supported Node range
|
|
58
|
+
// this package targets — this guard exists for a future/older
|
|
59
|
+
// runtime where it might, not a reachable path today.
|
|
60
|
+
}
|
|
61
|
+
}, 100);
|
|
62
|
+
reaper.unref?.();
|
|
63
|
+
});
|
|
64
|
+
const stop = async () => {
|
|
65
|
+
if (stopped)
|
|
66
|
+
return;
|
|
67
|
+
stopped = true;
|
|
68
|
+
await closeServer();
|
|
69
|
+
};
|
|
70
|
+
const handle = async (req, res) => {
|
|
71
|
+
if (consumed || !req.url) {
|
|
72
|
+
res.statusCode = 410;
|
|
73
|
+
res.setHeader('content-type', 'text/plain; charset=utf-8');
|
|
74
|
+
res.end('Listener already consumed.');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
let parsed;
|
|
78
|
+
try {
|
|
79
|
+
parsed = new URL(req.url, `http://${host}:${port}`);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
res.statusCode = 400;
|
|
83
|
+
res.setHeader('content-type', 'text/plain; charset=utf-8');
|
|
84
|
+
res.end('Bad request.');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Ignore favicon.ico and any other path so the browser's incidental
|
|
88
|
+
// requests don't consume the slot meant for the callback path.
|
|
89
|
+
if (parsed.pathname !== callbackPath) {
|
|
90
|
+
res.statusCode = 404;
|
|
91
|
+
res.setHeader('content-type', 'text/plain; charset=utf-8');
|
|
92
|
+
res.end('Not found.');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const code = parsed.searchParams.get('code') ?? '';
|
|
96
|
+
const state = parsed.searchParams.get('state') ?? '';
|
|
97
|
+
const errorParam = parsed.searchParams.get('error') ?? '';
|
|
98
|
+
let outcome;
|
|
99
|
+
if (errorParam) {
|
|
100
|
+
outcome = state
|
|
101
|
+
? { kind: 'error', error: errorParam, state }
|
|
102
|
+
: { kind: 'error', error: errorParam };
|
|
103
|
+
}
|
|
104
|
+
else if (!code || !state) {
|
|
105
|
+
outcome = { kind: 'error', error: 'missing code or state' };
|
|
106
|
+
}
|
|
107
|
+
else if (state !== input.expectedState) {
|
|
108
|
+
outcome = { kind: 'error', error: 'state mismatch', state };
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
outcome = { kind: 'ok', code, state };
|
|
112
|
+
}
|
|
113
|
+
// Decide whether this hit *consumes* the listener. A stray browser tab
|
|
114
|
+
// replaying an old `?state=...` (or `?error=...&state=...`) would
|
|
115
|
+
// otherwise close a shared fixed-port listener before the real redirect
|
|
116
|
+
// can arrive. Keep the listener open on stale/malformed requests; the
|
|
117
|
+
// real callback will still find it. Consume on:
|
|
118
|
+
// - ok callback (matched state, code present)
|
|
119
|
+
// - explicit ?error= without a state (the server rejected before
|
|
120
|
+
// issuing state, so there's nothing to match against — safe to
|
|
121
|
+
// consume)
|
|
122
|
+
// - explicit ?error= with state matching expectedState (the server
|
|
123
|
+
// told the user the dance failed; propagate now instead of waiting
|
|
124
|
+
// for the timeout)
|
|
125
|
+
// An ?error= with a *mismatched* state is treated like the stale
|
|
126
|
+
// success replay above: 400 the browser, leave the listener live.
|
|
127
|
+
const errorConsumes = Boolean(errorParam) && (!state || state === input.expectedState);
|
|
128
|
+
const consumesListener = outcome.kind === 'ok' || errorConsumes;
|
|
129
|
+
if (consumesListener) {
|
|
130
|
+
consumed = true;
|
|
131
|
+
}
|
|
132
|
+
res.statusCode = outcome.kind === 'ok' ? 200 : 400;
|
|
133
|
+
res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
134
|
+
res.end(renderResultPage(outcome));
|
|
135
|
+
if (!consumesListener) {
|
|
136
|
+
// Stale-tab replay or malformed request — don't surface to the
|
|
137
|
+
// caller and don't tear down the listener. The browser sees the
|
|
138
|
+
// 400 page; the real flow can still complete on a later hit.
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
await input.onCallback(outcome);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
console.error('[oauth-callback-server] onCallback failed:', err);
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
void stop();
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
const server = http.createServer((req, res) => {
|
|
152
|
+
void handle(req, res);
|
|
153
|
+
});
|
|
154
|
+
await new Promise((resolve, reject) => {
|
|
155
|
+
const onError = (err) => {
|
|
156
|
+
if (err.code === 'EADDRINUSE') {
|
|
157
|
+
reject(new Error(`Port ${port} is already in use — close any other process listening on ${host}:${port} (e.g. an in-flight OAuth flow) and try again`));
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
reject(err);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
server.once('error', onError);
|
|
164
|
+
server.listen(port, host, () => {
|
|
165
|
+
server.removeListener('error', onError);
|
|
166
|
+
resolve();
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
serverRef = server;
|
|
170
|
+
timer = setTimeout(() => {
|
|
171
|
+
Promise.resolve(input.onCallback({
|
|
172
|
+
kind: 'error',
|
|
173
|
+
error: 'OAuth timed out — sign in again',
|
|
174
|
+
})).catch(() => {
|
|
175
|
+
// already logging in handle(); this branch is best-effort cleanup.
|
|
176
|
+
});
|
|
177
|
+
void stop();
|
|
178
|
+
}, timeoutMs);
|
|
179
|
+
// unref so the timer doesn't keep the event loop alive in tests.
|
|
180
|
+
timer.unref?.();
|
|
181
|
+
const addr = server.address();
|
|
182
|
+
return {
|
|
183
|
+
address: { host: addr.address, port: addr.port },
|
|
184
|
+
stop,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function renderResultPage(outcome) {
|
|
188
|
+
if (outcome.kind === 'ok') {
|
|
189
|
+
return `<!doctype html>
|
|
190
|
+
<html lang="en"><head><meta charset="utf-8"><title>Authorized</title></head>
|
|
191
|
+
<body style="font:14px system-ui;padding:40px;max-width:480px;margin:auto;text-align:center;color:#222;">
|
|
192
|
+
<h1 style="font-size:18px;margin:0 0 12px;">Authorized!</h1>
|
|
193
|
+
<p style="color:#666;">The host application now has access. You can close this tab and return to it.</p>
|
|
194
|
+
</body></html>`;
|
|
195
|
+
}
|
|
196
|
+
// No `|| 'unknown error'` fallback: every 'error'-kind outcome this file
|
|
197
|
+
// constructs (state/code validation, state mismatch, timeout) always sets
|
|
198
|
+
// a non-empty `error` string, so the field is never falsy in practice —
|
|
199
|
+
// this documents that instead of adding an unreachable fallback branch.
|
|
200
|
+
const reason = escapeHtml(outcome.error);
|
|
201
|
+
return `<!doctype html>
|
|
202
|
+
<html lang="en"><head><meta charset="utf-8"><title>Sign-in failed</title></head>
|
|
203
|
+
<body style="font:14px system-ui;padding:40px;max-width:480px;margin:auto;text-align:center;color:#222;">
|
|
204
|
+
<h1 style="font-size:18px;margin:0 0 12px;">Sign-in failed</h1>
|
|
205
|
+
<p style="color:#c00;">${reason}</p>
|
|
206
|
+
<p style="color:#666;">Close this tab and retry sign-in from the host application.</p>
|
|
207
|
+
</body></html>`;
|
|
208
|
+
}
|
|
209
|
+
function escapeHtml(s) {
|
|
210
|
+
return s
|
|
211
|
+
.replace(/&/g, '&')
|
|
212
|
+
.replace(/</g, '<')
|
|
213
|
+
.replace(/>/g, '>')
|
|
214
|
+
.replace(/"/g, '"')
|
|
215
|
+
.replace(/'/g, ''');
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=oauth-callback-server.js.map
|