open-multi-agent-kit 1.0.0 → 1.2.2
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 +52 -1
- package/README.md +2 -2
- package/dist/approval-api.d.ts +5 -0
- package/dist/approval-api.d.ts.map +1 -0
- package/dist/approval-api.js +5 -0
- package/dist/approval-api.js.map +1 -0
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +1 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/session-picker.d.ts +2 -2
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/commands/verified-run-cli.d.ts.map +1 -1
- package/dist/commands/verified-run-cli.js +69 -22
- package/dist/commands/verified-run-cli.js.map +1 -1
- package/dist/commands/verified-run-signal.d.ts +3 -0
- package/dist/commands/verified-run-signal.d.ts.map +1 -0
- package/dist/commands/verified-run-signal.js +15 -0
- package/dist/commands/verified-run-signal.js.map +1 -0
- package/dist/coordination/awareness.d.ts +32 -0
- package/dist/coordination/awareness.d.ts.map +1 -0
- package/dist/coordination/awareness.js +55 -0
- package/dist/coordination/awareness.js.map +1 -0
- package/dist/coordination/broker.d.ts +79 -0
- package/dist/coordination/broker.d.ts.map +1 -0
- package/dist/coordination/broker.js +202 -0
- package/dist/coordination/broker.js.map +1 -0
- package/dist/coordination/index.d.ts +16 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +16 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/integration.d.ts +59 -0
- package/dist/coordination/integration.d.ts.map +1 -0
- package/dist/coordination/integration.js +126 -0
- package/dist/coordination/integration.js.map +1 -0
- package/dist/coordination/operation.d.ts +107 -0
- package/dist/coordination/operation.d.ts.map +1 -0
- package/dist/coordination/operation.js +231 -0
- package/dist/coordination/operation.js.map +1 -0
- package/dist/coordination/resource.d.ts +33 -0
- package/dist/coordination/resource.d.ts.map +1 -0
- package/dist/coordination/resource.js +95 -0
- package/dist/coordination/resource.js.map +1 -0
- package/dist/coordination/session.d.ts +74 -0
- package/dist/coordination/session.d.ts.map +1 -0
- package/dist/coordination/session.js +143 -0
- package/dist/coordination/session.js.map +1 -0
- package/dist/coordination/types.d.ts +68 -0
- package/dist/coordination/types.d.ts.map +1 -0
- package/dist/coordination/types.js +26 -0
- package/dist/coordination/types.js.map +1 -0
- package/dist/core/adaptorch-bridge.d.ts +1 -1
- package/dist/core/adaptorch-bridge.d.ts.map +1 -1
- package/dist/core/adaptorch-bridge.js +1 -1
- package/dist/core/adaptorch-bridge.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +16 -16
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +35 -15
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.d.ts.map +1 -0
- package/dist/core/canonical-json.js +20 -0
- package/dist/core/canonical-json.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +7 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +14 -29
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/control-state.d.ts +41 -0
- package/dist/core/compaction/control-state.d.ts.map +1 -0
- package/dist/core/compaction/control-state.js +85 -0
- package/dist/core/compaction/control-state.js.map +1 -0
- package/dist/core/compaction/fallback.d.ts +71 -0
- package/dist/core/compaction/fallback.d.ts.map +1 -0
- package/dist/core/compaction/fallback.js +118 -0
- package/dist/core/compaction/fallback.js.map +1 -0
- package/dist/core/compaction/index.d.ts +2 -0
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +2 -0
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/model-failover.d.ts +21 -0
- package/dist/core/compaction/model-failover.d.ts.map +1 -0
- package/dist/core/compaction/model-failover.js +46 -0
- package/dist/core/compaction/model-failover.js.map +1 -0
- package/dist/core/compaction/session-summary.d.ts +21 -0
- package/dist/core/compaction/session-summary.d.ts.map +1 -0
- package/dist/core/compaction/session-summary.js +27 -0
- package/dist/core/compaction/session-summary.js.map +1 -0
- package/dist/core/context-budget-headroom-candidates.d.ts +16 -1
- package/dist/core/context-budget-headroom-candidates.d.ts.map +1 -1
- package/dist/core/context-budget-headroom-candidates.js +31 -13
- package/dist/core/context-budget-headroom-candidates.js.map +1 -1
- package/dist/core/context-budget-headroom-types.d.ts +7 -1
- package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
- package/dist/core/context-budget-headroom-types.js +0 -1
- package/dist/core/context-budget-headroom-types.js.map +1 -1
- package/dist/core/context-budget-headroom.d.ts +10 -0
- package/dist/core/context-budget-headroom.d.ts.map +1 -1
- package/dist/core/context-budget-headroom.js +11 -2
- package/dist/core/context-budget-headroom.js.map +1 -1
- package/dist/core/context-budget-v2-global-pass.d.ts +21 -0
- package/dist/core/context-budget-v2-global-pass.d.ts.map +1 -0
- package/dist/core/context-budget-v2-global-pass.js +203 -0
- package/dist/core/context-budget-v2-global-pass.js.map +1 -0
- package/dist/core/context-budget-v2-planned-items.d.ts +12 -0
- package/dist/core/context-budget-v2-planned-items.d.ts.map +1 -1
- package/dist/core/context-budget-v2-planned-items.js +21 -2
- package/dist/core/context-budget-v2-planned-items.js.map +1 -1
- package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
- package/dist/core/context-budget-v2-planner.js +18 -19
- package/dist/core/context-budget-v2-planner.js.map +1 -1
- package/dist/core/context-budget-v2-scoring.d.ts +7 -1
- package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
- package/dist/core/context-budget-v2-scoring.js.map +1 -1
- package/dist/core/context-budget-v2-selection.d.ts +3 -0
- package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
- package/dist/core/context-budget-v2-selection.js +6 -2
- package/dist/core/context-budget-v2-selection.js.map +1 -1
- package/dist/core/context-budget-v2-types.d.ts +6 -1
- package/dist/core/context-budget-v2-types.d.ts.map +1 -1
- package/dist/core/context-budget-v2-types.js +6 -1
- package/dist/core/context-budget-v2-types.js.map +1 -1
- package/dist/core/export-html/template.js +14 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/session-lifecycle-types.d.ts +14 -0
- package/dist/core/extensions/session-lifecycle-types.d.ts.map +1 -0
- package/dist/core/extensions/session-lifecycle-types.js +2 -0
- package/dist/core/extensions/session-lifecycle-types.js.map +1 -0
- package/dist/core/extensions/types.d.ts +4 -9
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +10 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +3 -6
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/legacy-resource-policy.d.ts +7 -0
- package/dist/core/legacy-resource-policy.d.ts.map +1 -0
- package/dist/core/legacy-resource-policy.js +9 -0
- package/dist/core/legacy-resource-policy.js.map +1 -0
- package/dist/core/mcp/config.d.ts.map +1 -1
- package/dist/core/mcp/config.js +17 -3
- package/dist/core/mcp/config.js.map +1 -1
- package/dist/core/mcp/connection-queue.d.ts +12 -0
- package/dist/core/mcp/connection-queue.d.ts.map +1 -0
- package/dist/core/mcp/connection-queue.js +46 -0
- package/dist/core/mcp/connection-queue.js.map +1 -0
- package/dist/core/mcp/manager-runtime.d.ts +55 -0
- package/dist/core/mcp/manager-runtime.d.ts.map +1 -0
- package/dist/core/mcp/manager-runtime.js +66 -0
- package/dist/core/mcp/manager-runtime.js.map +1 -0
- package/dist/core/mcp/manager.d.ts +12 -68
- package/dist/core/mcp/manager.d.ts.map +1 -1
- package/dist/core/mcp/manager.js +33 -113
- package/dist/core/mcp/manager.js.map +1 -1
- package/dist/core/mcp/protocol.d.ts.map +1 -1
- package/dist/core/mcp/protocol.js +70 -40
- package/dist/core/mcp/protocol.js.map +1 -1
- package/dist/core/package-manager.d.ts +4 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +59 -129
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/package-resource-patterns.d.ts +7 -0
- package/dist/core/package-resource-patterns.d.ts.map +1 -0
- package/dist/core/package-resource-patterns.js +99 -0
- package/dist/core/package-resource-patterns.js.map +1 -0
- package/dist/core/provider-default-models.d.ts +1 -0
- package/dist/core/provider-default-models.d.ts.map +1 -1
- package/dist/core/provider-default-models.js +1 -0
- package/dist/core/provider-default-models.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/provider-resilience.d.ts +9 -0
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +15 -0
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/reasoning-router-resolver.d.ts +7 -0
- package/dist/core/reasoning-router-resolver.d.ts.map +1 -1
- package/dist/core/reasoning-router-resolver.js +21 -3
- package/dist/core/reasoning-router-resolver.js.map +1 -1
- package/dist/core/reasoning-router-v4.d.ts +13 -7
- package/dist/core/reasoning-router-v4.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4.js +8 -5
- package/dist/core/reasoning-router-v4.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +4 -8
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/run-execution-api.d.ts +8 -1
- package/dist/core/run-execution-api.d.ts.map +1 -1
- package/dist/core/run-execution-api.js +4 -0
- package/dist/core/run-execution-api.js.map +1 -1
- package/dist/core/run-journal.d.ts +1 -2
- package/dist/core/run-journal.d.ts.map +1 -1
- package/dist/core/run-journal.js +2 -19
- package/dist/core/run-journal.js.map +1 -1
- package/dist/core/session-compaction-service.d.ts +15 -0
- package/dist/core/session-compaction-service.d.ts.map +1 -1
- package/dist/core/session-compaction-service.js +17 -4
- package/dist/core/session-compaction-service.js.map +1 -1
- package/dist/core/session-listing.d.ts +51 -0
- package/dist/core/session-listing.d.ts.map +1 -0
- package/dist/core/session-listing.js +111 -0
- package/dist/core/session-listing.js.map +1 -0
- package/dist/core/session-manager.d.ts +12 -37
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +12 -118
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-message-text.d.ts +5 -0
- package/dist/core/session-message-text.d.ts.map +1 -0
- package/dist/core/session-message-text.js +9 -0
- package/dist/core/session-message-text.js.map +1 -0
- package/dist/core/skills-catalog-cache.d.ts +2 -0
- package/dist/core/skills-catalog-cache.d.ts.map +1 -1
- package/dist/core/skills-catalog-cache.js +71 -17
- package/dist/core/skills-catalog-cache.js.map +1 -1
- package/dist/core/todo-runtime-state.d.ts +12 -0
- package/dist/core/todo-runtime-state.d.ts.map +1 -1
- package/dist/core/todo-runtime-state.js +23 -0
- package/dist/core/todo-runtime-state.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/verified-run/authority-clock.d.ts +3 -0
- package/dist/core/verified-run/authority-clock.d.ts.map +1 -0
- package/dist/core/verified-run/authority-clock.js +25 -0
- package/dist/core/verified-run/authority-clock.js.map +1 -0
- package/dist/core/verified-run/authority-errors.d.ts +10 -0
- package/dist/core/verified-run/authority-errors.d.ts.map +1 -0
- package/dist/core/verified-run/authority-errors.js +17 -0
- package/dist/core/verified-run/authority-errors.js.map +1 -0
- package/dist/core/verified-run/authority-events.d.ts +126 -0
- package/dist/core/verified-run/authority-events.d.ts.map +1 -0
- package/dist/core/verified-run/authority-events.js +482 -0
- package/dist/core/verified-run/authority-events.js.map +1 -0
- package/dist/core/verified-run/authority-journal.d.ts +27 -0
- package/dist/core/verified-run/authority-journal.d.ts.map +1 -0
- package/dist/core/verified-run/authority-journal.js +83 -0
- package/dist/core/verified-run/authority-journal.js.map +1 -0
- package/dist/core/verified-run/authority-meaning.d.ts +13 -0
- package/dist/core/verified-run/authority-meaning.d.ts.map +1 -0
- package/dist/core/verified-run/authority-meaning.js +40 -0
- package/dist/core/verified-run/authority-meaning.js.map +1 -0
- package/dist/core/verified-run/authority-runtime.d.ts +82 -0
- package/dist/core/verified-run/authority-runtime.d.ts.map +1 -0
- package/dist/core/verified-run/authority-runtime.js +169 -0
- package/dist/core/verified-run/authority-runtime.js.map +1 -0
- package/dist/core/verified-run/authority-store.d.ts +204 -0
- package/dist/core/verified-run/authority-store.d.ts.map +1 -0
- package/dist/core/verified-run/authority-store.js +852 -0
- package/dist/core/verified-run/authority-store.js.map +1 -0
- package/dist/core/verified-run/broker.d.ts +8 -1
- package/dist/core/verified-run/broker.d.ts.map +1 -1
- package/dist/core/verified-run/broker.js +94 -90
- package/dist/core/verified-run/broker.js.map +1 -1
- package/dist/core/verified-run/candidate-policy.d.ts +10 -0
- package/dist/core/verified-run/candidate-policy.d.ts.map +1 -0
- package/dist/core/verified-run/candidate-policy.js +33 -0
- package/dist/core/verified-run/candidate-policy.js.map +1 -0
- package/dist/core/verified-run/candidate.d.ts.map +1 -1
- package/dist/core/verified-run/candidate.js +5 -10
- package/dist/core/verified-run/candidate.js.map +1 -1
- package/dist/core/verified-run/coordinator.d.ts +35 -17
- package/dist/core/verified-run/coordinator.d.ts.map +1 -1
- package/dist/core/verified-run/coordinator.js +111 -57
- package/dist/core/verified-run/coordinator.js.map +1 -1
- package/dist/core/verified-run/dag-phase.d.ts.map +1 -1
- package/dist/core/verified-run/dag-phase.js +1 -1
- package/dist/core/verified-run/dag-phase.js.map +1 -1
- package/dist/core/verified-run/dag-recovery.d.ts +5 -1
- package/dist/core/verified-run/dag-recovery.d.ts.map +1 -1
- package/dist/core/verified-run/dag-recovery.js +10 -4
- package/dist/core/verified-run/dag-recovery.js.map +1 -1
- package/dist/core/verified-run/event-parser.d.ts.map +1 -1
- package/dist/core/verified-run/event-parser.js +33 -0
- package/dist/core/verified-run/event-parser.js.map +1 -1
- package/dist/core/verified-run/evidence-read-projection.d.ts +4 -0
- package/dist/core/verified-run/evidence-read-projection.d.ts.map +1 -0
- package/dist/core/verified-run/evidence-read-projection.js +27 -0
- package/dist/core/verified-run/evidence-read-projection.js.map +1 -0
- package/dist/core/verified-run/evidence.d.ts +12 -1
- package/dist/core/verified-run/evidence.d.ts.map +1 -1
- package/dist/core/verified-run/evidence.js +51 -2
- package/dist/core/verified-run/evidence.js.map +1 -1
- package/dist/core/verified-run/git-candidate-preflight.d.ts +4 -0
- package/dist/core/verified-run/git-candidate-preflight.d.ts.map +1 -0
- package/dist/core/verified-run/git-candidate-preflight.js +34 -0
- package/dist/core/verified-run/git-candidate-preflight.js.map +1 -0
- package/dist/core/verified-run/git-effect-supervisor.d.ts +24 -0
- package/dist/core/verified-run/git-effect-supervisor.d.ts.map +1 -0
- package/dist/core/verified-run/git-effect-supervisor.js +174 -0
- package/dist/core/verified-run/git-effect-supervisor.js.map +1 -0
- package/dist/core/verified-run/git-execution.d.ts +27 -0
- package/dist/core/verified-run/git-execution.d.ts.map +1 -0
- package/dist/core/verified-run/git-execution.js +118 -0
- package/dist/core/verified-run/git-execution.js.map +1 -0
- package/dist/core/verified-run/git-plumbing.d.ts +37 -0
- package/dist/core/verified-run/git-plumbing.d.ts.map +1 -0
- package/dist/core/verified-run/git-plumbing.js +171 -0
- package/dist/core/verified-run/git-plumbing.js.map +1 -0
- package/dist/core/verified-run/git-publication-worker.d.ts +2 -0
- package/dist/core/verified-run/git-publication-worker.d.ts.map +1 -0
- package/dist/core/verified-run/git-publication-worker.js +54 -0
- package/dist/core/verified-run/git-publication-worker.js.map +1 -0
- package/dist/core/verified-run/git-sandbox-layout.d.ts +4 -0
- package/dist/core/verified-run/git-sandbox-layout.d.ts.map +1 -0
- package/dist/core/verified-run/git-sandbox-layout.js +29 -0
- package/dist/core/verified-run/git-sandbox-layout.js.map +1 -0
- package/dist/core/verified-run/git-worker-protocol.d.ts +19 -0
- package/dist/core/verified-run/git-worker-protocol.d.ts.map +1 -0
- package/dist/core/verified-run/git-worker-protocol.js +109 -0
- package/dist/core/verified-run/git-worker-protocol.js.map +1 -0
- package/dist/core/verified-run/git-worker-runtime.d.ts +19 -0
- package/dist/core/verified-run/git-worker-runtime.d.ts.map +1 -0
- package/dist/core/verified-run/git-worker-runtime.js +74 -0
- package/dist/core/verified-run/git-worker-runtime.js.map +1 -0
- package/dist/core/verified-run/journal.d.ts +2 -3
- package/dist/core/verified-run/journal.d.ts.map +1 -1
- package/dist/core/verified-run/journal.js.map +1 -1
- package/dist/core/verified-run/namespace-identity.d.ts.map +1 -1
- package/dist/core/verified-run/namespace-identity.js +1 -1
- package/dist/core/verified-run/namespace-identity.js.map +1 -1
- package/dist/core/verified-run/owned-execution.d.ts +10 -1
- package/dist/core/verified-run/owned-execution.d.ts.map +1 -1
- package/dist/core/verified-run/owned-execution.js +124 -31
- package/dist/core/verified-run/owned-execution.js.map +1 -1
- package/dist/core/verified-run/phase-context.d.ts +2 -0
- package/dist/core/verified-run/phase-context.d.ts.map +1 -1
- package/dist/core/verified-run/phase-context.js.map +1 -1
- package/dist/core/verified-run/projection.d.ts.map +1 -1
- package/dist/core/verified-run/projection.js +51 -1
- package/dist/core/verified-run/projection.js.map +1 -1
- package/dist/core/verified-run/publish-preflight.d.ts +12 -0
- package/dist/core/verified-run/publish-preflight.d.ts.map +1 -0
- package/dist/core/verified-run/publish-preflight.js +38 -0
- package/dist/core/verified-run/publish-preflight.js.map +1 -0
- package/dist/core/verified-run/publish-start.d.ts +5 -0
- package/dist/core/verified-run/publish-start.d.ts.map +1 -0
- package/dist/core/verified-run/publish-start.js +7 -0
- package/dist/core/verified-run/publish-start.js.map +1 -0
- package/dist/core/verified-run/recovery-projection.d.ts.map +1 -1
- package/dist/core/verified-run/recovery-projection.js +5 -0
- package/dist/core/verified-run/recovery-projection.js.map +1 -1
- package/dist/core/verified-run/recovery.d.ts +5 -1
- package/dist/core/verified-run/recovery.d.ts.map +1 -1
- package/dist/core/verified-run/recovery.js +10 -4
- package/dist/core/verified-run/recovery.js.map +1 -1
- package/dist/core/verified-run/run-plan.d.ts +17 -0
- package/dist/core/verified-run/run-plan.d.ts.map +1 -0
- package/dist/core/verified-run/run-plan.js +18 -0
- package/dist/core/verified-run/run-plan.js.map +1 -0
- package/dist/core/verified-run/run-publish-owned.d.ts +6 -0
- package/dist/core/verified-run/run-publish-owned.d.ts.map +1 -0
- package/dist/core/verified-run/run-publish-owned.js +199 -0
- package/dist/core/verified-run/run-publish-owned.js.map +1 -0
- package/dist/core/verified-run/run-publish.d.ts +19 -0
- package/dist/core/verified-run/run-publish.d.ts.map +1 -0
- package/dist/core/verified-run/run-publish.js +210 -0
- package/dist/core/verified-run/run-publish.js.map +1 -0
- package/dist/core/verified-run/run-status-owned.d.ts +4 -0
- package/dist/core/verified-run/run-status-owned.d.ts.map +1 -0
- package/dist/core/verified-run/run-status-owned.js +14 -0
- package/dist/core/verified-run/run-status-owned.js.map +1 -0
- package/dist/core/verified-run/run-status.d.ts +133 -0
- package/dist/core/verified-run/run-status.d.ts.map +1 -0
- package/dist/core/verified-run/run-status.js +193 -0
- package/dist/core/verified-run/run-status.js.map +1 -0
- package/dist/core/verified-run/run-types.d.ts +31 -0
- package/dist/core/verified-run/run-types.d.ts.map +1 -1
- package/dist/core/verified-run/run-types.js.map +1 -1
- package/dist/core/verified-run/storage.d.ts.map +1 -1
- package/dist/core/verified-run/storage.js +1 -1
- package/dist/core/verified-run/storage.js.map +1 -1
- package/dist/core/verified-run/supervisor-adapter.d.ts +77 -0
- package/dist/core/verified-run/supervisor-adapter.d.ts.map +1 -0
- package/dist/core/verified-run/supervisor-adapter.js +164 -0
- package/dist/core/verified-run/supervisor-adapter.js.map +1 -0
- package/dist/core/verified-run/verification-phase.d.ts.map +1 -1
- package/dist/core/verified-run/verification-phase.js +1 -1
- package/dist/core/verified-run/verification-phase.js.map +1 -1
- package/dist/core/verified-run/writer-phase.d.ts.map +1 -1
- package/dist/core/verified-run/writer-phase.js +1 -0
- package/dist/core/verified-run/writer-phase.js.map +1 -1
- package/dist/core/verified-run/writer-recovery.d.ts +2 -0
- package/dist/core/verified-run/writer-recovery.d.ts.map +1 -1
- package/dist/core/verified-run/writer-recovery.js +1 -0
- package/dist/core/verified-run/writer-recovery.js.map +1 -1
- package/dist/core/workload-shard-execution-types.d.ts +4 -1
- package/dist/core/workload-shard-execution-types.d.ts.map +1 -1
- package/dist/core/workload-shard-execution-types.js.map +1 -1
- package/dist/core/workload-shard-executor.d.ts +2 -2
- package/dist/core/workload-shard-executor.d.ts.map +1 -1
- package/dist/core/workload-shard-executor.js +16 -37
- package/dist/core/workload-shard-executor.js.map +1 -1
- package/dist/core/workload-shard-frontier.d.ts +5 -0
- package/dist/core/workload-shard-frontier.d.ts.map +1 -0
- package/dist/core/workload-shard-frontier.js +47 -0
- package/dist/core/workload-shard-frontier.js.map +1 -0
- package/dist/core/workload-shard-runner.d.ts.map +1 -1
- package/dist/core/workload-shard-runner.js +28 -17
- package/dist/core/workload-shard-runner.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -1
- package/dist/main.js.map +1 -1
- package/dist/metacognition/bridge-result.d.ts +148 -0
- package/dist/metacognition/bridge-result.d.ts.map +1 -0
- package/dist/metacognition/bridge-result.js +46 -0
- package/dist/metacognition/bridge-result.js.map +1 -0
- package/dist/metacognition/calibration-selective.d.ts +78 -0
- package/dist/metacognition/calibration-selective.d.ts.map +1 -0
- package/dist/metacognition/calibration-selective.js +167 -0
- package/dist/metacognition/calibration-selective.js.map +1 -0
- package/dist/metacognition/calibration.d.ts +62 -0
- package/dist/metacognition/calibration.d.ts.map +1 -0
- package/dist/metacognition/calibration.js +122 -0
- package/dist/metacognition/calibration.js.map +1 -0
- package/dist/metacognition/checkpoint.d.ts +60 -0
- package/dist/metacognition/checkpoint.d.ts.map +1 -0
- package/dist/metacognition/checkpoint.js +57 -0
- package/dist/metacognition/checkpoint.js.map +1 -0
- package/dist/metacognition/context7.d.ts +48 -0
- package/dist/metacognition/context7.d.ts.map +1 -0
- package/dist/metacognition/context7.js +154 -0
- package/dist/metacognition/context7.js.map +1 -0
- package/dist/metacognition/decision.d.ts +44 -0
- package/dist/metacognition/decision.d.ts.map +1 -0
- package/dist/metacognition/decision.js +111 -0
- package/dist/metacognition/decision.js.map +1 -0
- package/dist/metacognition/evaluation.d.ts +73 -0
- package/dist/metacognition/evaluation.d.ts.map +1 -0
- package/dist/metacognition/evaluation.js +97 -0
- package/dist/metacognition/evaluation.js.map +1 -0
- package/dist/metacognition/index.d.ts +32 -0
- package/dist/metacognition/index.d.ts.map +1 -0
- package/dist/metacognition/index.js +32 -0
- package/dist/metacognition/index.js.map +1 -0
- package/dist/metacognition/knowledge-action.d.ts +43 -0
- package/dist/metacognition/knowledge-action.d.ts.map +1 -0
- package/dist/metacognition/knowledge-action.js +60 -0
- package/dist/metacognition/knowledge-action.js.map +1 -0
- package/dist/metacognition/knowledge.d.ts +84 -0
- package/dist/metacognition/knowledge.d.ts.map +1 -0
- package/dist/metacognition/knowledge.js +165 -0
- package/dist/metacognition/knowledge.js.map +1 -0
- package/dist/metacognition/obligations.d.ts +82 -0
- package/dist/metacognition/obligations.d.ts.map +1 -0
- package/dist/metacognition/obligations.js +139 -0
- package/dist/metacognition/obligations.js.map +1 -0
- package/dist/metacognition/observation-validity.d.ts +83 -0
- package/dist/metacognition/observation-validity.d.ts.map +1 -0
- package/dist/metacognition/observation-validity.js +118 -0
- package/dist/metacognition/observation-validity.js.map +1 -0
- package/dist/metacognition/observe.d.ts +45 -0
- package/dist/metacognition/observe.d.ts.map +1 -0
- package/dist/metacognition/observe.js +59 -0
- package/dist/metacognition/observe.js.map +1 -0
- package/dist/metacognition/policy.d.ts +53 -0
- package/dist/metacognition/policy.d.ts.map +1 -0
- package/dist/metacognition/policy.js +155 -0
- package/dist/metacognition/policy.js.map +1 -0
- package/dist/metacognition/predictions.d.ts +78 -0
- package/dist/metacognition/predictions.d.ts.map +1 -0
- package/dist/metacognition/predictions.js +181 -0
- package/dist/metacognition/predictions.js.map +1 -0
- package/dist/metacognition/retrieval.d.ts +53 -0
- package/dist/metacognition/retrieval.d.ts.map +1 -0
- package/dist/metacognition/retrieval.js +170 -0
- package/dist/metacognition/retrieval.js.map +1 -0
- package/dist/metacognition/risk.d.ts +48 -0
- package/dist/metacognition/risk.d.ts.map +1 -0
- package/dist/metacognition/risk.js +179 -0
- package/dist/metacognition/risk.js.map +1 -0
- package/dist/metacognition/route-economics.d.ts +95 -0
- package/dist/metacognition/route-economics.d.ts.map +1 -0
- package/dist/metacognition/route-economics.js +110 -0
- package/dist/metacognition/route-economics.js.map +1 -0
- package/dist/metacognition/runtime-bridge.d.ts +81 -0
- package/dist/metacognition/runtime-bridge.d.ts.map +1 -0
- package/dist/metacognition/runtime-bridge.js +458 -0
- package/dist/metacognition/runtime-bridge.js.map +1 -0
- package/dist/metacognition/skills.d.ts +42 -0
- package/dist/metacognition/skills.d.ts.map +1 -0
- package/dist/metacognition/skills.js +220 -0
- package/dist/metacognition/skills.js.map +1 -0
- package/dist/metacognition/state.d.ts +110 -0
- package/dist/metacognition/state.d.ts.map +1 -0
- package/dist/metacognition/state.js +52 -0
- package/dist/metacognition/state.js.map +1 -0
- package/dist/metacognition/validation.d.ts +19 -0
- package/dist/metacognition/validation.d.ts.map +1 -0
- package/dist/metacognition/validation.js +58 -0
- package/dist/metacognition/validation.js.map +1 -0
- package/dist/metacognition/verification.d.ts +93 -0
- package/dist/metacognition/verification.d.ts.map +1 -0
- package/dist/metacognition/verification.js +132 -0
- package/dist/metacognition/verification.js.map +1 -0
- package/dist/metacognition/verifier.d.ts +49 -0
- package/dist/metacognition/verifier.d.ts.map +1 -0
- package/dist/metacognition/verifier.js +88 -0
- package/dist/metacognition/verifier.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +2 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +42 -26
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/chat-container.d.ts +7 -0
- package/dist/modes/interactive/components/chat-container.d.ts.map +1 -0
- package/dist/modes/interactive/components/chat-container.js +14 -0
- package/dist/modes/interactive/components/chat-container.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +4 -2
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +0 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-async-search.d.ts +33 -0
- package/dist/modes/interactive/components/session-selector-async-search.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-async-search.js +109 -0
- package/dist/modes/interactive/components/session-selector-async-search.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-loaders.d.ts +6 -0
- package/dist/modes/interactive/components/session-selector-loaders.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-loaders.js +9 -0
- package/dist/modes/interactive/components/session-selector-loaders.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-tree.d.ts +16 -0
- package/dist/modes/interactive/components/session-selector-tree.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-tree.js +46 -0
- package/dist/modes/interactive/components/session-selector-tree.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +6 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +36 -76
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution-images.d.ts +32 -0
- package/dist/modes/interactive/components/tool-execution-images.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution-images.js +144 -0
- package/dist/modes/interactive/components/tool-execution-images.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -4
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +22 -71
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -9
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tui-diagnostics.d.ts +8 -4
- package/dist/modes/interactive/tui-diagnostics.d.ts.map +1 -1
- package/dist/modes/interactive/tui-diagnostics.js +35 -1
- package/dist/modes/interactive/tui-diagnostics.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +14 -17
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-response.d.ts +5 -0
- package/dist/modes/rpc/rpc-response.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-response.js +17 -0
- package/dist/modes/rpc/rpc-response.js.map +1 -0
- package/dist/observation/identity.d.ts +14 -0
- package/dist/observation/identity.d.ts.map +1 -0
- package/dist/observation/identity.js +29 -0
- package/dist/observation/identity.js.map +1 -0
- package/dist/observation/index.d.ts +13 -0
- package/dist/observation/index.d.ts.map +1 -0
- package/dist/observation/index.js +13 -0
- package/dist/observation/index.js.map +1 -0
- package/dist/observation/observe-mode.d.ts +46 -0
- package/dist/observation/observe-mode.d.ts.map +1 -0
- package/dist/observation/observe-mode.js +83 -0
- package/dist/observation/observe-mode.js.map +1 -0
- package/dist/observation/store.d.ts +53 -0
- package/dist/observation/store.d.ts.map +1 -0
- package/dist/observation/store.js +126 -0
- package/dist/observation/store.js.map +1 -0
- package/dist/observation/types.d.ts +72 -0
- package/dist/observation/types.d.ts.map +1 -0
- package/dist/observation/types.js +9 -0
- package/dist/observation/types.js.map +1 -0
- package/dist/observation/view.d.ts +39 -0
- package/dist/observation/view.d.ts.map +1 -0
- package/dist/observation/view.js +173 -0
- package/dist/observation/view.js.map +1 -0
- 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.map +1 -1
- package/dist/utils/tools-manager.js +3 -5
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/adaptorch-preview-spec.md +7 -7
- package/docs/atomic-commit-planning.md +69 -0
- package/docs/compaction.md +26 -1
- package/docs/extensions.md +14 -0
- package/docs/mcp.md +22 -0
- package/docs/metacognition.md +130 -0
- package/docs/model-catalog-refresh.md +218 -1
- package/docs/models.md +1 -1
- package/docs/providers.md +53 -0
- package/docs/runtime-algorithms.md +156 -7
- package/docs/session-format.md +8 -0
- package/docs/sessions.md +19 -0
- package/docs/skills.md +19 -0
- package/docs/terminal-setup.md +15 -0
- package/docs/tui.md +41 -0
- package/docs/verified-run-safety.md +75 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +18 -18
- package/package.json +6 -8
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function matchesAnyPattern(filePath: string, patterns: string[], baseDir: string): boolean;
|
|
2
|
+
export declare function matchesAnyExactPattern(filePath: string, patterns: string[], baseDir: string): boolean;
|
|
3
|
+
export declare function getOverridePatterns(entries: string[]): string[];
|
|
4
|
+
export declare function isEnabledByOverrides(filePath: string, patterns: string[], baseDir: string): boolean;
|
|
5
|
+
/** Plain includes, then exclusions, forced exact includes and forced exact exclusions. */
|
|
6
|
+
export declare function applyPatterns(allPaths: string[], patterns: string[], baseDir: string): Set<string>;
|
|
7
|
+
//# sourceMappingURL=package-resource-patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-resource-patterns.d.ts","sourceRoot":"","sources":["../../src/core/package-resource-patterns.ts"],"names":[],"mappings":"AAOA,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAwBhG;AAOD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAerG;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAE/D;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAUnG;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAyBlG","sourcesContent":["import { basename, dirname, relative, sep } from \"node:path\";\nimport { minimatch } from \"minimatch\";\n\nfunction toPosixPath(path: string): string {\n\treturn path.split(sep).join(\"/\");\n}\n\nexport function matchesAnyPattern(filePath: string, patterns: string[], baseDir: string): boolean {\n\tconst rel = toPosixPath(relative(baseDir, filePath));\n\tconst name = basename(filePath);\n\tconst filePathPosix = toPosixPath(filePath);\n\tconst isSkillFile = name === \"SKILL.md\";\n\tconst parentDir = isSkillFile ? dirname(filePath) : undefined;\n\tconst parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir!)) : undefined;\n\tconst parentName = isSkillFile ? basename(parentDir!) : undefined;\n\tconst parentDirPosix = isSkillFile ? toPosixPath(parentDir!) : undefined;\n\treturn patterns.some((pattern) => {\n\t\tconst normalizedPattern = toPosixPath(pattern);\n\t\tif (\n\t\t\tminimatch(rel, normalizedPattern) ||\n\t\t\tminimatch(name, normalizedPattern) ||\n\t\t\tminimatch(filePathPosix, normalizedPattern)\n\t\t)\n\t\t\treturn true;\n\t\tif (!isSkillFile) return false;\n\t\treturn (\n\t\t\tminimatch(parentRel!, normalizedPattern) ||\n\t\t\tminimatch(parentName!, normalizedPattern) ||\n\t\t\tminimatch(parentDirPosix!, normalizedPattern)\n\t\t);\n\t});\n}\n\nfunction normalizeExactPattern(pattern: string): string {\n\tconst normalized = pattern.startsWith(\"./\") || pattern.startsWith(\".\\\\\") ? pattern.slice(2) : pattern;\n\treturn toPosixPath(normalized);\n}\n\nexport function matchesAnyExactPattern(filePath: string, patterns: string[], baseDir: string): boolean {\n\tif (patterns.length === 0) return false;\n\tconst rel = toPosixPath(relative(baseDir, filePath));\n\tconst name = basename(filePath);\n\tconst filePathPosix = toPosixPath(filePath);\n\tconst isSkillFile = name === \"SKILL.md\";\n\tconst parentDir = isSkillFile ? dirname(filePath) : undefined;\n\tconst parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir!)) : undefined;\n\tconst parentDirPosix = isSkillFile ? toPosixPath(parentDir!) : undefined;\n\treturn patterns.some((pattern) => {\n\t\tconst normalized = normalizeExactPattern(pattern);\n\t\tif (normalized === rel || normalized === filePathPosix) return true;\n\t\tif (!isSkillFile) return false;\n\t\treturn normalized === parentRel || normalized === parentDirPosix;\n\t});\n}\n\nexport function getOverridePatterns(entries: string[]): string[] {\n\treturn entries.filter((pattern) => pattern.startsWith(\"!\") || pattern.startsWith(\"+\") || pattern.startsWith(\"-\"));\n}\n\nexport function isEnabledByOverrides(filePath: string, patterns: string[], baseDir: string): boolean {\n\tconst overrides = getOverridePatterns(patterns);\n\tconst excludes = overrides.filter((pattern) => pattern.startsWith(\"!\")).map((pattern) => pattern.slice(1));\n\tconst forceIncludes = overrides.filter((pattern) => pattern.startsWith(\"+\")).map((pattern) => pattern.slice(1));\n\tconst forceExcludes = overrides.filter((pattern) => pattern.startsWith(\"-\")).map((pattern) => pattern.slice(1));\n\tlet enabled = true;\n\tif (excludes.length > 0 && matchesAnyPattern(filePath, excludes, baseDir)) enabled = false;\n\tif (forceIncludes.length > 0 && matchesAnyExactPattern(filePath, forceIncludes, baseDir)) enabled = true;\n\tif (forceExcludes.length > 0 && matchesAnyExactPattern(filePath, forceExcludes, baseDir)) enabled = false;\n\treturn enabled;\n}\n\n/** Plain includes, then exclusions, forced exact includes and forced exact exclusions. */\nexport function applyPatterns(allPaths: string[], patterns: string[], baseDir: string): Set<string> {\n\tconst includes: string[] = [];\n\tconst excludes: string[] = [];\n\tconst forceIncludes: string[] = [];\n\tconst forceExcludes: string[] = [];\n\tfor (const p of patterns) {\n\t\tif (p.startsWith(\"+\")) forceIncludes.push(p.slice(1));\n\t\telse if (p.startsWith(\"-\")) forceExcludes.push(p.slice(1));\n\t\telse if (p.startsWith(\"!\")) excludes.push(p.slice(1));\n\t\telse includes.push(p);\n\t}\n\tlet result =\n\t\tincludes.length === 0\n\t\t\t? [...allPaths]\n\t\t\t: allPaths.filter((filePath) => matchesAnyPattern(filePath, includes, baseDir));\n\tif (excludes.length > 0) result = result.filter((filePath) => !matchesAnyPattern(filePath, excludes, baseDir));\n\tif (forceIncludes.length > 0) {\n\t\tfor (const filePath of allPaths) {\n\t\t\tif (!result.includes(filePath) && matchesAnyExactPattern(filePath, forceIncludes, baseDir))\n\t\t\t\tresult.push(filePath);\n\t\t}\n\t}\n\tif (forceExcludes.length > 0)\n\t\tresult = result.filter((filePath) => !matchesAnyExactPattern(filePath, forceExcludes, baseDir));\n\treturn new Set(result);\n}\n"]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { basename, dirname, relative, sep } from "node:path";
|
|
2
|
+
import { minimatch } from "minimatch";
|
|
3
|
+
function toPosixPath(path) {
|
|
4
|
+
return path.split(sep).join("/");
|
|
5
|
+
}
|
|
6
|
+
export function matchesAnyPattern(filePath, patterns, baseDir) {
|
|
7
|
+
const rel = toPosixPath(relative(baseDir, filePath));
|
|
8
|
+
const name = basename(filePath);
|
|
9
|
+
const filePathPosix = toPosixPath(filePath);
|
|
10
|
+
const isSkillFile = name === "SKILL.md";
|
|
11
|
+
const parentDir = isSkillFile ? dirname(filePath) : undefined;
|
|
12
|
+
const parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir)) : undefined;
|
|
13
|
+
const parentName = isSkillFile ? basename(parentDir) : undefined;
|
|
14
|
+
const parentDirPosix = isSkillFile ? toPosixPath(parentDir) : undefined;
|
|
15
|
+
return patterns.some((pattern) => {
|
|
16
|
+
const normalizedPattern = toPosixPath(pattern);
|
|
17
|
+
if (minimatch(rel, normalizedPattern) ||
|
|
18
|
+
minimatch(name, normalizedPattern) ||
|
|
19
|
+
minimatch(filePathPosix, normalizedPattern))
|
|
20
|
+
return true;
|
|
21
|
+
if (!isSkillFile)
|
|
22
|
+
return false;
|
|
23
|
+
return (minimatch(parentRel, normalizedPattern) ||
|
|
24
|
+
minimatch(parentName, normalizedPattern) ||
|
|
25
|
+
minimatch(parentDirPosix, normalizedPattern));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function normalizeExactPattern(pattern) {
|
|
29
|
+
const normalized = pattern.startsWith("./") || pattern.startsWith(".\\") ? pattern.slice(2) : pattern;
|
|
30
|
+
return toPosixPath(normalized);
|
|
31
|
+
}
|
|
32
|
+
export function matchesAnyExactPattern(filePath, patterns, baseDir) {
|
|
33
|
+
if (patterns.length === 0)
|
|
34
|
+
return false;
|
|
35
|
+
const rel = toPosixPath(relative(baseDir, filePath));
|
|
36
|
+
const name = basename(filePath);
|
|
37
|
+
const filePathPosix = toPosixPath(filePath);
|
|
38
|
+
const isSkillFile = name === "SKILL.md";
|
|
39
|
+
const parentDir = isSkillFile ? dirname(filePath) : undefined;
|
|
40
|
+
const parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir)) : undefined;
|
|
41
|
+
const parentDirPosix = isSkillFile ? toPosixPath(parentDir) : undefined;
|
|
42
|
+
return patterns.some((pattern) => {
|
|
43
|
+
const normalized = normalizeExactPattern(pattern);
|
|
44
|
+
if (normalized === rel || normalized === filePathPosix)
|
|
45
|
+
return true;
|
|
46
|
+
if (!isSkillFile)
|
|
47
|
+
return false;
|
|
48
|
+
return normalized === parentRel || normalized === parentDirPosix;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
export function getOverridePatterns(entries) {
|
|
52
|
+
return entries.filter((pattern) => pattern.startsWith("!") || pattern.startsWith("+") || pattern.startsWith("-"));
|
|
53
|
+
}
|
|
54
|
+
export function isEnabledByOverrides(filePath, patterns, baseDir) {
|
|
55
|
+
const overrides = getOverridePatterns(patterns);
|
|
56
|
+
const excludes = overrides.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
|
|
57
|
+
const forceIncludes = overrides.filter((pattern) => pattern.startsWith("+")).map((pattern) => pattern.slice(1));
|
|
58
|
+
const forceExcludes = overrides.filter((pattern) => pattern.startsWith("-")).map((pattern) => pattern.slice(1));
|
|
59
|
+
let enabled = true;
|
|
60
|
+
if (excludes.length > 0 && matchesAnyPattern(filePath, excludes, baseDir))
|
|
61
|
+
enabled = false;
|
|
62
|
+
if (forceIncludes.length > 0 && matchesAnyExactPattern(filePath, forceIncludes, baseDir))
|
|
63
|
+
enabled = true;
|
|
64
|
+
if (forceExcludes.length > 0 && matchesAnyExactPattern(filePath, forceExcludes, baseDir))
|
|
65
|
+
enabled = false;
|
|
66
|
+
return enabled;
|
|
67
|
+
}
|
|
68
|
+
/** Plain includes, then exclusions, forced exact includes and forced exact exclusions. */
|
|
69
|
+
export function applyPatterns(allPaths, patterns, baseDir) {
|
|
70
|
+
const includes = [];
|
|
71
|
+
const excludes = [];
|
|
72
|
+
const forceIncludes = [];
|
|
73
|
+
const forceExcludes = [];
|
|
74
|
+
for (const p of patterns) {
|
|
75
|
+
if (p.startsWith("+"))
|
|
76
|
+
forceIncludes.push(p.slice(1));
|
|
77
|
+
else if (p.startsWith("-"))
|
|
78
|
+
forceExcludes.push(p.slice(1));
|
|
79
|
+
else if (p.startsWith("!"))
|
|
80
|
+
excludes.push(p.slice(1));
|
|
81
|
+
else
|
|
82
|
+
includes.push(p);
|
|
83
|
+
}
|
|
84
|
+
let result = includes.length === 0
|
|
85
|
+
? [...allPaths]
|
|
86
|
+
: allPaths.filter((filePath) => matchesAnyPattern(filePath, includes, baseDir));
|
|
87
|
+
if (excludes.length > 0)
|
|
88
|
+
result = result.filter((filePath) => !matchesAnyPattern(filePath, excludes, baseDir));
|
|
89
|
+
if (forceIncludes.length > 0) {
|
|
90
|
+
for (const filePath of allPaths) {
|
|
91
|
+
if (!result.includes(filePath) && matchesAnyExactPattern(filePath, forceIncludes, baseDir))
|
|
92
|
+
result.push(filePath);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (forceExcludes.length > 0)
|
|
96
|
+
result = result.filter((filePath) => !matchesAnyExactPattern(filePath, forceExcludes, baseDir));
|
|
97
|
+
return new Set(result);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=package-resource-patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-resource-patterns.js","sourceRoot":"","sources":["../../src/core/package-resource-patterns.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename, dirname, relative, sep } from \"node:path\";\nimport { minimatch } from \"minimatch\";\n\nfunction toPosixPath(path: string): string {\n\treturn path.split(sep).join(\"/\");\n}\n\nexport function matchesAnyPattern(filePath: string, patterns: string[], baseDir: string): boolean {\n\tconst rel = toPosixPath(relative(baseDir, filePath));\n\tconst name = basename(filePath);\n\tconst filePathPosix = toPosixPath(filePath);\n\tconst isSkillFile = name === \"SKILL.md\";\n\tconst parentDir = isSkillFile ? dirname(filePath) : undefined;\n\tconst parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir!)) : undefined;\n\tconst parentName = isSkillFile ? basename(parentDir!) : undefined;\n\tconst parentDirPosix = isSkillFile ? toPosixPath(parentDir!) : undefined;\n\treturn patterns.some((pattern) => {\n\t\tconst normalizedPattern = toPosixPath(pattern);\n\t\tif (\n\t\t\tminimatch(rel, normalizedPattern) ||\n\t\t\tminimatch(name, normalizedPattern) ||\n\t\t\tminimatch(filePathPosix, normalizedPattern)\n\t\t)\n\t\t\treturn true;\n\t\tif (!isSkillFile) return false;\n\t\treturn (\n\t\t\tminimatch(parentRel!, normalizedPattern) ||\n\t\t\tminimatch(parentName!, normalizedPattern) ||\n\t\t\tminimatch(parentDirPosix!, normalizedPattern)\n\t\t);\n\t});\n}\n\nfunction normalizeExactPattern(pattern: string): string {\n\tconst normalized = pattern.startsWith(\"./\") || pattern.startsWith(\".\\\\\") ? pattern.slice(2) : pattern;\n\treturn toPosixPath(normalized);\n}\n\nexport function matchesAnyExactPattern(filePath: string, patterns: string[], baseDir: string): boolean {\n\tif (patterns.length === 0) return false;\n\tconst rel = toPosixPath(relative(baseDir, filePath));\n\tconst name = basename(filePath);\n\tconst filePathPosix = toPosixPath(filePath);\n\tconst isSkillFile = name === \"SKILL.md\";\n\tconst parentDir = isSkillFile ? dirname(filePath) : undefined;\n\tconst parentRel = isSkillFile ? toPosixPath(relative(baseDir, parentDir!)) : undefined;\n\tconst parentDirPosix = isSkillFile ? toPosixPath(parentDir!) : undefined;\n\treturn patterns.some((pattern) => {\n\t\tconst normalized = normalizeExactPattern(pattern);\n\t\tif (normalized === rel || normalized === filePathPosix) return true;\n\t\tif (!isSkillFile) return false;\n\t\treturn normalized === parentRel || normalized === parentDirPosix;\n\t});\n}\n\nexport function getOverridePatterns(entries: string[]): string[] {\n\treturn entries.filter((pattern) => pattern.startsWith(\"!\") || pattern.startsWith(\"+\") || pattern.startsWith(\"-\"));\n}\n\nexport function isEnabledByOverrides(filePath: string, patterns: string[], baseDir: string): boolean {\n\tconst overrides = getOverridePatterns(patterns);\n\tconst excludes = overrides.filter((pattern) => pattern.startsWith(\"!\")).map((pattern) => pattern.slice(1));\n\tconst forceIncludes = overrides.filter((pattern) => pattern.startsWith(\"+\")).map((pattern) => pattern.slice(1));\n\tconst forceExcludes = overrides.filter((pattern) => pattern.startsWith(\"-\")).map((pattern) => pattern.slice(1));\n\tlet enabled = true;\n\tif (excludes.length > 0 && matchesAnyPattern(filePath, excludes, baseDir)) enabled = false;\n\tif (forceIncludes.length > 0 && matchesAnyExactPattern(filePath, forceIncludes, baseDir)) enabled = true;\n\tif (forceExcludes.length > 0 && matchesAnyExactPattern(filePath, forceExcludes, baseDir)) enabled = false;\n\treturn enabled;\n}\n\n/** Plain includes, then exclusions, forced exact includes and forced exact exclusions. */\nexport function applyPatterns(allPaths: string[], patterns: string[], baseDir: string): Set<string> {\n\tconst includes: string[] = [];\n\tconst excludes: string[] = [];\n\tconst forceIncludes: string[] = [];\n\tconst forceExcludes: string[] = [];\n\tfor (const p of patterns) {\n\t\tif (p.startsWith(\"+\")) forceIncludes.push(p.slice(1));\n\t\telse if (p.startsWith(\"-\")) forceExcludes.push(p.slice(1));\n\t\telse if (p.startsWith(\"!\")) excludes.push(p.slice(1));\n\t\telse includes.push(p);\n\t}\n\tlet result =\n\t\tincludes.length === 0\n\t\t\t? [...allPaths]\n\t\t\t: allPaths.filter((filePath) => matchesAnyPattern(filePath, includes, baseDir));\n\tif (excludes.length > 0) result = result.filter((filePath) => !matchesAnyPattern(filePath, excludes, baseDir));\n\tif (forceIncludes.length > 0) {\n\t\tfor (const filePath of allPaths) {\n\t\t\tif (!result.includes(filePath) && matchesAnyExactPattern(filePath, forceIncludes, baseDir))\n\t\t\t\tresult.push(filePath);\n\t\t}\n\t}\n\tif (forceExcludes.length > 0)\n\t\tresult = result.filter((filePath) => !matchesAnyExactPattern(filePath, forceExcludes, baseDir));\n\treturn new Set(result);\n}\n"]}
|
|
@@ -38,6 +38,7 @@ export declare const defaultModelPerProvider: {
|
|
|
38
38
|
readonly "xiaomi-token-plan-sgp": string;
|
|
39
39
|
readonly zyloo: string;
|
|
40
40
|
readonly cursor: string;
|
|
41
|
+
readonly workbuddy: string;
|
|
41
42
|
readonly "modelstudio-maas": "qwen3.8-max";
|
|
42
43
|
};
|
|
43
44
|
//# sourceMappingURL=provider-default-models.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-default-models.d.ts","sourceRoot":"","sources":["../../src/core/provider-default-models.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"provider-default-models.d.ts","sourceRoot":"","sources":["../../src/core/provider-default-models.ts"],"names":[],"mappings":"AAmDA,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG1B,CAAC","sourcesContent":["import type { KnownProvider } from \"omk-ai\";\n\n/** Default model IDs for every built-in provider. */\nconst builtInDefaultModelPerProvider = {\n\t\"amazon-bedrock\": \"us.anthropic.claude-opus-4-6-v1\",\n\t\"ant-ling\": \"Ring-2.6-1T\",\n\tanthropic: \"claude-opus-4-8\",\n\topenai: \"gpt-5.4\",\n\t\"azure-openai-responses\": \"gpt-5.4\",\n\t\"openai-codex\": \"gpt-5.5\",\n\tnvidia: \"nvidia/nemotron-3-super-120b-a12b\",\n\tdeepseek: \"deepseek-v4-pro\",\n\tdevin: \"swe-2\",\n\tmeta: \"muse-spark-1.3\",\n\tgoogle: \"gemini-3.1-pro-preview\",\n\t\"google-vertex\": \"gemini-3.1-pro-preview\",\n\t\"github-copilot\": \"gpt-5.4\",\n\topenrouter: \"moonshotai/kimi-k2.6\",\n\t\"vercel-ai-gateway\": \"zai/glm-5.1\",\n\txai: \"grok-4.20-0309-reasoning\",\n\tgroq: \"openai/gpt-oss-120b\",\n\tcerebras: \"zai-glm-4.7\",\n\tzai: \"glm-5.1\",\n\t\"zai-coding-cn\": \"glm-5.1\",\n\tmistral: \"devstral-medium-latest\",\n\tminimax: \"MiniMax-M2.7\",\n\t\"minimax-cn\": \"MiniMax-M2.7\",\n\tmoonshotai: \"kimi-k2.6\",\n\t\"moonshotai-cn\": \"kimi-k2.6\",\n\thuggingface: \"moonshotai/Kimi-K2.6\",\n\tfireworks: \"accounts/fireworks/models/kimi-k2p6\",\n\ttogether: \"moonshotai/Kimi-K2.6\",\n\topencode: \"kimi-k2.6\",\n\t\"opencode-go\": \"kimi-k2.6\",\n\t\"kimi-coding\": \"k3\",\n\t\"cloudflare-workers-ai\": \"@cf/moonshotai/kimi-k2.6\",\n\t\"cloudflare-ai-gateway\": \"workers-ai/@cf/moonshotai/kimi-k2.6\",\n\txiaomi: \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-cn\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-ams\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-sgp\": \"mimo-v2.5-pro\",\n\tzyloo: \"claude-opus-4-7\",\n\tcursor: \"default\",\n\tworkbuddy: \"auto\",\n} satisfies Record<KnownProvider, string>;\n\n/** Recommended defaults for providers supplied through models.json or extensions. */\nconst customDefaultModelPerProvider = {\n\t\"modelstudio-maas\": \"qwen3.8-max\",\n} as const satisfies Readonly<Record<string, string>>;\n\nexport const defaultModelPerProvider = {\n\t...builtInDefaultModelPerProvider,\n\t...customDefaultModelPerProvider,\n} as const;\n"]}
|
|
@@ -39,6 +39,7 @@ const builtInDefaultModelPerProvider = {
|
|
|
39
39
|
"xiaomi-token-plan-sgp": "mimo-v2.5-pro",
|
|
40
40
|
zyloo: "claude-opus-4-7",
|
|
41
41
|
cursor: "default",
|
|
42
|
+
workbuddy: "auto",
|
|
42
43
|
};
|
|
43
44
|
/** Recommended defaults for providers supplied through models.json or extensions. */
|
|
44
45
|
const customDefaultModelPerProvider = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-default-models.js","sourceRoot":"","sources":["../../src/core/provider-default-models.ts"],"names":[],"mappings":"AAEA,qDAAqD;AACrD,MAAM,8BAA8B,GAAG;IACtC,gBAAgB,EAAE,iCAAiC;IACnD,UAAU,EAAE,aAAa;IACzB,SAAS,EAAE,iBAAiB;IAC5B,MAAM,EAAE,SAAS;IACjB,wBAAwB,EAAE,SAAS;IACnC,cAAc,EAAE,SAAS;IACzB,MAAM,EAAE,mCAAmC;IAC3C,QAAQ,EAAE,iBAAiB;IAC3B,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,wBAAwB;IAChC,eAAe,EAAE,wBAAwB;IACzC,gBAAgB,EAAE,SAAS;IAC3B,UAAU,EAAE,sBAAsB;IAClC,mBAAmB,EAAE,aAAa;IAClC,GAAG,EAAE,0BAA0B;IAC/B,IAAI,EAAE,qBAAqB;IAC3B,QAAQ,EAAE,aAAa;IACvB,GAAG,EAAE,SAAS;IACd,eAAe,EAAE,SAAS;IAC1B,OAAO,EAAE,wBAAwB;IACjC,OAAO,EAAE,cAAc;IACvB,YAAY,EAAE,cAAc;IAC5B,UAAU,EAAE,WAAW;IACvB,eAAe,EAAE,WAAW;IAC5B,WAAW,EAAE,sBAAsB;IACnC,SAAS,EAAE,qCAAqC;IAChD,QAAQ,EAAE,sBAAsB;IAChC,QAAQ,EAAE,WAAW;IACrB,aAAa,EAAE,WAAW;IAC1B,aAAa,EAAE,IAAI;IACnB,uBAAuB,EAAE,0BAA0B;IACnD,uBAAuB,EAAE,qCAAqC;IAC9D,MAAM,EAAE,eAAe;IACvB,sBAAsB,EAAE,eAAe;IACvC,uBAAuB,EAAE,eAAe;IACxC,uBAAuB,EAAE,eAAe;IACxC,KAAK,EAAE,iBAAiB;IACxB,MAAM,EAAE,SAAS;CACuB,CAAC;AAE1C,qFAAqF;AACrF,MAAM,6BAA6B,GAAG;IACrC,kBAAkB,EAAE,aAAa;CACmB,CAAC;AAEtD,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACtC,GAAG,8BAA8B;IACjC,GAAG,6BAA6B;CACvB,CAAC","sourcesContent":["import type { KnownProvider } from \"omk-ai\";\n\n/** Default model IDs for every built-in provider. */\nconst builtInDefaultModelPerProvider = {\n\t\"amazon-bedrock\": \"us.anthropic.claude-opus-4-6-v1\",\n\t\"ant-ling\": \"Ring-2.6-1T\",\n\tanthropic: \"claude-opus-4-8\",\n\topenai: \"gpt-5.4\",\n\t\"azure-openai-responses\": \"gpt-5.4\",\n\t\"openai-codex\": \"gpt-5.5\",\n\tnvidia: \"nvidia/nemotron-3-super-120b-a12b\",\n\tdeepseek: \"deepseek-v4-pro\",\n\tdevin: \"swe-2\",\n\tmeta: \"muse-spark-1.3\",\n\tgoogle: \"gemini-3.1-pro-preview\",\n\t\"google-vertex\": \"gemini-3.1-pro-preview\",\n\t\"github-copilot\": \"gpt-5.4\",\n\topenrouter: \"moonshotai/kimi-k2.6\",\n\t\"vercel-ai-gateway\": \"zai/glm-5.1\",\n\txai: \"grok-4.20-0309-reasoning\",\n\tgroq: \"openai/gpt-oss-120b\",\n\tcerebras: \"zai-glm-4.7\",\n\tzai: \"glm-5.1\",\n\t\"zai-coding-cn\": \"glm-5.1\",\n\tmistral: \"devstral-medium-latest\",\n\tminimax: \"MiniMax-M2.7\",\n\t\"minimax-cn\": \"MiniMax-M2.7\",\n\tmoonshotai: \"kimi-k2.6\",\n\t\"moonshotai-cn\": \"kimi-k2.6\",\n\thuggingface: \"moonshotai/Kimi-K2.6\",\n\tfireworks: \"accounts/fireworks/models/kimi-k2p6\",\n\ttogether: \"moonshotai/Kimi-K2.6\",\n\topencode: \"kimi-k2.6\",\n\t\"opencode-go\": \"kimi-k2.6\",\n\t\"kimi-coding\": \"k3\",\n\t\"cloudflare-workers-ai\": \"@cf/moonshotai/kimi-k2.6\",\n\t\"cloudflare-ai-gateway\": \"workers-ai/@cf/moonshotai/kimi-k2.6\",\n\txiaomi: \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-cn\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-ams\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-sgp\": \"mimo-v2.5-pro\",\n\tzyloo: \"claude-opus-4-7\",\n\tcursor: \"default\",\n} satisfies Record<KnownProvider, string>;\n\n/** Recommended defaults for providers supplied through models.json or extensions. */\nconst customDefaultModelPerProvider = {\n\t\"modelstudio-maas\": \"qwen3.8-max\",\n} as const satisfies Readonly<Record<string, string>>;\n\nexport const defaultModelPerProvider = {\n\t...builtInDefaultModelPerProvider,\n\t...customDefaultModelPerProvider,\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"provider-default-models.js","sourceRoot":"","sources":["../../src/core/provider-default-models.ts"],"names":[],"mappings":"AAEA,qDAAqD;AACrD,MAAM,8BAA8B,GAAG;IACtC,gBAAgB,EAAE,iCAAiC;IACnD,UAAU,EAAE,aAAa;IACzB,SAAS,EAAE,iBAAiB;IAC5B,MAAM,EAAE,SAAS;IACjB,wBAAwB,EAAE,SAAS;IACnC,cAAc,EAAE,SAAS;IACzB,MAAM,EAAE,mCAAmC;IAC3C,QAAQ,EAAE,iBAAiB;IAC3B,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,wBAAwB;IAChC,eAAe,EAAE,wBAAwB;IACzC,gBAAgB,EAAE,SAAS;IAC3B,UAAU,EAAE,sBAAsB;IAClC,mBAAmB,EAAE,aAAa;IAClC,GAAG,EAAE,0BAA0B;IAC/B,IAAI,EAAE,qBAAqB;IAC3B,QAAQ,EAAE,aAAa;IACvB,GAAG,EAAE,SAAS;IACd,eAAe,EAAE,SAAS;IAC1B,OAAO,EAAE,wBAAwB;IACjC,OAAO,EAAE,cAAc;IACvB,YAAY,EAAE,cAAc;IAC5B,UAAU,EAAE,WAAW;IACvB,eAAe,EAAE,WAAW;IAC5B,WAAW,EAAE,sBAAsB;IACnC,SAAS,EAAE,qCAAqC;IAChD,QAAQ,EAAE,sBAAsB;IAChC,QAAQ,EAAE,WAAW;IACrB,aAAa,EAAE,WAAW;IAC1B,aAAa,EAAE,IAAI;IACnB,uBAAuB,EAAE,0BAA0B;IACnD,uBAAuB,EAAE,qCAAqC;IAC9D,MAAM,EAAE,eAAe;IACvB,sBAAsB,EAAE,eAAe;IACvC,uBAAuB,EAAE,eAAe;IACxC,uBAAuB,EAAE,eAAe;IACxC,KAAK,EAAE,iBAAiB;IACxB,MAAM,EAAE,SAAS;IACjB,SAAS,EAAE,MAAM;CACuB,CAAC;AAE1C,qFAAqF;AACrF,MAAM,6BAA6B,GAAG;IACrC,kBAAkB,EAAE,aAAa;CACmB,CAAC;AAEtD,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACtC,GAAG,8BAA8B;IACjC,GAAG,6BAA6B;CACvB,CAAC","sourcesContent":["import type { KnownProvider } from \"omk-ai\";\n\n/** Default model IDs for every built-in provider. */\nconst builtInDefaultModelPerProvider = {\n\t\"amazon-bedrock\": \"us.anthropic.claude-opus-4-6-v1\",\n\t\"ant-ling\": \"Ring-2.6-1T\",\n\tanthropic: \"claude-opus-4-8\",\n\topenai: \"gpt-5.4\",\n\t\"azure-openai-responses\": \"gpt-5.4\",\n\t\"openai-codex\": \"gpt-5.5\",\n\tnvidia: \"nvidia/nemotron-3-super-120b-a12b\",\n\tdeepseek: \"deepseek-v4-pro\",\n\tdevin: \"swe-2\",\n\tmeta: \"muse-spark-1.3\",\n\tgoogle: \"gemini-3.1-pro-preview\",\n\t\"google-vertex\": \"gemini-3.1-pro-preview\",\n\t\"github-copilot\": \"gpt-5.4\",\n\topenrouter: \"moonshotai/kimi-k2.6\",\n\t\"vercel-ai-gateway\": \"zai/glm-5.1\",\n\txai: \"grok-4.20-0309-reasoning\",\n\tgroq: \"openai/gpt-oss-120b\",\n\tcerebras: \"zai-glm-4.7\",\n\tzai: \"glm-5.1\",\n\t\"zai-coding-cn\": \"glm-5.1\",\n\tmistral: \"devstral-medium-latest\",\n\tminimax: \"MiniMax-M2.7\",\n\t\"minimax-cn\": \"MiniMax-M2.7\",\n\tmoonshotai: \"kimi-k2.6\",\n\t\"moonshotai-cn\": \"kimi-k2.6\",\n\thuggingface: \"moonshotai/Kimi-K2.6\",\n\tfireworks: \"accounts/fireworks/models/kimi-k2p6\",\n\ttogether: \"moonshotai/Kimi-K2.6\",\n\topencode: \"kimi-k2.6\",\n\t\"opencode-go\": \"kimi-k2.6\",\n\t\"kimi-coding\": \"k3\",\n\t\"cloudflare-workers-ai\": \"@cf/moonshotai/kimi-k2.6\",\n\t\"cloudflare-ai-gateway\": \"workers-ai/@cf/moonshotai/kimi-k2.6\",\n\txiaomi: \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-cn\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-ams\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-sgp\": \"mimo-v2.5-pro\",\n\tzyloo: \"claude-opus-4-7\",\n\tcursor: \"default\",\n\tworkbuddy: \"auto\",\n} satisfies Record<KnownProvider, string>;\n\n/** Recommended defaults for providers supplied through models.json or extensions. */\nconst customDefaultModelPerProvider = {\n\t\"modelstudio-maas\": \"qwen3.8-max\",\n} as const satisfies Readonly<Record<string, string>>;\n\nexport const defaultModelPerProvider = {\n\t...builtInDefaultModelPerProvider,\n\t...customDefaultModelPerProvider,\n} as const;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-display-names.d.ts","sourceRoot":"","sources":["../../src/core/provider-display-names.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"provider-display-names.d.ts","sourceRoot":"","sources":["../../src/core/provider-display-names.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAuClE,CAAC","sourcesContent":["export const BUILT_IN_PROVIDER_DISPLAY_NAMES: Record<string, string> = {\n\tanthropic: \"Anthropic\",\n\t\"amazon-bedrock\": \"Amazon Bedrock\",\n\t\"ant-ling\": \"Ant Ling\",\n\t\"azure-openai-responses\": \"Azure OpenAI Responses\",\n\tcerebras: \"Cerebras\",\n\t\"cloudflare-ai-gateway\": \"Cloudflare AI Gateway\",\n\t\"cloudflare-workers-ai\": \"Cloudflare Workers AI\",\n\tdeepseek: \"DeepSeek\",\n\tdevin: \"Devin CLI session token\",\n\tcursor: \"Cursor subscription\",\n\tfireworks: \"Fireworks\",\n\tgoogle: \"Google Gemini\",\n\t\"google-vertex\": \"Google Vertex AI\",\n\tgroq: \"Groq\",\n\thuggingface: \"Hugging Face\",\n\t\"kimi-coding\": \"Kimi For Coding\",\n\tworkbuddy: \"WorkBuddy (CodeBuddy) plan key\",\n\tmeta: \"Meta Model API\",\n\tmistral: \"Mistral\",\n\tminimax: \"MiniMax\",\n\t\"minimax-cn\": \"MiniMax (China)\",\n\tmoonshotai: \"Moonshot AI\",\n\t\"moonshotai-cn\": \"Moonshot AI (China)\",\n\tnvidia: \"NVIDIA NIM\",\n\topencode: \"OpenCode Zen\",\n\t\"opencode-go\": \"OpenCode Go\",\n\topenai: \"OpenAI\",\n\topenrouter: \"OpenRouter\",\n\ttogether: \"Together AI\",\n\t\"vercel-ai-gateway\": \"Vercel AI Gateway\",\n\txai: \"xAI\",\n\tzai: \"ZAI\",\n\t\"zai-coding-cn\": \"ZAI Coding Plan (China)\",\n\txiaomi: \"Xiaomi MiMo\",\n\t\"xiaomi-token-plan-cn\": \"Xiaomi MiMo Token Plan (China)\",\n\t\"xiaomi-token-plan-ams\": \"Xiaomi MiMo Token Plan (Amsterdam)\",\n\t\"xiaomi-token-plan-sgp\": \"Xiaomi MiMo Token Plan (Singapore)\",\n\tzyloo: \"Zyloo\",\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-display-names.js","sourceRoot":"","sources":["../../src/core/provider-display-names.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,+BAA+B,GAA2B;IACtE,SAAS,EAAE,WAAW;IACtB,gBAAgB,EAAE,gBAAgB;IAClC,UAAU,EAAE,UAAU;IACtB,wBAAwB,EAAE,wBAAwB;IAClD,QAAQ,EAAE,UAAU;IACpB,uBAAuB,EAAE,uBAAuB;IAChD,uBAAuB,EAAE,uBAAuB;IAChD,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,yBAAyB;IAChC,MAAM,EAAE,qBAAqB;IAC7B,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,eAAe;IACvB,eAAe,EAAE,kBAAkB;IACnC,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,cAAc;IAC3B,aAAa,EAAE,iBAAiB;IAChC,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,iBAAiB;IAC/B,UAAU,EAAE,aAAa;IACzB,eAAe,EAAE,qBAAqB;IACtC,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,cAAc;IACxB,aAAa,EAAE,aAAa;IAC5B,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,aAAa;IACvB,mBAAmB,EAAE,mBAAmB;IACxC,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,eAAe,EAAE,yBAAyB;IAC1C,MAAM,EAAE,aAAa;IACrB,sBAAsB,EAAE,gCAAgC;IACxD,uBAAuB,EAAE,oCAAoC;IAC7D,uBAAuB,EAAE,oCAAoC;IAC7D,KAAK,EAAE,OAAO;CACd,CAAC","sourcesContent":["export const BUILT_IN_PROVIDER_DISPLAY_NAMES: Record<string, string> = {\n\tanthropic: \"Anthropic\",\n\t\"amazon-bedrock\": \"Amazon Bedrock\",\n\t\"ant-ling\": \"Ant Ling\",\n\t\"azure-openai-responses\": \"Azure OpenAI Responses\",\n\tcerebras: \"Cerebras\",\n\t\"cloudflare-ai-gateway\": \"Cloudflare AI Gateway\",\n\t\"cloudflare-workers-ai\": \"Cloudflare Workers AI\",\n\tdeepseek: \"DeepSeek\",\n\tdevin: \"Devin CLI session token\",\n\tcursor: \"Cursor subscription\",\n\tfireworks: \"Fireworks\",\n\tgoogle: \"Google Gemini\",\n\t\"google-vertex\": \"Google Vertex AI\",\n\tgroq: \"Groq\",\n\thuggingface: \"Hugging Face\",\n\t\"kimi-coding\": \"Kimi For Coding\",\n\tmeta: \"Meta Model API\",\n\tmistral: \"Mistral\",\n\tminimax: \"MiniMax\",\n\t\"minimax-cn\": \"MiniMax (China)\",\n\tmoonshotai: \"Moonshot AI\",\n\t\"moonshotai-cn\": \"Moonshot AI (China)\",\n\tnvidia: \"NVIDIA NIM\",\n\topencode: \"OpenCode Zen\",\n\t\"opencode-go\": \"OpenCode Go\",\n\topenai: \"OpenAI\",\n\topenrouter: \"OpenRouter\",\n\ttogether: \"Together AI\",\n\t\"vercel-ai-gateway\": \"Vercel AI Gateway\",\n\txai: \"xAI\",\n\tzai: \"ZAI\",\n\t\"zai-coding-cn\": \"ZAI Coding Plan (China)\",\n\txiaomi: \"Xiaomi MiMo\",\n\t\"xiaomi-token-plan-cn\": \"Xiaomi MiMo Token Plan (China)\",\n\t\"xiaomi-token-plan-ams\": \"Xiaomi MiMo Token Plan (Amsterdam)\",\n\t\"xiaomi-token-plan-sgp\": \"Xiaomi MiMo Token Plan (Singapore)\",\n\tzyloo: \"Zyloo\",\n};\n"]}
|
|
1
|
+
{"version":3,"file":"provider-display-names.js","sourceRoot":"","sources":["../../src/core/provider-display-names.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,+BAA+B,GAA2B;IACtE,SAAS,EAAE,WAAW;IACtB,gBAAgB,EAAE,gBAAgB;IAClC,UAAU,EAAE,UAAU;IACtB,wBAAwB,EAAE,wBAAwB;IAClD,QAAQ,EAAE,UAAU;IACpB,uBAAuB,EAAE,uBAAuB;IAChD,uBAAuB,EAAE,uBAAuB;IAChD,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,yBAAyB;IAChC,MAAM,EAAE,qBAAqB;IAC7B,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,eAAe;IACvB,eAAe,EAAE,kBAAkB;IACnC,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,cAAc;IAC3B,aAAa,EAAE,iBAAiB;IAChC,SAAS,EAAE,gCAAgC;IAC3C,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,iBAAiB;IAC/B,UAAU,EAAE,aAAa;IACzB,eAAe,EAAE,qBAAqB;IACtC,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,cAAc;IACxB,aAAa,EAAE,aAAa;IAC5B,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,aAAa;IACvB,mBAAmB,EAAE,mBAAmB;IACxC,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,eAAe,EAAE,yBAAyB;IAC1C,MAAM,EAAE,aAAa;IACrB,sBAAsB,EAAE,gCAAgC;IACxD,uBAAuB,EAAE,oCAAoC;IAC7D,uBAAuB,EAAE,oCAAoC;IAC7D,KAAK,EAAE,OAAO;CACd,CAAC","sourcesContent":["export const BUILT_IN_PROVIDER_DISPLAY_NAMES: Record<string, string> = {\n\tanthropic: \"Anthropic\",\n\t\"amazon-bedrock\": \"Amazon Bedrock\",\n\t\"ant-ling\": \"Ant Ling\",\n\t\"azure-openai-responses\": \"Azure OpenAI Responses\",\n\tcerebras: \"Cerebras\",\n\t\"cloudflare-ai-gateway\": \"Cloudflare AI Gateway\",\n\t\"cloudflare-workers-ai\": \"Cloudflare Workers AI\",\n\tdeepseek: \"DeepSeek\",\n\tdevin: \"Devin CLI session token\",\n\tcursor: \"Cursor subscription\",\n\tfireworks: \"Fireworks\",\n\tgoogle: \"Google Gemini\",\n\t\"google-vertex\": \"Google Vertex AI\",\n\tgroq: \"Groq\",\n\thuggingface: \"Hugging Face\",\n\t\"kimi-coding\": \"Kimi For Coding\",\n\tworkbuddy: \"WorkBuddy (CodeBuddy) plan key\",\n\tmeta: \"Meta Model API\",\n\tmistral: \"Mistral\",\n\tminimax: \"MiniMax\",\n\t\"minimax-cn\": \"MiniMax (China)\",\n\tmoonshotai: \"Moonshot AI\",\n\t\"moonshotai-cn\": \"Moonshot AI (China)\",\n\tnvidia: \"NVIDIA NIM\",\n\topencode: \"OpenCode Zen\",\n\t\"opencode-go\": \"OpenCode Go\",\n\topenai: \"OpenAI\",\n\topenrouter: \"OpenRouter\",\n\ttogether: \"Together AI\",\n\t\"vercel-ai-gateway\": \"Vercel AI Gateway\",\n\txai: \"xAI\",\n\tzai: \"ZAI\",\n\t\"zai-coding-cn\": \"ZAI Coding Plan (China)\",\n\txiaomi: \"Xiaomi MiMo\",\n\t\"xiaomi-token-plan-cn\": \"Xiaomi MiMo Token Plan (China)\",\n\t\"xiaomi-token-plan-ams\": \"Xiaomi MiMo Token Plan (Amsterdam)\",\n\t\"xiaomi-token-plan-sgp\": \"Xiaomi MiMo Token Plan (Singapore)\",\n\tzyloo: \"Zyloo\",\n};\n"]}
|
|
@@ -37,6 +37,15 @@ export declare function isContentSafetyStopMessage(text: string | undefined): bo
|
|
|
37
37
|
* candidate — so these classify as retryable-with-failover, not auth-fatal.
|
|
38
38
|
*/
|
|
39
39
|
export declare function isQuotaExhaustionMessage(text: string | undefined): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Terminal per-candidate failures inside a failover chain: the candidate
|
|
42
|
+
* provider can never serve this request — quota/billing exhaustion, auth or
|
|
43
|
+
* entitlement denial (401/403, permission_error, authentication_error), or a
|
|
44
|
+
* permanent 4xx (unsupported model, invalid request). Absorbing them lets the
|
|
45
|
+
* chain reach the next candidate; a transient 5xx still aborts so the same
|
|
46
|
+
* model can retry instead of silently hopping providers mid-recovery.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isTerminalProviderErrorMessage(text: string | undefined): boolean;
|
|
40
49
|
/**
|
|
41
50
|
* Anthropic rejecting the spoofed Claude Code client version because the target
|
|
42
51
|
* model is gated on a newer one (`claude_code_version_too_old`, HTTP 400).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-resilience.d.ts","sourceRoot":"","sources":["../../src/core/provider-resilience.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provider resilience — root-level recovery for sticky safety models and\n * sanitize-and-retry protocol failures (orphan tool_call_id, terminated streams).\n *\n * This is not a jailbreak layer. It keeps sessions alive when a provider\n * false-positives or returns a sticky transcript-shape error.\n */\n\nexport type FailoverCandidate = Readonly<{\n\treadonly provider: string;\n\treadonly id: string;\n}>;\n\n/** Models known to emit high false-positive content/safety stops on coding work. */\nexport const STICKY_SAFETY_MODEL_RE = /fable/i;\n\n/** Claude lines that must stay on-model when they refuse. No DeepSeek hop. */\nexport const NO_SAFETY_FAILOVER_MODEL_RE = /(?:claude-)?(?:fable|opus|sonnet)/i;\n\n/** Default failover chain when a sticky safety model refuses a turn. */\nexport const DEFAULT_SAFETY_FAILOVER_CANDIDATES: readonly FailoverCandidate[] = [\n\t{ provider: \"kimi-coding\", id: \"k3\" },\n\t{ provider: \"modelstudio-maas\", id: \"qwen3.8-max\" },\n\t{ provider: \"xai\", id: \"grok-4.5\" },\n\t{ provider: \"deepseek\", id: \"deepseek-v4-pro\" },\n\t{ provider: \"deepseek\", id: \"deepseek-v4-flash\" },\n\t{ provider: \"modelstudio-maas\", id: \"deepseek-v4-pro\" },\n\t{ provider: \"kimi-coding\", id: \"kimi-for-coding\" },\n] as const;\n\nexport type ProviderResilienceSettings = Readonly<{\n\t/** When true (default), refuse selecting sticky safety models (e.g. claude-fable-5). */\n\treadonly blockStickySafetyModels?: boolean;\n\t/** When true (default), auto-switch model on content/safety stop before retry. */\n\treadonly autoFailoverOnSafetyStop?: boolean;\n\t/** Ordered failover targets. Falls back to DEFAULT_SAFETY_FAILOVER_CANDIDATES. */\n\treadonly failoverCandidates?: readonly FailoverCandidate[];\n}>;\n\nexport const DEFAULT_PROVIDER_RESILIENCE: Required<\n\tPick<ProviderResilienceSettings, \"blockStickySafetyModels\" | \"autoFailoverOnSafetyStop\">\n> & {\n\treadonly failoverCandidates: readonly FailoverCandidate[];\n} = {\n\tblockStickySafetyModels: true,\n\tautoFailoverOnSafetyStop: true,\n\tfailoverCandidates: DEFAULT_SAFETY_FAILOVER_CANDIDATES,\n};\n\nexport function isStickySafetyModel(modelId: string | undefined, provider?: string | undefined): boolean {\n\tconst id = (modelId ?? \"\").trim();\n\tif (!id) return false;\n\tif (STICKY_SAFETY_MODEL_RE.test(id)) return true;\n\tconst p = (provider ?? \"\").toLowerCase();\n\treturn p.includes(\"anthropic\") && STICKY_SAFETY_MODEL_RE.test(id);\n}\n\n/** Fable / Opus / Sonnet stay on the requested id after a safety stop. */\nexport function isNoSafetyFailoverModel(modelId: string | undefined, provider?: string | undefined): boolean {\n\tconst id = (modelId ?? \"\").trim();\n\tif (!id) return false;\n\tif (NO_SAFETY_FAILOVER_MODEL_RE.test(id)) return true;\n\tconst p = (provider ?? \"\").toLowerCase();\n\treturn p.includes(\"anthropic\") && NO_SAFETY_FAILOVER_MODEL_RE.test(id);\n}\n\nexport function isContentSafetyStopMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /content\\/safety stop|stop_reason\\s*=\\s*(refusal|sensitive)|safety stop|provider\\.refusal|kind=provider_refusal/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Billing/quota exhaustion (\"usage limit for this billing cycle\",\n * \"insufficient_quota\", zero balance, ...). Same-model retry is useless until\n * the cycle resets, but the turn can still be saved by failing over to another\n * candidate — so these classify as retryable-with-failover, not auth-fatal.\n */\nexport function isQuotaExhaustionMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /usage limit|GoUsageLimitError|FreeUsageLimitError|available balance|insufficient_quota|insufficient balance|insufficient credits|out of budget|quota exceeded|quota\\s+(?:has been\\s+|was\\s+|is\\s+)?exhaust|billing/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Anthropic rejecting the spoofed Claude Code client version because the target\n * model is gated on a newer one (`claude_code_version_too_old`, HTTP 400).\n * Permanent for this build: every retry and every failover re-sends the same\n * user-agent, so the fix is bumping `CLAUDE_CODE_VERSION` in omk-ai (or\n * selecting an ungated model).\n */\nexport function isClaudeCodeVersionTooOldMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /claude_code_version_too_old|does not support this model;\\s*version\\s+[\\d.]+\\s+or newer is required/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Codex HTTP 400 when a ChatGPT-account OAuth session asks for a model the\n * account catalog does not serve (`gpt-6-astra` during the 2026-09-04 rollout).\n * Permanent for this login: same-model retry, transcript sanitize, and /new\n * session all re-send the same slug and get the same 400. Switch model or use\n * an API-key route that has the model.\n */\nexport function isCodexChatgptAccountUnsupportedModelMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /model is not supported when using Codex with a ChatGPT account/i.test(text);\n}\n\n/** Orphan tool results / Kimi-K3 protocol shape errors that heal after sanitize+retry. */\nexport function isOrphanToolCallIdError(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /tool_call_id\\s+is\\s+not\\s+found|tool_call_id\\s+not\\s+found|unknown\\s+tool_call_id/i.test(text);\n}\n\n/**\n * Status-code-context match: a bare `500` inside a message body (\"saved 500\n * records\") is not a status code, so numeric matches require an adjacent\n * transport word — either a code-context word before the digits (\"HTTP 429\",\n * \"error 503\", \"status 401\") or a status-context word after them (\"503\n * Upstream request failed\", \"429 Too Many Requests\", \"500 Internal Server\n * Error\"). Structured `status`/`errorCode` fields on the caller's side still\n * outrank this text heuristic entirely.\n */\nexport function hasStatusCodeLike(text: string, codes: readonly number[]): boolean {\n\tconst left = /(?:https?|status(?:\\s*code)?|error(?:\\s*code)?|code)\\s*:?\\s*(\\d{3})\\b/gi;\n\tconst right =\n\t\t/\\b(\\d{3})\\s+(?:too many|upstream|bad gateway|service unavailable|internal server|gateway|error|status|request failed|timed? ?out|unauthori[sz]ed|forbidden)/gi;\n\tfor (const re of [left, right]) {\n\t\tre.lastIndex = 0;\n\t\tfor (;;) {\n\t\t\tconst match = re.exec(text);\n\t\t\tif (match === null) break;\n\t\t\tif (codes.includes(Number.parseInt(match[1], 10))) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Transient upstream availability failures: gateway 5xx passthroughs\n * (\"503 Upstream request failed\", \"Endpoint is unavailable\") and dropped\n * streams that never carried a finish reason (\"Stream ended without\n * finish_reason\"). Transport problems, not transcript-shape problems — they\n * heal by backoff/retry or switching model, never by transcript sanitization.\n */\nexport function isUpstreamUnavailableMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn (\n\t\t/upstream(?: request)? failed|upstream connect|endpoint (?:is )?unavailable|stream ended without finish_reason/i.test(\n\t\t\ttext,\n\t\t) || hasStatusCodeLike(text, [500, 502, 503, 504])\n\t);\n}\n\n/**\n * Route families: the same underlying model served by several provider\n * routes. Matched on the model id OR display name so alias routes like\n * `openrouter/stealth/ox-alpha`, `opencode-go/ox-alpha-free`, and\n * `opencode/x-preview-f-free` (\"Ox Alpha Free (Unlimited)\") rotate as one\n * ox-alpha family.\n */\nconst MODEL_ROUTE_FAMILIES: readonly { readonly pattern: RegExp; readonly family: string }[] = [\n\t{ pattern: /(?:^|[-_/])ox[-_ ]?alpha(?:[-_/\\s(]|$)/i, family: \"ox-alpha\" },\n\t// union-alpha is served by opencode-go/union-alpha (anthropic-messages) and\n\t// openrouter/stealth/union-alpha (openai-completions); both map to one family\n\t// so an upstream-unavailable 503/empty stream rotates to the live route.\n\t{ pattern: /(?:^|[-_/])union[-_ ]?alpha(?:[-_/\\s(]|$)/i, family: \"union-alpha\" },\n];\n\n/** Family key for a model route, or undefined when it has no known alias group. */\nexport function modelRouteFamily(model: {\n\treadonly provider?: string | undefined;\n\treadonly id: string;\n\treadonly name?: string | undefined;\n}): string | undefined {\n\tfor (const { pattern, family } of MODEL_ROUTE_FAMILIES) {\n\t\tif (pattern.test(model.id)) return family;\n\t\tif (model.name && pattern.test(model.name)) return family;\n\t}\n\treturn undefined;\n}\n\n/**\n * Alternative provider routes serving the same model family as\n * {@link failed}, in registry order, excluding the failed route itself.\n * Callers filter by authentication and per-turn failure bookkeeping.\n */\nexport function sameModelRouteCandidates<\n\tT extends { readonly provider: string; readonly id: string; readonly name?: string | undefined },\n>(\n\tfailed: { readonly provider: string; readonly id: string; readonly name?: string | undefined },\n\tavailable: readonly T[],\n): T[] {\n\tconst family = modelRouteFamily(failed);\n\tif (!family) return [];\n\tconst candidates: T[] = [];\n\tfor (const model of available) {\n\t\tif (model.provider === failed.provider && model.id === failed.id) continue;\n\t\tif (modelRouteFamily(model) === family) candidates.push(model);\n\t}\n\treturn candidates;\n}\n\n/**\n * Errors the agent loop may auto-retry (after optional failover / message sanitize).\n * Kept in one place so agent-session and tests share the same contract.\n */\nexport function isTransientProviderErrorMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\t// Checked first: the payload carries `invalid_request_error`, which the\n\t// pattern below treats as transient, but a stale client version never heals\n\t// by retrying.\n\tif (isClaudeCodeVersionTooOldMessage(text)) return false;\n\tif (isCodexChatgptAccountUnsupportedModelMessage(text)) return false;\n\t// `at capacity|high demand`: xAI serves overload as HTTP 429 whose body carries\n\t// no status or limit token, so the message-level classifier misses it and the\n\t// turn never auto-retries (observed 2026-09-03, xai/grok-4.6).\n\tif (\n\t\t/overloaded|at capacity|high demand|provider.?returned.?error|rate.?limit|too many requests|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|stream ended before terminal|http2 request did not get a response|timed? out|timeout|\\bterminated\\b|retry delay|content\\/safety stop|stop_reason\\s*=\\s*(refusal|sensitive)|safety stop|tool_call_id\\s+is\\s+not\\s+found|tool_call_id\\s+not\\s+found|invalid_request_error|json error injected into sse stream|injected into sse/i.test(\n\t\t\ttext,\n\t\t)\n\t) {\n\t\treturn true;\n\t}\n\t// Status-looking numbers only count with adjacent transport context — a\n\t// bare `500` in a message body (\"saved 500 records\") is not a status code.\n\treturn hasStatusCodeLike(text, [429, 500, 502, 503, 504]);\n}\n\nexport function resolveFailoverCandidates(\n\tsettings: ProviderResilienceSettings | undefined,\n): readonly FailoverCandidate[] {\n\tconst custom = settings?.failoverCandidates;\n\tif (custom && custom.length > 0) return custom;\n\treturn DEFAULT_SAFETY_FAILOVER_CANDIDATES;\n}\n\n/** Explicit `--model` / `--provider` pins stay on the requested model. */\nexport function shouldHonorSafetyFailover(options: {\n\treadonly autoFailoverOnSafetyStop: boolean;\n\treadonly modelPinned: boolean;\n\treadonly modelId?: string;\n\treadonly provider?: string;\n}): boolean {\n\tif (!options.autoFailoverOnSafetyStop || options.modelPinned) return false;\n\treturn !isNoSafetyFailoverModel(options.modelId, options.provider);\n}\n\n/** Sticky-model eject still applies unless the user pinned that model. */\nexport function shouldEjectStickySafetyModel(options: {\n\treadonly blockStickySafetyModels: boolean;\n\treadonly modelPinned: boolean;\n}): boolean {\n\treturn options.blockStickySafetyModels && !options.modelPinned;\n}\n\nexport function resolveProviderResilience(settings: ProviderResilienceSettings | undefined): {\n\treadonly blockStickySafetyModels: boolean;\n\treadonly autoFailoverOnSafetyStop: boolean;\n\treadonly failoverCandidates: readonly FailoverCandidate[];\n} {\n\treturn {\n\t\tblockStickySafetyModels: settings?.blockStickySafetyModels ?? DEFAULT_PROVIDER_RESILIENCE.blockStickySafetyModels,\n\t\tautoFailoverOnSafetyStop:\n\t\t\tsettings?.autoFailoverOnSafetyStop ?? DEFAULT_PROVIDER_RESILIENCE.autoFailoverOnSafetyStop,\n\t\tfailoverCandidates: resolveFailoverCandidates(settings),\n\t};\n}\n\n/**\n * Pick first failover candidate that is not the current model and passes `isAllowed`.\n * Pure — caller performs auth checks and setModel.\n */\nexport function pickFailoverCandidate(\n\tcandidates: readonly FailoverCandidate[],\n\tcurrent: { readonly provider?: string; readonly id?: string } | undefined,\n\tisAllowed: (candidate: FailoverCandidate) => boolean,\n): FailoverCandidate | undefined {\n\tfor (const c of candidates) {\n\t\tif (current && c.provider === current.provider && c.id === current.id) continue;\n\t\tif (isStickySafetyModel(c.id, c.provider)) continue;\n\t\tif (!isAllowed(c)) continue;\n\t\treturn c;\n\t}\n\treturn undefined;\n}\n\nexport function stickySafetyBlockMessage(modelId: string, provider: string): string {\n\treturn (\n\t\t`Blocked sticky safety model ${provider}/${modelId} (providerResilience.blockStickySafetyModels). ` +\n\t\t`Use kimi-coding/k3, modelstudio-maas/qwen3.8-max, grok-4.5, or deepseek; ` +\n\t\t`or set providerResilience.blockStickySafetyModels=false.`\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"provider-resilience.d.ts","sourceRoot":"","sources":["../../src/core/provider-resilience.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provider resilience — root-level recovery for sticky safety models and\n * sanitize-and-retry protocol failures (orphan tool_call_id, terminated streams).\n *\n * This is not a jailbreak layer. It keeps sessions alive when a provider\n * false-positives or returns a sticky transcript-shape error.\n */\n\nexport type FailoverCandidate = Readonly<{\n\treadonly provider: string;\n\treadonly id: string;\n}>;\n\n/** Models known to emit high false-positive content/safety stops on coding work. */\nexport const STICKY_SAFETY_MODEL_RE = /fable/i;\n\n/** Claude lines that must stay on-model when they refuse. No DeepSeek hop. */\nexport const NO_SAFETY_FAILOVER_MODEL_RE = /(?:claude-)?(?:fable|opus|sonnet)/i;\n\n/** Default failover chain when a sticky safety model refuses a turn. */\nexport const DEFAULT_SAFETY_FAILOVER_CANDIDATES: readonly FailoverCandidate[] = [\n\t{ provider: \"kimi-coding\", id: \"k3\" },\n\t{ provider: \"modelstudio-maas\", id: \"qwen3.8-max\" },\n\t{ provider: \"xai\", id: \"grok-4.5\" },\n\t{ provider: \"deepseek\", id: \"deepseek-v4-pro\" },\n\t{ provider: \"deepseek\", id: \"deepseek-v4-flash\" },\n\t{ provider: \"modelstudio-maas\", id: \"deepseek-v4-pro\" },\n\t{ provider: \"kimi-coding\", id: \"kimi-for-coding\" },\n] as const;\n\nexport type ProviderResilienceSettings = Readonly<{\n\t/** When true (default), refuse selecting sticky safety models (e.g. claude-fable-5). */\n\treadonly blockStickySafetyModels?: boolean;\n\t/** When true (default), auto-switch model on content/safety stop before retry. */\n\treadonly autoFailoverOnSafetyStop?: boolean;\n\t/** Ordered failover targets. Falls back to DEFAULT_SAFETY_FAILOVER_CANDIDATES. */\n\treadonly failoverCandidates?: readonly FailoverCandidate[];\n}>;\n\nexport const DEFAULT_PROVIDER_RESILIENCE: Required<\n\tPick<ProviderResilienceSettings, \"blockStickySafetyModels\" | \"autoFailoverOnSafetyStop\">\n> & {\n\treadonly failoverCandidates: readonly FailoverCandidate[];\n} = {\n\tblockStickySafetyModels: true,\n\tautoFailoverOnSafetyStop: true,\n\tfailoverCandidates: DEFAULT_SAFETY_FAILOVER_CANDIDATES,\n};\n\nexport function isStickySafetyModel(modelId: string | undefined, provider?: string | undefined): boolean {\n\tconst id = (modelId ?? \"\").trim();\n\tif (!id) return false;\n\tif (STICKY_SAFETY_MODEL_RE.test(id)) return true;\n\tconst p = (provider ?? \"\").toLowerCase();\n\treturn p.includes(\"anthropic\") && STICKY_SAFETY_MODEL_RE.test(id);\n}\n\n/** Fable / Opus / Sonnet stay on the requested id after a safety stop. */\nexport function isNoSafetyFailoverModel(modelId: string | undefined, provider?: string | undefined): boolean {\n\tconst id = (modelId ?? \"\").trim();\n\tif (!id) return false;\n\tif (NO_SAFETY_FAILOVER_MODEL_RE.test(id)) return true;\n\tconst p = (provider ?? \"\").toLowerCase();\n\treturn p.includes(\"anthropic\") && NO_SAFETY_FAILOVER_MODEL_RE.test(id);\n}\n\nexport function isContentSafetyStopMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /content\\/safety stop|stop_reason\\s*=\\s*(refusal|sensitive)|safety stop|provider\\.refusal|kind=provider_refusal/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Billing/quota exhaustion (\"usage limit for this billing cycle\",\n * \"insufficient_quota\", zero balance, ...). Same-model retry is useless until\n * the cycle resets, but the turn can still be saved by failing over to another\n * candidate — so these classify as retryable-with-failover, not auth-fatal.\n */\nexport function isQuotaExhaustionMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /usage limit|GoUsageLimitError|FreeUsageLimitError|available balance|insufficient_quota|insufficient balance|insufficient credits|out of budget|quota exceeded|quota\\s+(?:has been\\s+|was\\s+|is\\s+)?exhaust|billing/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Terminal per-candidate failures inside a failover chain: the candidate\n * provider can never serve this request — quota/billing exhaustion, auth or\n * entitlement denial (401/403, permission_error, authentication_error), or a\n * permanent 4xx (unsupported model, invalid request). Absorbing them lets the\n * chain reach the next candidate; a transient 5xx still aborts so the same\n * model can retry instead of silently hopping providers mid-recovery.\n */\nexport function isTerminalProviderErrorMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\tif (isQuotaExhaustionMessage(text)) return true;\n\treturn /permission_error|authentication_error|unsupported_model|model_not_supported|invalid_api_key|unauthori[sz]ed|forbidden|does not have access|\\b4(?:01|03|02|04|22)\\b/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Anthropic rejecting the spoofed Claude Code client version because the target\n * model is gated on a newer one (`claude_code_version_too_old`, HTTP 400).\n * Permanent for this build: every retry and every failover re-sends the same\n * user-agent, so the fix is bumping `CLAUDE_CODE_VERSION` in omk-ai (or\n * selecting an ungated model).\n */\nexport function isClaudeCodeVersionTooOldMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /claude_code_version_too_old|does not support this model;\\s*version\\s+[\\d.]+\\s+or newer is required/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Codex HTTP 400 when a ChatGPT-account OAuth session asks for a model the\n * account catalog does not serve (`gpt-6-astra` during the 2026-09-04 rollout).\n * Permanent for this login: same-model retry, transcript sanitize, and /new\n * session all re-send the same slug and get the same 400. Switch model or use\n * an API-key route that has the model.\n */\nexport function isCodexChatgptAccountUnsupportedModelMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /model is not supported when using Codex with a ChatGPT account/i.test(text);\n}\n\n/** Orphan tool results / Kimi-K3 protocol shape errors that heal after sanitize+retry. */\nexport function isOrphanToolCallIdError(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /tool_call_id\\s+is\\s+not\\s+found|tool_call_id\\s+not\\s+found|unknown\\s+tool_call_id/i.test(text);\n}\n\n/**\n * Status-code-context match: a bare `500` inside a message body (\"saved 500\n * records\") is not a status code, so numeric matches require an adjacent\n * transport word — either a code-context word before the digits (\"HTTP 429\",\n * \"error 503\", \"status 401\") or a status-context word after them (\"503\n * Upstream request failed\", \"429 Too Many Requests\", \"500 Internal Server\n * Error\"). Structured `status`/`errorCode` fields on the caller's side still\n * outrank this text heuristic entirely.\n */\nexport function hasStatusCodeLike(text: string, codes: readonly number[]): boolean {\n\tconst left = /(?:https?|status(?:\\s*code)?|error(?:\\s*code)?|code)\\s*:?\\s*(\\d{3})\\b/gi;\n\tconst right =\n\t\t/\\b(\\d{3})\\s+(?:too many|upstream|bad gateway|service unavailable|internal server|gateway|error|status|request failed|timed? ?out|unauthori[sz]ed|forbidden)/gi;\n\tfor (const re of [left, right]) {\n\t\tre.lastIndex = 0;\n\t\tfor (;;) {\n\t\t\tconst match = re.exec(text);\n\t\t\tif (match === null) break;\n\t\t\tif (codes.includes(Number.parseInt(match[1], 10))) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Transient upstream availability failures: gateway 5xx passthroughs\n * (\"503 Upstream request failed\", \"Endpoint is unavailable\") and dropped\n * streams that never carried a finish reason (\"Stream ended without\n * finish_reason\"). Transport problems, not transcript-shape problems — they\n * heal by backoff/retry or switching model, never by transcript sanitization.\n */\nexport function isUpstreamUnavailableMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn (\n\t\t/upstream(?: request)? failed|upstream connect|endpoint (?:is )?unavailable|stream ended without finish_reason/i.test(\n\t\t\ttext,\n\t\t) || hasStatusCodeLike(text, [500, 502, 503, 504])\n\t);\n}\n\n/**\n * Route families: the same underlying model served by several provider\n * routes. Matched on the model id OR display name so alias routes like\n * `openrouter/stealth/ox-alpha`, `opencode-go/ox-alpha-free`, and\n * `opencode/x-preview-f-free` (\"Ox Alpha Free (Unlimited)\") rotate as one\n * ox-alpha family.\n */\nconst MODEL_ROUTE_FAMILIES: readonly { readonly pattern: RegExp; readonly family: string }[] = [\n\t{ pattern: /(?:^|[-_/])ox[-_ ]?alpha(?:[-_/\\s(]|$)/i, family: \"ox-alpha\" },\n\t// union-alpha is served by opencode-go/union-alpha (anthropic-messages) and\n\t// openrouter/stealth/union-alpha (openai-completions); both map to one family\n\t// so an upstream-unavailable 503/empty stream rotates to the live route.\n\t{ pattern: /(?:^|[-_/])union[-_ ]?alpha(?:[-_/\\s(]|$)/i, family: \"union-alpha\" },\n];\n\n/** Family key for a model route, or undefined when it has no known alias group. */\nexport function modelRouteFamily(model: {\n\treadonly provider?: string | undefined;\n\treadonly id: string;\n\treadonly name?: string | undefined;\n}): string | undefined {\n\tfor (const { pattern, family } of MODEL_ROUTE_FAMILIES) {\n\t\tif (pattern.test(model.id)) return family;\n\t\tif (model.name && pattern.test(model.name)) return family;\n\t}\n\treturn undefined;\n}\n\n/**\n * Alternative provider routes serving the same model family as\n * {@link failed}, in registry order, excluding the failed route itself.\n * Callers filter by authentication and per-turn failure bookkeeping.\n */\nexport function sameModelRouteCandidates<\n\tT extends { readonly provider: string; readonly id: string; readonly name?: string | undefined },\n>(\n\tfailed: { readonly provider: string; readonly id: string; readonly name?: string | undefined },\n\tavailable: readonly T[],\n): T[] {\n\tconst family = modelRouteFamily(failed);\n\tif (!family) return [];\n\tconst candidates: T[] = [];\n\tfor (const model of available) {\n\t\tif (model.provider === failed.provider && model.id === failed.id) continue;\n\t\tif (modelRouteFamily(model) === family) candidates.push(model);\n\t}\n\treturn candidates;\n}\n\n/**\n * Errors the agent loop may auto-retry (after optional failover / message sanitize).\n * Kept in one place so agent-session and tests share the same contract.\n */\nexport function isTransientProviderErrorMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\t// Checked first: the payload carries `invalid_request_error`, which the\n\t// pattern below treats as transient, but a stale client version never heals\n\t// by retrying.\n\tif (isClaudeCodeVersionTooOldMessage(text)) return false;\n\tif (isCodexChatgptAccountUnsupportedModelMessage(text)) return false;\n\t// `at capacity|high demand`: xAI serves overload as HTTP 429 whose body carries\n\t// no status or limit token, so the message-level classifier misses it and the\n\t// turn never auto-retries (observed 2026-09-03, xai/grok-4.6).\n\tif (\n\t\t/overloaded|at capacity|high demand|provider.?returned.?error|rate.?limit|too many requests|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|stream ended before terminal|http2 request did not get a response|timed? out|timeout|\\bterminated\\b|retry delay|content\\/safety stop|stop_reason\\s*=\\s*(refusal|sensitive)|safety stop|tool_call_id\\s+is\\s+not\\s+found|tool_call_id\\s+not\\s+found|invalid_request_error|json error injected into sse stream|injected into sse/i.test(\n\t\t\ttext,\n\t\t)\n\t) {\n\t\treturn true;\n\t}\n\t// Status-looking numbers only count with adjacent transport context — a\n\t// bare `500` in a message body (\"saved 500 records\") is not a status code.\n\treturn hasStatusCodeLike(text, [429, 500, 502, 503, 504]);\n}\n\nexport function resolveFailoverCandidates(\n\tsettings: ProviderResilienceSettings | undefined,\n): readonly FailoverCandidate[] {\n\tconst custom = settings?.failoverCandidates;\n\tif (custom && custom.length > 0) return custom;\n\treturn DEFAULT_SAFETY_FAILOVER_CANDIDATES;\n}\n\n/** Explicit `--model` / `--provider` pins stay on the requested model. */\nexport function shouldHonorSafetyFailover(options: {\n\treadonly autoFailoverOnSafetyStop: boolean;\n\treadonly modelPinned: boolean;\n\treadonly modelId?: string;\n\treadonly provider?: string;\n}): boolean {\n\tif (!options.autoFailoverOnSafetyStop || options.modelPinned) return false;\n\treturn !isNoSafetyFailoverModel(options.modelId, options.provider);\n}\n\n/** Sticky-model eject still applies unless the user pinned that model. */\nexport function shouldEjectStickySafetyModel(options: {\n\treadonly blockStickySafetyModels: boolean;\n\treadonly modelPinned: boolean;\n}): boolean {\n\treturn options.blockStickySafetyModels && !options.modelPinned;\n}\n\nexport function resolveProviderResilience(settings: ProviderResilienceSettings | undefined): {\n\treadonly blockStickySafetyModels: boolean;\n\treadonly autoFailoverOnSafetyStop: boolean;\n\treadonly failoverCandidates: readonly FailoverCandidate[];\n} {\n\treturn {\n\t\tblockStickySafetyModels: settings?.blockStickySafetyModels ?? DEFAULT_PROVIDER_RESILIENCE.blockStickySafetyModels,\n\t\tautoFailoverOnSafetyStop:\n\t\t\tsettings?.autoFailoverOnSafetyStop ?? DEFAULT_PROVIDER_RESILIENCE.autoFailoverOnSafetyStop,\n\t\tfailoverCandidates: resolveFailoverCandidates(settings),\n\t};\n}\n\n/**\n * Pick first failover candidate that is not the current model and passes `isAllowed`.\n * Pure — caller performs auth checks and setModel.\n */\nexport function pickFailoverCandidate(\n\tcandidates: readonly FailoverCandidate[],\n\tcurrent: { readonly provider?: string; readonly id?: string } | undefined,\n\tisAllowed: (candidate: FailoverCandidate) => boolean,\n): FailoverCandidate | undefined {\n\tfor (const c of candidates) {\n\t\tif (current && c.provider === current.provider && c.id === current.id) continue;\n\t\tif (isStickySafetyModel(c.id, c.provider)) continue;\n\t\tif (!isAllowed(c)) continue;\n\t\treturn c;\n\t}\n\treturn undefined;\n}\n\nexport function stickySafetyBlockMessage(modelId: string, provider: string): string {\n\treturn (\n\t\t`Blocked sticky safety model ${provider}/${modelId} (providerResilience.blockStickySafetyModels). ` +\n\t\t`Use kimi-coding/k3, modelstudio-maas/qwen3.8-max, grok-4.5, or deepseek; ` +\n\t\t`or set providerResilience.blockStickySafetyModels=false.`\n\t);\n}\n"]}
|
|
@@ -59,6 +59,21 @@ export function isQuotaExhaustionMessage(text) {
|
|
|
59
59
|
return false;
|
|
60
60
|
return /usage limit|GoUsageLimitError|FreeUsageLimitError|available balance|insufficient_quota|insufficient balance|insufficient credits|out of budget|quota exceeded|quota\s+(?:has been\s+|was\s+|is\s+)?exhaust|billing/i.test(text);
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Terminal per-candidate failures inside a failover chain: the candidate
|
|
64
|
+
* provider can never serve this request — quota/billing exhaustion, auth or
|
|
65
|
+
* entitlement denial (401/403, permission_error, authentication_error), or a
|
|
66
|
+
* permanent 4xx (unsupported model, invalid request). Absorbing them lets the
|
|
67
|
+
* chain reach the next candidate; a transient 5xx still aborts so the same
|
|
68
|
+
* model can retry instead of silently hopping providers mid-recovery.
|
|
69
|
+
*/
|
|
70
|
+
export function isTerminalProviderErrorMessage(text) {
|
|
71
|
+
if (!text)
|
|
72
|
+
return false;
|
|
73
|
+
if (isQuotaExhaustionMessage(text))
|
|
74
|
+
return true;
|
|
75
|
+
return /permission_error|authentication_error|unsupported_model|model_not_supported|invalid_api_key|unauthori[sz]ed|forbidden|does not have access|\b4(?:01|03|02|04|22)\b/i.test(text);
|
|
76
|
+
}
|
|
62
77
|
/**
|
|
63
78
|
* Anthropic rejecting the spoofed Claude Code client version because the target
|
|
64
79
|
* model is gated on a newer one (`claude_code_version_too_old`, HTTP 400).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-resilience.js","sourceRoot":"","sources":["../../src/core/provider-resilience.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provider resilience — root-level recovery for sticky safety models and\n * sanitize-and-retry protocol failures (orphan tool_call_id, terminated streams).\n *\n * This is not a jailbreak layer. It keeps sessions alive when a provider\n * false-positives or returns a sticky transcript-shape error.\n */\n\nexport type FailoverCandidate = Readonly<{\n\treadonly provider: string;\n\treadonly id: string;\n}>;\n\n/** Models known to emit high false-positive content/safety stops on coding work. */\nexport const STICKY_SAFETY_MODEL_RE = /fable/i;\n\n/** Claude lines that must stay on-model when they refuse. No DeepSeek hop. */\nexport const NO_SAFETY_FAILOVER_MODEL_RE = /(?:claude-)?(?:fable|opus|sonnet)/i;\n\n/** Default failover chain when a sticky safety model refuses a turn. */\nexport const DEFAULT_SAFETY_FAILOVER_CANDIDATES: readonly FailoverCandidate[] = [\n\t{ provider: \"kimi-coding\", id: \"k3\" },\n\t{ provider: \"modelstudio-maas\", id: \"qwen3.8-max\" },\n\t{ provider: \"xai\", id: \"grok-4.5\" },\n\t{ provider: \"deepseek\", id: \"deepseek-v4-pro\" },\n\t{ provider: \"deepseek\", id: \"deepseek-v4-flash\" },\n\t{ provider: \"modelstudio-maas\", id: \"deepseek-v4-pro\" },\n\t{ provider: \"kimi-coding\", id: \"kimi-for-coding\" },\n] as const;\n\nexport type ProviderResilienceSettings = Readonly<{\n\t/** When true (default), refuse selecting sticky safety models (e.g. claude-fable-5). */\n\treadonly blockStickySafetyModels?: boolean;\n\t/** When true (default), auto-switch model on content/safety stop before retry. */\n\treadonly autoFailoverOnSafetyStop?: boolean;\n\t/** Ordered failover targets. Falls back to DEFAULT_SAFETY_FAILOVER_CANDIDATES. */\n\treadonly failoverCandidates?: readonly FailoverCandidate[];\n}>;\n\nexport const DEFAULT_PROVIDER_RESILIENCE: Required<\n\tPick<ProviderResilienceSettings, \"blockStickySafetyModels\" | \"autoFailoverOnSafetyStop\">\n> & {\n\treadonly failoverCandidates: readonly FailoverCandidate[];\n} = {\n\tblockStickySafetyModels: true,\n\tautoFailoverOnSafetyStop: true,\n\tfailoverCandidates: DEFAULT_SAFETY_FAILOVER_CANDIDATES,\n};\n\nexport function isStickySafetyModel(modelId: string | undefined, provider?: string | undefined): boolean {\n\tconst id = (modelId ?? \"\").trim();\n\tif (!id) return false;\n\tif (STICKY_SAFETY_MODEL_RE.test(id)) return true;\n\tconst p = (provider ?? \"\").toLowerCase();\n\treturn p.includes(\"anthropic\") && STICKY_SAFETY_MODEL_RE.test(id);\n}\n\n/** Fable / Opus / Sonnet stay on the requested id after a safety stop. */\nexport function isNoSafetyFailoverModel(modelId: string | undefined, provider?: string | undefined): boolean {\n\tconst id = (modelId ?? \"\").trim();\n\tif (!id) return false;\n\tif (NO_SAFETY_FAILOVER_MODEL_RE.test(id)) return true;\n\tconst p = (provider ?? \"\").toLowerCase();\n\treturn p.includes(\"anthropic\") && NO_SAFETY_FAILOVER_MODEL_RE.test(id);\n}\n\nexport function isContentSafetyStopMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /content\\/safety stop|stop_reason\\s*=\\s*(refusal|sensitive)|safety stop|provider\\.refusal|kind=provider_refusal/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Billing/quota exhaustion (\"usage limit for this billing cycle\",\n * \"insufficient_quota\", zero balance, ...). Same-model retry is useless until\n * the cycle resets, but the turn can still be saved by failing over to another\n * candidate — so these classify as retryable-with-failover, not auth-fatal.\n */\nexport function isQuotaExhaustionMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /usage limit|GoUsageLimitError|FreeUsageLimitError|available balance|insufficient_quota|insufficient balance|insufficient credits|out of budget|quota exceeded|quota\\s+(?:has been\\s+|was\\s+|is\\s+)?exhaust|billing/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Anthropic rejecting the spoofed Claude Code client version because the target\n * model is gated on a newer one (`claude_code_version_too_old`, HTTP 400).\n * Permanent for this build: every retry and every failover re-sends the same\n * user-agent, so the fix is bumping `CLAUDE_CODE_VERSION` in omk-ai (or\n * selecting an ungated model).\n */\nexport function isClaudeCodeVersionTooOldMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /claude_code_version_too_old|does not support this model;\\s*version\\s+[\\d.]+\\s+or newer is required/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Codex HTTP 400 when a ChatGPT-account OAuth session asks for a model the\n * account catalog does not serve (`gpt-6-astra` during the 2026-09-04 rollout).\n * Permanent for this login: same-model retry, transcript sanitize, and /new\n * session all re-send the same slug and get the same 400. Switch model or use\n * an API-key route that has the model.\n */\nexport function isCodexChatgptAccountUnsupportedModelMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /model is not supported when using Codex with a ChatGPT account/i.test(text);\n}\n\n/** Orphan tool results / Kimi-K3 protocol shape errors that heal after sanitize+retry. */\nexport function isOrphanToolCallIdError(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /tool_call_id\\s+is\\s+not\\s+found|tool_call_id\\s+not\\s+found|unknown\\s+tool_call_id/i.test(text);\n}\n\n/**\n * Status-code-context match: a bare `500` inside a message body (\"saved 500\n * records\") is not a status code, so numeric matches require an adjacent\n * transport word — either a code-context word before the digits (\"HTTP 429\",\n * \"error 503\", \"status 401\") or a status-context word after them (\"503\n * Upstream request failed\", \"429 Too Many Requests\", \"500 Internal Server\n * Error\"). Structured `status`/`errorCode` fields on the caller's side still\n * outrank this text heuristic entirely.\n */\nexport function hasStatusCodeLike(text: string, codes: readonly number[]): boolean {\n\tconst left = /(?:https?|status(?:\\s*code)?|error(?:\\s*code)?|code)\\s*:?\\s*(\\d{3})\\b/gi;\n\tconst right =\n\t\t/\\b(\\d{3})\\s+(?:too many|upstream|bad gateway|service unavailable|internal server|gateway|error|status|request failed|timed? ?out|unauthori[sz]ed|forbidden)/gi;\n\tfor (const re of [left, right]) {\n\t\tre.lastIndex = 0;\n\t\tfor (;;) {\n\t\t\tconst match = re.exec(text);\n\t\t\tif (match === null) break;\n\t\t\tif (codes.includes(Number.parseInt(match[1], 10))) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Transient upstream availability failures: gateway 5xx passthroughs\n * (\"503 Upstream request failed\", \"Endpoint is unavailable\") and dropped\n * streams that never carried a finish reason (\"Stream ended without\n * finish_reason\"). Transport problems, not transcript-shape problems — they\n * heal by backoff/retry or switching model, never by transcript sanitization.\n */\nexport function isUpstreamUnavailableMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn (\n\t\t/upstream(?: request)? failed|upstream connect|endpoint (?:is )?unavailable|stream ended without finish_reason/i.test(\n\t\t\ttext,\n\t\t) || hasStatusCodeLike(text, [500, 502, 503, 504])\n\t);\n}\n\n/**\n * Route families: the same underlying model served by several provider\n * routes. Matched on the model id OR display name so alias routes like\n * `openrouter/stealth/ox-alpha`, `opencode-go/ox-alpha-free`, and\n * `opencode/x-preview-f-free` (\"Ox Alpha Free (Unlimited)\") rotate as one\n * ox-alpha family.\n */\nconst MODEL_ROUTE_FAMILIES: readonly { readonly pattern: RegExp; readonly family: string }[] = [\n\t{ pattern: /(?:^|[-_/])ox[-_ ]?alpha(?:[-_/\\s(]|$)/i, family: \"ox-alpha\" },\n\t// union-alpha is served by opencode-go/union-alpha (anthropic-messages) and\n\t// openrouter/stealth/union-alpha (openai-completions); both map to one family\n\t// so an upstream-unavailable 503/empty stream rotates to the live route.\n\t{ pattern: /(?:^|[-_/])union[-_ ]?alpha(?:[-_/\\s(]|$)/i, family: \"union-alpha\" },\n];\n\n/** Family key for a model route, or undefined when it has no known alias group. */\nexport function modelRouteFamily(model: {\n\treadonly provider?: string | undefined;\n\treadonly id: string;\n\treadonly name?: string | undefined;\n}): string | undefined {\n\tfor (const { pattern, family } of MODEL_ROUTE_FAMILIES) {\n\t\tif (pattern.test(model.id)) return family;\n\t\tif (model.name && pattern.test(model.name)) return family;\n\t}\n\treturn undefined;\n}\n\n/**\n * Alternative provider routes serving the same model family as\n * {@link failed}, in registry order, excluding the failed route itself.\n * Callers filter by authentication and per-turn failure bookkeeping.\n */\nexport function sameModelRouteCandidates<\n\tT extends { readonly provider: string; readonly id: string; readonly name?: string | undefined },\n>(\n\tfailed: { readonly provider: string; readonly id: string; readonly name?: string | undefined },\n\tavailable: readonly T[],\n): T[] {\n\tconst family = modelRouteFamily(failed);\n\tif (!family) return [];\n\tconst candidates: T[] = [];\n\tfor (const model of available) {\n\t\tif (model.provider === failed.provider && model.id === failed.id) continue;\n\t\tif (modelRouteFamily(model) === family) candidates.push(model);\n\t}\n\treturn candidates;\n}\n\n/**\n * Errors the agent loop may auto-retry (after optional failover / message sanitize).\n * Kept in one place so agent-session and tests share the same contract.\n */\nexport function isTransientProviderErrorMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\t// Checked first: the payload carries `invalid_request_error`, which the\n\t// pattern below treats as transient, but a stale client version never heals\n\t// by retrying.\n\tif (isClaudeCodeVersionTooOldMessage(text)) return false;\n\tif (isCodexChatgptAccountUnsupportedModelMessage(text)) return false;\n\t// `at capacity|high demand`: xAI serves overload as HTTP 429 whose body carries\n\t// no status or limit token, so the message-level classifier misses it and the\n\t// turn never auto-retries (observed 2026-09-03, xai/grok-4.6).\n\tif (\n\t\t/overloaded|at capacity|high demand|provider.?returned.?error|rate.?limit|too many requests|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|stream ended before terminal|http2 request did not get a response|timed? out|timeout|\\bterminated\\b|retry delay|content\\/safety stop|stop_reason\\s*=\\s*(refusal|sensitive)|safety stop|tool_call_id\\s+is\\s+not\\s+found|tool_call_id\\s+not\\s+found|invalid_request_error|json error injected into sse stream|injected into sse/i.test(\n\t\t\ttext,\n\t\t)\n\t) {\n\t\treturn true;\n\t}\n\t// Status-looking numbers only count with adjacent transport context — a\n\t// bare `500` in a message body (\"saved 500 records\") is not a status code.\n\treturn hasStatusCodeLike(text, [429, 500, 502, 503, 504]);\n}\n\nexport function resolveFailoverCandidates(\n\tsettings: ProviderResilienceSettings | undefined,\n): readonly FailoverCandidate[] {\n\tconst custom = settings?.failoverCandidates;\n\tif (custom && custom.length > 0) return custom;\n\treturn DEFAULT_SAFETY_FAILOVER_CANDIDATES;\n}\n\n/** Explicit `--model` / `--provider` pins stay on the requested model. */\nexport function shouldHonorSafetyFailover(options: {\n\treadonly autoFailoverOnSafetyStop: boolean;\n\treadonly modelPinned: boolean;\n\treadonly modelId?: string;\n\treadonly provider?: string;\n}): boolean {\n\tif (!options.autoFailoverOnSafetyStop || options.modelPinned) return false;\n\treturn !isNoSafetyFailoverModel(options.modelId, options.provider);\n}\n\n/** Sticky-model eject still applies unless the user pinned that model. */\nexport function shouldEjectStickySafetyModel(options: {\n\treadonly blockStickySafetyModels: boolean;\n\treadonly modelPinned: boolean;\n}): boolean {\n\treturn options.blockStickySafetyModels && !options.modelPinned;\n}\n\nexport function resolveProviderResilience(settings: ProviderResilienceSettings | undefined): {\n\treadonly blockStickySafetyModels: boolean;\n\treadonly autoFailoverOnSafetyStop: boolean;\n\treadonly failoverCandidates: readonly FailoverCandidate[];\n} {\n\treturn {\n\t\tblockStickySafetyModels: settings?.blockStickySafetyModels ?? DEFAULT_PROVIDER_RESILIENCE.blockStickySafetyModels,\n\t\tautoFailoverOnSafetyStop:\n\t\t\tsettings?.autoFailoverOnSafetyStop ?? DEFAULT_PROVIDER_RESILIENCE.autoFailoverOnSafetyStop,\n\t\tfailoverCandidates: resolveFailoverCandidates(settings),\n\t};\n}\n\n/**\n * Pick first failover candidate that is not the current model and passes `isAllowed`.\n * Pure — caller performs auth checks and setModel.\n */\nexport function pickFailoverCandidate(\n\tcandidates: readonly FailoverCandidate[],\n\tcurrent: { readonly provider?: string; readonly id?: string } | undefined,\n\tisAllowed: (candidate: FailoverCandidate) => boolean,\n): FailoverCandidate | undefined {\n\tfor (const c of candidates) {\n\t\tif (current && c.provider === current.provider && c.id === current.id) continue;\n\t\tif (isStickySafetyModel(c.id, c.provider)) continue;\n\t\tif (!isAllowed(c)) continue;\n\t\treturn c;\n\t}\n\treturn undefined;\n}\n\nexport function stickySafetyBlockMessage(modelId: string, provider: string): string {\n\treturn (\n\t\t`Blocked sticky safety model ${provider}/${modelId} (providerResilience.blockStickySafetyModels). ` +\n\t\t`Use kimi-coding/k3, modelstudio-maas/qwen3.8-max, grok-4.5, or deepseek; ` +\n\t\t`or set providerResilience.blockStickySafetyModels=false.`\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"provider-resilience.js","sourceRoot":"","sources":["../../src/core/provider-resilience.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provider resilience — root-level recovery for sticky safety models and\n * sanitize-and-retry protocol failures (orphan tool_call_id, terminated streams).\n *\n * This is not a jailbreak layer. It keeps sessions alive when a provider\n * false-positives or returns a sticky transcript-shape error.\n */\n\nexport type FailoverCandidate = Readonly<{\n\treadonly provider: string;\n\treadonly id: string;\n}>;\n\n/** Models known to emit high false-positive content/safety stops on coding work. */\nexport const STICKY_SAFETY_MODEL_RE = /fable/i;\n\n/** Claude lines that must stay on-model when they refuse. No DeepSeek hop. */\nexport const NO_SAFETY_FAILOVER_MODEL_RE = /(?:claude-)?(?:fable|opus|sonnet)/i;\n\n/** Default failover chain when a sticky safety model refuses a turn. */\nexport const DEFAULT_SAFETY_FAILOVER_CANDIDATES: readonly FailoverCandidate[] = [\n\t{ provider: \"kimi-coding\", id: \"k3\" },\n\t{ provider: \"modelstudio-maas\", id: \"qwen3.8-max\" },\n\t{ provider: \"xai\", id: \"grok-4.5\" },\n\t{ provider: \"deepseek\", id: \"deepseek-v4-pro\" },\n\t{ provider: \"deepseek\", id: \"deepseek-v4-flash\" },\n\t{ provider: \"modelstudio-maas\", id: \"deepseek-v4-pro\" },\n\t{ provider: \"kimi-coding\", id: \"kimi-for-coding\" },\n] as const;\n\nexport type ProviderResilienceSettings = Readonly<{\n\t/** When true (default), refuse selecting sticky safety models (e.g. claude-fable-5). */\n\treadonly blockStickySafetyModels?: boolean;\n\t/** When true (default), auto-switch model on content/safety stop before retry. */\n\treadonly autoFailoverOnSafetyStop?: boolean;\n\t/** Ordered failover targets. Falls back to DEFAULT_SAFETY_FAILOVER_CANDIDATES. */\n\treadonly failoverCandidates?: readonly FailoverCandidate[];\n}>;\n\nexport const DEFAULT_PROVIDER_RESILIENCE: Required<\n\tPick<ProviderResilienceSettings, \"blockStickySafetyModels\" | \"autoFailoverOnSafetyStop\">\n> & {\n\treadonly failoverCandidates: readonly FailoverCandidate[];\n} = {\n\tblockStickySafetyModels: true,\n\tautoFailoverOnSafetyStop: true,\n\tfailoverCandidates: DEFAULT_SAFETY_FAILOVER_CANDIDATES,\n};\n\nexport function isStickySafetyModel(modelId: string | undefined, provider?: string | undefined): boolean {\n\tconst id = (modelId ?? \"\").trim();\n\tif (!id) return false;\n\tif (STICKY_SAFETY_MODEL_RE.test(id)) return true;\n\tconst p = (provider ?? \"\").toLowerCase();\n\treturn p.includes(\"anthropic\") && STICKY_SAFETY_MODEL_RE.test(id);\n}\n\n/** Fable / Opus / Sonnet stay on the requested id after a safety stop. */\nexport function isNoSafetyFailoverModel(modelId: string | undefined, provider?: string | undefined): boolean {\n\tconst id = (modelId ?? \"\").trim();\n\tif (!id) return false;\n\tif (NO_SAFETY_FAILOVER_MODEL_RE.test(id)) return true;\n\tconst p = (provider ?? \"\").toLowerCase();\n\treturn p.includes(\"anthropic\") && NO_SAFETY_FAILOVER_MODEL_RE.test(id);\n}\n\nexport function isContentSafetyStopMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /content\\/safety stop|stop_reason\\s*=\\s*(refusal|sensitive)|safety stop|provider\\.refusal|kind=provider_refusal/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Billing/quota exhaustion (\"usage limit for this billing cycle\",\n * \"insufficient_quota\", zero balance, ...). Same-model retry is useless until\n * the cycle resets, but the turn can still be saved by failing over to another\n * candidate — so these classify as retryable-with-failover, not auth-fatal.\n */\nexport function isQuotaExhaustionMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /usage limit|GoUsageLimitError|FreeUsageLimitError|available balance|insufficient_quota|insufficient balance|insufficient credits|out of budget|quota exceeded|quota\\s+(?:has been\\s+|was\\s+|is\\s+)?exhaust|billing/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Terminal per-candidate failures inside a failover chain: the candidate\n * provider can never serve this request — quota/billing exhaustion, auth or\n * entitlement denial (401/403, permission_error, authentication_error), or a\n * permanent 4xx (unsupported model, invalid request). Absorbing them lets the\n * chain reach the next candidate; a transient 5xx still aborts so the same\n * model can retry instead of silently hopping providers mid-recovery.\n */\nexport function isTerminalProviderErrorMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\tif (isQuotaExhaustionMessage(text)) return true;\n\treturn /permission_error|authentication_error|unsupported_model|model_not_supported|invalid_api_key|unauthori[sz]ed|forbidden|does not have access|\\b4(?:01|03|02|04|22)\\b/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Anthropic rejecting the spoofed Claude Code client version because the target\n * model is gated on a newer one (`claude_code_version_too_old`, HTTP 400).\n * Permanent for this build: every retry and every failover re-sends the same\n * user-agent, so the fix is bumping `CLAUDE_CODE_VERSION` in omk-ai (or\n * selecting an ungated model).\n */\nexport function isClaudeCodeVersionTooOldMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /claude_code_version_too_old|does not support this model;\\s*version\\s+[\\d.]+\\s+or newer is required/i.test(\n\t\ttext,\n\t);\n}\n\n/**\n * Codex HTTP 400 when a ChatGPT-account OAuth session asks for a model the\n * account catalog does not serve (`gpt-6-astra` during the 2026-09-04 rollout).\n * Permanent for this login: same-model retry, transcript sanitize, and /new\n * session all re-send the same slug and get the same 400. Switch model or use\n * an API-key route that has the model.\n */\nexport function isCodexChatgptAccountUnsupportedModelMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /model is not supported when using Codex with a ChatGPT account/i.test(text);\n}\n\n/** Orphan tool results / Kimi-K3 protocol shape errors that heal after sanitize+retry. */\nexport function isOrphanToolCallIdError(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn /tool_call_id\\s+is\\s+not\\s+found|tool_call_id\\s+not\\s+found|unknown\\s+tool_call_id/i.test(text);\n}\n\n/**\n * Status-code-context match: a bare `500` inside a message body (\"saved 500\n * records\") is not a status code, so numeric matches require an adjacent\n * transport word — either a code-context word before the digits (\"HTTP 429\",\n * \"error 503\", \"status 401\") or a status-context word after them (\"503\n * Upstream request failed\", \"429 Too Many Requests\", \"500 Internal Server\n * Error\"). Structured `status`/`errorCode` fields on the caller's side still\n * outrank this text heuristic entirely.\n */\nexport function hasStatusCodeLike(text: string, codes: readonly number[]): boolean {\n\tconst left = /(?:https?|status(?:\\s*code)?|error(?:\\s*code)?|code)\\s*:?\\s*(\\d{3})\\b/gi;\n\tconst right =\n\t\t/\\b(\\d{3})\\s+(?:too many|upstream|bad gateway|service unavailable|internal server|gateway|error|status|request failed|timed? ?out|unauthori[sz]ed|forbidden)/gi;\n\tfor (const re of [left, right]) {\n\t\tre.lastIndex = 0;\n\t\tfor (;;) {\n\t\t\tconst match = re.exec(text);\n\t\t\tif (match === null) break;\n\t\t\tif (codes.includes(Number.parseInt(match[1], 10))) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Transient upstream availability failures: gateway 5xx passthroughs\n * (\"503 Upstream request failed\", \"Endpoint is unavailable\") and dropped\n * streams that never carried a finish reason (\"Stream ended without\n * finish_reason\"). Transport problems, not transcript-shape problems — they\n * heal by backoff/retry or switching model, never by transcript sanitization.\n */\nexport function isUpstreamUnavailableMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\treturn (\n\t\t/upstream(?: request)? failed|upstream connect|endpoint (?:is )?unavailable|stream ended without finish_reason/i.test(\n\t\t\ttext,\n\t\t) || hasStatusCodeLike(text, [500, 502, 503, 504])\n\t);\n}\n\n/**\n * Route families: the same underlying model served by several provider\n * routes. Matched on the model id OR display name so alias routes like\n * `openrouter/stealth/ox-alpha`, `opencode-go/ox-alpha-free`, and\n * `opencode/x-preview-f-free` (\"Ox Alpha Free (Unlimited)\") rotate as one\n * ox-alpha family.\n */\nconst MODEL_ROUTE_FAMILIES: readonly { readonly pattern: RegExp; readonly family: string }[] = [\n\t{ pattern: /(?:^|[-_/])ox[-_ ]?alpha(?:[-_/\\s(]|$)/i, family: \"ox-alpha\" },\n\t// union-alpha is served by opencode-go/union-alpha (anthropic-messages) and\n\t// openrouter/stealth/union-alpha (openai-completions); both map to one family\n\t// so an upstream-unavailable 503/empty stream rotates to the live route.\n\t{ pattern: /(?:^|[-_/])union[-_ ]?alpha(?:[-_/\\s(]|$)/i, family: \"union-alpha\" },\n];\n\n/** Family key for a model route, or undefined when it has no known alias group. */\nexport function modelRouteFamily(model: {\n\treadonly provider?: string | undefined;\n\treadonly id: string;\n\treadonly name?: string | undefined;\n}): string | undefined {\n\tfor (const { pattern, family } of MODEL_ROUTE_FAMILIES) {\n\t\tif (pattern.test(model.id)) return family;\n\t\tif (model.name && pattern.test(model.name)) return family;\n\t}\n\treturn undefined;\n}\n\n/**\n * Alternative provider routes serving the same model family as\n * {@link failed}, in registry order, excluding the failed route itself.\n * Callers filter by authentication and per-turn failure bookkeeping.\n */\nexport function sameModelRouteCandidates<\n\tT extends { readonly provider: string; readonly id: string; readonly name?: string | undefined },\n>(\n\tfailed: { readonly provider: string; readonly id: string; readonly name?: string | undefined },\n\tavailable: readonly T[],\n): T[] {\n\tconst family = modelRouteFamily(failed);\n\tif (!family) return [];\n\tconst candidates: T[] = [];\n\tfor (const model of available) {\n\t\tif (model.provider === failed.provider && model.id === failed.id) continue;\n\t\tif (modelRouteFamily(model) === family) candidates.push(model);\n\t}\n\treturn candidates;\n}\n\n/**\n * Errors the agent loop may auto-retry (after optional failover / message sanitize).\n * Kept in one place so agent-session and tests share the same contract.\n */\nexport function isTransientProviderErrorMessage(text: string | undefined): boolean {\n\tif (!text) return false;\n\t// Checked first: the payload carries `invalid_request_error`, which the\n\t// pattern below treats as transient, but a stale client version never heals\n\t// by retrying.\n\tif (isClaudeCodeVersionTooOldMessage(text)) return false;\n\tif (isCodexChatgptAccountUnsupportedModelMessage(text)) return false;\n\t// `at capacity|high demand`: xAI serves overload as HTTP 429 whose body carries\n\t// no status or limit token, so the message-level classifier misses it and the\n\t// turn never auto-retries (observed 2026-09-03, xai/grok-4.6).\n\tif (\n\t\t/overloaded|at capacity|high demand|provider.?returned.?error|rate.?limit|too many requests|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|stream ended before terminal|http2 request did not get a response|timed? out|timeout|\\bterminated\\b|retry delay|content\\/safety stop|stop_reason\\s*=\\s*(refusal|sensitive)|safety stop|tool_call_id\\s+is\\s+not\\s+found|tool_call_id\\s+not\\s+found|invalid_request_error|json error injected into sse stream|injected into sse/i.test(\n\t\t\ttext,\n\t\t)\n\t) {\n\t\treturn true;\n\t}\n\t// Status-looking numbers only count with adjacent transport context — a\n\t// bare `500` in a message body (\"saved 500 records\") is not a status code.\n\treturn hasStatusCodeLike(text, [429, 500, 502, 503, 504]);\n}\n\nexport function resolveFailoverCandidates(\n\tsettings: ProviderResilienceSettings | undefined,\n): readonly FailoverCandidate[] {\n\tconst custom = settings?.failoverCandidates;\n\tif (custom && custom.length > 0) return custom;\n\treturn DEFAULT_SAFETY_FAILOVER_CANDIDATES;\n}\n\n/** Explicit `--model` / `--provider` pins stay on the requested model. */\nexport function shouldHonorSafetyFailover(options: {\n\treadonly autoFailoverOnSafetyStop: boolean;\n\treadonly modelPinned: boolean;\n\treadonly modelId?: string;\n\treadonly provider?: string;\n}): boolean {\n\tif (!options.autoFailoverOnSafetyStop || options.modelPinned) return false;\n\treturn !isNoSafetyFailoverModel(options.modelId, options.provider);\n}\n\n/** Sticky-model eject still applies unless the user pinned that model. */\nexport function shouldEjectStickySafetyModel(options: {\n\treadonly blockStickySafetyModels: boolean;\n\treadonly modelPinned: boolean;\n}): boolean {\n\treturn options.blockStickySafetyModels && !options.modelPinned;\n}\n\nexport function resolveProviderResilience(settings: ProviderResilienceSettings | undefined): {\n\treadonly blockStickySafetyModels: boolean;\n\treadonly autoFailoverOnSafetyStop: boolean;\n\treadonly failoverCandidates: readonly FailoverCandidate[];\n} {\n\treturn {\n\t\tblockStickySafetyModels: settings?.blockStickySafetyModels ?? DEFAULT_PROVIDER_RESILIENCE.blockStickySafetyModels,\n\t\tautoFailoverOnSafetyStop:\n\t\t\tsettings?.autoFailoverOnSafetyStop ?? DEFAULT_PROVIDER_RESILIENCE.autoFailoverOnSafetyStop,\n\t\tfailoverCandidates: resolveFailoverCandidates(settings),\n\t};\n}\n\n/**\n * Pick first failover candidate that is not the current model and passes `isAllowed`.\n * Pure — caller performs auth checks and setModel.\n */\nexport function pickFailoverCandidate(\n\tcandidates: readonly FailoverCandidate[],\n\tcurrent: { readonly provider?: string; readonly id?: string } | undefined,\n\tisAllowed: (candidate: FailoverCandidate) => boolean,\n): FailoverCandidate | undefined {\n\tfor (const c of candidates) {\n\t\tif (current && c.provider === current.provider && c.id === current.id) continue;\n\t\tif (isStickySafetyModel(c.id, c.provider)) continue;\n\t\tif (!isAllowed(c)) continue;\n\t\treturn c;\n\t}\n\treturn undefined;\n}\n\nexport function stickySafetyBlockMessage(modelId: string, provider: string): string {\n\treturn (\n\t\t`Blocked sticky safety model ${provider}/${modelId} (providerResilience.blockStickySafetyModels). ` +\n\t\t`Use kimi-coding/k3, modelstudio-maas/qwen3.8-max, grok-4.5, or deepseek; ` +\n\t\t`or set providerResilience.blockStickySafetyModels=false.`\n\t);\n}\n"]}
|
|
@@ -36,6 +36,13 @@ export declare function clampToAvailable(targetIndex: number, availableLevels: r
|
|
|
36
36
|
* -> optional hint fusion (bounded ±BIAS_MAX steps toward hint.level, only
|
|
37
37
|
* when hint.confidence >= HINT_CONFIDENCE_THRESHOLD) -> non-negative
|
|
38
38
|
* escalationSteps bump -> clamp to availableLevels.
|
|
39
|
+
*
|
|
40
|
+
* `bias` and `escalationSteps` are normalized to finite integers first (see
|
|
41
|
+
* {@link normalizeLadderSteps}); callers that need to reject invalid numbers
|
|
42
|
+
* must validate before calling, as the session's bias-snapshot validator does.
|
|
43
|
+
* The escalation term is monotone at a fixed bias and hint only: it is not a
|
|
44
|
+
* floor at the class base level, because a negative bias applied earlier can
|
|
45
|
+
* outweigh it.
|
|
39
46
|
*/
|
|
40
47
|
export declare function resolveThinkingLevelCore(taskClass: ReasoningTaskClass, availableLevels: readonly ThinkingLevel[], laneType: ReasoningLane | undefined, bias: number, hint: {
|
|
41
48
|
level: ThinkingLevel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reasoning-router-resolver.d.ts","sourceRoot":"","sources":["../../src/core/reasoning-router-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,mDAAmD;AACnD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEnH,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAElG,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAAkE,CAAC;AAExH,iIAAiI;AACjI,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAQ1F,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAItE,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"reasoning-router-resolver.d.ts","sourceRoot":"","sources":["../../src/core/reasoning-router-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,mDAAmD;AACnD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEnH,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAElG,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAAkE,CAAC;AAExH,iIAAiI;AACjI,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAQ1F,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAItE,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAiB7C;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,CAU9G;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACvC,SAAS,EAAE,kBAAkB,EAC7B,eAAe,EAAE,SAAS,aAAa,EAAE,EACzC,QAAQ,EAAE,aAAa,GAAG,SAAS,EACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EACzD,eAAe,EAAE,MAAM,GACrB,aAAa,CAqBf","sourcesContent":["/**\n * Shared resolver core for the v4 reasoning router: canonical task-class ->\n * ThinkingLevel rule table, lane-step adjustment, ladder-index clamping, and\n * bounded bias/hint/escalation resolution logic.\n *\n * Deterministic, side-effect-free: no clock, randomness, or I/O.\n */\n\nimport type { ThinkingLevel } from \"omk-agent-core\";\n\n/** The 7-class union used by the v4 classifier. */\nexport type ReasoningTaskClass = \"trivial\" | \"simple-edit\" | \"code-gen\" | \"debug\" | \"refactor\" | \"review\" | \"plan\";\n\n/** The 6-lane union used by the v4 classifier. */\nexport type ReasoningLane = \"planner\" | \"security\" | \"explorer\" | \"coder\" | \"reviewer\" | \"tester\";\n\n/** Reasoning ladder used for targets and clamping. Intentionally excludes \"off\". */\nexport const REASONING_LADDER: readonly ThinkingLevel[] = [\"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\", \"ultra\"];\n\n/** Static rule table: task class -> recommended ThinkingLevel (before lane adjustment, bias, hint, escalation, and clamping). */\nexport const TASK_CLASS_THINKING_LEVELS: Readonly<Record<ReasoningTaskClass, ThinkingLevel>> = {\n\ttrivial: \"minimal\",\n\t\"simple-edit\": \"low\",\n\t\"code-gen\": \"medium\",\n\tdebug: \"high\",\n\trefactor: \"high\",\n\treview: \"high\",\n\tplan: \"xhigh\",\n};\n\n/** Lane adjustment in ladder steps: planner/security escalate, explorer de-escalates. */\nexport const LANE_STEP: Readonly<Partial<Record<ReasoningLane, 1 | -1>>> = {\n\tplanner: 1,\n\tsecurity: 1,\n\texplorer: -1,\n};\n\n/** Maximum magnitude of the learning/consult bias (ladder steps). */\nexport const BIAS_MAX = 2;\n/** Confidence floor at which an override hint is fused into the target. */\nexport const HINT_CONFIDENCE_THRESHOLD = 0.7;\n\nfunction clampToLadderIndex(index: number): number {\n\treturn Math.max(0, Math.min(index, REASONING_LADDER.length - 1));\n}\n\n/**\n * Ladder steps are integers. A non-finite step is neutralized to 0 and a\n * fraction is truncated toward zero, so a corrupted `bias` or escalation\n * keeps the class's own level instead of walking the lookup off the integer\n * rungs (a `3.5` target matches no rung and used to fall to the lowest\n * available level; `NaN` did the same, `±Infinity` saturated the clamp).\n */\nfunction normalizeLadderSteps(steps: number): number {\n\treturn Number.isFinite(steps) ? Math.trunc(steps) : 0;\n}\n\n/**\n * Clamp a target ladder index to capability: the highest level in\n * `availableLevels` that is <= the target; if no available level is at/below\n * the target, return the lowest available reasoning level. Never invents a\n * level outside `availableLevels`. `\"off\"` is only returned when\n * `availableLevels` is empty (callers are expected to bypass the router\n * entirely for models with `reasoning: false`).\n */\nexport function clampToAvailable(targetIndex: number, availableLevels: readonly ThinkingLevel[]): ThinkingLevel {\n\tconst availableOnLadder = REASONING_LADDER.filter((level) => availableLevels.includes(level));\n\tif (availableOnLadder.length === 0) {\n\t\treturn availableLevels[0] ?? \"off\";\n\t}\n\tfor (let i = targetIndex; i >= 0; i--) {\n\t\tconst candidate = REASONING_LADDER[i];\n\t\tif (availableOnLadder.includes(candidate)) return candidate;\n\t}\n\treturn availableOnLadder[0];\n}\n\n/**\n * Canonical resolver core for v4.\n *\n * Pipeline: base rule table -> lane step -> bounded bias [-BIAS_MAX,+BIAS_MAX]\n * -> optional hint fusion (bounded ±BIAS_MAX steps toward hint.level, only\n * when hint.confidence >= HINT_CONFIDENCE_THRESHOLD) -> non-negative\n * escalationSteps bump -> clamp to availableLevels.\n *\n * `bias` and `escalationSteps` are normalized to finite integers first (see\n * {@link normalizeLadderSteps}); callers that need to reject invalid numbers\n * must validate before calling, as the session's bias-snapshot validator does.\n * The escalation term is monotone at a fixed bias and hint only: it is not a\n * floor at the class base level, because a negative bias applied earlier can\n * outweigh it.\n */\nexport function resolveThinkingLevelCore(\n\ttaskClass: ReasoningTaskClass,\n\tavailableLevels: readonly ThinkingLevel[],\n\tlaneType: ReasoningLane | undefined,\n\tbias: number,\n\thint: { level: ThinkingLevel; confidence: number } | null,\n\tescalationSteps: number,\n): ThinkingLevel {\n\tconst baseIndex = REASONING_LADDER.indexOf(TASK_CLASS_THINKING_LEVELS[taskClass]);\n\tconst laneStep = laneType ? (LANE_STEP[laneType] ?? 0) : 0;\n\tconst biasClamped = Math.max(-BIAS_MAX, Math.min(BIAS_MAX, normalizeLadderSteps(bias)));\n\tlet targetIndex = clampToLadderIndex(baseIndex + laneStep + biasClamped);\n\n\tif (hint !== null && hint.confidence >= HINT_CONFIDENCE_THRESHOLD) {\n\t\tconst hintIndex = REASONING_LADDER.indexOf(hint.level);\n\t\tif (hintIndex >= 0) {\n\t\t\tconst delta = hintIndex - targetIndex;\n\t\t\tconst step = Math.max(-BIAS_MAX, Math.min(BIAS_MAX, delta));\n\t\t\ttargetIndex = clampToLadderIndex(targetIndex + step);\n\t\t}\n\t}\n\n\tconst escalation = normalizeLadderSteps(escalationSteps);\n\tif (escalation > 0) {\n\t\ttargetIndex = clampToLadderIndex(targetIndex + escalation);\n\t}\n\n\treturn clampToAvailable(targetIndex, availableLevels);\n}\n"]}
|
|
@@ -30,6 +30,16 @@ export const HINT_CONFIDENCE_THRESHOLD = 0.7;
|
|
|
30
30
|
function clampToLadderIndex(index) {
|
|
31
31
|
return Math.max(0, Math.min(index, REASONING_LADDER.length - 1));
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Ladder steps are integers. A non-finite step is neutralized to 0 and a
|
|
35
|
+
* fraction is truncated toward zero, so a corrupted `bias` or escalation
|
|
36
|
+
* keeps the class's own level instead of walking the lookup off the integer
|
|
37
|
+
* rungs (a `3.5` target matches no rung and used to fall to the lowest
|
|
38
|
+
* available level; `NaN` did the same, `±Infinity` saturated the clamp).
|
|
39
|
+
*/
|
|
40
|
+
function normalizeLadderSteps(steps) {
|
|
41
|
+
return Number.isFinite(steps) ? Math.trunc(steps) : 0;
|
|
42
|
+
}
|
|
33
43
|
/**
|
|
34
44
|
* Clamp a target ladder index to capability: the highest level in
|
|
35
45
|
* `availableLevels` that is <= the target; if no available level is at/below
|
|
@@ -57,11 +67,18 @@ export function clampToAvailable(targetIndex, availableLevels) {
|
|
|
57
67
|
* -> optional hint fusion (bounded ±BIAS_MAX steps toward hint.level, only
|
|
58
68
|
* when hint.confidence >= HINT_CONFIDENCE_THRESHOLD) -> non-negative
|
|
59
69
|
* escalationSteps bump -> clamp to availableLevels.
|
|
70
|
+
*
|
|
71
|
+
* `bias` and `escalationSteps` are normalized to finite integers first (see
|
|
72
|
+
* {@link normalizeLadderSteps}); callers that need to reject invalid numbers
|
|
73
|
+
* must validate before calling, as the session's bias-snapshot validator does.
|
|
74
|
+
* The escalation term is monotone at a fixed bias and hint only: it is not a
|
|
75
|
+
* floor at the class base level, because a negative bias applied earlier can
|
|
76
|
+
* outweigh it.
|
|
60
77
|
*/
|
|
61
78
|
export function resolveThinkingLevelCore(taskClass, availableLevels, laneType, bias, hint, escalationSteps) {
|
|
62
79
|
const baseIndex = REASONING_LADDER.indexOf(TASK_CLASS_THINKING_LEVELS[taskClass]);
|
|
63
80
|
const laneStep = laneType ? (LANE_STEP[laneType] ?? 0) : 0;
|
|
64
|
-
const biasClamped = Math.max(-BIAS_MAX, Math.min(BIAS_MAX, bias));
|
|
81
|
+
const biasClamped = Math.max(-BIAS_MAX, Math.min(BIAS_MAX, normalizeLadderSteps(bias)));
|
|
65
82
|
let targetIndex = clampToLadderIndex(baseIndex + laneStep + biasClamped);
|
|
66
83
|
if (hint !== null && hint.confidence >= HINT_CONFIDENCE_THRESHOLD) {
|
|
67
84
|
const hintIndex = REASONING_LADDER.indexOf(hint.level);
|
|
@@ -71,8 +88,9 @@ export function resolveThinkingLevelCore(taskClass, availableLevels, laneType, b
|
|
|
71
88
|
targetIndex = clampToLadderIndex(targetIndex + step);
|
|
72
89
|
}
|
|
73
90
|
}
|
|
74
|
-
|
|
75
|
-
|
|
91
|
+
const escalation = normalizeLadderSteps(escalationSteps);
|
|
92
|
+
if (escalation > 0) {
|
|
93
|
+
targetIndex = clampToLadderIndex(targetIndex + escalation);
|
|
76
94
|
}
|
|
77
95
|
return clampToAvailable(targetIndex, availableLevels);
|
|
78
96
|
}
|