@happyvertical/smrt-core 0.44.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/AGENTS.md +8 -8
  2. package/agents/change-feed.md +3 -2
  3. package/agents/generators.md +34 -0
  4. package/agents/revision-guard.md +66 -0
  5. package/dist/browser.js +2 -1
  6. package/dist/cascade.d.ts +5 -9
  7. package/dist/cascade.d.ts.map +1 -1
  8. package/dist/cascade.js +65 -30
  9. package/dist/cascade.js.map +1 -1
  10. package/dist/change-feed.d.ts +60 -1
  11. package/dist/change-feed.d.ts.map +1 -1
  12. package/dist/change-feed.js +464 -27
  13. package/dist/change-feed.js.map +1 -1
  14. package/dist/change-signals.d.ts.map +1 -1
  15. package/dist/change-signals.js +13 -11
  16. package/dist/change-signals.js.map +1 -1
  17. package/dist/embedded-write-queue.d.ts +8 -0
  18. package/dist/embedded-write-queue.d.ts.map +1 -1
  19. package/dist/embedded-write-queue.js +12 -2
  20. package/dist/embedded-write-queue.js.map +1 -1
  21. package/dist/generators/cli.d.ts.map +1 -1
  22. package/dist/generators/cli.js +10 -18
  23. package/dist/generators/cli.js.map +1 -1
  24. package/dist/generators/custom-action.d.ts +216 -0
  25. package/dist/generators/custom-action.d.ts.map +1 -1
  26. package/dist/generators/custom-action.js +256 -1
  27. package/dist/generators/custom-action.js.map +1 -1
  28. package/dist/generators/index.d.ts +2 -1
  29. package/dist/generators/index.d.ts.map +1 -1
  30. package/dist/generators/index.js +3 -2
  31. package/dist/generators/mcp.d.ts.map +1 -1
  32. package/dist/generators/mcp.js +14 -39
  33. package/dist/generators/mcp.js.map +1 -1
  34. package/dist/generators/preflight-route.d.ts +151 -0
  35. package/dist/generators/preflight-route.d.ts.map +1 -0
  36. package/dist/generators/preflight-route.js +194 -0
  37. package/dist/generators/preflight-route.js.map +1 -0
  38. package/dist/generators/rest.d.ts +12 -0
  39. package/dist/generators/rest.d.ts.map +1 -1
  40. package/dist/generators/rest.js +14 -15
  41. package/dist/generators/rest.js.map +1 -1
  42. package/dist/generators/tool-schema.d.ts.map +1 -1
  43. package/dist/generators/tool-schema.js +2 -8
  44. package/dist/generators/tool-schema.js.map +1 -1
  45. package/dist/generators.js +3 -2
  46. package/dist/index.d.ts +3 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +7 -4
  49. package/dist/knowledge.d.ts.map +1 -1
  50. package/dist/knowledge.js +283 -35
  51. package/dist/knowledge.js.map +1 -1
  52. package/dist/manifest/static-manifest.d.ts.map +1 -1
  53. package/dist/manifest/static-manifest.js +6 -2
  54. package/dist/manifest/static-manifest.js.map +1 -1
  55. package/dist/manifest/store.js +1 -1
  56. package/dist/manifest/store.js.map +1 -1
  57. package/dist/manifest.json +8 -2
  58. package/dist/object.d.ts +31 -1
  59. package/dist/object.d.ts.map +1 -1
  60. package/dist/object.js +57 -9
  61. package/dist/object.js.map +1 -1
  62. package/dist/registry/framework-base-classes.d.ts +10 -0
  63. package/dist/registry/framework-base-classes.d.ts.map +1 -0
  64. package/dist/registry/framework-base-classes.js +92 -0
  65. package/dist/registry/framework-base-classes.js.map +1 -0
  66. package/dist/registry/schema-builder.d.ts.map +1 -1
  67. package/dist/registry/schema-builder.js +2 -0
  68. package/dist/registry/schema-builder.js.map +1 -1
  69. package/dist/registry/types.d.ts +27 -6
  70. package/dist/registry/types.d.ts.map +1 -1
  71. package/dist/registry.d.ts +1 -0
  72. package/dist/registry.d.ts.map +1 -1
  73. package/dist/registry.js +2 -1
  74. package/dist/registry.js.map +1 -1
  75. package/dist/revision-guard.d.ts +84 -0
  76. package/dist/revision-guard.d.ts.map +1 -0
  77. package/dist/revision-guard.js +120 -0
  78. package/dist/revision-guard.js.map +1 -0
  79. package/dist/scanner/manifest-generator.d.ts +46 -16
  80. package/dist/scanner/manifest-generator.d.ts.map +1 -1
  81. package/dist/scanner/manifest-generator.js +198 -45
  82. package/dist/scanner/manifest-generator.js.map +1 -1
  83. package/dist/smrt-knowledge.json +18 -9
  84. package/dist/system/bootstrap.d.ts.map +1 -1
  85. package/dist/system/bootstrap.js +2 -1
  86. package/dist/system/bootstrap.js.map +1 -1
  87. package/dist/system/schema.d.ts +75 -2
  88. package/dist/system/schema.d.ts.map +1 -1
  89. package/dist/system/schema.js +326 -4
  90. package/dist/system/schema.js.map +1 -1
  91. package/dist/vite-plugin/index.d.ts.map +1 -1
  92. package/dist/vite-plugin/index.js +48 -23
  93. package/dist/vite-plugin/index.js.map +1 -1
  94. package/dist/vite-plugin/sveltekit-generator.d.ts +33 -7
  95. package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
  96. package/dist/vite-plugin/sveltekit-generator.js +88 -17
  97. package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
  98. package/dist/vite-plugin/sync-apply-route.d.ts.map +1 -1
  99. package/dist/vite-plugin/sync-apply-route.js +2 -0
  100. package/dist/vite-plugin/sync-apply-route.js.map +1 -1
  101. package/dist/vite-plugin/web-collections.d.ts.map +1 -1
  102. package/dist/vite-plugin/web-collections.js +28 -5
  103. package/dist/vite-plugin/web-collections.js.map +1 -1
  104. 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;
@@ -744,7 +758,7 @@ async function generateMCPModule(manifest) {
744
758
 
745
759
  import { SmrtMCPServer } from '@happyvertical/smrt-core/runtime';
746
760
 
747
- export const tools = ${new ManifestGenerator().generateMCPTools(manifest)};
761
+ export const tools = ${new ManifestGenerator().generateMCPToolsCode(manifest)};
748
762
 
749
763
  export function createMCPServer(options = {}) {
750
764
  const server = new SmrtMCPServer({
@@ -753,12 +767,19 @@ export function createMCPServer(options = {}) {
753
767
  ...options
754
768
  });
755
769
 
756
- // Add all generated tools to the server
770
+ // Add all generated tools to the server. A handler supplied through the
771
+ // documented \`createMCPServer({ handlers })\` option wins; the throwing
772
+ // placeholder is only for tools the application did not wire up (#2631).
773
+ const handlers = options.handlers || {};
757
774
  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
- });
775
+ const handler = handlers[tool.name];
776
+ server.addTool(
777
+ tool,
778
+ handler ||
779
+ (async () => {
780
+ throw new Error(\`Tool '\${tool.name}' handler must be provided by application\`);
781
+ }),
782
+ );
762
783
  }
763
784
 
764
785
  return server;
@@ -787,7 +808,8 @@ export function createMCPServer(options = {}) {
787
808
  */
788
809
  function generateClientModeTypes(manifest) {
789
810
  const typeDefinitions = [];
790
- for (const [objectName, objectMeta] of Object.entries(manifest.objects)) {
811
+ for (const objectMeta of Object.values(manifest.objects)) {
812
+ const interfaceName = objectMeta.className;
791
813
  const fields = objectMeta.fields || {};
792
814
  const propertyLines = [];
793
815
  for (const [fieldName, fieldDef] of Object.entries(fields)) {
@@ -818,7 +840,7 @@ function generateClientModeTypes(manifest) {
818
840
  propertyLines.push(` ${fieldName}${optional}: ${type};`);
819
841
  }
820
842
  propertyLines.unshift(" id?: string;", " created_at?: string;", " updated_at?: string;");
821
- const interfaceDef = `export interface ${objectName}Data {\n${propertyLines.join("\n")}\n}`;
843
+ const interfaceDef = `export interface ${interfaceName}Data {\n${propertyLines.join("\n")}\n}`;
822
844
  typeDefinitions.push(interfaceDef);
823
845
  }
824
846
  return typeDefinitions.join("\n\n");
@@ -1327,29 +1349,32 @@ async function generateCLIModule(manifest) {
1327
1349
  return true;
1328
1350
  };
1329
1351
  const collectionName = objectDef.collection;
1330
- const commandName = (objectDef.className || className).toLowerCase();
1331
- objectImports.push(`// Import ${className} and ${className}Collection for CLI operations`);
1352
+ const simpleClassName = objectDef.className || className;
1353
+ const commandName = simpleClassName.toLowerCase();
1354
+ objectImports.push(`// Import ${simpleClassName} for CLI operations`);
1332
1355
  const availableCommands = [];
1333
1356
  if (shouldInclude("list")) availableCommands.push(`'${commandName}:list'`);
1334
1357
  if (shouldInclude("get")) availableCommands.push(`'${commandName}:get'`);
1335
1358
  if (shouldInclude("create")) availableCommands.push(`'${commandName}:create'`);
1336
1359
  if (shouldInclude("update")) availableCommands.push(`'${commandName}:update'`);
1337
1360
  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;
1361
+ for (const methodName of resolveCustomActionNames(Object.entries(objectDef.methods), {
1362
+ include: included ?? void 0,
1363
+ exclude: excluded
1364
+ }, [
1365
+ "list",
1366
+ "get",
1367
+ "create",
1368
+ "update",
1369
+ "delete"
1370
+ ])) {
1371
+ if (methodName.startsWith("_")) continue;
1347
1372
  if (shouldInclude(methodName)) availableCommands.push(`'${commandName}:${methodName}'`);
1348
1373
  }
1349
1374
  if (availableCommands.length > 0) commands.push(`
1350
- // ${className} commands
1351
- ${className}: {
1352
- collection: '${collectionName}',
1375
+ // ${simpleClassName} commands
1376
+ ${JSON.stringify(simpleClassName)}: {
1377
+ collection: ${JSON.stringify(collectionName)},
1353
1378
  commands: [${availableCommands.join(", ")}]
1354
1379
  }`);
1355
1380
  }