mixdog 1.2.0 → 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.
Files changed (201) hide show
  1. package/README.md +7 -5
  2. package/package.json +1 -1
  3. package/src/defaults/shipped-history.json +4 -0
  4. package/src/defaults/skills/pptx/SKILL.md +6 -6
  5. package/src/defaults/skills/pptx/references/review.md +6 -4
  6. package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
  7. package/src/defaults/skills/setup/references/actions.md +13 -3
  8. package/src/defaults/skills/visualize/SKILL.md +12 -9
  9. package/src/rules/shared/60-verification.md +3 -1
  10. package/src/rules/shared/70-delivery.md +4 -2
  11. package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
  12. package/src/runtime/agent/orchestrator/config.mjs +10 -4
  13. package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
  14. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
  15. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
  16. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +86 -8
  17. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +5 -1
  18. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +65 -7
  19. package/src/runtime/agent/orchestrator/mcp/client.mjs +128 -44
  20. package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
  21. package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
  22. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
  23. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  24. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +19 -11
  25. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
  26. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
  27. package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
  28. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +444 -0
  29. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  30. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
  31. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +9 -2
  32. package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
  33. package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
  34. package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
  35. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
  36. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
  37. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
  38. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
  39. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
  40. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
  41. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
  42. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +2 -1
  43. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +9 -3
  44. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
  45. package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
  46. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
  47. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
  48. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
  49. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +267 -84
  50. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
  51. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
  52. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
  53. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
  54. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -0
  55. package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
  56. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
  57. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
  58. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
  59. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
  60. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
  61. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
  62. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
  63. package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
  64. package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
  65. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
  66. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
  67. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
  68. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +6 -4
  69. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
  70. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
  71. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
  72. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
  74. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
  75. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
  76. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
  77. package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
  78. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
  79. package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
  80. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
  81. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
  82. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +7 -0
  83. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +19 -12
  84. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
  85. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
  86. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
  87. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +21 -2
  89. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
  90. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
  91. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
  92. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
  93. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
  94. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
  95. package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
  96. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
  97. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
  98. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
  99. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
  100. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
  101. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
  102. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
  103. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
  104. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
  105. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
  106. package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
  107. package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
  108. package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
  109. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
  110. package/src/runtime/attachments/store.d.mts +3 -0
  111. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
  112. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
  113. package/src/runtime/channels/lib/worker-main.mjs +17 -14
  114. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
  115. package/src/runtime/effort-judge/judge-client.mjs +56 -18
  116. package/src/runtime/memory/lib/memory.mjs +1 -1
  117. package/src/runtime/memory/lib/session-ingest.mjs +2 -2
  118. package/src/runtime/shared/atomic-file.mjs +25 -4
  119. package/src/runtime/shared/extension-scopes.mjs +5 -3
  120. package/src/runtime/shared/file-lock.mjs +37 -11
  121. package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
  122. package/src/runtime/shared/llm/model-catalog.mjs +0 -12
  123. package/src/runtime/shared/llm/provider-catalog-registry.mjs +6 -0
  124. package/src/runtime/shared/plugin-manifest.mjs +18 -9
  125. package/src/runtime/shared/pristine-execution-contract.json +9 -2
  126. package/src/runtime/shared/pristine-execution.mjs +28 -4
  127. package/src/runtime/shared/provider-accounts.mjs +124 -20
  128. package/src/runtime/shared/provider-api-key.mjs +12 -0
  129. package/src/runtime/shared/shell-display.mjs +9 -3
  130. package/src/runtime/shared/skill-mentions.d.mts +10 -0
  131. package/src/runtime/shared/skill-mentions.mjs +133 -0
  132. package/src/runtime/shared/skill-script-runtime.mjs +264 -0
  133. package/src/runtime/shared/tool-primitives.mjs +35 -2
  134. package/src/runtime/shared/turn-worktree-snapshot.mjs +25 -5
  135. package/src/runtime/shared/worker-requests.mjs +15 -2
  136. package/src/session-runtime/automation-agents.mjs +8 -2
  137. package/src/session-runtime/boot/apis.mjs +55 -0
  138. package/src/session-runtime/boot/config.mjs +5 -2
  139. package/src/session-runtime/boot/facade.mjs +1 -0
  140. package/src/session-runtime/boot/infrastructure.mjs +29 -18
  141. package/src/session-runtime/conversation-import/discovery.mjs +698 -0
  142. package/src/session-runtime/conversation-import/service.mjs +369 -0
  143. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
  144. package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
  145. package/src/session-runtime/mcp-glue/connect.mjs +57 -10
  146. package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
  147. package/src/session-runtime/mcp-glue/server-catalog.mjs +115 -30
  148. package/src/session-runtime/mcp-glue.mjs +22 -2
  149. package/src/session-runtime/new-session-config.mjs +3 -2
  150. package/src/session-runtime/notification-bus.mjs +9 -2
  151. package/src/session-runtime/provider-auth/accounts.mjs +33 -15
  152. package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
  153. package/src/session-runtime/provider-readiness.mjs +16 -10
  154. package/src/session-runtime/resource-extension-sync.mjs +20 -5
  155. package/src/session-runtime/resource-mcp-api.mjs +101 -77
  156. package/src/session-runtime/resource-plugins-api.mjs +29 -41
  157. package/src/session-runtime/resource-scope-decorate.mjs +6 -8
  158. package/src/session-runtime/resource-skills-api.mjs +23 -2
  159. package/src/session-runtime/schedule-session-run.mjs +1 -1
  160. package/src/session-runtime/services/channel-session-router.mjs +4 -1
  161. package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
  162. package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
  163. package/src/session-runtime/services/provider-admin.mjs +64 -18
  164. package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
  165. package/src/session-runtime/setup-tool/executor.mjs +12 -1
  166. package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
  167. package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
  168. package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
  169. package/src/session-runtime/skills-api.mjs +7 -3
  170. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  171. package/src/session-runtime/webhook-session-run.mjs +16 -4
  172. package/src/skill-script-entry.mjs +36 -0
  173. package/src/standalone/daemon-stored-session-views.mjs +11 -3
  174. package/src/standalone/daemon.mjs +41 -4
  175. package/src/standalone/session-protocol.mjs +5 -0
  176. package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
  177. package/src/tui/App.jsx +9 -1
  178. package/src/tui/app/app-view/floating-panel.jsx +9 -1
  179. package/src/tui/app/app-view.jsx +6 -0
  180. package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
  181. package/src/tui/app/model-options.mjs +2 -0
  182. package/src/tui/app/skill-mention-palette.mjs +88 -0
  183. package/src/tui/app/slash-palette.mjs +23 -7
  184. package/src/tui/app/transcript-row-estimate.mjs +11 -3
  185. package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
  186. package/src/tui/app/use-prompt-state.mjs +5 -0
  187. package/src/tui/components/Message.jsx +22 -1
  188. package/src/tui/components/PromptInput.jsx +21 -3
  189. package/src/tui/components/SlashCommandPalette.jsx +12 -3
  190. package/src/tui/components/TranscriptItem.jsx +9 -1
  191. package/src/tui/components/prompt-input/key-handler.mjs +21 -8
  192. package/src/tui/components/user-message-skills.mjs +38 -0
  193. package/src/tui/dist/index.mjs +507 -171
  194. package/src/tui/session/queue-helpers.mjs +7 -2
  195. package/src/tui/session/session-api/extensions.mjs +4 -2
  196. package/src/tui/session/session-api/settings.mjs +7 -0
  197. package/src/tui/session/session-flow/drain.mjs +14 -4
  198. package/src/tui/session/tui-steering-persist.mjs +25 -9
  199. package/src/tui/session/turn.mjs +17 -0
  200. package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
  201. package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
@@ -23394,15 +23394,30 @@ function warnLockRateLimited(warnedAt, lockPath, line) {
23394
23394
  } catch {
23395
23395
  }
23396
23396
  }
23397
- function reportLockWait(lockPath, waitedMs, mode) {
23397
+ function formatLockTiming(timing) {
23398
+ return Object.entries(timing || {}).filter(([, ms]) => Number.isFinite(ms)).map(([name, ms]) => ` ${name}=${ms}ms`).join("");
23399
+ }
23400
+ function recordLockTiming(lockPath, fields) {
23401
+ const lease = heldLockPaths.getStore()?.get(lockPath);
23402
+ if (lease?.active) Object.assign(lease.timing, fields);
23403
+ }
23404
+ function reportLockWait(lockPath, waitedMs, mode, timing) {
23398
23405
  if (waitedMs < LOCK_WAIT_WARN_MS) return;
23399
- warnLockRateLimited(lockWaitWarnedAt, lockPath, `[atomic-file] ${mode} lock wait ${waitedMs}ms: ${lockPath}
23400
- `);
23406
+ warnLockRateLimited(
23407
+ lockWaitWarnedAt,
23408
+ lockPath,
23409
+ `[atomic-file] ${mode} lock wait ${waitedMs}ms:${formatLockTiming(timing)} ${lockPath}
23410
+ `
23411
+ );
23401
23412
  }
23402
- function reportLockHeld(lockPath, heldMs, mode) {
23413
+ function reportLockHeld(lockPath, heldMs, mode, timing) {
23403
23414
  if (heldMs < LOCK_HELD_WARN_MS) return;
23404
- warnLockRateLimited(lockHeldWarnedAt, lockPath, `[atomic-file] ${mode} lock held ${heldMs}ms: ${lockPath}
23405
- `);
23415
+ warnLockRateLimited(
23416
+ lockHeldWarnedAt,
23417
+ lockPath,
23418
+ `[atomic-file] ${mode} lock held ${heldMs}ms:${formatLockTiming(timing)} ${lockPath}
23419
+ `
23420
+ );
23406
23421
  }
23407
23422
  function* tryAcquireReclaimGuard(lockPath) {
23408
23423
  const guardPath = `${lockPath}.reclaim`;
@@ -23572,7 +23587,7 @@ function sweepStagedLockFiles(lockPath, now = Date.now()) {
23572
23587
  }
23573
23588
  return removed;
23574
23589
  }
23575
- function* acquireLock(lockPath, opts, mode, markHeld) {
23590
+ function* acquireLock(lockPath, opts, mode, markHeld, timing = null) {
23576
23591
  const timeoutMs = lockTimeoutMs(opts);
23577
23592
  const staleMs = lockStaleMs(opts);
23578
23593
  const deadline = Date.now() + timeoutMs;
@@ -23599,7 +23614,9 @@ function* acquireLock(lockPath, opts, mode, markHeld) {
23599
23614
  attempt += 1;
23600
23615
  continue;
23601
23616
  }
23602
- reportLockWait(lockPath, Date.now() - waitStartedAt, mode);
23617
+ const osMs = Date.now() - waitStartedAt;
23618
+ if (timing) timing.osAcquireMs = osMs;
23619
+ reportLockWait(lockPath, osMs, mode, timing);
23603
23620
  return;
23604
23621
  }
23605
23622
  throw timeoutError(lockPath, timeoutMs, lastError, yield* describeLockHolder(lockPath));
@@ -23625,12 +23642,14 @@ function withFileLockSync(lockPath, fn, opts = {}) {
23625
23642
  async function withFileLock(lockPath, fn, opts = {}) {
23626
23643
  if (heldLockPaths.getStore()?.get(lockPath)?.active) return fn();
23627
23644
  if (lockTimeoutMs(opts) <= 0) return withOsFileLock(lockPath, fn, opts);
23628
- return lockQueue(lockPath, () => withOsFileLock(lockPath, fn, opts));
23645
+ const enqueuedAt = Date.now();
23646
+ return lockQueue(lockPath, () => withOsFileLock(lockPath, fn, opts, Date.now() - enqueuedAt));
23629
23647
  }
23630
- async function withOsFileLock(lockPath, fn, opts = {}) {
23631
- await runAsync(acquireLock(lockPath, opts, "async", true));
23648
+ async function withOsFileLock(lockPath, fn, opts = {}, queueWaitMs = 0) {
23649
+ const timing = { queueWaitMs };
23650
+ await runAsync(acquireLock(lockPath, opts, "async", true, timing));
23632
23651
  const heldSince = Date.now();
23633
- const lease = { active: false };
23652
+ const lease = { active: false, timing };
23634
23653
  try {
23635
23654
  if (opts.secret === true) await enforceOwnerOnlyAclWin32Async(lockPath, { fresh: true });
23636
23655
  const held = new Map(heldLockPaths.getStore() || []);
@@ -23642,7 +23661,7 @@ async function withOsFileLock(lockPath, fn, opts = {}) {
23642
23661
  try {
23643
23662
  await runAsync(releaseLock(lockPath));
23644
23663
  } finally {
23645
- reportLockHeld(lockPath, Date.now() - heldSince, "async");
23664
+ reportLockHeld(lockPath, Date.now() - heldSince, "async", timing);
23646
23665
  unmarkOsHeld(lockPath);
23647
23666
  }
23648
23667
  }
@@ -23919,7 +23938,28 @@ async function writeFileAtomicAsync(filePath, data, opts = {}) {
23919
23938
  throw err;
23920
23939
  }
23921
23940
  };
23922
- return opts.lock === true ? withFileLock(`${filePath}.lock`, () => _runAdaptiveFileIo(run), opts) : _runAdaptiveFileIo(run);
23941
+ if (opts.lock !== true) return _runAdaptiveFileIo(run);
23942
+ const lockPath = `${filePath}.lock`;
23943
+ return withFileLock(
23944
+ lockPath,
23945
+ async () => {
23946
+ const queuedAt = Date.now();
23947
+ let startedAt = 0;
23948
+ try {
23949
+ return await _runAdaptiveFileIo(() => {
23950
+ startedAt = Date.now();
23951
+ return run();
23952
+ });
23953
+ } finally {
23954
+ const now = Date.now();
23955
+ recordLockTiming(lockPath, {
23956
+ ioGateWaitMs: (startedAt || now) - queuedAt,
23957
+ writeMs: startedAt ? now - startedAt : 0
23958
+ });
23959
+ }
23960
+ },
23961
+ opts
23962
+ );
23923
23963
  }
23924
23964
  function writeJsonAtomicAsync(filePath, value, opts = {}) {
23925
23965
  return writeFileAtomicAsync(filePath, `${JSON.stringify(value, null, opts.compact ? 0 : 2)}
@@ -35075,7 +35115,7 @@ import { performance as performance2 } from "node:perf_hooks";
35075
35115
  import { format } from "node:util";
35076
35116
 
35077
35117
  // src/tui/App.jsx
35078
- import { useState as useState19, useCallback as useCallback29, useEffect as useEffect30, useLayoutEffect as useLayoutEffect9, useMemo as useMemo9, useRef as useRef29 } from "react";
35118
+ import { useState as useState20, useCallback as useCallback29, useEffect as useEffect31, useLayoutEffect as useLayoutEffect9, useMemo as useMemo9, useRef as useRef29 } from "react";
35079
35119
 
35080
35120
  // src/tui/hooks/useSession.mjs
35081
35121
  import { useSyncExternalStore } from "react";
@@ -35489,6 +35529,154 @@ function slashArgumentHint(value) {
35489
35529
  return command?.params ? `${command.usage} ${command.params}` : "";
35490
35530
  }
35491
35531
 
35532
+ // src/tui/app/skill-mention-palette.mjs
35533
+ import { useEffect as useEffect7, useState as useState6 } from "react";
35534
+
35535
+ // src/runtime/shared/skill-mentions.mjs
35536
+ var MENTION = /(^|[\s([{"'`])\$([a-z0-9][a-z0-9-]{0,63})(?![A-Za-z0-9_-])/g;
35537
+ var RESERVED_NAMES = /* @__PURE__ */ new Set([
35538
+ "path",
35539
+ "home",
35540
+ "user",
35541
+ "shell",
35542
+ "pwd",
35543
+ "tmpdir",
35544
+ "temp",
35545
+ "tmp",
35546
+ "lang",
35547
+ "term",
35548
+ "xdg_config_home",
35549
+ "userprofile",
35550
+ "appdata",
35551
+ "localappdata",
35552
+ "programfiles",
35553
+ "systemroot",
35554
+ "windir",
35555
+ "comspec"
35556
+ ]);
35557
+ function isReservedMentionName(name) {
35558
+ const value = String(name ?? "");
35559
+ return /^[0-9]+$/.test(value) || RESERVED_NAMES.has(value.toLowerCase());
35560
+ }
35561
+ var FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
35562
+ var FENCE_CLOSE = /^ {0,3}(`{3,}|~{3,})[ \t]*$/;
35563
+ function inlineCodeRanges(source, from, to, ranges) {
35564
+ const runs = [];
35565
+ const re = /`+/g;
35566
+ re.lastIndex = from;
35567
+ for (let match = re.exec(source); match && match.index < to; match = re.exec(source)) {
35568
+ runs.push({ start: match.index, end: Math.min(to, match.index + match[0].length) });
35569
+ }
35570
+ for (let index = 0; index < runs.length; index += 1) {
35571
+ const length = runs[index].end - runs[index].start;
35572
+ const close = runs.findIndex((run, at) => at > index && run.end - run.start === length);
35573
+ if (close < 0) continue;
35574
+ ranges.push([runs[index].start, runs[close].end]);
35575
+ index = close;
35576
+ }
35577
+ }
35578
+ function codeRanges(source) {
35579
+ const ranges = [];
35580
+ let open = null;
35581
+ let proseStart = 0;
35582
+ for (let at = 0; at <= source.length; ) {
35583
+ const newline = source.indexOf("\n", at);
35584
+ const end = newline < 0 ? source.length : newline;
35585
+ const next = newline < 0 ? source.length + 1 : newline + 1;
35586
+ const line = source.slice(at, end).replace(/\r$/, "");
35587
+ if (!open) {
35588
+ const fence = FENCE_OPEN.exec(line);
35589
+ if (fence && !(fence[1][0] === "`" && fence[2].includes("`"))) {
35590
+ inlineCodeRanges(source, proseStart, at, ranges);
35591
+ open = { char: fence[1][0], length: fence[1].length, start: at };
35592
+ }
35593
+ } else {
35594
+ const fence = FENCE_CLOSE.exec(line);
35595
+ if (fence && fence[1][0] === open.char && fence[1].length >= open.length) {
35596
+ ranges.push([open.start, Math.min(next, source.length)]);
35597
+ proseStart = Math.min(next, source.length);
35598
+ open = null;
35599
+ }
35600
+ }
35601
+ at = next;
35602
+ }
35603
+ if (open) ranges.push([open.start, source.length]);
35604
+ else inlineCodeRanges(source, proseStart, source.length, ranges);
35605
+ return ranges;
35606
+ }
35607
+ function isInMarkdownCode(text, offset) {
35608
+ const source = typeof text === "string" ? text : "";
35609
+ if (!Number.isInteger(offset) || !source.includes("`") && !source.includes("~~~")) return false;
35610
+ return codeRanges(source).some(([from, to]) => offset >= from && offset < to);
35611
+ }
35612
+ function skillMentionCandidates(text) {
35613
+ const source = typeof text === "string" ? text : "";
35614
+ const found = [];
35615
+ let code = null;
35616
+ for (const match of source.matchAll(MENTION)) {
35617
+ if (isReservedMentionName(match[2])) continue;
35618
+ const start = match.index + match[1].length;
35619
+ code ??= source.includes("`") || source.includes("~~~") ? codeRanges(source) : [];
35620
+ if (code.some(([from, to]) => start >= from && start < to)) continue;
35621
+ found.push({ name: match[2], start, end: start + 1 + match[2].length });
35622
+ }
35623
+ return found;
35624
+ }
35625
+ function skillMentions(text, isSkill) {
35626
+ return skillMentionCandidates(text).filter((mention) => isSkill(mention.name));
35627
+ }
35628
+
35629
+ // src/tui/app/skill-mention-palette.mjs
35630
+ var MENTION_TAIL = /(^|[\s([{"'`])\$([a-z0-9][a-z0-9-]{0,63})?$/;
35631
+ var caretIn = (text, caret) => Number.isInteger(caret) ? Math.max(0, Math.min(text.length, caret)) : text.length;
35632
+ function skillMentionQuery(value, caret) {
35633
+ const text = String(value ?? "");
35634
+ const end = caretIn(text, caret);
35635
+ const match = MENTION_TAIL.exec(text.slice(0, end));
35636
+ if (!match) return null;
35637
+ const start = match.index + match[1].length;
35638
+ if (isInMarkdownCode(text, start)) return null;
35639
+ return { query: match[2] || "", start, end };
35640
+ }
35641
+ var byName = (a, b) => a.name.localeCompare(b.name, "en");
35642
+ function skillMentionItems(skills, query) {
35643
+ const needle = String(query || "").toLowerCase();
35644
+ const usable = (Array.isArray(skills) ? skills : []).filter(
35645
+ (skill) => typeof skill?.name === "string" && skill.name && skill.enabled !== false && skill.activeHere !== false && skill.source !== "builtin" && // `$path`/`$300` are never mentions, so offering them would insert prose.
35646
+ !isReservedMentionName(skill.name)
35647
+ );
35648
+ const prefix = usable.filter((skill) => skill.name.startsWith(needle)).sort(byName);
35649
+ const contains = needle ? usable.filter((skill) => !skill.name.startsWith(needle) && skill.name.includes(needle)).sort(byName) : [];
35650
+ return [...prefix, ...contains].map((skill) => ({
35651
+ kind: "skill",
35652
+ name: skill.name,
35653
+ label: `$${skill.name}`,
35654
+ description: skill.description || ""
35655
+ }));
35656
+ }
35657
+ function completeSkillMention(value, name, caret) {
35658
+ const text = String(value ?? "");
35659
+ const mention = skillMentionQuery(text, caret);
35660
+ if (!mention || !name) return void 0;
35661
+ const head = `${text.slice(0, mention.start)}$${name} `;
35662
+ return { value: head + text.slice(mention.end), cursor: head.length };
35663
+ }
35664
+ function useSkillMentionSkills(store, active) {
35665
+ const [skills, setSkills] = useState6([]);
35666
+ useEffect7(() => {
35667
+ if (!active) return void 0;
35668
+ let live = true;
35669
+ Promise.resolve().then(() => store.skillsStatus?.()).then((status) => {
35670
+ if (live) setSkills(Array.isArray(status?.skills) ? status.skills : []);
35671
+ }).catch(() => {
35672
+ });
35673
+ return () => {
35674
+ live = false;
35675
+ };
35676
+ }, [store, active]);
35677
+ return skills;
35678
+ }
35679
+
35492
35680
  // src/tui/app/slash-palette.mjs
35493
35681
  function deriveSlashPalette({
35494
35682
  providerPrompt,
@@ -35500,13 +35688,28 @@ function deriveSlashPalette({
35500
35688
  exiting,
35501
35689
  commandBusy,
35502
35690
  promptDraft,
35503
- slashDismissedFor
35691
+ slashDismissedFor,
35692
+ skills = [],
35693
+ promptCaret = null
35504
35694
  }) {
35505
35695
  const activeSlashQuery = providerPrompt || settingsPrompt || toolApproval || contextPanel || usagePanel ? null : slashQuery(promptDraft);
35506
- const slashModeLive = activeSlashQuery !== null && !picker && !toolApproval && !contextPanel && !usagePanel && !exiting && !commandBusy;
35507
- const slashCommands = !slashModeLive ? [] : SLASH_COMMANDS.filter((command) => slashCommandMatches(command, activeSlashQuery)).sort(compareSlashCommands);
35508
- const slashPaletteOpen = slashModeLive && slashDismissedFor !== promptDraft;
35509
- return { activeSlashQuery, slashCommands, slashPaletteOpen };
35696
+ const surfaceFree = !picker && !toolApproval && !contextPanel && !usagePanel && !exiting && !commandBusy;
35697
+ const slashModeLive = activeSlashQuery !== null && surfaceFree;
35698
+ if (!slashModeLive) {
35699
+ const mention = surfaceFree && !providerPrompt && !settingsPrompt ? skillMentionQuery(promptDraft, promptCaret) : null;
35700
+ const slashCommands2 = mention ? skillMentionItems(skills, mention.query) : [];
35701
+ return {
35702
+ activeSlashQuery: mention ? mention.query : null,
35703
+ slashCommands: slashCommands2,
35704
+ slashPaletteOpen: slashCommands2.length > 0 && slashDismissedFor !== promptDraft,
35705
+ paletteKind: mention ? "skills" : "commands"
35706
+ };
35707
+ }
35708
+ const slashCommands = SLASH_COMMANDS.filter((command) => slashCommandMatches(command, activeSlashQuery)).sort(
35709
+ compareSlashCommands
35710
+ );
35711
+ const slashPaletteOpen = slashDismissedFor !== promptDraft;
35712
+ return { activeSlashQuery, slashCommands, slashPaletteOpen, paletteKind: "commands" };
35510
35713
  }
35511
35714
 
35512
35715
  // src/tui/app/panel-epoch.mjs
@@ -35611,7 +35814,7 @@ function resolvePickerState(prev, resolved, { pickerOpenedFromEnterRef, pickerOp
35611
35814
  }
35612
35815
 
35613
35816
  // src/tui/app/use-prompt-layout-rows.mjs
35614
- import { useCallback as useCallback5, useEffect as useEffect7 } from "react";
35817
+ import { useCallback as useCallback5, useEffect as useEffect8 } from "react";
35615
35818
  import stringWidth3 from "string-width";
35616
35819
 
35617
35820
  // src/tui/display-width.mjs
@@ -35796,10 +35999,10 @@ function usePromptLayoutRows({
35796
35999
  },
35797
36000
  [promptContentColumns]
35798
36001
  );
35799
- useEffect7(() => {
36002
+ useEffect8(() => {
35800
36003
  syncPromptLayoutRows(promptLayoutValueRef.current);
35801
36004
  }, [syncPromptLayoutRows]);
35802
- useEffect7(() => {
36005
+ useEffect8(() => {
35803
36006
  const kind = String(settingsPrompt?.kind || "");
35804
36007
  if (!CORE_MULTILINE_TEXT_ENTRY_KINDS.has(kind)) {
35805
36008
  setTextEntryLayoutRows(1);
@@ -35812,7 +36015,7 @@ function usePromptLayoutRows({
35812
36015
  }
35813
36016
 
35814
36017
  // src/tui/app/use-panel-transition.mjs
35815
- import { useEffect as useEffect8 } from "react";
36018
+ import { useEffect as useEffect9 } from "react";
35816
36019
  function usePanelTransition({
35817
36020
  panelTransitionRef,
35818
36021
  panelCloseInkMaskRowsRef,
@@ -35824,7 +36027,7 @@ function usePanelTransition({
35824
36027
  setPanelInkMaskEpoch,
35825
36028
  setPanelTransitionEpoch
35826
36029
  }) {
35827
- useEffect8(() => {
36030
+ useEffect9(() => {
35828
36031
  const transition = panelTransitionRef.current;
35829
36032
  const pendingInkMask = panelCloseInkMaskRowsRef.current;
35830
36033
  const hadTransitionClearance = panelTransitionClearRows > 0 || panelTransitionGuardRows > 0;
@@ -35841,13 +36044,13 @@ function usePanelTransition({
35841
36044
  const timer2 = setTimeout(() => setPanelTransitionEpoch((epoch) => epoch + 1), 0);
35842
36045
  return () => clearTimeout(timer2);
35843
36046
  }, [panelLayoutSignature, bottomClusterRows, panelTransitionClearRows, panelTransitionGuardRows]);
35844
- useEffect8(() => {
36047
+ useEffect9(() => {
35845
36048
  panelTransitionRef.current.tailId = latestTranscriptItem?.id ?? null;
35846
36049
  });
35847
36050
  }
35848
36051
 
35849
36052
  // src/tui/app/use-ui-open-request.mjs
35850
- import { useEffect as useEffect9, useRef as useRef4 } from "react";
36053
+ import { useEffect as useEffect10, useRef as useRef4 } from "react";
35851
36054
  var SETUP_SECTION_TARGETS = Object.freeze({
35852
36055
  developer: ({ openDeveloperPicker }) => openDeveloperPicker(),
35853
36056
  voice: ({ openSettingsPicker }) => openSettingsPicker(),
@@ -35855,7 +36058,7 @@ var SETUP_SECTION_TARGETS = Object.freeze({
35855
36058
  });
35856
36059
  function useUiOpenRequest({ uiOpenRequest, runSlashCommand, sections }) {
35857
36060
  const seenRef = useRef4(0);
35858
- useEffect9(() => {
36061
+ useEffect10(() => {
35859
36062
  const request = uiOpenRequest;
35860
36063
  const seq = Number(request?.seq) || 0;
35861
36064
  if (!request?.command || seq <= seenRef.current) return;
@@ -35867,7 +36070,7 @@ function useUiOpenRequest({ uiOpenRequest, runSlashCommand, sections }) {
35867
36070
  }
35868
36071
 
35869
36072
  // src/tui/app/use-mouse-input.mjs
35870
- import { useCallback as useCallback6, useEffect as useEffect10, useRef as useRef5 } from "react";
36073
+ import { useCallback as useCallback6, useEffect as useEffect11, useRef as useRef5 } from "react";
35871
36074
 
35872
36075
  // src/tui/markdown/streaming-markdown.mjs
35873
36076
  import { marked as marked2 } from "marked";
@@ -38936,8 +39139,21 @@ function stripToolPrefix(name) {
38936
39139
  function rawToolName(name) {
38937
39140
  return String(name || "tool").replace(/^functions\./, "");
38938
39141
  }
38939
- function parseMcpToolName(name) {
38940
- const text = rawToolName(name);
39142
+ var mcpToolIdentities = /* @__PURE__ */ new Map();
39143
+ function knownMcpToolIdentity(name) {
39144
+ const known = mcpToolIdentities.get(rawToolName(name));
39145
+ return known ? { ...known } : null;
39146
+ }
39147
+ function parseMcpToolName(nameOrTool) {
39148
+ if (nameOrTool && typeof nameOrTool === "object") {
39149
+ const server = String(nameOrTool.mcpServerName || "").trim();
39150
+ const parsed = parseMcpToolName(nameOrTool.name);
39151
+ if (!server) return parsed;
39152
+ return { server, tool: String(nameOrTool.mcpToolName || "") || parsed?.tool || "" };
39153
+ }
39154
+ const text = rawToolName(nameOrTool);
39155
+ const known = mcpToolIdentities.get(text);
39156
+ if (known) return { ...known };
38941
39157
  const match = /^mcp__(.+?)__(.+)$/.exec(text);
38942
39158
  if (!match) return null;
38943
39159
  return { server: match[1], tool: match[2] };
@@ -39041,6 +39257,8 @@ function toolSearchDisplayLabel(args = {}) {
39041
39257
  function displayToolSearchTarget(value) {
39042
39258
  const text = String(value || "").trim();
39043
39259
  if (/^skill:/i.test(text)) return text.slice("skill:".length);
39260
+ const known = knownMcpToolIdentity(text);
39261
+ if (known) return `${known.server}.${known.tool}`;
39044
39262
  const mcp = /^mcp__(.*?)__(.+)$/.exec(text);
39045
39263
  if (mcp) return `${mcp[1]}.${mcp[2]}`;
39046
39264
  return stripToolPrefix(text);
@@ -42760,6 +42978,29 @@ function deriveToolCardModel(input = {}, options = {}) {
42760
42978
  };
42761
42979
  }
42762
42980
 
42981
+ // src/tui/components/user-message-skills.mjs
42982
+ function appliedSkillNames(value) {
42983
+ return (Array.isArray(value) ? value : []).filter((name) => typeof name === "string" && name);
42984
+ }
42985
+ function appliedSkillsLine(value) {
42986
+ const names = appliedSkillNames(value);
42987
+ return names.length ? `Skills applied: ${names.join(", ")}` : "";
42988
+ }
42989
+ function userTextSegments(text, value) {
42990
+ const source = String(text ?? "");
42991
+ const applied = new Set(appliedSkillNames(value));
42992
+ if (!applied.size) return [{ text: source, mention: false }];
42993
+ const segments = [];
42994
+ let at = 0;
42995
+ for (const mention of skillMentions(source, (name) => applied.has(name))) {
42996
+ if (mention.start > at) segments.push({ text: source.slice(at, mention.start), mention: false });
42997
+ segments.push({ text: source.slice(mention.start, mention.end), mention: true });
42998
+ at = mention.end;
42999
+ }
43000
+ if (at < source.length || !segments.length) segments.push({ text: source.slice(at), mention: false });
43001
+ return segments;
43002
+ }
43003
+
42763
43004
  // src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs
42764
43005
  function aggregateRawResultForDisplay(text) {
42765
43006
  if (typeof text !== "string" || !/^\[lines \d+-\d+\]$/m.test(text)) return text;
@@ -43364,8 +43605,10 @@ function estimateToolRenderedResultRows(value, { pathArg = "", isShell = false,
43364
43605
  function estimateTranscriptItemRows(item, columns, toolOutputExpanded, attachedTool = false) {
43365
43606
  if (!item) return 1;
43366
43607
  switch (item.kind) {
43367
- case "user":
43368
- return 1 + estimateWrappedRows(item.text, columns, 4);
43608
+ case "user": {
43609
+ const skillsLine = appliedSkillsLine(item.appliedSkills);
43610
+ return 1 + estimateWrappedRows(item.text, columns, 4) + (skillsLine ? estimateWrappedRows(skillsLine, columns, 4) : 0);
43611
+ }
43369
43612
  case "assistant":
43370
43613
  return 1 + (item.streaming ? measureStreamingMarkdownRenderedRows(item.text, columns, item.id) : measureMarkdownRenderedRows(item.text, columns, { trimPartialFences: true }));
43371
43614
  case "tool": {
@@ -44416,12 +44659,12 @@ function useMouseInput({
44416
44659
  const passthroughCtrlWheelZoom = useCallback6(() => {
44417
44660
  zoomRestoreSchedulerRef.current.passthrough();
44418
44661
  }, []);
44419
- useEffect10(() => {
44662
+ useEffect11(() => {
44420
44663
  const scheduler = zoomRestoreSchedulerRef.current;
44421
44664
  scheduler.attach();
44422
44665
  return () => scheduler.detach();
44423
44666
  }, []);
44424
- useEffect10(() => {
44667
+ useEffect11(() => {
44425
44668
  if (!inkInput || !isRawModeSupported) return void 0;
44426
44669
  const geometry = createMouseGeometry({
44427
44670
  transcriptViewportRef,
@@ -44511,7 +44754,7 @@ function useMouseInput({
44511
44754
  }
44512
44755
 
44513
44756
  // src/tui/app/use-transcript-scroll.mjs
44514
- import { useCallback as useCallback12, useEffect as useEffect13, useLayoutEffect as useLayoutEffect3, useRef as useRef10 } from "react";
44757
+ import { useCallback as useCallback12, useEffect as useEffect14, useLayoutEffect as useLayoutEffect3, useRef as useRef10 } from "react";
44515
44758
 
44516
44759
  // src/tui/app/transcript-scroll-anchor.mjs
44517
44760
  function readingAnchorAt(geom, target) {
@@ -44533,7 +44776,7 @@ function bottomSnapRows(viewRows) {
44533
44776
  }
44534
44777
 
44535
44778
  // src/tui/app/use-selection-stitch.mjs
44536
- import { useCallback as useCallback7, useEffect as useEffect11, useRef as useRef6 } from "react";
44779
+ import { useCallback as useCallback7, useEffect as useEffect12, useRef as useRef6 } from "react";
44537
44780
  function storeStitchRows(buffer, rows2, scroll) {
44538
44781
  for (const row of rows2) {
44539
44782
  if (!row || typeof row.y !== "number") continue;
@@ -44547,7 +44790,7 @@ function useSelectionStitchBuffer({ store, dragRef, scrollTargetRef }) {
44547
44790
  const stitchBufferRef = useRef6(/* @__PURE__ */ new Map());
44548
44791
  const stitchHarvestTimerRef = useRef6(null);
44549
44792
  const stitchHarvestScrollRef = useRef6(0);
44550
- useEffect11(
44793
+ useEffect12(
44551
44794
  () => () => {
44552
44795
  if (stitchHarvestTimerRef.current) clearTimeout(stitchHarvestTimerRef.current);
44553
44796
  stitchHarvestTimerRef.current = null;
@@ -44676,7 +44919,7 @@ function useTranscriptFollow({
44676
44919
  }
44677
44920
 
44678
44921
  // src/tui/app/use-selection-paint.mjs
44679
- import { useCallback as useCallback9, useEffect as useEffect12, useRef as useRef8 } from "react";
44922
+ import { useCallback as useCallback9, useEffect as useEffect13, useRef as useRef8 } from "react";
44680
44923
 
44681
44924
  // src/tui/session/render-frame-source.mjs
44682
44925
  var sources = /* @__PURE__ */ new Set();
@@ -44868,7 +45111,7 @@ function useSelectionPaint({
44868
45111
  }) {
44869
45112
  const selectionPaintRef = useRef8({ t: 0, rect: null, pending: null, timer: null });
44870
45113
  const selectionTextCaptureRef = useRef8(0);
44871
- useEffect12(
45114
+ useEffect13(
44872
45115
  () => () => {
44873
45116
  const paintState = selectionPaintRef.current;
44874
45117
  if (paintState.timer) clearTimeout(paintState.timer);
@@ -45114,7 +45357,7 @@ function useSelectionFocusMove({
45114
45357
  // src/tui/app/use-transcript-scroll.mjs
45115
45358
  function useScrollCoalescer(scrollTranscriptRows) {
45116
45359
  const scrollCoalesceRef = useRef10({ pendingRows: 0, direction: 0, timer: null });
45117
- useEffect13(
45360
+ useEffect14(
45118
45361
  () => () => {
45119
45362
  const state = scrollCoalesceRef.current;
45120
45363
  if (state.timer) clearTimeout(state.timer);
@@ -45370,9 +45613,9 @@ function useTranscriptScroll({
45370
45613
  }
45371
45614
 
45372
45615
  // src/tui/app/use-transcript-scroll-state.mjs
45373
- import { useRef as useRef11, useState as useState6 } from "react";
45616
+ import { useRef as useRef11, useState as useState7 } from "react";
45374
45617
  function useTranscriptScrollState() {
45375
- const [scrollOffset, setScrollOffset] = useState6(0);
45618
+ const [scrollOffset, setScrollOffset] = useState7(0);
45376
45619
  const scrollPositionRef = useRef11(0);
45377
45620
  const scrollTargetRef = useRef11(0);
45378
45621
  const maxScrollRowsRef = useRef11(0);
@@ -45380,7 +45623,7 @@ function useTranscriptScrollState() {
45380
45623
  const transcriptAnchorRef = useRef11(null);
45381
45624
  const transcriptAnchorDirtyRef = useRef11(false);
45382
45625
  const transcriptGeomRef = useRef11({ prefixRows: null, totalRows: 0, viewRows: 1 });
45383
- const [measuredRowsVersion, setMeasuredRowsVersion] = useState6(0);
45626
+ const [measuredRowsVersion, setMeasuredRowsVersion] = useState7(0);
45384
45627
  const followingRef = useRef11(false);
45385
45628
  const lastItemsCountRef = useRef11(0);
45386
45629
  const lastFirstItemIdRef = useRef11(null);
@@ -45403,13 +45646,14 @@ function useTranscriptScrollState() {
45403
45646
  }
45404
45647
 
45405
45648
  // src/tui/app/use-prompt-state.mjs
45406
- import { useRef as useRef12, useState as useState7 } from "react";
45649
+ import { useRef as useRef12, useState as useState8 } from "react";
45407
45650
  function usePromptState() {
45408
- const [promptDraft, setPromptDraft] = useState7("");
45409
- const [promptDraftOverride, setPromptDraftOverride] = useState7(null);
45651
+ const [promptDraft, setPromptDraft] = useState8("");
45652
+ const [promptDraftOverride, setPromptDraftOverride] = useState8(null);
45653
+ const [promptCaret, setPromptCaret] = useState8(null);
45410
45654
  const promptLayoutValueRef = useRef12("");
45411
- const [, setPromptLayoutRows] = useState7(1);
45412
- const [textEntryLayoutRows, setTextEntryLayoutRows] = useState7(1);
45655
+ const [, setPromptLayoutRows] = useState8(1);
45656
+ const [textEntryLayoutRows, setTextEntryLayoutRows] = useState8(1);
45413
45657
  const promptValueRef = useRef12("");
45414
45658
  const promptSelectionRef = useRef12(null);
45415
45659
  const promptBoxRectRef = useRef12(null);
@@ -45421,6 +45665,8 @@ function usePromptState() {
45421
45665
  setPromptDraft,
45422
45666
  promptDraftOverride,
45423
45667
  setPromptDraftOverride,
45668
+ promptCaret,
45669
+ setPromptCaret,
45424
45670
  promptLayoutValueRef,
45425
45671
  setPromptLayoutRows,
45426
45672
  textEntryLayoutRows,
@@ -45468,7 +45714,7 @@ function useInteractionRefs() {
45468
45714
  }
45469
45715
 
45470
45716
  // src/tui/app/use-pasted-buffers.mjs
45471
- import { useCallback as useCallback13, useRef as useRef14, useState as useState8 } from "react";
45717
+ import { useCallback as useCallback13, useRef as useRef14, useState as useState9 } from "react";
45472
45718
 
45473
45719
  // src/tui/paste-attachments.mjs
45474
45720
  import { execFile } from "node:child_process";
@@ -46035,7 +46281,7 @@ async function readClipboardText() {
46035
46281
 
46036
46282
  // src/tui/app/use-pasted-buffers.mjs
46037
46283
  function usePastedBufferSlice({ toEntry, formatRef }) {
46038
- const [, setBuffers] = useState8({});
46284
+ const [, setBuffers] = useState9({});
46039
46285
  const buffersRef = useRef14({});
46040
46286
  const nextIdRef = useRef14(1);
46041
46287
  const install = useCallback13((buffers, { merge = true } = {}) => {
@@ -46104,11 +46350,11 @@ function usePastedBuffers() {
46104
46350
  }
46105
46351
 
46106
46352
  // src/tui/app/use-prompt-hint.mjs
46107
- import { useCallback as useCallback14, useEffect as useEffect14, useRef as useRef15, useState as useState9 } from "react";
46353
+ import { useCallback as useCallback14, useEffect as useEffect15, useRef as useRef15, useState as useState10 } from "react";
46108
46354
  var PROMPT_HINT_DISMISS_MS = 2200;
46109
46355
  function usePromptHint() {
46110
- const [promptHint, setPromptHint] = useState9("");
46111
- const [promptHintTone, setPromptHintTone] = useState9("info");
46356
+ const [promptHint, setPromptHint] = useState10("");
46357
+ const [promptHintTone, setPromptHintTone] = useState10("info");
46112
46358
  const promptHintTimerRef = useRef15(null);
46113
46359
  const promptHintActiveRef = useRef15(false);
46114
46360
  const showPromptHint = useCallback14((text, tone = "info", dismissMs = PROMPT_HINT_DISMISS_MS) => {
@@ -46135,7 +46381,7 @@ function usePromptHint() {
46135
46381
  setPromptHint("");
46136
46382
  setPromptHintTone("info");
46137
46383
  }, []);
46138
- useEffect14(
46384
+ useEffect15(
46139
46385
  () => () => {
46140
46386
  if (promptHintTimerRef.current) clearTimeout(promptHintTimerRef.current);
46141
46387
  },
@@ -46153,7 +46399,7 @@ function usePromptHint() {
46153
46399
  }
46154
46400
 
46155
46401
  // src/tui/app/use-welcome-prompt-hint.mjs
46156
- import { useCallback as useCallback15, useEffect as useEffect15, useRef as useRef16, useState as useState10 } from "react";
46402
+ import { useCallback as useCallback15, useEffect as useEffect16, useRef as useRef16, useState as useState11 } from "react";
46157
46403
 
46158
46404
  // src/tui/app/app-format.mjs
46159
46405
  import stringWidth5 from "string-width";
@@ -46654,8 +46900,8 @@ function cleanRightMessage(value) {
46654
46900
 
46655
46901
  // src/tui/app/use-welcome-prompt-hint.mjs
46656
46902
  function useWelcomePromptHint({ store, state, toastErrorSignature }) {
46657
- const [welcomePromptHintDismissed, setWelcomePromptHintDismissed] = useState10(false);
46658
- const [conditionalWelcomePromptHint, setConditionalWelcomePromptHint] = useState10("");
46903
+ const [welcomePromptHintDismissed, setWelcomePromptHintDismissed] = useState11(false);
46904
+ const [conditionalWelcomePromptHint, setConditionalWelcomePromptHint] = useState11("");
46659
46905
  const welcomePromptHintRef = useRef16(null);
46660
46906
  if (welcomePromptHintRef.current === null) {
46661
46907
  welcomePromptHintRef.current = randomWelcomePromptHint();
@@ -46665,7 +46911,7 @@ function useWelcomePromptHint({ store, state, toastErrorSignature }) {
46665
46911
  if (!welcomePromptHintVisibleRef.current) return;
46666
46912
  setWelcomePromptHintDismissed(true);
46667
46913
  }, []);
46668
- useEffect15(() => {
46914
+ useEffect16(() => {
46669
46915
  let alive = true;
46670
46916
  const refreshConditionalWelcomeHint = async () => {
46671
46917
  let quickModels;
@@ -48372,7 +48618,7 @@ function renderWelcomeBanner({ frameColumns, cwd: cwd2 }) {
48372
48618
  }
48373
48619
 
48374
48620
  // src/tui/hooks/useSharedTick.mjs
48375
- import { useEffect as useEffect16, useRef as useRef17, useState as useState11 } from "react";
48621
+ import { useEffect as useEffect17, useRef as useRef17, useState as useState12 } from "react";
48376
48622
  var TICK_SLOP_MS = 16;
48377
48623
  var subscribers = /* @__PURE__ */ new Set();
48378
48624
  var timer = null;
@@ -48407,10 +48653,10 @@ function onTick() {
48407
48653
  reconcileTimer();
48408
48654
  }
48409
48655
  function useSharedTick(intervalMs, isActive = true, onTick2 = null) {
48410
- const [, setTick] = useState11(0);
48656
+ const [, setTick] = useState12(0);
48411
48657
  const cbRef = useRef17(onTick2);
48412
48658
  cbRef.current = onTick2;
48413
- useEffect16(() => {
48659
+ useEffect17(() => {
48414
48660
  if (!isActive) return void 0;
48415
48661
  const interval = Math.max(1, Number(intervalMs) || 0);
48416
48662
  const sub = {
@@ -49232,6 +49478,12 @@ var PROVIDER_CATALOGS = Object.freeze({
49232
49478
  // Effort tiers live in the wire id; a row without levels has no effort
49233
49479
  // surface (resolveAntigravityWireModel drops the effort).
49234
49480
  "antigravity-oauth": { relay: true, rosterFiles: ["antigravity-oauth-models.json"], rosterLadderFinal: true },
49481
+ // api.commandcode.ai/provider/v1 relays other vendors' models.
49482
+ "command-code-oauth": {
49483
+ relay: true,
49484
+ rosterFiles: ["command-code-oauth-models.json"],
49485
+ rosterLimitsAuthoritative: true
49486
+ },
49235
49487
  "cursor-oauth": { relay: true },
49236
49488
  "cursor-api": { relay: true },
49237
49489
  "opencode-go": { relay: true }
@@ -50000,7 +50252,7 @@ ${freshL2}` : cachedL1;
50000
50252
  }
50001
50253
 
50002
50254
  // src/tui/components/status-line/use-statusline-text.mjs
50003
- import { useEffect as useEffect17, useRef as useRef19, useState as useState12 } from "react";
50255
+ import { useEffect as useEffect18, useRef as useRef19, useState as useState13 } from "react";
50004
50256
  function useStatusLineText({
50005
50257
  sessionId,
50006
50258
  clientHostPid,
@@ -50023,7 +50275,7 @@ function useStatusLineText({
50023
50275
  initialLine,
50024
50276
  themeEpoch
50025
50277
  }) {
50026
- const [line, setLine] = useState12(
50278
+ const [line, setLine] = useState13(
50027
50279
  () => normalizeStatusLine(
50028
50280
  initialLine || localBootStatusLine({
50029
50281
  provider,
@@ -50042,7 +50294,7 @@ function useStatusLineText({
50042
50294
  })
50043
50295
  )
50044
50296
  );
50045
- const [refreshTick, setRefreshTick] = useState12(0);
50297
+ const [refreshTick, setRefreshTick] = useState13(0);
50046
50298
  const statuslineArgsRef = useRef19(null);
50047
50299
  const bootFullDoneRef = useRef19(false);
50048
50300
  const mountAtRef = useRef19(Date.now());
@@ -50092,13 +50344,13 @@ function useStatusLineText({
50092
50344
  String(statsForSignature.currentContextSource || "")
50093
50345
  ].join("|");
50094
50346
  const refreshMs = hasActiveStatuslineWork(line, agentWorkers, agentJobs, activeTools) ? STATUSLINE_ACTIVE_REFRESH_MS : STATUSLINE_REFRESH_MS;
50095
- useEffect17(() => {
50347
+ useEffect18(() => {
50096
50348
  scheduleStatuslineModulePrewarm();
50097
50349
  }, []);
50098
50350
  useSharedTick(refreshMs, true, () => {
50099
50351
  setRefreshTick((tick) => (tick + 1) % 1e6);
50100
50352
  });
50101
- useEffect17(() => {
50353
+ useEffect18(() => {
50102
50354
  let alive = true;
50103
50355
  let bootRetryTimer = null;
50104
50356
  const effectId = renderEffectIdRef.current + 1;
@@ -50287,7 +50539,7 @@ function StatusLineView({
50287
50539
  var StatusLine = React11.memo(StatusLineView);
50288
50540
 
50289
50541
  // src/tui/components/PromptInput.jsx
50290
- import { useEffect as useEffect18, useLayoutEffect as useLayoutEffect4, useState as useState13, useRef as useRef20 } from "react";
50542
+ import { useEffect as useEffect19, useLayoutEffect as useLayoutEffect4, useState as useState14, useRef as useRef20 } from "react";
50291
50543
 
50292
50544
  // src/tui/input-editing.mjs
50293
50545
  var graphemeSegmenter4 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
@@ -50990,6 +51242,11 @@ function gridSelectionActive(suppressShiftNavRef) {
50990
51242
  if (typeof suppressShiftNavRef?.current === "function") return suppressShiftNavRef.current();
50991
51243
  return Boolean(suppressShiftNavRef?.current);
50992
51244
  }
51245
+ function paletteResultDraft(result) {
51246
+ if (typeof result === "string") return { value: result, cursor: result.length, selectionAnchor: null };
51247
+ if (typeof result?.value === "string") return { value: result.value, cursor: result.cursor, selectionAnchor: null };
51248
+ return null;
51249
+ }
50993
51250
  function createPromptKeyHandler(ctx) {
50994
51251
  const {
50995
51252
  disabled,
@@ -51003,6 +51260,7 @@ function createPromptKeyHandler(ctx) {
51003
51260
  submitDraft,
51004
51261
  commandPaletteActive,
51005
51262
  commandPaletteOptionCount,
51263
+ commandPaletteMovesCaret,
51006
51264
  onCommandPaletteNavigate,
51007
51265
  onCommandPaletteAccept,
51008
51266
  onCommandPaletteComplete,
@@ -51083,8 +51341,11 @@ function createPromptKeyHandler(ctx) {
51083
51341
  return;
51084
51342
  }
51085
51343
  if (commandPaletteActive) {
51086
- const accepted = onCommandPaletteAccept?.(draftRef.current.value);
51087
- if (accepted !== false) {
51344
+ const accepted = onCommandPaletteAccept?.(draftRef.current.value, draftRef.current.cursor);
51345
+ const replacement = paletteResultDraft(accepted);
51346
+ if (replacement) {
51347
+ commitDraft(replacement);
51348
+ } else if (accepted !== false) {
51088
51349
  commitDraft({ value: "", cursor: 0, selectionAnchor: null });
51089
51350
  }
51090
51351
  return;
@@ -51163,10 +51424,10 @@ ${d.value.slice(d.cursor)}`,
51163
51424
  }
51164
51425
  if (key.tab) {
51165
51426
  if (commandPaletteActive) {
51166
- const completed = onCommandPaletteComplete?.(draftRef.current.value);
51167
- if (typeof completed === "string") {
51168
- commitDraft({ value: completed, cursor: completed.length, selectionAnchor: null });
51169
- }
51427
+ const completed = paletteResultDraft(
51428
+ onCommandPaletteComplete?.(draftRef.current.value, draftRef.current.cursor)
51429
+ );
51430
+ if (completed) commitDraft(completed);
51170
51431
  return;
51171
51432
  }
51172
51433
  if (onTab?.(draftRef.current.value) === true) return;
@@ -51176,7 +51437,7 @@ ${d.value.slice(d.cursor)}`,
51176
51437
  return;
51177
51438
  }
51178
51439
  if (key.leftArrow || rawShiftLeft) {
51179
- if (commandPaletteActive) {
51440
+ if (commandPaletteActive && !commandPaletteMovesCaret) {
51180
51441
  onCommandPaletteNavigate?.("left");
51181
51442
  return;
51182
51443
  }
@@ -51186,7 +51447,7 @@ ${d.value.slice(d.cursor)}`,
51186
51447
  return;
51187
51448
  }
51188
51449
  if (key.rightArrow || rawShiftRight) {
51189
- if (commandPaletteActive) {
51450
+ if (commandPaletteActive && !commandPaletteMovesCaret) {
51190
51451
  onCommandPaletteNavigate?.("right");
51191
51452
  return;
51192
51453
  }
@@ -51393,6 +51654,8 @@ function PromptInput({
51393
51654
  commandPaletteActive = false,
51394
51655
  commandPaletteOpen = commandPaletteActive,
51395
51656
  commandPaletteOptionCount = commandPaletteActive ? 2 : 0,
51657
+ commandPaletteMovesCaret = false,
51658
+ onCaretChange,
51396
51659
  mask = false,
51397
51660
  hint = "",
51398
51661
  hintTone = "info",
@@ -51415,13 +51678,14 @@ function PromptInput({
51415
51678
  mouseSelectionRef,
51416
51679
  suppressShiftNavRef
51417
51680
  }) {
51418
- const [draft, setDraft] = useState13(() => {
51681
+ const [draft, setDraft] = useState14(() => {
51419
51682
  const value2 = String(initialValue || "");
51420
51683
  return { value: value2, cursor: value2.length, selectionAnchor: null };
51421
51684
  });
51422
- const [, bumpCursorAnchorEpoch] = useState13(0);
51685
+ const [, bumpCursorAnchorEpoch] = useState14(0);
51423
51686
  const draftRef = useRef20(draft);
51424
51687
  const lastReportedValueRef = useRef20(draft.value);
51688
+ const lastReportedCursorRef = useRef20(null);
51425
51689
  const pasteGenerationRef = useRef20(0);
51426
51690
  const submitGateRef = useRef20(false);
51427
51691
  const escapeClearAtRef = useRef20(0);
@@ -51464,7 +51728,7 @@ function PromptInput({
51464
51728
  flush: flushImmediate
51465
51729
  });
51466
51730
  };
51467
- useEffect18(
51731
+ useEffect19(
51468
51732
  () => () => {
51469
51733
  cancelPromptImmediateFlush(flushThrottleRef.current);
51470
51734
  },
@@ -51491,8 +51755,15 @@ function PromptInput({
51491
51755
  lastReportedValueRef.current = next.value;
51492
51756
  onDraftChange?.(next.value);
51493
51757
  }
51758
+ reportCaret(next.cursor);
51494
51759
  if (valueRef) valueRef.current = next.value;
51495
51760
  };
51761
+ function reportCaret(nextCursor) {
51762
+ if (nextCursor === lastReportedCursorRef.current) return;
51763
+ lastReportedCursorRef.current = nextCursor;
51764
+ onCaretChange?.(nextCursor);
51765
+ }
51766
+ useEffect19(() => reportCaret(draftRef.current.cursor), []);
51496
51767
  const installCursorAnchor = () => {
51497
51768
  if (!boxRef.current || boxRef.current.internal_cursorAnchor) return false;
51498
51769
  boxRef.current.internal_cursorAnchor = createCursorAnchor({
@@ -51515,7 +51786,7 @@ function PromptInput({
51515
51786
  commitDraft
51516
51787
  });
51517
51788
  }
51518
- useEffect18(
51789
+ useEffect19(
51519
51790
  () => () => {
51520
51791
  const state = mouseExtendCoalesceRef.current;
51521
51792
  if (state.timer) clearTimeout(state.timer);
@@ -51573,7 +51844,7 @@ function PromptInput({
51573
51844
  apply(handled);
51574
51845
  }
51575
51846
  };
51576
- useEffect18(() => {
51847
+ useEffect19(() => {
51577
51848
  if (!draftOverride || typeof draftOverride.value !== "string") return;
51578
51849
  pasteGenerationRef.current += 1;
51579
51850
  const nextValue = draftOverride.value;
@@ -51582,7 +51853,7 @@ function PromptInput({
51582
51853
  commitDraft({ value: nextValue, cursor: nextCursor, selectionAnchor: nextAnchor }, { skipHistory: true });
51583
51854
  undoStack.reset();
51584
51855
  }, [draftOverride?.id, draftOverride?.value, draftOverride?.cursor, draftOverride?.selectionAnchor]);
51585
- useEffect18(
51856
+ useEffect19(
51586
51857
  () => () => {
51587
51858
  pasteGenerationRef.current += 1;
51588
51859
  if (selectionRef) selectionRef.current = null;
@@ -51611,8 +51882,11 @@ function PromptInput({
51611
51882
  const current = draftRef.current;
51612
51883
  const next = prefix ? insertText(current, prefix) : current;
51613
51884
  if (commandPaletteActive) {
51614
- const accepted = onCommandPaletteAccept?.(next.value);
51615
- if (accepted !== false) {
51885
+ const accepted = onCommandPaletteAccept?.(next.value, next.cursor);
51886
+ const replacement = paletteResultDraft(accepted);
51887
+ if (replacement) {
51888
+ commitDraft(replacement);
51889
+ } else if (accepted !== false) {
51616
51890
  commitDraft({ value: "", cursor: 0, selectionAnchor: null });
51617
51891
  } else if (next !== current) {
51618
51892
  commitDraft(next);
@@ -51641,6 +51915,7 @@ function PromptInput({
51641
51915
  commandPaletteActive,
51642
51916
  commandPaletteOpen,
51643
51917
  commandPaletteOptionCount,
51918
+ commandPaletteMovesCaret,
51644
51919
  onCommandPaletteNavigate,
51645
51920
  onCommandPaletteAccept,
51646
51921
  onCommandPaletteCancel,
@@ -52032,20 +52307,20 @@ function usePickerInput({
52032
52307
  }
52033
52308
 
52034
52309
  // src/tui/components/picker/use-picker-selection.mjs
52035
- import { useEffect as useEffect19, useRef as useRef21, useState as useState14 } from "react";
52310
+ import { useEffect as useEffect20, useRef as useRef21, useState as useState15 } from "react";
52036
52311
  function usePickerSelection({ items, initialIndex, onHighlight, confirmButtons, confirmBar }) {
52037
- const [selectedIndex, setSelectedIndex] = useState14(() => clampItemIndex(initialIndex, items.length));
52038
- const [confirmFocus, setConfirmFocus] = useState14(-1);
52312
+ const [selectedIndex, setSelectedIndex] = useState15(() => clampItemIndex(initialIndex, items.length));
52313
+ const [confirmFocus, setConfirmFocus] = useState15(-1);
52039
52314
  const lastTabAtRef = useRef21(0);
52040
- useEffect19(() => {
52315
+ useEffect20(() => {
52041
52316
  setConfirmFocus(-1);
52042
52317
  }, [confirmButtons.length, confirmBar]);
52043
- const [selectionMemo] = useState14(() => ({ value: null, initialIndex }));
52044
- useEffect19(() => {
52318
+ const [selectionMemo] = useState15(() => ({ value: null, initialIndex }));
52319
+ useEffect20(() => {
52045
52320
  const item = items[selectedIndex];
52046
52321
  if (item && item.value != null) selectionMemo.value = item.value;
52047
52322
  }, [items, selectedIndex, selectionMemo]);
52048
- useEffect19(() => {
52323
+ useEffect20(() => {
52049
52324
  setSelectedIndex((i) => {
52050
52325
  if (selectionMemo.value != null) {
52051
52326
  const found = items.findIndex((entry) => entry && entry.value === selectionMemo.value);
@@ -52056,7 +52331,7 @@ function usePickerSelection({ items, initialIndex, onHighlight, confirmButtons,
52056
52331
  return Math.min(Math.max(0, i), Math.max(0, items.length - 1));
52057
52332
  });
52058
52333
  }, [items, selectionMemo, initialIndex]);
52059
- useEffect19(() => {
52334
+ useEffect20(() => {
52060
52335
  if (initialIndex == null) {
52061
52336
  selectionMemo.initialIndex = null;
52062
52337
  return;
@@ -52065,7 +52340,7 @@ function usePickerSelection({ items, initialIndex, onHighlight, confirmButtons,
52065
52340
  selectionMemo.initialIndex = initialIndex;
52066
52341
  setSelectedIndex(clampItemIndex(initialIndex, items.length));
52067
52342
  }, [initialIndex, items.length, selectionMemo]);
52068
- useEffect19(() => {
52343
+ useEffect20(() => {
52069
52344
  if (typeof onHighlight !== "function") return;
52070
52345
  const item = items[selectedIndex];
52071
52346
  if (item) onHighlight(item.value, item, selectedIndex);
@@ -52313,12 +52588,21 @@ function queryMatchesAlias(command, query) {
52313
52588
  );
52314
52589
  }
52315
52590
  function commandDisplayLabel(command, query) {
52591
+ if (command?.label) return command.label;
52316
52592
  const usage = String(command?.usage || command?.name || "").replace(/^\/+/, "");
52317
52593
  const aliasText = command?.showAliasUsage !== false && queryMatchesAlias(command, query) && Array.isArray(command?.aliasUsage) && command.aliasUsage.length > 0 ? ` (${command.aliasUsage.join(", ")})` : "";
52318
52594
  const label = ACRONYM_LABELS.get(usage.toLowerCase()) || (usage ? `${usage.charAt(0).toUpperCase()}${usage.slice(1)}` : usage);
52319
52595
  return `${label}${aliasText}`;
52320
52596
  }
52321
- function SlashCommandPalette({ commands: commands2, selectedIndex = 0, title = "Commands", columns = 80, query = "" }) {
52597
+ function SlashCommandPalette({
52598
+ commands: commands2,
52599
+ selectedIndex = 0,
52600
+ title = "Commands",
52601
+ columns = 80,
52602
+ query = "",
52603
+ description: descriptionText = SLASH_DESCRIPTION,
52604
+ help: helpText = SLASH_HELP
52605
+ }) {
52322
52606
  const total = commands2.length;
52323
52607
  const half = Math.floor(MAX_VISIBLE2 / 2);
52324
52608
  let start = Math.max(0, selectedIndex - half);
@@ -52331,9 +52615,9 @@ function SlashCommandPalette({ commands: commands2, selectedIndex = 0, title = "
52331
52615
  const blankRows = Math.max(0, MAX_VISIBLE2 - visible.length - (noMatches ? 1 : 0));
52332
52616
  const labelWidth = Math.min(COMMAND_LABEL_WIDTH, Math.max(12, Math.floor(columns * 0.45)));
52333
52617
  const descriptionWidth = Math.max(0, columns - labelWidth - 12);
52334
- const description = truncatePanelText(SLASH_DESCRIPTION, Math.max(0, columns - 4));
52618
+ const description = truncatePanelText(descriptionText, Math.max(0, columns - 4));
52335
52619
  const titleWidth = stringWidth9(String(title || ""));
52336
- const help = truncatePanelText(SLASH_HELP, Math.max(0, columns - titleWidth - 7));
52620
+ const help = truncatePanelText(helpText, Math.max(0, columns - titleWidth - 7));
52337
52621
  return /* @__PURE__ */ jsx11(Box_default, { flexDirection: "column", flexShrink: 0, width: "100%", children: /* @__PURE__ */ jsxs9(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: theme.promptBorder, paddingX: 1, width: "100%", children: [
52338
52622
  /* @__PURE__ */ jsxs9(Box_default, { flexDirection: "row", justifyContent: "space-between", children: [
52339
52623
  /* @__PURE__ */ jsx11(Text, { color: theme.panelTitle, wrap: "truncate", children: title }),
@@ -52374,7 +52658,7 @@ var CommandRow = React13.memo(function CommandRow2({ command, isSelected, labelW
52374
52658
  import stringWidth11 from "string-width";
52375
52659
 
52376
52660
  // src/tui/components/ContextInspector.jsx
52377
- import { useEffect as useEffect20, useRef as useRef22, useState as useState15 } from "react";
52661
+ import { useEffect as useEffect21, useRef as useRef22, useState as useState16 } from "react";
52378
52662
  import wrapAnsi4 from "wrap-ansi";
52379
52663
  import stringWidth10 from "string-width";
52380
52664
 
@@ -52435,13 +52719,13 @@ function fitLine2(text, width) {
52435
52719
  return result;
52436
52720
  }
52437
52721
  function ContextInspector({ inspection, columns, rows: rows2 = 16, windowTokens, onInspect, onRefresh }) {
52438
- const [category, setCategory] = useState15("");
52439
- const [index, setIndex] = useState15(0);
52440
- const [preview, setPreview] = useState15(null);
52441
- const [scroll, setScroll] = useState15(0);
52442
- const [fit, setFit] = useState15(false);
52722
+ const [category, setCategory] = useState16("");
52723
+ const [index, setIndex] = useState16(0);
52724
+ const [preview, setPreview] = useState16(null);
52725
+ const [scroll, setScroll] = useState16(0);
52726
+ const [fit, setFit] = useState16(false);
52443
52727
  const request = useRef22(0);
52444
- useEffect20(
52728
+ useEffect21(
52445
52729
  () => () => {
52446
52730
  request.current += 1;
52447
52731
  },
@@ -52807,7 +53091,7 @@ function ContextPanel({
52807
53091
  }
52808
53092
 
52809
53093
  // src/tui/components/UsagePanel.jsx
52810
- import { useEffect as useEffect21, useState as useState16 } from "react";
53094
+ import { useEffect as useEffect22, useState as useState17 } from "react";
52811
53095
  import stringWidth12 from "string-width";
52812
53096
 
52813
53097
  // src/session-runtime/services/usage-dashboard-model.mjs
@@ -53023,11 +53307,11 @@ function UsagePanel({ dashboard, loading = false, columns = 80, fillHeight = fal
53023
53307
  const hasMeasuredRows = Number(panelRows) > 0;
53024
53308
  const maxProviderRows = hasMeasuredRows ? Math.max(1, Math.floor(panelRows) - 6) : rows2.length;
53025
53309
  const maxScrollOffset = Math.max(0, rows2.length - maxProviderRows);
53026
- const [scrollOffset, setScrollOffset] = useState16(0);
53310
+ const [scrollOffset, setScrollOffset] = useState17(0);
53027
53311
  const visibleRows = hasMeasuredRows ? rows2.slice(scrollOffset, scrollOffset + maxProviderRows) : rows2;
53028
53312
  const scrollable = rows2.length > maxProviderRows;
53029
53313
  const helpText = `${scrollable || isLoading || isChecking ? "\u2191/\u2193 Scroll \xB7 PgUp/PgDn Page \xB7 " : ""}Esc Back \xB7 /usage refresh`;
53030
- useEffect21(() => {
53314
+ useEffect22(() => {
53031
53315
  setScrollOffset((offset) => Math.min(Math.max(0, offset), maxScrollOffset));
53032
53316
  }, [maxScrollOffset]);
53033
53317
  use_input_default((_input, key) => {
@@ -53106,7 +53390,7 @@ function UsagePanel({ dashboard, loading = false, columns = 80, fillHeight = fal
53106
53390
  }
53107
53391
 
53108
53392
  // src/tui/components/TextEntryPanel.jsx
53109
- import { useEffect as useEffect22, useLayoutEffect as useLayoutEffect5, useRef as useRef23, useState as useState17 } from "react";
53393
+ import { useEffect as useEffect23, useLayoutEffect as useLayoutEffect5, useRef as useRef23, useState as useState18 } from "react";
53110
53394
  import stringWidth14 from "string-width";
53111
53395
 
53112
53396
  // src/tui/components/text-entry-layout.mjs
@@ -53261,12 +53545,12 @@ function TextEntryPanel({
53261
53545
  onSubmit,
53262
53546
  onCancel
53263
53547
  }) {
53264
- const [draft, setDraft] = useState17(() => ({
53548
+ const [draft, setDraft] = useState18(() => ({
53265
53549
  value: String(initialValue || ""),
53266
53550
  cursor: String(initialValue || "").length,
53267
53551
  selectionAnchor: null
53268
53552
  }));
53269
- const [, bumpCursorAnchorEpoch] = useState17(0);
53553
+ const [, bumpCursorAnchorEpoch] = useState18(0);
53270
53554
  const draftRef = useRef23(draft);
53271
53555
  const submitGateRef = useRef23(false);
53272
53556
  const boxRef = useRef23(null);
@@ -53295,13 +53579,13 @@ function TextEntryPanel({
53295
53579
  commitDraft(fn(draftRef.current), options);
53296
53580
  };
53297
53581
  const moveDraftVertically = createVerticalMover({ draftRef, contentWidthRef, preferredColumnRef, commitDraft });
53298
- useEffect22(() => {
53582
+ useEffect23(() => {
53299
53583
  const value = String(initialValue || "");
53300
53584
  commitDraft({ value, cursor: value.length, selectionAnchor: null });
53301
53585
  }, [title, initialValue]);
53302
53586
  const labelCells = stringWidth14(String(promptLabel || ""));
53303
53587
  const contentCells = Math.max(1, columns - 4 - labelCells);
53304
- useEffect22(() => {
53588
+ useEffect23(() => {
53305
53589
  if (!multiline) {
53306
53590
  onContentRowsChange?.(1);
53307
53591
  return;
@@ -53584,6 +53868,10 @@ function settingsPromptFields(kind) {
53584
53868
 
53585
53869
  // src/tui/app/app-view/floating-panel.jsx
53586
53870
  import { jsx as jsx16 } from "react/jsx-runtime";
53871
+ var SKILL_PALETTE_TEXT = {
53872
+ description: "Type to filter \xB7 Enter or Tab inserts the highlighted skill.",
53873
+ help: "\u2191/\u2193 select \xB7 Enter insert \xB7 Esc cancel"
53874
+ };
53587
53875
  function renderToolApproval({ toolApproval, store, frameColumns, expandedOptionPanel }) {
53588
53876
  const resolve3 = (approved) => {
53589
53877
  store.resolveToolApproval?.(toolApproval.id, {
@@ -53730,14 +54018,16 @@ function renderFloatingPanel(ctx) {
53730
54018
  );
53731
54019
  }
53732
54020
  if (slashPaletteOpen) {
54021
+ const skills = ctx.paletteKind === "skills";
53733
54022
  return /* @__PURE__ */ jsx16(
53734
54023
  SlashCommandPalette,
53735
54024
  {
53736
54025
  commands: slashCommands,
53737
54026
  selectedIndex: slashIndex,
53738
- title: "Commands",
54027
+ title: skills ? "Skills" : "Commands",
53739
54028
  columns: frameColumns,
53740
- query: activeSlashQuery
54029
+ query: activeSlashQuery,
54030
+ ...skills ? SKILL_PALETTE_TEXT : {}
53741
54031
  }
53742
54032
  );
53743
54033
  }
@@ -54074,10 +54364,13 @@ var UserMessage = React16.memo(function UserMessage2({
54074
54364
  text,
54075
54365
  attached = false,
54076
54366
  columns,
54367
+ appliedSkills,
54077
54368
  themeEpoch: _themeEpoch = 0
54078
54369
  }) {
54079
54370
  const bandColumns = Math.max(1, columns - 1);
54080
- return /* @__PURE__ */ jsx20(
54371
+ const skillsLine = appliedSkillsLine(appliedSkills);
54372
+ const segments = userTextSegments(text, appliedSkills);
54373
+ return /* @__PURE__ */ jsxs15(
54081
54374
  Box_default,
54082
54375
  {
54083
54376
  flexDirection: "column",
@@ -54086,7 +54379,12 @@ var UserMessage = React16.memo(function UserMessage2({
54086
54379
  backgroundColor: theme.userMessageBackground,
54087
54380
  paddingLeft: 2,
54088
54381
  paddingRight: 1,
54089
- children: /* @__PURE__ */ jsx20(Text, { color: theme.mixdogIvory, wrap: "wrap", children: text })
54382
+ children: [
54383
+ /* @__PURE__ */ jsx20(Text, { color: theme.mixdogIvory, wrap: "wrap", children: segments.length === 1 && !segments[0].mention ? text : segments.map(
54384
+ (segment, index) => segment.mention ? /* @__PURE__ */ jsx20(Text, { color: theme.panelTitle, bold: true, children: segment.text }, index) : segment.text
54385
+ ) }),
54386
+ skillsLine ? /* @__PURE__ */ jsx20(Text, { color: theme.subtle, wrap: "wrap", children: skillsLine }) : null
54387
+ ]
54090
54388
  }
54091
54389
  );
54092
54390
  });
@@ -54649,7 +54947,16 @@ var Item = React17.memo(function Item2({
54649
54947
  let node = null;
54650
54948
  switch (item.kind) {
54651
54949
  case "user":
54652
- node = /* @__PURE__ */ jsx27(UserMessage, { text: item.text, attached: prevKind === "user", columns, themeEpoch });
54950
+ node = /* @__PURE__ */ jsx27(
54951
+ UserMessage,
54952
+ {
54953
+ text: item.text,
54954
+ attached: prevKind === "user",
54955
+ columns,
54956
+ appliedSkills: item.appliedSkills,
54957
+ themeEpoch
54958
+ }
54959
+ );
54653
54960
  break;
54654
54961
  case "assistant":
54655
54962
  node = /* @__PURE__ */ jsx27(
@@ -54946,8 +55253,10 @@ function renderAppView(ctx) {
54946
55253
  inputHint,
54947
55254
  inputHintTone,
54948
55255
  liveSpinner,
55256
+ onPromptCaretChange,
54949
55257
  onPromptDraftChange,
54950
55258
  onSubmit,
55259
+ paletteKind,
54951
55260
  panelTransitionClearRows,
54952
55261
  picker,
54953
55262
  promptBoxRectRef,
@@ -54980,6 +55289,7 @@ function renderAppView(ctx) {
54980
55289
  onSubmit,
54981
55290
  disabled: exiting || !!picker || !!contextPanel || !!toolApproval || !tuiReady,
54982
55291
  onDraftChange: onPromptDraftChange,
55292
+ onCaretChange: onPromptCaretChange,
54983
55293
  interruptActive: state.busy,
54984
55294
  onInterrupt: handlePromptInterrupt,
54985
55295
  initialValue: promptDraft,
@@ -54999,6 +55309,7 @@ function renderAppView(ctx) {
54999
55309
  commandPaletteActive: slashPaletteOpen && slashCommands.length > 0,
55000
55310
  commandPaletteOpen: slashPaletteOpen,
55001
55311
  commandPaletteOptionCount: slashCommands.length,
55312
+ commandPaletteMovesCaret: paletteKind === "skills",
55002
55313
  onCommandPaletteNavigate: (direction) => {
55003
55314
  setSlashIndex((index) => stepPaletteIndex(index, direction, slashCommands.length));
55004
55315
  },
@@ -55278,9 +55589,10 @@ function usePromptDraftFlow({
55278
55589
  [settingsPrompt, setSettingsPrompt, openProjectPicker, openMemoryCorePicker, openAutoClearPicker]
55279
55590
  );
55280
55591
  const acceptSlashPalette = useCallback18(
55281
- (draftValue = "") => {
55592
+ (draftValue = "", caret) => {
55282
55593
  const command = slashCommands[slashIndex];
55283
55594
  if (!command) return false;
55595
+ if (command.kind === "skill") return completeSkillMention(draftValue, command.name, caret) ?? false;
55284
55596
  return withPickerEnterLatch(
55285
55597
  pickerOpenedFromEnterRef,
55286
55598
  pickerOpenedFromEnterTimerRef,
@@ -55290,9 +55602,10 @@ function usePromptDraftFlow({
55290
55602
  [slashCommands, slashIndex, pickerOpenedFromEnterRef, pickerOpenedFromEnterTimerRef, runSlashCommand]
55291
55603
  );
55292
55604
  const completeSlashPalette = useCallback18(
55293
- (draftValue = "") => {
55605
+ (draftValue = "", caret) => {
55294
55606
  const command = slashCommands[slashIndex];
55295
55607
  if (!command) return void 0;
55608
+ if (command.kind === "skill") return completeSkillMention(draftValue, command.name, caret);
55296
55609
  const token = slashCommandTokenForPaletteAccept(command, draftValue);
55297
55610
  return token ? `/${token} ` : void 0;
55298
55611
  },
@@ -55899,32 +56212,45 @@ function createMcpServersPicker({ store, theme: theme2, surface, getPicker, setP
55899
56212
  }
55900
56213
 
55901
56214
  // src/tui/app/extension-pickers/plugins-pickers.mjs
56215
+ function mcpNames(p) {
56216
+ if (Array.isArray(p.mcpServers)) return p.mcpServers.map((server) => server.name);
56217
+ return p.mcpServerName ? [p.mcpServerName] : [];
56218
+ }
56219
+ var hasMcp = (p) => mcpNames(p).length > 0 || Boolean(p.mcpScript || p.mcpInline);
56220
+ function serverState(server) {
56221
+ if (server.serverEnabled === false) return "off";
56222
+ if (server.enabled === false) return "plugin off";
56223
+ return server.status || (server.connected ? "connected" : "disconnected");
56224
+ }
55902
56225
  var mcpSummary = (p) => {
55903
- if (!p.mcpScript) return "(none)";
55904
- const state = p.mcpEnabled ? "enabled" : "available";
55905
- return `${state} (${p.mcpServerName || "plugin-mcp"})`;
56226
+ if (!hasMcp(p))
56227
+ return Array.isArray(p.mcpErrors) && p.mcpErrors.length ? `(invalid: ${p.mcpErrors[0].message})` : "(none)";
56228
+ if (!Array.isArray(p.mcpServers)) return `${p.mcpEnabled ? "enabled" : "available"} (${mcpNames(p).join(", ")})`;
56229
+ const errors = Array.isArray(p.mcpErrors) && p.mcpErrors.length ? ` \xB7 ${p.mcpErrors.length} declaration error(s)` : "";
56230
+ return `${p.mcpServers.map((server) => `${server.name} ${serverState(server)}`).join(", ")}${errors}`;
55906
56231
  };
55907
56232
  function mcpActionItem(p) {
55908
- if (!p.mcpScript) {
56233
+ if (!hasMcp(p)) {
55909
56234
  return {
55910
56235
  value: "enable-mcp",
55911
- label: "No MCP script",
55912
- description: "plugin does not expose scripts/run-mcp.mjs or mcp/server.mjs",
56236
+ label: "No MCP server",
56237
+ description: "plugin declares no MCP servers (.mcp.json or manifest mcpServers)",
55913
56238
  _action: "noop"
55914
56239
  };
55915
56240
  }
55916
56241
  return {
55917
56242
  value: "enable-mcp",
55918
- label: p.mcpEnabled ? "Refresh MCP server" : "Enable MCP server",
55919
- description: `${p.mcpServerName || "plugin-mcp"} \xB7 ${p.mcpEnabled ? "configured" : p.mcpScript}`,
56243
+ label: p.mcpEnabled ? "Reconnect MCP servers" : "Enable MCP servers",
56244
+ description: `${mcpNames(p).join(", ") || "plugin MCP"} \xB7 ${p.mcpEnabled ? "on" : "turned off"}`,
55920
56245
  _action: "enable-mcp"
55921
56246
  };
55922
56247
  }
55923
56248
  function pluginSummary(plugin) {
55924
56249
  const version = plugin.version ? ` \xB7 ${plugin.version}` : "";
55925
- const mcpState = plugin.mcpEnabled ? "enabled" : plugin.mcpScript;
55926
- const mcp = plugin.mcpScript ? ` \xB7 mcp ${mcpState}` : "";
55927
- return `${plugin.sourceType || plugin.source}${version} \xB7 skills ${plugin.skillCount || 0}${mcp}`;
56250
+ const mcpOff = plugin.mcpEnabled ? "" : " off";
56251
+ const mcp = hasMcp(plugin) ? ` \xB7 mcp ${mcpNames(plugin).length || 1}${mcpOff}` : "";
56252
+ const warning = plugin.warning ? ` \xB7 \u26A0 ${plugin.warning}` : "";
56253
+ return `${plugin.sourceType || plugin.source}${version} \xB7 skills ${plugin.skillCount || 0}${mcp}${warning}`;
55928
56254
  }
55929
56255
  var pluginInfoNotice = (p) => [
55930
56256
  `${p.title || p.name}${p.version ? ` ${p.version}` : ""}`,
@@ -55933,6 +56259,7 @@ var pluginInfoNotice = (p) => [
55933
56259
  `mcp: ${mcpSummary(p)}`,
55934
56260
  `applies to: ${Array.isArray(p.scope) && p.scope.length ? p.scope.join(", ") : "all projects"}`,
55935
56261
  `root: ${p.root}`,
56262
+ p.warning ? `warning: ${p.warning}` : "",
55936
56263
  p.description ? `
55937
56264
  ${p.description}` : ""
55938
56265
  ].filter(Boolean).join("\n");
@@ -55958,9 +56285,9 @@ var pluginDetailItems = (p) => [
55958
56285
  },
55959
56286
  {
55960
56287
  value: "copy-mcp-name",
55961
- label: p.mcpScript ? "Copy MCP server name" : "No MCP server name",
55962
- description: p.mcpServerName || "",
55963
- _action: p.mcpScript ? "copy-mcp-name" : "noop"
56288
+ label: mcpNames(p).length ? "Copy MCP server name" : "No MCP server name",
56289
+ description: mcpNames(p).join(", "),
56290
+ _action: mcpNames(p).length ? "copy-mcp-name" : "noop"
55964
56291
  },
55965
56292
  {
55966
56293
  value: "uninstall",
@@ -56000,7 +56327,7 @@ function createPluginsPickers({
56000
56327
  return;
56001
56328
  }
56002
56329
  if (detail._action === "enable-mcp") {
56003
- void store.enablePluginMcp?.(p).then(own.defer(() => openMcpPicker())).catch((e) => store.pushNotice(`plugin MCP enable failed: ${e?.message || e}`, "error"));
56330
+ void store.enablePluginMcp?.(p).then(own.defer(() => openMcpPicker())).catch((e) => store.pushNotice(`plugin MCP reconnect failed: ${e?.message || e}`, "error"));
56004
56331
  return;
56005
56332
  }
56006
56333
  if (detail._action === "copy-root") {
@@ -56008,7 +56335,7 @@ function createPluginsPickers({
56008
56335
  return;
56009
56336
  }
56010
56337
  if (detail._action === "copy-mcp-name") {
56011
- copyText(p.mcpServerName || "", `copied plugin MCP server: ${p.mcpServerName}`);
56338
+ copyText(mcpNames(p).join(", "), `copied plugin MCP server: ${mcpNames(p).join(", ")}`);
56012
56339
  return;
56013
56340
  }
56014
56341
  if (detail._action === "uninstall") {
@@ -57094,6 +57421,7 @@ var PROVIDER_DISPLAY_NAMES = /* @__PURE__ */ new Map([
57094
57421
  ["anthropic-oauth", "Anthropic OAuth"],
57095
57422
  ["grok-oauth", "Grok OAuth"],
57096
57423
  ["muse-code-oauth", "Muse Code"],
57424
+ ["command-code-oauth", "Command Code"],
57097
57425
  ["mimo-oauth", "MiMo"],
57098
57426
  ["cursor-oauth", "Cursor OAuth"],
57099
57427
  ["antigravity-oauth", "Antigravity OAuth"],
@@ -57140,6 +57468,7 @@ var PROVIDER_DISPLAY_RANKS = {
57140
57468
  "anthropic-oauth": 20,
57141
57469
  "grok-oauth": 30,
57142
57470
  "muse-code-oauth": 33,
57471
+ "command-code-oauth": 33.5,
57143
57472
  "mimo-oauth": 34,
57144
57473
  "antigravity-oauth": 31,
57145
57474
  "cursor-oauth": 32,
@@ -61135,7 +61464,7 @@ function useMessageSelector({
61135
61464
  }
61136
61465
 
61137
61466
  // src/tui/app/use-terminal-chrome.mjs
61138
- import { useEffect as useEffect23 } from "react";
61467
+ import { useEffect as useEffect24 } from "react";
61139
61468
 
61140
61469
  // src/tui/keyboard-protocol.mjs
61141
61470
  var ENABLE_KITTY_KEYBOARD = "\x1B[>1u";
@@ -61160,7 +61489,7 @@ function supportsExtendedKeys() {
61160
61489
 
61161
61490
  // src/tui/app/use-terminal-chrome.mjs
61162
61491
  function useTerminalChrome({ stdout: stdout2, isRawModeSupported, setResizeState }) {
61163
- useEffect23(() => {
61492
+ useEffect24(() => {
61164
61493
  if (!stdout2) return void 0;
61165
61494
  let trailing = null;
61166
61495
  const DEBOUNCE_MS = 80;
@@ -61195,7 +61524,7 @@ function useTerminalChrome({ stdout: stdout2, isRawModeSupported, setResizeState
61195
61524
  stdout2.off("resize", onResize);
61196
61525
  };
61197
61526
  }, [stdout2]);
61198
- useEffect23(() => {
61527
+ useEffect24(() => {
61199
61528
  if (!isRawModeSupported || !stdout2?.write) return;
61200
61529
  if (!supportsExtendedKeys()) return;
61201
61530
  try {
@@ -61206,7 +61535,7 @@ function useTerminalChrome({ stdout: stdout2, isRawModeSupported, setResizeState
61206
61535
  }
61207
61536
 
61208
61537
  // src/tui/app/use-transcript-window.mjs
61209
- import { useCallback as useCallback21, useEffect as useEffect25, useLayoutEffect as useLayoutEffect8 } from "react";
61538
+ import { useCallback as useCallback21, useEffect as useEffect26, useLayoutEffect as useLayoutEffect8 } from "react";
61210
61539
 
61211
61540
  // src/tui/session/transcript-spill.mjs
61212
61541
  import { readFileSync as readFileSync15 } from "node:fs";
@@ -61718,7 +62047,7 @@ function overlayHintPlacement(renderedItems, transcriptWindow, { overlayHintRequ
61718
62047
  }
61719
62048
 
61720
62049
  // src/tui/app/use-transcript-window/selection-shift.mjs
61721
- import { useEffect as useEffect24, useLayoutEffect as useLayoutEffect7 } from "react";
62050
+ import { useEffect as useEffect25, useLayoutEffect as useLayoutEffect7 } from "react";
61722
62051
  function useSelectionLayoutShift({
61723
62052
  transcriptWindow,
61724
62053
  transcriptContentHeight,
@@ -61752,7 +62081,7 @@ function useSelectionLayoutShift({
61752
62081
  withSelectionClip,
61753
62082
  paintSelectionRect
61754
62083
  ]);
61755
- useEffect24(() => {
62084
+ useEffect25(() => {
61756
62085
  if (!dragRef.current.rect) return;
61757
62086
  const clippedRect = withSelectionClip(dragRef.current.rect);
61758
62087
  dragRef.current = { ...dragRef.current, rect: clippedRect };
@@ -61892,7 +62221,7 @@ function useTranscriptWindow({
61892
62221
  withSelectionClip,
61893
62222
  paintSelectionRect
61894
62223
  });
61895
- useEffect25(() => {
62224
+ useEffect26(() => {
61896
62225
  clampScrollToOverflow(scrollRefs, {
61897
62226
  maxRows: transcriptWindow.maxScrollRows,
61898
62227
  scrollOffset,
@@ -62250,7 +62579,7 @@ function usePromptHistoryNavigation({
62250
62579
  }
62251
62580
 
62252
62581
  // src/tui/app/prompt-handlers/use-prompt-interrupt.mjs
62253
- import { useCallback as useCallback24, useEffect as useEffect26, useRef as useRef27 } from "react";
62582
+ import { useCallback as useCallback24, useEffect as useEffect27, useRef as useRef27 } from "react";
62254
62583
 
62255
62584
  // src/tui/components/prompt-input/interrupt-policy.mjs
62256
62585
  function promptInterruptRestoreText(result, currentText = "") {
@@ -62295,7 +62624,7 @@ function usePromptInterrupt({
62295
62624
  },
62296
62625
  [store, promptValueRef, restoreAttachments, clearPromptHint, syncPromptLayoutRows, setPromptDraftOverride]
62297
62626
  );
62298
- useEffect26(() => {
62627
+ useEffect27(() => {
62299
62628
  const pending = pendingRestoreRef.current;
62300
62629
  if (!pending) return;
62301
62630
  if (commitAsyncRestore(pending)) pendingRestoreRef.current = null;
@@ -62546,7 +62875,7 @@ function usePromptHandlers({
62546
62875
  }
62547
62876
 
62548
62877
  // src/tui/app/use-model-catalog-cache.mjs
62549
- import { useCallback as useCallback27, useEffect as useEffect27, useRef as useRef28 } from "react";
62878
+ import { useCallback as useCallback27, useEffect as useEffect28, useRef as useRef28 } from "react";
62550
62879
  function useModelCatalogCache({ store, onboardingRef }) {
62551
62880
  const providerModelsCacheRef = useRef28({ models: null, at: 0 });
62552
62881
  const webSearchModelsCacheRef = useRef28({ models: null, at: 0 });
@@ -62562,7 +62891,7 @@ function useModelCatalogCache({ store, onboardingRef }) {
62562
62891
  webSearchModelsCacheRef.current = { models: null, at: 0 };
62563
62892
  }
62564
62893
  }, []);
62565
- useEffect27(() => {
62894
+ useEffect28(() => {
62566
62895
  let alive = true;
62567
62896
  const timer2 = setTimeout(async () => {
62568
62897
  const seq = onboardingPrefetchSeqRef.current;
@@ -62598,10 +62927,10 @@ function useModelCatalogCache({ store, onboardingRef }) {
62598
62927
  }
62599
62928
 
62600
62929
  // src/tui/app/use-disabled-skills.mjs
62601
- import { useCallback as useCallback28, useEffect as useEffect28, useState as useState18 } from "react";
62930
+ import { useCallback as useCallback28, useEffect as useEffect29, useState as useState19 } from "react";
62602
62931
  function useDisabledSkills({ store }) {
62603
- const [disabledSkills, setDisabledSkillsInner] = useState18(() => /* @__PURE__ */ new Set());
62604
- useEffect28(() => {
62932
+ const [disabledSkills, setDisabledSkillsInner] = useState19(() => /* @__PURE__ */ new Set());
62933
+ useEffect29(() => {
62605
62934
  let alive = true;
62606
62935
  void Promise.resolve(store.getDisabledSkills?.()).then((result) => {
62607
62936
  if (!alive) return;
@@ -62635,7 +62964,7 @@ function useDisabledSkills({ store }) {
62635
62964
  }
62636
62965
 
62637
62966
  // src/tui/app/use-onboarding-start.mjs
62638
- import { useEffect as useEffect29 } from "react";
62967
+ import { useEffect as useEffect30 } from "react";
62639
62968
  function resolveOnboardingCompleted(store, onboardingCompleted) {
62640
62969
  if (typeof onboardingCompleted === "boolean") return onboardingCompleted;
62641
62970
  try {
@@ -62654,7 +62983,7 @@ function useOnboardingStart({
62654
62983
  setOnboardingActive,
62655
62984
  openOnboardingAuthStep
62656
62985
  }) {
62657
- useEffect29(() => {
62986
+ useEffect30(() => {
62658
62987
  if (onboardingStartedRef.current) return void 0;
62659
62988
  if (resolveOnboardingCompleted(store, onboardingCompleted) && !forceOnboarding) return void 0;
62660
62989
  let canceled = false;
@@ -62672,17 +63001,17 @@ function useOnboardingStart({
62672
63001
  // src/tui/App.jsx
62673
63002
  function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardingCompleted = void 0 }) {
62674
63003
  const state = useSession(store);
62675
- const [toolOutputExpanded, setToolOutputExpanded] = useState19(false);
62676
- const [onboardingActive, setOnboardingActive] = useState19(false);
63004
+ const [toolOutputExpanded, setToolOutputExpanded] = useState20(false);
63005
+ const [onboardingActive, setOnboardingActive] = useState20(false);
62677
63006
  const { exit } = use_app_default();
62678
63007
  const { isRawModeSupported, internal_eventEmitter: inkInput } = use_stdin_default();
62679
63008
  const { stdout: stdout2 } = use_stdout_default();
62680
- const [exiting, setExiting] = useState19(false);
62681
- const [tuiReady, setTuiReady] = useState19(false);
63009
+ const [exiting, setExiting] = useState20(false);
63010
+ const [tuiReady, setTuiReady] = useState20(false);
62682
63011
  const exitRequestedRef = useRef29(false);
62683
- const [resizeState, setResizeState] = useState19(() => ({ ...terminalSize2(stdout2), epoch: 0 }));
62684
- const [panelTransitionEpoch, setPanelTransitionEpoch] = useState19(0);
62685
- const [panelInkMaskEpoch, setPanelInkMaskEpoch] = useState19(0);
63012
+ const [resizeState, setResizeState] = useState20(() => ({ ...terminalSize2(stdout2), epoch: 0 }));
63013
+ const [panelTransitionEpoch, setPanelTransitionEpoch] = useState20(0);
63014
+ const [panelInkMaskEpoch, setPanelInkMaskEpoch] = useState20(0);
62686
63015
  const rightSafetyColumns = 1;
62687
63016
  const frameColumns = Math.max(1, resizeState.columns - rightSafetyColumns);
62688
63017
  const {
@@ -62704,7 +63033,7 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
62704
63033
  const pickerOpenedFromEnterRef = useRef29(false);
62705
63034
  const pickerOpenedFromEnterTimerRef = useRef29(null);
62706
63035
  const projectPickerRef = useRef29(null);
62707
- const [picker, setPickerState] = useState19(null);
63036
+ const [picker, setPickerState] = useState20(null);
62708
63037
  const livePickerRef = useRef29(null);
62709
63038
  const setPicker = useCallback29((next) => {
62710
63039
  const previousPicker = livePickerRef.current;
@@ -62718,8 +63047,8 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
62718
63047
  );
62719
63048
  }, []);
62720
63049
  livePickerRef.current = picker;
62721
- const [contextPanel, setContextPanel] = useState19(null);
62722
- const [usagePanel, setUsagePanel] = useState19(null);
63050
+ const [contextPanel, setContextPanel] = useState20(null);
63051
+ const [usagePanel, setUsagePanel] = useState20(null);
62723
63052
  const surfaceRef = useRef29(null);
62724
63053
  if (!surfaceRef.current) {
62725
63054
  surfaceRef.current = createPanelSurface({ setPicker, setContextPanel, setUsagePanel });
@@ -62728,9 +63057,9 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
62728
63057
  const settingsHeavyCacheRef = useRef29(null);
62729
63058
  const settingsRequestRef = useRef29(0);
62730
63059
  const closeUsagePanel = useCallback29(() => surface.closeUsage(), [surface]);
62731
- const [providerPrompt, setProviderPrompt] = useState19(null);
63060
+ const [providerPrompt, setProviderPrompt] = useState20(null);
62732
63061
  const oauthSubmitRef = useRef29(false);
62733
- const [settingsPrompt, setSettingsPrompt] = useState19(null);
63062
+ const [settingsPrompt, setSettingsPrompt] = useState20(null);
62734
63063
  const projectPicker = createProjectPicker({
62735
63064
  state,
62736
63065
  store,
@@ -62750,7 +63079,7 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
62750
63079
  setPicker(projectPicker.buildProjectPickerState({ initialEntry: true, loading: true }));
62751
63080
  }
62752
63081
  }
62753
- useEffect30(() => {
63082
+ useEffect31(() => {
62754
63083
  if (livePickerRef.current?._projectInitialPending !== true) return;
62755
63084
  void projectPickerRef.current?.openProjectPicker({ initialEntry: true });
62756
63085
  }, [store]);
@@ -62762,6 +63091,8 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
62762
63091
  setPromptDraft,
62763
63092
  promptDraftOverride,
62764
63093
  setPromptDraftOverride,
63094
+ promptCaret,
63095
+ setPromptCaret,
62765
63096
  promptLayoutValueRef,
62766
63097
  setPromptLayoutRows,
62767
63098
  textEntryLayoutRows,
@@ -62803,8 +63134,8 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
62803
63134
  welcomePromptHintVisibleRef,
62804
63135
  dismissWelcomePromptHint
62805
63136
  } = useWelcomePromptHint({ store, state, toastErrorSignature });
62806
- const [slashIndex, setSlashIndex] = useState19(0);
62807
- const [slashDismissedFor, setSlashDismissedFor] = useState19("");
63137
+ const [slashIndex, setSlashIndex] = useState20(0);
63138
+ const [slashDismissedFor, setSlashDismissedFor] = useState20("");
62808
63139
  const slashPaletteRef = useRef29({ open: false, count: 0 });
62809
63140
  const scrollFocusRef = useRef29({});
62810
63141
  const onboardingStartedRef = useRef29(false);
@@ -62886,7 +63217,7 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
62886
63217
  settingsPrompt,
62887
63218
  setTextEntryLayoutRows
62888
63219
  });
62889
- useEffect30(() => {
63220
+ useEffect31(() => {
62890
63221
  const timer2 = setTimeout(() => setTuiReady(true), 0);
62891
63222
  return () => clearTimeout(timer2);
62892
63223
  }, []);
@@ -62932,7 +63263,7 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
62932
63263
  getStitchedSelectionText,
62933
63264
  showSelectionCopyHint
62934
63265
  });
62935
- useEffect30(
63266
+ useEffect31(
62936
63267
  () => () => {
62937
63268
  stopSmoothScroll();
62938
63269
  },
@@ -63060,7 +63391,7 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
63060
63391
  setSettingsPrompt,
63061
63392
  closeUsagePanel
63062
63393
  });
63063
- useEffect30(() => {
63394
+ useEffect31(() => {
63064
63395
  if (contextPanel?.kind === "context") openContextPicker();
63065
63396
  }, [
63066
63397
  contextPanel?.kind,
@@ -63112,7 +63443,8 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
63112
63443
  pastedImagesRef,
63113
63444
  pastedTextsRef
63114
63445
  });
63115
- const { activeSlashQuery, slashCommands, slashPaletteOpen } = deriveSlashPalette({
63446
+ const mentionSkills = useSkillMentionSkills(store, skillMentionQuery(promptDraft, promptCaret) !== null);
63447
+ const { activeSlashQuery, slashCommands, slashPaletteOpen, paletteKind } = deriveSlashPalette({
63116
63448
  providerPrompt,
63117
63449
  settingsPrompt,
63118
63450
  toolApproval,
@@ -63122,7 +63454,9 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
63122
63454
  exiting,
63123
63455
  commandBusy: state.commandBusy,
63124
63456
  promptDraft,
63125
- slashDismissedFor
63457
+ slashDismissedFor,
63458
+ skills: mentionSkills,
63459
+ promptCaret
63126
63460
  });
63127
63461
  slashPaletteRef.current = { open: slashPaletteOpen, count: slashCommands.length };
63128
63462
  scrollFocusRef.current = {
@@ -63134,7 +63468,7 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
63134
63468
  providerPrompt: !!providerPrompt,
63135
63469
  settingsPrompt: !!settingsPrompt
63136
63470
  };
63137
- useEffect30(() => {
63471
+ useEffect31(() => {
63138
63472
  setSlashIndex((index) => Math.min(index, Math.max(0, slashCommands.length - 1)));
63139
63473
  }, [slashCommands.length, activeSlashQuery]);
63140
63474
  const {
@@ -63302,10 +63636,12 @@ function App2({ store, initialStatusLine = "", forceOnboarding = false, onboardi
63302
63636
  hasUserMessages,
63303
63637
  initialStatusLine,
63304
63638
  onPromptDraftChange,
63639
+ onPromptCaretChange: setPromptCaret,
63305
63640
  onSubmit,
63306
63641
  overlayHintAttachItemIndex,
63307
63642
  overlayHintFallbackRow,
63308
63643
  overlayHintOnLastItem,
63644
+ paletteKind,
63309
63645
  panelInkMaskEpoch,
63310
63646
  panelTransitionEpoch,
63311
63647
  picker,