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
|
@@ -29,6 +29,12 @@ import {
|
|
|
29
29
|
pruneEmptyPendingIdSet,
|
|
30
30
|
} from './pending-claim-ledger.mjs';
|
|
31
31
|
import { legacyPendingMessagesPath } from './pending-spool-path.mjs';
|
|
32
|
+
import {
|
|
33
|
+
TASK_WAIT_WAKE_NOTIFICATION,
|
|
34
|
+
TASK_WAIT_WAKE_USER,
|
|
35
|
+
interruptTaskWaitForSession,
|
|
36
|
+
registerTaskWaitSteeringCheck,
|
|
37
|
+
} from '../task-wait-control.mjs';
|
|
32
38
|
import { pruneCleanupConfirmedLedger } from './pending-delivered-ledger.mjs';
|
|
33
39
|
// The durable delivered-id ledger on the session record lives in
|
|
34
40
|
// pending-delivered-ledger.mjs; re-exported so prior importers stay unchanged.
|
|
@@ -51,6 +57,8 @@ import {
|
|
|
51
57
|
PENDING_MODE_TASK_NOTIFICATION,
|
|
52
58
|
_groupPendingMessageEntries,
|
|
53
59
|
_mergePendingMessageEntries,
|
|
60
|
+
completionExecutionId,
|
|
61
|
+
completionIsDelivered,
|
|
54
62
|
completionWasDelivered,
|
|
55
63
|
entryLifecycleToken,
|
|
56
64
|
isCompletionNotificationEntry,
|
|
@@ -447,9 +455,52 @@ export function enqueuePendingMessage(sessionId, message) {
|
|
|
447
455
|
}
|
|
448
456
|
q.push(entry);
|
|
449
457
|
const bufferedDepth = schedulePendingMessagePersist(sessionId, entry);
|
|
458
|
+
const wake = pendingEntryWake(entry);
|
|
459
|
+
if (wake) {
|
|
460
|
+
interruptTaskWaitForSession(
|
|
461
|
+
sessionId,
|
|
462
|
+
wake,
|
|
463
|
+
wake === TASK_WAIT_WAKE_NOTIFICATION ? completionExecutionId(entry) : null
|
|
464
|
+
);
|
|
465
|
+
}
|
|
450
466
|
return Math.max(q.length, bufferedDepth || 0);
|
|
451
467
|
}
|
|
452
468
|
|
|
469
|
+
// What one queued entry wakes a passive task wait or shell hold for, so it
|
|
470
|
+
// reaches the loop now: steering (a Lead message to its agent) as user input,
|
|
471
|
+
// and an undelivered task completion (agent/shell, any status). A plain
|
|
472
|
+
// channel notice (scheduled or event-rule inject) waits for the turn, as it
|
|
473
|
+
// does in the Lead's queue.
|
|
474
|
+
function pendingEntryWake(entry) {
|
|
475
|
+
if (pendingEntryMode(entry) === PENDING_MODE_PROMPT) return TASK_WAIT_WAKE_USER;
|
|
476
|
+
if (isCompletionNotificationEntry(entry) && !completionIsDelivered(entry)) return TASK_WAIT_WAKE_NOTIFICATION;
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Anything already queued when a wait or hold begins ends it at once, exactly
|
|
481
|
+
// like what arrives during it. A completion the agent already received is no
|
|
482
|
+
// longer deliverable and never wakes.
|
|
483
|
+
registerTaskWaitSteeringCheck((sessionId) => {
|
|
484
|
+
let wake = false;
|
|
485
|
+
for (const entry of _sessionPendingMessages.get(sessionId) || []) {
|
|
486
|
+
const found = pendingEntryWake(entry);
|
|
487
|
+
if (found === TASK_WAIT_WAKE_USER) return found;
|
|
488
|
+
wake = wake || found;
|
|
489
|
+
}
|
|
490
|
+
return wake;
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// True when this session's queue holds task notifications and nothing else:
|
|
494
|
+
// the mid-chain boundary may then take the whole queue without bypassing the
|
|
495
|
+
// prompt filters that keep queued prompts for the terminal boundary.
|
|
496
|
+
export function pendingQueueHoldsOnlyNotifications(sessionId) {
|
|
497
|
+
const queued = [
|
|
498
|
+
...(_sessionPendingMessages.get(sessionId) || []),
|
|
499
|
+
...(_hydratedPendingMessages.get(sessionId) || []),
|
|
500
|
+
];
|
|
501
|
+
return queued.length > 0 && queued.every((entry) => pendingEntryMode(entry) === PENDING_MODE_TASK_NOTIFICATION);
|
|
502
|
+
}
|
|
503
|
+
|
|
453
504
|
// Drain order: enqueue time, then source (hydrated < buffered < memory), then
|
|
454
505
|
// position within the source.
|
|
455
506
|
function byEnqueueOrder(a, b) {
|
|
@@ -468,19 +519,13 @@ export function drainPendingMessages(sessionId) {
|
|
|
468
519
|
// This path is deliberately memory-only: no file lock, stat, parse, or
|
|
469
520
|
// atomic rename can run in the agent-completion tick.
|
|
470
521
|
const buffered = takeBufferedPendingMessages(sessionId);
|
|
471
|
-
//
|
|
472
|
-
//
|
|
473
|
-
//
|
|
474
|
-
//
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
//
|
|
478
|
-
// them here dropped the notification entirely. On a genuine resume the
|
|
479
|
-
// in-memory queue is empty, so keeping it only ever delivers live entries.
|
|
480
|
-
// Genuine user/steering messages carry no marker and are kept in order in
|
|
481
|
-
// both paths.
|
|
482
|
-
// Drain-time belt: drop MARKED in-memory completion entries whose text hash
|
|
483
|
-
// was already delivered+ACKed (TUI execution-ui) this process — those would
|
|
522
|
+
// A completion that reached the spool and was never acknowledged was never
|
|
523
|
+
// delivered to the model (delivery acknowledges and removes it), so it
|
|
524
|
+
// survives a restart: the hydrated disk entries drain like live in-memory
|
|
525
|
+
// ones. Dropping them on resume lost a finished (or failed) task's only
|
|
526
|
+
// notification.
|
|
527
|
+
// Drain-time belt: drop MARKED completion entries whose text hash was
|
|
528
|
+
// already delivered+ACKed (TUI execution-ui) this process — those would
|
|
484
529
|
// double-inject next turn. Only marked completion entries are eligible;
|
|
485
530
|
// genuine user/steering entries carry no marker and are always kept.
|
|
486
531
|
const deliveredIds = new Set();
|
|
@@ -494,10 +539,11 @@ export function drainPendingMessages(sessionId) {
|
|
|
494
539
|
deliveredEntries.push(entry);
|
|
495
540
|
return false;
|
|
496
541
|
};
|
|
542
|
+
const hydratedKept = hydrated.filter(keepUndelivered);
|
|
497
543
|
const memoryKept = memory.filter(keepUndelivered);
|
|
498
544
|
const bufferedKept = buffered.filter(keepUndelivered);
|
|
499
545
|
const tagged = [
|
|
500
|
-
...
|
|
546
|
+
...hydratedKept.map((entry, index) => ({ entry, source: 0, index })),
|
|
501
547
|
...bufferedKept.map((entry, index) => ({ entry, source: 1, index })),
|
|
502
548
|
...memoryKept.map((entry, index) => ({ entry, source: 2, index })),
|
|
503
549
|
];
|
|
@@ -512,14 +558,8 @@ export function drainPendingMessages(sessionId) {
|
|
|
512
558
|
if (!prior || item.source > prior.source) byId.set(normalized.id, { ...item, entry: normalized });
|
|
513
559
|
}
|
|
514
560
|
const ordered = [...byId.values()].sort(byEnqueueOrder);
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
.map(({ entry }) => entry);
|
|
518
|
-
const acknowledged = [...deliveredEntries, ...dropped];
|
|
519
|
-
if (acknowledged.length > 0) acknowledgePendingMessages(sessionId, acknowledged);
|
|
520
|
-
const visible = modelVisiblePendingMessages(
|
|
521
|
-
ordered.filter(({ entry }) => !dropped.includes(entry)).map(({ entry }) => entry)
|
|
522
|
-
);
|
|
561
|
+
if (deliveredEntries.length > 0) acknowledgePendingMessages(sessionId, deliveredEntries);
|
|
562
|
+
const visible = modelVisiblePendingMessages(ordered.map(({ entry }) => entry));
|
|
523
563
|
// Epoch gate. Normalization above rebuilds every entry, but each copy
|
|
524
564
|
// inherits the IMMUTABLE token the entry was accepted under. An entry from
|
|
525
565
|
// an older epoch (a cross-process close/detach moved the generation while
|
|
@@ -207,29 +207,46 @@ function bp3SliceAt(text, heading) {
|
|
|
207
207
|
|
|
208
208
|
/**
|
|
209
209
|
* Replace the workspace-scoped tail of a BP3 core (composeSystemPrompt order:
|
|
210
|
-
* …, `#
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
210
|
+
* …, `# Instruction Files`, `# Core Memory`). Core memory is the last,
|
|
211
|
+
* separator-free part; the instruction-files slice before it may itself
|
|
212
|
+
* contain separators, so both are cut by position. A core from before that
|
|
213
|
+
* order (memory, then instruction files) is read too and written in the
|
|
214
|
+
* current order. `undefined` keeps a slice, an empty string drops it.
|
|
214
215
|
* @param {string} core
|
|
215
216
|
* @param {{ coreMemoryContext?: string, instructionFilesContext?: string }} slices
|
|
216
217
|
*/
|
|
217
218
|
export function replaceWorkspaceCoreSlices(core, { coreMemoryContext, instructionFilesContext } = {}) {
|
|
219
|
+
let { head, instructionFiles, memory } = splitWorkspaceCoreSlices(core);
|
|
220
|
+
if (coreMemoryContext !== undefined) {
|
|
221
|
+
const value = trimmedSlice(coreMemoryContext);
|
|
222
|
+
memory = value ? `${CORE_MEMORY_HEADING}${value}` : '';
|
|
223
|
+
}
|
|
224
|
+
if (instructionFilesContext !== undefined) instructionFiles = trimmedSlice(instructionFilesContext);
|
|
225
|
+
return [head, instructionFiles, memory].filter((part) => part?.trim()).join(BP3_PART_SEPARATOR);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** A BP3 core's `{ head, instructionFiles, memory }` (each '' when absent). */
|
|
229
|
+
function splitWorkspaceCoreSlices(core) {
|
|
218
230
|
let head = String(core || '');
|
|
231
|
+
let memory = '';
|
|
232
|
+
const memoryAt = bp3SliceAt(head, CORE_MEMORY_HEADING);
|
|
233
|
+
if (memoryAt) {
|
|
234
|
+
memory = head.slice(memoryAt.start);
|
|
235
|
+
head = head.slice(0, memoryAt.cut);
|
|
236
|
+
const legacy = memory.indexOf(`${BP3_PART_SEPARATOR}${INSTRUCTION_FILES_HEADING}`);
|
|
237
|
+
if (legacy >= 0) {
|
|
238
|
+
const instructions = memory.slice(legacy + BP3_PART_SEPARATOR.length);
|
|
239
|
+
memory = memory.slice(0, legacy);
|
|
240
|
+
head = head ? `${head}${BP3_PART_SEPARATOR}${instructions}` : instructions;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
219
243
|
let instructionFiles = '';
|
|
220
244
|
const instructionAt = bp3SliceAt(head, INSTRUCTION_FILES_HEADING);
|
|
221
245
|
if (instructionAt) {
|
|
222
246
|
instructionFiles = head.slice(instructionAt.start);
|
|
223
247
|
head = head.slice(0, instructionAt.cut);
|
|
224
248
|
}
|
|
225
|
-
|
|
226
|
-
if (coreMemoryContext !== undefined) {
|
|
227
|
-
parts = parts.filter((part) => !part.startsWith(CORE_MEMORY_HEADING));
|
|
228
|
-
const memory = trimmedSlice(coreMemoryContext);
|
|
229
|
-
if (memory) parts.push(`${CORE_MEMORY_HEADING}${memory}`);
|
|
230
|
-
}
|
|
231
|
-
if (instructionFilesContext !== undefined) instructionFiles = trimmedSlice(instructionFilesContext);
|
|
232
|
-
return [...parts, instructionFiles].filter((part) => part?.trim()).join(BP3_PART_SEPARATOR);
|
|
249
|
+
return { head, instructionFiles, memory };
|
|
233
250
|
}
|
|
234
251
|
|
|
235
252
|
/**
|
|
@@ -286,9 +303,7 @@ function textOf(message) {
|
|
|
286
303
|
*/
|
|
287
304
|
function presentedWorkspace(session) {
|
|
288
305
|
const core = session.bp3EnvSplit === true ? textOf(bp3SystemMessage(session)) : String(session.bp3CoreContext || '');
|
|
289
|
-
const
|
|
290
|
-
const head = instructionAt ? core.slice(0, instructionAt.cut) : core;
|
|
291
|
-
const memory = (head ? head.split(BP3_PART_SEPARATOR) : []).find((part) => part.startsWith(CORE_MEMORY_HEADING));
|
|
306
|
+
const { instructionFiles, memory } = splitWorkspaceCoreSlices(core);
|
|
292
307
|
const tail = typeof session.bp3EnvironmentContext === 'string' ? session.bp3EnvironmentContext : '';
|
|
293
308
|
const facts = tail.split(BP3_PART_SEPARATOR)[0] || '';
|
|
294
309
|
const promptText = [textOf(bpEnvSystemMessage(session)), textOf(bp3SystemMessage(session))].join('\n');
|
|
@@ -297,10 +312,23 @@ function presentedWorkspace(session) {
|
|
|
297
312
|
cwd: cwd ? cwd.trim() : null,
|
|
298
313
|
environmentContext: facts.startsWith('- ') ? facts.trim() : '',
|
|
299
314
|
coreMemoryContext: memory ? memory.slice(CORE_MEMORY_HEADING.length).trim() : '',
|
|
300
|
-
instructionFilesContext:
|
|
315
|
+
instructionFilesContext: instructionFiles.trim(),
|
|
301
316
|
};
|
|
302
317
|
}
|
|
303
318
|
|
|
319
|
+
/**
|
|
320
|
+
* A rebuilt BP3 core head (composed without workspace slices) followed by the
|
|
321
|
+
* instruction-files and core-memory slices the session's prompt presents now,
|
|
322
|
+
* so a rebuild of the rest of the core (a mid-conversation workflow switch)
|
|
323
|
+
* leaves what the model was told about its workspace — and any staged
|
|
324
|
+
* workspaceReroot — as it was.
|
|
325
|
+
*/
|
|
326
|
+
export function withPresentedWorkspaceSlices(session, nextHead) {
|
|
327
|
+
const core = session.bp3EnvSplit === true ? textOf(bp3SystemMessage(session)) : String(session.bp3CoreContext || '');
|
|
328
|
+
const { instructionFiles, memory } = splitWorkspaceCoreSlices(core);
|
|
329
|
+
return [nextHead, instructionFiles, memory].filter((part) => part?.trim()).join(BP3_PART_SEPARATOR);
|
|
330
|
+
}
|
|
331
|
+
|
|
304
332
|
const WORKSPACE_SLICES = ['environmentContext', 'coreMemoryContext', 'instructionFilesContext'];
|
|
305
333
|
|
|
306
334
|
/**
|
|
@@ -112,20 +112,36 @@ export function _buildAgentRules(profile = 'full') {
|
|
|
112
112
|
);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
// One `part` of LEAD.md (rules-builder buildLeadRoleContent): 'common' (the
|
|
116
|
+
// lines every Lead shares), 'coding' / 'agent' (the mode-variant passages),
|
|
117
|
+
// 'identity' (the coding identity sentence).
|
|
118
|
+
export function _buildLeadRules({ includeLeadBrief = true, part = 'common' } = {}) {
|
|
116
119
|
const PLUGIN_ROOT = mixdogRoot();
|
|
117
120
|
const DATA_DIR = resolvePluginData();
|
|
118
121
|
const RULES_DIR = join(PLUGIN_ROOT, 'rules');
|
|
122
|
+
const variant = includeLeadBrief ? 'delegating' : 'delegation-free';
|
|
119
123
|
return buildCachedRules(
|
|
120
124
|
'buildLeadRoleContent',
|
|
121
125
|
'lead role rules',
|
|
122
126
|
[join(RULES_DIR, 'lead'), join(DATA_DIR, 'mixdog-config.json')],
|
|
123
|
-
{ PLUGIN_ROOT, DATA_DIR, includeLeadBrief },
|
|
124
|
-
|
|
127
|
+
{ PLUGIN_ROOT, DATA_DIR, includeLeadBrief, part },
|
|
128
|
+
`${variant}\n${part}`
|
|
125
129
|
);
|
|
126
130
|
}
|
|
127
131
|
|
|
128
|
-
|
|
132
|
+
// One agent-mode rule file (rules/agent-mode): 'conduct', 'mixy' or 'routine'.
|
|
133
|
+
export function _buildAgentModeRules({ part = 'conduct' } = {}) {
|
|
134
|
+
const PLUGIN_ROOT = mixdogRoot();
|
|
135
|
+
return buildCachedRules(
|
|
136
|
+
'buildAgentModeContent',
|
|
137
|
+
'agent mode rules',
|
|
138
|
+
[join(PLUGIN_ROOT, 'rules', 'agent-mode')],
|
|
139
|
+
{ PLUGIN_ROOT, part },
|
|
140
|
+
part
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function _buildLeadMetaContext({ includeOutputStyle = true } = {}) {
|
|
129
145
|
const PLUGIN_ROOT = mixdogRoot();
|
|
130
146
|
const DATA_DIR = resolvePluginData();
|
|
131
147
|
const RULES_DIR = join(PLUGIN_ROOT, 'rules');
|
|
@@ -138,7 +154,8 @@ export function _buildLeadMetaContext() {
|
|
|
138
154
|
join(PLUGIN_ROOT, 'output-styles'),
|
|
139
155
|
join(DATA_DIR, 'output-styles'),
|
|
140
156
|
],
|
|
141
|
-
{ PLUGIN_ROOT, DATA_DIR }
|
|
157
|
+
{ PLUGIN_ROOT, DATA_DIR, includeOutputStyle },
|
|
158
|
+
includeOutputStyle ? 'style' : 'no-style'
|
|
142
159
|
);
|
|
143
160
|
}
|
|
144
161
|
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
// }
|
|
24
24
|
import { createAbortController } from '../../../../shared/abort-controller.mjs';
|
|
25
25
|
import { emitSessionApprovalWaitChange } from '../../../../shared/session-approval-wait.mjs';
|
|
26
|
+
import { emitSessionActivityChange } from '../../../../shared/session-activity-signal.mjs';
|
|
26
27
|
import { DEFAULT_ACTIVITY_HEARTBEAT_MS } from '../../stall-policy.mjs';
|
|
27
28
|
import { MODEL_THINKING_STAGE, awaitingModelResponse, lastProgressAt } from '../../../../shared/quiet-progress.mjs';
|
|
28
29
|
import { finishBrowserTurn } from '../../../../browser-bridge/client.mjs';
|
|
@@ -177,12 +178,14 @@ export function markSessionAskStart(id) {
|
|
|
177
178
|
entry.modelRequestStartedAt = null;
|
|
178
179
|
entry.lastProgressAt = now;
|
|
179
180
|
entry.updatedAt = now;
|
|
181
|
+
entry.taskWaits = 0;
|
|
182
|
+
emitSessionActivityChange(id);
|
|
180
183
|
}
|
|
181
184
|
/** The provider put the request on the wire; its response headers are
|
|
182
185
|
* pending. The turn stays `requesting` (every stage set and the watchdog
|
|
183
186
|
* clock are unchanged); the send time lets surfaces show "model thinking"
|
|
184
187
|
* until transport arrives. Not progress: lastProgressAt is untouched. */
|
|
185
|
-
|
|
188
|
+
function markSessionRequestSent(id) {
|
|
186
189
|
if (!id) return;
|
|
187
190
|
const entry = _runtimeState.get(id);
|
|
188
191
|
if (!entry || entry.closed || entry.controller?.signal?.aborted || entry.stage !== 'requesting') return;
|
|
@@ -321,6 +324,23 @@ export function beginSessionApprovalWait(id) {
|
|
|
321
324
|
emitSessionApprovalWaitChange(id, null, meta);
|
|
322
325
|
};
|
|
323
326
|
}
|
|
327
|
+
// A turn parked on a background task (`task wait`): published as
|
|
328
|
+
// `awaitingTask` so status surfaces show the session waiting, not working.
|
|
329
|
+
// Counted like approval waits; never creates an entry. Returns the idempotent
|
|
330
|
+
// release.
|
|
331
|
+
export function beginSessionTaskWait(id) {
|
|
332
|
+
const entry = id ? _runtimeState.get(id) : null;
|
|
333
|
+
if (!entry) return () => {};
|
|
334
|
+
entry.taskWaits = (entry.taskWaits || 0) + 1;
|
|
335
|
+
if (entry.taskWaits === 1) emitSessionActivityChange(id);
|
|
336
|
+
let released = false;
|
|
337
|
+
return () => {
|
|
338
|
+
if (released) return;
|
|
339
|
+
released = true;
|
|
340
|
+
entry.taskWaits = Math.max(0, (entry.taskWaits || 0) - 1);
|
|
341
|
+
if (entry.taskWaits === 0) emitSessionActivityChange(id);
|
|
342
|
+
};
|
|
343
|
+
}
|
|
324
344
|
// Parent AbortSignal listeners are dropped on askSession unwind (finally /
|
|
325
345
|
// terminal return) and on error/cancel/close — not in markSessionDone, which
|
|
326
346
|
// also runs between queued follow-up turns within one ask.
|
|
@@ -335,6 +355,8 @@ function _settleTerminalEntry(entry, stage, lastError) {
|
|
|
335
355
|
entry.doneAt = settledAt;
|
|
336
356
|
entry.lastProgressAt = settledAt;
|
|
337
357
|
entry.updatedAt = settledAt;
|
|
358
|
+
entry.taskWaits = 0;
|
|
359
|
+
emitSessionActivityChange(entry.session?.id || '');
|
|
338
360
|
}
|
|
339
361
|
export function markSessionDone(id, { empty = false } = {}) {
|
|
340
362
|
if (!id) return;
|
|
@@ -3,7 +3,16 @@
|
|
|
3
3
|
// when tombstone=false), aborts the in-flight controller, tears down
|
|
4
4
|
// runtime/bash/dedup/offload/pending state, and defers the runtime-map clear.
|
|
5
5
|
// abortSessionTurn cancels the current turn without tombstoning.
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
markSessionClosed,
|
|
8
|
+
markSessionClosedAsync,
|
|
9
|
+
markSessionClosedAttempt,
|
|
10
|
+
bumpSessionGeneration,
|
|
11
|
+
bumpSessionGenerationAttempt,
|
|
12
|
+
isLifecycleRetry,
|
|
13
|
+
getSessionLifecycleCommitError,
|
|
14
|
+
} from '../store.mjs';
|
|
15
|
+
import { sleep } from '../../../../shared/sleep.mjs';
|
|
7
16
|
import { clearReadDedupSession } from '../read-dedup.mjs';
|
|
8
17
|
import { SessionClosedError } from './session-errors.mjs';
|
|
9
18
|
import { _dropPendingMessageState } from './pending-messages.mjs';
|
|
@@ -36,44 +45,79 @@ import { forgetSideQuestion } from '../side-question-store.mjs';
|
|
|
36
45
|
* TOMBSTONE_MAX_AGE_MS (1h — vastly longer than the microsecond in-flight race).
|
|
37
46
|
*/
|
|
38
47
|
export function closeSession(id, reason = 'manual', opts = {}) {
|
|
39
|
-
// tombstone=false: detach runtime resources (heartbeat, bash shells,
|
|
40
|
-
// controller abort, runtime-map clear) WITHOUT planting the disk
|
|
41
|
-
// tombstone. Used for non-empty sessions on /resume-away, /new, and
|
|
42
|
-
// TUI exit: a tombstone would drop the session from the Resume list
|
|
43
|
-
// immediately and let sweepTombstones() hard-delete it even though it
|
|
44
|
-
// has real conversation content worth resuming. Only truly-empty
|
|
45
|
-
// scratch sessions should still tombstone.
|
|
46
|
-
const tombstone = opts.tombstone !== false;
|
|
47
48
|
if (!id) return false;
|
|
49
|
+
const tombstone = opts.tombstone !== false;
|
|
48
50
|
const entry = _getRuntimeEntry(id);
|
|
49
|
-
|
|
50
|
-
// iterations, the current partial response, and observed tool results into
|
|
51
|
-
// one canonical transcript. Stage that in-memory snapshot synchronously
|
|
52
|
-
// BEFORE the lifecycle generation changes; once generation is bumped, the
|
|
53
|
-
// normal cancellation cleanup save is intentionally rejected as stale. It
|
|
54
|
-
// is only staged: a refused barrier rolls it back so the turn keeps running
|
|
55
|
-
// and checkpointing as if no close had been attempted.
|
|
56
|
-
let closeSnapshot = null;
|
|
57
|
-
try {
|
|
58
|
-
closeSnapshot = entry?.prepareCloseSnapshot?.tentative?.(reason) ?? null;
|
|
59
|
-
} catch {
|
|
60
|
-
/* best-effort */
|
|
61
|
-
}
|
|
62
|
-
// 1. Tombstone first — this wins the race against saveSession().
|
|
63
|
-
// Skipped when tombstone=false: no closed:true marker is planted, so
|
|
64
|
-
// the session file stays intact and resumeSession() will accept it.
|
|
65
|
-
// We still bump the on-disk generation via bumpSessionGeneration() —
|
|
66
|
-
// that alone is what protects the session from a late save race: any
|
|
67
|
-
// saveSession() still in flight from this detached turn (e.g. the
|
|
68
|
-
// cancel-cleanup save below) carries the OLD generation as its
|
|
69
|
-
// expectedGeneration, so _shouldDrop()'s ownership-counter rule drops
|
|
70
|
-
// it once disk generation moves past that. Without this bump the late
|
|
71
|
-
// write could silently overwrite the session after the user resumes
|
|
72
|
-
// it back (BL: burned-session late-save clobber).
|
|
51
|
+
const closeSnapshot = stageCloseSnapshot(entry, reason);
|
|
73
52
|
const outcome = { absent: false };
|
|
74
53
|
const newGen = tombstone
|
|
75
54
|
? markSessionClosed(id, reason, { outcome })
|
|
76
55
|
: bumpSessionGeneration(id, reason, { outcome });
|
|
56
|
+
return finishClose({ id, reason, tombstone, entry, closeSnapshot, newGen, outcome });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* closeSession that never blocks the event loop. Each barrier attempt runs
|
|
61
|
+
* synchronously exactly as closeSession's barrier does (the first one before
|
|
62
|
+
* this function first yields), but a rename the OS refuses with retries left
|
|
63
|
+
* is waited out with a timer instead of sleepSync. Between attempts the staged
|
|
64
|
+
* close snapshot is rolled back, so the turn keeps running untouched, and it
|
|
65
|
+
* is re-staged from the then-current turn right before the next attempt: the
|
|
66
|
+
* barrier that lands always carries the latest transcript. The session is
|
|
67
|
+
* torn down — and reported closed — only after its barrier is on disk.
|
|
68
|
+
*/
|
|
69
|
+
export async function closeSessionAsync(id, reason = 'manual', opts = {}) {
|
|
70
|
+
if (!id) return false;
|
|
71
|
+
const tombstone = opts.tombstone !== false;
|
|
72
|
+
const entry = _getRuntimeEntry(id);
|
|
73
|
+
for (let attempt = 0; ; attempt++) {
|
|
74
|
+
const closeSnapshot = stageCloseSnapshot(entry, reason);
|
|
75
|
+
const outcome = { absent: false };
|
|
76
|
+
const newGen = tombstone
|
|
77
|
+
? markSessionClosedAttempt(id, reason, { outcome }, attempt)
|
|
78
|
+
: bumpSessionGenerationAttempt(id, reason, { outcome }, attempt);
|
|
79
|
+
if (!isLifecycleRetry(newGen)) {
|
|
80
|
+
return finishClose({ id, reason, tombstone, entry, closeSnapshot, newGen, outcome });
|
|
81
|
+
}
|
|
82
|
+
closeSnapshot?.rollback();
|
|
83
|
+
await sleep(newGen.retryInMs);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// askSession owns the interruption tracker that can merge committed
|
|
88
|
+
// iterations, the current partial response, and observed tool results into
|
|
89
|
+
// one canonical transcript. Stage that in-memory snapshot synchronously
|
|
90
|
+
// BEFORE the lifecycle generation changes; once generation is bumped, the
|
|
91
|
+
// normal cancellation cleanup save is intentionally rejected as stale. It
|
|
92
|
+
// is only staged: a refused barrier rolls it back so the turn keeps running
|
|
93
|
+
// and checkpointing as if no close had been attempted.
|
|
94
|
+
function stageCloseSnapshot(entry, reason) {
|
|
95
|
+
try {
|
|
96
|
+
return entry?.prepareCloseSnapshot?.tentative?.(reason) ?? null;
|
|
97
|
+
} catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// tombstone=false: detach runtime resources (heartbeat, bash shells,
|
|
103
|
+
// controller abort, runtime-map clear) WITHOUT planting the disk
|
|
104
|
+
// tombstone. Used for non-empty sessions on /resume-away, /new, and
|
|
105
|
+
// TUI exit: a tombstone would drop the session from the Resume list
|
|
106
|
+
// immediately and let sweepTombstones() hard-delete it even though it
|
|
107
|
+
// has real conversation content worth resuming. Only truly-empty
|
|
108
|
+
// scratch sessions should still tombstone.
|
|
109
|
+
//
|
|
110
|
+
// The barrier (`newGen`) came first — it wins the race against saveSession().
|
|
111
|
+
// tombstone=false plants no closed:true marker, so the session file stays
|
|
112
|
+
// intact and resumeSession() will accept it, but the on-disk generation is
|
|
113
|
+
// still bumped (bumpSessionGeneration): that alone protects the session from
|
|
114
|
+
// a late save race. Any saveSession() still in flight from this detached turn
|
|
115
|
+
// (e.g. the cancel-cleanup save below) carries the OLD generation as its
|
|
116
|
+
// expectedGeneration, so _shouldDrop()'s ownership-counter rule drops it once
|
|
117
|
+
// disk generation moves past that. Without this bump the late write could
|
|
118
|
+
// silently overwrite the session after the user resumes it back (BL:
|
|
119
|
+
// burned-session late-save clobber).
|
|
120
|
+
function finishClose({ id, reason, tombstone, entry, closeSnapshot, newGen, outcome }) {
|
|
77
121
|
// Durable lifecycle barrier check. ANY nonnumeric result means the barrier
|
|
78
122
|
// is not on disk — a write failure, a liveness/ownership veto, a contended
|
|
79
123
|
// commit lock, or a missing record. Only a failed write publishes a
|
|
@@ -154,7 +198,10 @@ function reportCloseBarrierFailure({ id, reason, tombstone, entry }) {
|
|
|
154
198
|
*/
|
|
155
199
|
function cancelOwnedShellProcesses({ id, reason, tombstone }) {
|
|
156
200
|
const record = (result) => {
|
|
157
|
-
|
|
201
|
+
// Off the event loop's critical path: a refused rename retries on timers.
|
|
202
|
+
if (tombstone && result?.confirmed === false) {
|
|
203
|
+
markSessionClosedAsync(id, reason, { cancelStatus: 'cancel-unconfirmed' }).catch(() => {});
|
|
204
|
+
}
|
|
158
205
|
};
|
|
159
206
|
// A cancel that threw proved nothing either.
|
|
160
207
|
const unconfirmed = () => record({ confirmed: false });
|
|
@@ -28,6 +28,7 @@ import { mintSessionId } from './session-id.mjs';
|
|
|
28
28
|
import { hideCompactionArchive } from '../compaction-archive-capture.mjs';
|
|
29
29
|
import { writeStderrBestEffort } from '../../../../shared/best-effort-stderr.mjs';
|
|
30
30
|
import { forgetSideQuestion } from '../side-question-store.mjs';
|
|
31
|
+
import { isAgentHomeSessionId } from '../agent-home.mjs';
|
|
31
32
|
|
|
32
33
|
/** Force-flush session metrics to disk. */
|
|
33
34
|
export async function flushSessionMetrics(sessionId) {
|
|
@@ -207,9 +208,12 @@ function clearTokenAccounting(session, messages, keep, beforeMessageTokens) {
|
|
|
207
208
|
// Fork the outgoing transcript to a separate resumable session BEFORE the wipe,
|
|
208
209
|
// so the conversation about to be discarded stays reachable via /resume under a
|
|
209
210
|
// fresh id. Best-effort: any failure here must never block the clear itself.
|
|
210
|
-
|
|
211
|
+
// `archiveAs` names the fork (an agent home's "대화 새로 시작": the host
|
|
212
|
+
// archives that id before the clear) and makes it durable first: the returned
|
|
213
|
+
// promise settles once the copy is on disk, and the wipe waits on it.
|
|
214
|
+
function forkOutgoingTranscript(session, messages, now, archiveAs = '') {
|
|
211
215
|
try {
|
|
212
|
-
const forkId = mintSessionId();
|
|
216
|
+
const forkId = archiveAs || mintSessionId();
|
|
213
217
|
const fork = {
|
|
214
218
|
...session,
|
|
215
219
|
id: forkId,
|
|
@@ -234,6 +238,15 @@ function forkOutgoingTranscript(session, messages, now) {
|
|
|
234
238
|
delete fork.compaction.archive;
|
|
235
239
|
}
|
|
236
240
|
setLiveSession(fork);
|
|
241
|
+
if (archiveAs) {
|
|
242
|
+
return saveSessionAsync(fork).then(
|
|
243
|
+
() => evictLiveSession(forkId),
|
|
244
|
+
(err) => {
|
|
245
|
+
evictLiveSession(forkId);
|
|
246
|
+
throw err;
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
}
|
|
237
250
|
void saveSessionAsync(fork)
|
|
238
251
|
.then(() => {
|
|
239
252
|
// The fork is a cold snapshot kept for /resume. Once durable on
|
|
@@ -247,17 +260,33 @@ function forkOutgoingTranscript(session, messages, now) {
|
|
|
247
260
|
writeStderrBestEffort(`[session] clear-fork save failed (sess=${forkId}): ${err?.message || err}\n`);
|
|
248
261
|
});
|
|
249
262
|
} catch (err) {
|
|
263
|
+
if (archiveAs) throw err;
|
|
250
264
|
writeStderrBestEffort(`[session] clear-fork failed (sess=${session.id}): ${err?.message || err}\n`);
|
|
251
265
|
}
|
|
252
266
|
}
|
|
253
267
|
|
|
268
|
+
const ARCHIVE_ID = /^sess_[A-Za-z0-9_-]{8,200}$/;
|
|
269
|
+
|
|
270
|
+
/** The fork id a clear was asked to archive under, '' when none. */
|
|
271
|
+
function clearArchiveId(value, sessionId) {
|
|
272
|
+
if (value === undefined || value === null || value === '') return '';
|
|
273
|
+
const id = String(value);
|
|
274
|
+
if (!ARCHIVE_ID.test(id) || id === sessionId || isAgentHomeSessionId(id)) {
|
|
275
|
+
throw new Error('clear: archiveAs must be a fresh session id');
|
|
276
|
+
}
|
|
277
|
+
if (loadSession(id)) throw new Error(`clear: session ${id} already exists`);
|
|
278
|
+
return id;
|
|
279
|
+
}
|
|
280
|
+
|
|
254
281
|
export async function clearSessionMessages(sessionId, options = {}) {
|
|
255
282
|
const session = loadSession(sessionId);
|
|
256
283
|
if (!session) return false;
|
|
257
284
|
// Don't resurrect a closed session just to clear its messages.
|
|
258
285
|
if (session.closed === true) return false;
|
|
259
286
|
const clearOptions = options && typeof options === 'object' ? options : {};
|
|
260
|
-
const
|
|
287
|
+
const archiveAs = clearArchiveId(clearOptions.archiveAs, sessionId);
|
|
288
|
+
// An archived reset keeps the whole transcript: never compacted first.
|
|
289
|
+
const compact = clearOptions.compact === true && !archiveAs;
|
|
261
290
|
const currentMessages = Array.isArray(session.messages) ? session.messages : [];
|
|
262
291
|
const beforeMessageTokens = estimateMessagesTokens(currentMessages);
|
|
263
292
|
const { messages, clearCompactError } = compact
|
|
@@ -275,8 +304,14 @@ export async function clearSessionMessages(sessionId, options = {}) {
|
|
|
275
304
|
// content the live session retains via the summary, so the fork duplicated
|
|
276
305
|
// it as a confusing extra Recent row ("Re-attached after compaction…" —
|
|
277
306
|
// user report). Plain /clear (no summary kept) still forks.
|
|
307
|
+
// `fork: false` (a room member's reset: the room's own log keeps the
|
|
308
|
+
// conversation) skips the copy; an `archiveAs` clear always keeps one.
|
|
278
309
|
const summaryCarriedForward = keep.some(isCompactSummaryMessage);
|
|
279
|
-
|
|
310
|
+
const keepCopy = clearOptions.fork !== false || Boolean(archiveAs);
|
|
311
|
+
if (keepCopy && hasUserConversationMessage(messages) && !summaryCarriedForward) {
|
|
312
|
+
const fork = forkOutgoingTranscript(session, messages, now, archiveAs);
|
|
313
|
+
if (archiveAs) await fork;
|
|
314
|
+
}
|
|
280
315
|
|
|
281
316
|
session.messages = keep;
|
|
282
317
|
// Clear truncates the transcript wholesale; drop the provider prefix
|
|
@@ -9,6 +9,7 @@ import { saveSession, saveSessionAsync, saveSessionAsyncDeferred, loadSession, s
|
|
|
9
9
|
import { _liveSessions } from '../store/live-state.mjs';
|
|
10
10
|
import { _recoverTurnCheckpointDurably } from './turn-checkpoint-recovery.mjs';
|
|
11
11
|
import { isAgentOwner } from '../../agent-owner.mjs';
|
|
12
|
+
import { AGENT_MODE, resolveSessionMode, sessionModeOf } from '../agent-mode.mjs';
|
|
12
13
|
import { getHiddenAgent } from '../../internal-agents.mjs';
|
|
13
14
|
import { loadConfig } from '../../config.mjs';
|
|
14
15
|
import {
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
import { normalizeAutoClearConfig, resolveAutoClearIdleMs } from '../../runtime-core/config-helpers.mjs';
|
|
20
21
|
import { _buildBaseRules } from './rules-cache.mjs';
|
|
21
22
|
import { composeSessionSystem, seedSessionMessages } from './session-prompt-composition.mjs';
|
|
23
|
+
import { agentProfileRevision, leadRosterRevision } from '../../context/role-instructions.mjs';
|
|
22
24
|
import {
|
|
23
25
|
_prepareResumeTools,
|
|
24
26
|
delegationDisabled,
|
|
@@ -206,12 +208,22 @@ function logSessionSurface({ resolvedAgent, toolPermission, tools }) {
|
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
210
|
|
|
209
|
-
export function createSession(
|
|
210
|
-
const presetObj =
|
|
211
|
-
const resolved = resolveAgentRuntimeProfile(
|
|
211
|
+
export function createSession(createOpts) {
|
|
212
|
+
const presetObj = createOpts.preset && typeof createOpts.preset === 'object' ? createOpts.preset : null;
|
|
213
|
+
const resolved = resolveAgentRuntimeProfile(createOpts, presetObj);
|
|
212
214
|
const { profile } = resolved;
|
|
213
|
-
const route = resolveSessionRoute(
|
|
215
|
+
const route = resolveSessionRoute(createOpts, presetObj, profile);
|
|
214
216
|
const { providerName, modelName, provider, toolPreset, id } = route;
|
|
217
|
+
// Agent or coding mode (agent-mode.mjs), resolved once and persisted. An
|
|
218
|
+
// agent-mode Lead acts as its agent: a schedule/webhook run that names only
|
|
219
|
+
// its `ownerAgentId` gets that agent's role, persona and connector policy
|
|
220
|
+
// (all keyed by `session.agent`), as its home thread does.
|
|
221
|
+
const sessionMode = sessionModeOf({ ...createOpts, id });
|
|
222
|
+
const actingAgent = resolveSessionMode({ session: { ...createOpts, id } }).agentId;
|
|
223
|
+
const opts =
|
|
224
|
+
sessionMode === AGENT_MODE && !createOpts.agent && actingAgent
|
|
225
|
+
? { ...createOpts, agent: actingAgent, sessionMode }
|
|
226
|
+
: { ...createOpts, sessionMode };
|
|
215
227
|
const routeFallbacks = normalizeWorkflowRoute({
|
|
216
228
|
provider: providerName,
|
|
217
229
|
model: modelName,
|
|
@@ -227,7 +239,10 @@ export function createSession(opts) {
|
|
|
227
239
|
// Scoped to explicit-breakpoint (Anthropic-family) providers only.
|
|
228
240
|
const providerCacheOpts = resolved.providerCacheOpts || buildSessionProviderCacheOpts(providerName, id, opts.agent);
|
|
229
241
|
const surface = resolveSessionToolSurface(opts, { profile, toolPreset, modelName });
|
|
230
|
-
|
|
242
|
+
// The agent profile the prompt is composed from, read first: an edit landing
|
|
243
|
+
// during composition leaves the stamp behind, never ahead (refreshAgentProfile).
|
|
244
|
+
const agentProfile = surface.ownerIsAgent ? '' : agentProfileRevision(surface.resolvedAgent);
|
|
245
|
+
const prompt = composeSessionSystem(opts, { profile, providerName, modelName, surface, sessionMode });
|
|
231
246
|
const messages = seedSessionMessages(prompt, opts.files);
|
|
232
247
|
logSessionSurface(surface);
|
|
233
248
|
const contextMeta = resolveSessionContextMeta(provider, modelName, {
|
|
@@ -246,6 +261,11 @@ export function createSession(opts) {
|
|
|
246
261
|
origin: sessionOriginFields(opts, { profile, presetObj, providerCacheOpts, surface }),
|
|
247
262
|
});
|
|
248
263
|
session.providerCacheOptsOverride = Boolean(resolved.providerCacheOpts);
|
|
264
|
+
if (agentProfile) {
|
|
265
|
+
session.agentProfileRevision = agentProfile;
|
|
266
|
+
// The bot roster its prompt lists (a Lead's catalog slices).
|
|
267
|
+
session.agentRosterRevision = leadRosterRevision(opts.leadWorkflowParts);
|
|
268
|
+
}
|
|
249
269
|
if (routeFallbacks?.length) session.routeFallbacks = routeFallbacks;
|
|
250
270
|
// A non-native agent sends core + bridge, built from its filtered tools.
|
|
251
271
|
applyAgentToolExposure(session);
|
|
@@ -532,6 +552,8 @@ export async function resumeSession(sessionId, preset, options = {}) {
|
|
|
532
552
|
ensureCodexWireSessionId(session);
|
|
533
553
|
if (!_applyDesktopResumeScope(session, options)) return null;
|
|
534
554
|
if (!session.owner) session.owner = 'user';
|
|
555
|
+
// Records from before the mode existed get it resolved and stamped.
|
|
556
|
+
session.sessionMode = sessionModeOf(session);
|
|
535
557
|
if (Object.hasOwn(options, 'mcpScopeId')) {
|
|
536
558
|
session.mcpScopeId = String(options.mcpScopeId || '').trim() || null;
|
|
537
559
|
}
|