mixdog 1.1.2 → 1.2.1
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 +8 -5
- package/package.json +2 -1
- package/scripts/lib/run-node-tests.mjs +9 -0
- package/scripts/prune-desktop-runtime.mjs +3 -0
- package/scripts/test-direct.mjs +4 -2
- package/src/defaults/shipped-history.json +10 -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 +18 -5
- package/src/defaults/skills/visualize/SKILL.md +160 -0
- package/src/defaults/skills/visualize/references/craft.md +88 -0
- package/src/headless-command.mjs +56 -3
- package/src/headless-exec.mjs +17 -1
- package/src/help.mjs +2 -0
- 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-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
- package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +19 -5
- 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 +133 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +55 -8
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +86 -8
- package/src/runtime/agent/orchestrator/mcp/client.mjs +474 -164
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
- 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 +444 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +21 -6
- package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +82 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +556 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +15 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
- 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-xai-send.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +47 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -11
- 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/model-capabilities.mjs +16 -1
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +278 -84
- 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/runtime-core/tool-defs.mjs +10 -3
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -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/execution-tail.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +24 -13
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
- 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/continuation.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +9 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
- package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +33 -22
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +23 -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 +202 -374
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
- 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 +48 -9
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +161 -0
- 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/cache-layers.mjs +52 -2
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
- 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-cache-policy.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +203 -33
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +83 -68
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +20 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
- 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/builtin/task-tool.mjs +56 -13
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
- 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/code-graph/trusted-roots.mjs +25 -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/patch/ui-diff.mjs +78 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/attachments/store.mjs +38 -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/session-ingest.mjs +2 -2
- package/src/runtime/shared/atomic-file.mjs +33 -6
- package/src/runtime/shared/best-effort-stderr.mjs +8 -0
- package/src/runtime/shared/code-graph-state.mjs +12 -0
- package/src/runtime/shared/defaults-separation.mjs +2 -0
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/git-runner-worker.mjs +3 -2
- package/src/runtime/shared/git-runner.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
- package/src/runtime/shared/llm/default-context-window.mjs +6 -0
- package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
- package/src/runtime/shared/llm/model-catalog.mjs +240 -130
- package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +162 -0
- package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
- package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
- package/src/runtime/shared/model-proxy-mode.mjs +19 -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 +125 -21
- package/src/runtime/shared/provider-api-key.mjs +33 -1
- package/src/runtime/shared/schedule-model-ref.mjs +11 -2
- package/src/runtime/shared/session-usage-totals.mjs +19 -0
- package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/singleton-owner.mjs +36 -6
- 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-segments.mjs +68 -14
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/tool-surface.mjs +7 -0
- package/src/runtime/shared/tool-work-units.mjs +14 -0
- package/src/runtime/shared/transcript-metadata.mjs +17 -1
- package/src/runtime/shared/turn-changes.mjs +791 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
- package/src/runtime/shared/turn-snapshot.mjs +690 -81
- package/src/runtime/shared/turn-worktree-snapshot.mjs +185 -15
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
- package/src/runtime/shared/worktrees/contract.mjs +551 -0
- package/src/runtime/shared/worktrees/disk.mjs +57 -0
- package/src/runtime/shared/worktrees/git.mjs +247 -0
- package/src/runtime/shared/worktrees/include.mjs +480 -0
- package/src/runtime/shared/worktrees/lock.mjs +46 -0
- package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
- package/src/runtime/shared/worktrees/manager.mjs +1215 -0
- package/src/runtime/shared/worktrees/merge.mjs +182 -0
- package/src/runtime/shared/worktrees/owner.mjs +46 -0
- package/src/runtime/shared/worktrees/paths.mjs +62 -0
- package/src/runtime/shared/worktrees/registry.mjs +110 -0
- package/src/runtime/shared/worktrees/settings.mjs +84 -0
- package/src/runtime/shared/worktrees/slug.mjs +62 -0
- package/src/runtime/shared/worktrees/test-support.mjs +96 -0
- package/src/runtime/visualize-bridge/client.mjs +181 -0
- package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +90 -0
- package/src/session-runtime/boot/config.mjs +7 -2
- package/src/session-runtime/boot/facade.mjs +21 -0
- package/src/session-runtime/boot/infrastructure.mjs +30 -18
- package/src/session-runtime/boot/session.mjs +1 -0
- package/src/session-runtime/boot/tools.mjs +4 -0
- package/src/session-runtime/config-lifecycle.mjs +10 -1
- 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 +21 -6
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/global-extensions.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
- package/src/session-runtime/internal-tool-executor.mjs +9 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
- package/src/session-runtime/mcp-glue/connect.mjs +68 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +122 -33
- package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
- package/src/session-runtime/mcp-glue.mjs +22 -2
- package/src/session-runtime/model-route/route-persist.mjs +3 -0
- package/src/session-runtime/model-route/set-route.mjs +15 -2
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +18 -3
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
- 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/resource-extension-sync.mjs +45 -7
- package/src/session-runtime/resource-mcp-api.mjs +121 -84
- 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/route-resolution.mjs +10 -1
- package/src/session-runtime/route-state.mjs +16 -2
- package/src/session-runtime/runtime-core.mjs +5 -0
- package/src/session-runtime/runtime-facade.mjs +8 -0
- package/src/session-runtime/runtime-review-api.mjs +9 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
- package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
- package/src/session-runtime/services/agent-tool.mjs +1 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/daemon-candidate.mjs +3 -2
- package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
- 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/session-create/session-options.mjs +10 -1
- package/src/session-runtime/session-turn-api.mjs +1 -0
- package/src/session-runtime/settings-api.mjs +4 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
- package/src/session-runtime/settings-worktree-api.mjs +17 -0
- package/src/session-runtime/setup-tool/executor.mjs +23 -5
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +38 -4
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/agent-ops.mjs +12 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +14 -3
- package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
- package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
- package/src/session-runtime/turn/turn-run.mjs +6 -7
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
- package/src/session-runtime/workspace/admission-gate.mjs +197 -0
- package/src/session-runtime/workspace/project-branches.mjs +136 -0
- package/src/session-runtime/workspace/transition-steps.mjs +364 -0
- package/src/session-runtime/workspace/transitions.mjs +651 -0
- package/src/session-runtime/workspace/workspace-state.mjs +112 -0
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/channel-transport/http-routes.mjs +17 -0
- package/src/standalone/channel-transport.mjs +13 -1
- package/src/standalone/daemon-desktop-runtime.mjs +1 -0
- package/src/standalone/daemon-owner.mjs +372 -0
- package/src/standalone/daemon-stored-session-views.mjs +15 -4
- package/src/standalone/daemon.mjs +179 -8
- package/src/standalone/desktop-service-registry.mjs +20 -0
- package/src/standalone/local-session-runtime.mjs +11 -0
- package/src/standalone/session-client/attachment-calls.mjs +3 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
- package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
- package/src/standalone/session-client.mjs +104 -13
- package/src/standalone/session-protocol.mjs +21 -0
- package/src/standalone/session-proxy.mjs +3 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
- package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
- package/src/standalone/session-service/projection/revisions.mjs +2 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
- package/src/standalone/session-service/projection/workspace.mjs +14 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +17 -4
- package/src/standalone/session-transport/call-route.mjs +13 -0
- package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
- package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
- package/src/standalone/session-transport/client-registry.mjs +20 -3
- package/src/standalone/session-transport/routes.mjs +79 -2
- package/src/standalone/session-transport/stack.mjs +2 -0
- package/src/standalone/session-transport.mjs +24 -1
- 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 +6 -0
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/message-selector.mjs +2 -1
- package/src/tui/app/model-options.mjs +37 -5
- package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
- package/src/tui/app/model-picker.mjs +4 -2
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- 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/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +839 -207
- package/src/tui/index.jsx +10 -2
- package/src/tui/session/compaction-view.mjs +147 -0
- package/src/tui/session/context-state.mjs +6 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +2 -1
- package/src/tui/session/session-api/commands.mjs +10 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +4 -2
- package/src/tui/session/session-api/intake/rewind.mjs +2 -1
- package/src/tui/session/session-api/integrations.mjs +17 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
- package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
- package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
- package/src/tui/session/session-api/routes.mjs +10 -1
- package/src/tui/session/session-api/settings.mjs +9 -0
- package/src/tui/session/session-api/worktree.mjs +60 -0
- package/src/tui/session/session-api.mjs +2 -0
- package/src/tui/session/session-flow/auto-clear.mjs +31 -12
- package/src/tui/session/session-flow/drain.mjs +27 -3
- package/src/tui/session/session-flow/session-reset.mjs +4 -3
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/transcript-intake.mjs +14 -5
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn-stream.mjs +32 -4
- package/src/tui/session/turn-tool-cards.mjs +10 -2
- package/src/tui/session/turn.mjs +56 -10
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
|
@@ -3,34 +3,52 @@
|
|
|
3
3
|
// (info / update / MCP / copy / uninstall) and the add-plugin prompt.
|
|
4
4
|
import { readStatus, withScope } from './scope-note.mjs';
|
|
5
5
|
|
|
6
|
+
// A plugin's MCP servers are derived from its declarations (`mcpServers` on
|
|
7
|
+
// the status row); older hosts only report `mcpScript`/`mcpServerName`.
|
|
8
|
+
function mcpNames(p) {
|
|
9
|
+
if (Array.isArray(p.mcpServers)) return p.mcpServers.map((server) => server.name);
|
|
10
|
+
return p.mcpServerName ? [p.mcpServerName] : [];
|
|
11
|
+
}
|
|
12
|
+
const hasMcp = (p) => mcpNames(p).length > 0 || Boolean(p.mcpScript || p.mcpInline);
|
|
13
|
+
|
|
14
|
+
function serverState(server) {
|
|
15
|
+
if (server.serverEnabled === false) return 'off';
|
|
16
|
+
if (server.enabled === false) return 'plugin off';
|
|
17
|
+
return server.status || (server.connected ? 'connected' : 'disconnected');
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
const mcpSummary = (p) => {
|
|
7
|
-
if (!p
|
|
8
|
-
|
|
9
|
-
return `${
|
|
21
|
+
if (!hasMcp(p))
|
|
22
|
+
return Array.isArray(p.mcpErrors) && p.mcpErrors.length ? `(invalid: ${p.mcpErrors[0].message})` : '(none)';
|
|
23
|
+
if (!Array.isArray(p.mcpServers)) return `${p.mcpEnabled ? 'enabled' : 'available'} (${mcpNames(p).join(', ')})`;
|
|
24
|
+
const errors =
|
|
25
|
+
Array.isArray(p.mcpErrors) && p.mcpErrors.length ? ` · ${p.mcpErrors.length} declaration error(s)` : '';
|
|
26
|
+
return `${p.mcpServers.map((server) => `${server.name} ${serverState(server)}`).join(', ')}${errors}`;
|
|
10
27
|
};
|
|
11
28
|
|
|
12
29
|
function mcpActionItem(p) {
|
|
13
|
-
if (!p
|
|
30
|
+
if (!hasMcp(p)) {
|
|
14
31
|
return {
|
|
15
32
|
value: 'enable-mcp',
|
|
16
|
-
label: 'No MCP
|
|
17
|
-
description: 'plugin
|
|
33
|
+
label: 'No MCP server',
|
|
34
|
+
description: 'plugin declares no MCP servers (.mcp.json or manifest mcpServers)',
|
|
18
35
|
_action: 'noop',
|
|
19
36
|
};
|
|
20
37
|
}
|
|
21
38
|
return {
|
|
22
39
|
value: 'enable-mcp',
|
|
23
|
-
label: p.mcpEnabled ? '
|
|
24
|
-
description: `${p.
|
|
40
|
+
label: p.mcpEnabled ? 'Reconnect MCP servers' : 'Enable MCP servers',
|
|
41
|
+
description: `${mcpNames(p).join(', ') || 'plugin MCP'} · ${p.mcpEnabled ? 'on' : 'turned off'}`,
|
|
25
42
|
_action: 'enable-mcp',
|
|
26
43
|
};
|
|
27
44
|
}
|
|
28
45
|
|
|
29
46
|
function pluginSummary(plugin) {
|
|
30
47
|
const version = plugin.version ? ` · ${plugin.version}` : '';
|
|
31
|
-
const
|
|
32
|
-
const mcp = plugin
|
|
33
|
-
|
|
48
|
+
const mcpOff = plugin.mcpEnabled ? '' : ' off';
|
|
49
|
+
const mcp = hasMcp(plugin) ? ` · mcp ${mcpNames(plugin).length || 1}${mcpOff}` : '';
|
|
50
|
+
const warning = plugin.warning ? ` · ⚠ ${plugin.warning}` : '';
|
|
51
|
+
return `${plugin.sourceType || plugin.source}${version} · skills ${plugin.skillCount || 0}${mcp}${warning}`;
|
|
34
52
|
}
|
|
35
53
|
|
|
36
54
|
const pluginInfoNotice = (p) =>
|
|
@@ -41,6 +59,7 @@ const pluginInfoNotice = (p) =>
|
|
|
41
59
|
`mcp: ${mcpSummary(p)}`,
|
|
42
60
|
`applies to: ${Array.isArray(p.scope) && p.scope.length ? p.scope.join(', ') : 'all projects'}`,
|
|
43
61
|
`root: ${p.root}`,
|
|
62
|
+
p.warning ? `warning: ${p.warning}` : '',
|
|
44
63
|
p.description ? `\n${p.description}` : '',
|
|
45
64
|
]
|
|
46
65
|
.filter(Boolean)
|
|
@@ -68,9 +87,9 @@ const pluginDetailItems = (p) => [
|
|
|
68
87
|
},
|
|
69
88
|
{
|
|
70
89
|
value: 'copy-mcp-name',
|
|
71
|
-
label: p.
|
|
72
|
-
description: p.
|
|
73
|
-
_action: p.
|
|
90
|
+
label: mcpNames(p).length ? 'Copy MCP server name' : 'No MCP server name',
|
|
91
|
+
description: mcpNames(p).join(', '),
|
|
92
|
+
_action: mcpNames(p).length ? 'copy-mcp-name' : 'noop',
|
|
74
93
|
},
|
|
75
94
|
{
|
|
76
95
|
value: 'uninstall',
|
|
@@ -127,7 +146,7 @@ export function createPluginsPickers({
|
|
|
127
146
|
void store
|
|
128
147
|
.enablePluginMcp?.(p)
|
|
129
148
|
.then(own.defer(() => openMcpPicker()))
|
|
130
|
-
.catch((e) => store.pushNotice(`plugin MCP
|
|
149
|
+
.catch((e) => store.pushNotice(`plugin MCP reconnect failed: ${e?.message || e}`, 'error'));
|
|
131
150
|
return;
|
|
132
151
|
}
|
|
133
152
|
if (detail._action === 'copy-root') {
|
|
@@ -135,7 +154,7 @@ export function createPluginsPickers({
|
|
|
135
154
|
return;
|
|
136
155
|
}
|
|
137
156
|
if (detail._action === 'copy-mcp-name') {
|
|
138
|
-
copyText(p.
|
|
157
|
+
copyText(mcpNames(p).join(', '), `copied plugin MCP server: ${mcpNames(p).join(', ')}`);
|
|
139
158
|
return;
|
|
140
159
|
}
|
|
141
160
|
if (detail._action === 'uninstall') {
|
|
@@ -18,7 +18,8 @@ function selectableUserItems(items, limit = MAX_SELECTABLE_MESSAGES) {
|
|
|
18
18
|
for (let index = source.length - 1; index >= 0 && rows.length < limit; index -= 1) {
|
|
19
19
|
const item = source[index];
|
|
20
20
|
if (item?.kind !== 'user') continue;
|
|
21
|
-
|
|
21
|
+
// Prompts a compaction archived are display-only.
|
|
22
|
+
if (item?.id == null || item.archived === true) continue;
|
|
22
23
|
const text = String(item.text || '').trim();
|
|
23
24
|
if (!text) continue;
|
|
24
25
|
rows.push({ id: String(item.id), text });
|
|
@@ -169,6 +169,7 @@ const PROVIDER_DISPLAY_NAMES = new Map([
|
|
|
169
169
|
['anthropic-oauth', 'Anthropic OAuth'],
|
|
170
170
|
['grok-oauth', 'Grok OAuth'],
|
|
171
171
|
['muse-code-oauth', 'Muse Code'],
|
|
172
|
+
['command-code-oauth', 'Command Code'],
|
|
172
173
|
['mimo-oauth', 'MiMo'],
|
|
173
174
|
['cursor-oauth', 'Cursor OAuth'],
|
|
174
175
|
['antigravity-oauth', 'Antigravity OAuth'],
|
|
@@ -191,12 +192,41 @@ const PROVIDER_DISPLAY_NAMES = new Map([
|
|
|
191
192
|
export const providerDisplayName = (provider) =>
|
|
192
193
|
PROVIDER_DISPLAY_NAMES.get(String(provider || '').toLowerCase()) ?? (provider || 'Provider');
|
|
193
194
|
|
|
195
|
+
export const resolveProviderDisplayName = (provider, providerNames = null) =>
|
|
196
|
+
(String(provider || '')
|
|
197
|
+
.trim()
|
|
198
|
+
.startsWith('custom-') &&
|
|
199
|
+
providerNames?.[String(provider).trim()]) ||
|
|
200
|
+
providerDisplayName(provider);
|
|
201
|
+
|
|
202
|
+
export const loadProviderDisplayNames = async (store) => {
|
|
203
|
+
let setup = null;
|
|
204
|
+
try {
|
|
205
|
+
setup = await store?.getProviderSetup?.();
|
|
206
|
+
} catch {
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
const names = {};
|
|
210
|
+
for (const group of ['api', 'oauth', 'local']) {
|
|
211
|
+
const entries = setup?.[group];
|
|
212
|
+
if (!Array.isArray(entries)) continue;
|
|
213
|
+
for (const entry of entries) {
|
|
214
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
215
|
+
const id = String(entry.id || entry.provider || '').trim();
|
|
216
|
+
const name = String(entry.name || entry.label || '').trim();
|
|
217
|
+
if (id && name) names[id] = name;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return names;
|
|
221
|
+
};
|
|
222
|
+
|
|
194
223
|
const PROVIDER_DISPLAY_RANKS = {
|
|
195
224
|
default: 0,
|
|
196
225
|
'openai-oauth': 10,
|
|
197
226
|
'anthropic-oauth': 20,
|
|
198
227
|
'grok-oauth': 30,
|
|
199
228
|
'muse-code-oauth': 33,
|
|
229
|
+
'command-code-oauth': 33.5,
|
|
200
230
|
'mimo-oauth': 34,
|
|
201
231
|
'antigravity-oauth': 31,
|
|
202
232
|
'cursor-oauth': 32,
|
|
@@ -247,7 +277,7 @@ const routeModelDisplayName = (route) =>
|
|
|
247
277
|
.filter(Boolean)
|
|
248
278
|
.join(' ');
|
|
249
279
|
|
|
250
|
-
const groupModelsByProvider = (models) => {
|
|
280
|
+
const groupModelsByProvider = (models, providerNames = null) => {
|
|
251
281
|
const providers = new Map();
|
|
252
282
|
for (const model of models) {
|
|
253
283
|
if (!providers.has(model.provider)) providers.set(model.provider, []);
|
|
@@ -257,22 +287,24 @@ const groupModelsByProvider = (models) => {
|
|
|
257
287
|
const orderedProviders = [...providers.keys()].sort((a, b) => {
|
|
258
288
|
const rank = providerDisplayRank(a) - providerDisplayRank(b);
|
|
259
289
|
if (rank !== 0) return rank;
|
|
260
|
-
const label =
|
|
290
|
+
const label = resolveProviderDisplayName(a, providerNames).localeCompare(
|
|
291
|
+
resolveProviderDisplayName(b, providerNames)
|
|
292
|
+
);
|
|
261
293
|
if (label !== 0) return label;
|
|
262
294
|
return a.localeCompare(b);
|
|
263
295
|
});
|
|
264
296
|
return { providers, orderedProviders };
|
|
265
297
|
};
|
|
266
298
|
|
|
267
|
-
export const buildModelProviderItems = (models, currentRoute = null) => {
|
|
268
|
-
const { providers, orderedProviders } = groupModelsByProvider(models);
|
|
299
|
+
export const buildModelProviderItems = (models, currentRoute = null, providerNames = null) => {
|
|
300
|
+
const { providers, orderedProviders } = groupModelsByProvider(models, providerNames);
|
|
269
301
|
return orderedProviders.map((provider) => {
|
|
270
302
|
const providerModels = providers.get(provider) || [];
|
|
271
303
|
const currentModel =
|
|
272
304
|
currentRoute?.provider === provider ? providerModels.find((model) => model.id === currentRoute.model) : null;
|
|
273
305
|
return {
|
|
274
306
|
value: `provider:${provider}`,
|
|
275
|
-
label:
|
|
307
|
+
label: resolveProviderDisplayName(provider, providerNames),
|
|
276
308
|
marker: currentModel ? '✓' : '',
|
|
277
309
|
markerColor: theme.success,
|
|
278
310
|
meta: currentModel ? modelRecordDisplayName(currentModel) : '',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// One provider's model list: rows from the catalog, the footer for the
|
|
3
3
|
// highlighted row, and the keys that change its selections (←/→ effort,
|
|
4
4
|
// C/Shift+C context, Tab Fast, T thinking). Enter saves through the caller.
|
|
5
|
-
import { buildProviderModelItems,
|
|
5
|
+
import { buildProviderModelItems, resolveProviderDisplayName } from '../model-options.mjs';
|
|
6
6
|
import { modelFooter } from './model-footer.mjs';
|
|
7
7
|
import { createRouteSelection } from './route-selection.mjs';
|
|
8
8
|
|
|
@@ -73,7 +73,7 @@ export function openProviderModelsPicker({ view, provider, onBack, saveRoute })
|
|
|
73
73
|
)
|
|
74
74
|
);
|
|
75
75
|
view.paint({
|
|
76
|
-
title:
|
|
76
|
+
title: resolveProviderDisplayName(provider, view.providerNames),
|
|
77
77
|
description: options.modelDescription || 'Select a model. Adjust Effort with ←/→.',
|
|
78
78
|
footer: (item) => modelFooter(selection, item?._model),
|
|
79
79
|
help:
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* state (getState) is read through a getter so it always reflects the current
|
|
11
11
|
* render.
|
|
12
12
|
*/
|
|
13
|
-
import { normalizeModelOptions, buildModelProviderItems } from './model-options.mjs';
|
|
13
|
+
import { normalizeModelOptions, buildModelProviderItems, loadProviderDisplayNames } from './model-options.mjs';
|
|
14
14
|
import { createModelCatalog } from './model-picker/catalog-load.mjs';
|
|
15
15
|
import { openProviderModelsPicker, saveSelectedRoute } from './model-picker/provider-models-list.mjs';
|
|
16
16
|
|
|
@@ -77,6 +77,7 @@ export function createModelPicker({
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
const models = normalizeModelOptions(providerModels);
|
|
80
|
+
const providerNames = await loadProviderDisplayNames(store);
|
|
80
81
|
const activeRoute = options.currentRoute || {
|
|
81
82
|
provider: state.provider,
|
|
82
83
|
model: state.model,
|
|
@@ -90,6 +91,7 @@ export function createModelPicker({
|
|
|
90
91
|
state,
|
|
91
92
|
models,
|
|
92
93
|
activeRoute,
|
|
94
|
+
providerNames,
|
|
93
95
|
returnTo,
|
|
94
96
|
returnLabel,
|
|
95
97
|
returnOnNestedCancel,
|
|
@@ -114,7 +116,7 @@ export function createModelPicker({
|
|
|
114
116
|
providerListHighlightProvider = renderOptions.highlightProvider;
|
|
115
117
|
}
|
|
116
118
|
const highlightProvider = renderOptions.highlightProvider || providerListHighlightProvider || null;
|
|
117
|
-
const providerItems = buildModelProviderItems(models, activeRoute);
|
|
119
|
+
const providerItems = buildModelProviderItems(models, activeRoute, providerNames);
|
|
118
120
|
const providerHighlight = highlightProvider || activeRoute?.provider || null;
|
|
119
121
|
const providerInitialIndex = Math.max(
|
|
120
122
|
0,
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* app/skill-mention-palette.mjs — `$name` skill completion in the prompt.
|
|
3
|
+
*
|
|
4
|
+
* Typing `$` at the start of the draft or after whitespace/an opening
|
|
5
|
+
* bracket or quote (the shared runtime mention rule, runtime/shared/
|
|
6
|
+
* skill-mentions.mjs) opens the command palette with the user's enabled
|
|
7
|
+
* custom skills; accepting inserts `$name `. Built-in skills are not listed,
|
|
8
|
+
* but still load when their name is typed: the runtime resolves mentions.
|
|
9
|
+
*/
|
|
10
|
+
import { useEffect, useState } from 'react';
|
|
11
|
+
import { isInMarkdownCode, isReservedMentionName } from '../../runtime/shared/skill-mentions.mjs';
|
|
12
|
+
|
|
13
|
+
// A mention being typed just before the caret: `$` plus a partial name.
|
|
14
|
+
const MENTION_TAIL = /(^|[\s([{"'`])\$([a-z0-9][a-z0-9-]{0,63})?$/;
|
|
15
|
+
|
|
16
|
+
const caretIn = (text, caret) => (Number.isInteger(caret) ? Math.max(0, Math.min(text.length, caret)) : text.length);
|
|
17
|
+
|
|
18
|
+
/** The mention being typed before `caret` (default: end of `value`), or null.
|
|
19
|
+
* `start` is the `$`, `end` the caret. */
|
|
20
|
+
export function skillMentionQuery(value, caret) {
|
|
21
|
+
const text = String(value ?? '');
|
|
22
|
+
const end = caretIn(text, caret);
|
|
23
|
+
const match = MENTION_TAIL.exec(text.slice(0, end));
|
|
24
|
+
if (!match) return null;
|
|
25
|
+
const start = match.index + match[1].length;
|
|
26
|
+
// `$` inside inline code or a fenced block is never a mention (the shared
|
|
27
|
+
// parser's rule, judged on the whole draft like the desktop composer).
|
|
28
|
+
if (isInMarkdownCode(text, start)) return null;
|
|
29
|
+
return { query: match[2] || '', start, end };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const byName = (a, b) => a.name.localeCompare(b.name, 'en');
|
|
33
|
+
|
|
34
|
+
/** Palette rows for `query`: enabled, in-project (not `activeHere:false`)
|
|
35
|
+
* non-built-in skills whose name starts with the query, then those that
|
|
36
|
+
* merely contain it, each alphabetical. */
|
|
37
|
+
export function skillMentionItems(skills, query) {
|
|
38
|
+
const needle = String(query || '').toLowerCase();
|
|
39
|
+
const usable = (Array.isArray(skills) ? skills : []).filter(
|
|
40
|
+
(skill) =>
|
|
41
|
+
typeof skill?.name === 'string' &&
|
|
42
|
+
skill.name &&
|
|
43
|
+
skill.enabled !== false &&
|
|
44
|
+
skill.activeHere !== false &&
|
|
45
|
+
skill.source !== 'builtin' &&
|
|
46
|
+
// `$path`/`$300` are never mentions, so offering them would insert prose.
|
|
47
|
+
!isReservedMentionName(skill.name)
|
|
48
|
+
);
|
|
49
|
+
const prefix = usable.filter((skill) => skill.name.startsWith(needle)).sort(byName);
|
|
50
|
+
const contains = needle
|
|
51
|
+
? usable.filter((skill) => !skill.name.startsWith(needle) && skill.name.includes(needle)).sort(byName)
|
|
52
|
+
: [];
|
|
53
|
+
return [...prefix, ...contains].map((skill) => ({
|
|
54
|
+
kind: 'skill',
|
|
55
|
+
name: skill.name,
|
|
56
|
+
label: `$${skill.name}`,
|
|
57
|
+
description: skill.description || '',
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The draft with the `$fragment` before `caret` replaced by `$name `; the
|
|
62
|
+
* text after the caret is kept and the caret lands after the insertion. */
|
|
63
|
+
export function completeSkillMention(value, name, caret) {
|
|
64
|
+
const text = String(value ?? '');
|
|
65
|
+
const mention = skillMentionQuery(text, caret);
|
|
66
|
+
if (!mention || !name) return undefined;
|
|
67
|
+
const head = `${text.slice(0, mention.start)}$${name} `;
|
|
68
|
+
return { value: head + text.slice(mention.end), cursor: head.length };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** The skill list for the palette, fetched each time a mention starts. */
|
|
72
|
+
export function useSkillMentionSkills(store, active) {
|
|
73
|
+
const [skills, setSkills] = useState([]);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (!active) return undefined;
|
|
76
|
+
let live = true;
|
|
77
|
+
Promise.resolve()
|
|
78
|
+
.then(() => store.skillsStatus?.())
|
|
79
|
+
.then((status) => {
|
|
80
|
+
if (live) setSkills(Array.isArray(status?.skills) ? status.skills : []);
|
|
81
|
+
})
|
|
82
|
+
.catch(() => {});
|
|
83
|
+
return () => {
|
|
84
|
+
live = false;
|
|
85
|
+
};
|
|
86
|
+
}, [store, active]);
|
|
87
|
+
return skills;
|
|
88
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* app/slash-palette.mjs — which slash palette (if any) the prompt draft opens.
|
|
3
3
|
*/
|
|
4
4
|
import { SLASH_COMMANDS, slashQuery, slashCommandMatches, compareSlashCommands } from './slash-commands.mjs';
|
|
5
|
+
import { skillMentionItems, skillMentionQuery } from './skill-mention-palette.mjs';
|
|
5
6
|
|
|
6
7
|
export function deriveSlashPalette({
|
|
7
8
|
providerPrompt,
|
|
@@ -14,18 +15,33 @@ export function deriveSlashPalette({
|
|
|
14
15
|
commandBusy,
|
|
15
16
|
promptDraft,
|
|
16
17
|
slashDismissedFor,
|
|
18
|
+
skills = [],
|
|
19
|
+
promptCaret = null,
|
|
17
20
|
}) {
|
|
18
21
|
const activeSlashQuery =
|
|
19
22
|
providerPrompt || settingsPrompt || toolApproval || contextPanel || usagePanel ? null : slashQuery(promptDraft);
|
|
23
|
+
const surfaceFree = !picker && !toolApproval && !contextPanel && !usagePanel && !exiting && !commandBusy;
|
|
20
24
|
// "Slash mode" is live whenever a /token is being edited and no other
|
|
21
25
|
// surface owns the floating area. The palette stays OPEN for the whole
|
|
22
26
|
// slash session — including 0-match frames — so its 14-row layout never
|
|
23
27
|
// unmounts/remounts per keystroke (fullscreen repaint flicker fix).
|
|
24
|
-
const slashModeLive =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
const slashModeLive = activeSlashQuery !== null && surfaceFree;
|
|
29
|
+
if (!slashModeLive) {
|
|
30
|
+
// `$name` completion shares the palette, but opens only while a skill
|
|
31
|
+
// matches: `$HOME` or `$300` in prose must not raise a panel.
|
|
32
|
+
const mention =
|
|
33
|
+
surfaceFree && !providerPrompt && !settingsPrompt ? skillMentionQuery(promptDraft, promptCaret) : null;
|
|
34
|
+
const slashCommands = mention ? skillMentionItems(skills, mention.query) : [];
|
|
35
|
+
return {
|
|
36
|
+
activeSlashQuery: mention ? mention.query : null,
|
|
37
|
+
slashCommands,
|
|
38
|
+
slashPaletteOpen: slashCommands.length > 0 && slashDismissedFor !== promptDraft,
|
|
39
|
+
paletteKind: mention ? 'skills' : 'commands',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const slashCommands = SLASH_COMMANDS.filter((command) => slashCommandMatches(command, activeSlashQuery)).sort(
|
|
43
|
+
compareSlashCommands
|
|
44
|
+
);
|
|
45
|
+
const slashPaletteOpen = slashDismissedFor !== promptDraft;
|
|
46
|
+
return { activeSlashQuery, slashCommands, slashPaletteOpen, paletteKind: 'commands' };
|
|
31
47
|
}
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
import { isShellTool } from '../../runtime/shared/tool-card-model/shell-surface.mjs';
|
|
21
21
|
import { stripLeadingStatusMarkerFromText } from '../../runtime/shared/tool-card-model/terminal-status.mjs';
|
|
22
22
|
import { readRowsForDisplay } from '../../runtime/shared/read-row-numbers.mjs';
|
|
23
|
+
import { appliedSkillsLine } from '../components/user-message-skills.mjs';
|
|
23
24
|
import { aggregateRawResultForDisplay } from '../session/tool-result-status.mjs';
|
|
24
25
|
import { formatExpandedResult, wrapExpandedResultLines } from '../components/tool-output-format.mjs';
|
|
25
26
|
import {
|
|
@@ -100,7 +101,9 @@ function toolDisplayedResultTextForRows(item) {
|
|
|
100
101
|
const backgroundError = String(bgArgs.error || '');
|
|
101
102
|
const normalizedName = String(normalizeToolName(item?.name) || '').toLowerCase();
|
|
102
103
|
const errorOnlyResult =
|
|
103
|
-
Boolean(rt) &&
|
|
104
|
+
Boolean(rt) &&
|
|
105
|
+
hasBackgroundMetaForRows(normalizedName, bgArgs, rt) &&
|
|
106
|
+
isBackgroundErrorOnlyBody(rt, backgroundError);
|
|
104
107
|
if (!toolItemPendingForRows(item) && isBackgroundTaskTool(normalizedName)) {
|
|
105
108
|
const meta = parseBackgroundTaskResultForRows(rt);
|
|
106
109
|
if (meta?.hasResponse && String(meta.body || '').trim()) {
|
|
@@ -213,8 +216,13 @@ function estimateToolRenderedResultRows(value, { pathArg = '', isShell = false,
|
|
|
213
216
|
export function estimateTranscriptItemRows(item, columns, toolOutputExpanded, attachedTool = false) {
|
|
214
217
|
if (!item) return 1;
|
|
215
218
|
switch (item.kind) {
|
|
216
|
-
case 'user':
|
|
217
|
-
|
|
219
|
+
case 'user': {
|
|
220
|
+
// UserMessage: marginTop + wrapped text + the applied-skills line.
|
|
221
|
+
const skillsLine = appliedSkillsLine(item.appliedSkills);
|
|
222
|
+
return (
|
|
223
|
+
1 + estimateWrappedRows(item.text, columns, 4) + (skillsLine ? estimateWrappedRows(skillsLine, columns, 4) : 0)
|
|
224
|
+
);
|
|
225
|
+
}
|
|
218
226
|
case 'assistant':
|
|
219
227
|
// marginTop={1} (AssistantMessage <Box>) + rendered body height.
|
|
220
228
|
return (
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { useCallback } from 'react';
|
|
10
10
|
import { slashCommandTokenForPaletteAccept } from './slash-commands.mjs';
|
|
11
11
|
import { withPickerEnterLatch } from './picker-enter-latch.mjs';
|
|
12
|
+
import { completeSkillMention } from './skill-mention-palette.mjs';
|
|
12
13
|
import { applyPromptDraftChange } from './use-prompt-draft-flow/draft-change.mjs';
|
|
13
14
|
import { cancelProviderPromptFlow, cancelSettingsPromptFlow } from './use-prompt-draft-flow/prompt-cancels.mjs';
|
|
14
15
|
|
|
@@ -85,9 +86,12 @@ export function usePromptDraftFlow({
|
|
|
85
86
|
);
|
|
86
87
|
|
|
87
88
|
const acceptSlashPalette = useCallback(
|
|
88
|
-
(draftValue = '') => {
|
|
89
|
+
(draftValue = '', caret) => {
|
|
89
90
|
const command = slashCommands[slashIndex];
|
|
90
91
|
if (!command) return false;
|
|
92
|
+
// A skill row completes the `$name` mention at the caret (the returned
|
|
93
|
+
// { value, cursor } replaces the draft) instead of running anything.
|
|
94
|
+
if (command.kind === 'skill') return completeSkillMention(draftValue, command.name, caret) ?? false;
|
|
91
95
|
return withPickerEnterLatch(pickerOpenedFromEnterRef, pickerOpenedFromEnterTimerRef, () =>
|
|
92
96
|
runSlashCommand(slashCommandTokenForPaletteAccept(command, draftValue), '')
|
|
93
97
|
);
|
|
@@ -96,9 +100,10 @@ export function usePromptDraftFlow({
|
|
|
96
100
|
);
|
|
97
101
|
|
|
98
102
|
const completeSlashPalette = useCallback(
|
|
99
|
-
(draftValue = '') => {
|
|
103
|
+
(draftValue = '', caret) => {
|
|
100
104
|
const command = slashCommands[slashIndex];
|
|
101
105
|
if (!command) return undefined;
|
|
106
|
+
if (command.kind === 'skill') return completeSkillMention(draftValue, command.name, caret);
|
|
102
107
|
const token = slashCommandTokenForPaletteAccept(command, draftValue);
|
|
103
108
|
return token ? `/${token} ` : undefined;
|
|
104
109
|
},
|
|
@@ -7,6 +7,9 @@ import { useRef, useState } from 'react';
|
|
|
7
7
|
export function usePromptState() {
|
|
8
8
|
const [promptDraft, setPromptDraft] = useState('');
|
|
9
9
|
const [promptDraftOverride, setPromptDraftOverride] = useState(null);
|
|
10
|
+
// The prompt caret offset as reported by PromptInput (null = end of draft);
|
|
11
|
+
// the `$name` skill palette reads the mention before it.
|
|
12
|
+
const [promptCaret, setPromptCaret] = useState(null);
|
|
10
13
|
const promptLayoutValueRef = useRef('');
|
|
11
14
|
const [, setPromptLayoutRows] = useState(1);
|
|
12
15
|
const [textEntryLayoutRows, setTextEntryLayoutRows] = useState(1);
|
|
@@ -26,6 +29,8 @@ export function usePromptState() {
|
|
|
26
29
|
setPromptDraft,
|
|
27
30
|
promptDraftOverride,
|
|
28
31
|
setPromptDraftOverride,
|
|
32
|
+
promptCaret,
|
|
33
|
+
setPromptCaret,
|
|
29
34
|
promptLayoutValueRef,
|
|
30
35
|
setPromptLayoutRows,
|
|
31
36
|
textEntryLayoutRows,
|
|
@@ -17,6 +17,7 @@ import { Box, Text } from 'ink';
|
|
|
17
17
|
import { theme, TURN_MARKER } from '../theme.mjs';
|
|
18
18
|
import { StreamingMarkdown, resetStreamingMarkdownStablePrefix, windowPlainStreamingText } from './Markdown.jsx';
|
|
19
19
|
import { assistantBodyWidth } from '../markdown/table-layout.mjs';
|
|
20
|
+
import { appliedSkillsLine, userTextSegments } from './user-message-skills.mjs';
|
|
20
21
|
|
|
21
22
|
// `themeEpoch` is a memo-busting prop (threaded from App): the active theme
|
|
22
23
|
// mutates `theme` in-place, so a /theme switch must re-render this memoized row
|
|
@@ -66,6 +67,7 @@ export const UserMessage = React.memo(function UserMessage({
|
|
|
66
67
|
text,
|
|
67
68
|
attached = false,
|
|
68
69
|
columns,
|
|
70
|
+
appliedSkills,
|
|
69
71
|
themeEpoch: _themeEpoch = 0,
|
|
70
72
|
}) {
|
|
71
73
|
// `attached` = the previous transcript row is also a user message (consecutive
|
|
@@ -79,6 +81,10 @@ export const UserMessage = React.memo(function UserMessage({
|
|
|
79
81
|
// makes Windows Terminal/conhost auto-wrap, which drifts the alt-screen frame
|
|
80
82
|
// and stacks stale gray bands on re-render. One narrower cell is invisible.
|
|
81
83
|
const bandColumns = Math.max(1, columns - 1);
|
|
84
|
+
// `$name` tokens of the skills this turn applied are marked; the applied
|
|
85
|
+
// skills are listed on their own line (user-message-skills.mjs).
|
|
86
|
+
const skillsLine = appliedSkillsLine(appliedSkills);
|
|
87
|
+
const segments = userTextSegments(text, appliedSkills);
|
|
82
88
|
return (
|
|
83
89
|
<Box
|
|
84
90
|
flexDirection="column"
|
|
@@ -89,8 +95,23 @@ export const UserMessage = React.memo(function UserMessage({
|
|
|
89
95
|
paddingRight={1}
|
|
90
96
|
>
|
|
91
97
|
<Text color={theme.mixdogIvory} wrap="wrap">
|
|
92
|
-
{
|
|
98
|
+
{segments.length === 1 && !segments[0].mention
|
|
99
|
+
? text
|
|
100
|
+
: segments.map((segment, index) =>
|
|
101
|
+
segment.mention ? (
|
|
102
|
+
<Text key={index} color={theme.panelTitle} bold>
|
|
103
|
+
{segment.text}
|
|
104
|
+
</Text>
|
|
105
|
+
) : (
|
|
106
|
+
segment.text
|
|
107
|
+
)
|
|
108
|
+
)}
|
|
93
109
|
</Text>
|
|
110
|
+
{skillsLine ? (
|
|
111
|
+
<Text color={theme.subtle} wrap="wrap">
|
|
112
|
+
{skillsLine}
|
|
113
|
+
</Text>
|
|
114
|
+
) : null}
|
|
94
115
|
</Box>
|
|
95
116
|
);
|
|
96
117
|
});
|
|
@@ -24,7 +24,7 @@ import { createVerticalMover } from './prompt-input/edit-chords.mjs';
|
|
|
24
24
|
import { cancelPromptImmediateFlush, schedulePromptImmediateFlush } from './prompt-input/immediate-render.mjs';
|
|
25
25
|
import { renderSelectedText } from './prompt-input/selected-text.jsx';
|
|
26
26
|
import { IME_LEFT_GUARD_COLUMNS, createCursorAnchor } from './prompt-input/cursor-anchor.mjs';
|
|
27
|
-
import { createPromptKeyHandler } from './prompt-input/key-handler.mjs';
|
|
27
|
+
import { createPromptKeyHandler, paletteResultDraft } from './prompt-input/key-handler.mjs';
|
|
28
28
|
import { createPromptMouseSelection } from './prompt-input/mouse-selection.mjs';
|
|
29
29
|
import { createUndoStack } from './prompt-input/undo-stack.mjs';
|
|
30
30
|
|
|
@@ -37,6 +37,8 @@ export function PromptInput({
|
|
|
37
37
|
commandPaletteActive = false,
|
|
38
38
|
commandPaletteOpen = commandPaletteActive,
|
|
39
39
|
commandPaletteOptionCount = commandPaletteActive ? 2 : 0,
|
|
40
|
+
commandPaletteMovesCaret = false,
|
|
41
|
+
onCaretChange,
|
|
40
42
|
mask = false,
|
|
41
43
|
hint = '',
|
|
42
44
|
hintTone = 'info',
|
|
@@ -66,6 +68,7 @@ export function PromptInput({
|
|
|
66
68
|
const [, bumpCursorAnchorEpoch] = useState(0);
|
|
67
69
|
const draftRef = useRef(draft);
|
|
68
70
|
const lastReportedValueRef = useRef(draft.value);
|
|
71
|
+
const lastReportedCursorRef = useRef(null);
|
|
69
72
|
// Bumped on every submit/draftOverride replace/unmount so an async paste
|
|
70
73
|
// (clipboard read or onPasteText promise) that resolves after the draft
|
|
71
74
|
// moved on can detect staleness and drop its result instead of mutating
|
|
@@ -171,9 +174,20 @@ export function PromptInput({
|
|
|
171
174
|
lastReportedValueRef.current = next.value;
|
|
172
175
|
onDraftChange?.(next.value);
|
|
173
176
|
}
|
|
177
|
+
reportCaret(next.cursor);
|
|
174
178
|
if (valueRef) valueRef.current = next.value;
|
|
175
179
|
};
|
|
176
180
|
|
|
181
|
+
// The caret offset for caret-aware completion (`$name` skill mentions).
|
|
182
|
+
function reportCaret(nextCursor) {
|
|
183
|
+
if (nextCursor === lastReportedCursorRef.current) return;
|
|
184
|
+
lastReportedCursorRef.current = nextCursor;
|
|
185
|
+
onCaretChange?.(nextCursor);
|
|
186
|
+
}
|
|
187
|
+
// A (re)mounted input starts at the end of its initial value.
|
|
188
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: mount-only report
|
|
189
|
+
useEffect(() => reportCaret(draftRef.current.cursor), []);
|
|
190
|
+
|
|
177
191
|
const installCursorAnchor = () => {
|
|
178
192
|
if (!boxRef.current || boxRef.current.internal_cursorAnchor) return false;
|
|
179
193
|
// The anchor function itself (box-rect publish + caret math) lives in
|
|
@@ -327,8 +341,11 @@ export function PromptInput({
|
|
|
327
341
|
const current = draftRef.current;
|
|
328
342
|
const next = prefix ? insertText(current, prefix) : current;
|
|
329
343
|
if (commandPaletteActive) {
|
|
330
|
-
const accepted = onCommandPaletteAccept?.(next.value);
|
|
331
|
-
|
|
344
|
+
const accepted = onCommandPaletteAccept?.(next.value, next.cursor);
|
|
345
|
+
const replacement = paletteResultDraft(accepted);
|
|
346
|
+
if (replacement) {
|
|
347
|
+
commitDraft(replacement);
|
|
348
|
+
} else if (accepted !== false) {
|
|
332
349
|
commitDraft({ value: '', cursor: 0, selectionAnchor: null });
|
|
333
350
|
} else if (next !== current) {
|
|
334
351
|
commitDraft(next);
|
|
@@ -361,6 +378,7 @@ export function PromptInput({
|
|
|
361
378
|
commandPaletteActive,
|
|
362
379
|
commandPaletteOpen,
|
|
363
380
|
commandPaletteOptionCount,
|
|
381
|
+
commandPaletteMovesCaret,
|
|
364
382
|
onCommandPaletteNavigate,
|
|
365
383
|
onCommandPaletteAccept,
|
|
366
384
|
onCommandPaletteCancel,
|
|
@@ -28,6 +28,7 @@ function queryMatchesAlias(command, query) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function commandDisplayLabel(command, query) {
|
|
31
|
+
if (command?.label) return command.label;
|
|
31
32
|
const usage = String(command?.usage || command?.name || '').replace(/^\/+/, '');
|
|
32
33
|
const aliasText =
|
|
33
34
|
command?.showAliasUsage !== false &&
|
|
@@ -41,7 +42,15 @@ function commandDisplayLabel(command, query) {
|
|
|
41
42
|
return `${label}${aliasText}`;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
export function SlashCommandPalette({
|
|
45
|
+
export function SlashCommandPalette({
|
|
46
|
+
commands,
|
|
47
|
+
selectedIndex = 0,
|
|
48
|
+
title = 'Commands',
|
|
49
|
+
columns = 80,
|
|
50
|
+
query = '',
|
|
51
|
+
description: descriptionText = SLASH_DESCRIPTION,
|
|
52
|
+
help: helpText = SLASH_HELP,
|
|
53
|
+
}) {
|
|
45
54
|
const total = commands.length;
|
|
46
55
|
const half = Math.floor(MAX_VISIBLE / 2);
|
|
47
56
|
let start = Math.max(0, selectedIndex - half);
|
|
@@ -58,9 +67,9 @@ export function SlashCommandPalette({ commands, selectedIndex = 0, title = 'Comm
|
|
|
58
67
|
const labelWidth = Math.min(COMMAND_LABEL_WIDTH, Math.max(12, Math.floor(columns * 0.45)));
|
|
59
68
|
const descriptionWidth = Math.max(0, columns - labelWidth - 12);
|
|
60
69
|
// Standard panel rhythm: title row, blank, description/hint row, blank, content.
|
|
61
|
-
const description = truncateText(
|
|
70
|
+
const description = truncateText(descriptionText, Math.max(0, columns - 4));
|
|
62
71
|
const titleWidth = stringWidth(String(title || ''));
|
|
63
|
-
const help = truncateText(
|
|
72
|
+
const help = truncateText(helpText, Math.max(0, columns - titleWidth - 7));
|
|
64
73
|
|
|
65
74
|
return (
|
|
66
75
|
<Box flexDirection="column" flexShrink={0} width="100%">
|
|
@@ -80,7 +80,15 @@ export const Item = React.memo(function Item({
|
|
|
80
80
|
let node = null;
|
|
81
81
|
switch (item.kind) {
|
|
82
82
|
case 'user':
|
|
83
|
-
node =
|
|
83
|
+
node = (
|
|
84
|
+
<UserMessage
|
|
85
|
+
text={item.text}
|
|
86
|
+
attached={prevKind === 'user'}
|
|
87
|
+
columns={columns}
|
|
88
|
+
appliedSkills={item.appliedSkills}
|
|
89
|
+
themeEpoch={themeEpoch}
|
|
90
|
+
/>
|
|
91
|
+
);
|
|
84
92
|
break;
|
|
85
93
|
case 'assistant':
|
|
86
94
|
node = (
|