mixdog 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/package.json +1 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +13 -3
- package/src/defaults/skills/visualize/SKILL.md +12 -9
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config.mjs +10 -4
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
- package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +25 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +73 -35
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +30 -14
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +447 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +102 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +21 -82
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +34 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +268 -181
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +819 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +41 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/pg/process.mjs +34 -24
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/atomic-file.mjs +25 -4
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/err-text.mjs +25 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -52
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +124 -20
- package/src/runtime/shared/provider-api-key.mjs +12 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/turn-changes.mjs +447 -219
- package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
- package/src/runtime/shared/turn-snapshot.mjs +170 -48
- package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/contract.mjs +0 -24
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +61 -0
- package/src/session-runtime/boot/config.mjs +5 -2
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +35 -18
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/connect.mjs +83 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
- package/src/session-runtime/mcp-glue.mjs +25 -2
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +83 -15
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +9 -2
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +24 -5
- package/src/session-runtime/resource-mcp-api.mjs +198 -78
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/runtime-review-api.mjs +13 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +12 -1
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-stored-session-views.mjs +11 -3
- package/src/standalone/daemon-telemetry.mjs +55 -0
- package/src/standalone/daemon.mjs +44 -11
- package/src/standalone/session-protocol.mjs +12 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
- package/src/standalone/session-service-api.mjs +5 -0
- package/src/standalone/session-service.mjs +1 -0
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +7 -0
- package/src/tui/app/create-app-pickers.mjs +4 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +13 -16
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-commands.mjs +7 -2
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +1323 -214
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +33 -24
- package/src/tui/session/session-api/extensions.mjs +26 -2
- package/src/tui/session/session-api/integrations.mjs +7 -0
- package/src/tui/session/session-api/lifecycle.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +12 -14
- package/src/tui/session/session-flow/drain.mjs +21 -5
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn.mjs +55 -15
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -35,6 +35,10 @@ export async function runWebhookSession({
|
|
|
35
35
|
workflow = null,
|
|
36
36
|
attachments = null,
|
|
37
37
|
signal = null,
|
|
38
|
+
// Endpoint-authored instructions: the run's ONLY skill-selection input.
|
|
39
|
+
// `prompt` also carries the fenced external payload, which must never
|
|
40
|
+
// select a skill; absent means nothing selects.
|
|
41
|
+
skillSelection = '',
|
|
38
42
|
}) {
|
|
39
43
|
const endpoint = String(name || '').trim();
|
|
40
44
|
const body = String(prompt || '').trim();
|
|
@@ -63,9 +67,17 @@ export async function runWebhookSession({
|
|
|
63
67
|
// askOpts.signal is the parent-abort link: it is cascaded onto the turn
|
|
64
68
|
// controller, so aborting it stops the in-flight provider/tool work instead
|
|
65
69
|
// of leaving a timed-out delivery's session running with live side effects.
|
|
66
|
-
const ask = (turnContent) =>
|
|
67
|
-
askSession(session.id, turnContent, null, null, projectCwd || undefined, undefined,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
const ask = (turnContent, askOpts) =>
|
|
71
|
+
askSession(session.id, turnContent, null, null, projectCwd || undefined, undefined, {
|
|
72
|
+
...askOpts,
|
|
73
|
+
...(signal ? { signal } : {}),
|
|
74
|
+
});
|
|
75
|
+
// Agents the run delegates to report back; each result is the next turn
|
|
76
|
+
// (runAutomationTurns marks those turns as task notifications).
|
|
77
|
+
const result = await runAutomationTurns(
|
|
78
|
+
session.id,
|
|
79
|
+
() => ask(content, { skillSelection: String(skillSelection ?? '') }),
|
|
80
|
+
ask
|
|
81
|
+
);
|
|
70
82
|
return { sessionId: session.id, result: String(result?.content || '') };
|
|
71
83
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Entry the skill-script launcher runs (src/runtime/shared/skill-script-runtime.mjs):
|
|
3
|
+
// <runtime executable> skill-script-entry.mjs <script.mjs> [args...]
|
|
4
|
+
// The script then sees itself as the main module, exactly as under
|
|
5
|
+
// `node <script.mjs> [args...]`, and its exit code is the process's.
|
|
6
|
+
|
|
7
|
+
// Before anything can import sharp: Electron on Linux must use its wasm build.
|
|
8
|
+
await import('./runtime/shared/sharp-electron-linux.mjs');
|
|
9
|
+
// Node mode belongs to this process only; whatever the script starts is a
|
|
10
|
+
// normal child again.
|
|
11
|
+
delete process.env.ELECTRON_RUN_AS_NODE;
|
|
12
|
+
|
|
13
|
+
const { pathToFileURL } = await import('node:url');
|
|
14
|
+
const { canonicalSkillScriptPath, decodeSkillArgv, SKILL_ARGV_ENV } = await import(
|
|
15
|
+
'./runtime/shared/skill-script-runtime.mjs'
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
// The PowerShell `mixdog-skill-node` function passes its arguments in the
|
|
19
|
+
// environment (see renderPowerShellSkillFunction); the script never sees them.
|
|
20
|
+
const envArgv = process.argv.length === 2 ? decodeSkillArgv(process.env[SKILL_ARGV_ENV]) : null;
|
|
21
|
+
delete process.env[SKILL_ARGV_ENV];
|
|
22
|
+
const [execPath, , target, ...args] = envArgv ? [process.argv[0], process.argv[1], ...envArgv] : process.argv;
|
|
23
|
+
if (!target) {
|
|
24
|
+
console.error('Usage: <skill launcher> <script.mjs> [args...]');
|
|
25
|
+
process.exitCode = 2;
|
|
26
|
+
} else {
|
|
27
|
+
const script = canonicalSkillScriptPath(target);
|
|
28
|
+
// The scripts' main check compares import.meta.url with argv[1].
|
|
29
|
+
process.argv = [execPath, script, ...args];
|
|
30
|
+
try {
|
|
31
|
+
await import(pathToFileURL(script).href);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error(error?.stack || String(error));
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/** Whether an idle GC sweep may start: no service call and no running turn
|
|
2
|
+
* (provider stream / tool call). Background-task-only sessions and memory
|
|
3
|
+
* agents do not block it — unlike drainDeferral, which guards shutdown. */
|
|
4
|
+
export function idleGcEligible(work) {
|
|
5
|
+
const { activeCalls = 0, queuedCalls = 0, turnBusySessions = 0 } = work || {};
|
|
6
|
+
return !(activeCalls > 0 || queuedCalls > 0 || turnBusySessions > 0);
|
|
7
|
+
}
|
|
8
|
+
|
|
1
9
|
/** Whether self-shutdown must wait for in-flight work. A forced replacement
|
|
2
10
|
* never waits: shutdown() aborts busy sessions, service calls and agent runs. */
|
|
3
11
|
export function drainDeferral(work, { force = false } = {}) {
|
|
@@ -78,9 +78,17 @@ export function createStoredSessionViews({ desktopRuntime, dataDir }) {
|
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
const store = await desktopRuntime.loadSessionStore();
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
81
|
+
const refreshFromStorage = options.refreshFromStorage === true;
|
|
82
|
+
// Paged ordinary catalog ({ sessions, nextCursor }) only on the explicit
|
|
83
|
+
// `page: { limit, cursor }` option (`limit` alone keeps its old meaning:
|
|
84
|
+
// ignored, full array). An authoritative refresh is never paged.
|
|
85
|
+
const page = options.page && typeof options.page === 'object' ? options.page : null;
|
|
86
|
+
if (page && !refreshFromStorage && store.listStoredSessionSummaryPage) {
|
|
87
|
+
return store.listStoredSessionSummaryPage({ limit: page.limit, cursor: page.cursor });
|
|
88
|
+
}
|
|
89
|
+
// The async listing may answer from the session catalog DB.
|
|
90
|
+
if (store.listStoredSessionSummariesAsync) return store.listStoredSessionSummariesAsync({ refreshFromStorage });
|
|
91
|
+
return store.listStoredSessionSummaries({ refreshFromStorage });
|
|
84
92
|
},
|
|
85
93
|
};
|
|
86
94
|
}
|
|
@@ -93,6 +93,52 @@ export function collectDaemonTelemetry({
|
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Tracks the smallest heapUsed observed right after a major GC (mark-sweep-
|
|
98
|
+
* compact) — the retained-set size, which heapUsed at an arbitrary instant
|
|
99
|
+
* hides. Sampled per telemetry interval; no per-GC logging. Returns null when
|
|
100
|
+
* PerformanceObserver is unavailable.
|
|
101
|
+
*/
|
|
102
|
+
export function createPostGcHeapTracker({
|
|
103
|
+
heapUsed = () => v8.getHeapStatistics().used_heap_size,
|
|
104
|
+
observe = (onGc) => {
|
|
105
|
+
const obs = new PerformanceObserver((list) => {
|
|
106
|
+
for (const entry of list.getEntries()) onGc(entry);
|
|
107
|
+
});
|
|
108
|
+
obs.observe({ entryTypes: ['gc'] });
|
|
109
|
+
return () => obs.disconnect();
|
|
110
|
+
},
|
|
111
|
+
} = {}) {
|
|
112
|
+
let min = -1;
|
|
113
|
+
let disconnect = null;
|
|
114
|
+
try {
|
|
115
|
+
disconnect = observe((entry) => {
|
|
116
|
+
// NODE_PERFORMANCE_GC_MAJOR = 4 (older Node: entry.kind); newer: entry.detail.kind.
|
|
117
|
+
const kind = entry?.detail?.kind ?? entry?.kind;
|
|
118
|
+
if (kind !== 4) return;
|
|
119
|
+
const used = byteCount(heapUsed());
|
|
120
|
+
if (used >= 0 && (min < 0 || used < min)) min = used;
|
|
121
|
+
});
|
|
122
|
+
} catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
/** Min post-major-GC heap since the last take; -1 when none ran. */
|
|
127
|
+
take() {
|
|
128
|
+
const value = min;
|
|
129
|
+
min = -1;
|
|
130
|
+
return value;
|
|
131
|
+
},
|
|
132
|
+
stop() {
|
|
133
|
+
try {
|
|
134
|
+
disconnect?.();
|
|
135
|
+
} catch {
|
|
136
|
+
/* already gone */
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
96
142
|
export function formatDaemonTelemetry(record, reason = 'periodic') {
|
|
97
143
|
const row = record && typeof record === 'object' ? record : collectDaemonTelemetry();
|
|
98
144
|
return [
|
|
@@ -110,6 +156,8 @@ export function formatDaemonTelemetry(record, reason = 'periodic') {
|
|
|
110
156
|
`queuedCalls=${row.queuedCalls}`,
|
|
111
157
|
`busySessions=${row.busySessions}`,
|
|
112
158
|
`busyMemoryAgents=${row.busyMemoryAgents}`,
|
|
159
|
+
// Present only when a major GC ran since the previous line.
|
|
160
|
+
...(byteCount(row.postGcHeapMinBytes) >= 0 ? [`postGcHeapMinBytes=${row.postGcHeapMinBytes}`] : []),
|
|
113
161
|
].join(' ');
|
|
114
162
|
}
|
|
115
163
|
|
|
@@ -123,8 +171,10 @@ export function createDaemonTelemetry({
|
|
|
123
171
|
heapStatistics,
|
|
124
172
|
setIntervalFn = setInterval,
|
|
125
173
|
clearIntervalFn = clearInterval,
|
|
174
|
+
createGcTracker = createPostGcHeapTracker,
|
|
126
175
|
} = {}) {
|
|
127
176
|
let timer = null;
|
|
177
|
+
let gcTracker = null;
|
|
128
178
|
|
|
129
179
|
function emit(reason = 'periodic') {
|
|
130
180
|
try {
|
|
@@ -141,6 +191,8 @@ export function createDaemonTelemetry({
|
|
|
141
191
|
heapStatistics,
|
|
142
192
|
work,
|
|
143
193
|
});
|
|
194
|
+
const postGc = gcTracker?.take() ?? -1;
|
|
195
|
+
if (postGc >= 0) record.postGcHeapMinBytes = postGc;
|
|
144
196
|
log(formatDaemonTelemetry(record, reason));
|
|
145
197
|
return record;
|
|
146
198
|
} catch {
|
|
@@ -159,6 +211,7 @@ export function createDaemonTelemetry({
|
|
|
159
211
|
|
|
160
212
|
function start(intervalMs = DAEMON_TELEMETRY_INTERVAL_MS) {
|
|
161
213
|
if (timer) return timer;
|
|
214
|
+
gcTracker ??= createGcTracker();
|
|
162
215
|
const delay = Number(intervalMs);
|
|
163
216
|
const ms = Number.isFinite(delay) && delay > 0 ? delay : DAEMON_TELEMETRY_INTERVAL_MS;
|
|
164
217
|
const handle = setIntervalFn(() => {
|
|
@@ -174,6 +227,8 @@ export function createDaemonTelemetry({
|
|
|
174
227
|
if (!timer) return;
|
|
175
228
|
clearIntervalFn(timer);
|
|
176
229
|
timer = null;
|
|
230
|
+
gcTracker?.stop();
|
|
231
|
+
gcTracker = null;
|
|
177
232
|
}
|
|
178
233
|
|
|
179
234
|
return { emit, start, stop };
|
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
startOwnerLivenessListener,
|
|
50
50
|
} from './daemon-owner.mjs';
|
|
51
51
|
import { remoteIntentPath } from '../runtime/shared/remote-intent.mjs';
|
|
52
|
+
import { modelProxyClientMode } from '../runtime/shared/model-proxy-mode.mjs';
|
|
52
53
|
import { setChannelNotifySink } from '../runtime/channels/lib/parent-bridge.mjs';
|
|
53
54
|
import { setOwnerContext } from '../runtime/channels/lib/runtime-paths.mjs';
|
|
54
55
|
import { safeIpcSend } from '../runtime/shared/safe-ipc-send.mjs';
|
|
@@ -64,7 +65,7 @@ import {
|
|
|
64
65
|
} from '../runtime/agent/orchestrator/providers/stream-json-pool.mjs';
|
|
65
66
|
import { createAgentDispatchBroker } from './agent-dispatch-broker.mjs';
|
|
66
67
|
import { createChannelTransport } from './channel-transport.mjs';
|
|
67
|
-
import { drainDeferral } from './daemon-drain-policy.mjs';
|
|
68
|
+
import { drainDeferral, idleGcEligible } from './daemon-drain-policy.mjs';
|
|
68
69
|
import { createChannelSessionRouter } from '../session-runtime/services/channel-session-router.mjs';
|
|
69
70
|
import { createSessionTransport } from './session-transport.mjs';
|
|
70
71
|
import { createSessionService } from './session-service.mjs';
|
|
@@ -144,6 +145,11 @@ let ownerLiveness = null;
|
|
|
144
145
|
// The endpoints daemon.json carries once published; a heartbeat re-publishes
|
|
145
146
|
// them when the file goes missing (TEMP cleanup).
|
|
146
147
|
let publishedEndpoints = null;
|
|
148
|
+
// Remote mode only: the loopback relay that lets headless runs started from
|
|
149
|
+
// model shells (skill scripts) reach the PC behind this daemon's model proxy
|
|
150
|
+
// channel (providers/model-proxy-bridge.mjs), and its running-call count.
|
|
151
|
+
let modelProxyBridge = null;
|
|
152
|
+
let modelProxyBridgeActive = 0;
|
|
147
153
|
const eventLoopDelay = monitorEventLoopDelay({ resolution: 20 });
|
|
148
154
|
eventLoopDelay.enable();
|
|
149
155
|
let idleGc = null;
|
|
@@ -218,6 +224,13 @@ async function shutdown(reason, code = 0) {
|
|
|
218
224
|
try {
|
|
219
225
|
setChannelNotifySink(null);
|
|
220
226
|
} catch {}
|
|
227
|
+
// Abort every relayed model call, close the bridge sockets and wait for the
|
|
228
|
+
// calls to settle before anything they depend on goes away.
|
|
229
|
+
try {
|
|
230
|
+
await modelProxyBridge?.close(`daemon shutdown: ${reason}`);
|
|
231
|
+
} catch (e) {
|
|
232
|
+
log(`model proxy bridge stop failed: ${e?.message || e}`);
|
|
233
|
+
}
|
|
221
234
|
try {
|
|
222
235
|
await sessionService?.stop?.(reason);
|
|
223
236
|
} catch (e) {
|
|
@@ -292,10 +305,11 @@ async function shutdown(reason, code = 0) {
|
|
|
292
305
|
* asks whether this process may exit; idle GC asks whether a pause is safe. */
|
|
293
306
|
function inFlightWork() {
|
|
294
307
|
return {
|
|
295
|
-
activeCalls: (transport?.activeCount ?? 0) + (sessionTransport?.activeCount ?? 0),
|
|
308
|
+
activeCalls: (transport?.activeCount ?? 0) + (sessionTransport?.activeCount ?? 0) + modelProxyBridgeActive,
|
|
296
309
|
queuedCalls: (transport?.queuedCount ?? 0) + (sessionTransport?.queuedCount ?? 0),
|
|
297
310
|
busySessions: sessionService?.busyCount ?? 0,
|
|
298
311
|
busyMemoryAgents: agentDispatchBroker?.snapshot?.().inFlight ?? 0,
|
|
312
|
+
turnBusySessions: sessionService?.turnBusyCount ?? 0,
|
|
299
313
|
};
|
|
300
314
|
}
|
|
301
315
|
|
|
@@ -340,11 +354,6 @@ daemonTelemetry = createDaemonTelemetry({
|
|
|
340
354
|
},
|
|
341
355
|
});
|
|
342
356
|
|
|
343
|
-
function daemonHasWorkInFlight() {
|
|
344
|
-
const work = inFlightWork();
|
|
345
|
-
return work.activeCalls > 0 || work.queuedCalls > 0 || work.busySessions > 0 || work.busyMemoryAgents > 0;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
357
|
/** One process, two front doors (channels + sessions): an idle side must never
|
|
349
358
|
* evict a busy one, so every self-shutdown trigger checks BOTH registries. */
|
|
350
359
|
let _lastDeferredLog = { key: '', at: 0, suppressed: 0 };
|
|
@@ -562,9 +571,9 @@ function daemonStatusSnapshot() {
|
|
|
562
571
|
|
|
563
572
|
/** The file every attacher reads to find this daemon: wire identity plus both
|
|
564
573
|
* loopback endpoints and their privileged tokens. */
|
|
565
|
-
function publishDaemonDiscovery({ channel, session }) {
|
|
574
|
+
function publishDaemonDiscovery({ channel, session, modelProxy = null }) {
|
|
566
575
|
// A re-publish keeps the first publication's startedAt.
|
|
567
|
-
publishedEndpoints = { channel, session, startedAt: publishedEndpoints?.startedAt ?? Date.now() };
|
|
576
|
+
publishedEndpoints = { channel, session, modelProxy, startedAt: publishedEndpoints?.startedAt ?? Date.now() };
|
|
568
577
|
writeJsonAtomicSync(
|
|
569
578
|
DAEMON_DISCOVERY_PATH,
|
|
570
579
|
{
|
|
@@ -577,12 +586,34 @@ function publishDaemonDiscovery({ channel, session }) {
|
|
|
577
586
|
endpoints: {
|
|
578
587
|
channel: { port: channel.port, token: channel.token },
|
|
579
588
|
session: { port: session.port, token: session.token },
|
|
589
|
+
...(modelProxy ? { modelProxy: { port: modelProxy.port, token: modelProxy.token } } : {}),
|
|
580
590
|
},
|
|
581
591
|
},
|
|
582
592
|
{ compact: true, secret: true }
|
|
583
593
|
);
|
|
584
594
|
}
|
|
585
595
|
|
|
596
|
+
/** Remote mode only: the model proxy bridge endpoint to publish, or null. */
|
|
597
|
+
async function startModelProxyBridge(bootPhases) {
|
|
598
|
+
if (!modelProxyClientMode()) return null;
|
|
599
|
+
const [{ createModelProxyBridgeServer }, { getModelProxyChannel }] = await Promise.all([
|
|
600
|
+
import('../runtime/agent/orchestrator/providers/model-proxy-bridge.mjs'),
|
|
601
|
+
import('../runtime/agent/orchestrator/providers/model-proxy-channel.mjs'),
|
|
602
|
+
]);
|
|
603
|
+
modelProxyBridge = createModelProxyBridgeServer({
|
|
604
|
+
channel: getModelProxyChannel(),
|
|
605
|
+
// Fenced or shutting down: no new relayed call.
|
|
606
|
+
admit: () => !shuttingDown && admitOwnerWork(),
|
|
607
|
+
trackWork: (active) => {
|
|
608
|
+
modelProxyBridgeActive = active;
|
|
609
|
+
},
|
|
610
|
+
log,
|
|
611
|
+
});
|
|
612
|
+
const endpoint = await bootPhases.measure('model-proxy-bridge-start', () => modelProxyBridge.start());
|
|
613
|
+
log(`model proxy bridge on 127.0.0.1:${endpoint.port}`);
|
|
614
|
+
return endpoint;
|
|
615
|
+
}
|
|
616
|
+
|
|
586
617
|
/** Asked by both front doors before every register/call: an expired lease
|
|
587
618
|
* fences here (answered 503), and after an event-loop stall nothing is
|
|
588
619
|
* served until the record is re-verified as ours. */
|
|
@@ -598,6 +629,7 @@ function fenceDaemon(reason) {
|
|
|
598
629
|
log(`${reason} — refusing new work and stopping so only one daemon serves`);
|
|
599
630
|
sessionTransport?.commitDrain?.(reason);
|
|
600
631
|
transport?.commitDrain?.(reason);
|
|
632
|
+
modelProxyBridge?.abortAll(reason);
|
|
601
633
|
try {
|
|
602
634
|
if (discoveryPid(DAEMON_DISCOVERY_PATH) === process.pid) rmSync(DAEMON_DISCOVERY_PATH, { force: true });
|
|
603
635
|
} catch (e) {
|
|
@@ -787,7 +819,7 @@ async function main() {
|
|
|
787
819
|
// Reclaim deferred garbage while nothing is in flight. V8 keeps a long-lived
|
|
788
820
|
// daemon's dead transcripts resident for as long as the heap limit stays out
|
|
789
821
|
// of sight; a measured sweep on this daemon returned 140MB in 98ms.
|
|
790
|
-
idleGc = createIdleGc({ isBusy:
|
|
822
|
+
idleGc = createIdleGc({ isBusy: () => !idleGcEligible(inFlightWork()), log });
|
|
791
823
|
if (idleGc.arm()) log('idle gc armed');
|
|
792
824
|
|
|
793
825
|
const channelsRuntime = createChannelsRuntimeLoader({
|
|
@@ -890,6 +922,7 @@ async function main() {
|
|
|
890
922
|
admitWork: admitOwnerWork,
|
|
891
923
|
});
|
|
892
924
|
const sessionEndpoint = await bootPhases.measure('session-transport-start', () => sessionTransport.start());
|
|
925
|
+
const modelProxyEndpoint = await startModelProxyBridge(bootPhases);
|
|
893
926
|
// A boot whose holder stopped answering may have been superseded by a
|
|
894
927
|
// contender between beats; never publish over the winner's endpoint. An
|
|
895
928
|
// unreadable record (an antivirus lock) is not a takeover.
|
|
@@ -900,7 +933,7 @@ async function main() {
|
|
|
900
933
|
exitRecorder.setReason(`owner claim superseded by pid=${ownerPid} before publish`, 0);
|
|
901
934
|
process.exit(0);
|
|
902
935
|
}
|
|
903
|
-
publishDaemonDiscovery({ channel: { port, token }, session: sessionEndpoint });
|
|
936
|
+
publishDaemonDiscovery({ channel: { port, token }, session: sessionEndpoint, modelProxy: modelProxyEndpoint });
|
|
904
937
|
bootPhases.mark('discovery-published');
|
|
905
938
|
log(`session front door on 127.0.0.1:${sessionEndpoint.port}`);
|
|
906
939
|
|
|
@@ -13,11 +13,13 @@ export const SESSION_READ_ACTIONS = Object.freeze([
|
|
|
13
13
|
'getChannelSetup',
|
|
14
14
|
'getChannelWorkerStatus',
|
|
15
15
|
'getCompactionSettings',
|
|
16
|
+
'getConversationImportJobs',
|
|
16
17
|
'getDeveloperSettings',
|
|
17
18
|
'getDisabledSkills',
|
|
18
19
|
'getMediaDefault',
|
|
19
20
|
'getMediaJob',
|
|
20
21
|
'getMcpServerConfig',
|
|
22
|
+
'getMcpOAuthLoginStatus',
|
|
21
23
|
'getOnboardingStatus',
|
|
22
24
|
'getOAuthProviderLoginStatus',
|
|
23
25
|
'getOutputStyle',
|
|
@@ -57,6 +59,7 @@ export const SESSION_READ_ACTIONS = Object.freeze([
|
|
|
57
59
|
'hooksStatus',
|
|
58
60
|
'inheritancePreflight',
|
|
59
61
|
'listAgents',
|
|
62
|
+
'listImportableConversations',
|
|
60
63
|
'listMediaAssets',
|
|
61
64
|
'listMediaLanes',
|
|
62
65
|
'listOutputStyles',
|
|
@@ -83,15 +86,19 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
|
|
|
83
86
|
'agentControl',
|
|
84
87
|
'authenticateProvider',
|
|
85
88
|
'beginOAuthProviderLogin',
|
|
89
|
+
'beginMcpOAuthLogin',
|
|
86
90
|
'updateProviderAccounts',
|
|
87
91
|
'cacheMediaThumbnail',
|
|
88
92
|
'cancelMediaJob',
|
|
89
93
|
'cancelOAuthProviderLogin',
|
|
94
|
+
'cancelMcpOAuthLogin',
|
|
95
|
+
'cancelConversationImport',
|
|
90
96
|
'checkForUpdate',
|
|
91
97
|
'clear',
|
|
92
98
|
'compact',
|
|
93
99
|
'completeOnboarding',
|
|
94
100
|
'completeOAuthProviderLogin',
|
|
101
|
+
'completeMcpOAuthLogin',
|
|
95
102
|
'consumeCodexRateLimitResetCredit',
|
|
96
103
|
'createWorkflow',
|
|
97
104
|
'deleteAgentDefinition',
|
|
@@ -115,9 +122,11 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
|
|
|
115
122
|
'memoryControl',
|
|
116
123
|
'openMediaAsset',
|
|
117
124
|
'openMediaFolder',
|
|
125
|
+
'probeMcpServerAuth',
|
|
118
126
|
'pushNotice',
|
|
119
127
|
'recall',
|
|
120
128
|
'reconnectMcp',
|
|
129
|
+
'registerConversationImportFile',
|
|
121
130
|
'reloadPlugins',
|
|
122
131
|
'reloadSkills',
|
|
123
132
|
'rememberPromptHistory',
|
|
@@ -139,6 +148,7 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
|
|
|
139
148
|
'revertTurnReviewFile',
|
|
140
149
|
'revertTurnChanges',
|
|
141
150
|
'reapplyTurnChanges',
|
|
151
|
+
'clearSessionChangeHistory',
|
|
142
152
|
'rewindToItem',
|
|
143
153
|
'runDoctor',
|
|
144
154
|
'runScheduleNow',
|
|
@@ -196,8 +206,10 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
|
|
|
196
206
|
'setWebhookEnabled',
|
|
197
207
|
'setWorkflow',
|
|
198
208
|
'setOrchestrationMode',
|
|
209
|
+
'signOutMcpServer',
|
|
199
210
|
'saveStarterGuideState',
|
|
200
211
|
'skipOnboarding',
|
|
212
|
+
'startConversationImport',
|
|
201
213
|
'startMediaJob',
|
|
202
214
|
'stopShellJob',
|
|
203
215
|
'switchContext',
|
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
// agent-tree/agent-cancel.mjs
|
|
2
2
|
// Cancelling an agent subtree: descendants first, then a durable canonical
|
|
3
3
|
// close of the session itself. Concurrent cancels of one id share a run.
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
cancelBackgroundTask,
|
|
6
|
+
cancelBackgroundTasks,
|
|
7
|
+
listBackgroundTasks,
|
|
8
|
+
} from '../../../runtime/shared/background-tasks.mjs';
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
// Cancel the running Agent task(s) bound to this session itself (owned by its
|
|
11
|
+
// parent) BEFORE the session closes, so the owner hears `cancelled` with the
|
|
12
|
+
// turn's partial output instead of the closed turn failing the task.
|
|
13
|
+
function cancelOwnAgentTasks(sessionId, reason) {
|
|
14
|
+
for (const row of listBackgroundTasks({ surface: 'agent' })) {
|
|
15
|
+
if (row.status === 'running' && row.sessionId === sessionId) cancelBackgroundTask(row.task_id, reason);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createAgentCancellation({
|
|
20
|
+
registry,
|
|
21
|
+
rehydrateAgentSessions,
|
|
22
|
+
sessionOwner,
|
|
23
|
+
entryForSession,
|
|
24
|
+
log,
|
|
25
|
+
rememberCancelTranscript,
|
|
26
|
+
}) {
|
|
7
27
|
const agentCancelRuns = new Map();
|
|
8
28
|
|
|
9
29
|
/** The runtime entry that can close this descriptor: the live owner, else a
|
|
@@ -39,6 +59,7 @@ export function createAgentCancellation({ registry, rehydrateAgentSessions, sess
|
|
|
39
59
|
});
|
|
40
60
|
const children = registry.childrenOf(id);
|
|
41
61
|
await Promise.all(children.map((childId) => cancelAgentTree(childId, reason)));
|
|
62
|
+
cancelOwnAgentTasks(id, reason);
|
|
42
63
|
const descriptor = registry.get(id);
|
|
43
64
|
if (!descriptor) return children.length > 0;
|
|
44
65
|
if (descriptor.closed) return true;
|
|
@@ -47,6 +68,16 @@ export function createAgentCancellation({ registry, rehydrateAgentSessions, sess
|
|
|
47
68
|
if (typeof closeCanonical !== 'function') {
|
|
48
69
|
throw new TypeError('session runtime must implement closeCanonicalSession');
|
|
49
70
|
}
|
|
71
|
+
// The close clears the transcript: capture a running turn's transcript
|
|
72
|
+
// first so the cancelled turn still hands off its partial output.
|
|
73
|
+
if (descriptor.status === 'running') {
|
|
74
|
+
try {
|
|
75
|
+
const { messages } = await entry.runtime.readModelMessages(0);
|
|
76
|
+
rememberCancelTranscript(id, messages);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
log(`agent cancel transcript read failed session=${id}: ${error?.message || error}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
50
81
|
const closed = await closeCanonical.call(entry.runtime, reason);
|
|
51
82
|
if (closed !== true) throw new Error(`agent session ${id} could not be durably closed`);
|
|
52
83
|
descriptor.closed = true;
|
|
@@ -12,16 +12,23 @@ export function createAgentTurns({
|
|
|
12
12
|
retainUnwatched,
|
|
13
13
|
createSession,
|
|
14
14
|
takeWatchdogStop,
|
|
15
|
+
takeCancelTranscript,
|
|
15
16
|
}) {
|
|
16
17
|
const createAgentChild = createAgentChildFactory({ registry, rehydrateAgentSessions, createSession });
|
|
17
18
|
|
|
18
|
-
// The progress watchdog
|
|
19
|
-
// the assistant text the turn produced, so the owner still gets a
|
|
20
|
-
// result.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
// The turn was stopped (progress watchdog or cancellation): rethrow its error
|
|
20
|
+
// carrying the assistant text the turn produced, so the owner still gets a
|
|
21
|
+
// partial result. A cancel that closed the session captured the transcript
|
|
22
|
+
// before the close cleared it.
|
|
23
|
+
async function withPartialHandoff(runtime, sessionId, error, messageStart) {
|
|
24
|
+
try {
|
|
25
|
+
const captured = takeCancelTranscript(sessionId);
|
|
26
|
+
const messages = captured
|
|
27
|
+
? captured.slice(messageStart)
|
|
28
|
+
: (await runtime.readModelMessages(messageStart)).messages;
|
|
29
|
+
const partial = partialHandoffTextFromSession({ messages });
|
|
30
|
+
if (partial) error.partialHandoff = partial;
|
|
31
|
+
} catch {}
|
|
25
32
|
return error;
|
|
26
33
|
}
|
|
27
34
|
|
|
@@ -44,6 +51,7 @@ export function createAgentTurns({
|
|
|
44
51
|
}
|
|
45
52
|
// A stop left over from an earlier turn must not relabel this one.
|
|
46
53
|
takeWatchdogStop(sessionId);
|
|
54
|
+
takeCancelTranscript(sessionId);
|
|
47
55
|
// Transcript length before this turn: where a watchdog stop's partial
|
|
48
56
|
// output starts.
|
|
49
57
|
const { messageCount: messageStart } = await entry.runtime.readModelMessages(Number.MAX_SAFE_INTEGER);
|
|
@@ -64,9 +72,16 @@ export function createAgentTurns({
|
|
|
64
72
|
throw new Error(String(detail.error || 'agent session turn failed'));
|
|
65
73
|
}
|
|
66
74
|
if (detail?.status === 'cancelled') {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
const stop = takeWatchdogStop(sessionId) || new Error('agent session turn cancelled');
|
|
76
|
+
throw await withPartialHandoff(entry.runtime, sessionId, stop, messageStart);
|
|
77
|
+
}
|
|
78
|
+
// Only a completed turn has a result; a rejected submission (session
|
|
79
|
+
// closing/terminal, steering persist failure) or any unknown status is a
|
|
80
|
+
// failure, never an empty completion.
|
|
81
|
+
if (detail?.status !== 'done' && detail?.status !== 'completed') {
|
|
82
|
+
const status = String(detail?.status || 'unknown');
|
|
83
|
+
const reason = String(detail?.reason || detail?.error || '').trim();
|
|
84
|
+
throw new Error(`agent turn ${status}${reason ? `: ${reason}` : ''}`);
|
|
70
85
|
}
|
|
71
86
|
const result = detail?.result || { content: '' };
|
|
72
87
|
descriptor.status = 'idle';
|
|
@@ -81,6 +96,7 @@ export function createAgentTurns({
|
|
|
81
96
|
descriptor.stage = descriptor.status;
|
|
82
97
|
throw error;
|
|
83
98
|
} finally {
|
|
99
|
+
takeCancelTranscript(sessionId);
|
|
84
100
|
descriptor.updatedAt = Date.now();
|
|
85
101
|
retainUnwatched(entry, 'agent child idle');
|
|
86
102
|
}
|
|
@@ -37,6 +37,16 @@ export function createAgentTree({
|
|
|
37
37
|
watchdogStops.delete(sessionId);
|
|
38
38
|
return error;
|
|
39
39
|
};
|
|
40
|
+
// Transcripts of running turns captured by a cancel just before it closes
|
|
41
|
+
// (and clears) the session, so the cancelled turn still reports the output
|
|
42
|
+
// it produced.
|
|
43
|
+
const cancelTranscripts = new Map();
|
|
44
|
+
const rememberCancelTranscript = (sessionId, messages) => cancelTranscripts.set(sessionId, messages);
|
|
45
|
+
const takeCancelTranscript = (sessionId) => {
|
|
46
|
+
const messages = cancelTranscripts.get(sessionId) || null;
|
|
47
|
+
cancelTranscripts.delete(sessionId);
|
|
48
|
+
return messages;
|
|
49
|
+
};
|
|
40
50
|
function getSessionProgressSnapshot(sessionId) {
|
|
41
51
|
const runtime = sessionOwner(sessionId)?.runtime;
|
|
42
52
|
if (typeof runtime?.getTurnLiveness !== 'function') return null;
|
|
@@ -58,6 +68,7 @@ export function createAgentTree({
|
|
|
58
68
|
retainUnwatched,
|
|
59
69
|
createSession,
|
|
60
70
|
takeWatchdogStop,
|
|
71
|
+
takeCancelTranscript,
|
|
61
72
|
});
|
|
62
73
|
const { cancelAgentTree, cancelAgentDescendants } = createAgentCancellation({
|
|
63
74
|
registry,
|
|
@@ -65,6 +76,7 @@ export function createAgentTree({
|
|
|
65
76
|
sessionOwner,
|
|
66
77
|
entryForSession,
|
|
67
78
|
log,
|
|
79
|
+
rememberCancelTranscript,
|
|
68
80
|
});
|
|
69
81
|
|
|
70
82
|
/** The descriptor as callers see it: status from the live runtime when one
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
// again, and the session's own lane runs the retry under the entry's
|
|
9
9
|
// generation. Overdue entries run as soon as the scheduler starts.
|
|
10
10
|
|
|
11
|
+
import { isAgentOnlySession } from '../../runtime/shared/quota-resume-store.mjs';
|
|
12
|
+
|
|
11
13
|
/** A still-exhausted reading is re-taken once, this much later. */
|
|
12
14
|
export const QUOTA_RESUME_RETRY_MS = 5 * 60_000;
|
|
13
15
|
/** A busy session is re-checked this much later, without spending an attempt. */
|
|
@@ -30,6 +32,12 @@ async function resumeDueEntry(entry, { store, materializeSession, readQuotaUsabl
|
|
|
30
32
|
return 'unavailable';
|
|
31
33
|
}
|
|
32
34
|
if (!isCurrent(store, entry)) return 'cancelled';
|
|
35
|
+
// A delegated agent child never owns a resume (the Lead decides retries), so
|
|
36
|
+
// an entry persisted for one never fires, whatever wrote it.
|
|
37
|
+
if (isAgentOnlySession({ id: sessionId, ...runtime?.session })) {
|
|
38
|
+
store.cancelQuotaResumeEntry(sessionId, { generation });
|
|
39
|
+
return 'agent-session';
|
|
40
|
+
}
|
|
33
41
|
let usable = false;
|
|
34
42
|
try {
|
|
35
43
|
usable = await readQuotaUsable(entry.provider, entry.model);
|
|
@@ -28,6 +28,12 @@ export function createBusyTracker({ sessions, currentSessionId }) {
|
|
|
28
28
|
// reaches a terminal state and its completion can be delivered back into
|
|
29
29
|
// this session.
|
|
30
30
|
if (sessionId && hasActiveBackgroundTasks({ callerSessionId: sessionId })) return true;
|
|
31
|
+
return sessionTurnBusy(entry);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// A turn is running (provider stream / tool call / queued input). Background
|
|
35
|
+
// tasks are deliberately not counted: they run outside the heap-churning turn.
|
|
36
|
+
function sessionTurnBusy(entry) {
|
|
31
37
|
if (typeof entry?.busy === 'boolean') return entry.busy;
|
|
32
38
|
try {
|
|
33
39
|
return updateEntryBusy(entry, entry.runtime.getState?.() || {});
|
|
@@ -46,5 +52,13 @@ export function createBusyTracker({ sessions, currentSessionId }) {
|
|
|
46
52
|
return count;
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
|
|
55
|
+
function liveTurnBusyCount() {
|
|
56
|
+
let count = 0;
|
|
57
|
+
for (const entry of sessions) {
|
|
58
|
+
if (sessionTurnBusy(entry)) count += 1;
|
|
59
|
+
}
|
|
60
|
+
return count;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { stateBusy, updateEntryBusy, sessionBusy, liveBusyCount, liveTurnBusyCount };
|
|
50
64
|
}
|
|
@@ -101,15 +101,20 @@ export function createSessionActionCalls(ctx) {
|
|
|
101
101
|
if (typeof listSessions !== 'function') {
|
|
102
102
|
throw new Error('session catalog is unavailable');
|
|
103
103
|
}
|
|
104
|
-
const
|
|
104
|
+
const listed = await listSessions({
|
|
105
105
|
...(options || {}),
|
|
106
106
|
// Agent-only records are an internal ancestry/reuse source, never part
|
|
107
107
|
// of the ordinary session catalog returned over the public transport.
|
|
108
108
|
includeAgentOnly: false,
|
|
109
109
|
});
|
|
110
|
+
// A `page: { limit, cursor }` request answers one page: { sessions, nextCursor }.
|
|
111
|
+
const page = listed && !Array.isArray(listed) && Array.isArray(listed.sessions) ? listed : null;
|
|
112
|
+
const sessions = page ? page.sessions : listed;
|
|
110
113
|
const remoteSession = typeof getRemoteSessionState === 'function' ? await getRemoteSessionState() : null;
|
|
114
|
+
const nextCursor = typeof page?.nextCursor === 'string' ? page.nextCursor : null;
|
|
111
115
|
return {
|
|
112
116
|
sessions: sanitizeForWire(Array.isArray(sessions) ? sessions : []),
|
|
117
|
+
...(page ? { nextCursor } : {}),
|
|
113
118
|
remoteSession: sanitizeForWire(remoteSession) ?? null,
|
|
114
119
|
};
|
|
115
120
|
}
|
|
@@ -29,6 +29,7 @@ export function createSessionServiceApi({
|
|
|
29
29
|
methods,
|
|
30
30
|
getSize,
|
|
31
31
|
getBusyCount,
|
|
32
|
+
getTurnBusyCount,
|
|
32
33
|
getStatus,
|
|
33
34
|
getExternalClientCount,
|
|
34
35
|
}) {
|
|
@@ -46,6 +47,10 @@ export function createSessionServiceApi({
|
|
|
46
47
|
get busyCount() {
|
|
47
48
|
return getBusyCount();
|
|
48
49
|
},
|
|
50
|
+
/** Sessions with a running turn; background-task-only sessions excluded. */
|
|
51
|
+
get turnBusyCount() {
|
|
52
|
+
return getTurnBusyCount();
|
|
53
|
+
},
|
|
49
54
|
get status() {
|
|
50
55
|
return getStatus();
|
|
51
56
|
},
|