mixdog 1.3.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSES/oh-my-pi-MIT.txt +23 -0
- package/NOTICE.md +17 -2
- package/README.md +11 -0
- package/package.json +3 -11
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/embed-google-oauth-client.mjs +49 -0
- package/scripts/gate-local.mjs +4 -2
- package/scripts/lib/test-spawn-ledger.mjs +46 -1
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +10 -1
- package/scripts/test.mjs +12 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +25 -1
- package/src/defaults/skills/browser-use/SKILL.md +77 -17
- 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 +33 -9
- package/src/defaults/skills/setup/SKILL.md +29 -2
- package/src/defaults/skills/setup/references/actions.md +117 -28
- package/src/defaults/skills/setup/references/surfaces.md +77 -35
- package/src/defaults/skills/setup-guide/SKILL.md +3 -3
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/keychain-cjs.cjs +359 -29
- package/src/lib/rules-builder.cjs +10 -8
- package/src/rules/agent/AGENT.md +6 -6
- package/src/rules/agent-mode/AGENT_MODE.md +10 -2
- package/src/rules/agent-mode/MIXY.md +12 -0
- package/src/rules/lead/LEAD.md +18 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
- 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/config.mjs +34 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +177 -73
- package/src/runtime/agent/orchestrator/mcp/client.mjs +25 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +230 -137
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +64 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- 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.mjs +160 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +142 -104
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
- package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
- package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -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 +19 -1
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +6 -1
- 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/opencode-go-gemini.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
- 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 +43 -3
- 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/providers/wire-protobuf-codec.mjs +368 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- 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 +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +148 -25
- 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/eager-dispatch.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +47 -9
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +51 -3
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -2
- 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 +14 -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 +10 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +23 -5
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
- 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-commit.mjs +2 -0
- 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 +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -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 +23 -13
- 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 +129 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
- package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +47 -11
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
- 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-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +133 -18
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
- 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/tool-batch/state.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +25 -2
- 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/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/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.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- 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/schedule-errors.mjs +51 -0
- package/src/runtime/channels/lib/scheduler.mjs +135 -154
- package/src/runtime/channels/lib/schedules-db.mjs +83 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +14 -2
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- 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 +19 -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 +27 -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/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/com/com-adapter.mjs +17 -1
- package/src/runtime/office/com/office-com-host.ps1 +51 -1
- package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
- package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
- package/src/runtime/office/pdf/document-preview.mjs +326 -8
- package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
- package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
- package/src/runtime/office/portable/portable-soffice.mjs +45 -5
- 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-hops.mjs +62 -2
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +51 -35
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +33 -2
- package/src/runtime/shared/connector-catalog.mjs +166 -8
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -14
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/developer-options.mjs +32 -1
- package/src/runtime/shared/err-text.mjs +24 -15
- 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/google-oauth-client.generated.json +4 -0
- package/src/runtime/shared/google-oauth-client.mjs +34 -9
- 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 +104 -0
- package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/llm/well-formed.mjs +66 -0
- package/src/runtime/shared/mixy-presence.mjs +22 -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 +231 -59
- package/src/runtime/shared/provider-api-key.mjs +19 -8
- 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 +52 -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 +34 -1
- 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-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -14
- package/src/runtime/shared/transcript-metadata.mjs +38 -0
- package/src/runtime/shared/user-data-guard.mjs +30 -2
- package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
- package/src/runtime/shared/worktrees/test-support.mjs +9 -4
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +27 -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 +486 -179
- package/src/session-runtime/agent-room-delivery.mjs +28 -1
- package/src/session-runtime/agent-task-sessions.mjs +561 -199
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/begin.mjs +3 -2
- 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 +8 -1
- package/src/session-runtime/bot-chain.mjs +32 -0
- package/src/session-runtime/bot-status.mjs +7 -4
- package/src/session-runtime/channel-config-api.mjs +63 -17
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
- package/src/session-runtime/internal-tool-executor.mjs +4 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
- 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 +61 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +927 -0
- package/src/session-runtime/model-route/route-tuning.mjs +10 -6
- 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 +35 -13
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-auth/login.mjs +7 -0
- package/src/session-runtime/provider-models/row-hydration.mjs +13 -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/routine-home-turn.mjs +33 -6
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/schedule-session-run.mjs +7 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- 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 +73 -31
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +128 -25
- package/src/session-runtime/services/schedule-access.mjs +14 -0
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +8 -4
- 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 +28 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +187 -29
- package/src/session-runtime/setup-tool/extended-actions.mjs +33 -2
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +68 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +92 -6
- package/src/session-runtime/task-session-route.mjs +99 -0
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +21 -4
- package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
- package/src/session-runtime/tool-surface.mjs +4 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
- package/src/session-runtime/workspace/transitions.mjs +10 -2
- 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 +161 -157
- package/src/standalone/daemon.mjs +33 -2
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +10 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- 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 +23 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-service.mjs +13 -0
- package/src/standalone/session-tool-output.mjs +21 -10
- package/src/tui/app/model-options.mjs +4 -27
- package/src/tui/dist/index.mjs +81 -65
- 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 +23 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/integrations.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +8 -0
- 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 +30 -2
- 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 +5 -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 +36 -3
- package/src/tui/session/turn.mjs +23 -2
- 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
|
@@ -18,6 +18,9 @@ import { resetOutputLimitRecovery, resolveOutputLimit } from './no-tool-turn/out
|
|
|
18
18
|
import { resolveRefusal } from './no-tool-turn/refusal.mjs';
|
|
19
19
|
import { resumeContinuation } from './no-tool-turn/continuation.mjs';
|
|
20
20
|
import { nudgeEmptyTurn } from './no-tool-turn/empty-nudge.mjs';
|
|
21
|
+
import { isReactionSuccess, reactionCallIds, takeReactionTarget } from '../../runtime-core/reaction-tool-defs.mjs';
|
|
22
|
+
import { messageIdOf } from '../message-ids.mjs';
|
|
23
|
+
import { isReactableMessage } from '../message-reactions.mjs';
|
|
21
24
|
|
|
22
25
|
// `escalateMaxTokens()` asks the live provider for a higher one-shot max_tokens
|
|
23
26
|
// (number) or reports none (null/undefined) — the loop stays provider-agnostic.
|
|
@@ -37,8 +40,11 @@ export function createNoToolTurnResolver({
|
|
|
37
40
|
outputEscalationUsed: false,
|
|
38
41
|
refusalRetryUsed: false,
|
|
39
42
|
emptyNudgeStreak: 0,
|
|
43
|
+
// Successful reactions (react tool): the input each was left against and
|
|
44
|
+
// whether it answered that input.
|
|
45
|
+
reactions: [],
|
|
40
46
|
// Structured provider continuation signals honored this turn. Diagnostic
|
|
41
|
-
// only:
|
|
47
|
+
// only: this count bounds nothing. A
|
|
42
48
|
// text-only continuation runaway is bounded by continuationsSinceToolBatch
|
|
43
49
|
// below; continuations interleaved with tool batches are not limited.
|
|
44
50
|
providerContinuationCount: 0,
|
|
@@ -46,6 +52,39 @@ export function createNoToolTurnResolver({
|
|
|
46
52
|
// continuation runaway (see PROVIDER_CONTINUATION_NO_TOOL_LIMIT).
|
|
47
53
|
continuationsSinceToolBatch: 0,
|
|
48
54
|
};
|
|
55
|
+
// The stable id (message-ids.mjs, kept across compaction) of the newest
|
|
56
|
+
// real user input; runtime reminders and notices are not reactable.
|
|
57
|
+
// A group-room member turn's prompt is a runtime message (not reactable)
|
|
58
|
+
// that carries the newest room-log user row it shows (`roomRow`).
|
|
59
|
+
const roomRowOf = (message) => message?.meta?.transcript?.roomRow || '';
|
|
60
|
+
const latestInput = () => messages.findLast((message) => isReactableMessage(message) || roomRowOf(message));
|
|
61
|
+
const latestInputId = () => messageIdOf(latestInput());
|
|
62
|
+
// A reaction exempts the input only while no newer input arrived since it
|
|
63
|
+
// landed (same latest input id) and it answered that input.
|
|
64
|
+
const reactionAnswersLatest = () => {
|
|
65
|
+
const id = latestInputId();
|
|
66
|
+
return state.reactions.some((reaction) => reaction.answered && reaction.inputId === id);
|
|
67
|
+
};
|
|
68
|
+
// What this batch's react calls hit, from the id the react tool recorded
|
|
69
|
+
// for each (never rebuilt from this transcript: a room reaction runs
|
|
70
|
+
// against the room's own log). Every record is consumed; a success that
|
|
71
|
+
// recorded none exempts nothing. A home-chat reaction answers the input
|
|
72
|
+
// only when it hit that very message; a room reaction, whose message is in
|
|
73
|
+
// another log, only when it hit the row this turn's prompt showed.
|
|
74
|
+
const batchReactions = (calls, results) => {
|
|
75
|
+
const input = latestInput();
|
|
76
|
+
const inputId = messageIdOf(input);
|
|
77
|
+
const hit = [];
|
|
78
|
+
for (const id of reactionCallIds(calls)) {
|
|
79
|
+
const target = takeReactionTarget(sessionId, id);
|
|
80
|
+
if (!target || !results.some((message) => isReactionSuccess(message, new Set([id])))) continue;
|
|
81
|
+
const answered = target.room
|
|
82
|
+
? roomRowOf(input) === target.messageId
|
|
83
|
+
: inputId !== '' && target.messageId === inputId;
|
|
84
|
+
hit.push({ inputId, answered });
|
|
85
|
+
}
|
|
86
|
+
return hit;
|
|
87
|
+
};
|
|
49
88
|
const trace = (iteration, kind, payload) => {
|
|
50
89
|
try {
|
|
51
90
|
appendAgentTrace({ sessionId, iteration, kind, payload, agent: sessionAgent || null });
|
|
@@ -101,7 +140,9 @@ export function createNoToolTurnResolver({
|
|
|
101
140
|
// output, …) and a text-only terminal turn is the correct shape —
|
|
102
141
|
// nudging them produces a contradictory user message that traps the
|
|
103
142
|
// model in a tool-call-blocked vs contract-required oscillation.
|
|
104
|
-
|
|
143
|
+
// A turn that left a reaction on the user's message may end with no
|
|
144
|
+
// text: the reaction is its answer (react tool), never an empty turn.
|
|
145
|
+
if (!hasContent && !HIDDEN_AGENT_NAMES.has(sessionAgent) && !reactionAnswersLatest()) {
|
|
105
146
|
return nudgeEmptyTurn(
|
|
106
147
|
response,
|
|
107
148
|
{ stopReason, isIncompleteStop: stopReason && INCOMPLETE_STOP_REASONS.has(stopReason) },
|
|
@@ -132,9 +173,16 @@ export function createNoToolTurnResolver({
|
|
|
132
173
|
state.emptyNudgeStreak = 0;
|
|
133
174
|
resetOutputLimitRecovery(state);
|
|
134
175
|
},
|
|
135
|
-
|
|
176
|
+
// `results` are the batch's tool result messages: only a react call that
|
|
177
|
+
// succeeded marks the turn as having reacted.
|
|
178
|
+
noteToolBatchCompleted(calls = [], results = []) {
|
|
136
179
|
state.continuationsSinceToolBatch = 0;
|
|
137
180
|
segments.clear();
|
|
181
|
+
state.reactions.push(...batchReactions(calls, results));
|
|
182
|
+
},
|
|
183
|
+
// The loop ended on a reaction that answered the latest user input.
|
|
184
|
+
get reactionCompleted() {
|
|
185
|
+
return reactionAnswersLatest();
|
|
138
186
|
},
|
|
139
187
|
get providerContinuations() {
|
|
140
188
|
return state.providerContinuationCount;
|
|
@@ -6,6 +6,12 @@ import { getProvider, initProviders } from '../../providers/registry.mjs';
|
|
|
6
6
|
import { loadConfig } from '../../config.mjs';
|
|
7
7
|
import { ensureProviderEnabled } from '../../runtime-core/config-helpers.mjs';
|
|
8
8
|
import { updateSessionRoute } from '../manager/session-lifecycle.mjs';
|
|
9
|
+
import {
|
|
10
|
+
liveRouteFallbacks,
|
|
11
|
+
nextRouteFallbackIndex,
|
|
12
|
+
routeFallbackHopped,
|
|
13
|
+
routeLeaf,
|
|
14
|
+
} from '../manager/route-fallback-chain.mjs';
|
|
9
15
|
import { pinSessionWireRoute } from '../../providers/wire-route.mjs';
|
|
10
16
|
import { buildRequestSendOptions } from '../manager/ask-turn-loop-options.mjs';
|
|
11
17
|
import { prepareTurnEffortConfiguration } from '../../providers/effort-configuration.mjs';
|
|
@@ -78,9 +84,13 @@ async function nextContextGrows(state, next) {
|
|
|
78
84
|
|
|
79
85
|
export async function advanceAgentRoute(state, error) {
|
|
80
86
|
const session = state.sessionRef;
|
|
81
|
-
if (!session?.agent
|
|
82
|
-
|
|
83
|
-
|
|
87
|
+
if (!session?.agent) return false;
|
|
88
|
+
// Read from the session's settings at this hop: a chain edited while it runs
|
|
89
|
+
// applies now, and one cleared to [] leaves the provider's own error.
|
|
90
|
+
const { chain } = liveRouteFallbacks(session, loadConfig({ secrets: false }));
|
|
91
|
+
if (!chain.length) return false;
|
|
92
|
+
const index = nextRouteFallbackIndex(session, chain);
|
|
93
|
+
const next = chain[index];
|
|
84
94
|
// Only THIS request must have produced nothing (its stream outcome says so):
|
|
85
95
|
// earlier requests of the turn may have run tools. Their calls and results
|
|
86
96
|
// are already in the live turn, which the next model continues from, so no
|
|
@@ -97,6 +107,8 @@ export async function advanceAgentRoute(state, error) {
|
|
|
97
107
|
const provider = getProvider(next.provider);
|
|
98
108
|
if (!provider) throw new Error(`Provider "${next.provider}" not available`);
|
|
99
109
|
const failed = routeFailure(session, error);
|
|
110
|
+
// The route a reset returns to (setup reset_route_fallback), kept from the first hop.
|
|
111
|
+
const primary = routeFallbackHopped(session) ? session.routeFallbackPrimary : routeLeaf(session);
|
|
100
112
|
// The left model's share of the turn ends here: the running total at the
|
|
101
113
|
// switch bounds it, so each model's tokens are booked at its own rates.
|
|
102
114
|
state.routeUsageHops = [
|
|
@@ -131,6 +143,8 @@ export async function advanceAgentRoute(state, error) {
|
|
|
131
143
|
{ crossProvider: true, session }
|
|
132
144
|
);
|
|
133
145
|
if (!updated) throw new Error('agent session closed during model fallback');
|
|
146
|
+
updated.routeFallbacks = chain;
|
|
147
|
+
if (primary) updated.routeFallbackPrimary = primary;
|
|
134
148
|
updated.routeFallbackIndex = index + 1;
|
|
135
149
|
updated.routeFallbackFailures = [...(session.routeFallbackFailures || []), failed];
|
|
136
150
|
await pinSessionWireRoute(updated, provider);
|
|
@@ -96,6 +96,9 @@ export async function beginIteration(state) {
|
|
|
96
96
|
opts.providerState = state.providerState;
|
|
97
97
|
if (state.forcedFirstTool && state.toolCallsTotal === 0) {
|
|
98
98
|
opts.toolChoice = 'required';
|
|
99
|
+
} else if (state.turnLimitNoticed) {
|
|
100
|
+
// A capped turn told to reply may only answer (turn-limits.mjs).
|
|
101
|
+
opts.toolChoice = 'none';
|
|
99
102
|
} else {
|
|
100
103
|
delete opts.toolChoice;
|
|
101
104
|
}
|
|
@@ -123,13 +126,16 @@ export async function beginIteration(state) {
|
|
|
123
126
|
getIterations: () => state.iterations,
|
|
124
127
|
getNextIteration: () => nextIteration,
|
|
125
128
|
repeatFailLimit: REPEAT_FAIL_LIMIT,
|
|
129
|
+
isTurnLimitNoticed: () => state.turnLimitNoticed === true,
|
|
126
130
|
});
|
|
127
131
|
const resolveToolCallId = createToolCallIdResolver(messages);
|
|
128
132
|
opts.onToolCall = (call) => {
|
|
129
133
|
resolveToolCallId(call);
|
|
130
134
|
try {
|
|
131
135
|
opts.onAssistantToolCallObserved?.(call, { eagerStarted: false });
|
|
132
|
-
} catch {
|
|
136
|
+
} catch {
|
|
137
|
+
// the tool-call observer is advisory
|
|
138
|
+
}
|
|
133
139
|
return eager.onToolCall(call);
|
|
134
140
|
};
|
|
135
141
|
return {
|
|
@@ -170,7 +176,9 @@ export async function sendProviderRequest(state, round) {
|
|
|
170
176
|
});
|
|
171
177
|
try {
|
|
172
178
|
opts.onProviderSendStarted?.();
|
|
173
|
-
} catch {
|
|
179
|
+
} catch {
|
|
180
|
+
// the send-started observer is advisory
|
|
181
|
+
}
|
|
174
182
|
// The request a /btw side question forks: kept while it is in flight, with
|
|
175
183
|
// its reply once it proceeds, and dropped again if it fails.
|
|
176
184
|
const sideQuestion = captureSideQuestionRequest({
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { normalizeToolEnvelope, makeToolEnvelope } from '../../tool-envelope.mjs';
|
|
6
6
|
import { resolveToolResultAfterHook } from '../tool-helpers.mjs';
|
|
7
|
+
import { effectiveToolCwd } from '../../../tools/builtin/bash-tool/shell-cwd.mjs';
|
|
7
8
|
|
|
8
9
|
export async function applyAfterToolHook(result, afterToolHook, { name, args, cwd, callerSessionId, toolCallId }) {
|
|
9
10
|
if (typeof afterToolHook !== 'function') return result;
|
|
@@ -15,7 +16,7 @@ export async function applyAfterToolHook(result, afterToolHook, { name, args, cw
|
|
|
15
16
|
const hookResult = await afterToolHook({
|
|
16
17
|
name,
|
|
17
18
|
args,
|
|
18
|
-
cwd,
|
|
19
|
+
cwd: effectiveToolCwd(name, args, cwd),
|
|
19
20
|
sessionId: callerSessionId,
|
|
20
21
|
toolCallId,
|
|
21
22
|
result: visible,
|
|
@@ -7,8 +7,15 @@ import { runAbortable, throwIfAborted } from '../../../../../shared/abort-race.m
|
|
|
7
7
|
import { evaluateExecPolicy } from '../../../tools/bash-policy-scan.mjs';
|
|
8
8
|
import { beginSessionApprovalWait } from '../../manager/runtime-liveness.mjs';
|
|
9
9
|
import { agentMcpToolPermission, writeAgentMcpToolPermission } from '../../../mcp/agent-connectors.mjs';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
actingBotId,
|
|
12
|
+
actingContactBotId,
|
|
13
|
+
allowAllActionsEnabled,
|
|
14
|
+
humanGateDecision,
|
|
15
|
+
recordHumanDecision,
|
|
16
|
+
} from '../../human-gate/gate.mjs';
|
|
11
17
|
import { applyEditedArgs } from '../../human-gate/requests.mjs';
|
|
18
|
+
import { effectiveToolCwd } from '../../../tools/builtin/bash-tool/shell-cwd.mjs';
|
|
12
19
|
|
|
13
20
|
const isArgsObject = (value) => value && typeof value === 'object' && !Array.isArray(value);
|
|
14
21
|
|
|
@@ -25,7 +32,7 @@ async function askApproval(
|
|
|
25
32
|
resolvePreToolAskApproval({
|
|
26
33
|
toolName: call.name,
|
|
27
34
|
args: call.args,
|
|
28
|
-
cwd: call.cwd,
|
|
35
|
+
cwd: effectiveToolCwd(call.name, call.args, call.cwd),
|
|
29
36
|
sessionId: callerSessionId,
|
|
30
37
|
toolCallId: executeOpts.toolCallId || null,
|
|
31
38
|
askReason,
|
|
@@ -62,13 +69,16 @@ export const CONNECTOR_APPROVAL_REASON = 'This connector tool is set to ask befo
|
|
|
62
69
|
* coding Lead, a task session, a workflow agent, a sub-agent) runs it unasked.
|
|
63
70
|
* Run after the hooks, on the final call: a renamed call is judged under its
|
|
64
71
|
* final name. A call the outbound gate owns (its card approved it, or a
|
|
65
|
-
* remembered outbound grant answered it) is not asked a second time.
|
|
72
|
+
* remembered outbound grant answered it) is not asked a second time. With the
|
|
73
|
+
* "Allow all actions" developer option on, `needs_approval` is not asked
|
|
74
|
+
* either (a payment or permanent delete was asked by the outbound gate above).
|
|
66
75
|
* @returns {Promise<{ denial: string } | null>} the denial, or null to run
|
|
67
76
|
*/
|
|
68
77
|
export function applyConnectorApproval(call, { agentId, callerSessionId, executeOpts, toolApprovalHook }) {
|
|
69
78
|
if (call.outboundApproved) return null;
|
|
70
79
|
if (!actingBotId(callerSessionId)) return null;
|
|
71
80
|
if (agentMcpToolPermission(agentId, call.name) !== 'needs_approval') return null;
|
|
81
|
+
if (allowAllActionsEnabled()) return null;
|
|
72
82
|
// "Always allow" is offered only to the contact bot that is acting, for its
|
|
73
83
|
// own policy entry for this one tool: never another bot or Mixy.
|
|
74
84
|
const botId = actingContactBotId(callerSessionId);
|
|
@@ -131,7 +141,7 @@ export async function applyBeforeToolHook({
|
|
|
131
141
|
{
|
|
132
142
|
name,
|
|
133
143
|
args,
|
|
134
|
-
cwd,
|
|
144
|
+
cwd: effectiveToolCwd(name, args, cwd),
|
|
135
145
|
sessionId: callerSessionId,
|
|
136
146
|
toolCallId: executeOpts.toolCallId || null,
|
|
137
147
|
},
|
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
* MCP, code graph, internal tools, shell, apply_patch, built-ins and foreign
|
|
4
4
|
* CLI adapters.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
executeMcpTool,
|
|
8
|
+
isBuiltinMailRead,
|
|
9
|
+
isMcpTool,
|
|
10
|
+
isRegisteredMcpTool,
|
|
11
|
+
mcpToolHasField,
|
|
12
|
+
} from '../../../mcp/client.mjs';
|
|
13
|
+
import { recordMailLinks } from '../../../../../browser-bridge/mail-links.mjs';
|
|
7
14
|
import {
|
|
8
15
|
executeBuiltinTool,
|
|
9
16
|
formatUnknownBuiltinToolMessage,
|
|
@@ -56,11 +63,18 @@ function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts
|
|
|
56
63
|
// an unknown argument.
|
|
57
64
|
const needsCwdInjection = cwd && mcpToolHasField(name, 'cwd', mcpScopeId) && (args == null || args.cwd == null);
|
|
58
65
|
const finalArgs = needsCwdInjection ? { ...(args || {}), cwd } : args;
|
|
59
|
-
|
|
66
|
+
const call = executeMcpTool(name, finalArgs, {
|
|
60
67
|
signal: executeOpts.signal || null,
|
|
61
68
|
ownerKey: callerSessionId,
|
|
62
69
|
scopeId: mcpScopeId,
|
|
63
70
|
});
|
|
71
|
+
if (!isBuiltinMailRead(name, mcpScopeId)) return call;
|
|
72
|
+
// The runtime's own record of the links in a mail it read for this session:
|
|
73
|
+
// the only way Browser Use may open a link carrying a token.
|
|
74
|
+
return call.then((result) => {
|
|
75
|
+
recordMailLinks(callerSessionId, result);
|
|
76
|
+
return result;
|
|
77
|
+
});
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
function dispatchInternal(
|
|
@@ -19,6 +19,7 @@ import { applyBeforeToolHook, applyConnectorApproval, applyShellElevationGate }
|
|
|
19
19
|
import { dispatchToolCall } from './tool-exec/dispatch.mjs';
|
|
20
20
|
import { applyAfterToolHook } from './tool-exec/after-hook.mjs';
|
|
21
21
|
import { runReadOnlyIoWithDeadline } from './tool-exec/read-only-deadline.mjs';
|
|
22
|
+
import { guardShellCall, requestedShellType } from '../../tools/builtin/bash-tool/misuse-guard.mjs';
|
|
22
23
|
|
|
23
24
|
export { runReadOnlyIoWithDeadline as _runReadOnlyIoWithDeadlineForTest };
|
|
24
25
|
export {
|
|
@@ -43,9 +44,23 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
|
|
|
43
44
|
const prepared = prepareToolCall(name, args, cwd, callerSessionId, sessionRef, executeOpts);
|
|
44
45
|
const { toolOpts, notifyFn, completionToolOpts } = prepared;
|
|
45
46
|
const toolApprovalHook = hookFrom(executeOpts, sessionRef, 'toolApprovalHook');
|
|
47
|
+
// Shell misuse is judged before any hook or approval sees the call, so they
|
|
48
|
+
// read the command that will run and the directory it runs in.
|
|
49
|
+
let callArgs = prepared.args;
|
|
50
|
+
if (name === 'shell') {
|
|
51
|
+
const guarded = guardShellCall(callArgs, {
|
|
52
|
+
shellType: requestedShellType(callArgs),
|
|
53
|
+
agent: sessionRef?.agent || null,
|
|
54
|
+
sessionId: callerSessionId,
|
|
55
|
+
telemetry: executeOpts.resultTelemetry,
|
|
56
|
+
});
|
|
57
|
+
if (guarded.failure) return guarded.failure;
|
|
58
|
+
callArgs = guarded.args;
|
|
59
|
+
completionToolOpts.shellGuardNotes = guarded.notes;
|
|
60
|
+
}
|
|
46
61
|
const hooked = await applyBeforeToolHook({
|
|
47
62
|
name,
|
|
48
|
-
args:
|
|
63
|
+
args: callArgs,
|
|
49
64
|
cwd: prepared.cwd,
|
|
50
65
|
callerSessionId,
|
|
51
66
|
executeOpts,
|
|
@@ -18,6 +18,7 @@ import { isAgentOwner } from '../../agent-owner.mjs';
|
|
|
18
18
|
import { honoredSchemaAllowlist } from '../manager/session-tool-surface.mjs';
|
|
19
19
|
import { syncSystemPrefix } from '../manager/prompt-utils.mjs';
|
|
20
20
|
import { invalidateProviderContextBaseline } from './compact-policy.mjs';
|
|
21
|
+
import { rebindToChangedPrefix } from '../thinking-binding.mjs';
|
|
21
22
|
|
|
22
23
|
/** Drop everything measured against the previous tool surface. */
|
|
23
24
|
function invalidateForToolSurfaceMigration(session) {
|
|
@@ -34,6 +35,14 @@ function invalidateForToolSurfaceMigration(session) {
|
|
|
34
35
|
*/
|
|
35
36
|
export function markToolSurfaceMigrated(session, intent = TOOL_SURFACE_MIGRATION_INTENT) {
|
|
36
37
|
invalidateForToolSurfaceMigration(session);
|
|
38
|
+
// The stored thinking was bound to the previous prefix and can never be
|
|
39
|
+
// replayed again (../thinking-binding.mjs); an open tool round a stopped
|
|
40
|
+
// turn left behind is ended first. Outside a turn only: a running turn sends
|
|
41
|
+
// from its own working transcript, whose latest tool round must keep its
|
|
42
|
+
// thinking.
|
|
43
|
+
if (Array.isArray(session.messages) && !Array.isArray(session.liveTurnMessages)) {
|
|
44
|
+
session.messages = rebindToChangedPrefix(session.messages);
|
|
45
|
+
}
|
|
37
46
|
session.pendingCacheBreakIntent = intent;
|
|
38
47
|
}
|
|
39
48
|
|
|
@@ -105,6 +114,7 @@ const AGENT_BRIDGE_FIELDS = [
|
|
|
105
114
|
'deferredToolDeltaRevision',
|
|
106
115
|
'nativeDeferredDiscovery',
|
|
107
116
|
'mcpServerInstructions',
|
|
117
|
+
'mcpInstructionsAnnounced',
|
|
108
118
|
];
|
|
109
119
|
|
|
110
120
|
/**
|
|
@@ -12,10 +12,7 @@ import {
|
|
|
12
12
|
loadSkillResource,
|
|
13
13
|
buildSkillToolEnvelope,
|
|
14
14
|
filterSkillsExcludingDisabled,
|
|
15
|
-
|
|
16
|
-
skillMissingFeature,
|
|
17
|
-
skillOutsideScope,
|
|
18
|
-
skillOutsideScopeError,
|
|
15
|
+
skillLoadRefusal,
|
|
19
16
|
} from '../../context/collect.mjs';
|
|
20
17
|
|
|
21
18
|
// Eager-dispatch: tools with readOnlyHint:true in their declaration are safe
|
|
@@ -95,12 +92,8 @@ export function buildSkillsListResponse(cwd) {
|
|
|
95
92
|
export function viewSkill(cwd, name, session = null) {
|
|
96
93
|
const skillName = String(name || '').trim();
|
|
97
94
|
if (!skillName) return 'Error: skill name is required';
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
100
|
-
return `Error: skill "${skillName}" needs the ${missingFeature} built-in feature, which is not installed or is switched off in Extensions → Plugin → Built-in`;
|
|
101
|
-
}
|
|
102
|
-
if (isSkillDisabled(skillName)) return `Error: skill "${skillName}" is disabled`;
|
|
103
|
-
if (skillOutsideScope(skillName, cwd)) return skillOutsideScopeError(skillName);
|
|
95
|
+
const refusal = skillLoadRefusal(skillName, cwd);
|
|
96
|
+
if (refusal) return refusal;
|
|
104
97
|
const res = loadSkillResource(skillName, cwd);
|
|
105
98
|
if (!res) return `Error: skill "${skillName}" not found`;
|
|
106
99
|
// Return the general tool envelope: the model-visible tool_result is the
|
|
@@ -9,6 +9,8 @@ import { processToolBatch } from '../tool-batch.mjs';
|
|
|
9
9
|
import { CROSS_TURN_CAP, REPEAT_FAIL_LIMIT } from './loop-state.mjs';
|
|
10
10
|
import { markStepEffort } from './step-auto-effort.mjs';
|
|
11
11
|
import { resolveExecutionToolCalls } from './tool-call-resolution.mjs';
|
|
12
|
+
import { rememberSensitiveValues } from '../sensitive-values.mjs';
|
|
13
|
+
import { callsAllowed, settleTurnLimits, turnLimitsOf } from './turn-limits.mjs';
|
|
12
14
|
|
|
13
15
|
function isSleepLikeToolCall(call) {
|
|
14
16
|
const name = String(call?.name || call?.toolName || call?.function?.name || '').toLowerCase();
|
|
@@ -17,9 +19,13 @@ function isSleepLikeToolCall(call) {
|
|
|
17
19
|
|
|
18
20
|
export async function runToolPhase(state, round, sent, onToolCall) {
|
|
19
21
|
const { opts, messages, tools, sessionId, sessionRef, signal, response } = state;
|
|
20
|
-
state.noToolTurn.noteToolCallTurn();
|
|
21
22
|
const calls = response.toolCalls;
|
|
23
|
+
state.noToolTurn.noteToolCallTurn();
|
|
22
24
|
round.resolveToolCallId.all(calls);
|
|
25
|
+
// A capped turn (turn-limits.mjs): calls past its cap are answered unrun,
|
|
26
|
+
// and a batch after it was told to reply ends it.
|
|
27
|
+
const allowed = callsAllowed(state);
|
|
28
|
+
const overrun = state.turnLimitNoticed === true;
|
|
23
29
|
state.toolCallsTotal += calls.length;
|
|
24
30
|
// Surface any mid-turn assistant text (preamble before a tool call) to the
|
|
25
31
|
// UI. Providers that stream via onTextDelta already rendered it; providers
|
|
@@ -36,14 +42,21 @@ export async function runToolPhase(state, round, sent, onToolCall) {
|
|
|
36
42
|
// derive the multi-tool adoption ratio without scanning message bodies.
|
|
37
43
|
// Audit records what runs: a bridged call_tool is recorded as its target.
|
|
38
44
|
// The wire calls stay the transcript identity (assistant turn below).
|
|
39
|
-
const
|
|
45
|
+
const executionCalls = resolveExecutionToolCalls(calls, sessionRef);
|
|
46
|
+
const toolBatchId = recordToolBatch(sessionId, executionCalls, state.iterations);
|
|
47
|
+
// A sensitive fill (a verification code): every stored copy of the
|
|
48
|
+
// transcript keeps a marker instead of the value; the call runs as is.
|
|
49
|
+
rememberSensitiveValues(sessionId, executionCalls);
|
|
40
50
|
await Promise.resolve(onToolCall?.(state.iterations, calls));
|
|
41
51
|
const assistantTurnMsg = buildToolCallAssistantMessage(response, { calls, opts });
|
|
42
52
|
commitAssistantMessage(messages, assistantTurnMsg, opts);
|
|
43
53
|
try {
|
|
44
54
|
opts.onToolPhaseStarted?.();
|
|
45
|
-
} catch {
|
|
55
|
+
} catch {
|
|
56
|
+
// the tool-phase-started observer is advisory
|
|
57
|
+
}
|
|
46
58
|
const toolsT0 = Date.now();
|
|
59
|
+
const resultsFrom = messages.length;
|
|
47
60
|
({ dedupStubTotal: state.dedupStubTotal, editCount: state.editCount } = await processToolBatch({
|
|
48
61
|
calls,
|
|
49
62
|
messages,
|
|
@@ -67,10 +80,13 @@ export async function runToolPhase(state, round, sent, onToolCall) {
|
|
|
67
80
|
pushToolResultMessage: state.pushToolResultMessage,
|
|
68
81
|
throwIfAborted: state.throwIfAborted,
|
|
69
82
|
repeatFailLimit: REPEAT_FAIL_LIMIT,
|
|
83
|
+
callsAllowed: allowed,
|
|
84
|
+
wrapUpAt: turnLimitsOf(state.opts)?.wrapUpAt,
|
|
70
85
|
}));
|
|
71
86
|
// A turn recovered from a stream cut that dropped an in-flight tool call
|
|
72
87
|
// carries a runtime notice for the model, delivered after its results.
|
|
73
88
|
if (response.recoveryNotice) messages.push(response.recoveryNotice);
|
|
89
|
+
settleTurnLimits(state, overrun);
|
|
74
90
|
const toolsEndedAt = Date.now();
|
|
75
91
|
// Starts the step judgment; the next request uses it if it has resolved by
|
|
76
92
|
// then (send-phase.mjs applyStepEffort), else the one after.
|
|
@@ -81,7 +97,9 @@ export async function runToolPhase(state, round, sent, onToolCall) {
|
|
|
81
97
|
calls: calls.length,
|
|
82
98
|
elapsedMs: toolsEndedAt - toolsT0,
|
|
83
99
|
});
|
|
84
|
-
} catch {
|
|
100
|
+
} catch {
|
|
101
|
+
// the tool-phase-completed observer is advisory
|
|
102
|
+
}
|
|
85
103
|
traceLoopPhaseTiming({
|
|
86
104
|
iteration: round.nextIteration,
|
|
87
105
|
preSendMs: sent.preSendMs,
|
|
@@ -91,6 +109,6 @@ export async function runToolPhase(state, round, sent, onToolCall) {
|
|
|
91
109
|
});
|
|
92
110
|
state.lastToolBatchEndedAt = toolsEndedAt;
|
|
93
111
|
state.toolBatchJustCompleted = true;
|
|
94
|
-
state.noToolTurn.noteToolBatchCompleted();
|
|
112
|
+
state.noToolTurn.noteToolBatchCompleted(calls, messages.slice(resultsFrom));
|
|
95
113
|
state.lastToolBatchHadSleep = calls.some(isSleepLikeToolCall);
|
|
96
114
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turn-limits.mjs — a turn's caps (sendOpts.turnLimits; a heartbeat turn's,
|
|
3
|
+
* manager/ask-turn-loop-options.mjs): `maxToolCalls` tool calls and
|
|
4
|
+
* `wrapUpAt` (epoch ms). A call past the cap, or one made after the wrap-up
|
|
5
|
+
* time, is answered without running. Once a cap is reached the model is told
|
|
6
|
+
* to reply, and every later request of the turn forbids tool use
|
|
7
|
+
* (toolChoice 'none'). A response that still calls tools after that ends the
|
|
8
|
+
* turn with no reply, its calls answered unrun. A capped turn runs no call
|
|
9
|
+
* eagerly (eager-dispatch.mjs), so none past the cap starts while streaming.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const NOTICE =
|
|
13
|
+
'[mixdog-runtime] This turn has reached its tool-call or time limit: no further tool call runs. Reply now with your final answer from what you already have.';
|
|
14
|
+
const REFUSAL =
|
|
15
|
+
'[turn-limit] This turn has reached its tool-call or time limit; this call was not run. Reply now without tools.';
|
|
16
|
+
|
|
17
|
+
/** `{ maxToolCalls, wrapUpAt }` of a capped turn (Infinity where unset), else null. */
|
|
18
|
+
export function turnLimitsOf(opts) {
|
|
19
|
+
const limits = opts?.turnLimits;
|
|
20
|
+
if (!limits || typeof limits !== 'object') return null;
|
|
21
|
+
return {
|
|
22
|
+
maxToolCalls: Number.isInteger(limits.maxToolCalls) && limits.maxToolCalls >= 0 ? limits.maxToolCalls : Infinity,
|
|
23
|
+
wrapUpAt: Number.isFinite(limits.wrapUpAt) ? limits.wrapUpAt : Infinity,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** How many calls of the next batch may run, before the loop counts them. */
|
|
28
|
+
export function callsAllowed(state, now = Date.now()) {
|
|
29
|
+
const limits = turnLimitsOf(state.opts);
|
|
30
|
+
if (!limits) return Infinity;
|
|
31
|
+
if (state.turnLimitNoticed || now >= limits.wrapUpAt) return 0;
|
|
32
|
+
return Math.max(0, limits.maxToolCalls - state.toolCallsTotal);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The answer to a call the cap kept from running. */
|
|
36
|
+
export function turnLimitRefusal(call) {
|
|
37
|
+
return { role: 'tool', content: REFUSAL, toolCallId: call.id, toolKind: 'error' };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* After a tool batch: `overrun` when the batch came after the turn was told
|
|
42
|
+
* to reply, which ends the turn (state.turnLimitEnded). Otherwise, once a cap
|
|
43
|
+
* is reached, the model is told once to reply.
|
|
44
|
+
*/
|
|
45
|
+
export function settleTurnLimits(state, overrun, now = Date.now()) {
|
|
46
|
+
if (overrun) {
|
|
47
|
+
state.turnLimitEnded = true;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const limits = turnLimitsOf(state.opts);
|
|
51
|
+
if (!limits || state.turnLimitNoticed) return;
|
|
52
|
+
if (state.toolCallsTotal < limits.maxToolCalls && now < limits.wrapUpAt) return;
|
|
53
|
+
state.turnLimitNoticed = true;
|
|
54
|
+
state.messages.push({ role: 'user', content: NOTICE, meta: { source: 'turn-limit' } });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** The turn's end after an overrun: no reply. */
|
|
58
|
+
export function endedWithoutReply(response) {
|
|
59
|
+
return { ...response, content: '', toolCalls: [] };
|
|
60
|
+
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
drainPendingMessages,
|
|
10
10
|
releasePendingMessages,
|
|
11
11
|
} from './pending-messages.mjs';
|
|
12
|
+
import { promptOriginOf } from '../../../../shared/prompt-origin.mjs';
|
|
12
13
|
|
|
13
14
|
const SYNTHETIC_PROMPT_SOURCES = ['goal-continuation', 'goal-closeout'];
|
|
14
15
|
|
|
@@ -35,6 +36,7 @@ const tailTurnFor = (group) => ({
|
|
|
35
36
|
content: group.content,
|
|
36
37
|
entries: group.entries,
|
|
37
38
|
...(group.hop ? { hop: group.hop } : {}),
|
|
39
|
+
...(group.origin ? { origin: group.origin } : {}),
|
|
38
40
|
...(group.mode === PENDING_MODE_TASK_NOTIFICATION
|
|
39
41
|
? promptSourceFields(PENDING_MODE_TASK_NOTIFICATION, group.execution)
|
|
40
42
|
: {}),
|
|
@@ -49,13 +51,19 @@ const queuedTurnInput = (tailTurn) => ({
|
|
|
49
51
|
pendingEntries: tailTurn.entries,
|
|
50
52
|
...(tailTurn.hop ? { hop: tailTurn.hop } : {}),
|
|
51
53
|
promptSource: promptSourceFields(tailTurn.source, tailTurn.execution),
|
|
54
|
+
...(tailTurn.origin ? { promptOrigin: tailTurn.origin } : {}),
|
|
52
55
|
});
|
|
53
56
|
|
|
54
|
-
|
|
57
|
+
// The caller's provenance of its initial prompt, apart from its presentation
|
|
58
|
+
// source: an inbound channel message or an agent report (shared/prompt-origin.mjs).
|
|
59
|
+
const initialPromptOriginFor = (promptOrigin) => promptOriginOf(promptOrigin);
|
|
60
|
+
|
|
61
|
+
export function createAskPromptQueue({ sessionId, promptSource, promptOrigin }) {
|
|
55
62
|
// Local FIFO of follow-up prompts drained from the pending-message queue
|
|
56
63
|
// after each turn — keeps queued `agent type=send` messages in order.
|
|
57
64
|
const tail = [];
|
|
58
65
|
let initialPromptSource = initialPromptSourceFor(promptSource);
|
|
66
|
+
let initialPromptOrigin = initialPromptOriginFor(promptOrigin);
|
|
59
67
|
// Queue entries of the input nextTurn handed out that no turn owns yet.
|
|
60
68
|
// Once a turn starts, its failure path acks or releases them instead.
|
|
61
69
|
let unstartedEntries = [];
|
|
@@ -67,13 +75,15 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
|
|
|
67
75
|
* and provenance — or null when nothing model-visible is left to run. */
|
|
68
76
|
const nextTurn = (original) => {
|
|
69
77
|
const source = initialPromptSource;
|
|
78
|
+
const origin = initialPromptOrigin;
|
|
70
79
|
initialPromptSource = null;
|
|
80
|
+
initialPromptOrigin = null;
|
|
71
81
|
let input;
|
|
72
82
|
if (tail.length > 0) {
|
|
73
83
|
// After the first turn, the next prompt comes from the drained queue.
|
|
74
84
|
input = queuedTurnInput(tail.shift());
|
|
75
85
|
} else if (hasModelVisiblePromptContent(original.prompt)) {
|
|
76
|
-
input = { ...original, pendingEntries: [], promptSource: source };
|
|
86
|
+
input = { ...original, pendingEntries: [], promptSource: source, ...(origin ? { promptOrigin: origin } : {}) };
|
|
77
87
|
} else {
|
|
78
88
|
// Idle resume: TUI kicks an empty ask() after execution completions
|
|
79
89
|
// mirror model-visible bodies into session pending. Drain that queue
|
|
@@ -19,6 +19,7 @@ import { armTurnDurability, claimTurnRuntime } from './ask-turn-open.mjs';
|
|
|
19
19
|
import { prepareAskTurn, runAskAgentLoop } from './ask-turn-execute.mjs';
|
|
20
20
|
import { commitAskTurn, publishAskTurn } from './ask-turn-settle.mjs';
|
|
21
21
|
import { finalizeAskTurnFailure } from './ask-turn-failure.mjs';
|
|
22
|
+
import { cacheWarmTurnKind, endCacheWarmTurn, failedTurnProvenance, noteCacheWarmTurn } from '../cache-warm.mjs';
|
|
22
23
|
|
|
23
24
|
export { _api_call_with_interrupt } from './ask-call-interrupt.mjs';
|
|
24
25
|
export {
|
|
@@ -168,7 +169,14 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
168
169
|
// return value (the queued tail turns supersede the original prompt's
|
|
169
170
|
// result, mirroring how a live chat returns the latest turn).
|
|
170
171
|
let result;
|
|
171
|
-
const queue = createAskPromptQueue({
|
|
172
|
+
const queue = createAskPromptQueue({
|
|
173
|
+
sessionId,
|
|
174
|
+
promptSource: askOpts.promptSource,
|
|
175
|
+
promptOrigin: askOpts.promptOrigin,
|
|
176
|
+
});
|
|
177
|
+
// The turn the prompt-cache warmer is told about last; it forgets it when
|
|
178
|
+
// the turn ends (endCacheWarmTurn), whatever way the ask unwinds.
|
|
179
|
+
let warmTurn = null;
|
|
172
180
|
// Hoisted so the outer finally (which runs once after the whole turn loop)
|
|
173
181
|
// can compare against the last turn's generation.
|
|
174
182
|
let askGeneration = 0;
|
|
@@ -213,6 +221,12 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
213
221
|
recoverCheckpoint: !crashRecoveryChecked,
|
|
214
222
|
emitStart: !sessionStartEmitted,
|
|
215
223
|
});
|
|
224
|
+
// The prompt-cache warmer learns idle gaps from real turns only; a
|
|
225
|
+
// retry is classified by the failed turn's stored provenance.
|
|
226
|
+
// The rebuilt retry message keeps that provenance (ask-turn-execute.mjs).
|
|
227
|
+
const retryProvenance = failedTurnProvenance(claimed.preSession?.messages, input);
|
|
228
|
+
if (retryProvenance) input.retryProvenance = retryProvenance;
|
|
229
|
+
warmTurn = noteCacheWarmTurn(sessionId, cacheWarmTurnKind(input, claimed.preSession?.messages));
|
|
216
230
|
crashRecoveryChecked = true;
|
|
217
231
|
sessionStartEmitted = true;
|
|
218
232
|
askGeneration = claimed.askGeneration;
|
|
@@ -234,6 +248,7 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
234
248
|
askStartedAt,
|
|
235
249
|
});
|
|
236
250
|
result = turn.result;
|
|
251
|
+
endCacheWarmTurn(sessionId, warmTurn);
|
|
237
252
|
// Turn complete. Drain the pending-message queue: any `agent type=send`
|
|
238
253
|
// that arrived while this turn was in flight runs next, in order, as a
|
|
239
254
|
// follow-up user turn. The mutex is still held, so a send racing this
|
|
@@ -264,6 +279,9 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
264
279
|
return result;
|
|
265
280
|
}
|
|
266
281
|
} finally {
|
|
282
|
+
// A failed/cancelled turn ends here too: its warmer turn entry goes (a
|
|
283
|
+
// later ask's own turn is never removed by this one).
|
|
284
|
+
endCacheWarmTurn(sessionId, warmTurn);
|
|
267
285
|
// A failed/cancelled turn ends the ask: the follow-up turns drained
|
|
268
286
|
// behind it never ran, so their entries go back to the pending queue.
|
|
269
287
|
queue.releaseUnstarted();
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// its empty-final forensic record), the usage/cost ledger row, and the
|
|
4
4
|
// opaque provider continuation state.
|
|
5
5
|
import { cloneProviderReplay } from '../../providers/lib/provider-replay.mjs';
|
|
6
|
+
import { turnReminderField } from '../loop/assistant-commit.mjs';
|
|
6
7
|
import { logLlmCall } from '../../usage-log.mjs';
|
|
7
8
|
import { runAbortable } from '../../../../shared/abort-race.mjs';
|
|
8
9
|
import { getAgentRuntimeSync } from './agent-runtime-singleton.mjs';
|
|
@@ -31,6 +32,7 @@ export function appendAssistantTurnMessage({ session, sessionId, result, transcr
|
|
|
31
32
|
...(result.providerMetadata && typeof result.providerMetadata === 'object'
|
|
32
33
|
? { providerMetadata: result.providerMetadata }
|
|
33
34
|
: {}),
|
|
35
|
+
...turnReminderField(result),
|
|
34
36
|
// Keep terminal provider evidence for non-empty turns too. A safety
|
|
35
37
|
// classifier can emit narration and then refuse; omitting this
|
|
36
38
|
// metadata made that shape indistinguishable from an ordinary
|