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
|
@@ -6,7 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { createClaudeReducer } from './claude.mjs';
|
|
8
8
|
import { createCodexReducer } from './codex.mjs';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
IMPORT_ERROR_INTERNAL,
|
|
11
|
+
IMPORT_WARNING_HISTORY_PARTIAL,
|
|
12
|
+
IMPORT_WARNING_MALFORMED,
|
|
13
|
+
conversationTitle,
|
|
14
|
+
normalizeTurns,
|
|
15
|
+
} from './turns.mjs';
|
|
10
16
|
|
|
11
17
|
export const IMPORT_SOURCES = Object.freeze(['codex', 'claude']);
|
|
12
18
|
/** A line or converted transcript beyond the import limits fails the file. */
|
|
@@ -35,7 +41,9 @@ const transcriptChars = (turns) => turns.reduce((total, turn) => total + turn.te
|
|
|
35
41
|
* (an over-long line or file). `result()` may be called repeatedly and also
|
|
36
42
|
* holds the normalized turns to `maxTranscriptChars`.
|
|
37
43
|
* `errorCode` is null for an importable result, else one of `empty` |
|
|
38
|
-
* `malformed` | `unsupported` | `
|
|
44
|
+
* `malformed` | `unsupported` | `internalRecord` (the source app's own
|
|
45
|
+
* subagent/review record; `internalKind` names it) | `tooLarge` (whose turns
|
|
46
|
+
* are not returned).
|
|
39
47
|
*/
|
|
40
48
|
export function createConversationConverter(
|
|
41
49
|
source,
|
|
@@ -47,18 +55,37 @@ export function createConversationConverter(
|
|
|
47
55
|
) {
|
|
48
56
|
if (!isImportSource(source)) throw new TypeError('source must be codex or claude.');
|
|
49
57
|
const reducer = source === 'codex' ? createCodexReducer() : createClaudeReducer();
|
|
50
|
-
let lines = 0;
|
|
51
58
|
let records = 0;
|
|
52
59
|
let malformed = 0;
|
|
53
60
|
let tooLarge = false;
|
|
61
|
+
let historyPartial = false;
|
|
54
62
|
return {
|
|
63
|
+
/** True while every message seen so far is a Claude sidechain message. */
|
|
64
|
+
get sidechainOnly() {
|
|
65
|
+
return reducer.sidechainOnly === true;
|
|
66
|
+
},
|
|
55
67
|
markTooLarge() {
|
|
56
68
|
tooLarge = true;
|
|
57
69
|
},
|
|
58
|
-
|
|
70
|
+
/** A history base could not be followed in full. */
|
|
71
|
+
markHistoryPartial() {
|
|
72
|
+
historyPartial = true;
|
|
73
|
+
},
|
|
74
|
+
/** Feed a line for the stored title only (Claude Code's tail window); other sources ignore it. */
|
|
75
|
+
pushTitleLine(raw) {
|
|
76
|
+
let value;
|
|
77
|
+
try {
|
|
78
|
+
value = JSON.parse(String(raw).trim());
|
|
79
|
+
} catch {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (value && typeof value === 'object') reducer.pushTitle?.(value);
|
|
83
|
+
},
|
|
84
|
+
/** `inherited` lines belong to a history base followed ahead of this file's own lines. */
|
|
85
|
+
pushLine(raw, { inherited = false } = {}) {
|
|
59
86
|
if (tooLarge) return false;
|
|
60
87
|
let line = String(raw);
|
|
61
|
-
if (
|
|
88
|
+
if (line.charCodeAt(0) === 0xfeff) line = line.slice(1);
|
|
62
89
|
if (line.endsWith('\r')) line = line.slice(0, -1);
|
|
63
90
|
if (!line.trim()) return true;
|
|
64
91
|
let value;
|
|
@@ -73,7 +100,7 @@ export function createConversationConverter(
|
|
|
73
100
|
return true;
|
|
74
101
|
}
|
|
75
102
|
records += 1;
|
|
76
|
-
reducer.push(value);
|
|
103
|
+
reducer.push(value, inherited);
|
|
77
104
|
if (
|
|
78
105
|
reducer.chars > maxTranscriptChars ||
|
|
79
106
|
reducer.entries > maxRetainedEntries ||
|
|
@@ -90,8 +117,10 @@ export function createConversationConverter(
|
|
|
90
117
|
if (transcriptChars(turns) > maxTranscriptChars) tooLarge = true;
|
|
91
118
|
const warnings = new Set(parsed.warnings);
|
|
92
119
|
if (malformed) warnings.add(IMPORT_WARNING_MALFORMED);
|
|
120
|
+
if (historyPartial) warnings.add(IMPORT_WARNING_HISTORY_PARTIAL);
|
|
93
121
|
let errorCode = null;
|
|
94
122
|
if (tooLarge) errorCode = IMPORT_ERROR_TOO_LARGE;
|
|
123
|
+
else if (parsed.internalKind) errorCode = IMPORT_ERROR_INTERNAL;
|
|
95
124
|
else if (!records) errorCode = malformed ? 'malformed' : 'empty';
|
|
96
125
|
else if (!parsed.recognized) errorCode = 'unsupported';
|
|
97
126
|
else if (!turns.length) errorCode = 'empty';
|
|
@@ -100,8 +129,10 @@ export function createConversationConverter(
|
|
|
100
129
|
errorCode,
|
|
101
130
|
foreignSessionId: parsed.foreignSessionId,
|
|
102
131
|
cwd: parsed.cwd,
|
|
132
|
+
internalKind: parsed.internalKind,
|
|
133
|
+
historyBase: parsed.historyBase ?? null,
|
|
103
134
|
turns: tooLarge ? [] : turns,
|
|
104
|
-
title: conversationTitle(turns),
|
|
135
|
+
title: parsed.storedTitle || conversationTitle(turns),
|
|
105
136
|
messageCount: tooLarge ? 0 : turns.length,
|
|
106
137
|
warnings: [...warnings],
|
|
107
138
|
};
|
|
@@ -70,6 +70,9 @@ export function importedTranscriptMessages(turns, importedAt) {
|
|
|
70
70
|
content: turn.text,
|
|
71
71
|
meta: {
|
|
72
72
|
source: IMPORTED_MESSAGE_SOURCE,
|
|
73
|
+
// Where the text holds a run of tool use, and which tools: the desktop
|
|
74
|
+
// draws each run as a native activity row.
|
|
75
|
+
...(turn.toolRuns?.length ? { importedToolRuns: turn.toolRuns } : {}),
|
|
73
76
|
transcript: { messageId: newTranscriptMessageId(), at: turn.at || importedAt },
|
|
74
77
|
},
|
|
75
78
|
}));
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
export const IMPORT_WARNING_IMAGE_OMITTED = 'imageOmitted';
|
|
10
10
|
export const IMPORT_WARNING_MALFORMED = 'malformed';
|
|
11
11
|
export const IMPORT_WARNING_CWD_MISSING = 'cwdMissing';
|
|
12
|
+
/** The conversation continues a history stored in another file that was not followed. */
|
|
13
|
+
export const IMPORT_WARNING_HISTORY_PARTIAL = 'historyPartial';
|
|
14
|
+
|
|
15
|
+
/** Failure code of a record the source app writes for its own use (not a conversation). */
|
|
16
|
+
export const IMPORT_ERROR_INTERNAL = 'internalRecord';
|
|
12
17
|
|
|
13
18
|
/** Stands in for an image the importer does not carry over. */
|
|
14
19
|
export const IMAGE_OMITTED_TEXT = '[image omitted]';
|
|
@@ -17,12 +22,49 @@ export const IMPORTED_USER_STUB_TEXT = '[Imported conversation continues from an
|
|
|
17
22
|
|
|
18
23
|
const TITLE_MAX_CHARS = 100;
|
|
19
24
|
|
|
20
|
-
/**
|
|
25
|
+
/** Note for a tool call: its name only, never its arguments. A run of notes
|
|
26
|
+
* becomes one compact line in the text and one structured entry in `toolRuns`. */
|
|
21
27
|
export function toolNote(name) {
|
|
22
|
-
const clean =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
const clean =
|
|
29
|
+
String(name || '')
|
|
30
|
+
.replace(/\s+/g, ' ')
|
|
31
|
+
.trim() || 'unknown';
|
|
32
|
+
return { text: `[ran tool: ${clean}]`, note: true, tool: clean };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Longest model-facing run line, and the longest tool name shown in it. */
|
|
36
|
+
export const TOOL_RUN_LINE_MAX_CHARS = 400;
|
|
37
|
+
const TOOL_RUN_NAME_MAX_CHARS = 40;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Model-facing line for one run of tool notes: `[ran tools: shell ×6, Read ×2]`.
|
|
41
|
+
* Bounded: names are clipped, and tools that do not fit are counted as
|
|
42
|
+
* `, +N more`. Deterministic in `tools`, so a stored line can be re-derived.
|
|
43
|
+
*/
|
|
44
|
+
export function toolRunLine(tools) {
|
|
45
|
+
const entries = tools.map(({ name, count }) => {
|
|
46
|
+
const chars = Array.from(String(name));
|
|
47
|
+
const shown =
|
|
48
|
+
chars.length > TOOL_RUN_NAME_MAX_CHARS ? `${chars.slice(0, TOOL_RUN_NAME_MAX_CHARS - 1).join('')}…` : name;
|
|
49
|
+
return `${shown} ×${count}`;
|
|
50
|
+
});
|
|
51
|
+
const omittedSuffix = (omitted) => (omitted > 0 ? `, +${omitted} more` : '');
|
|
52
|
+
let body = '';
|
|
53
|
+
let shownCount = 0;
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
const next = shownCount ? `${body}, ${entry}` : entry;
|
|
56
|
+
const length = `[ran tools: ${next}${omittedSuffix(entries.length - shownCount - 1)}]`.length;
|
|
57
|
+
if (shownCount && length > TOOL_RUN_LINE_MAX_CHARS) break;
|
|
58
|
+
body = next;
|
|
59
|
+
shownCount += 1;
|
|
60
|
+
}
|
|
61
|
+
return `[ran tools: ${body}${omittedSuffix(entries.length - shownCount)}]`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function toolRunCounts(notes) {
|
|
65
|
+
const counts = new Map();
|
|
66
|
+
for (const note of notes) counts.set(note.tool, (counts.get(note.tool) || 0) + 1);
|
|
67
|
+
return [...counts].map(([name, count]) => ({ name, count }));
|
|
26
68
|
}
|
|
27
69
|
|
|
28
70
|
export function textPart(text) {
|
|
@@ -42,18 +84,31 @@ export function timestampMs(value) {
|
|
|
42
84
|
return Number.isFinite(ms) && ms > 0 ? ms : null;
|
|
43
85
|
}
|
|
44
86
|
|
|
45
|
-
//
|
|
87
|
+
// Each run of consecutive tool notes collapses into one compact line; every
|
|
88
|
+
// boundary is a blank line. `toolRuns` locates those lines in `text`.
|
|
46
89
|
function joinParts(parts) {
|
|
47
|
-
|
|
48
|
-
let previous = null;
|
|
90
|
+
const blocks = [];
|
|
49
91
|
for (const part of parts) {
|
|
50
92
|
const piece = String(part.text || '').trim();
|
|
51
93
|
if (!piece) continue;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
94
|
+
const last = blocks[blocks.length - 1];
|
|
95
|
+
if (part.note && last?.notes) last.notes.push(part);
|
|
96
|
+
else blocks.push(part.note ? { notes: [part] } : { text: piece });
|
|
97
|
+
}
|
|
98
|
+
let text = '';
|
|
99
|
+
const toolRuns = [];
|
|
100
|
+
for (const block of blocks) {
|
|
101
|
+
if (text) text += '\n\n';
|
|
102
|
+
if (block.notes) {
|
|
103
|
+
const tools = toolRunCounts(block.notes);
|
|
104
|
+
const line = toolRunLine(tools);
|
|
105
|
+
toolRuns.push({ start: text.length, end: text.length + line.length, tools });
|
|
106
|
+
text += line;
|
|
107
|
+
} else {
|
|
108
|
+
text += block.text;
|
|
109
|
+
}
|
|
55
110
|
}
|
|
56
|
-
return { text,
|
|
111
|
+
return { text, toolRuns };
|
|
57
112
|
}
|
|
58
113
|
|
|
59
114
|
/**
|
|
@@ -72,9 +127,15 @@ export function normalizeTurns(rawTurns) {
|
|
|
72
127
|
else merged.push({ role: raw.role, parts: [...parts], at: timestampMs(raw.at) });
|
|
73
128
|
}
|
|
74
129
|
const turns = merged.map(({ role, parts, at }) => {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
if (
|
|
130
|
+
const joined = joinParts(parts);
|
|
131
|
+
const turn = { role, text: joined.text, at };
|
|
132
|
+
if (joined.toolRuns.length) turn.toolRuns = joined.toolRuns;
|
|
133
|
+
// A carried-over compaction summary never names the conversation; a slash
|
|
134
|
+
// command only when no typed prompt does.
|
|
135
|
+
if (parts.some((part) => part.summary || part.command)) {
|
|
136
|
+
turn.titleText = joinParts(parts.filter((part) => !part.summary && !part.command)).text;
|
|
137
|
+
}
|
|
138
|
+
if (parts.some((part) => part.command)) turn.commandText = joinParts(parts.filter((part) => part.command)).text;
|
|
78
139
|
return turn;
|
|
79
140
|
});
|
|
80
141
|
if (turns[0]?.role === 'assistant') {
|
|
@@ -83,19 +144,26 @@ export function normalizeTurns(rawTurns) {
|
|
|
83
144
|
return turns;
|
|
84
145
|
}
|
|
85
146
|
|
|
86
|
-
const
|
|
87
|
-
(
|
|
147
|
+
const textLines = (text) =>
|
|
148
|
+
String(text ?? '')
|
|
88
149
|
.split('\n')
|
|
89
150
|
.map((value) => value.replace(/\s+/g, ' ').trim())
|
|
90
151
|
.filter(Boolean);
|
|
91
152
|
|
|
153
|
+
const titleLines = (turn) => textLines(turn.titleText ?? turn.text);
|
|
154
|
+
|
|
155
|
+
/** First non-empty line of a title text, whitespace-normalized, ≤100 chars. */
|
|
156
|
+
export function titleFromText(text) {
|
|
157
|
+
const line = textLines(text)[0];
|
|
158
|
+
if (!line) return null;
|
|
159
|
+
return Array.from(line).slice(0, TITLE_MAX_CHARS).join('').trim() || null;
|
|
160
|
+
}
|
|
161
|
+
|
|
92
162
|
/** First line of the first genuine user turn, whitespace-normalized, ≤100 chars
|
|
93
|
-
* (an image marker only when the turn has no text line). */
|
|
163
|
+
* (an image marker only when the turn has no text line), else the first slash command. */
|
|
94
164
|
export function conversationTitle(turns) {
|
|
95
165
|
const first = turns.find((turn) => turn.role === 'user' && !turn.stub && titleLines(turn).length);
|
|
96
|
-
if (!first) return
|
|
166
|
+
if (!first) return titleFromText(turns.find((turn) => turn.role === 'user' && turn.commandText)?.commandText);
|
|
97
167
|
const lines = titleLines(first);
|
|
98
|
-
|
|
99
|
-
if (!line) return null;
|
|
100
|
-
return Array.from(line).slice(0, TITLE_MAX_CHARS).join('').trim() || null;
|
|
168
|
+
return titleFromText(lines.find((value) => value !== IMAGE_OMITTED_TEXT) || lines[0]);
|
|
101
169
|
}
|
|
@@ -24,6 +24,7 @@ export function createEagerDispatcher({
|
|
|
24
24
|
getIterations,
|
|
25
25
|
getNextIteration,
|
|
26
26
|
repeatFailLimit,
|
|
27
|
+
isTurnLimitNoticed = () => false,
|
|
27
28
|
executeToolFn = executeTool,
|
|
28
29
|
}) {
|
|
29
30
|
const pending = new Map();
|
|
@@ -56,7 +57,9 @@ export function createEagerDispatcher({
|
|
|
56
57
|
const startEagerTool = (wireCall) => {
|
|
57
58
|
// Streamed call_tool requests are admitted, ordered and executed as their
|
|
58
59
|
// targets; a projection error is answered by the serial batch instead.
|
|
59
|
-
|
|
60
|
+
// Once the turn was told to reply (any limit), no call runs: the batch
|
|
61
|
+
// refuses them, so none may start while the wrap-up response streams.
|
|
62
|
+
if (capped || isTurnLimitNoticed()) return null;
|
|
60
63
|
const call = resolveExecutionToolCall(wireCall, sessionRef);
|
|
61
64
|
if (!call?.id || pending.has(call.id) || !isParallelDispatchable(call.name)) return null;
|
|
62
65
|
const admitted = admission.admit(call);
|
|
@@ -98,7 +98,8 @@ const LEAD_NAME = 'Lead';
|
|
|
98
98
|
* bot-created task session, a bot's home chat or room member session) and
|
|
99
99
|
* the names from there down to the asker ("Lead › Reviewer", "사무관 ›
|
|
100
100
|
* Worker"). Only where the card shows: no bot identity, grant or remember
|
|
101
|
-
* scope follows from it. Null for a top-level session
|
|
101
|
+
* scope follows from it. Null for a top-level session (whose requests show
|
|
102
|
+
* in the chats handing it work instead: tui/session/tool-approval.mjs). */
|
|
102
103
|
export function approvalSurface(sessionId) {
|
|
103
104
|
const delegation = delegationOf(sessionId);
|
|
104
105
|
if (delegation.state !== 'resolved') return null;
|
|
@@ -156,7 +157,13 @@ async function describeEmails(call, outbound, ctx) {
|
|
|
156
157
|
const { executeMcpTool } = await import('../../mcp/client.mjs');
|
|
157
158
|
const ids = outbound.category === 'trash' && Array.isArray(call.args?.ids) ? call.args.ids.map(String) : [];
|
|
158
159
|
const shown = ids.slice(0, PREVIEW_MESSAGES);
|
|
159
|
-
|
|
160
|
+
// The account the call acts as (one server holds every Gmail account).
|
|
161
|
+
const chosen = typeof call.args?.account === 'string' ? call.args.account.trim() : '';
|
|
162
|
+
const raw = await executeMcpTool(
|
|
163
|
+
name,
|
|
164
|
+
{ ids: shown, ...(chosen ? { account: chosen } : {}) },
|
|
165
|
+
{ scopeId: ctx.mcpScopeId }
|
|
166
|
+
);
|
|
160
167
|
const { account, emails } = JSON.parse(raw);
|
|
161
168
|
const messages = (Array.isArray(emails) ? emails : []).map((mail) =>
|
|
162
169
|
[mail.from, mail.subject, String(mail.date || '').slice(0, 10)].filter(Boolean).join(' · ')
|
|
@@ -231,10 +238,9 @@ export async function humanGateDecision(call, decision, ctx = {}) {
|
|
|
231
238
|
editable: outbound.editable,
|
|
232
239
|
details: outbound.details,
|
|
233
240
|
},
|
|
234
|
-
|
|
241
|
+
// "Don't ask again" is the bot's permission.
|
|
242
|
+
remember: outboundRemember(outbound.category),
|
|
235
243
|
};
|
|
236
|
-
// "Don't ask again" is the bot's permission.
|
|
237
|
-
request.remember = outboundRemember(outbound.category);
|
|
238
244
|
const store = ctx.store || (await humanGateStore());
|
|
239
245
|
const mode = await store.modeFor({ agentId, action: outbound.category });
|
|
240
246
|
const base = decision && typeof decision === 'object' ? decision : {};
|
|
@@ -74,8 +74,6 @@ const MCP_OUTBOUND = new Map([
|
|
|
74
74
|
'slack_post_message',
|
|
75
75
|
'slack_reply_to_thread',
|
|
76
76
|
'chat_post_message',
|
|
77
|
-
'discord_send_message',
|
|
78
|
-
'telegram_send_message',
|
|
79
77
|
].map((name) => [name, 'message']),
|
|
80
78
|
...['create_post', 'publish_post', 'create_tweet', 'post_tweet', 'send_tweet'].map((name) => [name, 'publish']),
|
|
81
79
|
['submit_form', 'form'],
|
|
@@ -12,10 +12,23 @@
|
|
|
12
12
|
// the scopes it allows and can leave out `always`. Nothing here ever carries a
|
|
13
13
|
// secret value: a decision that names one is stripped to its verdict.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const HUMAN_REQUEST_KINDS = Object.freeze(['approval', 'outbound', 'secret', 'takeover', 'permission']);
|
|
16
|
+
const HUMAN_RESPONSES = Object.freeze(['approve', 'deny', 'edit-and-approve', 'provide-secret', 'skip', 'done']);
|
|
17
|
+
const REMEMBER_SCOPES = Object.freeze(['once', 'agent', 'always']);
|
|
18
18
|
export const SECRET_REQUEST_TIMEOUT_MS = 120_000;
|
|
19
|
+
/** What a secret's bound field is: a sign-in form (아이디 + 비밀번호), a lone
|
|
20
|
+
* password, a new password, or a one-time code; '' when unknown (computer). */
|
|
21
|
+
export const SECRET_FORMS = Object.freeze(['login', 'password', 'new-password', 'otp']);
|
|
22
|
+
/** Every result a secret handoff (and a declined or expired takeover) gives
|
|
23
|
+
* the agent: facts, never a verdict about the site. */
|
|
24
|
+
export const HANDOFF_OUTCOMES = Object.freeze([
|
|
25
|
+
'entered',
|
|
26
|
+
'user_skipped',
|
|
27
|
+
'no_field',
|
|
28
|
+
'page_changed',
|
|
29
|
+
'blocked',
|
|
30
|
+
'expired',
|
|
31
|
+
]);
|
|
19
32
|
|
|
20
33
|
const RESPONSES_BY_KIND = Object.freeze({
|
|
21
34
|
approval: ['approve', 'deny'],
|
|
@@ -49,7 +62,7 @@ const text = (value, limit = TEXT_LIMIT) => (typeof value === 'string' ? value.t
|
|
|
49
62
|
|
|
50
63
|
/** The human kind of a request; anything else (ask_user's 'question', a
|
|
51
64
|
* hook's bare ask) is an ordinary approval for responses. */
|
|
52
|
-
|
|
65
|
+
function humanRequestKind(request) {
|
|
53
66
|
return HUMAN_REQUEST_KINDS.includes(request?.kind) ? request.kind : 'approval';
|
|
54
67
|
}
|
|
55
68
|
|
|
@@ -103,11 +116,21 @@ export function humanRequestFields(input = {}) {
|
|
|
103
116
|
}
|
|
104
117
|
if (kind === 'secret') {
|
|
105
118
|
const secret = isRecord(input.secret) ? input.secret : {};
|
|
119
|
+
// The bound page's origin and what its field is (the desktop read it at
|
|
120
|
+
// request time, ask-user-tool.mjs): the card's title and inputs; no value.
|
|
121
|
+
const origin = loginPageUrl(secret.origin)?.origin || '';
|
|
122
|
+
const form = SECRET_FORMS.includes(secret.form) ? secret.form : '';
|
|
123
|
+
// A code's length is the bound field's own (credential-autofill.ts
|
|
124
|
+
// codeLength); absent, it stays unspecified.
|
|
125
|
+
const length = Number.isInteger(secret.length) && secret.length > 0 ? secret.length : 0;
|
|
106
126
|
fields.secret = {
|
|
107
127
|
requestId: text(secret.requestId),
|
|
108
128
|
surface: secret.surface === 'computer' ? 'computer' : 'browser',
|
|
109
129
|
target: text(secret.target),
|
|
110
130
|
field: text(secret.field),
|
|
131
|
+
...(origin ? { origin } : {}),
|
|
132
|
+
...(form ? { form } : {}),
|
|
133
|
+
...(form === 'otp' && length ? { length } : {}),
|
|
111
134
|
};
|
|
112
135
|
fields.args = { surface: fields.secret.surface, target: fields.secret.target, field: fields.secret.field };
|
|
113
136
|
fields.remember = ['once'];
|
|
@@ -132,12 +155,21 @@ export function humanRequestFields(input = {}) {
|
|
|
132
155
|
// A login takeover (purpose 'login') opens the desktop's sign-in window on
|
|
133
156
|
// its validated page instead of handing over the side panel.
|
|
134
157
|
const login = surface === 'browser' && takeover.purpose === 'login' ? loginPageUrl(takeover.url) : null;
|
|
158
|
+
// The saved logins of the sign-in page's origin: opaque ids and masked
|
|
159
|
+
// labels only (profile-import.ts credentialSuggestions), never a password.
|
|
160
|
+
const accounts = (login && Array.isArray(takeover.accounts) ? takeover.accounts : [])
|
|
161
|
+
.filter((account) => isRecord(account) && token(account.id, 128) && text(account.label, 120))
|
|
162
|
+
.map((account) => ({ id: token(account.id, 128), label: text(account.label, 120) }));
|
|
163
|
+
// The page those logins may be filled into, bound by the desktop at
|
|
164
|
+
// request time (ask-user-tool.mjs fillId): without it none is offered.
|
|
165
|
+
const fillId = /^secret_[A-Za-z0-9-]{8,80}$/.test(text(takeover.fillId, 100)) ? text(takeover.fillId, 100) : '';
|
|
135
166
|
fields.takeover = {
|
|
136
167
|
surface,
|
|
137
168
|
instructions: text(takeover.instructions, 2_000),
|
|
138
169
|
...(text(takeover.target) ? { target: text(takeover.target) } : {}),
|
|
139
170
|
...identity,
|
|
140
171
|
...(login ? { purpose: 'login', url: login.url, origin: login.origin } : {}),
|
|
172
|
+
...(accounts.length && fillId ? { accounts, fillId } : {}),
|
|
141
173
|
};
|
|
142
174
|
fields.remember = ['once'];
|
|
143
175
|
}
|
|
@@ -17,7 +17,7 @@ import { ACTION_KINDS, isRememberableAction } from './outbound-policy.mjs';
|
|
|
17
17
|
const ANY_AGENT = '*';
|
|
18
18
|
const FIELD_LIMIT = 200;
|
|
19
19
|
const AUDIT_KEYS = ['agentId', 'kind', 'action', 'tool', 'target', 'decision', 'device'];
|
|
20
|
-
const PERMISSION_MODES = Object.freeze(['ask', 'allow', 'block']);
|
|
20
|
+
export const PERMISSION_MODES = Object.freeze(['ask', 'allow', 'block']);
|
|
21
21
|
|
|
22
22
|
const field = (value) => String(value ?? '').slice(0, FIELD_LIMIT);
|
|
23
23
|
const grantId = (agentId, action) =>
|
|
@@ -16,11 +16,15 @@ import { CONTEXT_SHARE_RATIO, COMPACT_TARGET_MIN_TOKENS, COMPACT_SAFETY_PERCENT
|
|
|
16
16
|
import { HANDOFF_TIMEOUT_MAX_MS } from '../compact/constants.mjs';
|
|
17
17
|
import { envFlag, envPositiveInt } from '../../../../shared/env.mjs';
|
|
18
18
|
import { positiveInt } from '../../../../shared/numbers.mjs';
|
|
19
|
+
import { cacheWarmUseFor, lastCacheWarmUseAt } from '../../../../shared/idle-auto-clear-gate.mjs';
|
|
20
|
+
import { ACCOUNT_PROVIDERS } from '../../../../shared/provider-accounts.mjs';
|
|
21
|
+
import { plannedAccountId } from '../../providers/account-pool.mjs';
|
|
19
22
|
import { isAgentOwner } from '../../agent-owner.mjs';
|
|
20
23
|
import { isAgentModeSession } from '../agent-mode.mjs';
|
|
21
24
|
import { providerInputExcludesCache, providerNativePdf } from '../../providers/registry.mjs';
|
|
22
25
|
import { contentMediaBytes, contentMediaCount } from '../../providers/media-normalization.mjs';
|
|
23
26
|
import { splitProtectedContext } from '../compact/messages.mjs';
|
|
27
|
+
import { withLiveCompactionConfig } from '../../runtime-core/compaction-config-keys.mjs';
|
|
24
28
|
|
|
25
29
|
// Unified context-share rule (compact/constants.mjs CONTEXT_SHARE_RATIO): the
|
|
26
30
|
// post-compaction target is 25% of the boundary/context window. One
|
|
@@ -394,13 +398,6 @@ export function invalidateProviderContextBaseline(sessionRef) {
|
|
|
394
398
|
delete sessionRef.contextPressureUnanchoredReason;
|
|
395
399
|
}
|
|
396
400
|
|
|
397
|
-
// A baseline is refreshed on every provider_send/turn-end. When the transcript
|
|
398
|
-
// has grown but no fresh recording landed for this long, recording is failing
|
|
399
|
-
// (zero/absent usage keeps the OLD baseline because record() only returns
|
|
400
|
-
// false) — distrust it and fall back to the estimate. An idle session whose
|
|
401
|
-
// transcript did NOT grow keeps its baseline regardless of age.
|
|
402
|
-
const BASELINE_MAX_STALE_GROWTH_MS = 30 * 60 * 1000;
|
|
403
|
-
|
|
404
401
|
/**
|
|
405
402
|
* Does this anchor still describe this message prefix?
|
|
406
403
|
*
|
|
@@ -480,17 +477,19 @@ function providerBaselinePressureTokens(messages, sessionRef, policy, { includeC
|
|
|
480
477
|
? Math.max(0, tokens - Math.round(storedRequestReserve) + currentRequestReserve)
|
|
481
478
|
: tokens + currentRequestReserve;
|
|
482
479
|
}
|
|
483
|
-
// Staleness means
|
|
484
|
-
//
|
|
485
|
-
//
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
//
|
|
489
|
-
//
|
|
490
|
-
//
|
|
491
|
-
//
|
|
492
|
-
|
|
493
|
-
|
|
480
|
+
// Staleness means usage recording is failing: a provider request completed
|
|
481
|
+
// AFTER this reading without replacing it (every send records its usage
|
|
482
|
+
// after it starts, so a working recorder always leaves the reading newer
|
|
483
|
+
// than the last send) — zero/absent usage keeps the OLD baseline because
|
|
484
|
+
// record() only returns false. Never age on a clock: measured against `now`
|
|
485
|
+
// it discarded the reading of every session that sat unopened for a while
|
|
486
|
+
// (88 of 983 stored sessions), and measured against the session's last
|
|
487
|
+
// activity it discarded it whenever anything was appended more than half an
|
|
488
|
+
// hour after the last request — a user back from a break, an agent's result
|
|
489
|
+
// posted to a waiting Lead — so the next send compacted on the
|
|
490
|
+
// whole-transcript estimate, far above the provider's own count.
|
|
491
|
+
const lastSendAt = Number(sessionRef.lastProviderSendAt) || 0;
|
|
492
|
+
if (messages.length > count && baselineAt > 0 && lastSendAt > baselineAt) return null;
|
|
494
493
|
try {
|
|
495
494
|
// Baseline tokens are authoritative provider billing; only the growth
|
|
496
495
|
// after the baseline is a local estimate and needs billing calibration.
|
|
@@ -707,13 +706,40 @@ export function shouldCompactForRequestMedia(messages, provider = '') {
|
|
|
707
706
|
// Anthropic's 5m message-tail TTL (agent-runtime/cache-strategy.mjs gives it
|
|
708
707
|
// to agent sessions). A send this long after the previous one finds the tail
|
|
709
708
|
// cache expired and would rewrite the whole accumulated transcript; compacting
|
|
710
|
-
// first makes that cold write the compacted transcript instead.
|
|
709
|
+
// first makes that cold write the compacted transcript instead. The tail was
|
|
710
|
+
// last used by the session's own send or by a successful cache warm
|
|
711
|
+
// (cache-warm.mjs), which reads and refreshes it without moving
|
|
712
|
+
// lastProviderSendAt: a warmed tail has not expired — for a request on the
|
|
713
|
+
// warm's provider, model and account only, since the entry lives there.
|
|
711
714
|
const AGENT_MESSAGE_CACHE_TTL_MS = 5 * 60_000;
|
|
712
715
|
|
|
713
|
-
|
|
716
|
+
// The account the request would be served by: the roster's first pick for a
|
|
717
|
+
// provider with accounts (account-pool.mjs), '' for one without a roster.
|
|
718
|
+
function requestAccountId(provider, model, sessionRef, opts, messages) {
|
|
719
|
+
if (!ACCOUNT_PROVIDERS.includes(provider)) return '';
|
|
720
|
+
return plannedAccountId(provider, {
|
|
721
|
+
sessionId: opts?.sessionId || sessionRef?.id || null,
|
|
722
|
+
messages,
|
|
723
|
+
providerState: opts?.providerState,
|
|
724
|
+
model,
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/** Whether the agent session's 5m message tail expired before this request
|
|
729
|
+
* on `provider` / `model` (default: the session's route). */
|
|
730
|
+
export function shouldCompactForExpiredAgentCache(sessionRef, opts, { provider, model, messages = [] } = {}) {
|
|
714
731
|
if (!isAgentOwner(sessionRef) || opts?.cacheStrategy?.messages !== '5m') return false;
|
|
715
732
|
const lastSendAt = Number(sessionRef.lastProviderSendAt);
|
|
716
|
-
|
|
733
|
+
if (!(lastSendAt > 0)) return false;
|
|
734
|
+
const now = Date.now();
|
|
735
|
+
if (now - lastSendAt <= AGENT_MESSAGE_CACHE_TTL_MS) return false;
|
|
736
|
+
// No warm since the last send: the tail expired.
|
|
737
|
+
if (!(lastCacheWarmUseAt(sessionRef.id) > lastSendAt)) return true;
|
|
738
|
+
const route = { provider: provider || sessionRef.provider || '', model: model || sessionRef.model || '' };
|
|
739
|
+
const accountId = requestAccountId(route.provider, route.model, sessionRef, opts, messages);
|
|
740
|
+
if (accountId === null) return true;
|
|
741
|
+
const warmAt = cacheWarmUseFor(sessionRef.id, { ...route, accountId });
|
|
742
|
+
return now - Math.max(lastSendAt, warmAt) > AGENT_MESSAGE_CACHE_TTL_MS;
|
|
717
743
|
}
|
|
718
744
|
|
|
719
745
|
export function shouldCompactForSession(
|
|
@@ -795,9 +821,9 @@ function compactionTelemetryRecord(sessionRef, policy, meta, prev) {
|
|
|
795
821
|
if (terminalSuccess) return null;
|
|
796
822
|
return present ? (next ?? null) : (previous ?? null);
|
|
797
823
|
};
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
824
|
+
// Config-owned fields stay the live ones (withLiveCompactionConfig): `policy`
|
|
825
|
+
// was resolved before a compaction that a reload may have outlived.
|
|
826
|
+
return withLiveCompactionConfig(prev, {
|
|
801
827
|
requestReserveTokens: policy.requestReserveTokens || 0,
|
|
802
828
|
reserveTokens: policy.reserveTokens || 0,
|
|
803
829
|
boundaryTokens: policy.boundaryTokens || null,
|
|
@@ -848,7 +874,7 @@ function compactionTelemetryRecord(sessionRef, policy, meta, prev) {
|
|
|
848
874
|
compactCount: (prev.compactCount || 0) + (changed ? 1 : 0),
|
|
849
875
|
singleShotConsumed:
|
|
850
876
|
policy.singleShot === true && meta.stage === 'compacting' ? true : prev.singleShotConsumed === true,
|
|
851
|
-
};
|
|
877
|
+
});
|
|
852
878
|
}
|
|
853
879
|
|
|
854
880
|
// Postmortem ring buffer: the per-check telemetry record is overwritten on
|
|
@@ -18,6 +18,9 @@ import { summarizeOnSharedPrefix } from '../compact/forked-summary.mjs';
|
|
|
18
18
|
import { normalizeCompactionSummaryMode } from '../compact/summary-mode.mjs';
|
|
19
19
|
import { compactionCacheWarm, lighterSubscriptionModel } from '../compact/summary-route.mjs';
|
|
20
20
|
import { retireCompactionFork } from '../side-question-store.mjs';
|
|
21
|
+
import { buildSkillToolEnvelope, collectSkillsCached, currentSkillDelivery } from '../../context/collect.mjs';
|
|
22
|
+
import { loadSkillToolDependencies } from '../../runtime-core/skill-tool-loading.mjs';
|
|
23
|
+
import { parseNativeToolSearchPayload } from './tool-helpers.mjs';
|
|
21
24
|
|
|
22
25
|
// Conversation summarization triggers independently of the post-compact target:
|
|
23
26
|
// at 5% of the window, capped so a large window does not carry tens of
|
|
@@ -262,11 +265,42 @@ function freshContextBudget({ compactPolicy, sessionRef, provider, compactBudget
|
|
|
262
265
|
return { contextWindow, hardBudget, conversationInput, conversationTokens, conversationThresholdTokens };
|
|
263
266
|
}
|
|
264
267
|
|
|
268
|
+
// Compact restores each active skill from its current source, as the Skill
|
|
269
|
+
// tool would deliver it in this session now (null: it no longer loads). The
|
|
270
|
+
// real pass also re-arms the skill's current tool dependencies on the session
|
|
271
|
+
// surface and answers the native tool-search payload they produce (or, with
|
|
272
|
+
// none, the Skill result summary); a preview never touches the surface and
|
|
273
|
+
// keeps the transcript's loader pairs.
|
|
274
|
+
function currentSkillResolver(sessionRef, { preview = false } = {}) {
|
|
275
|
+
const cwd = sessionRef?.cwd || null;
|
|
276
|
+
const config = loadConfig({ secrets: false });
|
|
277
|
+
const skills = collectSkillsCached(cwd);
|
|
278
|
+
return (name) => {
|
|
279
|
+
const delivery = currentSkillDelivery(name, cwd, config, skills);
|
|
280
|
+
if (!delivery) return null;
|
|
281
|
+
const { resource } = delivery;
|
|
282
|
+
// The tools whose use counts as use of the skill: its tool dependencies,
|
|
283
|
+
// an MCP server as `mcp:<server>`.
|
|
284
|
+
const tools = (resource.toolDependencies || []).flatMap(({ type, value }) =>
|
|
285
|
+
type === 'tool' ? [value] : type === 'mcp' ? [`mcp:${value}`] : []
|
|
286
|
+
);
|
|
287
|
+
if (preview) return { body: delivery.body, native: undefined, tools };
|
|
288
|
+
const envelope = loadSkillToolDependencies(
|
|
289
|
+
buildSkillToolEnvelope(name, resource.content, resource.dir, resource),
|
|
290
|
+
sessionRef
|
|
291
|
+
);
|
|
292
|
+
const native = parseNativeToolSearchPayload('Skill', envelope.result);
|
|
293
|
+
return { body: delivery.body, native, summary: native?.summary ?? envelope.result, tools };
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
265
297
|
function freshContextBuildOptions(
|
|
266
|
-
{ compactPolicy = {}, sessionId, goalReminderText, activeTurn, referenceLatestAttachments },
|
|
298
|
+
{ sessionRef, compactPolicy = {}, sessionId, goalReminderText, activeTurn, referenceLatestAttachments, preview },
|
|
267
299
|
budget
|
|
268
300
|
) {
|
|
269
301
|
return {
|
|
302
|
+
// A sessionless call (no session gates to apply) keeps the transcript copies.
|
|
303
|
+
currentSkill: sessionRef ? currentSkillResolver(sessionRef, { preview }) : null,
|
|
270
304
|
reserveTokens: compactPolicy.reserveTokens,
|
|
271
305
|
maxBudgetTokens: budget.hardBudget,
|
|
272
306
|
force: true,
|
|
@@ -287,7 +321,7 @@ export function previewFreshContextCompaction(input) {
|
|
|
287
321
|
const budget = freshContextBudget(input);
|
|
288
322
|
const summaryTriggered = budget.conversationTokens >= budget.conversationThresholdTokens;
|
|
289
323
|
const result = freshContextCompactMessages(input.messages, input.compactBudgetTokens, {
|
|
290
|
-
...freshContextBuildOptions(input, budget),
|
|
324
|
+
...freshContextBuildOptions({ ...input, preview: true }, budget),
|
|
291
325
|
preview: true,
|
|
292
326
|
previewSummary: summaryTriggered,
|
|
293
327
|
});
|
|
@@ -346,7 +380,7 @@ export async function runFreshContextCompact({
|
|
|
346
380
|
});
|
|
347
381
|
const summaryTriggered = conversationTokens >= conversationThresholdTokens;
|
|
348
382
|
const buildOptions = freshContextBuildOptions(
|
|
349
|
-
{ compactPolicy, sessionId, goalReminderText, activeTurn, referenceLatestAttachments },
|
|
383
|
+
{ sessionRef, compactPolicy, sessionId, goalReminderText, activeTurn, referenceLatestAttachments },
|
|
350
384
|
{ contextWindow, hardBudget }
|
|
351
385
|
);
|
|
352
386
|
const build = (handoffText) =>
|
|
@@ -120,7 +120,9 @@ export function createLoopState({ provider, messages, model, tools, cwd, sendOpt
|
|
|
120
120
|
messages.push(message);
|
|
121
121
|
try {
|
|
122
122
|
opts.onToolResult?.(message);
|
|
123
|
-
} catch {
|
|
123
|
+
} catch {
|
|
124
|
+
// the tool-result observer is advisory
|
|
125
|
+
}
|
|
124
126
|
};
|
|
125
127
|
state.drainSteering = createSteeringDrain({
|
|
126
128
|
messages,
|
|
@@ -44,7 +44,7 @@ export function createNoToolTurnResolver({
|
|
|
44
44
|
// whether it answered that input.
|
|
45
45
|
reactions: [],
|
|
46
46
|
// Structured provider continuation signals honored this turn. Diagnostic
|
|
47
|
-
// only:
|
|
47
|
+
// only: this count bounds nothing. A
|
|
48
48
|
// text-only continuation runaway is bounded by continuationsSinceToolBatch
|
|
49
49
|
// below; continuations interleaved with tool batches are not limited.
|
|
50
50
|
providerContinuationCount: 0,
|