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
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
inheritedFromSessionId,
|
|
25
25
|
isStoredSessionId,
|
|
26
26
|
positiveNumber as _positiveNumber,
|
|
27
|
+
compactCount,
|
|
28
|
+
compactCountField,
|
|
27
29
|
realTurnCount,
|
|
28
30
|
workspaceSummary,
|
|
29
31
|
} from './store-summary-fields.mjs';
|
|
@@ -54,26 +56,50 @@ const _computeCleanPreview = cleanSummaryPreview;
|
|
|
54
56
|
// cleaning runs a chain of regex replaces that each allocate a copy. Those
|
|
55
57
|
// short strings repeat from flush to flush, so the pure result is memoized per
|
|
56
58
|
// (max, text). Long raw message text is not kept here (see _previewFromMessage).
|
|
59
|
+
// Every new message's raw text (up to the text limit) also passes through, so
|
|
60
|
+
// the memo is bounded by the characters it holds, least recently used first
|
|
61
|
+
// out: at 8192 entries alone it kept ~16–32 MB of message text per `max`.
|
|
57
62
|
const CLEAN_PREVIEW_MEMO_TEXT_LIMIT = 2048;
|
|
58
63
|
const CLEAN_PREVIEW_MEMO_ENTRIES = 8192;
|
|
59
|
-
const
|
|
64
|
+
const CLEAN_PREVIEW_MEMO_MAX_CHARS = 512 * 1024;
|
|
65
|
+
const cleanPreviewMemo = new Map(); // max → { byText: Map<text, cleaned>, chars }
|
|
60
66
|
|
|
61
67
|
function _cleanPreview(text, max = 240) {
|
|
62
68
|
if (typeof text !== 'string' || text.length > CLEAN_PREVIEW_MEMO_TEXT_LIMIT) return _computeCleanPreview(text, max);
|
|
63
|
-
let
|
|
64
|
-
if (!
|
|
65
|
-
|
|
66
|
-
cleanPreviewMemo.set(max,
|
|
69
|
+
let memo = cleanPreviewMemo.get(max);
|
|
70
|
+
if (!memo) {
|
|
71
|
+
memo = { byText: new Map(), chars: 0 };
|
|
72
|
+
cleanPreviewMemo.set(max, memo);
|
|
67
73
|
}
|
|
74
|
+
const { byText } = memo;
|
|
68
75
|
let cleaned = byText.get(text);
|
|
69
|
-
if (cleaned
|
|
70
|
-
|
|
71
|
-
if (byText.size >= CLEAN_PREVIEW_MEMO_ENTRIES) byText.clear();
|
|
76
|
+
if (cleaned !== undefined) {
|
|
77
|
+
byText.delete(text);
|
|
72
78
|
byText.set(text, cleaned);
|
|
79
|
+
return cleaned;
|
|
80
|
+
}
|
|
81
|
+
cleaned = _computeCleanPreview(text, max);
|
|
82
|
+
byText.set(text, cleaned);
|
|
83
|
+
memo.chars += text.length + cleaned.length;
|
|
84
|
+
for (const [oldText, oldCleaned] of byText) {
|
|
85
|
+
if (byText.size <= CLEAN_PREVIEW_MEMO_ENTRIES && memo.chars <= CLEAN_PREVIEW_MEMO_MAX_CHARS) break;
|
|
86
|
+
byText.delete(oldText);
|
|
87
|
+
memo.chars -= oldText.length + oldCleaned.length;
|
|
73
88
|
}
|
|
74
89
|
return cleaned;
|
|
75
90
|
}
|
|
76
91
|
|
|
92
|
+
/** Entries and characters the preview memo holds, summed over every `max` (tests). */
|
|
93
|
+
export function _cleanPreviewMemoStatsForTest() {
|
|
94
|
+
let entries = 0;
|
|
95
|
+
let chars = 0;
|
|
96
|
+
for (const memo of cleanPreviewMemo.values()) {
|
|
97
|
+
entries += memo.byText.size;
|
|
98
|
+
chars += memo.chars;
|
|
99
|
+
}
|
|
100
|
+
return { entries, chars };
|
|
101
|
+
}
|
|
102
|
+
|
|
77
103
|
const sessionMessageProjectionMemo = new WeakMap();
|
|
78
104
|
// message → { raw, preview }. A session's first real user message is
|
|
79
105
|
// re-checked on every save; its text is re-derived (cheap) and the preview is
|
|
@@ -265,6 +291,8 @@ export function _sessionSummary(session) {
|
|
|
265
291
|
taskType: session.taskType || null,
|
|
266
292
|
messageCount: messageProjection.count,
|
|
267
293
|
...(messageProjection.incoming ? { incomingTail: messageProjection.incoming.slice() } : {}),
|
|
294
|
+
// The numbering epoch of messageCount: a compaction restarts it.
|
|
295
|
+
compactCount: compactCount(session.compaction) ?? 0,
|
|
268
296
|
realTurnCount: messageProjection.real,
|
|
269
297
|
title: _cleanPreview(session.title || '', 100),
|
|
270
298
|
preview: messageProjection.preview,
|
|
@@ -324,6 +352,7 @@ function _normalizeSummaryRow(row) {
|
|
|
324
352
|
taskType: row.taskType || null,
|
|
325
353
|
messageCount: Math.max(0, Math.floor(Number(row.messageCount) || 0)),
|
|
326
354
|
...(Array.isArray(row.incomingTail) ? { incomingTail: normalizedIncomingTail(row.incomingTail) } : {}),
|
|
355
|
+
...compactCountField(row),
|
|
327
356
|
realTurnCount: realTurnCount(row),
|
|
328
357
|
title: _cleanPreview(row.title || '', 100),
|
|
329
358
|
preview: _cleanPreview(row.preview || ''),
|
|
@@ -24,27 +24,44 @@ import {
|
|
|
24
24
|
stampedDerivation,
|
|
25
25
|
storedSessionCatalogRow,
|
|
26
26
|
} from './store-summary-catalog.mjs';
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
createStoredTranscriptCache,
|
|
29
|
+
historyStampOf,
|
|
30
|
+
producedSlice,
|
|
31
|
+
projectionStampEpoch,
|
|
32
|
+
transcriptTextHash,
|
|
33
|
+
} from './store-transcript-cache.mjs';
|
|
28
34
|
import {
|
|
29
35
|
forgetStoredTranscriptOffThread,
|
|
30
36
|
OFFLOAD_MIN_CHARS,
|
|
31
37
|
projectStoredTranscriptOffThread,
|
|
32
38
|
storedTranscriptWorkerRunning,
|
|
33
39
|
} from './store-transcript-worker.mjs';
|
|
34
|
-
import {
|
|
40
|
+
import {
|
|
41
|
+
cursorPageRows,
|
|
42
|
+
heldRowsDigester,
|
|
43
|
+
prepareStoredTranscriptBase,
|
|
44
|
+
projectStoredTranscript,
|
|
45
|
+
storedHistorySlice,
|
|
46
|
+
windowStoredTranscript,
|
|
47
|
+
} from './store-transcript-projection.mjs';
|
|
35
48
|
import { dataDir } from './store-summary-locations.mjs';
|
|
36
49
|
import { isStoredSessionId, workspaceSummary } from './store-summary-fields.mjs';
|
|
37
50
|
import { readArchivedAgentResult } from './store-summary-archived-agent.mjs';
|
|
38
51
|
import {
|
|
52
|
+
compactionArchivePageFromText,
|
|
39
53
|
compactionArchivePath,
|
|
40
54
|
compactionArchiveRange,
|
|
41
|
-
readCompactionArchivePage,
|
|
42
55
|
visitCompactionArchive,
|
|
43
56
|
} from './compaction-archive.mjs';
|
|
44
57
|
import { attachmentHistoryRows } from './stored-attachment-history.mjs';
|
|
45
58
|
import { currentSessionCatalogDb, onSessionCatalogDbChange, sessionCatalogDb } from './catalog-db/index.mjs';
|
|
46
59
|
import { decodeCatalogCursor, encodeCatalogCursor, isAfterCursor } from './catalog-db/schema.mjs';
|
|
47
|
-
import {
|
|
60
|
+
import {
|
|
61
|
+
onSessionActivityChange,
|
|
62
|
+
onSessionApprovalCardChange,
|
|
63
|
+
onSessionBotWorkChange,
|
|
64
|
+
} from '../../../shared/session-activity-signal.mjs';
|
|
48
65
|
import { inFlightSessionActivity } from './manager/runtime-state.mjs';
|
|
49
66
|
import {
|
|
50
67
|
readCanonicalSessionRecord as readCanonicalLifecycle,
|
|
@@ -72,15 +89,55 @@ const storedTranscriptCache = createStoredTranscriptCache();
|
|
|
72
89
|
// lookup can neither fill nor evict.
|
|
73
90
|
const attachmentHistoryCache = createStoredTranscriptCache();
|
|
74
91
|
|
|
92
|
+
// The display histories of SMALL sessions (record and archive under
|
|
93
|
+
// OFFLOAD_MIN_CHARS, projected on this thread), kept for slicing within a
|
|
94
|
+
// source-character budget; a larger one never stays on this thread (its
|
|
95
|
+
// history lives in the projection worker, or is projected per read as a
|
|
96
|
+
// bounded window).
|
|
97
|
+
const SMALL_HISTORY_MAX_CHARS = 4 * 1024 * 1024;
|
|
98
|
+
const smallHistories = (() => {
|
|
99
|
+
const entries = new Map();
|
|
100
|
+
let chars = 0;
|
|
101
|
+
const drop = (sessionId) => {
|
|
102
|
+
const entry = entries.get(sessionId);
|
|
103
|
+
if (!entry) return;
|
|
104
|
+
entries.delete(sessionId);
|
|
105
|
+
chars -= entry.chars;
|
|
106
|
+
};
|
|
107
|
+
return {
|
|
108
|
+
get(sessionId, identity) {
|
|
109
|
+
const entry = entries.get(sessionId);
|
|
110
|
+
if (!entry || entry.identity !== identity) return null;
|
|
111
|
+
entries.delete(sessionId);
|
|
112
|
+
entries.set(sessionId, entry);
|
|
113
|
+
return entry.history;
|
|
114
|
+
},
|
|
115
|
+
retain(sessionId, identity, sourceChars, history) {
|
|
116
|
+
drop(sessionId);
|
|
117
|
+
if (sourceChars > SMALL_HISTORY_MAX_CHARS) return;
|
|
118
|
+
entries.set(sessionId, { identity, chars: sourceChars, history });
|
|
119
|
+
chars += sourceChars;
|
|
120
|
+
while (chars > SMALL_HISTORY_MAX_CHARS && entries.size > 1) drop(entries.keys().next().value);
|
|
121
|
+
},
|
|
122
|
+
forget: drop,
|
|
123
|
+
clear() {
|
|
124
|
+
entries.clear();
|
|
125
|
+
chars = 0;
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
})();
|
|
129
|
+
|
|
75
130
|
/** Test seam: forget every cached projection. */
|
|
76
131
|
export function clearStoredTranscriptCache() {
|
|
77
132
|
storedTranscriptCache.clear();
|
|
133
|
+
smallHistories.clear();
|
|
78
134
|
}
|
|
79
135
|
|
|
80
136
|
/** Drop one session's cold projections: it went live, or its last view left. */
|
|
81
137
|
export function forgetStoredSessionTranscript(sessionId) {
|
|
82
138
|
const id = String(sessionId || '').trim();
|
|
83
139
|
storedTranscriptCache.forget(`${id}|`);
|
|
140
|
+
smallHistories.forget(id);
|
|
84
141
|
if (id) forgetStoredTranscriptOffThread(id);
|
|
85
142
|
}
|
|
86
143
|
|
|
@@ -136,6 +193,10 @@ onSessionActivityChange(() => {
|
|
|
136
193
|
// A session started or stopped waiting on the user's approval: its catalog row
|
|
137
194
|
// (`awaitingApproval`) changed, though no store file did.
|
|
138
195
|
onSessionApprovalCardChange(() => notifyCatalogListeners('approval'));
|
|
196
|
+
// A bot started or stopped having a send in flight in a session: its catalog
|
|
197
|
+
// row (`handedBy`) changed, though neither a file nor the set of working
|
|
198
|
+
// sessions did (the work may already be running, or continue past the end).
|
|
199
|
+
onSessionBotWorkChange(() => notifyCatalogListeners('bot-work'));
|
|
139
200
|
|
|
140
201
|
/** `listener()` runs when a background pass finds a session file that changed
|
|
141
202
|
* without a directory or index change, i.e. when an ordinary listing would
|
|
@@ -378,10 +439,16 @@ export function storedSessionTranscriptStamp(id) {
|
|
|
378
439
|
* itself). The answer is the cache's `project` contract; a worker failure
|
|
379
440
|
* rejects and the cache runs the in-process pipeline instead. */
|
|
380
441
|
async function projectStoredTranscriptElsewhere(known, context) {
|
|
381
|
-
const { sessionId, recordPath,
|
|
442
|
+
const { sessionId, recordPath, timing, fingerprint, slice } = context;
|
|
382
443
|
timing.worker = storedTranscriptWorkerRunning(sessionId) ? 'warm' : 'cold';
|
|
383
444
|
const workerStartedAt = performance.now();
|
|
384
|
-
const answer = await projectStoredTranscriptOffThread({
|
|
445
|
+
const answer = await projectStoredTranscriptOffThread({
|
|
446
|
+
sessionId,
|
|
447
|
+
recordPath,
|
|
448
|
+
known,
|
|
449
|
+
fingerprint,
|
|
450
|
+
slice: { ...slice, epoch: projectionStampEpoch() },
|
|
451
|
+
});
|
|
385
452
|
timing.workerMs = performance.now() - workerStartedAt;
|
|
386
453
|
Object.assign(timing, answer.timing);
|
|
387
454
|
context.readState = answer.state;
|
|
@@ -389,15 +456,66 @@ async function projectStoredTranscriptElsewhere(known, context) {
|
|
|
389
456
|
if (answer.same) return answer;
|
|
390
457
|
if (answer.unreadable) return { ...answer, value: null };
|
|
391
458
|
if (answer.stamp) readCanonicalLifecycle.rememberStrictVerdict(recordPath, answer.stamp, answer.lifecycle);
|
|
392
|
-
|
|
393
|
-
answer.value.projectionStamp = nextProjectionStamp();
|
|
459
|
+
if (answer.historyBuilt === false) timing.history = 'retained';
|
|
394
460
|
return answer;
|
|
395
461
|
}
|
|
396
462
|
|
|
463
|
+
/** A projector (projectStoredTranscript's signature) for a historical-position
|
|
464
|
+
* read on this thread (a checkpoint sidecar, or the worker unavailable): the
|
|
465
|
+
* base once, then tail windows doubling from twice the page until one holds
|
|
466
|
+
* the cursor's row with the page beside it, or history ends. Never the whole
|
|
467
|
+
* display history: only as deep as the row itself. */
|
|
468
|
+
const CURSOR_WINDOW_MAX_ITEMS = 8_192;
|
|
469
|
+
|
|
470
|
+
function cursorWindowProjector(cursor, timing) {
|
|
471
|
+
return async (sessionId, doc, options) => {
|
|
472
|
+
const base = await prepareStoredTranscriptBase(sessionId, doc, options);
|
|
473
|
+
const id = cursor.before ?? cursor.after;
|
|
474
|
+
for (
|
|
475
|
+
let itemLimit = Math.max(64, cursor.maxRows * 2);
|
|
476
|
+
;
|
|
477
|
+
itemLimit = Math.min(itemLimit * 2, CURSOR_WINDOW_MAX_ITEMS)
|
|
478
|
+
) {
|
|
479
|
+
timing.cursorWindowItems = itemLimit;
|
|
480
|
+
const window = await windowStoredTranscript(sessionId, base, { itemLimit, includeMessages: false });
|
|
481
|
+
const at = window.items.findIndex((item) => item?.id === id);
|
|
482
|
+
if ((at >= 0 && (cursor.before == null || at >= cursor.maxRows)) || !window.transcriptHasOlder) return window;
|
|
483
|
+
// Never deeper on this thread: a row past the bound answers `reset`
|
|
484
|
+
// (the slice finds no such row), one at its edge a shorter page.
|
|
485
|
+
if (itemLimit >= CURSOR_WINDOW_MAX_ITEMS) return at >= 0 ? window : { ...window, items: [] };
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/** The slice `request` names of `history` (the display history, or a window
|
|
491
|
+
* of it), stamped `<history stamp>/<slice>`. */
|
|
492
|
+
async function sliceOf(history, request, historyStamp) {
|
|
493
|
+
const proven = Boolean(request.held) && request.baseHistory === historyStamp;
|
|
494
|
+
const value = storedHistorySlice(
|
|
495
|
+
history,
|
|
496
|
+
{ ...request, proven },
|
|
497
|
+
{ digestOf: request.held && !proven ? await heldRowsDigester() : null }
|
|
498
|
+
);
|
|
499
|
+
const { windowStamp } = value;
|
|
500
|
+
delete value.windowStamp;
|
|
501
|
+
value.projectionStamp = `${historyStamp}/${windowStamp}`;
|
|
502
|
+
return value;
|
|
503
|
+
}
|
|
504
|
+
|
|
397
505
|
/** Projects the strictly parsed record `text` (read at full stamp `stamp`, or
|
|
398
506
|
* null when not provably stable) into the cached transcript value. */
|
|
399
507
|
async function produceStoredTranscript(text, stamp, context) {
|
|
400
|
-
const { sessionId, recordPath, itemLimit, includeMessages, mode, checkpointAbsent, timing } =
|
|
508
|
+
const { sessionId, recordPath, itemLimit, slice, fingerprint, includeMessages, mode, checkpointAbsent, timing } =
|
|
509
|
+
context;
|
|
510
|
+
const historyStamp =
|
|
511
|
+
mode === 'items' ? historyStampOf(sessionId, transcriptTextHash(text), text.length, fingerprint) : null;
|
|
512
|
+
// A small session's retained history answers every other slice of it.
|
|
513
|
+
const keepHistory = mode === 'items' && checkpointAbsent && context.sourceChars < OFFLOAD_MIN_CHARS;
|
|
514
|
+
const retained = keepHistory ? smallHistories.get(sessionId, historyStamp) : null;
|
|
515
|
+
if (retained) {
|
|
516
|
+
timing.history = 'retained';
|
|
517
|
+
return producedSlice(await sliceOf(retained, slice, historyStamp), { historyBuilt: false });
|
|
518
|
+
}
|
|
401
519
|
const parseStartedAt = performance.now();
|
|
402
520
|
const record = readTopLevelLifecycleRecord(text);
|
|
403
521
|
timing.parseMs = performance.now() - parseStartedAt;
|
|
@@ -423,22 +541,29 @@ async function produceStoredTranscript(text, stamp, context) {
|
|
|
423
541
|
// load the hand-off serves, and projects the load cache's session
|
|
424
542
|
// exactly as before; only that projection is detached.
|
|
425
543
|
const projectStartedAt = performance.now();
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
544
|
+
const project = keepHistory || !slice.cursor ? projectStoredTranscript : cursorWindowProjector(slice.cursor, timing);
|
|
545
|
+
const projected = await project(sessionId, handedOver && checkpointAbsent ? JSON.parse(text) : record.doc, {
|
|
546
|
+
itemLimit,
|
|
547
|
+
// Only a small session's whole display history is built (and kept) on
|
|
548
|
+
// this thread; any other item read projects just its bounded window
|
|
549
|
+
// (a tail of that history) and slices it; a historical-position read
|
|
550
|
+
// projects the tail window reaching its row (cursorWindowProjector).
|
|
551
|
+
history: keepHistory,
|
|
552
|
+
includeMessages,
|
|
553
|
+
checkpointAbsent,
|
|
554
|
+
});
|
|
435
555
|
timing.projectMs = performance.now() - projectStartedAt;
|
|
436
|
-
if (
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
556
|
+
if (mode !== 'items' || !projected) return projected;
|
|
557
|
+
if (keepHistory) smallHistories.retain(sessionId, historyStamp, context.sourceChars, projected);
|
|
558
|
+
let value = await sliceOf(projected, slice, historyStamp);
|
|
559
|
+
if (handedOver && !checkpointAbsent) {
|
|
560
|
+
try {
|
|
561
|
+
value = structuredClone(value);
|
|
562
|
+
} catch {
|
|
563
|
+
// Served as projected.
|
|
564
|
+
}
|
|
441
565
|
}
|
|
566
|
+
return producedSlice(value);
|
|
442
567
|
}
|
|
443
568
|
|
|
444
569
|
/** The rows of one session's whole stored conversation that name attachments
|
|
@@ -484,6 +609,37 @@ async function readStoredAttachmentHistory(sessionId, recordPath, archivePath) {
|
|
|
484
609
|
return value ?? null;
|
|
485
610
|
}
|
|
486
611
|
|
|
612
|
+
/** One page of a session's compaction archive (`{ after, before, skip,
|
|
613
|
+
* limit }`, as readCompactionArchivePage pages it), cut from its visible rows
|
|
614
|
+
* built once per archive content in the transcript cache: paging a live
|
|
615
|
+
* session through a large segment slices instead of re-parsing it; `paging`
|
|
616
|
+
* keeps it cached under pressure (the cache's `pin`). */
|
|
617
|
+
async function readCachedCompactionArchivePage(sessionId, archivePath, range, paging) {
|
|
618
|
+
const after = Math.max(0, Math.floor(Number(range.after) || 0));
|
|
619
|
+
const before = Number(range.before);
|
|
620
|
+
const visible = { after, before: Number.isFinite(before) ? before : Number.POSITIVE_INFINITY };
|
|
621
|
+
const archive = probePath(archivePath);
|
|
622
|
+
if (archive.state !== PROBE_PRESENT) return { items: [], hasOlder: false };
|
|
623
|
+
const { value } = await storedTranscriptCache.read({
|
|
624
|
+
key: `${sessionId}|archive|${visible.after}:${visible.before}`,
|
|
625
|
+
group: `${sessionId}|archive`,
|
|
626
|
+
fingerprint: '',
|
|
627
|
+
fileStat: archive,
|
|
628
|
+
pin: paging,
|
|
629
|
+
loadText: () => {
|
|
630
|
+
const body = readTextFile(archivePath);
|
|
631
|
+
return body.state === PROBE_PRESENT ? body.text : null;
|
|
632
|
+
},
|
|
633
|
+
produce: async (text) => ({
|
|
634
|
+
items: (await compactionArchivePageFromText(text, { ...visible, limit: Number.POSITIVE_INFINITY })).items,
|
|
635
|
+
}),
|
|
636
|
+
});
|
|
637
|
+
const items = Array.isArray(value?.items) ? value.items : [];
|
|
638
|
+
const end = Math.max(0, items.length - Math.max(0, Math.floor(Number(range.skip) || 0)));
|
|
639
|
+
const start = Math.max(0, end - Math.max(0, Math.floor(Number(range.limit) || 0)));
|
|
640
|
+
return { items: items.slice(start, end), hasOlder: start > 0 };
|
|
641
|
+
}
|
|
642
|
+
|
|
487
643
|
/** Read exactly one persisted session for a visible desktop pane. This never
|
|
488
644
|
* enumerates siblings. Normal reads stay independent of runtime ownership;
|
|
489
645
|
* interrupted turns conditionally use the same durable reconnect recovery as
|
|
@@ -500,7 +656,7 @@ export async function readStoredSessionTranscript(id, options = {}) {
|
|
|
500
656
|
// One page of the display-only compaction archive (the live head loader
|
|
501
657
|
// pages it once a runtime's in-memory rows are exhausted).
|
|
502
658
|
if (options.compactionArchive && typeof options.compactionArchive === 'object') {
|
|
503
|
-
return
|
|
659
|
+
return readCachedCompactionArchivePage(sessionId, archivePath, options.compactionArchive, options.paging === true);
|
|
504
660
|
}
|
|
505
661
|
// The checkpoint sidecar shapes the projection as much as the record does,
|
|
506
662
|
// so its identity joins the cache fingerprint. Only a PROVABLY absent
|
|
@@ -516,6 +672,51 @@ export async function readStoredSessionTranscript(id, options = {}) {
|
|
|
516
672
|
const archive = probePath(archivePath);
|
|
517
673
|
const requestedLimit = Number(options.transcriptItemLimit);
|
|
518
674
|
const itemLimit = Number.isFinite(requestedLimit) && requestedLimit > 0 ? requestedLimit : Number.POSITIVE_INFINITY;
|
|
675
|
+
// `transcriptSkip`: the window's newest rows to leave out (a range read
|
|
676
|
+
// slices only the rows above them, with `skippedFirstId`).
|
|
677
|
+
const requestedSkip = Number(options.transcriptSkip);
|
|
678
|
+
const skip =
|
|
679
|
+
Number.isFinite(itemLimit) && Number.isSafeInteger(requestedSkip) && requestedSkip > 0
|
|
680
|
+
? Math.min(requestedSkip, itemLimit)
|
|
681
|
+
: 0;
|
|
682
|
+
// `transcriptHeld` (`{ firstId, count, digest }`): the newest rows a paged
|
|
683
|
+
// caller holds, proven by `transcriptBaseHistory` (the history stamp they
|
|
684
|
+
// were served under) or their digest, where the history is: only the page
|
|
685
|
+
// above them (`transcriptPage`: `{ maxRows, byteBudget }`) is sliced,
|
|
686
|
+
// whatever their count. Unproven, a tail of at most `maxRows` rows.
|
|
687
|
+
const heldOption = options.transcriptHeld;
|
|
688
|
+
const held =
|
|
689
|
+
Number.isFinite(itemLimit) && heldOption && Number.isSafeInteger(heldOption.count) && heldOption.count > 0
|
|
690
|
+
? { firstId: heldOption.firstId, count: heldOption.count, digest: String(heldOption.digest ?? '') }
|
|
691
|
+
: null;
|
|
692
|
+
const page = options.transcriptPage || {};
|
|
693
|
+
// `transcriptCursor` (`{ before | after, maxRows, byteBudget }`): a
|
|
694
|
+
// historical-position read — the rows next to one row, by its id.
|
|
695
|
+
const cursorOption = options.transcriptCursor;
|
|
696
|
+
const cursor =
|
|
697
|
+
cursorOption && (cursorOption.before != null || cursorOption.after != null)
|
|
698
|
+
? {
|
|
699
|
+
...(cursorOption.before != null ? { before: cursorOption.before } : { after: cursorOption.after }),
|
|
700
|
+
maxRows: cursorPageRows(cursorOption.maxRows),
|
|
701
|
+
byteBudget: Number(cursorOption.byteBudget) > 0 ? Number(cursorOption.byteBudget) : null,
|
|
702
|
+
}
|
|
703
|
+
: null;
|
|
704
|
+
const slice = cursor
|
|
705
|
+
? { cursor }
|
|
706
|
+
: held
|
|
707
|
+
? {
|
|
708
|
+
limit: itemLimit,
|
|
709
|
+
held,
|
|
710
|
+
baseHistory: typeof options.transcriptBaseHistory === 'string' ? options.transcriptBaseHistory : null,
|
|
711
|
+
maxRows: Math.max(1, Math.floor(Number(page.maxRows) || itemLimit)),
|
|
712
|
+
byteBudget: Number(page.byteBudget) > 0 ? Number(page.byteBudget) : null,
|
|
713
|
+
}
|
|
714
|
+
: { limit: itemLimit, skip };
|
|
715
|
+
const sliceKey = cursor
|
|
716
|
+
? `cursor:${cursor.before ?? ''}:${cursor.after ?? ''}:${cursor.maxRows}:${cursor.byteBudget}`
|
|
717
|
+
: held
|
|
718
|
+
? `held:${held.count}:${held.firstId}:${held.digest}:${slice.baseHistory}:${slice.maxRows}:${slice.byteBudget}`
|
|
719
|
+
: skip;
|
|
519
720
|
// Full stamp the loaded text provably came from (unchanged around the
|
|
520
721
|
// read), or null. Only such a parse may serve other readers.
|
|
521
722
|
let readStamp = null;
|
|
@@ -525,11 +726,27 @@ export async function readStoredSessionTranscript(id, options = {}) {
|
|
|
525
726
|
const mode = includeMessages ? 'messages' : 'items';
|
|
526
727
|
const checkpointAbsent = checkpoint.state === PROBE_ABSENT;
|
|
527
728
|
// Large, checkpoint-free item projections run off the daemon event loop.
|
|
528
|
-
|
|
729
|
+
// A large compaction archive counts: the display history holds its rows.
|
|
730
|
+
const sourceChars = recordStat.size + (archive.state === PROBE_PRESENT ? Number(archive.size) || 0 : 0);
|
|
731
|
+
const offloadable = !includeMessages && checkpointAbsent && sourceChars >= OFFLOAD_MIN_CHARS;
|
|
732
|
+
const fingerprint = [
|
|
733
|
+
checkpoint.state,
|
|
734
|
+
checkpoint.mtimeMs,
|
|
735
|
+
checkpoint.ctimeMs,
|
|
736
|
+
checkpoint.size,
|
|
737
|
+
checkpoint.ino,
|
|
738
|
+
checkpoint.dev,
|
|
739
|
+
archive.state,
|
|
740
|
+
archive.mtimeMs,
|
|
741
|
+
archive.size,
|
|
742
|
+
].join(':');
|
|
529
743
|
const produceContext = {
|
|
530
744
|
sessionId,
|
|
531
745
|
recordPath,
|
|
532
746
|
itemLimit,
|
|
747
|
+
slice,
|
|
748
|
+
sourceChars,
|
|
749
|
+
fingerprint,
|
|
533
750
|
includeMessages,
|
|
534
751
|
mode,
|
|
535
752
|
checkpointAbsent,
|
|
@@ -537,21 +754,16 @@ export async function readStoredSessionTranscript(id, options = {}) {
|
|
|
537
754
|
// How the record read went (the worker's read or loadText below).
|
|
538
755
|
readState: PROBE_PRESENT,
|
|
539
756
|
};
|
|
540
|
-
const { value, hit, read } = await storedTranscriptCache.read({
|
|
541
|
-
|
|
757
|
+
const { value, hit, read, built } = await storedTranscriptCache.read({
|
|
758
|
+
// One slice (window or page) per request; the group keeps one per
|
|
759
|
+
// session: the display history it is cut from stays with the thread
|
|
760
|
+
// that built it.
|
|
761
|
+
key: `${sessionId}|${itemLimit}|${sliceKey}|${mode}`,
|
|
542
762
|
// Growing history windows of one session replace each other.
|
|
543
763
|
group: `${sessionId}|${mode}`,
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
checkpoint.ctimeMs,
|
|
548
|
-
checkpoint.size,
|
|
549
|
-
checkpoint.ino,
|
|
550
|
-
checkpoint.dev,
|
|
551
|
-
archive.state,
|
|
552
|
-
archive.mtimeMs,
|
|
553
|
-
archive.size,
|
|
554
|
-
].join(':'),
|
|
764
|
+
// A page read keeps its slice cached under pressure.
|
|
765
|
+
pin: options.paging === true,
|
|
766
|
+
fingerprint,
|
|
555
767
|
fileStat: recordStat,
|
|
556
768
|
project: offloadable ? (known) => projectStoredTranscriptElsewhere(known, produceContext) : null,
|
|
557
769
|
loadText: async () => {
|
|
@@ -581,7 +793,8 @@ export async function readStoredSessionTranscript(id, options = {}) {
|
|
|
581
793
|
if (typeof options.trace === 'function') {
|
|
582
794
|
options.trace({
|
|
583
795
|
sessionId,
|
|
584
|
-
hit
|
|
796
|
+
// A slice of a history already built counts as a hit: nothing was projected.
|
|
797
|
+
hit: hit || built === false,
|
|
585
798
|
read,
|
|
586
799
|
ms: performance.now() - startedAt,
|
|
587
800
|
chars: recordStat.size,
|