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.
- package/README.md +3 -3
- package/dist/bin/commands/browser.js +52 -5
- package/dist/bin/commands/browser.js.map +1 -1
- package/dist/src/agent/args.js +69 -19
- package/dist/src/agent/args.js.map +1 -1
- package/dist/src/agent/codex-app-events.js +31 -1
- package/dist/src/agent/codex-app-events.js.map +1 -1
- package/dist/src/agent/cursor-model-inventory.js +140 -0
- package/dist/src/agent/cursor-model-inventory.js.map +1 -0
- package/dist/src/agent/grok-models.js +80 -0
- package/dist/src/agent/grok-models.js.map +1 -0
- package/dist/src/browser/actions.js +383 -20
- package/dist/src/browser/actions.js.map +1 -1
- package/dist/src/browser/grounding-candidate.js +272 -0
- package/dist/src/browser/grounding-candidate.js.map +1 -0
- package/dist/src/browser/grounding-eval.js +247 -0
- package/dist/src/browser/grounding-eval.js.map +1 -0
- package/dist/src/browser/image-size.js +63 -0
- package/dist/src/browser/image-size.js.map +1 -0
- package/dist/src/browser/index.js +1 -0
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/browser/occlusion.js +148 -0
- package/dist/src/browser/occlusion.js.map +1 -0
- package/dist/src/browser/verify-candidate.js +162 -0
- package/dist/src/browser/verify-candidate.js.map +1 -0
- package/dist/src/browser/vision-input.js +74 -0
- package/dist/src/browser/vision-input.js.map +1 -0
- package/dist/src/browser/vision-provider.js +75 -0
- package/dist/src/browser/vision-provider.js.map +1 -0
- package/dist/src/browser/vision.js +360 -47
- package/dist/src/browser/vision.js.map +1 -1
- package/dist/src/browser/web-ai/candidate-reconcile.js +14 -5
- package/dist/src/browser/web-ai/candidate-reconcile.js.map +1 -1
- package/dist/src/cli/claude-model-discovery.js +175 -0
- package/dist/src/cli/claude-model-discovery.js.map +1 -0
- package/dist/src/cli/claude-models.js +46 -0
- package/dist/src/cli/claude-models.js.map +1 -1
- package/dist/src/cli/registry-live.js +104 -1
- package/dist/src/cli/registry-live.js.map +1 -1
- package/dist/src/cli/registry.js +28 -5
- package/dist/src/cli/registry.js.map +1 -1
- package/dist/src/code-mode/host.js +6 -0
- package/dist/src/code-mode/host.js.map +1 -1
- package/dist/src/code-mode/manager.js +37 -8
- package/dist/src/code-mode/manager.js.map +1 -1
- package/dist/src/code-mode/providers/catalog.js +53 -1
- package/dist/src/code-mode/providers/catalog.js.map +1 -1
- package/dist/src/code-mode/providers/codex-app.js +6 -0
- package/dist/src/code-mode/providers/codex-app.js.map +1 -1
- package/dist/src/code-mode/providers/live-models.js +85 -0
- package/dist/src/code-mode/providers/live-models.js.map +1 -0
- package/dist/src/code-mode/providers/provider-live-models.js +120 -0
- package/dist/src/code-mode/providers/provider-live-models.js.map +1 -0
- package/dist/src/code-mode/session.js +37 -0
- package/dist/src/code-mode/session.js.map +1 -1
- package/dist/src/prompt/templates/a1-system.md +24 -14
- package/dist/src/prompt/templates/control-system.md +6 -11
- package/dist/src/prompt/templates/employee.md +5 -5
- package/dist/src/routes/browser.js +17 -5
- package/dist/src/routes/browser.js.map +1 -1
- package/package.json +1 -1
- package/public/css/activity.css +20 -1
- package/public/css/layout.css +7 -3
- package/public/dist/.vite/manifest.json +104 -105
- package/public/dist/assets/Agent-CQ4EBgY8.js +1 -0
- package/public/dist/assets/CodeCanvas-DWsx6sv5.js +2 -0
- package/public/dist/assets/DashboardMeta-Dh-tasbY.js +1 -0
- package/public/dist/assets/Display-NrqY_IaN.js +1 -0
- package/public/dist/assets/{Permissions-BzbnqenZ.js → Permissions-Bh947tUG.js} +1 -1
- package/public/dist/assets/Permissions-DzNJCt8K.js +1 -0
- package/public/dist/assets/app-BCBnxiGr.css +1 -0
- package/public/dist/assets/{app-x5Kray4W.js → app-Q0prKOFx.js} +4 -4
- package/public/dist/assets/{bgtask-badge-W9djRQVu.js → bgtask-badge-DAcWaUfS.js} +1 -1
- package/public/dist/assets/bgtask-badge-DHA2OQm8.js +1 -0
- package/public/dist/assets/{employees--_dmDw_a.js → employees-CWS3Juca.js} +1 -1
- package/public/dist/assets/{iframe-renderer-D4BmLtAq.js → iframe-renderer-DCDKBMb7.js} +2 -2
- package/public/dist/assets/iframe-renderer-RpvBly2x.js +1 -0
- package/public/dist/assets/manager-Nk7-RYPs.css +1 -0
- package/public/dist/assets/manager-XkR-DRaQ.js +5 -0
- package/public/dist/assets/manager-shortcuts-jsiX-zV6.js +1 -0
- package/public/dist/assets/memory-4YH8sz0L.js +1 -0
- package/public/dist/assets/{memory-DENQWzM8.js → memory-DhNdKZLO.js} +1 -1
- package/public/dist/assets/{message-history-BsrLcGJj.js → message-history-DbRTl1P0.js} +1 -1
- package/public/dist/assets/message-history-lVcLpAw8.js +1 -0
- package/public/dist/assets/{render-CF6Q1oIh.js → render-DP8SJtdZ.js} +1 -1
- package/public/dist/assets/settings--EGy3_B9.js +1 -0
- package/public/dist/assets/settings-85n9NjvX.js +1 -0
- package/public/dist/assets/{settings-B-C_jdZR.js → settings-C9_D-pn0.js} +32 -32
- package/public/dist/assets/settings-core-8wBl1mg-.js +1 -0
- package/public/dist/assets/{settings-core-BzAJLsKN.js → settings-core-BcVD2FgV.js} +1 -1
- package/public/dist/assets/{settings-embedding-dEMyByVi.js → settings-embedding-BSpq785l.js} +1 -1
- package/public/dist/assets/{settings-embedding-BSA42oKM.css → settings-embedding-LIMq5ebM.css} +1 -1
- package/public/dist/assets/{sidebar-fFEOpvJl.js → sidebar-BVhLb5Ft.js} +3 -3
- package/public/dist/assets/skills-6GFkHTlQ.js +1 -0
- package/public/dist/assets/{skills-Da_b06ci.js → skills-X7qxmHka.js} +1 -1
- package/public/dist/assets/{slash-commands-BbPUHHF4.js → slash-commands-BnDH4IU_.js} +1 -1
- package/public/dist/assets/slash-commands-qu8fPAZ3.js +1 -0
- package/public/dist/assets/{trace-drawer-B-QmzUfP.js → trace-drawer-DasaS1z4.js} +1 -1
- package/public/dist/assets/{ui-CkRUrIfp.js → ui-BtiBTXng.js} +1 -1
- package/public/dist/assets/ui-BucJ1zMA.js +1 -0
- package/public/dist/index.html +2 -2
- package/public/dist/manager/index.html +3 -3
- package/public/dist/settings/index.html +2 -2
- package/public/js/features/settings.ts +16 -0
- package/public/manager/src/App.tsx +10 -12
- package/public/manager/src/AppChrome.tsx +2 -3
- package/public/manager/src/InstancePreview.tsx +47 -0
- package/public/manager/src/SidebarRailRouter.tsx +34 -30
- package/public/manager/src/code/CodeComposer.tsx +31 -6
- package/public/manager/src/code/CodeSessionList.tsx +25 -7
- package/public/manager/src/code/CodeToastHost.tsx +49 -0
- package/public/manager/src/code/CodeTranscript.tsx +136 -26
- package/public/manager/src/code/CodeWorkbench.tsx +16 -2
- package/public/manager/src/code/ComposerFooter.tsx +130 -46
- package/public/manager/src/code/ContextUsageMeter.tsx +72 -0
- package/public/manager/src/code/ProviderGlyph.tsx +58 -0
- package/public/manager/src/code/code-composer.css +159 -175
- package/public/manager/src/code/code-controller-runtime.ts +3 -1
- package/public/manager/src/code/code-session-state.ts +7 -1
- package/public/manager/src/code/code-toasts.ts +73 -0
- package/public/manager/src/code/code-workbench.css +42 -1
- package/public/manager/src/code/code.css +130 -15
- package/public/manager/src/code/context-usage.ts +74 -0
- package/public/manager/src/code/pending-user-item.ts +46 -0
- package/public/manager/src/code/session-order.ts +70 -0
- package/public/manager/src/code/tool-summary.ts +101 -0
- package/public/manager/src/code/use-dictation.ts +130 -0
- package/public/manager/src/components/CommandCenter.tsx +4 -8
- package/public/manager/src/components/InstanceDetailPanel.tsx +0 -18
- package/public/manager/src/components/Workbench.tsx +6 -10
- package/public/manager/src/components/WorkbenchHeader.tsx +0 -11
- package/public/manager/src/dashboard-settings/dashboard-settings-ui.ts +3 -1
- package/public/manager/src/hooks/useDashboardView.ts +38 -38
- package/public/manager/src/manager-components.css +0 -8
- package/public/manager/src/manager-shortcut-runner.ts +0 -1
- package/public/manager/src/manager-shortcuts.ts +0 -2
- package/public/manager/src/settings/pages/Agent.tsx +5 -2
- package/public/manager/src/settings/pages/DashboardMeta.tsx +20 -1
- package/public/manager/src/settings/pages/Permissions.tsx +23 -4
- package/public/manager/src/settings/pages/components/agent/PermissionQuickSection.tsx +6 -2
- package/public/manager/src/settings/pages/components/agent/agent-save.ts +24 -1
- package/public/manager/src/settings/settings-icons.ts +3 -1
- package/public/manager/src/settings/settings-registry.ts +3 -3
- package/public/manager/src/settings-controls.css +0 -1
- package/public/manager/src/settings-standalone.tsx +8 -8
- package/public/manager/src/types.ts +0 -1
- package/scripts/check-private-boundary.mjs +101 -0
- package/scripts/grounding-eval.mjs +223 -0
- package/public/dist/assets/Agent-B8ZEWJ6B.js +0 -1
- package/public/dist/assets/CodeCanvas-Bj3lTSu6.js +0 -2
- package/public/dist/assets/DashboardMeta-CmZavI4H.js +0 -1
- package/public/dist/assets/Display-DFkjKcMk.js +0 -1
- package/public/dist/assets/Permissions-CJftCO6p.js +0 -1
- package/public/dist/assets/app-DVbrIl8f.css +0 -1
- package/public/dist/assets/bgtask-badge-CuAc8bAl.js +0 -1
- package/public/dist/assets/iframe-renderer-By2WO5bd.js +0 -1
- package/public/dist/assets/manager-CxLXWCGi.css +0 -1
- package/public/dist/assets/manager-DA3dF3eN.js +0 -5
- package/public/dist/assets/manager-shortcuts-CzGkE0ZG.js +0 -1
- package/public/dist/assets/memory-thjr2apY.js +0 -1
- package/public/dist/assets/message-history-CfU7_P5t.js +0 -1
- package/public/dist/assets/settings-DXA5L4DR.js +0 -1
- package/public/dist/assets/settings-Dy_IaNVH.js +0 -1
- package/public/dist/assets/settings-core-D7sAQqhC.js +0 -1
- package/public/dist/assets/skills-BcIievZp.js +0 -1
- package/public/dist/assets/slash-commands-B-5Shayl.js +0 -1
- 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:
|
|
19
|
+
gap: 12px;
|
|
14
20
|
width: min(100%, 980px);
|
|
15
21
|
margin: 0 auto;
|
|
16
|
-
padding:
|
|
17
|
-
border: 1px solid
|
|
18
|
-
border-radius:
|
|
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:
|
|
47
|
-
max-height:
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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-
|
|
77
|
-
background:
|
|
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:
|
|
116
|
+
gap: 4px;
|
|
90
117
|
align-items: center;
|
|
91
118
|
flex-wrap: wrap;
|
|
92
119
|
min-width: 0;
|
|
93
|
-
padding-top:
|
|
120
|
+
padding-top: 12px;
|
|
94
121
|
border-top: 1px solid var(--border-subtle);
|
|
95
122
|
overflow: visible;
|
|
96
123
|
}
|
|
97
|
-
.code-footer-
|
|
98
|
-
|
|
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:
|
|
111
|
-
grid-template-columns: auto minmax(0, auto) auto;
|
|
127
|
+
display: inline-flex;
|
|
112
128
|
align-items: center;
|
|
113
|
-
gap:
|
|
129
|
+
gap: 4px;
|
|
114
130
|
max-width: 100%;
|
|
115
|
-
height:
|
|
116
|
-
padding: 0
|
|
131
|
+
height: 28px;
|
|
132
|
+
padding: 0 8px;
|
|
117
133
|
border: 1px solid var(--border-subtle);
|
|
118
|
-
border-radius:
|
|
119
|
-
background:
|
|
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
|
|
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:
|
|
149
|
+
border-color: var(--border-strong);
|
|
127
150
|
background: var(--bg-raised);
|
|
128
151
|
}
|
|
129
|
-
.code-footer-menu-trigger:focus-visible {
|
|
130
|
-
|
|
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:
|
|
143
|
-
font-weight:
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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 -
|
|
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-
|
|
175
|
-
|
|
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)
|
|
223
|
+
grid-template-columns: auto minmax(0, 1fr) 16px;
|
|
180
224
|
align-items: center;
|
|
181
|
-
gap:
|
|
225
|
+
gap: 8px;
|
|
182
226
|
width: 100%;
|
|
183
|
-
min-height:
|
|
184
|
-
padding: 8px
|
|
185
|
-
border:
|
|
186
|
-
border-radius:
|
|
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:
|
|
194
|
-
.code-footer-dropup-option
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
.code-footer-
|
|
199
|
-
|
|
200
|
-
|
|
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-
|
|
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:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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-
|
|
276
|
-
.code-
|
|
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
|
-
|
|
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
|
-
|
|
291
|
-
.code-composer-footer {
|
|
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:
|
|
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
|
|
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 {
|
|
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;
|