mixdog 1.2.3 → 1.2.5
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 +1 -1
- package/scripts/gate-local.mjs +6 -4
- package/scripts/lib/gate-scheduler.mjs +29 -11
- package/scripts/mobile-release.mjs +5 -4
- package/scripts/probe-provider-catalog.mjs +31 -0
- package/scripts/provider-pingpong-live.mjs +128 -38
- package/scripts/session-sweep.mjs +5 -25
- package/src/agents/maintainer/AGENT.md +1 -1
- package/src/agents/maintainer/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +2 -4
- package/src/agents/security/AGENT.md +1 -2
- package/src/agents/writer/AGENT.md +2 -3
- package/src/defaults/shipped-history.json +7 -1
- package/src/defaults/skills/image/SKILL.md +21 -23
- package/src/lib/keychain-cjs.cjs +13 -11
- package/src/output-styles/common.md +2 -1
- package/src/rules/agent/AGENT.md +7 -5
- package/src/rules/lead/LEAD.md +13 -13
- package/src/rules/shared/45-destructive.md +4 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2 -5
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +81 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +41 -11
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -11
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -4
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -27
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +21 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
- package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
- package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +29 -8
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +32 -14
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
- package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
- package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
- package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +5 -11
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -32
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +160 -212
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
- package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +7 -8
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
- package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +204 -10
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
- package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
- package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +200 -17
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
- package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
- package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
- package/src/runtime/attachments/store.d.mts +9 -0
- package/src/runtime/attachments/store.mjs +80 -9
- package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
- package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
- package/src/runtime/computer-bridge/action-schema.mjs +178 -178
- package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
- package/src/runtime/effort-judge/judge-client.mjs +21 -4
- package/src/runtime/effort-judge/judge-worker.mjs +4 -1
- package/src/runtime/github/tool.mjs +118 -17
- package/src/runtime/media/adapters/codex-image.mjs +140 -21
- package/src/runtime/media/catalog.mjs +4 -4
- package/src/runtime/media/chatgpt-usage.mjs +55 -0
- package/src/runtime/media/defaults.mjs +37 -0
- package/src/runtime/media/jobs.mjs +12 -2
- package/src/runtime/media/lanes.mjs +12 -0
- package/src/runtime/media/tool-defs.mjs +15 -4
- package/src/runtime/media/tool.mjs +41 -12
- package/src/runtime/media/upstream-error.mjs +72 -6
- package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
- package/src/runtime/memory/lib/pg/process.mjs +5 -7
- package/src/runtime/memory/lib/pg/supervisor.mjs +4 -1
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/html-browser.mjs +18 -8
- package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
- package/src/runtime/office/core/office-write-ledger.mjs +1 -5
- package/src/runtime/office/index.mjs +2 -3
- package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
- package/src/runtime/session-search/session-search-ingest.mjs +1 -1
- package/src/runtime/shared/agent-reap-state.mjs +13 -0
- package/src/runtime/shared/atomic-file.d.mts +1 -1
- package/src/runtime/shared/background-tasks.mjs +6 -1
- package/src/runtime/shared/bounded-line-diff.mjs +11 -2
- package/src/runtime/shared/browser-launch.mjs +15 -0
- package/src/runtime/shared/err-text.mjs +42 -4
- package/src/runtime/shared/file-lock.mjs +6 -5
- package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
- package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
- package/src/runtime/shared/model-route-chain.d.mts +8 -0
- package/src/runtime/shared/model-route-chain.mjs +48 -0
- package/src/runtime/shared/model-route-fallback.mjs +22 -0
- package/src/runtime/shared/pid-liveness.mjs +12 -0
- package/src/runtime/shared/provider-api-key.mjs +6 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
- package/src/runtime/shared/quiet-progress.d.mts +35 -0
- package/src/runtime/shared/quiet-progress.mjs +101 -0
- package/src/runtime/shared/quota-resume-store.mjs +32 -1
- package/src/runtime/shared/read-row-numbers.mjs +44 -0
- package/src/runtime/shared/remote-intent.mjs +2 -42
- package/src/runtime/shared/slow-span.mjs +8 -1
- package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
- package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
- package/src/runtime/shared/tool-output-budget.mjs +2 -0
- package/src/runtime/shared/tool-result-summary.mjs +16 -2
- package/src/runtime/shared/tool-status.mjs +3 -2
- package/src/runtime/shared/tool-surface.mjs +2 -3
- package/src/runtime/shared/tool-work-units.mjs +22 -15
- package/src/runtime/shared/transcript-metadata.mjs +49 -1
- package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
- package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
- package/src/runtime/shared/transcript-writer.mjs +14 -4
- package/src/runtime/shared/turn-changes.mjs +2 -1
- package/src/runtime/shared/turn-snapshot.mjs +11 -3
- package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
- package/src/runtime/shared/worktrees/carry.mjs +6 -4
- package/src/runtime/shared/worktrees/contract.mjs +27 -1
- package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
- package/src/runtime/shared/worktrees/git-head.mjs +22 -13
- package/src/runtime/shared/worktrees/include.mjs +125 -7
- package/src/runtime/shared/worktrees/lock.mjs +1 -1
- package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
- package/src/runtime/shared/worktrees/manager.mjs +378 -32
- package/src/runtime/shared/worktrees/owner.mjs +2 -1
- package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
- package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
- package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
- package/src/runtime/terminal-bridge/client.mjs +14 -10
- package/src/session-runtime/boot/apis.mjs +7 -1
- package/src/session-runtime/boot/config.mjs +2 -0
- package/src/session-runtime/boot/facade.mjs +3 -0
- package/src/session-runtime/boot/session.mjs +3 -2
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/conversation-import/service.mjs +1 -1
- package/src/session-runtime/goal-facade-api.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
- package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
- package/src/session-runtime/lifecycle/shared.mjs +5 -6
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
- package/src/session-runtime/lifecycle/teardown.mjs +7 -16
- package/src/session-runtime/media-api.mjs +8 -0
- package/src/session-runtime/model-route/route-ownership.mjs +60 -0
- package/src/session-runtime/model-route/route-persist.mjs +3 -2
- package/src/session-runtime/model-route/set-route.mjs +114 -34
- package/src/session-runtime/model-route/web-search-route.mjs +7 -2
- package/src/session-runtime/model-route-api.mjs +4 -2
- package/src/session-runtime/native-web-search/routes.mjs +37 -24
- package/src/session-runtime/native-web-search.mjs +9 -8
- package/src/session-runtime/provider-auth/setup.mjs +4 -0
- package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
- package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
- package/src/session-runtime/provider-models.mjs +1 -0
- package/src/session-runtime/provider-usage.mjs +4 -0
- package/src/session-runtime/route-resolution.mjs +3 -1
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/runtime-facade.mjs +6 -0
- package/src/session-runtime/services/agent-task-status.mjs +2 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
- package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
- package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
- package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
- package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
- package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +9 -6
- package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
- package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -9
- package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
- package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
- package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
- package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +28 -8
- package/src/session-runtime/services/agent-tool.mjs +4 -0
- package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
- package/src/session-runtime/services/provider-admin.mjs +77 -0
- package/src/session-runtime/session-create/session-options.mjs +7 -5
- package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
- package/src/session-runtime/session-transcript.mjs +4 -5
- package/src/session-runtime/session-turn-api.mjs +3 -9
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
- package/src/session-runtime/setup-tool/executor.mjs +23 -5
- package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
- package/src/session-runtime/tool-policy-refresh.mjs +83 -32
- package/src/session-runtime/turn/agent-ops.mjs +49 -2
- package/src/session-runtime/turn/side-question-ops.mjs +1 -4
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
- package/src/session-runtime/turn/turn-run.mjs +1 -36
- package/src/session-runtime/usage-stats-api.mjs +4 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
- package/src/session-runtime/workspace/admission-gate.mjs +44 -15
- package/src/session-runtime/workspace/project-branches.mjs +28 -36
- package/src/session-runtime/workspace/transition-steps.mjs +96 -95
- package/src/session-runtime/workspace/transitions.mjs +248 -68
- package/src/standalone/channel-transport.mjs +3 -4
- package/src/standalone/daemon-desktop-runtime.mjs +32 -1
- package/src/standalone/daemon-pg-stop.mjs +1 -3
- package/src/standalone/daemon-session-control.mjs +88 -0
- package/src/standalone/daemon-stored-session-views.mjs +23 -3
- package/src/standalone/daemon.mjs +2 -0
- package/src/standalone/desktop-service-registry.mjs +32 -5
- package/src/standalone/local-session-runtime.mjs +11 -12
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-runtime-inline-host.mjs +2 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
- package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
- package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
- package/src/standalone/session-service/agent-tree.mjs +28 -2
- package/src/standalone/session-service/entries/session-loads.mjs +16 -5
- package/src/standalone/session-service/entries.mjs +1 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
- package/src/standalone/session-service/quota-resume.mjs +28 -13
- package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
- package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
- package/src/standalone/session-tool-output.mjs +82 -0
- package/src/tui/app/app-view.jsx +2 -1
- package/src/tui/app/provider-setup/provider-items.mjs +8 -0
- package/src/tui/app/provider-setup-picker.mjs +15 -3
- package/src/tui/app/slash-commands.mjs +6 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
- package/src/tui/components/Spinner.jsx +4 -0
- package/src/tui/components/SpinnerByline.jsx +21 -2
- package/src/tui/components/status-line/local-line.mjs +10 -2
- package/src/tui/dist/index.mjs +529 -270
- package/src/tui/session/active-tool-summary.mjs +1 -1
- package/src/tui/session/context-state.mjs +0 -3
- package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
- package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
- package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
- package/src/tui/session/quota-resume.mjs +140 -61
- package/src/tui/session/session-api/commands.mjs +4 -10
- package/src/tui/session/session-api/controls.mjs +12 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
- package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
- package/src/tui/session/session-api/lifecycle.mjs +13 -11
- package/src/tui/session/session-api/media.mjs +2 -0
- package/src/tui/session/session-api/routes.mjs +81 -57
- package/src/tui/session/session-api/settings.mjs +3 -3
- package/src/tui/session/session-api/worktree.mjs +3 -2
- package/src/tui/session/session-flow/auto-clear.mjs +1 -3
- package/src/tui/session/session-flow/drain.mjs +6 -4
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
- package/src/tui/session/session-flow/queue.mjs +1 -1
- package/src/tui/session/tool-approval.mjs +17 -8
- package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
- package/src/tui/session/tui-steering-persist.mjs +3 -5
- package/src/tui/session/turn-quiet.mjs +53 -0
- package/src/tui/session/turn-stream.mjs +5 -1
- package/src/tui/session/turn.mjs +38 -31
- package/src/tui/session/worktree-setup-notice.mjs +38 -0
- package/src/tui/spinner-meta.mjs +10 -0
- package/src/tui/spinner-verbs.mjs +3 -0
- package/src/ui/statusline.mjs +13 -3
- package/src/ui/streaming-markdown-heal.mjs +70 -18
- package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
- package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -302
- package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
- package/src/session-runtime/turn/share-ops.mjs +0 -77
- package/src/tui/session/cross-surface-share.mjs +0 -406
- package/src/tui/session/live-share/delta.mjs +0 -153
- package/src/tui/session/live-share/mirror.mjs +0 -106
- package/src/tui/session/live-share/owner.mjs +0 -254
- package/src/tui/session/live-share/retry.mjs +0 -54
- package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
- package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
- package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
- package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
- package/src/tui/session/live-share/viewer.mjs +0 -99
- package/src/tui/session/live-share/wire.mjs +0 -44
- package/src/tui/session/live-share.mjs +0 -154
- package/src/tui/session/shared-dir-watch.mjs +0 -69
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/tui/session/live-share/owner.mjs - owner leg: named-pipe / unix-socket
|
|
3
|
-
* server bound to ONE session id, pushing frame-batched deltas to attached
|
|
4
|
-
* viewers and relaying their submit/abort frames into the owner queue.
|
|
5
|
-
*/
|
|
6
|
-
import { createServer } from 'node:net';
|
|
7
|
-
import { unlinkSync } from 'node:fs';
|
|
8
|
-
import { attachLineReader, destroyQuietly, frameLine } from './wire.mjs';
|
|
9
|
-
import { EMPTY_BASELINE, baselineOf, deltaFrame, fullFrame } from './delta.mjs';
|
|
10
|
-
import { createRetryTimer, reconcileLeg } from './retry.mjs';
|
|
11
|
-
|
|
12
|
-
function isSubmitFrame(frame) {
|
|
13
|
-
return (
|
|
14
|
-
frame.t === 'submit' &&
|
|
15
|
-
((typeof frame.text === 'string' && frame.text.trim()) ||
|
|
16
|
-
typeof frame.prompt === 'string' ||
|
|
17
|
-
Array.isArray(frame.prompt))
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function unlinkQuietly(path) {
|
|
22
|
-
if (process.platform === 'win32' || !path) return;
|
|
23
|
-
try {
|
|
24
|
-
unlinkSync(path);
|
|
25
|
-
} catch {
|
|
26
|
-
/* never created / already gone */
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Sockets this process still serves. A process that exits without closing its
|
|
31
|
-
// sessions (daemon shutdown, tray Quit) must not leave them behind in /tmp.
|
|
32
|
-
const servedSocketPaths = new Set();
|
|
33
|
-
let exitCleanupInstalled = false;
|
|
34
|
-
function serveSocketPath(path) {
|
|
35
|
-
if (process.platform === 'win32' || !path) return;
|
|
36
|
-
servedSocketPaths.add(path);
|
|
37
|
-
if (exitCleanupInstalled) return;
|
|
38
|
-
exitCleanupInstalled = true;
|
|
39
|
-
process.once('exit', () => {
|
|
40
|
-
for (const served of servedSocketPaths) unlinkQuietly(served);
|
|
41
|
-
servedSocketPaths.clear();
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function createOwnerLeg({
|
|
46
|
-
ownerSessionId,
|
|
47
|
-
socketPathFor,
|
|
48
|
-
getPublishedState,
|
|
49
|
-
onRemoteSubmit,
|
|
50
|
-
onRemoteAbort,
|
|
51
|
-
isDisposed,
|
|
52
|
-
retryMinMs,
|
|
53
|
-
retryMaxMs,
|
|
54
|
-
}) {
|
|
55
|
-
let server = null;
|
|
56
|
-
let serverId = '';
|
|
57
|
-
let serverPath = '';
|
|
58
|
-
const sockets = new Set();
|
|
59
|
-
let baseline = EMPTY_BASELINE;
|
|
60
|
-
const retry = createRetryTimer({
|
|
61
|
-
minMs: retryMinMs,
|
|
62
|
-
maxMs: retryMaxMs,
|
|
63
|
-
shouldStart: (id) => !isDisposed() && !server && String(ownerSessionId() || '') === id,
|
|
64
|
-
start: (id) => startServer(id),
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const broadcast = (frame) => {
|
|
68
|
-
if (sockets.size === 0) return;
|
|
69
|
-
const line = frameLine(frame);
|
|
70
|
-
for (const socket of sockets) {
|
|
71
|
-
try {
|
|
72
|
-
socket.write(line);
|
|
73
|
-
} catch {
|
|
74
|
-
/* per-socket close handles it */
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// This pipe is bound to ONE session id (serverId). When the surface changes
|
|
80
|
-
// session identity — /new, /clear, a resume of another session, a context
|
|
81
|
-
// switch — the published store frames stop describing the session this pipe
|
|
82
|
-
// represents. Pushing them anyway handed a co-open viewer an empty (or
|
|
83
|
-
// foreign) transcript until the close/promote path restored it, which is the
|
|
84
|
-
// flash seen in the desktop app when the terminal ran /new. Frames are
|
|
85
|
-
// DROPPED without re-baselining, so a pipe that keeps its id (/clear) still
|
|
86
|
-
// ships the post-reset delta once the reset settles; a pipe whose id changed
|
|
87
|
-
// is torn down by the next ensure().
|
|
88
|
-
const frameStale = () => Boolean(serverId) && String(ownerSessionId() || '') !== serverId;
|
|
89
|
-
|
|
90
|
-
// Runs on every frame-batched publish. With no viewers it only re-baselines.
|
|
91
|
-
const onPublish = () => {
|
|
92
|
-
const st = getPublishedState();
|
|
93
|
-
if (!server || sockets.size === 0) {
|
|
94
|
-
baseline = baselineOf(st, '');
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
if (frameStale()) return;
|
|
98
|
-
const next = deltaFrame(baseline, st);
|
|
99
|
-
baseline = next.baseline;
|
|
100
|
-
if (next.frame) broadcast(next.frame);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const acceptSubmit = (socket, frame) => {
|
|
104
|
-
// Optional submission metadata (additive, old viewers omit it): the
|
|
105
|
-
// originating surface's submission id must survive the pipe so its
|
|
106
|
-
// optimistic user row releases when the SAME id settles in the
|
|
107
|
-
// owner's transcript (user: 방금 친 메세지가 2개 남는다).
|
|
108
|
-
const id = typeof frame.id === 'string' && frame.id.trim() ? frame.id : undefined;
|
|
109
|
-
const submittedAt = Number(frame.submittedAt);
|
|
110
|
-
const prompt = frame.prompt ?? frame.text;
|
|
111
|
-
const delivered =
|
|
112
|
-
onRemoteSubmit(prompt, {
|
|
113
|
-
...(frame.options && typeof frame.options === 'object' ? frame.options : {}),
|
|
114
|
-
...(id ? { id } : {}),
|
|
115
|
-
...(Number.isFinite(submittedAt) && submittedAt > 0 ? { submittedAt: Math.round(submittedAt) } : {}),
|
|
116
|
-
}) !== false;
|
|
117
|
-
// Acknowledge the verdict (additive: viewers without ack tokens are
|
|
118
|
-
// unaffected). A refusal travels back as ok:false so the sender
|
|
119
|
-
// re-delivers instead of assuming the prompt landed.
|
|
120
|
-
const ackId = typeof frame.ack === 'string' && frame.ack.trim() ? frame.ack : '';
|
|
121
|
-
if (!ackId) return;
|
|
122
|
-
try {
|
|
123
|
-
socket.write(frameLine({ t: 'submit-ack', ack: ackId, ok: delivered }));
|
|
124
|
-
} catch {
|
|
125
|
-
/* close handles it; the sender's ack timeout re-delivers */
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
const handleViewerFrame = (socket, frame) => {
|
|
130
|
-
if (isSubmitFrame(frame)) {
|
|
131
|
-
acceptSubmit(socket, frame);
|
|
132
|
-
} else if (frame.t === 'abort') {
|
|
133
|
-
// Viewer stop button: interrupt the owner's active turn here — the
|
|
134
|
-
// viewer process has no turn of its own to cancel.
|
|
135
|
-
onRemoteAbort?.();
|
|
136
|
-
} else if (frame.t === 'sync') {
|
|
137
|
-
if (frameStale()) return;
|
|
138
|
-
try {
|
|
139
|
-
socket.write(frameLine(fullFrame(serverId, getPublishedState())));
|
|
140
|
-
} catch {
|
|
141
|
-
/* close handles */
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const attachViewer = (socket) => {
|
|
147
|
-
socket.setNoDelay?.(true);
|
|
148
|
-
sockets.add(socket);
|
|
149
|
-
const cleanup = () => sockets.delete(socket);
|
|
150
|
-
socket.on('close', cleanup);
|
|
151
|
-
socket.on('error', () => {
|
|
152
|
-
cleanup();
|
|
153
|
-
destroyQuietly(socket);
|
|
154
|
-
});
|
|
155
|
-
attachLineReader(
|
|
156
|
-
socket,
|
|
157
|
-
(frame) => handleViewerFrame(socket, frame),
|
|
158
|
-
() => destroyQuietly(socket)
|
|
159
|
-
);
|
|
160
|
-
try {
|
|
161
|
-
// Connected mid-reset: this state belongs to another session, and a
|
|
162
|
-
// baseline taken from it would desync every later delta. Drop the
|
|
163
|
-
// socket — the viewer's own retry finds the rebound pipe (or promotes).
|
|
164
|
-
if (frameStale()) {
|
|
165
|
-
destroyQuietly(socket);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
const st = getPublishedState();
|
|
169
|
-
baseline = baselineOf(st);
|
|
170
|
-
socket.write(frameLine(fullFrame(serverId, st)));
|
|
171
|
-
} catch {
|
|
172
|
-
destroyQuietly(socket);
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const stopServer = () => {
|
|
177
|
-
retry.clear();
|
|
178
|
-
retry.reset();
|
|
179
|
-
if (!server) {
|
|
180
|
-
serverId = '';
|
|
181
|
-
serverPath = '';
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
try {
|
|
185
|
-
broadcast({ t: 'close' });
|
|
186
|
-
} catch {
|
|
187
|
-
/* sockets closing anyway */
|
|
188
|
-
}
|
|
189
|
-
for (const socket of sockets) destroyQuietly(socket);
|
|
190
|
-
sockets.clear();
|
|
191
|
-
const closing = server;
|
|
192
|
-
server = null;
|
|
193
|
-
try {
|
|
194
|
-
closing.close();
|
|
195
|
-
} catch {
|
|
196
|
-
/* already closed */
|
|
197
|
-
}
|
|
198
|
-
unlinkQuietly(serverPath);
|
|
199
|
-
servedSocketPaths.delete(serverPath);
|
|
200
|
-
serverId = '';
|
|
201
|
-
serverPath = '';
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
// EADDRINUSE (another live owner) or a transient listen failure: retry
|
|
205
|
-
// with a short bounded backoff while this surface still owns the id.
|
|
206
|
-
const retryAfterListenFailure = (id) => {
|
|
207
|
-
server = null;
|
|
208
|
-
serverId = '';
|
|
209
|
-
serverPath = '';
|
|
210
|
-
retry.schedule(id);
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
const startServer = (id) => {
|
|
214
|
-
if (isDisposed() || server || !id) return;
|
|
215
|
-
retry.clear();
|
|
216
|
-
const path = socketPathFor(id);
|
|
217
|
-
const next = createServer(attachViewer);
|
|
218
|
-
next.on('error', () => {
|
|
219
|
-
if (server === next) retryAfterListenFailure(id);
|
|
220
|
-
try {
|
|
221
|
-
next.close();
|
|
222
|
-
} catch {
|
|
223
|
-
/* already closed */
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
next.on('listening', () => {
|
|
227
|
-
if (server !== next) return;
|
|
228
|
-
retry.clear();
|
|
229
|
-
retry.reset();
|
|
230
|
-
});
|
|
231
|
-
unlinkQuietly(path);
|
|
232
|
-
server = next;
|
|
233
|
-
serverId = id;
|
|
234
|
-
serverPath = path;
|
|
235
|
-
serveSocketPath(path);
|
|
236
|
-
try {
|
|
237
|
-
next.listen(path);
|
|
238
|
-
} catch {
|
|
239
|
-
retryAfterListenFailure(id);
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
// Reconcile against the session this surface currently owns ('' = none).
|
|
244
|
-
const ensure = (ownerId) =>
|
|
245
|
-
reconcileLeg(ownerId, {
|
|
246
|
-
retry,
|
|
247
|
-
legId: () => serverId,
|
|
248
|
-
legUp: () => Boolean(server),
|
|
249
|
-
stop: stopServer,
|
|
250
|
-
start: startServer,
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
return { ensure, stop: stopServer, onPublish };
|
|
254
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/tui/session/live-share/retry.mjs - bounded exponential retry timer for
|
|
3
|
-
* pipe opens, keyed by the session id the pending retry belongs to.
|
|
4
|
-
*/
|
|
5
|
-
export function createRetryTimer({ minMs, maxMs, shouldStart, start }) {
|
|
6
|
-
let timer = null;
|
|
7
|
-
let id = '';
|
|
8
|
-
let delayMs = minMs;
|
|
9
|
-
|
|
10
|
-
function clear() {
|
|
11
|
-
if (timer) clearTimeout(timer);
|
|
12
|
-
timer = null;
|
|
13
|
-
id = '';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function schedule(target) {
|
|
17
|
-
const next = String(target || '');
|
|
18
|
-
if (!next || timer || !shouldStart(next)) return;
|
|
19
|
-
const delay = delayMs;
|
|
20
|
-
delayMs = Math.min(maxMs, Math.max(minMs, delayMs * 2));
|
|
21
|
-
id = next;
|
|
22
|
-
timer = setTimeout(() => {
|
|
23
|
-
timer = null;
|
|
24
|
-
id = '';
|
|
25
|
-
if (shouldStart(next)) start(next);
|
|
26
|
-
}, delay);
|
|
27
|
-
timer.unref?.();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
id: () => id,
|
|
32
|
-
pending: () => Boolean(timer),
|
|
33
|
-
clear,
|
|
34
|
-
reset: () => {
|
|
35
|
-
delayMs = minMs;
|
|
36
|
-
},
|
|
37
|
-
schedule,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Reconcile one live-share leg (the owner's pipe server, the viewer's client)
|
|
43
|
-
* against the session it should serve/follow — '' = none. A retry aimed at
|
|
44
|
-
* another session is dropped, a leg bound to another session is stopped, and a
|
|
45
|
-
* leg is (re)started only when nothing is up and no retry is already pending.
|
|
46
|
-
* `legId`/`legUp` are read lazily because both callers keep them in mutable
|
|
47
|
-
* closure state.
|
|
48
|
-
*/
|
|
49
|
-
export function reconcileLeg(targetId, { retry, legId, legUp, stop, start }) {
|
|
50
|
-
if (retry.id() && retry.id() !== targetId) retry.clear();
|
|
51
|
-
if (!targetId && retry.pending()) retry.clear();
|
|
52
|
-
if (legId() && legId() !== targetId) stop();
|
|
53
|
-
if (targetId && !legUp() && !retry.pending()) start(targetId);
|
|
54
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/tui/session/live-share/viewer/frame-router.mjs - where one owner frame
|
|
3
|
-
* goes: submit-ack verdicts, the mirrored state, and the full-frame sync
|
|
4
|
-
* barrier. Returns true when the frame ends the link (owner close).
|
|
5
|
-
*/
|
|
6
|
-
export function routeViewerFrame(frame, { socket, id, link, sync, acks, mirror, viewerSessionId }) {
|
|
7
|
-
if (link.socket !== socket) return false;
|
|
8
|
-
if (frame.t === 'close') return true;
|
|
9
|
-
// Delivery verdicts are session-independent: settle them before the
|
|
10
|
-
// session-scope guard, so a submit acknowledged during a session switch
|
|
11
|
-
// is not counted as lost (and re-sent as a duplicate).
|
|
12
|
-
if (frame.t === 'submit-ack') {
|
|
13
|
-
acks.settle(String(frame.ack || ''), frame.ok !== false);
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
if (viewerSessionId() !== id) return false;
|
|
17
|
-
try {
|
|
18
|
-
const synced = mirror.applyFrame(frame);
|
|
19
|
-
if (!synced) sync.requestSync(socket);
|
|
20
|
-
// A connected socket is not an entry boundary: the viewer must wait
|
|
21
|
-
// until the owner's atomic full frame has replaced the stale disk
|
|
22
|
-
// restore. Desktop resume holds its renderer publication on this
|
|
23
|
-
// barrier, preventing "last user message first, whole turn later".
|
|
24
|
-
if (frame.t === 'full') {
|
|
25
|
-
link.syncedId = id;
|
|
26
|
-
sync.settle(id, true);
|
|
27
|
-
}
|
|
28
|
-
} catch {
|
|
29
|
-
sync.requestSync(socket);
|
|
30
|
-
}
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/tui/session/live-share/viewer/pipe-client.mjs - the viewer's socket
|
|
3
|
-
* lifecycle: connect, frame routing into the mirror, teardown, and the retry
|
|
4
|
-
* timer that owns re-connection. The link record it mutates is the viewer
|
|
5
|
-
* leg's, so waitForSync/sendSubmit read the same `up`/`syncedId` state.
|
|
6
|
-
*/
|
|
7
|
-
import { connect } from 'node:net';
|
|
8
|
-
import { attachLineReader, destroyQuietly } from '../wire.mjs';
|
|
9
|
-
import { createRetryTimer } from '../retry.mjs';
|
|
10
|
-
import { routeViewerFrame } from './frame-router.mjs';
|
|
11
|
-
|
|
12
|
-
export function createPipeClient({
|
|
13
|
-
link,
|
|
14
|
-
sync,
|
|
15
|
-
acks,
|
|
16
|
-
mirror,
|
|
17
|
-
viewerSessionId,
|
|
18
|
-
socketPathFor,
|
|
19
|
-
onOwnerClosed,
|
|
20
|
-
isDisposed,
|
|
21
|
-
retryMinMs,
|
|
22
|
-
retryMaxMs,
|
|
23
|
-
}) {
|
|
24
|
-
const retry = createRetryTimer({
|
|
25
|
-
minMs: retryMinMs,
|
|
26
|
-
maxMs: retryMaxMs,
|
|
27
|
-
shouldStart: (id) => !isDisposed() && !link.socket && String(viewerSessionId() || '') === id,
|
|
28
|
-
start: (id) => startClient(id),
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const resetLink = () => {
|
|
32
|
-
link.socket = null;
|
|
33
|
-
link.id = '';
|
|
34
|
-
link.up = false;
|
|
35
|
-
link.syncedId = '';
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const stopClient = () => {
|
|
39
|
-
retry.clear();
|
|
40
|
-
retry.reset();
|
|
41
|
-
const closing = link.socket;
|
|
42
|
-
const closingId = link.id;
|
|
43
|
-
const wasUp = link.up;
|
|
44
|
-
resetLink();
|
|
45
|
-
if (closingId) sync.settle(closingId, false);
|
|
46
|
-
if (closing) destroyQuietly(closing);
|
|
47
|
-
// Deliberate teardown (session switch / role change / dispose) destroys
|
|
48
|
-
// the socket AFTER link.up is already false, so the socket's close
|
|
49
|
-
// handler sees wasUp=false and never clears the mirror. Clear it here:
|
|
50
|
-
// otherwise the owner's mirrored busy/spinner/queue leaks into the next
|
|
51
|
-
// resumed session as a frozen working indicator (user report: finished
|
|
52
|
-
// session shows a spinner + stop button after switching away from a
|
|
53
|
-
// busy live-attached session).
|
|
54
|
-
if (wasUp) mirror.clearLiveState();
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Frame routing: viewer/frame-router.mjs.
|
|
58
|
-
const onFrame = (socket, id, frame) =>
|
|
59
|
-
routeViewerFrame(frame, { socket, id, link, sync, acks, mirror, viewerSessionId });
|
|
60
|
-
|
|
61
|
-
const startClient = (id) => {
|
|
62
|
-
if (isDisposed() || link.socket || !id) return;
|
|
63
|
-
retry.clear();
|
|
64
|
-
let socket;
|
|
65
|
-
try {
|
|
66
|
-
socket = connect(socketPathFor(id));
|
|
67
|
-
} catch {
|
|
68
|
-
retry.schedule(id);
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
link.socket = socket;
|
|
72
|
-
link.id = id;
|
|
73
|
-
link.up = false;
|
|
74
|
-
link.syncedId = '';
|
|
75
|
-
socket.setNoDelay?.(true);
|
|
76
|
-
socket.on('connect', () => {
|
|
77
|
-
if (link.socket !== socket) return;
|
|
78
|
-
link.up = true;
|
|
79
|
-
retry.clear();
|
|
80
|
-
retry.reset();
|
|
81
|
-
});
|
|
82
|
-
const down = (ownerClosed) => {
|
|
83
|
-
const wasCurrent = link.socket === socket;
|
|
84
|
-
const wasUp = link.up && wasCurrent;
|
|
85
|
-
if (wasCurrent) resetLink();
|
|
86
|
-
// Anything still awaiting an ack died with this socket: report it as
|
|
87
|
-
// undelivered so the caller re-delivers durably.
|
|
88
|
-
if (wasCurrent) acks.failAll();
|
|
89
|
-
destroyQuietly(socket);
|
|
90
|
-
if (wasUp) mirror.clearLiveState();
|
|
91
|
-
// A live link that dropped means the owner ended or crashed: nudge the
|
|
92
|
-
// promotion path instead of waiting for the next store-mtime change.
|
|
93
|
-
if (wasUp) onOwnerClosed?.(id, ownerClosed);
|
|
94
|
-
if (wasCurrent) retry.schedule(id);
|
|
95
|
-
};
|
|
96
|
-
socket.on('error', () => down(false));
|
|
97
|
-
socket.on('close', () => down(false));
|
|
98
|
-
attachLineReader(
|
|
99
|
-
socket,
|
|
100
|
-
(frame) => {
|
|
101
|
-
if (onFrame(socket, id, frame)) down(true);
|
|
102
|
-
},
|
|
103
|
-
() => down(false)
|
|
104
|
-
);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
return { retry, startClient, stopClient };
|
|
108
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* live-share/viewer/submit-acks.mjs - submit delivery tracking. A pipe write
|
|
3
|
-
* only proves the bytes left this process: the owner can REFUSE the prompt
|
|
4
|
-
* (disposed / itself attached) and the socket can die before it is read.
|
|
5
|
-
* Every submit therefore carries an ack token, and an unacknowledged one is
|
|
6
|
-
* reported to the caller so it can re-deliver through the durable spool
|
|
7
|
-
* instead of losing the message.
|
|
8
|
-
*/
|
|
9
|
-
import { frameLine } from '../wire.mjs';
|
|
10
|
-
|
|
11
|
-
const SUBMIT_ACK_TIMEOUT_MS = 2_000;
|
|
12
|
-
|
|
13
|
-
/** The submit frame for `prompt`, tagged with its ack token. */
|
|
14
|
-
export function submitFrame(prompt, meta, ackId) {
|
|
15
|
-
const id = meta && meta.id != null && String(meta.id).trim() ? String(meta.id) : undefined;
|
|
16
|
-
const submittedAt = Number(meta?.submittedAt);
|
|
17
|
-
const displayText = String(
|
|
18
|
-
meta?.displayText ?? meta?.options?.displayText ?? (typeof prompt === 'string' ? prompt : '')
|
|
19
|
-
);
|
|
20
|
-
return frameLine({
|
|
21
|
-
t: 'submit',
|
|
22
|
-
text: displayText,
|
|
23
|
-
prompt,
|
|
24
|
-
...(meta?.options && typeof meta.options === 'object' ? { options: meta.options } : {}),
|
|
25
|
-
ack: ackId,
|
|
26
|
-
...(id ? { id } : {}),
|
|
27
|
-
...(Number.isFinite(submittedAt) && submittedAt > 0 ? { submittedAt: Math.round(submittedAt) } : {}),
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function createSubmitAcks() {
|
|
32
|
-
const pending = new Map();
|
|
33
|
-
let seq = 0;
|
|
34
|
-
|
|
35
|
-
function nextAckId() {
|
|
36
|
-
seq += 1;
|
|
37
|
-
return `ack-${process.pid}-${Date.now()}-${seq}`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function settle(ackId, delivered) {
|
|
41
|
-
const entry = pending.get(ackId);
|
|
42
|
-
if (!entry) return;
|
|
43
|
-
pending.delete(ackId);
|
|
44
|
-
clearTimeout(entry.timer);
|
|
45
|
-
if (delivered) return;
|
|
46
|
-
try {
|
|
47
|
-
entry.onUndelivered?.();
|
|
48
|
-
} catch {
|
|
49
|
-
/* fallback is best-effort */
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** Written, not yet delivered: an owner that never acknowledges triggers re-delivery. */
|
|
54
|
-
function track(ackId, onUndelivered) {
|
|
55
|
-
const timer = setTimeout(() => settle(ackId, false), SUBMIT_ACK_TIMEOUT_MS);
|
|
56
|
-
timer.unref?.();
|
|
57
|
-
pending.set(ackId, { timer, onUndelivered });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function failAll() {
|
|
61
|
-
for (const ackId of [...pending.keys()]) settle(ackId, false);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return { nextAckId, settle, track, failAll };
|
|
65
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* live-share/viewer/sync-waiters.mjs - callers waiting for the owner's atomic
|
|
3
|
-
* full frame of one session, plus the throttled desync-recovery request.
|
|
4
|
-
*/
|
|
5
|
-
import { frameLine } from '../wire.mjs';
|
|
6
|
-
|
|
7
|
-
// Desync-recovery `sync` requests are throttled so a corrupt stream cannot
|
|
8
|
-
// make the owner serialize full transcripts every frame.
|
|
9
|
-
const SYNC_REQUEST_MIN_INTERVAL_MS = 500;
|
|
10
|
-
|
|
11
|
-
export function createSyncWaiters() {
|
|
12
|
-
const waiters = new Set();
|
|
13
|
-
let lastSyncRequestAt = 0;
|
|
14
|
-
|
|
15
|
-
/** Resolve every waiter on `id` with `synced`. */
|
|
16
|
-
function settle(id, synced) {
|
|
17
|
-
for (const waiter of waiters) {
|
|
18
|
-
if (waiter.id === id) waiter.finish(synced);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** A promise that settles when `id` is fully synced, or false on timeout. */
|
|
23
|
-
function wait(id, timeoutMs) {
|
|
24
|
-
return new Promise((resolve) => {
|
|
25
|
-
const waiter = { id, timer: null, finish: null };
|
|
26
|
-
waiter.finish = (synced) => {
|
|
27
|
-
if (!waiters.delete(waiter)) return;
|
|
28
|
-
if (waiter.timer) clearTimeout(waiter.timer);
|
|
29
|
-
resolve(synced === true);
|
|
30
|
-
};
|
|
31
|
-
waiters.add(waiter);
|
|
32
|
-
waiter.timer = setTimeout(() => waiter.finish(false), Math.max(1, Number(timeoutMs) || 750));
|
|
33
|
-
waiter.timer.unref?.();
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function requestSync(socket) {
|
|
38
|
-
const now = Date.now();
|
|
39
|
-
if (now - lastSyncRequestAt < SYNC_REQUEST_MIN_INTERVAL_MS) return;
|
|
40
|
-
lastSyncRequestAt = now;
|
|
41
|
-
try {
|
|
42
|
-
socket.write(frameLine({ t: 'sync' }));
|
|
43
|
-
} catch {
|
|
44
|
-
/* close handles */
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function failAll() {
|
|
49
|
-
for (const waiter of waiters) waiter.finish(false);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return { settle, wait, requestSync, failAll };
|
|
53
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/tui/session/live-share/viewer.mjs - viewer leg: pipe client that
|
|
3
|
-
* mirrors owner deltas into the local store, tracks full-sync and submit-ack
|
|
4
|
-
* delivery, and sends submit/abort frames back to the owner. viewer/:
|
|
5
|
-
* sync-waiters (full-frame barrier + throttled resync), submit-acks
|
|
6
|
-
* (delivery tokens and the durable re-delivery fallback).
|
|
7
|
-
*/
|
|
8
|
-
import { frameLine } from './wire.mjs';
|
|
9
|
-
import { createMirror } from './mirror.mjs';
|
|
10
|
-
import { reconcileLeg } from './retry.mjs';
|
|
11
|
-
import { createPipeClient } from './viewer/pipe-client.mjs';
|
|
12
|
-
import { createSyncWaiters } from './viewer/sync-waiters.mjs';
|
|
13
|
-
import { createSubmitAcks, submitFrame } from './viewer/submit-acks.mjs';
|
|
14
|
-
|
|
15
|
-
export function createViewerLeg({
|
|
16
|
-
viewerSessionId,
|
|
17
|
-
socketPathFor,
|
|
18
|
-
viewerApply,
|
|
19
|
-
onOwnerClosed,
|
|
20
|
-
isDisposed,
|
|
21
|
-
reconcile,
|
|
22
|
-
retryMinMs,
|
|
23
|
-
retryMaxMs,
|
|
24
|
-
}) {
|
|
25
|
-
// The pipe client for the attached session: `up` flips on connect, and
|
|
26
|
-
// `syncedId` once the owner's atomic full frame has replaced the disk restore.
|
|
27
|
-
const link = { socket: null, id: '', up: false, syncedId: '' };
|
|
28
|
-
const sync = createSyncWaiters();
|
|
29
|
-
const acks = createSubmitAcks();
|
|
30
|
-
const mirror = createMirror(viewerApply);
|
|
31
|
-
// Socket lifecycle (connect, frame routing, teardown, retry): viewer/pipe-client.mjs.
|
|
32
|
-
const { retry, startClient, stopClient } = createPipeClient({
|
|
33
|
-
link,
|
|
34
|
-
sync,
|
|
35
|
-
acks,
|
|
36
|
-
mirror,
|
|
37
|
-
viewerSessionId,
|
|
38
|
-
socketPathFor,
|
|
39
|
-
onOwnerClosed,
|
|
40
|
-
isDisposed,
|
|
41
|
-
retryMinMs,
|
|
42
|
-
retryMaxMs,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const waitForSync = (id, timeoutMs = 1500) => {
|
|
46
|
-
const target = String(id || '');
|
|
47
|
-
if (!target) return Promise.resolve(false);
|
|
48
|
-
reconcile();
|
|
49
|
-
if (link.up && link.id === target && link.syncedId === target) {
|
|
50
|
-
return Promise.resolve(true);
|
|
51
|
-
}
|
|
52
|
-
return sync.wait(target, timeoutMs);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// Reconcile against the session this surface is attached to ('' = none).
|
|
56
|
-
const ensure = (attachId) =>
|
|
57
|
-
reconcileLeg(attachId, {
|
|
58
|
-
retry,
|
|
59
|
-
legId: () => link.id,
|
|
60
|
-
legUp: () => Boolean(link.socket),
|
|
61
|
-
stop: stopClient,
|
|
62
|
-
start: startClient,
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const sendSubmit = (prompt, meta = null) => {
|
|
66
|
-
if (!link.up || !link.socket) return false;
|
|
67
|
-
const ackId = acks.nextAckId();
|
|
68
|
-
const onUndelivered = typeof meta?.onUndelivered === 'function' ? meta.onUndelivered : null;
|
|
69
|
-
try {
|
|
70
|
-
link.socket.write(submitFrame(prompt, meta, ackId));
|
|
71
|
-
} catch {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
// Written, not yet delivered. The caller gets its synchronous `true`
|
|
75
|
-
// (the store contract), and an owner that never acknowledges — refusal,
|
|
76
|
-
// crash, half-open pipe — triggers the durable re-delivery instead of
|
|
77
|
-
// silently eating the prompt.
|
|
78
|
-
if (onUndelivered) acks.track(ackId, onUndelivered);
|
|
79
|
-
return true;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const sendAbort = () => {
|
|
83
|
-
if (!link.up || !link.socket) return false;
|
|
84
|
-
try {
|
|
85
|
-
link.socket.write(frameLine({ t: 'abort' }));
|
|
86
|
-
return true;
|
|
87
|
-
} catch {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const dispose = () => {
|
|
93
|
-
acks.failAll();
|
|
94
|
-
stopClient();
|
|
95
|
-
sync.failAll();
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
return { ensure, connected: () => link.up, waitForSync, sendSubmit, sendAbort, dispose };
|
|
99
|
-
}
|