mixdog 1.3.5 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +2 -2
- package/README.md +2 -2
- package/package.json +2 -11
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/gate-local.mjs +16 -5
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +37 -37
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +123 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -4
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +20 -2
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +7 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/app.mjs +4 -0
- package/src/defaults/shipped-history.json +22 -1
- package/src/defaults/skills/browser-use/SKILL.md +62 -12
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +35 -9
- package/src/defaults/skills/setup/SKILL.md +22 -0
- package/src/defaults/skills/setup/references/actions.md +39 -5
- package/src/defaults/skills/setup/references/surfaces.md +11 -2
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/rules-builder.cjs +39 -20
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +11 -10
- package/src/rules/lead/LEAD.md +23 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/rules/shared/70-delivery.md +7 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +17 -1
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
- package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +20 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +49 -16
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +49 -21
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +24 -14
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +130 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +79 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/scheduler.mjs +33 -147
- package/src/runtime/channels/lib/schedules-db.mjs +34 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/whisper-port.mjs +10 -1
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +10 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +28 -2
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +2 -13
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +29 -0
- package/src/runtime/shared/connector-catalog.mjs +150 -0
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -17
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +126 -0
- package/src/runtime/shared/llm/cost.mjs +5 -1
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +7 -1
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +10 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +48 -1
- package/src/runtime/shared/session-scratch.mjs +37 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +2 -15
- package/src/runtime/shared/tool-surface.mjs +3 -0
- package/src/runtime/shared/tool-work-units.mjs +2 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +15 -0
- package/src/runtime/shared/worktrees/manager.mjs +87 -38
- package/src/runtime/shared/worktrees/test-support.mjs +14 -13
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +29 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +489 -185
- package/src/session-runtime/agent-task-sessions.mjs +467 -229
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +11 -2
- package/src/session-runtime/bot-status.mjs +12 -6
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +271 -25
- package/src/session-runtime/conversation-import/service.mjs +26 -5
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +153 -33
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +2 -1
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -2
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +7 -13
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/provider-admin.mjs +2 -1
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +1 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +13 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +145 -22
- package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workspace/transitions.mjs +25 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +142 -190
- package/src/standalone/daemon.mjs +26 -3
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +30 -2
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-tool-output.mjs +15 -7
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/app/app-view/floating-panel.jsx +7 -4
- package/src/tui/app/model-options.mjs +3 -28
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +9 -5
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/dist/index.mjs +133 -92
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +7 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +17 -1
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +16 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +19 -2
- package/src/tui/session/turn.mjs +1 -0
- package/src/ui/statusline-agents.mjs +1 -3
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -453,8 +453,9 @@ function callArgs(call) {
|
|
|
453
453
|
return args && typeof args === 'object' ? args : {};
|
|
454
454
|
}
|
|
455
455
|
|
|
456
|
-
/** The paths one tool call wrote or produced
|
|
457
|
-
|
|
456
|
+
/** The paths one tool call wrote or produced; `written`: only those it
|
|
457
|
+
* actually created or modified (opening a file in visualize does neither). */
|
|
458
|
+
function toolCallOutputs(call, written) {
|
|
458
459
|
const name = String(call?.function?.name || call?.name || '');
|
|
459
460
|
const args = callArgs(call);
|
|
460
461
|
const text = (value) => (typeof value === 'string' && value.trim() ? [value.trim()] : []);
|
|
@@ -464,7 +465,7 @@ function toolCallOutputs(call) {
|
|
|
464
465
|
if (name === 'office') return OFFICE_WRITE_ACTIONS.has(args.action) ? [...text(args.output), ...text(args.path)] : [];
|
|
465
466
|
if (name === 'visualize') {
|
|
466
467
|
const input = args.input && typeof args.input === 'object' ? args.input : {};
|
|
467
|
-
const targets = args.action === 'open' && Array.isArray(input.targets) ? input.targets : [];
|
|
468
|
+
const targets = !written && args.action === 'open' && Array.isArray(input.targets) ? input.targets : [];
|
|
468
469
|
return [
|
|
469
470
|
...text(input.output),
|
|
470
471
|
...targets.filter((target) => typeof target === 'string' && !/^[a-z][a-z0-9+.-]*:\/\//i.test(target)),
|
|
@@ -520,8 +521,9 @@ export function turnSlice(messages, { runId = '', since = 0 } = {}) {
|
|
|
520
521
|
|
|
521
522
|
/** The candidate artifact paths of a turn's messages, most relevant first:
|
|
522
523
|
* what its final reply names, then media/office/visualize outputs, then the
|
|
523
|
-
* files it edited.
|
|
524
|
-
|
|
524
|
+
* files it edited. `written`: only the files it created or modified (no
|
|
525
|
+
* reply paths, no visualize open targets). */
|
|
526
|
+
export function turnArtifactCandidates(messages, { written = false } = {}) {
|
|
525
527
|
const list = Array.isArray(messages) ? messages : [];
|
|
526
528
|
const reply = list.findLast((message) => message?.role === 'assistant' && textOf(message.content).trim());
|
|
527
529
|
const produced = [];
|
|
@@ -535,10 +537,10 @@ export function turnArtifactCandidates(messages) {
|
|
|
535
537
|
: [];
|
|
536
538
|
for (const call of calls) {
|
|
537
539
|
const name = String(call?.function?.name || call?.name || '');
|
|
538
|
-
(name === 'edit' || name === 'apply_patch' ? edited : produced).push(...toolCallOutputs(call));
|
|
540
|
+
(name === 'edit' || name === 'apply_patch' ? edited : produced).push(...toolCallOutputs(call, written));
|
|
539
541
|
}
|
|
540
542
|
}
|
|
541
|
-
return [...(reply ? replyPaths(textOf(reply.content)) : []), ...produced, ...edited];
|
|
543
|
+
return [...(!written && reply ? replyPaths(textOf(reply.content)) : []), ...produced, ...edited];
|
|
542
544
|
}
|
|
543
545
|
|
|
544
546
|
/**
|
|
@@ -549,38 +551,16 @@ export function turnArtifactCandidates(messages) {
|
|
|
549
551
|
* the roots are left out silently; at most HANDOFF_LIMITS.count are kept.
|
|
550
552
|
*/
|
|
551
553
|
export function collectTurnArtifacts(messages, { cwd = '', roots = [] } = {}) {
|
|
552
|
-
const seen = new Set();
|
|
553
554
|
const files = [];
|
|
554
555
|
let omitted = 0;
|
|
555
556
|
const budget = createBudget();
|
|
556
|
-
for (const
|
|
557
|
-
// A candidate is a lexical path; its canonical form dedupes after the read.
|
|
558
|
-
const lexical = samePlatformPath(
|
|
559
|
-
isAbsolute(candidate) ? resolve(candidate) : resolve(cwd || process.cwd(), candidate)
|
|
560
|
-
);
|
|
561
|
-
if (seen.has(lexical)) continue;
|
|
562
|
-
seen.add(lexical);
|
|
563
|
-
let file;
|
|
564
|
-
try {
|
|
565
|
-
file = readContained(candidate, { cwd, roots, surface: 'artifact' });
|
|
566
|
-
} catch {
|
|
567
|
-
continue;
|
|
568
|
-
}
|
|
569
|
-
const key = samePlatformPath(file.path);
|
|
570
|
-
if (key !== lexical && seen.has(key)) continue;
|
|
571
|
-
seen.add(key);
|
|
557
|
+
for (const { file } of readableCandidates(turnArtifactCandidates(messages), { cwd, roots })) {
|
|
572
558
|
if (files.length >= HANDOFF_LIMITS.count) {
|
|
573
559
|
omitted += 1;
|
|
574
560
|
continue;
|
|
575
561
|
}
|
|
576
562
|
const { type, bytes } = file;
|
|
577
|
-
const entry =
|
|
578
|
-
path: file.path,
|
|
579
|
-
name: file.name,
|
|
580
|
-
kind: type?.kind || 'file',
|
|
581
|
-
mimeType: type?.mimeType || 'application/octet-stream',
|
|
582
|
-
size: file.size,
|
|
583
|
-
};
|
|
563
|
+
const entry = pathEntry(file);
|
|
584
564
|
const storable = bytes && (type.kind !== 'image' || SUPPORTED_IMAGE_MIME_TYPES.has(type.mimeType));
|
|
585
565
|
if (storable && budget.take(type.kind, bytes.length)) {
|
|
586
566
|
try {
|
|
@@ -591,3 +571,74 @@ export function collectTurnArtifacts(messages, { cwd = '', roots = [] } = {}) {
|
|
|
591
571
|
}
|
|
592
572
|
return { files, omitted };
|
|
593
573
|
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* The files `messages` (one turn) created or modified, inside `roots`, that
|
|
577
|
+
* `report` (the text handed to the Lead) does not name: `{ files, omitted }`
|
|
578
|
+
* as path-only entries, which the Lead forwards by path. Nothing is stored.
|
|
579
|
+
*/
|
|
580
|
+
export function collectUnreportedWrites(messages, { cwd = '', roots = [], report }) {
|
|
581
|
+
const found = [...readableCandidates(turnArtifactCandidates(messages, { written: true }), { cwd, roots })];
|
|
582
|
+
const unnamed = found.filter((item) => !reportNames(report, item, found, cwd));
|
|
583
|
+
return {
|
|
584
|
+
files: unnamed.slice(0, HANDOFF_LIMITS.count).map(({ file }) => pathEntry(file)),
|
|
585
|
+
omitted: Math.max(0, unnamed.length - HANDOFF_LIMITS.count),
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const lexicalKey = (path, cwd) => samePlatformPath(resolve(cwd || process.cwd(), path));
|
|
590
|
+
|
|
591
|
+
const pathEntry = (file) => ({
|
|
592
|
+
path: file.path,
|
|
593
|
+
name: file.name,
|
|
594
|
+
kind: file.type?.kind || 'file',
|
|
595
|
+
mimeType: file.type?.mimeType || 'application/octet-stream',
|
|
596
|
+
size: file.size,
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
/** The distinct files among `candidates` that can be read inside `roots`, with
|
|
600
|
+
* their lexical and canonical keys. A candidate is a lexical path; its
|
|
601
|
+
* canonical form dedupes after the read. */
|
|
602
|
+
function* readableCandidates(candidates, { cwd, roots }) {
|
|
603
|
+
const seen = new Set();
|
|
604
|
+
for (const candidate of candidates) {
|
|
605
|
+
const lexical = lexicalKey(candidate, cwd);
|
|
606
|
+
if (seen.has(lexical)) continue;
|
|
607
|
+
seen.add(lexical);
|
|
608
|
+
let file;
|
|
609
|
+
try {
|
|
610
|
+
file = readContained(candidate, { cwd, roots, surface: 'artifact' });
|
|
611
|
+
} catch {
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
const key = samePlatformPath(file.path);
|
|
615
|
+
if (key !== lexical && seen.has(key)) continue;
|
|
616
|
+
seen.add(key);
|
|
617
|
+
yield { file, lexical, key };
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/** Whether `report` names the produced file `item` among `found`: by its full
|
|
622
|
+
* path or a cwd-relative path resolving to it exactly, or by its bare file name
|
|
623
|
+
* when no other produced file shares that name. */
|
|
624
|
+
function reportNames(report, { file, lexical, key }, found, cwd) {
|
|
625
|
+
const flat = (value) => String(value).replaceAll('\\', '/');
|
|
626
|
+
const filePath = flat(file.path);
|
|
627
|
+
if (flat(report).includes(filePath)) return true;
|
|
628
|
+
const plain = report
|
|
629
|
+
.split(/[\s`"'<>()[\],;|]+/)
|
|
630
|
+
.map((token) => token.replace(/:\d+(?::\d+)?$/, '').replace(/[.:!?]+$/, ''))
|
|
631
|
+
.filter((token) => /\.[A-Za-z0-9]{1,8}$/.test(token) && !/^[a-z][a-z0-9+.-]*:\/\//i.test(token));
|
|
632
|
+
const refs = new Set([...replyPaths(report), ...plain]);
|
|
633
|
+
const unique = found.filter((other) => other.file.name === file.name).length === 1;
|
|
634
|
+
for (const ref of refs) {
|
|
635
|
+
const normalized = flat(ref).replace(/^(?:\.\/)+/, '');
|
|
636
|
+
if (!normalized.includes('/')) {
|
|
637
|
+
if (unique && normalized === file.name) return true;
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
const refKey = lexicalKey(ref, cwd);
|
|
641
|
+
if (refKey === lexical || refKey === key) return true;
|
|
642
|
+
}
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
@@ -1,40 +1,85 @@
|
|
|
1
1
|
// ask_user: put 1-4 multiple-choice questions to the user through the session's
|
|
2
2
|
// tool-approval hook (kind: 'question') and report the answers to the model.
|
|
3
|
+
// handoff_user (the secret / takeover handoff) shares this module's human-gate code.
|
|
3
4
|
import { randomUUID } from 'node:crypto';
|
|
4
5
|
import {
|
|
5
|
-
|
|
6
|
+
validateUserHandoff,
|
|
6
7
|
validateAskUserQuestions,
|
|
7
8
|
ASK_USER_MAX_TEXT,
|
|
8
9
|
} from '../../runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs';
|
|
9
10
|
import { createCallerContextResolvers } from './caller-context.mjs';
|
|
10
11
|
import { runAbortable } from '../../runtime/shared/abort-race.mjs';
|
|
11
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
HANDOFF_OUTCOMES as AGENT_OUTCOMES,
|
|
14
|
+
SECRET_REQUEST_TIMEOUT_MS,
|
|
15
|
+
} from '../../runtime/agent/orchestrator/session/human-gate/requests.mjs';
|
|
12
16
|
import {
|
|
13
17
|
agentIdForSession,
|
|
14
18
|
recordHumanDecision,
|
|
15
19
|
unattendedApprovalPort,
|
|
16
20
|
} from '../../runtime/agent/orchestrator/session/human-gate/gate.mjs';
|
|
17
|
-
import { browserSecretInput } from '../../runtime/browser-bridge/client.mjs';
|
|
18
|
-
import { computerSecretInput } from '../../runtime/computer-bridge/client.mjs';
|
|
21
|
+
import { browserHandoffPage, browserSecretInput } from '../../runtime/browser-bridge/client.mjs';
|
|
22
|
+
import { computerSecretBind, computerSecretInput } from '../../runtime/computer-bridge/client.mjs';
|
|
23
|
+
|
|
24
|
+
/** The settle reason of a takeover that expired (desktop takeover-gate.ts
|
|
25
|
+
* TAKEOVER_EXPIRED_REASON). */
|
|
26
|
+
const TAKEOVER_EXPIRED_REASON = 'expired';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The agent's result of a secret request, from the card's answer and the
|
|
30
|
+
* desktop's fill: one of requests.mjs HANDOFF_OUTCOMES. `fill` runs only for a provided
|
|
31
|
+
* value and answers 'entered' / 'no_field' / 'page_changed' / 'blocked' /
|
|
32
|
+
* 'expired'.
|
|
33
|
+
*/
|
|
34
|
+
export async function secretOutcome(result, fill) {
|
|
35
|
+
if (result?.timedOut === true || result?.reason === TAKEOVER_EXPIRED_REASON) return 'expired';
|
|
36
|
+
if (result?.approved !== true || result.response !== 'provide-secret') return 'user_skipped';
|
|
37
|
+
const filled = await fill();
|
|
38
|
+
return AGENT_OUTCOMES.includes(filled) && filled !== 'user_skipped' ? filled : 'blocked';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** A page address as the agent may see it: origin and path, no query or
|
|
42
|
+
* fragment (a sign-in redirect can carry a code or token there). */
|
|
43
|
+
function factUrl(value) {
|
|
44
|
+
try {
|
|
45
|
+
const url = new URL(String(value || ''));
|
|
46
|
+
return url.protocol === 'http:' || url.protocol === 'https:' ? `${url.origin}${url.pathname}` : '';
|
|
47
|
+
} catch {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The agent's result of a takeover: what the user did and where the page is
|
|
53
|
+
* now, never "signed in" (the agent checks the page). */
|
|
54
|
+
export function takeoverOutcome(result, pageUrl = '') {
|
|
55
|
+
if (result?.timedOut === true || result?.reason === TAKEOVER_EXPIRED_REASON) return 'expired';
|
|
56
|
+
if (result?.approved !== true) return 'user_skipped';
|
|
57
|
+
const url = factUrl(pageUrl);
|
|
58
|
+
const did = result.reason === 'saved_login' ? 'User chose a saved login; it was filled in' : 'User pressed Done';
|
|
59
|
+
return url ? `${did}; page now at ${url}` : did;
|
|
60
|
+
}
|
|
19
61
|
|
|
20
62
|
/**
|
|
21
|
-
* A secret or takeover handoff. Secret:
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* (
|
|
27
|
-
* main/takeover-gate.ts); the result is '
|
|
63
|
+
* A secret or takeover handoff. Secret: at request time the desktop binds the
|
|
64
|
+
* request to its page ({pageId, origin}) or, for computer use, it is bound to
|
|
65
|
+
* {window_id, ref}; the card collects the value on the desktop, which holds it
|
|
66
|
+
* for `requestId` and fills only that page, only while its origin is
|
|
67
|
+
* unchanged. Here only the outcome travels (secretOutcome). Takeover: the run
|
|
68
|
+
* waits until the user says done (that session's actions stay blocked
|
|
69
|
+
* meanwhile, desktop main/takeover-gate.ts); the result is takeoverOutcome's.
|
|
28
70
|
*/
|
|
29
71
|
export async function runAskUserHandoff(handoff, { hook, sessionId, toolCallId, signal, inputs = {} }) {
|
|
30
72
|
const secretInput = {
|
|
31
73
|
browser: inputs.browser || browserSecretInput,
|
|
32
74
|
computer: inputs.computer || computerSecretInput,
|
|
33
75
|
};
|
|
76
|
+
const page = inputs.page || browserHandoffPage;
|
|
77
|
+
const bindComputer = inputs.computerBind || computerSecretBind;
|
|
78
|
+
const identity = handoff.identity || {};
|
|
34
79
|
const gate = {
|
|
35
80
|
agentId: agentIdForSession(sessionId),
|
|
36
81
|
kind: handoff.kind,
|
|
37
|
-
tool: `
|
|
82
|
+
tool: `handoff_user:${handoff.surface}`,
|
|
38
83
|
target: handoff.target || handoff.field || '',
|
|
39
84
|
};
|
|
40
85
|
// A schedule or webhook run has nobody to take over: the step ends it now,
|
|
@@ -47,43 +92,96 @@ export async function runAskUserHandoff(handoff, { hook, sessionId, toolCallId,
|
|
|
47
92
|
return UNATTENDED_TAKEOVER;
|
|
48
93
|
}
|
|
49
94
|
if (typeof hook !== 'function') {
|
|
50
|
-
// Nobody can take over here: blocked, never "proceed".
|
|
95
|
+
// Nobody can take over or type here: blocked, never "proceed".
|
|
51
96
|
if (handoff.kind === 'takeover') return NO_TAKEOVER;
|
|
52
|
-
await recordHumanDecision(gate, { response: '
|
|
53
|
-
return '
|
|
97
|
+
await recordHumanDecision(gate, { response: 'blocked' });
|
|
98
|
+
return 'blocked';
|
|
54
99
|
}
|
|
55
100
|
if (handoff.kind === 'secret') {
|
|
56
101
|
const requestId = `secret_${randomUUID()}`;
|
|
102
|
+
// Bound now: the page (and its origin) the value may go to, and what its
|
|
103
|
+
// field is. A browser page that cannot be bound, or has no such field,
|
|
104
|
+
// never asks the user for a value it could not place.
|
|
105
|
+
let bound = {};
|
|
106
|
+
if (handoff.surface === 'browser') {
|
|
107
|
+
const facts = await page(
|
|
108
|
+
sessionId,
|
|
109
|
+
'secret_bind',
|
|
110
|
+
{ request_id: requestId, ...(identity.tab ? { tab: identity.tab } : {}), field: handoff.field },
|
|
111
|
+
{ signal }
|
|
112
|
+
);
|
|
113
|
+
let outcome = '';
|
|
114
|
+
if (!facts?.origin) outcome = 'blocked';
|
|
115
|
+
else if (!facts.form) outcome = 'no_field';
|
|
116
|
+
if (outcome) {
|
|
117
|
+
await recordHumanDecision(gate, { response: outcome });
|
|
118
|
+
return outcome;
|
|
119
|
+
}
|
|
120
|
+
bound = { origin: facts.origin, form: facts.form, ...(facts.length ? { length: facts.length } : {}) };
|
|
121
|
+
} else {
|
|
122
|
+
// Computer Use: bound to the exact window and field ref the agent named
|
|
123
|
+
// (from snapshot/find). Without both there is no field to confirm, and
|
|
124
|
+
// none is made up (never the focused field or the front window).
|
|
125
|
+
const outcome =
|
|
126
|
+
identity.windowId && identity.ref
|
|
127
|
+
? await bindComputer(sessionId, requestId, { windowId: identity.windowId, ref: identity.ref, signal })
|
|
128
|
+
: 'no_field';
|
|
129
|
+
if (outcome !== 'bound') {
|
|
130
|
+
const refused = outcome === 'no_field' ? 'no_field' : 'blocked';
|
|
131
|
+
await recordHumanDecision(gate, { response: refused });
|
|
132
|
+
return refused;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
57
135
|
const result = await runAbortable(signal, () =>
|
|
58
136
|
hook({
|
|
59
|
-
name: '
|
|
137
|
+
name: 'handoff_user',
|
|
60
138
|
kind: 'secret',
|
|
61
|
-
secret: { requestId, surface: handoff.surface, target: handoff.target, field: handoff.field },
|
|
139
|
+
secret: { requestId, surface: handoff.surface, target: handoff.target, field: handoff.field, ...bound },
|
|
62
140
|
reason: '',
|
|
63
141
|
timeoutMs: SECRET_REQUEST_TIMEOUT_MS,
|
|
64
142
|
sessionId,
|
|
65
143
|
toolCallId,
|
|
66
144
|
})
|
|
67
145
|
);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
146
|
+
const computerTarget = {
|
|
147
|
+
...(identity.ref ? { ref: identity.ref } : {}),
|
|
148
|
+
...(identity.windowId ? { windowId: identity.windowId } : {}),
|
|
149
|
+
};
|
|
150
|
+
const outcome = await secretOutcome(result, () =>
|
|
151
|
+
secretInput[handoff.surface](sessionId, requestId, {
|
|
152
|
+
signal,
|
|
153
|
+
...(handoff.surface === 'computer' ? computerTarget : {}),
|
|
154
|
+
})
|
|
155
|
+
);
|
|
156
|
+
await recordHumanDecision(gate, { response: outcome, device: result?.device });
|
|
157
|
+
return outcome;
|
|
75
158
|
}
|
|
159
|
+
// A sign-in page's saved logins (masked) let the card fill one for the
|
|
160
|
+
// user: the desktop offers them only for a page on that origin, bound now
|
|
161
|
+
// under `fillId` so the fill reaches that page alone (host-agent.ts fillBoundLogin).
|
|
162
|
+
const fillId = handoff.login ? `secret_${randomUUID()}` : '';
|
|
163
|
+
const accounts = handoff.login
|
|
164
|
+
? (
|
|
165
|
+
await page(
|
|
166
|
+
sessionId,
|
|
167
|
+
'login_accounts',
|
|
168
|
+
{ url: handoff.login.url, request_id: fillId, ...(identity.tab ? { tab: identity.tab } : {}) },
|
|
169
|
+
{ signal }
|
|
170
|
+
)
|
|
171
|
+
)?.accounts
|
|
172
|
+
: null;
|
|
76
173
|
const result = await runAbortable(signal, () =>
|
|
77
174
|
hook({
|
|
78
|
-
name: '
|
|
175
|
+
name: 'handoff_user',
|
|
79
176
|
kind: 'takeover',
|
|
80
177
|
takeover: {
|
|
81
178
|
surface: handoff.surface,
|
|
82
179
|
instructions: handoff.instructions,
|
|
83
180
|
target: handoff.target,
|
|
84
|
-
...
|
|
181
|
+
...identity,
|
|
85
182
|
// A login takeover: the desktop opens its sign-in window on this page.
|
|
86
183
|
...(handoff.login ? { purpose: 'login', url: handoff.login.url } : {}),
|
|
184
|
+
...(Array.isArray(accounts) && accounts.length ? { accounts, fillId } : {}),
|
|
87
185
|
},
|
|
88
186
|
args: { surface: handoff.surface, instructions: handoff.instructions },
|
|
89
187
|
reason: '',
|
|
@@ -92,8 +190,15 @@ export async function runAskUserHandoff(handoff, { hook, sessionId, toolCallId,
|
|
|
92
190
|
toolCallId,
|
|
93
191
|
})
|
|
94
192
|
);
|
|
95
|
-
const
|
|
96
|
-
|
|
193
|
+
const pageUrl =
|
|
194
|
+
result?.approved === true && handoff.surface === 'browser'
|
|
195
|
+
? (await page(sessionId, 'page_url', identity.tab ? { tab: identity.tab } : {}, { signal }))?.url
|
|
196
|
+
: '';
|
|
197
|
+
const answer = takeoverOutcome(result, pageUrl);
|
|
198
|
+
await recordHumanDecision(gate, {
|
|
199
|
+
response: answer.startsWith('User ') ? 'done' : answer,
|
|
200
|
+
device: result?.device,
|
|
201
|
+
});
|
|
97
202
|
return answer;
|
|
98
203
|
}
|
|
99
204
|
|
|
@@ -125,7 +230,7 @@ const DISMISSED =
|
|
|
125
230
|
'User closed the questions without answering. Proceed with your best judgment; ask again only if something new depends on it.';
|
|
126
231
|
|
|
127
232
|
/** Wire answers -> array aligned with questions; invalid entries become null. */
|
|
128
|
-
|
|
233
|
+
function normalizeAskUserAnswers(answers, questions) {
|
|
129
234
|
const list = Array.isArray(answers) ? answers.slice(0, 4) : [];
|
|
130
235
|
return questions.map((q, i) => {
|
|
131
236
|
const entry = list[i];
|
|
@@ -143,7 +248,7 @@ export function normalizeAskUserAnswers(answers, questions) {
|
|
|
143
248
|
|
|
144
249
|
// Strings are JSON-quoted so a quote inside one cannot end it early; typed
|
|
145
250
|
// text stays apart from the picked labels (`"picked" + "typed" (typed)`).
|
|
146
|
-
|
|
251
|
+
function formatAskUserAnswers(questions, answers) {
|
|
147
252
|
const quote = (text) => JSON.stringify(text);
|
|
148
253
|
const parts = questions.map((q, i) => {
|
|
149
254
|
const a = answers[i];
|
|
@@ -157,14 +262,14 @@ export function formatAskUserAnswers(questions, answers) {
|
|
|
157
262
|
|
|
158
263
|
/** A composer message sent instead of (or with) picking: kept when it is a
|
|
159
264
|
* non-empty string within the typed-answer limit, else dropped. */
|
|
160
|
-
|
|
265
|
+
function normalizeAskUserReply(reply) {
|
|
161
266
|
if (typeof reply !== 'string' || reply.length > ASK_USER_MAX_TEXT) return '';
|
|
162
267
|
return reply.trim();
|
|
163
268
|
}
|
|
164
269
|
|
|
165
270
|
// `User replied in chat: "<reply>". ` leads, then the usual picks sentence
|
|
166
271
|
// when any question was answered, else just the closing sentence.
|
|
167
|
-
|
|
272
|
+
function formatAskUserResult(questions, answers, reply) {
|
|
168
273
|
if (!reply) return formatAskUserAnswers(questions, answers);
|
|
169
274
|
const lead = `User replied in chat: ${JSON.stringify(reply)}. `;
|
|
170
275
|
if (answers.some(Boolean)) return `${lead}${formatAskUserAnswers(questions, answers)}`;
|
|
@@ -174,16 +279,14 @@ export function formatAskUserResult(questions, answers, reply) {
|
|
|
174
279
|
export function createAskUserToolHandlers({ rt }) {
|
|
175
280
|
const { sessionIdFor, signalFor } = createCallerContextResolvers(rt);
|
|
176
281
|
return {
|
|
282
|
+
handoff_user: async (args, { callerCtx }) =>
|
|
283
|
+
runAskUserHandoff(validateUserHandoff(args), {
|
|
284
|
+
hook: callerCtx?.toolApprovalHook,
|
|
285
|
+
sessionId: sessionIdFor(callerCtx),
|
|
286
|
+
toolCallId: callerCtx?.toolCallId || null,
|
|
287
|
+
signal: signalFor(callerCtx),
|
|
288
|
+
}),
|
|
177
289
|
ask_user: async (args, { callerCtx }) => {
|
|
178
|
-
const handoff = validateAskUserHandoff(args);
|
|
179
|
-
if (handoff) {
|
|
180
|
-
return runAskUserHandoff(handoff, {
|
|
181
|
-
hook: callerCtx?.toolApprovalHook,
|
|
182
|
-
sessionId: sessionIdFor(callerCtx),
|
|
183
|
-
toolCallId: callerCtx?.toolCallId || null,
|
|
184
|
-
signal: signalFor(callerCtx),
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
290
|
const questions = validateAskUserQuestions(args);
|
|
188
291
|
const hook = callerCtx?.toolApprovalHook;
|
|
189
292
|
if (typeof hook !== 'function') return NO_USER;
|
|
@@ -45,6 +45,8 @@ export function createBridgeToolHandlers({ rt }) {
|
|
|
45
45
|
cwd: callerCwd,
|
|
46
46
|
requestApproval: callerCtx?.toolApprovalHook,
|
|
47
47
|
toolCallId: callerCtx?.toolCallId || null,
|
|
48
|
+
// The agent turn, as for the browser: it scopes a saved-login fill's protection.
|
|
49
|
+
turnId: callerCtx?.turnId || rt.session?.usageMetricsTurnId,
|
|
48
50
|
signal: signalFor(callerCtx),
|
|
49
51
|
});
|
|
50
52
|
};
|
|
@@ -81,6 +83,7 @@ export function createBridgeToolHandlers({ rt }) {
|
|
|
81
83
|
}
|
|
82
84
|
return await executeVisualizeTool(args, {
|
|
83
85
|
sessionId: sessionIdFor(callerCtx),
|
|
86
|
+
callId: callerCtx?.toolCallId,
|
|
84
87
|
cwd: callerCwd,
|
|
85
88
|
signal: signalFor(callerCtx),
|
|
86
89
|
});
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
// the message is the user's row in the room's log. Never a coding session, a
|
|
5
5
|
// delegated worker, or a run nobody attends.
|
|
6
6
|
import { isAgentOwner } from '../../runtime/agent/orchestrator/agent-owner.mjs';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
noteReactionTarget,
|
|
9
|
+
validateReactionArgs,
|
|
10
|
+
} from '../../runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs';
|
|
8
11
|
import { agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
9
12
|
import { roomMemberOfSession, roomSessionId } from '../../runtime/agent/orchestrator/session/agent-room.mjs';
|
|
10
13
|
import { reactInSession } from '../../runtime/agent/orchestrator/session/message-reactions.mjs';
|
|
@@ -17,6 +17,7 @@ import { scheduleCallerScope } from '../services/schedule-access.mjs';
|
|
|
17
17
|
import { worktreeCallerScope } from '../services/worktree-access.mjs';
|
|
18
18
|
import { resolveHandoffAttachments, sessionRoots } from '../handoff-attachments.mjs';
|
|
19
19
|
import { delegationChainOf } from '../bot-chain.mjs';
|
|
20
|
+
import { BOT_TARGET_ACTIONS, resolveBotTarget } from '../bot-target.mjs';
|
|
20
21
|
|
|
21
22
|
const USER_TITLE_ERROR = 'session: the user already titled this session; the title was not changed';
|
|
22
23
|
|
|
@@ -50,6 +51,7 @@ export function createWorkspaceToolHandlers({
|
|
|
50
51
|
getSessionManager = () => null,
|
|
51
52
|
getLifecycleApi = () => null,
|
|
52
53
|
executeSessionControl = null,
|
|
54
|
+
listBots,
|
|
53
55
|
}) {
|
|
54
56
|
const assertLead = (action, callerCtx) => {
|
|
55
57
|
const callerSessionId = callerCtx?.callerSessionId || rt.session?.id || null;
|
|
@@ -110,12 +112,16 @@ export function createWorkspaceToolHandlers({
|
|
|
110
112
|
'session: create belongs to a bot conversation; delegated workers, agent task sessions and schedule/webhook runs cannot create agent task sessions'
|
|
111
113
|
);
|
|
112
114
|
}
|
|
115
|
+
// A bot id names that bot's home chat; every check below and in the
|
|
116
|
+
// control runs on the chat it resolves to.
|
|
117
|
+
const sessionTarget =
|
|
118
|
+
BOT_TARGET_ACTIONS.has(action) && target ? await resolveBotTarget(target, listBots) : target;
|
|
113
119
|
// A task session reaches its agent only through its reported result.
|
|
114
120
|
const origin = rt.session?.taskOrigin;
|
|
115
121
|
if (
|
|
116
122
|
action === 'send' &&
|
|
117
123
|
origin &&
|
|
118
|
-
(
|
|
124
|
+
(sessionTarget === origin.sessionId || agentIdOfHomeSession(sessionTarget) === origin.agentId)
|
|
119
125
|
) {
|
|
120
126
|
throw new Error('session: a task session reports to its agent only through its result');
|
|
121
127
|
}
|
|
@@ -129,7 +135,7 @@ export function createWorkspaceToolHandlers({
|
|
|
129
135
|
const attachmentParts = callerAttachmentParts(rt, args, callerCwd, 'session');
|
|
130
136
|
return JSON.stringify(
|
|
131
137
|
await executeSessionControl(
|
|
132
|
-
{ ...rest, action },
|
|
138
|
+
{ ...rest, action, ...(sessionTarget !== target ? { session_id: sessionTarget } : {}) },
|
|
133
139
|
{
|
|
134
140
|
callerSessionId,
|
|
135
141
|
callerAgentId,
|
|
@@ -150,14 +150,19 @@ export function buildColdHeir(source, now = Date.now()) {
|
|
|
150
150
|
// earlier folder) is the source's own: the heir's prompt is built for the
|
|
151
151
|
// folder it actually starts in. Project memory follows the Project, which a
|
|
152
152
|
// worktree shares, so the source's current memory slice carries over.
|
|
153
|
+
// In the same folder only the environment facts are rebuilt: they name the
|
|
154
|
+
// heir's own scratch directory, never the source's, while the inherited
|
|
155
|
+
// instruction files and memory stay as the source presented them.
|
|
153
156
|
const pending = source.workspaceReroot;
|
|
154
157
|
delete heir.workspaceReroot;
|
|
155
|
-
if (
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
if (heir.cwd) {
|
|
159
|
+
const context = buildWorkspacePromptContext(heir, heir.cwd);
|
|
160
|
+
refreshSessionWorkspaceContext(
|
|
161
|
+
heir,
|
|
162
|
+
projectFolder || pending
|
|
163
|
+
? { cwd: heir.cwd, ...context, coreMemoryContext: pending?.target?.coreMemoryContext }
|
|
164
|
+
: { cwd: heir.cwd, environmentContext: context.environmentContext }
|
|
165
|
+
);
|
|
161
166
|
}
|
|
162
167
|
invalidateContextUsageSnapshot(heir);
|
|
163
168
|
invalidateProviderContextBaseline(heir);
|
|
@@ -15,6 +15,10 @@ import {
|
|
|
15
15
|
inheritanceRouteTarget,
|
|
16
16
|
} from '../inheritance-fit.mjs';
|
|
17
17
|
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
18
|
+
import {
|
|
19
|
+
rebindToChangedPrefix,
|
|
20
|
+
requestPrefixIdentity,
|
|
21
|
+
} from '../../runtime/agent/orchestrator/session/thinking-binding.mjs';
|
|
18
22
|
import { buildColdHeir, committedSource, persistColdHeir } from './cold-heir.mjs';
|
|
19
23
|
|
|
20
24
|
export function createInheritance(deps, { compactConversation, saveSession }) {
|
|
@@ -155,8 +159,17 @@ export function createInheritance(deps, { compactConversation, saveSession }) {
|
|
|
155
159
|
async function carryConversation(source, target, { compact = false } = {}) {
|
|
156
160
|
// System blocks belong to the session that BUILT them: the target's own
|
|
157
161
|
// prompt was composed for the current model, tool surface, and workflow.
|
|
158
|
-
// Only the conversation itself travels
|
|
159
|
-
|
|
162
|
+
// Only the conversation itself travels — without its thinking replay when
|
|
163
|
+
// the heir's prompt or tools differ from the source's: that replay is
|
|
164
|
+
// bound to the source's prefix, so the provider would drop it (and every
|
|
165
|
+
// thinking block after it) or refuse it, while the heir's context estimate
|
|
166
|
+
// kept counting it (thinking-binding.mjs); an open tool round the source
|
|
167
|
+
// stopped in is ended for the heir. An identical prefix keeps it all.
|
|
168
|
+
const carrySource =
|
|
169
|
+
requestPrefixIdentity(source) === requestPrefixIdentity(target)
|
|
170
|
+
? source
|
|
171
|
+
: { ...source, messages: rebindToChangedPrefix(source.messages) };
|
|
172
|
+
let carried = inheritableMessages(carrySource.messages);
|
|
160
173
|
if (!hasUserConversationMessage(carried)) {
|
|
161
174
|
throw new Error('inheritFrom: the source session has no conversation to carry');
|
|
162
175
|
}
|
|
@@ -169,7 +182,7 @@ export function createInheritance(deps, { compactConversation, saveSession }) {
|
|
|
169
182
|
// compact:true summarizes even a conversation that fits; otherwise only
|
|
170
183
|
// one that cannot fit is compacted.
|
|
171
184
|
if (compact || (fit.known && !fit.fits)) {
|
|
172
|
-
const next = await fitConversationForHeir(
|
|
185
|
+
const next = await fitConversationForHeir(carrySource, target, carried, fit, { required: compact });
|
|
173
186
|
compacted = next !== carried;
|
|
174
187
|
carried = next;
|
|
175
188
|
}
|
|
@@ -21,7 +21,11 @@ import {
|
|
|
21
21
|
wantsIncomingTail,
|
|
22
22
|
} from '../../runtime/agent/orchestrator/session/store-summary-last-message.mjs';
|
|
23
23
|
import { isRealTurnMessage } from '../../runtime/agent/orchestrator/session/compact/user-message-kind.mjs';
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
compactCount as compactCountOf,
|
|
26
|
+
compactCountField,
|
|
27
|
+
realTurnCount as realTurnCountOf,
|
|
28
|
+
} from '../../runtime/agent/orchestrator/session/store-summary-fields.mjs';
|
|
25
29
|
|
|
26
30
|
const VISIBLE_OWNERS = ['cli', 'user', 'mixdog'];
|
|
27
31
|
|
|
@@ -77,7 +81,9 @@ export function leadSessionRow(s, working = false) {
|
|
|
77
81
|
if (sourceType === 'exec') return null;
|
|
78
82
|
if (!agentSession && !isLeadShaped(s, owner, sourceType)) return null;
|
|
79
83
|
const { preview, messageCount, realTurnCount, incomingTail } = previewOf(s);
|
|
80
|
-
|
|
84
|
+
// A titled one is not scratch: its prompt was rewound away (Esc-Esc message
|
|
85
|
+
// selector), so it stays listed rather than vanishing with its open tab.
|
|
86
|
+
if (!preview && messageCount === 0 && !cleanSessionPreview(s.title || '', 100)) return null;
|
|
81
87
|
const lastMessageRoutine = normalizeRoutineProvenance(s.lastMessageRoutine);
|
|
82
88
|
return {
|
|
83
89
|
id: s.id,
|
|
@@ -105,6 +111,10 @@ export function leadSessionRow(s, working = false) {
|
|
|
105
111
|
// sit among the counted ones: a bot row's unread pill counts those past
|
|
106
112
|
// the read cursor. Absent when unknown; clients then show one.
|
|
107
113
|
...(incomingTail ? { incomingTail } : {}),
|
|
114
|
+
// The numbering epoch of messageCount: each compaction restarts it. A
|
|
115
|
+
// summary row carries it at the top; a stored session in its compaction
|
|
116
|
+
// record. Unknown stays absent.
|
|
117
|
+
...compactCountField(compactCountOf(s) === null ? s.compaction : s),
|
|
108
118
|
title: cleanSessionPreview(s.title || '', 100),
|
|
109
119
|
preview,
|
|
110
120
|
// The latest user or assistant line (an agent contact's row shows it).
|