@agent-native/dispatch 0.24.6 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/dist/actions/connect-external-agent.d.ts +18 -0
- package/dist/actions/connect-external-agent.d.ts.map +1 -0
- package/dist/actions/connect-external-agent.js +68 -0
- package/dist/actions/connect-external-agent.js.map +1 -0
- package/dist/actions/create-workspace-resource.d.ts +14 -14
- package/dist/actions/create-workspace-resource.js +9 -2
- package/dist/actions/create-workspace-resource.js.map +1 -1
- package/dist/actions/create_workspace_app_embed_session.d.ts +13 -0
- package/dist/actions/create_workspace_app_embed_session.d.ts.map +1 -0
- package/dist/actions/create_workspace_app_embed_session.js +30 -0
- package/dist/actions/create_workspace_app_embed_session.js.map +1 -0
- package/dist/actions/import-agent-pack.d.ts +96 -0
- package/dist/actions/import-agent-pack.d.ts.map +1 -0
- package/dist/actions/import-agent-pack.js +116 -0
- package/dist/actions/import-agent-pack.js.map +1 -0
- package/dist/actions/import-agent.d.ts +60 -0
- package/dist/actions/import-agent.d.ts.map +1 -0
- package/dist/actions/import-agent.js +82 -0
- package/dist/actions/import-agent.js.map +1 -0
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +10 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/list-agent-pack.d.ts +36 -0
- package/dist/actions/list-agent-pack.d.ts.map +1 -0
- package/dist/actions/list-agent-pack.js +32 -0
- package/dist/actions/list-agent-pack.js.map +1 -0
- package/dist/actions/list-workspace-resource-options.d.ts +1 -1
- package/dist/actions/list-workspace-resource-options.js +8 -1
- package/dist/actions/list-workspace-resource-options.js.map +1 -1
- package/dist/actions/list-workspace-resources.d.ts +1 -1
- package/dist/actions/list-workspace-resources.js +8 -1
- package/dist/actions/list-workspace-resources.js.map +1 -1
- package/dist/actions/navigate.js +1 -1
- package/dist/actions/navigate.js.map +1 -1
- package/dist/actions/provider-api-register.d.ts +10 -10
- package/dist/actions/update-workspace-resource.d.ts +13 -13
- package/dist/actions/view-screen.js +18 -1
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/layout/Layout.d.ts +1 -8
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +33 -106
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/simple-agents-panel.d.ts +9 -0
- package/dist/components/simple-agents-panel.d.ts.map +1 -0
- package/dist/components/simple-agents-panel.js +405 -0
- package/dist/components/simple-agents-panel.js.map +1 -0
- package/dist/components/workspace-app-host.d.ts +29 -0
- package/dist/components/workspace-app-host.d.ts.map +1 -0
- package/dist/components/workspace-app-host.js +145 -0
- package/dist/components/workspace-app-host.js.map +1 -0
- package/dist/db/migrations.d.ts +2 -4
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +25 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.js +1 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/hooks/use-navigation-state.d.ts +1 -0
- package/dist/hooks/use-navigation-state.d.ts.map +1 -1
- package/dist/hooks/use-navigation-state.js +10 -0
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/lib/agent-pack.d.ts +31 -0
- package/dist/lib/agent-pack.d.ts.map +1 -0
- package/dist/lib/agent-pack.js +149 -0
- package/dist/lib/agent-pack.js.map +1 -0
- package/dist/lib/simple-agent-profile.d.ts +36 -0
- package/dist/lib/simple-agent-profile.d.ts.map +1 -0
- package/dist/lib/simple-agent-profile.js +183 -0
- package/dist/lib/simple-agent-profile.js.map +1 -0
- package/dist/routes/pages/agents.d.ts.map +1 -1
- package/dist/routes/pages/agents.js +11 -1
- package/dist/routes/pages/agents.js.map +1 -1
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +4 -95
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/chat.d.ts.map +1 -1
- package/dist/routes/pages/chat.js +62 -10
- package/dist/routes/pages/chat.js.map +1 -1
- package/dist/server/lib/agent-pack-store.d.ts +24 -0
- package/dist/server/lib/agent-pack-store.d.ts.map +1 -0
- package/dist/server/lib/agent-pack-store.js +22 -0
- package/dist/server/lib/agent-pack-store.js.map +1 -0
- package/dist/server/lib/dispatch-store.d.ts.map +1 -1
- package/dist/server/lib/dispatch-store.js +4 -0
- package/dist/server/lib/dispatch-store.js.map +1 -1
- package/dist/server/lib/mcp-gateway.d.ts +11 -0
- package/dist/server/lib/mcp-gateway.d.ts.map +1 -1
- package/dist/server/lib/mcp-gateway.js +155 -9
- package/dist/server/lib/mcp-gateway.js.map +1 -1
- package/dist/server/lib/workspace-resources-store.d.ts +15 -1
- package/dist/server/lib/workspace-resources-store.d.ts.map +1 -1
- package/dist/server/lib/workspace-resources-store.js +11 -2
- package/dist/server/lib/workspace-resources-store.js.map +1 -1
- package/dist/server/plugins/agent-chat.js +13 -0
- package/dist/server/plugins/agent-chat.js.map +1 -1
- package/dist/shared/feature-flags.d.ts +7 -0
- package/dist/shared/feature-flags.d.ts.map +1 -0
- package/dist/shared/feature-flags.js +12 -0
- package/dist/shared/feature-flags.js.map +1 -0
- package/dist/shared/workspace-sso.d.ts +36 -0
- package/dist/shared/workspace-sso.d.ts.map +1 -0
- package/dist/shared/workspace-sso.js +99 -0
- package/dist/shared/workspace-sso.js.map +1 -0
- package/package.json +5 -3
- package/src/actions/connect-external-agent.ts +92 -0
- package/src/actions/create-workspace-resource.ts +9 -2
- package/src/actions/create_workspace_app_embed_session.ts +32 -0
- package/src/actions/import-agent-pack.ts +146 -0
- package/src/actions/import-agent.ts +102 -0
- package/src/actions/index.spec.ts +13 -0
- package/src/actions/index.ts +10 -0
- package/src/actions/list-agent-pack.ts +43 -0
- package/src/actions/list-workspace-resource-options.ts +8 -1
- package/src/actions/list-workspace-resources.ts +8 -1
- package/src/actions/navigate.ts +1 -1
- package/src/actions/view-screen.spec.ts +29 -1
- package/src/actions/view-screen.ts +19 -1
- package/src/components/app-icon.spec.tsx +10 -0
- package/src/components/index.ts +1 -0
- package/src/components/layout/Layout.spec.tsx +2 -0
- package/src/components/layout/Layout.tsx +59 -171
- package/src/components/simple-agents-panel.spec.tsx +73 -0
- package/src/components/simple-agents-panel.tsx +1226 -0
- package/src/components/workspace-app-host.spec.tsx +204 -0
- package/src/components/workspace-app-host.tsx +359 -0
- package/src/db/migrations.spec.ts +5 -1
- package/src/db/migrations.ts +28 -1
- package/src/db/schema.ts +1 -1
- package/src/hooks/use-navigation-state.spec.ts +25 -0
- package/src/hooks/use-navigation-state.ts +11 -0
- package/src/lib/agent-pack.spec.ts +47 -0
- package/src/lib/agent-pack.ts +226 -0
- package/src/lib/simple-agent-profile.spec.ts +77 -0
- package/src/lib/simple-agent-profile.ts +247 -0
- package/src/routes/index.spec.ts +1 -0
- package/src/routes/pages/agents.tsx +21 -1
- package/src/routes/pages/apps.$appId.tsx +3 -240
- package/src/routes/pages/chat.spec.tsx +62 -0
- package/src/routes/pages/chat.tsx +117 -9
- package/src/server/lib/agent-pack-store.ts +35 -0
- package/src/server/lib/dispatch-store.ts +8 -0
- package/src/server/lib/mcp-gateway.spec.ts +141 -0
- package/src/server/lib/mcp-gateway.ts +227 -15
- package/src/server/lib/workspace-resources-store.ts +9 -2
- package/src/server/plugins/agent-chat.ts +13 -0
- package/src/shared/feature-flags.ts +13 -0
- package/src/shared/workspace-sso.ts +118 -0
|
@@ -0,0 +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;AAWpD,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,CA6ErB;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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { parseFrontmatter, parseSkillMetadata, } from "@agent-native/core/resources/metadata";
|
|
2
|
+
import { buildSimpleAgentContent, normalizeImportedAgent, slugifyAgentName, } from "./simple-agent-profile.js";
|
|
3
|
+
export const AGENT_PACK_MAX_FILES = 80;
|
|
4
|
+
export const AGENT_PACK_MAX_FILE_BYTES = 200_000;
|
|
5
|
+
export const AGENT_PACK_MAX_TOTAL_BYTES = 2_000_000;
|
|
6
|
+
const IGNORED_PACK_FILES = new Set([
|
|
7
|
+
".ds_store",
|
|
8
|
+
".git",
|
|
9
|
+
".gitignore",
|
|
10
|
+
".env",
|
|
11
|
+
".env.local",
|
|
12
|
+
"node_modules",
|
|
13
|
+
]);
|
|
14
|
+
function normalizePackPath(value) {
|
|
15
|
+
const normalized = value
|
|
16
|
+
.replaceAll("\\", "/")
|
|
17
|
+
.split("/")
|
|
18
|
+
.filter((part) => part && part !== ".")
|
|
19
|
+
.join("/")
|
|
20
|
+
.trim();
|
|
21
|
+
if (!normalized || normalized.startsWith("/") || normalized.includes("..")) {
|
|
22
|
+
throw new Error(`Invalid agent pack path: ${value}`);
|
|
23
|
+
}
|
|
24
|
+
if (normalized.length > 240) {
|
|
25
|
+
throw new Error(`Agent pack path is too long: ${value}`);
|
|
26
|
+
}
|
|
27
|
+
return normalized;
|
|
28
|
+
}
|
|
29
|
+
function shouldIgnorePackPath(path) {
|
|
30
|
+
return path
|
|
31
|
+
.split("/")
|
|
32
|
+
.some((part) => IGNORED_PACK_FILES.has(part.toLowerCase()));
|
|
33
|
+
}
|
|
34
|
+
function commonRoot(paths) {
|
|
35
|
+
const firstParts = paths.map((path) => path.split("/")[0]);
|
|
36
|
+
if (firstParts.length < 2 ||
|
|
37
|
+
!firstParts.every((part) => part === firstParts[0])) {
|
|
38
|
+
return "";
|
|
39
|
+
}
|
|
40
|
+
const root = firstParts[0];
|
|
41
|
+
if (!root ||
|
|
42
|
+
["skills", "context", "references", "files", "scripts"].includes(root)) {
|
|
43
|
+
return "";
|
|
44
|
+
}
|
|
45
|
+
return root;
|
|
46
|
+
}
|
|
47
|
+
function stripCommonRoot(files) {
|
|
48
|
+
const root = commonRoot(files.map((file) => normalizePackPath(file.path)));
|
|
49
|
+
if (!root)
|
|
50
|
+
return files;
|
|
51
|
+
return files.map((file) => ({
|
|
52
|
+
...file,
|
|
53
|
+
path: normalizePackPath(file.path).slice(root.length + 1),
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
function profileScore(file) {
|
|
57
|
+
const name = file.path.split("/").pop()?.toLowerCase() || "";
|
|
58
|
+
if (["agent.md", "agent.json", "profile.md"].includes(name))
|
|
59
|
+
return 100;
|
|
60
|
+
if (["agents.md", "claude.md", "instructions.md"].includes(name))
|
|
61
|
+
return 90;
|
|
62
|
+
if (name.endsWith(".md"))
|
|
63
|
+
return 50;
|
|
64
|
+
if (name.endsWith(".json"))
|
|
65
|
+
return 40;
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
function fileDescription(file) {
|
|
69
|
+
const frontmatter = parseFrontmatter(file.content);
|
|
70
|
+
const description = frontmatter?.fields.find((field) => field.key === "description")?.value;
|
|
71
|
+
if (description?.trim())
|
|
72
|
+
return description.trim();
|
|
73
|
+
const heading = file.content.match(/^#\s+(.+)$/m)?.[1]?.trim();
|
|
74
|
+
return heading || undefined;
|
|
75
|
+
}
|
|
76
|
+
function fileName(path) {
|
|
77
|
+
return path.split("/").pop() || path;
|
|
78
|
+
}
|
|
79
|
+
function isSkillFile(path) {
|
|
80
|
+
return (path.startsWith("skills/") &&
|
|
81
|
+
path.endsWith(".md") &&
|
|
82
|
+
(path.endsWith("/SKILL.md") || !path.slice("skills/".length).includes("/")));
|
|
83
|
+
}
|
|
84
|
+
export function normalizeAgentPack(inputFiles) {
|
|
85
|
+
if (inputFiles.length === 0) {
|
|
86
|
+
throw new Error("Choose an agent file or folder with at least one file.");
|
|
87
|
+
}
|
|
88
|
+
if (inputFiles.length > AGENT_PACK_MAX_FILES) {
|
|
89
|
+
throw new Error(`Agent packs can contain at most ${AGENT_PACK_MAX_FILES} files.`);
|
|
90
|
+
}
|
|
91
|
+
const files = stripCommonRoot(inputFiles.map((file) => {
|
|
92
|
+
const path = normalizePackPath(file.path);
|
|
93
|
+
if (shouldIgnorePackPath(path)) {
|
|
94
|
+
throw new Error(`Remove ignored or private path from the pack: ${path}`);
|
|
95
|
+
}
|
|
96
|
+
if (typeof file.content !== "string") {
|
|
97
|
+
throw new Error(`Agent pack file is not text: ${path}`);
|
|
98
|
+
}
|
|
99
|
+
const size = Buffer.byteLength(file.content, "utf8");
|
|
100
|
+
if (size > AGENT_PACK_MAX_FILE_BYTES) {
|
|
101
|
+
throw new Error(`${path} is too large. Keep text files under ${Math.round(AGENT_PACK_MAX_FILE_BYTES / 1024)} KB.`);
|
|
102
|
+
}
|
|
103
|
+
return { path, content: file.content };
|
|
104
|
+
}));
|
|
105
|
+
const totalBytes = files.reduce((total, file) => total + Buffer.byteLength(file.content, "utf8"), 0);
|
|
106
|
+
if (totalBytes > AGENT_PACK_MAX_TOTAL_BYTES) {
|
|
107
|
+
throw new Error(`Agent packs can contain at most ${Math.round(AGENT_PACK_MAX_TOTAL_BYTES / 1_000_000)} MB of text.`);
|
|
108
|
+
}
|
|
109
|
+
const profileFile = [...files]
|
|
110
|
+
.filter((file) => profileScore(file) > 0)
|
|
111
|
+
.sort((a, b) => profileScore(b) - profileScore(a) || a.path.localeCompare(b.path))[0];
|
|
112
|
+
if (!profileFile) {
|
|
113
|
+
throw new Error("An agent pack needs an agent.md, CLAUDE.md, or Markdown profile file.");
|
|
114
|
+
}
|
|
115
|
+
const profile = normalizeImportedAgent(profileFile.content, profileFile.path);
|
|
116
|
+
const warnings = [...profile.warnings];
|
|
117
|
+
const packFiles = files
|
|
118
|
+
.filter((file) => file !== profileFile)
|
|
119
|
+
.map((file) => {
|
|
120
|
+
const skill = isSkillFile(file.path)
|
|
121
|
+
? parseSkillMetadata(file.content, file.path)
|
|
122
|
+
: null;
|
|
123
|
+
return {
|
|
124
|
+
path: file.path,
|
|
125
|
+
content: file.content,
|
|
126
|
+
name: skill?.name || fileName(file.path),
|
|
127
|
+
description: skill?.description || fileDescription(file),
|
|
128
|
+
kind: skill ? "skill" : "agent-file",
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
if (packFiles.length === 0) {
|
|
132
|
+
warnings.push("This pack contains only the profile; add files under context/ or skills/ when needed.");
|
|
133
|
+
}
|
|
134
|
+
return { profile, profileFile, files: packFiles, warnings, totalBytes };
|
|
135
|
+
}
|
|
136
|
+
export function agentPackProfileContent(input) {
|
|
137
|
+
return buildSimpleAgentContent({
|
|
138
|
+
...input.profile,
|
|
139
|
+
tools: input.tools,
|
|
140
|
+
source: input.profile.source,
|
|
141
|
+
sourcePath: input.profile.sourcePath,
|
|
142
|
+
sourceHash: input.sourceHash,
|
|
143
|
+
importedAt: input.importedAt,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
export function agentPackRoot(agentNameOrSlug) {
|
|
147
|
+
return `agents/${slugifyAgentName(agentNameOrSlug)}`;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=agent-pack.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface SimpleAgentProfileInput {
|
|
2
|
+
name: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
model?: string;
|
|
5
|
+
tools?: string;
|
|
6
|
+
instructions: string;
|
|
7
|
+
source?: string;
|
|
8
|
+
sourcePath?: string;
|
|
9
|
+
sourceHash?: string;
|
|
10
|
+
importedAt?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ImportedAgentProfile {
|
|
13
|
+
name: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
tools?: string;
|
|
17
|
+
instructions: string;
|
|
18
|
+
slug: string;
|
|
19
|
+
source: "markdown" | "claude" | "json";
|
|
20
|
+
sourcePath?: string;
|
|
21
|
+
warnings: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface ImportedAgentToolValidation {
|
|
24
|
+
tools?: string;
|
|
25
|
+
warnings: string[];
|
|
26
|
+
}
|
|
27
|
+
export declare function slugifyAgentName(value: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Imported tool names are descriptive input, not a permission grant. Keep only
|
|
30
|
+
* names the current Dispatch surface can resolve and make every omission
|
|
31
|
+
* visible to the caller instead of persisting a misleading tool list.
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateImportedAgentTools(tools: string | undefined, availableToolNames: ReadonlySet<string>): ImportedAgentToolValidation;
|
|
34
|
+
export declare function normalizeImportedAgent(source: string, fileName?: string): ImportedAgentProfile;
|
|
35
|
+
export declare function buildSimpleAgentContent(input: SimpleAgentProfileInput): string;
|
|
36
|
+
//# sourceMappingURL=simple-agent-profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-agent-profile.d.ts","sourceRoot":"","sources":["../../src/lib/simple-agent-profile.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAeD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQtD;AAsCD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,GACtC,2BAA2B,CAwB7B;AAqFD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAChB,oBAAoB,CAOtB;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,uBAAuB,GAC7B,MAAM,CAqBR"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { frontmatterFieldsToObject, parseFrontmatter, serializeFrontmatter, } from "@agent-native/core/resources/metadata";
|
|
2
|
+
const SUPPORTED_FIELDS = new Set([
|
|
3
|
+
"name",
|
|
4
|
+
"description",
|
|
5
|
+
"model",
|
|
6
|
+
"tools",
|
|
7
|
+
"color",
|
|
8
|
+
"delegate-default",
|
|
9
|
+
"source",
|
|
10
|
+
"source-path",
|
|
11
|
+
"source-hash",
|
|
12
|
+
"imported-at",
|
|
13
|
+
]);
|
|
14
|
+
export function slugifyAgentName(value) {
|
|
15
|
+
return (value
|
|
16
|
+
.trim()
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
19
|
+
.replace(/^-+|-+$/g, "") || "agent");
|
|
20
|
+
}
|
|
21
|
+
function deriveName(fileName) {
|
|
22
|
+
const baseName = fileName?.replaceAll("\\", "/").split("/").pop();
|
|
23
|
+
const name = baseName?.replace(/\.(md|markdown|json|txt)$/i, "");
|
|
24
|
+
return name?.trim() || "Imported agent";
|
|
25
|
+
}
|
|
26
|
+
function stringValue(value) {
|
|
27
|
+
if (typeof value !== "string")
|
|
28
|
+
return undefined;
|
|
29
|
+
const trimmed = value.trim();
|
|
30
|
+
return trimmed || undefined;
|
|
31
|
+
}
|
|
32
|
+
function toolsValue(value) {
|
|
33
|
+
if (Array.isArray(value)) {
|
|
34
|
+
const tools = value.filter((item) => typeof item === "string");
|
|
35
|
+
return tools.length > 0 ? tools.join(", ") : undefined;
|
|
36
|
+
}
|
|
37
|
+
return stringValue(value);
|
|
38
|
+
}
|
|
39
|
+
function normalizeToolKey(value) {
|
|
40
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, "");
|
|
41
|
+
}
|
|
42
|
+
function importedToolNames(value) {
|
|
43
|
+
const trimmed = value.trim();
|
|
44
|
+
if (!trimmed || trimmed.toLowerCase() === "inherit")
|
|
45
|
+
return [];
|
|
46
|
+
const unwrapped = trimmed.replace(/^\[|\]$/g, "");
|
|
47
|
+
return unwrapped
|
|
48
|
+
.split(/[\n,]/)
|
|
49
|
+
.map((tool) => tool.trim().replace(/^['"]|['"]$/g, ""))
|
|
50
|
+
.filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Imported tool names are descriptive input, not a permission grant. Keep only
|
|
54
|
+
* names the current Dispatch surface can resolve and make every omission
|
|
55
|
+
* visible to the caller instead of persisting a misleading tool list.
|
|
56
|
+
*/
|
|
57
|
+
export function validateImportedAgentTools(tools, availableToolNames) {
|
|
58
|
+
const names = importedToolNames(tools ?? "");
|
|
59
|
+
if (names.length === 0)
|
|
60
|
+
return { warnings: [] };
|
|
61
|
+
const resolvable = new Map();
|
|
62
|
+
for (const name of availableToolNames) {
|
|
63
|
+
resolvable.set(normalizeToolKey(name), name);
|
|
64
|
+
}
|
|
65
|
+
const mapped = [];
|
|
66
|
+
const warnings = [];
|
|
67
|
+
for (const name of names) {
|
|
68
|
+
const resolved = resolvable.get(normalizeToolKey(name));
|
|
69
|
+
if (resolved) {
|
|
70
|
+
if (!mapped.includes(resolved))
|
|
71
|
+
mapped.push(resolved);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
warnings.push(`Skipped unmapped tool: ${name}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
tools: mapped.length > 0 ? mapped.join(", ") : undefined,
|
|
79
|
+
warnings,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function markdownProfile(source, fileName) {
|
|
83
|
+
const frontmatter = parseFrontmatter(source);
|
|
84
|
+
const values = frontmatterFieldsToObject(frontmatter);
|
|
85
|
+
const body = (frontmatter?.body ?? source).trim();
|
|
86
|
+
const heading = body.match(/^#\s+(.+)$/m)?.[1]?.trim();
|
|
87
|
+
const name = stringValue(values.name) || heading || deriveName(fileName);
|
|
88
|
+
const warnings = Object.keys(values)
|
|
89
|
+
.filter((key) => !SUPPORTED_FIELDS.has(key))
|
|
90
|
+
.map((key) => `Ignored unsupported field: ${key}`);
|
|
91
|
+
if (!body)
|
|
92
|
+
warnings.push("The imported agent has no instructions yet.");
|
|
93
|
+
return {
|
|
94
|
+
name,
|
|
95
|
+
description: stringValue(values.description),
|
|
96
|
+
model: stringValue(values.model),
|
|
97
|
+
tools: toolsValue(values.tools),
|
|
98
|
+
instructions: body,
|
|
99
|
+
slug: slugifyAgentName(name),
|
|
100
|
+
source: fileName?.includes(".claude/") ? "claude" : "markdown",
|
|
101
|
+
sourcePath: fileName,
|
|
102
|
+
warnings,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function jsonProfile(source, fileName) {
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
parsed = JSON.parse(source);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
throw new Error("This file looks like JSON, but it is not valid JSON.");
|
|
112
|
+
}
|
|
113
|
+
const record = parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
114
|
+
? parsed
|
|
115
|
+
: null;
|
|
116
|
+
const candidate = record?.agent &&
|
|
117
|
+
typeof record.agent === "object" &&
|
|
118
|
+
!Array.isArray(record.agent)
|
|
119
|
+
? record.agent
|
|
120
|
+
: record;
|
|
121
|
+
if (!candidate) {
|
|
122
|
+
throw new Error("Import a single agent definition, not a JSON list.");
|
|
123
|
+
}
|
|
124
|
+
const name = stringValue(candidate.name) ||
|
|
125
|
+
stringValue(candidate.title) ||
|
|
126
|
+
deriveName(fileName);
|
|
127
|
+
const instructions = stringValue(candidate.instructions) ||
|
|
128
|
+
stringValue(candidate.systemPrompt) ||
|
|
129
|
+
stringValue(candidate.prompt) ||
|
|
130
|
+
stringValue(candidate.content) ||
|
|
131
|
+
"";
|
|
132
|
+
const warnings = [];
|
|
133
|
+
for (const key of ["hooks", "env", "environment", "command", "args", "cwd"]) {
|
|
134
|
+
if (candidate[key] !== undefined) {
|
|
135
|
+
warnings.push(`Skipped unsafe capability: ${key}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (!instructions)
|
|
139
|
+
warnings.push("The imported agent has no instructions yet.");
|
|
140
|
+
return {
|
|
141
|
+
name,
|
|
142
|
+
description: stringValue(candidate.description),
|
|
143
|
+
model: stringValue(candidate.model),
|
|
144
|
+
tools: toolsValue(candidate.tools),
|
|
145
|
+
instructions,
|
|
146
|
+
slug: slugifyAgentName(name),
|
|
147
|
+
source: "json",
|
|
148
|
+
sourcePath: fileName,
|
|
149
|
+
warnings,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export function normalizeImportedAgent(source, fileName) {
|
|
153
|
+
const trimmed = source.trim();
|
|
154
|
+
if (!trimmed)
|
|
155
|
+
throw new Error("Paste an agent definition or choose a file.");
|
|
156
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
157
|
+
return jsonProfile(trimmed, fileName);
|
|
158
|
+
}
|
|
159
|
+
return markdownProfile(trimmed, fileName);
|
|
160
|
+
}
|
|
161
|
+
export function buildSimpleAgentContent(input) {
|
|
162
|
+
const fields = [
|
|
163
|
+
{ key: "name", value: input.name.trim() },
|
|
164
|
+
...(input.description?.trim()
|
|
165
|
+
? [{ key: "description", value: input.description.trim() }]
|
|
166
|
+
: []),
|
|
167
|
+
{ key: "model", value: input.model?.trim() || "inherit" },
|
|
168
|
+
{ key: "tools", value: input.tools?.trim() || "inherit" },
|
|
169
|
+
{ key: "delegate-default", value: "false" },
|
|
170
|
+
...(input.source ? [{ key: "source", value: input.source }] : []),
|
|
171
|
+
...(input.sourcePath
|
|
172
|
+
? [{ key: "source-path", value: input.sourcePath }]
|
|
173
|
+
: []),
|
|
174
|
+
...(input.sourceHash
|
|
175
|
+
? [{ key: "source-hash", value: input.sourceHash }]
|
|
176
|
+
: []),
|
|
177
|
+
...(input.importedAt
|
|
178
|
+
? [{ key: "imported-at", value: input.importedAt }]
|
|
179
|
+
: []),
|
|
180
|
+
];
|
|
181
|
+
return `${serializeFrontmatter(fields)}${input.instructions.trim()}\n`;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=simple-agent-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-agent-profile.js","sourceRoot":"","sources":["../../src/lib/simple-agent-profile.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n frontmatterFieldsToObject,\n parseFrontmatter,\n serializeFrontmatter,\n} from \"@agent-native/core/resources/metadata\";\n\nexport interface SimpleAgentProfileInput {\n name: string;\n description?: string;\n model?: string;\n tools?: string;\n instructions: string;\n source?: string;\n sourcePath?: string;\n sourceHash?: string;\n importedAt?: string;\n}\n\nexport interface ImportedAgentProfile {\n name: string;\n description?: string;\n model?: string;\n tools?: string;\n instructions: string;\n slug: string;\n source: \"markdown\" | \"claude\" | \"json\";\n sourcePath?: string;\n warnings: string[];\n}\n\nexport interface ImportedAgentToolValidation {\n tools?: string;\n warnings: string[];\n}\n\nconst SUPPORTED_FIELDS = new Set([\n \"name\",\n \"description\",\n \"model\",\n \"tools\",\n \"color\",\n \"delegate-default\",\n \"source\",\n \"source-path\",\n \"source-hash\",\n \"imported-at\",\n]);\n\nexport function slugifyAgentName(value: string): string {\n return (\n value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"agent\"\n );\n}\n\nfunction deriveName(fileName?: string): string {\n const baseName = fileName?.replaceAll(\"\\\\\", \"/\").split(\"/\").pop();\n const name = baseName?.replace(/\\.(md|markdown|json|txt)$/i, \"\");\n return name?.trim() || \"Imported agent\";\n}\n\nfunction stringValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction toolsValue(value: unknown): string | undefined {\n if (Array.isArray(value)) {\n const tools = value.filter(\n (item): item is string => typeof item === \"string\",\n );\n return tools.length > 0 ? tools.join(\", \") : undefined;\n }\n return stringValue(value);\n}\n\nfunction normalizeToolKey(value: string): string {\n return value.toLowerCase().replace(/[^a-z0-9]+/g, \"\");\n}\n\nfunction importedToolNames(value: string): string[] {\n const trimmed = value.trim();\n if (!trimmed || trimmed.toLowerCase() === \"inherit\") return [];\n const unwrapped = trimmed.replace(/^\\[|\\]$/g, \"\");\n return unwrapped\n .split(/[\\n,]/)\n .map((tool) => tool.trim().replace(/^['\"]|['\"]$/g, \"\"))\n .filter(Boolean);\n}\n\n/**\n * Imported tool names are descriptive input, not a permission grant. Keep only\n * names the current Dispatch surface can resolve and make every omission\n * visible to the caller instead of persisting a misleading tool list.\n */\nexport function validateImportedAgentTools(\n tools: string | undefined,\n availableToolNames: ReadonlySet<string>,\n): ImportedAgentToolValidation {\n const names = importedToolNames(tools ?? \"\");\n if (names.length === 0) return { warnings: [] };\n\n const resolvable = new Map<string, string>();\n for (const name of availableToolNames) {\n resolvable.set(normalizeToolKey(name), name);\n }\n\n const mapped: string[] = [];\n const warnings: string[] = [];\n for (const name of names) {\n const resolved = resolvable.get(normalizeToolKey(name));\n if (resolved) {\n if (!mapped.includes(resolved)) mapped.push(resolved);\n } else {\n warnings.push(`Skipped unmapped tool: ${name}`);\n }\n }\n\n return {\n tools: mapped.length > 0 ? mapped.join(\", \") : undefined,\n warnings,\n };\n}\n\nfunction markdownProfile(\n source: string,\n fileName?: string,\n): Omit<ImportedAgentProfile, \"source\"> & {\n source: \"markdown\" | \"claude\";\n} {\n const frontmatter = parseFrontmatter(source);\n const values = frontmatterFieldsToObject(frontmatter);\n const body = (frontmatter?.body ?? source).trim();\n const heading = body.match(/^#\\s+(.+)$/m)?.[1]?.trim();\n const name = stringValue(values.name) || heading || deriveName(fileName);\n const warnings = Object.keys(values)\n .filter((key) => !SUPPORTED_FIELDS.has(key))\n .map((key) => `Ignored unsupported field: ${key}`);\n if (!body) warnings.push(\"The imported agent has no instructions yet.\");\n\n return {\n name,\n description: stringValue(values.description),\n model: stringValue(values.model),\n tools: toolsValue(values.tools),\n instructions: body,\n slug: slugifyAgentName(name),\n source: fileName?.includes(\".claude/\") ? \"claude\" : \"markdown\",\n sourcePath: fileName,\n warnings,\n };\n}\n\nfunction jsonProfile(source: string, fileName?: string): ImportedAgentProfile {\n let parsed: unknown;\n try {\n parsed = JSON.parse(source);\n } catch {\n throw new Error(\"This file looks like JSON, but it is not valid JSON.\");\n }\n\n const record =\n parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : null;\n const candidate =\n record?.agent &&\n typeof record.agent === \"object\" &&\n !Array.isArray(record.agent)\n ? (record.agent as Record<string, unknown>)\n : record;\n if (!candidate) {\n throw new Error(\"Import a single agent definition, not a JSON list.\");\n }\n\n const name =\n stringValue(candidate.name) ||\n stringValue(candidate.title) ||\n deriveName(fileName);\n const instructions =\n stringValue(candidate.instructions) ||\n stringValue(candidate.systemPrompt) ||\n stringValue(candidate.prompt) ||\n stringValue(candidate.content) ||\n \"\";\n const warnings: string[] = [];\n for (const key of [\"hooks\", \"env\", \"environment\", \"command\", \"args\", \"cwd\"]) {\n if (candidate[key] !== undefined) {\n warnings.push(`Skipped unsafe capability: ${key}`);\n }\n }\n if (!instructions)\n warnings.push(\"The imported agent has no instructions yet.\");\n\n return {\n name,\n description: stringValue(candidate.description),\n model: stringValue(candidate.model),\n tools: toolsValue(candidate.tools),\n instructions,\n slug: slugifyAgentName(name),\n source: \"json\",\n sourcePath: fileName,\n warnings,\n };\n}\n\nexport function normalizeImportedAgent(\n source: string,\n fileName?: string,\n): ImportedAgentProfile {\n const trimmed = source.trim();\n if (!trimmed) throw new Error(\"Paste an agent definition or choose a file.\");\n if (trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\")) {\n return jsonProfile(trimmed, fileName);\n }\n return markdownProfile(trimmed, fileName);\n}\n\nexport function buildSimpleAgentContent(\n input: SimpleAgentProfileInput,\n): string {\n const fields = [\n { key: \"name\", value: input.name.trim() },\n ...(input.description?.trim()\n ? [{ key: \"description\", value: input.description.trim() }]\n : []),\n { key: \"model\", value: input.model?.trim() || \"inherit\" },\n { key: \"tools\", value: input.tools?.trim() || \"inherit\" },\n { key: \"delegate-default\", value: \"false\" },\n ...(input.source ? [{ key: \"source\", value: input.source }] : []),\n ...(input.sourcePath\n ? [{ key: \"source-path\", value: input.sourcePath }]\n : []),\n ...(input.sourceHash\n ? [{ key: \"source-hash\", value: input.sourceHash }]\n : []),\n ...(input.importedAt\n ? [{ key: \"imported-at\", value: input.importedAt }]\n : []),\n ];\n return `${serializeFrontmatter(fields)}${input.instructions.trim()}\\n`;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/agents.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/agents.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,IAAI;;IAEnB;AAkND,MAAM,CAAC,OAAO,UAAU,WAAW,oDAgBlC"}
|
|
@@ -3,10 +3,12 @@ import { useActionMutation, useActionQuery, } from "@agent-native/core/client/ho
|
|
|
3
3
|
import { useT } from "@agent-native/core/client/i18n";
|
|
4
4
|
import { IconCheck, IconCopy, IconPlugConnected } from "@tabler/icons-react";
|
|
5
5
|
import { useMemo, useState } from "react";
|
|
6
|
+
import { useLocation } from "react-router";
|
|
6
7
|
import { toast } from "sonner";
|
|
7
8
|
import { ActionQueryError } from "../../components/action-query-error.js";
|
|
8
9
|
import { AgentsPanel, } from "../../components/agents-panel.js";
|
|
9
10
|
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
11
|
+
import { SimpleAgentsPanel } from "../../components/simple-agents-panel.js";
|
|
10
12
|
import { Button } from "../../components/ui/button.js";
|
|
11
13
|
import { Input } from "../../components/ui/input.js";
|
|
12
14
|
import { Skeleton } from "../../components/ui/skeleton.js";
|
|
@@ -78,9 +80,17 @@ function DispatchMcpAccessPanel() {
|
|
|
78
80
|
optimistic?.selectedAppIds.includes(app.id) !== isSelected, onClick: () => toggleApp(app.id), className: "flex min-h-[76px] items-start gap-3 rounded-xl border bg-muted/20 px-3 py-3 text-left transition hover:bg-muted/40 disabled:cursor-not-allowed disabled:opacity-60", "aria-pressed": isSelected, children: [_jsx("span", { className: "mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-xs font-bold text-white", style: { backgroundColor: app.color }, children: app.name.charAt(0).toUpperCase() }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [app.name, isSelected ? (_jsx(IconCheck, { size: 14, className: "text-emerald-500" })) : null] }), _jsx("span", { className: "mt-1 line-clamp-2 block text-xs text-muted-foreground", children: app.description || app.url })] })] }, app.id));
|
|
79
81
|
}) })) : null] }));
|
|
80
82
|
}
|
|
81
|
-
|
|
83
|
+
function ConnectedAgentsRoute() {
|
|
82
84
|
const t = useT();
|
|
83
85
|
const agentsQuery = useActionQuery("list-connected-agents", {});
|
|
84
86
|
return (_jsx(DispatchShell, { title: t("dispatch.nav.agents"), description: t("dispatch.pages.agentsDescription"), children: _jsxs("div", { className: "space-y-4", children: [_jsx(DispatchMcpAccessPanel, {}), agentsQuery.isError ? (_jsx(ActionQueryError, { error: agentsQuery.error, onRetry: () => void agentsQuery.refetch() })) : (_jsx(AgentsPanel, { agents: (agentsQuery.data || []), onRefresh: agentsQuery.refetch }))] }) }));
|
|
85
87
|
}
|
|
88
|
+
export default function AgentsRoute() {
|
|
89
|
+
const t = useT();
|
|
90
|
+
const location = useLocation();
|
|
91
|
+
if (!location.pathname.startsWith("/admin/agents")) {
|
|
92
|
+
return (_jsx(DispatchShell, { title: t("dispatch.nav.agents"), description: t("dispatch.pages.simpleAgentsDescription"), children: _jsx(SimpleAgentsPanel, {}) }));
|
|
93
|
+
}
|
|
94
|
+
return _jsx(ConnectedAgentsRoute, {});
|
|
95
|
+
}
|
|
86
96
|
//# sourceMappingURL=agents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../../src/routes/pages/agents.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { IconCheck, IconCopy, IconPlugConnected } from \"@tabler/icons-react\";\nimport { useMemo, useState } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport {\n AgentsPanel,\n type ConnectedAgent,\n} from \"../../components/agents-panel\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\nimport { Input } from \"../../components/ui/input\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { Switch } from \"../../components/ui/switch\";\n\nexport function meta() {\n return [{ title: \"Agents — Dispatch\" }];\n}\n\ninterface McpAccessApp {\n id: string;\n name: string;\n description: string;\n url: string;\n color: string;\n granted: boolean;\n}\n\ntype McpAccessMode = \"all-apps\" | \"selected-apps\";\n\ninterface McpAccessState {\n mode: McpAccessMode;\n selectedAppIds: string[];\n}\n\nfunction dispatchMcpUrl(): string {\n const path = \"/mcp\";\n if (typeof window === \"undefined\") return path;\n return new URL(path, window.location.origin).href;\n}\n\nfunction DispatchMcpAccessPanel() {\n const t = useT();\n const { data, isLoading, isError, error, refetch } = useActionQuery(\n \"list-mcp-app-access\",\n {},\n );\n const [optimistic, setOptimistic] = useState<McpAccessState | null>(null);\n const saveAccess = useActionMutation(\"set-mcp-app-access\", {\n onSuccess: () => {\n setOptimistic(null);\n toast.success(t(\"dispatch.pages.mcpAccessUpdated\"));\n },\n onError: (error) => {\n setOptimistic(null);\n toast.error(error.message);\n },\n });\n\n const apps = ((data as { apps?: McpAccessApp[] } | undefined)?.apps ??\n []) as McpAccessApp[];\n const access =\n optimistic ??\n ({\n mode: ((data as { mode?: McpAccessMode } | undefined)?.mode ??\n \"all-apps\") as McpAccessMode,\n selectedAppIds:\n (data as { selectedAppIds?: string[] } | undefined)?.selectedAppIds ??\n [],\n } satisfies McpAccessState);\n const selected = useMemo(\n () => new Set(access.selectedAppIds),\n [access.selectedAppIds],\n );\n const grantedCount =\n access.mode === \"all-apps\" ? apps.length : access.selectedAppIds.length;\n const mcpUrl = dispatchMcpUrl();\n\n function persist(next: McpAccessState) {\n setOptimistic(next);\n saveAccess.mutate(next);\n }\n\n function toggleApp(appId: string) {\n const next = selected.has(appId)\n ? access.selectedAppIds.filter((id) => id !== appId)\n : [...access.selectedAppIds, appId];\n persist({ mode: \"selected-apps\", selectedAppIds: next });\n }\n\n async function copyUrl() {\n try {\n await navigator.clipboard.writeText(mcpUrl);\n toast.success(t(\"dispatch.pages.mcpUrlCopied\"));\n } catch {\n toast.error(t(\"dispatch.pages.mcpUrlCopyFailed\"));\n }\n }\n\n return (\n <section className=\"rounded-2xl bg-card p-5\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2 text-sm font-medium text-foreground\">\n <IconPlugConnected size={16} />\n {t(\"dispatch.pages.unifiedMcpGateway\")}\n </div>\n <div className=\"mt-1 max-w-2xl text-sm text-muted-foreground\">\n {t(\"dispatch.pages.unifiedMcpGatewayDescription\")}{\" \"}\n <code>list_apps</code>, <code>ask_app</code>, and{\" \"}\n <code>open_app</code>.\n </div>\n </div>\n <div className=\"flex items-center gap-3 rounded-xl border px-3 py-2\">\n <div>\n <div className=\"text-xs font-medium text-foreground\">\n {access.mode === \"all-apps\"\n ? t(\"dispatch.pages.allApps\")\n : t(\"dispatch.pages.selectedApps\")}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {isLoading ? (\n <Skeleton className=\"h-3 w-16\" />\n ) : (\n t(\"dispatch.pages.grantedCount\", { count: grantedCount })\n )}\n </div>\n </div>\n <Switch\n checked={access.mode === \"all-apps\"}\n disabled={saveAccess.isPending || apps.length === 0}\n onCheckedChange={(checked) =>\n persist({\n mode: checked ? \"all-apps\" : \"selected-apps\",\n selectedAppIds: checked\n ? access.selectedAppIds\n : apps.map((app) => app.id),\n })\n }\n aria-label={t(\"dispatch.pages.exposeAllAppsMcp\")}\n />\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-col gap-2 sm:flex-row\">\n <Input readOnly value={mcpUrl} className=\"font-mono text-xs\" />\n <Button type=\"button\" variant=\"outline\" onClick={copyUrl}>\n <IconCopy size={15} />\n {t(\"dispatch.pages.copyUrl\")}\n </Button>\n </div>\n\n {isError ? (\n <ActionQueryError\n className=\"mt-4\"\n error={error}\n onRetry={() => void refetch()}\n />\n ) : access.mode === \"selected-apps\" ? (\n <div className=\"mt-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-3\">\n {apps.map((app) => {\n const isSelected = selected.has(app.id);\n return (\n <button\n key={app.id}\n type=\"button\"\n disabled={\n saveAccess.isPending &&\n optimistic?.selectedAppIds.includes(app.id) !== isSelected\n }\n onClick={() => toggleApp(app.id)}\n className=\"flex min-h-[76px] items-start gap-3 rounded-xl border bg-muted/20 px-3 py-3 text-left transition hover:bg-muted/40 disabled:cursor-not-allowed disabled:opacity-60\"\n aria-pressed={isSelected}\n >\n <span\n className=\"mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-xs font-bold text-white\"\n style={{ backgroundColor: app.color }}\n >\n {app.name.charAt(0).toUpperCase()}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-center gap-2 text-sm font-medium text-foreground\">\n {app.name}\n {isSelected ? (\n <IconCheck size={14} className=\"text-emerald-500\" />\n ) : null}\n </span>\n <span className=\"mt-1 line-clamp-2 block text-xs text-muted-foreground\">\n {app.description || app.url}\n </span>\n </span>\n </button>\n );\n })}\n </div>\n ) : null}\n </section>\n );\n}\n\nexport default function AgentsRoute() {\n const t = useT();\n const agentsQuery = useActionQuery(\"list-connected-agents\", {});\n\n return (\n <DispatchShell\n title={t(\"dispatch.nav.agents\")}\n description={t(\"dispatch.pages.agentsDescription\")}\n >\n <div className=\"space-y-4\">\n <DispatchMcpAccessPanel />\n {agentsQuery.isError ? (\n <ActionQueryError\n error={agentsQuery.error}\n onRetry={() => void agentsQuery.refetch()}\n />\n ) : (\n <AgentsPanel\n agents={(agentsQuery.data || []) as ConnectedAgent[]}\n onRefresh={agentsQuery.refetch}\n />\n )}\n </div>\n </DispatchShell>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../../src/routes/pages/agents.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { IconCheck, IconCopy, IconPlugConnected } from \"@tabler/icons-react\";\nimport { useMemo, useState } from \"react\";\nimport { useLocation } from \"react-router\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport {\n AgentsPanel,\n type ConnectedAgent,\n} from \"../../components/agents-panel\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { SimpleAgentsPanel } from \"../../components/simple-agents-panel\";\nimport { Button } from \"../../components/ui/button\";\nimport { Input } from \"../../components/ui/input\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { Switch } from \"../../components/ui/switch\";\n\nexport function meta() {\n return [{ title: \"Agents — Dispatch\" }];\n}\n\ninterface McpAccessApp {\n id: string;\n name: string;\n description: string;\n url: string;\n color: string;\n granted: boolean;\n}\n\ntype McpAccessMode = \"all-apps\" | \"selected-apps\";\n\ninterface McpAccessState {\n mode: McpAccessMode;\n selectedAppIds: string[];\n}\n\nfunction dispatchMcpUrl(): string {\n const path = \"/mcp\";\n if (typeof window === \"undefined\") return path;\n return new URL(path, window.location.origin).href;\n}\n\nfunction DispatchMcpAccessPanel() {\n const t = useT();\n const { data, isLoading, isError, error, refetch } = useActionQuery(\n \"list-mcp-app-access\",\n {},\n );\n const [optimistic, setOptimistic] = useState<McpAccessState | null>(null);\n const saveAccess = useActionMutation(\"set-mcp-app-access\", {\n onSuccess: () => {\n setOptimistic(null);\n toast.success(t(\"dispatch.pages.mcpAccessUpdated\"));\n },\n onError: (error) => {\n setOptimistic(null);\n toast.error(error.message);\n },\n });\n\n const apps = ((data as { apps?: McpAccessApp[] } | undefined)?.apps ??\n []) as McpAccessApp[];\n const access =\n optimistic ??\n ({\n mode: ((data as { mode?: McpAccessMode } | undefined)?.mode ??\n \"all-apps\") as McpAccessMode,\n selectedAppIds:\n (data as { selectedAppIds?: string[] } | undefined)?.selectedAppIds ??\n [],\n } satisfies McpAccessState);\n const selected = useMemo(\n () => new Set(access.selectedAppIds),\n [access.selectedAppIds],\n );\n const grantedCount =\n access.mode === \"all-apps\" ? apps.length : access.selectedAppIds.length;\n const mcpUrl = dispatchMcpUrl();\n\n function persist(next: McpAccessState) {\n setOptimistic(next);\n saveAccess.mutate(next);\n }\n\n function toggleApp(appId: string) {\n const next = selected.has(appId)\n ? access.selectedAppIds.filter((id) => id !== appId)\n : [...access.selectedAppIds, appId];\n persist({ mode: \"selected-apps\", selectedAppIds: next });\n }\n\n async function copyUrl() {\n try {\n await navigator.clipboard.writeText(mcpUrl);\n toast.success(t(\"dispatch.pages.mcpUrlCopied\"));\n } catch {\n toast.error(t(\"dispatch.pages.mcpUrlCopyFailed\"));\n }\n }\n\n return (\n <section className=\"rounded-2xl bg-card p-5\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2 text-sm font-medium text-foreground\">\n <IconPlugConnected size={16} />\n {t(\"dispatch.pages.unifiedMcpGateway\")}\n </div>\n <div className=\"mt-1 max-w-2xl text-sm text-muted-foreground\">\n {t(\"dispatch.pages.unifiedMcpGatewayDescription\")}{\" \"}\n <code>list_apps</code>, <code>ask_app</code>, and{\" \"}\n <code>open_app</code>.\n </div>\n </div>\n <div className=\"flex items-center gap-3 rounded-xl border px-3 py-2\">\n <div>\n <div className=\"text-xs font-medium text-foreground\">\n {access.mode === \"all-apps\"\n ? t(\"dispatch.pages.allApps\")\n : t(\"dispatch.pages.selectedApps\")}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {isLoading ? (\n <Skeleton className=\"h-3 w-16\" />\n ) : (\n t(\"dispatch.pages.grantedCount\", { count: grantedCount })\n )}\n </div>\n </div>\n <Switch\n checked={access.mode === \"all-apps\"}\n disabled={saveAccess.isPending || apps.length === 0}\n onCheckedChange={(checked) =>\n persist({\n mode: checked ? \"all-apps\" : \"selected-apps\",\n selectedAppIds: checked\n ? access.selectedAppIds\n : apps.map((app) => app.id),\n })\n }\n aria-label={t(\"dispatch.pages.exposeAllAppsMcp\")}\n />\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-col gap-2 sm:flex-row\">\n <Input readOnly value={mcpUrl} className=\"font-mono text-xs\" />\n <Button type=\"button\" variant=\"outline\" onClick={copyUrl}>\n <IconCopy size={15} />\n {t(\"dispatch.pages.copyUrl\")}\n </Button>\n </div>\n\n {isError ? (\n <ActionQueryError\n className=\"mt-4\"\n error={error}\n onRetry={() => void refetch()}\n />\n ) : access.mode === \"selected-apps\" ? (\n <div className=\"mt-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-3\">\n {apps.map((app) => {\n const isSelected = selected.has(app.id);\n return (\n <button\n key={app.id}\n type=\"button\"\n disabled={\n saveAccess.isPending &&\n optimistic?.selectedAppIds.includes(app.id) !== isSelected\n }\n onClick={() => toggleApp(app.id)}\n className=\"flex min-h-[76px] items-start gap-3 rounded-xl border bg-muted/20 px-3 py-3 text-left transition hover:bg-muted/40 disabled:cursor-not-allowed disabled:opacity-60\"\n aria-pressed={isSelected}\n >\n <span\n className=\"mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-xs font-bold text-white\"\n style={{ backgroundColor: app.color }}\n >\n {app.name.charAt(0).toUpperCase()}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-center gap-2 text-sm font-medium text-foreground\">\n {app.name}\n {isSelected ? (\n <IconCheck size={14} className=\"text-emerald-500\" />\n ) : null}\n </span>\n <span className=\"mt-1 line-clamp-2 block text-xs text-muted-foreground\">\n {app.description || app.url}\n </span>\n </span>\n </button>\n );\n })}\n </div>\n ) : null}\n </section>\n );\n}\n\nfunction ConnectedAgentsRoute() {\n const t = useT();\n const agentsQuery = useActionQuery(\"list-connected-agents\", {});\n\n return (\n <DispatchShell\n title={t(\"dispatch.nav.agents\")}\n description={t(\"dispatch.pages.agentsDescription\")}\n >\n <div className=\"space-y-4\">\n <DispatchMcpAccessPanel />\n {agentsQuery.isError ? (\n <ActionQueryError\n error={agentsQuery.error}\n onRetry={() => void agentsQuery.refetch()}\n />\n ) : (\n <AgentsPanel\n agents={(agentsQuery.data || []) as ConnectedAgent[]}\n onRefresh={agentsQuery.refetch}\n />\n )}\n </div>\n </DispatchShell>\n );\n}\n\nexport default function AgentsRoute() {\n const t = useT();\n const location = useLocation();\n\n if (!location.pathname.startsWith(\"/admin/agents\")) {\n return (\n <DispatchShell\n title={t(\"dispatch.nav.agents\")}\n description={t(\"dispatch.pages.simpleAgentsDescription\")}\n >\n <SimpleAgentsPanel />\n </DispatchShell>\n );\n }\n\n return <ConnectedAgentsRoute />;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.$appId.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/apps.$appId.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apps.$appId.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/apps.$appId.tsx"],"names":[],"mappings":"AAIA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB,oDAGxC"}
|