mixdog 1.4.1 → 1.4.3
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/package.json +4 -3
- package/scripts/build-shipped-history.mjs +125 -33
- package/scripts/gate-local.mjs +220 -63
- package/scripts/graph-parity.mjs +8 -3
- package/scripts/lib/gate-scheduler.mjs +139 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/run-node-tests.mjs +71 -34
- package/scripts/lib/scoped-temp.mjs +1 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +9 -4
- package/scripts/lib/test-spawn-ledger.mjs +43 -3
- package/scripts/post-release-check.mjs +26 -16
- package/scripts/pptx-kit-index.mjs +5 -6
- package/scripts/provider-pingpong-live.mjs +1 -1
- package/scripts/prune-embedding-runtime.mjs +3 -1
- package/scripts/release-paths.mjs +7 -1
- package/scripts/suite-health.mjs +110 -28
- package/scripts/test.mjs +9 -14
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/explore/AGENT.md +22 -0
- package/src/agents/explore/agent.json +6 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +38 -2
- package/src/defaults/skills/browser-use/SKILL.md +4 -1
- package/src/defaults/skills/code-tidy/SKILL.md +71 -102
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
- package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
- package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
- package/src/defaults/skills/computer-use/SKILL.md +12 -2
- package/src/defaults/skills/setup/SKILL.md +2 -2
- package/src/defaults/skills/setup/references/actions.md +28 -9
- package/src/defaults/skills/setup/references/surfaces.md +5 -2
- package/src/defaults/skills/setup-guide/SKILL.md +11 -3
- package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
- package/src/defaults/skills/skill-creator/SKILL.md +85 -190
- package/src/defaults/skills/skill-creator/references/design.md +70 -162
- package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
- package/src/defaults/skills/test-suite/SKILL.md +194 -0
- package/src/defaults/skills/test-suite/references/case-management.md +51 -0
- package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
- package/src/defaults/skills/test-suite/references/reliability.md +49 -0
- package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
- package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
- package/src/defaults/skills/visualize/SKILL.md +6 -2
- package/src/lib/instruction-text.cjs +36 -0
- package/src/lib/rules-builder.cjs +40 -50
- package/src/orchestration/balanced.md +23 -0
- package/src/orchestration/focused.md +22 -0
- package/src/orchestration/none.md +5 -0
- package/src/orchestration/swarm.md +24 -0
- package/src/rules/agent-mode/AGENT_MODE.md +3 -1
- package/src/rules/agent-mode/MIXY.md +2 -2
- package/src/rules/lead/LEAD.md +3 -3
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +4 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
- package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
- package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
- package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
- package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
- package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
- package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
- package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
- package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
- package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/attachment-reference.mjs +1 -1
- package/src/runtime/attachments/pdf-extract.mjs +1 -1
- package/src/runtime/attachments/store.d.mts +1 -0
- package/src/runtime/attachments/store.mjs +2 -2
- package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
- package/src/runtime/channels/lib/scheduler.mjs +33 -0
- package/src/runtime/channels/lib/schedules-db.mjs +11 -4
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
- package/src/runtime/channels/lib/whisper-port.mjs +19 -10
- package/src/runtime/channels/lib/whisper-server.mjs +22 -13
- package/src/runtime/channels/lib/worker-main.mjs +9 -31
- package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
- package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
- package/src/runtime/connectors/gmail-app-password.mjs +4 -4
- package/src/runtime/connectors/google-mcp.mjs +1 -1
- package/src/runtime/effort-judge/judge-client.mjs +2 -2
- package/src/runtime/effort-judge/judge-input.mjs +4 -4
- package/src/runtime/explore/explorer.mjs +88 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/hardware.mjs +1 -1
- package/src/runtime/media/adapters/codex-image.mjs +3 -3
- package/src/runtime/media/adapters/gemini-video.mjs +1 -1
- package/src/runtime/media/media-usage.mjs +1 -1
- package/src/runtime/media/store.mjs +1 -1
- package/src/runtime/memory/index.mjs +15 -1
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
- package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
- package/src/runtime/memory/lib/memory-embed.mjs +83 -14
- package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
- package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
- package/src/runtime/memory/lib/memory.mjs +17 -0
- package/src/runtime/memory/lib/pg/process.mjs +1 -1
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
- package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
- package/src/runtime/office/capabilities.mjs +1 -1
- package/src/runtime/office/core/office-core.mjs +1 -1
- package/src/runtime/office/design/content-model.mjs +3 -3
- package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
- package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
- package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
- package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
- package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
- package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +8 -6
- package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
- package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.d.mts +8 -0
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +37 -10
- package/src/runtime/shared/background-wait.mjs +66 -0
- package/src/runtime/shared/child-guardian.mjs +17 -7
- package/src/runtime/shared/config.mjs +313 -16
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +14 -8
- package/src/runtime/shared/connector-catalog.mjs +70 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +21 -18
- package/src/runtime/shared/git-launch.d.mts +9 -0
- package/src/runtime/shared/git-launch.mjs +213 -0
- package/src/runtime/shared/git-runner-worker.mjs +2 -1
- package/src/runtime/shared/git-runner.mjs +7 -2
- package/src/runtime/shared/idle-gc.mjs +30 -7
- package/src/runtime/shared/llm/cost.mjs +6 -1
- package/src/runtime/shared/llm/http-agent.mjs +316 -29
- package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
- package/src/runtime/shared/llm/model-catalog.mjs +46 -6
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
- package/src/runtime/shared/llm/system-proxy.mjs +453 -0
- package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
- package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
- package/src/runtime/shared/maintenance-schedule.mjs +109 -0
- package/src/runtime/shared/process-runner.mjs +8 -4
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/routine-trigger.d.mts +13 -0
- package/src/runtime/shared/routine-trigger.mjs +34 -0
- package/src/runtime/shared/run-child.d.mts +2 -1
- package/src/runtime/shared/run-child.mjs +70 -18
- package/src/runtime/shared/session-scratch.mjs +14 -2
- package/src/runtime/shared/shipped-definitions.mjs +7 -1
- package/src/runtime/shared/staged-install-worker.mjs +5 -0
- package/src/runtime/shared/staged-update.mjs +47 -2
- package/src/runtime/shared/tool-card-model.golden.json +3 -12
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-surface.mjs +110 -36
- package/src/runtime/shared/tool-work-units.mjs +35 -6
- package/src/runtime/shared/turn-snapshot.mjs +26 -4
- package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
- package/src/runtime/shared/worker-requests.mjs +17 -3
- package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
- package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
- package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
- package/src/runtime/shared/worktrees/contract.mjs +16 -6
- package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
- package/src/runtime/shared/worktrees/disk.mjs +79 -2
- package/src/runtime/shared/worktrees/git.mjs +97 -7
- package/src/runtime/shared/worktrees/include.mjs +6 -4
- package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
- package/src/runtime/shared/worktrees/manager.mjs +962 -197
- package/src/runtime/shared/worktrees/settings.mjs +33 -7
- package/src/runtime/shared/worktrees/test-support.mjs +5 -1
- package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +9 -5
- package/src/runtime/tidy/resolve.mjs +19 -16
- package/src/runtime/tidy/runners/biome.mjs +3 -3
- package/src/runtime/tidy/tool.mjs +1 -1
- package/src/runtime/tidy/worktree.mjs +10 -6
- package/src/runtime/visualize-bridge/client.mjs +4 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +4 -23
- package/src/runtime/web-search/lib/web-tools.mjs +2 -2
- package/src/runtime/web-search/tool-defs.mjs +17 -26
- package/src/session-runtime/agent-profile-changes.mjs +55 -4
- package/src/session-runtime/agent-task-sessions.mjs +410 -353
- package/src/session-runtime/boot/apis.mjs +27 -4
- package/src/session-runtime/boot/begin.mjs +2 -0
- package/src/session-runtime/boot/config.mjs +10 -1
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/providers.mjs +70 -3
- package/src/session-runtime/boot/session.mjs +2 -0
- package/src/session-runtime/boot/tools.mjs +71 -25
- package/src/session-runtime/bot-status.mjs +103 -103
- package/src/session-runtime/channel-config-api.mjs +1 -0
- package/src/session-runtime/config-change-effects.mjs +179 -0
- package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
- package/src/session-runtime/config-lifecycle.mjs +160 -24
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/discovery.mjs +245 -47
- package/src/session-runtime/conversation-import/service.mjs +12 -5
- package/src/session-runtime/goal-facade-api.mjs +49 -3
- package/src/session-runtime/handoff-attachments.mjs +1 -1
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
- package/src/session-runtime/internal-tool-executor.mjs +12 -19
- package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
- package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
- package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
- package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
- package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
- package/src/session-runtime/mixy-heartbeat.mjs +1 -1
- package/src/session-runtime/model-route/set-route.mjs +40 -7
- package/src/session-runtime/native-web-search/routes.mjs +3 -3
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-auth/refresh.mjs +6 -3
- package/src/session-runtime/provider-auth/setup.mjs +1 -1
- package/src/session-runtime/provider-readiness.mjs +53 -4
- package/src/session-runtime/resource-api.mjs +1 -1
- package/src/session-runtime/resource-extension-sync.mjs +4 -8
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
- package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-plugins-api.mjs +4 -0
- package/src/session-runtime/routine-executor.mjs +152 -0
- package/src/session-runtime/routine-home-turn.mjs +46 -5
- package/src/session-runtime/runtime-facade.mjs +5 -0
- package/src/session-runtime/runtime-feature-gates.mjs +2 -11
- package/src/session-runtime/schedule-session-run.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
- package/src/session-runtime/services/agent-tool.mjs +51 -1
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-admin.mjs +18 -0
- package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
- package/src/session-runtime/services/daemon-candidate.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +14 -6
- package/src/session-runtime/services/provider-admin.mjs +281 -10
- package/src/session-runtime/services/seeds.mjs +7 -0
- package/src/session-runtime/services/usage-stats-model.mjs +32 -11
- package/src/session-runtime/session-create/materialize.mjs +4 -2
- package/src/session-runtime/session-create/session-options.mjs +2 -0
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
- package/src/session-runtime/settings-system-api.mjs +1 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
- package/src/session-runtime/setup-tool/executor.mjs +14 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
- package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
- package/src/session-runtime/tool-policy-refresh.mjs +182 -5
- package/src/session-runtime/tool-surface.mjs +38 -1
- package/src/session-runtime/turn/agent-ops.mjs +33 -2
- package/src/session-runtime/turn/session-ops.mjs +2 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
- package/src/session-runtime/turn/turn-run.mjs +1 -1
- package/src/session-runtime/webhook-session-run.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
- package/src/session-runtime/workflow-agents-api.mjs +2 -0
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/project-branches.mjs +1 -1
- package/src/session-runtime/workspace/session-view.mjs +149 -0
- package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
- package/src/session-runtime/workspace/transition-runner.mjs +188 -0
- package/src/session-runtime/workspace/transitions.mjs +128 -1070
- package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
- package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
- package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
- package/src/standalone/daemon-agent-control.mjs +25 -8
- package/src/standalone/daemon-desktop-runtime.mjs +8 -2
- package/src/standalone/daemon-lag-profiler.mjs +7 -7
- package/src/standalone/daemon-session-control.mjs +151 -136
- package/src/standalone/daemon.mjs +61 -2
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +21 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +15 -0
- package/src/standalone/session-service/agent-route-follow.mjs +23 -20
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
- package/src/standalone/session-service/agent-tree.mjs +45 -9
- package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
- package/src/standalone/session-service/quota-resume.mjs +9 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
- package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
- package/src/standalone/session-service/session-calls.mjs +2 -1
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/tui/App.jsx +162 -164
- package/src/tui/app/app-view/floating-panel.jsx +3 -0
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +22 -11
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/doctor.mjs +2 -2
- package/src/tui/app/panel-signature.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
- package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
- package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
- package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
- package/src/tui/app/provider-setup-picker.mjs +20 -13
- package/src/tui/app/settings-picker.mjs +53 -8
- package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
- package/src/tui/app/slash-commands.mjs +2 -1
- package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
- package/src/tui/app/slash-dispatch.mjs +1 -1
- package/src/tui/app/use-btw-panel.mjs +29 -0
- package/src/tui/app/use-context-panel-refresh.mjs +31 -0
- package/src/tui/app/use-model-catalog-cache.mjs +13 -10
- package/src/tui/app/use-mouse-input.mjs +11 -0
- package/src/tui/app/use-onboarding-start.mjs +8 -3
- package/src/tui/app/use-panel-transition.mjs +10 -1
- package/src/tui/app/use-pasted-buffers.mjs +28 -20
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
- package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
- package/src/tui/app/use-prompt-queue-history.mjs +5 -4
- package/src/tui/app/use-selection-focus.mjs +11 -2
- package/src/tui/app/use-selection-geometry.mjs +18 -9
- package/src/tui/app/use-selection-paint.mjs +4 -4
- package/src/tui/app/use-selection-stitch.mjs +3 -3
- package/src/tui/app/use-slash-palette.mjs +62 -0
- package/src/tui/app/use-terminal-chrome.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +48 -33
- package/src/tui/app/use-transcript-follow.mjs +12 -4
- package/src/tui/app/use-transcript-scroll.mjs +46 -17
- package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
- package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
- package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
- package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
- package/src/tui/app/use-transcript-window.mjs +21 -11
- package/src/tui/app/use-tui-ready.mjs +18 -0
- package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
- package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
- package/src/tui/components/Picker.jsx +27 -3
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
- package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
- package/src/tui/components/question-panel-model.mjs +4 -4
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/components/tool-execution/standard-card.jsx +3 -4
- package/src/tui/components/user-message-skills.mjs +1 -1
- package/src/tui/dist/index.mjs +2205 -1371
- package/src/tui/markdown/render-ansi.mjs +1 -1
- package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
- package/src/tui/session/agent-job-feed.mjs +2 -0
- package/src/tui/session/context-state.mjs +3 -0
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/quota-resume.mjs +1 -1
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +8 -0
- package/src/tui/session/session-api/intake/abort.mjs +2 -1
- package/src/tui/session/session-api/intake.mjs +2 -0
- package/src/tui/session/session-api/integrations.mjs +2 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-api/worktree.mjs +13 -1
- package/src/tui/session/session-flow/drain.mjs +11 -14
- package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
- package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
- package/src/tui/session/transcript-spill.mjs +92 -4
- package/src/tui/session/transcript-store.mjs +2 -0
- package/src/tui/session/turn-quiet.mjs +1 -1
- package/src/tui/session/turn.mjs +3 -0
- package/src/tui/session/worktree-setup-notice.mjs +1 -1
- package/src/tui/spinner-meta.mjs +3 -3
- package/src/tui/spinner-verbs.mjs +2 -2
- package/src/defaults/skills/goal-management/SKILL.md +0 -169
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
- package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
- package/src/session-runtime/goal-tasks.mjs +0 -1
|
@@ -1,20 +1,36 @@
|
|
|
1
|
-
// The one MCP server of a
|
|
2
|
-
// connectorAccountsOf):
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
1
|
+
// The one MCP server of a catalog connector (connector-catalog.mjs
|
|
2
|
+
// connectorAccountsOf): every connected account of Gmail, Notion, Postgres…
|
|
3
|
+
// behind one tool set, answered in-process. Underneath, each account is its
|
|
4
|
+
// own ordinary MCP connection with its own credentials (client-transport.mjs
|
|
5
|
+
// connectorAccountClient), and its tools are the ones its backend lists. This
|
|
6
|
+
// server lists their union (a tool whose schema differs between accounts is
|
|
7
|
+
// left out), each with one more optional argument, `account` (an account's
|
|
8
|
+
// address or name), which never reaches the account.
|
|
9
|
+
//
|
|
10
|
+
// The account a call uses: the one it names; else the one last used in its
|
|
11
|
+
// conversation, else the connector's last-used account (connectorAccountInUse),
|
|
12
|
+
// else the topmost connected account. A named or remembered account that is
|
|
13
|
+
// switched off, removed or needs a sign-in fails the call with the usable
|
|
14
|
+
// accounts listed; no other account ever stands in for it, a new account
|
|
15
|
+
// given a removed one's name included (a remembered account is bound to its
|
|
16
|
+
// identity, not its name). A conversation's
|
|
17
|
+
// call (`_meta[CONVERSATION_META]`) makes its account the last used, for the
|
|
18
|
+
// conversation and the connector. Every result of a call made on an account,
|
|
19
|
+
// errors included, says which account answered. A name binds a call to one
|
|
20
|
+
// account; an address or label two accounts share binds none.
|
|
21
|
+
// An account that fails stays listed with why (connectorAccountHealth); the
|
|
22
|
+
// server only fails to start when no account can be used.
|
|
23
|
+
import { randomUUID } from 'node:crypto';
|
|
24
|
+
import { join } from 'node:path';
|
|
25
|
+
import { readJsonStateSync, updateJsonAtomicSync } from '../shared/atomic-file.mjs';
|
|
26
|
+
import { readSection, updateSection } from '../shared/config.mjs';
|
|
12
27
|
import { accountsOfInstructions, connectorAccountsInstructions } from '../shared/connector-accounts.mjs';
|
|
13
|
-
import { connectorById } from '../shared/connector-catalog.mjs';
|
|
14
|
-
import {
|
|
15
|
-
import { googleMcpTools } from './google-mcp.mjs';
|
|
28
|
+
import { connectorAccountsOf, connectorById, connectorOfServer } from '../shared/connector-catalog.mjs';
|
|
29
|
+
import { resolvePluginData } from '../shared/plugin-paths.mjs';
|
|
16
30
|
|
|
17
31
|
const PROTOCOL_VERSION = '2025-06-18';
|
|
32
|
+
/** The `_meta` key of a tools/call that names the conversation it is made in. */
|
|
33
|
+
export const CONVERSATION_META = 'mixdog/conversation';
|
|
18
34
|
|
|
19
35
|
const json = (status, body) =>
|
|
20
36
|
new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json' } });
|
|
@@ -36,66 +52,289 @@ export function forgetConnectorAccountHealth(name) {
|
|
|
36
52
|
health.delete(name);
|
|
37
53
|
}
|
|
38
54
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
// ── The last-used account ───────────────────────────────────────────────────
|
|
56
|
+
// Per connector and per conversation, in the data dir (every runtime and every
|
|
57
|
+
// restart reads the same ones).
|
|
58
|
+
const ACCOUNTS_IN_USE_FILE = 'connector-accounts-in-use.json';
|
|
59
|
+
const inUseFile = () => join(resolvePluginData(), ACCOUNTS_IN_USE_FILE);
|
|
60
|
+
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
61
|
+
const validInUse = (value) => {
|
|
62
|
+
if (!isRecord(value)) throw new Error('the accounts in use must be an object');
|
|
63
|
+
return value;
|
|
64
|
+
};
|
|
44
65
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
// A remembered account is `{ name, id }`: the name it was called by and its
|
|
67
|
+
// identity (connector-catalog.mjs connectorAccountId: the random id stored
|
|
68
|
+
// with it). A name can be given to a new account once the old one is
|
|
69
|
+
// removed; the identity cannot, so it binds the choice to the account.
|
|
70
|
+
const readInUse = () => readJsonStateSync(inUseFile(), { validate: validInUse, fallback: {} });
|
|
71
|
+
|
|
72
|
+
// Set in the accounts-in-use file once its name-only records (from before
|
|
73
|
+
// identities) were bound to the accounts then under those names.
|
|
74
|
+
const IDS_MIGRATED = '#ids';
|
|
75
|
+
|
|
76
|
+
const hasId = (account) => typeof account?.id === 'string' && account.id !== '';
|
|
77
|
+
const missingIds = (servers) =>
|
|
78
|
+
Object.values(isRecord(servers) ? servers : {}).some((cfg) => connectorAccountsOf(cfg).some((one) => !hasId(one)));
|
|
79
|
+
|
|
80
|
+
/** Test seam: runs once the config lock that gave the ids is released, before
|
|
81
|
+
* the binding (where another process's write may land). */
|
|
82
|
+
export const accountIdsDeps = { afterIdsGiven: () => {} };
|
|
83
|
+
|
|
84
|
+
/** `servers` with a random id given to every connector account stored
|
|
85
|
+
* without one; null when every account has one. */
|
|
86
|
+
function withAccountIds(servers) {
|
|
87
|
+
if (!missingIds(servers)) return null;
|
|
88
|
+
return Object.fromEntries(
|
|
89
|
+
Object.entries(servers).map(([name, cfg]) => {
|
|
90
|
+
if (!connectorAccountsOf(cfg).some((one) => !hasId(one))) return [name, cfg];
|
|
91
|
+
const accounts = cfg.accounts.map((account) =>
|
|
92
|
+
isRecord(account) && !hasId(account) ? { ...account, id: randomUUID() } : account
|
|
93
|
+
);
|
|
94
|
+
return [name, { ...cfg, accounts }];
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Every stored connector account gets an identity, once, at every start and
|
|
101
|
+
* after a config change (an account written by hand has none). All under the
|
|
102
|
+
* accounts-in-use file's lock, so concurrent runs (processes, runtimes) and
|
|
103
|
+
* choices serialize: the config is changed only where an id is missing (an id
|
|
104
|
+
* once given is never replaced), and the first run also binds each name-only
|
|
105
|
+
* record (from before identities) to the account then under that name, which
|
|
106
|
+
* is where such a record routed until now, and marks that done. A name-only
|
|
107
|
+
* record found afterwards stays unbound (it fails closed). Records already
|
|
108
|
+
* holding an identity are never touched. True when it changed the config.
|
|
109
|
+
*
|
|
110
|
+
* The binding uses the accounts exactly as the ids were given or confirmed:
|
|
111
|
+
* the config is re-read nowhere after that, so an account replaced under the
|
|
112
|
+
* same name meanwhile (by another process) is never the one bound; it fails
|
|
113
|
+
* the identity check instead.
|
|
114
|
+
*/
|
|
115
|
+
export function ensureConnectorAccountIds() {
|
|
116
|
+
let changed = false;
|
|
117
|
+
updateJsonAtomicSync(inUseFile(), (current) => {
|
|
118
|
+
const stored = isRecord(current) ? current : {};
|
|
119
|
+
// The stored servers whose ids the binding below uses.
|
|
120
|
+
let snapshot = readSection('agent')?.mcpServers;
|
|
121
|
+
if (missingIds(snapshot)) {
|
|
122
|
+
updateSection('agent', (agent) => {
|
|
123
|
+
const servers = withAccountIds(agent.mcpServers);
|
|
124
|
+
snapshot = servers ?? agent.mcpServers;
|
|
125
|
+
if (!servers) return agent;
|
|
126
|
+
changed = true;
|
|
127
|
+
return { ...agent, mcpServers: servers };
|
|
128
|
+
});
|
|
129
|
+
accountIdsDeps.afterIdsGiven();
|
|
130
|
+
}
|
|
131
|
+
if (stored[IDS_MIGRATED]) return undefined;
|
|
132
|
+
const servers = Object.values(isRecord(snapshot) ? snapshot : {});
|
|
133
|
+
const next = { ...stored, [IDS_MIGRATED]: true };
|
|
134
|
+
for (const [connector, name] of Object.entries(stored)) {
|
|
135
|
+
if (typeof name !== 'string' || !name) continue;
|
|
136
|
+
const cfg = servers.find((one) => connectorOfServer(one) === connector && connectorAccountsOf(one).length);
|
|
137
|
+
const account = cfg && connectorAccountsOf(cfg).find((one) => one.name === name);
|
|
138
|
+
if (hasId(account)) next[connector] = { name, id: account.id };
|
|
139
|
+
}
|
|
140
|
+
return next;
|
|
141
|
+
});
|
|
142
|
+
return changed;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** The account catalog connector `connector` used last, null when none was
|
|
146
|
+
* recorded. A name-only record (from before identities, unbound) has an
|
|
147
|
+
* empty `id`. */
|
|
148
|
+
export function connectorAccountInUseRecord(connector) {
|
|
149
|
+
const value = readInUse()[connector];
|
|
150
|
+
if (typeof value === 'string') return value ? { name: value, id: '' } : null;
|
|
151
|
+
if (!isRecord(value) || typeof value.name !== 'string' || !value.name) return null;
|
|
152
|
+
return { name: value.name, id: typeof value.id === 'string' ? value.id : '' };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** The name of the account catalog connector `connector` used last, '' when
|
|
156
|
+
* none was recorded. */
|
|
157
|
+
export function connectorAccountInUse(connector) {
|
|
158
|
+
return connectorAccountInUseRecord(connector)?.name || '';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function rememberAccountInUse(connector, account) {
|
|
162
|
+
const current = connectorAccountInUseRecord(connector);
|
|
163
|
+
if (current?.name === account.name && current.id === account.id) return;
|
|
164
|
+
updateJsonAtomicSync(inUseFile(), (stored) => ({
|
|
165
|
+
...(isRecord(stored) ? stored : {}),
|
|
166
|
+
[connector]: { name: account.name, id: account.id },
|
|
61
167
|
}));
|
|
62
168
|
}
|
|
63
169
|
|
|
64
|
-
|
|
170
|
+
// Per conversation, in the data dir too, so a conversation resumed after a
|
|
171
|
+
// restart keeps its own account: conversation (its session id) → { accounts:
|
|
172
|
+
// (connector → { name, id }) }. A binding lives as long as its session: it is
|
|
173
|
+
// dropped only when the session is deleted (forgetConversationConnectorAccounts,
|
|
174
|
+
// a session purge hook), never to make room, so no live conversation falls
|
|
175
|
+
// back to another conversation's choice.
|
|
176
|
+
const CONVERSATION_ACCOUNTS_FILE = 'connector-accounts-by-conversation.json';
|
|
177
|
+
const conversationsFile = () => join(resolvePluginData(), CONVERSATION_ACCOUNTS_FILE);
|
|
65
178
|
|
|
66
|
-
|
|
179
|
+
/** Drop the connector accounts conversation `conversation` used (its session
|
|
180
|
+
* was deleted). */
|
|
181
|
+
export function forgetConversationConnectorAccounts(conversation) {
|
|
182
|
+
const id = text(conversation);
|
|
183
|
+
if (!id || !Object.hasOwn(readJsonStateSync(conversationsFile(), { validate: validInUse, fallback: {} }), id)) return;
|
|
184
|
+
updateJsonAtomicSync(conversationsFile(), (stored) => {
|
|
185
|
+
const { [id]: _gone, ...rest } = isRecord(stored) ? stored : {};
|
|
186
|
+
return rest;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
67
189
|
|
|
68
|
-
/** The account
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
190
|
+
/** The account conversation `conversation` used last on `connector`, or null. */
|
|
191
|
+
function conversationAccount(conversation, connector) {
|
|
192
|
+
const own = readJsonStateSync(conversationsFile(), { validate: validInUse, fallback: {} })[conversation];
|
|
193
|
+
const value = isRecord(own?.accounts) ? own.accounts[connector] : null;
|
|
194
|
+
if (!isRecord(value) || typeof value.name !== 'string' || !value.name) return null;
|
|
195
|
+
return { name: value.name, id: typeof value.id === 'string' ? value.id : '' };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function rememberConversationAccount(conversation, connector, account) {
|
|
199
|
+
const current = conversationAccount(conversation, connector);
|
|
200
|
+
if (current?.name === account.name && current.id === account.id) return;
|
|
201
|
+
updateJsonAtomicSync(conversationsFile(), (stored) => {
|
|
202
|
+
const all = isRecord(stored) ? stored : {};
|
|
203
|
+
const accounts = isRecord(all[conversation]?.accounts) ? all[conversation].accounts : {};
|
|
204
|
+
return {
|
|
205
|
+
...all,
|
|
206
|
+
[conversation]: { accounts: { ...accounts, [connector]: { name: account.name, id: account.id } } },
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const ACCOUNT_PROPERTY = Object.freeze({
|
|
212
|
+
type: 'string',
|
|
213
|
+
description: 'The account to use (its email address or account name). Left out: the account used last.',
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
/** `value` as JSON with every object's keys sorted, so equal schemas compare
|
|
217
|
+
* equal whatever order their keys were written in. */
|
|
218
|
+
const canonical = (value) => {
|
|
219
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;
|
|
220
|
+
if (isRecord(value)) {
|
|
221
|
+
const keys = Object.keys(value)
|
|
222
|
+
.filter((key) => value[key] !== undefined)
|
|
223
|
+
.sort();
|
|
224
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(',')}}`;
|
|
79
225
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
226
|
+
return JSON.stringify(value) ?? 'null';
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
/** The tools every account lists, once each, with `account` added; a tool
|
|
230
|
+
* two accounts list with different schemas is left out. */
|
|
231
|
+
function unionTools(states) {
|
|
232
|
+
const first = new Map();
|
|
233
|
+
const differs = new Set();
|
|
234
|
+
for (const { tools = [] } of states) {
|
|
235
|
+
for (const tool of tools) {
|
|
236
|
+
const seen = first.get(tool.name);
|
|
237
|
+
if (!seen) first.set(tool.name, tool);
|
|
238
|
+
else if (canonical(seen.inputSchema) !== canonical(tool.inputSchema)) differs.add(tool.name);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return [...first.values()]
|
|
242
|
+
.filter((tool) => !differs.has(tool.name))
|
|
243
|
+
.map((tool) => ({
|
|
244
|
+
...tool,
|
|
245
|
+
inputSchema: {
|
|
246
|
+
type: 'object',
|
|
247
|
+
...tool.inputSchema,
|
|
248
|
+
properties: { ...(tool.inputSchema?.properties || {}), account: ACCOUNT_PROPERTY },
|
|
249
|
+
},
|
|
250
|
+
}));
|
|
84
251
|
}
|
|
85
252
|
|
|
86
253
|
const noteOf = (state) => (state.authRequired ? 'needs sign-in' : 'unavailable');
|
|
254
|
+
const usable = (account) => health.get(account.name)?.authRequired !== true;
|
|
255
|
+
|
|
256
|
+
/** `result` saying which account answered it (`label`). */
|
|
257
|
+
const withAccountNote = (result, service, label) => ({
|
|
258
|
+
...result,
|
|
259
|
+
content: [
|
|
260
|
+
...(Array.isArray(result?.content) ? result.content : []),
|
|
261
|
+
{ type: 'text', text: `(${service} account: ${label})` },
|
|
262
|
+
],
|
|
263
|
+
});
|
|
87
264
|
|
|
88
265
|
/**
|
|
89
266
|
* A `fetch` answering the accounts server of `connector` in-process. Each of
|
|
90
|
-
* `accounts` is `{ name, email,
|
|
91
|
-
* `
|
|
92
|
-
*
|
|
93
|
-
*
|
|
267
|
+
* `accounts` is `{ name, id, email, connect(signal), callTool(params, { signal, onprogress }) }`
|
|
268
|
+
* (`id`: its identity, connector-catalog.mjs connectorAccountId):
|
|
269
|
+
* `connect` resolves `{ instructions, tools }` of that account's own MCP
|
|
270
|
+
* connection, `callTool` sends it one tools/call (reporting its progress to
|
|
271
|
+
* `onprogress`, when given) and resolves the result; both
|
|
272
|
+
* throw when the account cannot be reached (an `authRequired` error when it
|
|
273
|
+
* needs a sign-in). The fetch carries `connectorAccounts`: `{ connector,
|
|
274
|
+
* choose({ tool, wanted, conversation }) }`, `{ name, label }` of the account
|
|
275
|
+
* such a call would use (it throws the refusal otherwise), for binding a call
|
|
276
|
+
* to its account (by its unique name) before it is approved.
|
|
94
277
|
*/
|
|
95
278
|
export function withConnectorAccountsMcp({ connector, accounts }) {
|
|
96
279
|
const service = connectorById(connector)?.name || connector;
|
|
97
|
-
|
|
98
|
-
const
|
|
280
|
+
// account name → the names of the tools it lists (set once it answered).
|
|
281
|
+
const toolsOf = new Map();
|
|
282
|
+
let listed = [];
|
|
283
|
+
const same = (a, b) => Boolean(a) && a.toLowerCase() === b.toLowerCase();
|
|
284
|
+
/** What an account is called to the model: its address, with its name when
|
|
285
|
+
* another account shares that address. */
|
|
286
|
+
const labelOf = (account) => {
|
|
287
|
+
if (!account.email) return account.name;
|
|
288
|
+
const shared = accounts.some((other) => other !== account && same(other.email, account.email));
|
|
289
|
+
return shared ? `${account.email} (${account.name})` : account.email;
|
|
290
|
+
};
|
|
291
|
+
/** The account a call uses (see the header); throws the refusal. */
|
|
292
|
+
const choose = ({ tool, wanted, conversation }) => {
|
|
293
|
+
const refuse = (why) => {
|
|
294
|
+
const list = accounts.filter(usable).map(labelOf).join(', ') || 'none';
|
|
295
|
+
return new Error(`${why} Usable ${service} accounts: ${list}. Pass one as \`account\`.`);
|
|
296
|
+
};
|
|
297
|
+
const named = text(wanted);
|
|
298
|
+
let account;
|
|
299
|
+
if (named) {
|
|
300
|
+
// Its unique name, else the one account its address or label is.
|
|
301
|
+
let matches = accounts.filter((one) => same(one.name, named));
|
|
302
|
+
if (!matches.length) matches = accounts.filter((one) => same(one.email, named) || same(labelOf(one), named));
|
|
303
|
+
if (!matches.length) throw refuse(`No connected ${service} account is "${named}".`);
|
|
304
|
+
if (matches.length > 1) {
|
|
305
|
+
const names = matches.map((one) => one.name).join(', ');
|
|
306
|
+
throw refuse(`"${named}" is more than one ${service} account (${names}); name one.`);
|
|
307
|
+
}
|
|
308
|
+
[account] = matches;
|
|
309
|
+
} else {
|
|
310
|
+
const remembered =
|
|
311
|
+
(conversation && conversationAccount(conversation, connector)) || connectorAccountInUseRecord(connector);
|
|
312
|
+
if (remembered) {
|
|
313
|
+
account = accounts.find((one) => one.name === remembered.name);
|
|
314
|
+
// The name must still be the account it named: one removed and its
|
|
315
|
+
// name given to a new account, or a record without an identity (one
|
|
316
|
+
// ensureConnectorAccountIds did not bind, or an account picked before
|
|
317
|
+
// it had an id), fails closed until an account is picked again.
|
|
318
|
+
if (account && !remembered.id) {
|
|
319
|
+
throw refuse(
|
|
320
|
+
`The ${service} account used last (${remembered.name}) cannot be confirmed as the same account.`
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
if (account && account.id !== remembered.id) {
|
|
324
|
+
throw refuse(`The ${service} account used last (${remembered.name} (removed)) is not connected now.`);
|
|
325
|
+
}
|
|
326
|
+
if (!account) throw refuse(`The ${service} account used last (${remembered.name}) is not connected now.`);
|
|
327
|
+
} else {
|
|
328
|
+
account = accounts[0];
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (!usable(account)) throw refuse(`${labelOf(account)} needs a sign-in in Connectors.`);
|
|
332
|
+
const has = toolsOf.get(account.name);
|
|
333
|
+
if (has && !has.has(tool) && listed.some((one) => one.name === tool)) {
|
|
334
|
+
throw refuse(`${labelOf(account)} has no ${tool} tool.`);
|
|
335
|
+
}
|
|
336
|
+
return account;
|
|
337
|
+
};
|
|
99
338
|
const record = (account, state) => {
|
|
100
339
|
if (state.email) account.email = state.email;
|
|
101
340
|
health.set(account.name, {
|
|
@@ -109,13 +348,13 @@ export function withConnectorAccountsMcp({ connector, accounts }) {
|
|
|
109
348
|
record(account, state);
|
|
110
349
|
return state;
|
|
111
350
|
};
|
|
112
|
-
// Each account's own
|
|
351
|
+
// Each account's own connection: whether it can be used, its address and tools.
|
|
113
352
|
const probe = async (account, signal) => {
|
|
114
353
|
try {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
const [email = ''] = accountsOfInstructions(
|
|
118
|
-
const state = { email: account.email || email };
|
|
354
|
+
const { instructions, tools } = await account.connect(signal);
|
|
355
|
+
toolsOf.set(account.name, new Set(tools.map((tool) => tool.name)));
|
|
356
|
+
const [email = ''] = accountsOfInstructions(instructions);
|
|
357
|
+
const state = { email: account.email || email, instructions, tools };
|
|
119
358
|
record(account, state);
|
|
120
359
|
return state;
|
|
121
360
|
} catch (error) {
|
|
@@ -125,7 +364,9 @@ export function withConnectorAccountsMcp({ connector, accounts }) {
|
|
|
125
364
|
// The calls in flight by JSON-RPC id, so a `notifications/cancelled` for one
|
|
126
365
|
// aborts its downstream request.
|
|
127
366
|
const inflight = new Map();
|
|
128
|
-
|
|
367
|
+
/** One JSON-RPC request's reply; `notify` sends a notification ahead of it
|
|
368
|
+
* (a tools/call's progress). */
|
|
369
|
+
async function rpc(message, transportSignal, notify = null) {
|
|
129
370
|
const { id, method, params } = message || {};
|
|
130
371
|
const reply = (result) => ({ jsonrpc: '2.0', id, result });
|
|
131
372
|
if (method === 'initialize') {
|
|
@@ -138,55 +379,70 @@ export function withConnectorAccountsMcp({ connector, accounts }) {
|
|
|
138
379
|
error: { code: -32001, message: first?.error || `No ${service} account is connected` },
|
|
139
380
|
};
|
|
140
381
|
}
|
|
382
|
+
listed = unionTools(states);
|
|
383
|
+
// What the accounts' own servers tell the model (an in-process Google
|
|
384
|
+
// account's only names its address, which the account list says).
|
|
385
|
+
const own = [
|
|
386
|
+
...new Set(
|
|
387
|
+
states.map((state) => text(state.instructions)).filter((one) => one && !accountsOfInstructions(one).length)
|
|
388
|
+
),
|
|
389
|
+
];
|
|
390
|
+
const accountsLine = connectorAccountsInstructions(
|
|
391
|
+
accounts.map((account, index) => ({
|
|
392
|
+
email: labelOf(account),
|
|
393
|
+
...(states[index].error ? { note: noteOf(states[index]) } : {}),
|
|
394
|
+
}))
|
|
395
|
+
);
|
|
141
396
|
return reply({
|
|
142
397
|
protocolVersion: text(params?.protocolVersion) || PROTOCOL_VERSION,
|
|
143
398
|
capabilities: { tools: { listChanged: false } },
|
|
144
399
|
serverInfo: { name: `mixdog-${connector}`, version: '1.0.0' },
|
|
145
|
-
instructions:
|
|
146
|
-
accounts.map((account, index) => ({
|
|
147
|
-
email: labelOf(account),
|
|
148
|
-
...(states[index].error ? { note: noteOf(states[index]) } : {}),
|
|
149
|
-
}))
|
|
150
|
-
),
|
|
400
|
+
instructions: [accountsLine, ...own].filter(Boolean).join('\n\n') || undefined,
|
|
151
401
|
});
|
|
152
402
|
}
|
|
153
403
|
if (method === 'ping') return reply({});
|
|
154
404
|
if (method === 'tools/list') return reply({ tools: listed });
|
|
155
405
|
if (method === 'tools/call') {
|
|
156
406
|
const name = params?.name;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
const { account: chosen, ...args } = params?.arguments || {};
|
|
407
|
+
const { account: wanted, ...args } = params?.arguments || {};
|
|
408
|
+
const conversation = text(params?._meta?.[CONVERSATION_META]);
|
|
161
409
|
let account;
|
|
162
410
|
try {
|
|
163
|
-
account =
|
|
411
|
+
account = choose({ tool: name, wanted, conversation });
|
|
412
|
+
if (conversation) {
|
|
413
|
+
rememberConversationAccount(conversation, connector, account);
|
|
414
|
+
rememberAccountInUse(connector, account);
|
|
415
|
+
}
|
|
164
416
|
} catch (error) {
|
|
165
|
-
return reply(errorResult(error
|
|
417
|
+
return reply(errorResult(error?.message || String(error)));
|
|
166
418
|
}
|
|
167
419
|
const cancel = new AbortController();
|
|
168
420
|
const signal = transportSignal ? AbortSignal.any([transportSignal, cancel.signal]) : cancel.signal;
|
|
169
421
|
inflight.set(id, cancel);
|
|
422
|
+
// The account's progress reaches the caller under the caller's own token,
|
|
423
|
+
// so it resets the call's deadline as a direct server's progress does.
|
|
424
|
+
const progressToken = params?._meta?.progressToken;
|
|
425
|
+
const onprogress =
|
|
426
|
+
notify && progressToken !== undefined
|
|
427
|
+
? (progress) =>
|
|
428
|
+
notify({ jsonrpc: '2.0', method: 'notifications/progress', params: { ...progress, progressToken } })
|
|
429
|
+
: undefined;
|
|
170
430
|
try {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
{ signal }
|
|
174
|
-
);
|
|
175
|
-
if (answer?.error) return reply(errorResult(`${labelOf(account)}: ${answer.error.message}`));
|
|
431
|
+
// An unlisted tool (one only the approval gate calls) is the account's to answer.
|
|
432
|
+
const result = await account.callTool({ name, arguments: args }, { signal, onprogress });
|
|
176
433
|
if (health.get(account.name)?.error) record(account, {});
|
|
177
|
-
return reply(
|
|
434
|
+
return reply(withAccountNote(result, service, labelOf(account)));
|
|
178
435
|
} catch (error) {
|
|
179
436
|
// A cancelled call says nothing about the account's health.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return reply(errorResult(`${labelOf(account)}: ${state.error}`));
|
|
437
|
+
const why = signal.aborted ? 'cancelled' : failure(account, error).error;
|
|
438
|
+
return reply(withAccountNote(errorResult(why), service, labelOf(account)));
|
|
183
439
|
} finally {
|
|
184
440
|
inflight.delete(id);
|
|
185
441
|
}
|
|
186
442
|
}
|
|
187
443
|
return { jsonrpc: '2.0', id, error: { code: -32601, message: `Method not found: ${method}` } };
|
|
188
444
|
}
|
|
189
|
-
|
|
445
|
+
const fetchImpl = async (input, init) => {
|
|
190
446
|
const request = input instanceof Request ? input : null;
|
|
191
447
|
if (String(request?.method || init?.method || 'GET').toUpperCase() !== 'POST') {
|
|
192
448
|
return new Response(null, { status: 405, headers: { allow: 'POST' } });
|
|
@@ -203,28 +459,41 @@ export function withConnectorAccountsMcp({ connector, accounts }) {
|
|
|
203
459
|
for (const one of batch) {
|
|
204
460
|
if (one?.method === 'notifications/cancelled') inflight.get(one.params?.requestId)?.abort();
|
|
205
461
|
}
|
|
462
|
+
// A call asking for progress is answered as an event stream: its progress
|
|
463
|
+
// notifications, then its reply.
|
|
464
|
+
if (!Array.isArray(message) && message?.id !== undefined && message.params?._meta?.progressToken !== undefined) {
|
|
465
|
+
const encoder = new TextEncoder();
|
|
466
|
+
let open = true;
|
|
467
|
+
const stream = new ReadableStream({
|
|
468
|
+
start(controller) {
|
|
469
|
+
const send = (payload) => {
|
|
470
|
+
if (open) controller.enqueue(encoder.encode(`event: message\ndata: ${JSON.stringify(payload)}\n\n`));
|
|
471
|
+
};
|
|
472
|
+
void rpc(message, signal, send).then((answer) => {
|
|
473
|
+
send(answer);
|
|
474
|
+
if (open) controller.close();
|
|
475
|
+
open = false;
|
|
476
|
+
});
|
|
477
|
+
},
|
|
478
|
+
// The caller stopped reading (its call was aborted).
|
|
479
|
+
cancel() {
|
|
480
|
+
open = false;
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
return new Response(stream, { status: 200, headers: { 'content-type': 'text/event-stream' } });
|
|
484
|
+
}
|
|
206
485
|
const replies = (await Promise.all(batch.map((one) => (one?.id === undefined ? null : rpc(one, signal))))).filter(
|
|
207
486
|
Boolean
|
|
208
487
|
);
|
|
209
488
|
if (!replies.length) return new Response(null, { status: 202 });
|
|
210
489
|
return json(200, Array.isArray(message) ? replies : replies[0]);
|
|
211
490
|
};
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const response = await fetchImpl(url, {
|
|
219
|
-
method: 'POST',
|
|
220
|
-
headers: { 'content-type': 'application/json', accept: 'application/json, text/event-stream', ...headers },
|
|
221
|
-
body: JSON.stringify(message),
|
|
222
|
-
signal,
|
|
223
|
-
});
|
|
224
|
-
if (!response.ok) {
|
|
225
|
-
await response.body?.cancel();
|
|
226
|
-
throw new Error(`The account's server answered ${response.status}`);
|
|
227
|
-
}
|
|
228
|
-
return response.json();
|
|
491
|
+
fetchImpl.connectorAccounts = {
|
|
492
|
+
connector,
|
|
493
|
+
choose: (call) => {
|
|
494
|
+
const account = choose(call);
|
|
495
|
+
return { name: account.name, label: labelOf(account) };
|
|
496
|
+
},
|
|
229
497
|
};
|
|
498
|
+
return fetchImpl;
|
|
230
499
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// for each call. The password is checked with Gmail before it is saved, and
|
|
8
8
|
// never appears in a config, log, error or tool result.
|
|
9
9
|
import { createHash } from 'node:crypto';
|
|
10
|
-
import keychain from '
|
|
10
|
+
import { keychainSecretStore as keychain } from '../shared/config.mjs';
|
|
11
11
|
import { GMAIL_APP_PASSWORD, gmailAddress } from '../shared/connector-catalog.mjs';
|
|
12
12
|
import { connectorAccountsInstructions } from '../shared/connector-accounts.mjs';
|
|
13
13
|
|
|
@@ -723,9 +723,9 @@ const TOOLS = [
|
|
|
723
723
|
];
|
|
724
724
|
|
|
725
725
|
/** The tool definitions (name, description, schema, annotations) the server
|
|
726
|
-
* lists
|
|
727
|
-
|
|
728
|
-
return TOOLS.filter((tool) =>
|
|
726
|
+
* lists: never the ones only the approval gate calls. */
|
|
727
|
+
function gmailAppPasswordTools() {
|
|
728
|
+
return TOOLS.filter((tool) => !tool.hidden).map(({ run, hidden: _hidden, ...tool }) => tool);
|
|
729
729
|
}
|
|
730
730
|
|
|
731
731
|
// ── The MCP server at the reserved address ──────────────────────────────────
|
|
@@ -331,7 +331,7 @@ const SERVICES = {
|
|
|
331
331
|
|
|
332
332
|
/** The tool definitions (name, description, schema, annotations) of built-in
|
|
333
333
|
* Google service `service` (`gmail`, `calendar`, `drive`). */
|
|
334
|
-
|
|
334
|
+
function googleMcpTools(service) {
|
|
335
335
|
return (SERVICES[service]?.tools || []).map(({ run, ...tool }) => tool);
|
|
336
336
|
}
|
|
337
337
|
|
|
@@ -83,7 +83,7 @@ function waitReady(ms) {
|
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
function effortJudgeModelDir() {
|
|
87
87
|
return process.env.MIXDOG_EFFORT_JUDGE_DIR || join(resolvePluginData(), 'models', 'effort-judge');
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -280,7 +280,7 @@ async function runInstall() {
|
|
|
280
280
|
* background. Runs on the first judged turn of the process, never at runtime
|
|
281
281
|
* creation, so booting touches no network.
|
|
282
282
|
*/
|
|
283
|
-
|
|
283
|
+
function refreshEffortJudge() {
|
|
284
284
|
if (!onnxRuntimeSupported()) return;
|
|
285
285
|
installEffortJudge().catch((error) => {
|
|
286
286
|
// An older complete install still works.
|
|
@@ -17,7 +17,7 @@ const HEX = /(?<![0-9A-Za-z])[0-9a-fA-F]{12,}(?![0-9A-Za-z])/g;
|
|
|
17
17
|
const SPACES = /[ \t]+/g;
|
|
18
18
|
const BLANK_LINES = /\n[ \t]*\n[\n \t]*/g;
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
function cleanJudgeText(text) {
|
|
21
21
|
return String(text || '')
|
|
22
22
|
.replace(/\r\n?/g, '\n')
|
|
23
23
|
.replace(ANSI, '')
|
|
@@ -49,10 +49,10 @@ export function judgeInputClean(request, prev) {
|
|
|
49
49
|
// continues), the previous reply's first line (its topic), then as much of the
|
|
50
50
|
// reply's END (what a short approval answers) as remains. Training builds the
|
|
51
51
|
// same id sequence (clean_text.pack_ids) with the identical tokenizer.
|
|
52
|
-
|
|
52
|
+
const PACK_BUDGET = Object.freeze({ request: 64, prevRequest: 24, replyHead: 16 });
|
|
53
53
|
|
|
54
54
|
/** Split the cleaned previous reply into its first line and the remaining text. */
|
|
55
|
-
|
|
55
|
+
function splitReply(reply) {
|
|
56
56
|
const at = reply.indexOf('\n');
|
|
57
57
|
return at < 0 ? [reply, ''] : [reply.slice(0, at), reply.slice(at + 1)];
|
|
58
58
|
}
|
|
@@ -63,7 +63,7 @@ export function splitReply(reply) {
|
|
|
63
63
|
// A result keeps its start and end (where errors and summaries sit); the
|
|
64
64
|
// stored window (2000 + 1000 code points) bounds the cleaning work on huge
|
|
65
65
|
// outputs. Training builds the same text (clean_text.step_judge_text).
|
|
66
|
-
|
|
66
|
+
const STEP_CALLS = 3;
|
|
67
67
|
|
|
68
68
|
export function stepResultWindow(text) {
|
|
69
69
|
const cps = Array.from(String(text ?? ''));
|