mixdog 1.2.5 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSES/simple-icons-CC0-1.0.txt +30 -0
- package/NOTICE.md +19 -0
- package/package.json +4 -1
- package/scripts/check-model-recommendations.mjs +89 -0
- package/scripts/gate-local.mjs +7 -0
- package/scripts/lib/gate-scheduler.mjs +2 -2
- package/scripts/lib/isolated-test-env.mjs +16 -0
- package/scripts/lib/run-node-tests.mjs +5 -14
- package/scripts/provider-pingpong-live.mjs +9 -9
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +5 -4
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +17 -0
- package/src/defaults/skills/browser-use/SKILL.md +7 -1
- package/src/defaults/skills/computer-use/SKILL.md +3 -1
- package/src/defaults/skills/memory-management/SKILL.md +4 -1
- package/src/defaults/skills/setup/references/actions.md +11 -4
- package/src/defaults/skills/setup-guide/SKILL.md +175 -0
- package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
- package/src/defaults/skills/visualize/SKILL.md +3 -2
- package/src/lib/rules-builder.cjs +56 -7
- package/src/output-styles/common.md +22 -6
- package/src/output-styles/detailed.md +7 -5
- package/src/output-styles/minimal.md +7 -3
- package/src/output-styles/simple.md +2 -3
- package/src/rules/agent/AGENT.md +7 -1
- package/src/rules/agent-mode/AGENT_MODE.md +24 -0
- package/src/rules/agent-mode/MIXY.md +21 -0
- package/src/rules/agent-mode/ROUTINE.md +6 -0
- package/src/rules/lead/LEAD.md +9 -4
- package/src/rules/shared/10-tool-workflow.md +2 -1
- package/src/rules/shared/60-verification.md +4 -5
- package/src/rules/shared/70-delivery.md +3 -0
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
- package/src/runtime/agent/orchestrator/config.mjs +6 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +182 -13
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +5 -3
- package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +215 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +58 -64
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
- package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +41 -19
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +11 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
- package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
- package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +98 -4
- package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +15 -8
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +50 -20
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
- package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +162 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +641 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +165 -0
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
- package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +82 -33
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +11 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -5
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +55 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
- package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +70 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +277 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
- package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
- package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +325 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +84 -21
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +44 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
- package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +123 -32
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
- package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
- package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +64 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +10 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +104 -55
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/office-extract.mjs +11 -9
- package/src/runtime/browser-bridge/client.mjs +24 -0
- package/src/runtime/channels/lib/scheduler.mjs +40 -12
- package/src/runtime/channels/lib/schedules-db.mjs +71 -12
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
- package/src/runtime/channels/lib/webhook.mjs +0 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
- package/src/runtime/channels/lib/worker-main.mjs +17 -20
- package/src/runtime/computer-bridge/client.mjs +28 -1
- package/src/runtime/connectors/gmail-app-password.mjs +690 -0
- package/src/runtime/connectors/google-mcp.mjs +446 -0
- package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
- package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
- package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
- package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
- package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
- package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
- package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
- package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
- package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
- package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
- package/src/runtime/memory/lib/memory.mjs +7 -1
- package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
- package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
- package/src/runtime/memory/lib/tool-call-handler.mjs +9 -5
- package/src/runtime/memory/tool-defs.mjs +5 -0
- package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
- package/src/runtime/office/core/tabular.mjs +1 -1
- package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
- package/src/runtime/office/portable/docx-formatting.mjs +1 -1
- package/src/runtime/office/portable/docx-runs.mjs +1 -1
- package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
- package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
- package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
- package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
- package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
- package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
- package/src/runtime/office/portable/portable-opc.mjs +27 -13
- package/src/runtime/office/portable/portable-pivot.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
- package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
- package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
- package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
- package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
- package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
- package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
- package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
- package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
- package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
- package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
- package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
- package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
- package/src/runtime/office/portable/portable-xml.mjs +1 -1
- package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
- package/src/runtime/shared/agent-avatar.d.mts +64 -0
- package/src/runtime/shared/agent-avatar.mjs +320 -0
- package/src/runtime/shared/agent-route-config.d.mts +3 -0
- package/src/runtime/shared/agent-route-config.mjs +16 -0
- package/src/runtime/shared/atomic-file.mjs +36 -14
- package/src/runtime/shared/background-tasks.mjs +60 -20
- package/src/runtime/shared/child-spawn-gate.mjs +26 -16
- package/src/runtime/shared/config.mjs +8 -11
- package/src/runtime/shared/connector-accounts.mjs +15 -0
- package/src/runtime/shared/connector-catalog.d.mts +52 -0
- package/src/runtime/shared/connector-catalog.mjs +230 -0
- package/src/runtime/shared/connector-triggers.d.mts +3 -0
- package/src/runtime/shared/connector-triggers.mjs +43 -0
- package/src/runtime/shared/file-lock.mjs +7 -1
- package/src/runtime/shared/file-permissions-worker.mjs +38 -0
- package/src/runtime/shared/file-permissions.d.mts +19 -4
- package/src/runtime/shared/file-permissions.mjs +310 -4
- package/src/runtime/shared/git-runner-worker.mjs +6 -78
- package/src/runtime/shared/google-oauth-client.mjs +24 -0
- package/src/runtime/shared/held-request-host.d.mts +12 -0
- package/src/runtime/shared/held-request-host.mjs +71 -0
- package/src/runtime/shared/llm/http-agent.mjs +7 -3
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
- package/src/runtime/shared/memory-snapshot.mjs +5 -1
- package/src/runtime/shared/notify-trace.mjs +8 -1
- package/src/runtime/shared/plain-preview.d.mts +1 -0
- package/src/runtime/shared/plain-preview.mjs +28 -0
- package/src/runtime/shared/pristine-execution-contract.json +5 -1
- package/src/runtime/shared/process-runner-worker.mjs +7 -0
- package/src/runtime/shared/process-runner.mjs +38 -0
- package/src/runtime/shared/provider-accounts.mjs +2 -1
- package/src/runtime/shared/provider-api-key.mjs +0 -1
- package/src/runtime/shared/read-row-numbers.mjs +1 -1
- package/src/runtime/shared/resource-admission.mjs +60 -18
- package/src/runtime/shared/routine-limits.d.mts +11 -0
- package/src/runtime/shared/routine-limits.mjs +21 -0
- package/src/runtime/shared/routine-trigger.d.mts +10 -0
- package/src/runtime/shared/routine-trigger.mjs +44 -0
- package/src/runtime/shared/run-child.mjs +84 -0
- package/src/runtime/shared/schedule-model-ref.mjs +9 -10
- package/src/runtime/shared/session-activity-signal.mjs +23 -0
- package/src/runtime/shared/shell-output-summary.mjs +23 -0
- package/src/runtime/shared/singleton-owner.mjs +126 -42
- package/src/runtime/shared/slow-span.mjs +4 -12
- package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
- package/src/runtime/shared/tool-output-limit.mjs +4 -2
- package/src/runtime/shared/tool-output-marker.mjs +58 -0
- package/src/runtime/shared/transcript-metadata.mjs +10 -0
- package/src/runtime/shared/turn-changes.mjs +0 -8
- package/src/runtime/shared/usage-readout-totals.mjs +56 -0
- package/src/runtime/shared/user-data-guard.mjs +131 -34
- package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
- package/src/runtime/shared/worktrees/git-head.mjs +20 -2
- package/src/runtime/shared/worktrees/lock.mjs +3 -2
- package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
- package/src/runtime/tidy/runners/biome.mjs +3 -1
- package/src/runtime/tidy/shadow.mjs +2 -1
- package/src/runtime/web-search/index.mjs +5 -7
- package/src/runtime/web-search/lib/formatter.mjs +42 -6
- package/src/runtime/web-search/tool-defs.mjs +6 -1
- package/src/session-runtime/agent-home-delivery.mjs +459 -0
- package/src/session-runtime/agent-profile-changes.mjs +21 -0
- package/src/session-runtime/agent-room-delivery.mjs +92 -0
- package/src/session-runtime/agent-task-sessions.mjs +200 -0
- package/src/session-runtime/boot/apis.mjs +50 -18
- package/src/session-runtime/boot/facade.mjs +5 -8
- package/src/session-runtime/boot/infrastructure.mjs +28 -17
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/channel-config-api.mjs +53 -5
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
- package/src/session-runtime/held-requests.mjs +228 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +11 -4
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
- package/src/session-runtime/lifecycle/shared.mjs +25 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +5 -2
- package/src/session-runtime/lifecycle-api.mjs +3 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
- package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +112 -15
- package/src/session-runtime/model-route/set-route.mjs +14 -3
- package/src/session-runtime/owned-automation-run.mjs +229 -0
- package/src/session-runtime/provider-auth/login.mjs +10 -6
- package/src/session-runtime/provider-auth/setup.mjs +19 -2
- package/src/session-runtime/provider-catalog-cache.mjs +101 -25
- package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
- package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
- package/src/session-runtime/provider-models.mjs +76 -10
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/resource-api.mjs +5 -0
- package/src/session-runtime/resource-mcp-api.mjs +107 -13
- package/src/session-runtime/resource-skills-api.mjs +12 -0
- package/src/session-runtime/room-member-gate.mjs +48 -0
- package/src/session-runtime/routine-home-turn.mjs +156 -0
- package/src/session-runtime/routine-owner.mjs +48 -0
- package/src/session-runtime/schedule-session-run.mjs +30 -64
- package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +10 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
- package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
- package/src/session-runtime/services/agent-tool.mjs +20 -0
- package/src/session-runtime/services/channel-admin.mjs +93 -24
- package/src/session-runtime/services/memory-access.mjs +37 -0
- package/src/session-runtime/services/provider-admin.mjs +166 -59
- package/src/session-runtime/services/schedule-access.mjs +91 -0
- package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
- package/src/session-runtime/services/usage-dashboard.mjs +27 -69
- package/src/session-runtime/session-create/session-options.mjs +34 -7
- package/src/session-runtime/session-hooks.mjs +16 -8
- package/src/session-runtime/setup-tool/executor.mjs +68 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +72 -14
- package/src/session-runtime/setup-tool/settings-contract.mjs +8 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/skills-api.mjs +16 -1
- package/src/session-runtime/tool-policy-refresh.mjs +238 -29
- package/src/session-runtime/turn/session-ops.mjs +10 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +11 -2
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +3 -0
- package/src/session-runtime/usage-stats-api.mjs +6 -1
- package/src/session-runtime/webhook-session-run.mjs +49 -67
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +556 -22
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
- package/src/session-runtime/workflow-agents-api.mjs +4 -1
- package/src/standalone/channel-transport/http-routes.mjs +10 -9
- package/src/standalone/daemon-agent-control.mjs +1 -8
- package/src/standalone/daemon-desktop-runtime.mjs +20 -7
- package/src/standalone/daemon-owner.mjs +117 -25
- package/src/standalone/daemon-session-control.mjs +11 -2
- package/src/standalone/daemon.mjs +61 -17
- package/src/standalone/session-call-cache.mjs +6 -0
- package/src/standalone/session-protocol.mjs +28 -1
- package/src/standalone/session-service/retention/busy.mjs +7 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +9 -0
- package/src/standalone/session-service.mjs +19 -0
- package/src/standalone/session-transport/routes.mjs +7 -6
- package/src/tui/app/model-options.mjs +39 -2
- package/src/tui/app/model-picker.mjs +16 -2
- package/src/tui/app/provider-setup-picker.mjs +1 -2
- package/src/tui/app/slash-commands.mjs +20 -0
- package/src/tui/dist/index.mjs +487 -128
- package/src/tui/session/context-state.mjs +6 -1
- package/src/tui/session/notice-surface.mjs +35 -4
- package/src/tui/session/notice-text.mjs +0 -1
- package/src/tui/session/queue-helpers.mjs +2 -1
- package/src/tui/session/session-api/extensions.mjs +4 -0
- package/src/tui/session/session-api/intake/submission.mjs +12 -13
- package/src/tui/session/session-api/integrations.mjs +9 -5
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
- package/src/tui/session/session-api/lifecycle.mjs +17 -1
- package/src/tui/session/session-api/routes.mjs +48 -3
- package/src/tui/session/session-flow/drain.mjs +20 -3
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
- package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
- package/src/tui/session/session-flow/steering.mjs +104 -24
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/tool-approval.mjs +26 -5
- package/src/tui/session/transcript-intake.mjs +6 -2
- package/src/tui/session/transcript-spill.mjs +5 -1
- package/src/tui/session/tui-steering-persist.mjs +65 -42
- package/src/tui/session/turn-live-call.mjs +56 -0
- package/src/tui/session/turn-stream.mjs +33 -0
- package/src/tui/session/turn.mjs +50 -7
- package/src/ui/statusline.mjs +1 -6
- package/src/ui/streaming-markdown-heal.mjs +24 -7
- package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
- package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
- package/src/workflows/default/WORKFLOW.md +9 -13
- package/src/session-runtime/automation-agents.mjs +0 -94
- package/src/session-runtime/automation-workflow.mjs +0 -59
|
@@ -48,11 +48,21 @@ export function createWorkflowPacksApi(deps) {
|
|
|
48
48
|
}));
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
// `{ scope: 'session' }` (the composer's selector in a session): a session
|
|
52
|
+
// with a conversation switches alone from its next turn
|
|
53
|
+
// (switchSessionWorkflow) and the configured workflow — the default for new
|
|
54
|
+
// sessions — stays as it is. Without a conversation, and without the
|
|
55
|
+
// scope, the choice becomes the configured workflow and an empty session
|
|
56
|
+
// picks it up in place, as before.
|
|
57
|
+
async function setWorkflow(workflowId, options = {}) {
|
|
52
58
|
const requested = normalizeWorkflowId(workflowId, DEFAULT_WORKFLOW_ID);
|
|
53
59
|
const id = requested === 'solo' ? DEFAULT_WORKFLOW_ID : requested;
|
|
54
60
|
const pack = loadWorkflowPack(resolveDataDir(deps), id);
|
|
55
61
|
if (!pack || pack.id !== id) throw new Error(`workflow "${workflowId}" not found`);
|
|
62
|
+
if (options?.scope === 'session') {
|
|
63
|
+
const switched = await deps.switchSessionWorkflow?.(id);
|
|
64
|
+
if (switched) return { ...switched.workflow, ...switched };
|
|
65
|
+
}
|
|
56
66
|
saveActiveWorkflow(id);
|
|
57
67
|
const applied = await deps.refreshEmptySessionToolPolicy?.();
|
|
58
68
|
deps.invalidatePreSessionToolSurface?.();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createOnboardingApi } from './workflow-agents-api/onboarding.mjs';
|
|
2
2
|
import { createAgentEditorApi } from './workflow-agents-api/agent-editor.mjs';
|
|
3
|
+
import { createAgentConnectorsApi } from './workflow-agents-api/agent-connectors.mjs';
|
|
3
4
|
import { createAgentRouteApi } from './workflow-agents-api/agent-route.mjs';
|
|
4
5
|
import { createWorkflowPacksApi } from './workflow-agents-api/workflow-packs.mjs';
|
|
5
6
|
import { createStyleAndModeApi } from './workflow-agents-api/style-and-mode.mjs';
|
|
@@ -11,9 +12,11 @@ import { createStyleAndModeApi } from './workflow-agents-api/style-and-mode.mjs'
|
|
|
11
12
|
// getOnboardingStatus from the composed runtime API through `this`.
|
|
12
13
|
export function createWorkflowAgentsApi(deps) {
|
|
13
14
|
const routeApi = createAgentRouteApi(deps);
|
|
15
|
+
const editorApi = createAgentEditorApi({ ...deps, setAgentRoute: routeApi.setAgentRoute });
|
|
14
16
|
return {
|
|
15
17
|
...createOnboardingApi(deps),
|
|
16
|
-
...
|
|
18
|
+
...editorApi,
|
|
19
|
+
...createAgentConnectorsApi(deps, editorApi),
|
|
17
20
|
...routeApi,
|
|
18
21
|
...createWorkflowPacksApi(deps),
|
|
19
22
|
...createStyleAndModeApi(deps),
|
|
@@ -31,9 +31,10 @@ export function createChannelRoutes({
|
|
|
31
31
|
// Checked on every register/call/agent dispatch, first and again right
|
|
32
32
|
// before the work is handed on (the lease may have been fenced while the
|
|
33
33
|
// body was still arriving): a daemon that lost (or cannot re-verify) its
|
|
34
|
-
// owner lease serves nothing.
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
// owner lease serves nothing. `admitWork` may answer asynchronously (a
|
|
35
|
+
// request arriving during the lease's re-verification waits for it).
|
|
36
|
+
async function refuseUnadmitted(res) {
|
|
37
|
+
if (await admitWork()) return false;
|
|
37
38
|
sendError(res, 'daemon owner lease is not held', 503);
|
|
38
39
|
return true;
|
|
39
40
|
}
|
|
@@ -54,10 +55,10 @@ export function createChannelRoutes({
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
async function register(req, res) {
|
|
57
|
-
if (refuseUnadmitted(res)) return;
|
|
58
|
+
if (await refuseUnadmitted(res)) return;
|
|
58
59
|
if (state.drainCommitted) return sendDraining(res);
|
|
59
60
|
const body = await readChannelBody(req);
|
|
60
|
-
if (refuseUnadmitted(res)) return;
|
|
61
|
+
if (await refuseUnadmitted(res)) return;
|
|
61
62
|
const clientToken = registry.registerClient({
|
|
62
63
|
leadPid: body.leadPid,
|
|
63
64
|
cwd: body.cwd,
|
|
@@ -96,11 +97,11 @@ export function createChannelRoutes({
|
|
|
96
97
|
// channels client registry alive. The broker itself owns a parallel fair
|
|
97
98
|
// scheduler and per-call cancellation.
|
|
98
99
|
async function agentDispatch(req, res) {
|
|
99
|
-
if (refuseUnadmitted(res)) return;
|
|
100
|
+
if (await refuseUnadmitted(res)) return;
|
|
100
101
|
if (state.drainCommitted) return sendDraining(res);
|
|
101
102
|
if (!agentBroker?.dispatch) return sendError(res, 'agent broker unavailable', 503);
|
|
102
103
|
const body = await readChannelBody(req);
|
|
103
|
-
if (refuseUnadmitted(res)) return;
|
|
104
|
+
if (await refuseUnadmitted(res)) return;
|
|
104
105
|
const callId = String(body.callId || '').trim();
|
|
105
106
|
if (!callId) return sendError(res, 'callId required', 400);
|
|
106
107
|
res.on('close', () => {
|
|
@@ -130,10 +131,10 @@ export function createChannelRoutes({
|
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
async function call(req, res) {
|
|
133
|
-
if (refuseUnadmitted(res)) return;
|
|
134
|
+
if (await refuseUnadmitted(res)) return;
|
|
134
135
|
if (state.drainCommitted) return sendDraining(res);
|
|
135
136
|
const body = await readChannelBody(req);
|
|
136
|
-
if (refuseUnadmitted(res)) return;
|
|
137
|
+
if (await refuseUnadmitted(res)) return;
|
|
137
138
|
const clientToken = body.token || null;
|
|
138
139
|
const c = clientToken ? clients.get(clientToken) : null;
|
|
139
140
|
if (!c) return sendError(res, 'unknown client token', 404);
|
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
// this control exists — the host takes `execute` as a constructor option), and
|
|
9
9
|
// `cwd`. Output: { canonicalAgentTool, execute }.
|
|
10
10
|
|
|
11
|
-
import { deliverAutomationCompletion } from '../session-runtime/automation-agents.mjs';
|
|
12
|
-
|
|
13
11
|
export function createCanonicalAgentControl({ getSessionService, getSessionRuntimeHost, cwd }) {
|
|
14
12
|
let canonicalAgentToolPromise = null;
|
|
15
13
|
|
|
@@ -34,12 +32,7 @@ export function createCanonicalAgentControl({ getSessionService, getSessionRunti
|
|
|
34
32
|
isKeychainPrewarmReady: () => true,
|
|
35
33
|
sessionSurface: sessionService.agentSurface,
|
|
36
34
|
notifySessionCompletion(ownerSessionId, text, meta = {}) {
|
|
37
|
-
|
|
38
|
-
// agent-result waiter takes the completions it is owed.
|
|
39
|
-
return (
|
|
40
|
-
getSessionRuntimeHost()?.notifySessionCompletion?.(ownerSessionId, text, meta) === true ||
|
|
41
|
-
deliverAutomationCompletion(ownerSessionId, text, meta)
|
|
42
|
-
);
|
|
35
|
+
return getSessionRuntimeHost()?.notifySessionCompletion?.(ownerSessionId, text, meta) === true;
|
|
43
36
|
},
|
|
44
37
|
});
|
|
45
38
|
})
|
|
@@ -12,22 +12,33 @@
|
|
|
12
12
|
* this daemon's in-memory turn activity (every session runs inline here, so
|
|
13
13
|
* it is the single source of truth; worker index files only declare work). */
|
|
14
14
|
async function loadSessionStoreWithRuntimeActivity() {
|
|
15
|
-
const [store, runtime, progress] = await Promise.all([
|
|
15
|
+
const [store, runtime, progress, tasks] = await Promise.all([
|
|
16
16
|
import('../runtime/agent/orchestrator/session/store-summary-reader.mjs'),
|
|
17
17
|
// The import-free leaf holding the runtime map: no session manager graph.
|
|
18
18
|
import('../runtime/agent/orchestrator/session/manager/runtime-state.mjs'),
|
|
19
19
|
import('../runtime/agent/orchestrator/session/agent-pool-progress.mjs'),
|
|
20
|
+
import('../runtime/shared/background-tasks.mjs'),
|
|
20
21
|
]);
|
|
21
22
|
return {
|
|
22
23
|
...store,
|
|
23
24
|
// Running rows also carry their turn's progress stamp and stage (the
|
|
24
|
-
// quiet-time cue), read from the same runtime map
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
// quiet-time cue), read from the same runtime map; an idle row whose
|
|
26
|
+
// agent handed off background shell work that still runs reads waiting.
|
|
27
|
+
// The handed-off shell work of every row comes from one task scan. The
|
|
28
|
+
// store is read with awaited I/O (a listing runs on every activity
|
|
29
|
+
// change); the running set is taken once those reads are done.
|
|
30
|
+
listStoredAgentWorkers: async () => {
|
|
31
|
+
const rows = await store.listStoredAgentWorkersAsync({
|
|
32
|
+
runningSessionIds: () => runtime.inFlightSessionActivity().working,
|
|
33
|
+
});
|
|
34
|
+
const awaiting = tasks.activeBackgroundTaskSessionIds({ surface: 'shell', awaitedOnly: true });
|
|
35
|
+
return progress.withTurnProgress(
|
|
36
|
+
rows,
|
|
28
37
|
(sessionId) => runtime.runtimeState.get(sessionId),
|
|
29
|
-
runtime.isTurnInFlight
|
|
30
|
-
|
|
38
|
+
runtime.isTurnInFlight,
|
|
39
|
+
(sessionId) => awaiting.has(sessionId)
|
|
40
|
+
);
|
|
41
|
+
},
|
|
31
42
|
};
|
|
32
43
|
}
|
|
33
44
|
|
|
@@ -53,6 +64,8 @@ export function createDesktopRuntime({ getLocalSessionBridge }) {
|
|
|
53
64
|
loadStatuslineSegments: () => import('../runtime/shared/statusline/statusline-segments.mjs'),
|
|
54
65
|
loadConfig: () => import('../runtime/shared/config.mjs'),
|
|
55
66
|
loadDocumentPreview: () => import('../runtime/office/pdf/document-preview.mjs'),
|
|
67
|
+
// The desktop service's git children start on this worker, off the loop.
|
|
68
|
+
loadProcessRunner: () => import('../runtime/shared/process-runner.mjs'),
|
|
56
69
|
async executeCodeGraphTool(name, args, cwd) {
|
|
57
70
|
const graph = await import('../runtime/agent/orchestrator/tools/code-graph/dispatch.mjs');
|
|
58
71
|
return graph.executeCodeGraphTool(name, args, cwd);
|
|
@@ -15,6 +15,14 @@
|
|
|
15
15
|
// being renewed, and every register/call asks `admit()` first. After an
|
|
16
16
|
// event-loop stall nothing is served until a refresh under the claim lock
|
|
17
17
|
// proves the record still names it — a contender's claim takes that lock.
|
|
18
|
+
// A lease that ran out DURING such a stall (live when the loop stopped) is
|
|
19
|
+
// the one exception to the fence: the holder never had a turn to refresh
|
|
20
|
+
// or to fence, and a contender's reclaim is decided under the claim lock
|
|
21
|
+
// against the record's heartbeat there (daemonOwnerIsStale re-checks it),
|
|
22
|
+
// so a refresh that finds the record still naming this pid proves no
|
|
23
|
+
// contender took it and none can on its earlier proof. Without that, a sole
|
|
24
|
+
// daemon whose loop the machine starved past the lease killed itself and
|
|
25
|
+
// every running turn with no other daemon to take over.
|
|
18
26
|
// - Holder's record names `livenessPort` from its very first claim: a tiny
|
|
19
27
|
// loopback listener started BEFORE the claim (startOwnerLivenessListener)
|
|
20
28
|
// answers /health with the pid, through boot and for the process lifetime.
|
|
@@ -32,8 +40,9 @@
|
|
|
32
40
|
// daemon.json publishes, answering with that pid, proves them alive.
|
|
33
41
|
import http from 'node:http';
|
|
34
42
|
import { readFileSync } from 'node:fs';
|
|
43
|
+
import { readFile } from 'node:fs/promises';
|
|
35
44
|
import { isPidAlive } from '../runtime/shared/pid-liveness.mjs';
|
|
36
|
-
import { readSingletonOwner,
|
|
45
|
+
import { readSingletonOwner, refreshSingletonOwnerAsync } from '../runtime/shared/singleton-owner.mjs';
|
|
37
46
|
|
|
38
47
|
export const DAEMON_OWNER_STALE_MS = 60_000;
|
|
39
48
|
export const OWNER_PROBE_TIMEOUT_MS = 3_000;
|
|
@@ -58,11 +67,23 @@ export function daemonOwnerTimings(env = process.env) {
|
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
/** daemon.json's pid and session endpoint, or null when missing/unreadable. */
|
|
70
|
+
function discoveryOf(parsed) {
|
|
71
|
+
const session = parsed?.endpoints?.session;
|
|
72
|
+
return { pid: Number(parsed?.pid) || 0, port: Number(session?.port) || 0, token: session?.token || '' };
|
|
73
|
+
}
|
|
74
|
+
|
|
61
75
|
export function readDiscovery(discoveryPath) {
|
|
62
76
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return
|
|
77
|
+
return discoveryOf(JSON.parse(readFileSync(discoveryPath, 'utf8')));
|
|
78
|
+
} catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** readDiscovery without blocking the event loop. */
|
|
84
|
+
export async function readDiscoveryAsync(discoveryPath) {
|
|
85
|
+
try {
|
|
86
|
+
return discoveryOf(JSON.parse(await readFile(discoveryPath, 'utf8')));
|
|
66
87
|
} catch {
|
|
67
88
|
return null;
|
|
68
89
|
}
|
|
@@ -243,7 +264,10 @@ export function daemonOwnerIsStale(
|
|
|
243
264
|
* `tickMs` it checks the lease, notices stalls, and every `heartbeatMs`
|
|
244
265
|
* rewrites `owner` with a fresh wall-clock `heartbeatAt` under the claim lock
|
|
245
266
|
* (recreating a deleted record), then calls `onBeat`.
|
|
246
|
-
* - No successful refresh for `fenceMs`: fenced, never renewed (`onFenced`)
|
|
267
|
+
* - No successful refresh for `fenceMs`: fenced, never renewed (`onFenced`) —
|
|
268
|
+
* unless the lease ran out inside one stall (live when the loop stopped):
|
|
269
|
+
* then the refresh is retried every tick for `heartbeatMs` after the loop
|
|
270
|
+
* resumes, and fenced only if none succeeds by then.
|
|
247
271
|
* - The record names another pid: `onSuperseded(record)`.
|
|
248
272
|
* - A turn gap over `stallMs`: `admit()` refuses work until a refresh succeeds.
|
|
249
273
|
* The gap is logged once, with `describeStall(fromMono, toMono)` appended.
|
|
@@ -258,7 +282,7 @@ export function createOwnerHeartbeat({
|
|
|
258
282
|
stallMs,
|
|
259
283
|
now = Date.now,
|
|
260
284
|
monoNow = () => performance.now(),
|
|
261
|
-
refresh =
|
|
285
|
+
refresh = refreshSingletonOwnerAsync,
|
|
262
286
|
log = () => {},
|
|
263
287
|
describeStall = null,
|
|
264
288
|
onBeat = () => {},
|
|
@@ -272,6 +296,13 @@ export function createOwnerHeartbeat({
|
|
|
272
296
|
let lastBeatAt = leaseFrom;
|
|
273
297
|
let lastTurnAt = leaseFrom;
|
|
274
298
|
let needsVerify = false;
|
|
299
|
+
// Monotonic time the loop resumed from a stall that outlived the lease.
|
|
300
|
+
let stallResumedAt = null;
|
|
301
|
+
// The refresh in flight: a promise of its settled status, else null.
|
|
302
|
+
let pending = null;
|
|
303
|
+
// When the latest stall was noticed: only a refresh started after it can
|
|
304
|
+
// re-verify the record (an older one may have read it before the stall).
|
|
305
|
+
let stallNotedAt = Number.NEGATIVE_INFINITY;
|
|
275
306
|
let timer = null;
|
|
276
307
|
|
|
277
308
|
function halt(next) {
|
|
@@ -284,6 +315,12 @@ export function createOwnerHeartbeat({
|
|
|
284
315
|
return t - leaseFrom >= fenceMs;
|
|
285
316
|
}
|
|
286
317
|
|
|
318
|
+
// Expired and past re-verification: the refreshes failed while the loop
|
|
319
|
+
// ran, or no refresh landed within `heartbeatMs` of resuming from a stall.
|
|
320
|
+
function mustFence(t) {
|
|
321
|
+
return leaseExpired(t) && !(stallResumedAt !== null && t - stallResumedAt < heartbeatMs);
|
|
322
|
+
}
|
|
323
|
+
|
|
287
324
|
function fence(t) {
|
|
288
325
|
if (state !== 'active') return;
|
|
289
326
|
halt('fenced');
|
|
@@ -298,6 +335,8 @@ export function createOwnerHeartbeat({
|
|
|
298
335
|
lastTurnAt = t;
|
|
299
336
|
if (t - from <= stallMs) return;
|
|
300
337
|
needsVerify = true;
|
|
338
|
+
stallNotedAt = t;
|
|
339
|
+
if (state === 'active' && !leaseExpired(from) && leaseExpired(t)) stallResumedAt = t;
|
|
301
340
|
let detail = '';
|
|
302
341
|
try {
|
|
303
342
|
detail = describeStall?.(from, t) || '';
|
|
@@ -310,13 +349,53 @@ export function createOwnerHeartbeat({
|
|
|
310
349
|
);
|
|
311
350
|
}
|
|
312
351
|
|
|
352
|
+
// A refresh's verdict, applied once it is known. Fenced, superseded or
|
|
353
|
+
// stopped while it ran: nothing is renewed. A renewal counts from the
|
|
354
|
+
// moment the refresh started (`t`), never from when it answered.
|
|
355
|
+
function settle(t, heartbeatAt, result) {
|
|
356
|
+
if (state !== 'active') return result.status;
|
|
357
|
+
if (result.status === 'refreshed') {
|
|
358
|
+
if (leaseExpired(t)) {
|
|
359
|
+
log(
|
|
360
|
+
`owner lease re-verified ${Math.round(t - leaseFrom)}ms after its last refresh (event-loop stall)` +
|
|
361
|
+
' — the record still names this process; serving again'
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
leaseFrom = t;
|
|
365
|
+
lastRefreshAt = heartbeatAt;
|
|
366
|
+
if (t >= stallNotedAt) {
|
|
367
|
+
needsVerify = false;
|
|
368
|
+
stallResumedAt = null;
|
|
369
|
+
}
|
|
370
|
+
onBeat();
|
|
371
|
+
} else if (result.status === 'superseded') {
|
|
372
|
+
halt('superseded');
|
|
373
|
+
onSuperseded(result.owner);
|
|
374
|
+
} else if (result.status === 'busy') {
|
|
375
|
+
log('owner heartbeat skipped: claim lock busy');
|
|
376
|
+
}
|
|
377
|
+
return result.status;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function failedRefresh(error) {
|
|
381
|
+
log(`owner heartbeat failed: ${error?.message || error}`);
|
|
382
|
+
return { status: 'failed' };
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// One refresh at a time. An asynchronous refresh (the default: its file
|
|
386
|
+
// work and lock retries never block the loop) answers 'pending' here and
|
|
387
|
+
// settles later; the lease and fence keep their monotonic deadlines while
|
|
388
|
+
// it runs — a refresh still unanswered at the fence does not hold it off.
|
|
313
389
|
function beat() {
|
|
314
390
|
if (state !== 'active') return null;
|
|
391
|
+
if (pending) return 'pending';
|
|
315
392
|
const t = monoNow();
|
|
316
393
|
lastBeatAt = t;
|
|
317
|
-
// Checked before every renewal: an overdue beat
|
|
318
|
-
//
|
|
319
|
-
|
|
394
|
+
// Checked before every renewal: an overdue beat must fence, not extend a
|
|
395
|
+
// lease a contender may already have reclaimed — except right after a
|
|
396
|
+
// stall that outlived the lease, where the refresh itself (under the
|
|
397
|
+
// claim lock) answers whether one did.
|
|
398
|
+
if (mustFence(t)) {
|
|
320
399
|
fence(t);
|
|
321
400
|
return 'fenced';
|
|
322
401
|
}
|
|
@@ -325,28 +404,26 @@ export function createOwnerHeartbeat({
|
|
|
325
404
|
try {
|
|
326
405
|
result = refresh(ownerPath, { ...record, heartbeatAt });
|
|
327
406
|
} catch (error) {
|
|
328
|
-
|
|
329
|
-
result = { status: 'failed' };
|
|
330
|
-
}
|
|
331
|
-
if (result.status === 'refreshed') {
|
|
332
|
-
leaseFrom = t;
|
|
333
|
-
lastRefreshAt = heartbeatAt;
|
|
334
|
-
needsVerify = false;
|
|
335
|
-
onBeat();
|
|
336
|
-
} else if (result.status === 'superseded') {
|
|
337
|
-
halt('superseded');
|
|
338
|
-
onSuperseded(result.owner);
|
|
339
|
-
} else if (result.status === 'busy') {
|
|
340
|
-
log('owner heartbeat skipped: claim lock busy');
|
|
407
|
+
result = failedRefresh(error);
|
|
341
408
|
}
|
|
342
|
-
return result
|
|
409
|
+
if (typeof result?.then !== 'function') return settle(t, heartbeatAt, result);
|
|
410
|
+
pending = result
|
|
411
|
+
.then(
|
|
412
|
+
(value) => value,
|
|
413
|
+
(error) => failedRefresh(error)
|
|
414
|
+
)
|
|
415
|
+
.then((value) => {
|
|
416
|
+
pending = null;
|
|
417
|
+
return settle(t, heartbeatAt, value);
|
|
418
|
+
});
|
|
419
|
+
return 'pending';
|
|
343
420
|
}
|
|
344
421
|
|
|
345
422
|
function tick() {
|
|
346
423
|
if (state !== 'active') return;
|
|
347
424
|
const t = monoNow();
|
|
348
425
|
noteTurn(t);
|
|
349
|
-
if (
|
|
426
|
+
if (mustFence(t)) fence(t);
|
|
350
427
|
else if (needsVerify ? t - lastBeatAt >= tickMs : t - lastBeatAt >= heartbeatMs) beat();
|
|
351
428
|
}
|
|
352
429
|
|
|
@@ -363,7 +440,7 @@ export function createOwnerHeartbeat({
|
|
|
363
440
|
// Shutting down: no ticks run to measure stalls; the lease still bounds it.
|
|
364
441
|
if (state === 'stopped') return !leaseExpired(t);
|
|
365
442
|
noteTurn(t);
|
|
366
|
-
if (
|
|
443
|
+
if (mustFence(t)) {
|
|
367
444
|
fence(t);
|
|
368
445
|
return false;
|
|
369
446
|
}
|
|
@@ -372,8 +449,23 @@ export function createOwnerHeartbeat({
|
|
|
372
449
|
if (needsVerify && t - lastBeatAt >= tickMs) beat();
|
|
373
450
|
return state === 'active' && !needsVerify;
|
|
374
451
|
},
|
|
452
|
+
/** admit(), but a request arriving while the lease is being re-verified
|
|
453
|
+
* waits for the verifying refresh instead of being refused outright: at
|
|
454
|
+
* most two refreshes (one started before the stall cannot verify). */
|
|
455
|
+
async admitAsync() {
|
|
456
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
457
|
+
if (this.admit()) return true;
|
|
458
|
+
if (!pending) return false;
|
|
459
|
+
await pending;
|
|
460
|
+
}
|
|
461
|
+
return this.admit();
|
|
462
|
+
},
|
|
375
463
|
beat,
|
|
376
464
|
tick,
|
|
465
|
+
/** Settles with the in-flight refresh's status (null when none runs). */
|
|
466
|
+
settled() {
|
|
467
|
+
return pending ?? Promise.resolve(null);
|
|
468
|
+
},
|
|
377
469
|
/** Stop beating (shutdown). admit() keeps refusing once the lease runs out. */
|
|
378
470
|
stop() {
|
|
379
471
|
if (state === 'active') halt('stopped');
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import { SESSION_ID_PATTERN } from '../runtime/agent/orchestrator/runtime-core/session-id.mjs';
|
|
2
2
|
import { sessionListOutput, sessionReadOutput, SESSION_TOOL_OUTPUT_BYTES } from './session-tool-output.mjs';
|
|
3
|
+
import { createAgentTaskSessions } from '../session-runtime/agent-task-sessions.mjs';
|
|
3
4
|
|
|
4
5
|
const TARGET_ACTIONS = new Set(['status', 'read', 'send', 'cancel', 'delete']);
|
|
5
6
|
const MUTATING_ACTIONS = new Set(['send', 'cancel', 'delete']);
|
|
6
7
|
|
|
7
8
|
/** Model-facing session operations over the same service used by desktop and TUI. */
|
|
8
|
-
export function createSessionControl({
|
|
9
|
+
export function createSessionControl({
|
|
10
|
+
getSessionService,
|
|
11
|
+
agentTasks = createAgentTaskSessions({ getSessionService }),
|
|
12
|
+
}) {
|
|
9
13
|
return async function executeSessionControl(args = {}, context = {}) {
|
|
10
14
|
const action = args.action;
|
|
11
|
-
if (action !== 'list' && !TARGET_ACTIONS.has(action)) {
|
|
15
|
+
if (action !== 'list' && action !== 'create' && !TARGET_ACTIONS.has(action)) {
|
|
12
16
|
throw new Error(`session: unsupported remote action "${action}"`);
|
|
13
17
|
}
|
|
14
18
|
const caller = context.callerSessionId;
|
|
15
19
|
if (typeof caller !== 'string' || !SESSION_ID_PATTERN.test(caller)) {
|
|
16
20
|
throw new Error('session: caller session is required');
|
|
17
21
|
}
|
|
22
|
+
// `callerAgentId`: set only for an attended agent conversation (workspace-tools.mjs).
|
|
23
|
+
if (action === 'create') return agentTasks.create(args, context);
|
|
18
24
|
const sessionId = typeof args.session_id === 'string' ? args.session_id.trim() : '';
|
|
19
25
|
if (TARGET_ACTIONS.has(action) && (typeof sessionId !== 'string' || !SESSION_ID_PATTERN.test(sessionId))) {
|
|
20
26
|
throw new Error(`session: session_id is required for action=${action}`);
|
|
@@ -45,6 +51,9 @@ export function createSessionControl({ getSessionService }) {
|
|
|
45
51
|
if (typeof args.prompt !== 'string' || !args.prompt.trim()) {
|
|
46
52
|
throw new Error('session: prompt is required for action=send');
|
|
47
53
|
}
|
|
54
|
+
// The agent's follow-up in a task session it created reports back too.
|
|
55
|
+
const origin = await agentTasks.originFor(sessionId, context.callerAgentId);
|
|
56
|
+
if (origin) return { sessionId, accepted: await agentTasks.send(sessionId, args.prompt, origin) };
|
|
48
57
|
const result = await service.submitSession({
|
|
49
58
|
sessionId,
|
|
50
59
|
prompt: args.prompt,
|
|
@@ -35,7 +35,8 @@ import path from 'node:path';
|
|
|
35
35
|
import { rmSync } from 'node:fs';
|
|
36
36
|
import { fileURLToPath } from 'node:url';
|
|
37
37
|
import { monitorEventLoopDelay, performance } from 'node:perf_hooks';
|
|
38
|
-
import {
|
|
38
|
+
import { writeJsonAtomicAsync } from '../runtime/shared/atomic-file.mjs';
|
|
39
|
+
import { prewarmOwnerOnlyAclWin32 } from '../runtime/shared/file-permissions.mjs';
|
|
39
40
|
import { ensurePrivateRuntimeRoot, resolveRuntimeRoot } from '../runtime/shared/runtime-root.mjs';
|
|
40
41
|
import { ensureProcessListenerHeadroom } from '../runtime/shared/process-listener-headroom.mjs';
|
|
41
42
|
import { listenerLeakWarningLine } from '../runtime/shared/listener-leak-warning.mjs';
|
|
@@ -46,6 +47,7 @@ import {
|
|
|
46
47
|
daemonOwnerTimings,
|
|
47
48
|
discoveryPid,
|
|
48
49
|
proveDaemonOwnerRecord,
|
|
50
|
+
readDiscoveryAsync,
|
|
49
51
|
startOwnerLivenessListener,
|
|
50
52
|
} from './daemon-owner.mjs';
|
|
51
53
|
import { remoteIntentPath } from '../runtime/shared/remote-intent.mjs';
|
|
@@ -75,6 +77,8 @@ import { createStoredSessionViews } from './daemon-stored-session-views.mjs';
|
|
|
75
77
|
import * as quotaResumeStore from '../runtime/shared/quota-resume-store.mjs';
|
|
76
78
|
import { registerWorktreeCacheCleanups } from '../runtime/shared/worktrees/cache-cleanups.mjs';
|
|
77
79
|
import { createInlineSessionRuntimeHost } from './session-runtime-inline-host.mjs';
|
|
80
|
+
import { recoverScheduleResults, setAgentHomeLiveSurface } from '../session-runtime/agent-home-delivery.mjs';
|
|
81
|
+
import { recoverRoutineDeliveries } from '../session-runtime/owned-automation-run.mjs';
|
|
78
82
|
import { getStandaloneMemoryRuntime } from '../session-runtime/services/memory-runtime-proxy.mjs';
|
|
79
83
|
import { registerTranscriptPurgeHook } from '../session-runtime/session-transcript-purge.mjs';
|
|
80
84
|
import { createBootPhaseProfiler } from './boot-phase-profiler.mjs';
|
|
@@ -93,7 +97,6 @@ import { createDesktopRuntime } from './daemon-desktop-runtime.mjs';
|
|
|
93
97
|
import { createCanonicalAgentControl } from './daemon-agent-control.mjs';
|
|
94
98
|
import { createSessionControl } from './daemon-session-control.mjs';
|
|
95
99
|
import { flushAllIndexWrites } from '../session-runtime/services/agent-tool/index-write-queue.mjs';
|
|
96
|
-
import { registerAutomationAgentTool } from '../session-runtime/automation-agents.mjs';
|
|
97
100
|
import {
|
|
98
101
|
compareRuntimeVersions,
|
|
99
102
|
SESSION_CAPABILITY_FINGERPRINT,
|
|
@@ -607,11 +610,12 @@ function daemonStatusSnapshot() {
|
|
|
607
610
|
}
|
|
608
611
|
|
|
609
612
|
/** The file every attacher reads to find this daemon: wire identity plus both
|
|
610
|
-
* loopback endpoints and their privileged tokens.
|
|
613
|
+
* loopback endpoints and their privileged tokens. Written asynchronously
|
|
614
|
+
* (the secret file's owner-only ACL included), never on the event loop. */
|
|
611
615
|
function publishDaemonDiscovery({ channel, session, modelProxy = null }) {
|
|
612
616
|
// A re-publish keeps the first publication's startedAt.
|
|
613
617
|
publishedEndpoints = { channel, session, modelProxy, startedAt: publishedEndpoints?.startedAt ?? Date.now() };
|
|
614
|
-
|
|
618
|
+
return writeJsonAtomicAsync(
|
|
615
619
|
DAEMON_DISCOVERY_PATH,
|
|
616
620
|
{
|
|
617
621
|
protocol: SESSION_PROTOCOL,
|
|
@@ -658,6 +662,13 @@ function admitOwnerWork() {
|
|
|
658
662
|
return ownerHeartbeat ? ownerHeartbeat.admit() : true;
|
|
659
663
|
}
|
|
660
664
|
|
|
665
|
+
/** admitOwnerWork for the HTTP front doors: a request that arrives while the
|
|
666
|
+
* lease is being re-verified (the refresh is asynchronous) waits for that
|
|
667
|
+
* refresh instead of being refused. */
|
|
668
|
+
function admitOwnerWorkAsync() {
|
|
669
|
+
return ownerHeartbeat ? ownerHeartbeat.admitAsync() : true;
|
|
670
|
+
}
|
|
671
|
+
|
|
661
672
|
/** This process no longer holds (or is about to lose) the owner lease: refuse
|
|
662
673
|
* new work at once, unpublish its endpoint so launchers stop finding it, then
|
|
663
674
|
* shut down within the shutdown budget — before a contender may reclaim. */
|
|
@@ -678,14 +689,31 @@ function fenceDaemon(reason) {
|
|
|
678
689
|
/** Heartbeat follow-up while this process still owns the lock: a daemon.json
|
|
679
690
|
* deleted (TEMP cleanup) or overwritten while it runs is written again, so
|
|
680
691
|
* new clients keep finding the one daemon that serves this data dir. */
|
|
692
|
+
// Read and rewritten asynchronously, one check at a time: this runs after
|
|
693
|
+
// every heartbeat, and its synchronous read of daemon.json was measured
|
|
694
|
+
// blocking the loop for 5.9 s under disk contention.
|
|
695
|
+
let republishing = false;
|
|
681
696
|
function republishMissingDiscovery() {
|
|
682
|
-
if (!publishedEndpoints || shuttingDown ||
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
697
|
+
if (!publishedEndpoints || shuttingDown || republishing) return;
|
|
698
|
+
republishing = true;
|
|
699
|
+
void (async () => {
|
|
700
|
+
try {
|
|
701
|
+
if ((await readDiscoveryAsync(DAEMON_DISCOVERY_PATH))?.pid === process.pid || shuttingDown) return;
|
|
702
|
+
await publishDaemonDiscovery(publishedEndpoints);
|
|
703
|
+
// Fenced while it was written: take it back down (fenceDaemon already ran).
|
|
704
|
+
if (shuttingDown) {
|
|
705
|
+
if ((await readDiscoveryAsync(DAEMON_DISCOVERY_PATH))?.pid === process.pid) {
|
|
706
|
+
rmSync(DAEMON_DISCOVERY_PATH, { force: true });
|
|
707
|
+
}
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
log('daemon.json was missing or named another pid — re-published');
|
|
711
|
+
} catch (error) {
|
|
712
|
+
log(`daemon.json re-publish failed: ${error?.message || error}`);
|
|
713
|
+
} finally {
|
|
714
|
+
republishing = false;
|
|
715
|
+
}
|
|
716
|
+
})();
|
|
689
717
|
}
|
|
690
718
|
|
|
691
719
|
/** Ready handshake for the spawner, plus the log-sink handoff pinned to the
|
|
@@ -757,7 +785,7 @@ async function startChannelFrontDoor({ channelsRuntime, bootPhases }) {
|
|
|
757
785
|
transport = createChannelTransport({
|
|
758
786
|
handleCall: channelsRuntime.handleCall,
|
|
759
787
|
agentBroker: agentDispatchBroker,
|
|
760
|
-
admitWork:
|
|
788
|
+
admitWork: admitOwnerWorkAsync,
|
|
761
789
|
log,
|
|
762
790
|
// The durable channel link lives in this file. Without it a restart loses
|
|
763
791
|
// the pinned session (nothing to restore) and every catalog reports Remote
|
|
@@ -898,9 +926,6 @@ async function main() {
|
|
|
898
926
|
cwd: CWD,
|
|
899
927
|
});
|
|
900
928
|
canonicalAgentControl = agentControl;
|
|
901
|
-
// Schedules and webhooks run headless here; their sessions reach the same
|
|
902
|
-
// canonical agent control through the automation tool scope.
|
|
903
|
-
registerAutomationAgentTool(agentControl.execute);
|
|
904
929
|
const requestedRuntimeMode = String(process.env.MIXDOG_SESSION_RUNTIME_MODE || '')
|
|
905
930
|
.trim()
|
|
906
931
|
.toLowerCase();
|
|
@@ -957,6 +982,22 @@ async function main() {
|
|
|
957
982
|
},
|
|
958
983
|
log,
|
|
959
984
|
});
|
|
985
|
+
// Schedule results reach an open home thread at once (and wait out its turn).
|
|
986
|
+
setAgentHomeLiveSurface({
|
|
987
|
+
busy: (sessionId) => sessionService.liveSessionBusy(sessionId),
|
|
988
|
+
notice: (sessionId, notice) => sessionService.pushLiveSessionNotice(sessionId, notice),
|
|
989
|
+
// A task session's result (session create): the agent relays it in one turn.
|
|
990
|
+
wake: (sessionId, prompt) =>
|
|
991
|
+
sessionService.submitSession({ sessionId, prompt, options: { mode: 'prompt', kickoff: true } }),
|
|
992
|
+
// A routine fire: one queued turn in its bot's thread (routine-home-turn.mjs).
|
|
993
|
+
submit: async (sessionId, prompt, options) =>
|
|
994
|
+
(await sessionService.submitSession({ sessionId, prompt, options }))?.accepted === true,
|
|
995
|
+
abort: (sessionId) => sessionService.abortSession({ sessionId }),
|
|
996
|
+
});
|
|
997
|
+
// Results queued before a restart are posted now; results a finished run
|
|
998
|
+
// could not queue (kept on its routine's record) are queued again.
|
|
999
|
+
recoverScheduleResults().catch((error) => log(`routine results recovery failed: ${error?.message || error}`));
|
|
1000
|
+
recoverRoutineDeliveries().catch((error) => log(`routine delivery recovery failed: ${error?.message || error}`));
|
|
960
1001
|
sessionTransport = createSessionTransport({
|
|
961
1002
|
// ctx carries the CLIENT token: the session service refcounts views across
|
|
962
1003
|
// processes with it, so a terminal exiting cannot destroy the session a
|
|
@@ -974,7 +1015,7 @@ async function main() {
|
|
|
974
1015
|
} catch {}
|
|
975
1016
|
},
|
|
976
1017
|
onUpgradeRequested: requestDaemonReplacement,
|
|
977
|
-
admitWork:
|
|
1018
|
+
admitWork: admitOwnerWorkAsync,
|
|
978
1019
|
});
|
|
979
1020
|
const sessionEndpoint = await bootPhases.measure('session-transport-start', () => sessionTransport.start());
|
|
980
1021
|
const modelProxyEndpoint = await startModelProxyBridge(bootPhases);
|
|
@@ -988,7 +1029,7 @@ async function main() {
|
|
|
988
1029
|
exitRecorder.setReason(`owner claim superseded by pid=${ownerPid} before publish`, 0);
|
|
989
1030
|
process.exit(0);
|
|
990
1031
|
}
|
|
991
|
-
publishDaemonDiscovery({ channel: { port, token }, session: sessionEndpoint, modelProxy: modelProxyEndpoint });
|
|
1032
|
+
await publishDaemonDiscovery({ channel: { port, token }, session: sessionEndpoint, modelProxy: modelProxyEndpoint });
|
|
992
1033
|
bootPhases.mark('discovery-published');
|
|
993
1034
|
log(`session front door on 127.0.0.1:${sessionEndpoint.port}`);
|
|
994
1035
|
|
|
@@ -1000,6 +1041,9 @@ async function main() {
|
|
|
1000
1041
|
void sessionRuntimeHost?.warmLocalRuntime?.();
|
|
1001
1042
|
});
|
|
1002
1043
|
startPostgresInBackground();
|
|
1044
|
+
// Secret writes (token stores, config) find the ACL helpers already running
|
|
1045
|
+
// instead of starting one under their file lock.
|
|
1046
|
+
void prewarmOwnerOnlyAclWin32();
|
|
1003
1047
|
|
|
1004
1048
|
// Automation may spawn the shared daemon; keep schedules/webhooks live.
|
|
1005
1049
|
// A TUI-spawned daemon keeps the historical eager start (its channels client
|
|
@@ -85,6 +85,10 @@ export function createSessionCallCache({
|
|
|
85
85
|
// Identity cannot be removed inside the promised retry TTL.
|
|
86
86
|
for (const [key, record] of records) {
|
|
87
87
|
if (records.size <= maxEntries && retainedBytes <= maxBytes) return;
|
|
88
|
+
// Insertion order is `at` order and settledAt >= at, so no later record
|
|
89
|
+
// can have left its TTL: stop instead of rescanning every live entry on
|
|
90
|
+
// each new call while a burst holds the cache above its budget.
|
|
91
|
+
if (at - record.at < ttlMs) break;
|
|
88
92
|
if (!record.settled || !record.settledAt) continue;
|
|
89
93
|
if (at - record.settledAt < ttlMs) continue;
|
|
90
94
|
remove(key, record);
|
|
@@ -120,6 +124,8 @@ export function createSessionCallCache({
|
|
|
120
124
|
bytes: 0,
|
|
121
125
|
timer: null,
|
|
122
126
|
};
|
|
127
|
+
// Re-insert at the tail so Map order stays `at` order (prune relies on it).
|
|
128
|
+
remove(key);
|
|
123
129
|
records.set(key, record);
|
|
124
130
|
prune();
|
|
125
131
|
promise
|