mixdog 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/package.json +2 -1
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +7 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +58 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +12 -6
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +114 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +37 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +25 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +87 -5
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +13 -13
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +355 -37
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +93 -47
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +55 -10
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +26 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +121 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +42 -24
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +53 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +25 -4
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +71 -24
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +147 -8
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +63 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +31 -26
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +108 -3
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +6 -0
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +268 -100
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
- package/src/runtime/shared/turn-snapshot.mjs +857 -683
- package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +13 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +72 -7
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +17 -5
- package/src/session-runtime/model-route/set-route.mjs +2 -2
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +8 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +19 -0
- package/src/standalone/daemon.mjs +61 -1
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +6 -1
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +13 -3
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/dist/index.mjs +2413 -1465
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/session-api/commands.mjs +10 -0
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/integrations.mjs +9 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +2 -1
- package/src/tui/session/session-api/settings.mjs +6 -0
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +12 -5
- package/src/workflows/default/WORKFLOW.md +3 -1
|
@@ -79,6 +79,15 @@ export function createBuiltinToolSettings(
|
|
|
79
79
|
invalidateContextStatusCache();
|
|
80
80
|
return this.getRecapSettings();
|
|
81
81
|
},
|
|
82
|
+
// Whether the model may title the session (session tool, action=rename).
|
|
83
|
+
// Absent config means on; only the opt-out is stored.
|
|
84
|
+
getSessionTitleSettings() {
|
|
85
|
+
return { aiSessionTitles: getConfig()?.aiSessionTitles !== false };
|
|
86
|
+
},
|
|
87
|
+
setAiSessionTitles(enabled) {
|
|
88
|
+
saveConfigAndAdopt({ ...getConfig(), aiSessionTitles: enabled !== false });
|
|
89
|
+
return this.getSessionTitleSettings();
|
|
90
|
+
},
|
|
82
91
|
getToolModuleSettings() {
|
|
83
92
|
const config = getConfig();
|
|
84
93
|
const localProvider = getLocalProviderStatus?.() || {};
|
|
@@ -92,6 +92,7 @@ function routeInput(source) {
|
|
|
92
92
|
if (clean(source.model)) next.model = clean(source.model);
|
|
93
93
|
if (clean(source.effort)) next.effort = clean(source.effort);
|
|
94
94
|
if (typeof source.fast === 'boolean') next.fast = source.fast;
|
|
95
|
+
if (typeof source.autoEffort === 'boolean') next.autoEffort = source.autoEffort;
|
|
95
96
|
if (Object.hasOwn(source, 'modelParameters')) next.modelParameters = { ...source.modelParameters };
|
|
96
97
|
if (Object.hasOwn(source, 'contextPercent')) next.contextPercent = source.contextPercent;
|
|
97
98
|
if (Object.hasOwn(source, 'contextTokens')) next.contextTokens = source.contextTokens;
|
|
@@ -141,6 +142,34 @@ function publicProviderRows(setup) {
|
|
|
141
142
|
};
|
|
142
143
|
}
|
|
143
144
|
|
|
145
|
+
/** Minimal provider rows for the model: only providers with a credential (or
|
|
146
|
+
* one needing re-authentication), counts instead of account rosters. */
|
|
147
|
+
function configuredProviderRows(rows, accountCount) {
|
|
148
|
+
const providers = [];
|
|
149
|
+
let notConfigured = 0;
|
|
150
|
+
for (const [kind, list] of [
|
|
151
|
+
['api', rows.api],
|
|
152
|
+
['oauth', rows.oauth],
|
|
153
|
+
['local', rows.local],
|
|
154
|
+
]) {
|
|
155
|
+
for (const row of list) {
|
|
156
|
+
if (!row.authenticated && !row.reauthRequired) {
|
|
157
|
+
notConfigured += 1;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
providers.push({
|
|
161
|
+
id: row.id,
|
|
162
|
+
kind,
|
|
163
|
+
authenticated: row.authenticated,
|
|
164
|
+
status: row.status,
|
|
165
|
+
...(row.reauthRequired ? { reauthRequired: true } : {}),
|
|
166
|
+
...(kind === 'oauth' ? { accounts: row.authenticated ? accountCount(row.id) : 0 } : {}),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { ...(rows.pendingSecrets ? { pendingSecrets: true } : {}), providers, notConfigured };
|
|
171
|
+
}
|
|
172
|
+
|
|
144
173
|
/** OAuth account roster without usage meters or provider-side identities. */
|
|
145
174
|
function publicAccounts(pool) {
|
|
146
175
|
return {
|
|
@@ -300,8 +329,9 @@ const SETUP_STATUS_READERS = {
|
|
|
300
329
|
'local-provider': (rt) => rt.getToolModuleSettings().localProvider,
|
|
301
330
|
features: (rt, { getConfig }) => featureStatus(rt, getConfig),
|
|
302
331
|
shell: (rt) => rt.getSystemShell?.() || {},
|
|
303
|
-
providers: async (rt) => {
|
|
332
|
+
providers: async (rt, { detail }) => {
|
|
304
333
|
const rows = publicProviderRows(await rt.getProviderSetup?.({}));
|
|
334
|
+
if (!detail) return configuredProviderRows(rows, (id) => rt.getProviderAccounts(id).accounts.length);
|
|
305
335
|
rows.oauth = rows.oauth.map((row) =>
|
|
306
336
|
row.authenticated ? { ...row, accounts: publicAccounts(rt.getProviderAccounts(row.id)) } : row
|
|
307
337
|
);
|
|
@@ -339,7 +369,7 @@ function validateSetupInput(args) {
|
|
|
339
369
|
if (action !== 'set_agent_route' && Object.hasOwn(args.route, 'disabled')) {
|
|
340
370
|
throw new Error('route.disabled is only accepted by set_agent_route');
|
|
341
371
|
}
|
|
342
|
-
for (const field of ['contextPercent', 'contextTokens']) {
|
|
372
|
+
for (const field of ['contextPercent', 'contextTokens', 'autoEffort']) {
|
|
343
373
|
if (action !== 'set_route' && action !== 'set_agent_route' && Object.hasOwn(args.route, field)) {
|
|
344
374
|
throw new Error(`route.${field} is only accepted by set_route and set_agent_route`);
|
|
345
375
|
}
|
|
@@ -401,7 +431,7 @@ const SETUP_ACTION_HANDLERS = {
|
|
|
401
431
|
status: async (_rt, args, { readStatus, requestDesktop }) => {
|
|
402
432
|
const domain = clean(args.domain) || 'summary';
|
|
403
433
|
requireEnum(domain, SETUP_STATUS_DOMAINS, 'domain');
|
|
404
|
-
return { domain, ...(await readStatus(domain, requestDesktop)) };
|
|
434
|
+
return { domain, ...(await readStatus(domain, requestDesktop, args.detail === true)) };
|
|
405
435
|
},
|
|
406
436
|
open: (_rt, args, { openSurface }) => openSurface(args.target),
|
|
407
437
|
set_route: async (rt, args) => {
|
|
@@ -631,11 +661,11 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
|
|
|
631
661
|
return facade;
|
|
632
662
|
};
|
|
633
663
|
|
|
634
|
-
async function readStatus(domain, requestDesktop) {
|
|
664
|
+
async function readStatus(domain, requestDesktop, detail) {
|
|
635
665
|
const rt = api();
|
|
636
666
|
if (SETUP_DESKTOP_DOMAINS.includes(domain)) return requestDesktop({ action: 'status', domain });
|
|
637
667
|
if (!Object.hasOwn(SETUP_STATUS_READERS, domain)) throw new Error(`setup: unknown status domain "${domain}"`);
|
|
638
|
-
return SETUP_STATUS_READERS[domain](rt, { domain, getConfig: () => getConfig?.() || {} });
|
|
668
|
+
return SETUP_STATUS_READERS[domain](rt, { domain, detail, getConfig: () => getConfig?.() || {} });
|
|
639
669
|
}
|
|
640
670
|
|
|
641
671
|
function openSurface(target) {
|
|
@@ -669,7 +699,7 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
|
|
|
669
699
|
dispose: desktop.dispose,
|
|
670
700
|
async execute(args = {}, options = {}) {
|
|
671
701
|
const result = await execute(args, options);
|
|
672
|
-
if (READ_ONLY_SETUP_ACTIONS.has(args.action)) return JSON.stringify(result ?? {}
|
|
702
|
+
if (READ_ONLY_SETUP_ACTIONS.has(args.action)) return JSON.stringify(result ?? {});
|
|
673
703
|
await flushSettings?.();
|
|
674
704
|
// Attached surfaces re-read what changed instead of waiting for their
|
|
675
705
|
// next open or cache expiry.
|
|
@@ -1,11 +1,81 @@
|
|
|
1
1
|
import { SETUP_EXTENDED_PROPERTIES, SETUP_DESKTOP_ACTIONS } from './settings-contract.mjs';
|
|
2
2
|
import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
|
|
3
|
+
import { OPENAI_COMPAT_PRESETS } from '../../runtime/agent/orchestrator/providers/openai-compat-presets.mjs';
|
|
3
4
|
|
|
4
5
|
const own = (value, key) => Object.hasOwn(value || {}, key);
|
|
5
6
|
const pick = (value, keys) => Object.fromEntries(keys.filter((key) => own(value, key)).map((key) => [key, value[key]]));
|
|
6
7
|
const entryKeys = Object.keys(SETUP_EXTENDED_PROPERTIES.entry.properties);
|
|
7
8
|
const definitionKeys = Object.keys(SETUP_EXTENDED_PROPERTIES.definition.properties);
|
|
8
9
|
|
|
10
|
+
const MODEL_PAGE_DEFAULT = 25;
|
|
11
|
+
|
|
12
|
+
function providerIndex(rows) {
|
|
13
|
+
const counts = new Map();
|
|
14
|
+
for (const row of rows) counts.set(row.provider, (counts.get(row.provider) || 0) + 1);
|
|
15
|
+
return [...counts].map(([provider, count]) => {
|
|
16
|
+
const defaultModel = OPENAI_COMPAT_PRESETS[provider]?.defaultModel;
|
|
17
|
+
return { provider, count, ...(defaultModel ? { defaultModel } : {}) };
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function compactModelRow(row) {
|
|
22
|
+
const context = row.contextWindow || null;
|
|
23
|
+
const maxContext = Number(row.maxContextWindow) || 0;
|
|
24
|
+
return {
|
|
25
|
+
id: row.id,
|
|
26
|
+
display: row.display || row.id,
|
|
27
|
+
context,
|
|
28
|
+
...(maxContext > (context || 0) ? { maxContext } : {}),
|
|
29
|
+
efforts: (row.effortOptions || []).map((option) => option.value),
|
|
30
|
+
...(row.fastCapable === true ? { fast: true } : {}),
|
|
31
|
+
...(row.supportsVision === true ? { vision: true } : {}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const isPresent = (value) =>
|
|
36
|
+
value != null &&
|
|
37
|
+
value !== '' &&
|
|
38
|
+
value !== false &&
|
|
39
|
+
!(typeof value === 'object' && !Object.keys(value).length);
|
|
40
|
+
|
|
41
|
+
/** Everything set_route can use for one model; empty and false fields omitted. */
|
|
42
|
+
function modelDetail(row) {
|
|
43
|
+
const detail = {
|
|
44
|
+
provider: row.provider,
|
|
45
|
+
id: row.id,
|
|
46
|
+
display: row.display || row.id,
|
|
47
|
+
context: row.contextWindow,
|
|
48
|
+
maxContext: Number(row.maxContextWindow) > row.contextWindow ? row.maxContextWindow : null,
|
|
49
|
+
outputTokens: row.outputTokens,
|
|
50
|
+
vision: row.supportsVision,
|
|
51
|
+
webSearch: row.supportsWebSearch,
|
|
52
|
+
reasoning: row.supportsReasoning,
|
|
53
|
+
effortOptions: (row.effortOptions || []).map(({ value, label }) => ({ value, label })),
|
|
54
|
+
defaultEffort: row.defaultEffort,
|
|
55
|
+
fastCapable: row.fastCapable,
|
|
56
|
+
fastEfforts: row.fastEfforts,
|
|
57
|
+
defaultFast: row.defaultFast,
|
|
58
|
+
serviceTiers: row.serviceTiers,
|
|
59
|
+
defaultServiceTier: row.defaultServiceTier,
|
|
60
|
+
additionalSpeedTiers: row.additionalSpeedTiers,
|
|
61
|
+
modelParameterOptions: row.modelParameterOptions,
|
|
62
|
+
parameterVariants: row.parameterVariants,
|
|
63
|
+
defaultModelParameters: row.defaultModelParameters,
|
|
64
|
+
supportsMaxMode: row.supportsMaxMode,
|
|
65
|
+
};
|
|
66
|
+
return Object.fromEntries(Object.entries(detail).filter(([, value]) => isPresent(value)));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function findModel(rows, id, provider) {
|
|
70
|
+
const matches = rows.filter((row) => row.id === id && (!provider || row.provider === provider));
|
|
71
|
+
if (!matches.length) {
|
|
72
|
+
throw new Error(`model "${id}" not found${provider ? ` for provider "${provider}"` : ''}; list_models with catalog.provider returns its model ids`);
|
|
73
|
+
}
|
|
74
|
+
const providers = [...new Set(matches.map((row) => row.provider))];
|
|
75
|
+
if (providers.length > 1) throw new Error(`model "${id}" is offered by ${providers.join(', ')}; pass catalog.provider`);
|
|
76
|
+
return matches[0];
|
|
77
|
+
}
|
|
78
|
+
|
|
9
79
|
export function publicAutomation(row) {
|
|
10
80
|
const result = {
|
|
11
81
|
...pick(row, entryKeys),
|
|
@@ -136,12 +206,22 @@ async function saveDefinition(rt, args) {
|
|
|
136
206
|
export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
137
207
|
set_local_context: (rt, args) => rt.setLocalProviderContext(args.modelId, args.localContextWindow),
|
|
138
208
|
async list_models(rt, args) {
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return {
|
|
209
|
+
const { provider, model, page = 1, limit = MODEL_PAGE_DEFAULT, webSearch, refresh } = args.catalog || {};
|
|
210
|
+
const rows = webSearch
|
|
211
|
+
? await rt.listWebSearchModels({ refresh: refresh === true })
|
|
212
|
+
: await rt.listProviderModels({ refresh: refresh === true });
|
|
213
|
+
if (model) return { model: modelDetail(findModel(rows, model, provider)) };
|
|
214
|
+
if (!provider) return { providers: providerIndex(rows) };
|
|
215
|
+
const own = rows.filter((row) => row.provider === provider);
|
|
216
|
+
const pages = Math.max(1, Math.ceil(own.length / limit));
|
|
217
|
+
return {
|
|
218
|
+
provider,
|
|
219
|
+
total: own.length,
|
|
220
|
+
page,
|
|
221
|
+
pages,
|
|
222
|
+
...(page < pages ? { nextPage: page + 1 } : {}),
|
|
223
|
+
models: own.slice((page - 1) * limit, page * limit).map(compactModelRow),
|
|
224
|
+
};
|
|
145
225
|
},
|
|
146
226
|
set_orchestration_mode: (rt, args) => rt.setOrchestrationMode(args.mode),
|
|
147
227
|
get_mcp_server: async (rt, args) => publicMcpConfig(await rt.getMcpServerConfig(args.name)),
|
|
@@ -114,9 +114,19 @@ export const SETUP_MCP_SCHEMA = object({
|
|
|
114
114
|
|
|
115
115
|
export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
|
|
116
116
|
catalog: object({
|
|
117
|
-
provider:
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
provider: {
|
|
118
|
+
...text,
|
|
119
|
+
description: 'list_models: omit for the provider index; set for that provider\'s compact model rows.',
|
|
120
|
+
},
|
|
121
|
+
model: {
|
|
122
|
+
...text,
|
|
123
|
+
description:
|
|
124
|
+
'list_models: one model id; returns its full options (efforts, fast, service tiers, modelParameterOptions, parameterVariants) for set_route. Add provider when several offer the id.',
|
|
125
|
+
},
|
|
126
|
+
page: { type: 'integer', minimum: 1, description: 'list_models with provider: 1-based page; default 1.' },
|
|
127
|
+
limit: { type: 'integer', minimum: 1, maximum: 100, description: 'list_models with provider: rows per page; default 25.' },
|
|
128
|
+
webSearch: { ...boolean, description: 'list_models: native-search capable models only.' },
|
|
129
|
+
refresh: { ...boolean, description: 'list_models: refresh the catalog first.' },
|
|
120
130
|
}),
|
|
121
131
|
localContextWindow: {
|
|
122
132
|
type: ['integer', 'null'],
|
|
@@ -68,7 +68,7 @@ export const SETUP_OPEN_TARGETS = Object.freeze([
|
|
|
68
68
|
// Runtime dispatch contract. A trailing ? denotes an optional field. Keep
|
|
69
69
|
// this out of the wire schema: field descriptions already name their actions.
|
|
70
70
|
export const SETUP_ACTION_FIELDS = Object.freeze({
|
|
71
|
-
status: 'domain?',
|
|
71
|
+
status: 'domain? detail?',
|
|
72
72
|
open: 'target',
|
|
73
73
|
set_route: 'route',
|
|
74
74
|
set_agent_route: 'agent route',
|
|
@@ -136,6 +136,10 @@ const ROUTE_SCHEMA = {
|
|
|
136
136
|
model: { type: 'string' },
|
|
137
137
|
effort: { type: 'string' },
|
|
138
138
|
fast: { type: 'boolean' },
|
|
139
|
+
autoEffort: {
|
|
140
|
+
type: 'boolean',
|
|
141
|
+
description: 'Main and agent routes only: Auto reasoning for this route; omitted = preserved.',
|
|
142
|
+
},
|
|
139
143
|
modelParameters: { type: 'object', additionalProperties: { type: 'string' } },
|
|
140
144
|
// A typed enum is unrepresentable on Gemini; the bounds project everywhere
|
|
141
145
|
// and the executor rejects values that are not a multiple of 10.
|
|
@@ -157,7 +161,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
|
|
|
157
161
|
name: 'setup',
|
|
158
162
|
title: 'Setup',
|
|
159
163
|
description:
|
|
160
|
-
"Read or change this Mixdog installation's settings through the runtime. Load the setup skill first (local-provider for managed local-model installation). status reads one domain; open navigates the attached app to a settings surface. Secrets (API keys, OAuth) are never accepted. Changes apply to new sessions unless the result says otherwise.",
|
|
164
|
+
"Read or change this Mixdog installation's settings through the runtime. Load the setup skill first (local-provider for managed local-model installation). status reads one domain; open navigates the attached app to a settings surface; list_models returns a provider index, then one provider's paged compact rows, then one model's full options (catalog.model). Results are compact JSON. Secrets (API keys, OAuth) are never accepted. Changes apply to new sessions unless the result says otherwise.",
|
|
161
165
|
annotations: {
|
|
162
166
|
title: 'Setup',
|
|
163
167
|
readOnlyHint: false,
|
|
@@ -177,6 +181,11 @@ export const SETUP_TOOL_DEFS = Object.freeze([
|
|
|
177
181
|
enum: [...SETUP_STATUS_DOMAINS],
|
|
178
182
|
description: 'status: which domain to read; default summary.',
|
|
179
183
|
},
|
|
184
|
+
detail: {
|
|
185
|
+
type: 'boolean',
|
|
186
|
+
description:
|
|
187
|
+
'status providers: full rows for every provider (key URLs, expiry, account ids) instead of configured providers only.',
|
|
188
|
+
},
|
|
180
189
|
target: {
|
|
181
190
|
type: 'string',
|
|
182
191
|
enum: [...SETUP_OPEN_TARGETS],
|
|
@@ -236,7 +245,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
|
|
|
236
245
|
accountId: {
|
|
237
246
|
type: 'string',
|
|
238
247
|
description:
|
|
239
|
-
'forget_provider_auth: OAuth account id from status providers; required when the provider has several accounts.',
|
|
248
|
+
'forget_provider_auth: OAuth account id from status providers with detail:true; required when the provider has several accounts.',
|
|
240
249
|
},
|
|
241
250
|
providerAccount: {
|
|
242
251
|
type: 'object',
|
|
@@ -263,7 +272,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
|
|
|
263
272
|
properties: { id: { type: 'string' }, label: { type: 'string', maxLength: 80 } },
|
|
264
273
|
},
|
|
265
274
|
},
|
|
266
|
-
description: 'set_provider_account: OAuth account change; account ids from status providers.',
|
|
275
|
+
description: 'set_provider_account: OAuth account change; account ids from status providers with detail:true.',
|
|
267
276
|
},
|
|
268
277
|
modelId: {
|
|
269
278
|
type: 'string',
|
|
@@ -46,18 +46,16 @@ export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
|
|
|
46
46
|
}
|
|
47
47
|
return { kind: 'user' };
|
|
48
48
|
};
|
|
49
|
+
const enabledFlags = contextMod.skillEnabledFlags(skills);
|
|
49
50
|
return {
|
|
50
51
|
cwd,
|
|
51
52
|
count: skills.length,
|
|
52
53
|
tools: getTools().map(({ name }) => ({ name })),
|
|
53
|
-
skills: skills.map((skill) => {
|
|
54
|
+
skills: skills.map((skill, index) => {
|
|
54
55
|
const source = sourceForSkill(skill);
|
|
55
56
|
return {
|
|
56
57
|
name: skill.name,
|
|
57
|
-
enabled:
|
|
58
|
-
contextMod.isSkillDisabled?.(skill.name, null, skills) ||
|
|
59
|
-
contextMod.skillMissingFeature?.(skill.name, null, skills)
|
|
60
|
-
),
|
|
58
|
+
enabled: enabledFlags[index],
|
|
61
59
|
description: skill.description || '',
|
|
62
60
|
whenToUse: skill.whenToUse || '',
|
|
63
61
|
filePath: skill.filePath || null,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
filterDisallowedTools,
|
|
7
7
|
selectDeferredTools,
|
|
8
8
|
} from '../runtime/agent/orchestrator/runtime-core/tool-catalog.mjs';
|
|
9
|
+
import { AGENT_WORKER_DENIED_TOOLS } from '../runtime/agent/orchestrator/session/manager/tool-resolution.mjs';
|
|
9
10
|
import { LEAD_DISALLOWED_TOOLS } from '../runtime/agent/orchestrator/runtime-core/tool-defs.mjs';
|
|
10
11
|
import { deferredSurfaceModeForLead, toolSpecForMode } from '../runtime/agent/orchestrator/runtime-core/effort.mjs';
|
|
11
12
|
import { loadSkillToolDependencies } from '../runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs';
|
|
@@ -52,8 +53,11 @@ export function createToolSurface({
|
|
|
52
53
|
const workflowTools = hideAgentTool
|
|
53
54
|
? profileTools.filter((tool) => !agentToolNames.has(String(tool?.name || '')))
|
|
54
55
|
: profileTools;
|
|
56
|
+
const visibleTools = agentOwned
|
|
57
|
+
? workflowTools.filter((tool) => !AGENT_WORKER_DENIED_TOOLS.has(String(tool?.name || '').toLowerCase()))
|
|
58
|
+
: workflowTools;
|
|
55
59
|
const denied = new Set(getFeatureDisallowedTools().map((name) => String(name || '')));
|
|
56
|
-
return denied.size ?
|
|
60
|
+
return denied.size ? visibleTools.filter((tool) => !denied.has(String(tool?.name || ''))) : visibleTools;
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
function disallowedTools() {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/session-runtime/turn/compaction-gate.mjs - serializes a model-scheduled
|
|
3
|
+
* compaction (session tool) with everything that follows its turn. The
|
|
4
|
+
* compaction is chained, never left dangling: `after(fn)` wraps a command so it
|
|
5
|
+
* waits for the compaction in flight, and the compaction itself only runs if
|
|
6
|
+
* the session it was scheduled for is still the live one.
|
|
7
|
+
*/
|
|
8
|
+
export function createCompactionGate({ getSessionId, compact }) {
|
|
9
|
+
let tail = Promise.resolve();
|
|
10
|
+
const run = (sessionId) => {
|
|
11
|
+
tail = tail
|
|
12
|
+
.then(() => (getSessionId() === sessionId ? compact() : null))
|
|
13
|
+
.catch(() => {
|
|
14
|
+
/* best-effort: a scheduled compaction must never break teardown */
|
|
15
|
+
});
|
|
16
|
+
return tail;
|
|
17
|
+
};
|
|
18
|
+
const after =
|
|
19
|
+
(fn) =>
|
|
20
|
+
async (...args) => {
|
|
21
|
+
await tail;
|
|
22
|
+
return fn(...args);
|
|
23
|
+
};
|
|
24
|
+
return { run, after };
|
|
25
|
+
}
|
|
@@ -10,7 +10,6 @@ export function createSessionOps(deps) {
|
|
|
10
10
|
const {
|
|
11
11
|
getSession,
|
|
12
12
|
setSession,
|
|
13
|
-
getCurrentCwd,
|
|
14
13
|
setMode,
|
|
15
14
|
getActiveTurnCount,
|
|
16
15
|
mgr,
|
|
@@ -18,7 +17,7 @@ export function createSessionOps(deps) {
|
|
|
18
17
|
agentTool,
|
|
19
18
|
invalidatePreSessionToolSurface,
|
|
20
19
|
refreshEmptySessionToolPolicy,
|
|
21
|
-
|
|
20
|
+
switchProject,
|
|
22
21
|
resolveCwdPath,
|
|
23
22
|
agentStatusState,
|
|
24
23
|
getReservedSessionId,
|
|
@@ -122,9 +121,12 @@ export function createSessionOps(deps) {
|
|
|
122
121
|
return { messageCount: list.length, messages: list.slice(start) };
|
|
123
122
|
}
|
|
124
123
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
// The desktop/remote Project switch: refused while a turn runs or the
|
|
125
|
+
// session works in a managed worktree (switchProject); resolves once the
|
|
126
|
+
// prompt refresh landed. Its target is a registered Project or the task
|
|
127
|
+
// workspace, classified by desktop membership.
|
|
128
|
+
async function setCwd(path) {
|
|
129
|
+
return switchProject(resolveCwdPath(path), { classifyByMembership: true });
|
|
128
130
|
}
|
|
129
131
|
|
|
130
132
|
return {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/session-runtime/turn/side-question-ops.mjs - /btw side questions on the
|
|
3
|
+
* runtime's current session. They run beside an in-progress turn and touch no
|
|
4
|
+
* session state (see orchestrator/session/side-question.mjs).
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
askSideQuestion,
|
|
8
|
+
cancelSideQuestion,
|
|
9
|
+
} from '../../runtime/agent/orchestrator/session/side-question.mjs';
|
|
10
|
+
|
|
11
|
+
export function createSideQuestionOps({ getSession, getReservedSessionId }) {
|
|
12
|
+
const sessionId = () => getSession()?.id || getReservedSessionId?.() || '';
|
|
13
|
+
return {
|
|
14
|
+
/** @returns {Promise<{ text: string }>} */
|
|
15
|
+
askSide: (question) => askSideQuestion(sessionId(), question),
|
|
16
|
+
/** Abort the side question of `targetSessionId` (the session it was
|
|
17
|
+
* asked in), or of the current session when omitted. */
|
|
18
|
+
cancelSide: (targetSessionId) => {
|
|
19
|
+
cancelSideQuestion(typeof targetSessionId === 'string' && targetSessionId ? targetSessionId : sessionId());
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isVisibleStreamProgress } from '../../../runtime/shared/stream-progress.mjs';
|
|
2
|
+
import { toolCallDisplayIdentity } from '../../../runtime/shared/tool-primitives.mjs';
|
|
2
3
|
|
|
3
4
|
// The askSession callback bridge: caller callbacks pass through, with the
|
|
4
5
|
// transcript, first-visible timing, title release and warmup arming folded in.
|
|
@@ -6,10 +7,13 @@ export function createAskCallbacks({ transcript, notifyFnForSession, scheduleSea
|
|
|
6
7
|
function plannedToolCalls(session0, options) {
|
|
7
8
|
return async (iter, calls) => {
|
|
8
9
|
for (const call of calls || []) {
|
|
10
|
+
// A bridged call reports the tool it runs; the transcript keeps the wire call.
|
|
11
|
+
const identity = toolCallDisplayIdentity(call?.name, call?.arguments);
|
|
9
12
|
hooks.emit('tool:planned', {
|
|
10
13
|
sessionId: session0.id,
|
|
11
|
-
name:
|
|
14
|
+
name: identity.name || 'tool',
|
|
12
15
|
callId: call?.id || null,
|
|
16
|
+
...(identity.via ? { via: identity.via } : {}),
|
|
13
17
|
});
|
|
14
18
|
}
|
|
15
19
|
if (typeof options.onToolCall === 'function') {
|
|
@@ -49,9 +49,9 @@ export function createTurnPreparation({
|
|
|
49
49
|
// Slower servers remain available through the late-tool path; a reconnect
|
|
50
50
|
// in flight gets the same short TTFT grace BEFORE folding the catalog so it
|
|
51
51
|
// cannot hold the provider request. No reconnect in flight → no-op.
|
|
52
|
-
const awaitGrace = async () => {
|
|
52
|
+
const awaitGrace = async (options) => {
|
|
53
53
|
try {
|
|
54
|
-
await turn.awaitTurn(() => turn.timing.awaitMcpGrace());
|
|
54
|
+
await turn.awaitTurn(() => turn.timing.awaitMcpGrace(options));
|
|
55
55
|
} catch {
|
|
56
56
|
/* gate must never break the turn */
|
|
57
57
|
}
|
|
@@ -64,7 +64,12 @@ export function createTurnPreparation({
|
|
|
64
64
|
// One-shot: cleared before the fold so a throw still never re-runs it,
|
|
65
65
|
// and a resumed session (flag unset) skips straight to the late path.
|
|
66
66
|
session0.deferredInitialRefreshPending = false;
|
|
67
|
-
|
|
67
|
+
// A spawned agent runtime owns a fresh MCP scope whose connect starts at
|
|
68
|
+
// its boot, so the 0 ms default grace would hide every MCP tool from the
|
|
69
|
+
// agent's first (often only) turn. Agents are not on the user's TTFT
|
|
70
|
+
// path: wait for the initial connect within the server startup budget.
|
|
71
|
+
const agentOwned = session0.owner === 'agent' || session0.visibility === 'agent-only';
|
|
72
|
+
await awaitGrace({ untilConnected: agentOwned });
|
|
68
73
|
try {
|
|
69
74
|
refreshInitialDeferredMcpSurface(session0, scopedMcpTools(session0));
|
|
70
75
|
} catch {
|
|
@@ -28,6 +28,8 @@ export function createTurnSettlement({
|
|
|
28
28
|
setFirstTurnCompleted,
|
|
29
29
|
scheduleProviderWarmup,
|
|
30
30
|
scheduleProviderModelWarmup,
|
|
31
|
+
takePendingCompact,
|
|
32
|
+
runPendingCompact,
|
|
31
33
|
}) {
|
|
32
34
|
async function completeTurn(turn, session0, result) {
|
|
33
35
|
throwIfAborted(turn.signal);
|
|
@@ -99,6 +101,14 @@ export function createTurnSettlement({
|
|
|
99
101
|
/* lead pool must never break turn teardown */
|
|
100
102
|
}
|
|
101
103
|
setActiveTurnCount(Math.max(0, getActiveTurnCount() - 1));
|
|
104
|
+
// A compaction the model scheduled (session tool) runs once the turn is over.
|
|
105
|
+
// Only while the settled session is still the live one; otherwise it stays
|
|
106
|
+
// pending for that session and never compacts another. The runner chains
|
|
107
|
+
// the compaction so the next turn waits on it.
|
|
108
|
+
const settledId = turn.session0?.id;
|
|
109
|
+
if (getActiveTurnCount() === 0 && settledId && getSession()?.id === settledId && takePendingCompact?.(settledId)) {
|
|
110
|
+
runPendingCompact?.(settledId);
|
|
111
|
+
}
|
|
102
112
|
if (!isFirstTurnCompleted()) {
|
|
103
113
|
setFirstTurnCompleted(true);
|
|
104
114
|
scheduleProviderWarmup();
|
|
@@ -38,11 +38,12 @@ export function createTurnTimingFactory({ getSession, awaitInitialMcpConnect, mc
|
|
|
38
38
|
/* timing telemetry must never affect a turn */
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
-
// Give an in-flight MCP connect only a short TTFT grace.
|
|
42
|
-
|
|
41
|
+
// Give an in-flight MCP connect only a short TTFT grace. untilConnected
|
|
42
|
+
// waits for the initial connect bounded only by the server startup budget.
|
|
43
|
+
timing.awaitMcpGrace = async ({ untilConnected = false } = {}) => {
|
|
43
44
|
const graceStartedAt = performance.now();
|
|
44
45
|
try {
|
|
45
|
-
await awaitInitialMcpConnect?.(mcpTurnGraceMs);
|
|
46
|
+
await awaitInitialMcpConnect?.(untilConnected ? undefined : mcpTurnGraceMs);
|
|
46
47
|
} finally {
|
|
47
48
|
timing.mcpWaitMs += performance.now() - graceStartedAt;
|
|
48
49
|
}
|
|
@@ -13,6 +13,7 @@ import { createSnapshotTrackerFactory } from './turn-run/snapshot-tracker.mjs';
|
|
|
13
13
|
import { createTurnOpener } from './turn-run/turn-open.mjs';
|
|
14
14
|
import { createTurnPreparation } from './turn-run/turn-prepare.mjs';
|
|
15
15
|
import { createAskCallbacks } from './turn-run/ask-callbacks.mjs';
|
|
16
|
+
import { registerNativeWebSearchUsageSink } from '../native-web-search-usage.mjs';
|
|
16
17
|
import { createTurnSettlement } from './turn-run/turn-settle.mjs';
|
|
17
18
|
|
|
18
19
|
export function createTurnRunner(deps) {
|
|
@@ -94,15 +95,30 @@ export function createTurnRunner(deps) {
|
|
|
94
95
|
try {
|
|
95
96
|
const session0 = await prepareSession(turn, prompt, options);
|
|
96
97
|
const turnContext = await dispatchPromptSubmit(turn, session0, prompt, options);
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
const callbacks = askCallbacks(turn, session0, options);
|
|
99
|
+
// Register only once askSession's session lock is held: the first
|
|
100
|
+
// provider send of this turn. A turn queued behind another on the same
|
|
101
|
+
// session id therefore never receives the running turn's search usage.
|
|
102
|
+
let releaseWebSearchUsage = null;
|
|
103
|
+
const providerSendStarted = callbacks.onProviderSendStarted;
|
|
104
|
+
callbacks.onProviderSendStarted = (...args) => {
|
|
105
|
+
releaseWebSearchUsage ??= registerNativeWebSearchUsageSink(session0.id, options.onNativeWebSearchUsage);
|
|
106
|
+
return providerSendStarted(...args);
|
|
107
|
+
};
|
|
108
|
+
let result;
|
|
109
|
+
try {
|
|
110
|
+
result = await mgr.askSession(
|
|
111
|
+
session0.id,
|
|
112
|
+
prompt,
|
|
113
|
+
turnContext || null,
|
|
114
|
+
plannedToolCalls(session0, options),
|
|
115
|
+
getCurrentCwd(),
|
|
116
|
+
options.prefetch || null,
|
|
117
|
+
callbacks
|
|
118
|
+
);
|
|
119
|
+
} finally {
|
|
120
|
+
releaseWebSearchUsage?.();
|
|
121
|
+
}
|
|
106
122
|
return await completeTurn(turn, session0, result);
|
|
107
123
|
} catch (error) {
|
|
108
124
|
reportTurnError(turn, error);
|
|
@@ -82,22 +82,43 @@ function accountsInUse(accountPool) {
|
|
|
82
82
|
return inUse;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
function sessionUsageIds(sessionId, accountPool) {
|
|
89
|
-
const ids = [sessionId];
|
|
85
|
+
// Each subscription provider's account ids, read once per request.
|
|
86
|
+
function accountScopes(accountPool) {
|
|
87
|
+
const scopes = [];
|
|
90
88
|
for (const provider of ACCOUNT_PROVIDERS) {
|
|
91
89
|
try {
|
|
92
|
-
|
|
93
|
-
ids.push(accountScopedSessionId(provider, account.id, sessionId));
|
|
90
|
+
scopes.push([provider, accountPool(provider).accounts.map((account) => account.id)]);
|
|
94
91
|
} catch {
|
|
95
92
|
/* an unreadable pool leaves that provider's older records out */
|
|
96
93
|
}
|
|
97
94
|
}
|
|
95
|
+
return scopes;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Every id a session's spend was recorded under: its own, and the per-account
|
|
99
|
+
// provider session each subscription account sent it under before account
|
|
100
|
+
// sends recorded the visible session.
|
|
101
|
+
function sessionUsageIdsFor(scopes, sessionId) {
|
|
102
|
+
const ids = [sessionId];
|
|
103
|
+
for (const [provider, accounts] of scopes) {
|
|
104
|
+
for (const account of accounts) ids.push(accountScopedSessionId(provider, account, sessionId));
|
|
105
|
+
}
|
|
98
106
|
return ids;
|
|
99
107
|
}
|
|
100
108
|
|
|
109
|
+
// Other sessions a caller asks about beside its own (the composer island's
|
|
110
|
+
// agent sessions): bounded, distinct, never the caller's own id.
|
|
111
|
+
const MAX_SESSION_USAGE_IDS = 64;
|
|
112
|
+
function otherSessionIds(options, sessionId) {
|
|
113
|
+
const ids = Array.isArray(options?.sessionIds) ? options.sessionIds : [];
|
|
114
|
+
const unique = new Set();
|
|
115
|
+
for (const id of ids) {
|
|
116
|
+
if (typeof id === 'string' && id && id !== sessionId) unique.add(id);
|
|
117
|
+
if (unique.size >= MAX_SESSION_USAGE_IDS) break;
|
|
118
|
+
}
|
|
119
|
+
return [...unique];
|
|
120
|
+
}
|
|
121
|
+
|
|
101
122
|
/** `null` = all time. `0` = today. Anything else is a trailing day count. */
|
|
102
123
|
function normalizeDays(value) {
|
|
103
124
|
if (value === null || value === undefined || value === 'all') return null;
|
|
@@ -213,15 +234,26 @@ export function createUsageStatsApi({
|
|
|
213
234
|
return snapshot;
|
|
214
235
|
},
|
|
215
236
|
|
|
216
|
-
/**
|
|
217
|
-
|
|
237
|
+
/**
|
|
238
|
+
* This runtime's session from its first request, compactions included; null before it has one.
|
|
239
|
+
* `sessionIds` adds the same totals for each named session (the agents it spawned) under
|
|
240
|
+
* `sessions`, each read by its own id only.
|
|
241
|
+
*/
|
|
242
|
+
async getSessionUsage(options = {}) {
|
|
218
243
|
const sessionId = getSessionId();
|
|
219
244
|
if (!sessionId) return null;
|
|
220
245
|
const store = ledger();
|
|
221
246
|
if (!store) throw new Error('Usage ledger is unavailable');
|
|
222
247
|
await store.settleWrites();
|
|
223
|
-
const
|
|
224
|
-
|
|
248
|
+
const scopes = accountScopes(accountPool);
|
|
249
|
+
const usage = await store.sessionUsageAsync(sessionUsageIdsFor(scopes, sessionId));
|
|
250
|
+
const result = { sessionId, ...sessionUsageSnapshot(usage) };
|
|
251
|
+
const others = otherSessionIds(options, sessionId);
|
|
252
|
+
if (!others.length) return result;
|
|
253
|
+
const totals = await Promise.all(
|
|
254
|
+
others.map(async (id) => [id, sessionUsageSnapshot(await store.sessionUsageAsync(sessionUsageIdsFor(scopes, id)))])
|
|
255
|
+
);
|
|
256
|
+
return { ...result, sessions: Object.fromEntries(totals) };
|
|
225
257
|
},
|
|
226
258
|
|
|
227
259
|
/**
|