cli-jaw 2.17.41 → 2.17.42

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 (167) hide show
  1. package/README.md +3 -3
  2. package/dist/bin/commands/browser.js +52 -5
  3. package/dist/bin/commands/browser.js.map +1 -1
  4. package/dist/src/agent/args.js +69 -19
  5. package/dist/src/agent/args.js.map +1 -1
  6. package/dist/src/agent/codex-app-events.js +31 -1
  7. package/dist/src/agent/codex-app-events.js.map +1 -1
  8. package/dist/src/agent/cursor-model-inventory.js +140 -0
  9. package/dist/src/agent/cursor-model-inventory.js.map +1 -0
  10. package/dist/src/agent/grok-models.js +80 -0
  11. package/dist/src/agent/grok-models.js.map +1 -0
  12. package/dist/src/browser/actions.js +383 -20
  13. package/dist/src/browser/actions.js.map +1 -1
  14. package/dist/src/browser/grounding-candidate.js +272 -0
  15. package/dist/src/browser/grounding-candidate.js.map +1 -0
  16. package/dist/src/browser/grounding-eval.js +247 -0
  17. package/dist/src/browser/grounding-eval.js.map +1 -0
  18. package/dist/src/browser/image-size.js +63 -0
  19. package/dist/src/browser/image-size.js.map +1 -0
  20. package/dist/src/browser/index.js +1 -0
  21. package/dist/src/browser/index.js.map +1 -1
  22. package/dist/src/browser/occlusion.js +148 -0
  23. package/dist/src/browser/occlusion.js.map +1 -0
  24. package/dist/src/browser/verify-candidate.js +162 -0
  25. package/dist/src/browser/verify-candidate.js.map +1 -0
  26. package/dist/src/browser/vision-input.js +74 -0
  27. package/dist/src/browser/vision-input.js.map +1 -0
  28. package/dist/src/browser/vision-provider.js +75 -0
  29. package/dist/src/browser/vision-provider.js.map +1 -0
  30. package/dist/src/browser/vision.js +360 -47
  31. package/dist/src/browser/vision.js.map +1 -1
  32. package/dist/src/browser/web-ai/candidate-reconcile.js +14 -5
  33. package/dist/src/browser/web-ai/candidate-reconcile.js.map +1 -1
  34. package/dist/src/cli/claude-model-discovery.js +175 -0
  35. package/dist/src/cli/claude-model-discovery.js.map +1 -0
  36. package/dist/src/cli/claude-models.js +46 -0
  37. package/dist/src/cli/claude-models.js.map +1 -1
  38. package/dist/src/cli/registry-live.js +104 -1
  39. package/dist/src/cli/registry-live.js.map +1 -1
  40. package/dist/src/cli/registry.js +28 -5
  41. package/dist/src/cli/registry.js.map +1 -1
  42. package/dist/src/code-mode/host.js +6 -0
  43. package/dist/src/code-mode/host.js.map +1 -1
  44. package/dist/src/code-mode/manager.js +37 -8
  45. package/dist/src/code-mode/manager.js.map +1 -1
  46. package/dist/src/code-mode/providers/catalog.js +53 -1
  47. package/dist/src/code-mode/providers/catalog.js.map +1 -1
  48. package/dist/src/code-mode/providers/codex-app.js +6 -0
  49. package/dist/src/code-mode/providers/codex-app.js.map +1 -1
  50. package/dist/src/code-mode/providers/live-models.js +85 -0
  51. package/dist/src/code-mode/providers/live-models.js.map +1 -0
  52. package/dist/src/code-mode/providers/provider-live-models.js +120 -0
  53. package/dist/src/code-mode/providers/provider-live-models.js.map +1 -0
  54. package/dist/src/code-mode/session.js +37 -0
  55. package/dist/src/code-mode/session.js.map +1 -1
  56. package/dist/src/prompt/templates/a1-system.md +24 -14
  57. package/dist/src/prompt/templates/control-system.md +6 -11
  58. package/dist/src/prompt/templates/employee.md +5 -5
  59. package/dist/src/routes/browser.js +17 -5
  60. package/dist/src/routes/browser.js.map +1 -1
  61. package/package.json +1 -1
  62. package/public/css/activity.css +20 -1
  63. package/public/css/layout.css +7 -3
  64. package/public/dist/.vite/manifest.json +104 -105
  65. package/public/dist/assets/Agent-CQ4EBgY8.js +1 -0
  66. package/public/dist/assets/CodeCanvas-DWsx6sv5.js +2 -0
  67. package/public/dist/assets/DashboardMeta-Dh-tasbY.js +1 -0
  68. package/public/dist/assets/Display-NrqY_IaN.js +1 -0
  69. package/public/dist/assets/{Permissions-BzbnqenZ.js → Permissions-Bh947tUG.js} +1 -1
  70. package/public/dist/assets/Permissions-DzNJCt8K.js +1 -0
  71. package/public/dist/assets/app-BCBnxiGr.css +1 -0
  72. package/public/dist/assets/{app-x5Kray4W.js → app-Q0prKOFx.js} +4 -4
  73. package/public/dist/assets/{bgtask-badge-W9djRQVu.js → bgtask-badge-DAcWaUfS.js} +1 -1
  74. package/public/dist/assets/bgtask-badge-DHA2OQm8.js +1 -0
  75. package/public/dist/assets/{employees--_dmDw_a.js → employees-CWS3Juca.js} +1 -1
  76. package/public/dist/assets/{iframe-renderer-D4BmLtAq.js → iframe-renderer-DCDKBMb7.js} +2 -2
  77. package/public/dist/assets/iframe-renderer-RpvBly2x.js +1 -0
  78. package/public/dist/assets/manager-Nk7-RYPs.css +1 -0
  79. package/public/dist/assets/manager-XkR-DRaQ.js +5 -0
  80. package/public/dist/assets/manager-shortcuts-jsiX-zV6.js +1 -0
  81. package/public/dist/assets/memory-4YH8sz0L.js +1 -0
  82. package/public/dist/assets/{memory-DENQWzM8.js → memory-DhNdKZLO.js} +1 -1
  83. package/public/dist/assets/{message-history-BsrLcGJj.js → message-history-DbRTl1P0.js} +1 -1
  84. package/public/dist/assets/message-history-lVcLpAw8.js +1 -0
  85. package/public/dist/assets/{render-CF6Q1oIh.js → render-DP8SJtdZ.js} +1 -1
  86. package/public/dist/assets/settings--EGy3_B9.js +1 -0
  87. package/public/dist/assets/settings-85n9NjvX.js +1 -0
  88. package/public/dist/assets/{settings-B-C_jdZR.js → settings-C9_D-pn0.js} +32 -32
  89. package/public/dist/assets/settings-core-8wBl1mg-.js +1 -0
  90. package/public/dist/assets/{settings-core-BzAJLsKN.js → settings-core-BcVD2FgV.js} +1 -1
  91. package/public/dist/assets/{settings-embedding-dEMyByVi.js → settings-embedding-BSpq785l.js} +1 -1
  92. package/public/dist/assets/{settings-embedding-BSA42oKM.css → settings-embedding-LIMq5ebM.css} +1 -1
  93. package/public/dist/assets/{sidebar-fFEOpvJl.js → sidebar-BVhLb5Ft.js} +3 -3
  94. package/public/dist/assets/skills-6GFkHTlQ.js +1 -0
  95. package/public/dist/assets/{skills-Da_b06ci.js → skills-X7qxmHka.js} +1 -1
  96. package/public/dist/assets/{slash-commands-BbPUHHF4.js → slash-commands-BnDH4IU_.js} +1 -1
  97. package/public/dist/assets/slash-commands-qu8fPAZ3.js +1 -0
  98. package/public/dist/assets/{trace-drawer-B-QmzUfP.js → trace-drawer-DasaS1z4.js} +1 -1
  99. package/public/dist/assets/{ui-CkRUrIfp.js → ui-BtiBTXng.js} +1 -1
  100. package/public/dist/assets/ui-BucJ1zMA.js +1 -0
  101. package/public/dist/index.html +2 -2
  102. package/public/dist/manager/index.html +3 -3
  103. package/public/dist/settings/index.html +2 -2
  104. package/public/js/features/settings.ts +16 -0
  105. package/public/manager/src/App.tsx +10 -12
  106. package/public/manager/src/AppChrome.tsx +2 -3
  107. package/public/manager/src/InstancePreview.tsx +47 -0
  108. package/public/manager/src/SidebarRailRouter.tsx +34 -30
  109. package/public/manager/src/code/CodeComposer.tsx +31 -6
  110. package/public/manager/src/code/CodeSessionList.tsx +25 -7
  111. package/public/manager/src/code/CodeToastHost.tsx +49 -0
  112. package/public/manager/src/code/CodeTranscript.tsx +136 -26
  113. package/public/manager/src/code/CodeWorkbench.tsx +16 -2
  114. package/public/manager/src/code/ComposerFooter.tsx +130 -46
  115. package/public/manager/src/code/ContextUsageMeter.tsx +72 -0
  116. package/public/manager/src/code/ProviderGlyph.tsx +58 -0
  117. package/public/manager/src/code/code-composer.css +159 -175
  118. package/public/manager/src/code/code-controller-runtime.ts +3 -1
  119. package/public/manager/src/code/code-session-state.ts +7 -1
  120. package/public/manager/src/code/code-toasts.ts +73 -0
  121. package/public/manager/src/code/code-workbench.css +42 -1
  122. package/public/manager/src/code/code.css +130 -15
  123. package/public/manager/src/code/context-usage.ts +74 -0
  124. package/public/manager/src/code/pending-user-item.ts +46 -0
  125. package/public/manager/src/code/session-order.ts +70 -0
  126. package/public/manager/src/code/tool-summary.ts +101 -0
  127. package/public/manager/src/code/use-dictation.ts +130 -0
  128. package/public/manager/src/components/CommandCenter.tsx +4 -8
  129. package/public/manager/src/components/InstanceDetailPanel.tsx +0 -18
  130. package/public/manager/src/components/Workbench.tsx +6 -10
  131. package/public/manager/src/components/WorkbenchHeader.tsx +0 -11
  132. package/public/manager/src/dashboard-settings/dashboard-settings-ui.ts +3 -1
  133. package/public/manager/src/hooks/useDashboardView.ts +38 -38
  134. package/public/manager/src/manager-components.css +0 -8
  135. package/public/manager/src/manager-shortcut-runner.ts +0 -1
  136. package/public/manager/src/manager-shortcuts.ts +0 -2
  137. package/public/manager/src/settings/pages/Agent.tsx +5 -2
  138. package/public/manager/src/settings/pages/DashboardMeta.tsx +20 -1
  139. package/public/manager/src/settings/pages/Permissions.tsx +23 -4
  140. package/public/manager/src/settings/pages/components/agent/PermissionQuickSection.tsx +6 -2
  141. package/public/manager/src/settings/pages/components/agent/agent-save.ts +24 -1
  142. package/public/manager/src/settings/settings-icons.ts +3 -1
  143. package/public/manager/src/settings/settings-registry.ts +3 -3
  144. package/public/manager/src/settings-controls.css +0 -1
  145. package/public/manager/src/settings-standalone.tsx +8 -8
  146. package/public/manager/src/types.ts +0 -1
  147. package/scripts/check-private-boundary.mjs +101 -0
  148. package/scripts/grounding-eval.mjs +223 -0
  149. package/public/dist/assets/Agent-B8ZEWJ6B.js +0 -1
  150. package/public/dist/assets/CodeCanvas-Bj3lTSu6.js +0 -2
  151. package/public/dist/assets/DashboardMeta-CmZavI4H.js +0 -1
  152. package/public/dist/assets/Display-DFkjKcMk.js +0 -1
  153. package/public/dist/assets/Permissions-CJftCO6p.js +0 -1
  154. package/public/dist/assets/app-DVbrIl8f.css +0 -1
  155. package/public/dist/assets/bgtask-badge-CuAc8bAl.js +0 -1
  156. package/public/dist/assets/iframe-renderer-By2WO5bd.js +0 -1
  157. package/public/dist/assets/manager-CxLXWCGi.css +0 -1
  158. package/public/dist/assets/manager-DA3dF3eN.js +0 -5
  159. package/public/dist/assets/manager-shortcuts-CzGkE0ZG.js +0 -1
  160. package/public/dist/assets/memory-thjr2apY.js +0 -1
  161. package/public/dist/assets/message-history-CfU7_P5t.js +0 -1
  162. package/public/dist/assets/settings-DXA5L4DR.js +0 -1
  163. package/public/dist/assets/settings-Dy_IaNVH.js +0 -1
  164. package/public/dist/assets/settings-core-D7sAQqhC.js +0 -1
  165. package/public/dist/assets/skills-BcIievZp.js +0 -1
  166. package/public/dist/assets/slash-commands-B-5Shayl.js +0 -1
  167. package/public/dist/assets/ui-CJLdMfRx.js +0 -1
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Runtime glyphs for the composer's icon-only runtime trigger.
3
+ *
4
+ * These are the same brand marks the Classic UI already ships in
5
+ * public/assets/providers (lobehub/icons-static-svg, plus Cursor's own brand
6
+ * kit); the path data is inlined here because the Manager bundle has no
7
+ * ?raw import convention and a test-time JSDOM render must not depend on one.
8
+ * Keep them in sync with that directory rather than redrawing them.
9
+ *
10
+ * The marks are decorative: the accessible name lives on the button that wraps
11
+ * them, never in the SVG.
12
+ */
13
+ import type { CodeProviderId } from '../../../../src/code-mode/wire';
14
+
15
+ type Glyph = { viewBox: string; d: string; rule?: 'evenodd' };
16
+ const GLYPHS: Record<CodeProviderId, Glyph> = {
17
+ 'codex-app': { viewBox: '0 0 24 24', rule: 'evenodd', d: 'M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z' },
18
+ claude: { viewBox: '0 0 24 24', rule: 'evenodd', d: 'M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z' },
19
+ cursor: { viewBox: '675 357 250 286', d: 'M920.015 424.958L805.919 359.086C802.256 356.97 797.735 356.97 794.071 359.086L679.981 424.958C676.901 426.736 675 430.025 675 433.587V566.419C675 569.981 676.901 573.269 679.981 575.048L794.077 640.92C797.74 643.036 802.261 643.036 805.925 640.92L920.02 575.048C923.1 573.269 925.001 569.981 925.001 566.419V433.587C925.001 430.025 923.1 426.736 920.02 424.958H920.015ZM912.848 438.911L802.706 629.682C801.961 630.968 799.995 630.443 799.995 628.954V504.039C799.995 501.543 798.662 499.234 796.498 497.981L688.321 435.526C687.036 434.781 687.561 432.816 689.05 432.816H909.334C912.462 432.816 914.417 436.206 912.853 438.917H912.848V438.911Z' },
20
+ grok: { viewBox: '0 0 24 24', rule: 'evenodd', d: 'M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815' },
21
+ };
22
+
23
+ export function ProviderGlyph({ provider }: { provider: CodeProviderId }) {
24
+ const glyph = GLYPHS[provider];
25
+ return <svg className="code-provider-glyph" viewBox={glyph.viewBox} width="16" height="16"
26
+ aria-hidden="true" focusable="false" fill="currentColor"
27
+ {...(glyph.rule ? { fillRule: 'evenodd' as const, clipRule: 'evenodd' as const } : {})}>
28
+ <path d={glyph.d} />
29
+ </svg>;
30
+ }
31
+
32
+ export function SendGlyph() {
33
+ return <svg viewBox="0 0 20 20" width="16" height="16" aria-hidden="true" focusable="false">
34
+ <path d="M10 16V4.6M5.2 9.4 10 4.4l4.8 5" fill="none" stroke="currentColor"
35
+ strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" />
36
+ </svg>;
37
+ }
38
+
39
+ export function StopGlyph() {
40
+ return <svg viewBox="0 0 20 20" width="16" height="16" aria-hidden="true" focusable="false">
41
+ <rect x="6" y="6" width="8" height="8" rx="1.6" fill="currentColor" />
42
+ </svg>;
43
+ }
44
+
45
+ export function MicGlyph({ muted }: { muted?: boolean }) {
46
+ return <svg viewBox="0 0 20 20" width="16" height="16" aria-hidden="true" focusable="false">
47
+ <path d="M10 3.6a2 2 0 0 1 2 2v4.2a2 2 0 0 1-4 0V5.6a2 2 0 0 1 2-2ZM5.4 9.6a4.6 4.6 0 0 0 9.2 0M10 14.4V16.4"
48
+ fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
49
+ {muted && <path d="M4.6 4.6 15.4 15.4" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />}
50
+ </svg>;
51
+ }
52
+
53
+ export function CheckGlyph() {
54
+ return <svg className="code-footer-check" viewBox="0 0 20 20" width="16" height="16" aria-hidden="true" focusable="false">
55
+ <path d="m4.8 10.4 3.3 3.3 7.1-7.4" fill="none" stroke="currentColor" strokeWidth="1.8"
56
+ strokeLinecap="round" strokeLinejoin="round" />
57
+ </svg>;
58
+ }
@@ -1,4 +1,10 @@
1
- /* Code composer dock and native session controls. */
1
+ /* Code composer dock and native session controls.
2
+ *
3
+ * Geometry follows the composer grammar Codex-family desktop shells use, taken
4
+ * from the ZCode 3.3.4 bundle rather than guessed: a single 16px-radius shell
5
+ * with 12px padding and no shadow, 28px pill controls at radius 8px, a 28px
6
+ * icon submit, and 12px-radius dropups capped at 288px.
7
+ */
2
8
 
3
9
  .code-composer-dock {
4
10
  flex: 0 0 auto;
@@ -10,15 +16,15 @@
10
16
  }
11
17
  .code-composer-surface {
12
18
  display: grid;
13
- gap: 7px;
19
+ gap: 12px;
14
20
  width: min(100%, 980px);
15
21
  margin: 0 auto;
16
- padding: 8px;
17
- border: 1px solid color-mix(in srgb, var(--border-subtle) 86%, var(--accent));
18
- border-radius: 12px;
22
+ padding: 12px;
23
+ border: 1px solid var(--border-subtle);
24
+ border-radius: 16px;
19
25
  background: var(--bg-base);
20
- box-shadow: 0 12px 34px color-mix(in srgb, var(--bg-base) 68%, transparent);
21
26
  }
27
+ .code-composer-surface:focus-within { border-color: var(--border-strong); }
22
28
  .code-composer {
23
29
  display: grid;
24
30
  grid-template-columns: minmax(0, 1fr) auto;
@@ -31,20 +37,12 @@
31
37
  flex-direction: column;
32
38
  gap: 5px;
33
39
  min-width: 0;
34
- padding: 4px 6px 3px;
35
- border: 1px solid transparent;
36
- border-radius: 9px;
37
- background: transparent;
38
- }
39
- .code-composer-input-shell:focus-within {
40
- border-color: color-mix(in srgb, var(--accent) 48%, transparent);
41
- background: color-mix(in srgb, var(--bg-raised) 72%, transparent);
42
40
  }
43
41
  .code-composer-input {
44
42
  resize: none;
45
43
  width: 100%;
46
- min-height: 44px;
47
- max-height: 144px;
44
+ min-height: 40px;
45
+ max-height: 160px;
48
46
  padding: 0;
49
47
  border: 0;
50
48
  background: transparent;
@@ -60,233 +58,219 @@
60
58
  font-size: 10px;
61
59
  line-height: 1.2;
62
60
  }
61
+
62
+ /* Trailing action cluster: dictation, then submit/stop. */
63
+ .code-composer-actions { display: flex; align-items: center; gap: 4px; }
64
+ .code-composer-icon-button,
63
65
  .code-composer-send {
64
- min-width: 46px;
65
- height: 38px;
66
- min-height: 38px;
67
- padding: 0 11px;
68
- border: 1px solid color-mix(in srgb, var(--accent) 72%, var(--border-subtle));
69
- border-radius: 10px;
70
- background: var(--accent);
71
- color: var(--ink-on-accent);
72
- font-size: 12px;
73
- font-weight: 700;
66
+ display: inline-flex;
67
+ align-items: center;
68
+ justify-content: center;
69
+ width: 28px;
70
+ height: 28px;
71
+ padding: 0;
72
+ border-radius: 8px;
73
+ border: 1px solid transparent;
74
74
  cursor: pointer;
75
75
  }
76
- .code-composer-send:not(.code-composer-stop):hover:not(:disabled) {
77
- background: var(--accent);
76
+ .code-composer-icon-button {
77
+ background: transparent;
78
+ color: var(--text-secondary);
79
+ }
80
+ .code-composer-icon-button:hover:not(:disabled) {
81
+ background: var(--bg-raised);
82
+ color: var(--text-primary);
83
+ }
84
+ /* Recording is a live state, so it is visible without hovering. */
85
+ .code-composer-icon-button.is-recording {
86
+ border-color: var(--status-error);
87
+ color: var(--status-error);
88
+ }
89
+ .code-composer-send {
78
90
  border-color: var(--accent);
91
+ background: var(--accent);
79
92
  color: var(--ink-on-accent);
80
93
  }
94
+ .code-composer-send:disabled,
95
+ .code-composer-icon-button:disabled {
96
+ cursor: not-allowed;
97
+ opacity: 0.5;
98
+ }
81
99
  .code-composer-send:disabled {
82
100
  border-color: var(--border-subtle);
83
101
  background: var(--bg-raised);
84
102
  color: var(--text-dim);
85
- cursor: not-allowed;
86
103
  }
104
+ .code-composer-stop {
105
+ border-color: var(--status-warn);
106
+ background: var(--bg-raised);
107
+ color: var(--text-primary);
108
+ }
109
+ .code-composer-icon-button:focus-visible,
110
+ .code-composer-stop:focus-visible,
111
+ .code-composer-send:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
112
+
113
+ /* Footer: [runtime icon] [permission] ····· [model] [effort] */
87
114
  .code-composer-footer {
88
115
  display: flex;
89
- gap: 6px;
116
+ gap: 4px;
90
117
  align-items: center;
91
118
  flex-wrap: wrap;
92
119
  min-width: 0;
93
- padding-top: 7px;
120
+ padding-top: 12px;
94
121
  border-top: 1px solid var(--border-subtle);
95
122
  overflow: visible;
96
123
  }
97
- .code-footer-menu {
98
- position: relative;
99
- flex: 0 1 auto;
100
- min-width: 0;
101
- }
102
- .code-footer-menu:first-child {
103
- flex: 0 0 auto;
104
- }
105
- .code-footer-field-model {
106
- flex: 1 1 320px;
107
- max-width: min(42vw, 420px);
108
- }
124
+ .code-composer-footer-spacer { flex: 1 1 auto; min-width: 0; }
125
+ .code-footer-menu { position: relative; flex: 0 1 auto; min-width: 0; }
109
126
  .code-footer-menu-trigger {
110
- display: grid;
111
- grid-template-columns: auto minmax(0, auto) auto;
127
+ display: inline-flex;
112
128
  align-items: center;
113
- gap: 7px;
129
+ gap: 4px;
114
130
  max-width: 100%;
115
- height: 32px;
116
- padding: 0 10px;
131
+ height: 28px;
132
+ padding: 0 8px;
117
133
  border: 1px solid var(--border-subtle);
118
- border-radius: 999px;
119
- background: color-mix(in srgb, var(--bg-panel) 62%, var(--bg-base));
134
+ border-radius: 8px;
135
+ background: transparent;
120
136
  color: var(--text-primary);
121
137
  font: inherit;
138
+ font-size: 13px;
122
139
  cursor: pointer;
123
140
  }
124
- .code-footer-menu-trigger:hover,
141
+ .code-footer-menu-trigger.is-icon {
142
+ width: 28px;
143
+ padding: 0;
144
+ justify-content: center;
145
+ color: var(--text-secondary);
146
+ }
147
+ .code-footer-menu-trigger:hover:not(:disabled),
125
148
  .code-footer-menu-trigger[aria-expanded="true"] {
126
- border-color: color-mix(in srgb, var(--accent) 42%, var(--border-subtle));
149
+ border-color: var(--border-strong);
127
150
  background: var(--bg-raised);
128
151
  }
129
- .code-footer-menu-trigger:focus-visible {
130
- outline: 2px solid var(--ring);
131
- outline-offset: 2px;
132
- }
133
- .code-footer-menu-trigger:disabled {
134
- cursor: not-allowed;
135
- opacity: 0.62;
136
- }
152
+ .code-footer-menu-trigger:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
153
+ .code-footer-menu-trigger:disabled { cursor: not-allowed; opacity: 0.5; }
137
154
  .code-footer-menu-trigger strong {
138
155
  min-width: 0;
139
156
  overflow: hidden;
140
157
  text-overflow: ellipsis;
141
158
  white-space: nowrap;
142
- font-size: 12px;
143
- font-weight: 650;
159
+ font-size: 13px;
160
+ font-weight: 400;
144
161
  color: var(--text-primary);
145
162
  }
163
+ /*
164
+ * The value carries the meaning on every one of these pills and the accessible
165
+ * name already says which control it is, so a visible caption is redundant
166
+ * chrome. It stays in the DOM but not on screen.
167
+ */
146
168
  .code-footer-label {
147
- color: var(--text-dim);
148
- font-size: 10px;
149
- font-weight: 750;
150
- text-transform: uppercase;
151
- letter-spacing: 0.04em;
169
+ position: absolute;
170
+ width: 1px;
171
+ height: 1px;
172
+ padding: 0;
173
+ margin: -1px;
174
+ overflow: hidden;
175
+ clip-path: inset(50%);
152
176
  white-space: nowrap;
153
177
  }
154
- .code-footer-chevron {
155
- color: var(--text-dim);
156
- font-size: 13px;
157
- line-height: 1;
158
- }
178
+ .code-footer-model { flex: 0 1 auto; min-width: 0; max-width: min(46vw, 340px); }
179
+ .code-footer-model .code-footer-menu-trigger strong { font-weight: 500; }
180
+ .code-footer-effort .code-footer-menu-trigger { color: var(--text-secondary); }
181
+ .code-provider-glyph { flex: 0 0 auto; }
182
+
159
183
  .code-footer-dropup {
160
184
  position: absolute;
161
185
  left: 0;
162
186
  bottom: calc(100% + 8px);
163
187
  z-index: 35;
164
- width: max(260px, 100%);
165
- max-width: min(520px, calc(100vw - 28px));
166
- max-height: min(280px, 46vh);
167
- overflow-y: auto;
168
- padding: 6px;
188
+ display: flex;
189
+ flex-direction: column;
190
+ gap: 4px;
191
+ width: max(192px, 100%);
192
+ max-width: min(340px, calc(100vw - 28px));
193
+ max-height: 288px;
194
+ padding: 4px;
169
195
  border: 1px solid var(--border-subtle);
170
196
  border-radius: 12px;
171
197
  background: var(--bg-panel);
172
- box-shadow: 0 -18px 42px rgba(0,0,0,0.28);
198
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.18), 0 2px 4px -2px rgb(0 0 0 / 0.18);
199
+ }
200
+ .code-footer-dropup-list {
201
+ display: flex;
202
+ flex-direction: column;
203
+ gap: 2px;
204
+ min-height: 0;
205
+ overflow-y: auto;
206
+ overflow-x: hidden;
173
207
  }
174
- .code-footer-field-model .code-footer-dropup {
175
- width: min(520px, calc(100vw - 28px));
208
+ .code-footer-filter {
209
+ flex: 0 0 auto;
210
+ width: 100%;
211
+ height: 28px;
212
+ padding: 0 8px;
213
+ border: 1px solid var(--border-subtle);
214
+ border-radius: 8px;
215
+ background: var(--bg-base);
216
+ color: var(--text-primary);
217
+ font: inherit;
218
+ font-size: 13px;
176
219
  }
220
+ .code-footer-filter:focus-visible { outline: 2px solid var(--ring); outline-offset: -1px; }
177
221
  .code-footer-dropup-option {
178
222
  display: grid;
179
- grid-template-columns: minmax(0, 1fr) auto;
223
+ grid-template-columns: auto minmax(0, 1fr) 16px;
180
224
  align-items: center;
181
- gap: 10px;
225
+ gap: 8px;
182
226
  width: 100%;
183
- min-height: 44px;
184
- padding: 8px 10px;
185
- border: 1px solid transparent;
186
- border-radius: 9px;
227
+ min-height: 32px;
228
+ padding: 4px 8px;
229
+ border: 0;
230
+ border-radius: 8px;
187
231
  background: transparent;
188
232
  color: var(--text-primary);
189
233
  font: inherit;
190
234
  text-align: left;
191
235
  cursor: pointer;
192
236
  }
193
- .code-footer-dropup-option:hover,
194
- .code-footer-dropup-option.is-selected {
195
- border-color: color-mix(in srgb, var(--accent) 36%, var(--border-subtle));
196
- background: var(--bg-raised);
197
- }
198
- .code-footer-dropup-option:focus-visible {
199
- outline: 2px solid var(--ring);
200
- outline-offset: 1px;
201
- }
202
- .code-footer-dropup-option span,
203
- .code-footer-dropup-option strong,
204
- .code-footer-dropup-option small {
205
- min-width: 0;
237
+ .code-footer-dropup-option:not(:has(.code-footer-option-icon)) { grid-template-columns: minmax(0, 1fr) 16px; }
238
+ .code-footer-dropup-option:hover:not(:disabled) { background: var(--bg-raised); }
239
+ .code-footer-dropup-option:focus-visible { outline: 2px solid var(--ring); outline-offset: -2px; }
240
+ .code-footer-dropup-option:disabled { cursor: not-allowed; opacity: 0.5; }
241
+ .code-footer-option-icon { display: inline-flex; color: var(--text-secondary); }
242
+ .code-footer-option-text { display: grid; gap: 2px; min-width: 0; }
243
+ .code-footer-option-text strong {
244
+ font-size: 13px;
245
+ font-weight: 400;
206
246
  overflow: hidden;
207
247
  text-overflow: ellipsis;
208
248
  white-space: nowrap;
209
249
  }
210
- .code-footer-dropup-option span {
211
- display: grid;
212
- gap: 2px;
213
- }
214
- .code-footer-dropup-option strong {
215
- font-size: 13px;
216
- font-weight: 650;
217
- }
218
- .code-footer-dropup-option small {
250
+ .code-footer-option-text small {
219
251
  color: var(--text-dim);
220
- font-size: 12px;
221
- }
222
- .code-footer-dropup-option em {
223
- color: var(--accent);
224
- font-style: normal;
225
- font-size: 15px;
226
- font-weight: 800;
227
- }
228
- @media (max-width: 900px) {
229
- .code-footer-label {
230
- display: none;
231
- }
232
- .code-footer-field-model {
233
- flex-basis: 220px;
234
- max-width: 100%;
235
- }
236
- }
237
- @media (max-width: 720px) {
238
- .code-footer-menu-trigger {
239
- padding: 0 8px;
240
- gap: 5px;
241
- }
242
- .code-footer-menu-trigger strong {
243
- max-width: 120px;
244
- }
245
- .code-footer-field-model .code-footer-menu-trigger strong {
246
- max-width: 180px;
247
- }
248
- .code-footer-dropup {
249
- width: min(340px, calc(100vw - 28px));
250
- }
251
- }
252
- @media (max-width: 560px) {
253
- .code-composer-footer {
254
- overflow: visible;
255
- flex-wrap: wrap;
256
- }
257
- .code-composer-footer::-webkit-scrollbar {
258
- display: none;
259
- }
260
- .code-footer-menu {
261
- flex: 0 0 auto;
262
- }
263
- .code-footer-menu-trigger strong {
264
- max-width: 112px;
265
- }
266
- .code-footer-field-model .code-footer-menu-trigger strong {
267
- max-width: 150px;
268
- }
269
- }
270
- .code-footer-menu-trigger:focus {
271
- outline-color: var(--ring);
272
- color: var(--accent);
252
+ font-size: 11px;
253
+ overflow: hidden;
254
+ text-overflow: ellipsis;
255
+ white-space: nowrap;
273
256
  }
257
+ .code-footer-check { color: var(--text-primary); }
258
+ .code-footer-dropup-empty { margin: 0; padding: 8px; color: var(--text-dim); font-size: 12px; }
259
+
260
+ .code-footer-floating { position: fixed; z-index: 1000; box-sizing: border-box; }
261
+ .code-footer-floating .code-footer-option-text small { white-space: normal; overflow-wrap: anywhere; }
274
262
 
275
- .code-footer-floating { position: fixed; z-index: 1000; box-sizing: border-box; max-height: min(280px, 46dvh); }
276
- .code-footer-floating .code-footer-dropup-option small { white-space: normal; overflow-wrap: anywhere; }
277
- .code-footer-model-form { display: flex; flex: 1 1 220px; min-width: 0; gap: 6px; align-items: center; }
278
- .code-footer-model-form input { width: 100%; min-width: 0; padding: 6px 9px; border: 1px solid var(--border-subtle); border-radius: var(--control-radius); background: var(--bg-panel); color: var(--text-primary); font: inherit; font-size: 12px; }
279
- .code-footer-model-form input:focus-visible { outline: 2px solid var(--ring); }
280
- .code-footer-model-form button { font: inherit; font-size: 11px; }
281
- .code-footer-runtime { color: var(--text-secondary); font-size: 12px; }
282
- .code-composer-input-shell { border-color: var(--border-subtle); }
283
- .code-composer-stop { background: var(--bg-raised); color: var(--text-primary); border-color: var(--status-warn); }
284
- .code-composer-stop:focus-visible, .code-composer-send:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
285
- .code-policy-note, .code-selection-notice { margin: 0; color: var(--text-secondary); font-size: 11px; line-height: 1.5; overflow-wrap: anywhere; }
263
+ .code-selection-notice { margin: 0; color: var(--text-secondary); font-size: 11px; line-height: 1.5; overflow-wrap: anywhere; }
264
+ .code-composer-status { grid-column: 1 / -1; color: var(--text-dim); font-size: 11px; }
286
265
  .code-input-recovery { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; max-width: 980px; margin: 0 auto 6px; color: var(--text-secondary); font-size: 11px; }
287
266
  .code-action-error { color: var(--status-error); font-size: 12px; overflow-wrap: anywhere; grid-column: 1 / -1; }
288
- @media (max-width: 720px) { .code-composer-dock { padding: 8px; } }
267
+
268
+ @media (max-width: 720px) {
269
+ .code-composer-dock { padding: 8px; }
270
+ .code-composer-surface { border-radius: 14px; padding: 10px; }
271
+ }
289
272
  @media (max-width: 560px) {
290
- .code-footer-model-form { flex-basis: 100%; }
291
- .code-composer-footer { gap: 8px; }
273
+ /* The model pill keeps its own row so it never collapses to a few glyphs. */
274
+ .code-composer-footer-spacer { flex-basis: 100%; height: 0; }
275
+ .code-footer-model { max-width: 100%; }
292
276
  }
@@ -9,6 +9,7 @@ import {
9
9
  acknowledgeCodeSend, catalogSelection, codeDraftBook, createCodeDraft, persistCodeDraftBook, sessionSelection,
10
10
  type CodeDraft, type CodeDraftBook,
11
11
  } from './code-controller-drafts';
12
+ import { withPendingUserItem } from './pending-user-item';
12
13
 
13
14
  const MAX_DETAILS = 6;
14
15
  const MAX_INDEX = 1000;
@@ -198,7 +199,8 @@ export class CodeController {
198
199
  const row = this.info(id), detail = this.details.get(id);
199
200
  return row && detail?.synced ? { ...row, pendingPermissionCount: detail.permissions.length } : row;
200
201
  }).filter((row): row is CodeSessionInfo => !!row),
201
- selectedId: id, session, items: detail?.items ?? [], permissions: detail?.permissions ?? [],
202
+ selectedId: id, session, items: withPendingUserItem(draft, detail?.items ?? []),
203
+ permissions: detail?.permissions ?? [],
202
204
  input: draft.input, selection: session ? sessionSelection(session) : draft.selection,
203
205
  gitInfo: this.gitInfo, loading: this.indexLoading || !!detail?.hydrating || (!!id && !detail?.hydrated && !detail?.error),
204
206
  pending, busy: codeSessionBusy(session), synced, transport: this.transport,
@@ -61,7 +61,13 @@ function apply(state: CodeSessionState, event: CodeWireEvent): CodeSessionState
61
61
  let { items, session, permissions } = state;
62
62
  if (event.event === 'code_session') {
63
63
  if (!event.session || event.session.sessionId !== state.sessionId) return { ...state, needsSnapshot: true, synced: false };
64
- session = event.session;
64
+ // Usage is attached at read time, so a stored session event does not
65
+ // carry it. Replacing the record wholesale would blank the meter on
66
+ // every unrelated session change; the last figure stands until a
67
+ // snapshot or a listing supplies a newer one.
68
+ session = event.session.contextUsage === undefined && session?.contextUsage !== undefined
69
+ ? { ...event.session, contextUsage: session.contextUsage }
70
+ : event.session;
65
71
  permissions = permissions.filter(p => p.epoch === session!.epoch && p.turnId === session!.turnId);
66
72
  } else {
67
73
  const id = event.item?.itemId ?? event.update?.itemId;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * A transient notice that appears over the transcript and leaves on its own.
3
+ *
4
+ * The composer footer used to carry these inline, which pushed the input down
5
+ * and left a policy line sitting there long after it had been read. What
6
+ * belongs here is news -- a setting saved, a policy changed, an action failed.
7
+ * What does not belong here is anything the reader still has to act on: an
8
+ * unconfirmed send or an archived session has to stay on screen until it is
9
+ * resolved, and a notice that dismisses itself would strand them.
10
+ */
11
+ /**
12
+ * Only `warning` exists today, because the one notice this surface raises is a
13
+ * permission warning; an error the reader must act on stays inline instead. The
14
+ * union is kept because the shape of a second variant is already decided, but
15
+ * nothing in the app produces one, so there is no assertive region to route to.
16
+ */
17
+ export type CodeToastVariant = 'warning';
18
+
19
+ export type CodeToast = {
20
+ /** Stable per source, so a repeated notice replaces rather than stacks. */
21
+ id: string;
22
+ message: string;
23
+ variant: CodeToastVariant;
24
+ /** Non-finite or <= 0 stays until dismissed. */
25
+ durationMs: number;
26
+ /** Distinguishes two pushes of the same id, so the timer restarts. */
27
+ revision: number;
28
+ };
29
+
30
+ export const CODE_TOAST_DEFAULT_MS = 4000;
31
+ /** Three is enough to see a burst; more would cover the transcript. */
32
+ export const CODE_TOAST_MAX = 3;
33
+
34
+ export function codeToastAutoDismisses(toast: CodeToast): boolean {
35
+ return Number.isFinite(toast.durationMs) && toast.durationMs > 0;
36
+ }
37
+
38
+ /**
39
+ * Newest last, one entry per id. Re-pushing an id refreshes its content and
40
+ * restarts its timer through a bumped revision, and moves it to the end so a
41
+ * notice the reader just triggered is never the one dropped by the cap.
42
+ */
43
+ export function pushCodeToast(
44
+ list: readonly CodeToast[],
45
+ next: Omit<CodeToast, 'revision'>,
46
+ ): CodeToast[] {
47
+ const previous = list.find(toast => toast.id === next.id);
48
+ const kept = list.filter(toast => toast.id !== next.id);
49
+ kept.push({ ...next, revision: (previous?.revision ?? 0) + 1 });
50
+ return kept.slice(Math.max(0, kept.length - CODE_TOAST_MAX));
51
+ }
52
+
53
+ export function dismissCodeToast(list: readonly CodeToast[], id: string): CodeToast[] {
54
+ const next = list.filter(toast => toast.id !== id);
55
+ return next.length === list.length ? list as CodeToast[] : next;
56
+ }
57
+
58
+ /**
59
+ * What a producer says: either raise this notice, or retire it.
60
+ *
61
+ * Retiring matters for anything derived from current state. A warning about a
62
+ * permission policy has to leave when the policy does, or it goes on asserting
63
+ * something about the session that is no longer true.
64
+ */
65
+ export type CodeNotice =
66
+ | { id: string; message: string; variant: CodeToastVariant; durationMs?: number }
67
+ | { id: string; clear: true };
68
+
69
+ export function applyCodeNotice(list: readonly CodeToast[], notice: CodeNotice): CodeToast[] {
70
+ if ('clear' in notice) return dismissCodeToast(list, notice.id);
71
+ return pushCodeToast(list, { id: notice.id, message: notice.message, variant: notice.variant,
72
+ durationMs: notice.durationMs ?? CODE_TOAST_DEFAULT_MS });
73
+ }
@@ -135,8 +135,49 @@
135
135
  }
136
136
  .code-tool-summary::-webkit-details-marker { display: none; }
137
137
  .code-tool-summary:hover { background: var(--accent-soft); }
138
- .code-tool-chevron { flex-shrink: 0; font-weight: 800; line-height: 1; color: var(--text-dim); }
138
+ .code-tool-chevron {
139
+ flex-shrink: 0; font-weight: 800; line-height: 1; color: var(--text-dim);
140
+ /* Dimmed rather than hidden: a chevron that only appears on hover is
141
+ undiscoverable by touch and gives a keyboard user nothing to aim at. */
142
+ opacity: 0.35;
143
+ transition: transform 0.15s ease, opacity 0.15s ease;
144
+ }
145
+ .code-tool-summary:hover .code-tool-chevron,
146
+ .code-tool-summary:focus-visible .code-tool-chevron { opacity: 1; }
147
+ .code-tool-card[open] > .code-tool-summary .code-tool-chevron { transform: rotate(90deg); opacity: 1; }
139
148
  .code-tool-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 650; line-height: 1.15; }
149
+ /* A call in flight reads as in-flight. The verb already says so; this keeps the
150
+ row alive while it streams, and stopping is what marks completion -- no chip
151
+ that says "Done" on every successful row. */
152
+ /* The label is clipped with an ellipsis, and transparent text over a clipped
153
+ background is invisible rather than dim wherever the clip does not apply, so
154
+ the gradient is opted into only where it is supported. */
155
+ .code-tool-name-running { color: var(--text-dim); }
156
+ @supports (background-clip: text) or (-webkit-background-clip: text) {
157
+ .code-tool-name-running {
158
+ background: linear-gradient(90deg,
159
+ var(--text-dim) 0%, var(--text-dim) 34%,
160
+ var(--text-primary) 50%,
161
+ var(--text-dim) 66%, var(--text-dim) 100%);
162
+ background-size: 300% 100%;
163
+ -webkit-background-clip: text;
164
+ background-clip: text;
165
+ color: transparent;
166
+ animation: code-tool-shimmer 4s linear infinite;
167
+ }
168
+ }
169
+ @keyframes code-tool-shimmer {
170
+ from { background-position: 150% 0; }
171
+ to { background-position: -150% 0; }
172
+ }
173
+ /* Transparent text has no fallback under a forced palette, and a reader who
174
+ asked for less motion should not get a looping gradient either. */
175
+ @media (prefers-reduced-motion: reduce) {
176
+ .code-tool-name-running { animation: none; background: none; color: var(--text-primary); -webkit-text-fill-color: currentColor; }
177
+ }
178
+ @media (forced-colors: active) {
179
+ .code-tool-name-running { animation: none; background: none; color: CanvasText; -webkit-text-fill-color: currentColor; forced-color-adjust: none; }
180
+ }
140
181
  .code-tool-status {
141
182
  margin-left: auto;
142
183
  flex-shrink: 0;