@steerable/agent-ui 0.6.5 → 0.6.6

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.
@@ -139,6 +139,9 @@ export interface ChatPanelConnectedProps {
139
139
  emptyTitle?: string;
140
140
  emptyDescription?: string;
141
141
  inputPlaceholder?: string;
142
+ /** Extra controls rendered in the input toolbar (e.g. `ModelSelector`). */
143
+ inputToolbarLeft?: React.ReactNode;
144
+ inputToolbarRight?: React.ReactNode;
142
145
  renderMessage?: (props: MessageRendererProps) => React.ReactNode;
143
146
  renderToolCall?: (call: ToolCall, result?: ToolResult) => React.ReactNode;
144
147
  /** Apply the panel's own background/foreground tokens (default). */
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../src/components/ChatPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../src/components/ChatPanel.tsx"],"names":[],"mappings":"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"}
@@ -175,14 +175,14 @@ function ChatPanelMonolith(props) {
175
175
  return (_jsxs(ChatPanelRoot, { className: className, children: [header ? _jsx(ChatPanelHeader, { children: header }) : null, _jsx(ChatPanelMessages, { messages: messages, isStreaming: isStreaming, renderMessage: renderMessage, renderToolCall: renderToolCall, emptyState: emptyState }), _jsx(ChatPanelInput, { value: draft, onChange: setDraft, onSubmit: handleSubmit, onCancel: onCancel, isStreaming: isStreaming, disabled: disabled, placeholder: inputPlaceholder, keyMode: "enter" })] }));
176
176
  }
177
177
  function ChatPanelConnected(props) {
178
- const { className, header, emptyPrompts, emptyTitle, emptyDescription, inputPlaceholder, renderMessage, renderToolCall, styled = true, } = props;
178
+ const { className, header, emptyPrompts, emptyTitle, emptyDescription, inputPlaceholder, inputToolbarLeft, inputToolbarRight, renderMessage, renderToolCall, styled = true, } = props;
179
179
  const session = useChatSessionContext();
180
180
  const { composer } = session;
181
181
  const emptyState = emptyPrompts || emptyTitle || emptyDescription ? (_jsx(ChatPanelEmpty, { prompts: emptyPrompts, title: emptyTitle, description: emptyDescription, onSelectPrompt: (text) => {
182
182
  composer.setValue(text);
183
183
  void composer.submit();
184
184
  } })) : undefined;
185
- return (_jsxs(ChatPanelRoot, { className: className, unstyled: !styled, children: [header ? _jsx(ChatPanelHeader, { children: header }) : null, _jsx(ChatPanelMessages, { messages: session.messages, isStreaming: session.isStreaming, renderMessage: renderMessage, renderToolCall: renderToolCall, emptyState: emptyState }), _jsx(ChatPanelInput, { value: composer.value, onChange: composer.setValue, onSubmit: composer.submit, onCancel: composer.cancel, isStreaming: session.isStreaming, placeholder: inputPlaceholder })] }));
185
+ return (_jsxs(ChatPanelRoot, { className: className, unstyled: !styled, children: [header ? _jsx(ChatPanelHeader, { children: header }) : null, _jsx(ChatPanelMessages, { messages: session.messages, isStreaming: session.isStreaming, renderMessage: renderMessage, renderToolCall: renderToolCall, emptyState: emptyState }), _jsx(ChatPanelInput, { value: composer.value, onChange: composer.setValue, onSubmit: composer.submit, onCancel: composer.cancel, isStreaming: session.isStreaming, placeholder: inputPlaceholder, toolbarLeft: inputToolbarLeft, toolbarRight: inputToolbarRight })] }));
186
186
  }
187
187
  // `ChatPanel` is the monolith (backwards-compat); the compound parts hang
188
188
  // off it as named attributes. This mirrors Radix's pattern so consumers can
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPanel.js","sourceRoot":"","sources":["../../src/components/ChatPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatPanel.js","sourceRoot":"","sources":["../../src/components/ChatPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * `ModelSelector` — model + reasoning-effort picker backed by the gateway's
3
+ * live catalog.
4
+ *
5
+ * The sidecar's `models.list` RPC answers the ids the gateway actually
6
+ * accepts, each joined with catalog capabilities (window, modalities,
7
+ * reasoning levels, pricing). The catalog is discovery, not a routing
8
+ * whitelist: the current model stays selectable even when unlisted, and the
9
+ * offline state degrades to a badge instead of blocking the composer.
10
+ *
11
+ * Stability contract (same as `useAgentSession`): `transport` is held by ref
12
+ * and the listing refetches only when `baseUrl` changes — call the returned
13
+ * refresh path by remounting or changing `baseUrl` if the transport swapped.
14
+ */
15
+ export interface ModelCatalogEntry {
16
+ id: string;
17
+ name: string;
18
+ /** Context window in tokens; null when neither gateway nor catalog knows. */
19
+ window: number | null;
20
+ modalities: string[];
21
+ /** Supported reasoning-effort levels, canonical order; empty = no knob. */
22
+ reasoningLevels: string[];
23
+ pricing: {
24
+ promptPerMtok: number | null;
25
+ completionPerMtok: number | null;
26
+ } | null;
27
+ /** Catalog key that supplied capability fields; null = capabilities unknown. */
28
+ joinedFrom: string | null;
29
+ capabilities: 'known' | 'unknown';
30
+ }
31
+ export interface ModelCatalogResponse {
32
+ models: ModelCatalogEntry[];
33
+ catalogStatus: 'live' | 'stale' | 'offline';
34
+ /** Epoch seconds of the successful fetch the listing came from. */
35
+ fetchedAt?: number;
36
+ /** Present when catalogStatus is 'offline'. */
37
+ error?: string;
38
+ current?: {
39
+ model: string | null;
40
+ reasoningEffort: string | null;
41
+ };
42
+ }
43
+ export interface ModelCatalogTransport {
44
+ listModels: (params?: {
45
+ baseUrl?: string;
46
+ }) => Promise<ModelCatalogResponse>;
47
+ }
48
+ export interface ModelSelectorProps {
49
+ transport: ModelCatalogTransport;
50
+ /** Gateway base URL the sidecar queries; omit to use the sidecar's env. */
51
+ baseUrl?: string;
52
+ /** Currently selected model id (controlled). */
53
+ model: string;
54
+ /** Currently selected reasoning effort; null/undefined = no explicit request. */
55
+ reasoningEffort?: string | null;
56
+ onSelectModel: (id: string) => void;
57
+ onSelectEffort?: (effort: string | null) => void;
58
+ disabled?: boolean;
59
+ className?: string;
60
+ }
61
+ export declare function ModelSelector(props: ModelSelectorProps): import("react/jsx-runtime").JSX.Element;
62
+ //# sourceMappingURL=ModelSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelSelector.d.ts","sourceRoot":"","sources":["../../src/components/ModelSelector.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2EAA2E;IAC3E,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACnF,gFAAgF;IAChF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,OAAO,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5C,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACpE;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC9E;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,qBAAqB,CAAC;IACjC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CAiJtD"}
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
+ import { cn } from './cn.js';
4
+ const selectClass = 'h-7 max-w-[180px] rounded-agent-md border border-agent-border bg-agent-canvas px-2 text-xs text-agent-foreground outline-none transition-colors hover:bg-agent-muted disabled:cursor-not-allowed disabled:opacity-50';
5
+ export function ModelSelector(props) {
6
+ const { transport, baseUrl, model, reasoningEffort, onSelectModel, onSelectEffort, disabled = false, className, } = props;
7
+ const transportRef = useRef(transport);
8
+ transportRef.current = transport;
9
+ const [catalog, setCatalog] = useState(null);
10
+ const [loading, setLoading] = useState(true);
11
+ useEffect(() => {
12
+ let cancelled = false;
13
+ setLoading(true);
14
+ transportRef.current
15
+ .listModels(baseUrl ? { baseUrl } : undefined)
16
+ .then((response) => {
17
+ if (!cancelled)
18
+ setCatalog(response);
19
+ })
20
+ .catch(() => {
21
+ // A transport-level failure (sidecar gone, RPC error) degrades to the
22
+ // same offline state the sidecar itself reports for an unreachable
23
+ // gateway — the composer stays usable.
24
+ if (!cancelled) {
25
+ setCatalog({ models: [], catalogStatus: 'offline' });
26
+ }
27
+ })
28
+ .finally(() => {
29
+ if (!cancelled)
30
+ setLoading(false);
31
+ });
32
+ return () => {
33
+ cancelled = true;
34
+ };
35
+ }, [baseUrl]);
36
+ const entries = useMemo(() => {
37
+ const list = catalog?.models ?? [];
38
+ // Discovery, not a whitelist: the active model stays selectable even
39
+ // when the gateway listing does not contain it (catalog offline, or an
40
+ // id the gateway accepts but does not advertise).
41
+ if (model && !list.some((entry) => entry.id === model)) {
42
+ return [
43
+ {
44
+ id: model,
45
+ name: model,
46
+ window: null,
47
+ modalities: [],
48
+ reasoningLevels: [],
49
+ pricing: null,
50
+ joinedFrom: null,
51
+ capabilities: 'unknown',
52
+ },
53
+ ...list,
54
+ ];
55
+ }
56
+ return list;
57
+ }, [catalog, model]);
58
+ const selected = entries.find((entry) => entry.id === model);
59
+ if (loading) {
60
+ return (_jsx("div", { className: cn('inline-flex h-7 items-center rounded-agent-md border border-agent-border bg-agent-canvas px-2 text-xs text-agent-muted-foreground', className), "aria-live": "polite", children: "Loading models\u2026" }));
61
+ }
62
+ const offline = catalog?.catalogStatus === 'offline';
63
+ return (_jsxs("div", { className: cn('inline-flex items-center gap-1.5', className), "data-catalog-status": catalog?.catalogStatus ?? 'unknown', children: [_jsxs("select", { "aria-label": "Model", className: cn(selectClass, 'min-w-[8rem]'), value: model, disabled: disabled || offline, onChange: (event) => onSelectModel(event.target.value), title: offline
64
+ ? `Model catalog unavailable — using the configured model. ${catalog?.error ?? ''}`
65
+ : selected
66
+ ? `${selected.name}${selected.window ? ` — ${Math.round(selected.window / 1024)}k window` : ''}${selected.capabilities === 'unknown' ? ' — capabilities unknown' : ''}`
67
+ : model, children: [entries.map((entry) => (_jsxs("option", { value: entry.id, children: [entry.id, entry.capabilities === 'unknown' ? ' (?)' : ''] }, entry.id))), entries.length === 0 && model ? _jsx("option", { value: model, children: model }) : null] }), selected && selected.reasoningLevels.length > 0 && onSelectEffort ? (_jsxs("select", { "aria-label": "Reasoning effort", className: selectClass, value: reasoningEffort ?? '', disabled: disabled, onChange: (event) => onSelectEffort(event.target.value || null), title: "Reasoning effort \u2014 an unsupported level is rejected by the sidecar, never silently dropped", children: [_jsx("option", { value: "", children: "default" }), selected.reasoningLevels.map((level) => (_jsx("option", { value: level, children: level }, level)))] })) : null, offline ? (_jsx("span", { className: "inline-flex items-center rounded-agent-md border border-agent-border bg-agent-muted px-1.5 py-0.5 text-[10px] text-agent-muted-foreground", title: catalog?.error ?? 'Model catalog unavailable', children: "catalog offline" })) : catalog?.catalogStatus === 'stale' ? (_jsx("span", { className: "inline-flex items-center rounded-agent-md border border-agent-border bg-agent-muted px-1.5 py-0.5 text-[10px] text-agent-muted-foreground", title: "Refresh failed; showing the previous listing", children: "stale" })) : null] }));
68
+ }
69
+ //# sourceMappingURL=ModelSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelSelector.js","sourceRoot":"","sources":["../../src/components/ModelSelector.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ModelSelector } from './ModelSelector';
3
+ /**
4
+ * `ModelSelector` against canned transports: the live gateway catalog, the
5
+ * stale-cache degradation, and the offline state (gateway unreachable — the
6
+ * composer stays usable, the picker degrades to a badge).
7
+ */
8
+ declare const meta: Meta<typeof ModelSelector>;
9
+ export default meta;
10
+ type Story = StoryObj<typeof ModelSelector>;
11
+ export declare const Live: Story;
12
+ export declare const Stale: Story;
13
+ export declare const Offline: Story;
14
+ //# sourceMappingURL=ModelSelector.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelSelector.stories.d.ts","sourceRoot":"","sources":["../../src/components/ModelSelector.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMhD;;;;GAIG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAGpC,CAAC;AACF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,aAAa,CAAC,CAAC;AA8E5C,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { ModelSelector } from './ModelSelector';
4
+ /**
5
+ * `ModelSelector` against canned transports: the live gateway catalog, the
6
+ * stale-cache degradation, and the offline state (gateway unreachable — the
7
+ * composer stays usable, the picker degrades to a badge).
8
+ */
9
+ const meta = {
10
+ title: 'Components/ModelSelector',
11
+ component: ModelSelector,
12
+ };
13
+ export default meta;
14
+ const LIVE_CATALOG = {
15
+ models: [
16
+ {
17
+ id: 'openai/deepseek/deepseek-v4-flash',
18
+ name: 'DeepSeek V4 Flash',
19
+ window: 1_048_576,
20
+ modalities: ['text'],
21
+ reasoningLevels: ['low', 'high'],
22
+ pricing: { promptPerMtok: 0.14, completionPerMtok: 0.28 },
23
+ joinedFrom: 'openrouter/deepseek/deepseek-v4-flash',
24
+ capabilities: 'known',
25
+ },
26
+ {
27
+ id: 'openai/qwen/qwen3.8-27b',
28
+ name: 'Qwen 3.8 27B',
29
+ window: 262_144,
30
+ modalities: ['text', 'image'],
31
+ reasoningLevels: ['low', 'medium'],
32
+ pricing: { promptPerMtok: 0.2, completionPerMtok: 0.8 },
33
+ joinedFrom: 'openrouter/qwen/qwen3.8-27b',
34
+ capabilities: 'known',
35
+ },
36
+ {
37
+ id: 'openai/z-ai/glm-5.3-flash',
38
+ name: 'GLM 5.3 Flash',
39
+ window: 1_048_576,
40
+ modalities: ['text', 'image'],
41
+ reasoningLevels: ['low', 'high', 'max'],
42
+ pricing: null,
43
+ joinedFrom: 'openrouter/z-ai/glm-5.3-flash',
44
+ capabilities: 'known',
45
+ },
46
+ {
47
+ id: 'openai/acme-internal-1',
48
+ name: 'openai/acme-internal-1',
49
+ window: 60_000,
50
+ modalities: ['text'],
51
+ reasoningLevels: [],
52
+ pricing: null,
53
+ joinedFrom: null,
54
+ capabilities: 'unknown',
55
+ },
56
+ ],
57
+ catalogStatus: 'live',
58
+ fetchedAt: 1_757_000_000,
59
+ current: { model: 'openai/qwen/qwen3.8-27b', reasoningEffort: null },
60
+ };
61
+ function transportOf(impl) {
62
+ return { listModels: impl };
63
+ }
64
+ function Demo({ catalog }) {
65
+ const [model, setModel] = useState('openai/qwen/qwen3.8-27b');
66
+ const [effort, setEffort] = useState(null);
67
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsx(ModelSelector, { transport: transportOf(async () => catalog), model: model, reasoningEffort: effort, onSelectModel: (id) => {
68
+ setModel(id);
69
+ setEffort(null);
70
+ }, onSelectEffort: setEffort }), _jsxs("div", { style: { fontSize: 12, opacity: 0.7 }, children: ["selection: ", model, " / ", effort ?? 'default'] })] }));
71
+ }
72
+ export const Live = {
73
+ render: () => _jsx(Demo, { catalog: LIVE_CATALOG }),
74
+ };
75
+ export const Stale = {
76
+ render: () => _jsx(Demo, { catalog: { ...LIVE_CATALOG, catalogStatus: 'stale' } }),
77
+ };
78
+ export const Offline = {
79
+ render: () => (_jsx(Demo, { catalog: {
80
+ models: [],
81
+ catalogStatus: 'offline',
82
+ error: 'gateway catalog fetch failed: connection refused',
83
+ } })),
84
+ };
85
+ //# sourceMappingURL=ModelSelector.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelSelector.stories.js","sourceRoot":"","sources":["../../src/components/ModelSelector.stories.tsx"],"names":[],"mappings":"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"}
@@ -4,6 +4,8 @@ export { ChatPanel } from './ChatPanel.js';
4
4
  export type { ChatPanelProps, ChatPanelRootProps, ChatPanelHeaderProps, ChatPanelMessagesProps, ChatPanelInputProps, ChatPanelInputHandle, ChatPanelEmptyProps, ChatPanelStreamingStatusProps, } from './ChatPanel.js';
5
5
  export { AgentSelector } from './AgentSelector.js';
6
6
  export type { AgentSelectorProps } from './AgentSelector.js';
7
+ export { ModelSelector } from './ModelSelector.js';
8
+ export type { ModelCatalogEntry, ModelCatalogResponse, ModelCatalogTransport, ModelSelectorProps, } from './ModelSelector.js';
7
9
  export { OrchestrationPlanCard } from './OrchestrationPlanCard.js';
8
10
  export type { OrchestrationPlanCardProps, OrchestrationStep, OrchestrationStepStatus, } from './OrchestrationPlanCard.js';
9
11
  export { ToolCallRenderer } from './ToolCallRenderer.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  export { MessageList } from './MessageList.js';
2
2
  export { ChatPanel } from './ChatPanel.js';
3
3
  export { AgentSelector } from './AgentSelector.js';
4
+ export { ModelSelector } from './ModelSelector.js';
4
5
  export { OrchestrationPlanCard } from './OrchestrationPlanCard.js';
5
6
  export { ToolCallRenderer } from './ToolCallRenderer.js';
6
7
  export { SSEStreamView } from './SSEStreamView.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAY3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAOnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAY3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAQnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAOnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steerable/agent-ui",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Steerable framework Tier 4 — headless React hooks (useAgentSession, useChatStream, useToolCallStatus) and Tailwind-themed components (ChatPanel, MessageList, OrchestrationPlanCard, ToolCallRenderer, SSEStreamView) for embedding Steerable agents in any React app.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://steerableframework.com/storybook/",
@@ -57,7 +57,7 @@
57
57
  "README.md"
58
58
  ],
59
59
  "dependencies": {
60
- "@steerable/agent-protocol": "0.6.5"
60
+ "@steerable/agent-protocol": "0.6.6"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "react": ">=18.0.0",
@@ -588,6 +588,9 @@ export interface ChatPanelConnectedProps {
588
588
  emptyTitle?: string;
589
589
  emptyDescription?: string;
590
590
  inputPlaceholder?: string;
591
+ /** Extra controls rendered in the input toolbar (e.g. `ModelSelector`). */
592
+ inputToolbarLeft?: React.ReactNode;
593
+ inputToolbarRight?: React.ReactNode;
591
594
  renderMessage?: (props: MessageRendererProps) => React.ReactNode;
592
595
  renderToolCall?: (call: ToolCall, result?: ToolResult) => React.ReactNode;
593
596
  /** Apply the panel's own background/foreground tokens (default). */
@@ -602,6 +605,8 @@ function ChatPanelConnected(props: ChatPanelConnectedProps) {
602
605
  emptyTitle,
603
606
  emptyDescription,
604
607
  inputPlaceholder,
608
+ inputToolbarLeft,
609
+ inputToolbarRight,
605
610
  renderMessage,
606
611
  renderToolCall,
607
612
  styled = true,
@@ -639,6 +644,8 @@ function ChatPanelConnected(props: ChatPanelConnectedProps) {
639
644
  onCancel={composer.cancel}
640
645
  isStreaming={session.isStreaming}
641
646
  placeholder={inputPlaceholder}
647
+ toolbarLeft={inputToolbarLeft}
648
+ toolbarRight={inputToolbarRight}
642
649
  />
643
650
  </ChatPanelRoot>
644
651
  );
@@ -0,0 +1,116 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { useState } from 'react';
3
+ import { ModelSelector } from './ModelSelector';
4
+ import type {
5
+ ModelCatalogResponse,
6
+ ModelCatalogTransport,
7
+ } from './ModelSelector';
8
+
9
+ /**
10
+ * `ModelSelector` against canned transports: the live gateway catalog, the
11
+ * stale-cache degradation, and the offline state (gateway unreachable — the
12
+ * composer stays usable, the picker degrades to a badge).
13
+ */
14
+ const meta: Meta<typeof ModelSelector> = {
15
+ title: 'Components/ModelSelector',
16
+ component: ModelSelector,
17
+ };
18
+ export default meta;
19
+
20
+ type Story = StoryObj<typeof ModelSelector>;
21
+
22
+ const LIVE_CATALOG: ModelCatalogResponse = {
23
+ models: [
24
+ {
25
+ id: 'openai/deepseek/deepseek-v4-flash',
26
+ name: 'DeepSeek V4 Flash',
27
+ window: 1_048_576,
28
+ modalities: ['text'],
29
+ reasoningLevels: ['low', 'high'],
30
+ pricing: { promptPerMtok: 0.14, completionPerMtok: 0.28 },
31
+ joinedFrom: 'openrouter/deepseek/deepseek-v4-flash',
32
+ capabilities: 'known',
33
+ },
34
+ {
35
+ id: 'openai/qwen/qwen3.8-27b',
36
+ name: 'Qwen 3.8 27B',
37
+ window: 262_144,
38
+ modalities: ['text', 'image'],
39
+ reasoningLevels: ['low', 'medium'],
40
+ pricing: { promptPerMtok: 0.2, completionPerMtok: 0.8 },
41
+ joinedFrom: 'openrouter/qwen/qwen3.8-27b',
42
+ capabilities: 'known',
43
+ },
44
+ {
45
+ id: 'openai/z-ai/glm-5.3-flash',
46
+ name: 'GLM 5.3 Flash',
47
+ window: 1_048_576,
48
+ modalities: ['text', 'image'],
49
+ reasoningLevels: ['low', 'high', 'max'],
50
+ pricing: null,
51
+ joinedFrom: 'openrouter/z-ai/glm-5.3-flash',
52
+ capabilities: 'known',
53
+ },
54
+ {
55
+ id: 'openai/acme-internal-1',
56
+ name: 'openai/acme-internal-1',
57
+ window: 60_000,
58
+ modalities: ['text'],
59
+ reasoningLevels: [],
60
+ pricing: null,
61
+ joinedFrom: null,
62
+ capabilities: 'unknown',
63
+ },
64
+ ],
65
+ catalogStatus: 'live',
66
+ fetchedAt: 1_757_000_000,
67
+ current: { model: 'openai/qwen/qwen3.8-27b', reasoningEffort: null },
68
+ };
69
+
70
+ function transportOf(
71
+ impl: ModelCatalogTransport['listModels'],
72
+ ): ModelCatalogTransport {
73
+ return { listModels: impl };
74
+ }
75
+
76
+ function Demo({ catalog }: { catalog: ModelCatalogResponse }) {
77
+ const [model, setModel] = useState('openai/qwen/qwen3.8-27b');
78
+ const [effort, setEffort] = useState<string | null>(null);
79
+ return (
80
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
81
+ <ModelSelector
82
+ transport={transportOf(async () => catalog)}
83
+ model={model}
84
+ reasoningEffort={effort}
85
+ onSelectModel={(id) => {
86
+ setModel(id);
87
+ setEffort(null);
88
+ }}
89
+ onSelectEffort={setEffort}
90
+ />
91
+ <div style={{ fontSize: 12, opacity: 0.7 }}>
92
+ selection: {model} / {effort ?? 'default'}
93
+ </div>
94
+ </div>
95
+ );
96
+ }
97
+
98
+ export const Live: Story = {
99
+ render: () => <Demo catalog={LIVE_CATALOG} />,
100
+ };
101
+
102
+ export const Stale: Story = {
103
+ render: () => <Demo catalog={{ ...LIVE_CATALOG, catalogStatus: 'stale' }} />,
104
+ };
105
+
106
+ export const Offline: Story = {
107
+ render: () => (
108
+ <Demo
109
+ catalog={{
110
+ models: [],
111
+ catalogStatus: 'offline',
112
+ error: 'gateway catalog fetch failed: connection refused',
113
+ }}
114
+ />
115
+ ),
116
+ };
@@ -0,0 +1,181 @@
1
+ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { ModelSelector } from './ModelSelector';
4
+ import type {
5
+ ModelCatalogResponse,
6
+ ModelCatalogTransport,
7
+ } from './ModelSelector';
8
+
9
+ const CATALOG: ModelCatalogResponse = {
10
+ models: [
11
+ {
12
+ id: 'openai/deepseek/deepseek-v4-flash',
13
+ name: 'DeepSeek V4 Flash',
14
+ window: 1_048_576,
15
+ modalities: ['text'],
16
+ reasoningLevels: ['low', 'high'],
17
+ pricing: { promptPerMtok: 0.14, completionPerMtok: 0.28 },
18
+ joinedFrom: 'openrouter/deepseek/deepseek-v4-flash',
19
+ capabilities: 'known',
20
+ },
21
+ {
22
+ id: 'openai/qwen/qwen3.8-27b',
23
+ name: 'Qwen 3.8 27B',
24
+ window: 262_144,
25
+ modalities: ['text', 'image'],
26
+ reasoningLevels: ['low', 'medium'],
27
+ pricing: null,
28
+ joinedFrom: 'openrouter/qwen/qwen3.8-27b',
29
+ capabilities: 'known',
30
+ },
31
+ {
32
+ id: 'openai/acme-internal-1',
33
+ name: 'openai/acme-internal-1',
34
+ window: 60_000,
35
+ modalities: ['text'],
36
+ reasoningLevels: [],
37
+ pricing: null,
38
+ joinedFrom: null,
39
+ capabilities: 'unknown',
40
+ },
41
+ ],
42
+ catalogStatus: 'live',
43
+ fetchedAt: 1_757_000_000,
44
+ current: { model: 'openai/qwen/qwen3.8-27b', reasoningEffort: null },
45
+ };
46
+
47
+ function transportOf(
48
+ impl: ModelCatalogTransport['listModels'],
49
+ ): ModelCatalogTransport {
50
+ return { listModels: vi.fn(impl) };
51
+ }
52
+
53
+ describe('ModelSelector', () => {
54
+ it('lists the gateway catalog and reports the selection', async () => {
55
+ const onSelectModel = vi.fn();
56
+ render(
57
+ <ModelSelector
58
+ transport={transportOf(async () => CATALOG)}
59
+ model="openai/qwen/qwen3.8-27b"
60
+ onSelectModel={onSelectModel}
61
+ />,
62
+ );
63
+
64
+ const select = await screen.findByRole('combobox', { name: 'Model' });
65
+ expect((select as HTMLSelectElement).value).toBe('openai/qwen/qwen3.8-27b');
66
+ expect(screen.getByText('openai/deepseek/deepseek-v4-flash')).toBeTruthy();
67
+
68
+ fireEvent.change(select, {
69
+ target: { value: 'openai/deepseek/deepseek-v4-flash' },
70
+ });
71
+ expect(onSelectModel).toHaveBeenCalledWith('openai/deepseek/deepseek-v4-flash');
72
+ });
73
+
74
+ it('offers the joined reasoning levels for the selected model', async () => {
75
+ const onSelectEffort = vi.fn();
76
+ render(
77
+ <ModelSelector
78
+ transport={transportOf(async () => CATALOG)}
79
+ model="openai/qwen/qwen3.8-27b"
80
+ reasoningEffort={null}
81
+ onSelectModel={() => {}}
82
+ onSelectEffort={onSelectEffort}
83
+ />,
84
+ );
85
+
86
+ const effort = await screen.findByRole('combobox', {
87
+ name: 'Reasoning effort',
88
+ });
89
+ const options = Array.from(effort.querySelectorAll('option')).map(
90
+ (option) => option.value,
91
+ );
92
+ expect(options).toEqual(['', 'low', 'medium']);
93
+
94
+ fireEvent.change(effort, { target: { value: 'medium' } });
95
+ expect(onSelectEffort).toHaveBeenCalledWith('medium');
96
+ });
97
+
98
+ it('hides the effort picker for models without a reasoning knob', async () => {
99
+ render(
100
+ <ModelSelector
101
+ transport={transportOf(async () => CATALOG)}
102
+ model="openai/acme-internal-1"
103
+ onSelectModel={() => {}}
104
+ onSelectEffort={() => {}}
105
+ />,
106
+ );
107
+
108
+ await screen.findByRole('combobox', { name: 'Model' });
109
+ expect(
110
+ screen.queryByRole('combobox', { name: 'Reasoning effort' }),
111
+ ).toBeNull();
112
+ });
113
+
114
+ it('keeps an unlisted current model selectable (discovery, not whitelist)', async () => {
115
+ render(
116
+ <ModelSelector
117
+ transport={transportOf(async () => CATALOG)}
118
+ model="openai/custom-fine-tune"
119
+ onSelectModel={() => {}}
120
+ />,
121
+ );
122
+
123
+ const select = await screen.findByRole('combobox', { name: 'Model' });
124
+ expect((select as HTMLSelectElement).value).toBe('openai/custom-fine-tune');
125
+ });
126
+
127
+ it('shows the offline state and disables the picker when the catalog is unreachable', async () => {
128
+ render(
129
+ <ModelSelector
130
+ transport={transportOf(async () => ({
131
+ models: [],
132
+ catalogStatus: 'offline',
133
+ error: 'connection refused',
134
+ }))}
135
+ model="openai/qwen/qwen3.8-27b"
136
+ onSelectModel={() => {}}
137
+ />,
138
+ );
139
+
140
+ await screen.findByText('catalog offline');
141
+ const select = screen.getByRole('combobox', { name: 'Model' });
142
+ expect((select as HTMLSelectElement).disabled).toBe(true);
143
+ // The configured model is still displayed, not blanked.
144
+ expect((select as HTMLSelectElement).value).toBe('openai/qwen/qwen3.8-27b');
145
+ });
146
+
147
+ it('degrades to offline when the transport itself fails', async () => {
148
+ render(
149
+ <ModelSelector
150
+ transport={transportOf(async () => {
151
+ throw new Error('sidecar gone');
152
+ })}
153
+ model="openai/qwen/qwen3.8-27b"
154
+ onSelectModel={() => {}}
155
+ />,
156
+ );
157
+
158
+ await screen.findByText('catalog offline');
159
+ });
160
+
161
+ it('marks a stale listing without disabling selection', async () => {
162
+ render(
163
+ <ModelSelector
164
+ transport={transportOf(async () => ({
165
+ ...CATALOG,
166
+ catalogStatus: 'stale' as const,
167
+ }))}
168
+ model="openai/qwen/qwen3.8-27b"
169
+ onSelectModel={() => {}}
170
+ />,
171
+ );
172
+
173
+ await screen.findByText('stale');
174
+ await waitFor(() =>
175
+ expect(
176
+ (screen.getByRole('combobox', { name: 'Model' }) as HTMLSelectElement)
177
+ .disabled,
178
+ ).toBe(false),
179
+ );
180
+ });
181
+ });
@@ -0,0 +1,209 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react';
2
+ import { cn } from './cn.js';
3
+
4
+ /**
5
+ * `ModelSelector` — model + reasoning-effort picker backed by the gateway's
6
+ * live catalog.
7
+ *
8
+ * The sidecar's `models.list` RPC answers the ids the gateway actually
9
+ * accepts, each joined with catalog capabilities (window, modalities,
10
+ * reasoning levels, pricing). The catalog is discovery, not a routing
11
+ * whitelist: the current model stays selectable even when unlisted, and the
12
+ * offline state degrades to a badge instead of blocking the composer.
13
+ *
14
+ * Stability contract (same as `useAgentSession`): `transport` is held by ref
15
+ * and the listing refetches only when `baseUrl` changes — call the returned
16
+ * refresh path by remounting or changing `baseUrl` if the transport swapped.
17
+ */
18
+
19
+ export interface ModelCatalogEntry {
20
+ id: string;
21
+ name: string;
22
+ /** Context window in tokens; null when neither gateway nor catalog knows. */
23
+ window: number | null;
24
+ modalities: string[];
25
+ /** Supported reasoning-effort levels, canonical order; empty = no knob. */
26
+ reasoningLevels: string[];
27
+ pricing: { promptPerMtok: number | null; completionPerMtok: number | null } | null;
28
+ /** Catalog key that supplied capability fields; null = capabilities unknown. */
29
+ joinedFrom: string | null;
30
+ capabilities: 'known' | 'unknown';
31
+ }
32
+
33
+ export interface ModelCatalogResponse {
34
+ models: ModelCatalogEntry[];
35
+ catalogStatus: 'live' | 'stale' | 'offline';
36
+ /** Epoch seconds of the successful fetch the listing came from. */
37
+ fetchedAt?: number;
38
+ /** Present when catalogStatus is 'offline'. */
39
+ error?: string;
40
+ current?: { model: string | null; reasoningEffort: string | null };
41
+ }
42
+
43
+ export interface ModelCatalogTransport {
44
+ listModels: (params?: { baseUrl?: string }) => Promise<ModelCatalogResponse>;
45
+ }
46
+
47
+ export interface ModelSelectorProps {
48
+ transport: ModelCatalogTransport;
49
+ /** Gateway base URL the sidecar queries; omit to use the sidecar's env. */
50
+ baseUrl?: string;
51
+ /** Currently selected model id (controlled). */
52
+ model: string;
53
+ /** Currently selected reasoning effort; null/undefined = no explicit request. */
54
+ reasoningEffort?: string | null;
55
+ onSelectModel: (id: string) => void;
56
+ onSelectEffort?: (effort: string | null) => void;
57
+ disabled?: boolean;
58
+ className?: string;
59
+ }
60
+
61
+ const selectClass =
62
+ 'h-7 max-w-[180px] rounded-agent-md border border-agent-border bg-agent-canvas px-2 text-xs text-agent-foreground outline-none transition-colors hover:bg-agent-muted disabled:cursor-not-allowed disabled:opacity-50';
63
+
64
+ export function ModelSelector(props: ModelSelectorProps) {
65
+ const {
66
+ transport,
67
+ baseUrl,
68
+ model,
69
+ reasoningEffort,
70
+ onSelectModel,
71
+ onSelectEffort,
72
+ disabled = false,
73
+ className,
74
+ } = props;
75
+
76
+ const transportRef = useRef(transport);
77
+ transportRef.current = transport;
78
+ const [catalog, setCatalog] = useState<ModelCatalogResponse | null>(null);
79
+ const [loading, setLoading] = useState(true);
80
+
81
+ useEffect(() => {
82
+ let cancelled = false;
83
+ setLoading(true);
84
+ transportRef.current
85
+ .listModels(baseUrl ? { baseUrl } : undefined)
86
+ .then((response) => {
87
+ if (!cancelled) setCatalog(response);
88
+ })
89
+ .catch(() => {
90
+ // A transport-level failure (sidecar gone, RPC error) degrades to the
91
+ // same offline state the sidecar itself reports for an unreachable
92
+ // gateway — the composer stays usable.
93
+ if (!cancelled) {
94
+ setCatalog({ models: [], catalogStatus: 'offline' });
95
+ }
96
+ })
97
+ .finally(() => {
98
+ if (!cancelled) setLoading(false);
99
+ });
100
+ return () => {
101
+ cancelled = true;
102
+ };
103
+ }, [baseUrl]);
104
+
105
+ const entries = useMemo(() => {
106
+ const list = catalog?.models ?? [];
107
+ // Discovery, not a whitelist: the active model stays selectable even
108
+ // when the gateway listing does not contain it (catalog offline, or an
109
+ // id the gateway accepts but does not advertise).
110
+ if (model && !list.some((entry) => entry.id === model)) {
111
+ return [
112
+ {
113
+ id: model,
114
+ name: model,
115
+ window: null,
116
+ modalities: [],
117
+ reasoningLevels: [],
118
+ pricing: null,
119
+ joinedFrom: null,
120
+ capabilities: 'unknown' as const,
121
+ },
122
+ ...list,
123
+ ];
124
+ }
125
+ return list;
126
+ }, [catalog, model]);
127
+
128
+ const selected = entries.find((entry) => entry.id === model);
129
+
130
+ if (loading) {
131
+ return (
132
+ <div
133
+ className={cn(
134
+ 'inline-flex h-7 items-center rounded-agent-md border border-agent-border bg-agent-canvas px-2 text-xs text-agent-muted-foreground',
135
+ className,
136
+ )}
137
+ aria-live="polite"
138
+ >
139
+ Loading models…
140
+ </div>
141
+ );
142
+ }
143
+
144
+ const offline = catalog?.catalogStatus === 'offline';
145
+
146
+ return (
147
+ <div
148
+ className={cn('inline-flex items-center gap-1.5', className)}
149
+ data-catalog-status={catalog?.catalogStatus ?? 'unknown'}
150
+ >
151
+ <select
152
+ aria-label="Model"
153
+ className={cn(selectClass, 'min-w-[8rem]')}
154
+ value={model}
155
+ disabled={disabled || offline}
156
+ onChange={(event) => onSelectModel(event.target.value)}
157
+ title={
158
+ offline
159
+ ? `Model catalog unavailable — using the configured model. ${catalog?.error ?? ''}`
160
+ : selected
161
+ ? `${selected.name}${selected.window ? ` — ${Math.round(selected.window / 1024)}k window` : ''}${selected.capabilities === 'unknown' ? ' — capabilities unknown' : ''}`
162
+ : model
163
+ }
164
+ >
165
+ {entries.map((entry) => (
166
+ <option key={entry.id} value={entry.id}>
167
+ {entry.id}
168
+ {entry.capabilities === 'unknown' ? ' (?)' : ''}
169
+ </option>
170
+ ))}
171
+ {entries.length === 0 && model ? <option value={model}>{model}</option> : null}
172
+ </select>
173
+
174
+ {selected && selected.reasoningLevels.length > 0 && onSelectEffort ? (
175
+ <select
176
+ aria-label="Reasoning effort"
177
+ className={selectClass}
178
+ value={reasoningEffort ?? ''}
179
+ disabled={disabled}
180
+ onChange={(event) => onSelectEffort(event.target.value || null)}
181
+ title="Reasoning effort — an unsupported level is rejected by the sidecar, never silently dropped"
182
+ >
183
+ <option value="">default</option>
184
+ {selected.reasoningLevels.map((level) => (
185
+ <option key={level} value={level}>
186
+ {level}
187
+ </option>
188
+ ))}
189
+ </select>
190
+ ) : null}
191
+
192
+ {offline ? (
193
+ <span
194
+ className="inline-flex items-center rounded-agent-md border border-agent-border bg-agent-muted px-1.5 py-0.5 text-[10px] text-agent-muted-foreground"
195
+ title={catalog?.error ?? 'Model catalog unavailable'}
196
+ >
197
+ catalog offline
198
+ </span>
199
+ ) : catalog?.catalogStatus === 'stale' ? (
200
+ <span
201
+ className="inline-flex items-center rounded-agent-md border border-agent-border bg-agent-muted px-1.5 py-0.5 text-[10px] text-agent-muted-foreground"
202
+ title="Refresh failed; showing the previous listing"
203
+ >
204
+ stale
205
+ </span>
206
+ ) : null}
207
+ </div>
208
+ );
209
+ }
@@ -16,6 +16,14 @@ export type {
16
16
  export { AgentSelector } from './AgentSelector.js';
17
17
  export type { AgentSelectorProps } from './AgentSelector.js';
18
18
 
19
+ export { ModelSelector } from './ModelSelector.js';
20
+ export type {
21
+ ModelCatalogEntry,
22
+ ModelCatalogResponse,
23
+ ModelCatalogTransport,
24
+ ModelSelectorProps,
25
+ } from './ModelSelector.js';
26
+
19
27
  export { OrchestrationPlanCard } from './OrchestrationPlanCard.js';
20
28
  export type {
21
29
  OrchestrationPlanCardProps,