mixdog 1.3.0 → 1.3.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/NOTICE.md +52 -9
- package/README.md +8 -4
- package/package.json +2 -2
- package/scripts/native-release-status.mjs +238 -0
- package/src/defaults/shipped-history.json +8 -1
- package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
- package/src/defaults/skills/setup/SKILL.md +23 -1
- package/src/defaults/skills/setup/references/actions.md +54 -4
- package/src/defaults/skills/setup/references/surfaces.md +23 -3
- package/src/defaults/skills/setup-guide/SKILL.md +17 -10
- package/src/defaults/skills/visualize/SKILL.md +9 -6
- package/src/defaults/skills/visualize/references/craft.md +8 -1
- package/src/help.mjs +1 -1
- package/src/lib/keychain-cjs.cjs +4 -1
- package/src/lib/rules-builder.cjs +14 -7
- package/src/output-styles/common.md +13 -8
- package/src/rules/agent-mode/AGENT_MODE.md +9 -6
- package/src/rules/agent-mode/MIXY.md +11 -6
- package/src/rules/lead/LEAD.md +2 -2
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/20-research.md +2 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
- package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
- package/src/runtime/agent/orchestrator/config.mjs +11 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +81 -16
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -4
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +6 -10
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +80 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +67 -38
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +34 -16
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +19 -1
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -0
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -1
- package/src/runtime/agent/orchestrator/providers/mixdog-local.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +5 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +10 -2
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +30 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +14 -2
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
- package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +5 -5
- package/src/runtime/agent/orchestrator/runtime-core/route-context-state.mjs +81 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +12 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +17 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +41 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +21 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +149 -45
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +14 -11
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +68 -18
- package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
- package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +156 -25
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +21 -9
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +189 -105
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +111 -9
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -14
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +38 -5
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +46 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +99 -0
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +62 -47
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +6 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +42 -10
- package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +35 -4
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +179 -16
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +8 -3
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +36 -1
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +49 -14
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +134 -17
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +35 -13
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +6 -14
- package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +34 -21
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
- package/src/runtime/attachments/attachment-reference.mjs +155 -0
- package/src/runtime/attachments/limits.mjs +5 -1
- package/src/runtime/attachments/office-extract.mjs +3 -6
- package/src/runtime/attachments/pdf-extract.mjs +84 -10
- package/src/runtime/attachments/store.mjs +55 -30
- package/src/runtime/browser-bridge/client.mjs +73 -20
- package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
- package/src/runtime/channels/lib/scheduler.mjs +14 -7
- package/src/runtime/channels/lib/state-file.mjs +15 -15
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
- package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
- package/src/runtime/channels/lib/worker-main.mjs +3 -2
- package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
- package/src/runtime/effort-judge/judge-client.mjs +6 -3
- package/src/runtime/effort-judge/model-install.mjs +16 -8
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- package/src/runtime/local-provider/asset-installer.mjs +10 -4
- package/src/runtime/local-provider/catalog.mjs +5 -2
- package/src/runtime/local-provider/registered-models.mjs +64 -27
- package/src/runtime/local-provider/server.mjs +2 -3
- package/src/runtime/media/adapters/image-api.mjs +89 -0
- package/src/runtime/media/auth.mjs +64 -1
- package/src/runtime/media/catalog.mjs +66 -4
- package/src/runtime/media/jobs.mjs +4 -0
- package/src/runtime/media/lanes.mjs +46 -5
- package/src/runtime/media/media-usage.mjs +17 -0
- package/src/runtime/media/renditions.mjs +15 -15
- package/src/runtime/media/store.mjs +36 -35
- package/src/runtime/media/tool.mjs +8 -1
- package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
- package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
- package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
- package/src/runtime/memory/lib/pg/process.mjs +8 -4
- package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
- package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
- package/src/runtime/office/core/journal.mjs +7 -14
- package/src/runtime/office/design/library/design-library-core.mjs +4 -16
- package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
- package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
- package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
- package/src/runtime/office/pdf/pdf-render.mjs +30 -18
- package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +4 -0
- package/src/runtime/shared/agent-kind-migration.mjs +200 -0
- package/src/runtime/shared/agent-kind.mjs +152 -0
- package/src/runtime/shared/agent-message-envelope.d.mts +6 -0
- package/src/runtime/shared/agent-message-envelope.mjs +44 -0
- package/src/runtime/shared/agent-reap-state.d.mts +4 -0
- package/src/runtime/shared/agent-route-config.d.mts +1 -0
- package/src/runtime/shared/agent-route-config.mjs +22 -8
- package/src/runtime/shared/agent-store.mjs +149 -0
- package/src/runtime/shared/agent-task-starts.mjs +27 -0
- package/src/runtime/shared/atomic-file.d.mts +50 -0
- package/src/runtime/shared/atomic-file.mjs +394 -132
- package/src/runtime/shared/background-tasks.mjs +7 -4
- package/src/runtime/shared/bot-hops.mjs +30 -0
- package/src/runtime/shared/bot-split-migration.mjs +457 -0
- package/src/runtime/shared/bounded-download.mjs +4 -2
- package/src/runtime/shared/config-patch.mjs +20 -1
- package/src/runtime/shared/config.mjs +39 -9
- package/src/runtime/shared/connector-catalog.d.mts +1 -2
- package/src/runtime/shared/connector-catalog.mjs +2 -4
- package/src/runtime/shared/connector-triggers.mjs +2 -0
- package/src/runtime/shared/defaults-separation.mjs +6 -2
- package/src/runtime/shared/delegated-approval-host.mjs +74 -0
- package/src/runtime/shared/err-text.mjs +7 -1
- package/src/runtime/shared/error-presentation.mjs +113 -10
- package/src/runtime/shared/file-has-data.mjs +28 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
- package/src/runtime/shared/handoff-artifacts.mjs +61 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
- package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
- package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
- package/src/runtime/shared/model-route-fallback.mjs +79 -7
- package/src/runtime/shared/pending-agent-work.mjs +54 -0
- package/src/runtime/shared/plain-preview.mjs +22 -17
- package/src/runtime/shared/process-lifecycle.mjs +8 -12
- package/src/runtime/shared/projects.mjs +50 -41
- package/src/runtime/shared/provider-accounts.mjs +17 -12
- package/src/runtime/shared/routine-trigger.d.mts +6 -1
- package/src/runtime/shared/routine-trigger.mjs +14 -6
- package/src/runtime/shared/run-child.d.mts +3 -0
- package/src/runtime/shared/run-child.mjs +24 -3
- package/src/runtime/shared/sensitive-path-rules.d.mts +15 -0
- package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
- package/src/runtime/shared/session-baseline-store.mjs +8 -2
- package/src/runtime/shared/singleton-owner.mjs +7 -6
- package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
- package/src/runtime/shared/staged-update.mjs +4 -2
- package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
- package/src/runtime/shared/tool-execution-contract.mjs +6 -0
- package/src/runtime/shared/transcript-metadata.mjs +28 -3
- package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
- package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
- package/src/runtime/shared/turn-snapshot.mjs +44 -2
- package/src/runtime/shared/usage-readout-totals.mjs +15 -13
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +46 -44
- package/src/runtime/shared/utf8-cut.mjs +10 -0
- package/src/runtime/shared/worktrees/activity-gate.mjs +269 -61
- package/src/runtime/shared/worktrees/registry.mjs +26 -26
- package/src/runtime/tidy/core-install.mjs +26 -4
- package/src/runtime/tidy/install.mjs +91 -23
- package/src/runtime/web-search/lib/config.mjs +4 -16
- package/src/session-runtime/agent-home-delivery.mjs +859 -136
- package/src/session-runtime/agent-room-delivery.mjs +167 -19
- package/src/session-runtime/agent-task-sessions.mjs +831 -69
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +58 -24
- package/src/session-runtime/boot/config.mjs +1 -0
- package/src/session-runtime/boot/facade.mjs +11 -1
- package/src/session-runtime/boot/infrastructure.mjs +14 -2
- package/src/session-runtime/boot/providers.mjs +16 -6
- package/src/session-runtime/boot/shared.mjs +12 -6
- package/src/session-runtime/boot/tools.mjs +2 -2
- package/src/session-runtime/bot-status.mjs +432 -0
- package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
- package/src/session-runtime/config-lifecycle.mjs +78 -32
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/handoff-attachments.mjs +593 -0
- package/src/session-runtime/held-requests.mjs +36 -33
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +45 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown.mjs +11 -3
- package/src/session-runtime/mcp-glue/connect.mjs +100 -186
- package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
- package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
- package/src/session-runtime/media-api.mjs +5 -2
- package/src/session-runtime/model-route/route-persist.mjs +2 -2
- package/src/session-runtime/model-route/route-tuning.mjs +11 -2
- package/src/session-runtime/model-route/set-route.mjs +82 -2
- package/src/session-runtime/native-web-search.mjs +2 -2
- package/src/session-runtime/new-session-config.mjs +6 -1
- package/src/session-runtime/owned-automation-run.mjs +8 -1
- package/src/session-runtime/room-member-gate.mjs +16 -3
- package/src/session-runtime/route-resolution.mjs +21 -19
- package/src/session-runtime/route-state.mjs +1 -59
- package/src/session-runtime/routine-home-turn.mjs +5 -3
- package/src/session-runtime/runtime-bootstrap.mjs +5 -3
- package/src/session-runtime/runtime-paths.mjs +11 -5
- package/src/session-runtime/runtime-tunables.mjs +6 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +11 -2
- package/src/session-runtime/services/agent-tool/close-flow.mjs +4 -2
- package/src/session-runtime/services/agent-tool/execute-send.mjs +1 -0
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +1 -0
- package/src/session-runtime/services/agent-tool/helpers.mjs +24 -5
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +36 -24
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +12 -6
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +22 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +4 -6
- package/src/session-runtime/services/agent-tool.mjs +6 -0
- package/src/session-runtime/services/daemon-crash-capture/daemon-exit-record.mjs +1 -1
- package/src/session-runtime/services/daemon-crash-capture/retention.mjs +4 -3
- package/src/session-runtime/services/hook-bus/config-loader.mjs +14 -5
- package/src/session-runtime/services/hook-bus/rule-file.mjs +49 -11
- package/src/session-runtime/services/plugin-admin.mjs +26 -26
- package/src/session-runtime/services/provider-admin.mjs +14 -4
- package/src/session-runtime/services/schedule-access.mjs +33 -4
- package/src/session-runtime/services/seeds.mjs +4 -3
- package/src/session-runtime/services/usage-dashboard.mjs +1 -1
- package/src/session-runtime/services/usage-stats-model.mjs +2 -1
- package/src/session-runtime/session-create/materialize.mjs +2 -3
- package/src/session-runtime/session-create/session-options.mjs +15 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +63 -1
- package/src/session-runtime/settings-compaction-api.mjs +86 -39
- package/src/session-runtime/setup-tool/executor.mjs +20 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +19 -7
- package/src/session-runtime/setup-tool/settings-contract.mjs +37 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
- package/src/session-runtime/skills-api.mjs +12 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +265 -0
- package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
- package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
- package/src/session-runtime/tool-policy/policy-stage.mjs +165 -0
- package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
- package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
- package/src/session-runtime/tool-policy-refresh.mjs +47 -358
- package/src/session-runtime/tool-surface.mjs +5 -3
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +99 -81
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +2 -1
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +578 -301
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +113 -53
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
- package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
- package/src/session-runtime/workspace/workspace-state.mjs +7 -6
- package/src/standalone/daemon-agent-control.mjs +4 -1
- package/src/standalone/daemon-session-control.mjs +60 -11
- package/src/standalone/daemon.mjs +34 -4
- package/src/standalone/local-session-runtime.mjs +22 -14
- package/src/standalone/session-client.mjs +7 -2
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +46 -3
- package/src/standalone/session-service/agent-tree.mjs +4 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +19 -0
- package/src/standalone/session-service.mjs +11 -0
- package/src/standalone/session-state-projection.mjs +19 -9
- package/src/standalone/session-tool-output.mjs +35 -9
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
- package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
- package/src/tui/dist/index.mjs +599 -342
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/notice-surface.mjs +3 -4
- package/src/tui/session/session-api/intake/abort.mjs +19 -1
- package/src/tui/session/session-api/media.mjs +2 -1
- package/src/tui/session/session-api/routes-agent-definitions.mjs +75 -0
- package/src/tui/session/session-api/routes-write.mjs +203 -0
- package/src/tui/session/session-api/routes.mjs +23 -236
- package/src/tui/session/session-api/settings.mjs +14 -1
- package/src/tui/session/session-flow/drain.mjs +28 -3
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +4 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +8 -3
- package/src/tui/session/tool-approval.mjs +185 -20
- package/src/tui/session/transcript-intake.mjs +4 -0
- package/src/tui/session/turn-live-call.mjs +11 -3
- package/src/tui/session/turn.mjs +36 -17
- package/src/tui/transcript-tool-failures.mjs +8 -2
- package/src/vendor/statusline/src/gateway/route-meta.mjs +7 -8
- package/src/vendor/statusline/src/gateway/session-routes.mjs +6 -7
- package/src/rules/agent-mode/ROUTINE.md +0 -6
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Diagnostic per-block prefix fingerprint of an Anthropic request: the tools,
|
|
2
|
+
// each system block (BP1/BP2/BP3/env, the routing prefix included) and the
|
|
3
|
+
// cache_control marker positions, as short hashes only — never any text, so
|
|
4
|
+
// it is safe in shipped builds. The last two requests per session are kept in
|
|
5
|
+
// memory so a usage-detected cache miss (session/loop/send-phase.mjs) can say
|
|
6
|
+
// which block or marker moved.
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
|
|
9
|
+
const HASH_CHARS = 12;
|
|
10
|
+
const MAX_SESSIONS = 256;
|
|
11
|
+
const bySession = new Map();
|
|
12
|
+
|
|
13
|
+
const hash = (value) =>
|
|
14
|
+
createHash('sha256')
|
|
15
|
+
.update(JSON.stringify(value ?? null))
|
|
16
|
+
.digest('hex')
|
|
17
|
+
.slice(0, HASH_CHARS);
|
|
18
|
+
|
|
19
|
+
const withoutMarker = (block) => {
|
|
20
|
+
if (!block || typeof block !== 'object') return block;
|
|
21
|
+
const { cache_control: _marker, ...rest } = block;
|
|
22
|
+
return rest;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const markerTtl = (marker) => (marker?.ttl ? String(marker.ttl) : '5m');
|
|
26
|
+
|
|
27
|
+
/** `{ tools, system: [hash…], markers: ['s1:1h', 'm12:5m', …] }` of a request body. */
|
|
28
|
+
export function anthropicPrefixFingerprint(body) {
|
|
29
|
+
const system = Array.isArray(body?.system) ? body.system : [];
|
|
30
|
+
const messages = Array.isArray(body?.messages) ? body.messages : [];
|
|
31
|
+
const markers = [];
|
|
32
|
+
system.forEach((block, index) => {
|
|
33
|
+
if (block?.cache_control) markers.push(`s${index}:${markerTtl(block.cache_control)}`);
|
|
34
|
+
});
|
|
35
|
+
messages.forEach((message, index) => {
|
|
36
|
+
const content = Array.isArray(message?.content) ? message.content : [];
|
|
37
|
+
const marked = content.find((block) => block?.cache_control);
|
|
38
|
+
if (marked) markers.push(`m${index}:${markerTtl(marked.cache_control)}`);
|
|
39
|
+
});
|
|
40
|
+
return { tools: hash(body?.tools || []), system: system.map((block) => hash(withoutMarker(block))), markers };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Keep `fingerprint` as the session's latest request (the one before it stays as previous). */
|
|
44
|
+
export function recordAnthropicPrefix(sessionId, fingerprint) {
|
|
45
|
+
if (!sessionId || !fingerprint) return;
|
|
46
|
+
const key = String(sessionId);
|
|
47
|
+
const previous = bySession.get(key)?.current || null;
|
|
48
|
+
bySession.delete(key);
|
|
49
|
+
bySession.set(key, { previous, current: fingerprint });
|
|
50
|
+
if (bySession.size > MAX_SESSIONS) bySession.delete(bySession.keys().next().value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The session's latest fingerprint, or null. */
|
|
54
|
+
export function latestAnthropicPrefix(sessionId) {
|
|
55
|
+
return bySession.get(String(sessionId || ''))?.current || null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** `{ changedBlocks: 'tools,s3' | 'none', markersChanged }` between the session's
|
|
59
|
+
* last two requests, or null before it has two. */
|
|
60
|
+
export function anthropicPrefixChanges(sessionId) {
|
|
61
|
+
const entry = bySession.get(String(sessionId || ''));
|
|
62
|
+
if (!entry?.previous) return null;
|
|
63
|
+
const { previous, current } = entry;
|
|
64
|
+
const changed = [];
|
|
65
|
+
if (previous.tools !== current.tools) changed.push('tools');
|
|
66
|
+
const blocks = Math.max(previous.system.length, current.system.length);
|
|
67
|
+
for (let index = 0; index < blocks; index += 1) {
|
|
68
|
+
if (previous.system[index] !== current.system[index]) changed.push(`s${index}`);
|
|
69
|
+
}
|
|
70
|
+
// Message markers move every turn; only the system markers are a layout change.
|
|
71
|
+
const systemMarkers = (print) => print.markers.filter((marker) => marker.startsWith('s')).join(',');
|
|
72
|
+
return {
|
|
73
|
+
changedBlocks: changed.length ? changed.join(',') : 'none',
|
|
74
|
+
markersChanged: systemMarkers(previous) !== systemMarkers(current),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -10,6 +10,7 @@ import { mergeFlatSchemaProperty } from './flat-schema-merge.mjs';
|
|
|
10
10
|
import { reportedCostUsd } from './usage-primitives.mjs';
|
|
11
11
|
import { reportInvalidTool, wireInputSchema } from './claude-bridge-schema.mjs';
|
|
12
12
|
import { normalizeServerToolUse } from './anthropic-server-tool-usage.mjs';
|
|
13
|
+
import { ANTHROPIC_TOOL_CALL_IDS, withWireToolCallIds } from './tool-call-wire-ids.mjs';
|
|
13
14
|
export const ANTHROPIC_CACHE_TTL_STABLE = { type: 'ephemeral', ttl: '1h' };
|
|
14
15
|
const ANTHROPIC_CACHE_TTL_VOLATILE = { type: 'ephemeral' };
|
|
15
16
|
|
|
@@ -81,6 +82,22 @@ function appendAnthropicCacheControl(content, ttl = ANTHROPIC_CACHE_TTL_VOLATILE
|
|
|
81
82
|
return next;
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
// The builders lift the tail reminder off (splitTailReminder) before lowering and
|
|
86
|
+
// cache marking, then append it here as the final text block, so the message
|
|
87
|
+
// breakpoint stays on the block before it and the cached prefix is unchanged.
|
|
88
|
+
export function appendAnthropicTailReminder(anthropicMessages, reminder) {
|
|
89
|
+
if (!reminder) return anthropicMessages;
|
|
90
|
+
const block = { type: 'text', text: reminder };
|
|
91
|
+
const last = anthropicMessages[anthropicMessages.length - 1];
|
|
92
|
+
if (last?.role === 'user') {
|
|
93
|
+
const content = typeof last.content === 'string' ? [{ type: 'text', text: last.content }] : last.content || [];
|
|
94
|
+
last.content = [...content, block];
|
|
95
|
+
} else {
|
|
96
|
+
anthropicMessages.push({ role: 'user', content: [block] });
|
|
97
|
+
}
|
|
98
|
+
return anthropicMessages;
|
|
99
|
+
}
|
|
100
|
+
|
|
84
101
|
export function resolveAnthropicCacheTtls(opts) {
|
|
85
102
|
const strategy = opts?.cacheStrategy || {};
|
|
86
103
|
const pick = (layer, fallback) => {
|
|
@@ -232,7 +249,8 @@ const ANTHROPIC_NATIVE_PROVIDERS = new Set(['anthropic', 'anthropic-oauth']);
|
|
|
232
249
|
|
|
233
250
|
// `provider`: the engine's provider name. A gateway on a native Messages
|
|
234
251
|
// route (wire-route.mjs) also replays the references it tagged itself.
|
|
235
|
-
export function toAnthropicMessages(
|
|
252
|
+
export function toAnthropicMessages(transcript, availableTools, provider = '') {
|
|
253
|
+
const messages = withWireToolCallIds(transcript, ANTHROPIC_TOOL_CALL_IDS);
|
|
236
254
|
const ownProvider = String(provider || '').toLowerCase();
|
|
237
255
|
const availableNames = anthropicToolNameSet(availableTools);
|
|
238
256
|
const result = [];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// The tail reminder (session/tail-reminder-rules.mjs) rides the outgoing request
|
|
2
|
+
// as its last message, marked meta.source 'tail-reminder'. It is ephemeral: a
|
|
3
|
+
// provider builder that keeps per-message state (cache breakpoints, message
|
|
4
|
+
// counts, continuation indexes, tool-loop closure) lifts it off first with
|
|
5
|
+
// splitTailReminder, builds from the real history, and appends the reminder as
|
|
6
|
+
// the final wire element, so the history-derived prefix never contains it.
|
|
7
|
+
export const TAIL_REMINDER_META = 'tail-reminder';
|
|
8
|
+
|
|
9
|
+
export function splitTailReminder(messages) {
|
|
10
|
+
const last = Array.isArray(messages) ? messages[messages.length - 1] : null;
|
|
11
|
+
if (last?.role !== 'user' || last.meta?.source !== TAIL_REMINDER_META) return { messages, reminder: '' };
|
|
12
|
+
return { messages: messages.slice(0, -1), reminder: String(last.content || '') };
|
|
13
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Tool-call ids at the wire. A transcript keeps each tool call's id as the
|
|
2
|
+
// provider that produced it minted it; after a model switch another provider
|
|
3
|
+
// may refuse it (Anthropic accepts only [A-Za-z0-9_-]; OpenAI chat caps the
|
|
4
|
+
// length). Each request builder projects the ids onto its own rule just
|
|
5
|
+
// before lowering: a valid id passes unchanged (so native replay items and
|
|
6
|
+
// the provider's own ids stay byte-exact), an invalid one becomes a
|
|
7
|
+
// deterministic, collision-free stand-in, and a call and its result always
|
|
8
|
+
// map to the same value. Persisted history is never rewritten.
|
|
9
|
+
import { createHash } from 'node:crypto';
|
|
10
|
+
|
|
11
|
+
export const ANTHROPIC_TOOL_CALL_IDS = Object.freeze({ allowed: /^[A-Za-z0-9_-]+$/, maxLength: 64 });
|
|
12
|
+
export const OPENAI_RESPONSES_TOOL_CALL_IDS = Object.freeze({ allowed: /^[A-Za-z0-9_.:-]+$/, maxLength: 64 });
|
|
13
|
+
export const OPENAI_CHAT_TOOL_CALL_IDS = Object.freeze({ allowed: /^[A-Za-z0-9_.:-]+$/, maxLength: 40 });
|
|
14
|
+
|
|
15
|
+
const HASH_CHARS = 10;
|
|
16
|
+
|
|
17
|
+
function standIn(id, rule, salt) {
|
|
18
|
+
const hash = createHash('sha256').update(`${salt}\u0000${id}`).digest('hex').slice(0, HASH_CHARS);
|
|
19
|
+
const stem = String(id)
|
|
20
|
+
.replace(/[^A-Za-z0-9_-]+/g, '_')
|
|
21
|
+
.replace(/^_+|_+$/g, '')
|
|
22
|
+
.slice(0, Math.max(0, rule.maxLength - HASH_CHARS - 1));
|
|
23
|
+
return stem ? `${stem}_${hash}` : `call_${hash}`.slice(0, rule.maxLength);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const isValid = (id, rule) => id.length > 0 && id.length <= rule.maxLength && rule.allowed.test(id);
|
|
27
|
+
|
|
28
|
+
/** id → wire id for every tool call and result in `messages` under `rule`. */
|
|
29
|
+
export function toolCallWireIdMap(messages, rule) {
|
|
30
|
+
const ids = new Set();
|
|
31
|
+
for (const message of Array.isArray(messages) ? messages : []) {
|
|
32
|
+
if (message?.role === 'assistant')
|
|
33
|
+
for (const call of message.toolCalls || []) if (call?.id) ids.add(String(call.id));
|
|
34
|
+
if (message?.role === 'tool' && message.toolCallId) ids.add(String(message.toolCallId));
|
|
35
|
+
}
|
|
36
|
+
const map = new Map();
|
|
37
|
+
const taken = new Set([...ids].filter((id) => isValid(id, rule)));
|
|
38
|
+
for (const id of ids) {
|
|
39
|
+
if (isValid(id, rule)) continue;
|
|
40
|
+
let salt = 0;
|
|
41
|
+
let wire = standIn(id, rule, salt);
|
|
42
|
+
while (taken.has(wire)) wire = standIn(id, rule, ++salt);
|
|
43
|
+
taken.add(wire);
|
|
44
|
+
map.set(id, wire);
|
|
45
|
+
}
|
|
46
|
+
return map;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** `messages` with tool-call ids projected onto `rule`; the same array when none needs it. */
|
|
50
|
+
export function withWireToolCallIds(messages, rule) {
|
|
51
|
+
const map = toolCallWireIdMap(messages, rule);
|
|
52
|
+
if (!map.size) return messages;
|
|
53
|
+
return messages.map((message) => {
|
|
54
|
+
if (message?.role === 'tool' && map.has(String(message.toolCallId))) {
|
|
55
|
+
return { ...message, toolCallId: map.get(String(message.toolCallId)) };
|
|
56
|
+
}
|
|
57
|
+
if (message?.role !== 'assistant' || !message.toolCalls?.some((call) => map.has(String(call?.id)))) return message;
|
|
58
|
+
return {
|
|
59
|
+
...message,
|
|
60
|
+
toolCalls: message.toolCalls.map((call) =>
|
|
61
|
+
map.has(String(call?.id)) ? { ...call, id: map.get(String(call.id)) } : call
|
|
62
|
+
),
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -652,9 +652,17 @@ export function contentImageDescriptors(content) {
|
|
|
652
652
|
// one-line description.
|
|
653
653
|
// The page count (recorded by intake and by the read tool) rides on the part
|
|
654
654
|
// itself, so an inline part and its stored reference carry the same one.
|
|
655
|
+
// The text-layer character count (recorded with it) prices the text a native
|
|
656
|
+
// reader extracts on top of each page image.
|
|
655
657
|
function pdfDescriptor(sizeBytes, part) {
|
|
656
658
|
const pageCount = Math.floor(Number(part?.pageCount));
|
|
657
|
-
|
|
659
|
+
const textChars = Number(part?.textChars);
|
|
660
|
+
return {
|
|
661
|
+
mimeType: 'application/pdf',
|
|
662
|
+
sizeBytes,
|
|
663
|
+
...(pageCount > 0 ? { pageCount } : {}),
|
|
664
|
+
...(pageCount > 0 && Number.isFinite(textChars) && textChars >= 0 ? { textChars: Math.floor(textChars) } : {}),
|
|
665
|
+
};
|
|
658
666
|
}
|
|
659
667
|
|
|
660
668
|
export function contentFileDescriptors(content) {
|
|
@@ -974,6 +982,13 @@ function normalizeAnthropicPart(part) {
|
|
|
974
982
|
if (part?.type === 'text' && isAttachmentReference(part)) {
|
|
975
983
|
return { type: 'text', text: attachmentTextForPart(part) };
|
|
976
984
|
}
|
|
985
|
+
// A media reference (attachment-reference.mjs) is a text part whose
|
|
986
|
+
// `attachmentReference` metadata stays in saved history. It is not a
|
|
987
|
+
// Messages API text-block field, and the API rejects the whole request for it.
|
|
988
|
+
if (part?.type === 'text' && part.attachmentReference !== undefined) {
|
|
989
|
+
const { attachmentReference: _internal, ...wirePart } = part;
|
|
990
|
+
return wirePart;
|
|
991
|
+
}
|
|
977
992
|
return part;
|
|
978
993
|
}
|
|
979
994
|
|
|
@@ -13,8 +13,10 @@ import { beginLocalInference, localModelState } from '../../../local-provider/mo
|
|
|
13
13
|
|
|
14
14
|
export class MixdogLocalProvider {
|
|
15
15
|
static inputExcludesCache = false;
|
|
16
|
-
// The managed local runtime is text-only: PDFs lower to text
|
|
16
|
+
// The managed local runtime is text-only: PDFs lower to text and images to
|
|
17
|
+
// a placeholder (input-capabilities.mjs).
|
|
17
18
|
nativePdf = false;
|
|
19
|
+
takesImages = false;
|
|
18
20
|
|
|
19
21
|
constructor(config = {}, { ensureServer = ensureLocalProviderServer, runRequest = runLocalProviderRequest } = {}) {
|
|
20
22
|
this.name = 'mixdog-local';
|
|
@@ -111,6 +111,7 @@ export class ModelProxyProvider {
|
|
|
111
111
|
// Adapter traits are reported by the PC's real instance.
|
|
112
112
|
if (typeof this.config.modelProxy?.nativePdf === 'boolean') this.nativePdf = this.config.modelProxy.nativePdf;
|
|
113
113
|
if (this.config.modelProxy?.consumesReadWindows === true) this.consumesReadWindows = true;
|
|
114
|
+
if (this.config.modelProxy?.takesImages === false) this.takesImages = false;
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
#call(method, fields = {}, options = {}) {
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
// handshake-header projection, and the per-turn x-codex-turn-state guard.
|
|
4
4
|
// openai-oauth-ws.mjs owns the transport flow only.
|
|
5
5
|
import { createHash, randomUUID } from 'node:crypto';
|
|
6
|
-
import { existsSync, mkdirSync, readFileSync
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
|
+
import { writeFileAtomicSync } from '../../../shared/atomic-file.mjs';
|
|
8
9
|
import { cleanString } from '../../../shared/clean.mjs';
|
|
9
10
|
import { getPluginData } from '../config.mjs';
|
|
10
11
|
import { activateCodexTurnState } from './openai-turn-state.mjs';
|
|
@@ -77,15 +78,14 @@ function _codexInstallationId(sendOpts) {
|
|
|
77
78
|
const generated = randomUUID();
|
|
78
79
|
try {
|
|
79
80
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
} catch {
|
|
81
|
+
// Atomic create-if-absent; a damaged (empty/NUL) file is replaced whole.
|
|
82
|
+
if (!writeFileAtomicSync(file, generated, { createOnly: true, mode: 0o644 })) {
|
|
83
83
|
const winner = readFileSync(file, 'utf8').trim().toLowerCase();
|
|
84
84
|
if (UUID_RE.test(winner)) {
|
|
85
85
|
_installationId = winner;
|
|
86
86
|
return _installationId;
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
writeFileAtomicSync(file, generated, { mode: 0o644 });
|
|
89
89
|
}
|
|
90
90
|
} catch {}
|
|
91
91
|
_installationId = generated;
|
|
@@ -94,10 +94,14 @@ async function compatModelsError(name, res, apiKey = '') {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
// `keyless` omits the Authorization header entirely (keyless endpoints);
|
|
97
|
-
// `signal` aborts the request together with the list timeout
|
|
98
|
-
|
|
97
|
+
// `signal` aborts the request together with the list timeout; `timeoutMs`
|
|
98
|
+
// replaces the default list timeout for callers that wait on a slow catalog.
|
|
99
|
+
export async function fetchCompatModelItems(
|
|
100
|
+
provider,
|
|
101
|
+
{ signal = null, keyless = false, timeoutMs = MODEL_LIST_TIMEOUT_MS } = {}
|
|
102
|
+
) {
|
|
99
103
|
const name = provider.name;
|
|
100
|
-
const timeout = createTimeoutSignal(signal,
|
|
104
|
+
const timeout = createTimeoutSignal(signal, timeoutMs, `${name} model list`);
|
|
101
105
|
try {
|
|
102
106
|
const apiKey = keyless ? '' : resolveProviderApiKey(name, provider.config || provider);
|
|
103
107
|
const res = await fetch(`${String(provider.baseURL || '').replace(/\/+$/, '')}/models`, {
|
|
@@ -137,9 +141,9 @@ function nativeMode(m) {
|
|
|
137
141
|
return null;
|
|
138
142
|
}
|
|
139
143
|
|
|
140
|
-
export async function listCompatModels(provider, { throwOnError = false, signal = null } = {}) {
|
|
144
|
+
export async function listCompatModels(provider, { throwOnError = false, signal = null, timeoutMs } = {}) {
|
|
141
145
|
try {
|
|
142
|
-
const list = await provider._fetchModelItems({ signal });
|
|
146
|
+
const list = await provider._fetchModelItems({ signal, timeoutMs });
|
|
143
147
|
const models = [];
|
|
144
148
|
for (const m of list) {
|
|
145
149
|
const contextWindow = Number(
|
|
@@ -29,6 +29,7 @@ import { isCustomProviderName, resolveCustomReasoning } from './custom-reasoning
|
|
|
29
29
|
import { projectEffortConfiguration, withEffortConfigurationFallback } from './effort-configuration.mjs';
|
|
30
30
|
import { normalizeCacheKey } from '../agent-runtime/cache-strategy.mjs';
|
|
31
31
|
import { createProviderReplay } from './lib/provider-replay.mjs';
|
|
32
|
+
import { splitTailReminder } from './lib/tail-reminder-split.mjs';
|
|
32
33
|
import {
|
|
33
34
|
applyCompatToolChoice,
|
|
34
35
|
compatResponsesReplayProvider,
|
|
@@ -296,7 +297,13 @@ export function sendCompatResponses(provider, messages, useModel, tools, opts =
|
|
|
296
297
|
return withEffortConfigurationFallback(provider.name, useModel, opts, send);
|
|
297
298
|
}
|
|
298
299
|
|
|
299
|
-
async function sendCompatResponsesOnce(provider,
|
|
300
|
+
async function sendCompatResponsesOnce(provider, requestMessages, useModel, tools, opts) {
|
|
301
|
+
// The continuation state below is indexed by transcript position
|
|
302
|
+
// (seenMessageCount, reasoning messageIndex): the ephemeral tail reminder is
|
|
303
|
+
// not part of the transcript, so it is lifted off here and appended to the
|
|
304
|
+
// wire input last.
|
|
305
|
+
const { messages: transcript, reminder } = splitTailReminder(requestMessages);
|
|
306
|
+
let messages = transcript;
|
|
300
307
|
const replayProvider = compatResponsesReplayProvider(provider.name);
|
|
301
308
|
const signal = opts.signal || null;
|
|
302
309
|
if (signal?.aborted) {
|
|
@@ -320,6 +327,7 @@ async function sendCompatResponsesOnce(provider, messages, useModel, tools, opts
|
|
|
320
327
|
includeSystem: provider.config?.responsesSystemAsInstructions !== true,
|
|
321
328
|
});
|
|
322
329
|
const instructions = provider.config?.responsesSystemAsInstructions === true ? xaiSystemInstructions(messages) : '';
|
|
330
|
+
if (reminder) input.push({ role: 'user', content: [{ type: 'input_text', text: reminder }] });
|
|
323
331
|
const params = buildCompatResponsesParams({
|
|
324
332
|
provider,
|
|
325
333
|
useModel,
|
|
@@ -104,10 +104,16 @@ export const COMPAT_RETRY_PROFILES = Object.freeze({
|
|
|
104
104
|
}),
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
// A provider without a profile (custom endpoints, gateways, local servers)
|
|
108
|
+
// keeps the shared ladder, but a Retry-After beyond a minute is not waited
|
|
109
|
+
// out: it surfaces with its wait so the account pool can rotate and the
|
|
110
|
+
// notice can name when to try again.
|
|
111
|
+
export const COMPAT_DEFAULT_MAX_RETRY_AFTER_MS = 60_000;
|
|
112
|
+
|
|
113
|
+
/** withRetry options (attempt budget, schedule, jitter) for a provider; only the advice ceiling for the shared defaults. */
|
|
108
114
|
export function compatRetryOptions(providerName) {
|
|
109
115
|
const profile = COMPAT_RETRY_PROFILES[providerName];
|
|
110
|
-
if (!profile) return {};
|
|
116
|
+
if (!profile) return { maxRetryAfterMs: COMPAT_DEFAULT_MAX_RETRY_AFTER_MS };
|
|
111
117
|
return {
|
|
112
118
|
maxAttempts: profile.maxAttempts,
|
|
113
119
|
backoffMs: profile.backoffMs,
|
|
@@ -17,6 +17,11 @@ import {
|
|
|
17
17
|
} from './media-normalization.mjs';
|
|
18
18
|
import { customToolCallFromResponseItem, nativeToolSearchCallFromArguments } from './custom-tool-wire.mjs';
|
|
19
19
|
import { providerReplayItems } from './lib/provider-replay.mjs';
|
|
20
|
+
import {
|
|
21
|
+
OPENAI_CHAT_TOOL_CALL_IDS,
|
|
22
|
+
OPENAI_RESPONSES_TOOL_CALL_IDS,
|
|
23
|
+
withWireToolCallIds,
|
|
24
|
+
} from './lib/tool-call-wire-ids.mjs';
|
|
20
25
|
import { acceptedWireTools } from './lib/claude-bridge-schema.mjs';
|
|
21
26
|
import { ensureResponsesCallOutputs } from './lib/wire-pairing.mjs';
|
|
22
27
|
import { responsesEffortUpdates } from './effort-configuration.mjs';
|
|
@@ -34,7 +39,9 @@ export function resolveCompatMaxOutputTokens(opts = {}) {
|
|
|
34
39
|
);
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
export function toOpenAIMessages(
|
|
42
|
+
export function toOpenAIMessages(transcript, providerName, options = {}) {
|
|
43
|
+
const messages =
|
|
44
|
+
options.preserveToolCallIds === true ? transcript : withWireToolCallIds(transcript, OPENAI_CHAT_TOOL_CALL_IDS);
|
|
38
45
|
// NOTE: chat.completions has no equivalent slot for replaying reasoning
|
|
39
46
|
// encrypted_content the way the Responses API does (no `type:'reasoning'`
|
|
40
47
|
// input item). Whatever reasoningItems may be attached to assistant
|
|
@@ -421,7 +428,8 @@ export function xaiSystemInstructions(messages) {
|
|
|
421
428
|
return instructions || undefined;
|
|
422
429
|
}
|
|
423
430
|
|
|
424
|
-
export function toXaiResponsesInput(
|
|
431
|
+
export function toXaiResponsesInput(transcript, providerState, options = {}) {
|
|
432
|
+
const messages = withWireToolCallIds(transcript, OPENAI_RESPONSES_TOOL_CALL_IDS);
|
|
425
433
|
const includeSystem = options.includeSystem !== false;
|
|
426
434
|
// Generic Responses callers (opencode-go gateway) keep their own state
|
|
427
435
|
// slot and replay tag so a provider switch never replays foreign items.
|
|
@@ -41,7 +41,25 @@ function promptCacheForm(model) {
|
|
|
41
41
|
return openAiSupportsExtendedRetention(model) ? 'retention' : null;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
// The environment developer item buildRequestBody places first in `input`:
|
|
45
|
+
// the end of the session's stable prefix (tools + instructions + environment).
|
|
46
|
+
// Top-level `instructions` cannot carry a breakpoint, so this is the earliest
|
|
47
|
+
// place one fits.
|
|
48
|
+
function stablePrefixBlock(body) {
|
|
49
|
+
const first = Array.isArray(body.input) ? body.input[0] : null;
|
|
50
|
+
const content = first?.type === 'message' && first.role === 'developer' ? first.content : null;
|
|
51
|
+
const block = Array.isArray(content) && content.length === 1 ? content[0] : null;
|
|
52
|
+
return block?.type === 'input_text' && String(block.text || '').startsWith('<environment_context>') ? block : null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Public-API cache lifetime fields. GPT-5.6+: request ttl "30m" for the
|
|
57
|
+
* moving tail; `prefixTtl` '12h' (Lead class, cache-strategy.mjs
|
|
58
|
+
* resolveOpenAiPrefixCacheTtl) adds one explicit 12h breakpoint at the end of
|
|
59
|
+
* the stable prefix in the default implicit mode, so the implicit tail
|
|
60
|
+
* breakpoint stays 30m. Earlier models are unchanged.
|
|
61
|
+
*/
|
|
62
|
+
export function applyOpenAIDirectCachePolicy(body, model, storeResponses, { prefixTtl = null } = {}) {
|
|
45
63
|
body.store = storeResponses;
|
|
46
64
|
delete body.prompt_cache_retention;
|
|
47
65
|
delete body.prompt_cache_options;
|
|
@@ -49,7 +67,16 @@ export function applyOpenAIDirectCachePolicy(body, model, storeResponses) {
|
|
|
49
67
|
// response storage is disabled. The provider's default cache still applies.
|
|
50
68
|
if (!storeResponses) return body;
|
|
51
69
|
const form = promptCacheForm(model);
|
|
52
|
-
if (form === 'options')
|
|
53
|
-
|
|
70
|
+
if (form === 'options') {
|
|
71
|
+
body.prompt_cache_options = { ttl: '30m' };
|
|
72
|
+
const block = prefixTtl === '12h' ? stablePrefixBlock(body) : null;
|
|
73
|
+
if (block) {
|
|
74
|
+
const [first, ...rest] = body.input;
|
|
75
|
+
body.input = [
|
|
76
|
+
{ ...first, content: [{ ...block, prompt_cache_breakpoint: { mode: 'explicit', ttl: '12h' } }] },
|
|
77
|
+
...rest,
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
} else if (form === 'retention') body.prompt_cache_retention = '24h';
|
|
54
81
|
return body;
|
|
55
82
|
}
|
|
@@ -25,7 +25,7 @@ export function openAiCatalogMeta(model) {
|
|
|
25
25
|
// gpt-5.4 -> [5, 4]; gpt-6-astra -> [6, 0]; non-GPT ids -> null.
|
|
26
26
|
// A bare multi-digit major with no minor or family suffix (gpt-60) is not a
|
|
27
27
|
// generation id.
|
|
28
|
-
function gptVersion(id) {
|
|
28
|
+
export function gptVersion(id) {
|
|
29
29
|
const m = /^gpt-(\d+)(?:\.(\d+))?(?=-|$)/.exec(id);
|
|
30
30
|
if (!m || (m[1].length > 1 && m[2] === undefined && m[0] === id)) return null;
|
|
31
31
|
return [Number(m[1]), Number(m[2] || 0)];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Transcript lowering is independent of request/turn metadata. A retained
|
|
2
2
|
// message must have the same wire representation in every subsequent request.
|
|
3
3
|
import { providerReplayItems } from './lib/provider-replay.mjs';
|
|
4
|
+
import { OPENAI_RESPONSES_TOOL_CALL_IDS, withWireToolCallIds } from './lib/tool-call-wire-ids.mjs';
|
|
4
5
|
import { responsesEffortUpdates } from './effort-configuration.mjs';
|
|
5
6
|
import { ensureResponsesCallOutputs } from './lib/wire-pairing.mjs';
|
|
6
7
|
import { normalizeContentForOpenAIResponses, splitToolContentForOpenAIResponses } from './media-normalization.mjs';
|
|
@@ -147,7 +148,8 @@ function pushAssistantToolCalls(toolCalls, { out, customToolCallIds, nativeSearc
|
|
|
147
148
|
* - `includeSystem`, `nativePdf`, `splitToolContent`, `startIndex`: the
|
|
148
149
|
* gateway's system/media/continuation handling.
|
|
149
150
|
*/
|
|
150
|
-
export function convertMessagesToResponsesInput(
|
|
151
|
+
export function convertMessagesToResponsesInput(transcript, opts = {}) {
|
|
152
|
+
const messages = withWireToolCallIds(transcript, OPENAI_RESPONSES_TOOL_CALL_IDS);
|
|
151
153
|
const out = [];
|
|
152
154
|
const pendingToolMedia = [];
|
|
153
155
|
const pendingToolLoads = [];
|
|
@@ -142,7 +142,9 @@ export class OpenAIDirectProvider {
|
|
|
142
142
|
// Keep public response storage and model-specific cache options out of
|
|
143
143
|
// the shared OAuth payload. Storage opt-out still forces full frames in
|
|
144
144
|
// _computeDelta; retained output items make those frames self-contained.
|
|
145
|
-
applyOpenAIDirectCachePolicy(body, useModel, _envFlag('MIXDOG_OAI_STORE', true)
|
|
145
|
+
applyOpenAIDirectCachePolicy(body, useModel, _envFlag('MIXDOG_OAI_STORE', true), {
|
|
146
|
+
prefixTtl: opts.promptCachePrefixTtl || null,
|
|
147
|
+
});
|
|
146
148
|
// poolKey MUST be sessionId-only. Falling back to promptCacheKey would
|
|
147
149
|
// let unrelated raw sessions sharing the same provider-scoped cache
|
|
148
150
|
// bucket reuse each other's pooled socket and inherit lastResponseId
|
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
* The organization's remote config (`/api/v2/config` → providers.opencode-go)
|
|
5
5
|
* is the authority for the inference base URL, the request headers and the
|
|
6
6
|
* model catalog (the gateway's own `/models` is not served on this base).
|
|
7
|
+
* When that config lists no models at all (the console serves `models: {}` for
|
|
8
|
+
* an organization without overrides, as the OpenCode CLI sees it), the catalog
|
|
9
|
+
* is the models.dev `opencode-go` provider, the list the CLI itself shows.
|
|
7
10
|
* Requests run on the OpenCode Go gateway engines (opencode-go.mjs) with the
|
|
8
11
|
* access token as the bearer; a 401 refreshes the token once and retries.
|
|
9
12
|
*/
|
|
10
13
|
import { scrubOAuthSecrets } from './lib/oauth-token-utils.mjs';
|
|
11
|
-
import { getModelMetadataSync } from './model-catalog.mjs';
|
|
14
|
+
import { getModelMetadataSync, getModelsDevProviderModelsSync, loadModelsDevCatalog } from './model-catalog.mjs';
|
|
12
15
|
import { makeModelCache } from './model-cache.mjs';
|
|
13
16
|
import { OpenCodeGoProvider, WIRE_API_BY_NPM, resolveOpenCodeGoWireRoute } from './opencode-go.mjs';
|
|
14
17
|
import { fetchOpenCodeGoOAuthUsageSnapshot } from './opencode-go-usage.mjs';
|
|
@@ -90,11 +93,51 @@ function catalogRow(id, model, providerPackage) {
|
|
|
90
93
|
};
|
|
91
94
|
}
|
|
92
95
|
|
|
96
|
+
// A models.dev row in the remote config's model shape, for catalogRow.
|
|
97
|
+
function configModelFromModelsDev(row) {
|
|
98
|
+
const cost = isPlainObject(row.cost) ? row.cost : null;
|
|
99
|
+
const effort = Array.isArray(row.reasoning_options)
|
|
100
|
+
? row.reasoning_options.find((option) => option?.type === 'effort')?.values
|
|
101
|
+
: null;
|
|
102
|
+
return {
|
|
103
|
+
name: row.name,
|
|
104
|
+
...(typeof row.npm === 'string' ? { package: row.npm } : {}),
|
|
105
|
+
limit: row.limit,
|
|
106
|
+
...(cost
|
|
107
|
+
? { cost: { input: cost.input, output: cost.output, cache: { read: cost.cache_read, write: cost.cache_write } } }
|
|
108
|
+
: {}),
|
|
109
|
+
...(typeof row.reasoning === 'boolean'
|
|
110
|
+
? { capabilities: { reasoning: { supported: row.reasoning, ...(effort ? { effort } : {}) } } }
|
|
111
|
+
: {}),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// models.dev serves the Go models over the OpenAI-compatible package unless a row names its own.
|
|
116
|
+
const MODELS_DEV_PROVIDER_PACKAGE = '@ai-sdk/openai-compatible';
|
|
117
|
+
|
|
118
|
+
const listsGoModels = (json) => Object.keys(json?.providers?.[CONFIG_PROVIDER_KEY]?.models || {}).length > 0;
|
|
119
|
+
|
|
120
|
+
// The models.dev Go catalog, loaded first because the sync read is null on a cold cache.
|
|
121
|
+
// The loader swallows its own failure, so a missing catalog is a failed discovery
|
|
122
|
+
// (the last published roster stays), never an authoritative empty roster.
|
|
123
|
+
async function loadModelsDevGoModels() {
|
|
124
|
+
await loadModelsDevCatalog();
|
|
125
|
+
const models = getModelsDevProviderModelsSync(CONFIG_PROVIDER_KEY);
|
|
126
|
+
if (!models || Object.keys(models).length === 0) {
|
|
127
|
+
throw openCodeGoError(
|
|
128
|
+
`[${PROVIDER_ID}] the OpenCode organization config lists no models and the models.dev OpenCode Go catalog is unavailable`,
|
|
129
|
+
{ kind: 'catalog' }
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
return models;
|
|
133
|
+
}
|
|
134
|
+
|
|
93
135
|
/**
|
|
94
136
|
* The Go provider of a remote config response: `{ baseURL, headers, models }`
|
|
95
|
-
* with one catalog row per enabled model.
|
|
137
|
+
* with one catalog row per enabled model. A config that lists no models takes
|
|
138
|
+
* the models.dev Go models (`modelsDevModels`, id → row) instead.
|
|
96
139
|
*/
|
|
97
|
-
export function goConfigFromResponse(json) {
|
|
140
|
+
export function goConfigFromResponse(json, modelsDevModels = null) {
|
|
98
141
|
const entry = json?.providers?.[CONFIG_PROVIDER_KEY];
|
|
99
142
|
if (!isPlainObject(entry)) {
|
|
100
143
|
throw openCodeGoError(`[${PROVIDER_ID}] the OpenCode organization config has no OpenCode Go provider`, {
|
|
@@ -102,9 +145,20 @@ export function goConfigFromResponse(json) {
|
|
|
102
145
|
});
|
|
103
146
|
}
|
|
104
147
|
const providerPackage = typeof entry.package === 'string' ? entry.package : '';
|
|
105
|
-
const
|
|
148
|
+
const fallback = !listsGoModels(json) && isPlainObject(modelsDevModels);
|
|
149
|
+
const source = fallback
|
|
150
|
+
? Object.fromEntries(
|
|
151
|
+
Object.entries(modelsDevModels).map(([id, row]) => [
|
|
152
|
+
id,
|
|
153
|
+
isPlainObject(row) ? configModelFromModelsDev(row) : row,
|
|
154
|
+
])
|
|
155
|
+
)
|
|
156
|
+
: isPlainObject(entry.models)
|
|
157
|
+
? entry.models
|
|
158
|
+
: {};
|
|
159
|
+
const models = Object.entries(source)
|
|
106
160
|
.filter(([id, model]) => id && isPlainObject(model) && model.disabled !== true)
|
|
107
|
-
.map(([id, model]) => catalogRow(id, model, providerPackage));
|
|
161
|
+
.map(([id, model]) => catalogRow(id, model, fallback ? MODELS_DEV_PROVIDER_PACKAGE : providerPackage));
|
|
108
162
|
return {
|
|
109
163
|
baseURL:
|
|
110
164
|
typeof entry.settings?.baseURL === 'string' && entry.settings.baseURL
|
|
@@ -172,9 +226,8 @@ export class OpenCodeGoOAuthProvider {
|
|
|
172
226
|
const current = loadTokens();
|
|
173
227
|
return current?.account_id === tokens.account_id && current?.org_id === tokens.org_id;
|
|
174
228
|
});
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
);
|
|
229
|
+
const response = await consoleGetJson(CONFIG_URL, tokens, { fetchFn: this.config.fetchImpl, refresh: true });
|
|
230
|
+
const remote = goConfigFromResponse(response, listsGoModels(response) ? null : await loadModelsDevGoModels());
|
|
178
231
|
publish(remote.models, {
|
|
179
232
|
baseURL: remote.baseURL,
|
|
180
233
|
headers: remote.headers,
|
|
@@ -335,8 +335,19 @@ const CODE_KINDS = new Map(
|
|
|
335
335
|
quota_exhausted: ['quota_exceeded', 'quota_exhausted', 'usage_limit_reached', 'provider_accounts_exhausted'],
|
|
336
336
|
context_overflow: ['context_length_exceeded', 'context_window_exceeded', 'model_context_window_exceeded'],
|
|
337
337
|
request_too_large: ['request_too_large', 'payload_too_large', 'request_entity_too_large'],
|
|
338
|
-
|
|
339
|
-
|
|
338
|
+
// Google names a rejected or expired key with an ErrorInfo reason on an
|
|
339
|
+
// INVALID_ARGUMENT 400; the reason outranks the envelope status.
|
|
340
|
+
auth: [
|
|
341
|
+
'invalid_api_key',
|
|
342
|
+
'authentication_error',
|
|
343
|
+
'unauthenticated',
|
|
344
|
+
'unauthorized',
|
|
345
|
+
'invalid_authentication',
|
|
346
|
+
'api_key_invalid',
|
|
347
|
+
'api_key_expired',
|
|
348
|
+
'access_token_expired',
|
|
349
|
+
],
|
|
350
|
+
permission: ['permission_error', 'permission_denied', 'forbidden', 'service_disabled', 'api_key_service_blocked'],
|
|
340
351
|
overloaded: [
|
|
341
352
|
'server_is_overloaded',
|
|
342
353
|
'overloaded_error',
|
|
@@ -374,6 +385,7 @@ const CODE_KINDS = new Map(
|
|
|
374
385
|
'not_found',
|
|
375
386
|
'not_found_error',
|
|
376
387
|
'model_not_found',
|
|
388
|
+
'model_not_supported',
|
|
377
389
|
'unsupported_parameter',
|
|
378
390
|
],
|
|
379
391
|
}).flatMap(([kind, codes]) => codes.map((code) => [code, kind]))
|
|
@@ -509,6 +509,15 @@ export function providerInputExcludesCache(name) {
|
|
|
509
509
|
export function providerNativePdf(name) {
|
|
510
510
|
return providerTakesNativePdf(providers.get(String(name || '').toLowerCase()));
|
|
511
511
|
}
|
|
512
|
+
/**
|
|
513
|
+
* Whether the named provider sends image input to its models: false only for
|
|
514
|
+
* an adapter that declares `takesImages = false` (the text-only local
|
|
515
|
+
* runtime, which lowers every image to a placeholder). A pure lookup; an
|
|
516
|
+
* unknown provider is treated as taking images, as attachments are.
|
|
517
|
+
*/
|
|
518
|
+
export function providerReadsImages(name) {
|
|
519
|
+
return providers.get(String(name || '').toLowerCase())?.takesImages !== false;
|
|
520
|
+
}
|
|
512
521
|
/**
|
|
513
522
|
* Whether the named provider's adapter declares `consumesReadWindows`: it
|
|
514
523
|
* needs the structured clip report of read results. A pure lookup; a proxy
|