mixdog 1.3.4 → 1.4.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/oh-my-pi-MIT.txt +23 -0
- package/NOTICE.md +17 -2
- package/README.md +11 -0
- package/package.json +3 -11
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/embed-google-oauth-client.mjs +49 -0
- package/scripts/gate-local.mjs +4 -2
- package/scripts/lib/test-spawn-ledger.mjs +46 -1
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +10 -1
- package/scripts/test.mjs +12 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +25 -1
- package/src/defaults/skills/browser-use/SKILL.md +77 -17
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +33 -9
- package/src/defaults/skills/setup/SKILL.md +29 -2
- package/src/defaults/skills/setup/references/actions.md +117 -28
- package/src/defaults/skills/setup/references/surfaces.md +77 -35
- package/src/defaults/skills/setup-guide/SKILL.md +3 -3
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/keychain-cjs.cjs +359 -29
- package/src/lib/rules-builder.cjs +10 -8
- package/src/rules/agent/AGENT.md +6 -6
- package/src/rules/agent-mode/AGENT_MODE.md +10 -2
- package/src/rules/agent-mode/MIXY.md +12 -0
- package/src/rules/lead/LEAD.md +18 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/config.mjs +34 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +177 -73
- package/src/runtime/agent/orchestrator/mcp/client.mjs +25 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +230 -137
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +64 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +160 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +142 -104
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
- package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
- package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +19 -1
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
- 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-error-contract.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +43 -3
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/wire-protobuf-codec.mjs +368 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +148 -25
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +47 -9
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +51 -3
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +14 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +23 -5
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
- package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +47 -11
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +133 -18
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +25 -2
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/schedule-errors.mjs +51 -0
- package/src/runtime/channels/lib/scheduler.mjs +135 -154
- package/src/runtime/channels/lib/schedules-db.mjs +83 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +14 -2
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +19 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/office/com/com-adapter.mjs +17 -1
- package/src/runtime/office/com/office-com-host.ps1 +51 -1
- package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
- package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
- package/src/runtime/office/pdf/document-preview.mjs +326 -8
- package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
- package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
- package/src/runtime/office/portable/portable-soffice.mjs +45 -5
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bot-hops.mjs +62 -2
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +51 -35
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +33 -2
- package/src/runtime/shared/connector-catalog.mjs +166 -8
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -14
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/developer-options.mjs +32 -1
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/google-oauth-client.generated.json +4 -0
- package/src/runtime/shared/google-oauth-client.mjs +34 -9
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
- package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/llm/well-formed.mjs +66 -0
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +231 -59
- package/src/runtime/shared/provider-api-key.mjs +19 -8
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +52 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +34 -1
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -14
- package/src/runtime/shared/transcript-metadata.mjs +38 -0
- package/src/runtime/shared/user-data-guard.mjs +30 -2
- package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
- package/src/runtime/shared/worktrees/test-support.mjs +9 -4
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +27 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +486 -179
- package/src/session-runtime/agent-room-delivery.mjs +28 -1
- package/src/session-runtime/agent-task-sessions.mjs +561 -199
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/begin.mjs +3 -2
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +8 -1
- package/src/session-runtime/bot-chain.mjs +32 -0
- package/src/session-runtime/bot-status.mjs +7 -4
- package/src/session-runtime/channel-config-api.mjs +63 -17
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
- package/src/session-runtime/internal-tool-executor.mjs +4 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +61 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +927 -0
- package/src/session-runtime/model-route/route-tuning.mjs +10 -6
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +35 -13
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-auth/login.mjs +7 -0
- package/src/session-runtime/provider-models/row-hydration.mjs +13 -2
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/routine-home-turn.mjs +33 -6
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/schedule-session-run.mjs +7 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +73 -31
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +128 -25
- package/src/session-runtime/services/schedule-access.mjs +14 -0
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +8 -4
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +28 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +187 -29
- package/src/session-runtime/setup-tool/extended-actions.mjs +33 -2
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +68 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +92 -6
- package/src/session-runtime/task-session-route.mjs +99 -0
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +21 -4
- package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
- package/src/session-runtime/tool-surface.mjs +4 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
- package/src/session-runtime/workspace/transitions.mjs +10 -2
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +161 -157
- package/src/standalone/daemon.mjs +33 -2
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +10 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-service.mjs +13 -0
- package/src/standalone/session-tool-output.mjs +21 -10
- package/src/tui/app/model-options.mjs +4 -27
- package/src/tui/dist/index.mjs +81 -65
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +23 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/integrations.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +8 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +30 -2
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +36 -3
- package/src/tui/session/turn.mjs +23 -2
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -25,10 +25,10 @@ export interface ConnectorCatalogEntry {
|
|
|
25
25
|
id: string;
|
|
26
26
|
name: string;
|
|
27
27
|
backend: ConnectorBackend;
|
|
28
|
-
/** Offered only after the user enters their own Google OAuth client. */
|
|
29
|
-
ownKey?: boolean;
|
|
30
28
|
/** Curated deferred-tool manifest line (connector-triggers.mjs). */
|
|
31
29
|
trigger: string;
|
|
30
|
+
/** New connections go by app password only (Gmail). */
|
|
31
|
+
appPasswordOnly?: boolean;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export const CONNECTOR_CATALOG: readonly ConnectorCatalogEntry[];
|
|
@@ -43,9 +43,40 @@ export function connectorServerInput(
|
|
|
43
43
|
key?: string,
|
|
44
44
|
options?: { extraAccount?: boolean }
|
|
45
45
|
): Record<string, unknown>;
|
|
46
|
+
export function connectorAppPasswordOnly(entry: ConnectorCatalogEntry | null | undefined): boolean;
|
|
47
|
+
export function connectorUsesGoogleClient(entry: ConnectorCatalogEntry | null | undefined): boolean;
|
|
46
48
|
export function connectorMultiAccount(entry: ConnectorCatalogEntry | null | undefined): boolean;
|
|
47
49
|
export const GMAIL_APP_PASSWORD: Readonly<{ url: string; accountHeader: string; helpUrl: string }>;
|
|
48
50
|
export function gmailAddress(value: unknown): string;
|
|
49
51
|
export function gmailAppPasswordValue(value: unknown): string;
|
|
50
52
|
export function gmailAppPasswordAccount(cfg: unknown): string;
|
|
51
53
|
export function gmailAppPasswordServerInput(name: string, email: string, password: string): Record<string, unknown>;
|
|
54
|
+
|
|
55
|
+
/** One stored account of a multi-account connector server. */
|
|
56
|
+
export interface ConnectorAccountEntry {
|
|
57
|
+
name: string;
|
|
58
|
+
url: string;
|
|
59
|
+
headers?: Record<string, string>;
|
|
60
|
+
oauthClientId?: string;
|
|
61
|
+
/** `false`: the account is kept but neither connected nor called. */
|
|
62
|
+
enabled?: boolean;
|
|
63
|
+
}
|
|
64
|
+
export function connectorAccountsUrl(id: string): string;
|
|
65
|
+
export function connectorAccountsOf(cfg: unknown): ConnectorAccountEntry[];
|
|
66
|
+
export function connectorAccountServer(
|
|
67
|
+
cfg: Record<string, unknown>,
|
|
68
|
+
account: ConnectorAccountEntry
|
|
69
|
+
): Record<string, unknown>;
|
|
70
|
+
export function connectorAccountServers(cfg: unknown): Record<string, unknown>[];
|
|
71
|
+
export function connectorAccountEnabled(account: ConnectorAccountEntry): boolean;
|
|
72
|
+
export function connectorLiveAccountServers(cfg: unknown): Record<string, unknown>[];
|
|
73
|
+
export function withConnectorAccountEnabled(
|
|
74
|
+
cfg: Record<string, unknown>,
|
|
75
|
+
name: string,
|
|
76
|
+
enabled: boolean
|
|
77
|
+
): Record<string, unknown>;
|
|
78
|
+
export function connectorAccountEntry(name: string, cfg: Record<string, unknown>): ConnectorAccountEntry;
|
|
79
|
+
export function mergeConnectorAccountServers(servers: Record<string, unknown>): {
|
|
80
|
+
servers: Record<string, unknown>;
|
|
81
|
+
merged: { connector: string; name: string; from: string[] }[];
|
|
82
|
+
};
|
|
@@ -53,20 +53,18 @@ export const CONNECTOR_CATALOG = Object.freeze(
|
|
|
53
53
|
id: 'gmail',
|
|
54
54
|
name: 'Gmail',
|
|
55
55
|
backend: google('gmail', GOOGLE_SCOPES.gmail, ['send_email']),
|
|
56
|
+
// New Gmail connections use an app password only (GMAIL_APP_PASSWORD);
|
|
57
|
+
// a Gmail server already on the Google sign-in keeps working.
|
|
58
|
+
appPasswordOnly: true,
|
|
56
59
|
},
|
|
57
|
-
// Calendar and Drive are offered only to a user who entered their own
|
|
58
|
-
// Google OAuth client (Connectors → add custom → 내 Google 키): `ownKey`.
|
|
59
|
-
// Existing connections keep working; Mixy and the chat cards never offer them.
|
|
60
60
|
{
|
|
61
61
|
id: 'google-calendar',
|
|
62
62
|
name: 'Google Calendar',
|
|
63
|
-
ownKey: true,
|
|
64
63
|
backend: google('calendar', GOOGLE_SCOPES.calendar, ['delete_event']),
|
|
65
64
|
},
|
|
66
65
|
{
|
|
67
66
|
id: 'google-drive',
|
|
68
67
|
name: 'Google Drive',
|
|
69
|
-
ownKey: true,
|
|
70
68
|
backend: google('drive', GOOGLE_SCOPES.drive, []),
|
|
71
69
|
},
|
|
72
70
|
{
|
|
@@ -113,9 +111,8 @@ export const CONNECTOR_CATALOG = Object.freeze(
|
|
|
113
111
|
].map((entry) => Object.freeze({ ...entry, trigger: connectorTrigger(entry.id) }))
|
|
114
112
|
);
|
|
115
113
|
|
|
116
|
-
/** The ids
|
|
117
|
-
|
|
118
|
-
export const CONNECTOR_IDS = Object.freeze(CONNECTOR_CATALOG.filter((entry) => !entry.ownKey).map((entry) => entry.id));
|
|
114
|
+
/** The ids the setup tool's `connect_connector` offers: the whole catalog. */
|
|
115
|
+
export const CONNECTOR_IDS = Object.freeze(CONNECTOR_CATALOG.map((entry) => entry.id));
|
|
119
116
|
|
|
120
117
|
/** The catalog entry for `id`, or null. */
|
|
121
118
|
export function connectorById(id) {
|
|
@@ -193,6 +190,167 @@ export function connectorMultiAccount(entry) {
|
|
|
193
190
|
return entry?.backend?.kind === 'oauth' && entry.backend.oauthClient === 'google';
|
|
194
191
|
}
|
|
195
192
|
|
|
193
|
+
// ── One server per multi-account connector ──────────────────────────────────
|
|
194
|
+
// A multi-account connector is ONE MCP server (`gmail`, `google-calendar`,
|
|
195
|
+
// `google-drive`) holding its accounts:
|
|
196
|
+
// { type: 'http', url: connectorAccountsUrl(id), connector: id,
|
|
197
|
+
// accounts: [{ name, url, headers?, oauthClientId? }, …] }
|
|
198
|
+
// Each account keeps the transport it had as a server of its own (the Google
|
|
199
|
+
// sign-in URL its tokens are stored under, or the app-password address and
|
|
200
|
+
// account header), so its keychain entries are untouched. Account names share
|
|
201
|
+
// the server-name space (`gmail`, `gmail-2`…): a name-based call (remove, sign
|
|
202
|
+
// in, sign out) that names an account acts on that account. The server is
|
|
203
|
+
// answered in-process (connectors/connector-accounts-mcp.mjs): one tool set
|
|
204
|
+
// with an `account` argument.
|
|
205
|
+
const ACCOUNT_FIELDS = ['url', 'headers', 'oauthClientId'];
|
|
206
|
+
|
|
207
|
+
/** The reserved (never resolvable) address of connector `id`'s accounts server. */
|
|
208
|
+
export function connectorAccountsUrl(id) {
|
|
209
|
+
return `https://connectors.mixdog.invalid/${encodeURIComponent(id)}/mcp`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
213
|
+
|
|
214
|
+
/** The stored accounts of a multi-account connector server, [] for any other
|
|
215
|
+
* config (a legacy one-account server included). */
|
|
216
|
+
export function connectorAccountsOf(cfg) {
|
|
217
|
+
if (!isRecord(cfg) || !Array.isArray(cfg.accounts)) return [];
|
|
218
|
+
if (!connectorMultiAccount(connectorById(connectorOfServer(cfg)))) return [];
|
|
219
|
+
return cfg.accounts.filter(
|
|
220
|
+
(account) =>
|
|
221
|
+
isRecord(account) && typeof account.name === 'string' && account.name && typeof account.url === 'string'
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** The one-account server config of `account` of server `cfg` (the shape the
|
|
226
|
+
* account had as a server of its own), named by the account. */
|
|
227
|
+
export function connectorAccountServer(cfg, account) {
|
|
228
|
+
const out = { name: account.name, type: 'http' };
|
|
229
|
+
for (const field of ACCOUNT_FIELDS) if (account[field] !== undefined) out[field] = account[field];
|
|
230
|
+
out.connector = cfg.connector;
|
|
231
|
+
return out;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Every account of `cfg` as its one-account server config. */
|
|
235
|
+
export function connectorAccountServers(cfg) {
|
|
236
|
+
return connectorAccountsOf(cfg).map((account) => connectorAccountServer(cfg, account));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Whether stored account `account` is switched on (`enabled: false` is off). */
|
|
240
|
+
export const connectorAccountEnabled = (account) => account.enabled !== false;
|
|
241
|
+
|
|
242
|
+
/** The switched-on accounts of `cfg` as their one-account server configs: the
|
|
243
|
+
* ones the server connects and routes calls to. */
|
|
244
|
+
export function connectorLiveAccountServers(cfg) {
|
|
245
|
+
return connectorAccountsOf(cfg)
|
|
246
|
+
.filter(connectorAccountEnabled)
|
|
247
|
+
.map((account) => connectorAccountServer(cfg, account));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Server `cfg` with its account `name` switched on or off. Off flags the
|
|
252
|
+
* account (`enabled: false`) and switches the server off with its last
|
|
253
|
+
* switched-on account. On drops the flag (a switched-on account carries none)
|
|
254
|
+
* and switches the server on. Every other entry stays as stored.
|
|
255
|
+
*/
|
|
256
|
+
export function withConnectorAccountEnabled(cfg, name, enabled) {
|
|
257
|
+
const accounts = cfg.accounts.map((account) => {
|
|
258
|
+
if (!isRecord(account) || account.name !== name) return account;
|
|
259
|
+
const { enabled: _enabled, ...rest } = account;
|
|
260
|
+
return enabled ? rest : { ...rest, enabled: false };
|
|
261
|
+
});
|
|
262
|
+
const next = { ...cfg, accounts };
|
|
263
|
+
if (enabled) return { ...next, enabled: true };
|
|
264
|
+
return connectorAccountsOf(next).some(connectorAccountEnabled) ? next : { ...next, enabled: false };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** The stored account entry of one-account config `cfg` under `name`. */
|
|
268
|
+
export function connectorAccountEntry(name, cfg) {
|
|
269
|
+
const out = { name };
|
|
270
|
+
for (const field of ACCOUNT_FIELDS) if (cfg?.[field] !== undefined) out[field] = cfg[field];
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const naturalOrder = (a, b) => a.localeCompare(b, 'en', { numeric: true });
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Merges every multi-account connector's servers into one server holding the
|
|
278
|
+
* accounts: legacy one-account servers (`gmail`, `gmail-2`…, Calendar and
|
|
279
|
+
* Drive alike) and any second accounts server. The server keeps the name of
|
|
280
|
+
* an existing accounts server, else the connector id when a server has it,
|
|
281
|
+
* else the first name; its other fields come from that server. Accounts keep
|
|
282
|
+
* their names, transports and order (that server's first); a second entry
|
|
283
|
+
* for the same name or app-password address is dropped. The merged server is
|
|
284
|
+
* off only when every merged one was; otherwise the accounts of a merged
|
|
285
|
+
* server that was off stay off (`enabled: false` on the account), and an
|
|
286
|
+
* account's own `enabled: false` is kept. A server left with no switched-on
|
|
287
|
+
* account is off. Idempotent: `merged` is empty when
|
|
288
|
+
* nothing changed. Returns `{ servers, merged: [{ connector, name, from }] }`.
|
|
289
|
+
*/
|
|
290
|
+
export function mergeConnectorAccountServers(input) {
|
|
291
|
+
const servers = isRecord(input) ? { ...input } : {};
|
|
292
|
+
const merged = [];
|
|
293
|
+
for (const entry of CONNECTOR_CATALOG.filter(connectorMultiAccount)) {
|
|
294
|
+
const names = Object.keys(servers)
|
|
295
|
+
.filter((name) => isRecord(servers[name]) && connectorOfServer(servers[name]) === entry.id)
|
|
296
|
+
.sort(naturalOrder);
|
|
297
|
+
if (!names.length) continue;
|
|
298
|
+
const grouped = names.filter((name) => Array.isArray(servers[name].accounts));
|
|
299
|
+
if (names.length === 1 && grouped.length === 1) continue;
|
|
300
|
+
const target = grouped[0] ?? (names.includes(entry.id) ? entry.id : names[0]);
|
|
301
|
+
const order = [target, ...names.filter((name) => name !== target)];
|
|
302
|
+
const off = order.every((name) => input[name].enabled === false);
|
|
303
|
+
const accounts = [];
|
|
304
|
+
const seenNames = new Set();
|
|
305
|
+
const seenAddresses = new Set();
|
|
306
|
+
for (const name of order) {
|
|
307
|
+
const cfg = servers[name];
|
|
308
|
+
const own = Array.isArray(cfg.accounts) ? connectorAccountsOf(cfg) : [connectorAccountEntry(name, cfg)];
|
|
309
|
+
// A merged server that was off keeps its accounts off, unless the whole
|
|
310
|
+
// connector is off (then re-enabling it brings every account back).
|
|
311
|
+
const serverOff = !off && cfg.enabled === false;
|
|
312
|
+
for (const account of own) {
|
|
313
|
+
const address = gmailAppPasswordAccount(connectorAccountServer(cfg, account));
|
|
314
|
+
if (seenNames.has(account.name) || (address && seenAddresses.has(address))) continue;
|
|
315
|
+
seenNames.add(account.name);
|
|
316
|
+
if (address) seenAddresses.add(address);
|
|
317
|
+
accounts.push(serverOff ? { ...account, enabled: false } : account);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const {
|
|
321
|
+
type: _type,
|
|
322
|
+
url: _url,
|
|
323
|
+
headers: _headers,
|
|
324
|
+
oauthClientId: _client,
|
|
325
|
+
accounts: _accounts,
|
|
326
|
+
enabled: _enabled,
|
|
327
|
+
...rest
|
|
328
|
+
} = servers[target];
|
|
329
|
+
for (const name of order) delete servers[name];
|
|
330
|
+
servers[target] = {
|
|
331
|
+
...rest,
|
|
332
|
+
type: 'http',
|
|
333
|
+
url: connectorAccountsUrl(entry.id),
|
|
334
|
+
connector: entry.id,
|
|
335
|
+
accounts,
|
|
336
|
+
...(off || (accounts.length > 0 && !accounts.some(connectorAccountEnabled)) ? { enabled: false } : {}),
|
|
337
|
+
};
|
|
338
|
+
merged.push({ connector: entry.id, name: target, from: order });
|
|
339
|
+
}
|
|
340
|
+
return { servers, merged };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** Whether a new connection of `entry` goes by app password only (Gmail). */
|
|
344
|
+
export function connectorAppPasswordOnly(entry) {
|
|
345
|
+
return entry?.appPasswordOnly === true;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** Whether `entry` signs in with Mixdog's built-in Google client (or the
|
|
349
|
+
* user's own Google client in its place). */
|
|
350
|
+
export function connectorUsesGoogleClient(entry) {
|
|
351
|
+
return entry?.backend?.kind === 'oauth' && entry.backend.oauthClient === 'google';
|
|
352
|
+
}
|
|
353
|
+
|
|
196
354
|
/** The MCP server input that connects catalog entry `entry` under `name`
|
|
197
355
|
* (oauth / apiKey); `key` fills an apiKey backend; `extraAccount`
|
|
198
356
|
* makes it one more account of a multi-account connector. */
|
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
// Curated selection triggers for catalog connectors (MCP servers). A catalog
|
|
2
2
|
// entry carries its line as `trigger`; the deferred-tool manifest lists each
|
|
3
3
|
// connected server once as `- mcp__<server id>: <trigger>`, so one line must
|
|
4
|
-
// say
|
|
5
|
-
//
|
|
4
|
+
// say WHEN to call the server (the user requests it covers, plus a close
|
|
5
|
+
// negative where useful), not list its capabilities; plain ASCII English, at
|
|
6
|
+
// most CONNECTOR_TRIGGER_MAX_CHARS characters.
|
|
6
7
|
export const CONNECTOR_TRIGGER_MAX_CHARS = 100;
|
|
7
8
|
|
|
8
9
|
export const CONNECTOR_TRIGGERS = Object.freeze({
|
|
9
10
|
// Not a catalog connector (Mixdog uses the signed-in GitHub CLI), but a
|
|
10
11
|
// user-added `github` MCP server still gets this line.
|
|
11
|
-
github: 'GitHub
|
|
12
|
-
notion: 'Notion pages, databases and
|
|
13
|
-
linear: '
|
|
14
|
-
sentry: '
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
github: 'GitHub issues, pull requests, Actions runs and repo code search; not local Git history.',
|
|
13
|
+
notion: 'Finding, reading or updating Notion pages, databases and team notes.',
|
|
14
|
+
linear: 'Looking up, creating or triaging Linear issues, projects and cycles.',
|
|
15
|
+
sentry: 'Investigating production errors, stack traces and releases in Sentry.',
|
|
16
|
+
// The line never names an account: that arrives with the server's
|
|
17
|
+
// instructions when its tools are loaded.
|
|
18
|
+
gmail: 'Gmail email: sending, reading, searching or organizing mail.',
|
|
19
|
+
'google-calendar': 'Google Calendar: checking, creating or editing events.',
|
|
20
|
+
'google-drive': 'Google Drive: finding, reading or creating files Mixdog made or was given; not local files.',
|
|
21
|
+
jira: 'Looking up, creating or transitioning Jira tickets, sprints and JQL searches.',
|
|
22
|
+
confluence: 'Searching, reading or editing Confluence wiki pages; not Jira tickets.',
|
|
23
|
+
dropbox: 'Finding, reading, uploading or sharing Dropbox files; not local files.',
|
|
24
|
+
trello: 'Viewing, creating or moving Trello boards, lists and cards.',
|
|
25
|
+
airtable: 'Querying or updating Airtable bases, tables and records.',
|
|
26
|
+
stripe: 'Checking or acting on Stripe payments, invoices, subscriptions and refunds.',
|
|
27
|
+
vercel: 'Checking Vercel deployments, domains, logs and build errors.',
|
|
28
|
+
supabase: 'Working with Supabase Postgres tables, SQL, auth, storage or edge functions.',
|
|
29
|
+
postgres: 'Running SQL or inspecting schemas on a connected PostgreSQL database; not local files.',
|
|
30
|
+
'hugging-face': 'Finding Hugging Face Hub models, datasets, Spaces or papers; not local GGUF setup.',
|
|
28
31
|
});
|
|
29
32
|
|
|
30
33
|
// Server ids differ only in separators and case (google_calendar, huggingface).
|
|
@@ -40,13 +40,12 @@ const AGENT_SECTION_DEFAULTS = Object.freeze({
|
|
|
40
40
|
const MODULE_DEFAULTS = Object.freeze({ enabled: true });
|
|
41
41
|
|
|
42
42
|
export const CHANNELS_DEFAULTS = Object.freeze({
|
|
43
|
-
access: Object.freeze({ dmPolicy: 'allowlist', allowFrom: [], channels: {} }),
|
|
44
43
|
webhook: Object.freeze({ enabled: true, port: 3333 }),
|
|
45
44
|
});
|
|
46
45
|
|
|
47
46
|
// Disabled-agent roster shipped before `advisor` joined the defaults
|
|
48
47
|
// (worker … writer plus the Maintainer). Stored full lists are read against it.
|
|
49
|
-
|
|
48
|
+
const PREVIOUS_DISABLED_AGENT_ROSTER = Object.freeze([
|
|
50
49
|
'front-worker',
|
|
51
50
|
'heavy-worker',
|
|
52
51
|
'maintainer',
|
|
@@ -168,17 +167,6 @@ function removeLegacyKeys(root, dataDir) {
|
|
|
168
167
|
if (isPlainObject(agent.agents)) agent.agents = withoutRetiredAgentRoutes(agent.agents, dataDir);
|
|
169
168
|
next.agent = agent;
|
|
170
169
|
}
|
|
171
|
-
const channelEntries = next.channels?.access?.channels;
|
|
172
|
-
if (isPlainObject(channelEntries)) {
|
|
173
|
-
const channels = Object.fromEntries(
|
|
174
|
-
Object.entries(channelEntries).map(([id, entry]) => {
|
|
175
|
-
if (!isPlainObject(entry)) return [id, entry];
|
|
176
|
-
const { requireMention: _retired, ...rest } = entry;
|
|
177
|
-
return [id, rest];
|
|
178
|
-
})
|
|
179
|
-
);
|
|
180
|
-
next.channels = { ...next.channels, access: { ...next.channels.access, channels } };
|
|
181
|
-
}
|
|
182
170
|
return next;
|
|
183
171
|
}
|
|
184
172
|
|
|
@@ -188,7 +176,7 @@ function removeLegacyKeys(root, dataDir) {
|
|
|
188
176
|
* not set the marker. `stripRouteDefaults` drops shipped presets and
|
|
189
177
|
* maintenance routes (their defaults live with the agent config).
|
|
190
178
|
*/
|
|
191
|
-
|
|
179
|
+
function separateDefaultsInConfig(
|
|
192
180
|
root,
|
|
193
181
|
{ stripRouteDefaults = (agent) => agent, dataDir = resolvePluginData() } = {}
|
|
194
182
|
) {
|
|
@@ -6,14 +6,86 @@
|
|
|
6
6
|
// owner, and the copy is withdrawn as soon as the owner settles (answered in
|
|
7
7
|
// either place, timed out, its turn ended). Like held-request-host.mjs this
|
|
8
8
|
// registry is process-wide and dependency-free.
|
|
9
|
+
// Hand-offs take the same path: a session chats handed work to (`session`
|
|
10
|
+
// send / create from a bot conversation, agent-task-sessions.mjs) shows its
|
|
11
|
+
// own approvals in EVERY chat whose hand-off to it still owes its report, one
|
|
12
|
+
// copy per chat, all settling the one request. The report watch store
|
|
13
|
+
// (session-runtime/agent-home-delivery.mjs) notes and ends hand-offs as its
|
|
14
|
+
// watches come and go, whatever removes them; a chat
|
|
15
|
+
// whose last hand-off to the session ends loses its copy, the others keep
|
|
16
|
+
// theirs.
|
|
9
17
|
|
|
10
18
|
const KEY = Symbol.for('mixdog.delegatedApprovalHost.v1');
|
|
11
19
|
|
|
12
20
|
function registry() {
|
|
13
|
-
globalThis[KEY] ??= { queues: new Set(), pending: new Map(), opener: null };
|
|
21
|
+
globalThis[KEY] ??= { queues: new Set(), pending: new Map(), opener: null, handoffs: new Map(), ended: new Set() };
|
|
14
22
|
return globalThis[KEY];
|
|
15
23
|
}
|
|
16
24
|
|
|
25
|
+
/** The chats with a live hand-off to `sessionId`, each once (in noting order)
|
|
26
|
+
* with the name its latest hand-off gave the session: Map chat → `{ title }`. */
|
|
27
|
+
export function handoffChatsOf(sessionId) {
|
|
28
|
+
const chats = new Map();
|
|
29
|
+
for (const handoff of registry().handoffs.values()) {
|
|
30
|
+
if (handoff.sessionId !== sessionId) continue;
|
|
31
|
+
chats.delete(handoff.surfaceSessionId);
|
|
32
|
+
chats.set(handoff.surfaceSessionId, { title: handoff.title });
|
|
33
|
+
}
|
|
34
|
+
return chats;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Bring each pending request of `sessionId` that hand-offs reach to exactly
|
|
38
|
+
* the chats now handing it work: a new chat gets its copy, a chat whose
|
|
39
|
+
* hand-offs all ended loses only its own. */
|
|
40
|
+
function syncHandoffCopies(sessionId) {
|
|
41
|
+
const { pending } = registry();
|
|
42
|
+
const chats = handoffChatsOf(sessionId);
|
|
43
|
+
for (const asked of pending.values()) {
|
|
44
|
+
if (!asked.copies || asked.sessionId !== sessionId) continue;
|
|
45
|
+
for (const [chat, copy] of asked.copies) {
|
|
46
|
+
if (chats.has(chat)) continue;
|
|
47
|
+
asked.copies.delete(chat);
|
|
48
|
+
for (const queue of liveQueuesOf(chat)) queue.withdraw(copy.id, null);
|
|
49
|
+
}
|
|
50
|
+
for (const [chat, handoff] of chats) {
|
|
51
|
+
if (asked.copies.has(chat)) continue;
|
|
52
|
+
const copy = { id: asked.id, sessionId: chat, request: asked.copyFor(chat, handoff), answer: asked.answer };
|
|
53
|
+
asked.copies.set(chat, copy);
|
|
54
|
+
deliver(copy, () => pending.get(asked.id) === asked && asked.copies.get(chat) === copy);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Run ids of hand-offs that ended: never noted again (a watch read before it
|
|
60
|
+
// was removed must not bring it back, however many hand-offs ended since).
|
|
61
|
+
// Run ids are never reused, so an ended id is final for the life of the
|
|
62
|
+
// process and there is nothing to age out: no count decides what is
|
|
63
|
+
// forgotten. One id string is kept per ended hand-off.
|
|
64
|
+
|
|
65
|
+
/** Chat `homeSessionId` handed session `taskSessionId` work (`title`: the
|
|
66
|
+
* target's name in that chat) under report watch `runId`. */
|
|
67
|
+
export function noteHandoff({ runId, taskSessionId, homeSessionId, title }) {
|
|
68
|
+
if (!runId || !taskSessionId || !homeSessionId || taskSessionId === homeSessionId) return;
|
|
69
|
+
if (registry().ended.has(String(runId))) return;
|
|
70
|
+
registry().handoffs.set(String(runId), {
|
|
71
|
+
sessionId: String(taskSessionId),
|
|
72
|
+
surfaceSessionId: String(homeSessionId),
|
|
73
|
+
title: String(title || ''),
|
|
74
|
+
});
|
|
75
|
+
syncHandoffCopies(String(taskSessionId));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The report watch `runId` is gone (its work reported back, was never
|
|
79
|
+
* taken, or the watch was retired): its hand-off ends for good. */
|
|
80
|
+
export function endHandoff(runId) {
|
|
81
|
+
const { handoffs, ended } = registry();
|
|
82
|
+
ended.add(String(runId));
|
|
83
|
+
const handoff = handoffs.get(String(runId));
|
|
84
|
+
if (!handoff) return;
|
|
85
|
+
handoffs.delete(String(runId));
|
|
86
|
+
syncHandoffCopies(handoff.sessionId);
|
|
87
|
+
}
|
|
88
|
+
|
|
17
89
|
/** `queue`: `{ sessionId() → string, disposed() → boolean, offer(delegated),
|
|
18
90
|
* withdraw(id, result) }` — one session runtime's approval queue. */
|
|
19
91
|
export function registerApprovalQueue(queue) {
|
|
@@ -46,20 +118,36 @@ function offerTo(sessionId, delegated) {
|
|
|
46
118
|
return live.length > 0;
|
|
47
119
|
}
|
|
48
120
|
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
const {
|
|
53
|
-
|
|
54
|
-
if (offerTo(delegated.sessionId, delegated) || typeof opener !== 'function') return;
|
|
121
|
+
/** Offer `copy` in its chat now, or once that chat loads while `current()`
|
|
122
|
+
* still holds. */
|
|
123
|
+
function deliver(copy, current) {
|
|
124
|
+
const { opener } = registry();
|
|
125
|
+
if (offerTo(copy.sessionId, copy) || typeof opener !== 'function') return;
|
|
55
126
|
void Promise.resolve()
|
|
56
|
-
.then(() => opener(
|
|
127
|
+
.then(() => opener(copy.sessionId))
|
|
57
128
|
.then(() => {
|
|
58
|
-
if (
|
|
129
|
+
if (current()) offerTo(copy.sessionId, copy);
|
|
59
130
|
})
|
|
60
131
|
.catch(() => {});
|
|
61
132
|
}
|
|
62
133
|
|
|
134
|
+
/** Show `delegated` (`{ id, sessionId, request, answer(...finishArgs) → boolean }`,
|
|
135
|
+
* `sessionId` being the top-level conversation) there, now or once it loads. */
|
|
136
|
+
export function delegateApproval(delegated) {
|
|
137
|
+
const { pending } = registry();
|
|
138
|
+
pending.set(delegated.id, delegated);
|
|
139
|
+
deliver(delegated, () => pending.get(delegated.id) === delegated);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** A top-level session's request (`{ id, sessionId, request, answer }`,
|
|
143
|
+
* `sessionId` being the asking session) that every chat handing it work
|
|
144
|
+
* shows too, now and while it waits: `copyFor(chat, { title })` is the
|
|
145
|
+
* request as that chat shows it. */
|
|
146
|
+
export function delegateToHandoffs(asked) {
|
|
147
|
+
registry().pending.set(asked.id, { ...asked, copies: new Map() });
|
|
148
|
+
syncHandoffCopies(asked.sessionId);
|
|
149
|
+
}
|
|
150
|
+
|
|
63
151
|
/** The owner settled `id`: every copy goes away. `result` (`{ approved, device }`)
|
|
64
152
|
* lets the copy say who answered. */
|
|
65
153
|
export function withdrawDelegatedApproval(id, result = null) {
|
|
@@ -68,7 +156,11 @@ export function withdrawDelegatedApproval(id, result = null) {
|
|
|
68
156
|
for (const queue of queues) queue.withdraw(id, result);
|
|
69
157
|
}
|
|
70
158
|
|
|
71
|
-
/** The pending delegated approvals a top-level session
|
|
159
|
+
/** The pending delegated approvals (and hand-off copies) a top-level session
|
|
160
|
+
* should show. */
|
|
72
161
|
export function delegatedApprovalsFor(sessionId) {
|
|
73
|
-
return [...registry().pending.values()].
|
|
162
|
+
return [...registry().pending.values()].flatMap((delegated) => {
|
|
163
|
+
if (delegated.copies) return delegated.copies.has(sessionId) ? [delegated.copies.get(sessionId)] : [];
|
|
164
|
+
return delegated.sessionId === sessionId ? [delegated] : [];
|
|
165
|
+
});
|
|
74
166
|
}
|
|
@@ -5,12 +5,25 @@
|
|
|
5
5
|
// `developer.<optionId>` is true. Default off. An option with a `warning`
|
|
6
6
|
// turns on only after the user confirms that warning; an option with a
|
|
7
7
|
// `provider` gates that dev-only OAuth provider.
|
|
8
|
-
import { readSection } from './config.mjs';
|
|
8
|
+
import { readSection, readSectionStrict } from './config.mjs';
|
|
9
9
|
|
|
10
10
|
const OAUTH_RISK_WARNING =
|
|
11
11
|
'Using this provider through OAuth carries a high risk of penalties such as account restrictions.';
|
|
12
12
|
|
|
13
13
|
export const DEVELOPER_SECTIONS = Object.freeze([
|
|
14
|
+
Object.freeze({
|
|
15
|
+
id: 'approvals',
|
|
16
|
+
label: 'Approvals',
|
|
17
|
+
options: Object.freeze([
|
|
18
|
+
Object.freeze({
|
|
19
|
+
id: 'allowAllActions',
|
|
20
|
+
label: 'Allow all actions',
|
|
21
|
+
description: 'Skips the approval cards for every action except payments and permanent deletes.',
|
|
22
|
+
warning:
|
|
23
|
+
'Turning this on lets agents act without asking you first, except for payments and permanent deletes. Use it only if you accept that risk.',
|
|
24
|
+
}),
|
|
25
|
+
]),
|
|
26
|
+
}),
|
|
14
27
|
Object.freeze({
|
|
15
28
|
id: 'providers',
|
|
16
29
|
label: 'Providers',
|
|
@@ -30,6 +43,13 @@ export const DEVELOPER_SECTIONS = Object.freeze([
|
|
|
30
43
|
warning: OAUTH_RISK_WARNING,
|
|
31
44
|
provider: 'cursor-oauth',
|
|
32
45
|
}),
|
|
46
|
+
Object.freeze({
|
|
47
|
+
id: 'devinOAuth',
|
|
48
|
+
label: 'Devin',
|
|
49
|
+
description: 'Show Devin OAuth in Providers and the model picker.',
|
|
50
|
+
warning: OAUTH_RISK_WARNING,
|
|
51
|
+
provider: 'devin-oauth',
|
|
52
|
+
}),
|
|
33
53
|
Object.freeze({
|
|
34
54
|
id: 'mimoOAuth',
|
|
35
55
|
label: 'MiMo',
|
|
@@ -74,6 +94,17 @@ export function developerOptionEnabled(id, stored = storedDeveloperConfig()) {
|
|
|
74
94
|
return developerOption(id) !== null && normalizeDeveloperConfig(stored)[id] === true;
|
|
75
95
|
}
|
|
76
96
|
|
|
97
|
+
/** `developerOptionEnabled` for a safety bypass: fail-closed. Read straight
|
|
98
|
+
* from the config file, so a missing or malformed config is never restored
|
|
99
|
+
* from a backup (which may hold a stale `true`); any error means off. */
|
|
100
|
+
export function developerOptionEnabledStrict(id) {
|
|
101
|
+
try {
|
|
102
|
+
return developerOption(id) !== null && normalizeDeveloperConfig(readSectionStrict('agent').developer)[id] === true;
|
|
103
|
+
} catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
77
108
|
/** Settings view of every section; `stored` defaults to the on-disk values. */
|
|
78
109
|
export function developerSettingsView(stored = storedDeveloperConfig()) {
|
|
79
110
|
const values = normalizeDeveloperConfig(stored);
|
|
@@ -206,24 +206,25 @@ function hasTypedEvidence(error) {
|
|
|
206
206
|
);
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
// The window a provider timeout names (providerTimeoutError's message
|
|
210
|
-
|
|
209
|
+
// The window a provider timeout names (providerTimeoutError's message, or a
|
|
210
|
+
// first-byte watchdog's "within Nms"), or 0.
|
|
211
|
+
const timedOutMs = (text) => Number(/(?:timed out after|within) (\d+)ms/i.exec(text)?.[1]) || 0;
|
|
211
212
|
|
|
212
213
|
// A provider timeout before the model produced anything (isFirstByteTimeout):
|
|
213
|
-
// the model is slow, not the connection.
|
|
214
|
-
|
|
214
|
+
// the model is slow, not the connection. The provider name comes from the
|
|
215
|
+
// caller's own provider config, never from the error.
|
|
216
|
+
function stillThinkingText(error, text, providerLabel) {
|
|
215
217
|
const ms = Number(error.waitedMs) || timedOutMs(text);
|
|
216
|
-
const provider =
|
|
217
|
-
typeof error.providerLabel === 'string' && error.providerLabel ? error.providerLabel : 'the provider';
|
|
218
|
+
const provider = typeof providerLabel === 'string' && providerLabel ? providerLabel : 'the provider';
|
|
218
219
|
const attempts = Number(error.attempts) > 0 ? `; attempts: ${Math.floor(Number(error.attempts))}` : '';
|
|
219
220
|
return `Model still thinking: no output in ${formatDurationMs(ms)}; ${provider} sent nothing yet${attempts}.`;
|
|
220
221
|
}
|
|
221
222
|
|
|
222
223
|
// Stamped provider timeout phases and stream cuts. Null when the error names
|
|
223
224
|
// neither, so the text rules below decide.
|
|
224
|
-
function typedStreamFailureText(error, text) {
|
|
225
|
+
function typedStreamFailureText(error, text, providerLabel) {
|
|
225
226
|
if (!error || typeof error !== 'object') return null;
|
|
226
|
-
if (isFirstByteTimeout(error)) return stillThinkingText(error, text);
|
|
227
|
+
if (isFirstByteTimeout(error)) return stillThinkingText(error, text, providerLabel);
|
|
227
228
|
if (error.timeoutPhase === TIMEOUT_PHASE.IDLE) {
|
|
228
229
|
const ms = timedOutMs(text);
|
|
229
230
|
return ms > 0 ? `No progress ${formatDurationMs(ms)}.` : 'No progress.';
|
|
@@ -267,7 +268,7 @@ export function presentErrorText(error, options = {}) {
|
|
|
267
268
|
if (embeddedError) text = embeddedError;
|
|
268
269
|
text = oneLine(stripErrorPrefix(text));
|
|
269
270
|
if (!text) return 'Unknown error';
|
|
270
|
-
const streamFailure = typedStreamFailureText(error, text);
|
|
271
|
+
const streamFailure = typedStreamFailureText(error, text, options.providerLabel);
|
|
271
272
|
if (streamFailure) return streamFailure;
|
|
272
273
|
|
|
273
274
|
if (code === 'PROVIDER_PREFIX_MUTATION' || name === 'ProviderPrefixMutationError') {
|
|
@@ -369,12 +370,20 @@ export function presentErrorText(error, options = {}) {
|
|
|
369
370
|
return capText(safeErrorDetails(text) || 'Unknown error', max);
|
|
370
371
|
}
|
|
371
372
|
|
|
372
|
-
/**
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
373
|
+
/**
|
|
374
|
+
* Our own wording for a typed timeout retry (`first_response_timeout` /
|
|
375
|
+
* `stalled`), built only from the error's stamps and the window in its
|
|
376
|
+
* message; null for any other class. No error text is ever echoed.
|
|
377
|
+
*/
|
|
378
|
+
export function retryTimeoutText(error, reasonClass, providerLabel = null) {
|
|
379
|
+
const text = String(error?.message ?? '');
|
|
380
|
+
const ms = timedOutMs(text);
|
|
381
|
+
if (reasonClass === 'first_response_timeout') {
|
|
382
|
+
if (isFirstByteTimeout(error)) return stillThinkingText(error, text, providerLabel).replace(/\.$/, '');
|
|
383
|
+
return ms > 0 ? `No first response ${formatDurationMs(ms)}` : 'No first response';
|
|
384
|
+
}
|
|
385
|
+
if (reasonClass === 'stalled') return ms > 0 ? `No progress ${formatDurationMs(ms)}` : 'No progress';
|
|
386
|
+
return null;
|
|
378
387
|
}
|
|
379
388
|
|
|
380
389
|
/** The one retry status line every surface shows: `reason · retry n/max in 15s`. */
|
|
@@ -3,14 +3,6 @@ export function enforceOwnerOnlyAclWin32(targetPath: string, options?: { fresh?:
|
|
|
3
3
|
/** Test hook: the live per-process ACL helper, or null. */
|
|
4
4
|
export function ownerOnlyAclHelperForTests(): import('node:child_process').ChildProcess | null;
|
|
5
5
|
|
|
6
|
-
/** Test/diagnostic hook: helper attachment, pending requests, starts in the restart window. */
|
|
7
|
-
export function ownerOnlyAclHelperStats(): {
|
|
8
|
-
alive: boolean;
|
|
9
|
-
pid: number | null;
|
|
10
|
-
pending: number;
|
|
11
|
-
recentStarts: number;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
6
|
/** Non-fresh calls verify (and tighten) the real DACL on every call through a shared helper. */
|
|
15
7
|
export function enforceOwnerOnlyAclWin32Async(targetPath: string, options?: { fresh?: boolean }): Promise<void>;
|
|
16
8
|
|