mixdog 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/scripts/build-shipped-history.mjs +115 -33
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/gate-local.mjs +183 -63
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/gate-scheduler.mjs +138 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +91 -66
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +124 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +16 -4
- package/scripts/lib/test-spawn-ledger.mjs +12 -3
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -5
- package/scripts/suite-health.mjs +115 -24
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +9 -14
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/explore/AGENT.md +22 -0
- package/src/agents/explore/agent.json +6 -0
- package/src/app.mjs +4 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +23 -2
- package/src/defaults/skills/browser-use/SKILL.md +10 -5
- package/src/defaults/skills/code-tidy/SKILL.md +71 -102
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
- package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
- package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
- package/src/defaults/skills/computer-use/SKILL.md +16 -4
- package/src/defaults/skills/goal-management/SKILL.md +1 -1
- package/src/defaults/skills/setup/references/actions.md +12 -6
- package/src/defaults/skills/setup/references/surfaces.md +2 -2
- package/src/defaults/skills/setup-guide/SKILL.md +5 -2
- package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
- package/src/defaults/skills/skill-creator/SKILL.md +85 -190
- package/src/defaults/skills/skill-creator/references/design.md +70 -162
- package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
- package/src/defaults/skills/test-suite/SKILL.md +194 -0
- package/src/defaults/skills/test-suite/references/case-management.md +51 -0
- package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
- package/src/defaults/skills/test-suite/references/reliability.md +49 -0
- package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
- package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
- package/src/defaults/skills/visualize/SKILL.md +6 -2
- package/src/lib/rules-builder.cjs +35 -42
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +5 -4
- package/src/rules/lead/LEAD.md +12 -7
- package/src/rules/shared/10-tool-workflow.md +3 -1
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -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 +10 -9
- package/src/rules/shared/70-delivery.md +8 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
- package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- 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 +31 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
- 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-page.mjs +0 -18
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
- 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 +160 -31
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
- package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
- 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 +160 -36
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
- 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 +100 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
- 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 +14 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
- 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/owner-route-fallbacks.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
- package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- 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/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- 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/native-spawn-client.mjs +99 -2
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/whisper-port.mjs +29 -11
- package/src/runtime/channels/lib/whisper-server.mjs +10 -1
- package/src/runtime/computer-bridge/action-schema.mjs +2 -2
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
- 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/connectors/connector-accounts-mcp.mjs +236 -103
- package/src/runtime/connectors/gmail-app-password.mjs +3 -3
- package/src/runtime/explore/explorer.mjs +93 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- 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/index.mjs +4 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +10 -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/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 +4 -2
- 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/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +15 -6
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +11 -4
- package/src/runtime/shared/connector-catalog.mjs +60 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/defaults-separation.mjs +1 -4
- 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-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +13 -15
- package/src/runtime/shared/git-launch.d.mts +9 -0
- package/src/runtime/shared/git-launch.mjs +213 -0
- package/src/runtime/shared/git-runner-worker.mjs +2 -1
- package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
- package/src/runtime/shared/llm/cost.mjs +11 -2
- package/src/runtime/shared/llm/http-agent.mjs +313 -29
- package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
- package/src/runtime/shared/llm/model-catalog.mjs +46 -6
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
- package/src/runtime/shared/llm/system-proxy.mjs +452 -0
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- 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/provider-accounts.mjs +52 -2
- package/src/runtime/shared/session-activity-signal.mjs +14 -0
- package/src/runtime/shared/session-scratch.mjs +37 -0
- package/src/runtime/shared/staged-install-worker.mjs +5 -0
- package/src/runtime/shared/staged-update.mjs +47 -2
- 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 +1 -1
- package/src/runtime/shared/tool-surface.mjs +113 -36
- package/src/runtime/shared/tool-work-units.mjs +6 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
- package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
- package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
- package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +72 -0
- package/src/runtime/shared/worktrees/manager.mjs +285 -168
- package/src/runtime/shared/worktrees/test-support.mjs +6 -10
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +7 -4
- package/src/runtime/tidy/resolve.mjs +19 -16
- package/src/runtime/tidy/runners/biome.mjs +3 -3
- package/src/runtime/tidy/tool.mjs +1 -1
- package/src/runtime/tidy/worktree.mjs +10 -6
- package/src/runtime/visualize-bridge/client.mjs +6 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +1 -1
- package/src/session-runtime/agent-home-delivery.mjs +41 -0
- package/src/session-runtime/agent-task-sessions.mjs +458 -312
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/bot-status.mjs +107 -101
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +401 -36
- package/src/session-runtime/conversation-import/service.mjs +35 -8
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
- package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
- package/src/session-runtime/mixy-heartbeat.mjs +1 -1
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- 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 +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
- package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- 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/send-flow.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
- package/src/session-runtime/services/daemon-candidate.mjs +4 -1
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +10 -6
- package/src/session-runtime/services/provider-admin.mjs +283 -11
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
- package/src/session-runtime/settings-system-api.mjs +1 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
- package/src/session-runtime/setup-tool/executor.mjs +6 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
- package/src/session-runtime/turn/agent-ops.mjs +23 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/session-view.mjs +149 -0
- package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
- package/src/session-runtime/workspace/transition-runner.mjs +188 -0
- package/src/session-runtime/workspace/transitions.mjs +108 -1041
- package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
- package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
- package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
- package/src/standalone/daemon-desktop-runtime.mjs +2 -0
- package/src/standalone/daemon-session-control.mjs +169 -138
- package/src/standalone/daemon.mjs +7 -0
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +5 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- package/src/standalone/session-service/agent-tree.mjs +45 -9
- package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
- package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/App.jsx +154 -164
- package/src/tui/app/app-view/floating-panel.jsx +10 -4
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +21 -10
- 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/prompt-handlers/use-prompt-history-nav.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
- package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
- package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
- package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +29 -18
- package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
- package/src/tui/app/slash-dispatch.mjs +1 -1
- package/src/tui/app/use-btw-panel.mjs +29 -0
- package/src/tui/app/use-context-panel-refresh.mjs +31 -0
- package/src/tui/app/use-model-catalog-cache.mjs +13 -10
- package/src/tui/app/use-mouse-input.mjs +11 -0
- package/src/tui/app/use-onboarding-start.mjs +8 -3
- package/src/tui/app/use-panel-transition.mjs +10 -1
- package/src/tui/app/use-pasted-buffers.mjs +28 -20
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
- package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
- package/src/tui/app/use-prompt-queue-history.mjs +3 -2
- package/src/tui/app/use-selection-focus.mjs +11 -2
- package/src/tui/app/use-selection-geometry.mjs +18 -9
- package/src/tui/app/use-selection-paint.mjs +4 -4
- package/src/tui/app/use-selection-stitch.mjs +3 -3
- package/src/tui/app/use-slash-palette.mjs +62 -0
- package/src/tui/app/use-terminal-chrome.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +47 -32
- package/src/tui/app/use-transcript-follow.mjs +12 -4
- package/src/tui/app/use-transcript-scroll.mjs +46 -17
- package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
- package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
- package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
- package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
- package/src/tui/app/use-transcript-window.mjs +21 -11
- package/src/tui/app/use-tui-ready.mjs +18 -0
- package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
- package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
- package/src/tui/components/Picker.jsx +27 -3
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/dist/index.mjs +1963 -1361
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +8 -0
- package/src/tui/session/session-api/intake/abort.mjs +2 -1
- package/src/tui/session/session-api/intake.mjs +2 -0
- package/src/tui/session/session-api/integrations.mjs +2 -2
- package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
- package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
- package/src/tui/session/transcript-spill.mjs +92 -4
- package/src/tui/session/transcript-store.mjs +2 -0
- package/src/ui/statusline-agents.mjs +1 -3
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// cache-warm.mjs — keeps a session's prompt cache readable for its next turn
|
|
2
2
|
// — every session, Lead, bot or sub-agent, while warming is on
|
|
3
|
-
// (`promptCacheWarming`, default
|
|
3
|
+
// (`promptCacheWarming`, default off) — one interval at a time while the
|
|
4
4
|
// session idles, as far as the session's own history of returns says it
|
|
5
5
|
// pays. A warm re-sends the session's last real request
|
|
6
6
|
// (side-question-store.mjs) through the provider's cache-warm mode
|
|
@@ -36,7 +36,11 @@
|
|
|
36
36
|
// warm counts as cache use for the idle auto-clear (sessionActivityTimestamp
|
|
37
37
|
// in idle-auto-clear-gate.mjs), so its deadline moves with each one.
|
|
38
38
|
// Any fact the rule needs that is not known (written tier, prices, prompt
|
|
39
|
-
// size, the account holding the entry) means no warm.
|
|
39
|
+
// size, the account holding the entry) means no warm. A warm never goes into
|
|
40
|
+
// an entry past its lifetime (counted from the last confirmed read or write,
|
|
41
|
+
// checked at the refresh point and again right before dispatch), and a
|
|
42
|
+
// session whose warm missed inside the lifetime gets no further chain until
|
|
43
|
+
// its cached prefix is dropped. The chain stops on a
|
|
40
44
|
// miss, a failure, a late timer, a turn in flight, a new real request
|
|
41
45
|
// (side-question-store.mjs cancels), a compaction, a clear, a close, or a
|
|
42
46
|
// delete; the auto-clear then runs from the last real or successful warm
|
|
@@ -54,6 +58,7 @@
|
|
|
54
58
|
// /btw side questions, memory recap, prewarms, warms). The planner counts
|
|
55
59
|
// idle time from the same anchor. Each session learns from its own gaps. A gap still open at the idle window is recorded as
|
|
56
60
|
// censored there.
|
|
61
|
+
import { loadConfig } from '../config.mjs';
|
|
57
62
|
import { ACCOUNT_PROVIDERS } from '../../../shared/provider-accounts.mjs';
|
|
58
63
|
import { setCacheWarmUseSource } from '../../../shared/idle-auto-clear-gate.mjs';
|
|
59
64
|
import {
|
|
@@ -97,9 +102,9 @@ export const IDLE_RETURN_LOOKBACK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
|
97
102
|
const WILSON_Z_95 = 1.959963984540054;
|
|
98
103
|
|
|
99
104
|
/** Whether prompt-cache warming is on (config `promptCacheWarming`, default
|
|
100
|
-
*
|
|
105
|
+
* off; config.mjs migrates the earlier target list). */
|
|
101
106
|
export function cacheWarmingEnabled(config) {
|
|
102
|
-
return config?.promptCacheWarming
|
|
107
|
+
return config?.promptCacheWarming === true;
|
|
103
108
|
}
|
|
104
109
|
|
|
105
110
|
/** The lower bound of the 95% Wilson score interval of `hits` in `n`
|
|
@@ -134,6 +139,26 @@ export function sessionReturnChance(gaps, elapsedMs, withinMs) {
|
|
|
134
139
|
return { idle, returns, p: wilsonLowerBound(returns, idle) };
|
|
135
140
|
}
|
|
136
141
|
|
|
142
|
+
// A write below this many tokens is prompt growth, never a rewrite: 4096 is
|
|
143
|
+
// the largest minimum cacheable prompt length of the supported models.
|
|
144
|
+
export const CACHE_WARM_REWRITE_FLOOR_TOKENS = 4096;
|
|
145
|
+
|
|
146
|
+
/** Whether a warm's `usage` shows a substantial rewrite with poor read
|
|
147
|
+
* coverage: the write reaches the floor and the read covers less than half
|
|
148
|
+
* of read + write. A read of most of the prompt plus the new tail is a hit. */
|
|
149
|
+
export function warmRewrote(usage) {
|
|
150
|
+
const read = Number(usage?.cachedTokens) || 0;
|
|
151
|
+
const write = Number(usage?.cacheWriteTokens) || 0;
|
|
152
|
+
return write >= CACHE_WARM_REWRITE_FLOOR_TOKENS && read < write;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Whether an entry last used at `touchAt` and living `ttlMs` will have
|
|
156
|
+
* expired by the time a warm sent at `now` reaches the provider (`latencyMs`
|
|
157
|
+
* later): a warm into an expired entry rewrites the whole prompt. */
|
|
158
|
+
export function cacheEntryLapsed(touchAt, ttlMs, now, latencyMs = null) {
|
|
159
|
+
return touchAt + ttlMs - now <= (Number(latencyMs) || 0);
|
|
160
|
+
}
|
|
161
|
+
|
|
137
162
|
/** When a warm goes out after the last cache use of an entry living `ttlMs`. */
|
|
138
163
|
export function cacheWarmDelayMs(ttlMs) {
|
|
139
164
|
return Math.max(1, ttlMs - CACHE_WARM_LEAD_MS);
|
|
@@ -223,7 +248,7 @@ export function planCacheWarm({ now, touchAt, ttlMs, lastCallAt, gaps, promptTok
|
|
|
223
248
|
// fires at or after the refresh point, TTL − lead, so the lead itself cannot
|
|
224
249
|
// be the floor; the chain's measured warm latency (none before the first
|
|
225
250
|
// warm) is.
|
|
226
|
-
if (touchAt
|
|
251
|
+
if (cacheEntryLapsed(touchAt, ttlMs, now, latencyMs)) return { stop: 'late timer' };
|
|
227
252
|
const economics = cacheWarmEconomics(promptTokens, prices);
|
|
228
253
|
if (!economics) return { stop: 'prompt size or cache prices unknown' };
|
|
229
254
|
const interval = cacheWarmDelayMs(ttlMs);
|
|
@@ -238,11 +263,35 @@ export function planCacheWarm({ now, touchAt, ttlMs, lastCallAt, gaps, promptTok
|
|
|
238
263
|
|
|
239
264
|
// Defaults of the injectable dependencies.
|
|
240
265
|
|
|
241
|
-
|
|
242
|
-
|
|
266
|
+
// The synchronous on/off state `armCacheWarm` and the restart re-arm gate on.
|
|
267
|
+
// It is always definite: the first call reads the config (synchronous, from
|
|
268
|
+
// disk in a fresh process, where it is authoritative) and caches the value;
|
|
269
|
+
// from then on only the setting call (noteCacheWarmingEnabled) writes it.
|
|
270
|
+
// Refresh-point reads (`deps.enabled`) never do, so a stale read cannot
|
|
271
|
+
// switch warming off globally.
|
|
272
|
+
let warmingOn = null;
|
|
273
|
+
|
|
274
|
+
function enabledNow() {
|
|
275
|
+
warmingOn ??= deps.readConfigEnabled();
|
|
276
|
+
return warmingOn;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** The setting changed (settings-builtin-tools-api.mjs
|
|
280
|
+
* setCacheWarmingEnabled): authoritative; off cancels every armed chain. */
|
|
281
|
+
export function noteCacheWarmingEnabled(enabled) {
|
|
282
|
+
warmingOn = enabled === true;
|
|
283
|
+
if (warmingOn) return;
|
|
284
|
+
for (const sessionId of [...chains.keys()]) cancelCacheWarm(sessionId);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function defaultReadConfigEnabled() {
|
|
243
288
|
return cacheWarmingEnabled(loadConfig({ secrets: false }));
|
|
244
289
|
}
|
|
245
290
|
|
|
291
|
+
async function defaultEnabled() {
|
|
292
|
+
return defaultReadConfigEnabled();
|
|
293
|
+
}
|
|
294
|
+
|
|
246
295
|
// Per-token dollars of a cache read, a cache write of `ttlMs`'s tier and an
|
|
247
296
|
// output token for the request's model, from the pricing catalog (null when
|
|
248
297
|
// unpriced), at the rates of a prompt of `promptTokens`: a model priced by
|
|
@@ -351,6 +400,7 @@ const DEFAULT_DEPS = Object.freeze({
|
|
|
351
400
|
now: () => Date.now(),
|
|
352
401
|
timers: globalThis,
|
|
353
402
|
enabled: defaultEnabled,
|
|
403
|
+
readConfigEnabled: defaultReadConfigEnabled,
|
|
354
404
|
turnInFlight: (sessionId) => isTurnInFlight(runtimeState.get(sessionId)),
|
|
355
405
|
lastSentRequest: defaultLastSentRequest,
|
|
356
406
|
providersReady: defaultProvidersReady,
|
|
@@ -366,12 +416,15 @@ let deps = DEFAULT_DEPS;
|
|
|
366
416
|
|
|
367
417
|
// The idle auto-clear measures idleness from the last cache use, a
|
|
368
418
|
// successful warm included (durable in the touch store).
|
|
369
|
-
|
|
419
|
+
// The record names the route and account the warm read, so only a request
|
|
420
|
+
// on that same prefix counts it as fresh cache (compact-policy.mjs).
|
|
421
|
+
setCacheWarmUseSource((sessionId) => (sessionId ? deps.touches().warmUse(sessionId) : null));
|
|
370
422
|
|
|
371
423
|
// A session deleted for good drops everything it learned and touched.
|
|
372
424
|
registerSessionPurgeHook((sessionId) => {
|
|
373
425
|
cancelCacheWarm(sessionId);
|
|
374
426
|
turns.delete(sessionId);
|
|
427
|
+
missedSessions.delete(sessionId);
|
|
375
428
|
deps.touches().forget(sessionId);
|
|
376
429
|
deps.touches().forgetWarmUse(sessionId);
|
|
377
430
|
deps.gaps().forget(sessionId);
|
|
@@ -411,6 +464,8 @@ async function planFor(sessionId, chain, at) {
|
|
|
411
464
|
/** Test seam: replace some dependencies; call with no argument to restore. */
|
|
412
465
|
export function _setCacheWarmDepsForTest(overrides = null) {
|
|
413
466
|
for (const sessionId of [...chains.keys()]) cancelCacheWarm(sessionId);
|
|
467
|
+
missedSessions.clear();
|
|
468
|
+
warmingOn = null;
|
|
414
469
|
deps = overrides ? { ...DEFAULT_DEPS, ...overrides } : DEFAULT_DEPS;
|
|
415
470
|
}
|
|
416
471
|
|
|
@@ -418,6 +473,13 @@ export function _setCacheWarmDepsForTest(overrides = null) {
|
|
|
418
473
|
// accountId, latencyMs, refreshAt, timer, controller }.
|
|
419
474
|
const chains = new Map();
|
|
420
475
|
|
|
476
|
+
// Sessions whose warm read little of what it rewrote while the entry was
|
|
477
|
+
// still inside its lifetime: the warm does not match what the real requests
|
|
478
|
+
// cache, so no later chain of the session is armed (each would rewrite the
|
|
479
|
+
// prompt once more) until its cached prefix is dropped (forgetCacheWarm) or
|
|
480
|
+
// the session is deleted.
|
|
481
|
+
const missedSessions = new Set();
|
|
482
|
+
|
|
421
483
|
/** The armed chain of `sessionId` (tests and diagnostics). */
|
|
422
484
|
export function cacheWarmChain(sessionId) {
|
|
423
485
|
return chains.get(sessionId) || null;
|
|
@@ -596,6 +658,7 @@ export function cancelCacheWarm(sessionId) {
|
|
|
596
658
|
export function forgetCacheWarm(sessionId) {
|
|
597
659
|
cancelCacheWarm(sessionId);
|
|
598
660
|
if (!sessionId) return;
|
|
661
|
+
missedSessions.delete(sessionId);
|
|
599
662
|
deps.touches().forget(sessionId);
|
|
600
663
|
deps.touches().forgetWarmUse(sessionId);
|
|
601
664
|
}
|
|
@@ -648,7 +711,8 @@ function warmTarget(chain) {
|
|
|
648
711
|
/**
|
|
649
712
|
* Arm the session's warm chain from a real request that settled with
|
|
650
713
|
* `response`, and record the confirmed touch durably; replaces any chain.
|
|
651
|
-
* Nothing is armed
|
|
714
|
+
* Nothing is armed while warming is off (enabledNow). Nothing is armed
|
|
715
|
+
* — and the durable touch is dropped — for an ineligible
|
|
652
716
|
* request, one without a send time, or a response that does not prove the
|
|
653
717
|
* tier it wrote or the prompt size.
|
|
654
718
|
*/
|
|
@@ -663,7 +727,17 @@ export function armCacheWarm(sessionId, request, response) {
|
|
|
663
727
|
if (sessionId && request && realActivity(sessionId, request)) {
|
|
664
728
|
deps.gaps().open(sessionId, Number(request.sentAt));
|
|
665
729
|
}
|
|
730
|
+
// Warming off: no chain, no timer and no durable touch (the idle gap above
|
|
731
|
+
// is still learned); the touch of an earlier cache use no longer holds.
|
|
732
|
+
if (!enabledNow()) {
|
|
733
|
+
if (sessionId) deps.touches().forget(sessionId);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
666
736
|
if (!sessionId || !request || cacheWarmIneligibility(request)) return;
|
|
737
|
+
if (missedSessions.has(sessionId)) {
|
|
738
|
+
deps.touches().forget(sessionId);
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
667
741
|
const usage = response?.usage || {};
|
|
668
742
|
const touchAt = Number(request.sentAt);
|
|
669
743
|
const ttlMs = writtenCacheTtlMs(usage, request.opts.cacheStrategy);
|
|
@@ -695,7 +769,7 @@ export function armCacheWarm(sessionId, request, response) {
|
|
|
695
769
|
* many chains were armed.
|
|
696
770
|
*/
|
|
697
771
|
export async function rearmCacheWarmsAfterRestart() {
|
|
698
|
-
if (!(
|
|
772
|
+
if (!enabledNow()) return 0;
|
|
699
773
|
const candidates = [];
|
|
700
774
|
for (const sessionId of deps.touches().ids()) {
|
|
701
775
|
if (chains.has(sessionId)) continue;
|
|
@@ -711,12 +785,16 @@ export async function rearmCacheWarmsAfterRestart() {
|
|
|
711
785
|
await deps.providersReady();
|
|
712
786
|
let armed = 0;
|
|
713
787
|
for (const [sessionId, touch] of candidates) {
|
|
788
|
+
// Re-checked after every await: a setter that turned warming off since
|
|
789
|
+
// has cancelled the chains and nothing more may start.
|
|
790
|
+
if (!enabledNow()) return armed;
|
|
714
791
|
let request = null;
|
|
715
792
|
try {
|
|
716
793
|
request = await deps.lastSentRequest(sessionId);
|
|
717
794
|
} catch (error) {
|
|
718
795
|
deps.log(`${sessionId}: restart re-arm skipped (${error?.message || error})`);
|
|
719
796
|
}
|
|
797
|
+
if (!enabledNow()) return armed;
|
|
720
798
|
if (!request || cacheWarmIneligibility(request) || chains.has(sessionId)) continue;
|
|
721
799
|
startChain(sessionId, {
|
|
722
800
|
request,
|
|
@@ -758,7 +836,12 @@ async function fireWarm(sessionId, chain) {
|
|
|
758
836
|
// Last check before dispatch, after the final await: a turn that began
|
|
759
837
|
// during the lookups has the cache to itself.
|
|
760
838
|
if (deps.turnInFlight(sessionId)) return stopChain(sessionId, chain, 'turn in flight');
|
|
839
|
+
// The lookups above took time: the entry must still live when the warm goes
|
|
840
|
+
// out, counted from its last confirmed read or write.
|
|
761
841
|
const sentAt = deps.now();
|
|
842
|
+
if (cacheEntryLapsed(chain.touchAt, chain.ttlMs, sentAt, chain.latencyMs)) {
|
|
843
|
+
return stopChain(sessionId, chain, 'entry expired before dispatch');
|
|
844
|
+
}
|
|
762
845
|
let usage = null;
|
|
763
846
|
let reportedAt = null;
|
|
764
847
|
let failure = null;
|
|
@@ -779,14 +862,21 @@ async function fireWarm(sessionId, chain) {
|
|
|
779
862
|
}
|
|
780
863
|
if (chains.get(sessionId) !== chain) return;
|
|
781
864
|
if (failure) return stopChain(sessionId, chain, `warm failed: ${failure?.message || failure}`);
|
|
782
|
-
|
|
865
|
+
const read = Number(usage?.cachedTokens) || 0;
|
|
866
|
+
const rewrite = warmRewrote(usage);
|
|
867
|
+
if (!(read > 0) || rewrite) {
|
|
783
868
|
deps.touches().forget(sessionId);
|
|
869
|
+
if (rewrite) missedSessions.add(sessionId);
|
|
784
870
|
return stopChain(sessionId, chain, 'warm missed the cache');
|
|
785
871
|
}
|
|
786
872
|
chain.touchAt = sentAt;
|
|
787
873
|
chain.latencyMs = (reportedAt ?? deps.now()) - sentAt;
|
|
788
874
|
recordTouch(sessionId, chain);
|
|
789
875
|
// A read without a write is cache use: the idle auto-clear counts from it.
|
|
790
|
-
deps.touches().recordWarmUse(sessionId, sentAt
|
|
876
|
+
deps.touches().recordWarmUse(sessionId, sentAt, {
|
|
877
|
+
provider: chain.request.provider.name,
|
|
878
|
+
model: chain.request.model,
|
|
879
|
+
accountId: target.accountId,
|
|
880
|
+
});
|
|
791
881
|
scheduleWarm(sessionId, chain);
|
|
792
882
|
}
|
|
@@ -11,7 +11,7 @@ import { createHash } from 'node:crypto';
|
|
|
11
11
|
|
|
12
12
|
/** Bumped whenever the table layout or a codec changes: the DB is then
|
|
13
13
|
* dropped and backfilled again from the JSON catalog. */
|
|
14
|
-
export const SCHEMA_VERSION =
|
|
14
|
+
export const SCHEMA_VERSION = 11;
|
|
15
15
|
/** PRAGMA application_id ('MXSC'): a file without it is not this catalog. */
|
|
16
16
|
export const APPLICATION_ID = 0x4d585343;
|
|
17
17
|
|
|
@@ -68,6 +68,9 @@ const FIELDS = [
|
|
|
68
68
|
// Places of the incoming messages with text among the counted ones, for the
|
|
69
69
|
// unread count of a bot home / room log; absent otherwise (schema 10).
|
|
70
70
|
['incomingTail', 'incoming_tail', 'optjson'],
|
|
71
|
+
// Compactions the session has had: the epoch of its message numbering;
|
|
72
|
+
// absent for a row written before schema 11.
|
|
73
|
+
['compactCount', 'compact_count', 'optjson'],
|
|
71
74
|
];
|
|
72
75
|
|
|
73
76
|
const COLUMN_TYPES = { text: 'TEXT', real: 'REAL', int: 'INTEGER', bool: 'INTEGER', json: 'TEXT', optjson: 'TEXT' };
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
isProtectedContextAckMessage,
|
|
10
10
|
latestActualUserInstructionIndex,
|
|
11
11
|
pendingTaskNotificationIndexes,
|
|
12
|
+
requestStart,
|
|
12
13
|
} from './messages.mjs';
|
|
13
14
|
import { staleObservations, supersedeObservation } from './observation-supersession.mjs';
|
|
14
15
|
import { carryMessageId, withoutMessageIdsReplacer } from '../message-ids.mjs';
|
|
@@ -101,14 +102,6 @@ export function executionTokens(messages) {
|
|
|
101
102
|
);
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
function requestStart(messages, index) {
|
|
105
|
-
for (let i = index; i >= 0; i -= 1) {
|
|
106
|
-
if (!isActualUserInstructionMessage(messages[i])) continue;
|
|
107
|
-
if (messages[i]?.meta?.source !== 'steering') return i;
|
|
108
|
-
}
|
|
109
|
-
return latestActualUserInstructionIndex(messages.slice(0, index + 1));
|
|
110
|
-
}
|
|
111
|
-
|
|
112
105
|
// Each assistant tool-call turn with the tool results that directly follow it.
|
|
113
106
|
function executionGroups(messages) {
|
|
114
107
|
const groups = [];
|
|
@@ -43,6 +43,29 @@ export function latestActualUserInstructionIndex(messages) {
|
|
|
43
43
|
return -1;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// The user instruction that began the request `index` belongs to; a steering
|
|
47
|
+
// message continues the request instead of starting one.
|
|
48
|
+
export function requestStart(messages, index) {
|
|
49
|
+
for (let i = index; i >= 0; i -= 1) {
|
|
50
|
+
if (!isActualUserInstructionMessage(messages[i])) continue;
|
|
51
|
+
if (messages[i]?.meta?.source !== 'steering') return i;
|
|
52
|
+
}
|
|
53
|
+
return latestActualUserInstructionIndex(messages.slice(0, index + 1));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// A tool call's arguments as an object, whether stored parsed or as JSON text.
|
|
57
|
+
export function callArguments(call) {
|
|
58
|
+
let args = call?.arguments;
|
|
59
|
+
if (typeof args === 'string') {
|
|
60
|
+
try {
|
|
61
|
+
args = JSON.parse(args);
|
|
62
|
+
} catch {
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return args && typeof args === 'object' ? args : {};
|
|
67
|
+
}
|
|
68
|
+
|
|
46
69
|
export function latestActualUserInstructionMessage(messages) {
|
|
47
70
|
const index = latestActualUserInstructionIndex(messages);
|
|
48
71
|
return index >= 0 ? { ...messages[index] } : null;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
// Observations that a later one of the same browser page
|
|
2
|
-
// replaced. Such a result's refs
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// keeps every
|
|
1
|
+
// Observations that a later one of the same browser page, desktop window,
|
|
2
|
+
// visualize tab (inspect / check) or image file replaced. Such a result's refs
|
|
3
|
+
// have expired, and its element list and pixels describe a state that no
|
|
4
|
+
// longer exists. Only compaction drops them: between compactions the
|
|
5
|
+
// transcript stays append-only so the provider cache prefix holds, and
|
|
6
|
+
// compaction rewrites that prefix anyway. The execution archive keeps every
|
|
7
|
+
// original.
|
|
8
|
+
import { callArguments, requestStart } from './messages.mjs';
|
|
9
|
+
|
|
7
10
|
const BROWSER_TOOLS = new Set(['browser', 'browser_devtools']);
|
|
8
11
|
const SNAPSHOT_LINE = /(?:^|\n)Snapshot:\s+((p\d+)-s\d+)\b/;
|
|
9
12
|
const TERMINAL_LINE = /(?:^|\n)Terminal:\s+(session-terminal:\S+)/;
|
|
@@ -52,13 +55,40 @@ function containsRun(newer, older) {
|
|
|
52
55
|
return false;
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
const VISUALIZE_READS = new Set(['inspect', 'check']);
|
|
59
|
+
const IMAGE_FILE = /\.(?:png|jpe?g|gif|webp)$/i;
|
|
60
|
+
// What a superseded computer frame keeps besides its reference.
|
|
61
|
+
const FRAME_OUTCOME_KEYS = ['ok', 'action', 'actions', 'status', 'error', 'window_id'];
|
|
62
|
+
|
|
63
|
+
// A visualize read-out is the same observation only for the same tab, kind of
|
|
64
|
+
// read, viewport and scope: a mobile inspect does not replace a desktop one.
|
|
65
|
+
function visualizeKey(args) {
|
|
66
|
+
const input = args.input && typeof args.input === 'object' ? args.input : {};
|
|
67
|
+
if (!VISUALIZE_READS.has(args.action) || typeof input.tab !== 'string' || !input.tab) return null;
|
|
68
|
+
const scope = args.action === 'inspect' ? `:${JSON.stringify(input.viewport ?? null)}:${input.selector ?? ''}` : '';
|
|
69
|
+
return { key: `visualize:${args.action}:${input.tab}${scope}`, action: args.action, tab: input.tab };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// What one tool result observed, keyed by the page, window, tab or file it
|
|
73
|
+
// describes.
|
|
74
|
+
function observationOf(message, call) {
|
|
57
75
|
if (message?.role !== 'tool' || message.toolKind === 'error') return null;
|
|
76
|
+
const toolName = String(call?.name || '');
|
|
58
77
|
const parts = contentParts(message.content);
|
|
78
|
+
if (toolName === 'read') {
|
|
79
|
+
const args = callArguments(call);
|
|
80
|
+
const path = typeof args.path === 'string' ? args.path : args.file_path;
|
|
81
|
+
if (typeof path !== 'string' || !IMAGE_FILE.test(path) || !parts.some(isImagePart)) return null;
|
|
82
|
+
return { key: `image:${path.replace(/\\/g, '/')}`, imagePath: path, requestScoped: true };
|
|
83
|
+
}
|
|
59
84
|
const textIndex = parts.findIndex((part) => part?.type === 'text' && !isImagePart(part));
|
|
60
85
|
if (textIndex < 0) return null;
|
|
61
86
|
const text = String(parts[textIndex].text);
|
|
87
|
+
if (toolName === 'visualize') {
|
|
88
|
+
if (/^\[Visualize \w+ of tab \S+ superseded:/.test(text)) return null;
|
|
89
|
+
const read = visualizeKey(callArguments(call));
|
|
90
|
+
return read ? { key: read.key, parts, textIndex, visualize: read, requestScoped: true } : null;
|
|
91
|
+
}
|
|
62
92
|
if (BROWSER_TOOLS.has(toolName)) {
|
|
63
93
|
const snapshot = SNAPSHOT_LINE.exec(text);
|
|
64
94
|
return snapshot ? { key: `browser:${snapshot[2]}`, parts, textIndex, text, snapshot } : null;
|
|
@@ -82,40 +112,90 @@ function observationOf(message, toolName) {
|
|
|
82
112
|
const frame = value?.observation && typeof value.observation === 'object' ? value.observation : value;
|
|
83
113
|
const windowId = frame?.window_id || value?.window_id;
|
|
84
114
|
const observed = Array.isArray(frame?.elements) || frame?.ocr !== undefined || parts.some(isImagePart);
|
|
85
|
-
|
|
115
|
+
if (windowId && observed) return { key: `computer:${windowId}`, parts, textIndex, value, frame };
|
|
116
|
+
// A stub an earlier compaction wrote in the fuller format.
|
|
117
|
+
const slim =
|
|
118
|
+
typeof frame?.superseded === 'string' &&
|
|
119
|
+
Object.keys(frame).some((name) => name !== 'superseded' && !FRAME_OUTCOME_KEYS.includes(name));
|
|
120
|
+
return slim ? { stub: true, parts, textIndex, value, frame, reference: frame.superseded } : null;
|
|
86
121
|
}
|
|
87
122
|
|
|
88
|
-
|
|
89
|
-
|
|
123
|
+
// Transcript indices whose results are still in use and must stay verbatim:
|
|
124
|
+
// the latest tool-call group (the batch the session continues from, which
|
|
125
|
+
// compaction always retains) and any group with a call that has no result yet.
|
|
126
|
+
function protectedObservationIndices(messages) {
|
|
127
|
+
const protectedIndices = new Set();
|
|
128
|
+
const protect = (from, to) => {
|
|
129
|
+
for (let index = from; index < to; index += 1) protectedIndices.add(index);
|
|
130
|
+
};
|
|
131
|
+
let latest = null;
|
|
132
|
+
for (let index = 0; index < messages.length; index += 1) {
|
|
133
|
+
const message = messages[index];
|
|
134
|
+
if (message?.role !== 'assistant' || !message.toolCalls?.length) continue;
|
|
135
|
+
const start = index;
|
|
136
|
+
const answered = new Set();
|
|
137
|
+
while (messages[index + 1]?.role === 'tool') {
|
|
138
|
+
index += 1;
|
|
139
|
+
answered.add(messages[index].toolCallId);
|
|
140
|
+
}
|
|
141
|
+
latest = [start, index + 1];
|
|
142
|
+
if (message.toolCalls.some((call) => !answered.has(call?.id))) protect(...latest);
|
|
143
|
+
}
|
|
144
|
+
if (latest) protect(...latest);
|
|
145
|
+
return protectedIndices;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Tool results that a later observation of the same page, window, tab or
|
|
149
|
+
* file replaced, keyed by transcript index. Protected results are never
|
|
150
|
+
* listed, though they still count as the newer observation of what they
|
|
151
|
+
* describe. An image file read or visualize read-out is also kept for the
|
|
152
|
+
* whole active request (everything since the last user instruction), since
|
|
153
|
+
* the request may compare it with a later one; once a newer user message
|
|
154
|
+
* exists it is replaceable. */
|
|
90
155
|
export function staleObservations(messages) {
|
|
91
|
-
const
|
|
156
|
+
const protectedIndices = protectedObservationIndices(messages);
|
|
157
|
+
const activeRequest = Math.max(requestStart(messages, messages.length - 1), 0);
|
|
158
|
+
const calls = new Map();
|
|
92
159
|
for (const message of messages) {
|
|
93
160
|
if (message?.role !== 'assistant' || !Array.isArray(message.toolCalls)) continue;
|
|
94
|
-
for (const call of message.toolCalls) if (call?.id)
|
|
161
|
+
for (const call of message.toolCalls) if (call?.id) calls.set(call.id, call);
|
|
95
162
|
}
|
|
96
163
|
const newest = new Set();
|
|
97
164
|
const terminalReads = new Map();
|
|
98
165
|
const stale = new Map();
|
|
99
166
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
100
|
-
const found = observationOf(messages[index],
|
|
167
|
+
const found = observationOf(messages[index], calls.get(messages[index]?.toolCallId));
|
|
101
168
|
if (!found) continue;
|
|
102
|
-
|
|
169
|
+
const replaceable = !protectedIndices.has(index) && !(found.requestScoped && index >= activeRequest);
|
|
170
|
+
if (found.stub) {
|
|
171
|
+
if (replaceable) stale.set(index, found);
|
|
172
|
+
} else if (found.body) {
|
|
103
173
|
const newer = terminalReads.get(found.key) ?? [];
|
|
104
|
-
if (newer.some((body) => containsRun(body, found.body))) stale.set(index, found);
|
|
174
|
+
if (replaceable && newer.some((body) => containsRun(body, found.body))) stale.set(index, found);
|
|
105
175
|
newer.push(found.body);
|
|
106
176
|
terminalReads.set(found.key, newer);
|
|
107
|
-
} else if (newest.has(found.key))
|
|
108
|
-
|
|
177
|
+
} else if (newest.has(found.key)) {
|
|
178
|
+
if (replaceable) stale.set(index, found);
|
|
179
|
+
} else newest.add(found.key);
|
|
109
180
|
}
|
|
110
181
|
return stale;
|
|
111
182
|
}
|
|
112
183
|
|
|
113
184
|
/** The result without its replaced observation. A browser result keeps what
|
|
114
185
|
* precedes its snapshot (effect notes, a script's value) and a computer
|
|
115
|
-
* result its action outcome;
|
|
186
|
+
* result its action outcome plus a reference; none keeps elements, OCR text,
|
|
187
|
+
* frame metadata or pixels. A visualize read-out or image file read becomes a
|
|
188
|
+
* one-line placeholder naming what it was and how to get it again. */
|
|
116
189
|
export function supersedeObservation(message, found, origin) {
|
|
117
190
|
let text;
|
|
118
|
-
if (found.
|
|
191
|
+
if (found.imagePath) {
|
|
192
|
+
text = `[Image read of ${found.imagePath} superseded: a newer read of this file follows. Read the file again to view it. ${origin}]`;
|
|
193
|
+
return { ...message, content: withParts(message.content, [{ type: 'text', text }]) };
|
|
194
|
+
}
|
|
195
|
+
if (found.visualize) {
|
|
196
|
+
const { action, tab } = found.visualize;
|
|
197
|
+
text = `[Visualize ${action} of tab ${tab} superseded: a newer ${action} of this tab follows. Run visualize ${action} on the tab again to get it. ${origin}]`;
|
|
198
|
+
} else if (found.terminal) {
|
|
119
199
|
text = `[Terminal ${found.terminal} read superseded: a newer read of this tab follows. ${origin}]`;
|
|
120
200
|
} else if (found.snapshot) {
|
|
121
201
|
const { snapshot } = found;
|
|
@@ -126,9 +206,9 @@ export function supersedeObservation(message, found, origin) {
|
|
|
126
206
|
const note = `[Snapshot ${snapshot[1]} superseded: a newer snapshot of this page follows. ${origin}]`;
|
|
127
207
|
text = before ? `${before}\n\n${note}` : note;
|
|
128
208
|
} else {
|
|
129
|
-
const frame = {
|
|
130
|
-
|
|
131
|
-
|
|
209
|
+
const frame = {};
|
|
210
|
+
for (const name of FRAME_OUTCOME_KEYS) if (found.frame[name] !== undefined) frame[name] = found.frame[name];
|
|
211
|
+
frame.superseded = found.reference ?? `a newer observation of this window follows. ${origin}`;
|
|
132
212
|
text = JSON.stringify(found.frame === found.value ? frame : { ...found.value, observation: frame });
|
|
133
213
|
}
|
|
134
214
|
const parts = found.parts.flatMap((part, index) => {
|