@happyvertical/smrt-agents 0.37.1 → 0.37.3

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.
@@ -1,173 +1,119 @@
1
- import { readFileSync, existsSync } from "node:fs";
1
+ import { n as extractAgentPackagesFromConfig } from "./chunks/manifest-utils-CtMyFQDx.js";
2
+ import { existsSync, readFileSync } from "node:fs";
2
3
  import { createRequire } from "node:module";
3
- import { resolve, dirname } from "node:path";
4
- import { e as extractAgentPackagesFromConfig } from "./chunks/manifest-utils-CMeEKwgq.js";
5
- const VIRTUAL_MODULE_ID = "virtual:smrt-agent-registrations";
6
- const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
4
+ import { dirname, resolve } from "node:path";
5
+ //#region src/vite-plugin.ts
6
+ var VIRTUAL_MODULE_ID = "virtual:smrt-agent-registrations";
7
+ var RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
7
8
  function toSafeIdentifier(packageName) {
8
- return packageName.replace("@", "").replace(/[/.-]/g, "_");
9
+ return packageName.replace("@", "").replace(/[/.-]/g, "_");
9
10
  }
10
11
  function vitePluginAgentRoutes(options = {}) {
11
- let projectRoot = process.cwd();
12
- let agentPackages = [];
13
- return {
14
- name: "smrt-agent-routes",
15
- configResolved(config) {
16
- projectRoot = config.root;
17
- const configPath = options.configPath || resolve(projectRoot, "smrt.config.js");
18
- try {
19
- agentPackages = extractAgentPackagesFromConfig(configPath);
20
- } catch {
21
- }
22
- if (agentPackages.length === 0 && options.agents) {
23
- agentPackages = options.agents.map((a) => a.packageName);
24
- }
25
- if (agentPackages.length > 0) {
26
- console.log(
27
- `[smrt-agent-routes] Discovered ${agentPackages.length} agents: ${agentPackages.map((p) => p.split("/").pop()).join(", ")}`
28
- );
29
- }
30
- },
31
- resolveId(id) {
32
- if (id === VIRTUAL_MODULE_ID) {
33
- return RESOLVED_VIRTUAL_MODULE_ID;
34
- }
35
- },
36
- load(id) {
37
- if (id !== RESOLVED_VIRTUAL_MODULE_ID) return;
38
- if (agentPackages.length === 0) {
39
- return `// No agents configured in smrt.config.js
12
+ let projectRoot = process.cwd();
13
+ let agentPackages = [];
14
+ return {
15
+ name: "smrt-agent-routes",
16
+ configResolved(config) {
17
+ projectRoot = config.root;
18
+ const configPath = options.configPath || resolve(projectRoot, "smrt.config.js");
19
+ try {
20
+ agentPackages = extractAgentPackagesFromConfig(configPath);
21
+ } catch {}
22
+ if (agentPackages.length === 0 && options.agents) agentPackages = options.agents.map((a) => a.packageName);
23
+ if (agentPackages.length > 0) console.log(`[smrt-agent-routes] Discovered ${agentPackages.length} agents: ${agentPackages.map((p) => p.split("/").pop()).join(", ")}`);
24
+ },
25
+ resolveId(id) {
26
+ if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
27
+ },
28
+ load(id) {
29
+ if (id !== RESOLVED_VIRTUAL_MODULE_ID) return;
30
+ if (agentPackages.length === 0) return `// No agents configured in smrt.config.js
40
31
  export const agentAdminRegistry = new Map();
41
32
  export function initializeAgentRegistrations() {}
42
33
  `;
43
- }
44
- const lines = [
45
- "/**",
46
- " * Auto-generated agent registrations",
47
- ` * Source: smrt.config.js (${agentPackages.length} agents)`,
48
- " * Generated by @happyvertical/smrt-agents/vite",
49
- " */",
50
- "import { AgentUIRegistry } from '@happyvertical/smrt-agents/ui';",
51
- ""
52
- ];
53
- const registrations = [];
54
- for (let i = 0; i < agentPackages.length; i++) {
55
- const pkg = agentPackages[i];
56
- const safeName = toSafeIdentifier(pkg);
57
- const manifestVar = `manifest_${safeName}`;
58
- let agentClass = null;
59
- let manifestPath = null;
60
- try {
61
- const localRequire = createRequire(
62
- resolve(projectRoot, "package.json")
63
- );
64
- manifestPath = localRequire.resolve(`${pkg}/manifest`);
65
- const manifestContent = readFileSync(manifestPath, "utf-8");
66
- const manifest = JSON.parse(manifestContent);
67
- for (const obj of Object.values(manifest.objects)) {
68
- if (obj.agent) {
69
- agentClass = obj.className;
70
- break;
71
- }
72
- }
73
- } catch {
74
- console.warn(
75
- `[smrt-agent-routes] Could not read manifest for ${pkg} — skipping`
76
- );
77
- continue;
78
- }
79
- if (!agentClass) {
80
- console.warn(
81
- `[smrt-agent-routes] No agent object found in manifest for ${pkg} — skipping`
82
- );
83
- continue;
84
- }
85
- let hasAdmin = false;
86
- try {
87
- let pkgDir = dirname(manifestPath);
88
- while (!existsSync(resolve(pkgDir, "package.json"))) {
89
- const parent = dirname(pkgDir);
90
- if (parent === pkgDir) {
91
- break;
92
- }
93
- pkgDir = parent;
94
- }
95
- const pkgJson = JSON.parse(
96
- readFileSync(resolve(pkgDir, "package.json"), "utf-8")
97
- );
98
- hasAdmin = !!pkgJson.exports?.["./admin"];
99
- } catch {
100
- }
101
- registrations.push({
102
- packageName: pkg,
103
- manifestVar,
104
- agentClass,
105
- hasAdmin
106
- });
107
- lines.push(`import ${manifestVar} from '${pkg}/manifest';`);
108
- }
109
- lines.push("");
110
- lines.push(
111
- "function extractAgentManifest(manifest, agentClass) {",
112
- " for (const obj of Object.values(manifest.objects)) {",
113
- " if (obj.className === agentClass && obj.agent) {",
114
- " return obj.agent;",
115
- " }",
116
- " }",
117
- " return null;",
118
- "}",
119
- ""
120
- );
121
- lines.push("// Register agent manifests");
122
- for (const { manifestVar, agentClass } of registrations) {
123
- const key = JSON.stringify(agentClass);
124
- lines.push(
125
- `{`,
126
- ` const m = extractAgentManifest(${manifestVar}, ${key});`,
127
- ` if (m) AgentUIRegistry.registerManifest(${key}, m);`,
128
- `}`
129
- );
130
- }
131
- lines.push("");
132
- lines.push(
133
- "// Import admin modules (AgentAdminExport contract + legacy slot registration)"
134
- );
135
- const adminImports = [];
136
- for (const { packageName, agentClass, hasAdmin } of registrations) {
137
- if (hasAdmin) {
138
- const adminVar = `admin_${toSafeIdentifier(packageName)}`;
139
- lines.push(`import * as ${adminVar} from '${packageName}/admin';`);
140
- adminImports.push({ agentClass, adminVar });
141
- } else {
142
- lines.push(
143
- `// ${packageName}/admin — not available (no ./admin export)`
144
- );
145
- }
146
- }
147
- lines.push("");
148
- lines.push("// Agent admin registry: agentClass -> AgentAdminExport");
149
- lines.push("export const agentAdminRegistry = new Map();");
150
- for (const { agentClass, adminVar } of adminImports) {
151
- const key = JSON.stringify(agentClass);
152
- lines.push(
153
- `if (${adminVar}.default) {`,
154
- ` agentAdminRegistry.set(${key}, {`,
155
- ` default: ${adminVar}.default,`,
156
- ` createAPIClient: ${adminVar}.createAPIClient,`,
157
- ` navItems: ${adminVar}.navItems,`,
158
- ` });`,
159
- `}`
160
- );
161
- }
162
- lines.push("");
163
- lines.push("// Export for explicit initialization if needed");
164
- lines.push("export function initializeAgentRegistrations() {}");
165
- lines.push("");
166
- return lines.join("\n");
167
- }
168
- };
34
+ const lines = [
35
+ "/**",
36
+ " * Auto-generated agent registrations",
37
+ ` * Source: smrt.config.js (${agentPackages.length} agents)`,
38
+ " * Generated by @happyvertical/smrt-agents/vite",
39
+ " */",
40
+ "import { AgentUIRegistry } from '@happyvertical/smrt-agents/ui';",
41
+ ""
42
+ ];
43
+ const registrations = [];
44
+ for (let i = 0; i < agentPackages.length; i++) {
45
+ const pkg = agentPackages[i];
46
+ const manifestVar = `manifest_${toSafeIdentifier(pkg)}`;
47
+ let agentClass = null;
48
+ let manifestPath = null;
49
+ try {
50
+ manifestPath = createRequire(resolve(projectRoot, "package.json")).resolve(`${pkg}/manifest`);
51
+ const manifestContent = readFileSync(manifestPath, "utf-8");
52
+ const manifest = JSON.parse(manifestContent);
53
+ for (const obj of Object.values(manifest.objects)) if (obj.agent) {
54
+ agentClass = obj.className;
55
+ break;
56
+ }
57
+ } catch {
58
+ console.warn(`[smrt-agent-routes] Could not read manifest for ${pkg} \u2014 skipping`);
59
+ continue;
60
+ }
61
+ if (!agentClass) {
62
+ console.warn(`[smrt-agent-routes] No agent object found in manifest for ${pkg} \u2014 skipping`);
63
+ continue;
64
+ }
65
+ let hasAdmin = false;
66
+ try {
67
+ let pkgDir = dirname(manifestPath);
68
+ while (!existsSync(resolve(pkgDir, "package.json"))) {
69
+ const parent = dirname(pkgDir);
70
+ if (parent === pkgDir) break;
71
+ pkgDir = parent;
72
+ }
73
+ hasAdmin = !!JSON.parse(readFileSync(resolve(pkgDir, "package.json"), "utf-8")).exports?.["./admin"];
74
+ } catch {}
75
+ registrations.push({
76
+ packageName: pkg,
77
+ manifestVar,
78
+ agentClass,
79
+ hasAdmin
80
+ });
81
+ lines.push(`import ${manifestVar} from '${pkg}/manifest';`);
82
+ }
83
+ lines.push("");
84
+ lines.push("function extractAgentManifest(manifest, agentClass) {", " for (const obj of Object.values(manifest.objects)) {", " if (obj.className === agentClass && obj.agent) {", " return obj.agent;", " }", " }", " return null;", "}", "");
85
+ lines.push("// Register agent manifests");
86
+ for (const { manifestVar, agentClass } of registrations) {
87
+ const key = JSON.stringify(agentClass);
88
+ lines.push(`{`, ` const m = extractAgentManifest(${manifestVar}, ${key});`, ` if (m) AgentUIRegistry.registerManifest(${key}, m);`, `}`);
89
+ }
90
+ lines.push("");
91
+ lines.push("// Import admin modules (AgentAdminExport contract + legacy slot registration)");
92
+ const adminImports = [];
93
+ for (const { packageName, agentClass, hasAdmin } of registrations) if (hasAdmin) {
94
+ const adminVar = `admin_${toSafeIdentifier(packageName)}`;
95
+ lines.push(`import * as ${adminVar} from '${packageName}/admin';`);
96
+ adminImports.push({
97
+ agentClass,
98
+ adminVar
99
+ });
100
+ } else lines.push(`// ${packageName}/admin \u2014 not available (no ./admin export)`);
101
+ lines.push("");
102
+ lines.push("// Agent admin registry: agentClass -> AgentAdminExport");
103
+ lines.push("export const agentAdminRegistry = new Map();");
104
+ for (const { agentClass, adminVar } of adminImports) {
105
+ const key = JSON.stringify(agentClass);
106
+ lines.push(`if (${adminVar}.default) {`, ` agentAdminRegistry.set(${key}, {`, ` default: ${adminVar}.default,`, ` createAPIClient: ${adminVar}.createAPIClient,`, ` navItems: ${adminVar}.navItems,`, ` });`, `}`);
107
+ }
108
+ lines.push("");
109
+ lines.push("// Export for explicit initialization if needed");
110
+ lines.push("export function initializeAgentRegistrations() {}");
111
+ lines.push("");
112
+ return lines.join("\n");
113
+ }
114
+ };
169
115
  }
170
- export {
171
- vitePluginAgentRoutes
172
- };
173
- //# sourceMappingURL=vite-plugin.js.map
116
+ //#endregion
117
+ export { vitePluginAgentRoutes };
118
+
119
+ //# sourceMappingURL=vite-plugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.js","sources":["../src/vite-plugin.ts"],"sourcesContent":["/**\n * Vite Plugin: Agent Auto-Registration\n *\n * Provides the `virtual:smrt-agent-registrations` virtual module.\n * When imported, this module registers each agent's manifest with\n * AgentUIRegistry and imports the agent's `./admin` entry (if it exists)\n * for side-effect component registration.\n *\n * Agent packages are discovered from smrt.config.js's `agents` array,\n * or from the `agents` option passed directly to the plugin.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { vitePluginAgentRoutes } from '@happyvertical/smrt-agents/vite';\n *\n * export default defineConfig({\n * plugins: [\n * sveltekit(),\n * vitePluginAgentRoutes({\n * agents: [\n * { packageName: '@happyvertical/praeco', agentClass: 'Praeco' },\n * ],\n * }),\n * ],\n * });\n * ```\n *\n * ```ts\n * // In your app:\n * import 'virtual:smrt-agent-registrations';\n * ```\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, resolve } from 'node:path';\nimport {\n extractAgentPackagesFromConfig,\n type PackageManifest,\n} from './server/manifest-utils.js';\n\nconst VIRTUAL_MODULE_ID = 'virtual:smrt-agent-registrations';\nconst RESOLVED_VIRTUAL_MODULE_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\n/** Convert a package name to a safe JS identifier (e.g., '@test/with-admin' → 'test_with_admin') */\nfunction toSafeIdentifier(packageName: string): string {\n return packageName.replace('@', '').replace(/[/.-]/g, '_');\n}\n\nexport interface AgentRoutesPluginOptions {\n /** Path to smrt.config.js (default: <project root>/smrt.config.js) */\n configPath?: string;\n /**\n * Agent packages to register. Falls back to reading smrt.config.js `agents` array\n * if not provided. When provided, `agentClass` is used as a hint but the plugin\n * still reads each package's manifest to discover the actual agent class.\n */\n agents?: Array<{\n packageName: string;\n agentClass: string;\n }>;\n}\n\n/**\n * Vite plugin that auto-registers agent manifests and admin components.\n *\n * Provides `virtual:smrt-agent-registrations` — import it to register\n * all agents declared in smrt.config.js.\n */\nexport function vitePluginAgentRoutes(options: AgentRoutesPluginOptions = {}): {\n name: string;\n resolveId: (id: string) => string | undefined;\n load: (id: string) => string | undefined;\n configResolved?: (config: { root: string }) => void;\n} {\n let projectRoot = process.cwd();\n let agentPackages: string[] = [];\n\n return {\n name: 'smrt-agent-routes',\n\n configResolved(config: { root: string }) {\n projectRoot = config.root;\n\n // Try to load smrt.config.js using shared config extraction\n const configPath =\n options.configPath || resolve(projectRoot, 'smrt.config.js');\n\n try {\n agentPackages = extractAgentPackagesFromConfig(configPath);\n } catch {\n // Config not found or unreadable — fall back to options.agents\n }\n\n // Fall back to legacy options.agents if config didn't provide packages\n if (agentPackages.length === 0 && options.agents) {\n agentPackages = options.agents.map((a) => a.packageName);\n }\n\n if (agentPackages.length > 0) {\n console.log(\n `[smrt-agent-routes] Discovered ${agentPackages.length} agents: ${agentPackages.map((p) => p.split('/').pop()).join(', ')}`,\n );\n }\n },\n\n resolveId(id: string) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n },\n\n load(id: string) {\n if (id !== RESOLVED_VIRTUAL_MODULE_ID) return;\n\n if (agentPackages.length === 0) {\n return `// No agents configured in smrt.config.js\\nexport const agentAdminRegistry = new Map();\\nexport function initializeAgentRegistrations() {}\\n`;\n }\n\n const lines: string[] = [\n '/**',\n ' * Auto-generated agent registrations',\n ` * Source: smrt.config.js (${agentPackages.length} agents)`,\n ' * Generated by @happyvertical/smrt-agents/vite',\n ' */',\n \"import { AgentUIRegistry } from '@happyvertical/smrt-agents/ui';\",\n '',\n ];\n\n // For each agent package, try to resolve its manifest and find the agent class\n const registrations: Array<{\n packageName: string;\n manifestVar: string;\n agentClass: string | null;\n hasAdmin: boolean;\n }> = [];\n\n for (let i = 0; i < agentPackages.length; i++) {\n const pkg = agentPackages[i];\n const safeName = toSafeIdentifier(pkg);\n const manifestVar = `manifest_${safeName}`;\n\n // Try to read the manifest to extract the agent class name\n let agentClass: string | null = null;\n let manifestPath: string | null = null;\n try {\n const localRequire = createRequire(\n resolve(projectRoot, 'package.json'),\n );\n manifestPath = localRequire.resolve(`${pkg}/manifest`);\n const manifestContent = readFileSync(manifestPath, 'utf-8');\n const manifest: PackageManifest = JSON.parse(manifestContent);\n\n // Find the agent object (one with agent metadata)\n for (const obj of Object.values(manifest.objects)) {\n if (obj.agent) {\n agentClass = obj.className;\n break;\n }\n }\n } catch {\n // Manifest not found or unparseable — skip this agent\n console.warn(\n `[smrt-agent-routes] Could not read manifest for ${pkg} — skipping`,\n );\n continue;\n }\n\n if (!agentClass) {\n console.warn(\n `[smrt-agent-routes] No agent object found in manifest for ${pkg} — skipping`,\n );\n continue;\n }\n\n // Check if ./admin export exists by reading the package's exports field.\n // We can't use createRequire().resolve() because CJS resolution doesn't\n // recognise 'svelte' or 'import' conditions — only 'default'/'require'/'node'.\n // Derive the package root from the manifest path we already resolved.\n let hasAdmin = false;\n try {\n let pkgDir = dirname(manifestPath!);\n while (!existsSync(resolve(pkgDir, 'package.json'))) {\n const parent = dirname(pkgDir);\n if (parent === pkgDir) {\n break;\n }\n pkgDir = parent;\n }\n const pkgJson = JSON.parse(\n readFileSync(resolve(pkgDir, 'package.json'), 'utf-8'),\n );\n hasAdmin = !!pkgJson.exports?.['./admin'];\n } catch {\n // Failed to read package.json or parse exports — treat as no admin export\n }\n\n registrations.push({\n packageName: pkg,\n manifestVar,\n agentClass,\n hasAdmin,\n });\n\n // Import manifest\n lines.push(`import ${manifestVar} from '${pkg}/manifest';`);\n }\n\n lines.push('');\n\n // Generate the extractAgentManifest helper inline in the virtual module.\n // This runs in the browser, so it can't import from ./server.\n lines.push(\n 'function extractAgentManifest(manifest, agentClass) {',\n ' for (const obj of Object.values(manifest.objects)) {',\n ' if (obj.className === agentClass && obj.agent) {',\n ' return obj.agent;',\n ' }',\n ' }',\n ' return null;',\n '}',\n '',\n );\n\n // Register manifests\n lines.push('// Register agent manifests');\n for (const { manifestVar, agentClass } of registrations) {\n const key = JSON.stringify(agentClass);\n lines.push(\n `{`,\n ` const m = extractAgentManifest(${manifestVar}, ${key});`,\n ` if (m) AgentUIRegistry.registerManifest(${key}, m);`,\n `}`,\n );\n }\n lines.push('');\n\n // Import admin modules — named imports for AgentAdminExport contract,\n // plus side-effect registration of legacy slot components\n lines.push(\n '// Import admin modules (AgentAdminExport contract + legacy slot registration)',\n );\n\n const adminImports: Array<{ agentClass: string; adminVar: string }> = [];\n\n for (const { packageName, agentClass, hasAdmin } of registrations) {\n if (hasAdmin) {\n const adminVar = `admin_${toSafeIdentifier(packageName)}`;\n // Use namespace import so missing optional exports (navItems) resolve\n // as undefined instead of throwing a hard ESM error.\n lines.push(`import * as ${adminVar} from '${packageName}/admin';`);\n adminImports.push({ agentClass: agentClass!, adminVar });\n } else {\n lines.push(\n `// ${packageName}/admin — not available (no ./admin export)`,\n );\n }\n }\n\n lines.push('');\n\n // Build the agentAdminRegistry Map\n lines.push('// Agent admin registry: agentClass -> AgentAdminExport');\n lines.push('export const agentAdminRegistry = new Map();');\n for (const { agentClass, adminVar } of adminImports) {\n const key = JSON.stringify(agentClass);\n lines.push(\n `if (${adminVar}.default) {`,\n ` agentAdminRegistry.set(${key}, {`,\n ` default: ${adminVar}.default,`,\n ` createAPIClient: ${adminVar}.createAPIClient,`,\n ` navItems: ${adminVar}.navItems,`,\n ` });`,\n `}`,\n );\n }\n\n lines.push('');\n lines.push('// Export for explicit initialization if needed');\n lines.push('export function initializeAgentRegistrations() {}');\n lines.push('');\n\n return lines.join('\\n');\n },\n };\n}\n"],"names":[],"mappings":";;;;AA0CA,MAAM,oBAAoB;AAC1B,MAAM,6BAA6B,KAAK,iBAAiB;AAGzD,SAAS,iBAAiB,aAA6B;AACrD,SAAO,YAAY,QAAQ,KAAK,EAAE,EAAE,QAAQ,UAAU,GAAG;AAC3D;AAsBO,SAAS,sBAAsB,UAAoC,IAKxE;AACA,MAAI,cAAc,QAAQ,IAAA;AAC1B,MAAI,gBAA0B,CAAA;AAE9B,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,eAAe,QAA0B;AACvC,oBAAc,OAAO;AAGrB,YAAM,aACJ,QAAQ,cAAc,QAAQ,aAAa,gBAAgB;AAE7D,UAAI;AACF,wBAAgB,+BAA+B,UAAU;AAAA,MAC3D,QAAQ;AAAA,MAER;AAGA,UAAI,cAAc,WAAW,KAAK,QAAQ,QAAQ;AAChD,wBAAgB,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,WAAW;AAAA,MACzD;AAEA,UAAI,cAAc,SAAS,GAAG;AAC5B,gBAAQ;AAAA,UACN,kCAAkC,cAAc,MAAM,YAAY,cAAc,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,IAAA,CAAK,EAAE,KAAK,IAAI,CAAC;AAAA,QAAA;AAAA,MAE7H;AAAA,IACF;AAAA,IAEA,UAAU,IAAY;AACpB,UAAI,OAAO,mBAAmB;AAC5B,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,KAAK,IAAY;AACf,UAAI,OAAO,2BAA4B;AAEvC,UAAI,cAAc,WAAW,GAAG;AAC9B,eAAO;AAAA;AAAA;AAAA;AAAA,MACT;AAEA,YAAM,QAAkB;AAAA,QACtB;AAAA,QACA;AAAA,QACA,8BAA8B,cAAc,MAAM;AAAA,QAClD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAIF,YAAM,gBAKD,CAAA;AAEL,eAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC7C,cAAM,MAAM,cAAc,CAAC;AAC3B,cAAM,WAAW,iBAAiB,GAAG;AACrC,cAAM,cAAc,YAAY,QAAQ;AAGxC,YAAI,aAA4B;AAChC,YAAI,eAA8B;AAClC,YAAI;AACF,gBAAM,eAAe;AAAA,YACnB,QAAQ,aAAa,cAAc;AAAA,UAAA;AAErC,yBAAe,aAAa,QAAQ,GAAG,GAAG,WAAW;AACrD,gBAAM,kBAAkB,aAAa,cAAc,OAAO;AAC1D,gBAAM,WAA4B,KAAK,MAAM,eAAe;AAG5D,qBAAW,OAAO,OAAO,OAAO,SAAS,OAAO,GAAG;AACjD,gBAAI,IAAI,OAAO;AACb,2BAAa,IAAI;AACjB;AAAA,YACF;AAAA,UACF;AAAA,QACF,QAAQ;AAEN,kBAAQ;AAAA,YACN,mDAAmD,GAAG;AAAA,UAAA;AAExD;AAAA,QACF;AAEA,YAAI,CAAC,YAAY;AACf,kBAAQ;AAAA,YACN,6DAA6D,GAAG;AAAA,UAAA;AAElE;AAAA,QACF;AAMA,YAAI,WAAW;AACf,YAAI;AACF,cAAI,SAAS,QAAQ,YAAa;AAClC,iBAAO,CAAC,WAAW,QAAQ,QAAQ,cAAc,CAAC,GAAG;AACnD,kBAAM,SAAS,QAAQ,MAAM;AAC7B,gBAAI,WAAW,QAAQ;AACrB;AAAA,YACF;AACA,qBAAS;AAAA,UACX;AACA,gBAAM,UAAU,KAAK;AAAA,YACnB,aAAa,QAAQ,QAAQ,cAAc,GAAG,OAAO;AAAA,UAAA;AAEvD,qBAAW,CAAC,CAAC,QAAQ,UAAU,SAAS;AAAA,QAC1C,QAAQ;AAAA,QAER;AAEA,sBAAc,KAAK;AAAA,UACjB,aAAa;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,QAAA,CACD;AAGD,cAAM,KAAK,UAAU,WAAW,UAAU,GAAG,aAAa;AAAA,MAC5D;AAEA,YAAM,KAAK,EAAE;AAIb,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAIF,YAAM,KAAK,6BAA6B;AACxC,iBAAW,EAAE,aAAa,WAAA,KAAgB,eAAe;AACvD,cAAM,MAAM,KAAK,UAAU,UAAU;AACrC,cAAM;AAAA,UACJ;AAAA,UACA,oCAAoC,WAAW,KAAK,GAAG;AAAA,UACvD,6CAA6C,GAAG;AAAA,UAChD;AAAA,QAAA;AAAA,MAEJ;AACA,YAAM,KAAK,EAAE;AAIb,YAAM;AAAA,QACJ;AAAA,MAAA;AAGF,YAAM,eAAgE,CAAA;AAEtE,iBAAW,EAAE,aAAa,YAAY,SAAA,KAAc,eAAe;AACjE,YAAI,UAAU;AACZ,gBAAM,WAAW,SAAS,iBAAiB,WAAW,CAAC;AAGvD,gBAAM,KAAK,eAAe,QAAQ,UAAU,WAAW,UAAU;AACjE,uBAAa,KAAK,EAAE,YAAyB,SAAA,CAAU;AAAA,QACzD,OAAO;AACL,gBAAM;AAAA,YACJ,MAAM,WAAW;AAAA,UAAA;AAAA,QAErB;AAAA,MACF;AAEA,YAAM,KAAK,EAAE;AAGb,YAAM,KAAK,yDAAyD;AACpE,YAAM,KAAK,8CAA8C;AACzD,iBAAW,EAAE,YAAY,SAAA,KAAc,cAAc;AACnD,cAAM,MAAM,KAAK,UAAU,UAAU;AACrC,cAAM;AAAA,UACJ,OAAO,QAAQ;AAAA,UACf,4BAA4B,GAAG;AAAA,UAC/B,gBAAgB,QAAQ;AAAA,UACxB,wBAAwB,QAAQ;AAAA,UAChC,iBAAiB,QAAQ;AAAA,UACzB;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,iDAAiD;AAC5D,YAAM,KAAK,mDAAmD;AAC9D,YAAM,KAAK,EAAE;AAEb,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"vite-plugin.js","names":[],"sources":["../src/vite-plugin.ts"],"sourcesContent":["/**\n * Vite Plugin: Agent Auto-Registration\n *\n * Provides the `virtual:smrt-agent-registrations` virtual module.\n * When imported, this module registers each agent's manifest with\n * AgentUIRegistry and imports the agent's `./admin` entry (if it exists)\n * for side-effect component registration.\n *\n * Agent packages are discovered from smrt.config.js's `agents` array,\n * or from the `agents` option passed directly to the plugin.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { vitePluginAgentRoutes } from '@happyvertical/smrt-agents/vite';\n *\n * export default defineConfig({\n * plugins: [\n * sveltekit(),\n * vitePluginAgentRoutes({\n * agents: [\n * { packageName: '@happyvertical/praeco', agentClass: 'Praeco' },\n * ],\n * }),\n * ],\n * });\n * ```\n *\n * ```ts\n * // In your app:\n * import 'virtual:smrt-agent-registrations';\n * ```\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, resolve } from 'node:path';\nimport {\n extractAgentPackagesFromConfig,\n type PackageManifest,\n} from './server/manifest-utils.js';\n\nconst VIRTUAL_MODULE_ID = 'virtual:smrt-agent-registrations';\nconst RESOLVED_VIRTUAL_MODULE_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\n/** Convert a package name to a safe JS identifier (e.g., '@test/with-admin' → 'test_with_admin') */\nfunction toSafeIdentifier(packageName: string): string {\n return packageName.replace('@', '').replace(/[/.-]/g, '_');\n}\n\nexport interface AgentRoutesPluginOptions {\n /** Path to smrt.config.js (default: <project root>/smrt.config.js) */\n configPath?: string;\n /**\n * Agent packages to register. Falls back to reading smrt.config.js `agents` array\n * if not provided. When provided, `agentClass` is used as a hint but the plugin\n * still reads each package's manifest to discover the actual agent class.\n */\n agents?: Array<{\n packageName: string;\n agentClass: string;\n }>;\n}\n\n/**\n * Vite plugin that auto-registers agent manifests and admin components.\n *\n * Provides `virtual:smrt-agent-registrations` — import it to register\n * all agents declared in smrt.config.js.\n */\nexport function vitePluginAgentRoutes(options: AgentRoutesPluginOptions = {}): {\n name: string;\n resolveId: (id: string) => string | undefined;\n load: (id: string) => string | undefined;\n configResolved?: (config: { root: string }) => void;\n} {\n let projectRoot = process.cwd();\n let agentPackages: string[] = [];\n\n return {\n name: 'smrt-agent-routes',\n\n configResolved(config: { root: string }) {\n projectRoot = config.root;\n\n // Try to load smrt.config.js using shared config extraction\n const configPath =\n options.configPath || resolve(projectRoot, 'smrt.config.js');\n\n try {\n agentPackages = extractAgentPackagesFromConfig(configPath);\n } catch {\n // Config not found or unreadable — fall back to options.agents\n }\n\n // Fall back to legacy options.agents if config didn't provide packages\n if (agentPackages.length === 0 && options.agents) {\n agentPackages = options.agents.map((a) => a.packageName);\n }\n\n if (agentPackages.length > 0) {\n console.log(\n `[smrt-agent-routes] Discovered ${agentPackages.length} agents: ${agentPackages.map((p) => p.split('/').pop()).join(', ')}`,\n );\n }\n },\n\n resolveId(id: string) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n },\n\n load(id: string) {\n if (id !== RESOLVED_VIRTUAL_MODULE_ID) return;\n\n if (agentPackages.length === 0) {\n return `// No agents configured in smrt.config.js\\nexport const agentAdminRegistry = new Map();\\nexport function initializeAgentRegistrations() {}\\n`;\n }\n\n const lines: string[] = [\n '/**',\n ' * Auto-generated agent registrations',\n ` * Source: smrt.config.js (${agentPackages.length} agents)`,\n ' * Generated by @happyvertical/smrt-agents/vite',\n ' */',\n \"import { AgentUIRegistry } from '@happyvertical/smrt-agents/ui';\",\n '',\n ];\n\n // For each agent package, try to resolve its manifest and find the agent class\n const registrations: Array<{\n packageName: string;\n manifestVar: string;\n agentClass: string | null;\n hasAdmin: boolean;\n }> = [];\n\n for (let i = 0; i < agentPackages.length; i++) {\n const pkg = agentPackages[i];\n const safeName = toSafeIdentifier(pkg);\n const manifestVar = `manifest_${safeName}`;\n\n // Try to read the manifest to extract the agent class name\n let agentClass: string | null = null;\n let manifestPath: string | null = null;\n try {\n const localRequire = createRequire(\n resolve(projectRoot, 'package.json'),\n );\n manifestPath = localRequire.resolve(`${pkg}/manifest`);\n const manifestContent = readFileSync(manifestPath, 'utf-8');\n const manifest: PackageManifest = JSON.parse(manifestContent);\n\n // Find the agent object (one with agent metadata)\n for (const obj of Object.values(manifest.objects)) {\n if (obj.agent) {\n agentClass = obj.className;\n break;\n }\n }\n } catch {\n // Manifest not found or unparseable — skip this agent\n console.warn(\n `[smrt-agent-routes] Could not read manifest for ${pkg} — skipping`,\n );\n continue;\n }\n\n if (!agentClass) {\n console.warn(\n `[smrt-agent-routes] No agent object found in manifest for ${pkg} — skipping`,\n );\n continue;\n }\n\n // Check if ./admin export exists by reading the package's exports field.\n // We can't use createRequire().resolve() because CJS resolution doesn't\n // recognise 'svelte' or 'import' conditions — only 'default'/'require'/'node'.\n // Derive the package root from the manifest path we already resolved.\n let hasAdmin = false;\n try {\n let pkgDir = dirname(manifestPath!);\n while (!existsSync(resolve(pkgDir, 'package.json'))) {\n const parent = dirname(pkgDir);\n if (parent === pkgDir) {\n break;\n }\n pkgDir = parent;\n }\n const pkgJson = JSON.parse(\n readFileSync(resolve(pkgDir, 'package.json'), 'utf-8'),\n );\n hasAdmin = !!pkgJson.exports?.['./admin'];\n } catch {\n // Failed to read package.json or parse exports — treat as no admin export\n }\n\n registrations.push({\n packageName: pkg,\n manifestVar,\n agentClass,\n hasAdmin,\n });\n\n // Import manifest\n lines.push(`import ${manifestVar} from '${pkg}/manifest';`);\n }\n\n lines.push('');\n\n // Generate the extractAgentManifest helper inline in the virtual module.\n // This runs in the browser, so it can't import from ./server.\n lines.push(\n 'function extractAgentManifest(manifest, agentClass) {',\n ' for (const obj of Object.values(manifest.objects)) {',\n ' if (obj.className === agentClass && obj.agent) {',\n ' return obj.agent;',\n ' }',\n ' }',\n ' return null;',\n '}',\n '',\n );\n\n // Register manifests\n lines.push('// Register agent manifests');\n for (const { manifestVar, agentClass } of registrations) {\n const key = JSON.stringify(agentClass);\n lines.push(\n `{`,\n ` const m = extractAgentManifest(${manifestVar}, ${key});`,\n ` if (m) AgentUIRegistry.registerManifest(${key}, m);`,\n `}`,\n );\n }\n lines.push('');\n\n // Import admin modules — named imports for AgentAdminExport contract,\n // plus side-effect registration of legacy slot components\n lines.push(\n '// Import admin modules (AgentAdminExport contract + legacy slot registration)',\n );\n\n const adminImports: Array<{ agentClass: string; adminVar: string }> = [];\n\n for (const { packageName, agentClass, hasAdmin } of registrations) {\n if (hasAdmin) {\n const adminVar = `admin_${toSafeIdentifier(packageName)}`;\n // Use namespace import so missing optional exports (navItems) resolve\n // as undefined instead of throwing a hard ESM error.\n lines.push(`import * as ${adminVar} from '${packageName}/admin';`);\n adminImports.push({ agentClass: agentClass!, adminVar });\n } else {\n lines.push(\n `// ${packageName}/admin — not available (no ./admin export)`,\n );\n }\n }\n\n lines.push('');\n\n // Build the agentAdminRegistry Map\n lines.push('// Agent admin registry: agentClass -> AgentAdminExport');\n lines.push('export const agentAdminRegistry = new Map();');\n for (const { agentClass, adminVar } of adminImports) {\n const key = JSON.stringify(agentClass);\n lines.push(\n `if (${adminVar}.default) {`,\n ` agentAdminRegistry.set(${key}, {`,\n ` default: ${adminVar}.default,`,\n ` createAPIClient: ${adminVar}.createAPIClient,`,\n ` navItems: ${adminVar}.navItems,`,\n ` });`,\n `}`,\n );\n }\n\n lines.push('');\n lines.push('// Export for explicit initialization if needed');\n lines.push('export function initializeAgentRegistrations() {}');\n lines.push('');\n\n return lines.join('\\n');\n },\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-agents",
3
- "version": "0.37.1",
3
+ "version": "0.37.3",
4
4
  "type": "module",
5
5
  "smrtRawPrimitives": "strict",
6
6
  "description": "Agent framework for building autonomous actors in the SMRT ecosystem",
@@ -48,7 +48,7 @@
48
48
  "AGENTS.md"
49
49
  ],
50
50
  "peerDependencies": {
51
- "svelte": "^5.0.0"
51
+ "svelte": "^5.56.4"
52
52
  },
53
53
  "peerDependenciesMeta": {
54
54
  "svelte": {
@@ -56,33 +56,33 @@
56
56
  }
57
57
  },
58
58
  "dependencies": {
59
- "@happyvertical/ai": "^0.74.10",
60
- "@happyvertical/files": "^0.74.10",
61
- "@happyvertical/utils": "^0.74.10",
62
- "@happyvertical/smrt-core": "0.37.1",
63
- "@happyvertical/smrt-config": "0.37.1",
64
- "@happyvertical/smrt-secrets": "0.37.1",
65
- "@happyvertical/smrt-tenancy": "0.37.1",
66
- "@happyvertical/smrt-types": "0.37.1",
67
- "@happyvertical/smrt-ui": "0.37.1",
68
- "@happyvertical/smrt-users": "0.37.1"
59
+ "@happyvertical/ai": "^0.74.11",
60
+ "@happyvertical/files": "^0.74.11",
61
+ "@happyvertical/utils": "^0.74.11",
62
+ "@happyvertical/smrt-config": "0.37.3",
63
+ "@happyvertical/smrt-core": "0.37.3",
64
+ "@happyvertical/smrt-tenancy": "0.37.3",
65
+ "@happyvertical/smrt-types": "0.37.3",
66
+ "@happyvertical/smrt-secrets": "0.37.3",
67
+ "@happyvertical/smrt-ui": "0.37.3",
68
+ "@happyvertical/smrt-users": "0.37.3"
69
69
  },
70
70
  "devDependencies": {
71
- "@happyvertical/logger": "^0.74.10",
72
- "@happyvertical/sql": "^0.74.10",
73
- "@sentry/node": "^10.51.0",
74
- "@sveltejs/package": "^2.5.7",
75
- "@sveltejs/vite-plugin-svelte": "^6.2.4",
76
- "@testing-library/svelte": "^5.3.1",
71
+ "@happyvertical/logger": "^0.74.11",
72
+ "@happyvertical/sql": "^0.74.11",
73
+ "@sentry/node": "^10.62.0",
74
+ "@sveltejs/package": "^2.5.8",
75
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
76
+ "@testing-library/svelte": "^5.4.2",
77
77
  "@testing-library/user-event": "^14.6.1",
78
- "@types/node": "25.0.9",
78
+ "@types/node": "24.13.2",
79
79
  "fast-glob": "3.3.3",
80
- "svelte-check": "^4.3.5",
81
- "svelte": "^5.18.0",
80
+ "svelte-check": "^4.7.1",
81
+ "svelte": "^5.56.4",
82
82
  "typescript": "^5.9.3",
83
- "vite": "^7.3.6",
84
- "vitest": "^4.0.17",
85
- "@happyvertical/smrt-vitest": "0.37.1"
83
+ "vite": "^8.1.2",
84
+ "vitest": "^4.1.9",
85
+ "@happyvertical/smrt-vitest": "0.37.3"
86
86
  },
87
87
  "keywords": [
88
88
  "agent",
@@ -1,189 +0,0 @@
1
- import { ObjectRegistry, getClassName, field, smrt, SmrtObject, SmrtCollection } from "@happyvertical/smrt-core";
2
- import { tenantId, TenantScoped, queryGlobal, queryWithGlobals } from "@happyvertical/smrt-tenancy";
3
- function getAgentTypeName(name) {
4
- const registered = ObjectRegistry.getClass(name);
5
- return registered?.qualifiedName || registered?.name || name;
6
- }
7
- function getAgentClassName(name) {
8
- const registered = ObjectRegistry.getClass(name);
9
- return registered?.name || getClassName(name);
10
- }
11
- function getAgentTypeAliases(name) {
12
- return Array.from(
13
- new Set([getAgentTypeName(name), getAgentClassName(name)].filter(Boolean))
14
- );
15
- }
16
- var __defProp = Object.defineProperty;
17
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
18
- var __decorateClass = (decorators, target, key, kind) => {
19
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
20
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
21
- if (decorator = decorators[i])
22
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
23
- if (kind && result) __defProp(target, key, result);
24
- return result;
25
- };
26
- let AgentConfig = class extends SmrtObject {
27
- tenantId = null;
28
- agentId = "";
29
- agentClass = "";
30
- slotId = "";
31
- configData = {};
32
- schemaVersion = 1;
33
- /**
34
- * Load all configs for a specific agent
35
- *
36
- * @param agentId - Agent instance ID
37
- * @param options - Database options
38
- * @returns Map of slotId → configData
39
- */
40
- static async forAgent(agentId, options) {
41
- const configsByAgent = await AgentConfig.forAgents([agentId], options);
42
- return configsByAgent.get(agentId) ?? /* @__PURE__ */ new Map();
43
- }
44
- /**
45
- * Load configs for multiple agents in a single query.
46
- *
47
- * @param agentIds - Agent instance IDs
48
- * @param options - Database options
49
- * @returns Map of agentId -> (slotId -> configData)
50
- */
51
- static async forAgents(agentIds, options) {
52
- const configsByAgent = /* @__PURE__ */ new Map();
53
- if (agentIds.length === 0) {
54
- return configsByAgent;
55
- }
56
- const collection = await AgentConfigCollection.create(options);
57
- const configs = await collection.list({
58
- where: { "agentId in": agentIds }
59
- });
60
- for (const config of configs) {
61
- if (!configsByAgent.has(config.agentId)) {
62
- configsByAgent.set(config.agentId, /* @__PURE__ */ new Map());
63
- }
64
- configsByAgent.get(config.agentId)?.set(config.slotId, config.configData);
65
- }
66
- return configsByAgent;
67
- }
68
- /**
69
- * Load config for a specific agent and slot
70
- *
71
- * @param agentId - Agent instance ID
72
- * @param slotId - UI slot ID
73
- * @param options - Database options
74
- * @returns Config data or undefined if not found
75
- */
76
- static async forSlot(agentId, slotId, options) {
77
- const collection = await AgentConfigCollection.create(options);
78
- const configs = await collection.list({
79
- where: { agentId, slotId },
80
- limit: 1
81
- });
82
- return configs[0]?.configData;
83
- }
84
- /**
85
- * Save or update config for an agent slot
86
- *
87
- * @param data - Config data including agentId, agentClass, slotId, configData
88
- * @param options - Database options
89
- * @returns Saved AgentConfig instance
90
- */
91
- static async saveSlot(data, options) {
92
- const normalizedAgentClass = getAgentTypeName(data.agentClass);
93
- const collection = await AgentConfigCollection.create(options);
94
- const existingConfigs = await collection.list({
95
- where: { agentId: data.agentId, slotId: data.slotId },
96
- limit: 1
97
- });
98
- if (existingConfigs.length > 0) {
99
- const existing = existingConfigs[0];
100
- existing.configData = data.configData;
101
- existing.agentClass = normalizedAgentClass;
102
- await existing.save();
103
- return existing;
104
- }
105
- const config = await collection.create({
106
- agentId: data.agentId,
107
- agentClass: normalizedAgentClass,
108
- slotId: data.slotId,
109
- configData: data.configData,
110
- slug: `${data.agentId}-${data.slotId}`
111
- });
112
- await config.save();
113
- return config;
114
- }
115
- };
116
- __decorateClass([
117
- tenantId({ nullable: true })
118
- ], AgentConfig.prototype, "tenantId", 2);
119
- __decorateClass([
120
- field({ type: "text" })
121
- ], AgentConfig.prototype, "agentId", 2);
122
- __decorateClass([
123
- field({ type: "text" })
124
- ], AgentConfig.prototype, "agentClass", 2);
125
- __decorateClass([
126
- field({ type: "text" })
127
- ], AgentConfig.prototype, "slotId", 2);
128
- __decorateClass([
129
- field({ type: "json", sensitive: true })
130
- ], AgentConfig.prototype, "configData", 2);
131
- __decorateClass([
132
- field({ type: "integer" })
133
- ], AgentConfig.prototype, "schemaVersion", 2);
134
- AgentConfig = __decorateClass([
135
- TenantScoped({ mode: "optional" }),
136
- smrt({
137
- tableName: "agent_configs",
138
- api: { include: ["list", "get", "create", "update", "delete"] },
139
- mcp: { include: ["list", "get"] },
140
- cli: true
141
- })
142
- ], AgentConfig);
143
- class AgentConfigCollection extends SmrtCollection {
144
- static _itemClass = AgentConfig;
145
- /**
146
- * Find all configs for a specific tenant
147
- * @param tenantId - Tenant ID to filter by
148
- * @returns Array of AgentConfig objects for the tenant
149
- */
150
- async findByTenant(tenantId2) {
151
- return this.list({ where: { tenantId: tenantId2 } });
152
- }
153
- /**
154
- * Find all global configs (not associated with any tenant).
155
- *
156
- * Routes through the shared tenant-global helper so it does not throw under
157
- * an active tenant context (an explicit `tenant_id IS NULL` filter would be
158
- * flagged as an isolation violation). (#1600)
159
- *
160
- * @returns Array of global AgentConfig objects
161
- */
162
- async findGlobal() {
163
- return queryGlobal(this);
164
- }
165
- /**
166
- * Find configs for a tenant including global configs.
167
- *
168
- * Fails closed if an active tenant context requests a different tenant's
169
- * rows; the admin/system path keeps the cross-tenant capability. (#1600)
170
- *
171
- * @param tenantId - Tenant ID to include
172
- * @returns Array of AgentConfig objects for the tenant and global configs
173
- */
174
- async findWithGlobals(tenantId2) {
175
- return queryWithGlobals(
176
- this,
177
- tenantId2,
178
- "AgentConfig.findWithGlobals"
179
- );
180
- }
181
- }
182
- export {
183
- AgentConfig as A,
184
- getAgentClassName as a,
185
- getAgentTypeAliases as b,
186
- AgentConfigCollection as c,
187
- getAgentTypeName as g
188
- };
189
- //# sourceMappingURL=config-JYiYqNE-.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-JYiYqNE-.js","sources":["../../src/identity.ts","../../src/config.ts"],"sourcesContent":["import { getClassName, ObjectRegistry } from '@happyvertical/smrt-core';\n\n/**\n * Return the canonical agent type identifier for storage and dispatch routing.\n *\n * Uses the registry's qualified name when available and falls back to the input\n * name for dynamically defined or unregistered classes.\n */\nexport function getAgentTypeName(name: string): string {\n const registered = ObjectRegistry.getClass(name);\n return registered?.qualifiedName || registered?.name || name;\n}\n\n/**\n * Return the human-readable class name for UI and logs.\n */\nexport function getAgentClassName(name: string): string {\n const registered = ObjectRegistry.getClass(name);\n return registered?.name || getClassName(name);\n}\n\n/**\n * Return all meaningful aliases for an agent type.\n *\n * The qualified name is first so persistence lookups prefer canonical rows,\n * while the simple class name keeps legacy rows discoverable during migration.\n */\nexport function getAgentTypeAliases(name: string): string[] {\n return Array.from(\n new Set([getAgentTypeName(name), getAgentClassName(name)].filter(Boolean)),\n );\n}\n","/**\n * AgentConfig - Persistent configuration storage for agents\n *\n * This module provides database-backed configuration for agents,\n * enabling consuming apps to persist agent settings.\n *\n * @module\n */\n\nimport {\n field,\n type SmrtClassOptions,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n queryGlobal,\n queryWithGlobals,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport { getAgentTypeName } from './identity.js';\n\n/**\n * AgentConfig stores agent configuration in the database\n *\n * Each config record maps to a UI slot for an agent instance:\n * - agentId: The agent instance's ID\n * - agentClass: The canonical agent type (qualified name when available)\n * - slotId: The configuration slot (e.g., 'sources', 'settings')\n * - configData: JSON object containing the configuration\n *\n * @example\n * ```typescript\n * // Save config for an agent slot\n * const config = new AgentConfig({\n * agentId: agent.id,\n * agentClass: 'Praeco',\n * slotId: 'sources',\n * configData: { scrapers: ['civicweb', 'govstack'] },\n * db: options.db\n * });\n * await config.initialize();\n * await config.save();\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'agent_configs',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class AgentConfig extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global agent configs\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * ID of the agent instance this config belongs to\n */\n @field({ type: 'text' })\n agentId: string = '';\n\n /**\n * Canonical agent type for this config (qualified name when available)\n */\n @field({ type: 'text' })\n agentClass: string = '';\n\n /**\n * UI slot ID (e.g., 'sources', 'settings', 'reports')\n */\n @field({ type: 'text' })\n slotId: string = '';\n\n /**\n * Configuration data stored as JSON\n *\n * Sensitive (#1540): agent config blobs routinely carry API keys/credentials,\n * so this is excluded from generated API/MCP responses and rejected as a\n * `where` filter key.\n */\n @field({ type: 'json', sensitive: true })\n configData: Record<string, unknown> = {};\n\n /**\n * Schema version for future migrations\n */\n @field({ type: 'integer' })\n schemaVersion: number = 1;\n\n /**\n * Load all configs for a specific agent\n *\n * @param agentId - Agent instance ID\n * @param options - Database options\n * @returns Map of slotId → configData\n */\n static async forAgent(\n agentId: string,\n options: SmrtClassOptions,\n ): Promise<Map<string, Record<string, unknown>>> {\n const configsByAgent = await AgentConfig.forAgents([agentId], options);\n return configsByAgent.get(agentId) ?? new Map();\n }\n\n /**\n * Load configs for multiple agents in a single query.\n *\n * @param agentIds - Agent instance IDs\n * @param options - Database options\n * @returns Map of agentId -> (slotId -> configData)\n */\n static async forAgents(\n agentIds: string[],\n options: SmrtClassOptions,\n ): Promise<Map<string, Map<string, Record<string, unknown>>>> {\n const configsByAgent = new Map<\n string,\n Map<string, Record<string, unknown>>\n >();\n if (agentIds.length === 0) {\n return configsByAgent;\n }\n\n const collection = await AgentConfigCollection.create(options);\n const configs = await collection.list({\n where: { 'agentId in': agentIds },\n });\n\n for (const config of configs) {\n if (!configsByAgent.has(config.agentId)) {\n configsByAgent.set(config.agentId, new Map());\n }\n configsByAgent.get(config.agentId)?.set(config.slotId, config.configData);\n }\n\n return configsByAgent;\n }\n\n /**\n * Load config for a specific agent and slot\n *\n * @param agentId - Agent instance ID\n * @param slotId - UI slot ID\n * @param options - Database options\n * @returns Config data or undefined if not found\n */\n static async forSlot(\n agentId: string,\n slotId: string,\n options: SmrtClassOptions,\n ): Promise<Record<string, unknown> | undefined> {\n const collection = await AgentConfigCollection.create(options);\n const configs = await collection.list({\n where: { agentId, slotId },\n limit: 1,\n });\n return configs[0]?.configData;\n }\n\n /**\n * Save or update config for an agent slot\n *\n * @param data - Config data including agentId, agentClass, slotId, configData\n * @param options - Database options\n * @returns Saved AgentConfig instance\n */\n static async saveSlot(\n data: {\n agentId: string;\n agentClass: string;\n slotId: string;\n configData: Record<string, unknown>;\n },\n options: SmrtClassOptions,\n ): Promise<AgentConfig> {\n const normalizedAgentClass = getAgentTypeName(data.agentClass);\n const collection = await AgentConfigCollection.create(options);\n\n // Check for existing config using list with where clause\n const existingConfigs = await collection.list({\n where: { agentId: data.agentId, slotId: data.slotId },\n limit: 1,\n });\n\n if (existingConfigs.length > 0) {\n // Update existing\n const existing = existingConfigs[0];\n existing.configData = data.configData;\n existing.agentClass = normalizedAgentClass;\n await existing.save();\n return existing;\n }\n\n // Create new\n const config = await collection.create({\n agentId: data.agentId,\n agentClass: normalizedAgentClass,\n slotId: data.slotId,\n configData: data.configData,\n slug: `${data.agentId}-${data.slotId}`,\n });\n await config.save();\n return config;\n }\n}\n\n/**\n * Collection for AgentConfig objects\n */\nexport class AgentConfigCollection extends SmrtCollection<AgentConfig> {\n static readonly _itemClass = AgentConfig;\n\n /**\n * Find all configs for a specific tenant\n * @param tenantId - Tenant ID to filter by\n * @returns Array of AgentConfig objects for the tenant\n */\n async findByTenant(tenantId: string): Promise<AgentConfig[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global configs (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global AgentConfig objects\n */\n async findGlobal(): Promise<AgentConfig[]> {\n return queryGlobal<AgentConfig>(this);\n }\n\n /**\n * Find configs for a tenant including global configs.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to include\n * @returns Array of AgentConfig objects for the tenant and global configs\n */\n async findWithGlobals(tenantId: string): Promise<AgentConfig[]> {\n return queryWithGlobals<AgentConfig>(\n this,\n tenantId,\n 'AgentConfig.findWithGlobals',\n );\n }\n}\n"],"names":["tenantId"],"mappings":"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"}