@truefoundry/trueforge-ui 0.0.0 → 0.1.0-rc.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 (55) hide show
  1. package/CHANGELOG.md +340 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +17 -0
  4. package/README.md +640 -3
  5. package/dist/ConnectorSettings-CLBEWGQJ.js +898 -0
  6. package/dist/ConnectorSettings-CLBEWGQJ.js.map +1 -0
  7. package/dist/DockLayout-WRF7EQLD.js +35 -0
  8. package/dist/DockLayout-WRF7EQLD.js.map +1 -0
  9. package/dist/DrawerLayout-X2UXYTOS.js +156 -0
  10. package/dist/DrawerLayout-X2UXYTOS.js.map +1 -0
  11. package/dist/ModelSettings-IJ55QJQO.js +1082 -0
  12. package/dist/ModelSettings-IJ55QJQO.js.map +1 -0
  13. package/dist/OpenUiFenceBlock-SLLZSTMJ.js +9 -0
  14. package/dist/OpenUiFenceBlock-SLLZSTMJ.js.map +1 -0
  15. package/dist/SandboxSettings-S5XGZWOL.js +505 -0
  16. package/dist/SandboxSettings-S5XGZWOL.js.map +1 -0
  17. package/dist/SettingsBuilder-64Y33NP3.js +128 -0
  18. package/dist/SettingsBuilder-64Y33NP3.js.map +1 -0
  19. package/dist/SidebarLayout-M7HEOZVK.js +236 -0
  20. package/dist/SidebarLayout-M7HEOZVK.js.map +1 -0
  21. package/dist/SkillSettings-MXK4ZEI7.js +389 -0
  22. package/dist/SkillSettings-MXK4ZEI7.js.map +1 -0
  23. package/dist/WidgetLayout-7MDOKLHU.js +101 -0
  24. package/dist/WidgetLayout-7MDOKLHU.js.map +1 -0
  25. package/dist/assistant-ui.d.ts +1 -0
  26. package/dist/assistant-ui.js +9 -0
  27. package/dist/assistant-ui.js.map +1 -0
  28. package/dist/chunk-42GF723P.js +24 -0
  29. package/dist/chunk-42GF723P.js.map +1 -0
  30. package/dist/chunk-CFLVPV5M.js +29 -0
  31. package/dist/chunk-CFLVPV5M.js.map +1 -0
  32. package/dist/chunk-M6MHLVSO.js +8 -0
  33. package/dist/chunk-M6MHLVSO.js.map +1 -0
  34. package/dist/chunk-NBMP2XNL.js +89 -0
  35. package/dist/chunk-NBMP2XNL.js.map +1 -0
  36. package/dist/chunk-UBOFEI77.js +567 -0
  37. package/dist/chunk-UBOFEI77.js.map +1 -0
  38. package/dist/chunk-UHGSHDBM.js +633 -0
  39. package/dist/chunk-UHGSHDBM.js.map +1 -0
  40. package/dist/chunk-UXZOL5GO.js +2088 -0
  41. package/dist/chunk-UXZOL5GO.js.map +1 -0
  42. package/dist/chunk-WFC3W4C3.js +73 -0
  43. package/dist/chunk-WFC3W4C3.js.map +1 -0
  44. package/dist/chunk-XSHXH6EI.js +6800 -0
  45. package/dist/chunk-XSHXH6EI.js.map +1 -0
  46. package/dist/createTrueFoundryServer-B72bU-J7.d.ts +28 -0
  47. package/dist/index.d.ts +1569 -0
  48. package/dist/index.js +781 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +479 -0
  51. package/dist/plugins/trueforge-agent-server-adapter/index.js +830 -0
  52. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -0
  53. package/dist/styles.css +2 -0
  54. package/package.json +129 -6
  55. package/index.js +0 -1
@@ -0,0 +1,389 @@
1
+ "use client";
2
+ import {
3
+ Button,
4
+ CenteredModal,
5
+ SearchInput_default,
6
+ auiInputClass,
7
+ getErrorMessage,
8
+ useToasterOptional
9
+ } from "./chunk-XSHXH6EI.js";
10
+ import {
11
+ Icon,
12
+ useCatalogServer
13
+ } from "./chunk-UHGSHDBM.js";
14
+ import "./chunk-42GF723P.js";
15
+ import "./chunk-UBOFEI77.js";
16
+
17
+ // src/containers/SettingsBuilder/SkillSettings.tsx
18
+ import { useCallback, useEffect, useMemo, useState as useState2 } from "react";
19
+
20
+ // src/containers/SettingsBuilder/ImportGithubSkillForm.tsx
21
+ import { useState } from "react";
22
+ import { jsx, jsxs } from "react/jsx-runtime";
23
+ var ImportGithubSkillForm = ({ open, onOpenChange, onImport, busy = false, error }) => {
24
+ const [name, setName] = useState("");
25
+ const [description, setDescription] = useState("");
26
+ const [repoURL, setRepoURL] = useState("");
27
+ const [path, setPath] = useState("");
28
+ const [ref, setRef] = useState("");
29
+ const reset = () => {
30
+ setName("");
31
+ setDescription("");
32
+ setRepoURL("");
33
+ setPath("");
34
+ setRef("");
35
+ };
36
+ const close = () => {
37
+ reset();
38
+ onOpenChange(false);
39
+ };
40
+ const handleSubmit = async (event) => {
41
+ event.preventDefault();
42
+ if (!name.trim() || !description.trim() || !repoURL.trim() || !path.trim() || !ref.trim() || busy) return;
43
+ try {
44
+ await onImport({
45
+ name: name.trim(),
46
+ description: description.trim(),
47
+ repoURL: repoURL.trim(),
48
+ path: path.trim(),
49
+ ref: ref.trim()
50
+ });
51
+ close();
52
+ } catch {
53
+ }
54
+ };
55
+ const canImport = Boolean(name.trim() && description.trim() && repoURL.trim() && path.trim() && ref.trim()) && !busy;
56
+ return /* @__PURE__ */ jsx(
57
+ CenteredModal,
58
+ {
59
+ open,
60
+ onOpenChange: (nextOpen) => {
61
+ if (!nextOpen) close();
62
+ },
63
+ title: "Import from GitHub",
64
+ description: "Import a skill from a SKILL.md file in a GitHub repository.",
65
+ headerIcon: /* @__PURE__ */ jsx("span", { className: "flex size-11 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary", children: /* @__PURE__ */ jsx(Icon, { name: "github", className: "size-5" }) }),
66
+ contentSized: true,
67
+ className: "md:max-w-2xl",
68
+ children: /* @__PURE__ */ jsx("form", { onSubmit: (e) => void handleSubmit(e), children: /* @__PURE__ */ jsxs("div", { className: "space-y-5 px-5 py-5 md:px-6", children: [
69
+ /* @__PURE__ */ jsxs("div", { children: [
70
+ /* @__PURE__ */ jsx("label", { htmlFor: "skill-name", className: "mb-2 block text-sm font-semibold text-text-primary", children: "Name" }),
71
+ /* @__PURE__ */ jsx(
72
+ "input",
73
+ {
74
+ id: "skill-name",
75
+ value: name,
76
+ onChange: (event) => {
77
+ setName(event.target.value);
78
+ },
79
+ placeholder: "release-notes",
80
+ autoFocus: true,
81
+ required: true,
82
+ className: auiInputClass("h-11")
83
+ }
84
+ )
85
+ ] }),
86
+ /* @__PURE__ */ jsxs("div", { children: [
87
+ /* @__PURE__ */ jsx("label", { htmlFor: "skill-description", className: "mb-2 block text-sm font-semibold text-text-primary", children: "Description" }),
88
+ /* @__PURE__ */ jsx(
89
+ "textarea",
90
+ {
91
+ id: "skill-description",
92
+ value: description,
93
+ onChange: (event) => {
94
+ setDescription(event.target.value);
95
+ },
96
+ placeholder: "Generate release notes from merged pull requests",
97
+ required: true,
98
+ rows: 3,
99
+ className: auiInputClass("resize-y py-2.5")
100
+ }
101
+ )
102
+ ] }),
103
+ /* @__PURE__ */ jsxs("div", { children: [
104
+ /* @__PURE__ */ jsx("label", { htmlFor: "skill-repo-url", className: "mb-2 block text-sm font-semibold text-text-primary", children: "Repository URL" }),
105
+ /* @__PURE__ */ jsx(
106
+ "input",
107
+ {
108
+ id: "skill-repo-url",
109
+ type: "url",
110
+ value: repoURL,
111
+ onChange: (event) => {
112
+ setRepoURL(event.target.value);
113
+ },
114
+ placeholder: "https://github.com/org/repo",
115
+ required: true,
116
+ className: auiInputClass("h-11")
117
+ }
118
+ )
119
+ ] }),
120
+ /* @__PURE__ */ jsxs("div", { children: [
121
+ /* @__PURE__ */ jsx("label", { htmlFor: "skill-path", className: "mb-2 block text-sm font-semibold text-text-primary", children: "Folder containing the SKILL.md" }),
122
+ /* @__PURE__ */ jsx(
123
+ "input",
124
+ {
125
+ id: "skill-path",
126
+ value: path,
127
+ onChange: (event) => {
128
+ setPath(event.target.value);
129
+ },
130
+ placeholder: "skills/release-notes",
131
+ required: true,
132
+ className: auiInputClass("h-11")
133
+ }
134
+ )
135
+ ] }),
136
+ /* @__PURE__ */ jsxs("div", { children: [
137
+ /* @__PURE__ */ jsx("label", { htmlFor: "skill-ref", className: "mb-2 block text-sm font-semibold text-text-primary", children: "Branch" }),
138
+ /* @__PURE__ */ jsx(
139
+ "input",
140
+ {
141
+ id: "skill-ref",
142
+ value: ref,
143
+ onChange: (event) => {
144
+ setRef(event.target.value);
145
+ },
146
+ placeholder: "main",
147
+ required: true,
148
+ className: auiInputClass("h-11")
149
+ }
150
+ )
151
+ ] }),
152
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
153
+ error ? /* @__PURE__ */ jsx("p", { className: "text-failure-bg text-sm", children: error }) : null,
154
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !canImport, className: "w-full", children: "Import" })
155
+ ] })
156
+ ] }) })
157
+ }
158
+ );
159
+ };
160
+ var ImportGithubSkillForm_default = ImportGithubSkillForm;
161
+
162
+ // src/containers/SettingsBuilder/SkillSettings.tsx
163
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
164
+ var matchesQuery = (query, name, description) => !query || name.toLowerCase().includes(query) || description.toLowerCase().includes(query);
165
+ var isRegistrySkill = (skill) => "catalogId" in skill;
166
+ var SkillSettings = () => {
167
+ const { skillCatalog } = useCatalogServer();
168
+ const toaster = useToasterOptional();
169
+ const [query, setQuery] = useState2("");
170
+ const [skills, setSkills] = useState2([]);
171
+ const [catalog, setCatalog] = useState2([]);
172
+ const [loading, setLoading] = useState2(true);
173
+ const [error, setError] = useState2(null);
174
+ const [formError, setFormError] = useState2(null);
175
+ const [busy, setBusy] = useState2(false);
176
+ const [importOpen, setImportOpen] = useState2(false);
177
+ const refresh = useCallback(async () => {
178
+ if (!skillCatalog) return;
179
+ setLoading(true);
180
+ setError(null);
181
+ try {
182
+ const [defined, available] = await Promise.all([skillCatalog.listSkills(), skillCatalog.getSkillCatalog()]);
183
+ setSkills(defined);
184
+ setCatalog(available);
185
+ } catch (err) {
186
+ setError(getErrorMessage(err, "Failed to load skills"));
187
+ } finally {
188
+ setLoading(false);
189
+ }
190
+ }, [skillCatalog]);
191
+ useEffect(() => {
192
+ void refresh();
193
+ }, [refresh]);
194
+ const normalizedQuery = query.trim().toLowerCase();
195
+ const selectedSkills = useMemo(
196
+ () => skills.filter((skill) => matchesQuery(normalizedQuery, skill.name, skill.description)),
197
+ [skills, normalizedQuery]
198
+ );
199
+ const availableSkills = useMemo(() => {
200
+ const selectedCatalogIds = new Set(skills.flatMap((skill) => isRegistrySkill(skill) ? [skill.catalogId] : []));
201
+ return catalog.filter(
202
+ (entry) => !selectedCatalogIds.has(entry.id) && matchesQuery(normalizedQuery, entry.name, entry.description)
203
+ );
204
+ }, [catalog, skills, normalizedQuery]);
205
+ const runMutation = async (fn, setMutationError = setError) => {
206
+ setBusy(true);
207
+ setError(null);
208
+ try {
209
+ await fn();
210
+ await refresh();
211
+ } catch (err) {
212
+ setMutationError(getErrorMessage(err, "Request failed"));
213
+ throw err;
214
+ } finally {
215
+ setBusy(false);
216
+ }
217
+ };
218
+ if (!skillCatalog) {
219
+ return /* @__PURE__ */ jsx2("p", { className: "text-sm text-text-secondary", children: "Skills catalog is not available." });
220
+ }
221
+ const handleSelect = (entry) => {
222
+ void runMutation(async () => {
223
+ await skillCatalog.createSkill({
224
+ catalogId: entry.id,
225
+ name: entry.name,
226
+ description: entry.description,
227
+ repoURL: entry.repoURL,
228
+ path: entry.path,
229
+ ref: entry.ref
230
+ });
231
+ }).catch(() => {
232
+ });
233
+ };
234
+ const handleRemove = (skill) => {
235
+ const deleteSkill = skillCatalog.deleteSkill;
236
+ if (!deleteSkill) return;
237
+ void runMutation(async () => {
238
+ await deleteSkill({ id: skill.id });
239
+ }).catch(() => {
240
+ });
241
+ };
242
+ const handleImport = async (draft) => {
243
+ setFormError(null);
244
+ await runMutation(async () => {
245
+ await skillCatalog.createSkill(draft);
246
+ }, setFormError);
247
+ setTimeout(() => {
248
+ toaster?.showSuccess({ title: `${draft.name} imported` });
249
+ }, 0);
250
+ };
251
+ const renderRow = ({
252
+ key,
253
+ name,
254
+ description,
255
+ action
256
+ }) => /* @__PURE__ */ jsxs2("article", { className: "flex min-h-16 items-center gap-3 border-b border-border p-3 last:border-b-0", children: [
257
+ /* @__PURE__ */ jsx2(
258
+ "span",
259
+ {
260
+ className: "flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg",
261
+ "aria-hidden": true,
262
+ children: /* @__PURE__ */ jsx2(Icon, { name: "lightbulb", className: "size-4.5 text-text-primary" })
263
+ }
264
+ ),
265
+ /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
266
+ /* @__PURE__ */ jsx2("h5", { className: "truncate text-sm font-medium text-text-primary", children: name }),
267
+ description ? /* @__PURE__ */ jsx2("p", { className: "mt-0.5 truncate text-sm text-text-secondary", children: description }) : null
268
+ ] }),
269
+ action
270
+ ] }, key);
271
+ const hasMatches = selectedSkills.length > 0 || availableSkills.length > 0;
272
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
273
+ /* @__PURE__ */ jsx2("h3", { className: "text-xl font-semibold tracking-tight text-text-primary", children: "Skills" }),
274
+ /* @__PURE__ */ jsx2("p", { className: "mt-1 text-sm text-text-secondary", children: "Use built-in skills or import custom skills from GitHub." }),
275
+ error ? /* @__PURE__ */ jsx2("p", { className: "mt-3 rounded-md border border-failure-bg/30 bg-failure-bg/10 px-3 py-2 text-sm text-failure-bg", children: error }) : null,
276
+ /* @__PURE__ */ jsxs2("div", { className: "mt-4 flex min-h-0 flex-1 flex-col gap-3", children: [
277
+ /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2 sm:flex-row", children: [
278
+ /* @__PURE__ */ jsx2("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx2(SearchInput_default, { query, setQuery, placeholder: "Search skills" }) }),
279
+ /* @__PURE__ */ jsxs2(
280
+ Button,
281
+ {
282
+ variant: "secondary",
283
+ type: "button",
284
+ className: "shrink-0",
285
+ disabled: busy,
286
+ onClick: () => {
287
+ setFormError(null);
288
+ setImportOpen(true);
289
+ },
290
+ children: [
291
+ /* @__PURE__ */ jsx2(Icon, { name: "github", className: "size-4" }),
292
+ "Import from GitHub"
293
+ ]
294
+ }
295
+ )
296
+ ] }),
297
+ /* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col gap-5 overflow-y-auto pb-1", children: [
298
+ loading ? /* @__PURE__ */ jsx2("p", { className: "py-8 text-center text-sm text-text-secondary", children: "Loading\u2026" }) : null,
299
+ !loading && selectedSkills.length > 0 ? /* @__PURE__ */ jsxs2("section", { "aria-labelledby": "enabled-skills-heading", children: [
300
+ /* @__PURE__ */ jsxs2(
301
+ "h4",
302
+ {
303
+ id: "enabled-skills-heading",
304
+ className: "mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary",
305
+ children: [
306
+ "Enabled \xB7 ",
307
+ selectedSkills.length
308
+ ]
309
+ }
310
+ ),
311
+ /* @__PURE__ */ jsx2("div", { className: "overflow-hidden rounded-xl border border-border bg-card-bg", children: selectedSkills.map(
312
+ (skill) => renderRow({
313
+ key: skill.id,
314
+ name: skill.name,
315
+ description: skill.description,
316
+ action: skillCatalog.deleteSkill ? /* @__PURE__ */ jsx2(
317
+ Button,
318
+ {
319
+ variant: "outline",
320
+ size: "sm",
321
+ type: "button",
322
+ disabled: busy,
323
+ "aria-label": `Remove ${skill.name}`,
324
+ onClick: () => {
325
+ handleRemove(skill);
326
+ },
327
+ children: "Remove"
328
+ }
329
+ ) : null
330
+ })
331
+ ) })
332
+ ] }) : null,
333
+ !loading && availableSkills.length > 0 ? /* @__PURE__ */ jsxs2("section", { "aria-labelledby": "available-skills-heading", children: [
334
+ /* @__PURE__ */ jsxs2(
335
+ "h4",
336
+ {
337
+ id: "available-skills-heading",
338
+ className: "mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary",
339
+ children: [
340
+ "Available \xB7 ",
341
+ availableSkills.length
342
+ ]
343
+ }
344
+ ),
345
+ /* @__PURE__ */ jsx2("div", { className: "overflow-hidden rounded-xl border border-border bg-card-bg", children: availableSkills.map(
346
+ (entry) => renderRow({
347
+ key: entry.id,
348
+ name: entry.name,
349
+ description: entry.description,
350
+ action: /* @__PURE__ */ jsx2(
351
+ Button,
352
+ {
353
+ variant: "outline",
354
+ size: "sm",
355
+ type: "button",
356
+ disabled: busy,
357
+ "aria-label": `Enable ${entry.name}`,
358
+ onClick: () => {
359
+ handleSelect(entry);
360
+ },
361
+ children: "Enable"
362
+ }
363
+ )
364
+ })
365
+ ) })
366
+ ] }) : null,
367
+ !loading && !hasMatches ? /* @__PURE__ */ jsx2("div", { className: "flex flex-1 items-center justify-center rounded-xl border border-dashed border-border p-8 text-center text-sm text-text-secondary", children: normalizedQuery ? `No skills match \u201C${query.trim()}\u201D.` : "No skills yet." }) : null
368
+ ] })
369
+ ] }),
370
+ /* @__PURE__ */ jsx2(
371
+ ImportGithubSkillForm_default,
372
+ {
373
+ open: importOpen,
374
+ onOpenChange: (open) => {
375
+ setImportOpen(open);
376
+ if (!open) setFormError(null);
377
+ },
378
+ onImport: handleImport,
379
+ busy,
380
+ error: formError
381
+ }
382
+ )
383
+ ] });
384
+ };
385
+ var SkillSettings_default = SkillSettings;
386
+ export {
387
+ SkillSettings_default as default
388
+ };
389
+ //# sourceMappingURL=SkillSettings-MXK4ZEI7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/containers/SettingsBuilder/SkillSettings.tsx","../src/containers/SettingsBuilder/ImportGithubSkillForm.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react';\n\nimport { Button } from '@/atoms/primitives/Button.js';\nimport SearchInput from '@/atoms/primitives/SearchInput.js';\nimport { Icon } from '@/icons/Icon.js';\nimport { useCatalogServer } from '../../server/ServerContext.js';\nimport type { RegistrySkill, SkillBase, SkillCatalogEntry, SkillConfigBase } from '../../server/types.js';\nimport { getErrorMessage } from '../../utils/getErrorMessage.js';\nimport { useToasterOptional } from '../ToasterContainer.js';\nimport ImportGithubSkillForm from './ImportGithubSkillForm.js';\n\nconst matchesQuery = (query: string, name: string, description: string) =>\n !query || name.toLowerCase().includes(query) || description.toLowerCase().includes(query);\n\nconst isRegistrySkill = (skill: SkillBase): skill is RegistrySkill => 'catalogId' in skill;\n\nconst SkillSettings = () => {\n const { skillCatalog } = useCatalogServer();\n const toaster = useToasterOptional();\n\n const [query, setQuery] = useState('');\n const [skills, setSkills] = useState<SkillBase[]>([]);\n const [catalog, setCatalog] = useState<SkillCatalogEntry[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [importOpen, setImportOpen] = useState(false);\n\n const refresh = useCallback(async () => {\n if (!skillCatalog) return;\n setLoading(true);\n setError(null);\n try {\n const [defined, available] = await Promise.all([skillCatalog.listSkills(), skillCatalog.getSkillCatalog()]);\n setSkills(defined);\n setCatalog(available);\n } catch (err) {\n setError(getErrorMessage(err, 'Failed to load skills'));\n } finally {\n setLoading(false);\n }\n }, [skillCatalog]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n const normalizedQuery = query.trim().toLowerCase();\n\n const selectedSkills = useMemo(\n () => skills.filter(skill => matchesQuery(normalizedQuery, skill.name, skill.description)),\n [skills, normalizedQuery],\n );\n\n const availableSkills = useMemo(() => {\n const selectedCatalogIds = new Set(skills.flatMap(skill => (isRegistrySkill(skill) ? [skill.catalogId] : [])));\n return catalog.filter(\n entry => !selectedCatalogIds.has(entry.id) && matchesQuery(normalizedQuery, entry.name, entry.description),\n );\n }, [catalog, skills, normalizedQuery]);\n\n const runMutation = async (fn: () => Promise<void>, setMutationError = setError) => {\n setBusy(true);\n setError(null);\n try {\n await fn();\n await refresh();\n } catch (err) {\n setMutationError(getErrorMessage(err, 'Request failed'));\n throw err;\n } finally {\n setBusy(false);\n }\n };\n\n if (!skillCatalog) {\n return <p className=\"text-sm text-text-secondary\">Skills catalog is not available.</p>;\n }\n\n const handleSelect = (entry: SkillCatalogEntry) => {\n void runMutation(async () => {\n await skillCatalog.createSkill({\n catalogId: entry.id,\n name: entry.name,\n description: entry.description,\n repoURL: entry.repoURL,\n path: entry.path,\n ref: entry.ref,\n });\n }).catch(() => {});\n };\n\n const handleRemove = (skill: SkillBase) => {\n const deleteSkill = skillCatalog.deleteSkill;\n if (!deleteSkill) return;\n void runMutation(async () => {\n await deleteSkill({ id: skill.id });\n }).catch(() => {});\n };\n\n const handleImport = async (draft: SkillConfigBase) => {\n setFormError(null);\n await runMutation(async () => {\n await skillCatalog.createSkill(draft);\n }, setFormError);\n setTimeout(() => {\n toaster?.showSuccess({ title: `${draft.name} imported` });\n }, 0);\n };\n\n const renderRow = ({\n key,\n name,\n description,\n action,\n }: {\n key: string;\n name: string;\n description: string;\n action: ReactNode;\n }) => (\n <article key={key} className=\"flex min-h-16 items-center gap-3 border-b border-border p-3 last:border-b-0\">\n <span\n className=\"flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg\"\n aria-hidden\n >\n <Icon name=\"lightbulb\" className=\"size-4.5 text-text-primary\" />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <h5 className=\"truncate text-sm font-medium text-text-primary\">{name}</h5>\n {description ? <p className=\"mt-0.5 truncate text-sm text-text-secondary\">{description}</p> : null}\n </div>\n\n {action}\n </article>\n );\n\n const hasMatches = selectedSkills.length > 0 || availableSkills.length > 0;\n\n return (\n <>\n <h3 className=\"text-xl font-semibold tracking-tight text-text-primary\">Skills</h3>\n <p className=\"mt-1 text-sm text-text-secondary\">Use built-in skills or import custom skills from GitHub.</p>\n\n {error ? (\n <p className=\"mt-3 rounded-md border border-failure-bg/30 bg-failure-bg/10 px-3 py-2 text-sm text-failure-bg\">\n {error}\n </p>\n ) : null}\n\n <div className=\"mt-4 flex min-h-0 flex-1 flex-col gap-3\">\n <div className=\"flex flex-col gap-2 sm:flex-row\">\n <div className=\"min-w-0 flex-1\">\n <SearchInput query={query} setQuery={setQuery} placeholder=\"Search skills\" />\n </div>\n <Button\n variant=\"secondary\"\n type=\"button\"\n className=\"shrink-0\"\n disabled={busy}\n onClick={() => {\n setFormError(null);\n setImportOpen(true);\n }}\n >\n <Icon name=\"github\" className=\"size-4\" />\n Import from GitHub\n </Button>\n </div>\n\n <div className=\"flex flex-1 flex-col gap-5 overflow-y-auto pb-1\">\n {loading ? <p className=\"py-8 text-center text-sm text-text-secondary\">Loading…</p> : null}\n\n {!loading && selectedSkills.length > 0 ? (\n <section aria-labelledby=\"enabled-skills-heading\">\n <h4\n id=\"enabled-skills-heading\"\n className=\"mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary\"\n >\n Enabled · {selectedSkills.length}\n </h4>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {selectedSkills.map(skill =>\n renderRow({\n key: skill.id,\n name: skill.name,\n description: skill.description,\n action: skillCatalog.deleteSkill ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n type=\"button\"\n disabled={busy}\n aria-label={`Remove ${skill.name}`}\n onClick={() => {\n handleRemove(skill);\n }}\n >\n Remove\n </Button>\n ) : null,\n }),\n )}\n </div>\n </section>\n ) : null}\n\n {!loading && availableSkills.length > 0 ? (\n <section aria-labelledby=\"available-skills-heading\">\n <h4\n id=\"available-skills-heading\"\n className=\"mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary\"\n >\n Available · {availableSkills.length}\n </h4>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {availableSkills.map(entry =>\n renderRow({\n key: entry.id,\n name: entry.name,\n description: entry.description,\n action: (\n <Button\n variant=\"outline\"\n size=\"sm\"\n type=\"button\"\n disabled={busy}\n aria-label={`Enable ${entry.name}`}\n onClick={() => {\n handleSelect(entry);\n }}\n >\n Enable\n </Button>\n ),\n }),\n )}\n </div>\n </section>\n ) : null}\n\n {!loading && !hasMatches ? (\n <div className=\"flex flex-1 items-center justify-center rounded-xl border border-dashed border-border p-8 text-center text-sm text-text-secondary\">\n {normalizedQuery ? `No skills match “${query.trim()}”.` : 'No skills yet.'}\n </div>\n ) : null}\n </div>\n </div>\n\n <ImportGithubSkillForm\n open={importOpen}\n onOpenChange={open => {\n setImportOpen(open);\n if (!open) setFormError(null);\n }}\n onImport={handleImport}\n busy={busy}\n error={formError}\n />\n </>\n );\n};\n\nexport default SkillSettings;\n","'use client';\n\nimport { useState, type SyntheticEvent } from 'react';\n\nimport { auiInputClass } from '@/atoms/lib/inputClasses.js';\nimport { Button } from '@/atoms/primitives/Button.js';\nimport { CenteredModal } from '@/atoms/primitives/CenteredModal.js';\nimport { Icon } from '@/icons/Icon.js';\nimport type { SkillConfigBase } from '../../server/types.js';\n\ntype ImportGithubSkillFormProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onImport: (draft: SkillConfigBase) => void | Promise<void>;\n busy?: boolean;\n error?: string | null;\n};\n\nconst ImportGithubSkillForm = ({ open, onOpenChange, onImport, busy = false, error }: ImportGithubSkillFormProps) => {\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [repoURL, setRepoURL] = useState('');\n const [path, setPath] = useState('');\n const [ref, setRef] = useState('');\n\n const reset = () => {\n setName('');\n setDescription('');\n setRepoURL('');\n setPath('');\n setRef('');\n };\n\n const close = () => {\n reset();\n onOpenChange(false);\n };\n\n const handleSubmit = async (event: SyntheticEvent<HTMLFormElement, SubmitEvent>) => {\n event.preventDefault();\n if (!name.trim() || !description.trim() || !repoURL.trim() || !path.trim() || !ref.trim() || busy) return;\n\n try {\n await onImport({\n name: name.trim(),\n description: description.trim(),\n repoURL: repoURL.trim(),\n path: path.trim(),\n ref: ref.trim(),\n });\n close();\n } catch {\n // Parent surfaces error; keep form open.\n }\n };\n\n const canImport = Boolean(name.trim() && description.trim() && repoURL.trim() && path.trim() && ref.trim()) && !busy;\n\n return (\n <CenteredModal\n open={open}\n onOpenChange={nextOpen => {\n if (!nextOpen) close();\n }}\n title=\"Import from GitHub\"\n description=\"Import a skill from a SKILL.md file in a GitHub repository.\"\n headerIcon={\n <span className=\"flex size-11 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\">\n <Icon name=\"github\" className=\"size-5\" />\n </span>\n }\n contentSized\n className=\"md:max-w-2xl\"\n >\n <form onSubmit={e => void handleSubmit(e)}>\n <div className=\"space-y-5 px-5 py-5 md:px-6\">\n <div>\n <label htmlFor=\"skill-name\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Name\n </label>\n <input\n id=\"skill-name\"\n value={name}\n onChange={event => {\n setName(event.target.value);\n }}\n placeholder=\"release-notes\"\n autoFocus\n required\n className={auiInputClass('h-11')}\n />\n </div>\n\n <div>\n <label htmlFor=\"skill-description\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Description\n </label>\n <textarea\n id=\"skill-description\"\n value={description}\n onChange={event => {\n setDescription(event.target.value);\n }}\n placeholder=\"Generate release notes from merged pull requests\"\n required\n rows={3}\n className={auiInputClass('resize-y py-2.5')}\n />\n </div>\n\n <div>\n <label htmlFor=\"skill-repo-url\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Repository URL\n </label>\n <input\n id=\"skill-repo-url\"\n type=\"url\"\n value={repoURL}\n onChange={event => {\n setRepoURL(event.target.value);\n }}\n placeholder=\"https://github.com/org/repo\"\n required\n className={auiInputClass('h-11')}\n />\n </div>\n\n <div>\n <label htmlFor=\"skill-path\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Folder containing the SKILL.md\n </label>\n <input\n id=\"skill-path\"\n value={path}\n onChange={event => {\n setPath(event.target.value);\n }}\n placeholder=\"skills/release-notes\"\n required\n className={auiInputClass('h-11')}\n />\n </div>\n\n <div>\n <label htmlFor=\"skill-ref\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Branch\n </label>\n <input\n id=\"skill-ref\"\n value={ref}\n onChange={event => {\n setRef(event.target.value);\n }}\n placeholder=\"main\"\n required\n className={auiInputClass('h-11')}\n />\n </div>\n\n <div className=\"space-y-3\">\n {error ? <p className=\"text-failure-bg text-sm\">{error}</p> : null}\n <Button type=\"submit\" disabled={!canImport} className=\"w-full\">\n Import\n </Button>\n </div>\n </div>\n </form>\n </CenteredModal>\n );\n};\n\nexport default ImportGithubSkillForm;\n"],"mappings":"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","names":["useState","jsx","jsxs","useState"]}
@@ -0,0 +1,101 @@
1
+ "use client";
2
+ import {
3
+ StackChatPanel
4
+ } from "./chunk-NBMP2XNL.js";
5
+ import "./chunk-WFC3W4C3.js";
6
+ import "./chunk-UXZOL5GO.js";
7
+ import "./chunk-M6MHLVSO.js";
8
+ import {
9
+ useSlot
10
+ } from "./chunk-XSHXH6EI.js";
11
+ import {
12
+ CompactLayoutProvider,
13
+ Icon,
14
+ auiButtonClass
15
+ } from "./chunk-UHGSHDBM.js";
16
+ import "./chunk-42GF723P.js";
17
+ import {
18
+ cn
19
+ } from "./chunk-UBOFEI77.js";
20
+
21
+ // src/layouts/WidgetLayout.tsx
22
+ import { useEffect, useRef, useState } from "react";
23
+ import { jsx, jsxs } from "react/jsx-runtime";
24
+ function WidgetLayout({ className }) {
25
+ const BrandLogo = useSlot("BrandLogo");
26
+ const [open, setOpen] = useState(false);
27
+ const fabRef = useRef(null);
28
+ const dialogRef = useRef(null);
29
+ const wasOpen = useRef(false);
30
+ useEffect(() => {
31
+ if (!open) return;
32
+ const onKeyDown = (event) => {
33
+ if (event.key === "Escape" && !dialogRef.current?.querySelector("dialog[open]")) {
34
+ setOpen(false);
35
+ }
36
+ };
37
+ window.addEventListener("keydown", onKeyDown);
38
+ return () => window.removeEventListener("keydown", onKeyDown);
39
+ }, [open]);
40
+ useEffect(() => {
41
+ if (open) {
42
+ wasOpen.current = true;
43
+ dialogRef.current?.focus();
44
+ return;
45
+ }
46
+ if (wasOpen.current) {
47
+ fabRef.current?.focus();
48
+ wasOpen.current = false;
49
+ }
50
+ }, [open]);
51
+ return /* @__PURE__ */ jsxs("div", { className: cn("pointer-events-none relative h-full min-h-0 w-full", className), children: [
52
+ open ? /* @__PURE__ */ jsx(
53
+ "div",
54
+ {
55
+ ref: dialogRef,
56
+ "data-aui-compact-layout": true,
57
+ className: "pointer-events-auto absolute right-[max(1.25rem,env(safe-area-inset-right,0px))] bottom-[calc(5.25rem+env(safe-area-inset-bottom,0px))] z-[19] flex h-[min(560px,calc(100%-6.5rem-env(safe-area-inset-bottom,0px)))] max-h-[calc(100%-6.5rem)] w-[min(380px,calc(100%-2.5rem))] flex-col overflow-hidden rounded-xl border border-border bg-primary-bg shadow-[0_16px_48px_color-mix(in_oklab,var(--shadow-color)_14%,transparent)] outline-none",
58
+ role: "dialog",
59
+ "aria-modal": true,
60
+ "aria-label": "Chat",
61
+ tabIndex: -1,
62
+ children: /* @__PURE__ */ jsx(CompactLayoutProvider, { children: /* @__PURE__ */ jsx(
63
+ StackChatPanel,
64
+ {
65
+ threadHeaderEnd: /* @__PURE__ */ jsx(
66
+ "button",
67
+ {
68
+ type: "button",
69
+ "aria-label": "Close",
70
+ title: "Close",
71
+ className: auiButtonClass({ variant: "ghost", size: "icon" }),
72
+ onClick: () => setOpen(false),
73
+ children: /* @__PURE__ */ jsx(Icon, { name: "xmark" })
74
+ }
75
+ )
76
+ }
77
+ ) })
78
+ }
79
+ ) : null,
80
+ /* @__PURE__ */ jsx(
81
+ "button",
82
+ {
83
+ ref: fabRef,
84
+ type: "button",
85
+ className: "pointer-events-auto absolute right-[max(1.25rem,env(safe-area-inset-right,0px))] bottom-[max(1.25rem,env(safe-area-inset-bottom,0px))] z-20 flex size-14 cursor-pointer items-center justify-center rounded-full text-sm font-medium shadow-[0_8px_24px_color-mix(in_oklab,var(--primary-button-bg)_45%,transparent)]",
86
+ style: {
87
+ backgroundColor: "var(--primary-button-bg)",
88
+ color: "var(--primary-button-text)"
89
+ },
90
+ "aria-expanded": open,
91
+ "aria-label": open ? "Close chat" : "Open chat",
92
+ onClick: () => setOpen((v) => !v),
93
+ children: open ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-xl leading-none", children: "\xD7" }) : /* @__PURE__ */ jsx(BrandLogo, { className: "size-6" })
94
+ }
95
+ )
96
+ ] });
97
+ }
98
+ export {
99
+ WidgetLayout
100
+ };
101
+ //# sourceMappingURL=WidgetLayout-7MDOKLHU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/layouts/WidgetLayout.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { auiButtonClass } from '../atoms/lib/buttonClasses.js';\nimport { cn } from '../atoms/lib/cn.js';\nimport { CompactLayoutProvider } from '../atoms/lib/CompactLayoutContext.js';\nimport { Icon } from '../icons/Icon.js';\nimport { useSlot } from '../theme/SlotsProvider.js';\nimport { StackChatPanel } from './StackChatPanel.js';\n\n/** FAB-anchored panel with the same list ↔ thread stack as `dock`. */\nexport function WidgetLayout({ className }: { className?: string }) {\n const BrandLogo = useSlot('BrandLogo');\n const [open, setOpen] = useState(false);\n const fabRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const wasOpen = useRef(false);\n\n useEffect(() => {\n if (!open) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !dialogRef.current?.querySelector('dialog[open]')) {\n setOpen(false);\n }\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [open]);\n\n useEffect(() => {\n if (open) {\n wasOpen.current = true;\n dialogRef.current?.focus();\n return;\n }\n if (wasOpen.current) {\n fabRef.current?.focus();\n wasOpen.current = false;\n }\n }, [open]);\n\n return (\n <div className={cn('pointer-events-none relative h-full min-h-0 w-full', className)}>\n {open ? (\n <div\n ref={dialogRef}\n data-aui-compact-layout\n className=\"pointer-events-auto absolute right-[max(1.25rem,env(safe-area-inset-right,0px))] bottom-[calc(5.25rem+env(safe-area-inset-bottom,0px))] z-[19] flex h-[min(560px,calc(100%-6.5rem-env(safe-area-inset-bottom,0px)))] max-h-[calc(100%-6.5rem)] w-[min(380px,calc(100%-2.5rem))] flex-col overflow-hidden rounded-xl border border-border bg-primary-bg shadow-[0_16px_48px_color-mix(in_oklab,var(--shadow-color)_14%,transparent)] outline-none\"\n role=\"dialog\"\n aria-modal={true}\n aria-label=\"Chat\"\n tabIndex={-1}\n >\n <CompactLayoutProvider>\n <StackChatPanel\n threadHeaderEnd={\n <button\n type=\"button\"\n aria-label=\"Close\"\n title=\"Close\"\n className={auiButtonClass({ variant: 'ghost', size: 'icon' })}\n onClick={() => setOpen(false)}\n >\n <Icon name=\"xmark\" />\n </button>\n }\n />\n </CompactLayoutProvider>\n </div>\n ) : null}\n {/* Native FAB: inline colors beat host unlayered Tailwind (SDK utilities are layered). */}\n <button\n ref={fabRef}\n type=\"button\"\n className=\"pointer-events-auto absolute right-[max(1.25rem,env(safe-area-inset-right,0px))] bottom-[max(1.25rem,env(safe-area-inset-bottom,0px))] z-20 flex size-14 cursor-pointer items-center justify-center rounded-full text-sm font-medium shadow-[0_8px_24px_color-mix(in_oklab,var(--primary-button-bg)_45%,transparent)]\"\n style={{\n backgroundColor: 'var(--primary-button-bg)',\n color: 'var(--primary-button-text)',\n }}\n aria-expanded={open}\n aria-label={open ? 'Close chat' : 'Open chat'}\n onClick={() => setOpen(v => !v)}\n >\n {open ? (\n <span aria-hidden className=\"text-xl leading-none\">\n ×\n </span>\n ) : (\n <BrandLogo className=\"size-6\" />\n )}\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,WAAW,QAAQ,gBAAgB;AAyCxC,SAqBc,KArBd;AA/BG,SAAS,aAAa,EAAE,UAAU,GAA2B;AAClE,QAAM,YAAY,QAAQ,WAAW;AACrC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,SAAS,OAA0B,IAAI;AAC7C,QAAM,YAAY,OAAuB,IAAI;AAC7C,QAAM,UAAU,OAAO,KAAK;AAE5B,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,YAAY,CAAC,UAAyB;AAC1C,UAAI,MAAM,QAAQ,YAAY,CAAC,UAAU,SAAS,cAAc,cAAc,GAAG;AAC/E,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AACA,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,MAAM,OAAO,oBAAoB,WAAW,SAAS;AAAA,EAC9D,GAAG,CAAC,IAAI,CAAC;AAET,YAAU,MAAM;AACd,QAAI,MAAM;AACR,cAAQ,UAAU;AAClB,gBAAU,SAAS,MAAM;AACzB;AAAA,IACF;AACA,QAAI,QAAQ,SAAS;AACnB,aAAO,SAAS,MAAM;AACtB,cAAQ,UAAU;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,SACE,qBAAC,SAAI,WAAW,GAAG,sDAAsD,SAAS,GAC/E;AAAA,WACC;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,2BAAuB;AAAA,QACvB,WAAU;AAAA,QACV,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,cAAW;AAAA,QACX,UAAU;AAAA,QAEV,8BAAC,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,iBACE;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,cAAW;AAAA,gBACX,OAAM;AAAA,gBACN,WAAW,eAAe,EAAE,SAAS,SAAS,MAAM,OAAO,CAAC;AAAA,gBAC5D,SAAS,MAAM,QAAQ,KAAK;AAAA,gBAE5B,8BAAC,QAAK,MAAK,SAAQ;AAAA;AAAA,YACrB;AAAA;AAAA,QAEJ,GACF;AAAA;AAAA,IACF,IACE;AAAA,IAEJ;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAO;AAAA,UACL,iBAAiB;AAAA,UACjB,OAAO;AAAA,QACT;AAAA,QACA,iBAAe;AAAA,QACf,cAAY,OAAO,eAAe;AAAA,QAClC,SAAS,MAAM,QAAQ,OAAK,CAAC,CAAC;AAAA,QAE7B,iBACC,oBAAC,UAAK,eAAW,MAAC,WAAU,wBAAuB,kBAEnD,IAEA,oBAAC,aAAU,WAAU,UAAS;AAAA;AAAA,IAElC;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1 @@
1
+ export { AssistantState, useAui, useAuiState } from '@assistant-ui/react';
@@ -0,0 +1,9 @@
1
+ import {
2
+ useAui,
3
+ useAuiState
4
+ } from "./chunk-M6MHLVSO.js";
5
+ export {
6
+ useAui,
7
+ useAuiState
8
+ };
9
+ //# sourceMappingURL=assistant-ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,24 @@
1
+ import {
2
+ cn,
3
+ useOptionalContentClassNames
4
+ } from "./chunk-UBOFEI77.js";
5
+
6
+ // src/atoms/OpenUiFenceBlock.tsx
7
+ import { Renderer } from "@openuidev/react-lang";
8
+ import { ThemeProvider, openuiLibrary } from "@openuidev/react-ui";
9
+ import { jsx } from "react/jsx-runtime";
10
+ function OpenUiFenceBlock({ content, isStreaming, darkTheme }) {
11
+ const classNames = useOptionalContentClassNames();
12
+ return /* @__PURE__ */ jsx("div", { className: cn("aui-openui mb-2 w-full min-w-0 max-w-full", classNames.openui?.root), children: /* @__PURE__ */ jsx(ThemeProvider, { mode: darkTheme ? "dark" : "light", cssSelector: ".markdown-openui-scope", children: /* @__PURE__ */ jsx(
13
+ "div",
14
+ {
15
+ className: cn("markdown-openui-scope min-w-0 w-full max-w-full overflow-x-auto", classNames.openui?.scope),
16
+ children: /* @__PURE__ */ jsx(Renderer, { response: content, library: openuiLibrary, isStreaming })
17
+ }
18
+ ) }) });
19
+ }
20
+
21
+ export {
22
+ OpenUiFenceBlock
23
+ };
24
+ //# sourceMappingURL=chunk-42GF723P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/atoms/OpenUiFenceBlock.tsx"],"sourcesContent":["'use client';\n\nimport { Renderer } from '@openuidev/react-lang';\nimport { ThemeProvider, openuiLibrary } from '@openuidev/react-ui';\n\nimport { useOptionalContentClassNames } from '../theme/ThemeProvider.js';\nimport { cn } from './lib/cn.js';\n\nexport type OpenUiFenceBlockProps = {\n content: string;\n isStreaming?: boolean;\n darkTheme?: boolean;\n};\n\nexport function OpenUiFenceBlock({ content, isStreaming, darkTheme }: OpenUiFenceBlockProps) {\n const classNames = useOptionalContentClassNames();\n\n return (\n <div className={cn('aui-openui mb-2 w-full min-w-0 max-w-full', classNames.openui?.root)}>\n <ThemeProvider mode={darkTheme ? 'dark' : 'light'} cssSelector=\".markdown-openui-scope\">\n <div\n className={cn('markdown-openui-scope min-w-0 w-full max-w-full overflow-x-auto', classNames.openui?.scope)}\n >\n <Renderer response={content} library={openuiLibrary} isStreaming={isStreaming} />\n </div>\n </ThemeProvider>\n </div>\n );\n}\n\ndeclare module '../theme/SlotsProvider.js' {\n interface AtomSlots {\n OpenUiFenceBlock: typeof OpenUiFenceBlock;\n }\n}\n"],"mappings":";;;;;;AAEA,SAAS,gBAAgB;AACzB,SAAS,eAAe,qBAAqB;AAoBnC;AATH,SAAS,iBAAiB,EAAE,SAAS,aAAa,UAAU,GAA0B;AAC3F,QAAM,aAAa,6BAA6B;AAEhD,SACE,oBAAC,SAAI,WAAW,GAAG,6CAA6C,WAAW,QAAQ,IAAI,GACrF,8BAAC,iBAAc,MAAM,YAAY,SAAS,SAAS,aAAY,0BAC7D;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,mEAAmE,WAAW,QAAQ,KAAK;AAAA,MAEzG,8BAAC,YAAS,UAAU,SAAS,SAAS,eAAe,aAA0B;AAAA;AAAA,EACjF,GACF,GACF;AAEJ;","names":[]}
@@ -0,0 +1,29 @@
1
+ // src/server/createTrueFoundryServer.ts
2
+ function createTrueFoundryServer(opts) {
3
+ const builder = {
4
+ getCapabilities: opts.getCapabilities,
5
+ getModels: opts.getModels,
6
+ getSkills: opts.getSkills,
7
+ getMcp: opts.getMcp,
8
+ searchAgents: opts.searchAgents,
9
+ saveAgent: opts.saveAgent,
10
+ deleteAgent: async (req) => {
11
+ if (opts.deleteAgent) {
12
+ await opts.deleteAgent(req);
13
+ return;
14
+ }
15
+ throw new Error("deleteAgent is host-owned. Pass deleteAgent to createTrueFoundryServer.");
16
+ }
17
+ };
18
+ const server = {
19
+ ...opts.chatServer,
20
+ ...builder,
21
+ ...opts.catalog != null ? { catalog: opts.catalog } : {}
22
+ };
23
+ return server;
24
+ }
25
+
26
+ export {
27
+ createTrueFoundryServer
28
+ };
29
+ //# sourceMappingURL=chunk-CFLVPV5M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server/createTrueFoundryServer.ts"],"sourcesContent":["import type {\n AgentBuilderCapabilitiesResponse,\n AgentBuilderServer,\n AgentChatServer,\n AgentLibraryEntry,\n AgentSkill,\n AgentSpec,\n CatalogServer,\n ConnectorState,\n ModelSelection,\n SaveAgentRequest,\n SaveAgentResult,\n SearchAgentsParams,\n} from './types.js';\n\nexport type CreateTrueFoundryServerOptions<\n TSpec extends AgentSpec = AgentSpec,\n TModel extends ModelSelection = ModelSelection,\n TSkill extends AgentSkill = AgentSkill,\n TMcp extends ConnectorState = ConnectorState,\n TAgent extends AgentLibraryEntry = AgentLibraryEntry,\n TSave extends SaveAgentResult = SaveAgentResult,\n TCatalog extends CatalogServer = CatalogServer,\n TCapabilities extends AgentBuilderCapabilitiesResponse = AgentBuilderCapabilitiesResponse,\n> = {\n /** Chat port — e.g. from `@truefoundry/agent-server-adapter`. */\n chatServer: AgentChatServer<TSpec>;\n getCapabilities: () => Promise<TCapabilities>;\n getModels: () => Promise<TModel[]>;\n getSkills: () => Promise<TSkill[]>;\n getMcp: () => Promise<TMcp[]>;\n searchAgents: (req?: SearchAgentsParams) => Promise<TAgent[]>;\n saveAgent: (req: SaveAgentRequest<TSpec>) => Promise<TSave>;\n deleteAgent?: (req: { agentName: string }) => Promise<void>;\n /** Settings catalog (models + connectors). Optional. */\n catalog?: TCatalog;\n};\n\nexport type TrueFoundryServer<\n TSpec extends AgentSpec = AgentSpec,\n TModel extends ModelSelection = ModelSelection,\n TSkill extends AgentSkill = AgentSkill,\n TMcp extends ConnectorState = ConnectorState,\n TAgent extends AgentLibraryEntry = AgentLibraryEntry,\n TSave extends SaveAgentResult = SaveAgentResult,\n TCatalog extends CatalogServer = CatalogServer,\n TCapabilities extends AgentBuilderCapabilitiesResponse = AgentBuilderCapabilitiesResponse,\n> = AgentChatServer<TSpec> &\n AgentBuilderServer<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCapabilities> & {\n catalog?: TCatalog;\n };\n\n/**\n * Composes an `AgentChatServer` with host-provided builder catalog callbacks\n * and an optional settings `catalog`.\n * Gateway wiring lives in the host (or `@truefoundry/agent-server-adapter`).\n */\nexport function createTrueFoundryServer<\n TSpec extends AgentSpec = AgentSpec,\n TModel extends ModelSelection = ModelSelection,\n TSkill extends AgentSkill = AgentSkill,\n TMcp extends ConnectorState = ConnectorState,\n TAgent extends AgentLibraryEntry = AgentLibraryEntry,\n TSave extends SaveAgentResult = SaveAgentResult,\n TCatalog extends CatalogServer = CatalogServer,\n TCapabilities extends AgentBuilderCapabilitiesResponse = AgentBuilderCapabilitiesResponse,\n>(\n opts: CreateTrueFoundryServerOptions<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCatalog, TCapabilities>,\n): TrueFoundryServer<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCatalog, TCapabilities> {\n const builder: AgentBuilderServer<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCapabilities> = {\n getCapabilities: opts.getCapabilities,\n getModels: opts.getModels,\n getSkills: opts.getSkills,\n getMcp: opts.getMcp,\n searchAgents: opts.searchAgents,\n saveAgent: opts.saveAgent,\n deleteAgent: async req => {\n if (opts.deleteAgent) {\n await opts.deleteAgent(req);\n return;\n }\n throw new Error('deleteAgent is host-owned. Pass deleteAgent to createTrueFoundryServer.');\n },\n };\n\n const server: TrueFoundryServer<TSpec, TModel, TSkill, TMcp, TAgent, TSave, TCatalog, TCapabilities> = {\n ...opts.chatServer,\n ...builder,\n ...(opts.catalog != null ? { catalog: opts.catalog } : {}),\n };\n return server;\n}\n"],"mappings":";AAyDO,SAAS,wBAUd,MACwF;AACxF,QAAM,UAAyF;AAAA,IAC7F,iBAAiB,KAAK;AAAA,IACtB,WAAW,KAAK;AAAA,IAChB,WAAW,KAAK;AAAA,IAChB,QAAQ,KAAK;AAAA,IACb,cAAc,KAAK;AAAA,IACnB,WAAW,KAAK;AAAA,IAChB,aAAa,OAAM,QAAO;AACxB,UAAI,KAAK,aAAa;AACpB,cAAM,KAAK,YAAY,GAAG;AAC1B;AAAA,MACF;AACA,YAAM,IAAI,MAAM,yEAAyE;AAAA,IAC3F;AAAA,EACF;AAEA,QAAM,SAAiG;AAAA,IACrG,GAAG,KAAK;AAAA,IACR,GAAG;AAAA,IACH,GAAI,KAAK,WAAW,OAAO,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,EAC1D;AACA,SAAO;AACT;","names":[]}
@@ -0,0 +1,8 @@
1
+ // src/assistant-ui.ts
2
+ import { useAui, useAuiState } from "@assistant-ui/react";
3
+
4
+ export {
5
+ useAui,
6
+ useAuiState
7
+ };
8
+ //# sourceMappingURL=chunk-M6MHLVSO.js.map