@agent-native/dispatch 0.36.2 → 0.36.3-nightly-20260914215457
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/simple-agents-panel.d.ts +6 -0
- package/dist/components/simple-agents-panel.d.ts.map +1 -1
- package/dist/components/simple-agents-panel.js +44 -14
- package/dist/components/simple-agents-panel.js.map +1 -1
- package/dist/lib/agent-pack.d.ts +8 -0
- package/dist/lib/agent-pack.d.ts.map +1 -1
- package/dist/lib/agent-pack.js +38 -0
- package/dist/lib/agent-pack.js.map +1 -1
- package/package.json +4 -4
- package/src/components/simple-agents-panel.spec.tsx +91 -0
- package/src/components/simple-agents-panel.tsx +63 -14
- package/src/lib/agent-pack.spec.ts +64 -1
- package/src/lib/agent-pack.ts +47 -0
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Folder pickers cannot filter by extension, so unsupported files are only
|
|
4
|
+
* visible after selection. Name them without turning a 40-file photo folder
|
|
5
|
+
* into a 40-line warning.
|
|
6
|
+
*/
|
|
7
|
+
export declare function summarizeSkippedPackFiles(skipped: string[], keptCount: number): string[];
|
|
2
8
|
export declare function isPendingWorkspaceResourceApproval(result: unknown): boolean;
|
|
3
9
|
export declare function handleAgentPackMutationSuccess(result: unknown, options: {
|
|
4
10
|
appliedMessage: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simple-agents-panel.d.ts","sourceRoot":"","sources":["../../src/components/simple-agents-panel.tsx"],"names":[],"mappings":"AAuBA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"simple-agents-panel.d.ts","sourceRoot":"","sources":["../../src/components/simple-agents-panel.tsx"],"names":[],"mappings":"AAuBA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA2Ff;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,EAAE,CAgBV;AAqBD,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,OAAO,WAQjE;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,OAAO,EACf,OAAO,EAAE;IACP,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,QASF;AAgkCD,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,GACN,GAAE;IACD,KAAK,CAAC,EAAE,SAAS,CAAC;CACd,4DA4EL"}
|
|
@@ -6,6 +6,7 @@ import { IconAdjustmentsHorizontal, IconChevronDown, IconDotsVertical, IconEdit,
|
|
|
6
6
|
import { useEffect, useRef, useState, } from "react";
|
|
7
7
|
import { useNavigate } from "react-router";
|
|
8
8
|
import { toast } from "sonner";
|
|
9
|
+
import { AGENT_PACK_FILE_ACCEPT, AGENT_PROFILE_FILE_ACCEPT, AGENT_PROFILE_FILE_EXTENSIONS, isImportableAgentPackFile, isImportableAgentProfileFile, } from "../lib/agent-pack.js";
|
|
9
10
|
import { buildSimpleAgentContent, slugifyAgentName, } from "../lib/simple-agent-profile.js";
|
|
10
11
|
import { ActionQueryError } from "./action-query-error.js";
|
|
11
12
|
import { AppIcon } from "./app-icon.js";
|
|
@@ -21,6 +22,29 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "
|
|
|
21
22
|
import { Skeleton } from "./ui/skeleton.js";
|
|
22
23
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs.js";
|
|
23
24
|
import { Textarea } from "./ui/textarea.js";
|
|
25
|
+
const MAX_LISTED_SKIPPED_FILES = 3;
|
|
26
|
+
/**
|
|
27
|
+
* Folder pickers cannot filter by extension, so unsupported files are only
|
|
28
|
+
* visible after selection. Name them without turning a 40-file photo folder
|
|
29
|
+
* into a 40-line warning.
|
|
30
|
+
*/
|
|
31
|
+
export function summarizeSkippedPackFiles(skipped, keptCount) {
|
|
32
|
+
if (skipped.length === 0)
|
|
33
|
+
return [];
|
|
34
|
+
if (keptCount === 0) {
|
|
35
|
+
return [
|
|
36
|
+
"No importable files in that folder. Agent folders take text files such as Markdown, JSON, and YAML.",
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
const listed = skipped.slice(0, MAX_LISTED_SKIPPED_FILES);
|
|
40
|
+
const remaining = skipped.length - listed.length;
|
|
41
|
+
const names = remaining > 0
|
|
42
|
+
? `${listed.join(", ")}, and ${remaining} more`
|
|
43
|
+
: listed.join(", ");
|
|
44
|
+
return [
|
|
45
|
+
`Skipped ${skipped.length} non-text ${skipped.length === 1 ? "file" : "files"}: ${names}.`,
|
|
46
|
+
];
|
|
47
|
+
}
|
|
24
48
|
const AGENT_ICON_KEYS = [
|
|
25
49
|
"brain",
|
|
26
50
|
"users",
|
|
@@ -295,12 +319,6 @@ function ImportAgentDialog({ onImported }) {
|
|
|
295
319
|
},
|
|
296
320
|
onError: (error) => toast.error(error.message),
|
|
297
321
|
});
|
|
298
|
-
useEffect(() => {
|
|
299
|
-
if (!folderRef.current)
|
|
300
|
-
return;
|
|
301
|
-
folderRef.current.setAttribute("webkitdirectory", "");
|
|
302
|
-
folderRef.current.setAttribute("directory", "");
|
|
303
|
-
}, [mode, open]);
|
|
304
322
|
function reset() {
|
|
305
323
|
setMode("file");
|
|
306
324
|
setSource("");
|
|
@@ -315,22 +333,30 @@ function ImportAgentDialog({ onImported }) {
|
|
|
315
333
|
}
|
|
316
334
|
async function handleFile(event) {
|
|
317
335
|
const file = event.target.files?.[0];
|
|
336
|
+
event.target.value = "";
|
|
318
337
|
if (!file)
|
|
319
338
|
return;
|
|
339
|
+
// `accept` is only a picker hint: every OS dialog lets the user switch to
|
|
340
|
+
// "All Files", and reading a PDF with file.text() yields mojibake that
|
|
341
|
+
// looks like a valid definition.
|
|
342
|
+
if (!isImportableAgentProfileFile(file.name)) {
|
|
343
|
+
toast.error(`${file.name} is not a supported agent file. Choose a ${AGENT_PROFILE_FILE_EXTENSIONS.join(", ")} file.`);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
320
346
|
setFileName(file.name);
|
|
321
347
|
setSource(await file.text());
|
|
322
348
|
}
|
|
323
349
|
async function handleFolder(event) {
|
|
324
350
|
const selectedFiles = Array.from(event.target.files ?? []);
|
|
351
|
+
event.target.value = "";
|
|
325
352
|
if (selectedFiles.length === 0)
|
|
326
353
|
return;
|
|
327
|
-
const
|
|
328
|
-
const textExtensions = /\.(md|markdown|txt|json|yaml|yml|csv|html|xml|toml|ts|tsx|js|mjs|py|sh)$/i;
|
|
354
|
+
const skipped = [];
|
|
329
355
|
const pack = await Promise.all(selectedFiles.map(async (file) => {
|
|
330
356
|
const path = file.webkitRelativePath ||
|
|
331
357
|
file.name;
|
|
332
|
-
if (!
|
|
333
|
-
|
|
358
|
+
if (!isImportableAgentPackFile(path)) {
|
|
359
|
+
skipped.push(path);
|
|
334
360
|
return null;
|
|
335
361
|
}
|
|
336
362
|
return { path, content: await file.text() };
|
|
@@ -338,19 +364,23 @@ function ImportAgentDialog({ onImported }) {
|
|
|
338
364
|
const files = pack.filter((file) => Boolean(file));
|
|
339
365
|
setPackFiles(files);
|
|
340
366
|
setPackName(files[0]?.path.split("/")[0] || "Selected folder");
|
|
341
|
-
setPackWarnings(
|
|
367
|
+
setPackWarnings(summarizeSkippedPackFiles(skipped, files.length));
|
|
342
368
|
}
|
|
343
369
|
return (_jsxs(Dialog, { open: open, onOpenChange: (nextOpen) => {
|
|
344
370
|
setOpen(nextOpen);
|
|
345
371
|
if (!nextOpen)
|
|
346
372
|
reset();
|
|
347
|
-
}, children: [_jsx(DialogTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", children: [_jsx(IconFileImport, { size: 16 }), "Import or connect"] }) }), _jsxs(DialogContent, { className: "max-w-2xl", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Import an agent" }), _jsx(DialogDescription, { className: "sr-only", children: "Import a Claude or JSON agent definition, or connect an external agent endpoint." })] }), _jsxs(Tabs, { value: mode, onValueChange: (value) => setMode(value), children: [_jsxs(TabsList, { className: "w-full justify-start", children: [_jsx(TabsTrigger, { value: "file", children: "Agent file" }), _jsx(TabsTrigger, { value: "folder", children: "Agent folder" }), _jsx(TabsTrigger, { value: "endpoint", children: "Connect endpoint" })] }), _jsxs(TabsContent, { value: "file", className: "flex flex-col gap-4 py-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs(Button, { type: "button", variant: "outline", onClick: () => fileRef.current?.click(), children: [_jsx(IconUpload, { size: 16 }), "Choose file"] }), _jsx("input", { ref: fileRef, type: "file", accept:
|
|
373
|
+
}, children: [_jsx(DialogTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", children: [_jsx(IconFileImport, { size: 16 }), "Import or connect"] }) }), _jsxs(DialogContent, { className: "max-w-2xl", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Import an agent" }), _jsx(DialogDescription, { className: "sr-only", children: "Import a Claude or JSON agent definition, or connect an external agent endpoint." })] }), _jsxs(Tabs, { value: mode, onValueChange: (value) => setMode(value), children: [_jsxs(TabsList, { className: "w-full justify-start", children: [_jsx(TabsTrigger, { value: "file", children: "Agent file" }), _jsx(TabsTrigger, { value: "folder", children: "Agent folder" }), _jsx(TabsTrigger, { value: "endpoint", children: "Connect endpoint" })] }), _jsxs(TabsContent, { value: "file", className: "flex flex-col gap-4 py-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs(Button, { type: "button", variant: "outline", onClick: () => fileRef.current?.click(), children: [_jsx(IconUpload, { size: 16 }), "Choose file"] }), _jsx("input", { ref: fileRef, type: "file", accept: AGENT_PROFILE_FILE_ACCEPT, className: "hidden", onChange: (event) => void handleFile(event) }), _jsx("span", { className: "text-xs text-muted-foreground", children: fileName || "Claude .md or JSON agent definition" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "import-agent-source", children: "Definition" }), _jsx(Textarea, { id: "import-agent-source", value: source, onChange: (event) => setSource(event.target.value), rows: 12, className: "font-mono text-sm", placeholder: "Paste a Claude-style agent file or a JSON definition" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "import-agent-scope", children: "Availability" }), _jsxs(Select, { value: scope, onValueChange: (value) => setScope(value), children: [_jsx(SelectTrigger, { id: "import-agent-scope", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "All apps" }), _jsx(SelectItem, { value: "selected", children: "Selected apps" })] })] })] }), _jsx(DialogFooter, { children: _jsx(Button, { onClick: () => importAgent.mutate({
|
|
348
374
|
source,
|
|
349
375
|
fileName: fileName || undefined,
|
|
350
376
|
scope,
|
|
351
|
-
}), disabled: !source.trim() || importAgent.isPending, children: importAgent.isPending ? "Importing..." : "Import agent" }) })] }), _jsxs(TabsContent, { value: "folder", className: "flex flex-col gap-4 py-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs(Button, { type: "button", variant: "outline", onClick: () => folderRef.current?.click(), children: [_jsx(IconFolder, { size: 16 }), "Choose folder"] }), _jsx("input", { ref: folderRef, type: "file", multiple: true,
|
|
377
|
+
}), disabled: !source.trim() || importAgent.isPending, children: importAgent.isPending ? "Importing..." : "Import agent" }) })] }), _jsxs(TabsContent, { value: "folder", className: "flex flex-col gap-4 py-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs(Button, { type: "button", variant: "outline", onClick: () => folderRef.current?.click(), children: [_jsx(IconFolder, { size: 16 }), "Choose folder"] }), _jsx("input", { ref: folderRef, type: "file", multiple: true, ...{ webkitdirectory: "", directory: "" },
|
|
378
|
+
// Directory pickers ignore accept; it only applies where
|
|
379
|
+
// webkitdirectory is unsupported and this falls back to
|
|
380
|
+
// multi-file selection.
|
|
381
|
+
accept: AGENT_PACK_FILE_ACCEPT, className: "hidden", onChange: (event) => void handleFolder(event) }), _jsx("span", { className: "text-xs text-muted-foreground", children: packName
|
|
352
382
|
? `${packName} · ${packFiles.length} files`
|
|
353
|
-
: "Claude Project or Cowork-style folder" })] }), packWarnings.length > 0 ? (_jsx("div", { className: "rounded-lg border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-800 dark:text-amber-200", children: packWarnings.join(" ") })) : null, _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "import-agent-pack-scope", children: "Availability" }), _jsxs(Select, { value: scope, onValueChange: (value) => setScope(value), children: [_jsx(SelectTrigger, { id: "import-agent-pack-scope", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "All apps" }), _jsx(SelectItem, { value: "selected", children: "Selected apps" })] })] })] }), _jsx(DialogFooter, { children: _jsx(Button, { onClick: () => importPack.mutate({ files: packFiles, scope }), disabled: packFiles.length === 0 || importPack.isPending, children: importPack.isPending ? "Importing..." : "Import agent pack" }) })] }), _jsxs(TabsContent, { value: "endpoint", className: "flex flex-col gap-4 py-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "external-agent-url", children: "Endpoint URL" }), _jsx(Input, { id: "external-agent-url", value: url, onChange: (event) => setUrl(event.target.value), placeholder: "https://agent.example.com" })] }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "external-agent-name", children: "Name" }), _jsx(Input, { id: "external-agent-name", value: endpointName, onChange: (event) => setEndpointName(event.target.value), placeholder: "Research partner" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Availability" }), _jsx("div", { className: "flex h-10 items-center", children: _jsx(Badge, { variant: "secondary", children: "Workspace" }) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "external-agent-description", children: "Description" }), _jsx(Input, { id: "external-agent-description", value: endpointDescription, onChange: (event) => setEndpointDescription(event.target.value), placeholder: "Optional" })] }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Dispatch stores the public endpoint only. Authenticate it after connecting." }), _jsx(DialogFooter, { children: _jsxs(Button, { onClick: () => connect.mutate({
|
|
383
|
+
: "Claude Project or Cowork-style folder · text files only" })] }), packWarnings.length > 0 ? (_jsx("div", { className: "rounded-lg border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-800 dark:text-amber-200", children: packWarnings.join(" ") })) : null, _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "import-agent-pack-scope", children: "Availability" }), _jsxs(Select, { value: scope, onValueChange: (value) => setScope(value), children: [_jsx(SelectTrigger, { id: "import-agent-pack-scope", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "All apps" }), _jsx(SelectItem, { value: "selected", children: "Selected apps" })] })] })] }), _jsx(DialogFooter, { children: _jsx(Button, { onClick: () => importPack.mutate({ files: packFiles, scope }), disabled: packFiles.length === 0 || importPack.isPending, children: importPack.isPending ? "Importing..." : "Import agent pack" }) })] }), _jsxs(TabsContent, { value: "endpoint", className: "flex flex-col gap-4 py-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "external-agent-url", children: "Endpoint URL" }), _jsx(Input, { id: "external-agent-url", value: url, onChange: (event) => setUrl(event.target.value), placeholder: "https://agent.example.com" })] }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "external-agent-name", children: "Name" }), _jsx(Input, { id: "external-agent-name", value: endpointName, onChange: (event) => setEndpointName(event.target.value), placeholder: "Research partner" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Availability" }), _jsx("div", { className: "flex h-10 items-center", children: _jsx(Badge, { variant: "secondary", children: "Workspace" }) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "external-agent-description", children: "Description" }), _jsx(Input, { id: "external-agent-description", value: endpointDescription, onChange: (event) => setEndpointDescription(event.target.value), placeholder: "Optional" })] }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Dispatch stores the public endpoint only. Authenticate it after connecting." }), _jsx(DialogFooter, { children: _jsxs(Button, { onClick: () => connect.mutate({
|
|
354
384
|
url,
|
|
355
385
|
name: endpointName || undefined,
|
|
356
386
|
description: endpointDescription || undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simple-agents-panel.js","sourceRoot":"","sources":["../../src/components/simple-agents-panel.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n navigateWithAgentChatViewTransition,\n sendToAgentChat,\n} from \"@agent-native/core/client/agent-chat\";\nimport {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { parseCustomAgentProfile } from \"@agent-native/core/resources/metadata\";\nimport {\n IconAdjustmentsHorizontal,\n IconChevronDown,\n IconDotsVertical,\n IconEdit,\n IconFileImport,\n IconFolder,\n IconLayoutGrid,\n IconMessageCircle,\n IconPlugConnected,\n IconPlus,\n IconTrash,\n IconUpload,\n} from \"@tabler/icons-react\";\nimport {\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type ReactNode,\n} from \"react\";\nimport { useNavigate } from \"react-router\";\nimport { toast } from \"sonner\";\n\nimport {\n buildSimpleAgentContent,\n slugifyAgentName,\n} from \"../lib/simple-agent-profile.js\";\nimport { ActionQueryError } from \"./action-query-error\";\nimport { AppIcon } from \"./app-icon\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"./ui/alert-dialog\";\nimport { Badge } from \"./ui/badge\";\nimport { Button } from \"./ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"./ui/collapsible\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"./ui/dialog\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"./ui/dropdown-menu\";\nimport { Input } from \"./ui/input\";\nimport { Label } from \"./ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"./ui/select\";\nimport { Skeleton } from \"./ui/skeleton\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"./ui/tabs\";\nimport { Textarea } from \"./ui/textarea\";\n\ninterface WorkspaceAgentResource {\n id: string;\n name: string;\n description: string | null;\n path: string;\n content: string;\n scope: \"all\" | \"selected\";\n updatedAt: number;\n}\n\ninterface AgentPackFileResource extends WorkspaceAgentResource {\n kind: \"agent-file\" | \"skill\";\n}\n\ninterface AgentPackResponse {\n profile: WorkspaceAgentResource;\n root: string;\n files: AgentPackFileResource[];\n}\n\ninterface AgentPackFileInput {\n path: string;\n content: string;\n}\n\nconst AGENT_ICON_KEYS = [\n \"brain\",\n \"users\",\n \"filetext\",\n \"chartbar\",\n \"route\",\n \"listcheck\",\n \"code\",\n \"messagecircle\",\n] as const;\n\nfunction agentIconKey(resource: Pick<WorkspaceAgentResource, \"id\" | \"name\">) {\n let hash = 0;\n for (const character of `${resource.id}:${resource.name}`) {\n hash = (hash * 31 + character.charCodeAt(0)) | 0;\n }\n return AGENT_ICON_KEYS[Math.abs(hash) % AGENT_ICON_KEYS.length];\n}\n\nexport function isPendingWorkspaceResourceApproval(result: unknown) {\n if (!result || typeof result !== \"object\") return false;\n const mutation = result as { status?: unknown; changeType?: unknown };\n return (\n mutation.status === \"pending\" &&\n typeof mutation.changeType === \"string\" &&\n mutation.changeType.startsWith(\"workspace-resource.\")\n );\n}\n\nexport function handleAgentPackMutationSuccess(\n result: unknown,\n options: {\n appliedMessage: string;\n approvalMessage: string;\n onApplied: () => void;\n notify?: (message: string) => void;\n },\n) {\n const notify = options.notify || ((message) => toast.success(message));\n if (isPendingWorkspaceResourceApproval(result)) {\n notify(options.approvalMessage);\n return;\n }\n notify(options.appliedMessage);\n options.onApplied();\n}\n\ninterface AgentEditorProps {\n resource?: WorkspaceAgentResource;\n trigger?: ReactNode;\n onSaved?: () => void;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nfunction profileFields(resource?: WorkspaceAgentResource) {\n if (!resource) {\n return {\n name: \"\",\n description: \"\",\n instructions: \"# Role\\n\\nDescribe how this agent should work.\\n\",\n model: \"inherit\",\n tools: \"inherit\",\n scope: \"all\" as const,\n };\n }\n\n const profile = parseCustomAgentProfile(resource.content, resource.path);\n return {\n name: profile?.name || resource.name,\n description: profile?.description || resource.description || \"\",\n instructions: profile?.instructions || resource.content,\n model: profile?.model || \"inherit\",\n tools: profile?.tools || \"inherit\",\n scope: resource.scope,\n };\n}\n\nfunction AgentEditorDialog({\n resource,\n trigger,\n onSaved,\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n}: AgentEditorProps) {\n const isEditing = Boolean(resource);\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = controlledOpen ?? uncontrolledOpen;\n const setOpen = controlledOnOpenChange ?? setUncontrolledOpen;\n const [name, setName] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [instructions, setInstructions] = useState(\"\");\n const [model, setModel] = useState(\"inherit\");\n const [tools, setTools] = useState(\"inherit\");\n const [scope, setScope] = useState<\"all\" | \"selected\">(\"all\");\n const [advancedOpen, setAdvancedOpen] = useState(false);\n\n useEffect(() => {\n if (!open) return;\n const fields = profileFields(resource);\n setName(fields.name);\n setDescription(fields.description);\n setInstructions(fields.instructions);\n setModel(fields.model);\n setTools(fields.tools);\n setScope(fields.scope);\n setAdvancedOpen(fields.model !== \"inherit\" || fields.tools !== \"inherit\");\n }, [open, resource]);\n\n const create = useActionMutation(\"create-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Agent created\");\n setOpen(false);\n onSaved?.();\n },\n onError: (error) => toast.error(error.message),\n });\n const update = useActionMutation(\"update-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Agent updated\");\n setOpen(false);\n onSaved?.();\n },\n onError: (error) => toast.error(error.message),\n });\n\n const pending = create.isPending || update.isPending;\n const canSave = Boolean(name.trim() && instructions.trim() && !pending);\n\n function save() {\n const content = buildSimpleAgentContent({\n name,\n description,\n model,\n tools,\n instructions,\n });\n if (resource) {\n update.mutate({\n id: resource.id,\n name: name.trim(),\n description: description.trim(),\n content,\n scope,\n });\n return;\n }\n create.mutate({\n kind: \"agent\",\n name: name.trim(),\n description: description.trim() || undefined,\n path: `agents/${slugifyAgentName(name)}.md`,\n content,\n scope,\n });\n }\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n {trigger ? (\n <DialogTrigger asChild>{trigger}</DialogTrigger>\n ) : controlledOpen === undefined ? (\n <DialogTrigger asChild>\n <Button size=\"sm\">\n <IconPlus size={16} />\n Create agent\n </Button>\n </DialogTrigger>\n ) : null}\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>\n {isEditing ? \"Manage agent\" : \"Create agent\"}\n </DialogTitle>\n <DialogDescription className=\"sr-only\">\n {isEditing\n ? \"Update this reusable agent profile.\"\n : \"Create a reusable agent profile.\"}\n </DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col gap-4 py-2\">\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-name\">Name</Label>\n <Input\n id=\"simple-agent-name\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n placeholder=\"User Research\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-scope\">Availability</Label>\n <Select\n value={scope}\n onValueChange={(value: \"all\" | \"selected\") => setScope(value)}\n >\n <SelectTrigger id=\"simple-agent-scope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All apps</SelectItem>\n <SelectItem value=\"selected\">Selected apps</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-description\">Description</Label>\n <Input\n id=\"simple-agent-description\"\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n placeholder=\"Synthesizes user research into clear insights\"\n />\n </div>\n <Collapsible open={advancedOpen} onOpenChange={setAdvancedOpen}>\n <CollapsibleTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"group -ml-2 gap-1.5 text-muted-foreground\"\n >\n <IconAdjustmentsHorizontal size={15} />\n Advanced\n <IconChevronDown\n className=\"transition-transform group-data-[state=open]:rotate-180\"\n size={15}\n />\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent className=\"pt-3\">\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-model\">Model</Label>\n <Input\n id=\"simple-agent-model\"\n value={model}\n onChange={(event) => setModel(event.target.value)}\n placeholder=\"inherit\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-tools\">Tools</Label>\n <Input\n id=\"simple-agent-tools\"\n value={tools}\n onChange={(event) => setTools(event.target.value)}\n placeholder=\"inherit\"\n />\n </div>\n </div>\n </CollapsibleContent>\n </Collapsible>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-instructions\">Instructions</Label>\n <Textarea\n id=\"simple-agent-instructions\"\n value={instructions}\n onChange={(event) => setInstructions(event.target.value)}\n rows={12}\n className=\"font-mono text-sm\"\n placeholder=\"# Role\\n\\nDescribe how this agent should work.\"\n />\n </div>\n </div>\n <DialogFooter>\n <Button onClick={save} disabled={!canSave}>\n {pending\n ? \"Saving...\"\n : isEditing\n ? \"Save changes\"\n : \"Create agent\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction AgentPackDialog({\n resource,\n onChanged,\n trigger,\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n}: {\n resource: WorkspaceAgentResource;\n onChanged?: () => void;\n trigger?: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = controlledOpen ?? uncontrolledOpen;\n const setOpen = controlledOnOpenChange ?? setUncontrolledOpen;\n const [selectedId, setSelectedId] = useState(resource.id);\n const [content, setContent] = useState(resource.content);\n const [addOpen, setAddOpen] = useState(false);\n const [newPath, setNewPath] = useState(\"\");\n const [newKind, setNewKind] = useState<\"agent-file\" | \"skill\">(\"agent-file\");\n const [newContent, setNewContent] = useState(\"\");\n const query = useActionQuery<AgentPackResponse>(\n \"list-agent-pack\",\n { agentId: resource.id },\n { enabled: open },\n );\n const update = useActionMutation(\"update-workspace-resource\", {\n onSuccess: (result) => {\n handleAgentPackMutationSuccess(result, {\n appliedMessage: \"Pack file updated\",\n approvalMessage: \"Pack file update queued for approval\",\n onApplied: () => {\n void query.refetch();\n onChanged?.();\n },\n });\n },\n onError: (error) => toast.error(error.message),\n });\n const create = useActionMutation(\"create-workspace-resource\", {\n onSuccess: (result) => {\n handleAgentPackMutationSuccess(result, {\n appliedMessage: \"Pack file added\",\n approvalMessage: \"Pack file addition queued for approval\",\n onApplied: () => {\n setAddOpen(false);\n setNewPath(\"\");\n setNewContent(\"\");\n void query.refetch();\n onChanged?.();\n },\n });\n },\n onError: (error) => toast.error(error.message),\n });\n const remove = useActionMutation(\"delete-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Pack file removed\");\n setSelectedId(resource.id);\n void query.refetch();\n onChanged?.();\n },\n onError: (error) => toast.error(error.message),\n });\n\n const files = query.data\n ? [{ ...query.data.profile, kind: \"agent\" as const }, ...query.data.files]\n : [];\n const selected = files.find((file) => file.id === selectedId) ?? files[0];\n\n useEffect(() => {\n if (!open) return;\n setSelectedId(resource.id);\n }, [open, resource.id]);\n\n useEffect(() => {\n if (!selected) return;\n setSelectedId(selected.id);\n setContent(selected.content);\n }, [selected?.id, selected?.content]);\n\n function addFile() {\n const relativePath = newPath.trim().replaceAll(\"\\\\\", \"/\");\n if (\n !relativePath ||\n relativePath.startsWith(\"/\") ||\n relativePath.includes(\"..\") ||\n relativePath.split(\"/\").some((part) => !part || part === \".\")\n ) {\n toast.error(\"Use a relative pack path without ..\");\n return;\n }\n const packPath =\n newKind === \"skill\" && !relativePath.startsWith(\"skills/\")\n ? `skills/${relativePath}`\n : relativePath;\n const name = packPath.split(\"/\").pop() || packPath;\n create.mutate({\n kind: newKind,\n name,\n path: `${query.data?.root || `agents/${slugifyAgentName(resource.name)}`}/${packPath}`,\n content: newContent,\n scope: resource.scope,\n });\n }\n\n return (\n <Dialog\n open={open}\n onOpenChange={(nextOpen) => {\n setOpen(nextOpen);\n if (!nextOpen) setAddOpen(false);\n }}\n >\n {trigger ? (\n <DialogTrigger asChild>{trigger}</DialogTrigger>\n ) : controlledOpen === undefined ? (\n <DialogTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\">\n <IconFolder size={15} />\n Pack\n </Button>\n </DialogTrigger>\n ) : null}\n <DialogContent className=\"max-w-4xl\">\n <DialogHeader>\n <DialogTitle>Agent pack</DialogTitle>\n <DialogDescription className=\"sr-only\">\n Edit the profile, reference files, context, and skills that belong\n to this agent.\n </DialogDescription>\n </DialogHeader>\n <div className=\"grid min-h-0 gap-4 md:grid-cols-[220px_minmax(0,1fr)]\">\n <div className=\"flex min-w-0 flex-col gap-2\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Files\n </span>\n <Dialog open={addOpen} onOpenChange={setAddOpen}>\n <DialogTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <IconPlus size={14} />\n Add\n </Button>\n </DialogTrigger>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Add pack file</DialogTitle>\n <DialogDescription className=\"sr-only\">\n Add a text reference or agent-owned skill to this pack.\n </DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col gap-4 py-2\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"agent-pack-file-path\">Path</Label>\n <Input\n id=\"agent-pack-file-path\"\n value={newPath}\n onChange={(event) => setNewPath(event.target.value)}\n placeholder=\"context/brief.md\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"agent-pack-file-kind\">Type</Label>\n <Select\n value={newKind}\n onValueChange={(value: \"agent-file\" | \"skill\") =>\n setNewKind(value)\n }\n >\n <SelectTrigger id=\"agent-pack-file-kind\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"agent-file\">\n Reference file\n </SelectItem>\n <SelectItem value=\"skill\">Skill</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"agent-pack-file-content\">Content</Label>\n <Textarea\n id=\"agent-pack-file-content\"\n value={newContent}\n onChange={(event) => setNewContent(event.target.value)}\n rows={8}\n className=\"font-mono text-sm\"\n />\n </div>\n </div>\n <DialogFooter>\n <Button\n onClick={addFile}\n disabled={!newPath.trim() || create.isPending}\n >\n {create.isPending ? \"Adding...\" : \"Add file\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n {query.isLoading ? (\n <Skeleton className=\"h-24 w-full\" />\n ) : (\n <div className=\"flex flex-col gap-1\">\n {files.map((file) => (\n <Button\n key={file.id}\n type=\"button\"\n variant={selected?.id === file.id ? \"secondary\" : \"ghost\"}\n className=\"h-auto w-full justify-start px-2 py-2 text-left\"\n onClick={() => setSelectedId(file.id)}\n >\n <span className=\"min-w-0 truncate text-xs\">\n {file.path.replace(`${query.data?.root || \"\"}/`, \"\")}\n </span>\n </Button>\n ))}\n </div>\n )}\n </div>\n <div className=\"flex min-w-0 flex-col gap-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-medium\">\n {selected?.path || \"Select a file\"}\n </div>\n {selected && selected.kind !== \"agent\" ? (\n <Badge variant=\"outline\">\n {selected.kind === \"skill\" ? \"Skill\" : \"Reference\"}\n </Badge>\n ) : null}\n </div>\n <div className=\"flex items-center gap-1\">\n {selected && selected.kind !== \"agent\" ? (\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\">\n <IconTrash size={15} />\n Remove\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n Remove this pack file?\n </AlertDialogTitle>\n <AlertDialogDescription>\n The file will no longer be available to this agent.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => remove.mutate({ id: selected.id })}\n disabled={remove.isPending}\n >\n Remove\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n ) : null}\n <Button\n size=\"sm\"\n onClick={() =>\n selected && update.mutate({ id: selected.id, content })\n }\n disabled={\n !selected ||\n update.isPending ||\n content === selected.content\n }\n >\n {update.isPending ? \"Saving...\" : \"Save file\"}\n </Button>\n </div>\n </div>\n <Textarea\n value={content}\n onChange={(event) => setContent(event.target.value)}\n disabled={!selected}\n rows={18}\n className=\"min-h-[360px] font-mono text-sm\"\n />\n </div>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction ImportAgentDialog({ onImported }: { onImported?: () => void }) {\n const [open, setOpen] = useState(false);\n const [mode, setMode] = useState<\"file\" | \"folder\" | \"endpoint\">(\"file\");\n const [source, setSource] = useState(\"\");\n const [fileName, setFileName] = useState(\"\");\n const [scope, setScope] = useState<\"all\" | \"selected\">(\"all\");\n const [url, setUrl] = useState(\"\");\n const [endpointName, setEndpointName] = useState(\"\");\n const [endpointDescription, setEndpointDescription] = useState(\"\");\n const [packFiles, setPackFiles] = useState<AgentPackFileInput[]>([]);\n const [packName, setPackName] = useState(\"\");\n const [packWarnings, setPackWarnings] = useState<string[]>([]);\n const fileRef = useRef<HTMLInputElement>(null);\n const folderRef = useRef<HTMLInputElement>(null);\n\n const importAgent = useActionMutation(\"import-agent\", {\n onSuccess: (result: { status: string; warnings?: string[] }) => {\n toast.success(\n result.status === \"unchanged\"\n ? \"Agent already imported\"\n : \"Agent imported\",\n );\n if (result.warnings?.length) {\n toast.info(result.warnings.join(\" \"));\n }\n setOpen(false);\n onImported?.();\n },\n onError: (error) => toast.error(error.message),\n });\n const connect = useActionMutation(\"connect-external-agent\", {\n onSuccess: () => {\n toast.success(\"Agent connected\");\n setOpen(false);\n onImported?.();\n },\n onError: (error) => toast.error(error.message),\n });\n const importPack = useActionMutation(\"import-agent-pack\", {\n onSuccess: (result: { status: string; warnings?: string[] }) => {\n toast.success(\n result.status === \"pending-approval\"\n ? \"Pack sent for approval\"\n : result.status === \"unchanged\"\n ? \"Agent pack already imported\"\n : \"Agent pack imported\",\n );\n if (result.warnings?.length) toast.info(result.warnings.join(\" \"));\n setOpen(false);\n onImported?.();\n },\n onError: (error) => toast.error(error.message),\n });\n\n useEffect(() => {\n if (!folderRef.current) return;\n folderRef.current.setAttribute(\"webkitdirectory\", \"\");\n folderRef.current.setAttribute(\"directory\", \"\");\n }, [mode, open]);\n\n function reset() {\n setMode(\"file\");\n setSource(\"\");\n setFileName(\"\");\n setScope(\"all\");\n setUrl(\"\");\n setEndpointName(\"\");\n setEndpointDescription(\"\");\n setPackFiles([]);\n setPackName(\"\");\n setPackWarnings([]);\n }\n\n async function handleFile(event: ChangeEvent<HTMLInputElement>) {\n const file = event.target.files?.[0];\n if (!file) return;\n setFileName(file.name);\n setSource(await file.text());\n }\n\n async function handleFolder(event: ChangeEvent<HTMLInputElement>) {\n const selectedFiles = Array.from(event.target.files ?? []);\n if (selectedFiles.length === 0) return;\n const warnings: string[] = [];\n const textExtensions =\n /\\.(md|markdown|txt|json|yaml|yml|csv|html|xml|toml|ts|tsx|js|mjs|py|sh)$/i;\n const pack = await Promise.all(\n selectedFiles.map(async (file) => {\n const path =\n (file as File & { webkitRelativePath?: string }).webkitRelativePath ||\n file.name;\n if (!textExtensions.test(path)) {\n warnings.push(`Skipped non-text file: ${path}`);\n return null;\n }\n return { path, content: await file.text() };\n }),\n );\n const files = pack.filter((file): file is AgentPackFileInput =>\n Boolean(file),\n );\n setPackFiles(files);\n setPackName(files[0]?.path.split(\"/\")[0] || \"Selected folder\");\n setPackWarnings(warnings);\n }\n\n return (\n <Dialog\n open={open}\n onOpenChange={(nextOpen) => {\n setOpen(nextOpen);\n if (!nextOpen) reset();\n }}\n >\n <DialogTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <IconFileImport size={16} />\n Import or connect\n </Button>\n </DialogTrigger>\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>Import an agent</DialogTitle>\n <DialogDescription className=\"sr-only\">\n Import a Claude or JSON agent definition, or connect an external\n agent endpoint.\n </DialogDescription>\n </DialogHeader>\n <Tabs\n value={mode}\n onValueChange={(value) =>\n setMode(value as \"file\" | \"folder\" | \"endpoint\")\n }\n >\n <TabsList className=\"w-full justify-start\">\n <TabsTrigger value=\"file\">Agent file</TabsTrigger>\n <TabsTrigger value=\"folder\">Agent folder</TabsTrigger>\n <TabsTrigger value=\"endpoint\">Connect endpoint</TabsTrigger>\n </TabsList>\n <TabsContent value=\"file\" className=\"flex flex-col gap-4 py-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => fileRef.current?.click()}\n >\n <IconUpload size={16} />\n Choose file\n </Button>\n <input\n ref={fileRef}\n type=\"file\"\n accept=\".md,.markdown,.json,.txt\"\n className=\"hidden\"\n onChange={(event) => void handleFile(event)}\n />\n <span className=\"text-xs text-muted-foreground\">\n {fileName || \"Claude .md or JSON agent definition\"}\n </span>\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"import-agent-source\">Definition</Label>\n <Textarea\n id=\"import-agent-source\"\n value={source}\n onChange={(event) => setSource(event.target.value)}\n rows={12}\n className=\"font-mono text-sm\"\n placeholder=\"Paste a Claude-style agent file or a JSON definition\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"import-agent-scope\">Availability</Label>\n <Select\n value={scope}\n onValueChange={(value: \"all\" | \"selected\") => setScope(value)}\n >\n <SelectTrigger id=\"import-agent-scope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All apps</SelectItem>\n <SelectItem value=\"selected\">Selected apps</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <DialogFooter>\n <Button\n onClick={() =>\n importAgent.mutate({\n source,\n fileName: fileName || undefined,\n scope,\n })\n }\n disabled={!source.trim() || importAgent.isPending}\n >\n {importAgent.isPending ? \"Importing...\" : \"Import agent\"}\n </Button>\n </DialogFooter>\n </TabsContent>\n <TabsContent value=\"folder\" className=\"flex flex-col gap-4 py-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => folderRef.current?.click()}\n >\n <IconFolder size={16} />\n Choose folder\n </Button>\n <input\n ref={folderRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(event) => void handleFolder(event)}\n />\n <span className=\"text-xs text-muted-foreground\">\n {packName\n ? `${packName} · ${packFiles.length} files`\n : \"Claude Project or Cowork-style folder\"}\n </span>\n </div>\n {packWarnings.length > 0 ? (\n <div className=\"rounded-lg border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-800 dark:text-amber-200\">\n {packWarnings.join(\" \")}\n </div>\n ) : null}\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"import-agent-pack-scope\">Availability</Label>\n <Select\n value={scope}\n onValueChange={(value: \"all\" | \"selected\") => setScope(value)}\n >\n <SelectTrigger id=\"import-agent-pack-scope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All apps</SelectItem>\n <SelectItem value=\"selected\">Selected apps</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <DialogFooter>\n <Button\n onClick={() => importPack.mutate({ files: packFiles, scope })}\n disabled={packFiles.length === 0 || importPack.isPending}\n >\n {importPack.isPending ? \"Importing...\" : \"Import agent pack\"}\n </Button>\n </DialogFooter>\n </TabsContent>\n <TabsContent value=\"endpoint\" className=\"flex flex-col gap-4 py-4\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"external-agent-url\">Endpoint URL</Label>\n <Input\n id=\"external-agent-url\"\n value={url}\n onChange={(event) => setUrl(event.target.value)}\n placeholder=\"https://agent.example.com\"\n />\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"external-agent-name\">Name</Label>\n <Input\n id=\"external-agent-name\"\n value={endpointName}\n onChange={(event) => setEndpointName(event.target.value)}\n placeholder=\"Research partner\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label>Availability</Label>\n <div className=\"flex h-10 items-center\">\n <Badge variant=\"secondary\">Workspace</Badge>\n </div>\n </div>\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"external-agent-description\">Description</Label>\n <Input\n id=\"external-agent-description\"\n value={endpointDescription}\n onChange={(event) => setEndpointDescription(event.target.value)}\n placeholder=\"Optional\"\n />\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Dispatch stores the public endpoint only. Authenticate it after\n connecting.\n </p>\n <DialogFooter>\n <Button\n onClick={() =>\n connect.mutate({\n url,\n name: endpointName || undefined,\n description: endpointDescription || undefined,\n scope: \"shared\",\n })\n }\n disabled={!url.trim() || connect.isPending}\n >\n <IconPlugConnected size={16} />\n {connect.isPending ? \"Connecting...\" : \"Connect agent\"}\n </Button>\n </DialogFooter>\n </TabsContent>\n </Tabs>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction DeleteAgentButton({\n resource,\n onDeleted,\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n}: {\n resource: WorkspaceAgentResource;\n onDeleted?: () => void;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = controlledOpen ?? uncontrolledOpen;\n const setOpen = controlledOnOpenChange ?? setUncontrolledOpen;\n const remove = useActionMutation(\"delete-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Agent removed\");\n onDeleted?.();\n },\n onError: (error) => toast.error(error.message),\n });\n\n return (\n <AlertDialog open={open} onOpenChange={setOpen}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Remove {resource.name}?</AlertDialogTitle>\n <AlertDialogDescription>\n This removes the reusable profile from the workspace apps.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => remove.mutate({ id: resource.id })}\n disabled={remove.isPending}\n >\n Remove\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n\nfunction AgentRow({\n resource,\n onDeleted,\n onSaved,\n}: {\n resource: WorkspaceAgentResource;\n onDeleted?: () => void;\n onSaved?: () => void;\n}) {\n const navigate = useNavigate();\n const [packOpen, setPackOpen] = useState(false);\n const [editorOpen, setEditorOpen] = useState(false);\n const [deleteOpen, setDeleteOpen] = useState(false);\n const packQuery = useActionQuery<AgentPackResponse>(\n \"list-agent-pack\",\n { agentId: resource.id },\n { enabled: false },\n );\n const promote = useActionMutation<\n AgentAppCreationResult,\n AgentAppCreationInput\n >(\"start-workspace-app-creation\", {\n onSuccess: (result) => {\n if (result.mode === \"local-agent\") {\n sendToAgentChat({\n message: result.prompt ?? result.message,\n submit: true,\n type: \"code\",\n newTab: true,\n reuseEmptyTab: true,\n });\n toast.success(\"Sent to the local agent\");\n return;\n }\n if (result.mode === \"builder\") {\n toast.success(\"App build started\", {\n description: result.message,\n action: result.url\n ? {\n label: \"Open in Builder\",\n onClick: () =>\n window.open(result.url, \"_blank\", \"noopener,noreferrer\"),\n }\n : undefined,\n });\n return;\n }\n toast.error(result.message);\n },\n onError: (error) => toast.error(error.message),\n });\n\n function chat() {\n navigateWithAgentChatViewTransition(\n navigate,\n `/chat?agent=${encodeURIComponent(resource.path)}`,\n );\n }\n\n async function buildApp() {\n const pack = await packQuery.refetch();\n if (pack.error || !pack.data) {\n toast.error(pack.error?.message || \"Could not load the agent pack\");\n return;\n }\n promote.mutate({\n appId: slugifyAgentName(resource.name),\n description: resource.description || undefined,\n prompt: `Turn the \"${resource.name}\" workspace agent into a focused workspace app. Preserve its role and instructions, make the app its usable face, and keep the original reusable agent profile available.`,\n resourceIds: [resource.id, ...pack.data.files.map((file) => file.id)],\n });\n }\n\n return (\n <div className=\"flex min-w-0 items-start gap-3 rounded-2xl border bg-card px-4 py-4\">\n <AppIcon\n id={resource.id}\n name={resource.name}\n icon={agentIconKey(resource)}\n size=\"sm\"\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {resource.name}\n </span>\n <Badge variant=\"outline\">\n {resource.scope === \"all\" ? \"All apps\" : \"Selected apps\"}\n </Badge>\n </div>\n {resource.description ? (\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {resource.description}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={chat}\n aria-label={`Chat with ${resource.name}`}\n >\n <IconMessageCircle size={15} />\n Chat\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`More actions for ${resource.name}`}\n title=\"More actions\"\n >\n <IconDotsVertical size={16} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuItem\n onSelect={() => {\n void buildApp();\n }}\n disabled={promote.isPending}\n >\n <IconLayoutGrid className=\"me-2 size-4\" />\n {promote.isPending ? \"Starting...\" : \"Build app\"}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => setPackOpen(true)}>\n <IconFolder className=\"me-2 size-4\" />\n Manage files\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => setEditorOpen(true)}>\n <IconEdit className=\"me-2 size-4\" />\n Edit\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-destructive focus:text-destructive\"\n onSelect={() => setDeleteOpen(true)}\n >\n <IconTrash className=\"me-2 size-4\" />\n Remove\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n <AgentPackDialog\n resource={resource}\n onChanged={onSaved}\n open={packOpen}\n onOpenChange={setPackOpen}\n />\n <AgentEditorDialog\n resource={resource}\n onSaved={onSaved}\n open={editorOpen}\n onOpenChange={setEditorOpen}\n />\n <DeleteAgentButton\n resource={resource}\n onDeleted={onDeleted}\n open={deleteOpen}\n onOpenChange={setDeleteOpen}\n />\n </div>\n </div>\n );\n}\n\ninterface AgentAppCreationInput {\n appId: string;\n description?: string;\n prompt: string;\n resourceIds: string[];\n}\n\ninterface AgentAppCreationResult {\n mode: \"builder\" | \"local-agent\" | \"builder-unavailable\" | \"coming-soon\";\n message: string;\n prompt?: string;\n url?: string;\n}\n\nexport function SimpleAgentsPanel({\n title,\n}: {\n title?: ReactNode;\n} = {}) {\n const query = useActionQuery<WorkspaceAgentResource[]>(\n \"list-workspace-resources\",\n { kind: \"agent\" },\n );\n const agents = query.data ?? [];\n const refreshAgents = () => void query.refetch();\n const importAction = <ImportAgentDialog onImported={refreshAgents} />;\n\n if (query.isError) {\n return (\n <ActionQueryError\n error={query.error}\n onRetry={() => void query.refetch()}\n />\n );\n }\n\n return (\n <section className=\"flex flex-col gap-4\">\n {title || agents.length > 0 ? (\n <div\n className={`flex flex-wrap items-center gap-3 ${title ? \"justify-between\" : \"justify-end\"}`}\n >\n {title ? (\n <h2 className=\"text-base font-medium text-foreground\">{title}</h2>\n ) : null}\n {agents.length > 0 ? (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {importAction}\n <AgentEditorDialog onSaved={refreshAgents} />\n </div>\n ) : null}\n </div>\n ) : null}\n {query.isLoading && agents.length === 0 ? (\n <div className=\"grid gap-3 md:grid-cols-2\">\n {[0, 1, 2].map((item) => (\n <div key={item} className=\"rounded-2xl border bg-card px-4 py-4\">\n <Skeleton className=\"h-4 w-1/3\" />\n <Skeleton className=\"mt-2 h-3 w-2/3\" />\n </div>\n ))}\n </div>\n ) : agents.length > 0 ? (\n <div className=\"grid gap-3 md:grid-cols-2\">\n {agents.map((agent) => (\n <AgentRow\n key={agent.id}\n resource={agent}\n onDeleted={() => void query.refetch()}\n onSaved={() => void query.refetch()}\n />\n ))}\n </div>\n ) : (\n <div className=\"rounded-2xl border border-dashed bg-card px-4 py-12 text-center\">\n <div className=\"text-sm font-medium text-foreground\">\n No agents yet\n </div>\n <div className=\"mt-4 flex flex-wrap justify-center gap-2\">\n <AgentEditorDialog\n onSaved={refreshAgents}\n trigger={\n <Button size=\"sm\">\n <IconPlus size={16} />\n Create an agent\n </Button>\n }\n />\n {importAction}\n </div>\n </div>\n )}\n </section>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"simple-agents-panel.js","sourceRoot":"","sources":["../../src/components/simple-agents-panel.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n navigateWithAgentChatViewTransition,\n sendToAgentChat,\n} from \"@agent-native/core/client/agent-chat\";\nimport {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { parseCustomAgentProfile } from \"@agent-native/core/resources/metadata\";\nimport {\n IconAdjustmentsHorizontal,\n IconChevronDown,\n IconDotsVertical,\n IconEdit,\n IconFileImport,\n IconFolder,\n IconLayoutGrid,\n IconMessageCircle,\n IconPlugConnected,\n IconPlus,\n IconTrash,\n IconUpload,\n} from \"@tabler/icons-react\";\nimport {\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type ReactNode,\n} from \"react\";\nimport { useNavigate } from \"react-router\";\nimport { toast } from \"sonner\";\n\nimport {\n AGENT_PACK_FILE_ACCEPT,\n AGENT_PROFILE_FILE_ACCEPT,\n AGENT_PROFILE_FILE_EXTENSIONS,\n isImportableAgentPackFile,\n isImportableAgentProfileFile,\n} from \"../lib/agent-pack.js\";\nimport {\n buildSimpleAgentContent,\n slugifyAgentName,\n} from \"../lib/simple-agent-profile.js\";\nimport { ActionQueryError } from \"./action-query-error\";\nimport { AppIcon } from \"./app-icon\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"./ui/alert-dialog\";\nimport { Badge } from \"./ui/badge\";\nimport { Button } from \"./ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"./ui/collapsible\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"./ui/dialog\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"./ui/dropdown-menu\";\nimport { Input } from \"./ui/input\";\nimport { Label } from \"./ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"./ui/select\";\nimport { Skeleton } from \"./ui/skeleton\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"./ui/tabs\";\nimport { Textarea } from \"./ui/textarea\";\n\ninterface WorkspaceAgentResource {\n id: string;\n name: string;\n description: string | null;\n path: string;\n content: string;\n scope: \"all\" | \"selected\";\n updatedAt: number;\n}\n\ninterface AgentPackFileResource extends WorkspaceAgentResource {\n kind: \"agent-file\" | \"skill\";\n}\n\ninterface AgentPackResponse {\n profile: WorkspaceAgentResource;\n root: string;\n files: AgentPackFileResource[];\n}\n\ninterface AgentPackFileInput {\n path: string;\n content: string;\n}\n\nconst MAX_LISTED_SKIPPED_FILES = 3;\n\n/**\n * Folder pickers cannot filter by extension, so unsupported files are only\n * visible after selection. Name them without turning a 40-file photo folder\n * into a 40-line warning.\n */\nexport function summarizeSkippedPackFiles(\n skipped: string[],\n keptCount: number,\n): string[] {\n if (skipped.length === 0) return [];\n if (keptCount === 0) {\n return [\n \"No importable files in that folder. Agent folders take text files such as Markdown, JSON, and YAML.\",\n ];\n }\n const listed = skipped.slice(0, MAX_LISTED_SKIPPED_FILES);\n const remaining = skipped.length - listed.length;\n const names =\n remaining > 0\n ? `${listed.join(\", \")}, and ${remaining} more`\n : listed.join(\", \");\n return [\n `Skipped ${skipped.length} non-text ${skipped.length === 1 ? \"file\" : \"files\"}: ${names}.`,\n ];\n}\n\nconst AGENT_ICON_KEYS = [\n \"brain\",\n \"users\",\n \"filetext\",\n \"chartbar\",\n \"route\",\n \"listcheck\",\n \"code\",\n \"messagecircle\",\n] as const;\n\nfunction agentIconKey(resource: Pick<WorkspaceAgentResource, \"id\" | \"name\">) {\n let hash = 0;\n for (const character of `${resource.id}:${resource.name}`) {\n hash = (hash * 31 + character.charCodeAt(0)) | 0;\n }\n return AGENT_ICON_KEYS[Math.abs(hash) % AGENT_ICON_KEYS.length];\n}\n\nexport function isPendingWorkspaceResourceApproval(result: unknown) {\n if (!result || typeof result !== \"object\") return false;\n const mutation = result as { status?: unknown; changeType?: unknown };\n return (\n mutation.status === \"pending\" &&\n typeof mutation.changeType === \"string\" &&\n mutation.changeType.startsWith(\"workspace-resource.\")\n );\n}\n\nexport function handleAgentPackMutationSuccess(\n result: unknown,\n options: {\n appliedMessage: string;\n approvalMessage: string;\n onApplied: () => void;\n notify?: (message: string) => void;\n },\n) {\n const notify = options.notify || ((message) => toast.success(message));\n if (isPendingWorkspaceResourceApproval(result)) {\n notify(options.approvalMessage);\n return;\n }\n notify(options.appliedMessage);\n options.onApplied();\n}\n\ninterface AgentEditorProps {\n resource?: WorkspaceAgentResource;\n trigger?: ReactNode;\n onSaved?: () => void;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nfunction profileFields(resource?: WorkspaceAgentResource) {\n if (!resource) {\n return {\n name: \"\",\n description: \"\",\n instructions: \"# Role\\n\\nDescribe how this agent should work.\\n\",\n model: \"inherit\",\n tools: \"inherit\",\n scope: \"all\" as const,\n };\n }\n\n const profile = parseCustomAgentProfile(resource.content, resource.path);\n return {\n name: profile?.name || resource.name,\n description: profile?.description || resource.description || \"\",\n instructions: profile?.instructions || resource.content,\n model: profile?.model || \"inherit\",\n tools: profile?.tools || \"inherit\",\n scope: resource.scope,\n };\n}\n\nfunction AgentEditorDialog({\n resource,\n trigger,\n onSaved,\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n}: AgentEditorProps) {\n const isEditing = Boolean(resource);\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = controlledOpen ?? uncontrolledOpen;\n const setOpen = controlledOnOpenChange ?? setUncontrolledOpen;\n const [name, setName] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [instructions, setInstructions] = useState(\"\");\n const [model, setModel] = useState(\"inherit\");\n const [tools, setTools] = useState(\"inherit\");\n const [scope, setScope] = useState<\"all\" | \"selected\">(\"all\");\n const [advancedOpen, setAdvancedOpen] = useState(false);\n\n useEffect(() => {\n if (!open) return;\n const fields = profileFields(resource);\n setName(fields.name);\n setDescription(fields.description);\n setInstructions(fields.instructions);\n setModel(fields.model);\n setTools(fields.tools);\n setScope(fields.scope);\n setAdvancedOpen(fields.model !== \"inherit\" || fields.tools !== \"inherit\");\n }, [open, resource]);\n\n const create = useActionMutation(\"create-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Agent created\");\n setOpen(false);\n onSaved?.();\n },\n onError: (error) => toast.error(error.message),\n });\n const update = useActionMutation(\"update-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Agent updated\");\n setOpen(false);\n onSaved?.();\n },\n onError: (error) => toast.error(error.message),\n });\n\n const pending = create.isPending || update.isPending;\n const canSave = Boolean(name.trim() && instructions.trim() && !pending);\n\n function save() {\n const content = buildSimpleAgentContent({\n name,\n description,\n model,\n tools,\n instructions,\n });\n if (resource) {\n update.mutate({\n id: resource.id,\n name: name.trim(),\n description: description.trim(),\n content,\n scope,\n });\n return;\n }\n create.mutate({\n kind: \"agent\",\n name: name.trim(),\n description: description.trim() || undefined,\n path: `agents/${slugifyAgentName(name)}.md`,\n content,\n scope,\n });\n }\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n {trigger ? (\n <DialogTrigger asChild>{trigger}</DialogTrigger>\n ) : controlledOpen === undefined ? (\n <DialogTrigger asChild>\n <Button size=\"sm\">\n <IconPlus size={16} />\n Create agent\n </Button>\n </DialogTrigger>\n ) : null}\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>\n {isEditing ? \"Manage agent\" : \"Create agent\"}\n </DialogTitle>\n <DialogDescription className=\"sr-only\">\n {isEditing\n ? \"Update this reusable agent profile.\"\n : \"Create a reusable agent profile.\"}\n </DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col gap-4 py-2\">\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-name\">Name</Label>\n <Input\n id=\"simple-agent-name\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n placeholder=\"User Research\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-scope\">Availability</Label>\n <Select\n value={scope}\n onValueChange={(value: \"all\" | \"selected\") => setScope(value)}\n >\n <SelectTrigger id=\"simple-agent-scope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All apps</SelectItem>\n <SelectItem value=\"selected\">Selected apps</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-description\">Description</Label>\n <Input\n id=\"simple-agent-description\"\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n placeholder=\"Synthesizes user research into clear insights\"\n />\n </div>\n <Collapsible open={advancedOpen} onOpenChange={setAdvancedOpen}>\n <CollapsibleTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"group -ml-2 gap-1.5 text-muted-foreground\"\n >\n <IconAdjustmentsHorizontal size={15} />\n Advanced\n <IconChevronDown\n className=\"transition-transform group-data-[state=open]:rotate-180\"\n size={15}\n />\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent className=\"pt-3\">\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-model\">Model</Label>\n <Input\n id=\"simple-agent-model\"\n value={model}\n onChange={(event) => setModel(event.target.value)}\n placeholder=\"inherit\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-tools\">Tools</Label>\n <Input\n id=\"simple-agent-tools\"\n value={tools}\n onChange={(event) => setTools(event.target.value)}\n placeholder=\"inherit\"\n />\n </div>\n </div>\n </CollapsibleContent>\n </Collapsible>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"simple-agent-instructions\">Instructions</Label>\n <Textarea\n id=\"simple-agent-instructions\"\n value={instructions}\n onChange={(event) => setInstructions(event.target.value)}\n rows={12}\n className=\"font-mono text-sm\"\n placeholder=\"# Role\\n\\nDescribe how this agent should work.\"\n />\n </div>\n </div>\n <DialogFooter>\n <Button onClick={save} disabled={!canSave}>\n {pending\n ? \"Saving...\"\n : isEditing\n ? \"Save changes\"\n : \"Create agent\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction AgentPackDialog({\n resource,\n onChanged,\n trigger,\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n}: {\n resource: WorkspaceAgentResource;\n onChanged?: () => void;\n trigger?: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = controlledOpen ?? uncontrolledOpen;\n const setOpen = controlledOnOpenChange ?? setUncontrolledOpen;\n const [selectedId, setSelectedId] = useState(resource.id);\n const [content, setContent] = useState(resource.content);\n const [addOpen, setAddOpen] = useState(false);\n const [newPath, setNewPath] = useState(\"\");\n const [newKind, setNewKind] = useState<\"agent-file\" | \"skill\">(\"agent-file\");\n const [newContent, setNewContent] = useState(\"\");\n const query = useActionQuery<AgentPackResponse>(\n \"list-agent-pack\",\n { agentId: resource.id },\n { enabled: open },\n );\n const update = useActionMutation(\"update-workspace-resource\", {\n onSuccess: (result) => {\n handleAgentPackMutationSuccess(result, {\n appliedMessage: \"Pack file updated\",\n approvalMessage: \"Pack file update queued for approval\",\n onApplied: () => {\n void query.refetch();\n onChanged?.();\n },\n });\n },\n onError: (error) => toast.error(error.message),\n });\n const create = useActionMutation(\"create-workspace-resource\", {\n onSuccess: (result) => {\n handleAgentPackMutationSuccess(result, {\n appliedMessage: \"Pack file added\",\n approvalMessage: \"Pack file addition queued for approval\",\n onApplied: () => {\n setAddOpen(false);\n setNewPath(\"\");\n setNewContent(\"\");\n void query.refetch();\n onChanged?.();\n },\n });\n },\n onError: (error) => toast.error(error.message),\n });\n const remove = useActionMutation(\"delete-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Pack file removed\");\n setSelectedId(resource.id);\n void query.refetch();\n onChanged?.();\n },\n onError: (error) => toast.error(error.message),\n });\n\n const files = query.data\n ? [{ ...query.data.profile, kind: \"agent\" as const }, ...query.data.files]\n : [];\n const selected = files.find((file) => file.id === selectedId) ?? files[0];\n\n useEffect(() => {\n if (!open) return;\n setSelectedId(resource.id);\n }, [open, resource.id]);\n\n useEffect(() => {\n if (!selected) return;\n setSelectedId(selected.id);\n setContent(selected.content);\n }, [selected?.id, selected?.content]);\n\n function addFile() {\n const relativePath = newPath.trim().replaceAll(\"\\\\\", \"/\");\n if (\n !relativePath ||\n relativePath.startsWith(\"/\") ||\n relativePath.includes(\"..\") ||\n relativePath.split(\"/\").some((part) => !part || part === \".\")\n ) {\n toast.error(\"Use a relative pack path without ..\");\n return;\n }\n const packPath =\n newKind === \"skill\" && !relativePath.startsWith(\"skills/\")\n ? `skills/${relativePath}`\n : relativePath;\n const name = packPath.split(\"/\").pop() || packPath;\n create.mutate({\n kind: newKind,\n name,\n path: `${query.data?.root || `agents/${slugifyAgentName(resource.name)}`}/${packPath}`,\n content: newContent,\n scope: resource.scope,\n });\n }\n\n return (\n <Dialog\n open={open}\n onOpenChange={(nextOpen) => {\n setOpen(nextOpen);\n if (!nextOpen) setAddOpen(false);\n }}\n >\n {trigger ? (\n <DialogTrigger asChild>{trigger}</DialogTrigger>\n ) : controlledOpen === undefined ? (\n <DialogTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\">\n <IconFolder size={15} />\n Pack\n </Button>\n </DialogTrigger>\n ) : null}\n <DialogContent className=\"max-w-4xl\">\n <DialogHeader>\n <DialogTitle>Agent pack</DialogTitle>\n <DialogDescription className=\"sr-only\">\n Edit the profile, reference files, context, and skills that belong\n to this agent.\n </DialogDescription>\n </DialogHeader>\n <div className=\"grid min-h-0 gap-4 md:grid-cols-[220px_minmax(0,1fr)]\">\n <div className=\"flex min-w-0 flex-col gap-2\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Files\n </span>\n <Dialog open={addOpen} onOpenChange={setAddOpen}>\n <DialogTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <IconPlus size={14} />\n Add\n </Button>\n </DialogTrigger>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Add pack file</DialogTitle>\n <DialogDescription className=\"sr-only\">\n Add a text reference or agent-owned skill to this pack.\n </DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col gap-4 py-2\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"agent-pack-file-path\">Path</Label>\n <Input\n id=\"agent-pack-file-path\"\n value={newPath}\n onChange={(event) => setNewPath(event.target.value)}\n placeholder=\"context/brief.md\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"agent-pack-file-kind\">Type</Label>\n <Select\n value={newKind}\n onValueChange={(value: \"agent-file\" | \"skill\") =>\n setNewKind(value)\n }\n >\n <SelectTrigger id=\"agent-pack-file-kind\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"agent-file\">\n Reference file\n </SelectItem>\n <SelectItem value=\"skill\">Skill</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"agent-pack-file-content\">Content</Label>\n <Textarea\n id=\"agent-pack-file-content\"\n value={newContent}\n onChange={(event) => setNewContent(event.target.value)}\n rows={8}\n className=\"font-mono text-sm\"\n />\n </div>\n </div>\n <DialogFooter>\n <Button\n onClick={addFile}\n disabled={!newPath.trim() || create.isPending}\n >\n {create.isPending ? \"Adding...\" : \"Add file\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n {query.isLoading ? (\n <Skeleton className=\"h-24 w-full\" />\n ) : (\n <div className=\"flex flex-col gap-1\">\n {files.map((file) => (\n <Button\n key={file.id}\n type=\"button\"\n variant={selected?.id === file.id ? \"secondary\" : \"ghost\"}\n className=\"h-auto w-full justify-start px-2 py-2 text-left\"\n onClick={() => setSelectedId(file.id)}\n >\n <span className=\"min-w-0 truncate text-xs\">\n {file.path.replace(`${query.data?.root || \"\"}/`, \"\")}\n </span>\n </Button>\n ))}\n </div>\n )}\n </div>\n <div className=\"flex min-w-0 flex-col gap-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-medium\">\n {selected?.path || \"Select a file\"}\n </div>\n {selected && selected.kind !== \"agent\" ? (\n <Badge variant=\"outline\">\n {selected.kind === \"skill\" ? \"Skill\" : \"Reference\"}\n </Badge>\n ) : null}\n </div>\n <div className=\"flex items-center gap-1\">\n {selected && selected.kind !== \"agent\" ? (\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\">\n <IconTrash size={15} />\n Remove\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n Remove this pack file?\n </AlertDialogTitle>\n <AlertDialogDescription>\n The file will no longer be available to this agent.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => remove.mutate({ id: selected.id })}\n disabled={remove.isPending}\n >\n Remove\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n ) : null}\n <Button\n size=\"sm\"\n onClick={() =>\n selected && update.mutate({ id: selected.id, content })\n }\n disabled={\n !selected ||\n update.isPending ||\n content === selected.content\n }\n >\n {update.isPending ? \"Saving...\" : \"Save file\"}\n </Button>\n </div>\n </div>\n <Textarea\n value={content}\n onChange={(event) => setContent(event.target.value)}\n disabled={!selected}\n rows={18}\n className=\"min-h-[360px] font-mono text-sm\"\n />\n </div>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction ImportAgentDialog({ onImported }: { onImported?: () => void }) {\n const [open, setOpen] = useState(false);\n const [mode, setMode] = useState<\"file\" | \"folder\" | \"endpoint\">(\"file\");\n const [source, setSource] = useState(\"\");\n const [fileName, setFileName] = useState(\"\");\n const [scope, setScope] = useState<\"all\" | \"selected\">(\"all\");\n const [url, setUrl] = useState(\"\");\n const [endpointName, setEndpointName] = useState(\"\");\n const [endpointDescription, setEndpointDescription] = useState(\"\");\n const [packFiles, setPackFiles] = useState<AgentPackFileInput[]>([]);\n const [packName, setPackName] = useState(\"\");\n const [packWarnings, setPackWarnings] = useState<string[]>([]);\n const fileRef = useRef<HTMLInputElement>(null);\n const folderRef = useRef<HTMLInputElement>(null);\n\n const importAgent = useActionMutation(\"import-agent\", {\n onSuccess: (result: { status: string; warnings?: string[] }) => {\n toast.success(\n result.status === \"unchanged\"\n ? \"Agent already imported\"\n : \"Agent imported\",\n );\n if (result.warnings?.length) {\n toast.info(result.warnings.join(\" \"));\n }\n setOpen(false);\n onImported?.();\n },\n onError: (error) => toast.error(error.message),\n });\n const connect = useActionMutation(\"connect-external-agent\", {\n onSuccess: () => {\n toast.success(\"Agent connected\");\n setOpen(false);\n onImported?.();\n },\n onError: (error) => toast.error(error.message),\n });\n const importPack = useActionMutation(\"import-agent-pack\", {\n onSuccess: (result: { status: string; warnings?: string[] }) => {\n toast.success(\n result.status === \"pending-approval\"\n ? \"Pack sent for approval\"\n : result.status === \"unchanged\"\n ? \"Agent pack already imported\"\n : \"Agent pack imported\",\n );\n if (result.warnings?.length) toast.info(result.warnings.join(\" \"));\n setOpen(false);\n onImported?.();\n },\n onError: (error) => toast.error(error.message),\n });\n\n function reset() {\n setMode(\"file\");\n setSource(\"\");\n setFileName(\"\");\n setScope(\"all\");\n setUrl(\"\");\n setEndpointName(\"\");\n setEndpointDescription(\"\");\n setPackFiles([]);\n setPackName(\"\");\n setPackWarnings([]);\n }\n\n async function handleFile(event: ChangeEvent<HTMLInputElement>) {\n const file = event.target.files?.[0];\n event.target.value = \"\";\n if (!file) return;\n // `accept` is only a picker hint: every OS dialog lets the user switch to\n // \"All Files\", and reading a PDF with file.text() yields mojibake that\n // looks like a valid definition.\n if (!isImportableAgentProfileFile(file.name)) {\n toast.error(\n `${file.name} is not a supported agent file. Choose a ${AGENT_PROFILE_FILE_EXTENSIONS.join(\", \")} file.`,\n );\n return;\n }\n setFileName(file.name);\n setSource(await file.text());\n }\n\n async function handleFolder(event: ChangeEvent<HTMLInputElement>) {\n const selectedFiles = Array.from(event.target.files ?? []);\n event.target.value = \"\";\n if (selectedFiles.length === 0) return;\n const skipped: string[] = [];\n const pack = await Promise.all(\n selectedFiles.map(async (file) => {\n const path =\n (file as File & { webkitRelativePath?: string }).webkitRelativePath ||\n file.name;\n if (!isImportableAgentPackFile(path)) {\n skipped.push(path);\n return null;\n }\n return { path, content: await file.text() };\n }),\n );\n const files = pack.filter((file): file is AgentPackFileInput =>\n Boolean(file),\n );\n setPackFiles(files);\n setPackName(files[0]?.path.split(\"/\")[0] || \"Selected folder\");\n setPackWarnings(summarizeSkippedPackFiles(skipped, files.length));\n }\n\n return (\n <Dialog\n open={open}\n onOpenChange={(nextOpen) => {\n setOpen(nextOpen);\n if (!nextOpen) reset();\n }}\n >\n <DialogTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <IconFileImport size={16} />\n Import or connect\n </Button>\n </DialogTrigger>\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>Import an agent</DialogTitle>\n <DialogDescription className=\"sr-only\">\n Import a Claude or JSON agent definition, or connect an external\n agent endpoint.\n </DialogDescription>\n </DialogHeader>\n <Tabs\n value={mode}\n onValueChange={(value) =>\n setMode(value as \"file\" | \"folder\" | \"endpoint\")\n }\n >\n <TabsList className=\"w-full justify-start\">\n <TabsTrigger value=\"file\">Agent file</TabsTrigger>\n <TabsTrigger value=\"folder\">Agent folder</TabsTrigger>\n <TabsTrigger value=\"endpoint\">Connect endpoint</TabsTrigger>\n </TabsList>\n <TabsContent value=\"file\" className=\"flex flex-col gap-4 py-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => fileRef.current?.click()}\n >\n <IconUpload size={16} />\n Choose file\n </Button>\n <input\n ref={fileRef}\n type=\"file\"\n accept={AGENT_PROFILE_FILE_ACCEPT}\n className=\"hidden\"\n onChange={(event) => void handleFile(event)}\n />\n <span className=\"text-xs text-muted-foreground\">\n {fileName || \"Claude .md or JSON agent definition\"}\n </span>\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"import-agent-source\">Definition</Label>\n <Textarea\n id=\"import-agent-source\"\n value={source}\n onChange={(event) => setSource(event.target.value)}\n rows={12}\n className=\"font-mono text-sm\"\n placeholder=\"Paste a Claude-style agent file or a JSON definition\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"import-agent-scope\">Availability</Label>\n <Select\n value={scope}\n onValueChange={(value: \"all\" | \"selected\") => setScope(value)}\n >\n <SelectTrigger id=\"import-agent-scope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All apps</SelectItem>\n <SelectItem value=\"selected\">Selected apps</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <DialogFooter>\n <Button\n onClick={() =>\n importAgent.mutate({\n source,\n fileName: fileName || undefined,\n scope,\n })\n }\n disabled={!source.trim() || importAgent.isPending}\n >\n {importAgent.isPending ? \"Importing...\" : \"Import agent\"}\n </Button>\n </DialogFooter>\n </TabsContent>\n <TabsContent value=\"folder\" className=\"flex flex-col gap-4 py-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => folderRef.current?.click()}\n >\n <IconFolder size={16} />\n Choose folder\n </Button>\n <input\n ref={folderRef}\n type=\"file\"\n multiple\n // Set declaratively: an effect keyed on the tab runs before\n // Radix mounts this panel, so the ref is still null and the\n // input silently stays a plain file picker.\n {...({ webkitdirectory: \"\", directory: \"\" } as {\n webkitdirectory: string;\n directory: string;\n })}\n // Directory pickers ignore accept; it only applies where\n // webkitdirectory is unsupported and this falls back to\n // multi-file selection.\n accept={AGENT_PACK_FILE_ACCEPT}\n className=\"hidden\"\n onChange={(event) => void handleFolder(event)}\n />\n <span className=\"text-xs text-muted-foreground\">\n {packName\n ? `${packName} · ${packFiles.length} files`\n : \"Claude Project or Cowork-style folder · text files only\"}\n </span>\n </div>\n {packWarnings.length > 0 ? (\n <div className=\"rounded-lg border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-800 dark:text-amber-200\">\n {packWarnings.join(\" \")}\n </div>\n ) : null}\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"import-agent-pack-scope\">Availability</Label>\n <Select\n value={scope}\n onValueChange={(value: \"all\" | \"selected\") => setScope(value)}\n >\n <SelectTrigger id=\"import-agent-pack-scope\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All apps</SelectItem>\n <SelectItem value=\"selected\">Selected apps</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <DialogFooter>\n <Button\n onClick={() => importPack.mutate({ files: packFiles, scope })}\n disabled={packFiles.length === 0 || importPack.isPending}\n >\n {importPack.isPending ? \"Importing...\" : \"Import agent pack\"}\n </Button>\n </DialogFooter>\n </TabsContent>\n <TabsContent value=\"endpoint\" className=\"flex flex-col gap-4 py-4\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"external-agent-url\">Endpoint URL</Label>\n <Input\n id=\"external-agent-url\"\n value={url}\n onChange={(event) => setUrl(event.target.value)}\n placeholder=\"https://agent.example.com\"\n />\n </div>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"external-agent-name\">Name</Label>\n <Input\n id=\"external-agent-name\"\n value={endpointName}\n onChange={(event) => setEndpointName(event.target.value)}\n placeholder=\"Research partner\"\n />\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label>Availability</Label>\n <div className=\"flex h-10 items-center\">\n <Badge variant=\"secondary\">Workspace</Badge>\n </div>\n </div>\n </div>\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"external-agent-description\">Description</Label>\n <Input\n id=\"external-agent-description\"\n value={endpointDescription}\n onChange={(event) => setEndpointDescription(event.target.value)}\n placeholder=\"Optional\"\n />\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Dispatch stores the public endpoint only. Authenticate it after\n connecting.\n </p>\n <DialogFooter>\n <Button\n onClick={() =>\n connect.mutate({\n url,\n name: endpointName || undefined,\n description: endpointDescription || undefined,\n scope: \"shared\",\n })\n }\n disabled={!url.trim() || connect.isPending}\n >\n <IconPlugConnected size={16} />\n {connect.isPending ? \"Connecting...\" : \"Connect agent\"}\n </Button>\n </DialogFooter>\n </TabsContent>\n </Tabs>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction DeleteAgentButton({\n resource,\n onDeleted,\n open: controlledOpen,\n onOpenChange: controlledOnOpenChange,\n}: {\n resource: WorkspaceAgentResource;\n onDeleted?: () => void;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = controlledOpen ?? uncontrolledOpen;\n const setOpen = controlledOnOpenChange ?? setUncontrolledOpen;\n const remove = useActionMutation(\"delete-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Agent removed\");\n onDeleted?.();\n },\n onError: (error) => toast.error(error.message),\n });\n\n return (\n <AlertDialog open={open} onOpenChange={setOpen}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Remove {resource.name}?</AlertDialogTitle>\n <AlertDialogDescription>\n This removes the reusable profile from the workspace apps.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => remove.mutate({ id: resource.id })}\n disabled={remove.isPending}\n >\n Remove\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n\nfunction AgentRow({\n resource,\n onDeleted,\n onSaved,\n}: {\n resource: WorkspaceAgentResource;\n onDeleted?: () => void;\n onSaved?: () => void;\n}) {\n const navigate = useNavigate();\n const [packOpen, setPackOpen] = useState(false);\n const [editorOpen, setEditorOpen] = useState(false);\n const [deleteOpen, setDeleteOpen] = useState(false);\n const packQuery = useActionQuery<AgentPackResponse>(\n \"list-agent-pack\",\n { agentId: resource.id },\n { enabled: false },\n );\n const promote = useActionMutation<\n AgentAppCreationResult,\n AgentAppCreationInput\n >(\"start-workspace-app-creation\", {\n onSuccess: (result) => {\n if (result.mode === \"local-agent\") {\n sendToAgentChat({\n message: result.prompt ?? result.message,\n submit: true,\n type: \"code\",\n newTab: true,\n reuseEmptyTab: true,\n });\n toast.success(\"Sent to the local agent\");\n return;\n }\n if (result.mode === \"builder\") {\n toast.success(\"App build started\", {\n description: result.message,\n action: result.url\n ? {\n label: \"Open in Builder\",\n onClick: () =>\n window.open(result.url, \"_blank\", \"noopener,noreferrer\"),\n }\n : undefined,\n });\n return;\n }\n toast.error(result.message);\n },\n onError: (error) => toast.error(error.message),\n });\n\n function chat() {\n navigateWithAgentChatViewTransition(\n navigate,\n `/chat?agent=${encodeURIComponent(resource.path)}`,\n );\n }\n\n async function buildApp() {\n const pack = await packQuery.refetch();\n if (pack.error || !pack.data) {\n toast.error(pack.error?.message || \"Could not load the agent pack\");\n return;\n }\n promote.mutate({\n appId: slugifyAgentName(resource.name),\n description: resource.description || undefined,\n prompt: `Turn the \"${resource.name}\" workspace agent into a focused workspace app. Preserve its role and instructions, make the app its usable face, and keep the original reusable agent profile available.`,\n resourceIds: [resource.id, ...pack.data.files.map((file) => file.id)],\n });\n }\n\n return (\n <div className=\"flex min-w-0 items-start gap-3 rounded-2xl border bg-card px-4 py-4\">\n <AppIcon\n id={resource.id}\n name={resource.name}\n icon={agentIconKey(resource)}\n size=\"sm\"\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {resource.name}\n </span>\n <Badge variant=\"outline\">\n {resource.scope === \"all\" ? \"All apps\" : \"Selected apps\"}\n </Badge>\n </div>\n {resource.description ? (\n <div className=\"mt-1 text-sm text-muted-foreground\">\n {resource.description}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={chat}\n aria-label={`Chat with ${resource.name}`}\n >\n <IconMessageCircle size={15} />\n Chat\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`More actions for ${resource.name}`}\n title=\"More actions\"\n >\n <IconDotsVertical size={16} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuItem\n onSelect={() => {\n void buildApp();\n }}\n disabled={promote.isPending}\n >\n <IconLayoutGrid className=\"me-2 size-4\" />\n {promote.isPending ? \"Starting...\" : \"Build app\"}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => setPackOpen(true)}>\n <IconFolder className=\"me-2 size-4\" />\n Manage files\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => setEditorOpen(true)}>\n <IconEdit className=\"me-2 size-4\" />\n Edit\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-destructive focus:text-destructive\"\n onSelect={() => setDeleteOpen(true)}\n >\n <IconTrash className=\"me-2 size-4\" />\n Remove\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n <AgentPackDialog\n resource={resource}\n onChanged={onSaved}\n open={packOpen}\n onOpenChange={setPackOpen}\n />\n <AgentEditorDialog\n resource={resource}\n onSaved={onSaved}\n open={editorOpen}\n onOpenChange={setEditorOpen}\n />\n <DeleteAgentButton\n resource={resource}\n onDeleted={onDeleted}\n open={deleteOpen}\n onOpenChange={setDeleteOpen}\n />\n </div>\n </div>\n );\n}\n\ninterface AgentAppCreationInput {\n appId: string;\n description?: string;\n prompt: string;\n resourceIds: string[];\n}\n\ninterface AgentAppCreationResult {\n mode: \"builder\" | \"local-agent\" | \"builder-unavailable\" | \"coming-soon\";\n message: string;\n prompt?: string;\n url?: string;\n}\n\nexport function SimpleAgentsPanel({\n title,\n}: {\n title?: ReactNode;\n} = {}) {\n const query = useActionQuery<WorkspaceAgentResource[]>(\n \"list-workspace-resources\",\n { kind: \"agent\" },\n );\n const agents = query.data ?? [];\n const refreshAgents = () => void query.refetch();\n const importAction = <ImportAgentDialog onImported={refreshAgents} />;\n\n if (query.isError) {\n return (\n <ActionQueryError\n error={query.error}\n onRetry={() => void query.refetch()}\n />\n );\n }\n\n return (\n <section className=\"flex flex-col gap-4\">\n {title || agents.length > 0 ? (\n <div\n className={`flex flex-wrap items-center gap-3 ${title ? \"justify-between\" : \"justify-end\"}`}\n >\n {title ? (\n <h2 className=\"text-base font-medium text-foreground\">{title}</h2>\n ) : null}\n {agents.length > 0 ? (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {importAction}\n <AgentEditorDialog onSaved={refreshAgents} />\n </div>\n ) : null}\n </div>\n ) : null}\n {query.isLoading && agents.length === 0 ? (\n <div className=\"grid gap-3 md:grid-cols-2\">\n {[0, 1, 2].map((item) => (\n <div key={item} className=\"rounded-2xl border bg-card px-4 py-4\">\n <Skeleton className=\"h-4 w-1/3\" />\n <Skeleton className=\"mt-2 h-3 w-2/3\" />\n </div>\n ))}\n </div>\n ) : agents.length > 0 ? (\n <div className=\"grid gap-3 md:grid-cols-2\">\n {agents.map((agent) => (\n <AgentRow\n key={agent.id}\n resource={agent}\n onDeleted={() => void query.refetch()}\n onSaved={() => void query.refetch()}\n />\n ))}\n </div>\n ) : (\n <div className=\"rounded-2xl border border-dashed bg-card px-4 py-12 text-center\">\n <div className=\"text-sm font-medium text-foreground\">\n No agents yet\n </div>\n <div className=\"mt-4 flex flex-wrap justify-center gap-2\">\n <AgentEditorDialog\n onSaved={refreshAgents}\n trigger={\n <Button size=\"sm\">\n <IconPlus size={16} />\n Create an agent\n </Button>\n }\n />\n {importAction}\n </div>\n </div>\n )}\n </section>\n );\n}\n"]}
|
package/dist/lib/agent-pack.d.ts
CHANGED
|
@@ -2,6 +2,14 @@ import { type ImportedAgentProfile } from "./simple-agent-profile.js";
|
|
|
2
2
|
export declare const AGENT_PACK_MAX_FILES = 80;
|
|
3
3
|
export declare const AGENT_PACK_MAX_FILE_BYTES = 200000;
|
|
4
4
|
export declare const AGENT_PACK_MAX_TOTAL_BYTES = 2000000;
|
|
5
|
+
/** Extensions a single-file agent profile import can parse. */
|
|
6
|
+
export declare const AGENT_PROFILE_FILE_EXTENSIONS: readonly [".md", ".markdown", ".json", ".txt"];
|
|
7
|
+
/** Extensions an agent pack keeps; everything else in a folder is skipped. */
|
|
8
|
+
export declare const AGENT_PACK_FILE_EXTENSIONS: readonly [".md", ".markdown", ".json", ".txt", ".yaml", ".yml", ".csv", ".html", ".xml", ".toml", ".ts", ".tsx", ".js", ".mjs", ".py", ".sh"];
|
|
9
|
+
export declare const AGENT_PROFILE_FILE_ACCEPT: string;
|
|
10
|
+
export declare const AGENT_PACK_FILE_ACCEPT: string;
|
|
11
|
+
export declare function isImportableAgentProfileFile(path: string): boolean;
|
|
12
|
+
export declare function isImportableAgentPackFile(path: string): boolean;
|
|
5
13
|
export interface AgentPackFileInput {
|
|
6
14
|
path: string;
|
|
7
15
|
content: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-pack.d.ts","sourceRoot":"","sources":["../../src/lib/agent-pack.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,yBAAyB,SAAU,CAAC;AACjD,eAAO,MAAM,0BAA0B,UAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-pack.d.ts","sourceRoot":"","sources":["../../src/lib/agent-pack.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,yBAAyB,SAAU,CAAC;AACjD,eAAO,MAAM,0BAA0B,UAAY,CAAC;AAEpD,+DAA+D;AAC/D,eAAO,MAAM,6BAA6B,YACxC,KAAK,EACL,WAAW,EACX,OAAO,EACP,MAAM,CACE,CAAC;AAEX,8EAA8E;AAC9E,eAAO,MAAM,0BAA0B,+IAc7B,CAAC;AAEX,eAAO,MAAM,yBAAyB,QACG,CAAC;AAC1C,eAAO,MAAM,sBAAsB,QAAuC,CAAC;AAO3E,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/D;AAWD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,WAAW,EAAE,kBAAkB,CAAC;IAChC,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACjC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAkFD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,kBAAkB,EAAE,GAC/B,mBAAmB,CAkFrB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,OAAO,EAAE,oBAAoB,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAST;AAED,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAE7D"}
|
package/dist/lib/agent-pack.js
CHANGED
|
@@ -3,6 +3,41 @@ import { buildSimpleAgentContent, normalizeImportedAgent, slugifyAgentName, } fr
|
|
|
3
3
|
export const AGENT_PACK_MAX_FILES = 80;
|
|
4
4
|
export const AGENT_PACK_MAX_FILE_BYTES = 200_000;
|
|
5
5
|
export const AGENT_PACK_MAX_TOTAL_BYTES = 2_000_000;
|
|
6
|
+
/** Extensions a single-file agent profile import can parse. */
|
|
7
|
+
export const AGENT_PROFILE_FILE_EXTENSIONS = [
|
|
8
|
+
".md",
|
|
9
|
+
".markdown",
|
|
10
|
+
".json",
|
|
11
|
+
".txt",
|
|
12
|
+
];
|
|
13
|
+
/** Extensions an agent pack keeps; everything else in a folder is skipped. */
|
|
14
|
+
export const AGENT_PACK_FILE_EXTENSIONS = [
|
|
15
|
+
...AGENT_PROFILE_FILE_EXTENSIONS,
|
|
16
|
+
".yaml",
|
|
17
|
+
".yml",
|
|
18
|
+
".csv",
|
|
19
|
+
".html",
|
|
20
|
+
".xml",
|
|
21
|
+
".toml",
|
|
22
|
+
".ts",
|
|
23
|
+
".tsx",
|
|
24
|
+
".js",
|
|
25
|
+
".mjs",
|
|
26
|
+
".py",
|
|
27
|
+
".sh",
|
|
28
|
+
];
|
|
29
|
+
export const AGENT_PROFILE_FILE_ACCEPT = AGENT_PROFILE_FILE_EXTENSIONS.join(",");
|
|
30
|
+
export const AGENT_PACK_FILE_ACCEPT = AGENT_PACK_FILE_EXTENSIONS.join(",");
|
|
31
|
+
function hasExtension(path, extensions) {
|
|
32
|
+
const name = path.replaceAll("\\", "/").split("/").pop()?.toLowerCase() ?? "";
|
|
33
|
+
return extensions.some((extension) => name.endsWith(extension));
|
|
34
|
+
}
|
|
35
|
+
export function isImportableAgentProfileFile(path) {
|
|
36
|
+
return hasExtension(path, AGENT_PROFILE_FILE_EXTENSIONS);
|
|
37
|
+
}
|
|
38
|
+
export function isImportableAgentPackFile(path) {
|
|
39
|
+
return hasExtension(path, AGENT_PACK_FILE_EXTENSIONS);
|
|
40
|
+
}
|
|
6
41
|
const IGNORED_PACK_FILES = new Set([
|
|
7
42
|
".ds_store",
|
|
8
43
|
".git",
|
|
@@ -96,6 +131,9 @@ export function normalizeAgentPack(inputFiles) {
|
|
|
96
131
|
if (typeof file.content !== "string") {
|
|
97
132
|
throw new Error(`Agent pack file is not text: ${path}`);
|
|
98
133
|
}
|
|
134
|
+
if (!isImportableAgentPackFile(path)) {
|
|
135
|
+
throw new Error(`Agent packs only accept text files (${AGENT_PACK_FILE_EXTENSIONS.join(", ")}). Remove ${path}.`);
|
|
136
|
+
}
|
|
99
137
|
const size = Buffer.byteLength(file.content, "utf8");
|
|
100
138
|
if (size > AGENT_PACK_MAX_FILE_BYTES) {
|
|
101
139
|
throw new Error(`${path} is too large. Keep text files under ${Math.round(AGENT_PACK_MAX_FILE_BYTES / 1024)} KB.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-pack.js","sourceRoot":"","sources":["../../src/lib/agent-pack.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n parseFrontmatter,\n parseSkillMetadata,\n} from \"@agent-native/core/resources/metadata\";\n\nimport {\n buildSimpleAgentContent,\n normalizeImportedAgent,\n slugifyAgentName,\n type ImportedAgentProfile,\n} from \"./simple-agent-profile.js\";\n\nexport const AGENT_PACK_MAX_FILES = 80;\nexport const AGENT_PACK_MAX_FILE_BYTES = 200_000;\nexport const AGENT_PACK_MAX_TOTAL_BYTES = 2_000_000;\n\nconst IGNORED_PACK_FILES = new Set([\n \".ds_store\",\n \".git\",\n \".gitignore\",\n \".env\",\n \".env.local\",\n \"node_modules\",\n]);\n\nexport interface AgentPackFileInput {\n path: string;\n content: string;\n}\n\nexport interface NormalizedAgentPackFile {\n path: string;\n content: string;\n name: string;\n description?: string;\n kind: \"agent-file\" | \"skill\";\n}\n\nexport interface NormalizedAgentPack {\n profile: ImportedAgentProfile;\n profileFile: AgentPackFileInput;\n files: NormalizedAgentPackFile[];\n warnings: string[];\n totalBytes: number;\n}\n\nfunction normalizePackPath(value: string): string {\n const normalized = value\n .replaceAll(\"\\\\\", \"/\")\n .split(\"/\")\n .filter((part) => part && part !== \".\")\n .join(\"/\")\n .trim();\n if (!normalized || normalized.startsWith(\"/\") || normalized.includes(\"..\")) {\n throw new Error(`Invalid agent pack path: ${value}`);\n }\n if (normalized.length > 240) {\n throw new Error(`Agent pack path is too long: ${value}`);\n }\n return normalized;\n}\n\nfunction shouldIgnorePackPath(path: string): boolean {\n return path\n .split(\"/\")\n .some((part) => IGNORED_PACK_FILES.has(part.toLowerCase()));\n}\n\nfunction commonRoot(paths: string[]): string {\n const firstParts = paths.map((path) => path.split(\"/\")[0]);\n if (\n firstParts.length < 2 ||\n !firstParts.every((part) => part === firstParts[0])\n ) {\n return \"\";\n }\n const root = firstParts[0];\n if (\n !root ||\n [\"skills\", \"context\", \"references\", \"files\", \"scripts\"].includes(root)\n ) {\n return \"\";\n }\n return root;\n}\n\nfunction stripCommonRoot(files: AgentPackFileInput[]): AgentPackFileInput[] {\n const root = commonRoot(files.map((file) => normalizePackPath(file.path)));\n if (!root) return files;\n return files.map((file) => ({\n ...file,\n path: normalizePackPath(file.path).slice(root.length + 1),\n }));\n}\n\nfunction profileScore(file: AgentPackFileInput): number {\n const name = file.path.split(\"/\").pop()?.toLowerCase() || \"\";\n if ([\"agent.md\", \"agent.json\", \"profile.md\"].includes(name)) return 100;\n if ([\"agents.md\", \"claude.md\", \"instructions.md\"].includes(name)) return 90;\n if (name.endsWith(\".md\")) return 50;\n if (name.endsWith(\".json\")) return 40;\n return 0;\n}\n\nfunction fileDescription(file: AgentPackFileInput): string | undefined {\n const frontmatter = parseFrontmatter(file.content);\n const description = frontmatter?.fields.find(\n (field) => field.key === \"description\",\n )?.value;\n if (description?.trim()) return description.trim();\n const heading = file.content.match(/^#\\s+(.+)$/m)?.[1]?.trim();\n return heading || undefined;\n}\n\nfunction fileName(path: string): string {\n return path.split(\"/\").pop() || path;\n}\n\nfunction isSkillFile(path: string): boolean {\n return (\n path.startsWith(\"skills/\") &&\n path.endsWith(\".md\") &&\n (path.endsWith(\"/SKILL.md\") || !path.slice(\"skills/\".length).includes(\"/\"))\n );\n}\n\nexport function normalizeAgentPack(\n inputFiles: AgentPackFileInput[],\n): NormalizedAgentPack {\n if (inputFiles.length === 0) {\n throw new Error(\"Choose an agent file or folder with at least one file.\");\n }\n if (inputFiles.length > AGENT_PACK_MAX_FILES) {\n throw new Error(\n `Agent packs can contain at most ${AGENT_PACK_MAX_FILES} files.`,\n );\n }\n\n const files = stripCommonRoot(\n inputFiles.map((file) => {\n const path = normalizePackPath(file.path);\n if (shouldIgnorePackPath(path)) {\n throw new Error(\n `Remove ignored or private path from the pack: ${path}`,\n );\n }\n if (typeof file.content !== \"string\") {\n throw new Error(`Agent pack file is not text: ${path}`);\n }\n const size = Buffer.byteLength(file.content, \"utf8\");\n if (size > AGENT_PACK_MAX_FILE_BYTES) {\n throw new Error(\n `${path} is too large. Keep text files under ${Math.round(AGENT_PACK_MAX_FILE_BYTES / 1024)} KB.`,\n );\n }\n return { path, content: file.content };\n }),\n );\n\n const totalBytes = files.reduce(\n (total, file) => total + Buffer.byteLength(file.content, \"utf8\"),\n 0,\n );\n if (totalBytes > AGENT_PACK_MAX_TOTAL_BYTES) {\n throw new Error(\n `Agent packs can contain at most ${Math.round(AGENT_PACK_MAX_TOTAL_BYTES / 1_000_000)} MB of text.`,\n );\n }\n\n const profileFile = [...files]\n .filter((file) => profileScore(file) > 0)\n .sort(\n (a, b) =>\n profileScore(b) - profileScore(a) || a.path.localeCompare(b.path),\n )[0];\n if (!profileFile) {\n throw new Error(\n \"An agent pack needs an agent.md, CLAUDE.md, or Markdown profile file.\",\n );\n }\n\n const profile = normalizeImportedAgent(profileFile.content, profileFile.path);\n const warnings: string[] = [...profile.warnings];\n const packFiles = files\n .filter((file) => file !== profileFile)\n .map((file): NormalizedAgentPackFile => {\n const skill = isSkillFile(file.path)\n ? parseSkillMetadata(file.content, file.path)\n : null;\n return {\n path: file.path,\n content: file.content,\n name: skill?.name || fileName(file.path),\n description: skill?.description || fileDescription(file),\n kind: skill ? \"skill\" : \"agent-file\",\n };\n });\n\n if (packFiles.length === 0) {\n warnings.push(\n \"This pack contains only the profile; add files under context/ or skills/ when needed.\",\n );\n }\n\n return { profile, profileFile, files: packFiles, warnings, totalBytes };\n}\n\nexport function agentPackProfileContent(input: {\n profile: ImportedAgentProfile;\n tools?: string;\n sourceHash?: string;\n importedAt?: string;\n}): string {\n return buildSimpleAgentContent({\n ...input.profile,\n tools: input.tools,\n source: input.profile.source,\n sourcePath: input.profile.sourcePath,\n sourceHash: input.sourceHash,\n importedAt: input.importedAt,\n });\n}\n\nexport function agentPackRoot(agentNameOrSlug: string): string {\n return `agents/${slugifyAgentName(agentNameOrSlug)}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent-pack.js","sourceRoot":"","sources":["../../src/lib/agent-pack.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n parseFrontmatter,\n parseSkillMetadata,\n} from \"@agent-native/core/resources/metadata\";\n\nimport {\n buildSimpleAgentContent,\n normalizeImportedAgent,\n slugifyAgentName,\n type ImportedAgentProfile,\n} from \"./simple-agent-profile.js\";\n\nexport const AGENT_PACK_MAX_FILES = 80;\nexport const AGENT_PACK_MAX_FILE_BYTES = 200_000;\nexport const AGENT_PACK_MAX_TOTAL_BYTES = 2_000_000;\n\n/** Extensions a single-file agent profile import can parse. */\nexport const AGENT_PROFILE_FILE_EXTENSIONS = [\n \".md\",\n \".markdown\",\n \".json\",\n \".txt\",\n] as const;\n\n/** Extensions an agent pack keeps; everything else in a folder is skipped. */\nexport const AGENT_PACK_FILE_EXTENSIONS = [\n ...AGENT_PROFILE_FILE_EXTENSIONS,\n \".yaml\",\n \".yml\",\n \".csv\",\n \".html\",\n \".xml\",\n \".toml\",\n \".ts\",\n \".tsx\",\n \".js\",\n \".mjs\",\n \".py\",\n \".sh\",\n] as const;\n\nexport const AGENT_PROFILE_FILE_ACCEPT =\n AGENT_PROFILE_FILE_EXTENSIONS.join(\",\");\nexport const AGENT_PACK_FILE_ACCEPT = AGENT_PACK_FILE_EXTENSIONS.join(\",\");\n\nfunction hasExtension(path: string, extensions: readonly string[]): boolean {\n const name = path.replaceAll(\"\\\\\", \"/\").split(\"/\").pop()?.toLowerCase() ?? \"\";\n return extensions.some((extension) => name.endsWith(extension));\n}\n\nexport function isImportableAgentProfileFile(path: string): boolean {\n return hasExtension(path, AGENT_PROFILE_FILE_EXTENSIONS);\n}\n\nexport function isImportableAgentPackFile(path: string): boolean {\n return hasExtension(path, AGENT_PACK_FILE_EXTENSIONS);\n}\n\nconst IGNORED_PACK_FILES = new Set([\n \".ds_store\",\n \".git\",\n \".gitignore\",\n \".env\",\n \".env.local\",\n \"node_modules\",\n]);\n\nexport interface AgentPackFileInput {\n path: string;\n content: string;\n}\n\nexport interface NormalizedAgentPackFile {\n path: string;\n content: string;\n name: string;\n description?: string;\n kind: \"agent-file\" | \"skill\";\n}\n\nexport interface NormalizedAgentPack {\n profile: ImportedAgentProfile;\n profileFile: AgentPackFileInput;\n files: NormalizedAgentPackFile[];\n warnings: string[];\n totalBytes: number;\n}\n\nfunction normalizePackPath(value: string): string {\n const normalized = value\n .replaceAll(\"\\\\\", \"/\")\n .split(\"/\")\n .filter((part) => part && part !== \".\")\n .join(\"/\")\n .trim();\n if (!normalized || normalized.startsWith(\"/\") || normalized.includes(\"..\")) {\n throw new Error(`Invalid agent pack path: ${value}`);\n }\n if (normalized.length > 240) {\n throw new Error(`Agent pack path is too long: ${value}`);\n }\n return normalized;\n}\n\nfunction shouldIgnorePackPath(path: string): boolean {\n return path\n .split(\"/\")\n .some((part) => IGNORED_PACK_FILES.has(part.toLowerCase()));\n}\n\nfunction commonRoot(paths: string[]): string {\n const firstParts = paths.map((path) => path.split(\"/\")[0]);\n if (\n firstParts.length < 2 ||\n !firstParts.every((part) => part === firstParts[0])\n ) {\n return \"\";\n }\n const root = firstParts[0];\n if (\n !root ||\n [\"skills\", \"context\", \"references\", \"files\", \"scripts\"].includes(root)\n ) {\n return \"\";\n }\n return root;\n}\n\nfunction stripCommonRoot(files: AgentPackFileInput[]): AgentPackFileInput[] {\n const root = commonRoot(files.map((file) => normalizePackPath(file.path)));\n if (!root) return files;\n return files.map((file) => ({\n ...file,\n path: normalizePackPath(file.path).slice(root.length + 1),\n }));\n}\n\nfunction profileScore(file: AgentPackFileInput): number {\n const name = file.path.split(\"/\").pop()?.toLowerCase() || \"\";\n if ([\"agent.md\", \"agent.json\", \"profile.md\"].includes(name)) return 100;\n if ([\"agents.md\", \"claude.md\", \"instructions.md\"].includes(name)) return 90;\n if (name.endsWith(\".md\")) return 50;\n if (name.endsWith(\".json\")) return 40;\n return 0;\n}\n\nfunction fileDescription(file: AgentPackFileInput): string | undefined {\n const frontmatter = parseFrontmatter(file.content);\n const description = frontmatter?.fields.find(\n (field) => field.key === \"description\",\n )?.value;\n if (description?.trim()) return description.trim();\n const heading = file.content.match(/^#\\s+(.+)$/m)?.[1]?.trim();\n return heading || undefined;\n}\n\nfunction fileName(path: string): string {\n return path.split(\"/\").pop() || path;\n}\n\nfunction isSkillFile(path: string): boolean {\n return (\n path.startsWith(\"skills/\") &&\n path.endsWith(\".md\") &&\n (path.endsWith(\"/SKILL.md\") || !path.slice(\"skills/\".length).includes(\"/\"))\n );\n}\n\nexport function normalizeAgentPack(\n inputFiles: AgentPackFileInput[],\n): NormalizedAgentPack {\n if (inputFiles.length === 0) {\n throw new Error(\"Choose an agent file or folder with at least one file.\");\n }\n if (inputFiles.length > AGENT_PACK_MAX_FILES) {\n throw new Error(\n `Agent packs can contain at most ${AGENT_PACK_MAX_FILES} files.`,\n );\n }\n\n const files = stripCommonRoot(\n inputFiles.map((file) => {\n const path = normalizePackPath(file.path);\n if (shouldIgnorePackPath(path)) {\n throw new Error(\n `Remove ignored or private path from the pack: ${path}`,\n );\n }\n if (typeof file.content !== \"string\") {\n throw new Error(`Agent pack file is not text: ${path}`);\n }\n if (!isImportableAgentPackFile(path)) {\n throw new Error(\n `Agent packs only accept text files (${AGENT_PACK_FILE_EXTENSIONS.join(\", \")}). Remove ${path}.`,\n );\n }\n const size = Buffer.byteLength(file.content, \"utf8\");\n if (size > AGENT_PACK_MAX_FILE_BYTES) {\n throw new Error(\n `${path} is too large. Keep text files under ${Math.round(AGENT_PACK_MAX_FILE_BYTES / 1024)} KB.`,\n );\n }\n return { path, content: file.content };\n }),\n );\n\n const totalBytes = files.reduce(\n (total, file) => total + Buffer.byteLength(file.content, \"utf8\"),\n 0,\n );\n if (totalBytes > AGENT_PACK_MAX_TOTAL_BYTES) {\n throw new Error(\n `Agent packs can contain at most ${Math.round(AGENT_PACK_MAX_TOTAL_BYTES / 1_000_000)} MB of text.`,\n );\n }\n\n const profileFile = [...files]\n .filter((file) => profileScore(file) > 0)\n .sort(\n (a, b) =>\n profileScore(b) - profileScore(a) || a.path.localeCompare(b.path),\n )[0];\n if (!profileFile) {\n throw new Error(\n \"An agent pack needs an agent.md, CLAUDE.md, or Markdown profile file.\",\n );\n }\n\n const profile = normalizeImportedAgent(profileFile.content, profileFile.path);\n const warnings: string[] = [...profile.warnings];\n const packFiles = files\n .filter((file) => file !== profileFile)\n .map((file): NormalizedAgentPackFile => {\n const skill = isSkillFile(file.path)\n ? parseSkillMetadata(file.content, file.path)\n : null;\n return {\n path: file.path,\n content: file.content,\n name: skill?.name || fileName(file.path),\n description: skill?.description || fileDescription(file),\n kind: skill ? \"skill\" : \"agent-file\",\n };\n });\n\n if (packFiles.length === 0) {\n warnings.push(\n \"This pack contains only the profile; add files under context/ or skills/ when needed.\",\n );\n }\n\n return { profile, profileFile, files: packFiles, warnings, totalBytes };\n}\n\nexport function agentPackProfileContent(input: {\n profile: ImportedAgentProfile;\n tools?: string;\n sourceHash?: string;\n importedAt?: string;\n}): string {\n return buildSimpleAgentContent({\n ...input.profile,\n tools: input.tools,\n source: input.profile.source,\n sourcePath: input.profile.sourcePath,\n sourceHash: input.sourceHash,\n importedAt: input.importedAt,\n });\n}\n\nexport function agentPackRoot(agentNameOrSlug: string): string {\n return `agents/${slugifyAgentName(agentNameOrSlug)}`;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/dispatch",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.3-nightly-20260914215457",
|
|
4
4
|
"description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"tailwind-merge": "^3.5.0",
|
|
89
89
|
"vaul": "^1.1.2",
|
|
90
90
|
"zod": "^4.3.6",
|
|
91
|
-
"@agent-native/toolkit": "0.20.
|
|
91
|
+
"@agent-native/toolkit": "0.20.1-nightly-20260914215457"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@react-router/dev": "^8.1.0",
|
|
@@ -102,10 +102,10 @@
|
|
|
102
102
|
"typescript-7": "npm:typescript@^7.0.2",
|
|
103
103
|
"vite": "8.1.0",
|
|
104
104
|
"vitest": "^4.1.5",
|
|
105
|
-
"@agent-native/core": "0.179.
|
|
105
|
+
"@agent-native/core": "0.179.1-nightly-20260914215457"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|
|
108
|
-
"@agent-native/core": "
|
|
108
|
+
"@agent-native/core": "0.179.1-nightly-20260914215457",
|
|
109
109
|
"react": ">=19.2.7",
|
|
110
110
|
"react-dom": ">=19.2.7",
|
|
111
111
|
"react-router": ">=8"
|
|
@@ -3,10 +3,15 @@ import React, { act } from "react";
|
|
|
3
3
|
import { createRoot, type Root } from "react-dom/client";
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
5
|
|
|
6
|
+
import {
|
|
7
|
+
AGENT_PACK_FILE_ACCEPT,
|
|
8
|
+
AGENT_PROFILE_FILE_ACCEPT,
|
|
9
|
+
} from "../lib/agent-pack.js";
|
|
6
10
|
import {
|
|
7
11
|
handleAgentPackMutationSuccess,
|
|
8
12
|
isPendingWorkspaceResourceApproval,
|
|
9
13
|
SimpleAgentsPanel,
|
|
14
|
+
summarizeSkippedPackFiles,
|
|
10
15
|
} from "./simple-agents-panel";
|
|
11
16
|
|
|
12
17
|
const queryState = vi.hoisted(() => ({
|
|
@@ -108,6 +113,27 @@ describe("agent pack resource mutations", () => {
|
|
|
108
113
|
});
|
|
109
114
|
});
|
|
110
115
|
|
|
116
|
+
function fileInputs(): HTMLInputElement[] {
|
|
117
|
+
return Array.from(
|
|
118
|
+
document.body.querySelectorAll<HTMLInputElement>('input[type="file"]'),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function fileInputAccepts(): (string | null)[] {
|
|
123
|
+
return fileInputs().map((input) => input.getAttribute("accept"));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Radix tabs switch on mousedown, not click, and unmount inactive content.
|
|
127
|
+
function selectTab(label: string): void {
|
|
128
|
+
const tab = Array.from(
|
|
129
|
+
document.body.querySelectorAll<HTMLElement>('[role="tab"]'),
|
|
130
|
+
).find((candidate) => candidate.textContent?.includes(label));
|
|
131
|
+
if (!tab) throw new Error(`No tab matching ${label}`);
|
|
132
|
+
tab.dispatchEvent(
|
|
133
|
+
new MouseEvent("mousedown", { bubbles: true, cancelable: true, button: 0 }),
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
111
137
|
describe("SimpleAgentsPanel", () => {
|
|
112
138
|
let container: HTMLDivElement;
|
|
113
139
|
let root: Root;
|
|
@@ -150,4 +176,69 @@ describe("SimpleAgentsPanel", () => {
|
|
|
150
176
|
expect(document.body.textContent).toContain("Import an agent");
|
|
151
177
|
expect(document.body.textContent).toContain("Connect endpoint");
|
|
152
178
|
});
|
|
179
|
+
|
|
180
|
+
it("filters both import pickers to the file types the import logic parses", async () => {
|
|
181
|
+
await act(async () => {
|
|
182
|
+
root.render(<SimpleAgentsPanel />);
|
|
183
|
+
});
|
|
184
|
+
await act(async () => {
|
|
185
|
+
Array.from(container.querySelectorAll("button"))
|
|
186
|
+
.find((button) => button.textContent?.includes("Import or connect"))
|
|
187
|
+
?.click();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
expect(fileInputAccepts()).toEqual([AGENT_PROFILE_FILE_ACCEPT]);
|
|
191
|
+
|
|
192
|
+
await act(async () => {
|
|
193
|
+
selectTab("Agent folder");
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
expect(fileInputAccepts()).toEqual([AGENT_PACK_FILE_ACCEPT]);
|
|
197
|
+
expect(document.body.textContent).toContain("text files only");
|
|
198
|
+
for (const accept of fileInputAccepts()) {
|
|
199
|
+
expect(accept).not.toContain(".pdf");
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("opens a folder picker rather than a plain file picker", async () => {
|
|
204
|
+
await act(async () => {
|
|
205
|
+
root.render(<SimpleAgentsPanel />);
|
|
206
|
+
});
|
|
207
|
+
await act(async () => {
|
|
208
|
+
Array.from(container.querySelectorAll("button"))
|
|
209
|
+
.find((button) => button.textContent?.includes("Import or connect"))
|
|
210
|
+
?.click();
|
|
211
|
+
});
|
|
212
|
+
await act(async () => {
|
|
213
|
+
selectTab("Agent folder");
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const [folderInput] = fileInputs();
|
|
217
|
+
expect(folderInput?.hasAttribute("webkitdirectory")).toBe(true);
|
|
218
|
+
expect(folderInput?.hasAttribute("multiple")).toBe(true);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe("summarizeSkippedPackFiles", () => {
|
|
223
|
+
it("stays quiet when every file was importable", () => {
|
|
224
|
+
expect(summarizeSkippedPackFiles([], 4)).toEqual([]);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("names the skipped files without listing a whole photo folder", () => {
|
|
228
|
+
expect(summarizeSkippedPackFiles(["a.pdf"], 3)).toEqual([
|
|
229
|
+
"Skipped 1 non-text file: a.pdf.",
|
|
230
|
+
]);
|
|
231
|
+
expect(
|
|
232
|
+
summarizeSkippedPackFiles(
|
|
233
|
+
["a.pdf", "b.png", "c.zip", "d.mov", "e.psd"],
|
|
234
|
+
3,
|
|
235
|
+
),
|
|
236
|
+
).toEqual(["Skipped 5 non-text files: a.pdf, b.png, c.zip, and 2 more."]);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it("explains the empty result instead of a bare disabled button", () => {
|
|
240
|
+
expect(summarizeSkippedPackFiles(["a.pdf", "b.png"], 0)).toEqual([
|
|
241
|
+
"No importable files in that folder. Agent folders take text files such as Markdown, JSON, and YAML.",
|
|
242
|
+
]);
|
|
243
|
+
});
|
|
153
244
|
});
|
|
@@ -31,6 +31,13 @@ import {
|
|
|
31
31
|
import { useNavigate } from "react-router";
|
|
32
32
|
import { toast } from "sonner";
|
|
33
33
|
|
|
34
|
+
import {
|
|
35
|
+
AGENT_PACK_FILE_ACCEPT,
|
|
36
|
+
AGENT_PROFILE_FILE_ACCEPT,
|
|
37
|
+
AGENT_PROFILE_FILE_EXTENSIONS,
|
|
38
|
+
isImportableAgentPackFile,
|
|
39
|
+
isImportableAgentProfileFile,
|
|
40
|
+
} from "../lib/agent-pack.js";
|
|
34
41
|
import {
|
|
35
42
|
buildSimpleAgentContent,
|
|
36
43
|
slugifyAgentName,
|
|
@@ -109,6 +116,34 @@ interface AgentPackFileInput {
|
|
|
109
116
|
content: string;
|
|
110
117
|
}
|
|
111
118
|
|
|
119
|
+
const MAX_LISTED_SKIPPED_FILES = 3;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Folder pickers cannot filter by extension, so unsupported files are only
|
|
123
|
+
* visible after selection. Name them without turning a 40-file photo folder
|
|
124
|
+
* into a 40-line warning.
|
|
125
|
+
*/
|
|
126
|
+
export function summarizeSkippedPackFiles(
|
|
127
|
+
skipped: string[],
|
|
128
|
+
keptCount: number,
|
|
129
|
+
): string[] {
|
|
130
|
+
if (skipped.length === 0) return [];
|
|
131
|
+
if (keptCount === 0) {
|
|
132
|
+
return [
|
|
133
|
+
"No importable files in that folder. Agent folders take text files such as Markdown, JSON, and YAML.",
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
const listed = skipped.slice(0, MAX_LISTED_SKIPPED_FILES);
|
|
137
|
+
const remaining = skipped.length - listed.length;
|
|
138
|
+
const names =
|
|
139
|
+
remaining > 0
|
|
140
|
+
? `${listed.join(", ")}, and ${remaining} more`
|
|
141
|
+
: listed.join(", ");
|
|
142
|
+
return [
|
|
143
|
+
`Skipped ${skipped.length} non-text ${skipped.length === 1 ? "file" : "files"}: ${names}.`,
|
|
144
|
+
];
|
|
145
|
+
}
|
|
146
|
+
|
|
112
147
|
const AGENT_ICON_KEYS = [
|
|
113
148
|
"brain",
|
|
114
149
|
"users",
|
|
@@ -739,12 +774,6 @@ function ImportAgentDialog({ onImported }: { onImported?: () => void }) {
|
|
|
739
774
|
onError: (error) => toast.error(error.message),
|
|
740
775
|
});
|
|
741
776
|
|
|
742
|
-
useEffect(() => {
|
|
743
|
-
if (!folderRef.current) return;
|
|
744
|
-
folderRef.current.setAttribute("webkitdirectory", "");
|
|
745
|
-
folderRef.current.setAttribute("directory", "");
|
|
746
|
-
}, [mode, open]);
|
|
747
|
-
|
|
748
777
|
function reset() {
|
|
749
778
|
setMode("file");
|
|
750
779
|
setSource("");
|
|
@@ -760,24 +789,33 @@ function ImportAgentDialog({ onImported }: { onImported?: () => void }) {
|
|
|
760
789
|
|
|
761
790
|
async function handleFile(event: ChangeEvent<HTMLInputElement>) {
|
|
762
791
|
const file = event.target.files?.[0];
|
|
792
|
+
event.target.value = "";
|
|
763
793
|
if (!file) return;
|
|
794
|
+
// `accept` is only a picker hint: every OS dialog lets the user switch to
|
|
795
|
+
// "All Files", and reading a PDF with file.text() yields mojibake that
|
|
796
|
+
// looks like a valid definition.
|
|
797
|
+
if (!isImportableAgentProfileFile(file.name)) {
|
|
798
|
+
toast.error(
|
|
799
|
+
`${file.name} is not a supported agent file. Choose a ${AGENT_PROFILE_FILE_EXTENSIONS.join(", ")} file.`,
|
|
800
|
+
);
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
764
803
|
setFileName(file.name);
|
|
765
804
|
setSource(await file.text());
|
|
766
805
|
}
|
|
767
806
|
|
|
768
807
|
async function handleFolder(event: ChangeEvent<HTMLInputElement>) {
|
|
769
808
|
const selectedFiles = Array.from(event.target.files ?? []);
|
|
809
|
+
event.target.value = "";
|
|
770
810
|
if (selectedFiles.length === 0) return;
|
|
771
|
-
const
|
|
772
|
-
const textExtensions =
|
|
773
|
-
/\.(md|markdown|txt|json|yaml|yml|csv|html|xml|toml|ts|tsx|js|mjs|py|sh)$/i;
|
|
811
|
+
const skipped: string[] = [];
|
|
774
812
|
const pack = await Promise.all(
|
|
775
813
|
selectedFiles.map(async (file) => {
|
|
776
814
|
const path =
|
|
777
815
|
(file as File & { webkitRelativePath?: string }).webkitRelativePath ||
|
|
778
816
|
file.name;
|
|
779
|
-
if (!
|
|
780
|
-
|
|
817
|
+
if (!isImportableAgentPackFile(path)) {
|
|
818
|
+
skipped.push(path);
|
|
781
819
|
return null;
|
|
782
820
|
}
|
|
783
821
|
return { path, content: await file.text() };
|
|
@@ -788,7 +826,7 @@ function ImportAgentDialog({ onImported }: { onImported?: () => void }) {
|
|
|
788
826
|
);
|
|
789
827
|
setPackFiles(files);
|
|
790
828
|
setPackName(files[0]?.path.split("/")[0] || "Selected folder");
|
|
791
|
-
setPackWarnings(
|
|
829
|
+
setPackWarnings(summarizeSkippedPackFiles(skipped, files.length));
|
|
792
830
|
}
|
|
793
831
|
|
|
794
832
|
return (
|
|
@@ -837,7 +875,7 @@ function ImportAgentDialog({ onImported }: { onImported?: () => void }) {
|
|
|
837
875
|
<input
|
|
838
876
|
ref={fileRef}
|
|
839
877
|
type="file"
|
|
840
|
-
accept=
|
|
878
|
+
accept={AGENT_PROFILE_FILE_ACCEPT}
|
|
841
879
|
className="hidden"
|
|
842
880
|
onChange={(event) => void handleFile(event)}
|
|
843
881
|
/>
|
|
@@ -900,13 +938,24 @@ function ImportAgentDialog({ onImported }: { onImported?: () => void }) {
|
|
|
900
938
|
ref={folderRef}
|
|
901
939
|
type="file"
|
|
902
940
|
multiple
|
|
941
|
+
// Set declaratively: an effect keyed on the tab runs before
|
|
942
|
+
// Radix mounts this panel, so the ref is still null and the
|
|
943
|
+
// input silently stays a plain file picker.
|
|
944
|
+
{...({ webkitdirectory: "", directory: "" } as {
|
|
945
|
+
webkitdirectory: string;
|
|
946
|
+
directory: string;
|
|
947
|
+
})}
|
|
948
|
+
// Directory pickers ignore accept; it only applies where
|
|
949
|
+
// webkitdirectory is unsupported and this falls back to
|
|
950
|
+
// multi-file selection.
|
|
951
|
+
accept={AGENT_PACK_FILE_ACCEPT}
|
|
903
952
|
className="hidden"
|
|
904
953
|
onChange={(event) => void handleFolder(event)}
|
|
905
954
|
/>
|
|
906
955
|
<span className="text-xs text-muted-foreground">
|
|
907
956
|
{packName
|
|
908
957
|
? `${packName} · ${packFiles.length} files`
|
|
909
|
-
: "Claude Project or Cowork-style folder"}
|
|
958
|
+
: "Claude Project or Cowork-style folder · text files only"}
|
|
910
959
|
</span>
|
|
911
960
|
</div>
|
|
912
961
|
{packWarnings.length > 0 ? (
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
AGENT_PACK_FILE_ACCEPT,
|
|
5
|
+
AGENT_PROFILE_FILE_ACCEPT,
|
|
6
|
+
agentPackRoot,
|
|
7
|
+
isImportableAgentPackFile,
|
|
8
|
+
isImportableAgentProfileFile,
|
|
9
|
+
normalizeAgentPack,
|
|
10
|
+
} from "./agent-pack.js";
|
|
4
11
|
|
|
5
12
|
describe("agent packs", () => {
|
|
6
13
|
it("normalizes a folder into a profile, references, and skills", () => {
|
|
@@ -44,4 +51,60 @@ describe("agent packs", () => {
|
|
|
44
51
|
]),
|
|
45
52
|
).toThrow("ignored or private");
|
|
46
53
|
});
|
|
54
|
+
|
|
55
|
+
it("rejects a pack file the import logic cannot read as text", () => {
|
|
56
|
+
expect(() =>
|
|
57
|
+
normalizeAgentPack([
|
|
58
|
+
{ path: "agent.md", content: "# Agent" },
|
|
59
|
+
{ path: "references/6a42e3ab (1).pdf", content: "%PDF-1.4 ..." },
|
|
60
|
+
]),
|
|
61
|
+
).toThrow("only accept text files");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe("importable agent file types", () => {
|
|
66
|
+
it("accepts the profile formats the single-file import can parse", () => {
|
|
67
|
+
for (const path of [
|
|
68
|
+
"agent.md",
|
|
69
|
+
"AGENT.MARKDOWN",
|
|
70
|
+
"agent.json",
|
|
71
|
+
"notes.txt",
|
|
72
|
+
]) {
|
|
73
|
+
expect(isImportableAgentProfileFile(path)).toBe(true);
|
|
74
|
+
}
|
|
75
|
+
for (const path of ["scan (1).pdf", "logo.png", "agent.yaml", "agent"]) {
|
|
76
|
+
expect(isImportableAgentProfileFile(path)).toBe(false);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("accepts the wider text set a folder import keeps", () => {
|
|
81
|
+
for (const path of [
|
|
82
|
+
"skills/interviews/SKILL.md",
|
|
83
|
+
"context/config.yaml",
|
|
84
|
+
"scripts/run.sh",
|
|
85
|
+
"src/index.tsx",
|
|
86
|
+
]) {
|
|
87
|
+
expect(isImportableAgentPackFile(path)).toBe(true);
|
|
88
|
+
}
|
|
89
|
+
for (const path of [
|
|
90
|
+
"references/6a42e3ab (1).pdf",
|
|
91
|
+
"assets/cover.png",
|
|
92
|
+
"archive.zip",
|
|
93
|
+
]) {
|
|
94
|
+
expect(isImportableAgentPackFile(path)).toBe(false);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("keeps the picker accept filters in step with the parsers", () => {
|
|
99
|
+
expect(AGENT_PROFILE_FILE_ACCEPT).toBe(".md,.markdown,.json,.txt");
|
|
100
|
+
for (const extension of AGENT_PACK_FILE_ACCEPT.split(",")) {
|
|
101
|
+
expect(isImportableAgentPackFile(`example${extension}`)).toBe(true);
|
|
102
|
+
}
|
|
103
|
+
for (const extension of AGENT_PROFILE_FILE_ACCEPT.split(",")) {
|
|
104
|
+
expect(isImportableAgentProfileFile(`example${extension}`)).toBe(true);
|
|
105
|
+
expect(AGENT_PACK_FILE_ACCEPT).toContain(extension);
|
|
106
|
+
}
|
|
107
|
+
expect(AGENT_PROFILE_FILE_ACCEPT).not.toContain(".pdf");
|
|
108
|
+
expect(AGENT_PACK_FILE_ACCEPT).not.toContain(".pdf");
|
|
109
|
+
});
|
|
47
110
|
});
|
package/src/lib/agent-pack.ts
CHANGED
|
@@ -14,6 +14,48 @@ export const AGENT_PACK_MAX_FILES = 80;
|
|
|
14
14
|
export const AGENT_PACK_MAX_FILE_BYTES = 200_000;
|
|
15
15
|
export const AGENT_PACK_MAX_TOTAL_BYTES = 2_000_000;
|
|
16
16
|
|
|
17
|
+
/** Extensions a single-file agent profile import can parse. */
|
|
18
|
+
export const AGENT_PROFILE_FILE_EXTENSIONS = [
|
|
19
|
+
".md",
|
|
20
|
+
".markdown",
|
|
21
|
+
".json",
|
|
22
|
+
".txt",
|
|
23
|
+
] as const;
|
|
24
|
+
|
|
25
|
+
/** Extensions an agent pack keeps; everything else in a folder is skipped. */
|
|
26
|
+
export const AGENT_PACK_FILE_EXTENSIONS = [
|
|
27
|
+
...AGENT_PROFILE_FILE_EXTENSIONS,
|
|
28
|
+
".yaml",
|
|
29
|
+
".yml",
|
|
30
|
+
".csv",
|
|
31
|
+
".html",
|
|
32
|
+
".xml",
|
|
33
|
+
".toml",
|
|
34
|
+
".ts",
|
|
35
|
+
".tsx",
|
|
36
|
+
".js",
|
|
37
|
+
".mjs",
|
|
38
|
+
".py",
|
|
39
|
+
".sh",
|
|
40
|
+
] as const;
|
|
41
|
+
|
|
42
|
+
export const AGENT_PROFILE_FILE_ACCEPT =
|
|
43
|
+
AGENT_PROFILE_FILE_EXTENSIONS.join(",");
|
|
44
|
+
export const AGENT_PACK_FILE_ACCEPT = AGENT_PACK_FILE_EXTENSIONS.join(",");
|
|
45
|
+
|
|
46
|
+
function hasExtension(path: string, extensions: readonly string[]): boolean {
|
|
47
|
+
const name = path.replaceAll("\\", "/").split("/").pop()?.toLowerCase() ?? "";
|
|
48
|
+
return extensions.some((extension) => name.endsWith(extension));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isImportableAgentProfileFile(path: string): boolean {
|
|
52
|
+
return hasExtension(path, AGENT_PROFILE_FILE_EXTENSIONS);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isImportableAgentPackFile(path: string): boolean {
|
|
56
|
+
return hasExtension(path, AGENT_PACK_FILE_EXTENSIONS);
|
|
57
|
+
}
|
|
58
|
+
|
|
17
59
|
const IGNORED_PACK_FILES = new Set([
|
|
18
60
|
".ds_store",
|
|
19
61
|
".git",
|
|
@@ -147,6 +189,11 @@ export function normalizeAgentPack(
|
|
|
147
189
|
if (typeof file.content !== "string") {
|
|
148
190
|
throw new Error(`Agent pack file is not text: ${path}`);
|
|
149
191
|
}
|
|
192
|
+
if (!isImportableAgentPackFile(path)) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`Agent packs only accept text files (${AGENT_PACK_FILE_EXTENSIONS.join(", ")}). Remove ${path}.`,
|
|
195
|
+
);
|
|
196
|
+
}
|
|
150
197
|
const size = Buffer.byteLength(file.content, "utf8");
|
|
151
198
|
if (size > AGENT_PACK_MAX_FILE_BYTES) {
|
|
152
199
|
throw new Error(
|