@solidxai/core-ui 0.1.19 → 0.1.20-beta.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 (43) hide show
  1. package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.d.ts.map +1 -1
  2. package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.js +3 -10
  3. package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.js.map +1 -1
  4. package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.tsx +3 -8
  5. package/dist/components/layout/AdminHeaderActions.d.ts.map +1 -1
  6. package/dist/components/layout/AdminHeaderActions.js +1 -29
  7. package/dist/components/layout/AdminHeaderActions.js.map +1 -1
  8. package/dist/components/layout/AdminHeaderActions.tsx +0 -42
  9. package/dist/components/layout/SolidAiStudioLayout.d.ts +0 -1
  10. package/dist/components/layout/SolidAiStudioLayout.d.ts.map +1 -1
  11. package/dist/components/layout/SolidAiStudioLayout.js +9 -161
  12. package/dist/components/layout/SolidAiStudioLayout.js.map +1 -1
  13. package/dist/components/layout/SolidAiStudioLayout.tsx +7 -136
  14. package/dist/routes/AppEventListener.d.ts.map +1 -1
  15. package/dist/routes/AppEventListener.js +3 -3
  16. package/dist/routes/AppEventListener.js.map +1 -1
  17. package/dist/routes/AppEventListener.tsx +1 -2
  18. package/dist/routes/pages/admin/core/AgentHubTagsField.css +21 -0
  19. package/dist/routes/pages/admin/core/AgentHubTagsField.d.ts +17 -0
  20. package/dist/routes/pages/admin/core/AgentHubTagsField.d.ts.map +1 -0
  21. package/dist/routes/pages/admin/core/AgentHubTagsField.js +171 -0
  22. package/dist/routes/pages/admin/core/AgentHubTagsField.js.map +1 -0
  23. package/dist/routes/pages/admin/core/AgentHubTagsField.tsx +125 -0
  24. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.css +7 -0
  25. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.d.ts.map +1 -1
  26. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.js +65 -52
  27. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.js.map +1 -1
  28. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.tsx +53 -11
  29. package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.d.ts.map +1 -1
  30. package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.js +14 -69
  31. package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.js.map +1 -1
  32. package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx +15 -83
  33. package/dist/routes/pages/admin/core/AgentToolActivationDialog.d.ts +11 -0
  34. package/dist/routes/pages/admin/core/AgentToolActivationDialog.d.ts.map +1 -0
  35. package/dist/routes/pages/admin/core/AgentToolActivationDialog.js +166 -0
  36. package/dist/routes/pages/admin/core/AgentToolActivationDialog.js.map +1 -0
  37. package/dist/routes/pages/admin/core/AgentToolActivationDialog.tsx +140 -0
  38. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.css +26 -0
  39. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.d.ts.map +1 -1
  40. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.js +94 -71
  41. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.js.map +1 -1
  42. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.tsx +60 -52
  43. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { createPortal } from "react-dom";
3
- import { ArrowLeft, ChevronDown, ExternalLink, FlaskConical, Pencil, Plus, RefreshCw, Trash2 } from "lucide-react";
3
+ import { ArrowLeft, ChevronDown, Ellipsis, ExternalLink, Eye, FlaskConical, Pencil, Plus, RefreshCw, Trash2 } from "lucide-react";
4
4
  import { useDispatch } from "react-redux";
5
5
  import { useNavigate, useParams } from "react-router-dom";
6
6
  import { createSolidEntityApi } from "../../../../redux/api/solidEntityApi";
@@ -8,14 +8,16 @@ import { useGetSolidSettingsQuery } from "../../../../redux/api/solidSettingsApi
8
8
  import { getSettingsMap } from "../../../../helpers/settingsPayload";
9
9
  import { showToast } from "../../../../redux/features/toastSlice";
10
10
  import { AgentRegistryAuditPanel } from "./AgentRegistryAuditPanel";
11
+ import { AgentHubTagsField, agentHubTagsFrom, agentHubTagsPayload, type AgentHubTag } from "./AgentHubTagsField";
11
12
  import { AgentResourceCardWidget } from "../../../../components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget";
12
13
  import { AgentSessionsPanel } from "../../../../components/core/extension/solid-core/agentToolRegistry/AgentToolSessionsPanel";
13
14
  import { AgentProcessesPanel } from "../../../../components/core/extension/solid-core/agentToolRegistry/AgentProcessesPanel";
14
15
  import type { SolidKanbanCardWidgetProps } from "../../../../types/solid-core";
15
16
  import { SolidWorkflowStatusPill } from "../../../../components/core/form/SolidDraftPublishWorkflow";
16
17
  import { ALLOWED_MODELS_BY_PROVIDER, type AllowedModelProvider } from "../../../../constants/allowed-ai-models";
17
- import { SolidButton, SolidCodeEditor, SolidDialog, SolidDialogBody, SolidIconPicker, SolidInput, SolidTabGroup } from "../../../../components/shad-cn-ui";
18
+ import { SolidButton, SolidCodeEditor, SolidDialog, SolidDialogBody, SolidDropdownMenu, SolidDropdownMenuContent, SolidDropdownMenuItem, SolidDropdownMenuTrigger, SolidIconPicker, SolidInput, SolidTabGroup } from "../../../../components/shad-cn-ui";
18
19
  import { SolidAgentEmbedded } from "../../../../components/core/solid-agent/SolidAgentEmbedded";
20
+ import { SolidAgentMarkdown } from "../../../../components/core/solid-agent/SolidAgentMarkdown";
19
21
  import { AgentEmbeddingPanel } from "../../../../components/core/solid-agent/embed/AgentEmbeddingPanel";
20
22
  import "./AgentRegistryEditorPage.css";
21
23
 
@@ -27,6 +29,7 @@ type Agent = Item & {
27
29
  systemPrompt?: string; requiredInputs?: string; reasoningModelKey?: string; fastModelKey?: string; status?: string;
28
30
  stepLimit?: number; turnStepLimit?: number; costLimit?: number;
29
31
  agentSkills?: Link[]; agentTools?: Link[]; agentRoles?: Link[]; agentSecrets?: Link[];
32
+ tags?: AgentHubTag[];
30
33
  };
31
34
  type ProviderModelOption = { provider: AllowedModelProvider; model: string; value: string };
32
35
 
@@ -146,7 +149,7 @@ const agentRoleApi = createSolidEntityApi("agentRole");
146
149
  const agentSecretApi = createSolidEntityApi("agentSecret");
147
150
  const jobApi = createSolidEntityApi("agentJob");
148
151
 
149
- const skillFields = ["id", "name", "iconName", "description", "tags"];
152
+ const skillFields = ["id", "name", "iconName", "description"];
150
153
  const toolFields = [...skillFields, "type", "status", "lastLoadError"];
151
154
 
152
155
  function fieldsQuery(fields: string[]): string {
@@ -159,7 +162,7 @@ const detailFields = [
159
162
  ];
160
163
 
161
164
  const detailQuery = [
162
- "agentRoles", "agentRoles.roleMetadata", "agentSecrets", "agentSecrets.secret",
165
+ "agentRoles", "agentRoles.roleMetadata", "agentSecrets", "agentSecrets.secret", "tags",
163
166
  ].map((name, index) => `populate[${index}]=${name}`).join("&") + "&" + fieldsQuery(detailFields);
164
167
 
165
168
  // Group by link ID to project summary columns without populating full registry records.
@@ -199,7 +202,7 @@ function agentFormFromRecord(record: Agent) {
199
202
  name: record.name ?? "", title: record.title ?? "", description: record.description ?? "", iconName: record.iconName ?? "",
200
203
  inputs: parseInputs(record.requiredInputs), reasoningModelKey: record.reasoningModelKey ?? "", fastModelKey: record.fastModelKey ?? "",
201
204
  systemPrompt: record.systemPrompt ?? "", stepLimit: record.stepLimit ?? 100, turnStepLimit: record.turnStepLimit ?? 20,
202
- costLimit: Number(record.costLimit ?? 3), skillIds: skills.map((link) => link.agentSkillRegistry?.id).filter(Boolean),
205
+ costLimit: Number(record.costLimit ?? 3), tags: agentHubTagsFrom(record.tags), skillIds: skills.map((link) => link.agentSkillRegistry?.id).filter(Boolean),
203
206
  toolIds: tools.map((link) => link.agentToolRegistry?.id).filter(Boolean),
204
207
  roleIds: items(record.agentRoles).map((link) => link.roleMetadata?.id).filter(Boolean),
205
208
  secretIds: secrets.map((link) => link.secret?.id).filter(Boolean),
@@ -235,12 +238,34 @@ function useCatalog(api: typeof skillApi, query = "offset=0&limit=1000") {
235
238
  return { records: items(data?.records) as Item[], isLoading, refetch };
236
239
  }
237
240
 
238
- function LinkPicker({ label, description, options, selected, onAdd, onRemove, createUrl, render, renderSettings, linkFor }: {
241
+ function ResourcePreviewDialog({ item, kind, onClose }: { item: Item; kind: "skill" | "tool"; onClose: () => void }) {
242
+ const api = kind === "skill" ? skillApi : toolApi;
243
+ const field = kind === "skill" ? "body" : "sourceCode";
244
+ const { currentData, isFetching, isError, refetch } = api.useGetSolidEntityByIdQuery(
245
+ { id: item.id, qs: fieldsQuery(["id", field]) }, { refetchOnMountOrArgChange: true });
246
+ const record = recordFrom(currentData);
247
+ const content = record?.[field] ?? "";
248
+
249
+ return <SolidDialog open onOpenChange={(open) => { if (!open) onClose(); }} header={item.name ?? `View ${kind}`}
250
+ style={{ width: "min(64rem, 94vw)", maxWidth: "94vw" }}>
251
+ <SolidDialogBody className="agent-editor__resource-preview-body">
252
+ {isFetching ? <div className="agent-editor__empty" role="status">Loading {kind}…</div>
253
+ : isError || !record ? <div className="agent-editor__empty"><p role="alert">This {kind} could not be loaded.</p><SolidButton variant="secondary" onClick={() => void refetch()}>Retry</SolidButton></div>
254
+ : !content ? <div className="agent-editor__empty">No {kind === "skill" ? "skill body" : "source code"} available.</div>
255
+ : kind === "skill" ? <SolidAgentMarkdown text={content} />
256
+ : <SolidCodeEditor value={content} language="python" readOnly fontSize={12} height="min(65vh, 42rem)" />}
257
+ </SolidDialogBody>
258
+ </SolidDialog>;
259
+ }
260
+
261
+ function LinkPicker({ label, description, options, selected, onAdd, onRemove, createUrl, render, renderSettings, linkFor, onView, editUrlFor }: {
239
262
  label: string; description: string; options: Item[]; selected: Item[];
240
263
  onAdd: (id: number) => void; onRemove: (id: number) => void; createUrl?: string;
241
264
  render: (item: Item, link?: Link) => React.ReactNode;
242
265
  renderSettings?: (item: Item, link?: Link) => React.ReactNode;
243
266
  linkFor?: (id: number) => Link | undefined;
267
+ onView?: (item: Item) => void;
268
+ editUrlFor?: (item: Item) => string;
244
269
  }) {
245
270
  const [search, setSearch] = React.useState("");
246
271
  const [open, setOpen] = React.useState(false);
@@ -262,7 +287,14 @@ function LinkPicker({ label, description, options, selected, onAdd, onRemove, cr
262
287
  {selected.length ? <div className="agent-editor__cards">{selected.map((item) => <div className="agent-editor__linked-card" key={item.id}>
263
288
  <div className="agent-editor__card-content">{render(item, linkFor?.(item.id))}</div>
264
289
  {renderSettings?.(item, linkFor?.(item.id))}
265
- <button type="button" aria-label={`Remove ${item.name ?? item.displayName ?? item.key}`} onClick={() => onRemove(item.id)}><Trash2 size={16} /></button>
290
+ {onView && editUrlFor ? <SolidDropdownMenu>
291
+ <SolidDropdownMenuTrigger asChild><button type="button" className="agent-editor__resource-menu-trigger" aria-label={`Actions for ${item.name ?? item.displayName ?? item.key}`}><Ellipsis size={18} /></button></SolidDropdownMenuTrigger>
292
+ <SolidDropdownMenuContent className="agent-editor__resource-menu">
293
+ <SolidDropdownMenuItem onSelect={() => onView(item)}><Eye size={16} /> View</SolidDropdownMenuItem>
294
+ <SolidDropdownMenuItem asChild><a href={editUrlFor(item)} target="_blank" rel="noopener noreferrer"><Pencil size={16} /> Edit</a></SolidDropdownMenuItem>
295
+ <SolidDropdownMenuItem className="agent-editor__resource-delete" onSelect={() => onRemove(item.id)}><Trash2 size={16} /> Delete</SolidDropdownMenuItem>
296
+ </SolidDropdownMenuContent>
297
+ </SolidDropdownMenu> : <button type="button" aria-label={`Remove ${item.name ?? item.displayName ?? item.key}`} onClick={() => onRemove(item.id)}><Trash2 size={16} /></button>}
266
298
  </div>)}</div> : <div className="agent-editor__empty">No {label.toLowerCase()} linked yet.</div>}
267
299
  </section>;
268
300
  }
@@ -288,8 +320,8 @@ export function AgentRegistryEditorPage() {
288
320
  };
289
321
  }, [agentResult.currentData, skillLinks.currentData, toolLinks.currentData]);
290
322
  const { data: settings, isError: settingsError } = useGetSolidSettingsQuery(undefined);
291
- const skills = useCatalog(skillApi, `offset=0&limit=1000&${fieldsQuery(skillFields)}`);
292
- const tools = useCatalog(toolApi, `offset=0&limit=1000&${fieldsQuery(toolFields)}`);
323
+ const skills = useCatalog(skillApi, `offset=0&limit=1000&populate[0]=tags&${fieldsQuery(skillFields)}`);
324
+ const tools = useCatalog(toolApi, `offset=0&limit=1000&populate[0]=tags&${fieldsQuery(toolFields)}`);
293
325
  const roles = useCatalog(roleApi, "offset=0&limit=1000&populate[0]=module");
294
326
  const secrets = useCatalog(secretApi, "offset=0&limit=1000&fields[0]=id&fields[1]=key&fields[2]=displayName&fields[3]=description");
295
327
  const [createAgent, { isLoading: creating }] = entityApi.useCreateSolidEntityMutation();
@@ -315,6 +347,7 @@ export function AgentRegistryEditorPage() {
315
347
  if (tab === "jobs") void jobs.refetch();
316
348
  };
317
349
  const [testAgentOpen, setTestAgentOpen] = React.useState(false);
350
+ const [preview, setPreview] = React.useState<{ item: Item; kind: "skill" | "tool" } | null>(null);
318
351
  const [testAgentWindowMode, setTestAgentWindowMode] = React.useState<"docked" | "maximized">("maximized");
319
352
  const [name, setName] = React.useState("");
320
353
  const [title, setTitle] = React.useState("");
@@ -327,6 +360,8 @@ export function AgentRegistryEditorPage() {
327
360
  const [stepLimit, setStepLimit] = React.useState(100);
328
361
  const [turnStepLimit, setTurnStepLimit] = React.useState(20);
329
362
  const [costLimit, setCostLimit] = React.useState(3);
363
+ const [tags, setTags] = React.useState<AgentHubTag[]>([]);
364
+ const [creatingTag, setCreatingTag] = React.useState(false);
330
365
  const [skillIds, setSkillIds] = React.useState<number[]>([]);
331
366
  const [toolIds, setToolIds] = React.useState<number[]>([]);
332
367
  const [roleIds, setRoleIds] = React.useState<number[]>([]);
@@ -343,7 +378,7 @@ export function AgentRegistryEditorPage() {
343
378
  const baseline = React.useRef("");
344
379
 
345
380
  const currentForm = () => JSON.stringify({ name, title, description, iconName, inputs, reasoningModelKey, fastModelKey, systemPrompt,
346
- stepLimit: Number(stepLimit), turnStepLimit: Number(turnStepLimit), costLimit: Number(costLimit), skillIds, toolIds, roleIds, secretIds,
381
+ stepLimit: Number(stepLimit), turnStepLimit: Number(turnStepLimit), costLimit: Number(costLimit), tags, skillIds, toolIds, roleIds, secretIds,
347
382
  alwaysIncludeValues, requiresApprovalValues, secretEnvVarNames });
348
383
 
349
384
  React.useEffect(() => {
@@ -354,6 +389,7 @@ export function AgentRegistryEditorPage() {
354
389
  setReasoningModelKey(record.reasoningModelKey ?? ""); setFastModelKey(record.fastModelKey ?? "");
355
390
  setSystemPrompt(record.systemPrompt ?? ""); setStepLimit(record.stepLimit ?? 100);
356
391
  setTurnStepLimit(record.turnStepLimit ?? 20); setCostLimit(Number(record.costLimit ?? 3));
392
+ setTags(agentHubTagsFrom(record.tags));
357
393
  setSkillIds(items(record.agentSkills).map((link) => link.agentSkillRegistry?.id).filter(Boolean));
358
394
  setToolIds(items(record.agentTools).map((link) => link.agentToolRegistry?.id).filter(Boolean));
359
395
  setRoleIds(items(record.agentRoles).map((link) => link.roleMetadata?.id).filter(Boolean));
@@ -413,6 +449,7 @@ export function AgentRegistryEditorPage() {
413
449
  };
414
450
 
415
451
  const save = async (nextStatus?: "draft" | "active" | "disabled") => {
452
+ if (creatingTag) return;
416
453
  const next: Record<string, string> = {};
417
454
  if (!name.trim()) next.name = "Name is required.";
418
455
  if (!title.trim()) next.title = "Title is required.";
@@ -433,6 +470,7 @@ export function AgentRegistryEditorPage() {
433
470
  requiredInputs: JSON.stringify(inputs.map((input) => ({ ...input, name: input.name.trim(), description: input.description.trim() }))),
434
471
  reasoningModelKey, fastModelKey, systemPrompt, stepLimit: Number(stepLimit),
435
472
  turnStepLimit: Number(turnStepLimit), costLimit: Number(costLimit),
473
+ ...agentHubTagsPayload(tags),
436
474
  status: nextStatus ?? record?.status ?? "draft",
437
475
  };
438
476
  let newlyCreatedId: number | undefined;
@@ -507,6 +545,7 @@ export function AgentRegistryEditorPage() {
507
545
  <div className="agent-editor__grid">{field("Name", name, setName, "name", true)}{field("Title", title, setTitle, "title", true)}
508
546
  {field("Description", description, setDescription, "description")}<div className="agent-editor__field"><span>Icon</span><SolidIconPicker value={iconName} onChange={setIconName} /></div>
509
547
  </div>
548
+ <AgentHubTagsField value={tags} onChange={setTags} disabled={creating || updating || isLoading || isFetching || isError} onBusyChange={setCreatingTag} />
510
549
  <section className="agent-editor__section"><div className="agent-editor__section-head"><div><h2>Required inputs</h2><p>Define the variables people must provide when starting this agent.</p></div>
511
550
  {inputs.length > 0 && <SolidButton type="button" variant="secondary" size="small" onClick={() => setInputs((current) => [...current, { name: "", description: "", dataType: "string" }])}><Plus size={15} /> Add input</SolidButton>}
512
551
  </div>
@@ -551,12 +590,14 @@ export function AgentRegistryEditorPage() {
551
590
  {errors.systemPrompt && <small className="agent-editor__error">{errors.systemPrompt}</small>}</section> },
552
591
  { value: "skills", label: "Skills", content: <LinkPicker label="Skills" description="Skills available to this agent." options={skills.records} selected={linked(skillIds, skills.records, items(record?.agentSkills).map((link) => link.agentSkillRegistry).filter(Boolean))}
553
592
  onAdd={(id) => toggle(setSkillIds, id)} onRemove={(id) => toggle(setSkillIds, id)} createUrl="/admin/core/solid-core/agent-skill-registry/editor/new"
593
+ onView={(item) => setPreview({ item, kind: "skill" })} editUrlFor={(item) => `/admin/core/solid-core/agent-skill-registry/editor/${item.id}`}
554
594
  linkFor={(id) => linkForTarget(record?.agentSkills, "agentSkillRegistry", id)}
555
595
  render={(item) => <AgentResourceCardWidget {...({ rowData: item } as SolidKanbanCardWidgetProps)} />}
556
596
  renderSettings={(item) => <div className="agent-editor__link-settings">{linkSetting("Always include", alwaysIncludeValues[item.id] ?? true,
557
597
  (checked) => setAlwaysIncludeValues((current) => ({ ...current, [item.id]: checked })), "Add the full skill to the agent prompt. Turn off to load it on demand.")}</div>} /> },
558
598
  { value: "tools", label: "Tools", content: <LinkPicker label="Tools" description="Tools available to this agent." options={tools.records} selected={linked(toolIds, tools.records, items(record?.agentTools).map((link) => link.agentToolRegistry).filter(Boolean))}
559
599
  onAdd={(id) => toggle(setToolIds, id)} onRemove={(id) => toggle(setToolIds, id)} createUrl="/admin/core/solid-core/agent-tool-registry/editor/new"
600
+ onView={(item) => setPreview({ item, kind: "tool" })} editUrlFor={(item) => `/admin/core/solid-core/agent-tool-registry/editor/${item.id}`}
560
601
  linkFor={(id) => linkForTarget(record?.agentTools, "agentToolRegistry", id)}
561
602
  render={(item) => <AgentResourceCardWidget {...({ rowData: item } as SolidKanbanCardWidgetProps)} />}
562
603
  renderSettings={(item) => <div className="agent-editor__link-settings">{linkSetting("Require approval", requiresApprovalValues[item.id] ?? false,
@@ -592,8 +633,9 @@ export function AgentRegistryEditorPage() {
592
633
  return <main className="agent-editor"><header className="agent-editor__header"><div className="agent-editor__heading-with-refresh"><h1>{record?.id ? "Edit Agent" : "Create Agent"}</h1>{record?.id && <button type="button" className={`agent-editor__refresh${isFetching ? " is-loading" : ""}`} aria-label="Refresh agent" title="Refresh agent" disabled={isFetching || updating} onClick={requestRefresh}><RefreshCw size={14} /></button>}</div><div className="agent-editor__actions">
593
634
  <SolidButton variant="secondary" leftIcon={<ArrowLeft size={16} />} onClick={() => navigate(-1)}>Back</SolidButton>
594
635
  {record?.id && <SolidButton variant="secondary" leftIcon={<FlaskConical size={16} />} onClick={openAgentTest}>Test Agent</SolidButton>}
595
- <SolidButton loading={creating || updating} disabled={isLoading || isFetching || isError || (id !== "new" && !record?.id)} onClick={() => void save()}>Save Agent</SolidButton>
636
+ <SolidButton loading={creating || updating} disabled={creatingTag || isLoading || isFetching || isError || (id !== "new" && !record?.id)} onClick={() => void save()}>Save Agent</SolidButton>
596
637
  </div></header>
638
+ {preview && <ResourcePreviewDialog item={preview.item} kind={preview.kind} onClose={() => setPreview(null)} />}
597
639
  <SolidDialog open={confirmRefresh} onOpenChange={setConfirmRefresh} header="Discard unsaved changes?" style={{ width: "min(28rem, 94vw)" }}
598
640
  footer={<><SolidButton type="button" variant="secondary" onClick={() => setConfirmRefresh(false)}>Cancel</SolidButton><SolidButton type="button" disabled={isFetching} onClick={() => { setConfirmRefresh(false); void refetch(); }}>Refresh and discard</SolidButton></>}>
599
641
  <SolidDialogBody><p>You have unsaved changes. Refreshing will discard them and load the latest agent content.</p></SolidDialogBody>
@@ -1 +1 @@
1
- {"version":3,"file":"AgentSkillRegistryEditorPage.d.ts","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx"],"names":[],"mappings":"AAgBA,OAAO,oCAAoC,CAAC;AAiG5C,wBAAgB,4BAA4B,4CA0V3C"}
1
+ {"version":3,"file":"AgentSkillRegistryEditorPage.d.ts","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx"],"names":[],"mappings":"AAiBA,OAAO,oCAAoC,CAAC;AA8E5C,wBAAgB,4BAA4B,4CAwS3C"}
@@ -45,23 +45,15 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
45
45
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
46
  }
47
47
  };
48
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
49
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
50
- if (ar || !(i in from)) {
51
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
52
- ar[i] = from[i];
53
- }
54
- }
55
- return to.concat(ar || Array.prototype.slice.call(from));
56
- };
57
48
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
58
49
  import React from "react";
59
- import { ArrowLeft, Plus, RefreshCw, X } from "lucide-react";
50
+ import { ArrowLeft, RefreshCw } from "lucide-react";
60
51
  import { useDispatch } from "react-redux";
61
52
  import { useNavigate, useParams } from "react-router-dom";
62
53
  import { createSolidEntityApi } from "../../../../redux/api/solidEntityApi";
63
54
  import { showToast } from "../../../../redux/features/toastSlice";
64
55
  import { AgentRegistryAuditPanel } from "./AgentRegistryAuditPanel";
56
+ import { AgentHubTagsField, agentHubTagsFrom, agentHubTagsPayload } from "./AgentHubTagsField";
65
57
  import { SolidButton, SolidCodeEditor, SolidDialog, SolidDialogBody, SolidIconPicker, SolidInput, SolidTabGroup, } from "../../../../components/shad-cn-ui";
66
58
  import "./AgentSkillRegistryEditorPage.css";
67
59
  function extractEntityRecord(response) {
@@ -76,23 +68,6 @@ function extractEntityRecord(response) {
76
68
  }
77
69
  return candidate && typeof candidate === "object" ? candidate : undefined;
78
70
  }
79
- function parseTags(value) {
80
- if (Array.isArray(value)) {
81
- return value.map(function (tag) { return String(tag).trim(); }).filter(Boolean);
82
- }
83
- if (typeof value !== "string" || !value.trim())
84
- return [];
85
- try {
86
- var parsed = JSON.parse(value);
87
- if (Array.isArray(parsed)) {
88
- return parsed.map(function (tag) { return String(tag).trim(); }).filter(Boolean);
89
- }
90
- }
91
- catch (_a) {
92
- return value === "{}" ? [] : value.split(",").map(function (tag) { return tag.trim(); }).filter(Boolean);
93
- }
94
- return [];
95
- }
96
71
  function formatErrorMessage(value) {
97
72
  var _a, _b;
98
73
  if (typeof value === "string")
@@ -145,7 +120,7 @@ export function AgentSkillRegistryEditorPage() {
145
120
  var useCreateSolidEntityMutation = entityApi.useCreateSolidEntityMutation, useGetSolidEntityByIdQuery = entityApi.useGetSolidEntityByIdQuery, useUpdateSolidEntityMutation = entityApi.useUpdateSolidEntityMutation;
146
121
  var _b = useGetSolidEntityByIdQuery({
147
122
  id: id,
148
- qs: "populate[0]=agentSkills&populate[1]=agentSkills.agentRegistry",
123
+ qs: "populate[0]=agentSkills&populate[1]=agentSkills.agentRegistry&populate[2]=tags",
149
124
  }, { skip: !id || id === "new" }), response = _b.data, isLoading = _b.isLoading, isFetching = _b.isFetching, refetch = _b.refetch;
150
125
  var _c = useCreateSolidEntityMutation(), createSkill = _c[0], isCreating = _c[1].isLoading;
151
126
  var _d = useUpdateSolidEntityMutation(), updateSkill = _d[0], isSaving = _d[1].isLoading;
@@ -157,43 +132,34 @@ export function AgentSkillRegistryEditorPage() {
157
132
  var _j = React.useState(""), description = _j[0], setDescription = _j[1];
158
133
  var _k = React.useState(""), body = _k[0], setBody = _k[1];
159
134
  var _l = React.useState([]), tags = _l[0], setTags = _l[1];
160
- var _m = React.useState(""), tagDraft = _m[0], setTagDraft = _m[1];
135
+ var _m = React.useState(false), creatingTag = _m[0], setCreatingTag = _m[1];
161
136
  var _o = React.useState({}), fieldErrors = _o[0], setFieldErrors = _o[1];
162
137
  var _p = React.useState(0), auditRefreshVersion = _p[0], setAuditRefreshVersion = _p[1];
163
138
  var _q = React.useState(false), confirmRefresh = _q[0], setConfirmRefresh = _q[1];
164
139
  var baseline = React.useRef("");
165
- var currentForm = function () { return JSON.stringify({ name: name, type: type, iconName: iconName, description: description, body: body, tags: tags, tagDraft: tagDraft }); };
140
+ var currentForm = function () { return JSON.stringify({ name: name, type: type, iconName: iconName, description: description, body: body, tags: tags }); };
166
141
  React.useEffect(function () {
167
142
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
168
- var nextTags = parseTags(record === null || record === void 0 ? void 0 : record.tags);
143
+ var nextTags = agentHubTagsFrom(record === null || record === void 0 ? void 0 : record.tags);
169
144
  setName((_a = record === null || record === void 0 ? void 0 : record.name) !== null && _a !== void 0 ? _a : "");
170
145
  setType((_b = record === null || record === void 0 ? void 0 : record.type) !== null && _b !== void 0 ? _b : "custom");
171
146
  setIconName((_c = record === null || record === void 0 ? void 0 : record.iconName) !== null && _c !== void 0 ? _c : "");
172
147
  setDescription((_d = record === null || record === void 0 ? void 0 : record.description) !== null && _d !== void 0 ? _d : "");
173
148
  setBody((_e = record === null || record === void 0 ? void 0 : record.body) !== null && _e !== void 0 ? _e : "");
174
149
  setTags(nextTags);
175
- setTagDraft("");
176
- baseline.current = JSON.stringify({ name: (_f = record === null || record === void 0 ? void 0 : record.name) !== null && _f !== void 0 ? _f : "", type: (_g = record === null || record === void 0 ? void 0 : record.type) !== null && _g !== void 0 ? _g : "custom", iconName: (_h = record === null || record === void 0 ? void 0 : record.iconName) !== null && _h !== void 0 ? _h : "", description: (_j = record === null || record === void 0 ? void 0 : record.description) !== null && _j !== void 0 ? _j : "", body: (_k = record === null || record === void 0 ? void 0 : record.body) !== null && _k !== void 0 ? _k : "", tags: nextTags, tagDraft: "" });
150
+ baseline.current = JSON.stringify({ name: (_f = record === null || record === void 0 ? void 0 : record.name) !== null && _f !== void 0 ? _f : "", type: (_g = record === null || record === void 0 ? void 0 : record.type) !== null && _g !== void 0 ? _g : "custom", iconName: (_h = record === null || record === void 0 ? void 0 : record.iconName) !== null && _h !== void 0 ? _h : "", description: (_j = record === null || record === void 0 ? void 0 : record.description) !== null && _j !== void 0 ? _j : "", body: (_k = record === null || record === void 0 ? void 0 : record.body) !== null && _k !== void 0 ? _k : "", tags: nextTags });
177
151
  }, [record]);
178
152
  var isReadOnly = (record === null || record === void 0 ? void 0 : record.type) === "solidx";
179
153
  var isDirty = Boolean(record === null || record === void 0 ? void 0 : record.id) && currentForm() !== baseline.current;
180
154
  var requestRefresh = function () { return isDirty ? setConfirmRefresh(true) : void refetch(); };
181
- var addTag = function () {
182
- var nextTag = tagDraft.trim();
183
- if (!nextTag)
184
- return;
185
- if (!tags.some(function (tag) { return tag.toLowerCase() === nextTag.toLowerCase(); })) {
186
- setTags(function (current) { return __spreadArray(__spreadArray([], current, true), [nextTag], false); });
187
- }
188
- setTagDraft("");
189
- setFieldErrors(function (current) { return (__assign(__assign({}, current), { tags: "" })); });
190
- };
191
155
  var handleSave = function () { return __awaiter(_this, void 0, void 0, function () {
192
156
  var nextErrors, payload, result, createdId, error_1, errorDetail, serverFieldErrors, _i, _a, field;
193
157
  var _b, _c;
194
158
  return __generator(this, function (_d) {
195
159
  switch (_d.label) {
196
160
  case 0:
161
+ if (creatingTag)
162
+ return [2 /*return*/];
197
163
  nextErrors = {};
198
164
  if (!name.trim())
199
165
  nextErrors.name = "Name is required.";
@@ -203,8 +169,6 @@ export function AgentSkillRegistryEditorPage() {
203
169
  nextErrors.description = "Description is required.";
204
170
  if (!body.trim())
205
171
  nextErrors.body = "Skill instructions are required.";
206
- if (tags.length === 0)
207
- nextErrors.tags = "At least one tag is required.";
208
172
  setFieldErrors(nextErrors);
209
173
  if (Object.keys(nextErrors).length > 0) {
210
174
  setActiveTab(nextErrors.body ? "skill" : "general");
@@ -215,14 +179,7 @@ export function AgentSkillRegistryEditorPage() {
215
179
  }));
216
180
  return [2 /*return*/];
217
181
  }
218
- payload = {
219
- name: name.trim(),
220
- type: type,
221
- iconName: iconName || null,
222
- description: description.trim(),
223
- body: body,
224
- tags: JSON.stringify(tags),
225
- };
182
+ payload = __assign({ name: name.trim(), type: type, iconName: iconName || null, description: description.trim(), body: body }, agentHubTagsPayload(tags));
226
183
  _d.label = 1;
227
184
  case 1:
228
185
  _d.trys.push([1, 6, , 7]);
@@ -259,7 +216,7 @@ export function AgentSkillRegistryEditorPage() {
259
216
  errorDetail = getSaveErrorMessage(error_1);
260
217
  serverFieldErrors = {};
261
218
  if (/required|not be empty|cannot be empty|should not be empty/i.test(errorDetail)) {
262
- for (_i = 0, _a = ["name", "type", "description", "body", "tags"]; _i < _a.length; _i++) {
219
+ for (_i = 0, _a = ["name", "type", "description", "body"]; _i < _a.length; _i++) {
263
220
  field = _a[_i];
264
221
  if (!new RegExp("\\b".concat(field, "\\b"), "i").test(errorDetail))
265
222
  continue;
@@ -268,7 +225,7 @@ export function AgentSkillRegistryEditorPage() {
268
225
  }
269
226
  if (Object.keys(serverFieldErrors).length > 0) {
270
227
  setFieldErrors(serverFieldErrors);
271
- setActiveTab(serverFieldErrors.body || serverFieldErrors.tags ? "skill" : "general");
228
+ setActiveTab(serverFieldErrors.body ? "skill" : "general");
272
229
  }
273
230
  dispatch(showToast({
274
231
  severity: "error",
@@ -294,19 +251,7 @@ export function AgentSkillRegistryEditorPage() {
294
251
  } }), fieldErrors.description && _jsx("small", { id: "agent-skill-description-error", className: "agent-skill-editor__field-error", children: fieldErrors.description })] })] }), _jsxs("label", { className: "agent-skill-editor__field", children: [_jsxs("span", { children: ["Skill type ", _jsx("b", { children: "*" })] }), _jsxs("select", { value: type, "aria-invalid": Boolean(fieldErrors.type), "aria-describedby": fieldErrors.type ? "agent-skill-type-error" : undefined, className: fieldErrors.type ? "agent-skill-editor__input--invalid" : undefined, onChange: function (event) {
295
252
  setType(event.target.value);
296
253
  setFieldErrors(function (current) { return (__assign(__assign({}, current), { type: "" })); });
297
- }, children: [isReadOnly && _jsx("option", { value: "solidx", children: "SolidX" }), _jsx("option", { value: "thirdparty", children: "Third Party" }), _jsx("option", { value: "custom", children: "Custom" })] }), fieldErrors.type && _jsx("small", { id: "agent-skill-type-error", className: "agent-skill-editor__field-error", children: fieldErrors.type })] }), _jsxs("div", { className: "agent-skill-editor__field", children: [_jsxs("span", { children: ["Tags ", _jsx("b", { children: "*" })] }), _jsxs("div", { className: "agent-skill-editor__tag-input".concat(fieldErrors.tags ? " agent-skill-editor__tag-input--invalid" : ""), children: [tags.map(function (tag, index) { return (_jsxs("span", { className: "agent-skill-editor__tag", children: [tag, _jsx("button", { type: "button", "aria-label": "Remove ".concat(tag), onClick: function () {
298
- setTags(function (current) {
299
- var nextTags = current.filter(function (_, tagIndex) { return tagIndex !== index; });
300
- if (nextTags.length > 0)
301
- setFieldErrors(function (errors) { return (__assign(__assign({}, errors), { tags: "" })); });
302
- return nextTags;
303
- });
304
- }, children: _jsx(X, { size: 13 }) })] }, "".concat(tag, "-").concat(index))); }), _jsx("input", { value: tagDraft, "aria-label": "Add a tag", placeholder: "Type a tag and press Enter", onChange: function (event) { return setTagDraft(event.target.value); }, onKeyDown: function (event) {
305
- if (event.key === "Enter") {
306
- event.preventDefault();
307
- addTag();
308
- }
309
- } }), _jsxs(SolidButton, { type: "button", variant: "secondary", size: "small", onClick: addTag, children: [_jsx(Plus, { size: 14 }), " Add"] })] }), fieldErrors.tags && _jsx("small", { className: "agent-skill-editor__field-error", children: fieldErrors.tags }), _jsx("small", { children: "Tags are saved as a JSON array." })] })] })),
254
+ }, children: [isReadOnly && _jsx("option", { value: "solidx", children: "SolidX" }), _jsx("option", { value: "thirdparty", children: "Third Party" }), _jsx("option", { value: "custom", children: "Custom" })] }), fieldErrors.type && _jsx("small", { id: "agent-skill-type-error", className: "agent-skill-editor__field-error", children: fieldErrors.type })] }), _jsx(AgentHubTagsField, { value: tags, onChange: setTags, disabled: isReadOnly || isCreating || isSaving, onBusyChange: setCreatingTag })] })),
310
255
  },
311
256
  {
312
257
  value: "skill",
@@ -325,6 +270,6 @@ export function AgentSkillRegistryEditorPage() {
325
270
  }) })) : (_jsx("div", { className: "agent-skill-editor__empty", children: "No agents are currently associated with this skill." }))] })),
326
271
  },
327
272
  ];
328
- return (_jsxs("main", { className: "agent-skill-editor", children: [_jsxs("header", { className: "agent-skill-editor__header", children: [_jsx("div", { children: _jsxs("div", { className: "agent-skill-editor__heading-with-refresh", children: [_jsx("h1", { children: record ? "Edit Skill" : "Create Skill" }), (record === null || record === void 0 ? void 0 : record.id) && _jsx("button", { type: "button", className: "agent-skill-editor__refresh".concat(isFetching ? " is-loading" : ""), "aria-label": "Refresh skill", title: "Refresh skill", disabled: isFetching || isSaving, onClick: requestRefresh, children: _jsx(RefreshCw, { size: 14 }) })] }) }), _jsxs("div", { className: "agent-skill-editor__actions", children: [_jsx(SolidButton, { variant: "secondary", leftIcon: _jsx(ArrowLeft, { size: 16 }), onClick: function () { return navigate(-1); }, children: "Back" }), !isReadOnly && (_jsx(SolidButton, { loading: isCreating || isSaving, onClick: handleSave, children: "Save Skill" }))] })] }), _jsx(SolidDialog, { open: confirmRefresh, onOpenChange: setConfirmRefresh, header: "Discard unsaved changes?", style: { width: "min(28rem, 94vw)" }, footer: _jsxs(_Fragment, { children: [_jsx(SolidButton, { type: "button", variant: "secondary", onClick: function () { return setConfirmRefresh(false); }, children: "Cancel" }), _jsx(SolidButton, { type: "button", disabled: isFetching, onClick: function () { setConfirmRefresh(false); void refetch(); }, children: "Refresh and discard" })] }), children: _jsx(SolidDialogBody, { children: _jsx("p", { children: "You have unsaved changes. Refreshing will discard them and load the latest skill content." }) }) }), isLoading ? (_jsx("div", { className: "agent-skill-editor__loading", children: "Loading skill\u2026" })) : (record === null || record === void 0 ? void 0 : record.id) ? (_jsx(AgentRegistryAuditPanel, { modelSingularName: "agentSkillRegistry", recordId: record.id, refreshVersion: auditRefreshVersion, modelUserKey: record.name, children: _jsx(SolidTabGroup, { tabs: tabs, value: activeTab, onValueChange: setActiveTab, className: "agent-skill-editor__tabs", listClassName: "agent-skill-editor__tab-list", panelClassName: "agent-skill-editor__tab-panel" }) })) : (_jsx(SolidTabGroup, { tabs: tabs, value: activeTab, onValueChange: setActiveTab, className: "agent-skill-editor__tabs", listClassName: "agent-skill-editor__tab-list", panelClassName: "agent-skill-editor__tab-panel" }))] }));
273
+ return (_jsxs("main", { className: "agent-skill-editor", children: [_jsxs("header", { className: "agent-skill-editor__header", children: [_jsx("div", { children: _jsxs("div", { className: "agent-skill-editor__heading-with-refresh", children: [_jsx("h1", { children: record ? "Edit Skill" : "Create Skill" }), (record === null || record === void 0 ? void 0 : record.id) && _jsx("button", { type: "button", className: "agent-skill-editor__refresh".concat(isFetching ? " is-loading" : ""), "aria-label": "Refresh skill", title: "Refresh skill", disabled: isFetching || isSaving, onClick: requestRefresh, children: _jsx(RefreshCw, { size: 14 }) })] }) }), _jsxs("div", { className: "agent-skill-editor__actions", children: [_jsx(SolidButton, { variant: "secondary", leftIcon: _jsx(ArrowLeft, { size: 16 }), onClick: function () { return navigate(-1); }, children: "Back" }), !isReadOnly && (_jsx(SolidButton, { loading: isCreating || isSaving, disabled: creatingTag, onClick: handleSave, children: "Save Skill" }))] })] }), _jsx(SolidDialog, { open: confirmRefresh, onOpenChange: setConfirmRefresh, header: "Discard unsaved changes?", style: { width: "min(28rem, 94vw)" }, footer: _jsxs(_Fragment, { children: [_jsx(SolidButton, { type: "button", variant: "secondary", onClick: function () { return setConfirmRefresh(false); }, children: "Cancel" }), _jsx(SolidButton, { type: "button", disabled: isFetching, onClick: function () { setConfirmRefresh(false); void refetch(); }, children: "Refresh and discard" })] }), children: _jsx(SolidDialogBody, { children: _jsx("p", { children: "You have unsaved changes. Refreshing will discard them and load the latest skill content." }) }) }), isLoading ? (_jsx("div", { className: "agent-skill-editor__loading", children: "Loading skill\u2026" })) : (record === null || record === void 0 ? void 0 : record.id) ? (_jsx(AgentRegistryAuditPanel, { modelSingularName: "agentSkillRegistry", recordId: record.id, refreshVersion: auditRefreshVersion, modelUserKey: record.name, children: _jsx(SolidTabGroup, { tabs: tabs, value: activeTab, onValueChange: setActiveTab, className: "agent-skill-editor__tabs", listClassName: "agent-skill-editor__tab-list", panelClassName: "agent-skill-editor__tab-panel" }) })) : (_jsx(SolidTabGroup, { tabs: tabs, value: activeTab, onValueChange: setActiveTab, className: "agent-skill-editor__tabs", listClassName: "agent-skill-editor__tab-list", panelClassName: "agent-skill-editor__tab-panel" }))] }));
329
274
  }
330
275
  //# sourceMappingURL=AgentSkillRegistryEditorPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AgentSkillRegistryEditorPage.js","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EACL,WAAW,EACX,eAAe,EACf,WAAW,EACX,eAAe,EACf,eAAe,EACf,UAAU,EACV,aAAa,GACd,MAAM,mCAAmC,CAAC;AAC3C,OAAO,oCAAoC,CAAC;AAoB5C,SAAS,mBAAmB,CAAC,QAAiB;IAC5C,IAAI,SAAS,GAAY,QAAQ,CAAC;IAClC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE;QACzC,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QAClE,IAAM,KAAK,GAAG,SAAoC,CAAC;QACnD,IAAI,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACnD,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;KACxB;IACD,OAAO,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAgC,CAAC,CAAC,CAAC,SAAS,CAAC;AACnG,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACxB,OAAO,KAAK,CAAC,GAAG,CAAC,UAAC,GAAG,IAAK,OAAA,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAlB,CAAkB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;KAC/D;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAE1D,IAAI;QACF,IAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACzB,OAAO,MAAM,CAAC,GAAG,CAAC,UAAC,GAAG,IAAK,OAAA,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAlB,CAAkB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;SAChE;KACF;IAAC,WAAM;QACN,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,UAAC,GAAG,IAAK,OAAA,GAAG,CAAC,IAAI,EAAE,EAAV,CAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;KACxF;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;;IACxC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;IAChE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACxB,IAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,UAAC,OAAO,IAAwB,OAAA,OAAO,CAAC,OAAO,CAAC,EAAhB,CAAgB,CAAC,CAAC;QACxG,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;KAC1D;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QACtC,IAAM,KAAK,GAAG,KAAgC,CAAC;QAC/C,OAAO,MAAA,MAAA,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,mCACnC,kBAAkB,CAAC,KAAK,CAAC,WAAW,CAAC,mCACrC,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;KACtC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc;;IACzC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,uBAAuB,CAAC;IACxE,IAAM,QAAQ,GAAG,KAA4B,CAAC;IAC9C,4EAA4E;IAC5E,qDAAqD;IACrD,OAAO,MAAA,MAAA,MAAA,MAAA,kBAAkB,CAAC,MAAA,MAAA,QAAQ,CAAC,IAAI,0CAAE,IAAI,0CAAE,OAAO,CAAC,mCAClD,kBAAkB,CAAC,MAAA,QAAQ,CAAC,IAAI,0CAAE,OAAO,CAAC,mCAC1C,kBAAkB,CAAC,MAAA,QAAQ,CAAC,IAAI,0CAAE,KAAK,CAAC,mCACxC,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,mCACpC,uBAAuB,CAAC;AAC/B,CAAC;AAED,SAAS,WAAW,CAAC,MAAoB;IACvC,IAAM,OAAO,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,CAAC;IACpC,IAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAClC,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,OAAO;YACP,CAAC,CAAC,CAAC,OAAO,CAAC;YACX,CAAC,CAAC,EAAE,CAAC;IACT,IAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,OAAO,KAAK;SACT,GAAG,CAAC,UAAC,IAAI,IAAK,OAAA,IAAI,CAAC,aAAa,EAAlB,CAAkB,CAAC;SACjC,MAAM,CAAC,UAAC,KAAK,IAA8B,OAAA,OAAO,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,EAA3C,CAA2C,CAAC;SACvF,MAAM,CAAC,UAAC,KAAK;;QACZ,IAAM,GAAG,GAAG,MAAM,CAAC,MAAA,MAAA,MAAA,KAAK,CAAC,EAAE,mCAAI,KAAK,CAAC,IAAI,mCAAI,KAAK,CAAC,KAAK,mCAAI,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,4BAA4B;IAA5C,iBA0VC;IAzVS,IAAA,KAAY,SAAS,EAAkB,GAAhC,EAAP,EAAE,mBAAG,EAAE,KAAA,CAAiC;IAChD,IAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,cAAM,OAAA,oBAAoB,CAAC,oBAAoB,CAAC,EAA1C,CAA0C,EAAE,EAAE,CAAC,CAAC;IAEpF,IAAA,4BAA4B,GAG1B,SAAS,6BAHiB,EAC5B,0BAA0B,GAExB,SAAS,2BAFe,EAC1B,4BAA4B,GAC1B,SAAS,6BADiB,CAChB;IAER,IAAA,KAAqD,0BAA0B,CACnF;QACE,EAAE,IAAA;QACF,EAAE,EAAE,+DAA+D;KACpE,EACD,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE,CAC9B,EANa,QAAQ,UAAA,EAAE,SAAS,eAAA,EAAE,UAAU,gBAAA,EAAE,OAAO,aAMrD,CAAC;IACI,IAAA,KAA2C,4BAA4B,EAAE,EAAxE,WAAW,QAAA,EAAe,UAAU,kBAAoC,CAAC;IAC1E,IAAA,KAAyC,4BAA4B,EAAE,EAAtE,WAAW,QAAA,EAAe,QAAQ,kBAAoC,CAAC;IAC9E,IAAM,MAAM,GAAG,mBAAmB,CAAC,QAAQ,CAA4B,CAAC;IAElE,IAAA,KAA4B,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAApD,SAAS,QAAA,EAAE,YAAY,QAA6B,CAAC;IACtD,IAAA,KAAkB,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAnC,IAAI,QAAA,EAAE,OAAO,QAAsB,CAAC;IACrC,IAAA,KAAkB,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAzC,IAAI,QAAA,EAAE,OAAO,QAA4B,CAAC;IAC3C,IAAA,KAA0B,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAA3C,QAAQ,QAAA,EAAE,WAAW,QAAsB,CAAC;IAC7C,IAAA,KAAgC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAjD,WAAW,QAAA,EAAE,cAAc,QAAsB,CAAC;IACnD,IAAA,KAAkB,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAnC,IAAI,QAAA,EAAE,OAAO,QAAsB,CAAC;IACrC,IAAA,KAAkB,KAAK,CAAC,QAAQ,CAAW,EAAE,CAAC,EAA7C,IAAI,QAAA,EAAE,OAAO,QAAgC,CAAC;IAC/C,IAAA,KAA0B,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAA3C,QAAQ,QAAA,EAAE,WAAW,QAAsB,CAAC;IAC7C,IAAA,KAAgC,KAAK,CAAC,QAAQ,CAAyB,EAAE,CAAC,EAAzE,WAAW,QAAA,EAAE,cAAc,QAA8C,CAAC;IAC3E,IAAA,KAAgD,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAhE,mBAAmB,QAAA,EAAE,sBAAsB,QAAqB,CAAC;IAClE,IAAA,KAAsC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAA1D,cAAc,QAAA,EAAE,iBAAiB,QAAyB,CAAC;IAClE,IAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClC,IAAM,WAAW,GAAG,cAAM,OAAA,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,MAAA,EAAE,IAAI,MAAA,EAAE,QAAQ,UAAA,EAAE,WAAW,aAAA,EAAE,IAAI,MAAA,EAAE,IAAI,MAAA,EAAE,QAAQ,UAAA,EAAE,CAAC,EAA3E,CAA2E,CAAC;IAEtG,KAAK,CAAC,SAAS,CAAC;;QACd,IAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,CAAC,CAAC;QACzC,OAAO,CAAC,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,mCAAI,EAAE,CAAC,CAAC;QAC5B,OAAO,CAAC,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,mCAAI,QAAQ,CAAC,CAAC;QAClC,WAAW,CAAC,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,QAAQ,mCAAI,EAAE,CAAC,CAAC;QACpC,cAAc,CAAC,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,mCAAI,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,mCAAI,EAAE,CAAC,CAAC;QAC5B,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClB,WAAW,CAAC,EAAE,CAAC,CAAC;QAChB,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,mCAAI,EAAE,EAAE,IAAI,EAAE,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,mCAAI,QAAQ,EAAE,QAAQ,EAAE,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,QAAQ,mCAAI,EAAE,EAAE,WAAW,EAAE,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,mCAAI,EAAE,EAAE,IAAI,EAAE,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,mCAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IACpO,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,IAAM,UAAU,GAAG,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,MAAK,QAAQ,CAAC;IAC7C,IAAM,OAAO,GAAG,OAAO,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,EAAE,CAAC,IAAI,WAAW,EAAE,KAAK,QAAQ,CAAC,OAAO,CAAC;IAC1E,IAAM,cAAc,GAAG,cAAM,OAAA,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,EAAlD,CAAkD,CAAC;IAEhF,IAAM,MAAM,GAAG;QACb,IAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAC,GAAG,IAAK,OAAA,GAAG,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,EAA3C,CAA2C,CAAC,EAAE;YACpE,OAAO,CAAC,UAAC,OAAO,IAAK,uCAAI,OAAO,UAAE,OAAO,WAApB,CAAqB,CAAC,CAAC;SAC7C;QACD,WAAW,CAAC,EAAE,CAAC,CAAC;QAChB,cAAc,CAAC,UAAC,OAAO,IAAK,OAAA,uBAAM,OAAO,KAAE,IAAI,EAAE,EAAE,IAAG,EAA1B,CAA0B,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,IAAM,UAAU,GAAG;;;;;;oBACX,UAAU,GAA2B,EAAE,CAAC;oBAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;wBAAE,UAAU,CAAC,IAAI,GAAG,mBAAmB,CAAC;oBACxD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;wBAAE,UAAU,CAAC,IAAI,GAAG,yBAAyB,CAAC;oBAC9D,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;wBAAE,UAAU,CAAC,WAAW,GAAG,0BAA0B,CAAC;oBAC7E,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;wBAAE,UAAU,CAAC,IAAI,GAAG,kCAAkC,CAAC;oBACvE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;wBAAE,UAAU,CAAC,IAAI,GAAG,+BAA+B,CAAC;oBAEzE,cAAc,CAAC,UAAU,CAAC,CAAC;oBAC3B,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;wBACtC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;wBACpD,QAAQ,CAAC,SAAS,CAAC;4BACjB,QAAQ,EAAE,OAAO;4BACjB,OAAO,EAAE,qBAAqB;4BAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;yBAC5C,CAAC,CAAC,CAAC;wBACJ,sBAAO;qBACR;oBAEK,OAAO,GAAG;wBACd,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;wBACjB,IAAI,MAAA;wBACJ,QAAQ,EAAE,QAAQ,IAAI,IAAI;wBAC1B,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE;wBAC/B,IAAI,MAAA;wBACJ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;qBAC3B,CAAC;;;;yBAGI,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,EAAE,CAAA,EAAV,wBAAU;oBACZ,qBAAM,WAAW,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAA;;oBAA5D,SAA4D,CAAC;oBAC7D,QAAQ,CAAC,SAAS,CAAC;wBACjB,QAAQ,EAAE,SAAS;wBACnB,OAAO,EAAE,OAAO;wBAChB,MAAM,EAAE,6BAA6B;qBACtC,CAAC,CAAC,CAAC;oBACJ,sBAAsB,CAAC,UAAC,OAAO,IAAK,OAAA,OAAO,GAAG,CAAC,EAAX,CAAW,CAAC,CAAC;oBACjD,OAAO,EAAE,CAAC;;wBAEU,qBAAM,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAA;;oBAAjD,MAAM,GAAQ,SAAmC;oBACjD,SAAS,GAAG,MAAA,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,0CAAE,EAAE,mCAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,EAAE,CAAC;oBACjD,QAAQ,CAAC,SAAS,CAAC;wBACjB,QAAQ,EAAE,SAAS;wBACnB,OAAO,EAAE,SAAS;wBAClB,MAAM,EAAE,6BAA6B;qBACtC,CAAC,CAAC,CAAC;oBACJ,IAAI,SAAS,EAAE;wBACb,QAAQ,CAAC,6DAAsD,SAAS,CAAE,EAAE;4BAC1E,OAAO,EAAE,IAAI;yBACd,CAAC,CAAC;qBACJ;;;;;oBAGG,WAAW,GAAG,mBAAmB,CAAC,OAAK,CAAC,CAAC;oBACzC,iBAAiB,GAA2B,EAAE,CAAC;oBACrD,IAAI,4DAA4D,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;wBAClF,WAAmE,EAA/C,MAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,EAA/C,cAA+C,EAA/C,IAA+C,EAAE;4BAA1D,KAAK;4BACd,IAAI,CAAC,IAAI,MAAM,CAAC,aAAM,KAAK,QAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;gCAAE,SAAS;4BACnE,iBAAiB,CAAC,KAAK,CAAC,GAAG,UAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAe,CAAC;yBAChI;qBACF;oBACD,IAAI,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;wBAC7C,cAAc,CAAC,iBAAiB,CAAC,CAAC;wBAClC,YAAY,CAAC,iBAAiB,CAAC,IAAI,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;qBACtF;oBACD,QAAQ,CAAC,SAAS,CAAC;wBACjB,QAAQ,EAAE,OAAO;wBACjB,OAAO,EAAE,aAAa;wBACtB,MAAM,EAAE,WAAW;qBACpB,CAAC,CAAC,CAAC;;;;;SAEP,CAAC;IAEF,IAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,IAAM,IAAI,GAAG;QACX;YACE,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,cAAc;YACrB,OAAO,EAAE,CACP,oBAAU,SAAS,EAAC,6BAA6B,EAAC,QAAQ,EAAE,UAAU,aACnE,UAAU,IAAI,YAAG,SAAS,EAAC,mCAAmC,uFAA2E,EAC1I,eAAK,SAAS,EAAC,4BAA4B,aACzC,iBAAO,SAAS,EAAC,2BAA2B,aAC1C,oCAAW,4BAAQ,IAAO,EAC1B,KAAC,UAAU,IACT,KAAK,EAAE,IAAI,kBACG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,sBACrB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,SAAS,EACzE,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,SAAS,EAC9E,QAAQ,EAAE,UAAC,KAAK;4CACd,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;4CAC5B,cAAc,CAAC,UAAC,OAAO,IAAK,OAAA,uBAAM,OAAO,KAAE,IAAI,EAAE,EAAE,IAAG,EAA1B,CAA0B,CAAC,CAAC;wCAC1D,CAAC,GACD,EACD,WAAW,CAAC,IAAI,IAAI,gBAAO,EAAE,EAAC,wBAAwB,EAAC,SAAS,EAAC,iCAAiC,YAAE,WAAW,CAAC,IAAI,GAAS,IACxH,EACR,eAAK,SAAS,EAAC,2BAA2B,aACxC,kCAAiB,EACjB,KAAC,eAAe,IAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,GAAI,IACvD,EACN,iBAAO,SAAS,EAAC,2BAA2B,aAC1C,2CAAkB,4BAAQ,IAAO,EACjC,KAAC,UAAU,IACT,KAAK,EAAE,WAAW,kBACJ,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,sBAC5B,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,SAAS,EACvF,SAAS,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,SAAS,EACrF,QAAQ,EAAE,UAAC,KAAK;4CACd,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;4CACnC,cAAc,CAAC,UAAC,OAAO,IAAK,OAAA,uBAAM,OAAO,KAAE,WAAW,EAAE,EAAE,IAAG,EAAjC,CAAiC,CAAC,CAAC;wCACjE,CAAC,GACD,EACD,WAAW,CAAC,WAAW,IAAI,gBAAO,EAAE,EAAC,+BAA+B,EAAC,SAAS,EAAC,iCAAiC,YAAE,WAAW,CAAC,WAAW,GAAS,IAC7I,IACJ,EACN,iBAAO,SAAS,EAAC,2BAA2B,aAC1C,0CAAiB,4BAAQ,IAAO,EAChC,kBACE,KAAK,EAAE,IAAI,kBACG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,sBACrB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,SAAS,EACzE,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,SAAS,EAC9E,QAAQ,EAAE,UAAC,KAAK;oCACd,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oCAC5B,cAAc,CAAC,UAAC,OAAO,IAAK,OAAA,uBAAM,OAAO,KAAE,IAAI,EAAE,EAAE,IAAG,EAA1B,CAA0B,CAAC,CAAC;gCAC1D,CAAC,aAEA,UAAU,IAAI,iBAAQ,KAAK,EAAC,QAAQ,uBAAgB,EACrD,iBAAQ,KAAK,EAAC,YAAY,4BAAqB,EAC/C,iBAAQ,KAAK,EAAC,QAAQ,uBAAgB,IAC/B,EACR,WAAW,CAAC,IAAI,IAAI,gBAAO,EAAE,EAAC,wBAAwB,EAAC,SAAS,EAAC,iCAAiC,YAAE,WAAW,CAAC,IAAI,GAAS,IACxH,EACR,eAAK,SAAS,EAAC,2BAA2B,aACxC,oCAAW,4BAAQ,IAAO,EAC1B,eAAK,SAAS,EAAE,uCAAgC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,yCAAyC,CAAC,CAAC,CAAC,EAAE,CAAE,aAChH,IAAI,CAAC,GAAG,CAAC,UAAC,GAAG,EAAE,KAAK,IAAK,OAAA,CACxB,gBAAM,SAAS,EAAC,yBAAyB,aACtC,GAAG,EACJ,iBACE,IAAI,EAAC,QAAQ,gBACD,iBAAU,GAAG,CAAE,EAC3B,OAAO,EAAE;oDACP,OAAO,CAAC,UAAC,OAAO;wDACd,IAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,CAAC,EAAE,QAAQ,IAAK,OAAA,QAAQ,KAAK,KAAK,EAAlB,CAAkB,CAAC,CAAC;wDACrE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;4DAAE,cAAc,CAAC,UAAC,MAAM,IAAK,OAAA,uBAAM,MAAM,KAAE,IAAI,EAAE,EAAE,IAAG,EAAzB,CAAyB,CAAC,CAAC;wDAC/E,OAAO,QAAQ,CAAC;oDAClB,CAAC,CAAC,CAAC;gDACL,CAAC,YAED,KAAC,CAAC,IAAC,IAAI,EAAE,EAAE,GAAI,GACR,KAdoC,UAAG,GAAG,cAAI,KAAK,CAAE,CAezD,CACR,EAjByB,CAiBzB,CAAC,EACF,gBACE,KAAK,EAAE,QAAQ,gBACJ,WAAW,EACtB,WAAW,EAAC,4BAA4B,EACxC,QAAQ,EAAE,UAAC,KAAK,IAAK,OAAA,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAA/B,CAA+B,EACpD,SAAS,EAAE,UAAC,KAAK;4CACf,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE;gDACzB,KAAK,CAAC,cAAc,EAAE,CAAC;gDACvB,MAAM,EAAE,CAAC;6CACV;wCACH,CAAC,GACD,EACF,MAAC,WAAW,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,MAAM,aACzE,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,GAAI,YACN,IACV,EACL,WAAW,CAAC,IAAI,IAAI,gBAAO,SAAS,EAAC,iCAAiC,YAAE,WAAW,CAAC,IAAI,GAAS,EAClG,8DAA8C,IAC1C,IACG,CACZ;SACF;QACD;YACE,KAAK,EAAE,OAAO;YACd,KAAK,EAAE,OAAO;YACd,OAAO,EAAE,CACP,cAAK,SAAS,EAAC,2BAA2B,YACxC,mBAAS,SAAS,EAAC,2BAA2B,aAC5C,6BACE,gDAAuB,4BAAQ,IAAK,EACpC,gEAA4C,IACrC,EACT,KAAC,eAAe,IACd,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,UAAC,KAAK;gCACd,OAAO,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC,CAAC;gCACrB,cAAc,CAAC,UAAC,OAAO,IAAK,OAAA,uBAAM,OAAO,KAAE,IAAI,EAAE,EAAE,IAAG,EAA1B,CAA0B,CAAC,CAAC;4BAC1D,CAAC,EACD,QAAQ,EAAC,UAAU,EACnB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,EAAE,EACZ,MAAM,EAAC,kCAAkC,EACzC,SAAS,EAAE,kCAA2B,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,EAAE,CAAE,GACpG,EACD,WAAW,CAAC,IAAI,IAAI,gBAAO,SAAS,EAAC,gEAAgE,YAAE,WAAW,CAAC,IAAI,GAAS,IACzH,GACN,CACP;SACF;QACD;YACE,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,CACP,mBAAS,SAAS,EAAC,4BAA4B,aAC7C,0BACE,6CAA0B,EAC1B,wFAAoE,IAChE,EACL,SAAS,CAAC,CAAC,CAAC,CACX,0DAAiC,CAClC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAClB,cAAK,SAAS,EAAC,gCAAgC,YAC5C,MAAM,CAAC,GAAG,CAAC,UAAC,KAAK,EAAE,KAAK;;4BAAK,OAAA,CAC5B,mBAAS,SAAS,EAAC,gCAAgC,aACjD,yBAAO,CAAC,MAAA,MAAA,KAAK,CAAC,IAAI,mCAAI,KAAK,CAAC,KAAK,mCAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,GAAQ,EAC3E,2BAAS,MAAA,MAAA,KAAK,CAAC,IAAI,mCAAI,KAAK,CAAC,KAAK,mCAAI,eAAe,GAAU,KAFR,MAAM,CAAC,MAAA,MAAA,KAAK,CAAC,EAAE,mCAAI,KAAK,CAAC,IAAI,mCAAI,KAAK,CAAC,CAGtF,CACX,CAAA;yBAAA,CAAC,GACE,CACP,CAAC,CAAC,CAAC,CACF,cAAK,SAAS,EAAC,2BAA2B,oEAA0D,CACrG,IACO,CACX;SACF;KACF,CAAC;IAEF,OAAO,CACL,gBAAM,SAAS,EAAC,oBAAoB,aAClC,kBAAQ,SAAS,EAAC,4BAA4B,aAC5C,wBACE,eAAK,SAAS,EAAC,0CAA0C,aAAC,uBAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,GAAM,EAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,EAAE,KAAI,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,qCAA8B,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAE,gBAAa,eAAe,EAAC,KAAK,EAAC,eAAe,EAAC,QAAQ,EAAE,UAAU,IAAI,QAAQ,EAAE,OAAO,EAAE,cAAc,YAAE,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,GAAS,IAAO,GAC3W,EACN,eAAK,SAAS,EAAC,6BAA6B,aAC1C,KAAC,WAAW,IAAC,OAAO,EAAC,WAAW,EAAC,QAAQ,EAAE,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,EAAE,OAAO,EAAE,cAAM,OAAA,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAZ,CAAY,qBAEjF,EACb,CAAC,UAAU,IAAI,CACd,KAAC,WAAW,IAAC,OAAO,EAAE,UAAU,IAAI,QAAQ,EAAE,OAAO,EAAE,UAAU,2BAEnD,CACf,IACG,IACC,EAET,KAAC,WAAW,IAAC,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,EAAC,0BAA0B,EAAC,KAAK,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,EACxI,MAAM,EAAE,8BAAE,KAAC,WAAW,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,WAAW,EAAC,OAAO,EAAE,cAAM,OAAA,iBAAiB,CAAC,KAAK,CAAC,EAAxB,CAAwB,uBAAsB,EAAA,KAAC,WAAW,IAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,cAAQ,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,oCAAmC,IAAG,YACzQ,KAAC,eAAe,cAAC,oHAAgG,GAAkB,GACvH,EAEb,SAAS,CAAC,CAAC,CAAC,CACX,cAAK,SAAS,EAAC,6BAA6B,oCAAqB,CAClE,CAAC,CAAC,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,EAAE,EAAC,CAAC,CAAC,CACf,KAAC,uBAAuB,IACtB,iBAAiB,EAAC,oBAAoB,EACtC,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,cAAc,EAAE,mBAAmB,EACnC,YAAY,EAAE,MAAM,CAAC,IAAI,YAEzB,KAAC,aAAa,IACZ,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,YAAY,EAC3B,SAAS,EAAC,0BAA0B,EACpC,aAAa,EAAC,8BAA8B,EAC5C,cAAc,EAAC,+BAA+B,GAC9C,GACsB,CAC3B,CAAC,CAAC,CAAC,CACF,KAAC,aAAa,IACZ,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,YAAY,EAC3B,SAAS,EAAC,0BAA0B,EACpC,aAAa,EAAC,8BAA8B,EAC5C,cAAc,EAAC,+BAA+B,GAC9C,CACH,IACI,CACR,CAAC;AACJ,CAAC","sourcesContent":["import React from \"react\";\nimport { ArrowLeft, Plus, RefreshCw, X } from \"lucide-react\";\nimport { useDispatch } from \"react-redux\";\nimport { useNavigate, useParams } from \"react-router-dom\";\nimport { createSolidEntityApi } from \"../../../../redux/api/solidEntityApi\";\nimport { showToast } from \"../../../../redux/features/toastSlice\";\nimport { AgentRegistryAuditPanel } from \"./AgentRegistryAuditPanel\";\nimport {\n SolidButton,\n SolidCodeEditor,\n SolidDialog,\n SolidDialogBody,\n SolidIconPicker,\n SolidInput,\n SolidTabGroup,\n} from \"../../../../components/shad-cn-ui\";\nimport \"./AgentSkillRegistryEditorPage.css\";\n\ntype AgentReference = {\n id?: number | string;\n name?: string;\n title?: string;\n agentRegistry?: AgentReference | number | string | null;\n};\n\ntype SkillRecord = {\n id: number;\n name?: string;\n type?: string;\n iconName?: string | null;\n description?: string;\n body?: string;\n tags?: unknown;\n agentSkills?: AgentReference[] | AgentReference | null;\n};\n\nfunction extractEntityRecord(response: unknown): Record<string, any> | undefined {\n let candidate: unknown = response;\n for (let depth = 0; depth < 3; depth += 1) {\n if (!candidate || typeof candidate !== \"object\") return undefined;\n const value = candidate as Record<string, unknown>;\n if (\"id\" in value || \"name\" in value) return value;\n candidate = value.data;\n }\n return candidate && typeof candidate === \"object\" ? candidate as Record<string, any> : undefined;\n}\n\nfunction parseTags(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.map((tag) => String(tag).trim()).filter(Boolean);\n }\n\n if (typeof value !== \"string\" || !value.trim()) return [];\n\n try {\n const parsed = JSON.parse(value);\n if (Array.isArray(parsed)) {\n return parsed.map((tag) => String(tag).trim()).filter(Boolean);\n }\n } catch {\n return value === \"{}\" ? [] : value.split(\",\").map((tag) => tag.trim()).filter(Boolean);\n }\n\n return [];\n}\n\nfunction formatErrorMessage(value: unknown): string | undefined {\n if (typeof value === \"string\") return value.trim() || undefined;\n if (Array.isArray(value)) {\n const messages = value.map(formatErrorMessage).filter((message): message is string => Boolean(message));\n return messages.length ? messages.join(\"; \") : undefined;\n }\n if (value && typeof value === \"object\") {\n const error = value as Record<string, unknown>;\n return formatErrorMessage(error.message)\n ?? formatErrorMessage(error.constraints)\n ?? formatErrorMessage(error.error);\n }\n return undefined;\n}\n\nfunction getSaveErrorMessage(error: unknown): string {\n if (!error || typeof error !== \"object\") return \"Failed to save skill.\";\n const apiError = error as Record<string, any>;\n // Nest validation details are nested at data.data.message; prefer them over\n // the generic outer \"Bad Request Exception\" message.\n return formatErrorMessage(apiError.data?.data?.message)\n ?? formatErrorMessage(apiError.data?.message)\n ?? formatErrorMessage(apiError.data?.error)\n ?? formatErrorMessage(apiError.message)\n ?? \"Failed to save skill.\";\n}\n\nfunction skillAgents(record?: SkillRecord): AgentReference[] {\n const related = record?.agentSkills;\n const links = Array.isArray(related)\n ? related\n : related\n ? [related]\n : [];\n const seen = new Set<string>();\n\n return links\n .map((link) => link.agentRegistry)\n .filter((agent): agent is AgentReference => Boolean(agent && typeof agent === \"object\"))\n .filter((agent) => {\n const key = String(agent.id ?? agent.name ?? agent.title ?? \"\");\n if (!key || seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport function AgentSkillRegistryEditorPage() {\n const { id = \"\" } = useParams<{ id: string }>();\n const navigate = useNavigate();\n const dispatch = useDispatch();\n const entityApi = React.useMemo(() => createSolidEntityApi(\"agentSkillRegistry\"), []);\n const {\n useCreateSolidEntityMutation,\n useGetSolidEntityByIdQuery,\n useUpdateSolidEntityMutation,\n } = entityApi;\n\n const { data: response, isLoading, isFetching, refetch } = useGetSolidEntityByIdQuery(\n {\n id,\n qs: \"populate[0]=agentSkills&populate[1]=agentSkills.agentRegistry\",\n },\n { skip: !id || id === \"new\" },\n );\n const [createSkill, { isLoading: isCreating }] = useCreateSolidEntityMutation();\n const [updateSkill, { isLoading: isSaving }] = useUpdateSolidEntityMutation();\n const record = extractEntityRecord(response) as SkillRecord | undefined;\n\n const [activeTab, setActiveTab] = React.useState(\"general\");\n const [name, setName] = React.useState(\"\");\n const [type, setType] = React.useState(\"custom\");\n const [iconName, setIconName] = React.useState(\"\");\n const [description, setDescription] = React.useState(\"\");\n const [body, setBody] = React.useState(\"\");\n const [tags, setTags] = React.useState<string[]>([]);\n const [tagDraft, setTagDraft] = React.useState(\"\");\n const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({});\n const [auditRefreshVersion, setAuditRefreshVersion] = React.useState(0);\n const [confirmRefresh, setConfirmRefresh] = React.useState(false);\n const baseline = React.useRef(\"\");\n const currentForm = () => JSON.stringify({ name, type, iconName, description, body, tags, tagDraft });\n\n React.useEffect(() => {\n const nextTags = parseTags(record?.tags);\n setName(record?.name ?? \"\");\n setType(record?.type ?? \"custom\");\n setIconName(record?.iconName ?? \"\");\n setDescription(record?.description ?? \"\");\n setBody(record?.body ?? \"\");\n setTags(nextTags);\n setTagDraft(\"\");\n baseline.current = JSON.stringify({ name: record?.name ?? \"\", type: record?.type ?? \"custom\", iconName: record?.iconName ?? \"\", description: record?.description ?? \"\", body: record?.body ?? \"\", tags: nextTags, tagDraft: \"\" });\n }, [record]);\n\n const isReadOnly = record?.type === \"solidx\";\n const isDirty = Boolean(record?.id) && currentForm() !== baseline.current;\n const requestRefresh = () => isDirty ? setConfirmRefresh(true) : void refetch();\n\n const addTag = () => {\n const nextTag = tagDraft.trim();\n if (!nextTag) return;\n if (!tags.some((tag) => tag.toLowerCase() === nextTag.toLowerCase())) {\n setTags((current) => [...current, nextTag]);\n }\n setTagDraft(\"\");\n setFieldErrors((current) => ({ ...current, tags: \"\" }));\n };\n\n const handleSave = async () => {\n const nextErrors: Record<string, string> = {};\n if (!name.trim()) nextErrors.name = \"Name is required.\";\n if (!type.trim()) nextErrors.type = \"Skill type is required.\";\n if (!description.trim()) nextErrors.description = \"Description is required.\";\n if (!body.trim()) nextErrors.body = \"Skill instructions are required.\";\n if (tags.length === 0) nextErrors.tags = \"At least one tag is required.\";\n\n setFieldErrors(nextErrors);\n if (Object.keys(nextErrors).length > 0) {\n setActiveTab(nextErrors.body ? \"skill\" : \"general\");\n dispatch(showToast({\n severity: \"error\",\n summary: \"Missing information\",\n detail: Object.values(nextErrors).join(\" \"),\n }));\n return;\n }\n\n const payload = {\n name: name.trim(),\n type,\n iconName: iconName || null,\n description: description.trim(),\n body,\n tags: JSON.stringify(tags),\n };\n\n try {\n if (record?.id) {\n await updateSkill({ id: record.id, data: payload }).unwrap();\n dispatch(showToast({\n severity: \"success\",\n summary: \"Saved\",\n detail: \"Skill updated successfully.\",\n }));\n setAuditRefreshVersion((version) => version + 1);\n refetch();\n } else {\n const result: any = await createSkill(payload).unwrap();\n const createdId = result?.data?.id ?? result?.id;\n dispatch(showToast({\n severity: \"success\",\n summary: \"Created\",\n detail: \"Skill created successfully.\",\n }));\n if (createdId) {\n navigate(`/admin/core/solid-core/agent-skill-registry/editor/${createdId}`, {\n replace: true,\n });\n }\n }\n } catch (error: any) {\n const errorDetail = getSaveErrorMessage(error);\n const serverFieldErrors: Record<string, string> = {};\n if (/required|not be empty|cannot be empty|should not be empty/i.test(errorDetail)) {\n for (const field of [\"name\", \"type\", \"description\", \"body\", \"tags\"]) {\n if (!new RegExp(`\\\\b${field}\\\\b`, \"i\").test(errorDetail)) continue;\n serverFieldErrors[field] = `${field === \"body\" ? \"Skill instructions\" : field[0].toUpperCase() + field.slice(1)} is required.`;\n }\n }\n if (Object.keys(serverFieldErrors).length > 0) {\n setFieldErrors(serverFieldErrors);\n setActiveTab(serverFieldErrors.body || serverFieldErrors.tags ? \"skill\" : \"general\");\n }\n dispatch(showToast({\n severity: \"error\",\n summary: \"Save failed\",\n detail: errorDetail,\n }));\n }\n };\n\n const agents = skillAgents(record);\n const tabs = [\n {\n value: \"general\",\n label: \"General Info\",\n content: (\n <fieldset className=\"agent-skill-editor__general\" disabled={isReadOnly}>\n {isReadOnly && <p className=\"agent-skill-editor__readonly-note\">SolidX skills are seeded by the AgentHub runtime and cannot be edited.</p>}\n <div className=\"agent-skill-editor__fields\">\n <label className=\"agent-skill-editor__field\">\n <span>Name <b>*</b></span>\n <SolidInput\n value={name}\n aria-invalid={Boolean(fieldErrors.name)}\n aria-describedby={fieldErrors.name ? \"agent-skill-name-error\" : undefined}\n className={fieldErrors.name ? \"agent-skill-editor__input--invalid\" : undefined}\n onChange={(event) => {\n setName(event.target.value);\n setFieldErrors((current) => ({ ...current, name: \"\" }));\n }}\n />\n {fieldErrors.name && <small id=\"agent-skill-name-error\" className=\"agent-skill-editor__field-error\">{fieldErrors.name}</small>}\n </label>\n <div className=\"agent-skill-editor__field\">\n <span>Icon</span>\n <SolidIconPicker value={iconName} onChange={setIconName} />\n </div>\n <label className=\"agent-skill-editor__field\">\n <span>Description <b>*</b></span>\n <SolidInput\n value={description}\n aria-invalid={Boolean(fieldErrors.description)}\n aria-describedby={fieldErrors.description ? \"agent-skill-description-error\" : undefined}\n className={fieldErrors.description ? \"agent-skill-editor__input--invalid\" : undefined}\n onChange={(event) => {\n setDescription(event.target.value);\n setFieldErrors((current) => ({ ...current, description: \"\" }));\n }}\n />\n {fieldErrors.description && <small id=\"agent-skill-description-error\" className=\"agent-skill-editor__field-error\">{fieldErrors.description}</small>}\n </label>\n </div>\n <label className=\"agent-skill-editor__field\">\n <span>Skill type <b>*</b></span>\n <select\n value={type}\n aria-invalid={Boolean(fieldErrors.type)}\n aria-describedby={fieldErrors.type ? \"agent-skill-type-error\" : undefined}\n className={fieldErrors.type ? \"agent-skill-editor__input--invalid\" : undefined}\n onChange={(event) => {\n setType(event.target.value);\n setFieldErrors((current) => ({ ...current, type: \"\" }));\n }}\n >\n {isReadOnly && <option value=\"solidx\">SolidX</option>}\n <option value=\"thirdparty\">Third Party</option>\n <option value=\"custom\">Custom</option>\n </select>\n {fieldErrors.type && <small id=\"agent-skill-type-error\" className=\"agent-skill-editor__field-error\">{fieldErrors.type}</small>}\n </label>\n <div className=\"agent-skill-editor__field\">\n <span>Tags <b>*</b></span>\n <div className={`agent-skill-editor__tag-input${fieldErrors.tags ? \" agent-skill-editor__tag-input--invalid\" : \"\"}`}>\n {tags.map((tag, index) => (\n <span className=\"agent-skill-editor__tag\" key={`${tag}-${index}`}>\n {tag}\n <button\n type=\"button\"\n aria-label={`Remove ${tag}`}\n onClick={() => {\n setTags((current) => {\n const nextTags = current.filter((_, tagIndex) => tagIndex !== index);\n if (nextTags.length > 0) setFieldErrors((errors) => ({ ...errors, tags: \"\" }));\n return nextTags;\n });\n }}\n >\n <X size={13} />\n </button>\n </span>\n ))}\n <input\n value={tagDraft}\n aria-label=\"Add a tag\"\n placeholder=\"Type a tag and press Enter\"\n onChange={(event) => setTagDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n addTag();\n }\n }}\n />\n <SolidButton type=\"button\" variant=\"secondary\" size=\"small\" onClick={addTag}>\n <Plus size={14} /> Add\n </SolidButton>\n </div>\n {fieldErrors.tags && <small className=\"agent-skill-editor__field-error\">{fieldErrors.tags}</small>}\n <small>Tags are saved as a JSON array.</small>\n </div>\n </fieldset>\n ),\n },\n {\n value: \"skill\",\n label: \"Skill\",\n content: (\n <div className=\"agent-skill-editor__skill\">\n <section className=\"agent-skill-editor__panel\">\n <header>\n <h2>Skill instructions <b>*</b></h2>\n <p>Write the skill's Markdown body here.</p>\n </header>\n <SolidCodeEditor\n value={body}\n onChange={(value) => {\n setBody(value ?? \"\");\n setFieldErrors((current) => ({ ...current, body: \"\" }));\n }}\n language=\"markdown\"\n readOnly={isReadOnly}\n fontSize={11}\n height=\"max(32rem, calc(100dvh - 18rem))\"\n className={`agent-skill-editor__code${fieldErrors.body ? \" agent-skill-editor__code--invalid\" : \"\"}`}\n />\n {fieldErrors.body && <small className=\"agent-skill-editor__field-error agent-skill-editor__body-error\">{fieldErrors.body}</small>}\n </section>\n </div>\n ),\n },\n {\n value: \"agents\",\n label: \"Agents\",\n content: (\n <section className=\"agent-skill-editor__agents\">\n <div>\n <h2>Associated agents</h2>\n <p>Agents linked to this skill. Associations are read-only here.</p>\n </div>\n {isLoading ? (\n <p>Loading associated agents…</p>\n ) : agents.length ? (\n <div className=\"agent-skill-editor__agent-grid\">\n {agents.map((agent, index) => (\n <article className=\"agent-skill-editor__agent-card\" key={String(agent.id ?? agent.name ?? index)}>\n <span>{(agent.name ?? agent.title ?? \"A\").slice(0, 1).toUpperCase()}</span>\n <strong>{agent.name ?? agent.title ?? \"Unnamed agent\"}</strong>\n </article>\n ))}\n </div>\n ) : (\n <div className=\"agent-skill-editor__empty\">No agents are currently associated with this skill.</div>\n )}\n </section>\n ),\n },\n ];\n\n return (\n <main className=\"agent-skill-editor\">\n <header className=\"agent-skill-editor__header\">\n <div>\n <div className=\"agent-skill-editor__heading-with-refresh\"><h1>{record ? \"Edit Skill\" : \"Create Skill\"}</h1>{record?.id && <button type=\"button\" className={`agent-skill-editor__refresh${isFetching ? \" is-loading\" : \"\"}`} aria-label=\"Refresh skill\" title=\"Refresh skill\" disabled={isFetching || isSaving} onClick={requestRefresh}><RefreshCw size={14} /></button>}</div>\n </div>\n <div className=\"agent-skill-editor__actions\">\n <SolidButton variant=\"secondary\" leftIcon={<ArrowLeft size={16} />} onClick={() => navigate(-1)}>\n Back\n </SolidButton>\n {!isReadOnly && (\n <SolidButton loading={isCreating || isSaving} onClick={handleSave}>\n Save Skill\n </SolidButton>\n )}\n </div>\n </header>\n\n <SolidDialog open={confirmRefresh} onOpenChange={setConfirmRefresh} header=\"Discard unsaved changes?\" style={{ width: \"min(28rem, 94vw)\" }}\n footer={<><SolidButton type=\"button\" variant=\"secondary\" onClick={() => setConfirmRefresh(false)}>Cancel</SolidButton><SolidButton type=\"button\" disabled={isFetching} onClick={() => { setConfirmRefresh(false); void refetch(); }}>Refresh and discard</SolidButton></>}>\n <SolidDialogBody><p>You have unsaved changes. Refreshing will discard them and load the latest skill content.</p></SolidDialogBody>\n </SolidDialog>\n\n {isLoading ? (\n <div className=\"agent-skill-editor__loading\">Loading skill…</div>\n ) : record?.id ? (\n <AgentRegistryAuditPanel\n modelSingularName=\"agentSkillRegistry\"\n recordId={record.id}\n refreshVersion={auditRefreshVersion}\n modelUserKey={record.name}\n >\n <SolidTabGroup\n tabs={tabs}\n value={activeTab}\n onValueChange={setActiveTab}\n className=\"agent-skill-editor__tabs\"\n listClassName=\"agent-skill-editor__tab-list\"\n panelClassName=\"agent-skill-editor__tab-panel\"\n />\n </AgentRegistryAuditPanel>\n ) : (\n <SolidTabGroup\n tabs={tabs}\n value={activeTab}\n onValueChange={setActiveTab}\n className=\"agent-skill-editor__tabs\"\n listClassName=\"agent-skill-editor__tab-list\"\n panelClassName=\"agent-skill-editor__tab-panel\"\n />\n )}\n </main>\n );\n}\n"]}
1
+ {"version":3,"file":"AgentSkillRegistryEditorPage.js","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { ArrowLeft, RefreshCw } from \"lucide-react\";\nimport { useDispatch } from \"react-redux\";\nimport { useNavigate, useParams } from \"react-router-dom\";\nimport { createSolidEntityApi } from \"../../../../redux/api/solidEntityApi\";\nimport { showToast } from \"../../../../redux/features/toastSlice\";\nimport { AgentRegistryAuditPanel } from \"./AgentRegistryAuditPanel\";\nimport { AgentHubTagsField, agentHubTagsFrom, agentHubTagsPayload, type AgentHubTag } from \"./AgentHubTagsField\";\nimport {\n SolidButton,\n SolidCodeEditor,\n SolidDialog,\n SolidDialogBody,\n SolidIconPicker,\n SolidInput,\n SolidTabGroup,\n} from \"../../../../components/shad-cn-ui\";\nimport \"./AgentSkillRegistryEditorPage.css\";\n\ntype AgentReference = {\n id?: number | string;\n name?: string;\n title?: string;\n agentRegistry?: AgentReference | number | string | null;\n};\n\ntype SkillRecord = {\n id: number;\n name?: string;\n type?: string;\n iconName?: string | null;\n description?: string;\n body?: string;\n tags?: AgentHubTag[];\n agentSkills?: AgentReference[] | AgentReference | null;\n};\n\nfunction extractEntityRecord(response: unknown): Record<string, any> | undefined {\n let candidate: unknown = response;\n for (let depth = 0; depth < 3; depth += 1) {\n if (!candidate || typeof candidate !== \"object\") return undefined;\n const value = candidate as Record<string, unknown>;\n if (\"id\" in value || \"name\" in value) return value;\n candidate = value.data;\n }\n return candidate && typeof candidate === \"object\" ? candidate as Record<string, any> : undefined;\n}\n\nfunction formatErrorMessage(value: unknown): string | undefined {\n if (typeof value === \"string\") return value.trim() || undefined;\n if (Array.isArray(value)) {\n const messages = value.map(formatErrorMessage).filter((message): message is string => Boolean(message));\n return messages.length ? messages.join(\"; \") : undefined;\n }\n if (value && typeof value === \"object\") {\n const error = value as Record<string, unknown>;\n return formatErrorMessage(error.message)\n ?? formatErrorMessage(error.constraints)\n ?? formatErrorMessage(error.error);\n }\n return undefined;\n}\n\nfunction getSaveErrorMessage(error: unknown): string {\n if (!error || typeof error !== \"object\") return \"Failed to save skill.\";\n const apiError = error as Record<string, any>;\n // Nest validation details are nested at data.data.message; prefer them over\n // the generic outer \"Bad Request Exception\" message.\n return formatErrorMessage(apiError.data?.data?.message)\n ?? formatErrorMessage(apiError.data?.message)\n ?? formatErrorMessage(apiError.data?.error)\n ?? formatErrorMessage(apiError.message)\n ?? \"Failed to save skill.\";\n}\n\nfunction skillAgents(record?: SkillRecord): AgentReference[] {\n const related = record?.agentSkills;\n const links = Array.isArray(related)\n ? related\n : related\n ? [related]\n : [];\n const seen = new Set<string>();\n\n return links\n .map((link) => link.agentRegistry)\n .filter((agent): agent is AgentReference => Boolean(agent && typeof agent === \"object\"))\n .filter((agent) => {\n const key = String(agent.id ?? agent.name ?? agent.title ?? \"\");\n if (!key || seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport function AgentSkillRegistryEditorPage() {\n const { id = \"\" } = useParams<{ id: string }>();\n const navigate = useNavigate();\n const dispatch = useDispatch();\n const entityApi = React.useMemo(() => createSolidEntityApi(\"agentSkillRegistry\"), []);\n const {\n useCreateSolidEntityMutation,\n useGetSolidEntityByIdQuery,\n useUpdateSolidEntityMutation,\n } = entityApi;\n\n const { data: response, isLoading, isFetching, refetch } = useGetSolidEntityByIdQuery(\n {\n id,\n qs: \"populate[0]=agentSkills&populate[1]=agentSkills.agentRegistry&populate[2]=tags\",\n },\n { skip: !id || id === \"new\" },\n );\n const [createSkill, { isLoading: isCreating }] = useCreateSolidEntityMutation();\n const [updateSkill, { isLoading: isSaving }] = useUpdateSolidEntityMutation();\n const record = extractEntityRecord(response) as SkillRecord | undefined;\n\n const [activeTab, setActiveTab] = React.useState(\"general\");\n const [name, setName] = React.useState(\"\");\n const [type, setType] = React.useState(\"custom\");\n const [iconName, setIconName] = React.useState(\"\");\n const [description, setDescription] = React.useState(\"\");\n const [body, setBody] = React.useState(\"\");\n const [tags, setTags] = React.useState<AgentHubTag[]>([]);\n const [creatingTag, setCreatingTag] = React.useState(false);\n const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({});\n const [auditRefreshVersion, setAuditRefreshVersion] = React.useState(0);\n const [confirmRefresh, setConfirmRefresh] = React.useState(false);\n const baseline = React.useRef(\"\");\n const currentForm = () => JSON.stringify({ name, type, iconName, description, body, tags });\n\n React.useEffect(() => {\n const nextTags = agentHubTagsFrom(record?.tags);\n setName(record?.name ?? \"\");\n setType(record?.type ?? \"custom\");\n setIconName(record?.iconName ?? \"\");\n setDescription(record?.description ?? \"\");\n setBody(record?.body ?? \"\");\n setTags(nextTags);\n baseline.current = JSON.stringify({ name: record?.name ?? \"\", type: record?.type ?? \"custom\", iconName: record?.iconName ?? \"\", description: record?.description ?? \"\", body: record?.body ?? \"\", tags: nextTags });\n }, [record]);\n\n const isReadOnly = record?.type === \"solidx\";\n const isDirty = Boolean(record?.id) && currentForm() !== baseline.current;\n const requestRefresh = () => isDirty ? setConfirmRefresh(true) : void refetch();\n\n const handleSave = async () => {\n if (creatingTag) return;\n const nextErrors: Record<string, string> = {};\n if (!name.trim()) nextErrors.name = \"Name is required.\";\n if (!type.trim()) nextErrors.type = \"Skill type is required.\";\n if (!description.trim()) nextErrors.description = \"Description is required.\";\n if (!body.trim()) nextErrors.body = \"Skill instructions are required.\";\n\n setFieldErrors(nextErrors);\n if (Object.keys(nextErrors).length > 0) {\n setActiveTab(nextErrors.body ? \"skill\" : \"general\");\n dispatch(showToast({\n severity: \"error\",\n summary: \"Missing information\",\n detail: Object.values(nextErrors).join(\" \"),\n }));\n return;\n }\n\n const payload = {\n name: name.trim(),\n type,\n iconName: iconName || null,\n description: description.trim(),\n body,\n ...agentHubTagsPayload(tags),\n };\n\n try {\n if (record?.id) {\n await updateSkill({ id: record.id, data: payload }).unwrap();\n dispatch(showToast({\n severity: \"success\",\n summary: \"Saved\",\n detail: \"Skill updated successfully.\",\n }));\n setAuditRefreshVersion((version) => version + 1);\n refetch();\n } else {\n const result: any = await createSkill(payload).unwrap();\n const createdId = result?.data?.id ?? result?.id;\n dispatch(showToast({\n severity: \"success\",\n summary: \"Created\",\n detail: \"Skill created successfully.\",\n }));\n if (createdId) {\n navigate(`/admin/core/solid-core/agent-skill-registry/editor/${createdId}`, {\n replace: true,\n });\n }\n }\n } catch (error: any) {\n const errorDetail = getSaveErrorMessage(error);\n const serverFieldErrors: Record<string, string> = {};\n if (/required|not be empty|cannot be empty|should not be empty/i.test(errorDetail)) {\n for (const field of [\"name\", \"type\", \"description\", \"body\"]) {\n if (!new RegExp(`\\\\b${field}\\\\b`, \"i\").test(errorDetail)) continue;\n serverFieldErrors[field] = `${field === \"body\" ? \"Skill instructions\" : field[0].toUpperCase() + field.slice(1)} is required.`;\n }\n }\n if (Object.keys(serverFieldErrors).length > 0) {\n setFieldErrors(serverFieldErrors);\n setActiveTab(serverFieldErrors.body ? \"skill\" : \"general\");\n }\n dispatch(showToast({\n severity: \"error\",\n summary: \"Save failed\",\n detail: errorDetail,\n }));\n }\n };\n\n const agents = skillAgents(record);\n const tabs = [\n {\n value: \"general\",\n label: \"General Info\",\n content: (\n <fieldset className=\"agent-skill-editor__general\" disabled={isReadOnly}>\n {isReadOnly && <p className=\"agent-skill-editor__readonly-note\">SolidX skills are seeded by the AgentHub runtime and cannot be edited.</p>}\n <div className=\"agent-skill-editor__fields\">\n <label className=\"agent-skill-editor__field\">\n <span>Name <b>*</b></span>\n <SolidInput\n value={name}\n aria-invalid={Boolean(fieldErrors.name)}\n aria-describedby={fieldErrors.name ? \"agent-skill-name-error\" : undefined}\n className={fieldErrors.name ? \"agent-skill-editor__input--invalid\" : undefined}\n onChange={(event) => {\n setName(event.target.value);\n setFieldErrors((current) => ({ ...current, name: \"\" }));\n }}\n />\n {fieldErrors.name && <small id=\"agent-skill-name-error\" className=\"agent-skill-editor__field-error\">{fieldErrors.name}</small>}\n </label>\n <div className=\"agent-skill-editor__field\">\n <span>Icon</span>\n <SolidIconPicker value={iconName} onChange={setIconName} />\n </div>\n <label className=\"agent-skill-editor__field\">\n <span>Description <b>*</b></span>\n <SolidInput\n value={description}\n aria-invalid={Boolean(fieldErrors.description)}\n aria-describedby={fieldErrors.description ? \"agent-skill-description-error\" : undefined}\n className={fieldErrors.description ? \"agent-skill-editor__input--invalid\" : undefined}\n onChange={(event) => {\n setDescription(event.target.value);\n setFieldErrors((current) => ({ ...current, description: \"\" }));\n }}\n />\n {fieldErrors.description && <small id=\"agent-skill-description-error\" className=\"agent-skill-editor__field-error\">{fieldErrors.description}</small>}\n </label>\n </div>\n <label className=\"agent-skill-editor__field\">\n <span>Skill type <b>*</b></span>\n <select\n value={type}\n aria-invalid={Boolean(fieldErrors.type)}\n aria-describedby={fieldErrors.type ? \"agent-skill-type-error\" : undefined}\n className={fieldErrors.type ? \"agent-skill-editor__input--invalid\" : undefined}\n onChange={(event) => {\n setType(event.target.value);\n setFieldErrors((current) => ({ ...current, type: \"\" }));\n }}\n >\n {isReadOnly && <option value=\"solidx\">SolidX</option>}\n <option value=\"thirdparty\">Third Party</option>\n <option value=\"custom\">Custom</option>\n </select>\n {fieldErrors.type && <small id=\"agent-skill-type-error\" className=\"agent-skill-editor__field-error\">{fieldErrors.type}</small>}\n </label>\n <AgentHubTagsField value={tags} onChange={setTags} disabled={isReadOnly || isCreating || isSaving} onBusyChange={setCreatingTag} />\n </fieldset>\n ),\n },\n {\n value: \"skill\",\n label: \"Skill\",\n content: (\n <div className=\"agent-skill-editor__skill\">\n <section className=\"agent-skill-editor__panel\">\n <header>\n <h2>Skill instructions <b>*</b></h2>\n <p>Write the skill's Markdown body here.</p>\n </header>\n <SolidCodeEditor\n value={body}\n onChange={(value) => {\n setBody(value ?? \"\");\n setFieldErrors((current) => ({ ...current, body: \"\" }));\n }}\n language=\"markdown\"\n readOnly={isReadOnly}\n fontSize={11}\n height=\"max(32rem, calc(100dvh - 18rem))\"\n className={`agent-skill-editor__code${fieldErrors.body ? \" agent-skill-editor__code--invalid\" : \"\"}`}\n />\n {fieldErrors.body && <small className=\"agent-skill-editor__field-error agent-skill-editor__body-error\">{fieldErrors.body}</small>}\n </section>\n </div>\n ),\n },\n {\n value: \"agents\",\n label: \"Agents\",\n content: (\n <section className=\"agent-skill-editor__agents\">\n <div>\n <h2>Associated agents</h2>\n <p>Agents linked to this skill. Associations are read-only here.</p>\n </div>\n {isLoading ? (\n <p>Loading associated agents…</p>\n ) : agents.length ? (\n <div className=\"agent-skill-editor__agent-grid\">\n {agents.map((agent, index) => (\n <article className=\"agent-skill-editor__agent-card\" key={String(agent.id ?? agent.name ?? index)}>\n <span>{(agent.name ?? agent.title ?? \"A\").slice(0, 1).toUpperCase()}</span>\n <strong>{agent.name ?? agent.title ?? \"Unnamed agent\"}</strong>\n </article>\n ))}\n </div>\n ) : (\n <div className=\"agent-skill-editor__empty\">No agents are currently associated with this skill.</div>\n )}\n </section>\n ),\n },\n ];\n\n return (\n <main className=\"agent-skill-editor\">\n <header className=\"agent-skill-editor__header\">\n <div>\n <div className=\"agent-skill-editor__heading-with-refresh\"><h1>{record ? \"Edit Skill\" : \"Create Skill\"}</h1>{record?.id && <button type=\"button\" className={`agent-skill-editor__refresh${isFetching ? \" is-loading\" : \"\"}`} aria-label=\"Refresh skill\" title=\"Refresh skill\" disabled={isFetching || isSaving} onClick={requestRefresh}><RefreshCw size={14} /></button>}</div>\n </div>\n <div className=\"agent-skill-editor__actions\">\n <SolidButton variant=\"secondary\" leftIcon={<ArrowLeft size={16} />} onClick={() => navigate(-1)}>\n Back\n </SolidButton>\n {!isReadOnly && (\n <SolidButton loading={isCreating || isSaving} disabled={creatingTag} onClick={handleSave}>\n Save Skill\n </SolidButton>\n )}\n </div>\n </header>\n\n <SolidDialog open={confirmRefresh} onOpenChange={setConfirmRefresh} header=\"Discard unsaved changes?\" style={{ width: \"min(28rem, 94vw)\" }}\n footer={<><SolidButton type=\"button\" variant=\"secondary\" onClick={() => setConfirmRefresh(false)}>Cancel</SolidButton><SolidButton type=\"button\" disabled={isFetching} onClick={() => { setConfirmRefresh(false); void refetch(); }}>Refresh and discard</SolidButton></>}>\n <SolidDialogBody><p>You have unsaved changes. Refreshing will discard them and load the latest skill content.</p></SolidDialogBody>\n </SolidDialog>\n\n {isLoading ? (\n <div className=\"agent-skill-editor__loading\">Loading skill…</div>\n ) : record?.id ? (\n <AgentRegistryAuditPanel\n modelSingularName=\"agentSkillRegistry\"\n recordId={record.id}\n refreshVersion={auditRefreshVersion}\n modelUserKey={record.name}\n >\n <SolidTabGroup\n tabs={tabs}\n value={activeTab}\n onValueChange={setActiveTab}\n className=\"agent-skill-editor__tabs\"\n listClassName=\"agent-skill-editor__tab-list\"\n panelClassName=\"agent-skill-editor__tab-panel\"\n />\n </AgentRegistryAuditPanel>\n ) : (\n <SolidTabGroup\n tabs={tabs}\n value={activeTab}\n onValueChange={setActiveTab}\n className=\"agent-skill-editor__tabs\"\n listClassName=\"agent-skill-editor__tab-list\"\n panelClassName=\"agent-skill-editor__tab-panel\"\n />\n )}\n </main>\n );\n}\n"]}