mixdog 1.2.5 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSES/simple-icons-CC0-1.0.txt +30 -0
- package/NOTICE.md +19 -0
- package/package.json +4 -1
- package/scripts/check-model-recommendations.mjs +89 -0
- package/scripts/gate-local.mjs +7 -0
- package/scripts/lib/gate-scheduler.mjs +2 -2
- package/scripts/lib/isolated-test-env.mjs +16 -0
- package/scripts/lib/run-node-tests.mjs +5 -14
- package/scripts/provider-pingpong-live.mjs +9 -9
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +5 -4
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +17 -0
- package/src/defaults/skills/browser-use/SKILL.md +7 -1
- package/src/defaults/skills/computer-use/SKILL.md +3 -1
- package/src/defaults/skills/memory-management/SKILL.md +4 -1
- package/src/defaults/skills/setup/references/actions.md +11 -4
- package/src/defaults/skills/setup-guide/SKILL.md +175 -0
- package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
- package/src/defaults/skills/visualize/SKILL.md +3 -2
- package/src/lib/rules-builder.cjs +56 -7
- package/src/output-styles/common.md +22 -6
- package/src/output-styles/detailed.md +7 -5
- package/src/output-styles/minimal.md +7 -3
- package/src/output-styles/simple.md +2 -3
- package/src/rules/agent/AGENT.md +7 -1
- package/src/rules/agent-mode/AGENT_MODE.md +24 -0
- package/src/rules/agent-mode/MIXY.md +21 -0
- package/src/rules/agent-mode/ROUTINE.md +6 -0
- package/src/rules/lead/LEAD.md +9 -4
- package/src/rules/shared/10-tool-workflow.md +2 -1
- package/src/rules/shared/60-verification.md +4 -5
- package/src/rules/shared/70-delivery.md +3 -0
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
- package/src/runtime/agent/orchestrator/config.mjs +6 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +182 -13
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +5 -3
- package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +215 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +58 -64
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
- package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +41 -19
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +11 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
- package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
- package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +98 -4
- package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +15 -8
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +50 -20
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
- package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +162 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +641 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +165 -0
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
- package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +82 -33
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +11 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -5
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +55 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
- package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +70 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +277 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
- package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
- package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +325 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +84 -21
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +44 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
- package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +123 -32
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
- package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
- package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +64 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +10 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +104 -55
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/office-extract.mjs +11 -9
- package/src/runtime/browser-bridge/client.mjs +24 -0
- package/src/runtime/channels/lib/scheduler.mjs +40 -12
- package/src/runtime/channels/lib/schedules-db.mjs +71 -12
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
- package/src/runtime/channels/lib/webhook.mjs +0 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
- package/src/runtime/channels/lib/worker-main.mjs +17 -20
- package/src/runtime/computer-bridge/client.mjs +28 -1
- package/src/runtime/connectors/gmail-app-password.mjs +690 -0
- package/src/runtime/connectors/google-mcp.mjs +446 -0
- package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
- package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
- package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
- package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
- package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
- package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
- package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
- package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
- package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
- package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
- package/src/runtime/memory/lib/memory.mjs +7 -1
- package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
- package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
- package/src/runtime/memory/lib/tool-call-handler.mjs +9 -5
- package/src/runtime/memory/tool-defs.mjs +5 -0
- package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
- package/src/runtime/office/core/tabular.mjs +1 -1
- package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
- package/src/runtime/office/portable/docx-formatting.mjs +1 -1
- package/src/runtime/office/portable/docx-runs.mjs +1 -1
- package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
- package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
- package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
- package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
- package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
- package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
- package/src/runtime/office/portable/portable-opc.mjs +27 -13
- package/src/runtime/office/portable/portable-pivot.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
- package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
- package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
- package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
- package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
- package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
- package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
- package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
- package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
- package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
- package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
- package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
- package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
- package/src/runtime/office/portable/portable-xml.mjs +1 -1
- package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
- package/src/runtime/shared/agent-avatar.d.mts +64 -0
- package/src/runtime/shared/agent-avatar.mjs +320 -0
- package/src/runtime/shared/agent-route-config.d.mts +3 -0
- package/src/runtime/shared/agent-route-config.mjs +16 -0
- package/src/runtime/shared/atomic-file.mjs +36 -14
- package/src/runtime/shared/background-tasks.mjs +60 -20
- package/src/runtime/shared/child-spawn-gate.mjs +26 -16
- package/src/runtime/shared/config.mjs +8 -11
- package/src/runtime/shared/connector-accounts.mjs +15 -0
- package/src/runtime/shared/connector-catalog.d.mts +52 -0
- package/src/runtime/shared/connector-catalog.mjs +230 -0
- package/src/runtime/shared/connector-triggers.d.mts +3 -0
- package/src/runtime/shared/connector-triggers.mjs +43 -0
- package/src/runtime/shared/file-lock.mjs +7 -1
- package/src/runtime/shared/file-permissions-worker.mjs +38 -0
- package/src/runtime/shared/file-permissions.d.mts +19 -4
- package/src/runtime/shared/file-permissions.mjs +310 -4
- package/src/runtime/shared/git-runner-worker.mjs +6 -78
- package/src/runtime/shared/google-oauth-client.mjs +24 -0
- package/src/runtime/shared/held-request-host.d.mts +12 -0
- package/src/runtime/shared/held-request-host.mjs +71 -0
- package/src/runtime/shared/llm/http-agent.mjs +7 -3
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
- package/src/runtime/shared/memory-snapshot.mjs +5 -1
- package/src/runtime/shared/notify-trace.mjs +8 -1
- package/src/runtime/shared/plain-preview.d.mts +1 -0
- package/src/runtime/shared/plain-preview.mjs +28 -0
- package/src/runtime/shared/pristine-execution-contract.json +5 -1
- package/src/runtime/shared/process-runner-worker.mjs +7 -0
- package/src/runtime/shared/process-runner.mjs +38 -0
- package/src/runtime/shared/provider-accounts.mjs +2 -1
- package/src/runtime/shared/provider-api-key.mjs +0 -1
- package/src/runtime/shared/read-row-numbers.mjs +1 -1
- package/src/runtime/shared/resource-admission.mjs +60 -18
- package/src/runtime/shared/routine-limits.d.mts +11 -0
- package/src/runtime/shared/routine-limits.mjs +21 -0
- package/src/runtime/shared/routine-trigger.d.mts +10 -0
- package/src/runtime/shared/routine-trigger.mjs +44 -0
- package/src/runtime/shared/run-child.mjs +84 -0
- package/src/runtime/shared/schedule-model-ref.mjs +9 -10
- package/src/runtime/shared/session-activity-signal.mjs +23 -0
- package/src/runtime/shared/shell-output-summary.mjs +23 -0
- package/src/runtime/shared/singleton-owner.mjs +126 -42
- package/src/runtime/shared/slow-span.mjs +4 -12
- package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
- package/src/runtime/shared/tool-output-limit.mjs +4 -2
- package/src/runtime/shared/tool-output-marker.mjs +58 -0
- package/src/runtime/shared/transcript-metadata.mjs +10 -0
- package/src/runtime/shared/turn-changes.mjs +0 -8
- package/src/runtime/shared/usage-readout-totals.mjs +56 -0
- package/src/runtime/shared/user-data-guard.mjs +131 -34
- package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
- package/src/runtime/shared/worktrees/git-head.mjs +20 -2
- package/src/runtime/shared/worktrees/lock.mjs +3 -2
- package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
- package/src/runtime/tidy/runners/biome.mjs +3 -1
- package/src/runtime/tidy/shadow.mjs +2 -1
- package/src/runtime/web-search/index.mjs +5 -7
- package/src/runtime/web-search/lib/formatter.mjs +42 -6
- package/src/runtime/web-search/tool-defs.mjs +6 -1
- package/src/session-runtime/agent-home-delivery.mjs +459 -0
- package/src/session-runtime/agent-profile-changes.mjs +21 -0
- package/src/session-runtime/agent-room-delivery.mjs +92 -0
- package/src/session-runtime/agent-task-sessions.mjs +200 -0
- package/src/session-runtime/boot/apis.mjs +50 -18
- package/src/session-runtime/boot/facade.mjs +5 -8
- package/src/session-runtime/boot/infrastructure.mjs +28 -17
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/channel-config-api.mjs +53 -5
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
- package/src/session-runtime/held-requests.mjs +228 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +11 -4
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
- package/src/session-runtime/lifecycle/shared.mjs +25 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +5 -2
- package/src/session-runtime/lifecycle-api.mjs +3 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
- package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +112 -15
- package/src/session-runtime/model-route/set-route.mjs +14 -3
- package/src/session-runtime/owned-automation-run.mjs +229 -0
- package/src/session-runtime/provider-auth/login.mjs +10 -6
- package/src/session-runtime/provider-auth/setup.mjs +19 -2
- package/src/session-runtime/provider-catalog-cache.mjs +101 -25
- package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
- package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
- package/src/session-runtime/provider-models.mjs +76 -10
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/resource-api.mjs +5 -0
- package/src/session-runtime/resource-mcp-api.mjs +107 -13
- package/src/session-runtime/resource-skills-api.mjs +12 -0
- package/src/session-runtime/room-member-gate.mjs +48 -0
- package/src/session-runtime/routine-home-turn.mjs +156 -0
- package/src/session-runtime/routine-owner.mjs +48 -0
- package/src/session-runtime/schedule-session-run.mjs +30 -64
- package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +10 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
- package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
- package/src/session-runtime/services/agent-tool.mjs +20 -0
- package/src/session-runtime/services/channel-admin.mjs +93 -24
- package/src/session-runtime/services/memory-access.mjs +37 -0
- package/src/session-runtime/services/provider-admin.mjs +166 -59
- package/src/session-runtime/services/schedule-access.mjs +91 -0
- package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
- package/src/session-runtime/services/usage-dashboard.mjs +27 -69
- package/src/session-runtime/session-create/session-options.mjs +34 -7
- package/src/session-runtime/session-hooks.mjs +16 -8
- package/src/session-runtime/setup-tool/executor.mjs +68 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +72 -14
- package/src/session-runtime/setup-tool/settings-contract.mjs +8 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/skills-api.mjs +16 -1
- package/src/session-runtime/tool-policy-refresh.mjs +238 -29
- package/src/session-runtime/turn/session-ops.mjs +10 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +11 -2
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +3 -0
- package/src/session-runtime/usage-stats-api.mjs +6 -1
- package/src/session-runtime/webhook-session-run.mjs +49 -67
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +556 -22
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
- package/src/session-runtime/workflow-agents-api.mjs +4 -1
- package/src/standalone/channel-transport/http-routes.mjs +10 -9
- package/src/standalone/daemon-agent-control.mjs +1 -8
- package/src/standalone/daemon-desktop-runtime.mjs +20 -7
- package/src/standalone/daemon-owner.mjs +117 -25
- package/src/standalone/daemon-session-control.mjs +11 -2
- package/src/standalone/daemon.mjs +61 -17
- package/src/standalone/session-call-cache.mjs +6 -0
- package/src/standalone/session-protocol.mjs +28 -1
- package/src/standalone/session-service/retention/busy.mjs +7 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +9 -0
- package/src/standalone/session-service.mjs +19 -0
- package/src/standalone/session-transport/routes.mjs +7 -6
- package/src/tui/app/model-options.mjs +39 -2
- package/src/tui/app/model-picker.mjs +16 -2
- package/src/tui/app/provider-setup-picker.mjs +1 -2
- package/src/tui/app/slash-commands.mjs +20 -0
- package/src/tui/dist/index.mjs +487 -128
- package/src/tui/session/context-state.mjs +6 -1
- package/src/tui/session/notice-surface.mjs +35 -4
- package/src/tui/session/notice-text.mjs +0 -1
- package/src/tui/session/queue-helpers.mjs +2 -1
- package/src/tui/session/session-api/extensions.mjs +4 -0
- package/src/tui/session/session-api/intake/submission.mjs +12 -13
- package/src/tui/session/session-api/integrations.mjs +9 -5
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
- package/src/tui/session/session-api/lifecycle.mjs +17 -1
- package/src/tui/session/session-api/routes.mjs +48 -3
- package/src/tui/session/session-flow/drain.mjs +20 -3
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
- package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
- package/src/tui/session/session-flow/steering.mjs +104 -24
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/tool-approval.mjs +26 -5
- package/src/tui/session/transcript-intake.mjs +6 -2
- package/src/tui/session/transcript-spill.mjs +5 -1
- package/src/tui/session/tui-steering-persist.mjs +65 -42
- package/src/tui/session/turn-live-call.mjs +56 -0
- package/src/tui/session/turn-stream.mjs +33 -0
- package/src/tui/session/turn.mjs +50 -7
- package/src/ui/statusline.mjs +1 -6
- package/src/ui/streaming-markdown-heal.mjs +24 -7
- package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
- package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
- package/src/workflows/default/WORKFLOW.md +9 -13
- package/src/session-runtime/automation-agents.mjs +0 -94
- package/src/session-runtime/automation-workflow.mjs +0 -59
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import { createServer } from 'node:http';
|
|
12
12
|
import { randomBytes } from 'node:crypto';
|
|
13
13
|
import { createOAuthPkce, parseOAuthCodeInput } from './lib/oauth-pkce.mjs';
|
|
14
|
-
import { OAUTH_PAGE_CONTENT_TYPE, oauthSuccessHtml } from './lib/oauth-page.mjs';
|
|
14
|
+
import { OAUTH_PAGE_CONTENT_TYPE, oauthErrorHtml, oauthSuccessHtml } from './lib/oauth-page.mjs';
|
|
15
15
|
import { openLoginUrl } from './lib/open-login-url.mjs';
|
|
16
16
|
|
|
17
17
|
const TOKEN_URL = 'https://auth.openai.com/oauth/token';
|
|
@@ -44,7 +44,8 @@ function _scrubOAuthLoginBody(text) {
|
|
|
44
44
|
export function createOpenAIOAuthLogin(deps) {
|
|
45
45
|
const { clientId, originator, extractAccountId, identityFromTokens, expiryFromAccessToken, saveTokens } = deps;
|
|
46
46
|
|
|
47
|
-
async function exchangeAuthorizationCode({ pkce, code }) {
|
|
47
|
+
async function exchangeAuthorizationCode({ pkce, code, signal = null }) {
|
|
48
|
+
signal?.throwIfAborted();
|
|
48
49
|
const cleanCode = String(code || '').trim();
|
|
49
50
|
if (!cleanCode) throw new Error('[openai-oauth] authorization code is required');
|
|
50
51
|
const tokenRes = await fetch(TOKEN_URL, {
|
|
@@ -58,7 +59,9 @@ export function createOpenAIOAuthLogin(deps) {
|
|
|
58
59
|
code_verifier: pkce.verifier,
|
|
59
60
|
}),
|
|
60
61
|
redirect: 'error',
|
|
61
|
-
signal:
|
|
62
|
+
signal: signal
|
|
63
|
+
? AbortSignal.any([signal, AbortSignal.timeout(TOKEN_TIMEOUT_MS)])
|
|
64
|
+
: AbortSignal.timeout(TOKEN_TIMEOUT_MS),
|
|
62
65
|
});
|
|
63
66
|
if (!tokenRes.ok) {
|
|
64
67
|
const text = await tokenRes.text().catch(() => '');
|
|
@@ -78,6 +81,8 @@ export function createOpenAIOAuthLogin(deps) {
|
|
|
78
81
|
account_id: extractAccountId(json.access_token),
|
|
79
82
|
identity: identityFromTokens(json.id_token, json.access_token),
|
|
80
83
|
};
|
|
84
|
+
// A cancelled login never stores the account it was exchanging.
|
|
85
|
+
signal?.throwIfAborted();
|
|
81
86
|
saveTokens(tokens);
|
|
82
87
|
return tokens;
|
|
83
88
|
}
|
|
@@ -100,11 +105,30 @@ export function createOpenAIOAuthLogin(deps) {
|
|
|
100
105
|
let server = null;
|
|
101
106
|
let timeout = null;
|
|
102
107
|
let finish = null;
|
|
108
|
+
let exchangePromise = null;
|
|
109
|
+
const controller = new AbortController();
|
|
110
|
+
// Browser and manual callbacks share one exchange: an authorization code is
|
|
111
|
+
// single-use, and a duplicate must not settle the login before the first.
|
|
112
|
+
const acceptCode = (code) => {
|
|
113
|
+
if (exchangePromise) return exchangePromise;
|
|
114
|
+
controller.signal.throwIfAborted();
|
|
115
|
+
// The browser deadline ends when a code arrives; the exchange has its own.
|
|
116
|
+
if (timeout) clearTimeout(timeout);
|
|
117
|
+
timeout = null;
|
|
118
|
+
exchangePromise = exchangeAuthorizationCode({ pkce, code, signal: controller.signal });
|
|
119
|
+
exchangePromise.then(
|
|
120
|
+
(tokens) => finish(tokens),
|
|
121
|
+
(err) => finish(null, err instanceof Error ? err : new Error(String(err)))
|
|
122
|
+
);
|
|
123
|
+
return exchangePromise;
|
|
124
|
+
};
|
|
103
125
|
const waitForCallback = new Promise((resolve, reject) => {
|
|
104
126
|
let settled = false;
|
|
105
127
|
finish = (value, error = null) => {
|
|
106
128
|
if (settled) return;
|
|
107
129
|
settled = true;
|
|
130
|
+
// Work arriving after the login settled (or was cancelled) is rejected.
|
|
131
|
+
controller.abort();
|
|
108
132
|
if (timeout) clearTimeout(timeout);
|
|
109
133
|
try {
|
|
110
134
|
server?.close();
|
|
@@ -122,19 +146,25 @@ export function createOpenAIOAuthLogin(deps) {
|
|
|
122
146
|
return;
|
|
123
147
|
}
|
|
124
148
|
const code = u.searchParams.get('code');
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
res.
|
|
128
|
-
|
|
149
|
+
const stateMatches = u.searchParams.get('state') === state;
|
|
150
|
+
if (!code || !stateMatches) {
|
|
151
|
+
res.writeHead(400, { 'Content-Type': OAUTH_PAGE_CONTENT_TYPE });
|
|
152
|
+
res.end(oauthErrorHtml('The sign-in callback was invalid or did not match this login.'));
|
|
153
|
+
// A request for another login is rejected alone; this login's
|
|
154
|
+
// legitimate callback may still arrive.
|
|
155
|
+
if (stateMatches && !exchangePromise) finish(null);
|
|
129
156
|
return;
|
|
130
157
|
}
|
|
131
|
-
res.writeHead(200, { 'Content-Type': OAUTH_PAGE_CONTENT_TYPE });
|
|
132
|
-
res.end(oauthSuccessHtml('OpenAI'));
|
|
133
158
|
try {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
159
|
+
await acceptCode(code);
|
|
160
|
+
// The login settles (closing the server) before this response is
|
|
161
|
+
// written; do not leave a keep-alive connection bound to it.
|
|
162
|
+
res.writeHead(200, { 'Content-Type': OAUTH_PAGE_CONTENT_TYPE, Connection: 'close' });
|
|
163
|
+
res.end(oauthSuccessHtml('OpenAI'));
|
|
164
|
+
} catch {
|
|
165
|
+
// The shared exchange reports its error through waitForCallback.
|
|
166
|
+
res.writeHead(500, { 'Content-Type': OAUTH_PAGE_CONTENT_TYPE, Connection: 'close' });
|
|
167
|
+
res.end(oauthErrorHtml('OpenAI could not complete the token exchange.'));
|
|
138
168
|
}
|
|
139
169
|
});
|
|
140
170
|
timeout = setTimeout(() => finish(null), LOGIN_TIMEOUT_MS);
|
|
@@ -161,9 +191,8 @@ export function createOpenAIOAuthLogin(deps) {
|
|
|
161
191
|
completeCode: async (input) => {
|
|
162
192
|
const parsed = parseOAuthCodeInput(input, { allowHashState: true });
|
|
163
193
|
if (parsed.state && parsed.state !== state) throw new Error('[openai-oauth] OAuth state mismatch');
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return tokens;
|
|
194
|
+
if (!parsed.code) throw new Error('[openai-oauth] authorization code is required');
|
|
195
|
+
return await acceptCode(parsed.code);
|
|
167
196
|
},
|
|
168
197
|
cancel: () => {
|
|
169
198
|
finish?.(null);
|
|
@@ -92,6 +92,15 @@ export function identityFromTokens(...tokens) {
|
|
|
92
92
|
return normalizeAccountIdentity({ id: [sub, accountId].filter(Boolean).join(':'), email });
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/** ChatGPT plan (e.g. plus, pro) from the first token carrying the claim, else null. */
|
|
96
|
+
export function planFromTokens(...tokens) {
|
|
97
|
+
for (const token of tokens) {
|
|
98
|
+
const plan = decodeJwtPayload(token)?.['https://api.openai.com/auth']?.chatgpt_plan_type;
|
|
99
|
+
if (typeof plan === 'string' && plan) return plan;
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
95
104
|
/** mtime of the token file, 0 when it is missing or unreadable. */
|
|
96
105
|
export function tokensFileMtimeMs() {
|
|
97
106
|
try {
|
|
@@ -165,6 +174,7 @@ export function describeOpenAIOAuthCredentials() {
|
|
|
165
174
|
...oauthCredentialStatus({ hasRefresh, expiresAt, detail: source, refreshSkewMs: TOKEN_REFRESH_SKEW_MS }),
|
|
166
175
|
...accountIdentityFields(tokens.identity),
|
|
167
176
|
...(accountId ? { accountId } : {}),
|
|
177
|
+
plan: planFromTokens(tokens.id_token, tokens.access_token),
|
|
168
178
|
};
|
|
169
179
|
} catch (err) {
|
|
170
180
|
return {
|
|
@@ -297,6 +297,7 @@ export async function sendViaWebSocket({
|
|
|
297
297
|
onStreamDelta,
|
|
298
298
|
onToolCall,
|
|
299
299
|
onTextDelta,
|
|
300
|
+
onStreamItemStart: typeof sendOpts?.onStreamItemStart === 'function' ? sendOpts.onStreamItemStart : null,
|
|
300
301
|
state: midState,
|
|
301
302
|
logSuppressedReasoningDeltas,
|
|
302
303
|
traceProvider,
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openai-ws-connect.mjs — how a Responses WebSocket reaches the server.
|
|
3
|
+
*
|
|
4
|
+
* Every pool handshake is a brand-new TCP+TLS connection (the upgrade detaches
|
|
5
|
+
* it from any HTTP keep-alive pool), so a burst of agents starting together
|
|
6
|
+
* pays one DNS resolution and one full TLS handshake per socket. This module
|
|
7
|
+
* removes the repeated work and the long stall:
|
|
8
|
+
*
|
|
9
|
+
* - lookup: one resolution per host, shared by concurrent handshakes and
|
|
10
|
+
* reused for a short TTL (libuv's small thread pool otherwise queues one
|
|
11
|
+
* getaddrinfo per socket behind unrelated file I/O);
|
|
12
|
+
* - TLS resumption: the latest session ticket per host rides the next
|
|
13
|
+
* connect, so later sockets skip the full key exchange;
|
|
14
|
+
* - hedged open: an upgrade that has not opened within the hedge window
|
|
15
|
+
* gets a parallel replacement attempt instead of waiting out the whole
|
|
16
|
+
* acquire timeout. The first leg to open wins; the rest are cancelled.
|
|
17
|
+
* Server decisions (any HTTP status on the upgrade, e.g. 429/401) end
|
|
18
|
+
* the race at once so backoff stays driven by real server signals.
|
|
19
|
+
*/
|
|
20
|
+
import { lookup as dnsLookup } from 'node:dns';
|
|
21
|
+
import net from 'node:net';
|
|
22
|
+
import tls from 'node:tls';
|
|
23
|
+
import { resolveTimeoutMs } from '../stall-policy.mjs';
|
|
24
|
+
|
|
25
|
+
const DNS_TTL_MS = resolveTimeoutMs('MIXDOG_PROVIDER_WS_DNS_TTL_MS', 30_000, { minMs: 1_000, maxMs: 300_000 });
|
|
26
|
+
// Observed production upgrades: p95 ≈ 0.55s, max ≈ 3.4s over 6k handshakes,
|
|
27
|
+
// so a leg still unopened after 3s is almost certainly stuck.
|
|
28
|
+
const WS_HEDGE_MS = resolveTimeoutMs('MIXDOG_PROVIDER_WS_HEDGE_MS', 3_000, { minMs: 500, maxMs: 60_000 });
|
|
29
|
+
|
|
30
|
+
const _dnsCache = new Map();
|
|
31
|
+
|
|
32
|
+
function _lookupKey(hostname, options) {
|
|
33
|
+
return `${hostname}\0${options?.family || 0}\0${options?.hints || 0}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function _answer(addresses, options, callback) {
|
|
37
|
+
if (options?.all) {
|
|
38
|
+
callback(null, addresses);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const first = addresses[0];
|
|
42
|
+
callback(null, first.address, first.family);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** dns.lookup-compatible resolver with in-flight coalescing and a short TTL. */
|
|
46
|
+
export function cachedLookup(hostname, options, callback) {
|
|
47
|
+
const opts = typeof options === 'function' ? {} : typeof options === 'number' ? { family: options } : options || {};
|
|
48
|
+
const cb = typeof options === 'function' ? options : callback;
|
|
49
|
+
const key = _lookupKey(hostname, opts);
|
|
50
|
+
const cached = _dnsCache.get(key);
|
|
51
|
+
if (cached?.addresses && cached.expiresAt > Date.now()) {
|
|
52
|
+
_answer(cached.addresses, opts, cb);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (cached?.waiters) {
|
|
56
|
+
cached.waiters.push({ opts, cb });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const record = { waiters: [{ opts, cb }] };
|
|
60
|
+
_dnsCache.set(key, record);
|
|
61
|
+
dnsLookup(hostname, { family: opts.family || 0, hints: opts.hints || 0, all: true }, (err, addresses) => {
|
|
62
|
+
const waiters = record.waiters;
|
|
63
|
+
if (err || !addresses?.length) {
|
|
64
|
+
if (_dnsCache.get(key) === record) _dnsCache.delete(key);
|
|
65
|
+
const failure = err || Object.assign(new Error(`lookup ${hostname} returned no address`), { code: 'ENOTFOUND' });
|
|
66
|
+
for (const waiter of waiters) waiter.cb(failure);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
_dnsCache.set(key, { addresses, expiresAt: Date.now() + DNS_TTL_MS });
|
|
70
|
+
for (const waiter of waiters) _answer(addresses, waiter.opts, waiter.cb);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const _tlsSessions = new Map();
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* `ws` createConnection: the shared lookup for every socket, plus TLS
|
|
78
|
+
* resumption for secure ones. Mirrors ws's own servername defaulting.
|
|
79
|
+
*/
|
|
80
|
+
export function createWsConnection(options) {
|
|
81
|
+
if (options.protocol === 'ws:' || options.protocol === 'http:') {
|
|
82
|
+
return net.connect({ ...options, path: options.socketPath, lookup: cachedLookup });
|
|
83
|
+
}
|
|
84
|
+
const sessionKey = `${options.host}:${options.port}`;
|
|
85
|
+
const servername =
|
|
86
|
+
options.servername || options.servername === '' ? options.servername : net.isIP(options.host) ? '' : options.host;
|
|
87
|
+
const socket = tls.connect({
|
|
88
|
+
...options,
|
|
89
|
+
path: undefined,
|
|
90
|
+
servername,
|
|
91
|
+
lookup: cachedLookup,
|
|
92
|
+
session: _tlsSessions.get(sessionKey),
|
|
93
|
+
});
|
|
94
|
+
socket.on('session', (session) => _tlsSessions.set(sessionKey, session));
|
|
95
|
+
return socket;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Test-only reset of the resolver and TLS session caches. */
|
|
99
|
+
export function _clearConnectCachesForTest() {
|
|
100
|
+
_dnsCache.clear();
|
|
101
|
+
_tlsSessions.clear();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function _abortReason(signal, fallback) {
|
|
105
|
+
return signal?.reason instanceof Error ? signal.reason : new Error(fallback);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Race handshake legs until one opens. `openLeg({ externalSignal })` opens one
|
|
110
|
+
* socket and resolves `{ socket }`. A new leg starts every `hedgeMs` while
|
|
111
|
+
* none has opened and the acquire deadline leaves room; a leg's transport
|
|
112
|
+
* failure only ends the race when nothing else is still connecting.
|
|
113
|
+
*/
|
|
114
|
+
export function openHedged({ openLeg, externalSignal, hedgeMs = WS_HEDGE_MS, deadlineMs, deadlineError }) {
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
const startedAt = Date.now();
|
|
117
|
+
const legs = new Set();
|
|
118
|
+
let settled = false;
|
|
119
|
+
let hedgeTimer = null;
|
|
120
|
+
let deadlineTimer = null;
|
|
121
|
+
let lastError = null;
|
|
122
|
+
|
|
123
|
+
const cleanup = () => {
|
|
124
|
+
if (hedgeTimer) clearTimeout(hedgeTimer);
|
|
125
|
+
if (deadlineTimer) clearTimeout(deadlineTimer);
|
|
126
|
+
externalSignal?.removeEventListener?.('abort', onExternalAbort);
|
|
127
|
+
};
|
|
128
|
+
const cancelLegs = (reason) => {
|
|
129
|
+
for (const leg of legs) leg.abort(reason);
|
|
130
|
+
legs.clear();
|
|
131
|
+
};
|
|
132
|
+
const finish = (ok, value) => {
|
|
133
|
+
if (settled) return;
|
|
134
|
+
settled = true;
|
|
135
|
+
cleanup();
|
|
136
|
+
(ok ? resolve : reject)(value);
|
|
137
|
+
};
|
|
138
|
+
const fail = (err) => {
|
|
139
|
+
cancelLegs(err);
|
|
140
|
+
finish(false, err);
|
|
141
|
+
};
|
|
142
|
+
function onExternalAbort() {
|
|
143
|
+
fail(_abortReason(externalSignal, 'OpenAI WS handshake aborted'));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const scheduleHedge = () => {
|
|
147
|
+
if (settled || !(hedgeMs > 0)) return;
|
|
148
|
+
if (Date.now() - startedAt + hedgeMs >= deadlineMs) return;
|
|
149
|
+
hedgeTimer = setTimeout(() => {
|
|
150
|
+
hedgeTimer = null;
|
|
151
|
+
startLeg();
|
|
152
|
+
}, hedgeMs);
|
|
153
|
+
hedgeTimer.unref?.();
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
function startLeg() {
|
|
157
|
+
if (settled) return;
|
|
158
|
+
const controller = new AbortController();
|
|
159
|
+
legs.add(controller);
|
|
160
|
+
Promise.resolve()
|
|
161
|
+
.then(() => openLeg({ externalSignal: controller.signal }))
|
|
162
|
+
.then(
|
|
163
|
+
(opened) => {
|
|
164
|
+
legs.delete(controller);
|
|
165
|
+
if (settled) {
|
|
166
|
+
try {
|
|
167
|
+
opened?.socket?.terminate?.();
|
|
168
|
+
} catch {}
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
cancelLegs(new Error('OpenAI WS handshake superseded by a faster attempt'));
|
|
172
|
+
finish(true, opened);
|
|
173
|
+
},
|
|
174
|
+
(err) => {
|
|
175
|
+
legs.delete(controller);
|
|
176
|
+
if (settled || controller.signal.aborted) return;
|
|
177
|
+
lastError = err;
|
|
178
|
+
// An HTTP status is the server's decision for this request
|
|
179
|
+
// (rate limit, auth, upgrade refusal): surface it unchanged.
|
|
180
|
+
if (err?.httpStatus != null || legs.size === 0) fail(err);
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
if (hedgeTimer) clearTimeout(hedgeTimer);
|
|
184
|
+
scheduleHedge();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (externalSignal?.aborted) {
|
|
188
|
+
onExternalAbort();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
externalSignal?.addEventListener?.('abort', onExternalAbort, { once: true });
|
|
192
|
+
deadlineTimer = setTimeout(() => fail(lastError?.httpStatus != null ? lastError : deadlineError()), deadlineMs);
|
|
193
|
+
deadlineTimer.unref?.();
|
|
194
|
+
startLeg();
|
|
195
|
+
});
|
|
196
|
+
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { createHash, randomBytes } from 'node:crypto';
|
|
10
10
|
import { performance } from 'node:perf_hooks';
|
|
11
11
|
import { attachHandshakeFailureHandlers, captureHandshakeUpgrade } from './openai-ws-handshake.mjs';
|
|
12
|
+
import { createWsConnection, openHedged } from './openai-ws-connect.mjs';
|
|
12
13
|
import { codexOriginator, codexUserAgent, codexVersionHeader } from './codex-client-meta.mjs';
|
|
13
14
|
import {
|
|
14
15
|
PROVIDER_WS_ACQUIRE_TIMEOUT_MS,
|
|
@@ -539,7 +540,26 @@ const WS_URL_BY_AUTH = { xai: XAI_WS_URL, 'openai-direct': OPENAI_WS_URL };
|
|
|
539
540
|
/** The auth kind an error label names; anything but xAI/direct is the OAuth (Codex) path. */
|
|
540
541
|
const _wsAuthKind = (auth) => (auth?.type === 'xai' || auth?.type === 'openai-direct' ? auth.type : 'openai-oauth');
|
|
541
542
|
|
|
542
|
-
|
|
543
|
+
function _acquireTimeoutError(auth) {
|
|
544
|
+
return Object.assign(
|
|
545
|
+
new Error(`${_wsErrLabel(_wsAuthKind(auth))} acquire timed out before open (${WS_ACQUIRE_TIMEOUT_MS}ms)`),
|
|
546
|
+
{ code: 'EWSACQUIRETIMEOUT', acquireTimeoutMs: WS_ACQUIRE_TIMEOUT_MS }
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// One acquire = a hedged race of handshake legs under the acquire deadline
|
|
551
|
+
// (openai-ws-connect.mjs): a stuck upgrade is replaced after the hedge window
|
|
552
|
+
// instead of costing the whole timeout plus a retry.
|
|
553
|
+
function _openSocket(args) {
|
|
554
|
+
return openHedged({
|
|
555
|
+
openLeg: ({ externalSignal }) => _openSocketLeg({ ...args, externalSignal }),
|
|
556
|
+
externalSignal: args.externalSignal,
|
|
557
|
+
deadlineMs: WS_ACQUIRE_TIMEOUT_MS,
|
|
558
|
+
deadlineError: () => _acquireTimeoutError(args.auth),
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
async function _openSocketLeg({ auth, sessionToken, externalSignal, cacheKey, codexHeaders }) {
|
|
543
563
|
// `ws` loads on the first socket, not at runtime boot via provider-admin.
|
|
544
564
|
const { default: WebSocket } = await import('ws');
|
|
545
565
|
const headers = _buildHandshakeHeaders({ auth, sessionToken, cacheKey, codexHeaders });
|
|
@@ -586,6 +606,7 @@ async function _openSocket({ auth, sessionToken, externalSignal, cacheKey, codex
|
|
|
586
606
|
headers,
|
|
587
607
|
handshakeTimeout: WS_HANDSHAKE_TIMEOUT_MS,
|
|
588
608
|
maxPayload: WS_MAX_INCOMING_FRAME_BYTES,
|
|
609
|
+
createConnection: createWsConnection,
|
|
589
610
|
});
|
|
590
611
|
acquireTimer = setTimeout(() => {
|
|
591
612
|
if (settled) return;
|
|
@@ -597,13 +618,7 @@ async function _openSocket({ auth, sessionToken, externalSignal, cacheKey, codex
|
|
|
597
618
|
try {
|
|
598
619
|
socket.terminate();
|
|
599
620
|
} catch {}
|
|
600
|
-
settle(
|
|
601
|
-
false,
|
|
602
|
-
Object.assign(
|
|
603
|
-
new Error(`${_wsErrLabel(_wsAuthKind(auth))} acquire timed out before open (${WS_ACQUIRE_TIMEOUT_MS}ms)`),
|
|
604
|
-
{ code: 'EWSACQUIRETIMEOUT', acquireTimeoutMs: WS_ACQUIRE_TIMEOUT_MS }
|
|
605
|
-
)
|
|
606
|
-
);
|
|
621
|
+
settle(false, _acquireTimeoutError(auth));
|
|
607
622
|
}, WS_ACQUIRE_TIMEOUT_MS);
|
|
608
623
|
try {
|
|
609
624
|
acquireTimer.unref?.();
|
|
@@ -764,6 +779,52 @@ function _onEntryClosed(poolKey, entry) {
|
|
|
764
779
|
if (!entry.ephemeral) _removeFromPool(poolKey, entry);
|
|
765
780
|
}
|
|
766
781
|
|
|
782
|
+
// Sessionless sends (no poolKey) carry no turn state or response chain of
|
|
783
|
+
// their own, so their connections are shared: one idle bucket per
|
|
784
|
+
// credential + cache key, no owner claim (concurrent sessionless callers
|
|
785
|
+
// each take a different idle socket or open one), and a reused socket starts
|
|
786
|
+
// with an empty chain so no request ever deltas against another caller's
|
|
787
|
+
// response. Without this every sessionless send paid a fresh handshake and
|
|
788
|
+
// closed the socket on release.
|
|
789
|
+
const SHARED_POOL_PREFIX = '\0shared:';
|
|
790
|
+
|
|
791
|
+
function _resetChain(entry) {
|
|
792
|
+
entry.lastResponseId = null;
|
|
793
|
+
entry.lastRequestSansInput = null;
|
|
794
|
+
entry.lastRequestInput = null;
|
|
795
|
+
entry.lastResponseItems = null;
|
|
796
|
+
entry.lastInputLen = 0;
|
|
797
|
+
entry.lastInputPrefixHash = null;
|
|
798
|
+
entry.turnState = null;
|
|
799
|
+
entry.turnStateScope = null;
|
|
800
|
+
entry.turnStateTurnId = null;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
async function _acquireShared({ auth, cacheKey, codexHeaders, externalSignal, acqStart }) {
|
|
804
|
+
const compatibility = _poolCompatibility(auth, cacheKey);
|
|
805
|
+
const sharedKey = `${SHARED_POOL_PREFIX}${compatibility.authIdentity}:${compatibility.cacheKeyIdentity}`;
|
|
806
|
+
const arr = _wsPool.get(sharedKey) || [];
|
|
807
|
+
_pruneStaleEntries(sharedKey, arr, compatibility);
|
|
808
|
+
const idle = await _takeIdleEntry(sharedKey, arr, compatibility, acqStart);
|
|
809
|
+
if (idle) {
|
|
810
|
+
_resetChain(idle);
|
|
811
|
+
return { entry: idle, reused: true, ownerWaitMs: 0 };
|
|
812
|
+
}
|
|
813
|
+
const entry = await _openPoolEntry({
|
|
814
|
+
auth,
|
|
815
|
+
cacheKey,
|
|
816
|
+
codexHeaders,
|
|
817
|
+
externalSignal,
|
|
818
|
+
compatibility,
|
|
819
|
+
ephemeral: false,
|
|
820
|
+
acqStart,
|
|
821
|
+
});
|
|
822
|
+
entry.sharedPoolKey = sharedKey;
|
|
823
|
+
_getPoolArr(sharedKey).push(entry);
|
|
824
|
+
entry.socket.on('close', () => _onEntryClosed(sharedKey, entry));
|
|
825
|
+
return { entry, reused: false, ownerWaitMs: 0 };
|
|
826
|
+
}
|
|
827
|
+
|
|
767
828
|
export async function acquireWebSocket({ auth, poolKey, cacheKey, codexHeaders, forceFresh, externalSignal }) {
|
|
768
829
|
const _acqStart = Date.now();
|
|
769
830
|
_acquireTrace(
|
|
@@ -772,6 +833,9 @@ export async function acquireWebSocket({ auth, poolKey, cacheKey, codexHeaders,
|
|
|
772
833
|
if (externalSignal?.aborted) {
|
|
773
834
|
throw _acquireAbortError(externalSignal);
|
|
774
835
|
}
|
|
836
|
+
if (!poolKey && !forceFresh) {
|
|
837
|
+
return _acquireShared({ auth, cacheKey, codexHeaders, externalSignal, acqStart: _acqStart });
|
|
838
|
+
}
|
|
775
839
|
const ownerClaim = await _claimPoolOwner(poolKey, externalSignal);
|
|
776
840
|
const acquired = (entry, reused) => {
|
|
777
841
|
_bindPoolOwner(poolKey, ownerClaim, entry);
|
|
@@ -825,8 +889,9 @@ export async function acquireWebSocket({ auth, poolKey, cacheKey, codexHeaders,
|
|
|
825
889
|
}
|
|
826
890
|
}
|
|
827
891
|
|
|
828
|
-
export function releaseWebSocket({ entry, poolKey, keep }) {
|
|
892
|
+
export function releaseWebSocket({ entry, poolKey: callerPoolKey, keep }) {
|
|
829
893
|
if (!entry) return;
|
|
894
|
+
const poolKey = callerPoolKey || entry.sharedPoolKey || null;
|
|
830
895
|
entry.busy = false;
|
|
831
896
|
if (!keep || !_isOpen(entry) || !poolKey || entry.ephemeral) {
|
|
832
897
|
try {
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { performance } from 'node:perf_hooks';
|
|
2
|
+
import { reportStreamItemStart, responsesItemStart } from '../lib/send-callbacks.mjs';
|
|
2
3
|
|
|
3
4
|
// The per-event fold: text/reasoning/tool deltas and item lifecycle feed the
|
|
4
5
|
// response state, the text relay and the semantic watchdog; terminal frames
|
|
5
6
|
// route to the terminal-frame handlers.
|
|
6
|
-
export function createWsEventSwitch({
|
|
7
|
+
export function createWsEventSwitch({
|
|
8
|
+
response,
|
|
9
|
+
textRelay,
|
|
10
|
+
watchdogs,
|
|
11
|
+
midState,
|
|
12
|
+
progress,
|
|
13
|
+
terminal,
|
|
14
|
+
streamingStart,
|
|
15
|
+
onStreamItemStart = null,
|
|
16
|
+
}) {
|
|
7
17
|
let firstDeltaEmitted = false;
|
|
8
18
|
|
|
9
19
|
function onResponseCreated(event) {
|
|
@@ -73,6 +83,7 @@ export function createWsEventSwitch({ response, textRelay, watchdogs, midState,
|
|
|
73
83
|
break;
|
|
74
84
|
case 'response.output_item.added':
|
|
75
85
|
response.noteItemAdded(event.item);
|
|
86
|
+
reportStreamItemStart(onStreamItemStart, responsesItemStart(event.item));
|
|
76
87
|
// Item lifecycle is genuine progress: reset the semantic-idle timer so
|
|
77
88
|
// long server-side tool latency after item-added (before any arg
|
|
78
89
|
// delta) is not mistaken for a silent stall.
|
|
@@ -102,6 +113,8 @@ export function createWsEventSwitch({ response, textRelay, watchdogs, midState,
|
|
|
102
113
|
break;
|
|
103
114
|
case 'response.output_item.done': {
|
|
104
115
|
const kind = response.completeOutputItem(event.item);
|
|
116
|
+
// A stream that names the phase only on the finished message.
|
|
117
|
+
if (event.item?.type === 'message') reportStreamItemStart(onStreamItemStart, responsesItemStart(event.item));
|
|
105
118
|
// Item-done is genuine lifecycle progress — reset semantic idle so
|
|
106
119
|
// latency before the next item/args does not stall.
|
|
107
120
|
watchdogs.resetSemantic();
|
|
@@ -96,6 +96,7 @@ export async function _streamResponse({
|
|
|
96
96
|
onStreamDelta,
|
|
97
97
|
onToolCall,
|
|
98
98
|
onTextDelta,
|
|
99
|
+
onStreamItemStart = null,
|
|
99
100
|
state,
|
|
100
101
|
logSuppressedReasoningDeltas = true,
|
|
101
102
|
traceProvider = 'openai-oauth',
|
|
@@ -236,6 +237,7 @@ export async function _streamResponse({
|
|
|
236
237
|
progress,
|
|
237
238
|
terminal,
|
|
238
239
|
streamingStart,
|
|
240
|
+
onStreamItemStart,
|
|
239
241
|
});
|
|
240
242
|
handlers = createSocketHandlers({
|
|
241
243
|
socket,
|