@bastani/atomic 0.9.18-alpha.5 → 0.9.18-alpha.7
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/CHANGELOG.md +88 -0
- package/README.md +3 -3
- package/dist/builtin/intercom/CHANGELOG.md +39 -0
- package/dist/builtin/intercom/README.md +22 -2
- package/dist/builtin/intercom/broker/broker.ts +676 -128
- package/dist/builtin/intercom/broker/client.ts +151 -35
- package/dist/builtin/intercom/broker/delivered-message-cache.ts +497 -37
- package/dist/builtin/intercom/broker/framing.ts +4 -2
- package/dist/builtin/intercom/broker/paths.ts +10 -0
- package/dist/builtin/intercom/broker/pending-send-registry.ts +1 -2
- package/dist/builtin/intercom/broker/send-handler.ts +311 -52
- package/dist/builtin/intercom/broker/send-signature.ts +4 -2
- package/dist/builtin/intercom/broker/socket-writes.ts +103 -0
- package/dist/builtin/intercom/broker/spawn.ts +9 -4
- package/dist/builtin/intercom/index.bundle.mjs +1410 -212
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/intercom/recoverable-disconnect.ts +52 -0
- package/dist/builtin/intercom/retry-policy.ts +8 -0
- package/dist/builtin/intercom/skills/intercom/SKILL.md +17 -9
- package/dist/builtin/intercom/types.ts +27 -8
- package/dist/builtin/intercom/workflow-stage-path-matching.ts +90 -0
- package/dist/builtin/intercom/workflow-stage-target.ts +57 -0
- package/dist/builtin/mcp/index.bundle.mjs +427 -126
- package/dist/builtin/mcp/package.json +2 -2
- package/dist/builtin/subagents/CHANGELOG.md +19 -0
- package/dist/builtin/subagents/README.md +3 -3
- package/dist/builtin/subagents/agents/code-simplifier.md +2 -2
- package/dist/builtin/subagents/agents/codebase-analyzer.md +2 -2
- package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +11 -11
- package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
- package/dist/builtin/subagents/agents/codebase-research-analyzer.md +2 -2
- package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
- package/dist/builtin/subagents/agents/debugger.md +3 -3
- package/dist/builtin/subagents/agents/worker.md +2 -2
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/subagents/skills/qlty/SKILL.md +29 -101
- package/dist/builtin/subagents/skills/qlty/references/manual-configuration.md +52 -0
- package/dist/builtin/subagents/skills/subagent/SKILL.md +11 -11
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +49 -132
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +46 -0
- package/dist/builtin/workflows/README.md +7 -7
- package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
- package/dist/builtin/workflows/builtin/{chunk-szz1ajz9.js → chunk-42s7sw0b.js} +9 -2
- package/dist/builtin/workflows/builtin/{chunk-2dqb5s2q.js → chunk-79fjkcvh.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-n58a7v26.js → chunk-b0v2xab1.js} +181 -10
- package/dist/builtin/workflows/builtin/{chunk-fghhy2a5.js → chunk-ed4jfn5t.js} +23 -5
- package/dist/builtin/workflows/builtin/{chunk-h3r2vkzc.js → chunk-hqpe2cyx.js} +60 -21
- package/dist/builtin/workflows/builtin/{chunk-hzzn6adg.js → chunk-k3w87x8y.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-82ha8p41.js → chunk-n8h4yyew.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-qwzvgxnq.js → chunk-reqr3sr3.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-c53y8bdh.js → chunk-wgccch41.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-0x6e303p.js → chunk-zbekjqew.js} +20 -7
- package/dist/builtin/workflows/builtin/{chunk-29wrp38a.js → chunk-ze5x3d1r.js} +1 -1
- package/dist/builtin/workflows/builtin/classify-and-act.js +2 -2
- package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +2 -2
- package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
- package/dist/builtin/workflows/builtin/goal.js +3 -3
- package/dist/builtin/workflows/builtin/index.js +11 -11
- package/dist/builtin/workflows/builtin/loop-until-done.js +2 -2
- package/dist/builtin/workflows/builtin/open-claude-design.js +2 -2
- package/dist/builtin/workflows/builtin/ralph.js +3 -3
- package/dist/builtin/workflows/builtin/steering-context.js +1 -1
- package/dist/builtin/workflows/builtin/tournament.js +2 -2
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/skills/prompt-engineer/SKILL.md +39 -52
- package/dist/builtin/workflows/skills/prompt-engineer/references/advanced_patterns.md +9 -37
- package/dist/builtin/workflows/skills/prompt-engineer/references/claude_fable_5.md +49 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/claude_fable_5_1.md +57 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/claude_opus_4_8.md +57 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/claude_opus_5.md +47 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/claude_sonnet_5.md +57 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/gpt_5_5.md +60 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/gpt_5_6.md +58 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/gpt_6_astra.md +58 -0
- package/dist/builtin/workflows/skills/prompt-engineer/references/quality_improvement.md +18 -4
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +3194 -737
- package/dist/builtin/workflows/src/index.js +899 -436
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +0 -10
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +4 -0
- package/dist/cli/list-models.js.map +1 -1
- package/dist/client/index.d.ts +1 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -2
- package/dist/client/index.js.map +1 -1
- package/dist/config.d.ts +0 -9
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -45
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +8 -6
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +1 -0
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-models.d.ts.map +1 -1
- package/dist/core/agent-session-models.js +3 -4
- package/dist/core/agent-session-models.js.map +1 -1
- package/dist/core/agent-session-queue-pause.d.ts.map +1 -1
- package/dist/core/agent-session-queue-pause.js +6 -0
- package/dist/core/agent-session-queue-pause.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +13 -5
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-tool-hooks.js +1 -1
- package/dist/core/agent-session-tool-hooks.js.map +1 -1
- package/dist/core/agent-session-tree.d.ts.map +1 -1
- package/dist/core/agent-session-tree.js +8 -0
- package/dist/core/agent-session-tree.js.map +1 -1
- package/dist/core/agent-session.d.ts +2 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +2 -2
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +4 -4
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/extensions/api-types.d.ts +8 -2
- package/dist/core/extensions/api-types.d.ts.map +1 -1
- package/dist/core/extensions/api-types.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +12 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/runner-shortcuts.d.ts.map +1 -1
- package/dist/core/extensions/runner-shortcuts.js +0 -1
- package/dist/core/extensions/runner-shortcuts.js.map +1 -1
- package/dist/core/fast-model-routing-transport.d.ts +12 -0
- package/dist/core/fast-model-routing-transport.d.ts.map +1 -0
- package/dist/core/{codex-fast-mode-transport.js → fast-model-routing-transport.js} +29 -29
- package/dist/core/fast-model-routing-transport.js.map +1 -0
- package/dist/core/fast-model-routing.d.ts +57 -0
- package/dist/core/fast-model-routing.d.ts.map +1 -0
- package/dist/core/fast-model-routing.js +201 -0
- package/dist/core/fast-model-routing.js.map +1 -0
- package/dist/core/fast-model-variants.d.ts +98 -0
- package/dist/core/fast-model-variants.d.ts.map +1 -0
- package/dist/core/fast-model-variants.js +148 -0
- package/dist/core/fast-model-variants.js.map +1 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +4 -2
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/keybindings.d.ts +0 -10
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +0 -8
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +15 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +3 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-resolver-initial.js +1 -1
- package/dist/core/model-resolver-initial.js.map +1 -1
- package/dist/core/model-runtime-streaming.d.ts +14 -1
- package/dist/core/model-runtime-streaming.d.ts.map +1 -1
- package/dist/core/model-runtime-streaming.js +25 -3
- package/dist/core/model-runtime-streaming.js.map +1 -1
- package/dist/core/model-runtime.d.ts +39 -2
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +91 -7
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/provider-composer-internal.d.ts.map +1 -1
- package/dist/core/provider-composer-internal.js +8 -2
- package/dist/core/provider-composer-internal.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +18 -18
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager-archive.d.ts.map +1 -1
- package/dist/core/session-manager-archive.js +25 -2
- package/dist/core/session-manager-archive.js.map +1 -1
- package/dist/core/settings-manager-core.d.ts +0 -2
- package/dist/core/settings-manager-core.d.ts.map +1 -1
- package/dist/core/settings-manager-core.js +2 -9
- package/dist/core/settings-manager-core.js.map +1 -1
- package/dist/core/settings-manager-internals.d.ts +0 -1
- package/dist/core/settings-manager-internals.d.ts.map +1 -1
- package/dist/core/settings-manager-internals.js.map +1 -1
- package/dist/core/settings-manager-ui-accessors.d.ts +0 -8
- package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-ui-accessors.js +0 -53
- package/dist/core/settings-manager-ui-accessors.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +0 -5
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/skills.d.ts +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +4 -2
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +0 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.js +7 -7
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/edit.d.ts +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +128 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/hashline.d.ts +2 -2
- package/dist/core/tools/hashline.d.ts.map +1 -1
- package/dist/core/tools/hashline.js +40 -10
- package/dist/core/tools/hashline.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +8 -8
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/workflow-stage-admission.d.ts +6 -0
- package/dist/core/workflow-stage-admission.d.ts.map +1 -1
- package/dist/core/workflow-stage-admission.js +14 -0
- package/dist/core/workflow-stage-admission.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/atomic-working-status.d.ts +4 -0
- package/dist/modes/interactive/components/atomic-working-status.d.ts.map +1 -1
- package/dist/modes/interactive/components/atomic-working-status.js +26 -1
- package/dist/modes/interactive/components/atomic-working-status.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +7 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +43 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +0 -6
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -2
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +0 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +6 -11
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -5
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +3 -19
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts +1 -2
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +4 -11
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/transcript-follow-indicator.js +3 -3
- package/dist/modes/interactive/components/transcript-follow-indicator.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +8 -8
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.js +5 -16
- package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
- package/dist/modes/interactive/interactive-bash-compact.js +2 -9
- package/dist/modes/interactive/interactive-bash-compact.js.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.js +3 -0
- package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-editor-actions.js +2 -2
- package/dist/modes/interactive/interactive-editor-actions.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-custom-ui.js +1 -0
- package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-dialogs.js +7 -0
- package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-runtime.js +20 -10
- package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-hotkeys-debug.js +1 -5
- package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
- package/dist/modes/interactive/interactive-initial-session-binding.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-initial-session-binding.js +3 -0
- package/dist/modes/interactive/interactive-initial-session-binding.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +0 -8
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +5 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +15 -9
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -3
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +1 -3
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +9 -12
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.js +10 -13
- package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +29 -0
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +2 -32
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.js +1 -5
- package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +1 -5
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-slash-commands.js +6 -13
- package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +19 -13
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-tui.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-tui.js +27 -3
- package/dist/modes/interactive/interactive-tui.js.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.js +1 -0
- package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.js +4 -1
- package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +13 -6
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +33 -18
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/custom-provider.md +2 -0
- package/docs/development.md +17 -0
- package/docs/docs.json +14 -2
- package/docs/extensions.md +9 -4
- package/docs/intercom.md +41 -7
- package/docs/keybindings.md +8 -6
- package/docs/models/evals.md +394 -0
- package/docs/models/model-selection.md +54 -27
- package/docs/models/pareto-efficiency.md +33 -16
- package/docs/models.md +37 -1
- package/docs/packages.md +2 -2
- package/docs/providers.md +44 -20
- package/docs/quickstart.md +8 -6
- package/docs/rpc.md +3 -3
- package/docs/sdk.md +2 -16
- package/docs/settings.md +19 -22
- package/docs/skills.md +4 -2
- package/docs/subagents.md +9 -3
- package/docs/tools/edit.md +373 -0
- package/docs/tools.md +3 -7
- package/docs/tui.md +2 -1
- package/docs/usage.md +3 -5
- package/docs/workflows/api-reference.md +1395 -0
- package/docs/workflows/authoring.md +678 -0
- package/docs/workflows/builtins.md +245 -0
- package/docs/workflows/operations.md +811 -0
- package/docs/workflows/reliable-design.md +2099 -0
- package/docs/workflows/verification.md +62 -0
- package/docs/workflows.md +15 -5183
- package/npm-shrinkwrap.json +584 -69
- package/package.json +7 -7
- package/dist/client/remote-session.d.ts +0 -64
- package/dist/client/remote-session.d.ts.map +0 -1
- package/dist/client/remote-session.js +0 -351
- package/dist/client/remote-session.js.map +0 -1
- package/dist/client/transcript.d.ts +0 -12
- package/dist/client/transcript.d.ts.map +0 -1
- package/dist/client/transcript.js +0 -98
- package/dist/client/transcript.js.map +0 -1
- package/dist/core/codex-fast-mode-transport.d.ts +0 -12
- package/dist/core/codex-fast-mode-transport.d.ts.map +0 -1
- package/dist/core/codex-fast-mode-transport.js.map +0 -1
- package/dist/core/codex-fast-mode.d.ts +0 -53
- package/dist/core/codex-fast-mode.d.ts.map +0 -1
- package/dist/core/codex-fast-mode.js +0 -249
- package/dist/core/codex-fast-mode.js.map +0 -1
- package/dist/modes/interactive/components/fast-mode-selector.d.ts +0 -27
- package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +0 -1
- package/dist/modes/interactive/components/fast-mode-selector.js +0 -107
- package/dist/modes/interactive/components/fast-mode-selector.js.map +0 -1
- package/dist/server/create-harness.d.ts +0 -53
- package/dist/server/create-harness.d.ts.map +0 -1
- package/dist/server/create-harness.js +0 -360
- package/dist/server/create-harness.js.map +0 -1
- package/docs/models/artificial-analysis-index.md +0 -83
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { closeOpenAICodexWebSocketSessions } from "@bastani/pi-ai/api/openai-codex-responses";
|
|
2
|
+
import { type Api, type AssistantMessageEventStream, type Context, type Model, type ModelFastRoute, type OpenAICodexResponsesOptions, type OpenAIResponsesOptions, type ProviderHeaders, type SimpleStreamOptions, type StreamOptions, type ThinkingLevel } from "@bastani/pi-ai/compat";
|
|
3
|
+
import { FAST_MODEL_SERVICE_TIER } from "./fast-model-variants.ts";
|
|
4
|
+
export interface FastRouteStreamOptions extends SimpleStreamOptions {
|
|
5
|
+
serviceTier?: typeof FAST_MODEL_SERVICE_TIER;
|
|
6
|
+
}
|
|
7
|
+
export interface FastRouteStreamers {
|
|
8
|
+
streamSimple: (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;
|
|
9
|
+
streamOpenAIResponses: (model: Model<"openai-responses">, context: Context, options?: OpenAIResponsesOptions) => AssistantMessageEventStream;
|
|
10
|
+
streamOpenAICodexResponses: (model: Model<"openai-codex-responses">, context: Context, options?: OpenAICodexResponsesOptions) => AssistantMessageEventStream;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Explicit route metadata is the only source of fast semantics. A model whose ID merely ends in
|
|
14
|
+
* `-fast` — a provider, `models.json`, or extension model that owns that exact ID — routes normally.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getModelFastRoute(model: Pick<Model<Api>, "fastRoute">): ModelFastRoute | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* The model ID this request sends upstream. An OpenAI-style fast route sends the base model and
|
|
19
|
+
* carries a priority service tier instead; a provider with real fast siblings sends its own
|
|
20
|
+
* advertised ID, which is already the canonical one. The canonical `-fast` identity always stays on
|
|
21
|
+
* the model object Atomic selected, persisted, and records — only the serialized request differs.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveUpstreamModelId(model: Pick<Model<Api>, "fastRoute" | "id">): string;
|
|
24
|
+
/**
|
|
25
|
+
* Whether a model uses the first-party OpenAI Codex provider identity and endpoint.
|
|
26
|
+
* A renamed provider on the same protocol remains non-first-party.
|
|
27
|
+
*/
|
|
28
|
+
export declare function usesFirstPartyCodexRouting(model: Pick<Model<Api>, "baseUrl" | "provider">): boolean;
|
|
29
|
+
/** A provider alias or proxy still uses the shared ChatGPT Codex protocol when its API does. */
|
|
30
|
+
export declare function usesChatGptCodexTransport(model: Pick<Model<Api>, "api">): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Eager first-party routing headers for a model that carries an OpenAI-style fast route.
|
|
33
|
+
*
|
|
34
|
+
* Derived entirely from the model: the headers are added only when the model's own `fastRoute`
|
|
35
|
+
* declares the priority tier and the model uses first-party Codex routing, and the hint names the
|
|
36
|
+
* route's upstream model ID — the same value the request serializes and
|
|
37
|
+
* `withChatGptCodexTransportRouting` reads from route metadata. There is no caller-supplied enable
|
|
38
|
+
* flag, so a model without a route can never be granted this identity.
|
|
39
|
+
*/
|
|
40
|
+
export declare function withCodexFastRouteHeaders(model: Pick<Model<Api>, "baseUrl" | "fastRoute" | "id" | "provider">, headers: ProviderHeaders | undefined): ProviderHeaders | undefined;
|
|
41
|
+
/** Attach the route's service tier to the outgoing stream options. */
|
|
42
|
+
export declare function withFastRouteStreamOptions(fastRoute: ModelFastRoute | undefined, options: SimpleStreamOptions | undefined): FastRouteStreamOptions | undefined;
|
|
43
|
+
/** A service-tier route needs pi-ai's native adapters; `streamSimple` drops `serviceTier`. */
|
|
44
|
+
export declare function shouldUseNativeFastRoute(model: Pick<Model<Api>, "api">, options: FastRouteStreamOptions | undefined): boolean;
|
|
45
|
+
type CloseCodexWebSocketSessions = typeof closeOpenAICodexWebSocketSessions;
|
|
46
|
+
export declare function withChatGptCodexTransportRouting<TOptions extends StreamOptions>(model: Model<Api>, options: TOptions, closeWebSocketSessions?: CloseCodexWebSocketSessions): TOptions;
|
|
47
|
+
export declare function mapFastRouteReasoningEffort(model: Model<Api>, reasoning: ThinkingLevel | undefined): ThinkingLevel | undefined;
|
|
48
|
+
export declare function buildOpenAIResponsesFastRouteOptions(model: Model<Api>, options: FastRouteStreamOptions | undefined): OpenAIResponsesOptions;
|
|
49
|
+
export declare function buildOpenAICodexResponsesFastRouteOptions(model: Model<Api>, options: FastRouteStreamOptions | undefined): OpenAICodexResponsesOptions;
|
|
50
|
+
/**
|
|
51
|
+
* Stream a request whose canonical selected model carries fast-route metadata. The provider adapter
|
|
52
|
+
* translates only the serialized request to the route's upstream ID; the model object keeps its
|
|
53
|
+
* canonical `-fast` identity.
|
|
54
|
+
*/
|
|
55
|
+
export declare function streamWithFastRoute(model: Model<Api>, context: Context, options: FastRouteStreamOptions | undefined, streamers?: FastRouteStreamers): AssistantMessageEventStream;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=fast-model-routing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-model-routing.d.ts","sourceRoot":"","sources":["../../src/core/fast-model-routing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { closeOpenAICodexWebSocketSessions } from "@bastani/pi-ai/api/openai-codex-responses";
|
|
2
|
+
import { clampThinkingLevel, streamOpenAICodexResponses, streamOpenAIResponses, streamSimple, } from "@bastani/pi-ai/compat";
|
|
3
|
+
import { CODEX_FAST_ROUTE_HEADER, CODEX_FAST_ROUTE_ORIGINATOR, clearCodexFastRouteRequestMarker, installCodexFastRouteWebSocketIdentity, isFirstPartyCodexBaseUrl, markCodexFastRouteRequest, wrapCodexFastRouteFetch, } from "./fast-model-routing-transport.js";
|
|
4
|
+
import { FAST_MODEL_SERVICE_TIER, isNativeFastRouteApi } from "./fast-model-variants.js";
|
|
5
|
+
const DEFAULT_FAST_ROUTE_STREAMERS = {
|
|
6
|
+
streamSimple,
|
|
7
|
+
streamOpenAIResponses,
|
|
8
|
+
streamOpenAICodexResponses,
|
|
9
|
+
};
|
|
10
|
+
const CODEX_WEBSOCKET_ROUTING_STATE_IDLE_MS = 6 * 60 * 1000;
|
|
11
|
+
const codexWebSocketRoutingState = new Map();
|
|
12
|
+
/**
|
|
13
|
+
* Explicit route metadata is the only source of fast semantics. A model whose ID merely ends in
|
|
14
|
+
* `-fast` — a provider, `models.json`, or extension model that owns that exact ID — routes normally.
|
|
15
|
+
*/
|
|
16
|
+
export function getModelFastRoute(model) {
|
|
17
|
+
return model.fastRoute;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The model ID this request sends upstream. An OpenAI-style fast route sends the base model and
|
|
21
|
+
* carries a priority service tier instead; a provider with real fast siblings sends its own
|
|
22
|
+
* advertised ID, which is already the canonical one. The canonical `-fast` identity always stays on
|
|
23
|
+
* the model object Atomic selected, persisted, and records — only the serialized request differs.
|
|
24
|
+
*/
|
|
25
|
+
export function resolveUpstreamModelId(model) {
|
|
26
|
+
return model.fastRoute?.upstreamModelId ?? model.id;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether a model uses the first-party OpenAI Codex provider identity and endpoint.
|
|
30
|
+
* A renamed provider on the same protocol remains non-first-party.
|
|
31
|
+
*/
|
|
32
|
+
export function usesFirstPartyCodexRouting(model) {
|
|
33
|
+
return model.provider === "openai-codex" && isFirstPartyCodexBaseUrl(model.baseUrl);
|
|
34
|
+
}
|
|
35
|
+
/** A provider alias or proxy still uses the shared ChatGPT Codex protocol when its API does. */
|
|
36
|
+
export function usesChatGptCodexTransport(model) {
|
|
37
|
+
return model.api === "openai-codex-responses";
|
|
38
|
+
}
|
|
39
|
+
function deleteHeader(headers, name) {
|
|
40
|
+
for (const existingName of Object.keys(headers)) {
|
|
41
|
+
if (existingName.toLowerCase() === name.toLowerCase())
|
|
42
|
+
delete headers[existingName];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function setHeader(headers, name, value) {
|
|
46
|
+
deleteHeader(headers, name);
|
|
47
|
+
headers[name] = value;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Eager first-party routing headers for a model that carries an OpenAI-style fast route.
|
|
51
|
+
*
|
|
52
|
+
* Derived entirely from the model: the headers are added only when the model's own `fastRoute`
|
|
53
|
+
* declares the priority tier and the model uses first-party Codex routing, and the hint names the
|
|
54
|
+
* route's upstream model ID — the same value the request serializes and
|
|
55
|
+
* `withChatGptCodexTransportRouting` reads from route metadata. There is no caller-supplied enable
|
|
56
|
+
* flag, so a model without a route can never be granted this identity.
|
|
57
|
+
*/
|
|
58
|
+
export function withCodexFastRouteHeaders(model, headers) {
|
|
59
|
+
if (getModelFastRoute(model)?.serviceTier !== FAST_MODEL_SERVICE_TIER || !usesFirstPartyCodexRouting(model)) {
|
|
60
|
+
return headers;
|
|
61
|
+
}
|
|
62
|
+
const fastHeaders = { ...(headers ?? {}) };
|
|
63
|
+
setHeader(fastHeaders, "originator", CODEX_FAST_ROUTE_ORIGINATOR);
|
|
64
|
+
setHeader(fastHeaders, CODEX_FAST_ROUTE_HEADER, `model=${resolveUpstreamModelId(model)};tier=${FAST_MODEL_SERVICE_TIER}`);
|
|
65
|
+
return fastHeaders;
|
|
66
|
+
}
|
|
67
|
+
/** Attach the route's service tier to the outgoing stream options. */
|
|
68
|
+
export function withFastRouteStreamOptions(fastRoute, options) {
|
|
69
|
+
if (fastRoute?.serviceTier === undefined)
|
|
70
|
+
return options;
|
|
71
|
+
return { ...(options ?? {}), headers: options?.headers, serviceTier: fastRoute.serviceTier };
|
|
72
|
+
}
|
|
73
|
+
/** A service-tier route needs pi-ai's native adapters; `streamSimple` drops `serviceTier`. */
|
|
74
|
+
export function shouldUseNativeFastRoute(model, options) {
|
|
75
|
+
return isNativeFastRouteApi(model.api) && options?.serviceTier === FAST_MODEL_SERVICE_TIER;
|
|
76
|
+
}
|
|
77
|
+
function codexEnvironmentScope(env) {
|
|
78
|
+
if (!env)
|
|
79
|
+
return "none";
|
|
80
|
+
const serialized = JSON.stringify(Object.entries(env).sort(([left], [right]) => left.localeCompare(right)));
|
|
81
|
+
let hash = 2166136261;
|
|
82
|
+
for (let index = 0; index < serialized.length; index += 1) {
|
|
83
|
+
hash = Math.imul(hash ^ serialized.charCodeAt(index), 16777619);
|
|
84
|
+
}
|
|
85
|
+
return (hash >>> 0).toString(16);
|
|
86
|
+
}
|
|
87
|
+
function updateCodexWebSocketRoutingState(model, routedModel, options, priority, closeWebSocketSessions) {
|
|
88
|
+
if (options.transport === "sse" || !options.sessionId)
|
|
89
|
+
return;
|
|
90
|
+
const signature = `${model.provider}\0${model.baseUrl}\0${codexEnvironmentScope(options.env)}\0${priority ? `priority:${routedModel}` : "normal"}`;
|
|
91
|
+
const previous = codexWebSocketRoutingState.get(options.sessionId);
|
|
92
|
+
if (previous?.signature !== undefined && previous.signature !== signature) {
|
|
93
|
+
closeWebSocketSessions(options.sessionId);
|
|
94
|
+
}
|
|
95
|
+
if (previous)
|
|
96
|
+
clearTimeout(previous.expiry);
|
|
97
|
+
const expiry = setTimeout(() => {
|
|
98
|
+
if (codexWebSocketRoutingState.get(options.sessionId)?.signature === signature) {
|
|
99
|
+
codexWebSocketRoutingState.delete(options.sessionId);
|
|
100
|
+
}
|
|
101
|
+
}, CODEX_WEBSOCKET_ROUTING_STATE_IDLE_MS);
|
|
102
|
+
expiry.unref?.();
|
|
103
|
+
codexWebSocketRoutingState.set(options.sessionId, { signature, expiry });
|
|
104
|
+
}
|
|
105
|
+
export function withChatGptCodexTransportRouting(model, options, closeWebSocketSessions = closeOpenAICodexWebSocketSessions) {
|
|
106
|
+
const headers = { ...(options.headers ?? {}) };
|
|
107
|
+
const onPayload = options.onPayload;
|
|
108
|
+
const priority = getModelFastRoute(model)?.serviceTier === FAST_MODEL_SERVICE_TIER && usesFirstPartyCodexRouting(model);
|
|
109
|
+
const routedModel = resolveUpstreamModelId(model);
|
|
110
|
+
return {
|
|
111
|
+
...options,
|
|
112
|
+
headers,
|
|
113
|
+
fetch: wrapCodexFastRouteFetch(options.fetch ?? globalThis.fetch),
|
|
114
|
+
onPayload: async (payload, requestModel) => {
|
|
115
|
+
const replacement = await onPayload?.(payload, requestModel);
|
|
116
|
+
const finalPayload = replacement === undefined ? payload : replacement;
|
|
117
|
+
deleteHeader(headers, CODEX_FAST_ROUTE_HEADER);
|
|
118
|
+
clearCodexFastRouteRequestMarker(headers);
|
|
119
|
+
if (priority) {
|
|
120
|
+
setHeader(headers, CODEX_FAST_ROUTE_HEADER, `model=${routedModel};tier=${FAST_MODEL_SERVICE_TIER}`);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
124
|
+
if (name.toLowerCase() === "originator" && value === CODEX_FAST_ROUTE_ORIGINATOR)
|
|
125
|
+
delete headers[name];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
markCodexFastRouteRequest(headers, priority);
|
|
129
|
+
updateCodexWebSocketRoutingState(model, routedModel, options, priority, closeWebSocketSessions);
|
|
130
|
+
return finalPayload;
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function buildFastRouteBaseProviderOptions(model, options) {
|
|
135
|
+
// Native fast-route streams bypass pi-ai's streamSimple base-options merge.
|
|
136
|
+
const samplingParams = model.samplingParams || options?.samplingParams
|
|
137
|
+
? { ...model.samplingParams, ...options?.samplingParams }
|
|
138
|
+
: undefined;
|
|
139
|
+
const providerOptions = {
|
|
140
|
+
samplingParams,
|
|
141
|
+
temperature: options?.temperature,
|
|
142
|
+
maxTokens: options?.maxTokens,
|
|
143
|
+
signal: options?.signal,
|
|
144
|
+
apiKey: options?.apiKey,
|
|
145
|
+
fetch: options?.fetch,
|
|
146
|
+
env: options?.env,
|
|
147
|
+
telemetryContext: options?.telemetryContext,
|
|
148
|
+
transport: options?.transport,
|
|
149
|
+
cacheRetention: options?.cacheRetention,
|
|
150
|
+
sessionId: options?.sessionId,
|
|
151
|
+
onPayload: options?.onPayload,
|
|
152
|
+
onResponse: options?.onResponse,
|
|
153
|
+
headers: options?.headers,
|
|
154
|
+
timeoutMs: options?.timeoutMs,
|
|
155
|
+
websocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,
|
|
156
|
+
streamDeadlineMs: options?.streamDeadlineMs,
|
|
157
|
+
maxRetries: options?.maxRetries,
|
|
158
|
+
maxRetryDelayMs: options?.maxRetryDelayMs,
|
|
159
|
+
metadata: options?.metadata,
|
|
160
|
+
};
|
|
161
|
+
return usesChatGptCodexTransport(model) ? withChatGptCodexTransportRouting(model, providerOptions) : providerOptions;
|
|
162
|
+
}
|
|
163
|
+
export function mapFastRouteReasoningEffort(model, reasoning) {
|
|
164
|
+
const clampedReasoning = reasoning ? clampThinkingLevel(model, reasoning) : undefined;
|
|
165
|
+
return clampedReasoning === "off" ? undefined : clampedReasoning;
|
|
166
|
+
}
|
|
167
|
+
export function buildOpenAIResponsesFastRouteOptions(model, options) {
|
|
168
|
+
return {
|
|
169
|
+
...buildFastRouteBaseProviderOptions(model, options),
|
|
170
|
+
reasoningEffort: mapFastRouteReasoningEffort(model, options?.reasoning),
|
|
171
|
+
serviceTier: options?.serviceTier,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
export function buildOpenAICodexResponsesFastRouteOptions(model, options) {
|
|
175
|
+
return {
|
|
176
|
+
...buildFastRouteBaseProviderOptions(model, options),
|
|
177
|
+
reasoningEffort: mapFastRouteReasoningEffort(model, options?.reasoning),
|
|
178
|
+
serviceTier: options?.serviceTier,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Stream a request whose canonical selected model carries fast-route metadata. The provider adapter
|
|
183
|
+
* translates only the serialized request to the route's upstream ID; the model object keeps its
|
|
184
|
+
* canonical `-fast` identity.
|
|
185
|
+
*/
|
|
186
|
+
export function streamWithFastRoute(model, context, options, streamers = DEFAULT_FAST_ROUTE_STREAMERS) {
|
|
187
|
+
if (shouldUseNativeFastRoute(model, options)) {
|
|
188
|
+
if (model.api === "openai-responses") {
|
|
189
|
+
return streamers.streamOpenAIResponses(model, context, buildOpenAIResponsesFastRouteOptions(model, options));
|
|
190
|
+
}
|
|
191
|
+
// The WebSocket handshake builds its headers inside pi-ai, and the runtime
|
|
192
|
+
// constructor can be cached before the first turn, so repair the identity
|
|
193
|
+
// through the global constructor rather than per-request options.
|
|
194
|
+
if (options?.transport !== "sse" && usesChatGptCodexTransport(model)) {
|
|
195
|
+
installCodexFastRouteWebSocketIdentity();
|
|
196
|
+
}
|
|
197
|
+
return streamers.streamOpenAICodexResponses(model, context, buildOpenAICodexResponsesFastRouteOptions(model, options));
|
|
198
|
+
}
|
|
199
|
+
return streamers.streamSimple(model, context, options);
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=fast-model-routing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-model-routing.js","sourceRoot":"","sources":["../../src/core/fast-model-routing.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeOpenAICodexWebSocketSessions } from \"@bastani/pi-ai/api/openai-codex-responses\";\nimport {\n\ttype Api,\n\ttype AssistantMessageEventStream,\n\ttype Context,\n\tclampThinkingLevel,\n\ttype Model,\n\ttype ModelFastRoute,\n\ttype OpenAICodexResponsesOptions,\n\ttype OpenAIResponsesOptions,\n\ttype ProviderHeaders,\n\ttype SimpleStreamOptions,\n\ttype StreamOptions,\n\tstreamOpenAICodexResponses,\n\tstreamOpenAIResponses,\n\tstreamSimple,\n\ttype ThinkingLevel,\n} from \"@bastani/pi-ai/compat\";\nimport {\n\tCODEX_FAST_ROUTE_HEADER,\n\tCODEX_FAST_ROUTE_ORIGINATOR,\n\tclearCodexFastRouteRequestMarker,\n\tinstallCodexFastRouteWebSocketIdentity,\n\tisFirstPartyCodexBaseUrl,\n\tmarkCodexFastRouteRequest,\n\twrapCodexFastRouteFetch,\n} from \"./fast-model-routing-transport.ts\";\nimport { FAST_MODEL_SERVICE_TIER, isNativeFastRouteApi } from \"./fast-model-variants.ts\";\n\nexport interface FastRouteStreamOptions extends SimpleStreamOptions {\n\tserviceTier?: typeof FAST_MODEL_SERVICE_TIER;\n}\n\nexport interface FastRouteStreamers {\n\tstreamSimple: (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;\n\tstreamOpenAIResponses: (\n\t\tmodel: Model<\"openai-responses\">,\n\t\tcontext: Context,\n\t\toptions?: OpenAIResponsesOptions,\n\t) => AssistantMessageEventStream;\n\tstreamOpenAICodexResponses: (\n\t\tmodel: Model<\"openai-codex-responses\">,\n\t\tcontext: Context,\n\t\toptions?: OpenAICodexResponsesOptions,\n\t) => AssistantMessageEventStream;\n}\n\nconst DEFAULT_FAST_ROUTE_STREAMERS: FastRouteStreamers = {\n\tstreamSimple,\n\tstreamOpenAIResponses,\n\tstreamOpenAICodexResponses,\n};\n\nconst CODEX_WEBSOCKET_ROUTING_STATE_IDLE_MS = 6 * 60 * 1000;\nconst codexWebSocketRoutingState = new Map<string, { signature: string; expiry: ReturnType<typeof setTimeout> }>();\n\n/**\n * Explicit route metadata is the only source of fast semantics. A model whose ID merely ends in\n * `-fast` — a provider, `models.json`, or extension model that owns that exact ID — routes normally.\n */\nexport function getModelFastRoute(model: Pick<Model<Api>, \"fastRoute\">): ModelFastRoute | undefined {\n\treturn model.fastRoute;\n}\n\n/**\n * The model ID this request sends upstream. An OpenAI-style fast route sends the base model and\n * carries a priority service tier instead; a provider with real fast siblings sends its own\n * advertised ID, which is already the canonical one. The canonical `-fast` identity always stays on\n * the model object Atomic selected, persisted, and records — only the serialized request differs.\n */\nexport function resolveUpstreamModelId(model: Pick<Model<Api>, \"fastRoute\" | \"id\">): string {\n\treturn model.fastRoute?.upstreamModelId ?? model.id;\n}\n\n/**\n * Whether a model uses the first-party OpenAI Codex provider identity and endpoint.\n * A renamed provider on the same protocol remains non-first-party.\n */\nexport function usesFirstPartyCodexRouting(model: Pick<Model<Api>, \"baseUrl\" | \"provider\">): boolean {\n\treturn model.provider === \"openai-codex\" && isFirstPartyCodexBaseUrl(model.baseUrl);\n}\n\n/** A provider alias or proxy still uses the shared ChatGPT Codex protocol when its API does. */\nexport function usesChatGptCodexTransport(model: Pick<Model<Api>, \"api\">): boolean {\n\treturn model.api === \"openai-codex-responses\";\n}\n\nfunction deleteHeader(headers: ProviderHeaders, name: string): void {\n\tfor (const existingName of Object.keys(headers)) {\n\t\tif (existingName.toLowerCase() === name.toLowerCase()) delete headers[existingName];\n\t}\n}\n\nfunction setHeader(headers: ProviderHeaders, name: string, value: string): void {\n\tdeleteHeader(headers, name);\n\theaders[name] = value;\n}\n\n/**\n * Eager first-party routing headers for a model that carries an OpenAI-style fast route.\n *\n * Derived entirely from the model: the headers are added only when the model's own `fastRoute`\n * declares the priority tier and the model uses first-party Codex routing, and the hint names the\n * route's upstream model ID — the same value the request serializes and\n * `withChatGptCodexTransportRouting` reads from route metadata. There is no caller-supplied enable\n * flag, so a model without a route can never be granted this identity.\n */\nexport function withCodexFastRouteHeaders(\n\tmodel: Pick<Model<Api>, \"baseUrl\" | \"fastRoute\" | \"id\" | \"provider\">,\n\theaders: ProviderHeaders | undefined,\n): ProviderHeaders | undefined {\n\tif (getModelFastRoute(model)?.serviceTier !== FAST_MODEL_SERVICE_TIER || !usesFirstPartyCodexRouting(model)) {\n\t\treturn headers;\n\t}\n\tconst fastHeaders: ProviderHeaders = { ...(headers ?? {}) };\n\tsetHeader(fastHeaders, \"originator\", CODEX_FAST_ROUTE_ORIGINATOR);\n\tsetHeader(\n\t\tfastHeaders,\n\t\tCODEX_FAST_ROUTE_HEADER,\n\t\t`model=${resolveUpstreamModelId(model)};tier=${FAST_MODEL_SERVICE_TIER}`,\n\t);\n\treturn fastHeaders;\n}\n\n/** Attach the route's service tier to the outgoing stream options. */\nexport function withFastRouteStreamOptions(\n\tfastRoute: ModelFastRoute | undefined,\n\toptions: SimpleStreamOptions | undefined,\n): FastRouteStreamOptions | undefined {\n\tif (fastRoute?.serviceTier === undefined) return options;\n\treturn { ...(options ?? {}), headers: options?.headers, serviceTier: fastRoute.serviceTier };\n}\n\n/** A service-tier route needs pi-ai's native adapters; `streamSimple` drops `serviceTier`. */\nexport function shouldUseNativeFastRoute(\n\tmodel: Pick<Model<Api>, \"api\">,\n\toptions: FastRouteStreamOptions | undefined,\n): boolean {\n\treturn isNativeFastRouteApi(model.api) && options?.serviceTier === FAST_MODEL_SERVICE_TIER;\n}\n\nfunction codexEnvironmentScope(env: StreamOptions[\"env\"]): string {\n\tif (!env) return \"none\";\n\tconst serialized = JSON.stringify(Object.entries(env).sort(([left], [right]) => left.localeCompare(right)));\n\tlet hash = 2166136261;\n\tfor (let index = 0; index < serialized.length; index += 1) {\n\t\thash = Math.imul(hash ^ serialized.charCodeAt(index), 16777619);\n\t}\n\treturn (hash >>> 0).toString(16);\n}\n\ntype CloseCodexWebSocketSessions = typeof closeOpenAICodexWebSocketSessions;\nfunction updateCodexWebSocketRoutingState(\n\tmodel: Pick<Model<Api>, \"baseUrl\" | \"provider\">,\n\troutedModel: string,\n\toptions: Pick<StreamOptions, \"env\" | \"sessionId\" | \"transport\">,\n\tpriority: boolean,\n\tcloseWebSocketSessions: CloseCodexWebSocketSessions,\n): void {\n\tif (options.transport === \"sse\" || !options.sessionId) return;\n\tconst signature = `${model.provider}\\0${model.baseUrl}\\0${codexEnvironmentScope(options.env)}\\0${priority ? `priority:${routedModel}` : \"normal\"}`;\n\tconst previous = codexWebSocketRoutingState.get(options.sessionId);\n\tif (previous?.signature !== undefined && previous.signature !== signature) {\n\t\tcloseWebSocketSessions(options.sessionId);\n\t}\n\tif (previous) clearTimeout(previous.expiry);\n\tconst expiry = setTimeout(() => {\n\t\tif (codexWebSocketRoutingState.get(options.sessionId!)?.signature === signature) {\n\t\t\tcodexWebSocketRoutingState.delete(options.sessionId!);\n\t\t}\n\t}, CODEX_WEBSOCKET_ROUTING_STATE_IDLE_MS);\n\texpiry.unref?.();\n\tcodexWebSocketRoutingState.set(options.sessionId, { signature, expiry });\n}\n\nexport function withChatGptCodexTransportRouting<TOptions extends StreamOptions>(\n\tmodel: Model<Api>,\n\toptions: TOptions,\n\tcloseWebSocketSessions: CloseCodexWebSocketSessions = closeOpenAICodexWebSocketSessions,\n): TOptions {\n\tconst headers: ProviderHeaders = { ...(options.headers ?? {}) };\n\tconst onPayload = options.onPayload;\n\tconst priority =\n\t\tgetModelFastRoute(model)?.serviceTier === FAST_MODEL_SERVICE_TIER && usesFirstPartyCodexRouting(model);\n\tconst routedModel = resolveUpstreamModelId(model);\n\treturn {\n\t\t...options,\n\t\theaders,\n\t\tfetch: wrapCodexFastRouteFetch(options.fetch ?? globalThis.fetch),\n\t\tonPayload: async (payload, requestModel) => {\n\t\t\tconst replacement = await onPayload?.(payload, requestModel);\n\t\t\tconst finalPayload = replacement === undefined ? payload : replacement;\n\t\t\tdeleteHeader(headers, CODEX_FAST_ROUTE_HEADER);\n\t\t\tclearCodexFastRouteRequestMarker(headers);\n\t\t\tif (priority) {\n\t\t\t\tsetHeader(headers, CODEX_FAST_ROUTE_HEADER, `model=${routedModel};tier=${FAST_MODEL_SERVICE_TIER}`);\n\t\t\t} else {\n\t\t\t\tfor (const [name, value] of Object.entries(headers)) {\n\t\t\t\t\tif (name.toLowerCase() === \"originator\" && value === CODEX_FAST_ROUTE_ORIGINATOR) delete headers[name];\n\t\t\t\t}\n\t\t\t}\n\t\t\tmarkCodexFastRouteRequest(headers, priority);\n\t\t\tupdateCodexWebSocketRoutingState(model, routedModel, options, priority, closeWebSocketSessions);\n\t\t\treturn finalPayload;\n\t\t},\n\t} as TOptions;\n}\n\nfunction buildFastRouteBaseProviderOptions(\n\tmodel: Model<Api>,\n\toptions: FastRouteStreamOptions | undefined,\n): StreamOptions {\n\t// Native fast-route streams bypass pi-ai's streamSimple base-options merge.\n\tconst samplingParams =\n\t\tmodel.samplingParams || options?.samplingParams\n\t\t\t? { ...model.samplingParams, ...options?.samplingParams }\n\t\t\t: undefined;\n\tconst providerOptions: StreamOptions = {\n\t\tsamplingParams,\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: options?.maxTokens,\n\t\tsignal: options?.signal,\n\t\tapiKey: options?.apiKey,\n\t\tfetch: options?.fetch,\n\t\tenv: options?.env,\n\t\ttelemetryContext: options?.telemetryContext,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\theaders: options?.headers,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\twebsocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,\n\t\tstreamDeadlineMs: options?.streamDeadlineMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t};\n\treturn usesChatGptCodexTransport(model) ? withChatGptCodexTransportRouting(model, providerOptions) : providerOptions;\n}\n\nexport function mapFastRouteReasoningEffort(\n\tmodel: Model<Api>,\n\treasoning: ThinkingLevel | undefined,\n): ThinkingLevel | undefined {\n\tconst clampedReasoning = reasoning ? clampThinkingLevel(model, reasoning) : undefined;\n\treturn clampedReasoning === \"off\" ? undefined : clampedReasoning;\n}\n\nexport function buildOpenAIResponsesFastRouteOptions(\n\tmodel: Model<Api>,\n\toptions: FastRouteStreamOptions | undefined,\n): OpenAIResponsesOptions {\n\treturn {\n\t\t...buildFastRouteBaseProviderOptions(model, options),\n\t\treasoningEffort: mapFastRouteReasoningEffort(model, options?.reasoning),\n\t\tserviceTier: options?.serviceTier,\n\t};\n}\n\nexport function buildOpenAICodexResponsesFastRouteOptions(\n\tmodel: Model<Api>,\n\toptions: FastRouteStreamOptions | undefined,\n): OpenAICodexResponsesOptions {\n\treturn {\n\t\t...buildFastRouteBaseProviderOptions(model, options),\n\t\treasoningEffort: mapFastRouteReasoningEffort(model, options?.reasoning),\n\t\tserviceTier: options?.serviceTier,\n\t};\n}\n\n/**\n * Stream a request whose canonical selected model carries fast-route metadata. The provider adapter\n * translates only the serialized request to the route's upstream ID; the model object keeps its\n * canonical `-fast` identity.\n */\nexport function streamWithFastRoute(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions: FastRouteStreamOptions | undefined,\n\tstreamers: FastRouteStreamers = DEFAULT_FAST_ROUTE_STREAMERS,\n): AssistantMessageEventStream {\n\tif (shouldUseNativeFastRoute(model, options)) {\n\t\tif (model.api === \"openai-responses\") {\n\t\t\treturn streamers.streamOpenAIResponses(\n\t\t\t\tmodel as Model<\"openai-responses\">,\n\t\t\t\tcontext,\n\t\t\t\tbuildOpenAIResponsesFastRouteOptions(model, options),\n\t\t\t);\n\t\t}\n\n\t\t// The WebSocket handshake builds its headers inside pi-ai, and the runtime\n\t\t// constructor can be cached before the first turn, so repair the identity\n\t\t// through the global constructor rather than per-request options.\n\t\tif (options?.transport !== \"sse\" && usesChatGptCodexTransport(model)) {\n\t\t\tinstallCodexFastRouteWebSocketIdentity();\n\t\t}\n\n\t\treturn streamers.streamOpenAICodexResponses(\n\t\t\tmodel as Model<\"openai-codex-responses\">,\n\t\t\tcontext,\n\t\t\tbuildOpenAICodexResponsesFastRouteOptions(model, options),\n\t\t);\n\t}\n\n\treturn streamers.streamSimple(model, context, options);\n}\n"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Api, Credential, Model, Provider } from "@bastani/pi-ai";
|
|
2
|
+
import type { ModelsJsonModelOverride } from "./model-config.ts";
|
|
3
|
+
/** Canonical suffix every selectable fast model variant carries. */
|
|
4
|
+
export declare const FAST_MODEL_ID_SUFFIX = "-fast";
|
|
5
|
+
/** Service tier OpenAI-style providers use to route fast traffic. */
|
|
6
|
+
export declare const FAST_MODEL_SERVICE_TIER: "priority";
|
|
7
|
+
/** A derived fast variant that was suppressed because something already owns its exact model ID. */
|
|
8
|
+
export interface FastModelVariantDiagnostic {
|
|
9
|
+
provider: string;
|
|
10
|
+
/** The exact selectable model ID that collided. */
|
|
11
|
+
modelId: string;
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
export interface FastModelVariantDerivation {
|
|
15
|
+
models: readonly Model<Api>[];
|
|
16
|
+
diagnostics: readonly FastModelVariantDiagnostic[];
|
|
17
|
+
}
|
|
18
|
+
export interface DeriveFastModelVariantsOptions {
|
|
19
|
+
/** Exact fast model IDs the stored GitHub Copilot credential advertises for this account. */
|
|
20
|
+
copilotFastModelIds?: readonly string[];
|
|
21
|
+
/** `models.json` `modelOverrides` for this provider, applied to derived entries by their exact `-fast` ID. */
|
|
22
|
+
modelOverrides?: Readonly<Record<string, ModelsJsonModelOverride>>;
|
|
23
|
+
/** APIs whose transport a registered extension owns for this provider. No variant is derived for them. */
|
|
24
|
+
extensionOwnedApis?: ReadonlySet<Api>;
|
|
25
|
+
}
|
|
26
|
+
export interface FastModelVariantsOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Synchronous read of the exact fast model IDs the stored GitHub Copilot credential advertises.
|
|
29
|
+
* Read per call so a credential that lands after provider composition still takes effect.
|
|
30
|
+
*/
|
|
31
|
+
getCopilotFastModelIds?: () => readonly string[] | undefined;
|
|
32
|
+
/** Synchronous read of this provider's `models.json` `modelOverrides`, so a reload takes effect. */
|
|
33
|
+
getModelOverrides?: () => Readonly<Record<string, ModelsJsonModelOverride>> | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Synchronous read of the APIs a registered extension supplies a stream function for. Read per call
|
|
36
|
+
* because extensions register after initial composition on some paths.
|
|
37
|
+
*/
|
|
38
|
+
getExtensionOwnedApis?: () => ReadonlySet<Api> | undefined;
|
|
39
|
+
/** Called after every derivation pass with the complete diagnostic list for this provider. */
|
|
40
|
+
onDiagnostics?: (providerId: string, diagnostics: readonly FastModelVariantDiagnostic[]) => void;
|
|
41
|
+
}
|
|
42
|
+
/** Canonical selectable ID of the fast variant of `baseModelId`. */
|
|
43
|
+
export declare function fastModelId(baseModelId: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* The two pi-ai adapters that serialize `service_tier`. `azure-openai-responses` and
|
|
46
|
+
* `openai-completions` have no such option, and `streamSimple` drops it, so a service-tier route on
|
|
47
|
+
* any other API would silently degrade to an ordinary request.
|
|
48
|
+
*/
|
|
49
|
+
export declare function isNativeFastRouteApi(api: Api): api is "openai-responses" | "openai-codex-responses";
|
|
50
|
+
/**
|
|
51
|
+
* OpenAI-style fast routing keeps the base upstream model ID and adds a priority service tier.
|
|
52
|
+
*
|
|
53
|
+
* Eligibility requires both a first-party provider ID and an adapter that serializes
|
|
54
|
+
* `service_tier`. A renamed provider, proxy, Azure OpenAI (`azure-openai-responses`), OpenRouter
|
|
55
|
+
* (`openai-completions`), and generic OpenAI-compatible providers do not qualify. An `openai` or
|
|
56
|
+
* `openai-codex` model on an adapter that cannot carry `service_tier` must not offer a fast variant,
|
|
57
|
+
* because selecting it would send an ordinary request under a name that promises otherwise.
|
|
58
|
+
*/
|
|
59
|
+
export declare function usesOpenAIFastServiceTier(model: Pick<Model<Api>, "api" | "provider">): boolean;
|
|
60
|
+
/** GitHub Copilot advertises real fast sibling model IDs per account; it never uses a service tier. */
|
|
61
|
+
export declare function isGitHubCopilotModel(model: Pick<Model<Api>, "provider">): boolean;
|
|
62
|
+
/** Read the exact fast model IDs a stored GitHub Copilot OAuth credential advertises. */
|
|
63
|
+
export declare function copilotAdvertisedFastModelIds(credential: Credential | undefined): readonly string[] | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Whether a stored GitHub Copilot OAuth credential advertises this exact model ID at all — as a
|
|
66
|
+
* selectable picker/policy model or as a fast sibling.
|
|
67
|
+
*
|
|
68
|
+
* Copilot's per-account advertisement is the authority the provider's own `filterModels` uses, so
|
|
69
|
+
* restoration consults the same lists. An ID the account advertises as an ordinary model is ordinary,
|
|
70
|
+
* whatever its name ends in.
|
|
71
|
+
*/
|
|
72
|
+
export declare function copilotAdvertisesModelId(credential: Credential | undefined, modelId: string): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Add a selectable `<base-model-id>-fast` entry for every eligible model, carrying the explicit
|
|
75
|
+
* {@link ModelFastRoute} metadata that gives it fast semantics. The input list is preserved verbatim
|
|
76
|
+
* and in order; each derived entry is appended directly after the model it derives from.
|
|
77
|
+
*
|
|
78
|
+
* A model whose exact `-fast` ID is already owned by the provider, a `models.json` custom model, or an
|
|
79
|
+
* extension wins: derivation is suppressed for it and a diagnostic is recorded. The owning model keeps
|
|
80
|
+
* whatever semantics it declares, because fast behavior comes only from `fastRoute`, never from the
|
|
81
|
+
* `-fast` suffix. For the same reason a base model whose ID already ends in `-fast` is never used to
|
|
82
|
+
* derive a `-fast-fast` variant: that is not a canonical ID this scheme defines.
|
|
83
|
+
*
|
|
84
|
+
* A derived entry is a real catalog model, so a `modelOverrides` entry keyed on its exact `-fast` ID
|
|
85
|
+
* applies to it after derivation. Without that pass the derived entry would inherit the *base* model's
|
|
86
|
+
* overrides and its own would be silently inert.
|
|
87
|
+
*
|
|
88
|
+
* No variant is derived for an API whose transport a registered extension owns, because Atomic cannot
|
|
89
|
+
* enforce the route through a transport it does not serialize.
|
|
90
|
+
*/
|
|
91
|
+
export declare function deriveFastModelVariants(providerId: string, models: readonly Model<Api>[], options?: DeriveFastModelVariantsOptions): FastModelVariantDerivation;
|
|
92
|
+
/**
|
|
93
|
+
* Overlay derived fast model variants onto a composed provider. Apply this after built-in,
|
|
94
|
+
* `models.json`, extension, and `modelOverrides` composition so exact user-owned `-fast` IDs are
|
|
95
|
+
* already present and win the collision.
|
|
96
|
+
*/
|
|
97
|
+
export declare function withFastModelVariants(provider: Provider, options?: FastModelVariantsOptions): Provider;
|
|
98
|
+
//# sourceMappingURL=fast-model-variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-model-variants.d.ts","sourceRoot":"","sources":["../../src/core/fast-model-variants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAkB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACvF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAGjE,oEAAoE;AACpE,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,EAAG,UAAmB,CAAC;AAE3D,oGAAoG;AACpG,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IAC1C,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9B,WAAW,EAAE,SAAS,0BAA0B,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,8BAA8B;IAC9C,6FAA6F;IAC7F,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,8GAA8G;IAC9G,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,CAAC;IACnE,0GAA0G;IAC1G,kBAAkB,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,wBAAwB;IACxC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7D,oGAAoG;IACpG,iBAAiB,CAAC,EAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,GAAG,SAAS,CAAC;IACxF;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,WAAW,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC3D,8FAA8F;IAC9F,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,0BAA0B,EAAE,KAAK,IAAI,CAAC;CACjG;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,kBAAkB,GAAG,wBAAwB,CAEnG;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,GAAG,OAAO,CAE9F;AAED,uGAAuG;AACvG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,GAAG,OAAO,CAEjF;AAOD,yFAAyF;AACzF,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAG/G;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAMrG;AAkBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,EAC7B,OAAO,GAAE,8BAAmC,GAC1C,0BAA0B,CAkC5B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,GAAE,wBAA6B,GAAG,QAAQ,CAe1G"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { applyModelOverride } from "./provider-composer-internal.js";
|
|
2
|
+
/** Canonical suffix every selectable fast model variant carries. */
|
|
3
|
+
export const FAST_MODEL_ID_SUFFIX = "-fast";
|
|
4
|
+
/** Service tier OpenAI-style providers use to route fast traffic. */
|
|
5
|
+
export const FAST_MODEL_SERVICE_TIER = "priority";
|
|
6
|
+
/** Canonical selectable ID of the fast variant of `baseModelId`. */
|
|
7
|
+
export function fastModelId(baseModelId) {
|
|
8
|
+
return `${baseModelId}${FAST_MODEL_ID_SUFFIX}`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The two pi-ai adapters that serialize `service_tier`. `azure-openai-responses` and
|
|
12
|
+
* `openai-completions` have no such option, and `streamSimple` drops it, so a service-tier route on
|
|
13
|
+
* any other API would silently degrade to an ordinary request.
|
|
14
|
+
*/
|
|
15
|
+
export function isNativeFastRouteApi(api) {
|
|
16
|
+
return api === "openai-responses" || api === "openai-codex-responses";
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* OpenAI-style fast routing keeps the base upstream model ID and adds a priority service tier.
|
|
20
|
+
*
|
|
21
|
+
* Eligibility requires both a first-party provider ID and an adapter that serializes
|
|
22
|
+
* `service_tier`. A renamed provider, proxy, Azure OpenAI (`azure-openai-responses`), OpenRouter
|
|
23
|
+
* (`openai-completions`), and generic OpenAI-compatible providers do not qualify. An `openai` or
|
|
24
|
+
* `openai-codex` model on an adapter that cannot carry `service_tier` must not offer a fast variant,
|
|
25
|
+
* because selecting it would send an ordinary request under a name that promises otherwise.
|
|
26
|
+
*/
|
|
27
|
+
export function usesOpenAIFastServiceTier(model) {
|
|
28
|
+
return isNativeFastRouteApi(model.api) && (model.provider === "openai" || model.provider === "openai-codex");
|
|
29
|
+
}
|
|
30
|
+
/** GitHub Copilot advertises real fast sibling model IDs per account; it never uses a service tier. */
|
|
31
|
+
export function isGitHubCopilotModel(model) {
|
|
32
|
+
return model.provider === "github-copilot";
|
|
33
|
+
}
|
|
34
|
+
function advertisedModelIds(value) {
|
|
35
|
+
if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string"))
|
|
36
|
+
return undefined;
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
/** Read the exact fast model IDs a stored GitHub Copilot OAuth credential advertises. */
|
|
40
|
+
export function copilotAdvertisedFastModelIds(credential) {
|
|
41
|
+
if (credential?.type !== "oauth")
|
|
42
|
+
return undefined;
|
|
43
|
+
return advertisedModelIds(credential.fastModelIds);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Whether a stored GitHub Copilot OAuth credential advertises this exact model ID at all — as a
|
|
47
|
+
* selectable picker/policy model or as a fast sibling.
|
|
48
|
+
*
|
|
49
|
+
* Copilot's per-account advertisement is the authority the provider's own `filterModels` uses, so
|
|
50
|
+
* restoration consults the same lists. An ID the account advertises as an ordinary model is ordinary,
|
|
51
|
+
* whatever its name ends in.
|
|
52
|
+
*/
|
|
53
|
+
export function copilotAdvertisesModelId(credential, modelId) {
|
|
54
|
+
if (credential?.type !== "oauth")
|
|
55
|
+
return false;
|
|
56
|
+
return (advertisedModelIds(credential.availableModelIds)?.includes(modelId) === true ||
|
|
57
|
+
advertisedModelIds(credential.fastModelIds)?.includes(modelId) === true);
|
|
58
|
+
}
|
|
59
|
+
function fastRouteForBaseModel(model, entitledCopilotFastModelIds) {
|
|
60
|
+
if (usesOpenAIFastServiceTier(model)) {
|
|
61
|
+
return { baseModelId: model.id, upstreamModelId: model.id, serviceTier: FAST_MODEL_SERVICE_TIER };
|
|
62
|
+
}
|
|
63
|
+
if (isGitHubCopilotModel(model)) {
|
|
64
|
+
const advertisedId = fastModelId(model.id);
|
|
65
|
+
return entitledCopilotFastModelIds.has(advertisedId)
|
|
66
|
+
? { baseModelId: model.id, upstreamModelId: advertisedId }
|
|
67
|
+
: undefined;
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Add a selectable `<base-model-id>-fast` entry for every eligible model, carrying the explicit
|
|
73
|
+
* {@link ModelFastRoute} metadata that gives it fast semantics. The input list is preserved verbatim
|
|
74
|
+
* and in order; each derived entry is appended directly after the model it derives from.
|
|
75
|
+
*
|
|
76
|
+
* A model whose exact `-fast` ID is already owned by the provider, a `models.json` custom model, or an
|
|
77
|
+
* extension wins: derivation is suppressed for it and a diagnostic is recorded. The owning model keeps
|
|
78
|
+
* whatever semantics it declares, because fast behavior comes only from `fastRoute`, never from the
|
|
79
|
+
* `-fast` suffix. For the same reason a base model whose ID already ends in `-fast` is never used to
|
|
80
|
+
* derive a `-fast-fast` variant: that is not a canonical ID this scheme defines.
|
|
81
|
+
*
|
|
82
|
+
* A derived entry is a real catalog model, so a `modelOverrides` entry keyed on its exact `-fast` ID
|
|
83
|
+
* applies to it after derivation. Without that pass the derived entry would inherit the *base* model's
|
|
84
|
+
* overrides and its own would be silently inert.
|
|
85
|
+
*
|
|
86
|
+
* No variant is derived for an API whose transport a registered extension owns, because Atomic cannot
|
|
87
|
+
* enforce the route through a transport it does not serialize.
|
|
88
|
+
*/
|
|
89
|
+
export function deriveFastModelVariants(providerId, models, options = {}) {
|
|
90
|
+
const ownedModelIds = new Set(models.map((model) => model.id));
|
|
91
|
+
const entitledCopilotFastModelIds = new Set(options.copilotFastModelIds ?? []);
|
|
92
|
+
const derived = [];
|
|
93
|
+
const diagnostics = [];
|
|
94
|
+
let changed = false;
|
|
95
|
+
for (const model of models) {
|
|
96
|
+
derived.push(model);
|
|
97
|
+
if (model.fastRoute !== undefined || model.id.endsWith(FAST_MODEL_ID_SUFFIX))
|
|
98
|
+
continue;
|
|
99
|
+
// An extension that supplies this API's stream function owns its serialization, so Atomic cannot
|
|
100
|
+
// guarantee the route reaches the wire. Publishing a `-fast` choice it may not honor is the same
|
|
101
|
+
// hazard as publishing one for an adapter that cannot carry the tier.
|
|
102
|
+
if (options.extensionOwnedApis?.has(model.api) === true)
|
|
103
|
+
continue;
|
|
104
|
+
const fastRoute = fastRouteForBaseModel(model, entitledCopilotFastModelIds);
|
|
105
|
+
if (!fastRoute)
|
|
106
|
+
continue;
|
|
107
|
+
const variantId = fastModelId(model.id);
|
|
108
|
+
if (ownedModelIds.has(variantId)) {
|
|
109
|
+
diagnostics.push({
|
|
110
|
+
provider: providerId,
|
|
111
|
+
modelId: variantId,
|
|
112
|
+
message: `Model "${providerId}/${variantId}" is already defined by the provider, models.json, or an extension, ` +
|
|
113
|
+
`so Atomic did not derive a fast variant of "${providerId}/${model.id}". ` +
|
|
114
|
+
`That model routes exactly as declared. Rename or remove it to get the derived fast variant instead.`,
|
|
115
|
+
});
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const override = options.modelOverrides?.[variantId];
|
|
119
|
+
const variant = { ...model, id: variantId, name: `${model.name} (fast)`, fastRoute };
|
|
120
|
+
derived.push(override ? applyModelOverride(variant, override) : variant);
|
|
121
|
+
changed = true;
|
|
122
|
+
}
|
|
123
|
+
if (!changed && diagnostics.length === 0)
|
|
124
|
+
return { models, diagnostics };
|
|
125
|
+
return { models: derived, diagnostics };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Overlay derived fast model variants onto a composed provider. Apply this after built-in,
|
|
129
|
+
* `models.json`, extension, and `modelOverrides` composition so exact user-owned `-fast` IDs are
|
|
130
|
+
* already present and win the collision.
|
|
131
|
+
*/
|
|
132
|
+
export function withFastModelVariants(provider, options = {}) {
|
|
133
|
+
return {
|
|
134
|
+
...provider,
|
|
135
|
+
getModels: () => {
|
|
136
|
+
const { models, diagnostics } = deriveFastModelVariants(provider.id, provider.getModels(), {
|
|
137
|
+
copilotFastModelIds: isGitHubCopilotModel({ provider: provider.id })
|
|
138
|
+
? options.getCopilotFastModelIds?.()
|
|
139
|
+
: undefined,
|
|
140
|
+
modelOverrides: options.getModelOverrides?.(),
|
|
141
|
+
extensionOwnedApis: options.getExtensionOwnedApis?.(),
|
|
142
|
+
});
|
|
143
|
+
options.onDiagnostics?.(provider.id, diagnostics);
|
|
144
|
+
return models;
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=fast-model-variants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-model-variants.js","sourceRoot":"","sources":["../../src/core/fast-model-variants.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,oEAAoE;AACpE,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C,qEAAqE;AACrE,MAAM,CAAC,MAAM,uBAAuB,GAAG,UAAmB,CAAC;AAyC3D,oEAAoE;AACpE,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC9C,OAAO,GAAG,WAAW,GAAG,oBAAoB,EAAE,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAQ;IAC5C,OAAO,GAAG,KAAK,kBAAkB,IAAI,GAAG,KAAK,wBAAwB,CAAC;AACvE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAA2C;IACpF,OAAO,oBAAoB,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC;AAC9G,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,oBAAoB,CAAC,KAAmC;IACvE,OAAO,KAAK,CAAC,QAAQ,KAAK,gBAAgB,CAAC;AAC5C,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAClG,OAAO,KAAK,CAAC;AACd,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,6BAA6B,CAAC,UAAkC;IAC/E,IAAI,UAAU,EAAE,IAAI,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACnD,OAAO,kBAAkB,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CAAC,UAAkC,EAAE,OAAe;IAC3F,IAAI,UAAU,EAAE,IAAI,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,CACN,kBAAkB,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI;QAC5E,kBAAkB,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,CACvE,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC7B,KAAiB,EACjB,2BAAgD;IAEhD,IAAI,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;IACnG,CAAC;IACD,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC3C,OAAO,2BAA2B,CAAC,GAAG,CAAC,YAAY,CAAC;YACnD,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,eAAe,EAAE,YAAY,EAAE;YAC1D,CAAC,CAAC,SAAS,CAAC;IACd,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,uBAAuB,CACtC,UAAkB,EAClB,MAA6B,EAC7B,OAAO,GAAmC,EAAE;IAE5C,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/D,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,WAAW,GAAiC,EAAE,CAAC;IACrD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;YAAE,SAAS;QACvF,iGAAiG;QACjG,iGAAiG;QACjG,sEAAsE;QACtE,IAAI,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI;YAAE,SAAS;QAClE,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC5E,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,WAAW,CAAC,IAAI,CAAC;gBAChB,QAAQ,EAAE,UAAU;gBACpB,OAAO,EAAE,SAAS;gBAClB,OAAO,EACN,UAAU,UAAU,IAAI,SAAS,sEAAsE;oBACvG,+CAA+C,UAAU,IAAI,KAAK,CAAC,EAAE,KAAK;oBAC1E,qGAAqG;aACtG,CAAC,CAAC;YACH,SAAS;QACV,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,OAAO,GAAe,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,SAAS,EAAE,SAAS,EAAE,CAAC;QACjG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACzE,OAAO,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACzE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAkB,EAAE,OAAO,GAA6B,EAAE;IAC/F,OAAO;QACN,GAAG,QAAQ;QACX,SAAS,EAAE,GAAG,EAAE;YACf,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,uBAAuB,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,SAAS,EAAE,EAAE;gBAC1F,mBAAmB,EAAE,oBAAoB,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACnE,CAAC,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE;oBACpC,CAAC,CAAC,SAAS;gBACZ,cAAc,EAAE,OAAO,CAAC,iBAAiB,EAAE,EAAE;gBAC7C,kBAAkB,EAAE,OAAO,CAAC,qBAAqB,EAAE,EAAE;aACrD,CAAC,CAAC;YACH,OAAO,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;YAClD,OAAO,MAAM,CAAC;QACf,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import type { Api, Credential, Model, ModelFastRoute, Provider } from \"@bastani/pi-ai\";\nimport type { ModelsJsonModelOverride } from \"./model-config.ts\";\nimport { applyModelOverride } from \"./provider-composer-internal.ts\";\n\n/** Canonical suffix every selectable fast model variant carries. */\nexport const FAST_MODEL_ID_SUFFIX = \"-fast\";\n\n/** Service tier OpenAI-style providers use to route fast traffic. */\nexport const FAST_MODEL_SERVICE_TIER = \"priority\" as const;\n\n/** A derived fast variant that was suppressed because something already owns its exact model ID. */\nexport interface FastModelVariantDiagnostic {\n\tprovider: string;\n\t/** The exact selectable model ID that collided. */\n\tmodelId: string;\n\tmessage: string;\n}\n\nexport interface FastModelVariantDerivation {\n\tmodels: readonly Model<Api>[];\n\tdiagnostics: readonly FastModelVariantDiagnostic[];\n}\n\nexport interface DeriveFastModelVariantsOptions {\n\t/** Exact fast model IDs the stored GitHub Copilot credential advertises for this account. */\n\tcopilotFastModelIds?: readonly string[];\n\t/** `models.json` `modelOverrides` for this provider, applied to derived entries by their exact `-fast` ID. */\n\tmodelOverrides?: Readonly<Record<string, ModelsJsonModelOverride>>;\n\t/** APIs whose transport a registered extension owns for this provider. No variant is derived for them. */\n\textensionOwnedApis?: ReadonlySet<Api>;\n}\n\nexport interface FastModelVariantsOptions {\n\t/**\n\t * Synchronous read of the exact fast model IDs the stored GitHub Copilot credential advertises.\n\t * Read per call so a credential that lands after provider composition still takes effect.\n\t */\n\tgetCopilotFastModelIds?: () => readonly string[] | undefined;\n\t/** Synchronous read of this provider's `models.json` `modelOverrides`, so a reload takes effect. */\n\tgetModelOverrides?: () => Readonly<Record<string, ModelsJsonModelOverride>> | undefined;\n\t/**\n\t * Synchronous read of the APIs a registered extension supplies a stream function for. Read per call\n\t * because extensions register after initial composition on some paths.\n\t */\n\tgetExtensionOwnedApis?: () => ReadonlySet<Api> | undefined;\n\t/** Called after every derivation pass with the complete diagnostic list for this provider. */\n\tonDiagnostics?: (providerId: string, diagnostics: readonly FastModelVariantDiagnostic[]) => void;\n}\n\n/** Canonical selectable ID of the fast variant of `baseModelId`. */\nexport function fastModelId(baseModelId: string): string {\n\treturn `${baseModelId}${FAST_MODEL_ID_SUFFIX}`;\n}\n\n/**\n * The two pi-ai adapters that serialize `service_tier`. `azure-openai-responses` and\n * `openai-completions` have no such option, and `streamSimple` drops it, so a service-tier route on\n * any other API would silently degrade to an ordinary request.\n */\nexport function isNativeFastRouteApi(api: Api): api is \"openai-responses\" | \"openai-codex-responses\" {\n\treturn api === \"openai-responses\" || api === \"openai-codex-responses\";\n}\n\n/**\n * OpenAI-style fast routing keeps the base upstream model ID and adds a priority service tier.\n *\n * Eligibility requires both a first-party provider ID and an adapter that serializes\n * `service_tier`. A renamed provider, proxy, Azure OpenAI (`azure-openai-responses`), OpenRouter\n * (`openai-completions`), and generic OpenAI-compatible providers do not qualify. An `openai` or\n * `openai-codex` model on an adapter that cannot carry `service_tier` must not offer a fast variant,\n * because selecting it would send an ordinary request under a name that promises otherwise.\n */\nexport function usesOpenAIFastServiceTier(model: Pick<Model<Api>, \"api\" | \"provider\">): boolean {\n\treturn isNativeFastRouteApi(model.api) && (model.provider === \"openai\" || model.provider === \"openai-codex\");\n}\n\n/** GitHub Copilot advertises real fast sibling model IDs per account; it never uses a service tier. */\nexport function isGitHubCopilotModel(model: Pick<Model<Api>, \"provider\">): boolean {\n\treturn model.provider === \"github-copilot\";\n}\n\nfunction advertisedModelIds(value: unknown): readonly string[] | undefined {\n\tif (!Array.isArray(value) || !value.every((entry) => typeof entry === \"string\")) return undefined;\n\treturn value;\n}\n\n/** Read the exact fast model IDs a stored GitHub Copilot OAuth credential advertises. */\nexport function copilotAdvertisedFastModelIds(credential: Credential | undefined): readonly string[] | undefined {\n\tif (credential?.type !== \"oauth\") return undefined;\n\treturn advertisedModelIds(credential.fastModelIds);\n}\n\n/**\n * Whether a stored GitHub Copilot OAuth credential advertises this exact model ID at all — as a\n * selectable picker/policy model or as a fast sibling.\n *\n * Copilot's per-account advertisement is the authority the provider's own `filterModels` uses, so\n * restoration consults the same lists. An ID the account advertises as an ordinary model is ordinary,\n * whatever its name ends in.\n */\nexport function copilotAdvertisesModelId(credential: Credential | undefined, modelId: string): boolean {\n\tif (credential?.type !== \"oauth\") return false;\n\treturn (\n\t\tadvertisedModelIds(credential.availableModelIds)?.includes(modelId) === true ||\n\t\tadvertisedModelIds(credential.fastModelIds)?.includes(modelId) === true\n\t);\n}\n\nfunction fastRouteForBaseModel(\n\tmodel: Model<Api>,\n\tentitledCopilotFastModelIds: ReadonlySet<string>,\n): ModelFastRoute | undefined {\n\tif (usesOpenAIFastServiceTier(model)) {\n\t\treturn { baseModelId: model.id, upstreamModelId: model.id, serviceTier: FAST_MODEL_SERVICE_TIER };\n\t}\n\tif (isGitHubCopilotModel(model)) {\n\t\tconst advertisedId = fastModelId(model.id);\n\t\treturn entitledCopilotFastModelIds.has(advertisedId)\n\t\t\t? { baseModelId: model.id, upstreamModelId: advertisedId }\n\t\t\t: undefined;\n\t}\n\treturn undefined;\n}\n\n/**\n * Add a selectable `<base-model-id>-fast` entry for every eligible model, carrying the explicit\n * {@link ModelFastRoute} metadata that gives it fast semantics. The input list is preserved verbatim\n * and in order; each derived entry is appended directly after the model it derives from.\n *\n * A model whose exact `-fast` ID is already owned by the provider, a `models.json` custom model, or an\n * extension wins: derivation is suppressed for it and a diagnostic is recorded. The owning model keeps\n * whatever semantics it declares, because fast behavior comes only from `fastRoute`, never from the\n * `-fast` suffix. For the same reason a base model whose ID already ends in `-fast` is never used to\n * derive a `-fast-fast` variant: that is not a canonical ID this scheme defines.\n *\n * A derived entry is a real catalog model, so a `modelOverrides` entry keyed on its exact `-fast` ID\n * applies to it after derivation. Without that pass the derived entry would inherit the *base* model's\n * overrides and its own would be silently inert.\n *\n * No variant is derived for an API whose transport a registered extension owns, because Atomic cannot\n * enforce the route through a transport it does not serialize.\n */\nexport function deriveFastModelVariants(\n\tproviderId: string,\n\tmodels: readonly Model<Api>[],\n\toptions: DeriveFastModelVariantsOptions = {},\n): FastModelVariantDerivation {\n\tconst ownedModelIds = new Set(models.map((model) => model.id));\n\tconst entitledCopilotFastModelIds = new Set(options.copilotFastModelIds ?? []);\n\tconst derived: Model<Api>[] = [];\n\tconst diagnostics: FastModelVariantDiagnostic[] = [];\n\tlet changed = false;\n\tfor (const model of models) {\n\t\tderived.push(model);\n\t\tif (model.fastRoute !== undefined || model.id.endsWith(FAST_MODEL_ID_SUFFIX)) continue;\n\t\t// An extension that supplies this API's stream function owns its serialization, so Atomic cannot\n\t\t// guarantee the route reaches the wire. Publishing a `-fast` choice it may not honor is the same\n\t\t// hazard as publishing one for an adapter that cannot carry the tier.\n\t\tif (options.extensionOwnedApis?.has(model.api) === true) continue;\n\t\tconst fastRoute = fastRouteForBaseModel(model, entitledCopilotFastModelIds);\n\t\tif (!fastRoute) continue;\n\t\tconst variantId = fastModelId(model.id);\n\t\tif (ownedModelIds.has(variantId)) {\n\t\t\tdiagnostics.push({\n\t\t\t\tprovider: providerId,\n\t\t\t\tmodelId: variantId,\n\t\t\t\tmessage:\n\t\t\t\t\t`Model \"${providerId}/${variantId}\" is already defined by the provider, models.json, or an extension, ` +\n\t\t\t\t\t`so Atomic did not derive a fast variant of \"${providerId}/${model.id}\". ` +\n\t\t\t\t\t`That model routes exactly as declared. Rename or remove it to get the derived fast variant instead.`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst override = options.modelOverrides?.[variantId];\n\t\tconst variant: Model<Api> = { ...model, id: variantId, name: `${model.name} (fast)`, fastRoute };\n\t\tderived.push(override ? applyModelOverride(variant, override) : variant);\n\t\tchanged = true;\n\t}\n\tif (!changed && diagnostics.length === 0) return { models, diagnostics };\n\treturn { models: derived, diagnostics };\n}\n\n/**\n * Overlay derived fast model variants onto a composed provider. Apply this after built-in,\n * `models.json`, extension, and `modelOverrides` composition so exact user-owned `-fast` IDs are\n * already present and win the collision.\n */\nexport function withFastModelVariants(provider: Provider, options: FastModelVariantsOptions = {}): Provider {\n\treturn {\n\t\t...provider,\n\t\tgetModels: () => {\n\t\t\tconst { models, diagnostics } = deriveFastModelVariants(provider.id, provider.getModels(), {\n\t\t\t\tcopilotFastModelIds: isGitHubCopilotModel({ provider: provider.id })\n\t\t\t\t\t? options.getCopilotFastModelIds?.()\n\t\t\t\t\t: undefined,\n\t\t\t\tmodelOverrides: options.getModelOverrides?.(),\n\t\t\t\textensionOwnedApis: options.getExtensionOwnedApis?.(),\n\t\t\t});\n\t\t\toptions.onDiagnostics?.(provider.id, diagnostics);\n\t\t\treturn models;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,eAAO,MAAM,4BAA4B,SAAU,CAAC;AA2CpD,eAAO,MAAM,yBAAyB;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,KAAM;;aAClC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,KAAM;;aACjC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,MAAO;;aAClC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,MAAO;;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,OAAS;;aACrC,KAAK,EAAE,UAAU;aAAE,SAAS,EAAE,CAAC;EACxB,CAAC;AAEX,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAWzE;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAK1E;AAED,wBAAgB,2BAA2B,CAC1C,SAAS,EAAE,MAAM,GACf,qBAAqB,CAAC,OAAO,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"http-dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,eAAO,MAAM,4BAA4B,SAAU,CAAC;AA2CpD,eAAO,MAAM,yBAAyB;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,KAAM;;aAClC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,KAAM;;aACjC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,MAAO;;aAClC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,MAAO;;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,OAAS;;aACrC,KAAK,EAAE,UAAU;aAAE,SAAS,EAAE,CAAC;EACxB,CAAC;AAEX,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAWzE;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAK1E;AAED,wBAAgB,2BAA2B,CAC1C,SAAS,EAAE,MAAM,GACf,qBAAqB,CAAC,OAAO,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAa3D;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAqC,GAAG,IAAI,CA4B9F"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
2
|
import * as undici from "undici";
|
|
3
|
-
import {
|
|
3
|
+
import { installCodexFastRouteWebSocketIdentity } from "./fast-model-routing-transport.js";
|
|
4
4
|
export const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 600_000;
|
|
5
5
|
const originalGlobalFetch = globalThis.fetch;
|
|
6
6
|
let installedGlobalFetch;
|
|
@@ -81,6 +81,8 @@ export function applyHttpProxySettings(httpProxy) {
|
|
|
81
81
|
export function createHttpDispatcherOptions(timeoutMs) {
|
|
82
82
|
return {
|
|
83
83
|
allowH2: false,
|
|
84
|
+
// Keep HTTP origins on CONNECT tunnels as they were before Undici 8.7.
|
|
85
|
+
proxyTunnel: true,
|
|
84
86
|
// Undici defaults to a 10s connect timeout; disable it so slow
|
|
85
87
|
// policy/proxy CONNECT establishment follows provider retry handling.
|
|
86
88
|
connectTimeout: 0,
|
|
@@ -144,7 +146,7 @@ export function configureHttpDispatcher(timeoutMs = DEFAULT_HTTP_IDLE_TIMEOUT_MS
|
|
|
144
146
|
// Undici replaces the WebSocket constructor pi-ai caches on first use.
|
|
145
147
|
// The wrapper only rewrites a shared Codex request carrying Atomic's
|
|
146
148
|
// final-payload routing marker, so all other handshakes stay unchanged.
|
|
147
|
-
|
|
149
|
+
installCodexFastRouteWebSocketIdentity();
|
|
148
150
|
}
|
|
149
151
|
}
|
|
150
152
|
//# sourceMappingURL=http-dispatcher.js.map
|