mixdog 1.2.2 → 1.2.3
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/README.md +18 -0
- package/package.json +2 -1
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +7 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +58 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +12 -6
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +114 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +37 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +25 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +87 -5
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +13 -13
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +355 -37
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +93 -47
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +55 -10
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +26 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +121 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +42 -24
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +53 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +25 -4
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +71 -24
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +147 -8
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +63 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +31 -26
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +108 -3
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +6 -0
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +268 -100
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
- package/src/runtime/shared/turn-snapshot.mjs +857 -683
- package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +13 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +72 -7
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +17 -5
- package/src/session-runtime/model-route/set-route.mjs +2 -2
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +8 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +19 -0
- package/src/standalone/daemon.mjs +61 -1
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +6 -1
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +13 -3
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/dist/index.mjs +2413 -1465
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/session-api/commands.mjs +10 -0
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/integrations.mjs +9 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +2 -1
- package/src/tui/session/session-api/settings.mjs +6 -0
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +12 -5
- package/src/workflows/default/WORKFLOW.md +3 -1
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { clean } from '../../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
7
7
|
import { forgetSessionSearch } from '../../../runtime/session-search/session-search-ingest.mjs';
|
|
8
|
-
import {
|
|
8
|
+
import { leadSessionRow } from '../session-catalog.mjs';
|
|
9
|
+
import { getStoreDir } from '../../../runtime/agent/orchestrator/session/store/paths-heartbeat.mjs';
|
|
10
|
+
import {
|
|
11
|
+
STORED_SESSION_UNREADABLE,
|
|
12
|
+
_storedSessionFromFile,
|
|
13
|
+
} from '../../../runtime/agent/orchestrator/session/store/serialize.mjs';
|
|
9
14
|
import { SESSION_ID_PATTERN } from '../shared.mjs';
|
|
10
15
|
import { replacementSessionCwd } from '../../workspace/workspace-state.mjs';
|
|
11
16
|
|
|
@@ -50,6 +55,15 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
|
|
58
|
+
// Availability is one strict read of the session's own file, filtered like
|
|
59
|
+
// the Lead catalog (an unreadable, foreign, closed or non-Lead record is not
|
|
60
|
+
// deletable). No catalog rebuild, no folder scan.
|
|
61
|
+
function isAvailableLead(sessionId) {
|
|
62
|
+
const stored = _storedSessionFromFile(getStoreDir(), `${sessionId}.json`);
|
|
63
|
+
if (!stored || stored === STORED_SESSION_UNREADABLE || stored.closed === true) return false;
|
|
64
|
+
return leadSessionRow(stored, new Map()) !== null;
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
// The deleted task's worktree: the autoCleanup setting decides (clean and
|
|
54
68
|
// merged → removed; otherwise kept). Off the deletion path; never fails it.
|
|
55
69
|
function releaseDeletedWorktree(sessionId) {
|
|
@@ -61,12 +75,18 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
61
75
|
async function deleteSession(id) {
|
|
62
76
|
const sessionId = clean(id);
|
|
63
77
|
if (!sessionId || !SESSION_ID_PATTERN.test(sessionId)) return false;
|
|
64
|
-
|
|
65
|
-
if (!available) return false;
|
|
78
|
+
if (!isAvailableLead(sessionId)) return false;
|
|
66
79
|
const childIds = ownedAgentSessionIds(sessionId);
|
|
67
80
|
const current = getSession();
|
|
81
|
+
const cleanupReason = 'desktop-session-delete';
|
|
68
82
|
if (current?.id !== sessionId) {
|
|
69
|
-
|
|
83
|
+
// A turn can still be running in a session that is no longer current.
|
|
84
|
+
// Stop its runtime first (controller abort, shells, generation bump) and
|
|
85
|
+
// release its lead row, agents and tasks, so nothing can write it back.
|
|
86
|
+
if (mgr.closeSession(sessionId, cleanupReason, { tombstone: false }) !== true) return false;
|
|
87
|
+
agentTool?.forgetLeadSession?.(sessionId);
|
|
88
|
+
releaseSessionWork(sessionId, cleanupReason);
|
|
89
|
+
const deleted = mgr.deleteSession(sessionId, { fenceWrites: true }) === true;
|
|
70
90
|
if (!deleted) return false;
|
|
71
91
|
void forgetSessionSearch(sessionId);
|
|
72
92
|
// The parent is already irreversibly gone, so child cleanup is
|
|
@@ -74,7 +94,7 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
74
94
|
// because its retained-parent proof disappeared with the parent.
|
|
75
95
|
for (const childId of childIds) {
|
|
76
96
|
try {
|
|
77
|
-
mgr.deleteSession(childId);
|
|
97
|
+
mgr.deleteSession(childId, { fenceWrites: true });
|
|
78
98
|
} catch {}
|
|
79
99
|
}
|
|
80
100
|
void releaseDeletedWorktree(sessionId);
|
|
@@ -83,12 +103,15 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
83
103
|
// Leaving a worktree-bound Lead: the replacement starts in the Project
|
|
84
104
|
// folder, and the worktree can go once nothing runs in it.
|
|
85
105
|
const projectFolder = replacementSessionCwd(current);
|
|
86
|
-
const cleanupReason = 'desktop-session-delete';
|
|
87
106
|
releaseSessionWork(sessionId, cleanupReason);
|
|
88
107
|
// Active sessions retain a tombstone until the normal sweep. Unlinking
|
|
89
108
|
// immediately would let a late provider/save continuation resurrect the
|
|
90
109
|
// deleted conversation after the user has moved to its replacement.
|
|
91
110
|
if (mgr.closeSession(sessionId, cleanupReason, { tombstone: true }) !== true) return false;
|
|
111
|
+
// The unwinding turn's late saves and its idle lead-row upsert must not
|
|
112
|
+
// touch the deleted conversation (an unguarded save would pass the tombstone).
|
|
113
|
+
mgr.fenceSessionWrites?.(sessionId);
|
|
114
|
+
agentTool?.forgetLeadSession?.(sessionId);
|
|
92
115
|
void forgetSessionSearch(sessionId);
|
|
93
116
|
// Active parent deletion uses the same durable tombstone boundary for
|
|
94
117
|
// every linked child. Their files then mature with the parent instead of
|
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { SessionClosedError } from '../../runtime/agent/orchestrator/session/manager/session-errors.mjs';
|
|
9
9
|
import { forgetSessionSaveBaseline } from '../../runtime/agent/orchestrator/session/store/save-worker.mjs';
|
|
10
|
+
import { flushAllIndexWrites } from '../services/agent-tool/index-write-queue.mjs';
|
|
10
11
|
import { unregisterLiveSession } from '../../runtime/shared/staged-update.mjs';
|
|
11
12
|
import { abortRuntime, closeCanonicalSession, closeOwnSession, dispatchSessionEnd } from './teardown/session-close.mjs';
|
|
12
13
|
import { settleAll, settleDetached, startRuntimeStops, startWorkStops } from './teardown/runtime-stops.mjs';
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
+
const CLOSE_ALL_DEADLINE_MS = 5000;
|
|
16
|
+
const PROCESS_EXIT_REASON =/exit|quit|shutdown|sighup|sigint|sigterm/;
|
|
15
17
|
const WARMUP_TIMER_KEYS = [
|
|
16
18
|
'providerSetupWarmupTimer',
|
|
17
19
|
'providerWarmupTimer',
|
|
@@ -118,6 +120,45 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
|
|
|
118
120
|
} catch {}
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
// Agent closes that have not settled yet (one per close invocation, kept
|
|
124
|
+
// past the bounded wait if it overran).
|
|
125
|
+
const outstandingCloses = new Set();
|
|
126
|
+
|
|
127
|
+
/** Persist every queued index write. A close only ever drains: the shared
|
|
128
|
+
* indexes stay registered (exit hook included) for the closes still to come. */
|
|
129
|
+
async function drainIndexWrites() {
|
|
130
|
+
try {
|
|
131
|
+
await agentTool.flushIndexWrites?.();
|
|
132
|
+
await flushAllIndexWrites();
|
|
133
|
+
} catch {}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// The disposal in progress (if any). New closes wait for it before starting
|
|
137
|
+
// their own closeAll, so no close produces writes while registrations are
|
|
138
|
+
// being released.
|
|
139
|
+
let indexDisposal = null;
|
|
140
|
+
|
|
141
|
+
/** Release this runtime's per-runtime index registrations (exit callbacks,
|
|
142
|
+
* approval writer, store refs) once its drain has completed. Idempotent. A
|
|
143
|
+
* drain that cannot complete tears nothing down: the registrations stay until
|
|
144
|
+
* a later close drains successfully. Exit flushing itself is process-owned. */
|
|
145
|
+
function disposeIndexes(settle) {
|
|
146
|
+
// Assign before disposal runs (deferred), clear on settlement: a synchronous
|
|
147
|
+
// dispose must not clear the slot before it is assigned.
|
|
148
|
+
indexDisposal ??= Promise.resolve()
|
|
149
|
+
.then(async () => {
|
|
150
|
+
if (typeof agentTool.disposeAsync === 'function') await agentTool.disposeAsync({ settle });
|
|
151
|
+
else agentTool.dispose?.({ settle });
|
|
152
|
+
})
|
|
153
|
+
.catch(() => {
|
|
154
|
+
/* drain failed: registrations are kept for a later retry */
|
|
155
|
+
})
|
|
156
|
+
.finally(() => {
|
|
157
|
+
indexDisposal = null;
|
|
158
|
+
});
|
|
159
|
+
return indexDisposal;
|
|
160
|
+
}
|
|
161
|
+
|
|
121
162
|
async function close(reason = 'cli-exit', options = {}) {
|
|
122
163
|
quiesce(reason);
|
|
123
164
|
const scope = teardownScope(reason, options, String(getSession()?.id || ''));
|
|
@@ -160,16 +201,40 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
|
|
|
160
201
|
// memory and must leave workers/rows for the re-materialized owner.
|
|
161
202
|
// Scoped teardown closes only THIS session's workers — the worker index
|
|
162
203
|
// is shared across every Lead in the process.
|
|
204
|
+
let closing = null;
|
|
205
|
+
while (indexDisposal) await indexDisposal;
|
|
163
206
|
if (scope.teardownReapsWork) {
|
|
207
|
+
// Every close runs its OWN scope's closeAll: a scoped close for one Lead
|
|
208
|
+
// never stands in for a process-wide close. Closing produces final index
|
|
209
|
+
// writes (settled rows, tombstones); the deadline only bounds how long
|
|
210
|
+
// teardown waits and does not stop the close.
|
|
211
|
+
const settled = () => {
|
|
212
|
+
outstandingCloses.delete(closing);
|
|
213
|
+
};
|
|
214
|
+
closing = new Promise((resolve) =>
|
|
215
|
+
resolve(agentTool.closeAll(reason, scope.scopedTeardown ? { callerSessionId: scope.closingSessionId } : {}))
|
|
216
|
+
).then(settled, settled);
|
|
217
|
+
outstandingCloses.add(closing);
|
|
164
218
|
try {
|
|
165
|
-
|
|
219
|
+
await withTeardownDeadline(closing, CLOSE_ALL_DEADLINE_MS, false);
|
|
166
220
|
} catch {}
|
|
167
221
|
}
|
|
168
|
-
//
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
222
|
+
// Drain after the closes settle, then release this runtime's index
|
|
223
|
+
// registrations. A close that overran its deadline chains this onto its
|
|
224
|
+
// settlement (teardown may return before then). The live outstanding set is
|
|
225
|
+
// re-checked after every wait and drain, so the single disposal runs only
|
|
226
|
+
// when no close is outstanding; the check and the disposal start share one
|
|
227
|
+
// tick, and closes admitted afterwards wait for it.
|
|
228
|
+
const finish = async () => {
|
|
229
|
+
for (;;) {
|
|
230
|
+
while (outstandingCloses.size > 0) await Promise.allSettled([...outstandingCloses]);
|
|
231
|
+
await drainIndexWrites();
|
|
232
|
+
if (outstandingCloses.size === 0) break;
|
|
233
|
+
}
|
|
234
|
+
await disposeIndexes(scope.teardownReapsWork === true);
|
|
235
|
+
};
|
|
236
|
+
if (outstandingCloses.size > 0) void finish();
|
|
237
|
+
else await finish();
|
|
173
238
|
const { ok, stops } = await inOwnLoopTurn(() => {
|
|
174
239
|
const runtimeStops = startRuntimeStops(deps, reason, scope);
|
|
175
240
|
const closed = closeOwnSession(deps, closeSurfaceSession, reason);
|
|
@@ -209,19 +209,31 @@ export function createMcpConnect({
|
|
|
209
209
|
budgetMs = Math.min(budgetMs, requestedMaxWaitMs);
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
-
// Swallow the in-flight rejection: failures are already captured in
|
|
213
|
-
// state.mcpFailures, and this gate must never reject the turn.
|
|
214
|
-
const settled = Promise.resolve(inFlight).catch(() => {});
|
|
215
212
|
// Budget disabled (0/off) = no per-server startup timeout, so the connect
|
|
216
213
|
// promise may never settle; never gate the turn on it — fall back to the
|
|
217
214
|
// legacy fire-and-forget behavior (late servers use the deferred path).
|
|
218
215
|
if (!(budgetMs > 0)) return;
|
|
219
216
|
let timer = null;
|
|
217
|
+
let expired = false;
|
|
220
218
|
const budget = new Promise((resolveBudget) => {
|
|
221
|
-
timer = setTimeout(
|
|
219
|
+
timer = setTimeout(() => {
|
|
220
|
+
expired = true;
|
|
221
|
+
resolveBudget();
|
|
222
|
+
}, budgetMs);
|
|
222
223
|
});
|
|
223
224
|
try {
|
|
224
|
-
|
|
225
|
+
// Follow replacement connects (a reconnect queued behind the captured
|
|
226
|
+
// run installs a new in-flight promise) inside ONE fixed deadline.
|
|
227
|
+
// Failures are already captured in state.mcpFailures, so rejections are
|
|
228
|
+
// swallowed: this gate must never reject the turn.
|
|
229
|
+
let current = inFlight;
|
|
230
|
+
while (current && !expired) {
|
|
231
|
+
await Promise.race([Promise.resolve(current).catch(() => {}), budget]);
|
|
232
|
+
if (expired) break;
|
|
233
|
+
// Let a queued reconnect install its promise before re-checking.
|
|
234
|
+
await Promise.race([new Promise((resolveTick) => setImmediate(resolveTick)), budget]);
|
|
235
|
+
current = state.mcpConnectInFlight;
|
|
236
|
+
}
|
|
225
237
|
} finally {
|
|
226
238
|
if (timer) clearTimeout(timer);
|
|
227
239
|
}
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
sessionRouteCommitted,
|
|
21
21
|
shouldRecreateEmptySessionForRouteChange,
|
|
22
22
|
} from '../../runtime/agent/orchestrator/runtime-core/session-route-policy.mjs';
|
|
23
|
-
import {
|
|
23
|
+
import { rebuildToolSurfaceForProviderWithMigration } from '../../runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs';
|
|
24
24
|
|
|
25
25
|
/** The request, completed from the live route where the caller left gaps. */
|
|
26
26
|
function completeRequest(deps, next) {
|
|
@@ -114,7 +114,7 @@ function updateSessionInPlace(deps, session, updateOptions) {
|
|
|
114
114
|
const updated = mgr.updateSessionRoute?.(session.id, fields, updateOptions);
|
|
115
115
|
if (updated) setSession(updated);
|
|
116
116
|
else Object.assign(session, fields);
|
|
117
|
-
|
|
117
|
+
rebuildToolSurfaceForProviderWithMigration(getSession(), route.provider);
|
|
118
118
|
writeStatuslineRoute(statusRoutes, getSession(), route);
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Per-session sink for usage spent by native web-search sends. The search runs
|
|
2
|
+
// as its own provider send under a derived session id, so the main stream
|
|
3
|
+
// never reports it; a turn's caller opts in with `onNativeWebSearchUsage` and
|
|
4
|
+
// receives the same delta shape `onUsageDelta` carries.
|
|
5
|
+
//
|
|
6
|
+
// Keyed by the owning session id, not async-local state: tools can execute
|
|
7
|
+
// from stream callbacks whose async context belongs to a pooled transport
|
|
8
|
+
// connection, not to the ask that is waiting on them.
|
|
9
|
+
//
|
|
10
|
+
// Each registration is its own entry that only its own release removes, so
|
|
11
|
+
// overlapping turns on one session id never restore or drop each other. The
|
|
12
|
+
// session lock serializes turns, so the most recent live entry belongs to the
|
|
13
|
+
// turn that is running; callers register once their turn owns the session.
|
|
14
|
+
import { usageDeltaEvent } from '../runtime/agent/orchestrator/session/loop/usage.mjs';
|
|
15
|
+
|
|
16
|
+
const entriesBySession = new Map();
|
|
17
|
+
|
|
18
|
+
/** Adds an owned sink entry for `sessionId`; the returned release removes exactly that entry. */
|
|
19
|
+
export function registerNativeWebSearchUsageSink(sessionId, sink) {
|
|
20
|
+
if (typeof sink !== 'function' || !sessionId) return () => {};
|
|
21
|
+
const entry = { sink };
|
|
22
|
+
let entries = entriesBySession.get(sessionId);
|
|
23
|
+
if (!entries) {
|
|
24
|
+
entries = [];
|
|
25
|
+
entriesBySession.set(sessionId, entries);
|
|
26
|
+
}
|
|
27
|
+
entries.push(entry);
|
|
28
|
+
return () => {
|
|
29
|
+
const live = entriesBySession.get(sessionId);
|
|
30
|
+
const index = live ? live.indexOf(entry) : -1;
|
|
31
|
+
if (index === -1) return;
|
|
32
|
+
live.splice(index, 1);
|
|
33
|
+
if (live.length === 0) entriesBySession.delete(sessionId);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function reportNativeWebSearchUsage({ ownerSessionId, sessionId, requestedModel, model, usage }) {
|
|
38
|
+
const entries = entriesBySession.get(ownerSessionId);
|
|
39
|
+
const sink = entries?.[entries.length - 1]?.sink;
|
|
40
|
+
if (!sink || !usage) return;
|
|
41
|
+
try {
|
|
42
|
+
const pending = sink({
|
|
43
|
+
...usageDeltaEvent({ sessionId, iterationIndex: 0, requestedModel, model, usage }),
|
|
44
|
+
source: 'native_web_search',
|
|
45
|
+
agentRole: 'web-search',
|
|
46
|
+
});
|
|
47
|
+
if (typeof pending?.then === 'function') pending.then(undefined, () => {});
|
|
48
|
+
} catch {
|
|
49
|
+
/* telemetry must never fail the search */
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
normalizeWebSearchAllowedDomain,
|
|
14
14
|
} from './native-web-search/tool-shape.mjs';
|
|
15
15
|
import { createWebSearchRouteCandidates } from './native-web-search/routes.mjs';
|
|
16
|
+
import { reportNativeWebSearchUsage } from './native-web-search-usage.mjs';
|
|
16
17
|
|
|
17
18
|
export function createNativeWebSearch(deps) {
|
|
18
19
|
const {
|
|
@@ -58,10 +59,11 @@ export function createNativeWebSearch(deps) {
|
|
|
58
59
|
}
|
|
59
60
|
const family = webSearchProviderFamily(candidate.provider);
|
|
60
61
|
const startedAt = Date.now();
|
|
62
|
+
const sendSessionId = `${getSession()?.id || 'web_search'}:native-web-search:${Date.now().toString(36)}`;
|
|
61
63
|
const result = await providerImpl.send(nativeWebSearchMessages(webSearchArgs), candidate.model, undefined, {
|
|
62
64
|
signal,
|
|
63
65
|
role: 'web-search',
|
|
64
|
-
sessionId:
|
|
66
|
+
sessionId: sendSessionId,
|
|
65
67
|
sourceType: 'native-web-search',
|
|
66
68
|
sourceName: 'web_search',
|
|
67
69
|
nativeTools: [toolFor(webSearchArgs, toolType, candidate.provider)],
|
|
@@ -73,6 +75,13 @@ export function createNativeWebSearch(deps) {
|
|
|
73
75
|
onStageChange: () => {},
|
|
74
76
|
onStreamDelta: () => {},
|
|
75
77
|
});
|
|
78
|
+
reportNativeWebSearchUsage({
|
|
79
|
+
ownerSessionId: getSession()?.id,
|
|
80
|
+
sessionId: sendSessionId,
|
|
81
|
+
requestedModel: candidate.model,
|
|
82
|
+
model: result?.model || candidate.model,
|
|
83
|
+
usage: result?.usage,
|
|
84
|
+
});
|
|
76
85
|
return {
|
|
77
86
|
content: String(result?.content || '').trim(),
|
|
78
87
|
provider: candidate.provider,
|
|
@@ -12,7 +12,6 @@ export function createNewSessionConfig({
|
|
|
12
12
|
initialRouteExplicit = false,
|
|
13
13
|
invalidatePreSessionToolSurface,
|
|
14
14
|
invalidateOutputStyleStatusCache,
|
|
15
|
-
invalidateSkills,
|
|
16
15
|
connectConfiguredMcp,
|
|
17
16
|
configureEmbedding,
|
|
18
17
|
}) {
|
|
@@ -33,7 +32,10 @@ export function createNewSessionConfig({
|
|
|
33
32
|
}
|
|
34
33
|
invalidateOutputStyleStatusCache();
|
|
35
34
|
invalidatePreSessionToolSurface();
|
|
36
|
-
|
|
35
|
+
// The installed-skill list is NOT dropped here: its cache is change-gated
|
|
36
|
+
// (every skill root's mtime signature, kept by change watchers), so a new
|
|
37
|
+
// session already sees any skill edit. Clearing it made every session
|
|
38
|
+
// creation re-read and re-parse every SKILL.md on the event loop.
|
|
37
39
|
await configureEmbedding(sharedCfgMod.readSection('memory')?.embedding || {});
|
|
38
40
|
if (!firstSession || !isDeepStrictEqual(previousMcp, mcpSettings())) {
|
|
39
41
|
// Reused runtimes may still own old connections. This reset is scoped to
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
removeCustomProvider,
|
|
13
13
|
updateCustomProviderModel,
|
|
14
14
|
testCustomProvider,
|
|
15
|
+
checkCustomProviderKeyEnv,
|
|
15
16
|
discoverCustomProviderModels,
|
|
16
17
|
} from '../services/provider-admin.mjs';
|
|
17
18
|
|
|
@@ -96,6 +97,9 @@ export function createLoginApi({ cfgMod, awaitKeychainPrewarm, reloadFullConfig,
|
|
|
96
97
|
await awaitKeychainPrewarm();
|
|
97
98
|
return await testCustomProvider(cfgMod, input);
|
|
98
99
|
},
|
|
100
|
+
checkCustomProviderKeyEnv(name) {
|
|
101
|
+
return checkCustomProviderKeyEnv(name);
|
|
102
|
+
},
|
|
99
103
|
async discoverCustomProviderModels(input) {
|
|
100
104
|
await awaitKeychainPrewarm();
|
|
101
105
|
return await discoverCustomProviderModels(cfgMod, input);
|
|
@@ -14,8 +14,13 @@ function listOf(status, key) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function createScopeDecorators({ getConfig, getCurrentCwd }) {
|
|
17
|
-
function scopeInfo(
|
|
18
|
-
|
|
17
|
+
function scopeInfo(
|
|
18
|
+
kind,
|
|
19
|
+
name,
|
|
20
|
+
pluginId = '',
|
|
21
|
+
cwd = getCurrentCwd(),
|
|
22
|
+
scopes = extensionScopesFromConfig(getConfig())
|
|
23
|
+
) {
|
|
19
24
|
const scope = extensionScopeProjects(scopes, kind, name);
|
|
20
25
|
const inheritedScope = pluginId ? extensionScopeProjects(scopes, 'plugins', pluginId) : null;
|
|
21
26
|
const activeHere =
|
|
@@ -35,11 +40,13 @@ export function createScopeDecorators({ getConfig, getCurrentCwd }) {
|
|
|
35
40
|
},
|
|
36
41
|
/** `cwd`: decide `activeHere` for that folder instead of the current one. */
|
|
37
42
|
skills(status, cwd = getCurrentCwd()) {
|
|
43
|
+
// One scope read for the whole list, not one per skill.
|
|
44
|
+
const scopes = extensionScopesFromConfig(getConfig());
|
|
38
45
|
return {
|
|
39
46
|
...status,
|
|
40
47
|
skills: listOf(status, 'skills').map((skill) => ({
|
|
41
48
|
...skill,
|
|
42
|
-
...scopeInfo('skills', skill.name, skill?.owner?.kind === 'plugin' ? clean(skill.owner.id) : '', cwd),
|
|
49
|
+
...scopeInfo('skills', skill.name, skill?.owner?.kind === 'plugin' ? clean(skill.owner.id) : '', cwd, scopes),
|
|
43
50
|
})),
|
|
44
51
|
};
|
|
45
52
|
},
|
|
@@ -3,8 +3,10 @@ import { turnReviewReply } from '../runtime/shared/turn-review-reply.mjs';
|
|
|
3
3
|
import {
|
|
4
4
|
clearSessionChangeHistory,
|
|
5
5
|
getSessionReviewDiff,
|
|
6
|
+
getSessionReviewFilePatch,
|
|
6
7
|
getTurnChanges,
|
|
7
8
|
getTurnReviewDiff,
|
|
9
|
+
getTurnReviewFilePatch,
|
|
8
10
|
reapplyTurnChanges,
|
|
9
11
|
revertTurnChanges,
|
|
10
12
|
revertTurnReview,
|
|
@@ -24,8 +26,9 @@ registerSessionPurgeHook((sessionId) => {
|
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
// Tool writes (apply_patch, mutating shell commands, git, watcher events)
|
|
27
|
-
// reach the
|
|
28
|
-
// after them captures the worktree, an unsignaled
|
|
29
|
+
// reach the turn's worktree snapshot as its change signal: a session review
|
|
30
|
+
// read right after them captures the worktree, an unsignaled one may reuse
|
|
31
|
+
// the last capture.
|
|
29
32
|
registerCacheInvalidationListener((paths) => noteTurnWorktreeChange(paths));
|
|
30
33
|
|
|
31
34
|
export function createRuntimeReviewApi({ getCwd, getSessionId }) {
|
|
@@ -35,6 +38,9 @@ export function createRuntimeReviewApi({ getCwd, getSessionId }) {
|
|
|
35
38
|
getTurnReviewDiff: (options = {}) =>
|
|
36
39
|
turnReviewReply((reviewOptions) => getTurnReviewDiff(getCwd(), getSessionId(), reviewOptions), options),
|
|
37
40
|
getSessionReviewDiff: () => getSessionReviewDiff(getCwd(), getSessionId()),
|
|
41
|
+
// One listed file's whole patch (a reply lists a large one `patchOmitted`).
|
|
42
|
+
getSessionReviewFilePatch: (file, oldPath) => getSessionReviewFilePatch(getCwd(), getSessionId(), file, oldPath),
|
|
43
|
+
getTurnReviewFilePatch: (file) => getTurnReviewFilePatch(getCwd(), getSessionId(), file),
|
|
38
44
|
revertTurnReview: (checkpointId) => revertTurnReview(getCwd(), getSessionId(), checkpointId),
|
|
39
45
|
revertTurnReviewFile: (file, checkpointId) => revertTurnReviewFile(getCwd(), getSessionId(), file, checkpointId),
|
|
40
46
|
// Historical per-turn changes, addressed by checkpointId (TurnChangesReply).
|
|
@@ -20,6 +20,7 @@ import { registerJsonProjection } from '../../../runtime/shared/pending-json-pro
|
|
|
20
20
|
import { sleep } from '../../../runtime/shared/sleep.mjs';
|
|
21
21
|
|
|
22
22
|
const RETRY_DELAYS_MS = [50, 250, 1000];
|
|
23
|
+
const RETRY_AFTER_FAILURE_MS = 15_000;
|
|
23
24
|
const unsettled = new Set(); // queues holding unpersisted writes
|
|
24
25
|
// Exit is the one place a bounded synchronous lock wait is acceptable: the
|
|
25
26
|
// loop is gone, and a dropped settlement would leave rows "running" forever.
|
|
@@ -122,8 +123,15 @@ function replayBatch(batch, args, mergeSet) {
|
|
|
122
123
|
replayRun();
|
|
123
124
|
}
|
|
124
125
|
|
|
126
|
+
// A write that cannot reach disk loses a state change other processes rely on
|
|
127
|
+
// (e.g. a deleted Lead row that never leaves the pool), so every failure is
|
|
128
|
+
// reported. In the daemon stderr IS daemon.log (daemon-log.mjs installRedirect).
|
|
125
129
|
function reportFailure(file, what, error) {
|
|
126
|
-
|
|
130
|
+
try {
|
|
131
|
+
process.stderr.write(`[index-write] ${file}: ${what}: ${error?.message || error}\n`);
|
|
132
|
+
} catch {
|
|
133
|
+
/* logging is best effort */
|
|
134
|
+
}
|
|
127
135
|
}
|
|
128
136
|
|
|
129
137
|
/**
|
|
@@ -151,9 +159,15 @@ export function createIndexWriteQueue({
|
|
|
151
159
|
let pending = []; // op sets not yet handed to a job
|
|
152
160
|
let inflight = []; // op sets of the running job
|
|
153
161
|
let running = null;
|
|
162
|
+
const failures = new WeakMap(); // settled job → the error that failed it
|
|
154
163
|
let timer = null;
|
|
164
|
+
let retryTimer = null;
|
|
155
165
|
|
|
156
166
|
function clearTimer() {
|
|
167
|
+
if (retryTimer) {
|
|
168
|
+
clearTimeout(retryTimer);
|
|
169
|
+
retryTimer = null;
|
|
170
|
+
}
|
|
157
171
|
if (!timer) return;
|
|
158
172
|
clearImmediate(timer);
|
|
159
173
|
timer = null;
|
|
@@ -173,8 +187,8 @@ export function createIndexWriteQueue({
|
|
|
173
187
|
return;
|
|
174
188
|
} catch (error) {
|
|
175
189
|
if (attempt >= RETRY_DELAYS_MS.length) {
|
|
176
|
-
reportFailure(file,
|
|
177
|
-
|
|
190
|
+
reportFailure(file, `${batch.length} unpersisted write(s) kept queued after retries`, error);
|
|
191
|
+
throw error;
|
|
178
192
|
}
|
|
179
193
|
await sleep(RETRY_DELAYS_MS[attempt]);
|
|
180
194
|
}
|
|
@@ -187,23 +201,45 @@ export function createIndexWriteQueue({
|
|
|
187
201
|
inflight = pending;
|
|
188
202
|
pending = [];
|
|
189
203
|
const batch = inflight;
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
204
|
+
const job = persist(batch).then(
|
|
205
|
+
() => {
|
|
206
|
+
inflight = [];
|
|
207
|
+
running = null;
|
|
208
|
+
onPersisted();
|
|
209
|
+
if (pending.length === 0) {
|
|
210
|
+
projection = null;
|
|
211
|
+
unsettled.delete(self);
|
|
212
|
+
}
|
|
213
|
+
schedule();
|
|
214
|
+
},
|
|
215
|
+
(error) => {
|
|
216
|
+
// Persistent failure: nothing reached disk. Requeue the batch ahead of
|
|
217
|
+
// newer writes (the projection and `unsettled` keep covering it) so a
|
|
218
|
+
// later flush, write or exit flush retries. Do not reschedule at once,
|
|
219
|
+
// a held foreign lock would otherwise be hammered; a slow unref'd retry
|
|
220
|
+
// keeps a failed LAST write (a delete) from waiting for unrelated traffic.
|
|
221
|
+
failures.set(job, error);
|
|
222
|
+
pending = [...batch, ...pending];
|
|
223
|
+
inflight = [];
|
|
224
|
+
running = null;
|
|
225
|
+
retryTimer = setTimeout(() => {
|
|
226
|
+
retryTimer = null;
|
|
227
|
+
schedule();
|
|
228
|
+
}, RETRY_AFTER_FAILURE_MS);
|
|
229
|
+
retryTimer.unref?.();
|
|
197
230
|
}
|
|
198
|
-
|
|
199
|
-
|
|
231
|
+
);
|
|
232
|
+
running = job;
|
|
200
233
|
}
|
|
201
234
|
|
|
202
|
-
/** Resolves once everything written so far is on disk
|
|
235
|
+
/** Resolves once everything written so far is on disk; rejects when a persist
|
|
236
|
+
* failed for good (the writes stay queued for a later flush). */
|
|
203
237
|
async function flush() {
|
|
204
238
|
for (;;) {
|
|
205
239
|
if (running) {
|
|
206
|
-
|
|
240
|
+
const job = running;
|
|
241
|
+
await job;
|
|
242
|
+
if (failures.has(job)) throw failures.get(job);
|
|
207
243
|
continue;
|
|
208
244
|
}
|
|
209
245
|
if (pending.length === 0) return;
|
|
@@ -212,10 +248,16 @@ export function createIndexWriteQueue({
|
|
|
212
248
|
}
|
|
213
249
|
}
|
|
214
250
|
|
|
215
|
-
/**
|
|
251
|
+
/** Persist pending ops synchronously (bounded lock wait). While an async job
|
|
252
|
+
* runs it owns the lock (and its ops are in flight): never wait on it, take
|
|
253
|
+
* over its lock, or replay its ops — report false and let that job and its
|
|
254
|
+
* follow-ups drain. At the last-resort process 'exit' hook that is
|
|
255
|
+
* best-effort: the graceful shutdown path drains before exit. */
|
|
216
256
|
function flushSync() {
|
|
217
|
-
|
|
218
|
-
if (
|
|
257
|
+
if (!file) return true;
|
|
258
|
+
if (running) return false;
|
|
259
|
+
const ops = pending;
|
|
260
|
+
if (ops.length === 0) return true;
|
|
219
261
|
clearTimer();
|
|
220
262
|
pending = [];
|
|
221
263
|
try {
|
|
@@ -225,10 +267,10 @@ export function createIndexWriteQueue({
|
|
|
225
267
|
});
|
|
226
268
|
} catch (error) {
|
|
227
269
|
reportFailure(file, `synchronous flush of ${ops.length} write(s) failed; kept queued`, error);
|
|
228
|
-
pending = ops;
|
|
270
|
+
pending = [...ops, ...pending];
|
|
271
|
+
schedule();
|
|
229
272
|
return false;
|
|
230
273
|
}
|
|
231
|
-
inflight = [];
|
|
232
274
|
projection = null;
|
|
233
275
|
unsettled.delete(self);
|
|
234
276
|
onPersisted();
|
|
@@ -251,9 +293,11 @@ export function createIndexWriteQueue({
|
|
|
251
293
|
version += 1;
|
|
252
294
|
pending.push(rerun ? mutator : ops);
|
|
253
295
|
unsettled.add(self);
|
|
296
|
+
installProcessExitFlush();
|
|
254
297
|
schedule();
|
|
255
298
|
return next;
|
|
256
|
-
} catch {
|
|
299
|
+
} catch (error) {
|
|
300
|
+
reportFailure(file, 'write rejected (mutator or document rewrite threw); nothing queued', error);
|
|
257
301
|
return null;
|
|
258
302
|
}
|
|
259
303
|
},
|
|
@@ -266,6 +310,23 @@ export function createIndexWriteQueue({
|
|
|
266
310
|
};
|
|
267
311
|
}
|
|
268
312
|
|
|
313
|
+
let processExitFlushInstalled = false;
|
|
314
|
+
|
|
315
|
+
/** The process owns last-resort exit flushing of every queue holding unpersisted
|
|
316
|
+
* writes, so a disposed (e.g. evicted) runtime needs no exit callback of its
|
|
317
|
+
* own. Best effort: a persist still running is left to the graceful drain. */
|
|
318
|
+
function installProcessExitFlush() {
|
|
319
|
+
if (processExitFlushInstalled) return;
|
|
320
|
+
processExitFlushInstalled = true;
|
|
321
|
+
process.on('exit', () => {
|
|
322
|
+
try {
|
|
323
|
+
flushAllIndexWritesSync();
|
|
324
|
+
} catch {
|
|
325
|
+
/* exit flush is best effort */
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
269
330
|
/** Synchronous variant (exit paths, tests that read the file directly). */
|
|
270
331
|
export function flushAllIndexWritesSync() {
|
|
271
332
|
for (const queue of [...unsettled]) queue.flushSync();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Ids of deleted Leads, shared by every lead-index instance of the process that
|
|
2
|
+
// uses one data dir. The delete runs in the control runtime while the deleted
|
|
3
|
+
// session's own (still loaded) runtime keeps settling turns through ITS index
|
|
4
|
+
// instance; a per-instance set never sees the delete, so that late idle upsert
|
|
5
|
+
// wrote the row back. The store's write fence (explicit deletes) is consulted
|
|
6
|
+
// as well, so a fenced id can never be added whichever instance asks.
|
|
7
|
+
import { resolve } from 'node:path';
|
|
8
|
+
import { isSessionWriteFenced } from '../../../../runtime/agent/orchestrator/session/store/live-state.mjs';
|
|
9
|
+
|
|
10
|
+
const FORGOTTEN_LEADS_MAX = 1024;
|
|
11
|
+
const registries = new Map(); // resolved data dir -> Set<sessionId>
|
|
12
|
+
|
|
13
|
+
export function createForgottenLeads(dataDir) {
|
|
14
|
+
const key = dataDir ? resolve(dataDir) : '';
|
|
15
|
+
let ids = registries.get(key);
|
|
16
|
+
if (!ids) {
|
|
17
|
+
ids = new Set();
|
|
18
|
+
registries.set(key, ids);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
/** A deleted Lead must never be written to the index again. */
|
|
22
|
+
forget(sessionId) {
|
|
23
|
+
ids.delete(sessionId);
|
|
24
|
+
ids.add(sessionId);
|
|
25
|
+
if (ids.size > FORGOTTEN_LEADS_MAX) ids.delete(ids.values().next().value);
|
|
26
|
+
},
|
|
27
|
+
isForgotten: (sessionId) => ids.has(sessionId) || isSessionWriteFenced(sessionId),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -42,7 +42,7 @@ export function createLeadIndexFile({ dataDir }) {
|
|
|
42
42
|
return parsed ? normalizeLeadRows(parsed) : [];
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const write = (mutator) => queue.write(mutator);
|
|
45
|
+
const write = (mutator, options) => queue.write(mutator, options);
|
|
46
46
|
|
|
47
47
|
return { path, read, write, flush: queue.flush, flushSync: queue.flushSync };
|
|
48
48
|
}
|