@happyvertical/smrt-core 0.44.1 → 0.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/agents/change-feed.md +3 -2
  2. package/dist/browser.js +2 -1
  3. package/dist/change-feed.d.ts +60 -1
  4. package/dist/change-feed.d.ts.map +1 -1
  5. package/dist/change-feed.js +464 -27
  6. package/dist/change-feed.js.map +1 -1
  7. package/dist/change-signals.d.ts.map +1 -1
  8. package/dist/change-signals.js +13 -11
  9. package/dist/change-signals.js.map +1 -1
  10. package/dist/generators/cli.d.ts.map +1 -1
  11. package/dist/generators/cli.js +10 -18
  12. package/dist/generators/cli.js.map +1 -1
  13. package/dist/generators/custom-action.d.ts +216 -0
  14. package/dist/generators/custom-action.d.ts.map +1 -1
  15. package/dist/generators/custom-action.js +256 -1
  16. package/dist/generators/custom-action.js.map +1 -1
  17. package/dist/generators/index.d.ts +1 -1
  18. package/dist/generators/index.d.ts.map +1 -1
  19. package/dist/generators/index.js +2 -2
  20. package/dist/generators/mcp.d.ts.map +1 -1
  21. package/dist/generators/mcp.js +14 -39
  22. package/dist/generators/mcp.js.map +1 -1
  23. package/dist/generators/rest.d.ts.map +1 -1
  24. package/dist/generators/rest.js +2 -0
  25. package/dist/generators/rest.js.map +1 -1
  26. package/dist/generators/tool-schema.d.ts.map +1 -1
  27. package/dist/generators/tool-schema.js +2 -8
  28. package/dist/generators/tool-schema.js.map +1 -1
  29. package/dist/generators.js +2 -2
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +4 -3
  33. package/dist/knowledge.d.ts.map +1 -1
  34. package/dist/knowledge.js +283 -35
  35. package/dist/knowledge.js.map +1 -1
  36. package/dist/manifest/static-manifest.js +1 -1
  37. package/dist/manifest/static-manifest.js.map +1 -1
  38. package/dist/manifest/store.js +1 -1
  39. package/dist/manifest.json +1 -1
  40. package/dist/registry/framework-base-classes.d.ts +10 -0
  41. package/dist/registry/framework-base-classes.d.ts.map +1 -0
  42. package/dist/registry/framework-base-classes.js +92 -0
  43. package/dist/registry/framework-base-classes.js.map +1 -0
  44. package/dist/registry/schema-builder.d.ts.map +1 -1
  45. package/dist/registry/schema-builder.js +2 -0
  46. package/dist/registry/schema-builder.js.map +1 -1
  47. package/dist/registry/types.d.ts +27 -6
  48. package/dist/registry/types.d.ts.map +1 -1
  49. package/dist/registry.d.ts +1 -0
  50. package/dist/registry.d.ts.map +1 -1
  51. package/dist/registry.js +2 -1
  52. package/dist/registry.js.map +1 -1
  53. package/dist/scanner/manifest-generator.d.ts +46 -16
  54. package/dist/scanner/manifest-generator.d.ts.map +1 -1
  55. package/dist/scanner/manifest-generator.js +198 -45
  56. package/dist/scanner/manifest-generator.js.map +1 -1
  57. package/dist/smrt-knowledge.json +5 -5
  58. package/dist/system/bootstrap.d.ts.map +1 -1
  59. package/dist/system/bootstrap.js +2 -1
  60. package/dist/system/bootstrap.js.map +1 -1
  61. package/dist/system/schema.d.ts +75 -2
  62. package/dist/system/schema.d.ts.map +1 -1
  63. package/dist/system/schema.js +326 -4
  64. package/dist/system/schema.js.map +1 -1
  65. package/dist/vite-plugin/index.d.ts +10 -0
  66. package/dist/vite-plugin/index.d.ts.map +1 -1
  67. package/dist/vite-plugin/index.js +52 -23
  68. package/dist/vite-plugin/index.js.map +1 -1
  69. package/dist/vite-plugin/resources-route.d.ts +18 -0
  70. package/dist/vite-plugin/resources-route.d.ts.map +1 -0
  71. package/dist/vite-plugin/resources-route.js +154 -0
  72. package/dist/vite-plugin/resources-route.js.map +1 -0
  73. package/dist/vite-plugin/sveltekit-generator.d.ts +43 -7
  74. package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
  75. package/dist/vite-plugin/sveltekit-generator.js +90 -17
  76. package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
  77. package/dist/vite-plugin/sync-apply-route.d.ts.map +1 -1
  78. package/dist/vite-plugin/sync-apply-route.js +2 -0
  79. package/dist/vite-plugin/sync-apply-route.js.map +1 -1
  80. package/dist/vite-plugin/web-collections.d.ts.map +1 -1
  81. package/dist/vite-plugin/web-collections.js +28 -5
  82. package/dist/vite-plugin/web-collections.js.map +1 -1
  83. package/package.json +4 -4
@@ -1,4 +1,5 @@
1
1
  import { DETERMINISTIC_GENERATED_AT } from "../scanner/types.js";
2
+ import { resolveCustomActionNames } from "../generators/custom-action.js";
2
3
  import { findCliApiCoherenceViolations, generateSvelteKitRoutes, methodNameToKebab, resolveApiActionRouteConfig, resolveApiActionSet, validateCliIncludeAgainstApi } from "./sveltekit-generator.js";
3
4
  import { buildWebCollectionDefinition, buildWebMcpToolDefinitions, buildWebToolDescriptors, computeWebManifestHash, selectWebCollectionEntries } from "./web-collections.js";
4
5
  import { buildDomainKnowledgeManifest } from "../knowledge.js";
@@ -136,12 +137,25 @@ function smrtPlugin(options = {}) {
136
137
  * so an in-flight decorator edit doesn't kill the dev server. Uses the same
137
138
  * remediation text as the strict build-time gate (`validateCliIncludeAgainstApi`)
138
139
  * so the dev-server message is as actionable as the build failure.
140
+ *
141
+ * `findCliApiCoherenceViolations` (#2638) now reports a violation for any
142
+ * `cli` config shape, including a bare `cli: true`/`cli: {}` default, but
143
+ * `validateCliIncludeAgainstApi` only THROWS for a class with a non-empty,
144
+ * explicit `cli.include` (see that function's doc comment for why: the
145
+ * broader default-surface population is real but unrelated pre-existing
146
+ * over-exposure this repo hasn't triaged, not a #2638 defect). So this
147
+ * warning must not unconditionally claim the build will fail — only an
148
+ * explicit `cli.include` naming the action makes that true today.
139
149
  */
140
150
  function warnCliApiCoherenceViolations(m) {
141
151
  if (!validateCliApiCoherence) return;
142
152
  const violations = findCliApiCoherenceViolations(m);
143
153
  if (violations.length === 0) return;
144
- for (const { className, unreachable } of violations) for (const action of unreachable) console.warn(`[smrt] ${className}.${action} is declared in cli.include but is not exposed via the api. Build will fail until this is resolved.\n Either:\n - Add '${action}' to api.include, or\n - Remove '${action}' from cli.include.\n The CLI invokes methods over HTTP; methods without API routes are unreachable.\n If this CLI is intentionally invoked in-process (no HTTP), set\n \`cli: { skipApiCheck: true }\` on the @smrt() decorator to acknowledge.`);
154
+ for (const { className, unreachable } of violations) {
155
+ const cliConfig = m.objects[className]?.decoratorConfig?.cli;
156
+ const isEnforced = typeof cliConfig === "object" && Array.isArray(cliConfig.include) && cliConfig.include.length > 0;
157
+ for (const action of unreachable) console.warn(`[smrt] ${className}.${action} is exposed as a CLI command but is not exposed via the api.` + (isEnforced ? " Build will fail until this is resolved.\n" : " (Not yet build-blocking for this cli:true/{} class -- see #2638.)\n") + ` Either:\n - Add '${action}' to api.include, or\n - Remove '${action}' from cli.include / add it to cli.exclude.\n The CLI invokes methods over HTTP; methods without API routes are unreachable.\n If this CLI is intentionally invoked in-process (no HTTP), set\n \`cli: { skipApiCheck: true }\` on the @smrt() decorator to acknowledge.`);
158
+ }
145
159
  }
146
160
  let server;
147
161
  let manifest = null;
@@ -168,6 +182,7 @@ function smrtPlugin(options = {}) {
168
182
  kebabRoutes: svelteKit.kebabRoutes ?? false,
169
183
  changesRoute: svelteKit.changesRoute,
170
184
  eventsRoute: svelteKit.eventsRoute,
185
+ resourcesRoute: svelteKit.resourcesRoute,
171
186
  knowledge: await resolveKnowledgeConfig(rootDir, currentManifest)
172
187
  });
173
188
  }
@@ -419,6 +434,7 @@ function smrtPlugin(options = {}) {
419
434
  kebabRoutes: svelteKit.kebabRoutes ?? false,
420
435
  changesRoute: svelteKit.changesRoute,
421
436
  eventsRoute: svelteKit.eventsRoute,
437
+ resourcesRoute: svelteKit.resourcesRoute,
422
438
  knowledge: await resolveKnowledgeConfig(projectRoot, manifest)
423
439
  });
424
440
  Object.values(VIRTUAL_MODULES).forEach((id) => {
@@ -448,6 +464,7 @@ function smrtPlugin(options = {}) {
448
464
  kebabRoutes: svelteKit.kebabRoutes ?? false,
449
465
  changesRoute: svelteKit.changesRoute,
450
466
  eventsRoute: svelteKit.eventsRoute,
467
+ resourcesRoute: svelteKit.resourcesRoute,
451
468
  knowledge: await resolveKnowledgeConfig(projectRoot, manifest)
452
469
  });
453
470
  }
@@ -473,6 +490,7 @@ function smrtPlugin(options = {}) {
473
490
  kebabRoutes: svelteKit.kebabRoutes ?? false,
474
491
  changesRoute: svelteKit.changesRoute,
475
492
  eventsRoute: svelteKit.eventsRoute,
493
+ resourcesRoute: svelteKit.resourcesRoute,
476
494
  knowledge: await resolveKnowledgeConfig(projectRoot, manifest)
477
495
  });
478
496
  }
@@ -744,7 +762,7 @@ async function generateMCPModule(manifest) {
744
762
 
745
763
  import { SmrtMCPServer } from '@happyvertical/smrt-core/runtime';
746
764
 
747
- export const tools = ${new ManifestGenerator().generateMCPTools(manifest)};
765
+ export const tools = ${new ManifestGenerator().generateMCPToolsCode(manifest)};
748
766
 
749
767
  export function createMCPServer(options = {}) {
750
768
  const server = new SmrtMCPServer({
@@ -753,12 +771,19 @@ export function createMCPServer(options = {}) {
753
771
  ...options
754
772
  });
755
773
 
756
- // Add all generated tools to the server
774
+ // Add all generated tools to the server. A handler supplied through the
775
+ // documented \`createMCPServer({ handlers })\` option wins; the throwing
776
+ // placeholder is only for tools the application did not wire up (#2631).
777
+ const handlers = options.handlers || {};
757
778
  for (const tool of tools) {
758
- server.addTool(tool, async (params) => {
759
- // Tool execution will be handled by the application
760
- throw new Error(\`Tool '\${tool.name}' handler must be provided by application\`);
761
- });
779
+ const handler = handlers[tool.name];
780
+ server.addTool(
781
+ tool,
782
+ handler ||
783
+ (async () => {
784
+ throw new Error(\`Tool '\${tool.name}' handler must be provided by application\`);
785
+ }),
786
+ );
762
787
  }
763
788
 
764
789
  return server;
@@ -787,7 +812,8 @@ export function createMCPServer(options = {}) {
787
812
  */
788
813
  function generateClientModeTypes(manifest) {
789
814
  const typeDefinitions = [];
790
- for (const [objectName, objectMeta] of Object.entries(manifest.objects)) {
815
+ for (const objectMeta of Object.values(manifest.objects)) {
816
+ const interfaceName = objectMeta.className;
791
817
  const fields = objectMeta.fields || {};
792
818
  const propertyLines = [];
793
819
  for (const [fieldName, fieldDef] of Object.entries(fields)) {
@@ -818,7 +844,7 @@ function generateClientModeTypes(manifest) {
818
844
  propertyLines.push(` ${fieldName}${optional}: ${type};`);
819
845
  }
820
846
  propertyLines.unshift(" id?: string;", " created_at?: string;", " updated_at?: string;");
821
- const interfaceDef = `export interface ${objectName}Data {\n${propertyLines.join("\n")}\n}`;
847
+ const interfaceDef = `export interface ${interfaceName}Data {\n${propertyLines.join("\n")}\n}`;
822
848
  typeDefinitions.push(interfaceDef);
823
849
  }
824
850
  return typeDefinitions.join("\n\n");
@@ -1327,29 +1353,32 @@ async function generateCLIModule(manifest) {
1327
1353
  return true;
1328
1354
  };
1329
1355
  const collectionName = objectDef.collection;
1330
- const commandName = (objectDef.className || className).toLowerCase();
1331
- objectImports.push(`// Import ${className} and ${className}Collection for CLI operations`);
1356
+ const simpleClassName = objectDef.className || className;
1357
+ const commandName = simpleClassName.toLowerCase();
1358
+ objectImports.push(`// Import ${simpleClassName} for CLI operations`);
1332
1359
  const availableCommands = [];
1333
1360
  if (shouldInclude("list")) availableCommands.push(`'${commandName}:list'`);
1334
1361
  if (shouldInclude("get")) availableCommands.push(`'${commandName}:get'`);
1335
1362
  if (shouldInclude("create")) availableCommands.push(`'${commandName}:create'`);
1336
1363
  if (shouldInclude("update")) availableCommands.push(`'${commandName}:update'`);
1337
1364
  if (shouldInclude("delete")) availableCommands.push(`'${commandName}:delete'`);
1338
- for (const [methodName, _method] of Object.entries(objectDef.methods)) {
1339
- if (methodName.startsWith("_") || [
1340
- "list",
1341
- "get",
1342
- "create",
1343
- "update",
1344
- "delete",
1345
- "save"
1346
- ].includes(methodName)) continue;
1365
+ for (const methodName of resolveCustomActionNames(Object.entries(objectDef.methods), {
1366
+ include: included ?? void 0,
1367
+ exclude: excluded
1368
+ }, [
1369
+ "list",
1370
+ "get",
1371
+ "create",
1372
+ "update",
1373
+ "delete"
1374
+ ])) {
1375
+ if (methodName.startsWith("_")) continue;
1347
1376
  if (shouldInclude(methodName)) availableCommands.push(`'${commandName}:${methodName}'`);
1348
1377
  }
1349
1378
  if (availableCommands.length > 0) commands.push(`
1350
- // ${className} commands
1351
- ${className}: {
1352
- collection: '${collectionName}',
1379
+ // ${simpleClassName} commands
1380
+ ${JSON.stringify(simpleClassName)}: {
1381
+ collection: ${JSON.stringify(collectionName)},
1353
1382
  commands: [${availableCommands.join(", ")}]
1354
1383
  }`);
1355
1384
  }