mixdog 1.3.5 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +2 -2
- package/README.md +2 -2
- package/package.json +2 -11
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/gate-local.mjs +16 -5
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +37 -37
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +123 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -4
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +20 -2
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +7 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/app.mjs +4 -0
- package/src/defaults/shipped-history.json +22 -1
- package/src/defaults/skills/browser-use/SKILL.md +62 -12
- 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 +35 -9
- package/src/defaults/skills/setup/SKILL.md +22 -0
- package/src/defaults/skills/setup/references/actions.md +39 -5
- package/src/defaults/skills/setup/references/surfaces.md +11 -2
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/rules-builder.cjs +39 -20
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +11 -10
- package/src/rules/lead/LEAD.md +23 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/rules/shared/70-delivery.md +7 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- 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/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +17 -1
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
- package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- 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-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -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 +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
- 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/openai-ws-stream/event-switch.mjs +20 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
- 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 +38 -0
- 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/runtime-core/ask-user-tool-defs.mjs +49 -16
- 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 +7 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
- 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/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
- 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 +5 -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 +49 -21
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
- 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-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -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 +24 -14
- 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 +130 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
- 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-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- 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/transcript-restore/restore.mjs +79 -3
- 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/stall-policy.mjs +23 -0
- 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/invocation-plan.mjs +2 -2
- 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/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
- 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/scheduler.mjs +33 -147
- package/src/runtime/channels/lib/schedules-db.mjs +34 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/whisper-port.mjs +10 -1
- 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 +10 -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 +28 -2
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -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/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- 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/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- 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-owned-work.mjs +56 -0
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +2 -13
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +29 -0
- package/src/runtime/shared/connector-catalog.mjs +150 -0
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -17
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- 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/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- 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 +126 -0
- package/src/runtime/shared/llm/cost.mjs +5 -1
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -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 +7 -1
- 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 +10 -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 +48 -1
- package/src/runtime/shared/session-scratch.mjs +37 -0
- 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-card-model/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +2 -15
- package/src/runtime/shared/tool-surface.mjs +3 -0
- package/src/runtime/shared/tool-work-units.mjs +2 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +15 -0
- package/src/runtime/shared/worktrees/manager.mjs +87 -38
- package/src/runtime/shared/worktrees/test-support.mjs +14 -13
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +29 -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 +489 -185
- package/src/session-runtime/agent-task-sessions.mjs +467 -229
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/apis.mjs +9 -0
- 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 +11 -2
- package/src/session-runtime/bot-status.mjs +12 -6
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +271 -25
- package/src/session-runtime/conversation-import/service.mjs +26 -5
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- 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 +55 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +153 -33
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- 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 +2 -1
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -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/resource-recall-api.mjs +6 -1
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- 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 +7 -13
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/provider-admin.mjs +2 -1
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +1 -0
- 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 +13 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +145 -22
- package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workspace/transitions.mjs +25 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
- 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 +142 -190
- package/src/standalone/daemon.mjs +26 -3
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- 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 +30 -2
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-tool-output.mjs +15 -7
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/app/app-view/floating-panel.jsx +7 -4
- package/src/tui/app/model-options.mjs +3 -28
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +9 -5
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/dist/index.mjs +133 -92
- 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 +7 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- 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 +17 -1
- 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 +16 -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 +19 -2
- package/src/tui/session/turn.mjs +1 -0
- package/src/ui/statusline-agents.mjs +1 -3
- 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
|
@@ -100,7 +100,11 @@ export function priceUsage(args) {
|
|
|
100
100
|
// A provider-billed figure for a media request (e.g. xAI cost_in_usd_ticks)
|
|
101
101
|
// is the price, with or without a catalog row.
|
|
102
102
|
const media = args.media || null;
|
|
103
|
-
if (
|
|
103
|
+
if (
|
|
104
|
+
typeof media?.reportedCostUsd === 'number' &&
|
|
105
|
+
Number.isFinite(media.reportedCostUsd) &&
|
|
106
|
+
media.reportedCostUsd >= 0
|
|
107
|
+
)
|
|
104
108
|
return {
|
|
105
109
|
input,
|
|
106
110
|
costUsd: Number(media.reportedCostUsd.toFixed(6)),
|
|
@@ -22,7 +22,7 @@ export function usageRollupDayKey(ts) {
|
|
|
22
22
|
// background runners. An unknown source counts as conversation on purpose: a
|
|
23
23
|
// new runner showing up in the user's totals is visible and correctable, while
|
|
24
24
|
// silently dropping the user's own turns is neither.
|
|
25
|
-
const BACKGROUND_SOURCES = new Set(['memory-cycle', 'schedule', 'webhook', 'native-web-search']);
|
|
25
|
+
const BACKGROUND_SOURCES = new Set(['memory-cycle', 'schedule', 'webhook', 'native-web-search', 'cache-warm']);
|
|
26
26
|
|
|
27
27
|
export function isConversationUsageSource(sourceType) {
|
|
28
28
|
const id = typeof sourceType === 'string' ? sourceType.trim().toLowerCase() : '';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { FETCH_BLOCKED_PORTS, FETCH_SAFE_ATTEMPTS } from './fetch-safe-listen.mjs';
|
|
2
|
+
|
|
1
3
|
// One loopback listener owns each bind attempt, its event handlers, and stop.
|
|
2
4
|
export function createLoopbackListener({
|
|
3
5
|
server,
|
|
@@ -24,7 +26,15 @@ export function createLoopbackListener({
|
|
|
24
26
|
|
|
25
27
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
26
28
|
const controller = new AbortController();
|
|
27
|
-
const attempt = {
|
|
29
|
+
const attempt = {
|
|
30
|
+
promise,
|
|
31
|
+
reject,
|
|
32
|
+
controller,
|
|
33
|
+
port: basePort,
|
|
34
|
+
bound: false,
|
|
35
|
+
blockedRetries: FETCH_SAFE_ATTEMPTS,
|
|
36
|
+
detach,
|
|
37
|
+
};
|
|
28
38
|
current = attempt;
|
|
29
39
|
|
|
30
40
|
function detach() {
|
|
@@ -35,6 +45,19 @@ export function createLoopbackListener({
|
|
|
35
45
|
function onListening() {
|
|
36
46
|
if (current !== attempt) return;
|
|
37
47
|
const boundPort = server.address().port;
|
|
48
|
+
// An OS-assigned port can be one fetch clients refuse ("bad port"):
|
|
49
|
+
// close it and take another, a bounded number of times.
|
|
50
|
+
if (attempt.port === 0 && FETCH_BLOCKED_PORTS.has(boundPort)) {
|
|
51
|
+
const exhausted = attempt.blockedRetries <= 0;
|
|
52
|
+
attempt.blockedRetries -= 1;
|
|
53
|
+
server.close(() => {
|
|
54
|
+
if (current !== attempt) return;
|
|
55
|
+
if (exhausted) onError(new Error('no fetch-safe loopback port was assigned'));
|
|
56
|
+
else listen();
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
server.off('listening', onListening);
|
|
38
61
|
attempt.bound = true;
|
|
39
62
|
reportListening(boundPort);
|
|
40
63
|
resolve(boundPort);
|
|
@@ -67,7 +90,7 @@ export function createLoopbackListener({
|
|
|
67
90
|
}
|
|
68
91
|
|
|
69
92
|
server.on('error', onError);
|
|
70
|
-
server.
|
|
93
|
+
server.on('listening', onListening);
|
|
71
94
|
listen();
|
|
72
95
|
return promise;
|
|
73
96
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Whether the representative bot (Mixy) exists: the one rule. The desktop
|
|
2
|
+
// answers from it (getLeadStatus `exists`, main/mixy-first.ts), and so do
|
|
3
|
+
// Mixy's routines (routine-owner.mjs `no-mixy`), her heartbeat and the
|
|
4
|
+
// heartbeat reports queued for her chat (mixy-heartbeat.mjs,
|
|
5
|
+
// agent-home-delivery.mjs), all through routine-owner.mjs readMixyExists.
|
|
6
|
+
//
|
|
7
|
+
// `created: false` (Mixy's agent.json) is no. Otherwise she exists on
|
|
8
|
+
// evidence that the user made or uses her:
|
|
9
|
+
// - a name (the 대표 에이전트 dialog always sets one; her profile can);
|
|
10
|
+
// - a message the user wrote in her thread (`homeChatted`,
|
|
11
|
+
// agent-kind.mjs homeThreadEvidence);
|
|
12
|
+
// - a schedule or webhook she owns (`ownsRoutines`): the user set it up,
|
|
13
|
+
// and since v1.3.0 it ran for her whether or not she was named.
|
|
14
|
+
// Without any of them she does not exist: v1.3.0's untouched automatic
|
|
15
|
+
// `{"created": true}`, and an undecided profile (`created` null). Her own
|
|
16
|
+
// posts in her thread, heartbeat reports and routine results, are no
|
|
17
|
+
// evidence. `ownsRoutines` is read only when nothing else decides.
|
|
18
|
+
export async function mixyExists(status, ownsRoutines) {
|
|
19
|
+
if (status?.created === false) return false;
|
|
20
|
+
if (String(status?.name ?? '').trim() || status?.homeChatted === true) return true;
|
|
21
|
+
return (await ownsRoutines()) === true;
|
|
22
|
+
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export function canonicalRouteProvider(value: unknown): string;
|
|
2
2
|
export function routeChain(route: Record<string, unknown>): Record<string, unknown>[];
|
|
3
|
-
export function
|
|
3
|
+
export function executionFallbacks(route: Record<string, unknown> | null | undefined): Record<string, unknown>[];
|
|
4
|
+
export function validateRouteChainProviders(
|
|
5
|
+
routes: Record<string, unknown>[],
|
|
6
|
+
options?: { allowDuplicates?: boolean }
|
|
7
|
+
): void;
|
|
4
8
|
export function normalizeRouteChain(
|
|
5
9
|
route: Record<string, unknown>,
|
|
6
10
|
normalizeLeaf: (route: Record<string, unknown>, fallback: Record<string, unknown>) => Record<string, unknown> | null,
|
|
7
|
-
fallback?: Record<string, unknown
|
|
11
|
+
fallback?: Record<string, unknown>,
|
|
12
|
+
options?: { strict?: boolean }
|
|
8
13
|
): Record<string, unknown> | null;
|
|
@@ -22,18 +22,36 @@ export function routeChain(route) {
|
|
|
22
22
|
return [primary, ...fallbacks];
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
/** The fallbacks a chain runs: those on a provider not already used by the
|
|
26
|
+
* primary or an earlier fallback. The stored list is never changed; a fallback
|
|
27
|
+
* on the main model's own provider (left there by a later main-model change)
|
|
28
|
+
* is simply inactive. */
|
|
29
|
+
export function executionFallbacks(route) {
|
|
30
|
+
const [primary, ...fallbacks] = routeChain(route);
|
|
31
|
+
if (!primary) return [];
|
|
32
|
+
const seen = new Set([canonicalRouteProvider(primary.provider)]);
|
|
33
|
+
return fallbacks.filter((entry) => {
|
|
34
|
+
const provider = canonicalRouteProvider(entry.provider);
|
|
35
|
+
if (seen.has(provider)) return false;
|
|
36
|
+
seen.add(provider);
|
|
37
|
+
return true;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** `allowDuplicates` accepts a stored chain whose fallbacks repeat a provider
|
|
42
|
+
* (see executionFallbacks); an explicit save validates without it. */
|
|
43
|
+
export function validateRouteChainProviders(routes, { allowDuplicates = false } = {}) {
|
|
26
44
|
const providers = new Set();
|
|
27
45
|
for (const route of routes) {
|
|
28
46
|
const provider = canonicalRouteProvider(route.provider);
|
|
29
47
|
if (!provider || !String(route.model || '').trim()) throw new Error('route requires provider and model');
|
|
30
|
-
if (providers.has(provider)) throw new Error(`duplicate route provider "${provider}"`);
|
|
48
|
+
if (!allowDuplicates && providers.has(provider)) throw new Error(`duplicate route provider "${provider}"`);
|
|
31
49
|
if (providers.size && provider === 'default') throw new Error('follow Main is only allowed as the primary route');
|
|
32
50
|
providers.add(provider);
|
|
33
51
|
}
|
|
34
52
|
}
|
|
35
53
|
|
|
36
|
-
export function normalizeRouteChain(route, normalizeLeaf, fallback = {}) {
|
|
54
|
+
export function normalizeRouteChain(route, normalizeLeaf, fallback = {}, { strict = true } = {}) {
|
|
37
55
|
const raw = routeChain({ ...fallback, ...route });
|
|
38
56
|
const primary = normalizeLeaf(route, fallback);
|
|
39
57
|
if (!primary) return null;
|
|
@@ -42,7 +60,7 @@ export function normalizeRouteChain(route, normalizeLeaf, fallback = {}) {
|
|
|
42
60
|
if (!normalized) throw new Error('fallback route requires provider and model');
|
|
43
61
|
return { ...normalized, provider: canonicalRouteProvider(normalized.provider) };
|
|
44
62
|
});
|
|
45
|
-
validateRouteChainProviders(routes);
|
|
63
|
+
validateRouteChainProviders(routes, { allowDuplicates: !strict });
|
|
46
64
|
const [first, ...rest] = routes;
|
|
47
65
|
return rest.length ? { ...first, fallbacks: rest } : first;
|
|
48
66
|
}
|
|
@@ -2,6 +2,16 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
import { isWSL } from './wsl.mjs';
|
|
3
3
|
import { detachedSpawnOpts } from './spawn-flags.mjs';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Whether a browser can plausibly open on this machine: not inside an SSH
|
|
7
|
+
* session, and on non-WSL Linux a DISPLAY or WAYLAND_DISPLAY exists.
|
|
8
|
+
*/
|
|
9
|
+
export function canOpenBrowser(env = process.env, platform = process.platform, wsl = isWSL()) {
|
|
10
|
+
if (env.SSH_TTY || env.SSH_CONNECTION) return false;
|
|
11
|
+
if (platform !== 'linux' || wsl) return true;
|
|
12
|
+
return Boolean(env.DISPLAY || env.WAYLAND_DISPLAY);
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
/**
|
|
6
16
|
* Open a URL in the user's default browser. Best-effort and non-blocking.
|
|
7
17
|
* Callers also print the URL, so opener failure should never block OAuth.
|
|
@@ -1,21 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
import { createSharedAbortable } from './abort-race.mjs';
|
|
2
|
+
|
|
3
|
+
/** Lazy per-dataDir PG handle: one in-flight init, bootstrap lock, retry after
|
|
4
|
+
* failure. `signal` withdraws a caller; the init (a PG runtime install
|
|
5
|
+
* included) is cancelled once every caller has (createSharedAbortable). */
|
|
2
6
|
export function createPgSchemaDb({ schema, ddl, defaultDataDir, ensurePg, withLock }) {
|
|
3
7
|
const ready = new Map();
|
|
4
|
-
return
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
return function getDb(dataDir = defaultDataDir(), { signal = null } = {}) {
|
|
9
|
+
let shared = ready.get(dataDir);
|
|
10
|
+
if (!shared) {
|
|
11
|
+
const entry = createSharedAbortable(
|
|
12
|
+
async (initSignal) => {
|
|
13
|
+
const { db, pool } = await ensurePg(dataDir, { schema, signal: initSignal });
|
|
14
|
+
initSignal.throwIfAborted();
|
|
15
|
+
// Serialize CREATE TABLE across concurrent first-boot processes on the
|
|
16
|
+
// same cluster-global advisory lock the adapter uses for schema bootstrap.
|
|
17
|
+
await withLock(pool, () => db.exec(ddl));
|
|
18
|
+
return db;
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
// Let the next call retry after a transient failure or a cancellation.
|
|
22
|
+
onSettled: (failed) => {
|
|
23
|
+
if (failed && ready.get(dataDir) === entry) ready.delete(dataDir);
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
shared = entry;
|
|
28
|
+
ready.set(dataDir, entry);
|
|
19
29
|
}
|
|
30
|
+
return shared.join(signal);
|
|
20
31
|
};
|
|
21
32
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const PROFILE_LANGUAGES = Object.freeze([
|
|
6
6
|
{ id: 'system', label: 'System (locale)', prompt: null },
|
|
7
7
|
{ id: 'en', label: 'English', prompt: 'English' },
|
|
8
|
-
{ id: 'ko', label: '
|
|
8
|
+
{ id: 'ko', label: '한국어', prompt: 'Korean' },
|
|
9
9
|
{ id: 'ja', label: '日本語', prompt: 'Japanese (日本語)' },
|
|
10
10
|
{ id: 'zh-Hans', label: '中文(简体)', prompt: 'Simplified Chinese (简体中文)' },
|
|
11
11
|
{ id: 'zh-Hant', label: '中文(繁體)', prompt: 'Traditional Chinese (繁體中文)' },
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const PROMPT_ORIGIN_CHANNEL: 'channel';
|
|
2
|
+
export declare const PROMPT_ORIGIN_AGENT_REPORT: 'agent-report';
|
|
3
|
+
export type PromptOrigin = typeof PROMPT_ORIGIN_CHANNEL | typeof PROMPT_ORIGIN_AGENT_REPORT;
|
|
4
|
+
export declare function promptOriginOf(value: unknown): PromptOrigin | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// A submitted prompt's provenance, carried apart from its presentation mode
|
|
2
|
+
// (`origin` on the submit options, the queue entry, the turn input and the
|
|
3
|
+
// stored user message's meta). Dependency-free: the desktop main process
|
|
4
|
+
// stamps it too (agent-room-turn.ts).
|
|
5
|
+
|
|
6
|
+
/** Real external activity presented as a task notification: an inbound
|
|
7
|
+
* channel message (Discord, Telegram, webhook event rules …). */
|
|
8
|
+
export const PROMPT_ORIGIN_CHANNEL = 'channel';
|
|
9
|
+
|
|
10
|
+
/** A turn the runtime starts because another bot or agent reported back: a
|
|
11
|
+
* bot-home wake (daemon.mjs `wake`) or a group-room member's relay of its
|
|
12
|
+
* reported work (agent-room-turn.ts). System-caused, though presented as a
|
|
13
|
+
* prompt. */
|
|
14
|
+
export const PROMPT_ORIGIN_AGENT_REPORT = 'agent-report';
|
|
15
|
+
|
|
16
|
+
const KNOWN_ORIGINS = new Set([PROMPT_ORIGIN_CHANNEL, PROMPT_ORIGIN_AGENT_REPORT]);
|
|
17
|
+
|
|
18
|
+
/** `value` when it is a known provenance, else null. */
|
|
19
|
+
export function promptOriginOf(value) {
|
|
20
|
+
return KNOWN_ORIGINS.has(value) ? value : null;
|
|
21
|
+
}
|
|
@@ -15,7 +15,7 @@ export const ACCOUNT_PROVIDERS = Object.freeze([
|
|
|
15
15
|
'antigravity-oauth',
|
|
16
16
|
'opencode-go-oauth',
|
|
17
17
|
]);
|
|
18
|
-
const MAX_ACCOUNTS = 20;
|
|
18
|
+
export const MAX_ACCOUNTS = 20;
|
|
19
19
|
// `dataDir` defaults to this process's data dir; an isolated runtime passes
|
|
20
20
|
// the host's dir explicitly while its own MIXDOG_DATA_DIR points elsewhere.
|
|
21
21
|
const file = (dataDir = resolvePluginData()) => join(dataDir, 'provider-accounts.json');
|
|
@@ -597,6 +597,12 @@ export function providerAccountExhaustedForModelOnly(row, now = Date.now(), mode
|
|
|
597
597
|
// enough that yesterday's number cannot send every fallback to one account.
|
|
598
598
|
const USAGE_EVIDENCE_MAX_AGE_MS = 60 * 60_000;
|
|
599
599
|
|
|
600
|
+
/** Whether a usage reading taken at `checkedAt` may still steer a decision. */
|
|
601
|
+
export function quotaReadingFresh(checkedAt, now = Date.now()) {
|
|
602
|
+
const at = Number(checkedAt);
|
|
603
|
+
return at > 0 && now - at <= USAGE_EVIDENCE_MAX_AGE_MS;
|
|
604
|
+
}
|
|
605
|
+
|
|
600
606
|
// Remaining headroom across every window that applies to this model, or null
|
|
601
607
|
// when nothing recent measured the account. The fullest window decides: an
|
|
602
608
|
// account with 4% of its burst window left cannot serve now, however untouched
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Display names for provider ids; an unknown id displays as itself.
|
|
2
|
+
const PROVIDER_DISPLAY_NAMES = new Map([
|
|
3
|
+
['openai-oauth', 'OpenAI OAuth'],
|
|
4
|
+
['anthropic-oauth', 'Anthropic OAuth'],
|
|
5
|
+
['grok-oauth', 'Grok OAuth'],
|
|
6
|
+
['muse-code-oauth', 'Muse Code'],
|
|
7
|
+
['command-code-oauth', 'Command Code'],
|
|
8
|
+
['mimo-oauth', 'MiMo'],
|
|
9
|
+
['cursor-oauth', 'Cursor OAuth'],
|
|
10
|
+
['devin-oauth', 'Devin'],
|
|
11
|
+
['antigravity-oauth', 'Antigravity OAuth'],
|
|
12
|
+
['openai', 'OpenAI API'],
|
|
13
|
+
['openai-api', 'OpenAI API'],
|
|
14
|
+
['anthropic', 'Anthropic API'],
|
|
15
|
+
['anthropic-api', 'Anthropic API'],
|
|
16
|
+
['gemini', 'Gemini API'],
|
|
17
|
+
['gemini-api', 'Gemini API'],
|
|
18
|
+
['xai', 'xAI API'],
|
|
19
|
+
['xai-api', 'xAI API'],
|
|
20
|
+
['deepseek', 'DeepSeek API'],
|
|
21
|
+
['deepseek-api', 'DeepSeek API'],
|
|
22
|
+
['opencode-go-oauth', 'OpenCode Go OAuth'],
|
|
23
|
+
['openrouter', 'OpenRouter'],
|
|
24
|
+
['mixdog-local', 'Local Provider'],
|
|
25
|
+
['default', 'Default'],
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
export const providerDisplayName = (provider) =>
|
|
29
|
+
PROVIDER_DISPLAY_NAMES.get(String(provider || '').toLowerCase()) ?? (provider || 'Provider');
|
|
@@ -8,6 +8,8 @@ export const TIMEOUT_PHASE = Object.freeze({
|
|
|
8
8
|
FIRST_CHUNK: 'first-chunk',
|
|
9
9
|
// A stream that already produced output went silent.
|
|
10
10
|
IDLE: 'idle',
|
|
11
|
+
// A sign-in token refresh did not answer: an auth problem, not a slow model.
|
|
12
|
+
AUTH: 'auth',
|
|
11
13
|
});
|
|
12
14
|
|
|
13
15
|
/** A timeout before the model produced anything: headers or first chunk. */
|
|
@@ -4,6 +4,8 @@ export interface RoutineTrigger {
|
|
|
4
4
|
event?: string;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
export declare const ROUTINE_QUIET: 'ROUTINE_QUIET';
|
|
8
|
+
export declare function isRoutineQuietReply(text: unknown): boolean;
|
|
7
9
|
export declare function routineTriggerHeader(input: {
|
|
8
10
|
kind: string;
|
|
9
11
|
name: string;
|
|
@@ -9,6 +9,15 @@ import { localTimestampParts } from './time-format.mjs';
|
|
|
9
9
|
const HEADER_PREFIX = '[Routine trigger]';
|
|
10
10
|
const KINDS = new Set(['schedule', 'webhook']);
|
|
11
11
|
|
|
12
|
+
/** The whole reply of a routine turn with nothing new to tell: kept in the
|
|
13
|
+
* record, never painted, previewed, counted unread or notified. */
|
|
14
|
+
export const ROUTINE_QUIET = 'ROUTINE_QUIET';
|
|
15
|
+
|
|
16
|
+
/** Whether a reply is exactly the routine quiet sentinel. */
|
|
17
|
+
export function isRoutineQuietReply(text) {
|
|
18
|
+
return String(text ?? '').trim() === ROUTINE_QUIET;
|
|
19
|
+
}
|
|
20
|
+
|
|
12
21
|
/** The first line of a routine turn's prompt: which routine fired, when (local
|
|
13
22
|
* time and zone: the turn gets no other date), and how to treat the turn.
|
|
14
23
|
* It is the routine's only conduct text. Only the turn's content carries it,
|
|
@@ -24,6 +33,7 @@ export function routineTriggerHeader({ kind, name, project = '', now = new Date(
|
|
|
24
33
|
'Payments and permanent deletes are refused here: report that and suggest doing it from the chat.',
|
|
25
34
|
'If a sign-in, code or CAPTCHA blocks you, stop and say which site needs the user.',
|
|
26
35
|
'Reply in this chat in plain words, without tool names; if you handed work off, say it started — its result arrives here later.',
|
|
36
|
+
`Tell what is new in a fitting tone; if nothing is worth telling, reply with exactly ${ROUTINE_QUIET}.`,
|
|
27
37
|
...(project ? [`Project folder: ${project}`] : []),
|
|
28
38
|
].join(' ');
|
|
29
39
|
}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
export interface SensitiveScope {
|
|
2
|
+
/** A Mixdog home or data folder, as path segments; only its secret subset is denied. */
|
|
2
3
|
root: string[];
|
|
3
|
-
/** Subfolders of the root that stay reachable. */
|
|
4
|
-
except: readonly string[];
|
|
5
|
-
/** Whole tree (a registered private root) or Mixdog's secret subset. */
|
|
6
|
-
whole: boolean;
|
|
7
4
|
}
|
|
8
|
-
export function
|
|
9
|
-
export function matchesSensitivePath(
|
|
10
|
-
path: string,
|
|
11
|
-
within?: readonly SensitiveScope[],
|
|
12
|
-
options?: { envTemplates?: boolean }
|
|
13
|
-
): boolean;
|
|
5
|
+
export function matchesSensitivePath(path: string, within?: readonly SensitiveScope[]): boolean;
|
|
14
6
|
export function mixdogSensitiveScopes(extraData?: readonly string[]): SensitiveScope[];
|
|
15
7
|
export function isSensitiveLocalPath(path: string, options?: { extraData?: readonly string[] }): boolean;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
// The credential / secret file deny list
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// between bots and agents (session-runtime/handoff-attachments.mjs).
|
|
1
|
+
// The credential / secret file deny list of the runtime's attachment
|
|
2
|
+
// hand-offs between bots and agents (session-runtime/handoff-attachments.mjs):
|
|
3
|
+
// an automatic transfer never carries a secret-bearing file. A paired device
|
|
4
|
+
// is the user's own and gets no such list (it opens what the desktop opens).
|
|
6
5
|
//
|
|
7
6
|
// Matching is on SEGMENTS of a path, lower-cased on every platform, so a
|
|
8
7
|
// denied name cannot hide behind letter case, trailing dots/spaces or an NTFS
|
|
@@ -113,10 +112,6 @@ const CREDENTIAL_FILES = new Set([
|
|
|
113
112
|
* checked in often enough with real values that no name is exempt) and
|
|
114
113
|
* `<stage>.env`. */
|
|
115
114
|
const ENV_FILE = /^(?:\.env.*|[^.]{1,64}(?:\.[^.]{1,64}){0,3}\.env)$/;
|
|
116
|
-
/** The dotenv templates a person may still open on purpose from a paired
|
|
117
|
-
* device (the desktop's remote file lanes, `envTemplates: true`); automatic
|
|
118
|
-
* transfers between bots and agents never get this allowance. */
|
|
119
|
-
const ENV_TEMPLATES = new Set(['.env.example', '.env.sample', '.env.template', '.env.dist']);
|
|
120
115
|
/** Credential JSON a cloud or OAuth client writes or downloads:
|
|
121
116
|
* `credentials.json`, `*credentials*.json`, `service-account*.json`,
|
|
122
117
|
* `client_secret*.json`. */
|
|
@@ -143,10 +138,9 @@ function backupOriginal(name) {
|
|
|
143
138
|
|
|
144
139
|
/** A file whose own name says it holds a secret, wherever it lives: a
|
|
145
140
|
* credential file, a dotenv file, a key or keystore, or a backup of one. */
|
|
146
|
-
function secretFileName(name
|
|
141
|
+
function secretFileName(name) {
|
|
147
142
|
const original = backupOriginal(name);
|
|
148
|
-
if (CREDENTIAL_FILES.has(original) || CREDENTIAL_JSON.test(original)) return true;
|
|
149
|
-
if (ENV_FILE.test(original)) return !(envTemplates && ENV_TEMPLATES.has(original));
|
|
143
|
+
if (CREDENTIAL_FILES.has(original) || CREDENTIAL_JSON.test(original) || ENV_FILE.test(original)) return true;
|
|
150
144
|
const dot = original.lastIndexOf('.');
|
|
151
145
|
if (dot >= 0 && KEY_EXTENSIONS.has(original.slice(dot))) return true;
|
|
152
146
|
return SSH_PRIVATE_KEY.test(original);
|
|
@@ -156,14 +150,7 @@ function secretFileName(name, { envTemplates = false } = {}) {
|
|
|
156
150
|
// (tool results, shell output, media), which stay reachable; only the files
|
|
157
151
|
// and folders that carry provider tokens, API keys, pairing and bridge secrets
|
|
158
152
|
// are denied.
|
|
159
|
-
const MIXDOG_SECRET_DIRECTORIES = new Set([
|
|
160
|
-
'secrets',
|
|
161
|
-
'mcp-oauth',
|
|
162
|
-
'provider-accounts',
|
|
163
|
-
'telegram',
|
|
164
|
-
'relay-data',
|
|
165
|
-
'dev-profile',
|
|
166
|
-
]);
|
|
153
|
+
const MIXDOG_SECRET_DIRECTORIES = new Set(['secrets', 'mcp-oauth', 'provider-accounts', 'relay-data', 'dev-profile']);
|
|
167
154
|
const MIXDOG_SECRET_FILE =
|
|
168
155
|
/^\.?(mixdog-config|provider-accounts|relay-hook-device|auth\.json|[a-z0-9-]+-oauth(-credentials)?\.json|[a-z0-9-]+-bridge\.json)/;
|
|
169
156
|
const MIXDOG_SECRET_EXTENSIONS = new Set(['.dpapi', '.token']);
|
|
@@ -177,7 +164,7 @@ function mixdogSecret(rest) {
|
|
|
177
164
|
|
|
178
165
|
/** The segments of a path as the rules compare them: no extended-path prefix,
|
|
179
166
|
* no NTFS stream suffix, no trailing dots or spaces, lower case. */
|
|
180
|
-
|
|
167
|
+
function sensitivePathSegments(path) {
|
|
181
168
|
return String(path)
|
|
182
169
|
.replace(/^[\\/]{2}[?.][\\/]/, '')
|
|
183
170
|
.split(/[\\/]+/)
|
|
@@ -198,30 +185,21 @@ function hasRun(segments, run) {
|
|
|
198
185
|
}
|
|
199
186
|
|
|
200
187
|
/**
|
|
201
|
-
* Whether `path` is denied under `within`: scopes `{ root: segments
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* true`, everything but `except`). Pass both the lexical and canonical form.
|
|
205
|
-
* `envTemplates`: a user-initiated remote open may read the dotenv
|
|
206
|
-
* templates; nothing else gets that allowance.
|
|
188
|
+
* Whether `path` is denied under `within`: scopes `{ root: segments }` —
|
|
189
|
+
* Mixdog's home and data folders, where only their secret subset is denied.
|
|
190
|
+
* Pass both the lexical and canonical form.
|
|
207
191
|
*/
|
|
208
|
-
export function matchesSensitivePath(path, within = []
|
|
192
|
+
export function matchesSensitivePath(path, within = []) {
|
|
209
193
|
const segments = sensitivePathSegments(resolve(path));
|
|
210
194
|
const name = segments[segments.length - 1] ?? '';
|
|
211
195
|
if (segments.some((segment) => SECRET_DIRECTORIES.has(segment))) return true;
|
|
212
|
-
if (secretFileName(name
|
|
213
|
-
|
|
214
|
-
({ root }) =>
|
|
196
|
+
if (secretFileName(name) || SECRET_SEQUENCES.some((run) => hasRun(segments, run))) return true;
|
|
197
|
+
return within.some(
|
|
198
|
+
({ root }) =>
|
|
199
|
+
root.length > 0 &&
|
|
200
|
+
root.every((segment, index) => segments[index] === segment) &&
|
|
201
|
+
mixdogSecret(segments.slice(root.length))
|
|
215
202
|
);
|
|
216
|
-
// Mixdog's home and data folders follow Mixdog's own rule even inside a
|
|
217
|
-
// registered private root: a dev or isolated profile keeps them in the app
|
|
218
|
-
// profile, and the tool output and media there stay reachable.
|
|
219
|
-
const own = containing.filter(({ whole }) => !whole);
|
|
220
|
-
if (own.length) return own.some(({ root }) => mixdogSecret(segments.slice(root.length)));
|
|
221
|
-
return containing.some(({ root, except }) => {
|
|
222
|
-
const rest = segments.slice(root.length);
|
|
223
|
-
return rest.length > 0 && !except.includes(rest[0]);
|
|
224
|
-
});
|
|
225
203
|
}
|
|
226
204
|
|
|
227
205
|
function realOrSelf(path) {
|
|
@@ -241,7 +219,7 @@ export function mixdogSensitiveScopes(extraData = []) {
|
|
|
241
219
|
const scopes = [];
|
|
242
220
|
for (const root of roots) {
|
|
243
221
|
for (const form of new Set([resolve(root), realOrSelf(resolve(root))])) {
|
|
244
|
-
scopes.push({ root: sensitivePathSegments(form)
|
|
222
|
+
scopes.push({ root: sensitivePathSegments(form) });
|
|
245
223
|
}
|
|
246
224
|
}
|
|
247
225
|
return scopes;
|
|
@@ -13,7 +13,54 @@ export function onSessionActivityChange(listener) {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function emitSessionActivityChange(sessionId = '') {
|
|
16
|
-
|
|
16
|
+
emit(listeners, sessionId);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// A turn started on a session: the one point every turn passes through, whoever
|
|
20
|
+
// started it. Unlike the activity pulse it never fires on a settle or a wait.
|
|
21
|
+
const turnStartListeners = new Set();
|
|
22
|
+
|
|
23
|
+
export function onSessionTurnStart(listener) {
|
|
24
|
+
if (typeof listener !== 'function') return () => {};
|
|
25
|
+
turnStartListeners.add(listener);
|
|
26
|
+
return () => turnStartListeners.delete(listener);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function emitSessionTurnStart(sessionId = '') {
|
|
30
|
+
emit(turnStartListeners, sessionId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// A live session started or stopped showing an approval card waiting on the
|
|
34
|
+
// user (its runtime state's `toolApproval`): the session catalog, which
|
|
35
|
+
// stamps that on each row, listens and re-reads.
|
|
36
|
+
const approvalCardListeners = new Set();
|
|
37
|
+
|
|
38
|
+
export function onSessionApprovalCardChange(listener) {
|
|
39
|
+
if (typeof listener !== 'function') return () => {};
|
|
40
|
+
approvalCardListeners.add(listener);
|
|
41
|
+
return () => approvalCardListeners.delete(listener);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function emitSessionApprovalCardChange(sessionId = '') {
|
|
45
|
+
emit(approvalCardListeners, sessionId);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// The bots whose sends are in flight in a session changed (bot-owned-work.mjs):
|
|
49
|
+
// the session catalog stamps them on each row (`handedBy`) and re-reads.
|
|
50
|
+
const botWorkListeners = new Set();
|
|
51
|
+
|
|
52
|
+
export function onSessionBotWorkChange(listener) {
|
|
53
|
+
if (typeof listener !== 'function') return () => {};
|
|
54
|
+
botWorkListeners.add(listener);
|
|
55
|
+
return () => botWorkListeners.delete(listener);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function emitSessionBotWorkChange(sessionId = '') {
|
|
59
|
+
emit(botWorkListeners, sessionId);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function emit(targets, sessionId) {
|
|
63
|
+
for (const listener of [...targets]) {
|
|
17
64
|
try {
|
|
18
65
|
listener(String(sessionId || ''));
|
|
19
66
|
} catch {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Per-session scratch directory under Mixdog's data directory. Processes the
|
|
2
|
+
// `shell` tool starts see it as TEMP/TMP/TMPDIR, so scratch files never land in
|
|
3
|
+
// the project, and it is removed with its session (session-delete.mjs).
|
|
4
|
+
import { mkdirSync, rmSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { resolvePluginData } from './plugin-paths.mjs';
|
|
7
|
+
|
|
8
|
+
const SESSION_ID = /^[A-Za-z0-9_-]+$/;
|
|
9
|
+
|
|
10
|
+
/** The session's scratch path (not created), or '' for an unusable id. */
|
|
11
|
+
export function sessionScratchDir(sessionId) {
|
|
12
|
+
const id = typeof sessionId === 'string' ? sessionId : '';
|
|
13
|
+
return SESSION_ID.test(id) ? join(resolvePluginData(), 'scratch', id) : '';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Create the session's scratch directory if absent; returns its path ('' without a session id). */
|
|
17
|
+
export function ensureSessionScratchDir(sessionId) {
|
|
18
|
+
const dir = sessionScratchDir(sessionId);
|
|
19
|
+
if (dir) mkdirSync(dir, { recursive: true });
|
|
20
|
+
return dir;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function removeSessionScratchDir(sessionId) {
|
|
24
|
+
const dir = sessionScratchDir(sessionId);
|
|
25
|
+
if (dir) rmSync(dir, { recursive: true, force: true });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Point an env's temp variables at the session's scratch directory. */
|
|
29
|
+
export function applySessionScratchEnv(env, sessionId) {
|
|
30
|
+
const dir = ensureSessionScratchDir(sessionId);
|
|
31
|
+
if (dir) {
|
|
32
|
+
env.TEMP = dir;
|
|
33
|
+
env.TMP = dir;
|
|
34
|
+
env.TMPDIR = dir;
|
|
35
|
+
}
|
|
36
|
+
return env;
|
|
37
|
+
}
|
|
@@ -4,7 +4,7 @@ export type SessionSidebarChange =
|
|
|
4
4
|
| { archived: true; cascade: false }
|
|
5
5
|
| { forgotten: true };
|
|
6
6
|
export type SessionSidebarHost = (sessionId: unknown, change: unknown) => unknown;
|
|
7
|
-
export type SessionSidebarState = { archived: Record<string, number> };
|
|
7
|
+
export type SessionSidebarState = { archived: Record<string, number>; favorites?: Record<string, number> };
|
|
8
8
|
export function registerSessionSidebarHost(
|
|
9
9
|
host: SessionSidebarHost,
|
|
10
10
|
options?: { state?: (() => SessionSidebarState | Promise<SessionSidebarState>) | null }
|
|
@@ -41,11 +41,15 @@ export async function applySessionSidebarChange(sessionId, change) {
|
|
|
41
41
|
await active.host(sessionId, change);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
/** The active desktop's flags, `{ archived }` (session id →
|
|
45
|
-
*
|
|
44
|
+
/** The active desktop's flags, `{ archived, favorites? }` (session id →
|
|
45
|
+
* epoch-ms stamp; `favorites` only from a desktop that reports them); null
|
|
46
|
+
* when no desktop (or one without a state reader) is attached. */
|
|
46
47
|
export async function readSessionSidebarState() {
|
|
47
48
|
const active = hosts().at(-1);
|
|
48
49
|
if (!active?.state) return null;
|
|
49
50
|
const state = await active.state();
|
|
50
|
-
return {
|
|
51
|
+
return {
|
|
52
|
+
archived: { ...state?.archived },
|
|
53
|
+
...(state?.favorites && typeof state.favorites === 'object' ? { favorites: { ...state.favorites } } : {}),
|
|
54
|
+
};
|
|
51
55
|
}
|