@stigmer/react 0.2.3 → 0.3.0

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 (118) hide show
  1. package/composer/ComposerToolbar.d.ts +5 -1
  2. package/composer/ComposerToolbar.d.ts.map +1 -1
  3. package/composer/ComposerToolbar.js +6 -3
  4. package/composer/ComposerToolbar.js.map +1 -1
  5. package/composer/SessionComposer.d.ts +17 -1
  6. package/composer/SessionComposer.d.ts.map +1 -1
  7. package/composer/SessionComposer.js +10 -3
  8. package/composer/SessionComposer.js.map +1 -1
  9. package/execution/MessageEntry.d.ts +3 -1
  10. package/execution/MessageEntry.d.ts.map +1 -1
  11. package/execution/MessageEntry.js +30 -1
  12. package/execution/MessageEntry.js.map +1 -1
  13. package/index.d.ts +3 -3
  14. package/index.d.ts.map +1 -1
  15. package/index.js +2 -2
  16. package/index.js.map +1 -1
  17. package/models/HarnessSelector.d.ts +41 -0
  18. package/models/HarnessSelector.d.ts.map +1 -0
  19. package/models/HarnessSelector.js +74 -0
  20. package/models/HarnessSelector.js.map +1 -0
  21. package/models/ModelSelector.d.ts +26 -16
  22. package/models/ModelSelector.d.ts.map +1 -1
  23. package/models/ModelSelector.js +128 -48
  24. package/models/ModelSelector.js.map +1 -1
  25. package/models/__tests__/HarnessSelector.test.d.ts +2 -0
  26. package/models/__tests__/HarnessSelector.test.d.ts.map +1 -0
  27. package/models/__tests__/HarnessSelector.test.js +160 -0
  28. package/models/__tests__/HarnessSelector.test.js.map +1 -0
  29. package/models/__tests__/harness.test.d.ts +2 -0
  30. package/models/__tests__/harness.test.d.ts.map +1 -0
  31. package/models/__tests__/harness.test.js +50 -0
  32. package/models/__tests__/harness.test.js.map +1 -0
  33. package/models/__tests__/useModelRegistry.test.d.ts +2 -0
  34. package/models/__tests__/useModelRegistry.test.d.ts.map +1 -0
  35. package/models/__tests__/useModelRegistry.test.js +148 -0
  36. package/models/__tests__/useModelRegistry.test.js.map +1 -0
  37. package/models/harness.d.ts +21 -0
  38. package/models/harness.d.ts.map +1 -0
  39. package/models/harness.js +34 -0
  40. package/models/harness.js.map +1 -0
  41. package/models/index.d.ts +7 -2
  42. package/models/index.d.ts.map +1 -1
  43. package/models/index.js +3 -1
  44. package/models/index.js.map +1 -1
  45. package/models/registry.d.ts +53 -13
  46. package/models/registry.d.ts.map +1 -1
  47. package/models/registry.js +51 -40
  48. package/models/registry.js.map +1 -1
  49. package/models/useModelRegistry.d.ts +39 -19
  50. package/models/useModelRegistry.d.ts.map +1 -1
  51. package/models/useModelRegistry.js +45 -23
  52. package/models/useModelRegistry.js.map +1 -1
  53. package/package.json +4 -4
  54. package/runner/RunnerListPanel.js +2 -1
  55. package/runner/RunnerListPanel.js.map +1 -1
  56. package/runner/__tests__/phase.test.js +6 -2
  57. package/runner/__tests__/phase.test.js.map +1 -1
  58. package/runner/phase.d.ts +9 -7
  59. package/runner/phase.d.ts.map +1 -1
  60. package/runner/phase.js +18 -12
  61. package/runner/phase.js.map +1 -1
  62. package/session/__tests__/useCreateSession.test.d.ts +2 -0
  63. package/session/__tests__/useCreateSession.test.d.ts.map +1 -0
  64. package/session/__tests__/useCreateSession.test.js +232 -0
  65. package/session/__tests__/useCreateSession.test.js.map +1 -0
  66. package/session/__tests__/useNewSessionFlow.test.d.ts +2 -0
  67. package/session/__tests__/useNewSessionFlow.test.d.ts.map +1 -0
  68. package/session/__tests__/useNewSessionFlow.test.js +199 -0
  69. package/session/__tests__/useNewSessionFlow.test.js.map +1 -0
  70. package/session/__tests__/useSessionConversation.test.js +37 -0
  71. package/session/__tests__/useSessionConversation.test.js.map +1 -1
  72. package/session/index.d.ts +1 -1
  73. package/session/index.d.ts.map +1 -1
  74. package/session/useCreateSession.d.ts +8 -0
  75. package/session/useCreateSession.d.ts.map +1 -1
  76. package/session/useCreateSession.js +2 -0
  77. package/session/useCreateSession.js.map +1 -1
  78. package/session/useNewSessionFlow.d.ts +6 -1
  79. package/session/useNewSessionFlow.d.ts.map +1 -1
  80. package/session/useNewSessionFlow.js +34 -8
  81. package/session/useNewSessionFlow.js.map +1 -1
  82. package/session/usePersistedModel.d.ts +16 -1
  83. package/session/usePersistedModel.d.ts.map +1 -1
  84. package/session/usePersistedModel.js +15 -6
  85. package/session/usePersistedModel.js.map +1 -1
  86. package/session/useSessionConversation.d.ts.map +1 -1
  87. package/session/useSessionConversation.js +6 -1
  88. package/session/useSessionConversation.js.map +1 -1
  89. package/session/useSessionPageFlow.d.ts +11 -0
  90. package/session/useSessionPageFlow.d.ts.map +1 -1
  91. package/session/useSessionPageFlow.js +11 -2
  92. package/session/useSessionPageFlow.js.map +1 -1
  93. package/src/composer/ComposerToolbar.tsx +24 -1
  94. package/src/composer/SessionComposer.tsx +35 -1
  95. package/src/execution/MessageEntry.tsx +134 -1
  96. package/src/index.ts +15 -1
  97. package/src/models/HarnessSelector.tsx +130 -0
  98. package/src/models/ModelSelector.tsx +285 -81
  99. package/src/models/__tests__/HarnessSelector.test.tsx +190 -0
  100. package/src/models/__tests__/harness.test.ts +66 -0
  101. package/src/models/__tests__/useModelRegistry.test.tsx +209 -0
  102. package/src/models/harness.ts +45 -0
  103. package/src/models/index.ts +7 -2
  104. package/src/models/registry.ts +122 -50
  105. package/src/models/useModelRegistry.ts +74 -24
  106. package/src/runner/RunnerListPanel.tsx +13 -5
  107. package/src/runner/__tests__/phase.test.ts +6 -2
  108. package/src/runner/phase.ts +18 -12
  109. package/src/session/__tests__/useCreateSession.test.tsx +296 -0
  110. package/src/session/__tests__/useNewSessionFlow.test.tsx +258 -0
  111. package/src/session/__tests__/useSessionConversation.test.tsx +53 -0
  112. package/src/session/index.ts +1 -1
  113. package/src/session/useCreateSession.ts +9 -0
  114. package/src/session/useNewSessionFlow.ts +46 -9
  115. package/src/session/usePersistedModel.ts +30 -6
  116. package/src/session/useSessionConversation.ts +6 -1
  117. package/src/session/useSessionPageFlow.ts +26 -2
  118. package/styles.css +1 -1
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useRef } from "react";
4
+ import { HARNESS_LABELS } from "./harness";
5
+ const OPTIONS = ["native", "cursor"];
6
+ /**
7
+ * Compact segmented control for choosing the session execution engine.
8
+ *
9
+ * Renders two mutually exclusive options — "Stigmer" (native) and
10
+ * "Cursor" (premium) — as adjacent pill segments. The Cursor segment
11
+ * carries a subtle premium tier indicator.
12
+ *
13
+ * Built as a `radiogroup` with full arrow-key navigation and ARIA
14
+ * semantics. All visual properties flow through `--stgm-*` tokens.
15
+ *
16
+ * Platform builders who need different rendering use
17
+ * {@link HarnessOption} and {@link HARNESS_LABELS} directly.
18
+ *
19
+ * @deprecated Use {@link ModelSelector} in unified mode (without the
20
+ * `harness` prop) instead. The unified model picker embeds an engine
21
+ * tag on each model row, eliminating the need for a separate harness
22
+ * control. This component is kept for backward compatibility.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * function LauncherToolbar() {
27
+ * const [harness, setHarness] = useState<HarnessOption>("native");
28
+ *
29
+ * return <HarnessSelector value={harness} onValueChange={setHarness} />;
30
+ * }
31
+ * ```
32
+ */
33
+ export function HarnessSelector({ value, onValueChange, className, disabled, }) {
34
+ const groupRef = useRef(null);
35
+ const handleKeyDown = useCallback((e) => {
36
+ if (disabled)
37
+ return;
38
+ const idx = OPTIONS.indexOf(value);
39
+ let next;
40
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") {
41
+ next = (idx + 1) % OPTIONS.length;
42
+ }
43
+ else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
44
+ next = (idx - 1 + OPTIONS.length) % OPTIONS.length;
45
+ }
46
+ if (next !== undefined) {
47
+ e.preventDefault();
48
+ onValueChange(OPTIONS[next]);
49
+ const buttons = groupRef.current?.querySelectorAll("[role=radio]");
50
+ buttons?.[next]?.focus();
51
+ }
52
+ }, [value, onValueChange, disabled]);
53
+ return (_jsx("div", { ref: groupRef, role: "radiogroup", "aria-label": "Execution engine", onKeyDown: handleKeyDown, className: [
54
+ "inline-flex items-center rounded-md border border-border bg-background p-0.5",
55
+ disabled ? "pointer-events-none opacity-50" : undefined,
56
+ className,
57
+ ]
58
+ .filter(Boolean)
59
+ .join(" "), children: OPTIONS.map((option) => {
60
+ const isActive = value === option;
61
+ return (_jsxs("button", { type: "button", role: "radio", "aria-checked": isActive, "aria-label": HARNESS_LABELS[option], tabIndex: isActive ? 0 : -1, disabled: disabled, onClick: () => {
62
+ if (!isActive)
63
+ onValueChange(option);
64
+ }, className: [
65
+ "inline-flex items-center gap-1 rounded-[5px] px-2 py-1 text-xs transition-colors",
66
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
67
+ "disabled:pointer-events-none",
68
+ isActive
69
+ ? "bg-accent font-medium text-foreground shadow-sm"
70
+ : "text-muted-foreground hover:text-foreground",
71
+ ].join(" "), children: [HARNESS_LABELS[option], option === "cursor" && (_jsx("span", { "aria-label": "premium", className: "text-[0.6rem] text-muted-foreground", children: "$$$" }))] }, option));
72
+ }) }));
73
+ }
74
+ //# sourceMappingURL=HarnessSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HarnessSelector.js","sourceRoot":"","sources":["../../src/models/HarnessSelector.tsx"],"names":[],"mappings":"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"}
@@ -1,35 +1,45 @@
1
+ import { type HarnessOption } from "./harness";
1
2
  /** Props for {@link ModelSelector}. */
2
3
  export interface ModelSelectorProps {
3
- /** Currently selected model ID. Falls back to {@link DEFAULT_MODEL_ID} when omitted. */
4
+ /** Currently selected compound key (`"native/claude-sonnet-4.6"`) or plain `modelId`. */
4
5
  readonly value?: string;
5
- /** Called when the user picks a different model. Receives the new `modelId`. */
6
+ /** Called when the user picks a different model. Receives the `modelId`. */
6
7
  readonly onValueChange: (modelId: string) => void;
8
+ /**
9
+ * When provided, restricts the catalog to a single harness (backward compat).
10
+ * When omitted, shows the unified picker with models from both engines.
11
+ */
12
+ readonly harness?: HarnessOption;
13
+ /**
14
+ * Fires when the selected model belongs to a different harness than
15
+ * the previous selection. Only relevant in unified mode (no `harness` prop).
16
+ */
17
+ readonly onHarnessResolved?: (harness: HarnessOption) => void;
7
18
  /** Additional CSS class names for the trigger button. */
8
19
  readonly className?: string;
9
20
  /** When true, disables the selector. */
10
21
  readonly disabled?: boolean;
11
22
  }
12
23
  /**
13
- * Theme-able model picker built on `@base-ui/react` Select for
14
- * accessible keyboard navigation and ARIA.
24
+ * Cursor-style model picker: a flat searchable list inside a popover.
15
25
  *
16
- * Consumes {@link useModelRegistry} internally. Groups models by
17
- * provider and shows a subtle cost-tier indicator.
26
+ * Shows a curated list of featured models by default. The user can
27
+ * expand via "Show All Models" or type to search the full catalog.
18
28
  *
19
- * All visual properties flow through `--stgm-*` tokens no
20
- * hardcoded colors or sizes.
29
+ * Each model row shows the display name, an engine tag
30
+ * ("Stigmer" / "Cursor"), and a cost-tier indicator.
21
31
  *
22
- * Platform builders who need different rendering use
23
- * `useModelRegistry()` directly.
32
+ * In unified mode (no `harness` prop), selecting a model implicitly
33
+ * resolves the harness via {@link ModelSelectorProps.onHarnessResolved}.
24
34
  *
25
35
  * @example
26
36
  * ```tsx
27
- * function ComposerHeader() {
28
- * const [modelId, setModelId] = useState<string>();
29
- *
30
- * return <ModelSelector value={modelId} onValueChange={setModelId} />;
31
- * }
37
+ * <ModelSelector
38
+ * value={selectedModelId}
39
+ * onValueChange={setSelectedModelId}
40
+ * onHarnessResolved={setHarness}
41
+ * />
32
42
  * ```
33
43
  */
34
- export declare function ModelSelector({ value, onValueChange, className, disabled, }: ModelSelectorProps): import("react/jsx-runtime").JSX.Element;
44
+ export declare function ModelSelector({ value, onValueChange, harness, onHarnessResolved, className, disabled, }: ModelSelectorProps): import("react/jsx-runtime").JSX.Element;
35
45
  //# sourceMappingURL=ModelSelector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ModelSelector.d.ts","sourceRoot":"","sources":["../../src/models/ModelSelector.tsx"],"names":[],"mappings":"AAkBA,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,yDAAyD;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,aAAa,EACb,SAAS,EACT,QAAQ,GACT,EAAE,kBAAkB,2CAsEpB"}
1
+ {"version":3,"file":"ModelSelector.d.ts","sourceRoot":"","sources":["../../src/models/ModelSelector.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAQ/D,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC9D,yDAAyD;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,aAAa,EACb,OAAO,EACP,iBAAiB,EACjB,SAAS,EACT,QAAQ,GACT,EAAE,kBAAkB,2CAuPpB"}
@@ -1,68 +1,148 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Select } from "@base-ui/react/select";
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ import { Popover } from "@base-ui/react/popover";
5
+ import { cn } from "@stigmer/theme";
4
6
  import { useModelRegistry } from "./useModelRegistry";
5
- const PROVIDER_LABELS = {
6
- anthropic: "Anthropic",
7
- openai: "OpenAI",
8
- ollama: "Ollama",
9
- };
10
- const COST_TIER_INDICATOR = {
7
+ import { modelKey } from "./registry";
8
+ import { HARNESS_LABELS } from "./harness";
9
+ const COST_TIER_LABEL = {
11
10
  economy: "$",
12
11
  standard: "$$",
13
12
  premium: "$$$",
14
13
  };
15
14
  /**
16
- * Theme-able model picker built on `@base-ui/react` Select for
17
- * accessible keyboard navigation and ARIA.
15
+ * Cursor-style model picker: a flat searchable list inside a popover.
18
16
  *
19
- * Consumes {@link useModelRegistry} internally. Groups models by
20
- * provider and shows a subtle cost-tier indicator.
17
+ * Shows a curated list of featured models by default. The user can
18
+ * expand via "Show All Models" or type to search the full catalog.
21
19
  *
22
- * All visual properties flow through `--stgm-*` tokens no
23
- * hardcoded colors or sizes.
20
+ * Each model row shows the display name, an engine tag
21
+ * ("Stigmer" / "Cursor"), and a cost-tier indicator.
24
22
  *
25
- * Platform builders who need different rendering use
26
- * `useModelRegistry()` directly.
23
+ * In unified mode (no `harness` prop), selecting a model implicitly
24
+ * resolves the harness via {@link ModelSelectorProps.onHarnessResolved}.
27
25
  *
28
26
  * @example
29
27
  * ```tsx
30
- * function ComposerHeader() {
31
- * const [modelId, setModelId] = useState<string>();
32
- *
33
- * return <ModelSelector value={modelId} onValueChange={setModelId} />;
34
- * }
28
+ * <ModelSelector
29
+ * value={selectedModelId}
30
+ * onValueChange={setSelectedModelId}
31
+ * onHarnessResolved={setHarness}
32
+ * />
35
33
  * ```
36
34
  */
37
- export function ModelSelector({ value, onValueChange, className, disabled, }) {
38
- const { byProvider, defaultModel, providers } = useModelRegistry();
39
- return (_jsxs(Select.Root, { value: value ?? defaultModel.modelId, onValueChange: (v) => { if (v !== null)
40
- onValueChange(v); }, disabled: disabled, children: [_jsxs(Select.Trigger, { className: [
41
- "inline-flex items-center gap-1.5 rounded-md border border-border",
42
- "bg-background px-2.5 py-1.5 text-xs text-foreground",
43
- "hover:bg-accent-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
44
- "disabled:pointer-events-none disabled:opacity-50",
45
- "transition-colors max-w-[14rem] max-sm:max-w-[8rem]",
46
- className,
47
- ]
48
- .filter(Boolean)
49
- .join(" "), children: [_jsx(Select.Value, { placeholder: "Select model", className: "truncate" }), _jsx(Select.Icon, { className: "text-muted-foreground", children: _jsx(ChevronIcon, {}) })] }), _jsx(Select.Portal, { children: _jsx(Select.Positioner, { sideOffset: 4, children: _jsx(Select.Popup, { className: [
50
- "z-popover max-h-72 min-w-[var(--anchor-width)] overflow-auto",
51
- "rounded-lg border border-border bg-popover p-1 shadow-md",
52
- "text-popover-foreground",
53
- ].join(" "), children: providers.map((provider) => {
54
- const models = byProvider.get(provider);
55
- if (!models?.length)
56
- return null;
57
- return (_jsxs(Select.Group, { children: [_jsx(Select.GroupLabel, { className: "px-2 py-1.5 text-[0.65rem] font-medium uppercase tracking-wider text-muted-foreground", children: PROVIDER_LABELS[provider] }), models.map((model) => (_jsxs(Select.Item, { value: model.modelId, className: [
58
- "flex cursor-pointer items-center justify-between gap-2",
59
- "rounded-md px-2 py-1.5 text-xs outline-none",
60
- "data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground",
61
- "data-[selected]:font-medium",
62
- ].join(" "), children: [_jsx(Select.ItemText, { children: model.displayName }), _jsx("span", { className: "text-[0.6rem] text-muted-foreground", children: COST_TIER_INDICATOR[model.costTier] })] }, model.modelId)))] }, provider));
63
- }) }) }) })] }));
35
+ export function ModelSelector({ value, onValueChange, harness, onHarnessResolved, className, disabled, }) {
36
+ const isUnified = harness === undefined;
37
+ const { models, featured, defaultModel, getModel, getByKey } = useModelRegistry(isUnified ? undefined : { harness });
38
+ const [open, setOpen] = useState(false);
39
+ const [searchQuery, setSearchQuery] = useState("");
40
+ const [showAll, setShowAll] = useState(false);
41
+ const [highlightIdx, setHighlightIdx] = useState(-1);
42
+ const searchRef = useRef(null);
43
+ const listRef = useRef(null);
44
+ const resolveSelected = useCallback(() => {
45
+ if (!value)
46
+ return undefined;
47
+ if (isUnified) {
48
+ const byKey = getByKey(value);
49
+ if (byKey)
50
+ return byKey;
51
+ }
52
+ return getModel(value);
53
+ }, [value, isUnified, getByKey, getModel]);
54
+ const selectedModel = resolveSelected() ?? defaultModel;
55
+ const isSearching = searchQuery.length > 0;
56
+ const lowerQuery = searchQuery.toLowerCase();
57
+ const visibleModels = useMemo(() => {
58
+ if (isSearching) {
59
+ return models.filter((m) => m.displayName.toLowerCase().includes(lowerQuery)
60
+ || m.modelId.toLowerCase().includes(lowerQuery)
61
+ || HARNESS_LABELS[m.harness].toLowerCase().includes(lowerQuery));
62
+ }
63
+ if (showAll)
64
+ return models;
65
+ return featured.length > 0 ? featured : models;
66
+ }, [models, featured, isSearching, showAll, lowerQuery]);
67
+ useEffect(() => {
68
+ setHighlightIdx(-1);
69
+ }, [visibleModels]);
70
+ useEffect(() => {
71
+ if (!open) {
72
+ setSearchQuery("");
73
+ setShowAll(false);
74
+ setHighlightIdx(-1);
75
+ }
76
+ }, [open]);
77
+ useEffect(() => {
78
+ if (open) {
79
+ requestAnimationFrame(() => searchRef.current?.focus());
80
+ }
81
+ }, [open]);
82
+ const selectModel = useCallback((model) => {
83
+ const key = isUnified ? modelKey(model.harness, model.modelId) : model.modelId;
84
+ onValueChange(key);
85
+ if (isUnified && onHarnessResolved && model.harness !== selectedModel?.harness) {
86
+ onHarnessResolved(model.harness);
87
+ }
88
+ setOpen(false);
89
+ }, [isUnified, onValueChange, onHarnessResolved, selectedModel]);
90
+ const scrollHighlightIntoView = useCallback((idx) => {
91
+ const container = listRef.current;
92
+ if (!container)
93
+ return;
94
+ const items = container.querySelectorAll("[data-model-option]");
95
+ items[idx]?.scrollIntoView({ block: "nearest" });
96
+ }, []);
97
+ const handleKeyDown = useCallback((e) => {
98
+ const len = visibleModels.length;
99
+ if (len === 0)
100
+ return;
101
+ switch (e.key) {
102
+ case "ArrowDown": {
103
+ e.preventDefault();
104
+ const next = highlightIdx < len - 1 ? highlightIdx + 1 : 0;
105
+ setHighlightIdx(next);
106
+ scrollHighlightIntoView(next);
107
+ break;
108
+ }
109
+ case "ArrowUp": {
110
+ e.preventDefault();
111
+ const prev = highlightIdx > 0 ? highlightIdx - 1 : len - 1;
112
+ setHighlightIdx(prev);
113
+ scrollHighlightIntoView(prev);
114
+ break;
115
+ }
116
+ case "Enter": {
117
+ e.preventDefault();
118
+ const target = highlightIdx >= 0 ? visibleModels[highlightIdx] : visibleModels[0];
119
+ if (target)
120
+ selectModel(target);
121
+ break;
122
+ }
123
+ case "Escape":
124
+ e.preventDefault();
125
+ setOpen(false);
126
+ break;
127
+ }
128
+ }, [visibleModels, highlightIdx, selectModel, scrollHighlightIntoView]);
129
+ const showShowAllButton = !isSearching && !showAll && featured.length > 0 && featured.length < models.length;
130
+ const triggerLabel = selectedModel.displayName;
131
+ const triggerHarness = isUnified ? HARNESS_LABELS[selectedModel.harness] : undefined;
132
+ const triggerCost = COST_TIER_LABEL[selectedModel.costTier];
133
+ return (_jsxs(Popover.Root, { open: open, onOpenChange: setOpen, children: [_jsxs(Popover.Trigger, { disabled: disabled, className: cn("inline-flex items-center gap-1.5 rounded-md border border-border", "bg-background px-2.5 py-1.5 text-xs text-foreground", "hover:bg-accent-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50", "transition-colors max-w-[18rem] max-sm:max-w-[10rem]", className), children: [_jsx("span", { className: "truncate", children: triggerLabel }), triggerHarness && (_jsx("span", { className: "shrink-0 rounded bg-muted px-1 py-0.5 text-[0.6rem] font-medium text-muted-foreground", children: triggerHarness })), _jsx("span", { className: "shrink-0 text-[0.6rem] text-muted-foreground", children: triggerCost }), _jsx(ChevronIcon, {})] }), _jsx(Popover.Portal, { children: _jsx(Popover.Positioner, { sideOffset: 4, children: _jsxs(Popover.Popup, { role: "dialog", "aria-label": "Model selector", className: cn("z-popover w-72 rounded-lg border border-border bg-popover shadow-md", "text-popover-foreground"), children: [_jsx("div", { className: "border-b border-border px-2 py-1.5", children: _jsx("input", { ref: searchRef, role: "searchbox", "aria-label": "Search models", placeholder: "Search models\u2026", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: handleKeyDown, className: cn("w-full bg-transparent text-xs text-foreground placeholder:text-muted-foreground", "outline-none") }) }), _jsxs("div", { ref: listRef, role: "listbox", "aria-label": "Available models", className: "max-h-64 overflow-y-auto p-1", children: [visibleModels.length === 0 && (_jsx("div", { className: "px-2 py-3 text-center text-xs text-muted-foreground", children: "No models found" })), visibleModels.map((model, idx) => {
134
+ const key = modelKey(model.harness, model.modelId);
135
+ const isSelected = selectedModel
136
+ ? model.harness === selectedModel.harness && model.modelId === selectedModel.modelId
137
+ : false;
138
+ const isHighlighted = idx === highlightIdx;
139
+ return (_jsxs("button", { "data-model-option": "", role: "option", "aria-selected": isSelected, type: "button", className: cn("flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-xs outline-none", "transition-colors", isHighlighted && "bg-accent text-accent-foreground", !isHighlighted && "hover:bg-accent-hover", isSelected && "font-medium"), onClick: () => selectModel(model), onMouseEnter: () => setHighlightIdx(idx), children: [_jsx("span", { className: "flex-1 truncate text-left", children: model.displayName }), isUnified && (_jsx("span", { className: "shrink-0 rounded bg-muted px-1 py-0.5 text-[0.55rem] font-medium text-muted-foreground", children: HARNESS_LABELS[model.harness] })), _jsx("span", { className: "shrink-0 text-[0.6rem] text-muted-foreground", children: COST_TIER_LABEL[model.costTier] }), isSelected && (_jsx(CheckIcon, { className: "shrink-0 text-primary" }))] }, key));
140
+ }), showShowAllButton && (_jsx("button", { type: "button", className: cn("mt-1 flex w-full items-center justify-center rounded-md border border-dashed border-border", "px-2 py-1.5 text-xs text-muted-foreground", "hover:bg-accent-hover hover:text-foreground transition-colors cursor-pointer"), onClick: () => setShowAll(true), children: "Show All Models" }))] })] }) }) })] }));
64
141
  }
65
142
  function ChevronIcon() {
66
- return (_jsx("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M2.5 3.75L5 6.25L7.5 3.75" }) }));
143
+ return (_jsx("svg", { className: "shrink-0 text-muted-foreground", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M2.5 3.75L5 6.25L7.5 3.75" }) }));
144
+ }
145
+ function CheckIcon({ className }) {
146
+ return (_jsx("svg", { className: className, width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M2 6L5 9L10 3" }) }));
67
147
  }
68
148
  //# sourceMappingURL=ModelSelector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ModelSelector.js","sourceRoot":"","sources":["../../src/models/ModelSelector.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ModelSelector.js","sourceRoot":"","sources":["../../src/models/ModelSelector.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=HarnessSelector.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HarnessSelector.test.d.ts","sourceRoot":"","sources":["../../../src/models/__tests__/HarnessSelector.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,160 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { describe, it, expect, vi, afterEach } from "vitest";
3
+ import { render, screen, fireEvent, cleanup } from "@testing-library/react";
4
+ import { HarnessSelector } from "../HarnessSelector";
5
+ function renderSelector(overrides = {}) {
6
+ const onValueChange = overrides.onValueChange ?? vi.fn();
7
+ const result = render(_jsx(HarnessSelector, { value: overrides.value ?? "native", onValueChange: onValueChange, disabled: overrides.disabled, className: overrides.className }));
8
+ return { ...result, onValueChange };
9
+ }
10
+ afterEach(cleanup);
11
+ describe("HarnessSelector", () => {
12
+ describe("ARIA structure", () => {
13
+ it("renders a radiogroup with correct aria-label", () => {
14
+ renderSelector();
15
+ const group = screen.getByRole("radiogroup", { name: "Execution engine" });
16
+ expect(group).toBeDefined();
17
+ });
18
+ it("renders exactly two radio buttons", () => {
19
+ renderSelector();
20
+ const radios = screen.getAllByRole("radio");
21
+ expect(radios).toHaveLength(2);
22
+ });
23
+ it("labels radio buttons with user-facing harness names", () => {
24
+ renderSelector();
25
+ expect(screen.getByRole("radio", { name: "Stigmer" })).toBeDefined();
26
+ expect(screen.getByRole("radio", { name: "Cursor" })).toBeDefined();
27
+ });
28
+ });
29
+ describe("checked state", () => {
30
+ it("marks native as checked when value is native", () => {
31
+ renderSelector({ value: "native" });
32
+ const native = screen.getByRole("radio", { name: "Stigmer" });
33
+ const cursor = screen.getByRole("radio", { name: "Cursor" });
34
+ expect(native.getAttribute("aria-checked")).toBe("true");
35
+ expect(cursor.getAttribute("aria-checked")).toBe("false");
36
+ });
37
+ it("marks cursor as checked when value is cursor", () => {
38
+ renderSelector({ value: "cursor" });
39
+ const native = screen.getByRole("radio", { name: "Stigmer" });
40
+ const cursor = screen.getByRole("radio", { name: "Cursor" });
41
+ expect(native.getAttribute("aria-checked")).toBe("false");
42
+ expect(cursor.getAttribute("aria-checked")).toBe("true");
43
+ });
44
+ });
45
+ describe("roving tabIndex", () => {
46
+ it("sets tabIndex 0 on the active option and -1 on inactive", () => {
47
+ renderSelector({ value: "native" });
48
+ const native = screen.getByRole("radio", { name: "Stigmer" });
49
+ const cursor = screen.getByRole("radio", { name: "Cursor" });
50
+ expect(native.tabIndex).toBe(0);
51
+ expect(cursor.tabIndex).toBe(-1);
52
+ });
53
+ it("reverses tabIndex when cursor is active", () => {
54
+ renderSelector({ value: "cursor" });
55
+ const native = screen.getByRole("radio", { name: "Stigmer" });
56
+ const cursor = screen.getByRole("radio", { name: "Cursor" });
57
+ expect(native.tabIndex).toBe(-1);
58
+ expect(cursor.tabIndex).toBe(0);
59
+ });
60
+ });
61
+ describe("click interaction", () => {
62
+ it("fires onValueChange when clicking an inactive option", () => {
63
+ const { onValueChange } = renderSelector({ value: "native" });
64
+ fireEvent.click(screen.getByRole("radio", { name: "Cursor" }));
65
+ expect(onValueChange).toHaveBeenCalledWith("cursor");
66
+ });
67
+ it("does not fire onValueChange when clicking the active option", () => {
68
+ const { onValueChange } = renderSelector({ value: "native" });
69
+ fireEvent.click(screen.getByRole("radio", { name: "Stigmer" }));
70
+ expect(onValueChange).not.toHaveBeenCalled();
71
+ });
72
+ });
73
+ describe("keyboard navigation", () => {
74
+ it("ArrowRight from native selects cursor", () => {
75
+ const { onValueChange } = renderSelector({ value: "native" });
76
+ const group = screen.getByRole("radiogroup");
77
+ fireEvent.keyDown(group, { key: "ArrowRight" });
78
+ expect(onValueChange).toHaveBeenCalledWith("cursor");
79
+ });
80
+ it("ArrowLeft from native wraps to cursor", () => {
81
+ const { onValueChange } = renderSelector({ value: "native" });
82
+ const group = screen.getByRole("radiogroup");
83
+ fireEvent.keyDown(group, { key: "ArrowLeft" });
84
+ expect(onValueChange).toHaveBeenCalledWith("cursor");
85
+ });
86
+ it("ArrowRight from cursor wraps to native", () => {
87
+ const { onValueChange } = renderSelector({ value: "cursor" });
88
+ const group = screen.getByRole("radiogroup");
89
+ fireEvent.keyDown(group, { key: "ArrowRight" });
90
+ expect(onValueChange).toHaveBeenCalledWith("native");
91
+ });
92
+ it("ArrowDown behaves the same as ArrowRight", () => {
93
+ const { onValueChange } = renderSelector({ value: "native" });
94
+ const group = screen.getByRole("radiogroup");
95
+ fireEvent.keyDown(group, { key: "ArrowDown" });
96
+ expect(onValueChange).toHaveBeenCalledWith("cursor");
97
+ });
98
+ it("ArrowUp behaves the same as ArrowLeft", () => {
99
+ const { onValueChange } = renderSelector({ value: "cursor" });
100
+ const group = screen.getByRole("radiogroup");
101
+ fireEvent.keyDown(group, { key: "ArrowUp" });
102
+ expect(onValueChange).toHaveBeenCalledWith("native");
103
+ });
104
+ it("ignores non-arrow keys", () => {
105
+ const { onValueChange } = renderSelector({ value: "native" });
106
+ const group = screen.getByRole("radiogroup");
107
+ fireEvent.keyDown(group, { key: "Enter" });
108
+ fireEvent.keyDown(group, { key: " " });
109
+ fireEvent.keyDown(group, { key: "Tab" });
110
+ expect(onValueChange).not.toHaveBeenCalled();
111
+ });
112
+ });
113
+ describe("disabled state", () => {
114
+ it("does not fire onValueChange on click when disabled", () => {
115
+ const { onValueChange } = renderSelector({
116
+ value: "native",
117
+ disabled: true,
118
+ });
119
+ fireEvent.click(screen.getByRole("radio", { name: "Cursor" }));
120
+ expect(onValueChange).not.toHaveBeenCalled();
121
+ });
122
+ it("does not fire onValueChange on keyboard when disabled", () => {
123
+ const { onValueChange } = renderSelector({
124
+ value: "native",
125
+ disabled: true,
126
+ });
127
+ const group = screen.getByRole("radiogroup");
128
+ fireEvent.keyDown(group, { key: "ArrowRight" });
129
+ expect(onValueChange).not.toHaveBeenCalled();
130
+ });
131
+ it("marks both radio buttons as disabled", () => {
132
+ renderSelector({ disabled: true });
133
+ const radios = screen.getAllByRole("radio");
134
+ for (const radio of radios) {
135
+ expect(radio.disabled).toBe(true);
136
+ }
137
+ });
138
+ });
139
+ describe("premium indicator", () => {
140
+ it("shows premium indicator on the cursor option", () => {
141
+ renderSelector({ value: "native" });
142
+ const premiumBadge = screen.getByLabelText("premium");
143
+ expect(premiumBadge).toBeDefined();
144
+ expect(premiumBadge.textContent).toBe("$$$");
145
+ });
146
+ it("does not show premium indicator on the native option", () => {
147
+ renderSelector({ value: "native" });
148
+ const premiumBadges = screen.getAllByLabelText("premium");
149
+ expect(premiumBadges).toHaveLength(1);
150
+ });
151
+ });
152
+ describe("className passthrough", () => {
153
+ it("appends custom className to the root container", () => {
154
+ renderSelector({ className: "my-custom-class" });
155
+ const group = screen.getByRole("radiogroup");
156
+ expect(group.className).toContain("my-custom-class");
157
+ });
158
+ });
159
+ });
160
+ //# sourceMappingURL=HarnessSelector.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HarnessSelector.test.js","sourceRoot":"","sources":["../../../src/models/__tests__/HarnessSelector.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=harness.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.test.d.ts","sourceRoot":"","sources":["../../../src/models/__tests__/harness.test.ts"],"names":[],"mappings":""}