mixdog 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +52 -9
- package/README.md +8 -4
- package/package.json +2 -2
- package/scripts/native-release-status.mjs +238 -0
- package/src/defaults/shipped-history.json +8 -1
- package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
- package/src/defaults/skills/setup/SKILL.md +23 -1
- package/src/defaults/skills/setup/references/actions.md +54 -4
- package/src/defaults/skills/setup/references/surfaces.md +23 -3
- package/src/defaults/skills/setup-guide/SKILL.md +17 -10
- package/src/defaults/skills/visualize/SKILL.md +9 -6
- package/src/defaults/skills/visualize/references/craft.md +8 -1
- package/src/help.mjs +1 -1
- package/src/lib/keychain-cjs.cjs +4 -1
- package/src/lib/rules-builder.cjs +14 -7
- package/src/output-styles/common.md +13 -8
- package/src/rules/agent-mode/AGENT_MODE.md +9 -6
- package/src/rules/agent-mode/MIXY.md +11 -6
- package/src/rules/lead/LEAD.md +2 -2
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/20-research.md +2 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
- package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
- package/src/runtime/agent/orchestrator/config.mjs +11 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +81 -16
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -4
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +6 -10
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +80 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +67 -38
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +34 -16
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +19 -1
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -0
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -1
- package/src/runtime/agent/orchestrator/providers/mixdog-local.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +5 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +10 -2
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +30 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +14 -2
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
- package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +5 -5
- package/src/runtime/agent/orchestrator/runtime-core/route-context-state.mjs +81 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +12 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +17 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +41 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +21 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +149 -45
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +14 -11
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +68 -18
- package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
- package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +156 -25
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +21 -9
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +189 -105
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +111 -9
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -14
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +38 -5
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +46 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +99 -0
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +62 -47
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +6 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +42 -10
- package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +35 -4
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +179 -16
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +8 -3
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +36 -1
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +49 -14
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +134 -17
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +35 -13
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +6 -14
- package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +34 -21
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
- package/src/runtime/attachments/attachment-reference.mjs +155 -0
- package/src/runtime/attachments/limits.mjs +5 -1
- package/src/runtime/attachments/office-extract.mjs +3 -6
- package/src/runtime/attachments/pdf-extract.mjs +84 -10
- package/src/runtime/attachments/store.mjs +55 -30
- package/src/runtime/browser-bridge/client.mjs +73 -20
- package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
- package/src/runtime/channels/lib/scheduler.mjs +14 -7
- package/src/runtime/channels/lib/state-file.mjs +15 -15
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
- package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
- package/src/runtime/channels/lib/worker-main.mjs +3 -2
- package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
- package/src/runtime/effort-judge/judge-client.mjs +6 -3
- package/src/runtime/effort-judge/model-install.mjs +16 -8
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- package/src/runtime/local-provider/asset-installer.mjs +10 -4
- package/src/runtime/local-provider/catalog.mjs +5 -2
- package/src/runtime/local-provider/registered-models.mjs +64 -27
- package/src/runtime/local-provider/server.mjs +2 -3
- package/src/runtime/media/adapters/image-api.mjs +89 -0
- package/src/runtime/media/auth.mjs +64 -1
- package/src/runtime/media/catalog.mjs +66 -4
- package/src/runtime/media/jobs.mjs +4 -0
- package/src/runtime/media/lanes.mjs +46 -5
- package/src/runtime/media/media-usage.mjs +17 -0
- package/src/runtime/media/renditions.mjs +15 -15
- package/src/runtime/media/store.mjs +36 -35
- package/src/runtime/media/tool.mjs +8 -1
- package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
- package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
- package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
- package/src/runtime/memory/lib/pg/process.mjs +8 -4
- package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
- package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
- package/src/runtime/office/core/journal.mjs +7 -14
- package/src/runtime/office/design/library/design-library-core.mjs +4 -16
- package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
- package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
- package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
- package/src/runtime/office/pdf/pdf-render.mjs +30 -18
- package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +4 -0
- package/src/runtime/shared/agent-kind-migration.mjs +200 -0
- package/src/runtime/shared/agent-kind.mjs +152 -0
- package/src/runtime/shared/agent-message-envelope.d.mts +6 -0
- package/src/runtime/shared/agent-message-envelope.mjs +44 -0
- package/src/runtime/shared/agent-reap-state.d.mts +4 -0
- package/src/runtime/shared/agent-route-config.d.mts +1 -0
- package/src/runtime/shared/agent-route-config.mjs +22 -8
- package/src/runtime/shared/agent-store.mjs +149 -0
- package/src/runtime/shared/agent-task-starts.mjs +27 -0
- package/src/runtime/shared/atomic-file.d.mts +50 -0
- package/src/runtime/shared/atomic-file.mjs +394 -132
- package/src/runtime/shared/background-tasks.mjs +7 -4
- package/src/runtime/shared/bot-hops.mjs +30 -0
- package/src/runtime/shared/bot-split-migration.mjs +457 -0
- package/src/runtime/shared/bounded-download.mjs +4 -2
- package/src/runtime/shared/config-patch.mjs +20 -1
- package/src/runtime/shared/config.mjs +39 -9
- package/src/runtime/shared/connector-catalog.d.mts +1 -2
- package/src/runtime/shared/connector-catalog.mjs +2 -4
- package/src/runtime/shared/connector-triggers.mjs +2 -0
- package/src/runtime/shared/defaults-separation.mjs +6 -2
- package/src/runtime/shared/delegated-approval-host.mjs +74 -0
- package/src/runtime/shared/err-text.mjs +7 -1
- package/src/runtime/shared/error-presentation.mjs +113 -10
- package/src/runtime/shared/file-has-data.mjs +28 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
- package/src/runtime/shared/handoff-artifacts.mjs +61 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
- package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
- package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
- package/src/runtime/shared/model-route-fallback.mjs +79 -7
- package/src/runtime/shared/pending-agent-work.mjs +54 -0
- package/src/runtime/shared/plain-preview.mjs +22 -17
- package/src/runtime/shared/process-lifecycle.mjs +8 -12
- package/src/runtime/shared/projects.mjs +50 -41
- package/src/runtime/shared/provider-accounts.mjs +17 -12
- package/src/runtime/shared/routine-trigger.d.mts +6 -1
- package/src/runtime/shared/routine-trigger.mjs +14 -6
- package/src/runtime/shared/run-child.d.mts +3 -0
- package/src/runtime/shared/run-child.mjs +24 -3
- package/src/runtime/shared/sensitive-path-rules.d.mts +15 -0
- package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
- package/src/runtime/shared/session-baseline-store.mjs +8 -2
- package/src/runtime/shared/singleton-owner.mjs +7 -6
- package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
- package/src/runtime/shared/staged-update.mjs +4 -2
- package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
- package/src/runtime/shared/tool-execution-contract.mjs +6 -0
- package/src/runtime/shared/transcript-metadata.mjs +28 -3
- package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
- package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
- package/src/runtime/shared/turn-snapshot.mjs +44 -2
- package/src/runtime/shared/usage-readout-totals.mjs +15 -13
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +46 -44
- package/src/runtime/shared/utf8-cut.mjs +10 -0
- package/src/runtime/shared/worktrees/activity-gate.mjs +269 -61
- package/src/runtime/shared/worktrees/registry.mjs +26 -26
- package/src/runtime/tidy/core-install.mjs +26 -4
- package/src/runtime/tidy/install.mjs +91 -23
- package/src/runtime/web-search/lib/config.mjs +4 -16
- package/src/session-runtime/agent-home-delivery.mjs +859 -136
- package/src/session-runtime/agent-room-delivery.mjs +167 -19
- package/src/session-runtime/agent-task-sessions.mjs +831 -69
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +58 -24
- package/src/session-runtime/boot/config.mjs +1 -0
- package/src/session-runtime/boot/facade.mjs +11 -1
- package/src/session-runtime/boot/infrastructure.mjs +14 -2
- package/src/session-runtime/boot/providers.mjs +16 -6
- package/src/session-runtime/boot/shared.mjs +12 -6
- package/src/session-runtime/boot/tools.mjs +2 -2
- package/src/session-runtime/bot-status.mjs +432 -0
- package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
- package/src/session-runtime/config-lifecycle.mjs +78 -32
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/handoff-attachments.mjs +593 -0
- package/src/session-runtime/held-requests.mjs +36 -33
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +45 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown.mjs +11 -3
- package/src/session-runtime/mcp-glue/connect.mjs +100 -186
- package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
- package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
- package/src/session-runtime/media-api.mjs +5 -2
- package/src/session-runtime/model-route/route-persist.mjs +2 -2
- package/src/session-runtime/model-route/route-tuning.mjs +11 -2
- package/src/session-runtime/model-route/set-route.mjs +82 -2
- package/src/session-runtime/native-web-search.mjs +2 -2
- package/src/session-runtime/new-session-config.mjs +6 -1
- package/src/session-runtime/owned-automation-run.mjs +8 -1
- package/src/session-runtime/room-member-gate.mjs +16 -3
- package/src/session-runtime/route-resolution.mjs +21 -19
- package/src/session-runtime/route-state.mjs +1 -59
- package/src/session-runtime/routine-home-turn.mjs +5 -3
- package/src/session-runtime/runtime-bootstrap.mjs +5 -3
- package/src/session-runtime/runtime-paths.mjs +11 -5
- package/src/session-runtime/runtime-tunables.mjs +6 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +11 -2
- package/src/session-runtime/services/agent-tool/close-flow.mjs +4 -2
- package/src/session-runtime/services/agent-tool/execute-send.mjs +1 -0
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +1 -0
- package/src/session-runtime/services/agent-tool/helpers.mjs +24 -5
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +36 -24
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +12 -6
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +22 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +4 -6
- package/src/session-runtime/services/agent-tool.mjs +6 -0
- package/src/session-runtime/services/daemon-crash-capture/daemon-exit-record.mjs +1 -1
- package/src/session-runtime/services/daemon-crash-capture/retention.mjs +4 -3
- package/src/session-runtime/services/hook-bus/config-loader.mjs +14 -5
- package/src/session-runtime/services/hook-bus/rule-file.mjs +49 -11
- package/src/session-runtime/services/plugin-admin.mjs +26 -26
- package/src/session-runtime/services/provider-admin.mjs +14 -4
- package/src/session-runtime/services/schedule-access.mjs +33 -4
- package/src/session-runtime/services/seeds.mjs +4 -3
- package/src/session-runtime/services/usage-dashboard.mjs +1 -1
- package/src/session-runtime/services/usage-stats-model.mjs +2 -1
- package/src/session-runtime/session-create/materialize.mjs +2 -3
- package/src/session-runtime/session-create/session-options.mjs +15 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +63 -1
- package/src/session-runtime/settings-compaction-api.mjs +86 -39
- package/src/session-runtime/setup-tool/executor.mjs +20 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +19 -7
- package/src/session-runtime/setup-tool/settings-contract.mjs +37 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
- package/src/session-runtime/skills-api.mjs +12 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +265 -0
- package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
- package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
- package/src/session-runtime/tool-policy/policy-stage.mjs +165 -0
- package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
- package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
- package/src/session-runtime/tool-policy-refresh.mjs +47 -358
- package/src/session-runtime/tool-surface.mjs +5 -3
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +99 -81
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +2 -1
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +578 -301
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +113 -53
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
- package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
- package/src/session-runtime/workspace/workspace-state.mjs +7 -6
- package/src/standalone/daemon-agent-control.mjs +4 -1
- package/src/standalone/daemon-session-control.mjs +60 -11
- package/src/standalone/daemon.mjs +34 -4
- package/src/standalone/local-session-runtime.mjs +22 -14
- package/src/standalone/session-client.mjs +7 -2
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +46 -3
- package/src/standalone/session-service/agent-tree.mjs +4 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +19 -0
- package/src/standalone/session-service.mjs +11 -0
- package/src/standalone/session-state-projection.mjs +19 -9
- package/src/standalone/session-tool-output.mjs +35 -9
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
- package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
- package/src/tui/dist/index.mjs +599 -342
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/notice-surface.mjs +3 -4
- package/src/tui/session/session-api/intake/abort.mjs +19 -1
- package/src/tui/session/session-api/media.mjs +2 -1
- package/src/tui/session/session-api/routes-agent-definitions.mjs +75 -0
- package/src/tui/session/session-api/routes-write.mjs +203 -0
- package/src/tui/session/session-api/routes.mjs +23 -236
- package/src/tui/session/session-api/settings.mjs +14 -1
- package/src/tui/session/session-flow/drain.mjs +28 -3
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +4 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +8 -3
- package/src/tui/session/tool-approval.mjs +185 -20
- package/src/tui/session/transcript-intake.mjs +4 -0
- package/src/tui/session/turn-live-call.mjs +11 -3
- package/src/tui/session/turn.mjs +36 -17
- package/src/tui/transcript-tool-failures.mjs +8 -2
- package/src/vendor/statusline/src/gateway/route-meta.mjs +7 -8
- package/src/vendor/statusline/src/gateway/session-routes.mjs +6 -7
- package/src/rules/agent-mode/ROUTINE.md +0 -6
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from './native-web-search/tool-shape.mjs';
|
|
15
15
|
import { createWebSearchRouteCandidates } from './native-web-search/routes.mjs';
|
|
16
16
|
import { reportNativeWebSearchUsage } from './native-web-search-usage.mjs';
|
|
17
|
-
import {
|
|
17
|
+
import { canFallbackCapacityRoute } from '../runtime/shared/model-route-fallback.mjs';
|
|
18
18
|
|
|
19
19
|
export function createNativeWebSearch(deps) {
|
|
20
20
|
const {
|
|
@@ -103,7 +103,7 @@ export function createNativeWebSearch(deps) {
|
|
|
103
103
|
try {
|
|
104
104
|
return await sendCandidate(candidate, toolType, webSearchArgs, signal);
|
|
105
105
|
} catch (err) {
|
|
106
|
-
if (!
|
|
106
|
+
if (!canFallbackCapacityRoute(err, { signal })) throw err;
|
|
107
107
|
errors.push(
|
|
108
108
|
`${candidate.provider}${candidate.model ? `/${candidate.model}` : ''}/${toolType}: ${err?.message || String(err)}`
|
|
109
109
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
+
import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
2
3
|
import { flushPendingSessionConfigWrites } from './config-lifecycle.mjs';
|
|
3
4
|
|
|
4
5
|
// Run only after the lifecycle has established that it needs a NEW session.
|
|
@@ -27,7 +28,11 @@ export function createNewSessionConfig({
|
|
|
27
28
|
if (!initialConfig || typeof initialConfig !== 'object') {
|
|
28
29
|
reloadFullConfig();
|
|
29
30
|
if (!firstSession || !initialRouteExplicit) {
|
|
30
|
-
|
|
31
|
+
const configured = resolveRoute(rt.config, {});
|
|
32
|
+
// With no Lead model configured the model picked for this runtime's
|
|
33
|
+
// still-empty conversation (a session-only choice never writes the
|
|
34
|
+
// Lead route) stands; the reload must not drop it before the first turn.
|
|
35
|
+
if (clean(configured?.model) || !clean(rt.route?.model)) rt.route = configured;
|
|
31
36
|
}
|
|
32
37
|
}
|
|
33
38
|
invalidateOutputStyleStatusCache();
|
|
@@ -101,7 +101,7 @@ async function queueResult(row, item, entry, { deliver, recordDelivery, onDelive
|
|
|
101
101
|
/**
|
|
102
102
|
* `row` is `{ name, ownerAgentId }`; `run({ signal })` resolves `{ sessionId,
|
|
103
103
|
* result }` (`signal` is the caller's cancellation, if any). Resolves the
|
|
104
|
-
* outcome, or `{ skipped: true, reason: 'owner' | 'overlap' | 'backoff' }`
|
|
104
|
+
* outcome, or `{ skipped: true, reason: 'owner' | 'overlap' | 'backoff' | 'paused' }`
|
|
105
105
|
* (an owner skip also names `ownerProblem` and its `message`); a failed run
|
|
106
106
|
* rejects.
|
|
107
107
|
*/
|
|
@@ -141,6 +141,13 @@ export async function runOwnedAutomation(kind, row, run, deps = {}) {
|
|
|
141
141
|
const state = await Promise.resolve()
|
|
142
142
|
.then(() => record.state(name))
|
|
143
143
|
.catch(() => null);
|
|
144
|
+
// Switched off (by the user, or by the failure limit): the cron claim and
|
|
145
|
+
// the webhook handler already refuse it, but a one-shot timer or a
|
|
146
|
+
// dispatch that raced the pause must not run it either.
|
|
147
|
+
if (state?.enabled === false) {
|
|
148
|
+
log(`${kind} "${name}": skipped, switched off`);
|
|
149
|
+
return await skip('paused');
|
|
150
|
+
}
|
|
144
151
|
const wait = routineBackoffRemaining(state, now(), limits);
|
|
145
152
|
if (wait > 0) {
|
|
146
153
|
log(`${kind} "${name}": skipped, backing off ${Math.ceil(wait / 1000)}s after failures in a row`);
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
// anything that can change files or state asks the user through the ordinary
|
|
3
3
|
// approval flow, whatever the agent's own permission or hook rules say — even
|
|
4
4
|
// an agent that normally runs auto-approved. A hook's deny still wins.
|
|
5
|
+
// Opening a task session (`session create`) runs as freely as in the agent's
|
|
6
|
+
// home thread: it changes nothing itself, and the task session is the user's
|
|
7
|
+
// own coding Lead, whose every side effect follows its usual approval rules.
|
|
5
8
|
import { analyzeShellCommandEffects } from '../runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs';
|
|
6
9
|
|
|
7
10
|
const READ_ONLY_TOOLS = new Set([
|
|
@@ -37,12 +40,22 @@ export async function isReadOnlyRoomCall({ name, args, cwd }, analyze = analyzeS
|
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
/** Whether `name(args)` opens a task session (session create). */
|
|
44
|
+
export function isTaskSessionCreate({ name, args }) {
|
|
45
|
+
return (
|
|
46
|
+
name === 'session' &&
|
|
47
|
+
String(args?.action ?? '')
|
|
48
|
+
.trim()
|
|
49
|
+
.toLowerCase() === 'create'
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
/** The PreToolUse decision for a room member's call: the hook's own `decision`
|
|
41
|
-
* when it denies
|
|
42
|
-
* any rewrite the hook made. */
|
|
54
|
+
* when it denies, the call only reads, or it opens a task session; otherwise
|
|
55
|
+
* an approval ask that keeps any rewrite the hook made. */
|
|
43
56
|
export async function roomMemberToolDecision(call, decision, analyze) {
|
|
44
57
|
const action = String(decision?.action || decision?.decision || '').toLowerCase();
|
|
45
58
|
if (action === 'deny' || action === 'block') return decision;
|
|
46
|
-
if (await isReadOnlyRoomCall(call, analyze)) return decision;
|
|
59
|
+
if (isTaskSessionCreate(call) || (await isReadOnlyRoomCall(call, analyze))) return decision;
|
|
47
60
|
return { ...(decision && typeof decision === 'object' ? decision : {}), action: 'ask', reason: ROOM_APPROVAL_REASON };
|
|
48
61
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Route resolution against the live runtime record:
|
|
2
|
-
//
|
|
1
|
+
// Route resolution against the live runtime record: refuse a model-less first
|
|
2
|
+
// turn (no auto-pick) and refresh the route's effort / Fast / context
|
|
3
3
|
// fields from provider metadata.
|
|
4
4
|
import { ensureProviderEnabled } from '../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
|
|
5
5
|
import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
@@ -22,17 +22,15 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
|
|
|
22
22
|
if (routeHasModel()) return rt.route;
|
|
23
23
|
const models = await runAbortable(signal, () => collectProviderModels());
|
|
24
24
|
throwIfAborted(signal);
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
// A model chosen during the catalog read stands: a new task's reservation
|
|
26
|
+
// prewarm starts on the empty route, its draft model lands meanwhile, and
|
|
27
|
+
// the first prompt joins this very prewarm.
|
|
28
|
+
if (routeHasModel()) return rt.route;
|
|
29
|
+
if (!models?.length) {
|
|
27
30
|
throw new Error('No provider models available. Open /providers to sign in, then /model to choose a model.');
|
|
28
31
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
provider: picked.provider,
|
|
32
|
-
model: picked.id,
|
|
33
|
-
preset: null,
|
|
34
|
-
};
|
|
35
|
-
return rt.route;
|
|
32
|
+
// Never auto-pick: the user chooses the model.
|
|
33
|
+
throw new Error('No model selected. Choose a model with /model first.');
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
async function refreshRouteEffort(modelMetaOverride = null, expectedRoute = null, signal = null, lease = null) {
|
|
@@ -53,15 +51,19 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
|
|
|
53
51
|
.find((option) => option?.id === 'context')
|
|
54
52
|
?.options?.find((option) => clean(option?.value) === contextValue);
|
|
55
53
|
const modelDisplay = routeModelDisplay(rt.config, targetRoute, modelMeta);
|
|
56
|
-
|
|
54
|
+
// Without a known window the selection (share, exact tokens, resolved
|
|
55
|
+
// window) is kept as requested — the session sizes it from the provider's
|
|
56
|
+
// window; dropping it silently put the route back on the model's default.
|
|
57
|
+
// With one it is the clamped value, absent when it is the default window.
|
|
58
|
+
const windowKnown = contextState.contextDefaultPercent !== undefined;
|
|
59
|
+
const selectedContextWindow = [
|
|
60
|
+
contextState.selectedContextWindow,
|
|
61
|
+
contextOption?.contextWindow,
|
|
62
|
+
windowKnown ? undefined : targetRoute.selectedContextWindow,
|
|
63
|
+
]
|
|
57
64
|
.map(Number)
|
|
58
65
|
.find((value) => value > 0);
|
|
59
|
-
|
|
60
|
-
// one it is the clamped value, absent when it is the default window.
|
|
61
|
-
const contextTokens =
|
|
62
|
-
contextState.contextDefaultPercent === undefined
|
|
63
|
-
? normalizeContextTokens(targetRoute.contextTokens)
|
|
64
|
-
: contextState.contextTokens;
|
|
66
|
+
const contextTokens = windowKnown ? contextState.contextTokens : normalizeContextTokens(targetRoute.contextTokens);
|
|
65
67
|
const { contextTokens: _requestedTokens, ...routeFields } = targetRoute;
|
|
66
68
|
rt.route = {
|
|
67
69
|
...routeFields,
|
|
@@ -69,7 +71,7 @@ export function createRouteResolution({ rt, collectProviderModels, ensureProvide
|
|
|
69
71
|
fastCapable,
|
|
70
72
|
effectiveEffort,
|
|
71
73
|
effortOptions: effortItemsFor(rt.route.provider, modelMeta, effectiveEffort),
|
|
72
|
-
contextPercent: contextState.contextPercent,
|
|
74
|
+
contextPercent: windowKnown ? contextState.contextPercent : targetRoute.contextPercent,
|
|
73
75
|
contextDefaultPercent: contextState.contextDefaultPercent,
|
|
74
76
|
...(contextTokens ? { contextTokens } : {}),
|
|
75
77
|
...(selectedContextWindow ? { selectedContextWindow } : {}),
|
|
@@ -7,8 +7,6 @@ import {
|
|
|
7
7
|
import { clean, hasOwn } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
8
8
|
import { coerceEffortFor } from '../runtime/agent/orchestrator/runtime-core/effort.mjs';
|
|
9
9
|
import { fastCapableFor } from '../runtime/agent/orchestrator/runtime-core/model-capabilities.mjs';
|
|
10
|
-
import { providerCachedModelMetadataSync } from '../runtime/agent/orchestrator/providers/provider-catalog-cache.mjs';
|
|
11
|
-
import { contextWindowRange, normalizeContextTokens } from '../runtime/shared/llm/default-context-window.mjs';
|
|
12
10
|
|
|
13
11
|
export function resolveRouteEffortState(targetRoute = {}, modelMeta = null) {
|
|
14
12
|
const requested = hasOwn(targetRoute, 'effort') ? targetRoute.effort : targetRoute.preset?.effort || null;
|
|
@@ -36,63 +34,7 @@ export function selectionFastCapable(provider, modelMeta, effort, modelParameter
|
|
|
36
34
|
return !modelMetaLooksResolved(modelMeta) || fastCapableFor(provider, modelMeta, effort, modelParameters);
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
// slider against, so they carry both windows (openai-oauth: 272k default /
|
|
41
|
-
// 1M max). Reading them keeps a percentage saved against the picker's scale
|
|
42
|
-
// meaningful; anything that only knows a single window would silently rescale
|
|
43
|
-
// it (30% of 272k instead of 30% of 1M).
|
|
44
|
-
function cachedRouteWindows(provider, model) {
|
|
45
|
-
const row = providerCachedModelMetadataSync(provider, model)?.rawProviderModel || null;
|
|
46
|
-
if (!row) return null;
|
|
47
|
-
const contextWindow = Number(row.contextWindow ?? row.context_window ?? row.max_input_tokens) || 0;
|
|
48
|
-
const maxContextWindow = Number(row.maxContextWindow ?? row.max_context_window) || 0;
|
|
49
|
-
return contextWindow > 0 || maxContextWindow > 0 ? { contextWindow, maxContextWindow } : null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function resolveRouteContextState(targetRoute = {}, modelMeta = null, windowLookup = cachedRouteWindows) {
|
|
53
|
-
// Only providers that implement getCachedModelInfo (openai-oauth, cursor,
|
|
54
|
-
// openai-compat, opencode-go) hand lookupModelMeta a window; every other one
|
|
55
|
-
// (anthropic-oauth, grok-oauth, gemini, …) gets the bare `{ id, provider }`
|
|
56
|
-
// placeholder. Reading the window from that alone yields 0, which dropped the
|
|
57
|
-
// saved context percentage for the entire session — while resolveSessionContextMeta
|
|
58
|
-
// went on to size that session from the provider/catalog window (Claude Opus 5:
|
|
59
|
-
// a full 1M rather than the selected 500k). Read the cached provider row here so
|
|
60
|
-
// the percentage and the session boundary cannot disagree.
|
|
61
|
-
const windowMeta =
|
|
62
|
-
Number(modelMeta?.contextWindow) > 0 || Number(modelMeta?.maxContextWindow) > 0
|
|
63
|
-
? modelMeta
|
|
64
|
-
: windowLookup?.(clean(targetRoute?.provider), clean(targetRoute?.model)) || modelMeta;
|
|
65
|
-
const { defaultWindow, maxWindow } = contextWindowRange({
|
|
66
|
-
provider: clean(targetRoute?.provider),
|
|
67
|
-
contextWindow: windowMeta?.contextWindow,
|
|
68
|
-
maxContextWindow: windowMeta?.maxContextWindow,
|
|
69
|
-
});
|
|
70
|
-
if (!maxWindow) {
|
|
71
|
-
return { contextPercent: undefined, contextDefaultPercent: undefined, selectedContextWindow: undefined };
|
|
72
|
-
}
|
|
73
|
-
const contextDefaultPercent = Math.max(10, Math.min(100, Math.round((defaultWindow / maxWindow) * 10) * 10));
|
|
74
|
-
// An exact token selection overrides the 10% stops. It is clamped to the
|
|
75
|
-
// selectable range; one that lands on the default window is the default.
|
|
76
|
-
const requestedTokens = normalizeContextTokens(targetRoute?.contextTokens);
|
|
77
|
-
if (requestedTokens) {
|
|
78
|
-
const contextTokens = Math.max(Math.ceil(maxWindow * 0.1), Math.min(maxWindow, requestedTokens));
|
|
79
|
-
if (contextTokens === defaultWindow) {
|
|
80
|
-
return { contextPercent: contextDefaultPercent, contextDefaultPercent, selectedContextWindow: defaultWindow };
|
|
81
|
-
}
|
|
82
|
-
const contextPercent = Math.max(10, Math.min(100, Math.round((contextTokens / maxWindow) * 10) * 10));
|
|
83
|
-
return { contextPercent, contextDefaultPercent, selectedContextWindow: contextTokens, contextTokens };
|
|
84
|
-
}
|
|
85
|
-
const requested = Number(targetRoute?.contextPercent);
|
|
86
|
-
const contextPercent =
|
|
87
|
-
Number.isFinite(requested) && requested > 0
|
|
88
|
-
? Math.max(10, Math.min(100, Math.round(requested / 10) * 10))
|
|
89
|
-
: contextDefaultPercent;
|
|
90
|
-
const selectedContextWindow =
|
|
91
|
-
contextPercent === contextDefaultPercent
|
|
92
|
-
? defaultWindow
|
|
93
|
-
: Math.max(1, Math.floor((maxWindow * contextPercent) / 100));
|
|
94
|
-
return { contextPercent, contextDefaultPercent, selectedContextWindow };
|
|
95
|
-
}
|
|
37
|
+
export { resolveRouteContextState } from '../runtime/agent/orchestrator/runtime-core/route-context-state.mjs';
|
|
96
38
|
|
|
97
39
|
/**
|
|
98
40
|
* Human label for the statusline. A display-only user alias
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
* it rides the thread's queue as its own `routine` entry (one per turn, never
|
|
10
10
|
* merged or steered into another), shows as a routine marker row, and selects
|
|
11
11
|
* skills only from the routine's instructions (`skillSelection`), never from a
|
|
12
|
-
* webhook payload. While it runs the thread counts as unattended
|
|
13
|
-
*
|
|
12
|
+
* webhook payload. While it runs the thread counts as an unattended run
|
|
13
|
+
* (held-requests.mjs): the saved routine is the user's grant, so it never asks
|
|
14
|
+
* (outbound actions are allowed within the bot's permissions; payments and
|
|
15
|
+
* permanent deletes are refused, human-gate/run-policy.mjs). Resolves with the
|
|
14
16
|
* reply once the turn ends; rejects when the turn fails, is cancelled, or the
|
|
15
17
|
* caller's `signal` aborts (which also aborts the turn once it runs).
|
|
16
18
|
*/
|
|
@@ -126,7 +128,7 @@ export async function runRoutineTurn(
|
|
|
126
128
|
onCommitted: () => {
|
|
127
129
|
if (started) return;
|
|
128
130
|
started = true;
|
|
129
|
-
// Nobody watches this turn:
|
|
131
|
+
// Nobody watches this turn: it never asks (run-policy.mjs).
|
|
130
132
|
unmark = markUnattendedRun(homeId, { kind, agentId, name });
|
|
131
133
|
if (aborted) void abortTurn();
|
|
132
134
|
},
|
|
@@ -13,22 +13,24 @@ import {
|
|
|
13
13
|
CODE_GRAPH_TOOL_DEFS,
|
|
14
14
|
STATUSLINE_SESSION_ROUTES,
|
|
15
15
|
STANDALONE_ROOT,
|
|
16
|
-
|
|
16
|
+
standaloneDataDir,
|
|
17
17
|
} from './runtime-paths.mjs';
|
|
18
18
|
|
|
19
19
|
export function prepareStandaloneEnvironment() {
|
|
20
20
|
process.env.MIXDOG_QUIET_SESSION_LOG ??= '1';
|
|
21
21
|
const startedAt = performance.now();
|
|
22
|
+
// Resolved per runtime start: this start's data folder, not the first one's.
|
|
23
|
+
const dataDir = standaloneDataDir();
|
|
22
24
|
ensureStandaloneEnvironment({
|
|
23
25
|
rootDir: STANDALONE_ROOT,
|
|
24
|
-
dataDir
|
|
26
|
+
dataDir,
|
|
25
27
|
});
|
|
26
28
|
// Office journals exist only for cross-process crash recovery, so startup just
|
|
27
29
|
// prunes expired ones in the background. Surfacing them as session context made
|
|
28
30
|
// every new session (agents included) re-announce unrelated leftovers for the
|
|
29
31
|
// full 30-day retention window; recovery stays reachable on demand through
|
|
30
32
|
// office action=transactions / action=recover.
|
|
31
|
-
listOfficeJournals(
|
|
33
|
+
listOfficeJournals(dataDir).catch(() => {});
|
|
32
34
|
bootProfile('standalone-env:ready', { ms: (performance.now() - startedAt).toFixed(1) });
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dirname, join } from 'node:path';
|
|
1
|
+
import { dirname } from 'node:path';
|
|
3
2
|
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { resolvePluginData } from '../runtime/shared/plugin-paths.mjs';
|
|
4
4
|
|
|
5
5
|
export const RUNTIME = '../runtime/agent/orchestrator';
|
|
6
6
|
export const WEB_SEARCH_RUNTIME = '../runtime/web-search/index.mjs';
|
|
@@ -12,10 +12,16 @@ export const STATUSLINE_SESSION_ROUTES = '../vendor/statusline/src/gateway/sessi
|
|
|
12
12
|
|
|
13
13
|
const SESSION_RUNTIME_DIR = dirname(fileURLToPath(import.meta.url));
|
|
14
14
|
export const STANDALONE_ROOT = dirname(SESSION_RUNTIME_DIR);
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The standalone data directory, resolved from the environment on every call.
|
|
18
|
+
* A runtime start (a pristine boundary, a second page session) retargets
|
|
19
|
+
* MIXDOG_DATA_DIR, so a load-time constant would point every later start back
|
|
20
|
+
* at the first run's folder.
|
|
21
|
+
*/
|
|
22
|
+
export const standaloneDataDir = resolvePluginData;
|
|
17
23
|
|
|
18
24
|
/** The data directory a runtime writes to: its config module's plugin data dir, else the standalone default. */
|
|
19
25
|
export function pluginDataDir(cfgMod) {
|
|
20
|
-
return cfgMod.getPluginData?.() ||
|
|
26
|
+
return cfgMod.getPluginData?.() || standaloneDataDir();
|
|
21
27
|
}
|
|
@@ -36,6 +36,12 @@ export function readRuntimeTunables() {
|
|
|
36
36
|
// connected tools fold synchronously; in-flight servers join through the
|
|
37
37
|
// late-tool announcement path. Operators may opt back into a grace window.
|
|
38
38
|
mcpTurnGraceMs: envDelayMs('MIXDOG_MCP_TURN_GRACE_MS', 0, { min: 0, max: 2_000 }),
|
|
39
|
+
// A spawned agent's first turn may be its only one, so it waits for the
|
|
40
|
+
// initial connect — but only this long: a slow-but-alive server (a
|
|
41
|
+
// 20 s handshake is seen in the wild) must not hold the first model
|
|
42
|
+
// request for its whole startup budget. Later servers join through the
|
|
43
|
+
// late-tool announcement path on the agent's next turn.
|
|
44
|
+
mcpAgentGraceMs: envDelayMs('MIXDOG_MCP_AGENT_GRACE_MS', 3_000, { min: 0, max: 30_000 }),
|
|
39
45
|
// Boot-time remote start is deferred past the first frame; see the caller.
|
|
40
46
|
remoteAutoStartDelayMs: envDelayMs('MIXDOG_REMOTE_AUTOSTART_DELAY_MS', 1_500, { min: 0, max: 60_000 }),
|
|
41
47
|
providerWarmupEnabled:
|
|
@@ -5,6 +5,7 @@ import { cancelBackgroundTask, listBackgroundTasks } from '../../../../runtime/s
|
|
|
5
5
|
import { presentErrorText } from '../../../../runtime/shared/err-text.mjs';
|
|
6
6
|
import { clean } from '../helpers.mjs';
|
|
7
7
|
import { isLeadPoolAgent } from '../worker-rows.mjs';
|
|
8
|
+
import { isUnnotifiedRestartFailure } from '../worker-index/row-liveness.mjs';
|
|
8
9
|
|
|
9
10
|
export function createCloseAll({ registry, close }) {
|
|
10
11
|
const { tags, tagAgents, tagCwds } = registry;
|
|
@@ -17,11 +18,13 @@ export function createCloseAll({ registry, close }) {
|
|
|
17
18
|
|
|
18
19
|
// Drop the closed workers' rows: every non-Lead row for an unscoped
|
|
19
20
|
// teardown, only this owner's (plus the rows just closed) for a scoped one.
|
|
21
|
+
// A row whose owner is still owed its restart failure stays (a process exit
|
|
22
|
+
// closes every worker; the next process tells the owner).
|
|
20
23
|
function purgeWorkerRows(ownerSessionId, closedSessionIds) {
|
|
21
24
|
registry.flushWorkerIndexMutations();
|
|
22
25
|
registry.writeWorkerRows((byKey, tombstonesByKey) => {
|
|
23
26
|
for (const [key, row] of [...byKey.entries()]) {
|
|
24
|
-
if (isLeadPoolAgent(row.agent)) continue;
|
|
27
|
+
if (isLeadPoolAgent(row.agent) || isUnnotifiedRestartFailure(row)) continue;
|
|
25
28
|
if (
|
|
26
29
|
ownerSessionId &&
|
|
27
30
|
clean(row.ownerSessionId) !== ownerSessionId &&
|
|
@@ -38,15 +41,20 @@ export function createCloseAll({ registry, close }) {
|
|
|
38
41
|
// Lead's workers: the worker index and task registry are shared by every
|
|
39
42
|
// Lead in the process, and an unscoped sweep wiped sibling Leads' idle
|
|
40
43
|
// workers mid-window.
|
|
44
|
+
// A process exit (`scope.processExit`) closes the workers but keeps their
|
|
45
|
+
// rows: the next process lists the finished ones for their pane window and
|
|
46
|
+
// settles the ones the exit cut off (restart-notify), exactly as after a
|
|
47
|
+
// crash. Dropping them emptied every sub-agent list after a daemon restart.
|
|
41
48
|
return async function closeAll(reason = 'cli-agent-close-all', scope = {}) {
|
|
42
49
|
const ownerSessionId = clean(scope.callerSessionId);
|
|
50
|
+
const keepRows = scope.processExit === true;
|
|
43
51
|
const context = ownerSessionId ? { callerSessionId: ownerSessionId } : {};
|
|
44
52
|
registry.refreshTagsFromSessions({ scanSessions: false, context });
|
|
45
53
|
const closed = [];
|
|
46
54
|
const failed = [];
|
|
47
55
|
for (const { tag, session } of registry.agentSessionEntries({ scanSessions: false, context })) {
|
|
48
56
|
try {
|
|
49
|
-
closed.push(await close({ sessionId: session.id }, context));
|
|
57
|
+
closed.push(await close({ sessionId: session.id }, context, { keepRow: keepRows }));
|
|
50
58
|
} catch (err) {
|
|
51
59
|
failed.push({ tag, error: presentErrorText(err, { surface: 'agent' }) });
|
|
52
60
|
}
|
|
@@ -57,6 +65,7 @@ export function createCloseAll({ registry, close }) {
|
|
|
57
65
|
closed.push({ closed: true, tag: task.tag || null, sessionId: task.sessionId || null, task_id: task.task_id });
|
|
58
66
|
}
|
|
59
67
|
if (!ownerSessionId) resetLocalTagState();
|
|
68
|
+
if (keepRows) return { closed, failed };
|
|
60
69
|
const closedSessionIds = new Set(closed.map((row) => clean(row.sessionId)).filter(Boolean));
|
|
61
70
|
purgeWorkerRows(ownerSessionId, closedSessionIds);
|
|
62
71
|
return { closed, failed };
|
|
@@ -37,7 +37,9 @@ export function createCloseFlow({ mgr, registry, views }) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
/** `keepRow`: a process exit closes the worker but leaves its row (and its
|
|
41
|
+
* descendants') for the next process (close-all.mjs). */
|
|
42
|
+
async function close(args, context = {}, { keepRow = false } = {}) {
|
|
41
43
|
const scopedContext = agentScope(args, context);
|
|
42
44
|
registry.refreshTagsFromSessions({ scanSessions: registry.wantsSessionScan(args), context: scopedContext });
|
|
43
45
|
const taskId = taskIdFromArgs(args);
|
|
@@ -73,7 +75,7 @@ export function createCloseFlow({ mgr, registry, views }) {
|
|
|
73
75
|
if (task?.taskId) cancelBackgroundTask(task.taskId, CLOSE_REASON);
|
|
74
76
|
// Drop the row only once the cancellation is DURABLY recorded: a failed
|
|
75
77
|
// close that still forgot the row would leave no cancelled state behind.
|
|
76
|
-
if (ok) {
|
|
78
|
+
if (ok && !keepRow) {
|
|
77
79
|
registry.forgetTerminalSession(tag, sessionId);
|
|
78
80
|
for (const descendantSessionId of descendantSessionIds) {
|
|
79
81
|
registry.removeWorkerRow({ sessionId: descendantSessionId });
|
|
@@ -70,6 +70,7 @@ export function createSendDispatch({ registry, defaultCwd, sendFlow, spawnFlow,
|
|
|
70
70
|
async function send(args, { scopedContext, callerCwd, context, notifyContext }) {
|
|
71
71
|
try {
|
|
72
72
|
const prepared = await sendFlow.prepareSend(args, scopedContext);
|
|
73
|
+
await sendFlow.adoptCaller(prepared, notifyContext);
|
|
73
74
|
return sendFlow.dispatchToExistingSession(prepared, notifyContext);
|
|
74
75
|
} catch (err) {
|
|
75
76
|
return await respawnDeadTagSend(err, args, { callerCwd, context, notifyContext });
|
|
@@ -51,6 +51,7 @@ export function createSpawnDispatch({
|
|
|
51
51
|
}
|
|
52
52
|
if (liveSessionId && registry.getLiveSession(liveSessionId)) {
|
|
53
53
|
const prepared = await sendFlow.prepareSend({ ...args, tag: explicitTag }, scopedContext);
|
|
54
|
+
await sendFlow.adoptCaller(prepared, notifyContext);
|
|
54
55
|
const route = requestedRoute(args);
|
|
55
56
|
return {
|
|
56
57
|
reused: sendFlow.dispatchToExistingSession(route ? { ...prepared, route } : prepared, notifyContext, {
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
import { PRESET_ALIASES } from './tool-def.mjs';
|
|
13
13
|
import { positiveInt } from '../../../runtime/shared/numbers.mjs';
|
|
14
14
|
import { clean } from '../../../runtime/shared/clean.mjs';
|
|
15
|
+
import { readAgentDefinitionKind } from '../../../runtime/shared/agent-kind.mjs';
|
|
16
|
+
import { isStoreBot, userDefinitionDir } from '../../../runtime/shared/agent-store.mjs';
|
|
15
17
|
import { normalizeContextTokens } from '../../../runtime/shared/llm/default-context-window.mjs';
|
|
16
18
|
|
|
17
19
|
export { positiveInt };
|
|
@@ -300,13 +302,18 @@ const _frontmatterPermCache = new Map(); // key -> { value, atMs }
|
|
|
300
302
|
const FRONTMATTER_PERM_CACHE_TTL_MS = envTimeoutMs('MIXDOG_AGENT_FRONTMATTER_TTL_MS', 5_000);
|
|
301
303
|
|
|
302
304
|
function agentDeleted(cleanAgent, dataDir) {
|
|
303
|
-
return Boolean(dataDir) && existsSync(join(dataDir,
|
|
305
|
+
return Boolean(dataDir) && existsSync(join(userDefinitionDir(dataDir, cleanAgent), '.deleted'));
|
|
304
306
|
}
|
|
305
307
|
|
|
306
308
|
/** Where an agent's definition may live, in precedence order: the data dir
|
|
307
309
|
* (user/custom agents) before the shipped source root. */
|
|
308
310
|
function agentDefinitionFiles(cleanAgent, dataDir, standaloneSourceRoot) {
|
|
309
311
|
const candidates = [];
|
|
312
|
+
if (dataDir && isStoreBot(dataDir, cleanAgent)) {
|
|
313
|
+
// A bot of the store: only its own folder (never the agents/ original).
|
|
314
|
+
candidates.push(join(userDefinitionDir(dataDir, cleanAgent), 'AGENT.md'));
|
|
315
|
+
return candidates;
|
|
316
|
+
}
|
|
310
317
|
if (dataDir) {
|
|
311
318
|
candidates.push(join(dataDir, 'agents', cleanAgent, 'AGENT.md'));
|
|
312
319
|
candidates.push(join(dataDir, 'agents', `${cleanAgent}.md`));
|
|
@@ -353,13 +360,25 @@ export function readAgentFrontmatterPermission(agent, dataDir, standaloneSourceR
|
|
|
353
360
|
}
|
|
354
361
|
|
|
355
362
|
const _frontmatterKindCache = new Map(); // key -> { value, atMs }
|
|
363
|
+
const _frontmatterKindValueCache = new Map(); // key -> { value, atMs }
|
|
356
364
|
|
|
357
|
-
/** The agent definition's
|
|
358
|
-
*
|
|
365
|
+
/** The agent definition's kind (isContactAgentId reads it), by the one
|
|
366
|
+
* read-only rule (agent-kind.mjs), cached per agent for the frontmatter TTL. */
|
|
359
367
|
export function readAgentFrontmatterKind(agent, dataDir, standaloneSourceRoot) {
|
|
360
|
-
|
|
361
|
-
|
|
368
|
+
const id = clean(agent);
|
|
369
|
+
if (!id || agentDeleted(id, dataDir)) return null;
|
|
370
|
+
const cacheKey = `${dataDir}\u0000${id}`;
|
|
371
|
+
const cached = _frontmatterKindCache.get(cacheKey);
|
|
372
|
+
if (cached && Date.now() - cached.atMs < FRONTMATTER_PERM_CACHE_TTL_MS) return cached.value;
|
|
373
|
+
// An explicit kind in the definition in effect (any layout) wins; only an
|
|
374
|
+
// unmarked user copy goes to the evidence rule.
|
|
375
|
+
const explicit = cachedFrontmatterValue(_frontmatterKindValueCache, id, dataDir, standaloneSourceRoot, (fm) =>
|
|
376
|
+
typeof fm.kind === 'string' && fm.kind.trim() ? fm.kind.trim().toLowerCase() : null
|
|
362
377
|
);
|
|
378
|
+
const value =
|
|
379
|
+
explicit || (dataDir ? readAgentDefinitionKind({ dataDir, shippedRoot: standaloneSourceRoot, id }) : null);
|
|
380
|
+
_frontmatterKindCache.set(cacheKey, { value, atMs: Date.now() });
|
|
381
|
+
return value;
|
|
363
382
|
}
|
|
364
383
|
|
|
365
384
|
/** The agent definition's `firstResponseTimeoutMs` (a non-negative integer;
|
|
@@ -28,6 +28,16 @@ export function restartNotificationId(row) {
|
|
|
28
28
|
return `restart:${clean(row.task_id) || `${clean(row.sessionId)}:${clean(row.finishedAt)}`}`;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/** The agent task id an execution id names: a task's own id, or the task a
|
|
32
|
+
* restart notification (restartNotificationId) reports; null for one keyed
|
|
33
|
+
* by session because its row recorded no task id. */
|
|
34
|
+
export function agentTaskIdOfExecution(executionId) {
|
|
35
|
+
const id = clean(executionId);
|
|
36
|
+
if (!id.startsWith('restart:')) return id || null;
|
|
37
|
+
const rest = id.slice('restart:'.length);
|
|
38
|
+
return rest && !rest.includes(':') ? rest : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
31
41
|
/** `pendingRestartFailures()` lists rows whose owner is not yet told;
|
|
32
42
|
* `markRestartNotified(rows)` stamps them. `mgr` supplies the persisted
|
|
33
43
|
* pending queue (enqueuePendingMessage / markCompletionEntry /
|
|
@@ -16,7 +16,14 @@ import {
|
|
|
16
16
|
terminalResultHook,
|
|
17
17
|
} from './job-task-reconcile.mjs';
|
|
18
18
|
import { createTurnReviewCollector } from './turn-review.mjs';
|
|
19
|
+
import { handoffContent } from '../../handoff-attachments.mjs';
|
|
20
|
+
import { rebindDelegation } from '../../../runtime/agent/orchestrator/session/human-gate/delegation.mjs';
|
|
19
21
|
import { settledWorkerStatus } from './worker-index/row-liveness.mjs';
|
|
22
|
+
import { whileTurnDispatched } from '../../../runtime/agent/orchestrator/session/manager/runtime-state.mjs';
|
|
23
|
+
|
|
24
|
+
function workerResultIdentity({ session, tag, sessionId }) {
|
|
25
|
+
return { tag, sessionId, agent: session.agent || null, provider: session.provider, model: session.model };
|
|
26
|
+
}
|
|
20
27
|
|
|
21
28
|
// `send` to an existing worker: resolve the live session, run one follow-up
|
|
22
29
|
// turn under the progress watchdog, and reconcile the job/worker row. Busy
|
|
@@ -41,11 +48,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
41
48
|
return (result) => {
|
|
42
49
|
const abnormalError = abnormalEmptyFinishError(result, session.agent || sendAgent);
|
|
43
50
|
return {
|
|
44
|
-
tag,
|
|
45
|
-
sessionId,
|
|
46
|
-
agent: session.agent || null,
|
|
47
|
-
provider: session.provider,
|
|
48
|
-
model: session.model,
|
|
51
|
+
...workerResultIdentity({ session, tag, sessionId }),
|
|
49
52
|
content: result?.content || '',
|
|
50
53
|
...(sessionSurface?.canonical === true ? { handoffOnly: true } : {}),
|
|
51
54
|
...(abnormalError ? { error: abnormalError } : {}),
|
|
@@ -69,12 +72,16 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
69
72
|
return hooks;
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
function runTurn({ session, sessionId, prompt, args }, turnHooks) {
|
|
75
|
+
function runTurn({ session, sessionId, prompt: text, args }, turnHooks) {
|
|
73
76
|
const cwd = session.cwd || defaultCwd;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
// The caller's forwarded files ride along as attachment parts.
|
|
78
|
+
const prompt = handoffContent(text, args.attachmentParts);
|
|
79
|
+
return whileTurnDispatched(sessionId, () => {
|
|
80
|
+
if (canUseSessionSurface(session)) {
|
|
81
|
+
return sessionSurface.runTurn({ session, prompt, context: args.context || null, cwd, ...turnHooks });
|
|
82
|
+
}
|
|
83
|
+
return mgr.askSession(sessionId, prompt, args.context || null, null, cwd, null, turnHooks);
|
|
84
|
+
});
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
async function runSend(prepared, notifyContext = null, job = null) {
|
|
@@ -107,11 +114,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
107
114
|
const settleCancelled = (error, result = null) => {
|
|
108
115
|
finalStatus = 'cancelled';
|
|
109
116
|
reconcileJobCancelled(job, {
|
|
110
|
-
tag,
|
|
111
|
-
sessionId,
|
|
112
|
-
agent: session.agent || null,
|
|
113
|
-
provider: session.provider,
|
|
114
|
-
model: session.model,
|
|
117
|
+
...workerResultIdentity({ session, tag, sessionId }),
|
|
115
118
|
content: turnPartialHandoff(error, mgr.getSession(sessionId), handoffMsgStart) || result?.content || '',
|
|
116
119
|
});
|
|
117
120
|
};
|
|
@@ -142,11 +145,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
142
145
|
if (partial) {
|
|
143
146
|
finalStatus = 'idle';
|
|
144
147
|
const value = {
|
|
145
|
-
tag,
|
|
146
|
-
sessionId,
|
|
147
|
-
agent: session.agent || null,
|
|
148
|
-
provider: session.provider,
|
|
149
|
-
model: session.model,
|
|
148
|
+
...workerResultIdentity({ session, tag, sessionId }),
|
|
150
149
|
content: watchdogStoppedHandoff(error, partial),
|
|
151
150
|
stallAbort: true,
|
|
152
151
|
};
|
|
@@ -161,7 +160,7 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
161
160
|
turnReview.complete();
|
|
162
161
|
watchdog?.stop?.();
|
|
163
162
|
registry.upsertWorkerSessionDeferred(session, tag, {
|
|
164
|
-
...settledWorkerStatus(finalStatus, stalled),
|
|
163
|
+
...settledWorkerStatus(finalStatus, stalled, job),
|
|
165
164
|
finishedAt: new Date().toISOString(),
|
|
166
165
|
});
|
|
167
166
|
reconcileJobFinally(job, finalStatus);
|
|
@@ -185,6 +184,14 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
185
184
|
return { ...prepared, session: mgr.getSession(sessionId) || session };
|
|
186
185
|
}
|
|
187
186
|
|
|
187
|
+
// The calling session hands this worker new work (a `send`, or a spawn of its
|
|
188
|
+
// tag): from now on the worker acts as that caller does, so a run's worker
|
|
189
|
+
// asks when the attended chat reuses it and the other way round. Not for a
|
|
190
|
+
// completion wake, which is the worker's own continuation.
|
|
191
|
+
function adoptCaller({ sessionId }, notifyContext) {
|
|
192
|
+
return rebindDelegation(sessionId, notifyContext?.callerSessionId);
|
|
193
|
+
}
|
|
194
|
+
|
|
188
195
|
// Shared send dispatch for an already-resolved live session. Used by the
|
|
189
196
|
// `send` branch AND by the `spawn` branch when an explicit tag maps to a
|
|
190
197
|
// live session (reuse path). Busy sessions queue the prompt; idle ones run a
|
|
@@ -194,7 +201,11 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
194
201
|
const { session, sessionId, prompt } = prepared;
|
|
195
202
|
const tag = registry.tagForSession(sessionId);
|
|
196
203
|
if (canUseSessionSurface(session) && views.isSessionBusy(sessionId)) {
|
|
197
|
-
const queued = await sessionSurface.enqueueTurn({
|
|
204
|
+
const queued = await sessionSurface.enqueueTurn({
|
|
205
|
+
session,
|
|
206
|
+
prompt: handoffContent(prompt, prepared.args.attachmentParts),
|
|
207
|
+
context: prepared.args.context || null,
|
|
208
|
+
});
|
|
198
209
|
if (queued) {
|
|
199
210
|
return renderResult({ queued: true, ...extras, tag, sessionId, agent: session.agent || null, ...queued });
|
|
200
211
|
}
|
|
@@ -204,7 +215,8 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
204
215
|
views.isSessionBusy(sessionId) &&
|
|
205
216
|
typeof mgr.enqueuePendingMessage === 'function'
|
|
206
217
|
) {
|
|
207
|
-
|
|
218
|
+
// The queued follow-up keeps the forwarded files, as the canonical queue does.
|
|
219
|
+
const queueDepth = mgr.enqueuePendingMessage(sessionId, handoffContent(prompt, prepared.args.attachmentParts));
|
|
208
220
|
return renderResult({ queued: true, ...extras, tag, sessionId, agent: session.agent || null, queueDepth });
|
|
209
221
|
}
|
|
210
222
|
const job = spawnFlow.startJob(
|
|
@@ -247,5 +259,5 @@ export function createSendFlow({ mgr, defaultCwd, sessionSurface, canUseSessionS
|
|
|
247
259
|
return true;
|
|
248
260
|
}
|
|
249
261
|
|
|
250
|
-
return { prepareSend, dispatchToExistingSession, wakeIdleWorker };
|
|
262
|
+
return { prepareSend, adoptCaller, dispatchToExistingSession, wakeIdleWorker };
|
|
251
263
|
}
|