mixdog 1.3.5 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +2 -2
- package/README.md +2 -2
- package/package.json +2 -11
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/gate-local.mjs +4 -2
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +10 -1
- package/scripts/test.mjs +7 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +17 -1
- package/src/defaults/skills/browser-use/SKILL.md +59 -11
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +33 -9
- package/src/defaults/skills/setup/SKILL.md +22 -0
- package/src/defaults/skills/setup/references/actions.md +39 -5
- package/src/defaults/skills/setup/references/surfaces.md +11 -2
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/rules-builder.cjs +10 -8
- package/src/rules/agent/AGENT.md +6 -6
- package/src/rules/lead/LEAD.md +18 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/config.mjs +17 -1
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
- package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +181 -133
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +145 -66
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -13
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +26 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +133 -22
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +18 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/scheduler.mjs +33 -147
- package/src/runtime/channels/lib/schedules-db.mjs +34 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +10 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +2 -13
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +29 -0
- package/src/runtime/shared/connector-catalog.mjs +150 -0
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -14
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +7 -1
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +10 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +34 -1
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -14
- package/src/runtime/shared/worktrees/test-support.mjs +9 -4
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +27 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +448 -185
- package/src/session-runtime/agent-task-sessions.mjs +329 -180
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +6 -1
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +153 -33
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +2 -1
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +7 -13
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +1 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +13 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +145 -22
- package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +16 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +124 -188
- package/src/standalone/daemon.mjs +26 -3
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-tool-output.mjs +15 -7
- package/src/tui/app/model-options.mjs +3 -28
- package/src/tui/dist/index.mjs +58 -64
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +7 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +17 -1
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +19 -2
- package/src/tui/session/turn.mjs +1 -0
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
readClaudeCodeCurrentRoute,
|
|
8
8
|
} from '../src/gateway/claude-current.mjs';
|
|
9
9
|
import {
|
|
10
|
-
normalizeClientHostPid,
|
|
11
10
|
readLatestGatewayHostRoute,
|
|
12
11
|
readGatewaySessionRoute,
|
|
13
12
|
} from '../src/gateway/session-routes.mjs';
|
|
@@ -16,33 +15,13 @@ import {
|
|
|
16
15
|
defaultEffectiveContextWindowPercent,
|
|
17
16
|
} from '../src/gateway/route-meta.mjs';
|
|
18
17
|
import { getModelMetadataSync } from '../../../runtime/agent/orchestrator/providers/model-catalog.mjs';
|
|
19
|
-
import { resolveRuntimeRoot } from '../../../runtime/shared/runtime-root.mjs';
|
|
20
18
|
import { withDefaultPresets } from '../../../runtime/agent/orchestrator/config-presets.mjs';
|
|
21
19
|
|
|
22
|
-
function positiveInt(value) {
|
|
23
|
-
const n = parseInt(String(value || ''), 10);
|
|
24
|
-
return Number.isFinite(n) && n > 0 ? n : 0;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
20
|
// Keep the last known OAuth usage snapshot visible while idle. Live refreshes
|
|
28
21
|
// replace it when available, but a delayed/failed refresh must not make the
|
|
29
22
|
// statusline usage segment disappear. Previous-launch snapshots stay hidden
|
|
30
23
|
// during boot until the current process captures usage once.
|
|
31
24
|
const STATUSLINE_PROCESS_STARTED_AT_MS = Date.now() - Math.floor((Number(process.uptime?.()) || 0) * 1000);
|
|
32
|
-
function isPidAlive(pid) {
|
|
33
|
-
const n = positiveInt(pid);
|
|
34
|
-
if (!n) return false;
|
|
35
|
-
try {
|
|
36
|
-
process.kill(n, 0);
|
|
37
|
-
return true;
|
|
38
|
-
} catch (e) {
|
|
39
|
-
return !!(e && e.code === 'EPERM');
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function runtimeRoot() {
|
|
44
|
-
return resolveRuntimeRoot();
|
|
45
|
-
}
|
|
46
25
|
|
|
47
26
|
function claudeConfigDir() {
|
|
48
27
|
return process.env.MIXDOG_CONFIG_DIR || path.join(os.homedir(), '.mixdog');
|
|
@@ -246,62 +225,11 @@ function routeContextMeta(provider, info = {}, inherited = {}) {
|
|
|
246
225
|
};
|
|
247
226
|
}
|
|
248
227
|
|
|
249
|
-
// Test-only export of the route context-meta resolver for the auto-compact
|
|
250
|
-
// limit migration smoke (scripts/compact-trigger-migration-smoke.mjs).
|
|
251
|
-
export const _routeContextMeta = routeContextMeta;
|
|
252
|
-
|
|
253
|
-
// Resolve the auto-compact limit displayed by loadGatewayStatus(). The active
|
|
254
|
-
// value MUST be validated against the ACTIVE route's own boundary/window, never
|
|
255
|
-
// configured?.contextWindow: the configured window can be larger than the
|
|
256
|
-
// active window, so validating a stale active full-window value (== active
|
|
257
|
-
// window) against the configured window would let it slip through as an
|
|
258
|
-
// explicit limit. The configured route's limit (already sanitized by
|
|
259
|
-
// routeContextMeta) is preferred when a configured route is present, but it
|
|
260
|
-
// never validates a stale active value.
|
|
261
|
-
function resolveStatusAutoCompactTokenLimit(configured, active = {}, lastCompact = null) {
|
|
262
|
-
if (configured) {
|
|
263
|
-
const c = num(configured.autoCompactTokenLimit, 0);
|
|
264
|
-
return c > 0 ? c : null;
|
|
265
|
-
}
|
|
266
|
-
const activeBoundary = num(
|
|
267
|
-
active?.gateway_context_window
|
|
268
|
-
?? active?.gateway_raw_context_window
|
|
269
|
-
?? lastCompact?.budgetWindow
|
|
270
|
-
?? lastCompact?.contextWindow,
|
|
271
|
-
0,
|
|
272
|
-
);
|
|
273
|
-
const raw = num(active?.gateway_auto_compact_token_limit, 0);
|
|
274
|
-
if (!(raw > 0)) return null;
|
|
275
|
-
if (activeBoundary > 0) return raw < activeBoundary ? raw : null;
|
|
276
|
-
return raw;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Test-only export of the status auto-compact-limit resolver.
|
|
280
|
-
export const _resolveStatusAutoCompactTokenLimit = resolveStatusAutoCompactTokenLimit;
|
|
281
|
-
|
|
282
228
|
export function compactBoundaryForStatus(routeInfo = {}, compact = null) {
|
|
283
229
|
const n = compactBoundaryDenominator(routeInfo, compact);
|
|
284
230
|
return n > 0 ? n : null;
|
|
285
231
|
}
|
|
286
232
|
|
|
287
|
-
function sessionIdFromTranscriptPath(transcriptPath) {
|
|
288
|
-
const base = path.basename(String(transcriptPath || ''));
|
|
289
|
-
return base.endsWith('.jsonl') ? base.slice(0, -6) : '';
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function gatewaySessionStatusFileName(sessionId, clientHostPid = null) {
|
|
293
|
-
const sid = cleanString(sessionId).replace(/[^0-9A-Za-z._-]/g, '');
|
|
294
|
-
if (!sid) return null;
|
|
295
|
-
const pid = normalizeClientHostPid(clientHostPid);
|
|
296
|
-
return pid ? `${sid}--host-${pid}.json` : `${sid}.json`;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function gatewaySessionStatus(sessionId, clientHostPid = null) {
|
|
300
|
-
const name = gatewaySessionStatusFileName(sessionId, clientHostPid);
|
|
301
|
-
if (!name) return null;
|
|
302
|
-
return readJson(path.join(runtimeRoot(), 'gateway-session-status', name));
|
|
303
|
-
}
|
|
304
|
-
|
|
305
233
|
function sessionRouteFor(gateway, sessionId, clientHostPid = null) {
|
|
306
234
|
const sid = cleanString(sessionId);
|
|
307
235
|
if (!sid) return { route: gateway, sessionScoped: false };
|
|
@@ -538,153 +466,7 @@ export function loadGatewayStatus(options = {}) {
|
|
|
538
466
|
balance: null,
|
|
539
467
|
routeSpend: null,
|
|
540
468
|
} : null;
|
|
541
|
-
|
|
542
|
-
const activeGlobal = activeOverride || readJson(path.join(runtimeRoot(), 'active-instance.json'));
|
|
543
|
-
const currentClientHostPid = normalizeClientHostPid(options.clientHostPid);
|
|
544
|
-
const sessionStatus = activeOverride || gatewaySessionStatus(options.sessionId, currentClientHostPid);
|
|
545
|
-
const active = sessionStatus || activeGlobal;
|
|
546
|
-
if (!active || !active.gateway_port || !active.gateway_provider || !active.gateway_model) return configuredStatus;
|
|
547
|
-
const ownerPid = positiveInt(active.gateway_server_pid);
|
|
548
|
-
if (ownerPid && !isPidAlive(ownerPid)) return configuredStatus;
|
|
549
|
-
const updatedAt = num(active.gateway_updated_at, 0) || num(active.updatedAt, 0);
|
|
550
|
-
if (updatedAt && Date.now() - updatedAt > 5 * 60_000) return configuredStatus;
|
|
551
|
-
// Gate active-instance metrics on a positive ownership proof. The display
|
|
552
|
-
// route itself always comes from the current session config (`configured`)
|
|
553
|
-
// when present; active-instance only contributes live usage for that same
|
|
554
|
-
// session/route, never model identity.
|
|
555
|
-
const currentSessionId = cleanString(options.sessionId);
|
|
556
|
-
const gatewayCcSessionMatch = currentSessionId && cleanString(active.gateway_cc_session_id) === currentSessionId;
|
|
557
|
-
const activeClientHostPid = normalizeClientHostPid(active.gateway_client_host_pid ?? active.clientHostPid);
|
|
558
|
-
const gatewayClientHostMatch = !currentClientHostPid || activeClientHostPid === currentClientHostPid;
|
|
559
|
-
const gwTranscript = typeof active.gateway_transcript_path === 'string' && active.gateway_transcript_path || null;
|
|
560
|
-
const currentTranscript = typeof activeGlobal?.transcriptPath === 'string' && activeGlobal.transcriptPath || null;
|
|
561
|
-
const gatewayTranscriptMatch = currentSessionId
|
|
562
|
-
? sessionIdFromTranscriptPath(gwTranscript) === currentSessionId
|
|
563
|
-
: !!(gwTranscript && currentTranscript && gwTranscript === currentTranscript);
|
|
564
|
-
const activeTranscriptMatch = currentSessionId
|
|
565
|
-
? sessionIdFromTranscriptPath(currentTranscript) === currentSessionId
|
|
566
|
-
: false;
|
|
567
|
-
const transcriptMatch = gatewayCcSessionMatch || gatewayTranscriptMatch || (!gwTranscript && activeTranscriptMatch);
|
|
568
|
-
const routeMatchesConfigured = configured
|
|
569
|
-
? configured.provider === active.gateway_provider && configured.model === active.gateway_model
|
|
570
|
-
: true;
|
|
571
|
-
const activeRouteBoundary = compactBoundaryForStatus({
|
|
572
|
-
autoCompactTokenLimit: active.gateway_auto_compact_token_limit,
|
|
573
|
-
contextWindow: active.gateway_context_window,
|
|
574
|
-
rawContextWindow: active.gateway_raw_context_window,
|
|
575
|
-
});
|
|
576
|
-
const configuredRouteBoundary = configured ? compactBoundaryForStatus(configured) : null;
|
|
577
|
-
const routeBoundaryMatchesConfigured = !configured
|
|
578
|
-
|| !configuredRouteBoundary
|
|
579
|
-
|| !activeRouteBoundary
|
|
580
|
-
|| configuredRouteBoundary === activeRouteBoundary;
|
|
581
|
-
const metricsOwnCurrentSession = !!(sessionStatus || gatewayCcSessionMatch || gatewayTranscriptMatch || activeTranscriptMatch);
|
|
582
|
-
const metricsMatch = gatewayClientHostMatch && metricsOwnCurrentSession && routeMatchesConfigured && routeBoundaryMatchesConfigured;
|
|
583
|
-
// Strong ownership = this session's own status file or an explicit session/
|
|
584
|
-
// transcript id match from the gateway advert. `activeTranscriptMatch` (the
|
|
585
|
-
// global active-instance transcript merely naming the current session) is NOT
|
|
586
|
-
// strong: right after /new the global record can already point at the new
|
|
587
|
-
// session while its stored gateway metrics (context pct, last usage) still
|
|
588
|
-
// belong to the previous one.
|
|
589
|
-
const strongSessionOwnership = !!(sessionStatus || gatewayCcSessionMatch || gatewayTranscriptMatch);
|
|
590
|
-
// A model switch can keep strong session ownership while the active gateway
|
|
591
|
-
// advert still contains the previous route's lastUsage.compact. Do not let
|
|
592
|
-
// that stale compact boundary override the configured/current route window.
|
|
593
|
-
const lastUsage = gatewayClientHostMatch && strongSessionOwnership && routeMatchesConfigured && routeBoundaryMatchesConfigured && active.gateway_last_usage && typeof active.gateway_last_usage === 'object'
|
|
594
|
-
? active.gateway_last_usage
|
|
595
|
-
: null;
|
|
596
|
-
const rawLastCompact = lastUsage?.compact && typeof lastUsage.compact === 'object'
|
|
597
|
-
? lastUsage.compact
|
|
598
|
-
: null;
|
|
599
|
-
// A model/window switch updates the active route fields (context/raw window)
|
|
600
|
-
// but can leave the PREVIOUS route's boundary inside gateway_last_usage.compact.
|
|
601
|
-
// routeBoundaryMatchesConfigured only checks the active route fields, so that
|
|
602
|
-
// stale compact telemetry would otherwise survive and, via compactBoundaryTokens,
|
|
603
|
-
// resurrect the previous boundary in compactBoundaryForStatus below. Drop the
|
|
604
|
-
// compact telemetry when its own implied boundary contradicts the active route
|
|
605
|
-
// window.
|
|
606
|
-
const lastCompactBoundary = rawLastCompact
|
|
607
|
-
? compactBoundaryForStatus({}, rawLastCompact)
|
|
608
|
-
: null;
|
|
609
|
-
const lastCompact = rawLastCompact
|
|
610
|
-
&& (!activeRouteBoundary || !lastCompactBoundary || lastCompactBoundary === activeRouteBoundary)
|
|
611
|
-
? rawLastCompact
|
|
612
|
-
: null;
|
|
613
|
-
const statusLastUsage = lastUsage
|
|
614
|
-
? {
|
|
615
|
-
...lastUsage,
|
|
616
|
-
compact: lastCompact,
|
|
617
|
-
}
|
|
618
|
-
: null;
|
|
619
|
-
const contextBoundary = compactBoundaryForStatus({
|
|
620
|
-
autoCompactTokenLimit: active.gateway_auto_compact_token_limit,
|
|
621
|
-
contextWindow: active.gateway_context_window,
|
|
622
|
-
rawContextWindow: active.gateway_raw_context_window,
|
|
623
|
-
}, lastCompact);
|
|
624
|
-
const liveContextTokens = num(options.activeContextTokens, null);
|
|
625
|
-
const compactRequestWithLiveTokens = lastUsage?.requestKind === 'compact' && liveContextTokens !== null;
|
|
626
|
-
const overflowContextTokens = !compactRequestWithLiveTokens && lastCompact?.overflow === true
|
|
627
|
-
? Math.max(
|
|
628
|
-
num(lastUsage?.promptTokens, 0),
|
|
629
|
-
num(lastCompact?.beforeTokens, 0),
|
|
630
|
-
num(lastCompact?.afterTokens, 0),
|
|
631
|
-
num(contextBoundary, 0),
|
|
632
|
-
)
|
|
633
|
-
: null;
|
|
634
|
-
const contextNumerator = liveContextTokens !== null && Number.isFinite(liveContextTokens)
|
|
635
|
-
? liveContextTokens
|
|
636
|
-
: (overflowContextTokens ?? null);
|
|
637
|
-
const recomputedContextUsedPct = pctOf(contextNumerator, contextBoundary);
|
|
638
|
-
const activeQuotaWindows = metricsMatch && Array.isArray(active.gateway_quota_windows)
|
|
639
|
-
? active.gateway_quota_windows
|
|
640
|
-
: [];
|
|
641
|
-
const statusProvider = configured?.provider || active.gateway_provider;
|
|
642
|
-
const statusProviderKind = configured?.providerKind
|
|
643
|
-
|| (routeMatchesConfigured ? cleanString(active.gateway_provider_kind) : '')
|
|
644
|
-
|| providerKind(statusProvider);
|
|
645
|
-
// Sanitize the auto-compact limit before display: a stale boundary/window-
|
|
646
|
-
// sized active.gateway_auto_compact_token_limit must not surface as an
|
|
647
|
-
// explicit autoCompactTokenLimit (the runtime would read it as the trigger
|
|
648
|
-
// and collapse the buffer). The active value must be validated against the
|
|
649
|
-
// ACTIVE route's own boundary/window — NOT configured?.contextWindow. The
|
|
650
|
-
// configured window can be larger than the active window, so using it would
|
|
651
|
-
// let a stale active full-window value (== active window) slip through. Use
|
|
652
|
-
// the active boundary (active context/raw window, or the lastCompact budget
|
|
653
|
-
// when present) and null the active value when it is >= that boundary.
|
|
654
|
-
const statusAutoCompactTokenLimit = resolveStatusAutoCompactTokenLimit(configured, active, lastCompact);
|
|
655
|
-
const activeStatus = {
|
|
656
|
-
provider: statusProvider,
|
|
657
|
-
model: configured?.model || active.gateway_model,
|
|
658
|
-
modelDisplay: configured?.modelDisplay
|
|
659
|
-
|| statuslineDisplayForModel(active.gateway_provider, active.gateway_model, {}, active.gateway_model_display)
|
|
660
|
-
|| active.gateway_model,
|
|
661
|
-
effort: configured?.effort ?? active.gateway_effort ?? '',
|
|
662
|
-
fast: configured?.fast ?? active.gateway_fast === true,
|
|
663
|
-
contextWindow: configured?.contextWindow ?? num(active.gateway_context_window, null),
|
|
664
|
-
rawContextWindow: configured?.rawContextWindow ?? num(active.gateway_raw_context_window, null),
|
|
665
|
-
effectiveContextWindowPercent: configured?.effectiveContextWindowPercent ?? num(active.gateway_effective_context_window_percent, null),
|
|
666
|
-
autoCompactTokenLimit: statusAutoCompactTokenLimit,
|
|
667
|
-
// Live recompute (from the caller's own context tokens) may use the weaker
|
|
668
|
-
// metricsMatch gate, but the STORED gateway_context_used_pct fallback needs
|
|
669
|
-
// strong ownership — otherwise a fresh /new session with a not-yet-updated
|
|
670
|
-
// active-instance record would keep showing the old session's context %.
|
|
671
|
-
contextUsedPct: metricsMatch
|
|
672
|
-
? recomputedContextUsedPct ?? (strongSessionOwnership ? num(active.gateway_context_used_pct, null) : null)
|
|
673
|
-
: null,
|
|
674
|
-
lastUsage: statusLastUsage,
|
|
675
|
-
quotaWindows: activeQuotaWindows.length ? activeQuotaWindows : (configuredStatus?.quotaWindows || []),
|
|
676
|
-
// Provenance for monotonic hysteresis: live active-instance windows are
|
|
677
|
-
// own-instance data timestamped by the advert's updatedAt; otherwise inherit
|
|
678
|
-
// the shared-cache fallback's (unowned) asOf. Older/unowned snapshots must
|
|
679
|
-
// not displace a value already rendered from newer/owned data.
|
|
680
|
-
quotaWindowsAsOf: activeQuotaWindows.length ? (updatedAt || 0) : num(configuredStatus?.quotaWindowsAsOf, 0),
|
|
681
|
-
quotaWindowsOwned: activeQuotaWindows.length ? metricsMatch : false,
|
|
682
|
-
balance: metricsMatch && active.gateway_balance && typeof active.gateway_balance === 'object' ? active.gateway_balance : (configuredStatus?.balance || null),
|
|
683
|
-
routeSpend: metricsMatch && active.gateway_route_spend && typeof active.gateway_route_spend === 'object' ? active.gateway_route_spend : (configuredStatus?.routeSpend || null),
|
|
684
|
-
providerKind: statusProviderKind,
|
|
685
|
-
};
|
|
686
|
-
if (!configured) return activeStatus;
|
|
687
|
-
return activeStatus;
|
|
469
|
+
return configuredStatus;
|
|
688
470
|
}
|
|
689
471
|
|
|
690
472
|
function isLocalEstimateWindow(window) {
|
|
@@ -307,10 +307,17 @@ function refreshUsageView() {
|
|
|
307
307
|
|
|
308
308
|
// Bounded compaction: keep the newest MAX_USAGE_EVENTS lines. Runs in the
|
|
309
309
|
// background under the store lock (appenders take it too, so no append is lost).
|
|
310
|
-
let compactRunning =
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
310
|
+
let compactRunning = null; // the compaction in flight
|
|
311
|
+
let compactTimer = null; // a compaction scheduled to run
|
|
312
|
+
let compactStore = null;
|
|
313
|
+
function compactUsageStore(store) {
|
|
314
|
+
compactRunning ??= runUsageCompaction(store).finally(() => {
|
|
315
|
+
compactRunning = null;
|
|
316
|
+
});
|
|
317
|
+
return compactRunning;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
async function runUsageCompaction(store) {
|
|
314
321
|
try {
|
|
315
322
|
await withFileLock(usageLockPath(store), async () => {
|
|
316
323
|
const lines = (await readFile(store, 'utf8')).split('\n').filter(l => l.trim());
|
|
@@ -319,8 +326,6 @@ async function compactUsageStore(store) {
|
|
|
319
326
|
});
|
|
320
327
|
} catch {
|
|
321
328
|
// Compaction is best effort; the next flush retries.
|
|
322
|
-
} finally {
|
|
323
|
-
compactRunning = false;
|
|
324
329
|
}
|
|
325
330
|
}
|
|
326
331
|
|
|
@@ -330,8 +335,13 @@ function maybeScheduleCompaction(store) {
|
|
|
330
335
|
} catch {
|
|
331
336
|
return;
|
|
332
337
|
}
|
|
333
|
-
|
|
334
|
-
|
|
338
|
+
if (compactTimer) return;
|
|
339
|
+
compactStore = store;
|
|
340
|
+
compactTimer = setTimeout(() => {
|
|
341
|
+
compactTimer = null;
|
|
342
|
+
void compactUsageStore(store);
|
|
343
|
+
}, 1000);
|
|
344
|
+
compactTimer.unref?.();
|
|
335
345
|
}
|
|
336
346
|
|
|
337
347
|
function takePendingUsageBatch() {
|
|
@@ -357,8 +367,12 @@ function flushGatewayUsageEvents() {
|
|
|
357
367
|
const flush = withFileLock(usageLockPath(store), async () => {
|
|
358
368
|
await mkdir(dirname(store), { recursive: true });
|
|
359
369
|
await appendFile(store, data);
|
|
360
|
-
}).then(() => maybeScheduleCompaction(store)).catch(() => {
|
|
361
|
-
// Local telemetry must never affect the routed model call
|
|
370
|
+
}).then(() => maybeScheduleCompaction(store)).catch((error) => {
|
|
371
|
+
// Local telemetry must never affect the routed model call, but a lost
|
|
372
|
+
// batch is reported rather than settled as written.
|
|
373
|
+
try {
|
|
374
|
+
process.stderr.write(`[statusline] gateway usage events not saved: ${error?.message || error}\n`);
|
|
375
|
+
} catch {}
|
|
362
376
|
});
|
|
363
377
|
usageFlushTail = Promise.all([usageFlushTail, flush]).then(() => {});
|
|
364
378
|
return usageFlushTail;
|
|
@@ -378,9 +392,17 @@ function flushGatewayUsageEventsSync() {
|
|
|
378
392
|
}
|
|
379
393
|
}
|
|
380
394
|
|
|
381
|
-
/** Resolves once every recorded usage event has been handed to disk
|
|
382
|
-
|
|
383
|
-
|
|
395
|
+
/** Resolves once every recorded usage event has been handed to disk and the
|
|
396
|
+
* compaction those writes scheduled (run now instead of on its timer) or
|
|
397
|
+
* started has rewritten the store. */
|
|
398
|
+
export async function settleGatewayUsageWrites() {
|
|
399
|
+
await flushGatewayUsageEvents();
|
|
400
|
+
if (compactTimer) {
|
|
401
|
+
clearTimeout(compactTimer);
|
|
402
|
+
compactTimer = null;
|
|
403
|
+
void compactUsageStore(compactStore);
|
|
404
|
+
}
|
|
405
|
+
await compactRunning;
|
|
384
406
|
}
|
|
385
407
|
|
|
386
408
|
function scheduleGatewayUsageFlush() {
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
const FILE_MODES = ['overview', 'imports', 'dependents', 'related', 'impact'];
|
|
2
|
-
const SYMBOL_MODES = ['find_symbol', 'symbol_search', 'search', 'references', 'callers', 'callees'];
|
|
3
|
-
const EXACT_MODES = ['find_symbol', 'references', 'callers', 'callees'];
|
|
4
|
-
const KEYWORD_MODES = ['symbol_search', 'search'];
|
|
5
|
-
const NEGATION =
|
|
6
|
-
/\b(?:no|not|never|without|cannot|won['’]t|ain['’]t|(?:is|are|was|were|do|does|did|has|have|had|can|could|would|should|must)(?:\s+not|n['’]t)|will\s+not|fail(?:s|ed|ing)?\s+to)\b/i;
|
|
7
|
-
|
|
8
|
-
const clauses = (text) =>
|
|
9
|
-
String(text || '')
|
|
10
|
-
.split(/[.;]\s*/)
|
|
11
|
-
.map((part) => part.trim())
|
|
12
|
-
.filter(Boolean);
|
|
13
|
-
const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
14
|
-
const includesTerm = (text, term) => {
|
|
15
|
-
if (/^[a-z_][a-z0-9_]*$/i.test(term)) {
|
|
16
|
-
return new RegExp(`(?<![a-z0-9_])${escapeRegExp(term)}(?![a-z0-9_])`, 'i').test(text);
|
|
17
|
-
}
|
|
18
|
-
return text.toLowerCase().includes(term.toLowerCase());
|
|
19
|
-
};
|
|
20
|
-
const includesAll = (text, terms) => terms.every((term) => includesTerm(text, term));
|
|
21
|
-
const hasPositiveClause = (text, terms) =>
|
|
22
|
-
clauses(text).some((clause) => !NEGATION.test(clause) && includesAll(clause, terms));
|
|
23
|
-
const hasModeClause = (text, label, modes) => hasPositiveClause(text, [label, ...modes]);
|
|
24
|
-
const hasContradictoryTargetAssignment = (text) =>
|
|
25
|
-
hasPositiveClause(text, [...FILE_MODES, 'symbols[]']) || hasPositiveClause(text, [...SYMBOL_MODES, 'files[]']);
|
|
26
|
-
const removeIdentifier = (text, identifier) =>
|
|
27
|
-
text.replace(new RegExp(`(?<![a-z0-9_])${escapeRegExp(identifier)}(?![a-z0-9_])`, 'gi'), '');
|
|
28
|
-
|
|
29
|
-
const CODE_GRAPH_EQUIVALENT_DESCRIPTION_PROBES = [
|
|
30
|
-
{
|
|
31
|
-
description: [
|
|
32
|
-
'Keywords use search/symbol_search while callers/callees/references/find_symbol use exact identifiers.',
|
|
33
|
-
'symbols[] targets callees, search, references, symbol_search, callers, and find_symbol symbol modes.',
|
|
34
|
-
'files[] targets impact, related, dependents, imports, and overview file modes.',
|
|
35
|
-
].join(' '),
|
|
36
|
-
modeDescription: [
|
|
37
|
-
'A file outline uses files[] for symbols with files.',
|
|
38
|
-
'Impact, related, dependents, imports, and overview are file modes.',
|
|
39
|
-
'Callees, callers, references, search, symbol_search, and find_symbol are symbol modes.',
|
|
40
|
-
'Keywords from fileless symbols route to symbol_search.',
|
|
41
|
-
].join(' '),
|
|
42
|
-
symbolsDescription: [
|
|
43
|
-
'Keywords select search/symbol_search while callers/callees/references/find_symbol select exact identifiers.',
|
|
44
|
-
'Pass multiple exact symbols in one symbols[] call.',
|
|
45
|
-
].join(' '),
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
description: [
|
|
49
|
-
'Exact identifiers route through callees, references, callers, or find_symbol.',
|
|
50
|
-
'Keywords route through search or symbol_search.',
|
|
51
|
-
'The overview, impact, imports, related, and dependents file modes accept files[].',
|
|
52
|
-
'The search, callees, find_symbol, references, symbol_search, and callers symbol modes accept symbols[].',
|
|
53
|
-
].join(' '),
|
|
54
|
-
modeDescription: [
|
|
55
|
-
'Related, overview, impact, dependents, and imports are file modes.',
|
|
56
|
-
'Symbols with files produce a file outline from files[].',
|
|
57
|
-
'References, callers, callees, find_symbol, search, and symbol_search are symbol modes.',
|
|
58
|
-
'Fileless symbols treat keywords as symbol_search input.',
|
|
59
|
-
].join(' '),
|
|
60
|
-
symbolsDescription: [
|
|
61
|
-
'Exact identifiers select references, callees, callers, or find_symbol.',
|
|
62
|
-
'Keywords select symbol_search or search.',
|
|
63
|
-
'Multiple exact symbols belong in one symbols[] call.',
|
|
64
|
-
].join(' '),
|
|
65
|
-
},
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
const CODE_GRAPH_DESCRIPTION_MUTATION_CORPUS = [
|
|
69
|
-
{
|
|
70
|
-
name: 'contracted negated file assignment',
|
|
71
|
-
mutate: (parts) => ({
|
|
72
|
-
...parts,
|
|
73
|
-
description: parts.description.replace(
|
|
74
|
-
/file modes (?:take|use) files\[\]/i,
|
|
75
|
-
"file modes aren't assigned files[]"
|
|
76
|
-
),
|
|
77
|
-
filesDescription: String(parts.filesDescription || '').replace(
|
|
78
|
-
/required for file modes/i,
|
|
79
|
-
'not required for file modes'
|
|
80
|
-
),
|
|
81
|
-
}),
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
name: 'contracted outline polarity inversion',
|
|
85
|
-
allPositiveProbes: true,
|
|
86
|
-
mutate: (parts) => ({
|
|
87
|
-
...parts,
|
|
88
|
-
modeDescription: parts.modeDescription.replace(/file outline/i, "isn't a file outline"),
|
|
89
|
-
}),
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
name: 'keyword routing polarity inversion',
|
|
93
|
-
allPositiveProbes: true,
|
|
94
|
-
mutate: (parts) => ({
|
|
95
|
-
...parts,
|
|
96
|
-
description: parts.description.replace(
|
|
97
|
-
/keywords(?::|\s+(?:use|route through|select|via))/i,
|
|
98
|
-
"keywords won't use"
|
|
99
|
-
),
|
|
100
|
-
}),
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'symbols-with-files outline inversion',
|
|
104
|
-
allPositiveProbes: true,
|
|
105
|
-
mutate: (parts) => ({
|
|
106
|
-
...parts,
|
|
107
|
-
modeDescription: parts.modeDescription.replace(/symbols with files/i, 'symbols without files'),
|
|
108
|
-
}),
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
name: 'contradictory file-mode assignment retained beside correct clause',
|
|
112
|
-
allPositiveProbes: true,
|
|
113
|
-
mutate: (parts) => ({
|
|
114
|
-
...parts,
|
|
115
|
-
description: `${parts.description} Overview, imports, dependents, related, and impact take symbols[].`,
|
|
116
|
-
}),
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
name: 'contradictory symbol-mode assignment retained beside correct clause',
|
|
120
|
-
allPositiveProbes: true,
|
|
121
|
-
mutate: (parts) => ({
|
|
122
|
-
...parts,
|
|
123
|
-
description: `${parts.description} Find_symbol, symbol_search, search, references, callers, and callees take files[].`,
|
|
124
|
-
}),
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
name: 'swapped file-mode/symbol-mode array assignments',
|
|
128
|
-
allPositiveProbes: true,
|
|
129
|
-
mutate: (parts) => ({
|
|
130
|
-
...parts,
|
|
131
|
-
description: `${parts.description} Overview, imports, dependents, related, and impact take symbols[]. Find_symbol, symbol_search, search, references, callers, and callees take files[].`,
|
|
132
|
-
}),
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
name: 'standalone search removed from symbol modes and keyword routing',
|
|
136
|
-
allPositiveProbes: true,
|
|
137
|
-
mutate: (parts) => ({
|
|
138
|
-
...parts,
|
|
139
|
-
description: removeIdentifier(parts.description, 'search'),
|
|
140
|
-
modeDescription: removeIdentifier(parts.modeDescription, 'search'),
|
|
141
|
-
symbolsDescription: removeIdentifier(parts.symbolsDescription, 'search'),
|
|
142
|
-
}),
|
|
143
|
-
},
|
|
144
|
-
];
|
|
145
|
-
|
|
146
|
-
function hasCodeGraphDescriptionContract({ description, modeDescription, filesDescription, symbolsDescription }) {
|
|
147
|
-
return (
|
|
148
|
-
(hasPositiveClause(description, ['file modes', 'files[]']) ||
|
|
149
|
-
hasPositiveClause(filesDescription, ['required for file modes'])) &&
|
|
150
|
-
(hasPositiveClause(description, ['symbol modes', 'symbols[]']) ||
|
|
151
|
-
hasPositiveClause(symbolsDescription, ['required for symbol modes'])) &&
|
|
152
|
-
hasPositiveClause(description, ['exact identifiers', ...EXACT_MODES]) &&
|
|
153
|
-
hasPositiveClause(description, ['keywords', ...KEYWORD_MODES]) &&
|
|
154
|
-
!hasContradictoryTargetAssignment(description) &&
|
|
155
|
-
hasModeClause(modeDescription, 'file modes', FILE_MODES) &&
|
|
156
|
-
hasPositiveClause(modeDescription, ['symbols with files', 'files[]', 'file outline']) &&
|
|
157
|
-
!hasContradictoryTargetAssignment(modeDescription) &&
|
|
158
|
-
!hasContradictoryTargetAssignment(filesDescription) &&
|
|
159
|
-
hasPositiveClause(symbolsDescription, ['exact identifiers']) &&
|
|
160
|
-
hasPositiveClause(symbolsDescription, ['keywords']) &&
|
|
161
|
-
!hasContradictoryTargetAssignment(symbolsDescription)
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function assertCodeGraphDescriptionContract(parts) {
|
|
166
|
-
if (!hasCodeGraphDescriptionContract(parts)) {
|
|
167
|
-
throw new Error('code_graph descriptions must preserve per-mode targets and exact-vs-keyword routing');
|
|
168
|
-
}
|
|
169
|
-
for (const probe of CODE_GRAPH_EQUIVALENT_DESCRIPTION_PROBES) {
|
|
170
|
-
if (!hasCodeGraphDescriptionContract(probe)) {
|
|
171
|
-
throw new Error('code_graph description contract must accept equivalent reordered compact prose');
|
|
172
|
-
}
|
|
173
|
-
for (const mutation of CODE_GRAPH_DESCRIPTION_MUTATION_CORPUS.filter((entry) => entry.allPositiveProbes)) {
|
|
174
|
-
const mutated = mutation.mutate(probe);
|
|
175
|
-
if (JSON.stringify(mutated) === JSON.stringify(probe)) {
|
|
176
|
-
throw new Error(`code_graph description mutation did not apply to positive probe: ${mutation.name}`);
|
|
177
|
-
}
|
|
178
|
-
if (hasCodeGraphDescriptionContract(mutated)) {
|
|
179
|
-
throw new Error(`code_graph description contract accepted positive-probe mutation: ${mutation.name}`);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
for (const mutation of CODE_GRAPH_DESCRIPTION_MUTATION_CORPUS) {
|
|
184
|
-
if (hasCodeGraphDescriptionContract(mutation.mutate(parts))) {
|
|
185
|
-
throw new Error(`code_graph description contract accepted mutation: ${mutation.name}`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// Daemon model: this runtime is the unconditional bridge owner, so a refresh
|
|
2
|
-
// just keeps the owned runtime in sync with channelBridgeActive.
|
|
3
|
-
export function createOwnershipRefresh({
|
|
4
|
-
state,
|
|
5
|
-
getBridgeRuntimeConnected,
|
|
6
|
-
getChannelBridgeActive,
|
|
7
|
-
startOwnedRuntime,
|
|
8
|
-
stopOwnedRuntime,
|
|
9
|
-
}) {
|
|
10
|
-
async function syncWithBridgeActivity(options) {
|
|
11
|
-
if (!getChannelBridgeActive()) {
|
|
12
|
-
if (getBridgeRuntimeConnected()) await stopOwnedRuntime('bridge inactive');
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
// Idempotent; early-returns when already connected.
|
|
16
|
-
await startOwnedRuntime(options);
|
|
17
|
-
}
|
|
18
|
-
// Concurrent callers coalesce onto the in-flight refresh so provider tool
|
|
19
|
-
// calls landing during a normal login wait for the same connect attempt
|
|
20
|
-
// instead of observing a spurious auto-connect failure.
|
|
21
|
-
async function refreshBridgeOwnership(options = {}) {
|
|
22
|
-
if (state.refreshInFlight) return state.refreshInFlight;
|
|
23
|
-
state.refreshInFlight = syncWithBridgeActivity(options);
|
|
24
|
-
try {
|
|
25
|
-
return await state.refreshInFlight;
|
|
26
|
-
} finally {
|
|
27
|
-
state.refreshInFlight = null;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function refreshBridgeOwnershipSafe(options = {}) {
|
|
31
|
-
refreshBridgeOwnership(options).catch((err) =>
|
|
32
|
-
process.stderr.write(`[channels] refreshBridgeOwnership rejected: ${err?.message || err}\n`)
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
return { refreshBridgeOwnership, refreshBridgeOwnershipSafe };
|
|
36
|
-
}
|