@neuronection/assistant-ui 0.57.0 → 0.59.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.
- package/CHANGELOG.md +19 -0
- package/dist/chunk-3Y6QOTVA.js +270 -0
- package/dist/chunk-3Y6QOTVA.js.map +1 -0
- package/dist/{chunk-FPX3AI3Z.js → chunk-GR6CSKQY.js} +3 -3
- package/dist/{chunk-FPX3AI3Z.js.map → chunk-GR6CSKQY.js.map} +1 -1
- package/dist/{chunk-3YIVKKT6.js → chunk-GUFHUKUA.js} +3 -3
- package/dist/{chunk-3YIVKKT6.js.map → chunk-GUFHUKUA.js.map} +1 -1
- package/dist/chunk-KDILZS2Z.js +3 -0
- package/dist/chunk-KDILZS2Z.js.map +1 -0
- package/dist/{chunk-KV67D3RP.js → chunk-O6BRNGXV.js} +2 -2
- package/dist/{chunk-KV67D3RP.js.map → chunk-O6BRNGXV.js.map} +1 -1
- package/dist/chunk-X6L5T65Q.js +81 -0
- package/dist/chunk-X6L5T65Q.js.map +1 -0
- package/dist/connection-test-row.js +1 -1
- package/dist/index.d.ts +114 -4
- package/dist/index.js +9 -8
- package/dist/model-picker.d.ts +16 -2
- package/dist/model-picker.js +1 -1
- package/dist/model-registry.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/task-assignment-picker.js +1 -1
- package/dist/web-search-providers.d.ts +99 -0
- package/dist/web-search-providers.js +3 -0
- package/dist/web-search-providers.js.map +1 -0
- package/package.json +5 -1
- package/dist/chunk-CCFVDJHU.js +0 -65
- package/dist/chunk-CCFVDJHU.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @neuronection/assistant-ui
|
|
2
2
|
|
|
3
|
+
## 0.59.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`2bf4216`](https://github.com/neuronection/assistant-ui/commit/2bf4216c2b1ea1da3f2dc1367298ce6fcd16c058) Thanks [@constLiakos](https://github.com/constLiakos)! - ModelPicker labeled null option (`nullOption?: { label: string }`): the option list leads with the labeled null (inherit) entry — rendered "Inherits — {resolved default model}" by the app — and choosing it assigns `null` (plan 29 / ADR-0036, the Decision defaults card's inherit rows). The props are discriminated: with `nullOption` set, `onChange` receives `string | null`; without it the contract is unchanged.
|
|
8
|
+
|
|
9
|
+
## 0.58.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`255c074`](https://github.com/neuronection/assistant-ui/commit/255c074c16bdbc7cc4d919d9ffea0d0334e0462e) Thanks [@constLiakos](https://github.com/constLiakos)! - `WebSearchProvidersPanel` — the family web-search settings surface
|
|
14
|
+
(ADR-0035 / plan 28): a controlled, presentational ordered multi-provider
|
|
15
|
+
list (enable, reorder, probe-test, edit, delete) with a catalog-driven
|
|
16
|
+
add/edit form. Data contracts mirror the family `providers[]` shape and
|
|
17
|
+
the vendored `search-providers.json` catalog; persistence, key sealing and
|
|
18
|
+
probe calls stay app-side. Study-assistant is the first consumer (its
|
|
19
|
+
local panel is deleted same-commit on adoption); desktop and career follow
|
|
20
|
+
in plan 28 Phases 3–4.
|
|
21
|
+
|
|
3
22
|
## 0.57.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { ConnectionTestRow } from './chunk-O6BRNGXV.js';
|
|
2
|
+
import { Button } from './chunk-4WBBF5LH.js';
|
|
3
|
+
import { cn } from './chunk-RVVXVTH3.js';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { Plus, ChevronUp, ChevronDown, Pencil, Trash2 } from 'lucide-react';
|
|
6
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
var inputClass = "min-w-0 flex-1 rounded-[var(--as-radius-sm)] border border-[var(--as-border)] bg-[var(--as-surface)] px-2 py-1.5 text-sm text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]";
|
|
9
|
+
var WebSearchProvidersPanel = React.forwardRef(function WebSearchProvidersPanel2({
|
|
10
|
+
providers,
|
|
11
|
+
catalog,
|
|
12
|
+
probes = {},
|
|
13
|
+
testingId = null,
|
|
14
|
+
busy = false,
|
|
15
|
+
labels,
|
|
16
|
+
onSave,
|
|
17
|
+
onDelete,
|
|
18
|
+
onMove,
|
|
19
|
+
onToggle,
|
|
20
|
+
onTest,
|
|
21
|
+
className
|
|
22
|
+
}, ref) {
|
|
23
|
+
const t = React.useMemo(
|
|
24
|
+
() => ({
|
|
25
|
+
title: labels?.title ?? "Web search providers",
|
|
26
|
+
hint: labels?.hint,
|
|
27
|
+
addLabel: labels?.addLabel ?? "Add provider",
|
|
28
|
+
emptyLabel: labels?.emptyLabel ?? "No web search providers yet.",
|
|
29
|
+
nameLabel: labels?.nameLabel ?? "Name (optional)",
|
|
30
|
+
typeLabel: labels?.typeLabel ?? "Provider type",
|
|
31
|
+
baseUrlLabel: labels?.baseUrlLabel ?? "Base URL (optional)",
|
|
32
|
+
baseUrlRequiredLabel: labels?.baseUrlRequiredLabel ?? "Base URL (required)",
|
|
33
|
+
keyLabel: labels?.keyLabel ?? "API key",
|
|
34
|
+
keyOptionalLabel: labels?.keyOptionalLabel ?? "API key (optional)",
|
|
35
|
+
keyStoredLabel: labels?.keyStoredLabel ?? "API key saved",
|
|
36
|
+
noKeyLabel: labels?.noKeyLabel ?? "no key",
|
|
37
|
+
saveLabel: labels?.saveLabel ?? "Save provider",
|
|
38
|
+
cancelLabel: labels?.cancelLabel ?? "Cancel",
|
|
39
|
+
editLabel: labels?.editLabel ?? "Edit provider",
|
|
40
|
+
deleteLabel: labels?.deleteLabel ?? "Delete provider",
|
|
41
|
+
moveUpLabel: labels?.moveUpLabel ?? "Move up",
|
|
42
|
+
moveDownLabel: labels?.moveDownLabel ?? "Move down",
|
|
43
|
+
enabledAriaLabel: labels?.enabledAriaLabel ?? "Enable provider",
|
|
44
|
+
disabledBadge: labels?.disabledBadge ?? "disabled",
|
|
45
|
+
testLabel: labels?.testLabel ?? "Test",
|
|
46
|
+
probeLabels: { ...labels?.probeLabels }
|
|
47
|
+
}),
|
|
48
|
+
[labels]
|
|
49
|
+
);
|
|
50
|
+
const [draft, setDraft] = React.useState(null);
|
|
51
|
+
const openAdd = () => {
|
|
52
|
+
const first = catalog.order[0];
|
|
53
|
+
if (first) setDraft({ type: first, name: "", baseUrl: "", googleCx: "", apiKey: null });
|
|
54
|
+
};
|
|
55
|
+
const openEdit = (provider) => setDraft({
|
|
56
|
+
id: provider.id,
|
|
57
|
+
type: provider.type,
|
|
58
|
+
name: provider.name,
|
|
59
|
+
baseUrl: provider.baseUrl ?? "",
|
|
60
|
+
googleCx: provider.googleCx ?? "",
|
|
61
|
+
apiKey: null
|
|
62
|
+
});
|
|
63
|
+
const draftEntry = draft ? catalog.entries[draft.type] : void 0;
|
|
64
|
+
const draftCxField = draftEntry?.fields?.some((field) => field.id === "google_cx") ?? false;
|
|
65
|
+
const saveDisabled = busy || draftEntry?.baseUrlRequired && !(draft?.baseUrl ?? "").trim() || draft?.id == null && (draftEntry?.requiresKey ?? false) && !(draft?.apiKey ?? "").trim();
|
|
66
|
+
return /* @__PURE__ */ jsxs(
|
|
67
|
+
"div",
|
|
68
|
+
{
|
|
69
|
+
ref,
|
|
70
|
+
"data-as": "web-search-providers",
|
|
71
|
+
className: cn(
|
|
72
|
+
"rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] p-4",
|
|
73
|
+
className
|
|
74
|
+
),
|
|
75
|
+
children: [
|
|
76
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
77
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
78
|
+
/* @__PURE__ */ jsx("p", { className: "text-base font-medium text-[var(--as-fg)]", children: t.title }),
|
|
79
|
+
t.hint ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-[var(--as-muted-fg)]", children: t.hint }) : null
|
|
80
|
+
] }),
|
|
81
|
+
draft === null ? /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: openAdd, children: [
|
|
82
|
+
/* @__PURE__ */ jsx(Plus, { className: "size-4", "aria-hidden": true }),
|
|
83
|
+
t.addLabel
|
|
84
|
+
] }) : null
|
|
85
|
+
] }),
|
|
86
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-3 space-y-2", "data-testid": "wsp-rows", children: providers.map((provider, index) => {
|
|
87
|
+
const probe = probes[provider.id];
|
|
88
|
+
const isTesting = testingId === provider.id;
|
|
89
|
+
const showProbeRow = probe != null || isTesting;
|
|
90
|
+
const probeStatus = !showProbeRow ? null : isTesting ? "testing" : probe.status === "ok" ? "ok" : "fail";
|
|
91
|
+
const probeText = probe && probe.status !== "ok" && probe.error ? probe.error : probe ? t.probeLabels[probe.status] ?? probe.status : null;
|
|
92
|
+
return /* @__PURE__ */ jsxs(
|
|
93
|
+
"li",
|
|
94
|
+
{
|
|
95
|
+
"data-testid": `wsp-row-${provider.id}`,
|
|
96
|
+
className: "border-border border-[var(--as-border)] space-y-1 rounded-[var(--as-radius-sm)] border p-3",
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
99
|
+
/* @__PURE__ */ jsxs("label", { className: "flex cursor-pointer items-center gap-2 text-sm font-medium text-[var(--as-fg)]", children: [
|
|
100
|
+
/* @__PURE__ */ jsx(
|
|
101
|
+
"input",
|
|
102
|
+
{
|
|
103
|
+
type: "checkbox",
|
|
104
|
+
checked: provider.enabled,
|
|
105
|
+
"aria-label": `${t.enabledAriaLabel}: ${provider.name}`,
|
|
106
|
+
onChange: (event) => onToggle(provider.id, event.target.checked)
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
provider.name
|
|
110
|
+
] }),
|
|
111
|
+
/* @__PURE__ */ jsx("span", { className: "rounded-full bg-[var(--as-secondary)] px-2 py-0.5 text-[11px] text-[var(--as-muted-fg)]", children: catalog.entries[provider.type]?.label ?? provider.type }),
|
|
112
|
+
provider.baseUrl ? /* @__PURE__ */ jsx("span", { className: "truncate font-mono text-xs text-[var(--as-muted-fg)]", children: provider.baseUrl }) : null,
|
|
113
|
+
/* @__PURE__ */ jsx("span", { className: "ml-auto text-xs text-[var(--as-muted-fg)]", children: provider.keySet ? provider.keyHint ?? t.keyStoredLabel : t.noKeyLabel })
|
|
114
|
+
] }),
|
|
115
|
+
showProbeRow ? /* @__PURE__ */ jsx(
|
|
116
|
+
ConnectionTestRow,
|
|
117
|
+
{
|
|
118
|
+
variant: "inline",
|
|
119
|
+
status: probeStatus ?? "idle",
|
|
120
|
+
latencyMs: probe?.latencyMs ?? null,
|
|
121
|
+
label: catalog.entries[provider.type]?.label ?? provider.type,
|
|
122
|
+
testLabel: t.testLabel,
|
|
123
|
+
okLabel: t.probeLabels.ok ?? probe?.status ?? "ok",
|
|
124
|
+
failLabel: probeText ?? t.probeLabels.error ?? probe?.status ?? "failed",
|
|
125
|
+
errorMessage: probe && probe.status === "ok" ? null : probe?.error ?? null
|
|
126
|
+
}
|
|
127
|
+
) : null,
|
|
128
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
129
|
+
/* @__PURE__ */ jsx(
|
|
130
|
+
Button,
|
|
131
|
+
{
|
|
132
|
+
variant: "outline",
|
|
133
|
+
size: "sm",
|
|
134
|
+
disabled: busy || testingId === provider.id,
|
|
135
|
+
onClick: () => onTest(provider.id),
|
|
136
|
+
children: t.testLabel
|
|
137
|
+
}
|
|
138
|
+
),
|
|
139
|
+
/* @__PURE__ */ jsx(
|
|
140
|
+
Button,
|
|
141
|
+
{
|
|
142
|
+
variant: "ghost",
|
|
143
|
+
size: "icon",
|
|
144
|
+
"aria-label": `${t.moveUpLabel}: ${provider.name}`,
|
|
145
|
+
disabled: index === 0 || busy,
|
|
146
|
+
onClick: () => onMove(provider.id, "up"),
|
|
147
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-4", "aria-hidden": true })
|
|
148
|
+
}
|
|
149
|
+
),
|
|
150
|
+
/* @__PURE__ */ jsx(
|
|
151
|
+
Button,
|
|
152
|
+
{
|
|
153
|
+
variant: "ghost",
|
|
154
|
+
size: "icon",
|
|
155
|
+
"aria-label": `${t.moveDownLabel}: ${provider.name}`,
|
|
156
|
+
disabled: index === providers.length - 1 || busy,
|
|
157
|
+
onClick: () => onMove(provider.id, "down"),
|
|
158
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4", "aria-hidden": true })
|
|
159
|
+
}
|
|
160
|
+
),
|
|
161
|
+
/* @__PURE__ */ jsx(
|
|
162
|
+
Button,
|
|
163
|
+
{
|
|
164
|
+
variant: "ghost",
|
|
165
|
+
size: "icon",
|
|
166
|
+
"aria-label": `${t.editLabel}: ${provider.name}`,
|
|
167
|
+
disabled: busy,
|
|
168
|
+
onClick: () => openEdit(provider),
|
|
169
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "size-4", "aria-hidden": true })
|
|
170
|
+
}
|
|
171
|
+
),
|
|
172
|
+
/* @__PURE__ */ jsx(
|
|
173
|
+
Button,
|
|
174
|
+
{
|
|
175
|
+
variant: "ghost",
|
|
176
|
+
size: "icon",
|
|
177
|
+
"aria-label": `${t.deleteLabel}: ${provider.name}`,
|
|
178
|
+
disabled: busy,
|
|
179
|
+
onClick: () => onDelete(provider.id),
|
|
180
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "size-4", "aria-hidden": true })
|
|
181
|
+
}
|
|
182
|
+
),
|
|
183
|
+
!provider.enabled ? /* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--as-muted-fg)]", children: t.disabledBadge }) : null
|
|
184
|
+
] })
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
provider.id
|
|
188
|
+
);
|
|
189
|
+
}) }),
|
|
190
|
+
providers.length === 0 && draft === null ? /* @__PURE__ */ jsx("p", { className: "py-4 text-center text-sm text-[var(--as-muted-fg)]", "data-testid": "wsp-empty", children: t.emptyLabel }) : null,
|
|
191
|
+
draft !== null ? /* @__PURE__ */ jsxs(
|
|
192
|
+
"form",
|
|
193
|
+
{
|
|
194
|
+
"data-testid": "wsp-form",
|
|
195
|
+
className: "mt-3 space-y-2 rounded-[var(--as-radius-sm)] border border-[var(--as-border)] p-3",
|
|
196
|
+
onSubmit: (event) => {
|
|
197
|
+
event.preventDefault();
|
|
198
|
+
onSave(draft);
|
|
199
|
+
},
|
|
200
|
+
children: [
|
|
201
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
202
|
+
/* @__PURE__ */ jsx(
|
|
203
|
+
"select",
|
|
204
|
+
{
|
|
205
|
+
className: inputClass,
|
|
206
|
+
value: draft.type,
|
|
207
|
+
disabled: draft.id != null || busy,
|
|
208
|
+
"aria-label": t.typeLabel,
|
|
209
|
+
onChange: (event) => setDraft({ ...draft, type: event.target.value, googleCx: "" }),
|
|
210
|
+
children: catalog.order.map((type) => /* @__PURE__ */ jsx("option", { value: type, children: catalog.entries[type]?.label ?? type }, type))
|
|
211
|
+
}
|
|
212
|
+
),
|
|
213
|
+
/* @__PURE__ */ jsx(
|
|
214
|
+
"input",
|
|
215
|
+
{
|
|
216
|
+
className: inputClass,
|
|
217
|
+
placeholder: t.nameLabel,
|
|
218
|
+
value: draft.name ?? "",
|
|
219
|
+
onChange: (event) => setDraft({ ...draft, name: event.target.value })
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
] }),
|
|
223
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
224
|
+
/* @__PURE__ */ jsx(
|
|
225
|
+
"input",
|
|
226
|
+
{
|
|
227
|
+
className: inputClass,
|
|
228
|
+
placeholder: draftEntry?.baseUrlRequired ? t.baseUrlRequiredLabel : draftEntry?.baseUrlHint ?? t.baseUrlLabel,
|
|
229
|
+
value: draft.baseUrl ?? "",
|
|
230
|
+
onChange: (event) => setDraft({ ...draft, baseUrl: event.target.value })
|
|
231
|
+
}
|
|
232
|
+
),
|
|
233
|
+
draftCxField ? /* @__PURE__ */ jsx(
|
|
234
|
+
"input",
|
|
235
|
+
{
|
|
236
|
+
className: cn(inputClass, "w-48 flex-none"),
|
|
237
|
+
placeholder: draftEntry?.fields?.find((f) => f.id === "google_cx")?.placeholder ?? "",
|
|
238
|
+
"aria-label": draftEntry?.fields?.find((f) => f.id === "google_cx")?.label ?? "Engine id",
|
|
239
|
+
value: draft.googleCx ?? "",
|
|
240
|
+
onChange: (event) => setDraft({ ...draft, googleCx: event.target.value })
|
|
241
|
+
}
|
|
242
|
+
) : null,
|
|
243
|
+
/* @__PURE__ */ jsx(
|
|
244
|
+
"input",
|
|
245
|
+
{
|
|
246
|
+
type: "password",
|
|
247
|
+
className: cn(inputClass, "w-48 flex-none"),
|
|
248
|
+
placeholder: draft.id != null ? t.keyStoredLabel : draftEntry?.requiresKey ? t.keyLabel : t.keyOptionalLabel,
|
|
249
|
+
"aria-label": t.keyLabel,
|
|
250
|
+
value: draft.apiKey ?? "",
|
|
251
|
+
onChange: (event) => setDraft({ ...draft, apiKey: event.target.value })
|
|
252
|
+
}
|
|
253
|
+
)
|
|
254
|
+
] }),
|
|
255
|
+
draftEntry?.notes ? /* @__PURE__ */ jsx("p", { className: "text-[11px] text-[var(--as-muted-fg)]", children: draftEntry.notes }) : null,
|
|
256
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
257
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", type: "submit", disabled: saveDisabled, children: t.saveLabel }),
|
|
258
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", type: "button", onClick: () => setDraft(null), children: t.cancelLabel })
|
|
259
|
+
] })
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
) : null
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
export { WebSearchProvidersPanel };
|
|
269
|
+
//# sourceMappingURL=chunk-3Y6QOTVA.js.map
|
|
270
|
+
//# sourceMappingURL=chunk-3Y6QOTVA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/web-search-providers/WebSearchProvidersPanel.tsx"],"names":["WebSearchProvidersPanel"],"mappings":"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","file":"chunk-3Y6QOTVA.js","sourcesContent":["import * as React from 'react'\nimport { ChevronDown, ChevronUp, Pencil, Plus, Trash2 } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\nimport { ConnectionTestRow, type ConnectionTestStatus } from '../connection-test-row/ConnectionTestRow'\n\nexport type WebSearchProbeStatus =\n | 'ok'\n | 'unreachable'\n | 'auth'\n | 'rate_limit'\n | 'json_disabled'\n | 'error'\n\nexport interface WebSearchProviderView {\n id: string\n name: string\n type: string\n enabled: boolean\n baseUrl?: string | null\n googleCx?: string | null\n keyHint?: string | null\n keySet: boolean\n}\n\nexport interface WebSearchProviderCatalogField {\n id: string\n label: string\n required: boolean\n placeholder?: string\n}\n\nexport interface WebSearchProviderCatalogEntry {\n label: string\n requiresKey: boolean\n keyUrl?: string | null\n baseUrl?: string | null\n baseUrlRequired: boolean\n baseUrlHint?: string | null\n notes?: string | null\n fields?: WebSearchProviderCatalogField[]\n}\n\nexport interface WebSearchProviderCatalog {\n /** Rendering + form order for provider types. */\n order: string[]\n entries: Record<string, WebSearchProviderCatalogEntry>\n}\n\nexport interface WebSearchProviderSaveInput {\n /** Absent = create. */\n id?: string\n type: string\n name?: string | null\n baseUrl?: string | null\n googleCx?: string | null\n /** `null` keeps the stored key, a value stores it. */\n apiKey?: string | null\n}\n\nexport interface WebSearchProviderProbeView {\n status: WebSearchProbeStatus\n latencyMs?: number | null\n error?: string | null\n}\n\nexport interface WebSearchProvidersPanelLabels {\n title?: string\n hint?: string\n addLabel?: string\n emptyLabel?: string\n nameLabel?: string\n typeLabel?: string\n baseUrlLabel?: string\n baseUrlRequiredLabel?: string\n keyLabel?: string\n keyOptionalLabel?: string\n keyStoredLabel?: string\n noKeyLabel?: string\n saveLabel?: string\n cancelLabel?: string\n editLabel?: string\n deleteLabel?: string\n moveUpLabel?: string\n moveDownLabel?: string\n enabledAriaLabel?: string\n disabledBadge?: string\n testLabel?: string\n probeLabels?: Partial<Record<WebSearchProbeStatus, string>>\n}\n\nexport interface WebSearchProvidersPanelProps {\n providers: WebSearchProviderView[]\n catalog: WebSearchProviderCatalog\n /** Connection probes keyed by provider id. */\n probes?: Record<string, WebSearchProviderProbeView>\n /** Id currently mid-test (shows the testing spinner). */\n testingId?: string | null\n busy?: boolean\n labels?: WebSearchProvidersPanelLabels\n onSave: (input: WebSearchProviderSaveInput) => void\n onDelete: (id: string) => void\n onMove: (id: string, direction: 'up' | 'down') => void\n onToggle: (id: string, enabled: boolean) => void\n onTest: (id: string) => void\n className?: string\n}\n\nconst inputClass =\n 'min-w-0 flex-1 rounded-[var(--as-radius-sm)] border border-[var(--as-border)] bg-[var(--as-surface)] px-2 py-1.5 text-sm text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]'\n\n/**\n * Presentational ordered web-search provider list (ADR-0035 family shape):\n * enable/reorder/test/edit/delete rows plus a catalog-driven add/edit form.\n * Fully controlled — persistence, keys and probes are app-side; the panel\n * renders and emits. The first enabled provider that answers wins is the\n * family's fallback semantics, surfaced here by row order.\n */\nexport const WebSearchProvidersPanel = React.forwardRef<\n HTMLDivElement,\n WebSearchProvidersPanelProps\n>(function WebSearchProvidersPanel(\n {\n providers,\n catalog,\n probes = {},\n testingId = null,\n busy = false,\n labels,\n onSave,\n onDelete,\n onMove,\n onToggle,\n onTest,\n className,\n },\n ref,\n) {\n const t = React.useMemo(\n () => ({\n title: labels?.title ?? 'Web search providers',\n hint: labels?.hint,\n addLabel: labels?.addLabel ?? 'Add provider',\n emptyLabel: labels?.emptyLabel ?? 'No web search providers yet.',\n nameLabel: labels?.nameLabel ?? 'Name (optional)',\n typeLabel: labels?.typeLabel ?? 'Provider type',\n baseUrlLabel: labels?.baseUrlLabel ?? 'Base URL (optional)',\n baseUrlRequiredLabel: labels?.baseUrlRequiredLabel ?? 'Base URL (required)',\n keyLabel: labels?.keyLabel ?? 'API key',\n keyOptionalLabel: labels?.keyOptionalLabel ?? 'API key (optional)',\n keyStoredLabel: labels?.keyStoredLabel ?? 'API key saved',\n noKeyLabel: labels?.noKeyLabel ?? 'no key',\n saveLabel: labels?.saveLabel ?? 'Save provider',\n cancelLabel: labels?.cancelLabel ?? 'Cancel',\n editLabel: labels?.editLabel ?? 'Edit provider',\n deleteLabel: labels?.deleteLabel ?? 'Delete provider',\n moveUpLabel: labels?.moveUpLabel ?? 'Move up',\n moveDownLabel: labels?.moveDownLabel ?? 'Move down',\n enabledAriaLabel: labels?.enabledAriaLabel ?? 'Enable provider',\n disabledBadge: labels?.disabledBadge ?? 'disabled',\n testLabel: labels?.testLabel ?? 'Test',\n probeLabels: { ...labels?.probeLabels },\n }),\n [labels],\n )\n\n const [draft, setDraft] = React.useState<WebSearchProviderSaveInput | null>(null)\n\n const openAdd = () => {\n const first = catalog.order[0]\n if (first) setDraft({ type: first, name: '', baseUrl: '', googleCx: '', apiKey: null })\n }\n\n const openEdit = (provider: WebSearchProviderView) =>\n setDraft({\n id: provider.id,\n type: provider.type,\n name: provider.name,\n baseUrl: provider.baseUrl ?? '',\n googleCx: provider.googleCx ?? '',\n apiKey: null,\n })\n\n const draftEntry = draft ? catalog.entries[draft.type] : undefined\n const draftCxField = draftEntry?.fields?.some((field) => field.id === 'google_cx') ?? false\n const saveDisabled =\n busy ||\n (draftEntry?.baseUrlRequired && !(draft?.baseUrl ?? '').trim()) ||\n (draft?.id == null && (draftEntry?.requiresKey ?? false) && !(draft?.apiKey ?? '').trim())\n\n return (\n <div\n ref={ref}\n data-as=\"web-search-providers\"\n className={cn(\n 'rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] p-4',\n className,\n )}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"text-base font-medium text-[var(--as-fg)]\">{t.title}</p>\n {t.hint ? (\n <p className=\"mt-0.5 text-xs text-[var(--as-muted-fg)]\">{t.hint}</p>\n ) : null}\n </div>\n {draft === null ? (\n <Button variant=\"outline\" size=\"sm\" onClick={openAdd}>\n <Plus className=\"size-4\" aria-hidden />\n {t.addLabel}\n </Button>\n ) : null}\n </div>\n\n <ul className=\"mt-3 space-y-2\" data-testid=\"wsp-rows\">\n {providers.map((provider, index) => {\n const probe = probes[provider.id]\n const isTesting = testingId === provider.id\n const showProbeRow = probe != null || isTesting\n const probeStatus: ConnectionTestStatus | null = !showProbeRow\n ? null\n : isTesting\n ? 'testing'\n : probe!.status === 'ok'\n ? 'ok'\n : 'fail'\n const probeText =\n probe && probe.status !== 'ok' && probe.error\n ? probe.error\n : probe\n ? (t.probeLabels[probe.status] ?? probe.status)\n : null\n return (\n <li\n key={provider.id}\n data-testid={`wsp-row-${provider.id}`}\n className=\"border-border border-[var(--as-border)] space-y-1 rounded-[var(--as-radius-sm)] border p-3\"\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <label className=\"flex cursor-pointer items-center gap-2 text-sm font-medium text-[var(--as-fg)]\">\n <input\n type=\"checkbox\"\n checked={provider.enabled}\n aria-label={`${t.enabledAriaLabel}: ${provider.name}`}\n onChange={(event) => onToggle(provider.id, event.target.checked)}\n />\n {provider.name}\n </label>\n <span className=\"rounded-full bg-[var(--as-secondary)] px-2 py-0.5 text-[11px] text-[var(--as-muted-fg)]\">\n {catalog.entries[provider.type]?.label ?? provider.type}\n </span>\n {provider.baseUrl ? (\n <span className=\"truncate font-mono text-xs text-[var(--as-muted-fg)]\">\n {provider.baseUrl}\n </span>\n ) : null}\n <span className=\"ml-auto text-xs text-[var(--as-muted-fg)]\">\n {provider.keySet\n ? (provider.keyHint ?? t.keyStoredLabel)\n : t.noKeyLabel}\n </span>\n </div>\n {showProbeRow ? (\n <ConnectionTestRow\n variant=\"inline\"\n status={probeStatus ?? 'idle'}\n latencyMs={probe?.latencyMs ?? null}\n label={catalog.entries[provider.type]?.label ?? provider.type}\n testLabel={t.testLabel}\n okLabel={t.probeLabels.ok ?? probe?.status ?? 'ok'}\n failLabel={probeText ?? t.probeLabels.error ?? probe?.status ?? 'failed'}\n errorMessage={probe && probe.status === 'ok' ? null : (probe?.error ?? null)}\n />\n ) : null}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={busy || testingId === provider.id}\n onClick={() => onTest(provider.id)}\n >\n {t.testLabel}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.moveUpLabel}: ${provider.name}`}\n disabled={index === 0 || busy}\n onClick={() => onMove(provider.id, 'up')}\n >\n <ChevronUp className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.moveDownLabel}: ${provider.name}`}\n disabled={index === providers.length - 1 || busy}\n onClick={() => onMove(provider.id, 'down')}\n >\n <ChevronDown className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.editLabel}: ${provider.name}`}\n disabled={busy}\n onClick={() => openEdit(provider)}\n >\n <Pencil className=\"size-4\" aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`${t.deleteLabel}: ${provider.name}`}\n disabled={busy}\n onClick={() => onDelete(provider.id)}\n >\n <Trash2 className=\"size-4\" aria-hidden />\n </Button>\n {!provider.enabled ? (\n <span className=\"text-xs text-[var(--as-muted-fg)]\">\n {t.disabledBadge}\n </span>\n ) : null}\n </div>\n </li>\n )\n })}\n </ul>\n\n {providers.length === 0 && draft === null ? (\n <p className=\"py-4 text-center text-sm text-[var(--as-muted-fg)]\" data-testid=\"wsp-empty\">\n {t.emptyLabel}\n </p>\n ) : null}\n\n {draft !== null ? (\n <form\n data-testid=\"wsp-form\"\n className=\"mt-3 space-y-2 rounded-[var(--as-radius-sm)] border border-[var(--as-border)] p-3\"\n onSubmit={(event) => {\n event.preventDefault()\n onSave(draft)\n }}\n >\n <div className=\"flex flex-wrap gap-2\">\n <select\n className={inputClass}\n value={draft.type}\n disabled={draft.id != null || busy}\n aria-label={t.typeLabel}\n onChange={(event) =>\n setDraft({ ...draft, type: event.target.value, googleCx: '' })\n }\n >\n {catalog.order.map((type) => (\n <option key={type} value={type}>\n {catalog.entries[type]?.label ?? type}\n </option>\n ))}\n </select>\n <input\n className={inputClass}\n placeholder={t.nameLabel}\n value={draft.name ?? ''}\n onChange={(event) => setDraft({ ...draft, name: event.target.value })}\n />\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={inputClass}\n placeholder={\n draftEntry?.baseUrlRequired\n ? t.baseUrlRequiredLabel\n : (draftEntry?.baseUrlHint ?? t.baseUrlLabel)\n }\n value={draft.baseUrl ?? ''}\n onChange={(event) => setDraft({ ...draft, baseUrl: event.target.value })}\n />\n {draftCxField ? (\n <input\n className={cn(inputClass, 'w-48 flex-none')}\n placeholder={draftEntry?.fields?.find((f) => f.id === 'google_cx')?.placeholder ?? ''}\n aria-label={draftEntry?.fields?.find((f) => f.id === 'google_cx')?.label ?? 'Engine id'}\n value={draft.googleCx ?? ''}\n onChange={(event) => setDraft({ ...draft, googleCx: event.target.value })}\n />\n ) : null}\n <input\n type=\"password\"\n className={cn(inputClass, 'w-48 flex-none')}\n placeholder={\n draft.id != null\n ? t.keyStoredLabel\n : draftEntry?.requiresKey\n ? t.keyLabel\n : t.keyOptionalLabel\n }\n aria-label={t.keyLabel}\n value={draft.apiKey ?? ''}\n onChange={(event) => setDraft({ ...draft, apiKey: event.target.value })}\n />\n </div>\n {draftEntry?.notes ? (\n <p className=\"text-[11px] text-[var(--as-muted-fg)]\">{draftEntry.notes}</p>\n ) : null}\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" type=\"submit\" disabled={saveDisabled}>\n {t.saveLabel}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" type=\"button\" onClick={() => setDraft(null)}>\n {t.cancelLabel}\n </Button>\n </div>\n </form>\n ) : null}\n </div>\n )\n})\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CapabilityChips } from './chunk-H5KOC7Z5.js';
|
|
2
|
-
import { ModelPicker } from './chunk-
|
|
2
|
+
import { ModelPicker } from './chunk-X6L5T65Q.js';
|
|
3
3
|
import { Modal, ModalContent, ModalHeader, ModalTitle, ModalFooter } from './chunk-FVQWIDB5.js';
|
|
4
4
|
import { beautifyId } from './chunk-B2G66OSQ.js';
|
|
5
5
|
import { Button } from './chunk-4WBBF5LH.js';
|
|
@@ -742,5 +742,5 @@ var ModelRegistry = React.forwardRef(
|
|
|
742
742
|
);
|
|
743
743
|
|
|
744
744
|
export { ModelRegistry };
|
|
745
|
-
//# sourceMappingURL=chunk-
|
|
746
|
-
//# sourceMappingURL=chunk-
|
|
745
|
+
//# sourceMappingURL=chunk-GR6CSKQY.js.map
|
|
746
|
+
//# sourceMappingURL=chunk-GR6CSKQY.js.map
|