@happyvertical/smrt-core 0.51.36 → 0.51.38
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/agents/build-knowledge.md +25 -0
- package/agents/generators.md +27 -0
- package/dist/consumer-plugin/artifact-publication.d.ts +2 -0
- package/dist/consumer-plugin/artifact-publication.d.ts.map +1 -1
- package/dist/consumer-plugin/artifact-publication.js +15 -1
- package/dist/consumer-plugin/artifact-publication.js.map +1 -1
- package/dist/consumer-plugin/index.d.ts.map +1 -1
- package/dist/consumer-plugin/index.js +3 -3
- package/dist/consumer-plugin/index.js.map +1 -1
- package/dist/generators/mcp-runtime-template.d.ts +17 -0
- package/dist/generators/mcp-runtime-template.d.ts.map +1 -1
- package/dist/generators/mcp-runtime-template.js +27 -19
- package/dist/generators/mcp-runtime-template.js.map +1 -1
- package/dist/generators/mcp-tool-name.d.ts +17 -0
- package/dist/generators/mcp-tool-name.d.ts.map +1 -0
- package/dist/generators/mcp-tool-name.js +33 -0
- package/dist/generators/mcp-tool-name.js.map +1 -0
- package/dist/generators/mcp.d.ts +46 -1
- package/dist/generators/mcp.d.ts.map +1 -1
- package/dist/generators/mcp.js +105 -53
- package/dist/generators/mcp.js.map +1 -1
- package/dist/generators/tool-schema.d.ts +6 -0
- package/dist/generators/tool-schema.d.ts.map +1 -1
- package/dist/generators/tool-schema.js +8 -3
- package/dist/generators/tool-schema.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/knowledge.d.ts +2 -0
- package/dist/knowledge.d.ts.map +1 -1
- package/dist/knowledge.js +3 -1
- package/dist/knowledge.js.map +1 -1
- package/dist/manifest/discover-base-classes.js +2 -2
- package/dist/manifest/discover-base-classes.js.map +1 -1
- package/dist/manifest/discover-smrt-packages.d.ts.map +1 -1
- package/dist/manifest/discover-smrt-packages.js +3 -2
- package/dist/manifest/discover-smrt-packages.js.map +1 -1
- package/dist/manifest/generator.d.ts +7 -0
- package/dist/manifest/generator.d.ts.map +1 -1
- package/dist/manifest/generator.js +30 -15
- package/dist/manifest/generator.js.map +1 -1
- package/dist/manifest/manager.d.ts.map +1 -1
- package/dist/manifest/manager.js +6 -2
- package/dist/manifest/manager.js.map +1 -1
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/node_modules/.pnpm/{brace-expansion@5.0.9 → brace-expansion@5.0.11}/node_modules/brace-expansion/dist/esm/index.js +32 -19
- package/dist/node_modules/.pnpm/brace-expansion@5.0.11/node_modules/brace-expansion/dist/esm/index.js.map +1 -0
- package/dist/node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/dist/esm/index.js +1 -1
- package/dist/scanner/types.d.ts +2 -0
- package/dist/scanner/types.d.ts.map +1 -1
- package/dist/scanner/types.js.map +1 -1
- package/dist/scripts/generate-manifest.js +44 -44
- package/dist/scripts/generate-test-manifest.js +49 -2
- package/dist/smrt-knowledge.json +7 -7
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +16 -6
- package/dist/vite-plugin/index.js.map +1 -1
- package/package.json +4 -4
- package/dist/node_modules/.pnpm/brace-expansion@5.0.9/node_modules/brace-expansion/dist/esm/index.js.map +0 -1
|
@@ -131,6 +131,12 @@ export declare function buildToolDescriptors(opts: {
|
|
|
131
131
|
toolPrefix?: string;
|
|
132
132
|
idType?: ToolIdType;
|
|
133
133
|
}): ToolDescriptor[];
|
|
134
|
+
/**
|
|
135
|
+
* Resolve the one canonical capability classification used by generated MCP
|
|
136
|
+
* and WebMCP descriptors. Consumers that author a tool outside a model must
|
|
137
|
+
* declare this same shape rather than infer safety from a name or HTTP verb.
|
|
138
|
+
*/
|
|
139
|
+
export declare function resolveToolSemantics(action: string, customAction?: CustomActionMetadata): Pick<ToolDescriptor, 'effect' | 'idempotent' | 'openWorld'>;
|
|
134
140
|
/** True when `action` is one of the fixed CRUD verbs (vs. a custom method). */
|
|
135
141
|
export declare function isCrudAction(action: string): boolean;
|
|
136
142
|
//# sourceMappingURL=tool-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-schema.d.ts","sourceRoot":"","sources":["../../src/generators/tool-schema.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"tool-schema.d.ts","sourceRoot":"","sources":["../../src/generators/tool-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -231,7 +231,7 @@ function buildToolDescriptors(opts) {
|
|
|
231
231
|
const prefix = (opts.toolPrefix ?? className).toLowerCase();
|
|
232
232
|
return actions.map((action) => {
|
|
233
233
|
const customAction = opts.customActions?.[action];
|
|
234
|
-
const semantics =
|
|
234
|
+
const semantics = resolveToolSemantics(action, customAction);
|
|
235
235
|
return {
|
|
236
236
|
action,
|
|
237
237
|
name: `${prefix}_${action}`.toLowerCase(),
|
|
@@ -242,7 +242,12 @@ function buildToolDescriptors(opts) {
|
|
|
242
242
|
};
|
|
243
243
|
});
|
|
244
244
|
}
|
|
245
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Resolve the one canonical capability classification used by generated MCP
|
|
247
|
+
* and WebMCP descriptors. Consumers that author a tool outside a model must
|
|
248
|
+
* declare this same shape rather than infer safety from a name or HTTP verb.
|
|
249
|
+
*/
|
|
250
|
+
function resolveToolSemantics(action, customAction) {
|
|
246
251
|
switch (action) {
|
|
247
252
|
case "list":
|
|
248
253
|
case "get": return {
|
|
@@ -277,6 +282,6 @@ function isCrudAction(action) {
|
|
|
277
282
|
return CRUD_ACTIONS.has(action);
|
|
278
283
|
}
|
|
279
284
|
//#endregion
|
|
280
|
-
export { JSON_SCHEMA_2020_12, MCP_SCHEMA_LIMITS, assertMcpJsonSchemaSafety, buildToolDescriptors, buildToolInputSchema, fieldTypeToJsonSchema, finalizeMcpJsonSchema, isCrudAction };
|
|
285
|
+
export { JSON_SCHEMA_2020_12, MCP_SCHEMA_LIMITS, assertMcpJsonSchemaSafety, buildToolDescriptors, buildToolInputSchema, fieldTypeToJsonSchema, finalizeMcpJsonSchema, isCrudAction, resolveToolSemantics };
|
|
281
286
|
|
|
282
287
|
//# sourceMappingURL=tool-schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-schema.js","names":[],"sources":["../../src/generators/tool-schema.ts"],"sourcesContent":["import {\n buildCustomActionInputSchema,\n CRUD_OPERATIONS,\n type CustomActionMetadata,\n type ToolEffect,\n} from './custom-action.js';\n\n/**\n * Transport-agnostic tool-descriptor builder (#1812, tracer).\n *\n * The single source of truth for turning a model's fields + exposed actions into\n * MCP-shaped tool descriptors (`{ name, description, inputSchema }`). This is the\n * shape both the Model Context Protocol AND Chrome's WebMCP\n * (`document.modelContext.registerTool`) consume — see\n * https://developer.chrome.com/docs/ai/webmcp.\n *\n * It is deliberately pure and free of `ObjectRegistry` / manifest coupling: it\n * takes a normalized {@link ToolFieldMeta}[] so BOTH callers can share it —\n * - `MCPGenerator` (`src/generators/mcp.ts`) for the Node stdio server, and\n * - the web-collections emitter (`src/vite-plugin/web-collections.ts`) for the\n * browser client-data runtime's WebMCP descriptors.\n *\n * Keeping one implementation removes the field-mapping drift risk the\n * \"three emission sites must agree\" contract in web-collections.ts already warns\n * about. The `fieldTypeToJsonSchema` / per-action skeletons below are ported\n * verbatim from mcp.ts's `fieldToMCPSchema` + `generateObjectTools`, so wiring\n * mcp.ts to call this helper is a mechanical, behavior-preserving refactor.\n */\n\n/**\n * A JSON Schema fragment. Values vary by field kind, so this is only ever\n * serialized into tool descriptors, never read back structurally.\n */\nexport type ToolJsonSchema = Record<string, unknown>;\n\n/** The only JSON Schema dialect emitted by generated MCP and WebMCP tools. */\nexport const JSON_SCHEMA_2020_12 =\n 'https://json-schema.org/draft/2020-12/schema';\n\n/**\n * Bounds for generated schemas. Field metadata is authored input, so it must\n * not turn a tools/list response into an unbounded composition or validation\n * workload. These limits are deliberately far above normal SMRT objects while\n * still keeping schemas comfortably inside MCP transport budgets.\n */\nexport const MCP_SCHEMA_LIMITS = {\n maxDepth: 16,\n maxNodes: 2_048,\n maxSerializedBytes: 65_536,\n} as const;\n\n/**\n * Apply the draft-2020-12 dialect and reject schemas that violate MCP's\n * bounded-composition contract. Generated schemas only ever reference local\n * `$defs`; external refs are neither emitted nor followed.\n */\nexport function finalizeMcpJsonSchema(schema: ToolJsonSchema): ToolJsonSchema {\n const finalized = {\n ...schema,\n $schema: JSON_SCHEMA_2020_12,\n };\n assertMcpJsonSchemaSafety(finalized);\n return finalized;\n}\n\n/**\n * Validate the resource envelope of an emitted schema without resolving refs.\n * This is intentionally structural rather than a general JSON-Schema\n * evaluator: the server already owns every schema it emits, and this guard\n * exists to keep authored metadata from introducing hostile shape growth.\n */\nexport function assertMcpJsonSchemaSafety(schema: ToolJsonSchema): void {\n let nodes = 0;\n const ancestors = new WeakSet<object>();\n\n const visit = (value: unknown, depth: number, key?: string): void => {\n nodes += 1;\n if (nodes > MCP_SCHEMA_LIMITS.maxNodes) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxNodes} nodes`,\n );\n }\n if (depth > MCP_SCHEMA_LIMITS.maxDepth) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxDepth} levels of depth`,\n );\n }\n if (key === '$ref') {\n if (\n typeof value !== 'string' ||\n !value.startsWith('#/$defs/') ||\n value.includes('://')\n ) {\n throw new Error(\n 'MCP JSON Schema may only use local #/$defs/ references',\n );\n }\n return;\n }\n if (value === null || typeof value !== 'object') return;\n if (ancestors.has(value)) {\n throw new Error('MCP JSON Schema must not contain cyclic values');\n }\n\n ancestors.add(value);\n if (Array.isArray(value)) {\n for (const entry of value) visit(entry, depth + 1);\n } else {\n for (const [childKey, child] of Object.entries(value)) {\n visit(child, depth + 1, childKey);\n }\n }\n ancestors.delete(value);\n };\n\n visit(schema, 0);\n\n let serialized: string;\n try {\n serialized = JSON.stringify(schema);\n } catch {\n throw new Error('MCP JSON Schema must be JSON-serializable');\n }\n if (\n new TextEncoder().encode(serialized).byteLength >\n MCP_SCHEMA_LIMITS.maxSerializedBytes\n ) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxSerializedBytes} serialized bytes`,\n );\n }\n}\n\n/**\n * Normalized field metadata — the intersection of what the runtime registry\n * (`FieldDefinition._meta`) and the build-time manifest (`WebFieldDefinition`)\n * can each supply. Callers flatten their own field source into this shape.\n */\nexport interface ToolFieldMeta {\n name: string;\n /** Field kind: text | integer | decimal | boolean | datetime | json | foreignKey | … */\n type: string;\n required?: boolean;\n description?: string;\n default?: unknown;\n maxLength?: number;\n minLength?: number;\n min?: number;\n max?: number;\n /** Field values may explicitly be null in the runtime/manifest contract. */\n nullable?: boolean;\n /** For `foreignKey`: the related class name, for the generated description. */\n related?: string;\n}\n\n/** Storage contract for the synthetic primary identifier. */\nexport type ToolIdType = 'uuid' | 'text';\n\n/** The CRUD verbs with dedicated input-schema skeletons; anything else is custom. */\nconst CRUD_ACTIONS = new Set<string>(CRUD_OPERATIONS);\n\nexport interface ToolRouteDescriptor {\n /** HTTP method emitted for the route. */\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n /** Whether the route targets one item or the whole collection. */\n scope: 'item' | 'collection';\n /** Route segments below the collection endpoint. Dynamic segments use `[x]`. */\n path: string[];\n /** Transport names rewritten by the tool schema (e.g. `actionId` → `id`). */\n parameterAliases?: Record<string, string>;\n /** The generated method accepts one `options` bag as its sole argument. */\n optionsBag?: boolean;\n}\n\n/** A single generated tool descriptor — the WebMCP / MCP tool shape. */\nexport interface ToolDescriptor {\n /** The action this tool performs (`list` | `get` | … | a custom method name). */\n action: string;\n /** Tool id, `${toolPrefix}_${action}` (e.g. `product_list`). */\n name: string;\n description: string;\n inputSchema: ToolJsonSchema;\n /** True when the declared effect is `read` → WebMCP `annotations.readOnlyHint`. */\n readOnly: boolean;\n /** Capability effect used by browser-tool exposure policy. */\n effect: ToolEffect;\n /** Whether repeating this tool with the same arguments is safe. */\n idempotent: boolean;\n /** Whether the tool may interact outside the SMRT application. */\n openWorld: boolean;\n /** Generated custom-route transport metadata, when the action has a route. */\n route?: ToolRouteDescriptor;\n}\n\n/**\n * Map one normalized field to its JSON-Schema fragment. Ported from\n * `MCPGenerator.fieldToMCPSchema` (mcp.ts) — keep the two in lockstep until\n * mcp.ts is switched to call this.\n */\nexport function fieldTypeToJsonSchema(field: ToolFieldMeta): ToolJsonSchema {\n const schema: ToolJsonSchema = {\n description: field.description || `${field.type} field`,\n };\n\n switch (field.type) {\n case 'text':\n schema.type = 'string';\n if (field.maxLength !== undefined) schema.maxLength = field.maxLength;\n if (field.minLength !== undefined) schema.minLength = field.minLength;\n break;\n case 'integer':\n schema.type = 'integer';\n if (field.min !== undefined) schema.minimum = field.min;\n if (field.max !== undefined) schema.maximum = field.max;\n break;\n case 'decimal':\n schema.type = 'number';\n if (field.min !== undefined) schema.minimum = field.min;\n if (field.max !== undefined) schema.maximum = field.max;\n break;\n case 'boolean':\n schema.type = 'boolean';\n break;\n case 'datetime':\n schema.type = 'string';\n schema.format = 'date-time';\n break;\n case 'json':\n schema.type = 'object';\n break;\n case 'foreignKey':\n case 'crossPackageRef':\n schema.type = 'string';\n // The generic relation hint is a fallback only — an authored\n // `@field({ description })` wins (#2046 threads descriptions into web\n // tool descriptors; clobbering them here would strip the help text).\n if (!field.description) {\n schema.description = `ID of related ${field.related || 'object'}`;\n }\n break;\n default:\n schema.type = 'string';\n }\n\n if (field.default !== undefined) {\n schema.default = field.default;\n }\n\n if (field.nullable && typeof schema.type === 'string') {\n schema.type = [schema.type, 'null'];\n }\n\n return schema;\n}\n\nfunction buildFieldProperties(fields: ToolFieldMeta[]): {\n properties: Record<string, ToolJsonSchema>;\n defs: Record<string, ToolJsonSchema>;\n} {\n const properties: Record<string, ToolJsonSchema> = {};\n const defs: Record<string, ToolJsonSchema> = {};\n\n fields.forEach((field, index) => {\n // Numeric keys avoid JSON Pointer escaping and keep output deterministic\n // even for an authored field name containing `/` or `~`.\n const defKey = `field_${index}`;\n defs[defKey] = fieldTypeToJsonSchema(field);\n properties[field.name] = { $ref: `#/$defs/${defKey}` };\n });\n\n return { properties, defs };\n}\n\n/**\n * Build the `inputSchema` for one action. CRUD verbs get the fixed skeletons\n * ported from mcp.ts's `generateObjectTools`; any other action is treated as a\n * custom method taking `{ id, options }`.\n */\nexport function buildToolInputSchema(\n action: string,\n fields: ToolFieldMeta[],\n customAction?: CustomActionMetadata,\n idType: ToolIdType = 'uuid',\n): ToolJsonSchema {\n const identifierSchema = (description: string): ToolJsonSchema => ({\n type: 'string',\n ...(idType === 'uuid' ? { format: 'uuid' } : {}),\n description,\n });\n\n switch (action) {\n case 'list':\n return finalizeMcpJsonSchema({\n type: 'object',\n properties: {\n limit: {\n type: 'integer',\n description: 'Maximum number of items to return',\n default: 50,\n minimum: 1,\n maximum: 1000,\n },\n offset: {\n type: 'integer',\n description: 'Number of items to skip',\n default: 0,\n minimum: 0,\n },\n orderBy: {\n type: 'string',\n description: 'Field to order by (e.g., \"created_at DESC\")',\n },\n where: {\n type: 'object',\n description: 'Filter conditions as key-value pairs',\n additionalProperties: true,\n },\n },\n });\n\n case 'get':\n // Either `id` OR `slug` identifies the object (collection.get resolves\n // both). The schema must require one of them just as the handler does,\n // while still allowing slug-only lookups.\n return finalizeMcpJsonSchema({\n type: 'object',\n anyOf: [{ required: ['id'] }, { required: ['slug'] }],\n properties: {\n id: identifierSchema('Unique identifier of the object'),\n slug: {\n type: 'string',\n description: 'URL-friendly identifier of the object',\n },\n },\n });\n\n case 'create': {\n const { properties, defs } = buildFieldProperties(fields);\n const required: string[] = [];\n for (const field of fields) {\n if (field.required) required.push(field.name);\n }\n return finalizeMcpJsonSchema({\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n ...(Object.keys(defs).length > 0 ? { $defs: defs } : {}),\n });\n }\n\n case 'update': {\n const { properties: fieldProperties, defs } =\n buildFieldProperties(fields);\n const properties: Record<string, ToolJsonSchema> = {\n id: identifierSchema('ID of the object to update'),\n ...fieldProperties,\n };\n return finalizeMcpJsonSchema({\n type: 'object',\n properties,\n required: ['id'],\n ...(Object.keys(defs).length > 0 ? { $defs: defs } : {}),\n });\n }\n\n case 'delete':\n return finalizeMcpJsonSchema({\n type: 'object',\n properties: {\n id: identifierSchema('ID of the object to delete'),\n },\n required: ['id'],\n });\n\n default:\n return finalizeMcpJsonSchema(\n buildCustomActionInputSchema(\n customAction ?? {\n scope: 'item',\n idRequired: true,\n isStatic: false,\n effect: 'destructive',\n idempotent: false,\n openWorld: true,\n },\n ),\n );\n }\n}\n\n/**\n * Human-readable description for a tool, matching mcp.ts's phrasing so the Node\n * MCP and WebMCP surfaces read identically.\n */\nfunction describeAction(action: string, className: string): string {\n switch (action) {\n case 'list':\n return `List ${className} objects with optional filtering`;\n case 'get':\n return `Get a specific ${className} by ID or slug`;\n case 'create':\n return `Create a new ${className}`;\n case 'update':\n return `Update an existing ${className}`;\n case 'delete':\n return `Delete a ${className} by ID`;\n default:\n return `Execute ${action} action on ${className}`;\n }\n}\n\n/**\n * Build the full descriptor set for a model. `toolPrefix` defaults to the\n * lowercased class name so tool ids match the existing Node MCP surface exactly\n * (`product_list`, `invoice_record_payment`), giving one stable tool vocabulary\n * across MCP and WebMCP.\n */\nexport function buildToolDescriptors(opts: {\n className: string;\n fields: ToolFieldMeta[];\n actions: string[];\n customActions?: Record<string, CustomActionMetadata>;\n toolPrefix?: string;\n idType?: ToolIdType;\n}): ToolDescriptor[] {\n const { className, fields, actions } = opts;\n const prefix = (opts.toolPrefix ?? className).toLowerCase();\n\n return actions.map((action) => {\n const customAction = opts.customActions?.[action];\n const semantics = toolSemantics(action, customAction);\n return {\n action,\n // Custom method names can contain underscores; the runtime splits on the\n // FIRST underscore only (mcp.ts #1378), so a lowercased join is safe here.\n name: `${prefix}_${action}`.toLowerCase(),\n description: describeAction(action, className),\n inputSchema: buildToolInputSchema(\n action,\n fields,\n customAction,\n opts.idType,\n ),\n readOnly: semantics.effect === 'read',\n ...semantics,\n };\n });\n}\n\nfunction toolSemantics(\n action: string,\n customAction?: CustomActionMetadata,\n): Pick<ToolDescriptor, 'effect' | 'idempotent' | 'openWorld'> {\n switch (action) {\n case 'list':\n case 'get':\n return { effect: 'read', idempotent: true, openWorld: false };\n case 'create':\n return { effect: 'write', idempotent: false, openWorld: false };\n case 'update':\n return { effect: 'write', idempotent: true, openWorld: false };\n case 'delete':\n return { effect: 'destructive', idempotent: true, openWorld: false };\n default:\n return {\n effect: customAction?.effect ?? 'destructive',\n idempotent: customAction?.idempotent ?? false,\n openWorld: customAction?.openWorld ?? true,\n };\n }\n}\n\n/** True when `action` is one of the fixed CRUD verbs (vs. a custom method). */\nexport function isCrudAction(action: string): boolean {\n return CRUD_ACTIONS.has(action);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tool-schema.js","names":[],"sources":["../../src/generators/tool-schema.ts"],"sourcesContent":["import {\n buildCustomActionInputSchema,\n CRUD_OPERATIONS,\n type CustomActionMetadata,\n type ToolEffect,\n} from './custom-action.js';\n\n/**\n * Transport-agnostic tool-descriptor builder (#1812, tracer).\n *\n * The single source of truth for turning a model's fields + exposed actions into\n * MCP-shaped tool descriptors (`{ name, description, inputSchema }`). This is the\n * shape both the Model Context Protocol AND Chrome's WebMCP\n * (`document.modelContext.registerTool`) consume — see\n * https://developer.chrome.com/docs/ai/webmcp.\n *\n * It is deliberately pure and free of `ObjectRegistry` / manifest coupling: it\n * takes a normalized {@link ToolFieldMeta}[] so BOTH callers can share it —\n * - `MCPGenerator` (`src/generators/mcp.ts`) for the Node stdio server, and\n * - the web-collections emitter (`src/vite-plugin/web-collections.ts`) for the\n * browser client-data runtime's WebMCP descriptors.\n *\n * Keeping one implementation removes the field-mapping drift risk the\n * \"three emission sites must agree\" contract in web-collections.ts already warns\n * about. The `fieldTypeToJsonSchema` / per-action skeletons below are ported\n * verbatim from mcp.ts's `fieldToMCPSchema` + `generateObjectTools`, so wiring\n * mcp.ts to call this helper is a mechanical, behavior-preserving refactor.\n */\n\n/**\n * A JSON Schema fragment. Values vary by field kind, so this is only ever\n * serialized into tool descriptors, never read back structurally.\n */\nexport type ToolJsonSchema = Record<string, unknown>;\n\n/** The only JSON Schema dialect emitted by generated MCP and WebMCP tools. */\nexport const JSON_SCHEMA_2020_12 =\n 'https://json-schema.org/draft/2020-12/schema';\n\n/**\n * Bounds for generated schemas. Field metadata is authored input, so it must\n * not turn a tools/list response into an unbounded composition or validation\n * workload. These limits are deliberately far above normal SMRT objects while\n * still keeping schemas comfortably inside MCP transport budgets.\n */\nexport const MCP_SCHEMA_LIMITS = {\n maxDepth: 16,\n maxNodes: 2_048,\n maxSerializedBytes: 65_536,\n} as const;\n\n/**\n * Apply the draft-2020-12 dialect and reject schemas that violate MCP's\n * bounded-composition contract. Generated schemas only ever reference local\n * `$defs`; external refs are neither emitted nor followed.\n */\nexport function finalizeMcpJsonSchema(schema: ToolJsonSchema): ToolJsonSchema {\n const finalized = {\n ...schema,\n $schema: JSON_SCHEMA_2020_12,\n };\n assertMcpJsonSchemaSafety(finalized);\n return finalized;\n}\n\n/**\n * Validate the resource envelope of an emitted schema without resolving refs.\n * This is intentionally structural rather than a general JSON-Schema\n * evaluator: the server already owns every schema it emits, and this guard\n * exists to keep authored metadata from introducing hostile shape growth.\n */\nexport function assertMcpJsonSchemaSafety(schema: ToolJsonSchema): void {\n let nodes = 0;\n const ancestors = new WeakSet<object>();\n\n const visit = (value: unknown, depth: number, key?: string): void => {\n nodes += 1;\n if (nodes > MCP_SCHEMA_LIMITS.maxNodes) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxNodes} nodes`,\n );\n }\n if (depth > MCP_SCHEMA_LIMITS.maxDepth) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxDepth} levels of depth`,\n );\n }\n if (key === '$ref') {\n if (\n typeof value !== 'string' ||\n !value.startsWith('#/$defs/') ||\n value.includes('://')\n ) {\n throw new Error(\n 'MCP JSON Schema may only use local #/$defs/ references',\n );\n }\n return;\n }\n if (value === null || typeof value !== 'object') return;\n if (ancestors.has(value)) {\n throw new Error('MCP JSON Schema must not contain cyclic values');\n }\n\n ancestors.add(value);\n if (Array.isArray(value)) {\n for (const entry of value) visit(entry, depth + 1);\n } else {\n for (const [childKey, child] of Object.entries(value)) {\n visit(child, depth + 1, childKey);\n }\n }\n ancestors.delete(value);\n };\n\n visit(schema, 0);\n\n let serialized: string;\n try {\n serialized = JSON.stringify(schema);\n } catch {\n throw new Error('MCP JSON Schema must be JSON-serializable');\n }\n if (\n new TextEncoder().encode(serialized).byteLength >\n MCP_SCHEMA_LIMITS.maxSerializedBytes\n ) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxSerializedBytes} serialized bytes`,\n );\n }\n}\n\n/**\n * Normalized field metadata — the intersection of what the runtime registry\n * (`FieldDefinition._meta`) and the build-time manifest (`WebFieldDefinition`)\n * can each supply. Callers flatten their own field source into this shape.\n */\nexport interface ToolFieldMeta {\n name: string;\n /** Field kind: text | integer | decimal | boolean | datetime | json | foreignKey | … */\n type: string;\n required?: boolean;\n description?: string;\n default?: unknown;\n maxLength?: number;\n minLength?: number;\n min?: number;\n max?: number;\n /** Field values may explicitly be null in the runtime/manifest contract. */\n nullable?: boolean;\n /** For `foreignKey`: the related class name, for the generated description. */\n related?: string;\n}\n\n/** Storage contract for the synthetic primary identifier. */\nexport type ToolIdType = 'uuid' | 'text';\n\n/** The CRUD verbs with dedicated input-schema skeletons; anything else is custom. */\nconst CRUD_ACTIONS = new Set<string>(CRUD_OPERATIONS);\n\nexport interface ToolRouteDescriptor {\n /** HTTP method emitted for the route. */\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n /** Whether the route targets one item or the whole collection. */\n scope: 'item' | 'collection';\n /** Route segments below the collection endpoint. Dynamic segments use `[x]`. */\n path: string[];\n /** Transport names rewritten by the tool schema (e.g. `actionId` → `id`). */\n parameterAliases?: Record<string, string>;\n /** The generated method accepts one `options` bag as its sole argument. */\n optionsBag?: boolean;\n}\n\n/** A single generated tool descriptor — the WebMCP / MCP tool shape. */\nexport interface ToolDescriptor {\n /** The action this tool performs (`list` | `get` | … | a custom method name). */\n action: string;\n /** Tool id, `${toolPrefix}_${action}` (e.g. `product_list`). */\n name: string;\n description: string;\n inputSchema: ToolJsonSchema;\n /** True when the declared effect is `read` → WebMCP `annotations.readOnlyHint`. */\n readOnly: boolean;\n /** Capability effect used by browser-tool exposure policy. */\n effect: ToolEffect;\n /** Whether repeating this tool with the same arguments is safe. */\n idempotent: boolean;\n /** Whether the tool may interact outside the SMRT application. */\n openWorld: boolean;\n /** Generated custom-route transport metadata, when the action has a route. */\n route?: ToolRouteDescriptor;\n}\n\n/**\n * Map one normalized field to its JSON-Schema fragment. Ported from\n * `MCPGenerator.fieldToMCPSchema` (mcp.ts) — keep the two in lockstep until\n * mcp.ts is switched to call this.\n */\nexport function fieldTypeToJsonSchema(field: ToolFieldMeta): ToolJsonSchema {\n const schema: ToolJsonSchema = {\n description: field.description || `${field.type} field`,\n };\n\n switch (field.type) {\n case 'text':\n schema.type = 'string';\n if (field.maxLength !== undefined) schema.maxLength = field.maxLength;\n if (field.minLength !== undefined) schema.minLength = field.minLength;\n break;\n case 'integer':\n schema.type = 'integer';\n if (field.min !== undefined) schema.minimum = field.min;\n if (field.max !== undefined) schema.maximum = field.max;\n break;\n case 'decimal':\n schema.type = 'number';\n if (field.min !== undefined) schema.minimum = field.min;\n if (field.max !== undefined) schema.maximum = field.max;\n break;\n case 'boolean':\n schema.type = 'boolean';\n break;\n case 'datetime':\n schema.type = 'string';\n schema.format = 'date-time';\n break;\n case 'json':\n schema.type = 'object';\n break;\n case 'foreignKey':\n case 'crossPackageRef':\n schema.type = 'string';\n // The generic relation hint is a fallback only — an authored\n // `@field({ description })` wins (#2046 threads descriptions into web\n // tool descriptors; clobbering them here would strip the help text).\n if (!field.description) {\n schema.description = `ID of related ${field.related || 'object'}`;\n }\n break;\n default:\n schema.type = 'string';\n }\n\n if (field.default !== undefined) {\n schema.default = field.default;\n }\n\n if (field.nullable && typeof schema.type === 'string') {\n schema.type = [schema.type, 'null'];\n }\n\n return schema;\n}\n\nfunction buildFieldProperties(fields: ToolFieldMeta[]): {\n properties: Record<string, ToolJsonSchema>;\n defs: Record<string, ToolJsonSchema>;\n} {\n const properties: Record<string, ToolJsonSchema> = {};\n const defs: Record<string, ToolJsonSchema> = {};\n\n fields.forEach((field, index) => {\n // Numeric keys avoid JSON Pointer escaping and keep output deterministic\n // even for an authored field name containing `/` or `~`.\n const defKey = `field_${index}`;\n defs[defKey] = fieldTypeToJsonSchema(field);\n properties[field.name] = { $ref: `#/$defs/${defKey}` };\n });\n\n return { properties, defs };\n}\n\n/**\n * Build the `inputSchema` for one action. CRUD verbs get the fixed skeletons\n * ported from mcp.ts's `generateObjectTools`; any other action is treated as a\n * custom method taking `{ id, options }`.\n */\nexport function buildToolInputSchema(\n action: string,\n fields: ToolFieldMeta[],\n customAction?: CustomActionMetadata,\n idType: ToolIdType = 'uuid',\n): ToolJsonSchema {\n const identifierSchema = (description: string): ToolJsonSchema => ({\n type: 'string',\n ...(idType === 'uuid' ? { format: 'uuid' } : {}),\n description,\n });\n\n switch (action) {\n case 'list':\n return finalizeMcpJsonSchema({\n type: 'object',\n properties: {\n limit: {\n type: 'integer',\n description: 'Maximum number of items to return',\n default: 50,\n minimum: 1,\n maximum: 1000,\n },\n offset: {\n type: 'integer',\n description: 'Number of items to skip',\n default: 0,\n minimum: 0,\n },\n orderBy: {\n type: 'string',\n description: 'Field to order by (e.g., \"created_at DESC\")',\n },\n where: {\n type: 'object',\n description: 'Filter conditions as key-value pairs',\n additionalProperties: true,\n },\n },\n });\n\n case 'get':\n // Either `id` OR `slug` identifies the object (collection.get resolves\n // both). The schema must require one of them just as the handler does,\n // while still allowing slug-only lookups.\n return finalizeMcpJsonSchema({\n type: 'object',\n anyOf: [{ required: ['id'] }, { required: ['slug'] }],\n properties: {\n id: identifierSchema('Unique identifier of the object'),\n slug: {\n type: 'string',\n description: 'URL-friendly identifier of the object',\n },\n },\n });\n\n case 'create': {\n const { properties, defs } = buildFieldProperties(fields);\n const required: string[] = [];\n for (const field of fields) {\n if (field.required) required.push(field.name);\n }\n return finalizeMcpJsonSchema({\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n ...(Object.keys(defs).length > 0 ? { $defs: defs } : {}),\n });\n }\n\n case 'update': {\n const { properties: fieldProperties, defs } =\n buildFieldProperties(fields);\n const properties: Record<string, ToolJsonSchema> = {\n id: identifierSchema('ID of the object to update'),\n ...fieldProperties,\n };\n return finalizeMcpJsonSchema({\n type: 'object',\n properties,\n required: ['id'],\n ...(Object.keys(defs).length > 0 ? { $defs: defs } : {}),\n });\n }\n\n case 'delete':\n return finalizeMcpJsonSchema({\n type: 'object',\n properties: {\n id: identifierSchema('ID of the object to delete'),\n },\n required: ['id'],\n });\n\n default:\n return finalizeMcpJsonSchema(\n buildCustomActionInputSchema(\n customAction ?? {\n scope: 'item',\n idRequired: true,\n isStatic: false,\n effect: 'destructive',\n idempotent: false,\n openWorld: true,\n },\n ),\n );\n }\n}\n\n/**\n * Human-readable description for a tool, matching mcp.ts's phrasing so the Node\n * MCP and WebMCP surfaces read identically.\n */\nfunction describeAction(action: string, className: string): string {\n switch (action) {\n case 'list':\n return `List ${className} objects with optional filtering`;\n case 'get':\n return `Get a specific ${className} by ID or slug`;\n case 'create':\n return `Create a new ${className}`;\n case 'update':\n return `Update an existing ${className}`;\n case 'delete':\n return `Delete a ${className} by ID`;\n default:\n return `Execute ${action} action on ${className}`;\n }\n}\n\n/**\n * Build the full descriptor set for a model. `toolPrefix` defaults to the\n * lowercased class name so tool ids match the existing Node MCP surface exactly\n * (`product_list`, `invoice_record_payment`), giving one stable tool vocabulary\n * across MCP and WebMCP.\n */\nexport function buildToolDescriptors(opts: {\n className: string;\n fields: ToolFieldMeta[];\n actions: string[];\n customActions?: Record<string, CustomActionMetadata>;\n toolPrefix?: string;\n idType?: ToolIdType;\n}): ToolDescriptor[] {\n const { className, fields, actions } = opts;\n const prefix = (opts.toolPrefix ?? className).toLowerCase();\n\n return actions.map((action) => {\n const customAction = opts.customActions?.[action];\n const semantics = resolveToolSemantics(action, customAction);\n return {\n action,\n // Custom method names can contain underscores; the runtime splits on the\n // FIRST underscore only (mcp.ts #1378), so a lowercased join is safe here.\n name: `${prefix}_${action}`.toLowerCase(),\n description: describeAction(action, className),\n inputSchema: buildToolInputSchema(\n action,\n fields,\n customAction,\n opts.idType,\n ),\n readOnly: semantics.effect === 'read',\n ...semantics,\n };\n });\n}\n\n/**\n * Resolve the one canonical capability classification used by generated MCP\n * and WebMCP descriptors. Consumers that author a tool outside a model must\n * declare this same shape rather than infer safety from a name or HTTP verb.\n */\nexport function resolveToolSemantics(\n action: string,\n customAction?: CustomActionMetadata,\n): Pick<ToolDescriptor, 'effect' | 'idempotent' | 'openWorld'> {\n switch (action) {\n case 'list':\n case 'get':\n return { effect: 'read', idempotent: true, openWorld: false };\n case 'create':\n return { effect: 'write', idempotent: false, openWorld: false };\n case 'update':\n return { effect: 'write', idempotent: true, openWorld: false };\n case 'delete':\n return { effect: 'destructive', idempotent: true, openWorld: false };\n default:\n return {\n effect: customAction?.effect ?? 'destructive',\n idempotent: customAction?.idempotent ?? false,\n openWorld: customAction?.openWorld ?? true,\n };\n }\n}\n\n/** True when `action` is one of the fixed CRUD verbs (vs. a custom method). */\nexport function isCrudAction(action: string): boolean {\n return CRUD_ACTIONS.has(action);\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ import { DEFAULT_LIST_LIMIT, DEFAULT_LIST_ORDER_BY, MAX_LIST_LIMIT, QueryBoundsE
|
|
|
36
36
|
import { applyPendingDecoratorRegistrations, registerCompatibleFieldDecorator, registerCompatibleMethodDecorator } from "./decorators/compatibility.js";
|
|
37
37
|
import { clone, getAdapterInfo, isValid, parse, safeParse, safeStringify, stringify } from "./utils/json.js";
|
|
38
38
|
import { createQualifiedName, getClassName, getPackageFromQualifiedName, isFromPackage, isQualifiedName, isType, parseQualifiedName, qualifiedNamesEqual } from "./utils/qualified-names.js";
|
|
39
|
+
import { publishArtifactFiles, publishAtomicArtifact } from "./consumer-plugin/artifact-publication.js";
|
|
39
40
|
import { convertTypeToJsonSchema, generateToolFromMethod, generateToolManifest, shouldIncludeMethod } from "./tools/tool-generator.js";
|
|
40
41
|
import { CRUD_OPERATIONS, SMRT_CUSTOM_ACTION_ERROR_METADATA_KEY, buildCustomActionInputSchema, buildCustomActionInvocationArgs, classifyMethodWireability, classifyParameterWireability, coerceCustomActionArgument, createClassNamePredicate, createManifestClassNamePredicate, customActionParameterInputName, declaredTypeAcceptsDate, declaresRuntimeRestRoute, declaresRuntimeRestRouteShape, isCrudOperation, isCrudToolAction, normalizeCustomActionFailure, queryStringDecoderFor, readMethodDecoratorConfig, resolveApiMethodExposure, resolveCustomActionMetadata, resolveDeclaredScopeMismatch, resolveEffectiveActionMetadata, toCustomActionBoolean, toCustomActionDate, toCustomActionNumber } from "./generators/custom-action.js";
|
|
41
42
|
import { ManifestGenerator } from "./scanner/manifest-generator.js";
|
|
@@ -73,6 +74,7 @@ import { generateOpenAPISpec, setupSwaggerUI } from "./generators/swagger.js";
|
|
|
73
74
|
import "./generators/index.js";
|
|
74
75
|
import { SmrtHierarchical } from "./hierarchical.js";
|
|
75
76
|
import { SmrtJunction } from "./junction.js";
|
|
77
|
+
import { resolveFileKnowledgeConfig } from "./knowledge-config.js";
|
|
76
78
|
import { discoverScopedPackageDirectories, readPackageAgentDoc } from "./knowledge-discovery.js";
|
|
77
79
|
import { buildKnowledgeGraph, checkKnowledgeGraphFreshness, discoverKnowledgeArtifactPaths, stableStringify } from "./knowledge-graph.js";
|
|
78
80
|
import { AGENT_SURFACE_HASH_PREFIX, MODULE_DOC_HASH_PREFIX, buildDomainKnowledgeManifest, readAgentModuleDocs, resolveAgentModuleDocPaths } from "./knowledge.js";
|
|
@@ -99,4 +101,4 @@ import "./system/index.js";
|
|
|
99
101
|
import { getTestDatabase } from "./testing/database.js";
|
|
100
102
|
import "./tools/index.js";
|
|
101
103
|
import { smrtPlugin } from "./vite-plugin/index.js";
|
|
102
|
-
export { AGENT_SURFACE_HASH_PREFIX, AIError, APIGenerator, AiUsageCollector, AiUsagePersistenceHandler, BOOTED_PROVENANCE, CACHE_INVALIDATION_CHANNEL, CHANGE_FEED_CREDENTIAL_TABLES, CHANGE_FEED_INTERCEPTOR_NAME, CHANGE_FEED_TABLE, CHANGE_SIGNAL_CHANNEL, CRUD_OPERATIONS, ConfigurationError, ContentHasher, CosineSimilarity, DEFAULT_AI_COST_RATES, DEFAULT_CHANGES_LIMIT, DEFAULT_DATA_QUERY_PAGE_LIMIT, DEFAULT_DATA_QUERY_RESULT_BYTES, DEFAULT_EMBEDDING_CONFIG, DEFAULT_EVENTS_HEARTBEAT_MS, DEFAULT_EVENTS_MAX_SUBSCRIBERS, DEFAULT_EVENTS_RETRY_AFTER_SECONDS, DEFAULT_FACET_LIMIT, DEFAULT_LEARNING_CONFIG, DEFAULT_LIST_LIMIT, DEFAULT_LIST_ORDER_BY, DEFAULT_POSTGRES_TIMEOUTS, DEFAULT_RETENTION_POLICY, DIAGNOSTICS_DEFAULT_LIMIT, DataQueryValidationError, DatabaseError, Dispatch, DispatchBus, DispatchCollection, DispatchSubscription, DispatchSubscriptionCollection, EmbeddingProvider, EmbeddingStorage, EmbeddingUnavailableError, ErrorUtils, FilesystemError, GlobalInterceptors, IN_LIST_CHUNK_SIZE, LearningMemory, LiveSchemaParityError, MAX_CHANGES_LIMIT, MAX_DATA_QUERY_CURSOR_LENGTH, MAX_DATA_QUERY_FACETS, MAX_DATA_QUERY_FILTERS, MAX_DATA_QUERY_FILTER_DEPTH, MAX_DATA_QUERY_IN_VALUES, MAX_DATA_QUERY_OFFSET, MAX_DATA_QUERY_PAGE_LIMIT, MAX_DATA_QUERY_REQUEST_BYTES, MAX_DATA_QUERY_RESULT_BYTES, MAX_DATA_QUERY_WARNINGS, MAX_FACET_FIELDS, MAX_FACET_LIMIT, MAX_LIST_LIMIT, MAX_STI_READ_SCOPE_TYPES, MAX_SYNC_APPLY_BATCH_SIZE, MCPGenerator, MCP_STABLE_CATALOG_TTL_MS, MODULE_DOC_HASH_PREFIX, ManifestBuilder, ManifestGenerator, ManifestManager, MetricsAdapter, NetworkError, ObjectRegistry, PLAYBOOK_PREFLIGHT_CAPABILITY, PLAYBOOK_PREFLIGHT_ROUTE_SEGMENT, POSTGRES_REVISION_GUARD_EXPRESSION, POSTGRES_TIMEOUT_ENV_VARS, PRIVATE_READ_CACHE_CONTROL, PubSubAdapter, QueryBoundsError, QueryOrderByError, RUN_ONCE_CLAIMS_TABLE, RunOnceClaimError, RuntimeError, SMRT_COLLECTION_BASE_NAMES, SMRT_CUSTOM_ACTION_ERROR_METADATA_KEY, SMRT_SCHEMA_VERSION, SYNC_APPLY_ROUTE_SEGMENTS, SYNC_APPLY_UUID_PATTERN, SYSTEM_DIAGNOSTICS_TABLES, SYSTEM_TABLE_NAMES, SchemaComparer, SignalBus, SignalSanitizer, SmrtClass, SmrtCollection, SmrtError, SmrtHierarchical, SmrtJunction, SmrtMCPServer, SmrtObject, SmrtPolymorphicAssociation, TenantIsolationError, ValidationError, ValidationReport, ValidationUtils, appendChange, appendChanges, applyOneToManyChildAccessors, applyPendingDecoratorRegistrations, applyPostgresPermissions, applyPostgresRuntimeTimeouts, applySyncWritablePolicy, assertPlainJson, assertPostgresSystemTimestampsCurrent, broadcastCacheInvalidation, buildCascadePlan, buildChangeEventStream, buildCustomActionInputSchema, buildCustomActionInvocationArgs, buildDefaultListOrderBy, buildDomainKnowledgeManifest, buildKnowledgeGraph, bumpChangeFeed, canonicalReadRepresentation, canonicalizeDataQuery, cascadeReferencesTo, changeEventSubscribersAtCapacity, checkKnowledgeGraphFreshness, checkLiveSchemaParity, childAccessorName, chunkArray, classifyDatabaseError, classifyDialectMessage, classifyMethodWireability, classifyParameterWireability, clearRetentionTasks, clone, coerceCustomActionArgument, collectForeignKeyOrphanCounts, computeBodyEtag, computeRuntimeWebManifestHash, computeTableVersionEtag, conditionalJsonResponse, config, convertTypeToJsonSchema, createClassNamePredicate, createDataQueryFingerprint, createDispatchBus, createFilesystemAdapter, createInterceptorContext, createMCPServer, createManifestClassNamePredicate, createQualifiedName, createRestServer, createSmrtClient, createSmrtServer, crossPackageRef, customActionParameterInputName, declareChangeFeedSensitiveTable, declaredTypeAcceptsDate, declaresRuntimeRestRoute, declaresRuntimeRestRouteShape, deriveRunOnceClaimKey, detectEngine, digestRunOnceContent, discoverKnowledgeArtifactPaths, discoverManifestEntry, discoverScopedPackageDirectories, drainChangeFeed, ensureBootstrapSystemTableCompatibility, ensureCacheInvalidationListener, ensureChangeFeedTable, ensureDeferredSystemTableCompatibility, ensureDispatchSubscriptionsSystemTableCompatibility, ensureDispatchSystemTableCompatibility, ensureJobEventsSystemTableCompatibility, ensureJobsSystemTableCompatibility, ensureLegacySystemTableCompatibility, ensureSystemTables, estimateAiUsageCost, eventStreamCapacityExceededResponse, executeCollectionReadPlan, executeDecision, executeToolCall, executeToolCalls, field, filterVisibleChangeFeedEntries, findManifestEntryByQualifiedName, foreignKey, formatToolResults, generateDDLForEngine, generateOpenAPISpec, generateSchemaDiff, generateToolFromMethod, generateToolManifest, getAdapterInfo, getAuthorizedChangesSince, getAuthorizedTenantScopedChangesSince, getCacheGeneration, getChangeFeedSensitiveTables, getChangesSince, getClassConfigResolvers, getClassName, getConfigResolver, getDatabaseEngine, getManifest, getPackageFromQualifiedName, getRetentionTasks, getSQLFromDiff, getSystemTableShapes, getTableVersion, getTenantScopedChangesSince, getTestDatabase, handlePlaybookPreflightRoute, hasActionableChanges, hasChangeFeedEntryVisibilityHook, hasChangeFeedTableAuthorizerHook, ifNoneMatchHasConcreteMatch, ifNoneMatchSatisfied, importOptionalDependency, invalidateCollectionCache, isAbortedTransactionError, isAdvisoryOnlyChange, isApiActionEnabledForObject, isChangeFeedDenyAll, isChangeFeedEntryVisible, isChangeFeedSensitiveTable, isCrudOperation, isCrudToolAction, isDatabaseInterface, isDeterministicDatabaseError, isEmbeddedDatabase, isFrameworkBaseClass, isFromPackage, isLazyConfigSentinel, isManualOrAdvisoryChange, isNotNullViolationError, isPostgresDatabase, isQualifiedName, isRestActionRoutable, isRestRoutePublic, isSmrtCollectionExtendsName, isStaleWrite, isTenantScopedClassResolved, isTransientDatabaseError, isType, isUniqueViolationError, isValid, listConfigResolvers, loadExternalManifest, loadExternalManifestSync, loadLocalTestManifestSync, loadManifestFromPathSync, manifest, manyToMany, meta, method, migratePostgresSystemTimestamps, normalizeCustomActionFailure, normalizeDataQueryRequest, normalizeDataQueryResult, normalizeDataQuerySchema, normalizeEventsMaxSubscribers, normalizeOnDelete, normalizeTypedHttpError, oneToMany, parse, parseQualifiedName, parseSyncApplyBatch, payloadMatchesRow, planForeignKeyCreation, planPostgresPermissions, planPostgresSystemTimestampMigrations, postgresRevisionCandidates, postgresRevisionCondition, processSyncApplyBatch, pruneAiUsage, pruneChangeFeed, pruneExpiredContexts, pruneRunOnceClaims, qualifiedNamesEqual, queryStringDecoderFor, readAgentModuleDocs, readDispatchHealth, readJobHealth, readMethodDecoratorConfig, readMigrationStatus, readPackageAgentDoc, readRecentChanges, readRegistryDrift, readScheduleHealth, readSystemDiagnostics, registerChangeFeedWriter, registerCompatibleFieldDecorator, registerCompatibleMethodDecorator, registerConfigResolver, registerFilesystemAdapterFactory, registerOptionalDependency, registerRetentionTask, resetChangeFeedWarnings, resetChangeSignals, resetCollectionCache, resetConfigResolvers, resetVerifiedTables, resolveAgentModuleDocPaths, resolveApiMethodExposure, resolveAuthorizedChangeFeedTables, resolveCustomActionMetadata, resolveDatabase, resolveDbCacheKey, resolveDeclaredScopeMismatch, resolveDispatchTenantId, resolveDispatchTenantScope, resolveEffectiveActionMetadata, resolveExistingRunOnceClaim, resolveGetStringFilter, resolveLazyConfig, resolveListLimit, resolveListOffset, resolveMCPToolListCacheHint, resolvePostgresTimeouts, resolveReadCacheControl, resolveRegisteredObjectName, resolveTenantEtagDiscriminator, restFieldReadPermissions, restMethodForApiAction, runCascadeDelete, runOnce, runRetentionSweep, runWithTenantGate, safeParse, safeStringify, sanitizeMessagePaths, setChangeFeedAuthorizer, setChangeFeedEntryVisibility, setDispatchTenantResolver, setTenantEntryPointRunner, setTenantScopedClassResolver, setupSwaggerUI, shouldIncludeMethod, signalVisibleToTenant, smrt, smrtPlugin, smrt as smrtRegistry, snapshotRegistry, sortMCPTools, stableStringify, startRestServer, staticManifest, stopCacheInvalidationListeners, stopChangeSignalListeners, stringify, subscribeToChangeSignals, tableExists, toCustomActionBoolean, toCustomActionDate, toCustomActionNumber, tryReserveChangeEventSubscriberSlot, unregisterChangeFeedWriter, unregisterConfigResolver, unregisterRetentionTask, usesEmbeddedRevisionFallback, validatePostgresPermissionContract, validateSyncApplyItem, validateToolCall, versionConditionalResponse, warnIfSharedCacheNeutralized, withEmbeddedWriteQueue, withEmbeddedWriteTransaction };
|
|
104
|
+
export { AGENT_SURFACE_HASH_PREFIX, AIError, APIGenerator, AiUsageCollector, AiUsagePersistenceHandler, BOOTED_PROVENANCE, CACHE_INVALIDATION_CHANNEL, CHANGE_FEED_CREDENTIAL_TABLES, CHANGE_FEED_INTERCEPTOR_NAME, CHANGE_FEED_TABLE, CHANGE_SIGNAL_CHANNEL, CRUD_OPERATIONS, ConfigurationError, ContentHasher, CosineSimilarity, DEFAULT_AI_COST_RATES, DEFAULT_CHANGES_LIMIT, DEFAULT_DATA_QUERY_PAGE_LIMIT, DEFAULT_DATA_QUERY_RESULT_BYTES, DEFAULT_EMBEDDING_CONFIG, DEFAULT_EVENTS_HEARTBEAT_MS, DEFAULT_EVENTS_MAX_SUBSCRIBERS, DEFAULT_EVENTS_RETRY_AFTER_SECONDS, DEFAULT_FACET_LIMIT, DEFAULT_LEARNING_CONFIG, DEFAULT_LIST_LIMIT, DEFAULT_LIST_ORDER_BY, DEFAULT_POSTGRES_TIMEOUTS, DEFAULT_RETENTION_POLICY, DIAGNOSTICS_DEFAULT_LIMIT, DataQueryValidationError, DatabaseError, Dispatch, DispatchBus, DispatchCollection, DispatchSubscription, DispatchSubscriptionCollection, EmbeddingProvider, EmbeddingStorage, EmbeddingUnavailableError, ErrorUtils, FilesystemError, GlobalInterceptors, IN_LIST_CHUNK_SIZE, LearningMemory, LiveSchemaParityError, MAX_CHANGES_LIMIT, MAX_DATA_QUERY_CURSOR_LENGTH, MAX_DATA_QUERY_FACETS, MAX_DATA_QUERY_FILTERS, MAX_DATA_QUERY_FILTER_DEPTH, MAX_DATA_QUERY_IN_VALUES, MAX_DATA_QUERY_OFFSET, MAX_DATA_QUERY_PAGE_LIMIT, MAX_DATA_QUERY_REQUEST_BYTES, MAX_DATA_QUERY_RESULT_BYTES, MAX_DATA_QUERY_WARNINGS, MAX_FACET_FIELDS, MAX_FACET_LIMIT, MAX_LIST_LIMIT, MAX_STI_READ_SCOPE_TYPES, MAX_SYNC_APPLY_BATCH_SIZE, MCPGenerator, MCP_STABLE_CATALOG_TTL_MS, MODULE_DOC_HASH_PREFIX, ManifestBuilder, ManifestGenerator, ManifestManager, MetricsAdapter, NetworkError, ObjectRegistry, PLAYBOOK_PREFLIGHT_CAPABILITY, PLAYBOOK_PREFLIGHT_ROUTE_SEGMENT, POSTGRES_REVISION_GUARD_EXPRESSION, POSTGRES_TIMEOUT_ENV_VARS, PRIVATE_READ_CACHE_CONTROL, PubSubAdapter, QueryBoundsError, QueryOrderByError, RUN_ONCE_CLAIMS_TABLE, RunOnceClaimError, RuntimeError, SMRT_COLLECTION_BASE_NAMES, SMRT_CUSTOM_ACTION_ERROR_METADATA_KEY, SMRT_SCHEMA_VERSION, SYNC_APPLY_ROUTE_SEGMENTS, SYNC_APPLY_UUID_PATTERN, SYSTEM_DIAGNOSTICS_TABLES, SYSTEM_TABLE_NAMES, SchemaComparer, SignalBus, SignalSanitizer, SmrtClass, SmrtCollection, SmrtError, SmrtHierarchical, SmrtJunction, SmrtMCPServer, SmrtObject, SmrtPolymorphicAssociation, TenantIsolationError, ValidationError, ValidationReport, ValidationUtils, appendChange, appendChanges, applyOneToManyChildAccessors, applyPendingDecoratorRegistrations, applyPostgresPermissions, applyPostgresRuntimeTimeouts, applySyncWritablePolicy, assertPlainJson, assertPostgresSystemTimestampsCurrent, broadcastCacheInvalidation, buildCascadePlan, buildChangeEventStream, buildCustomActionInputSchema, buildCustomActionInvocationArgs, buildDefaultListOrderBy, buildDomainKnowledgeManifest, buildKnowledgeGraph, bumpChangeFeed, canonicalReadRepresentation, canonicalizeDataQuery, cascadeReferencesTo, changeEventSubscribersAtCapacity, checkKnowledgeGraphFreshness, checkLiveSchemaParity, childAccessorName, chunkArray, classifyDatabaseError, classifyDialectMessage, classifyMethodWireability, classifyParameterWireability, clearRetentionTasks, clone, coerceCustomActionArgument, collectForeignKeyOrphanCounts, computeBodyEtag, computeRuntimeWebManifestHash, computeTableVersionEtag, conditionalJsonResponse, config, convertTypeToJsonSchema, createClassNamePredicate, createDataQueryFingerprint, createDispatchBus, createFilesystemAdapter, createInterceptorContext, createMCPServer, createManifestClassNamePredicate, createQualifiedName, createRestServer, createSmrtClient, createSmrtServer, crossPackageRef, customActionParameterInputName, declareChangeFeedSensitiveTable, declaredTypeAcceptsDate, declaresRuntimeRestRoute, declaresRuntimeRestRouteShape, deriveRunOnceClaimKey, detectEngine, digestRunOnceContent, discoverKnowledgeArtifactPaths, discoverManifestEntry, discoverScopedPackageDirectories, drainChangeFeed, ensureBootstrapSystemTableCompatibility, ensureCacheInvalidationListener, ensureChangeFeedTable, ensureDeferredSystemTableCompatibility, ensureDispatchSubscriptionsSystemTableCompatibility, ensureDispatchSystemTableCompatibility, ensureJobEventsSystemTableCompatibility, ensureJobsSystemTableCompatibility, ensureLegacySystemTableCompatibility, ensureSystemTables, estimateAiUsageCost, eventStreamCapacityExceededResponse, executeCollectionReadPlan, executeDecision, executeToolCall, executeToolCalls, field, filterVisibleChangeFeedEntries, findManifestEntryByQualifiedName, foreignKey, formatToolResults, generateDDLForEngine, generateOpenAPISpec, generateSchemaDiff, generateToolFromMethod, generateToolManifest, getAdapterInfo, getAuthorizedChangesSince, getAuthorizedTenantScopedChangesSince, getCacheGeneration, getChangeFeedSensitiveTables, getChangesSince, getClassConfigResolvers, getClassName, getConfigResolver, getDatabaseEngine, getManifest, getPackageFromQualifiedName, getRetentionTasks, getSQLFromDiff, getSystemTableShapes, getTableVersion, getTenantScopedChangesSince, getTestDatabase, handlePlaybookPreflightRoute, hasActionableChanges, hasChangeFeedEntryVisibilityHook, hasChangeFeedTableAuthorizerHook, ifNoneMatchHasConcreteMatch, ifNoneMatchSatisfied, importOptionalDependency, invalidateCollectionCache, isAbortedTransactionError, isAdvisoryOnlyChange, isApiActionEnabledForObject, isChangeFeedDenyAll, isChangeFeedEntryVisible, isChangeFeedSensitiveTable, isCrudOperation, isCrudToolAction, isDatabaseInterface, isDeterministicDatabaseError, isEmbeddedDatabase, isFrameworkBaseClass, isFromPackage, isLazyConfigSentinel, isManualOrAdvisoryChange, isNotNullViolationError, isPostgresDatabase, isQualifiedName, isRestActionRoutable, isRestRoutePublic, isSmrtCollectionExtendsName, isStaleWrite, isTenantScopedClassResolved, isTransientDatabaseError, isType, isUniqueViolationError, isValid, listConfigResolvers, loadExternalManifest, loadExternalManifestSync, loadLocalTestManifestSync, loadManifestFromPathSync, manifest, manyToMany, meta, method, migratePostgresSystemTimestamps, normalizeCustomActionFailure, normalizeDataQueryRequest, normalizeDataQueryResult, normalizeDataQuerySchema, normalizeEventsMaxSubscribers, normalizeOnDelete, normalizeTypedHttpError, oneToMany, parse, parseQualifiedName, parseSyncApplyBatch, payloadMatchesRow, planForeignKeyCreation, planPostgresPermissions, planPostgresSystemTimestampMigrations, postgresRevisionCandidates, postgresRevisionCondition, processSyncApplyBatch, pruneAiUsage, pruneChangeFeed, pruneExpiredContexts, pruneRunOnceClaims, publishArtifactFiles, publishAtomicArtifact, qualifiedNamesEqual, queryStringDecoderFor, readAgentModuleDocs, readDispatchHealth, readJobHealth, readMethodDecoratorConfig, readMigrationStatus, readPackageAgentDoc, readRecentChanges, readRegistryDrift, readScheduleHealth, readSystemDiagnostics, registerChangeFeedWriter, registerCompatibleFieldDecorator, registerCompatibleMethodDecorator, registerConfigResolver, registerFilesystemAdapterFactory, registerOptionalDependency, registerRetentionTask, resetChangeFeedWarnings, resetChangeSignals, resetCollectionCache, resetConfigResolvers, resetVerifiedTables, resolveAgentModuleDocPaths, resolveApiMethodExposure, resolveAuthorizedChangeFeedTables, resolveCustomActionMetadata, resolveDatabase, resolveDbCacheKey, resolveDeclaredScopeMismatch, resolveDispatchTenantId, resolveDispatchTenantScope, resolveEffectiveActionMetadata, resolveExistingRunOnceClaim, resolveFileKnowledgeConfig, resolveGetStringFilter, resolveLazyConfig, resolveListLimit, resolveListOffset, resolveMCPToolListCacheHint, resolvePostgresTimeouts, resolveReadCacheControl, resolveRegisteredObjectName, resolveTenantEtagDiscriminator, restFieldReadPermissions, restMethodForApiAction, runCascadeDelete, runOnce, runRetentionSweep, runWithTenantGate, safeParse, safeStringify, sanitizeMessagePaths, setChangeFeedAuthorizer, setChangeFeedEntryVisibility, setDispatchTenantResolver, setTenantEntryPointRunner, setTenantScopedClassResolver, setupSwaggerUI, shouldIncludeMethod, signalVisibleToTenant, smrt, smrtPlugin, smrt as smrtRegistry, snapshotRegistry, sortMCPTools, stableStringify, startRestServer, staticManifest, stopCacheInvalidationListeners, stopChangeSignalListeners, stringify, subscribeToChangeSignals, tableExists, toCustomActionBoolean, toCustomActionDate, toCustomActionNumber, tryReserveChangeEventSubscriberSlot, unregisterChangeFeedWriter, unregisterConfigResolver, unregisterRetentionTask, usesEmbeddedRevisionFallback, validatePostgresPermissionContract, validateSyncApplyItem, validateToolCall, versionConditionalResponse, warnIfSharedCacheNeutralized, withEmbeddedWriteQueue, withEmbeddedWriteTransaction };
|
package/dist/knowledge.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { AGENT_SURFACE_HASH_PREFIX, MODULE_DOC_HASH_PREFIX, readAgentModuleDocs, resolveAgentModuleDocPaths } from '@happyvertical/smrt-scanner/knowledge';
|
|
2
|
+
export { publishArtifactFiles, publishAtomicArtifact, } from './consumer-plugin/artifact-publication.js';
|
|
3
|
+
export { resolveFileKnowledgeConfig } from './knowledge-config.js';
|
|
2
4
|
export { discoverScopedPackageDirectories, readPackageAgentDoc, type ScopedPackageDirectory, } from './knowledge-discovery.js';
|
|
3
5
|
export { buildKnowledgeGraph, checkKnowledgeGraphFreshness, discoverKnowledgeArtifactPaths, type KnowledgeGraphEdge, type KnowledgeGraphEdgeType, type KnowledgeGraphFreshnessIssue, type KnowledgeGraphInput, type KnowledgeGraphObjectNode, type KnowledgeGraphPackageNode, type SmrtKnowledgeGraph, stableStringify, } from './knowledge-graph.js';
|
|
4
6
|
export { AGENT_SURFACE_HASH_PREFIX, MODULE_DOC_HASH_PREFIX, readAgentModuleDocs, resolveAgentModuleDocPaths, };
|
package/dist/knowledge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../src/knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,gCAAgC,EAChC,mBAAmB,EACnB,KAAK,sBAAsB,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,8BAA8B,EAC9B,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,0BAA0B,GAC3B,CAAC;AAKF,OAAO,KAAK,EACV,2BAA2B,EAC3B,qBAAqB,EAGrB,uBAAuB,EAMxB,MAAM,2BAA2B,CAAC;AAanC,OAAO,KAAK,EAEV,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAG5B;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,2BAA2B,CAAC;CAC5C;AA0CD,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,2BAA2B,GACnC,uBAAuB,CA0FzB"}
|
|
1
|
+
{"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../src/knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EACL,gCAAgC,EAChC,mBAAmB,EACnB,KAAK,sBAAsB,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,8BAA8B,EAC9B,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,0BAA0B,GAC3B,CAAC;AAKF,OAAO,KAAK,EACV,2BAA2B,EAC3B,qBAAqB,EAGrB,uBAAuB,EAMxB,MAAM,2BAA2B,CAAC;AAanC,OAAO,KAAK,EAEV,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAG5B;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,2BAA2B,CAAC;CAC5C;AA0CD,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,2BAA2B,GACnC,uBAAuB,CA0FzB"}
|
package/dist/knowledge.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { toSnakeCase } from "./utils/naming.js";
|
|
2
|
+
import { publishArtifactFiles, publishAtomicArtifact } from "./consumer-plugin/artifact-publication.js";
|
|
2
3
|
import { CRUD_OPERATIONS, createManifestClassNamePredicate, isCrudOperation, isCrudToolAction, isFrameworkLifecycleMethod, resolveApiMethodExposure, resolveCustomActionMetadata, resolveEffectiveActionMetadata } from "./generators/custom-action.js";
|
|
3
4
|
import { isFrameworkBaseClass } from "./registry/framework-base-classes.js";
|
|
5
|
+
import { resolveFileKnowledgeConfig } from "./knowledge-config.js";
|
|
4
6
|
import { discoverScopedPackageDirectories, readPackageAgentDoc } from "./knowledge-discovery.js";
|
|
5
7
|
import { buildKnowledgeGraph, checkKnowledgeGraphFreshness, discoverKnowledgeArtifactPaths, stableStringify } from "./knowledge-graph.js";
|
|
6
8
|
import { createHash } from "node:crypto";
|
|
@@ -761,6 +763,6 @@ function sortJson(value) {
|
|
|
761
763
|
return value;
|
|
762
764
|
}
|
|
763
765
|
//#endregion
|
|
764
|
-
export { AGENT_SURFACE_HASH_PREFIX, MODULE_DOC_HASH_PREFIX, buildDomainKnowledgeManifest, buildKnowledgeGraph, checkKnowledgeGraphFreshness, discoverKnowledgeArtifactPaths, discoverScopedPackageDirectories, readAgentModuleDocs, readPackageAgentDoc, resolveAgentModuleDocPaths, stableStringify };
|
|
766
|
+
export { AGENT_SURFACE_HASH_PREFIX, MODULE_DOC_HASH_PREFIX, buildDomainKnowledgeManifest, buildKnowledgeGraph, checkKnowledgeGraphFreshness, discoverKnowledgeArtifactPaths, discoverScopedPackageDirectories, publishArtifactFiles, publishAtomicArtifact, readAgentModuleDocs, readPackageAgentDoc, resolveAgentModuleDocPaths, resolveFileKnowledgeConfig, stableStringify };
|
|
765
767
|
|
|
766
768
|
//# sourceMappingURL=knowledge.js.map
|
package/dist/knowledge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge.js","names":[],"sources":["../src/knowledge.ts"],"sourcesContent":["import {\n AGENT_SURFACE_HASH_PREFIX,\n MODULE_DOC_HASH_PREFIX,\n readAgentModuleDocs,\n resolveAgentModuleDocPaths,\n} from '@happyvertical/smrt-scanner/knowledge';\n\nexport {\n discoverScopedPackageDirectories,\n readPackageAgentDoc,\n type ScopedPackageDirectory,\n} from './knowledge-discovery.js';\nexport {\n buildKnowledgeGraph,\n checkKnowledgeGraphFreshness,\n discoverKnowledgeArtifactPaths,\n type KnowledgeGraphEdge,\n type KnowledgeGraphEdgeType,\n type KnowledgeGraphFreshnessIssue,\n type KnowledgeGraphInput,\n type KnowledgeGraphObjectNode,\n type KnowledgeGraphPackageNode,\n type SmrtKnowledgeGraph,\n stableStringify,\n} from './knowledge-graph.js';\nexport {\n AGENT_SURFACE_HASH_PREFIX,\n MODULE_DOC_HASH_PREFIX,\n readAgentModuleDocs,\n resolveAgentModuleDocPaths,\n};\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type {\n DomainKnowledgeAgentSurface,\n DomainKnowledgeConfig,\n DomainKnowledgeField,\n DomainKnowledgeFieldConstraints,\n DomainKnowledgeManifest,\n DomainKnowledgeMethodSignature,\n DomainKnowledgeObject,\n DomainKnowledgeSurface,\n DomainKnowledgeTenant,\n DomainKnowledgeWithheldSurface,\n} from '@happyvertical/smrt-types';\nimport {\n type ApiMethodExposure,\n CRUD_OPERATIONS,\n createManifestClassNamePredicate,\n isCrudOperation,\n isCrudToolAction,\n isFrameworkLifecycleMethod,\n resolveApiMethodExposure,\n resolveCustomActionMetadata,\n resolveEffectiveActionMetadata,\n} from './generators/custom-action.js';\nimport { isFrameworkBaseClass } from './registry/framework-base-classes.js';\nimport type {\n SmartObjectDefinition,\n SmartObjectManifest,\n} from './scanner/types.js';\nimport { toSnakeCase } from './utils/naming.js';\n\n/**\n * Minimal package.json shape consumed by the knowledge builder.\n * `name`/`version` are typed concretely because they flow into the manifest's\n * string-typed metadata fields; everything else is read via `unknown`-accepting\n * helpers (`record()`, `exportKeys()`), so an index signature is sufficient.\n */\nexport interface PackageJsonLike {\n name?: string;\n version?: string;\n [key: string]: unknown;\n}\n\nexport interface BuildDomainKnowledgeOptions {\n manifest: SmartObjectManifest;\n rootDir: string;\n packageJson?: PackageJsonLike;\n manifestPath?: string;\n config?: DomainKnowledgeConfig;\n /**\n * The package's declared view intents and playbooks (#2591), produced by the\n * scanner's agent-surface matcher.\n *\n * Passed in rather than scanned here for one reason: the scanner carries a\n * native parser binary, and `smrt-core`'s main entry is browser-reachable.\n * The Vite plugin already imports the scanner lazily on the Node side and is\n * the one caller that writes this artifact, so it does the scan and hands the\n * result over.\n */\n agentSurface?: DomainKnowledgeAgentSurface;\n}\n\nconst SDK_PACKAGE_NAMES = new Set([\n '@happyvertical/ai',\n '@happyvertical/cache',\n '@happyvertical/documents',\n '@happyvertical/email',\n '@happyvertical/encryption',\n '@happyvertical/files',\n '@happyvertical/geo',\n '@happyvertical/images',\n '@happyvertical/jobs',\n '@happyvertical/json',\n '@happyvertical/logger',\n '@happyvertical/messages',\n '@happyvertical/ocr',\n '@happyvertical/pdf',\n '@happyvertical/projects',\n '@happyvertical/repos',\n '@happyvertical/secrets',\n '@happyvertical/spider',\n '@happyvertical/sql',\n '@happyvertical/utils',\n]);\n\nconst RELATIONSHIP_FIELD_TYPES = new Set([\n 'foreignKey',\n 'crossPackageRef',\n 'oneToMany',\n 'manyToMany',\n]);\n\n/**\n * The generated CRUD verbs, derived from the generators' own list so both\n * halves of this projection — which operations are ENUMERATED\n * (`resolveCrudOperations`) and which method names are RESERVED\n * (`reservesCrudName`) — move together. Reading one from `CRUD_OPERATIONS` and\n * the other from a local copy would let a new verb be suppressed as a custom\n * method while never being added as CRUD, dropping the surface entirely.\n */\nconst STANDARD_OPERATIONS: readonly string[] = CRUD_OPERATIONS;\n\nexport function buildDomainKnowledgeManifest(\n options: BuildDomainKnowledgeOptions,\n): DomainKnowledgeManifest {\n const rootDir = options.rootDir;\n const packageJson = options.packageJson ?? readPackageJson(rootDir) ?? {};\n const packageName = options.manifest.packageName ?? packageJson.name;\n const packageVersion = options.manifest.packageVersion ?? packageJson.version;\n const agentDocPath = existingPath(rootDir, 'AGENTS.md');\n const agentDocContent = agentDocPath\n ? readFileSync(agentDocPath, 'utf8')\n : undefined;\n const includeDocs = options.config?.includeDocs !== false;\n const agentDoc = includeDocs ? agentDocContent : undefined;\n // Module doc PATHS are always resolved so their hashes gate freshness even\n // when doc bodies are excluded from the artifact — same stance as `agents`.\n const moduleDocPaths = resolveAgentModuleDocPaths(rootDir, agentDocContent);\n const allDependencies = {\n ...record(packageJson.dependencies),\n ...record(packageJson.devDependencies),\n ...record(packageJson.peerDependencies),\n };\n const manifestObjects = Object.values(options.manifest.objects).filter(\n (object) => object.decoratorConfig?.knowledge !== false,\n );\n const objects = manifestObjects.map((object) =>\n buildKnowledgeObject(object, options.manifest),\n );\n const surfaces = objects.flatMap((object) => object.surfaces);\n const manifestJson = stableJson(normalizeManifestForHash(options.manifest));\n const agentSurface = normalizeAgentSurface(options.agentSurface);\n const relationshipsV2 = summarizeRelationships(objects, manifestObjects);\n\n return {\n schemaVersion: 1,\n sensitiveFieldsExcluded: true,\n generatedAt: new Date().toISOString(),\n packageName,\n packageVersion,\n sourceManifestPath: options.manifestPath\n ? relative(rootDir, options.manifestPath)\n : undefined,\n agentDocPath: agentDocPath ? relative(rootDir, agentDocPath) : undefined,\n sourceHashes: sourceHashes({\n manifest: { content: manifestJson },\n packageJson: fileHashSource(existingPath(rootDir, 'package.json')),\n agents: fileHashSource(agentDocPath),\n ...Object.fromEntries(\n moduleDocPaths.map((path) => [\n `${MODULE_DOC_HASH_PREFIX}${path}`,\n fileHashSource(join(rootDir, path)),\n ]),\n ),\n // A module declaring an intent or a playbook is an authored source of\n // this artifact exactly like `AGENTS.md` is, so editing one must mark the\n // artifact stale (#2591).\n ...Object.fromEntries(\n agentSurfaceSourcePaths(agentSurface).map((path) => [\n `${AGENT_SURFACE_HASH_PREFIX}${path}`,\n fileHashSource(join(rootDir, path)),\n ]),\n ),\n }),\n exports: exportKeys(packageJson.exports),\n dependencies: allDependencies,\n smrtDependencies: Object.keys(allDependencies)\n .filter((dep) => dep.startsWith('@happyvertical/smrt-'))\n .sort(),\n sdkDependencies: Object.keys(allDependencies)\n .filter((dep) => SDK_PACKAGE_NAMES.has(dep))\n .sort(),\n tags:\n options.config?.tags ?? deriveDefaultTags(packageJson, allDependencies),\n summary: options.config?.summary,\n risks:\n options.config?.risks ??\n deriveDefaultRisks({\n sensitiveFieldsExcluded: true,\n relationshipsV2,\n objects,\n }),\n objects,\n surfaces,\n prompts:\n options.config?.includePrompts === false ? [] : readPrompts(rootDir),\n relationshipsV2,\n agentDoc,\n moduleDocs:\n includeDocs && moduleDocPaths.length > 0\n ? readAgentModuleDocs(rootDir, agentDocContent)\n : undefined,\n agentSurface,\n };\n}\n\n/**\n * Drop an agent surface that carries nothing.\n *\n * Keeping the key absent for a package that declares no intent, no playbook,\n * and no diagnostic is what makes this field additive in practice: every\n * checked-in artifact for such a package stays byte-identical to what it\n * emitted before the field existed, so adding emission does not churn the\n * repository's knowledge artifacts.\n */\nfunction normalizeAgentSurface(\n surface: DomainKnowledgeAgentSurface | undefined,\n): DomainKnowledgeAgentSurface | undefined {\n if (!surface) return undefined;\n const empty =\n surface.intents.length === 0 &&\n surface.playbooks.length === 0 &&\n surface.diagnostics.length === 0;\n return empty ? undefined : surface;\n}\n\n/** Every package-relative module that contributed to the emitted surface. */\nfunction agentSurfaceSourcePaths(\n surface: DomainKnowledgeAgentSurface | undefined,\n): string[] {\n if (!surface) return [];\n const paths = new Set<string>();\n for (const intent of surface.intents) paths.add(intent.sourceFile);\n for (const playbook of surface.playbooks) paths.add(playbook.sourceFile);\n for (const diagnostic of surface.diagnostics)\n paths.add(diagnostic.sourceFile);\n return [...paths].sort();\n}\n\nfunction buildKnowledgeObject(\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): DomainKnowledgeObject {\n const knowledge =\n typeof object.decoratorConfig?.knowledge === 'object'\n ? object.decoratorConfig.knowledge\n : {};\n const fields = Object.entries(object.fields)\n .filter(([, field]) => !isSensitiveField(field))\n .map(([name, field]): DomainKnowledgeField => {\n const defaultValue = fieldValue(field, 'default');\n return {\n name,\n type: field.type,\n required: field.required,\n related: field.related,\n columnType: columnType(object, name),\n ...(defaultValue.present ? { default: defaultValue.value } : {}),\n constraints: fieldConstraints(field),\n readonly:\n field.readonly === true || field._meta?.readonly === true\n ? true\n : undefined,\n transient:\n field.transient === true || field._meta?.transient === true\n ? true\n : undefined,\n };\n });\n const sensitiveIdentifiers = sensitiveFieldIdentifiers(object.fields);\n const tenant = sanitizeTenantFacts(\n tenantFacts(object.decoratorConfig?.tenantScoped),\n sensitiveIdentifiers,\n );\n const conflictColumns = object.decoratorConfig?.conflictColumns?.filter(\n (column) => !sensitiveIdentifiers.has(column),\n );\n const relationships = fields\n .filter((field) => RELATIONSHIP_FIELD_TYPES.has(field.type))\n .map((field) => ({\n name: field.name,\n type: field.type,\n required: field.required,\n related: field.related,\n columnType: field.columnType,\n }));\n\n return {\n name: object.className,\n qualifiedName: object.qualifiedName,\n collection: object.collection,\n tableName: object.schema?.tableName,\n packageName: object.packageName,\n extends: object.extends,\n visibility: object.visibility,\n fields,\n relationships,\n methods: Object.keys(object.methods).sort(),\n methodSignatures: methodSignatures(object),\n tenant,\n tableStrategy: object.decoratorConfig?.tableStrategy,\n conflictColumns:\n conflictColumns && conflictColumns.length > 0\n ? conflictColumns\n : undefined,\n surfaces: objectSurfaces(object, manifest),\n ...withheldApiSurfaces(object, manifest),\n relationshipFeatures: relationshipFeatures(object, fields),\n tags: knowledge.tags ?? [],\n summary: knowledge.summary,\n risks: knowledge.risks ?? [],\n };\n}\n\nfunction isSensitiveField(field: SmartObjectDefinition['fields'][string]) {\n return field.sensitive === true || field._meta?.sensitive === true;\n}\n\nfunction sensitiveFieldIdentifiers(\n fields: SmartObjectDefinition['fields'],\n): Set<string> {\n return new Set(\n Object.entries(fields)\n .filter(([, field]) => isSensitiveField(field))\n .flatMap(([name]) => [name, toSnakeCase(name), camelToSnake(name)]),\n );\n}\n\nfunction fieldValue(\n field: SmartObjectDefinition['fields'][string],\n key: 'default' | 'min' | 'max' | 'minLength' | 'maxLength',\n): { present: boolean; value: unknown } {\n if (Object.hasOwn(field, key)) {\n return { present: field[key] !== undefined, value: field[key] };\n }\n const value = field._meta?.[key];\n return { present: value !== undefined, value };\n}\n\nfunction fieldConstraints(\n field: SmartObjectDefinition['fields'][string],\n): DomainKnowledgeFieldConstraints | undefined {\n const constraints: DomainKnowledgeFieldConstraints = {};\n for (const key of ['min', 'max', 'minLength', 'maxLength'] as const) {\n const value = fieldValue(field, key);\n if (value.present && typeof value.value === 'number') {\n constraints[key] = value.value;\n }\n }\n const pattern = normalizePattern(\n (field as { pattern?: unknown }).pattern ?? field._meta?.pattern,\n );\n if (pattern !== undefined) constraints.pattern = pattern;\n return Object.keys(constraints).length > 0 ? constraints : undefined;\n}\n\nfunction normalizePattern(pattern: unknown): string | undefined {\n if (typeof pattern === 'string') return pattern;\n if (pattern instanceof RegExp) return pattern.source;\n if (\n pattern &&\n typeof pattern === 'object' &&\n typeof (pattern as { source?: unknown }).source === 'string'\n ) {\n return (pattern as { source: string }).source;\n }\n return undefined;\n}\n\nfunction tenantFacts(\n tenantScoped: SmartObjectDefinition['decoratorConfig']['tenantScoped'],\n): DomainKnowledgeTenant | undefined {\n if (!tenantScoped) return undefined;\n if (tenantScoped === true) {\n return { scoped: true, mode: 'required', field: 'tenantId' };\n }\n return {\n scoped: true,\n mode: tenantScoped.mode ?? 'required',\n field: tenantScoped.field ?? 'tenantId',\n };\n}\n\nfunction sanitizeTenantFacts(\n tenant: DomainKnowledgeTenant | undefined,\n sensitiveIdentifiers: Set<string>,\n): DomainKnowledgeTenant | undefined {\n if (!tenant?.field || !sensitiveIdentifiers.has(tenant.field)) return tenant;\n return { scoped: tenant.scoped, mode: tenant.mode };\n}\n\nfunction methodSignatures(\n object: SmartObjectDefinition,\n): DomainKnowledgeMethodSignature[] | undefined {\n const signatures = Object.values(object.methods)\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((method) => ({\n name: method.name,\n async: method.async || undefined,\n static: method.isStatic || undefined,\n params:\n method.parameters.length > 0\n ? method.parameters.map(\n (parameter) =>\n `${parameter.name}${parameter.optional ? '?' : ''}: ${parameter.type}`,\n )\n : undefined,\n returns: method.returnType || undefined,\n }));\n return signatures.length > 0 ? signatures : undefined;\n}\n\nfunction objectSurfaces(\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): DomainKnowledgeSurface[] {\n return [\n ...configuredSurfaces('api', object, manifest),\n ...configuredSurfaces('cli', object, manifest),\n ...configuredSurfaces('mcp', object, manifest),\n ...aiSurfaces(object),\n ];\n}\n\n/**\n * Every API-exposure decision for one object's methods, from the shared\n * resolver the route emitters use — so a method reported here as exposed has a\n * route file, and one reported as withheld has none.\n *\n * The whole point of routing this through `resolveApiMethodExposure` rather\n * than a local mirror is that a fourth copy of the rule is a fourth chance to\n * disagree with the emitters (#2686).\n */\nfunction apiMethodDecisions(\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): Array<[string, ApiMethodExposure]> {\n const apiConfig = object.decoratorConfig?.api;\n const isModelClassName = createManifestClassNamePredicate(manifest);\n const collectionClass = isSurfaceCollectionClass(manifest, object);\n return Object.entries(object.methods).map(([name, method]) => [\n name,\n resolveApiMethodExposure({\n actionName: name,\n method,\n apiConfig,\n isCollectionClass: collectionClass,\n ...(isModelClassName ? { isModelClassName } : {}),\n }),\n ]);\n}\n\n/**\n * The `withheldSurfaces` half of the artifact: every public method the API\n * declined, with the reason.\n *\n * Reported for `api` only. `cli`/`mcp` gate on a much smaller, purely\n * name-based rule set that a reader can already infer from the config, while\n * the API's wire-ability heuristic rejects on a signature detail nothing else\n * in the artifact shows — which is exactly the silence #2686 set out to close.\n *\n * CRUD-reserved and non-public methods are excluded: neither was ever a\n * candidate custom action, so listing them would bury the actionable entries.\n */\nfunction withheldApiSurfaces(\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): { withheldSurfaces?: DomainKnowledgeWithheldSurface[] } {\n if (isFrameworkBaseClass(object.className, object.packageName)) return {};\n const withheld = apiMethodDecisions(object, manifest)\n .filter(\n ([, decision]) =>\n !decision.exposed &&\n decision.code !== 'crud-reserved' &&\n decision.code !== 'not-public',\n )\n .map(([operation, decision]) => ({\n kind: 'api' as const,\n operation,\n code: decision.code ?? 'unknown',\n reason: decision.reason ?? '',\n objectName: object.qualifiedName ?? object.className,\n }))\n .sort((a, b) => a.operation.localeCompare(b.operation));\n return withheld.length > 0 ? { withheldSurfaces: withheld } : {};\n}\n\nfunction configuredSurfaces(\n kind: 'api' | 'cli' | 'mcp',\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): DomainKnowledgeSurface[] {\n const config = object.decoratorConfig?.[kind];\n // NOTE: the `cli` projection models the reservation rule core's\n // `CLIGenerator` used to apply (retired by #2664 -- see git history for\n // the deleted `packages/core/src/generators/cli.ts`), which reserves a\n // CRUD verb unconditionally.\n // That is NOT the shipped local CLI: `packages/cli/src/cli-generator.ts`'s\n // generator reserves one only where the CRUD command is emitted (each of\n // its commands carries its own handler), so with\n // `cli: { include: ['list', 'get'] }` a public `create()` is a reachable\n // `${object}:create` there that this projection does not report.\n //\n // Retargeting this projection at the shipped binary is tracked on #2692.\n // That is a CONTRACT CHANGE rather than a cleanup: the generators genuinely\n // disagree, so `smrt-knowledge.json` snapshots would move. Predates #2646.\n const collectionClass = isSurfaceCollectionClass(manifest, object);\n const operations = configuredOperations(kind, object, config, manifest);\n return operations.map((operation) => {\n const route =\n kind === 'api' && !STANDARD_OPERATIONS.includes(operation)\n ? apiCustomRoute(object, operation, collectionClass)\n : undefined;\n return {\n kind,\n name: surfaceName(kind, object, operation),\n operation,\n objectName: object.qualifiedName ?? object.className,\n path: kind === 'api' ? apiPath(object, operation, route) : undefined,\n method: kind === 'api' ? apiMethod(operation, route) : undefined,\n };\n });\n}\n\n/**\n * `MCPGenerator.buildCustomActionTool()` registers a custom-action tool as\n * `` `${lowerName}_${methodName}`.toLowerCase() `` — lowercasing the WHOLE\n * joined string, not just the object-name prefix. A CRUD verb is already\n * lowercase so this is a no-op there, but a camelCase custom method name\n * (`findByDimensions`) would otherwise report a surface `name` the real tool\n * is never registered under. `packages/cli/src/cli-generator.ts`'s command\n * builder (`CLIGenerator`'s private `generateObjectCommands()`) does not\n * lowercase the method half of its command string, so `cli` keeps the\n * operation as-authored.\n *\n * Note the shapes differ from the transports' own: a `cli` surface `name`\n * here is `object_operation`, while the command a user types is\n * `object:operation`. `operation` is the field to correlate on.\n */\nfunction surfaceName(\n kind: 'api' | 'cli' | 'mcp',\n object: SmartObjectDefinition,\n operation: string,\n): string {\n if (kind === 'api') return `${object.collection}.${operation}`;\n const name = `${object.className.toLowerCase()}_${operation}`;\n return kind === 'mcp' ? name.toLowerCase() : name;\n}\n\n/**\n * A hand-written `SmrtCollection` subclass (`class WidgetCollection extends\n * SmrtCollection<Widget>`) is discovered structurally by the scanner and\n * lands in the manifest even without its own `@smrt()` decorator, so it never\n * registers with `ObjectRegistry` by decoration. `MCPGenerator` (and,\n * historically, core's now-retired `CLIGenerator`, #2664) iterate the\n * decoration-populated `ObjectRegistry` directly, not the manifest, so such a\n * class never gets its own MCP tools there — only its collection-scoped\n * custom actions get REST routes. The shipped local CLI\n * (`packages/cli/src/cli-generator.ts`) is a documented exception: its\n * `ensureManifestLoaded()` pre-registers every manifest entry into\n * `ObjectRegistry` via `registerFromManifest()` before generating commands,\n * with no collection-class filter, so a manifest-only collection class IS\n * reachable there (e.g. `smrt itemcollection:list`) even though this\n * projection reports none. Reporting full CRUD for it here would over-report\n * the projection's own (registry-scoped) surface, trading the #2619\n * under-report for a new false positive there -- it does not claim the\n * shipped CLI binary lacks the surface too.\n *\n * A deeper subclass (`SpecialCollection extends WidgetCollection`) carries no\n * `extendsTypeArg` of its own, so this walks the extends chain through the\n * manifest — mirroring `isCollectionManifestClass` in\n * `vite-plugin/web-collections.ts` (kept as a separate, lean implementation\n * here rather than imported: that module pulls in the full SvelteKit route\n * generator transitively, which would balloon the standalone `./knowledge`\n * build entry for a ~15-line check).\n */\nfunction isSurfaceCollectionClass(\n manifest: SmartObjectManifest,\n object: SmartObjectDefinition,\n seen: Set<string> = new Set(),\n): boolean {\n // Truthy check (not `!== undefined`) mirrors the scanner: a non-generic\n // base emitting `extendsTypeArg: null` must not be misread as a collection.\n if (object.extends === 'SmrtCollection' || object.extendsTypeArg) {\n return true;\n }\n const parentName = object.extendsQualified || object.extends;\n if (!parentName || seen.has(parentName)) return false;\n seen.add(parentName);\n const parent = findManifestObjectByName(manifest, parentName, object);\n return parent ? isSurfaceCollectionClass(manifest, parent, seen) : false;\n}\n\nfunction findManifestObjectByName(\n manifest: SmartObjectManifest,\n name: string,\n owner: SmartObjectDefinition,\n): SmartObjectDefinition | undefined {\n const entries = Object.entries(manifest.objects);\n if (name.includes(':')) {\n const exact = entries.find(\n ([key, candidate]) => (candidate.qualifiedName ?? key) === name,\n );\n if (exact) return exact[1];\n }\n // Prefer a same-package parent before falling back to a bare simple name:\n // an aggregated manifest can carry several classes sharing one simple name,\n // and resolving the wrong one misclassifies the collection-class carve-out.\n const ownerKey = entries.find(([, candidate]) => candidate === owner)?.[0];\n const ownerPackage = manifestObjectPackage(owner, ownerKey);\n if (ownerPackage) {\n const packageLocal = entries.find(\n ([key, candidate]) =>\n manifestObjectPackage(candidate, key) === ownerPackage &&\n candidate.className === name,\n );\n if (packageLocal) return packageLocal[1];\n }\n return entries.find(([, candidate]) => candidate.className === name)?.[1];\n}\n\n/**\n * An object's owning package. `packageName` is optional on\n * `SmartObjectDefinition` (older manifests and hand-built fixtures omit it),\n * so fall back to the package half of the qualified name — and, when that is\n * absent too, of the manifest key, which is qualified for every entry the\n * scanner writes. Mirrors `manifestObjectPackage` in\n * `vite-plugin/web-collections.ts`, key fallback included: without it an\n * entry carrying only a qualified key resolves no package at all, the\n * same-package preference is skipped, and a duplicate simple name can pick\n * the wrong parent.\n */\nfunction manifestObjectPackage(\n object: SmartObjectDefinition,\n manifestKey?: string,\n): string | undefined {\n if (object.packageName) return object.packageName;\n const qualifiedName = object.qualifiedName ?? manifestKey;\n const separator = qualifiedName?.lastIndexOf(':') ?? -1;\n return separator > 0 ? qualifiedName?.slice(0, separator) : undefined;\n}\n\n/**\n * Operations exposed for one object's `api`/`cli`/`mcp` surface, derived from\n * the same defaults `APIGenerator`/core's retired `CLIGenerator`\n * (#2664)/`MCPGenerator` apply rather\n * than from the presence of a config key (#2619): an omitted config is full\n * CRUD, not a closed surface — an `include` list, when present, is the\n * COMPLETE allowlist for custom methods too; without one, every public\n * method not explicitly excluded is exposed by default. Only `config ===\n * false` closes the surface entirely.\n *\n * Custom (non-CRUD, public) method gating is NOT identical across the three\n * kinds. Core's retired `CLIGenerator.listCommands()`/`assertCommandExposed()`\n * (#2664) and\n * `MCPGenerator.generateTools()` both refuse a framework lifecycle method\n * (`save`, `initialize`, ...) even when a class declares its own override —\n * it is the mechanism behind generated CRUD, not a distinct action (#2638) —\n * and `resolveCustomMethodNames()` below mirrors that same\n * `isFrameworkLifecycleMethod()` check for `kind === 'cli'` and\n * `kind === 'mcp'` (#2657, #2638). `api` remains ungated on this: the\n * generator did not change in #2650/#2638, and the fix there is a PR #2651\n * recommendation, not yet implemented.\n *\n * `resolveCustomMethodNames()` also mirrors two more `mcp`-only behaviors\n * that follow from its case-folded tool-id namespace (#2638): an `exclude`\n * entry is compared case-insensitively (matching `MCPGenerator`'s own\n * asymmetry fix -- `exclude` used to fail open on a cased entry the way\n * `include` never did), and two method names that fold onto the same tool id\n * (e.g. `Refresh`/`refresh`) are reported once, keeping whichever was\n * declared first, mirroring `MCPGenerator`'s per-object dedup. `cli`/`api`\n * keep declared casing in their command/route names, so neither behavior\n * applies to them.\n *\n * This `cli` projection models the reservation rule core's `CLIGenerator`\n * used to apply (`generators/cli.ts`, retired by #2664), not the shipped\n * local CLI transport (`packages/cli/src/cli-generator.ts`, the\n * `smrt <object>:<action>` binary): that generator does not gate on\n * `isFrameworkLifecycleMethod()` today, so a locally overridden lifecycle\n * method the artifact now reports as absent can still be invoked there.\n * Retargeting this projection at the shipped binary is a contract change\n * tracked on #2692, not part of this fix.\n */\nfunction configuredOperations(\n kind: 'api' | 'cli' | 'mcp',\n object: SmartObjectDefinition,\n config: unknown,\n manifest: SmartObjectManifest,\n): string[] {\n if (config === false) return [];\n // The framework's own abstract base classes (SmrtObject, SmrtCollection,\n // ...) are scaffolding, not resources: MCPGenerator/route generation and\n // packages/cli's CLIGenerator all skip them by class identity now (#2642),\n // independent of\n // their `decoratorConfig: {}` shape, so this mirrors the same shared\n // check rather than reporting a synthetic surface for them.\n if (isFrameworkBaseClass(object.className, object.packageName)) return [];\n const collectionClass = isSurfaceCollectionClass(manifest, object);\n const crud = collectionClass ? [] : resolveCrudOperations(config);\n // `api` delegates custom-method eligibility wholesale to the emitters' own\n // resolver — CRUD reservation, framework lifecycle methods, include/exclude,\n // `@method()` overrides, the wire-ability heuristic, and the receiver check\n // are all decided there, once (#2686). `cli`/`mcp` keep their own projection\n // of `CLIGenerator`/`MCPGenerator`, whose rules genuinely differ (case-folded\n // tool ids, per-object dedup) and which #2692 owns.\n if (kind === 'api') {\n const custom = apiMethodDecisions(object, manifest)\n .filter(([, decision]) => decision.exposed)\n .map(([operation]) => operation);\n return [...crud, ...custom];\n }\n const custom = resolveCustomMethodNames(\n Object.entries(object.methods),\n config,\n kind,\n );\n return [...crud, ...custom];\n}\n\nfunction resolveCrudOperations(config: unknown): string[] {\n const { include, exclude } = includeExcludeConfig(config);\n const base = include\n ? STANDARD_OPERATIONS.filter((operation) => include.includes(operation))\n : [...STANDARD_OPERATIONS];\n if (!exclude || exclude.length === 0) return base;\n const excluded = new Set(exclude);\n return base.filter((operation) => !excluded.has(operation));\n}\n\nfunction resolveCustomMethodNames(\n methods: Iterable<[string, { isPublic?: boolean }]>,\n config: unknown,\n kind: 'api' | 'cli' | 'mcp',\n): string[] {\n const { include, exclude } = includeExcludeConfig(config);\n const excluded = new Set(exclude ?? []);\n // MCP tool ids are case-folded, so `MCPGenerator` compares `exclude`\n // case-insensitively too (`exclude: ['Refresh']` must suppress a method\n // declared `refresh`, and vice versa, #2638) -- mirror that here for\n // `kind === 'mcp'` only. `cli`/`api` keep the declared casing in their\n // command/route names (same asymmetry `reservesCrudName` documents below),\n // so an exact-match `exclude` stays correct for them.\n const excludedLower =\n kind === 'mcp'\n ? new Set([...excluded].map((entry) => entry.toLowerCase()))\n : undefined;\n // Tool ids already claimed for this object's `mcp` surface, so two\n // distinctly-cased method names (e.g. `Refresh`/`refresh`) that fold onto\n // the same MCP tool id are reported once, not twice -- mirroring\n // `MCPGenerator`'s per-object dedup (first declared wins, #2638). `cli`/\n // `api` need no such set: their command/route names keep declared casing,\n // so two cased method names never collide there.\n const emittedLower = kind === 'mcp' ? new Set<string>() : undefined;\n const names: string[] = [];\n for (const [name, method] of methods) {\n if (reservesCrudName(kind, name)) continue;\n // A framework lifecycle method (save/initialize/...) is never a custom\n // CLI or MCP action, even when a class declares its own override — it is\n // the mechanism behind generated CRUD, not a distinct operation, matching\n // core's retired CLIGenerator's (#2664) and MCPGenerator's own\n // isFrameworkLifecycleMethod() gate\n // (#2657, #2638). `api` is deliberately left alone — see\n // configuredOperations' doc comment above.\n if ((kind === 'cli' || kind === 'mcp') && isFrameworkLifecycleMethod(name))\n continue;\n if (!method.isPublic) continue;\n if (\n excludedLower ? excludedLower.has(name.toLowerCase()) : excluded.has(name)\n )\n continue;\n if (include !== undefined && !include.includes(name)) continue;\n if (emittedLower) {\n const lower = name.toLowerCase();\n if (emittedLower.has(lower)) continue;\n emittedLower.add(lower);\n }\n names.push(name);\n }\n return names;\n}\n\n/**\n * Whether `kind` reserves `name` for its generated CRUD operation, so the\n * method behind it is not reported as a distinct surface.\n *\n * MCP folds case: its tool ids are lowercased whole\n * (`` `${object}_${method}`.toLowerCase() ``), so a method named `List` lands on\n * the `${object}_list` identifier the CRUD tool already owns and\n * `MCPGenerator` emits no separate tool for it (#2646). REST and the CLI keep\n * the declared casing in their route/command names, so only an exact match is\n * reserved there.\n *\n * Reads the emitters' own predicates rather than re-testing the verb list, and\n * `STANDARD_OPERATIONS` derives from `CRUD_OPERATIONS`, so a change to the\n * shared list reaches both halves of this projection together.\n */\nfunction reservesCrudName(kind: 'api' | 'cli' | 'mcp', name: string): boolean {\n return kind === 'mcp' ? isCrudToolAction(name) : isCrudOperation(name);\n}\n\nfunction includeExcludeConfig(config: unknown): {\n include?: string[];\n exclude?: string[];\n} {\n if (typeof config !== 'object' || config === null || Array.isArray(config)) {\n return {};\n }\n // A non-array `include`/`exclude` is treated as unset rather than\n // throwing later on `.includes()` — mirrors the same defensive stance\n // `shouldIncludeInApi` in `vite-plugin/sveltekit-generator.ts` takes for\n // a scanned decorator config that failed to resolve to an array.\n const record = config as { include?: unknown; exclude?: unknown };\n return {\n include: Array.isArray(record.include) ? record.include : undefined,\n exclude: Array.isArray(record.exclude) ? record.exclude : undefined,\n };\n}\n\nfunction aiSurfaces(object: SmartObjectDefinition): DomainKnowledgeSurface[] {\n return (object.tools ?? []).map((tool) => ({\n kind: 'ai',\n name: tool.function.name,\n operation: tool.function.name,\n description: tool.function.description,\n objectName: object.qualifiedName ?? object.className,\n }));\n}\n\n/** Route facts for one custom action, as `generateRoutesForObject` emits it. */\ninterface ApiCustomRoute {\n scope: 'item' | 'collection';\n segments: string[];\n method: string;\n}\n\n/**\n * Resolve a custom (non-CRUD) action's REST route the way the generator does,\n * or `undefined` when no route is emitted for it at all.\n *\n * A custom action's path is NOT `/collection/action`: `generateRoutesForObject`\n * nests an item-scoped action under `[id]`, and an instance method defaults to\n * item scope. Reporting the collection-shaped path for every public instance\n * method would advertise endpoints that do not exist — the exact failure this\n * projection exists to avoid. Scope comes from the shared\n * `resolveCustomActionMetadata`, the same resolver the REST, CLI, MCP, and\n * WebMCP paths use, so a `routes` override cannot drift between them.\n *\n * `kebabRoutes` is a Vite-plugin option rather than manifest data, so an\n * explicit `routes[action].path` is honored but the generator's optional\n * kebab-casing of a derived segment is not visible here.\n */\nfunction apiCustomRoute(\n object: SmartObjectDefinition,\n operation: string,\n collectionClass: boolean,\n): ApiCustomRoute | undefined {\n const method = object.methods[operation];\n const apiConfig = object.decoratorConfig?.api;\n const defaultScope: 'item' | 'collection' =\n collectionClass || method?.isStatic ? 'collection' : 'item';\n const scope = resolveActionScope(operation, method, apiConfig, defaultScope);\n\n // Mirrors the generator's own skips: a collection class emits only\n // collection-scoped routes, and a model class warns and skips a\n // collection-scoped non-static method (no receiver to bind).\n if (collectionClass) {\n if (scope !== 'collection') return undefined;\n } else if (scope === 'collection' && !method?.isStatic) {\n return undefined;\n }\n\n // `@method({ path, httpMethod })` wins field by field over the legacy\n // `api.routes[operation]` entry, exactly as `resolveApiActionRouteConfig`\n // resolves it for the emitter — otherwise the artifact would report the\n // pre-migration URL for a class that has moved to the decorator (#2686).\n const effective = resolveEffectiveActionMetadata({\n actionName: operation,\n ...(method ? { method } : {}),\n apiConfig,\n });\n const overridden =\n typeof effective.path === 'string'\n ? effective.path\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean)\n : [];\n return {\n scope,\n segments: overridden.length > 0 ? overridden : [operation],\n method: normalizeApiMethod(effective.httpMethod),\n };\n}\n\n/**\n * The shared resolver validates as it resolves — a `routes` entry declaring\n * `effect: 'read'` on a PUT/PATCH/DELETE route throws by design. This\n * projection reads untrusted scanned config and must not fail the whole\n * knowledge build for one malformed action (same defensive stance as\n * {@link includeExcludeConfig}), so fall back to the receiver the method\n * itself dictates — which a route-only override cannot change anyway.\n */\nfunction resolveActionScope(\n operation: string,\n method: SmartObjectDefinition['methods'][string] | undefined,\n apiConfig: unknown,\n defaultScope: 'item' | 'collection',\n): 'item' | 'collection' {\n try {\n return resolveCustomActionMetadata({\n actionName: operation,\n method,\n apiConfig,\n defaultScope,\n }).scope;\n } catch {\n return defaultScope;\n }\n}\n\n/** Mirrors `normalizeApiHttpMethod` in `vite-plugin/sveltekit-generator.ts`. */\nfunction normalizeApiMethod(method: unknown): string {\n const normalized =\n typeof method === 'string' ? method.toUpperCase() : undefined;\n switch (normalized) {\n case 'GET':\n case 'POST':\n case 'PUT':\n case 'PATCH':\n case 'DELETE':\n return normalized;\n default:\n return 'POST';\n }\n}\n\n/**\n * The collection segment of a generated REST route.\n *\n * `generateRoutesForObject` builds its route directory from\n * `objectDef.collection` verbatim, and the runtime dispatcher in\n * `generators/rest.ts` matches the URL segment against `info.collection`\n * verbatim, so this reports that and nothing else (#2630).\n *\n * In particular it does NOT read `api.path`, which configures a different\n * surface: `@happyvertical/smrt-agents`' own agent-facing route map derives\n * `api.path ?? tableName.replace(/_/g, '-')`. Honoring it here produced a\n * hybrid — `api.path` over `collection` — that matched neither transport and\n * named endpoints that 404 on both.\n */\nfunction apiCollectionSegment(object: SmartObjectDefinition): string {\n return object.collection;\n}\n\nfunction apiPath(\n object: SmartObjectDefinition,\n operation: string,\n route?: ApiCustomRoute,\n): string {\n const configuredPath = apiCollectionSegment(object);\n if (route) {\n const base =\n route.scope === 'collection'\n ? `/${configuredPath}`\n : `/${configuredPath}/[id]`;\n return `${base}/${route.segments.join('/')}`;\n }\n if (operation === 'list' || operation === 'create') {\n return `/${configuredPath}`;\n }\n if (STANDARD_OPERATIONS.includes(operation)) {\n return `/${configuredPath}/[id]`;\n }\n return `/${configuredPath}/${operation}`;\n}\n\nfunction apiMethod(operation: string, route?: ApiCustomRoute): string {\n if (route) return route.method;\n switch (operation) {\n case 'list':\n case 'get':\n return 'GET';\n case 'create':\n return 'POST';\n case 'update':\n return 'PATCH';\n case 'delete':\n return 'DELETE';\n default:\n return 'POST';\n }\n}\n\nfunction relationshipFeatures(\n object: SmartObjectDefinition,\n fields: DomainKnowledgeField[],\n): string[] {\n const features = new Set<string>();\n for (const field of fields) {\n if (field.type === 'foreignKey') features.add('foreignKey');\n if (field.type === 'crossPackageRef') features.add('crossPackageRef');\n if (field.type === 'oneToMany') features.add('oneToMany');\n if (field.type === 'manyToMany') features.add('manyToMany');\n }\n if (object.extends === 'SmrtJunction') features.add('SmrtJunction');\n if (object.extends === 'SmrtHierarchical') features.add('SmrtHierarchical');\n if (\n object.extends === 'SmrtPolymorphicAssociation' ||\n fields.some((field) => field.name === 'metaType') ||\n fields.some((field) => field.name === 'metaId')\n ) {\n features.add('SmrtPolymorphicAssociation');\n }\n if (\n Object.keys(object.schema?.columns ?? {}).some(\n (name) => object.schema?.columns[name]?.type === 'UUID',\n )\n ) {\n features.add('uuidColumns');\n }\n return [...features].sort();\n}\n\nfunction summarizeRelationships(\n objects: DomainKnowledgeObject[],\n manifestObjects: SmartObjectDefinition[],\n) {\n const fields = objects.flatMap((object) => object.fields);\n return {\n foreignKeyFields: fields.filter((field) => field.type === 'foreignKey')\n .length,\n crossPackageRefFields: fields.filter(\n (field) => field.type === 'crossPackageRef',\n ).length,\n junctionCollections: objects.filter((object) =>\n object.relationshipFeatures.includes('SmrtJunction'),\n ).length,\n hierarchicalObjects: objects.filter((object) =>\n object.relationshipFeatures.includes('SmrtHierarchical'),\n ).length,\n polymorphicAssociations: objects.filter((object) =>\n object.relationshipFeatures.includes('SmrtPolymorphicAssociation'),\n ).length,\n uuidColumns: manifestObjects.reduce(\n (count, object) =>\n count +\n Object.values(object.schema?.columns ?? {}).filter(\n (column) => column.type === 'UUID',\n ).length,\n 0,\n ),\n };\n}\n\n/**\n * Documented default `tags` derivation for a package's domain-knowledge\n * artifact when `@smrt({ knowledge: { tags } })` is not set (#2863).\n *\n * Never invents taxonomy: tags come only from `package.json#keywords`\n * (authored by the package owner) plus a `cross-package` tag when the\n * package declares a `@happyvertical/smrt-*` dependency. This keeps the\n * derivation deterministic and traceable to an authored source, matching\n * the \"populate tags/risks from scanner output where the manifest carries\n * the data\" scope — a package that wants richer tags still sets\n * `knowledge.tags` explicitly.\n */\nfunction deriveDefaultTags(\n packageJson: PackageJsonLike,\n allDependencies: Record<string, string>,\n): string[] {\n const tags = new Set<string>();\n const keywords = packageJson.keywords;\n if (Array.isArray(keywords)) {\n for (const keyword of keywords) {\n if (typeof keyword === 'string' && keyword.trim()) {\n tags.add(keyword.trim());\n }\n }\n }\n if (\n Object.keys(allDependencies).some((dep) =>\n dep.startsWith('@happyvertical/smrt-'),\n )\n ) {\n tags.add('cross-package');\n }\n return [...tags].sort();\n}\n\n/**\n * Documented default `risks` derivation (#2863). Each entry names a\n * structural fact the manifest already carries — never freeform prose — so\n * it stays deterministic and regenerable:\n *\n * - `sensitive-fields-excluded`: generation always strips sensitive fields\n * before projecting objects (`sensitiveFieldsExcluded` is unconditionally\n * `true`), so a reviewer relying on this artifact must not treat it as a\n * complete field inventory.\n * - `cross-package-refs:<n>`: the package reads or writes another package's\n * rows through `@crossPackageRef`; a reviewer must check that package's\n * tenancy and lifecycle guarantees too.\n * - `sti-inheritance`: at least one object shares a table via\n * `tableStrategy: 'sti'`; a schema change must consider every sibling.\n * - `polymorphic-associations:<n>`: at least one\n * `SmrtPolymorphicAssociation`, whose target type is resolved at read time\n * rather than by a foreign key constraint.\n */\nfunction deriveDefaultRisks(options: {\n sensitiveFieldsExcluded: true;\n relationshipsV2: ReturnType<typeof summarizeRelationships>;\n objects: DomainKnowledgeObject[];\n}): string[] {\n const risks = new Set<string>();\n if (options.sensitiveFieldsExcluded) {\n risks.add('sensitive-fields-excluded');\n }\n if (options.relationshipsV2.crossPackageRefFields > 0) {\n risks.add(\n `cross-package-refs:${options.relationshipsV2.crossPackageRefFields}`,\n );\n }\n if (options.objects.some((object) => object.tableStrategy === 'sti')) {\n risks.add('sti-inheritance');\n }\n if (options.relationshipsV2.polymorphicAssociations > 0) {\n risks.add(\n `polymorphic-associations:${options.relationshipsV2.polymorphicAssociations}`,\n );\n }\n return [...risks].sort();\n}\n\nfunction columnType(\n object: SmartObjectDefinition,\n fieldName: string,\n): string | undefined {\n const columnName = camelToSnake(fieldName);\n return object.schema?.columns[columnName]?.type;\n}\n\nfunction readPrompts(\n rootDir: string,\n): Array<{ filePath: string; key?: string }> {\n const srcDir = join(rootDir, 'src');\n if (!existsSync(srcDir)) return [];\n const prompts: Array<{ filePath: string; key?: string }> = [];\n for (const filePath of walkFiles(srcDir)) {\n if (!filePath.endsWith('.ts')) continue;\n const content = readFileSync(filePath, 'utf8');\n if (!content.includes('definePrompt')) continue;\n const keyMatch = content.match(/definePrompt\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]/);\n prompts.push({\n filePath: relative(rootDir, filePath),\n key: keyMatch?.[1],\n });\n }\n return prompts;\n}\n\nfunction walkFiles(dir: string): string[] {\n const files: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (\n entry.name === 'node_modules' ||\n entry.name === 'dist' ||\n entry.name === '.svelte-kit'\n ) {\n continue;\n }\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...walkFiles(fullPath));\n } else if (entry.isFile()) {\n files.push(fullPath);\n }\n }\n return files;\n}\n\nfunction sourceHashes(sources: Record<string, HashSource | undefined>) {\n const hashes: Record<string, string> = {};\n for (const [name, source] of Object.entries(sources)) {\n if (!source) continue;\n const content =\n 'content' in source ? source.content : readFileSync(source.path, 'utf8');\n hashes[name] = createHash('sha256').update(content).digest('hex');\n }\n return hashes;\n}\n\ntype HashSource = { content: string } | { path: string };\n\nfunction fileHashSource(path: string | undefined): HashSource | undefined {\n return path ? { path } : undefined;\n}\n\nfunction existingPath(rootDir: string, path: string): string | undefined {\n const fullPath = join(rootDir, path);\n return existsSync(fullPath) ? fullPath : undefined;\n}\n\nfunction readPackageJson(rootDir: string): PackageJsonLike | null {\n const path = join(rootDir, 'package.json');\n if (!existsSync(path)) return null;\n return JSON.parse(readFileSync(path, 'utf8'));\n}\n\nfunction record(value: unknown): Record<string, string> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, string>)\n : {};\n}\n\nfunction exportKeys(exportsField: unknown): string[] {\n if (typeof exportsField === 'string') return ['.'];\n if (\n typeof exportsField !== 'object' ||\n exportsField === null ||\n Array.isArray(exportsField)\n ) {\n return [];\n }\n return Object.keys(exportsField).sort();\n}\n\nfunction camelToSnake(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n .replace(/[-\\s]+/g, '_')\n .toLowerCase();\n}\n\nfunction normalizeManifestForHash(manifest: SmartObjectManifest): unknown {\n const normalized = JSON.parse(JSON.stringify(manifest)) as Record<\n string,\n unknown\n >;\n delete normalized.timestamp;\n return normalized;\n}\n\nfunction stableJson(value: unknown): string {\n return JSON.stringify(sortJson(value), null, 2);\n}\n\nfunction sortJson(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortJson);\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, entry]) => [key, sortJson(entry)]),\n );\n }\n return value;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"knowledge.js","names":[],"sources":["../src/knowledge.ts"],"sourcesContent":["import {\n AGENT_SURFACE_HASH_PREFIX,\n MODULE_DOC_HASH_PREFIX,\n readAgentModuleDocs,\n resolveAgentModuleDocPaths,\n} from '@happyvertical/smrt-scanner/knowledge';\n\nexport {\n publishArtifactFiles,\n publishAtomicArtifact,\n} from './consumer-plugin/artifact-publication.js';\nexport { resolveFileKnowledgeConfig } from './knowledge-config.js';\nexport {\n discoverScopedPackageDirectories,\n readPackageAgentDoc,\n type ScopedPackageDirectory,\n} from './knowledge-discovery.js';\nexport {\n buildKnowledgeGraph,\n checkKnowledgeGraphFreshness,\n discoverKnowledgeArtifactPaths,\n type KnowledgeGraphEdge,\n type KnowledgeGraphEdgeType,\n type KnowledgeGraphFreshnessIssue,\n type KnowledgeGraphInput,\n type KnowledgeGraphObjectNode,\n type KnowledgeGraphPackageNode,\n type SmrtKnowledgeGraph,\n stableStringify,\n} from './knowledge-graph.js';\nexport {\n AGENT_SURFACE_HASH_PREFIX,\n MODULE_DOC_HASH_PREFIX,\n readAgentModuleDocs,\n resolveAgentModuleDocPaths,\n};\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type {\n DomainKnowledgeAgentSurface,\n DomainKnowledgeConfig,\n DomainKnowledgeField,\n DomainKnowledgeFieldConstraints,\n DomainKnowledgeManifest,\n DomainKnowledgeMethodSignature,\n DomainKnowledgeObject,\n DomainKnowledgeSurface,\n DomainKnowledgeTenant,\n DomainKnowledgeWithheldSurface,\n} from '@happyvertical/smrt-types';\nimport {\n type ApiMethodExposure,\n CRUD_OPERATIONS,\n createManifestClassNamePredicate,\n isCrudOperation,\n isCrudToolAction,\n isFrameworkLifecycleMethod,\n resolveApiMethodExposure,\n resolveCustomActionMetadata,\n resolveEffectiveActionMetadata,\n} from './generators/custom-action.js';\nimport { isFrameworkBaseClass } from './registry/framework-base-classes.js';\nimport type {\n SmartObjectDefinition,\n SmartObjectManifest,\n} from './scanner/types.js';\nimport { toSnakeCase } from './utils/naming.js';\n\n/**\n * Minimal package.json shape consumed by the knowledge builder.\n * `name`/`version` are typed concretely because they flow into the manifest's\n * string-typed metadata fields; everything else is read via `unknown`-accepting\n * helpers (`record()`, `exportKeys()`), so an index signature is sufficient.\n */\nexport interface PackageJsonLike {\n name?: string;\n version?: string;\n [key: string]: unknown;\n}\n\nexport interface BuildDomainKnowledgeOptions {\n manifest: SmartObjectManifest;\n rootDir: string;\n packageJson?: PackageJsonLike;\n manifestPath?: string;\n config?: DomainKnowledgeConfig;\n /**\n * The package's declared view intents and playbooks (#2591), produced by the\n * scanner's agent-surface matcher.\n *\n * Passed in rather than scanned here for one reason: the scanner carries a\n * native parser binary, and `smrt-core`'s main entry is browser-reachable.\n * The Vite plugin already imports the scanner lazily on the Node side and is\n * the one caller that writes this artifact, so it does the scan and hands the\n * result over.\n */\n agentSurface?: DomainKnowledgeAgentSurface;\n}\n\nconst SDK_PACKAGE_NAMES = new Set([\n '@happyvertical/ai',\n '@happyvertical/cache',\n '@happyvertical/documents',\n '@happyvertical/email',\n '@happyvertical/encryption',\n '@happyvertical/files',\n '@happyvertical/geo',\n '@happyvertical/images',\n '@happyvertical/jobs',\n '@happyvertical/json',\n '@happyvertical/logger',\n '@happyvertical/messages',\n '@happyvertical/ocr',\n '@happyvertical/pdf',\n '@happyvertical/projects',\n '@happyvertical/repos',\n '@happyvertical/secrets',\n '@happyvertical/spider',\n '@happyvertical/sql',\n '@happyvertical/utils',\n]);\n\nconst RELATIONSHIP_FIELD_TYPES = new Set([\n 'foreignKey',\n 'crossPackageRef',\n 'oneToMany',\n 'manyToMany',\n]);\n\n/**\n * The generated CRUD verbs, derived from the generators' own list so both\n * halves of this projection — which operations are ENUMERATED\n * (`resolveCrudOperations`) and which method names are RESERVED\n * (`reservesCrudName`) — move together. Reading one from `CRUD_OPERATIONS` and\n * the other from a local copy would let a new verb be suppressed as a custom\n * method while never being added as CRUD, dropping the surface entirely.\n */\nconst STANDARD_OPERATIONS: readonly string[] = CRUD_OPERATIONS;\n\nexport function buildDomainKnowledgeManifest(\n options: BuildDomainKnowledgeOptions,\n): DomainKnowledgeManifest {\n const rootDir = options.rootDir;\n const packageJson = options.packageJson ?? readPackageJson(rootDir) ?? {};\n const packageName = options.manifest.packageName ?? packageJson.name;\n const packageVersion = options.manifest.packageVersion ?? packageJson.version;\n const agentDocPath = existingPath(rootDir, 'AGENTS.md');\n const agentDocContent = agentDocPath\n ? readFileSync(agentDocPath, 'utf8')\n : undefined;\n const includeDocs = options.config?.includeDocs !== false;\n const agentDoc = includeDocs ? agentDocContent : undefined;\n // Module doc PATHS are always resolved so their hashes gate freshness even\n // when doc bodies are excluded from the artifact — same stance as `agents`.\n const moduleDocPaths = resolveAgentModuleDocPaths(rootDir, agentDocContent);\n const allDependencies = {\n ...record(packageJson.dependencies),\n ...record(packageJson.devDependencies),\n ...record(packageJson.peerDependencies),\n };\n const manifestObjects = Object.values(options.manifest.objects).filter(\n (object) => object.decoratorConfig?.knowledge !== false,\n );\n const objects = manifestObjects.map((object) =>\n buildKnowledgeObject(object, options.manifest),\n );\n const surfaces = objects.flatMap((object) => object.surfaces);\n const manifestJson = stableJson(normalizeManifestForHash(options.manifest));\n const agentSurface = normalizeAgentSurface(options.agentSurface);\n const relationshipsV2 = summarizeRelationships(objects, manifestObjects);\n\n return {\n schemaVersion: 1,\n sensitiveFieldsExcluded: true,\n generatedAt: new Date().toISOString(),\n packageName,\n packageVersion,\n sourceManifestPath: options.manifestPath\n ? relative(rootDir, options.manifestPath)\n : undefined,\n agentDocPath: agentDocPath ? relative(rootDir, agentDocPath) : undefined,\n sourceHashes: sourceHashes({\n manifest: { content: manifestJson },\n packageJson: fileHashSource(existingPath(rootDir, 'package.json')),\n agents: fileHashSource(agentDocPath),\n ...Object.fromEntries(\n moduleDocPaths.map((path) => [\n `${MODULE_DOC_HASH_PREFIX}${path}`,\n fileHashSource(join(rootDir, path)),\n ]),\n ),\n // A module declaring an intent or a playbook is an authored source of\n // this artifact exactly like `AGENTS.md` is, so editing one must mark the\n // artifact stale (#2591).\n ...Object.fromEntries(\n agentSurfaceSourcePaths(agentSurface).map((path) => [\n `${AGENT_SURFACE_HASH_PREFIX}${path}`,\n fileHashSource(join(rootDir, path)),\n ]),\n ),\n }),\n exports: exportKeys(packageJson.exports),\n dependencies: allDependencies,\n smrtDependencies: Object.keys(allDependencies)\n .filter((dep) => dep.startsWith('@happyvertical/smrt-'))\n .sort(),\n sdkDependencies: Object.keys(allDependencies)\n .filter((dep) => SDK_PACKAGE_NAMES.has(dep))\n .sort(),\n tags:\n options.config?.tags ?? deriveDefaultTags(packageJson, allDependencies),\n summary: options.config?.summary,\n risks:\n options.config?.risks ??\n deriveDefaultRisks({\n sensitiveFieldsExcluded: true,\n relationshipsV2,\n objects,\n }),\n objects,\n surfaces,\n prompts:\n options.config?.includePrompts === false ? [] : readPrompts(rootDir),\n relationshipsV2,\n agentDoc,\n moduleDocs:\n includeDocs && moduleDocPaths.length > 0\n ? readAgentModuleDocs(rootDir, agentDocContent)\n : undefined,\n agentSurface,\n };\n}\n\n/**\n * Drop an agent surface that carries nothing.\n *\n * Keeping the key absent for a package that declares no intent, no playbook,\n * and no diagnostic is what makes this field additive in practice: every\n * checked-in artifact for such a package stays byte-identical to what it\n * emitted before the field existed, so adding emission does not churn the\n * repository's knowledge artifacts.\n */\nfunction normalizeAgentSurface(\n surface: DomainKnowledgeAgentSurface | undefined,\n): DomainKnowledgeAgentSurface | undefined {\n if (!surface) return undefined;\n const empty =\n surface.intents.length === 0 &&\n surface.playbooks.length === 0 &&\n surface.diagnostics.length === 0;\n return empty ? undefined : surface;\n}\n\n/** Every package-relative module that contributed to the emitted surface. */\nfunction agentSurfaceSourcePaths(\n surface: DomainKnowledgeAgentSurface | undefined,\n): string[] {\n if (!surface) return [];\n const paths = new Set<string>();\n for (const intent of surface.intents) paths.add(intent.sourceFile);\n for (const playbook of surface.playbooks) paths.add(playbook.sourceFile);\n for (const diagnostic of surface.diagnostics)\n paths.add(diagnostic.sourceFile);\n return [...paths].sort();\n}\n\nfunction buildKnowledgeObject(\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): DomainKnowledgeObject {\n const knowledge =\n typeof object.decoratorConfig?.knowledge === 'object'\n ? object.decoratorConfig.knowledge\n : {};\n const fields = Object.entries(object.fields)\n .filter(([, field]) => !isSensitiveField(field))\n .map(([name, field]): DomainKnowledgeField => {\n const defaultValue = fieldValue(field, 'default');\n return {\n name,\n type: field.type,\n required: field.required,\n related: field.related,\n columnType: columnType(object, name),\n ...(defaultValue.present ? { default: defaultValue.value } : {}),\n constraints: fieldConstraints(field),\n readonly:\n field.readonly === true || field._meta?.readonly === true\n ? true\n : undefined,\n transient:\n field.transient === true || field._meta?.transient === true\n ? true\n : undefined,\n };\n });\n const sensitiveIdentifiers = sensitiveFieldIdentifiers(object.fields);\n const tenant = sanitizeTenantFacts(\n tenantFacts(object.decoratorConfig?.tenantScoped),\n sensitiveIdentifiers,\n );\n const conflictColumns = object.decoratorConfig?.conflictColumns?.filter(\n (column) => !sensitiveIdentifiers.has(column),\n );\n const relationships = fields\n .filter((field) => RELATIONSHIP_FIELD_TYPES.has(field.type))\n .map((field) => ({\n name: field.name,\n type: field.type,\n required: field.required,\n related: field.related,\n columnType: field.columnType,\n }));\n\n return {\n name: object.className,\n qualifiedName: object.qualifiedName,\n collection: object.collection,\n tableName: object.schema?.tableName,\n packageName: object.packageName,\n extends: object.extends,\n visibility: object.visibility,\n fields,\n relationships,\n methods: Object.keys(object.methods).sort(),\n methodSignatures: methodSignatures(object),\n tenant,\n tableStrategy: object.decoratorConfig?.tableStrategy,\n conflictColumns:\n conflictColumns && conflictColumns.length > 0\n ? conflictColumns\n : undefined,\n surfaces: objectSurfaces(object, manifest),\n ...withheldApiSurfaces(object, manifest),\n relationshipFeatures: relationshipFeatures(object, fields),\n tags: knowledge.tags ?? [],\n summary: knowledge.summary,\n risks: knowledge.risks ?? [],\n };\n}\n\nfunction isSensitiveField(field: SmartObjectDefinition['fields'][string]) {\n return field.sensitive === true || field._meta?.sensitive === true;\n}\n\nfunction sensitiveFieldIdentifiers(\n fields: SmartObjectDefinition['fields'],\n): Set<string> {\n return new Set(\n Object.entries(fields)\n .filter(([, field]) => isSensitiveField(field))\n .flatMap(([name]) => [name, toSnakeCase(name), camelToSnake(name)]),\n );\n}\n\nfunction fieldValue(\n field: SmartObjectDefinition['fields'][string],\n key: 'default' | 'min' | 'max' | 'minLength' | 'maxLength',\n): { present: boolean; value: unknown } {\n if (Object.hasOwn(field, key)) {\n return { present: field[key] !== undefined, value: field[key] };\n }\n const value = field._meta?.[key];\n return { present: value !== undefined, value };\n}\n\nfunction fieldConstraints(\n field: SmartObjectDefinition['fields'][string],\n): DomainKnowledgeFieldConstraints | undefined {\n const constraints: DomainKnowledgeFieldConstraints = {};\n for (const key of ['min', 'max', 'minLength', 'maxLength'] as const) {\n const value = fieldValue(field, key);\n if (value.present && typeof value.value === 'number') {\n constraints[key] = value.value;\n }\n }\n const pattern = normalizePattern(\n (field as { pattern?: unknown }).pattern ?? field._meta?.pattern,\n );\n if (pattern !== undefined) constraints.pattern = pattern;\n return Object.keys(constraints).length > 0 ? constraints : undefined;\n}\n\nfunction normalizePattern(pattern: unknown): string | undefined {\n if (typeof pattern === 'string') return pattern;\n if (pattern instanceof RegExp) return pattern.source;\n if (\n pattern &&\n typeof pattern === 'object' &&\n typeof (pattern as { source?: unknown }).source === 'string'\n ) {\n return (pattern as { source: string }).source;\n }\n return undefined;\n}\n\nfunction tenantFacts(\n tenantScoped: SmartObjectDefinition['decoratorConfig']['tenantScoped'],\n): DomainKnowledgeTenant | undefined {\n if (!tenantScoped) return undefined;\n if (tenantScoped === true) {\n return { scoped: true, mode: 'required', field: 'tenantId' };\n }\n return {\n scoped: true,\n mode: tenantScoped.mode ?? 'required',\n field: tenantScoped.field ?? 'tenantId',\n };\n}\n\nfunction sanitizeTenantFacts(\n tenant: DomainKnowledgeTenant | undefined,\n sensitiveIdentifiers: Set<string>,\n): DomainKnowledgeTenant | undefined {\n if (!tenant?.field || !sensitiveIdentifiers.has(tenant.field)) return tenant;\n return { scoped: tenant.scoped, mode: tenant.mode };\n}\n\nfunction methodSignatures(\n object: SmartObjectDefinition,\n): DomainKnowledgeMethodSignature[] | undefined {\n const signatures = Object.values(object.methods)\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((method) => ({\n name: method.name,\n async: method.async || undefined,\n static: method.isStatic || undefined,\n params:\n method.parameters.length > 0\n ? method.parameters.map(\n (parameter) =>\n `${parameter.name}${parameter.optional ? '?' : ''}: ${parameter.type}`,\n )\n : undefined,\n returns: method.returnType || undefined,\n }));\n return signatures.length > 0 ? signatures : undefined;\n}\n\nfunction objectSurfaces(\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): DomainKnowledgeSurface[] {\n return [\n ...configuredSurfaces('api', object, manifest),\n ...configuredSurfaces('cli', object, manifest),\n ...configuredSurfaces('mcp', object, manifest),\n ...aiSurfaces(object),\n ];\n}\n\n/**\n * Every API-exposure decision for one object's methods, from the shared\n * resolver the route emitters use — so a method reported here as exposed has a\n * route file, and one reported as withheld has none.\n *\n * The whole point of routing this through `resolveApiMethodExposure` rather\n * than a local mirror is that a fourth copy of the rule is a fourth chance to\n * disagree with the emitters (#2686).\n */\nfunction apiMethodDecisions(\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): Array<[string, ApiMethodExposure]> {\n const apiConfig = object.decoratorConfig?.api;\n const isModelClassName = createManifestClassNamePredicate(manifest);\n const collectionClass = isSurfaceCollectionClass(manifest, object);\n return Object.entries(object.methods).map(([name, method]) => [\n name,\n resolveApiMethodExposure({\n actionName: name,\n method,\n apiConfig,\n isCollectionClass: collectionClass,\n ...(isModelClassName ? { isModelClassName } : {}),\n }),\n ]);\n}\n\n/**\n * The `withheldSurfaces` half of the artifact: every public method the API\n * declined, with the reason.\n *\n * Reported for `api` only. `cli`/`mcp` gate on a much smaller, purely\n * name-based rule set that a reader can already infer from the config, while\n * the API's wire-ability heuristic rejects on a signature detail nothing else\n * in the artifact shows — which is exactly the silence #2686 set out to close.\n *\n * CRUD-reserved and non-public methods are excluded: neither was ever a\n * candidate custom action, so listing them would bury the actionable entries.\n */\nfunction withheldApiSurfaces(\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): { withheldSurfaces?: DomainKnowledgeWithheldSurface[] } {\n if (isFrameworkBaseClass(object.className, object.packageName)) return {};\n const withheld = apiMethodDecisions(object, manifest)\n .filter(\n ([, decision]) =>\n !decision.exposed &&\n decision.code !== 'crud-reserved' &&\n decision.code !== 'not-public',\n )\n .map(([operation, decision]) => ({\n kind: 'api' as const,\n operation,\n code: decision.code ?? 'unknown',\n reason: decision.reason ?? '',\n objectName: object.qualifiedName ?? object.className,\n }))\n .sort((a, b) => a.operation.localeCompare(b.operation));\n return withheld.length > 0 ? { withheldSurfaces: withheld } : {};\n}\n\nfunction configuredSurfaces(\n kind: 'api' | 'cli' | 'mcp',\n object: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): DomainKnowledgeSurface[] {\n const config = object.decoratorConfig?.[kind];\n // NOTE: the `cli` projection models the reservation rule core's\n // `CLIGenerator` used to apply (retired by #2664 -- see git history for\n // the deleted `packages/core/src/generators/cli.ts`), which reserves a\n // CRUD verb unconditionally.\n // That is NOT the shipped local CLI: `packages/cli/src/cli-generator.ts`'s\n // generator reserves one only where the CRUD command is emitted (each of\n // its commands carries its own handler), so with\n // `cli: { include: ['list', 'get'] }` a public `create()` is a reachable\n // `${object}:create` there that this projection does not report.\n //\n // Retargeting this projection at the shipped binary is tracked on #2692.\n // That is a CONTRACT CHANGE rather than a cleanup: the generators genuinely\n // disagree, so `smrt-knowledge.json` snapshots would move. Predates #2646.\n const collectionClass = isSurfaceCollectionClass(manifest, object);\n const operations = configuredOperations(kind, object, config, manifest);\n return operations.map((operation) => {\n const route =\n kind === 'api' && !STANDARD_OPERATIONS.includes(operation)\n ? apiCustomRoute(object, operation, collectionClass)\n : undefined;\n return {\n kind,\n name: surfaceName(kind, object, operation),\n operation,\n objectName: object.qualifiedName ?? object.className,\n path: kind === 'api' ? apiPath(object, operation, route) : undefined,\n method: kind === 'api' ? apiMethod(operation, route) : undefined,\n };\n });\n}\n\n/**\n * `MCPGenerator.buildCustomActionTool()` registers a custom-action tool as\n * `` `${lowerName}_${methodName}`.toLowerCase() `` — lowercasing the WHOLE\n * joined string, not just the object-name prefix. A CRUD verb is already\n * lowercase so this is a no-op there, but a camelCase custom method name\n * (`findByDimensions`) would otherwise report a surface `name` the real tool\n * is never registered under. `packages/cli/src/cli-generator.ts`'s command\n * builder (`CLIGenerator`'s private `generateObjectCommands()`) does not\n * lowercase the method half of its command string, so `cli` keeps the\n * operation as-authored.\n *\n * Note the shapes differ from the transports' own: a `cli` surface `name`\n * here is `object_operation`, while the command a user types is\n * `object:operation`. `operation` is the field to correlate on.\n */\nfunction surfaceName(\n kind: 'api' | 'cli' | 'mcp',\n object: SmartObjectDefinition,\n operation: string,\n): string {\n if (kind === 'api') return `${object.collection}.${operation}`;\n const name = `${object.className.toLowerCase()}_${operation}`;\n return kind === 'mcp' ? name.toLowerCase() : name;\n}\n\n/**\n * A hand-written `SmrtCollection` subclass (`class WidgetCollection extends\n * SmrtCollection<Widget>`) is discovered structurally by the scanner and\n * lands in the manifest even without its own `@smrt()` decorator, so it never\n * registers with `ObjectRegistry` by decoration. `MCPGenerator` (and,\n * historically, core's now-retired `CLIGenerator`, #2664) iterate the\n * decoration-populated `ObjectRegistry` directly, not the manifest, so such a\n * class never gets its own MCP tools there — only its collection-scoped\n * custom actions get REST routes. The shipped local CLI\n * (`packages/cli/src/cli-generator.ts`) is a documented exception: its\n * `ensureManifestLoaded()` pre-registers every manifest entry into\n * `ObjectRegistry` via `registerFromManifest()` before generating commands,\n * with no collection-class filter, so a manifest-only collection class IS\n * reachable there (e.g. `smrt itemcollection:list`) even though this\n * projection reports none. Reporting full CRUD for it here would over-report\n * the projection's own (registry-scoped) surface, trading the #2619\n * under-report for a new false positive there -- it does not claim the\n * shipped CLI binary lacks the surface too.\n *\n * A deeper subclass (`SpecialCollection extends WidgetCollection`) carries no\n * `extendsTypeArg` of its own, so this walks the extends chain through the\n * manifest — mirroring `isCollectionManifestClass` in\n * `vite-plugin/web-collections.ts` (kept as a separate, lean implementation\n * here rather than imported: that module pulls in the full SvelteKit route\n * generator transitively, which would balloon the standalone `./knowledge`\n * build entry for a ~15-line check).\n */\nfunction isSurfaceCollectionClass(\n manifest: SmartObjectManifest,\n object: SmartObjectDefinition,\n seen: Set<string> = new Set(),\n): boolean {\n // Truthy check (not `!== undefined`) mirrors the scanner: a non-generic\n // base emitting `extendsTypeArg: null` must not be misread as a collection.\n if (object.extends === 'SmrtCollection' || object.extendsTypeArg) {\n return true;\n }\n const parentName = object.extendsQualified || object.extends;\n if (!parentName || seen.has(parentName)) return false;\n seen.add(parentName);\n const parent = findManifestObjectByName(manifest, parentName, object);\n return parent ? isSurfaceCollectionClass(manifest, parent, seen) : false;\n}\n\nfunction findManifestObjectByName(\n manifest: SmartObjectManifest,\n name: string,\n owner: SmartObjectDefinition,\n): SmartObjectDefinition | undefined {\n const entries = Object.entries(manifest.objects);\n if (name.includes(':')) {\n const exact = entries.find(\n ([key, candidate]) => (candidate.qualifiedName ?? key) === name,\n );\n if (exact) return exact[1];\n }\n // Prefer a same-package parent before falling back to a bare simple name:\n // an aggregated manifest can carry several classes sharing one simple name,\n // and resolving the wrong one misclassifies the collection-class carve-out.\n const ownerKey = entries.find(([, candidate]) => candidate === owner)?.[0];\n const ownerPackage = manifestObjectPackage(owner, ownerKey);\n if (ownerPackage) {\n const packageLocal = entries.find(\n ([key, candidate]) =>\n manifestObjectPackage(candidate, key) === ownerPackage &&\n candidate.className === name,\n );\n if (packageLocal) return packageLocal[1];\n }\n return entries.find(([, candidate]) => candidate.className === name)?.[1];\n}\n\n/**\n * An object's owning package. `packageName` is optional on\n * `SmartObjectDefinition` (older manifests and hand-built fixtures omit it),\n * so fall back to the package half of the qualified name — and, when that is\n * absent too, of the manifest key, which is qualified for every entry the\n * scanner writes. Mirrors `manifestObjectPackage` in\n * `vite-plugin/web-collections.ts`, key fallback included: without it an\n * entry carrying only a qualified key resolves no package at all, the\n * same-package preference is skipped, and a duplicate simple name can pick\n * the wrong parent.\n */\nfunction manifestObjectPackage(\n object: SmartObjectDefinition,\n manifestKey?: string,\n): string | undefined {\n if (object.packageName) return object.packageName;\n const qualifiedName = object.qualifiedName ?? manifestKey;\n const separator = qualifiedName?.lastIndexOf(':') ?? -1;\n return separator > 0 ? qualifiedName?.slice(0, separator) : undefined;\n}\n\n/**\n * Operations exposed for one object's `api`/`cli`/`mcp` surface, derived from\n * the same defaults `APIGenerator`/core's retired `CLIGenerator`\n * (#2664)/`MCPGenerator` apply rather\n * than from the presence of a config key (#2619): an omitted config is full\n * CRUD, not a closed surface — an `include` list, when present, is the\n * COMPLETE allowlist for custom methods too; without one, every public\n * method not explicitly excluded is exposed by default. Only `config ===\n * false` closes the surface entirely.\n *\n * Custom (non-CRUD, public) method gating is NOT identical across the three\n * kinds. Core's retired `CLIGenerator.listCommands()`/`assertCommandExposed()`\n * (#2664) and\n * `MCPGenerator.generateTools()` both refuse a framework lifecycle method\n * (`save`, `initialize`, ...) even when a class declares its own override —\n * it is the mechanism behind generated CRUD, not a distinct action (#2638) —\n * and `resolveCustomMethodNames()` below mirrors that same\n * `isFrameworkLifecycleMethod()` check for `kind === 'cli'` and\n * `kind === 'mcp'` (#2657, #2638). `api` remains ungated on this: the\n * generator did not change in #2650/#2638, and the fix there is a PR #2651\n * recommendation, not yet implemented.\n *\n * `resolveCustomMethodNames()` also mirrors two more `mcp`-only behaviors\n * that follow from its case-folded tool-id namespace (#2638): an `exclude`\n * entry is compared case-insensitively (matching `MCPGenerator`'s own\n * asymmetry fix -- `exclude` used to fail open on a cased entry the way\n * `include` never did), and two method names that fold onto the same tool id\n * (e.g. `Refresh`/`refresh`) are reported once, keeping whichever was\n * declared first, mirroring `MCPGenerator`'s per-object dedup. `cli`/`api`\n * keep declared casing in their command/route names, so neither behavior\n * applies to them.\n *\n * This `cli` projection models the reservation rule core's `CLIGenerator`\n * used to apply (`generators/cli.ts`, retired by #2664), not the shipped\n * local CLI transport (`packages/cli/src/cli-generator.ts`, the\n * `smrt <object>:<action>` binary): that generator does not gate on\n * `isFrameworkLifecycleMethod()` today, so a locally overridden lifecycle\n * method the artifact now reports as absent can still be invoked there.\n * Retargeting this projection at the shipped binary is a contract change\n * tracked on #2692, not part of this fix.\n */\nfunction configuredOperations(\n kind: 'api' | 'cli' | 'mcp',\n object: SmartObjectDefinition,\n config: unknown,\n manifest: SmartObjectManifest,\n): string[] {\n if (config === false) return [];\n // The framework's own abstract base classes (SmrtObject, SmrtCollection,\n // ...) are scaffolding, not resources: MCPGenerator/route generation and\n // packages/cli's CLIGenerator all skip them by class identity now (#2642),\n // independent of\n // their `decoratorConfig: {}` shape, so this mirrors the same shared\n // check rather than reporting a synthetic surface for them.\n if (isFrameworkBaseClass(object.className, object.packageName)) return [];\n const collectionClass = isSurfaceCollectionClass(manifest, object);\n const crud = collectionClass ? [] : resolveCrudOperations(config);\n // `api` delegates custom-method eligibility wholesale to the emitters' own\n // resolver — CRUD reservation, framework lifecycle methods, include/exclude,\n // `@method()` overrides, the wire-ability heuristic, and the receiver check\n // are all decided there, once (#2686). `cli`/`mcp` keep their own projection\n // of `CLIGenerator`/`MCPGenerator`, whose rules genuinely differ (case-folded\n // tool ids, per-object dedup) and which #2692 owns.\n if (kind === 'api') {\n const custom = apiMethodDecisions(object, manifest)\n .filter(([, decision]) => decision.exposed)\n .map(([operation]) => operation);\n return [...crud, ...custom];\n }\n const custom = resolveCustomMethodNames(\n Object.entries(object.methods),\n config,\n kind,\n );\n return [...crud, ...custom];\n}\n\nfunction resolveCrudOperations(config: unknown): string[] {\n const { include, exclude } = includeExcludeConfig(config);\n const base = include\n ? STANDARD_OPERATIONS.filter((operation) => include.includes(operation))\n : [...STANDARD_OPERATIONS];\n if (!exclude || exclude.length === 0) return base;\n const excluded = new Set(exclude);\n return base.filter((operation) => !excluded.has(operation));\n}\n\nfunction resolveCustomMethodNames(\n methods: Iterable<[string, { isPublic?: boolean }]>,\n config: unknown,\n kind: 'api' | 'cli' | 'mcp',\n): string[] {\n const { include, exclude } = includeExcludeConfig(config);\n const excluded = new Set(exclude ?? []);\n // MCP tool ids are case-folded, so `MCPGenerator` compares `exclude`\n // case-insensitively too (`exclude: ['Refresh']` must suppress a method\n // declared `refresh`, and vice versa, #2638) -- mirror that here for\n // `kind === 'mcp'` only. `cli`/`api` keep the declared casing in their\n // command/route names (same asymmetry `reservesCrudName` documents below),\n // so an exact-match `exclude` stays correct for them.\n const excludedLower =\n kind === 'mcp'\n ? new Set([...excluded].map((entry) => entry.toLowerCase()))\n : undefined;\n // Tool ids already claimed for this object's `mcp` surface, so two\n // distinctly-cased method names (e.g. `Refresh`/`refresh`) that fold onto\n // the same MCP tool id are reported once, not twice -- mirroring\n // `MCPGenerator`'s per-object dedup (first declared wins, #2638). `cli`/\n // `api` need no such set: their command/route names keep declared casing,\n // so two cased method names never collide there.\n const emittedLower = kind === 'mcp' ? new Set<string>() : undefined;\n const names: string[] = [];\n for (const [name, method] of methods) {\n if (reservesCrudName(kind, name)) continue;\n // A framework lifecycle method (save/initialize/...) is never a custom\n // CLI or MCP action, even when a class declares its own override — it is\n // the mechanism behind generated CRUD, not a distinct operation, matching\n // core's retired CLIGenerator's (#2664) and MCPGenerator's own\n // isFrameworkLifecycleMethod() gate\n // (#2657, #2638). `api` is deliberately left alone — see\n // configuredOperations' doc comment above.\n if ((kind === 'cli' || kind === 'mcp') && isFrameworkLifecycleMethod(name))\n continue;\n if (!method.isPublic) continue;\n if (\n excludedLower ? excludedLower.has(name.toLowerCase()) : excluded.has(name)\n )\n continue;\n if (include !== undefined && !include.includes(name)) continue;\n if (emittedLower) {\n const lower = name.toLowerCase();\n if (emittedLower.has(lower)) continue;\n emittedLower.add(lower);\n }\n names.push(name);\n }\n return names;\n}\n\n/**\n * Whether `kind` reserves `name` for its generated CRUD operation, so the\n * method behind it is not reported as a distinct surface.\n *\n * MCP folds case: its tool ids are lowercased whole\n * (`` `${object}_${method}`.toLowerCase() ``), so a method named `List` lands on\n * the `${object}_list` identifier the CRUD tool already owns and\n * `MCPGenerator` emits no separate tool for it (#2646). REST and the CLI keep\n * the declared casing in their route/command names, so only an exact match is\n * reserved there.\n *\n * Reads the emitters' own predicates rather than re-testing the verb list, and\n * `STANDARD_OPERATIONS` derives from `CRUD_OPERATIONS`, so a change to the\n * shared list reaches both halves of this projection together.\n */\nfunction reservesCrudName(kind: 'api' | 'cli' | 'mcp', name: string): boolean {\n return kind === 'mcp' ? isCrudToolAction(name) : isCrudOperation(name);\n}\n\nfunction includeExcludeConfig(config: unknown): {\n include?: string[];\n exclude?: string[];\n} {\n if (typeof config !== 'object' || config === null || Array.isArray(config)) {\n return {};\n }\n // A non-array `include`/`exclude` is treated as unset rather than\n // throwing later on `.includes()` — mirrors the same defensive stance\n // `shouldIncludeInApi` in `vite-plugin/sveltekit-generator.ts` takes for\n // a scanned decorator config that failed to resolve to an array.\n const record = config as { include?: unknown; exclude?: unknown };\n return {\n include: Array.isArray(record.include) ? record.include : undefined,\n exclude: Array.isArray(record.exclude) ? record.exclude : undefined,\n };\n}\n\nfunction aiSurfaces(object: SmartObjectDefinition): DomainKnowledgeSurface[] {\n return (object.tools ?? []).map((tool) => ({\n kind: 'ai',\n name: tool.function.name,\n operation: tool.function.name,\n description: tool.function.description,\n objectName: object.qualifiedName ?? object.className,\n }));\n}\n\n/** Route facts for one custom action, as `generateRoutesForObject` emits it. */\ninterface ApiCustomRoute {\n scope: 'item' | 'collection';\n segments: string[];\n method: string;\n}\n\n/**\n * Resolve a custom (non-CRUD) action's REST route the way the generator does,\n * or `undefined` when no route is emitted for it at all.\n *\n * A custom action's path is NOT `/collection/action`: `generateRoutesForObject`\n * nests an item-scoped action under `[id]`, and an instance method defaults to\n * item scope. Reporting the collection-shaped path for every public instance\n * method would advertise endpoints that do not exist — the exact failure this\n * projection exists to avoid. Scope comes from the shared\n * `resolveCustomActionMetadata`, the same resolver the REST, CLI, MCP, and\n * WebMCP paths use, so a `routes` override cannot drift between them.\n *\n * `kebabRoutes` is a Vite-plugin option rather than manifest data, so an\n * explicit `routes[action].path` is honored but the generator's optional\n * kebab-casing of a derived segment is not visible here.\n */\nfunction apiCustomRoute(\n object: SmartObjectDefinition,\n operation: string,\n collectionClass: boolean,\n): ApiCustomRoute | undefined {\n const method = object.methods[operation];\n const apiConfig = object.decoratorConfig?.api;\n const defaultScope: 'item' | 'collection' =\n collectionClass || method?.isStatic ? 'collection' : 'item';\n const scope = resolveActionScope(operation, method, apiConfig, defaultScope);\n\n // Mirrors the generator's own skips: a collection class emits only\n // collection-scoped routes, and a model class warns and skips a\n // collection-scoped non-static method (no receiver to bind).\n if (collectionClass) {\n if (scope !== 'collection') return undefined;\n } else if (scope === 'collection' && !method?.isStatic) {\n return undefined;\n }\n\n // `@method({ path, httpMethod })` wins field by field over the legacy\n // `api.routes[operation]` entry, exactly as `resolveApiActionRouteConfig`\n // resolves it for the emitter — otherwise the artifact would report the\n // pre-migration URL for a class that has moved to the decorator (#2686).\n const effective = resolveEffectiveActionMetadata({\n actionName: operation,\n ...(method ? { method } : {}),\n apiConfig,\n });\n const overridden =\n typeof effective.path === 'string'\n ? effective.path\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean)\n : [];\n return {\n scope,\n segments: overridden.length > 0 ? overridden : [operation],\n method: normalizeApiMethod(effective.httpMethod),\n };\n}\n\n/**\n * The shared resolver validates as it resolves — a `routes` entry declaring\n * `effect: 'read'` on a PUT/PATCH/DELETE route throws by design. This\n * projection reads untrusted scanned config and must not fail the whole\n * knowledge build for one malformed action (same defensive stance as\n * {@link includeExcludeConfig}), so fall back to the receiver the method\n * itself dictates — which a route-only override cannot change anyway.\n */\nfunction resolveActionScope(\n operation: string,\n method: SmartObjectDefinition['methods'][string] | undefined,\n apiConfig: unknown,\n defaultScope: 'item' | 'collection',\n): 'item' | 'collection' {\n try {\n return resolveCustomActionMetadata({\n actionName: operation,\n method,\n apiConfig,\n defaultScope,\n }).scope;\n } catch {\n return defaultScope;\n }\n}\n\n/** Mirrors `normalizeApiHttpMethod` in `vite-plugin/sveltekit-generator.ts`. */\nfunction normalizeApiMethod(method: unknown): string {\n const normalized =\n typeof method === 'string' ? method.toUpperCase() : undefined;\n switch (normalized) {\n case 'GET':\n case 'POST':\n case 'PUT':\n case 'PATCH':\n case 'DELETE':\n return normalized;\n default:\n return 'POST';\n }\n}\n\n/**\n * The collection segment of a generated REST route.\n *\n * `generateRoutesForObject` builds its route directory from\n * `objectDef.collection` verbatim, and the runtime dispatcher in\n * `generators/rest.ts` matches the URL segment against `info.collection`\n * verbatim, so this reports that and nothing else (#2630).\n *\n * In particular it does NOT read `api.path`, which configures a different\n * surface: `@happyvertical/smrt-agents`' own agent-facing route map derives\n * `api.path ?? tableName.replace(/_/g, '-')`. Honoring it here produced a\n * hybrid — `api.path` over `collection` — that matched neither transport and\n * named endpoints that 404 on both.\n */\nfunction apiCollectionSegment(object: SmartObjectDefinition): string {\n return object.collection;\n}\n\nfunction apiPath(\n object: SmartObjectDefinition,\n operation: string,\n route?: ApiCustomRoute,\n): string {\n const configuredPath = apiCollectionSegment(object);\n if (route) {\n const base =\n route.scope === 'collection'\n ? `/${configuredPath}`\n : `/${configuredPath}/[id]`;\n return `${base}/${route.segments.join('/')}`;\n }\n if (operation === 'list' || operation === 'create') {\n return `/${configuredPath}`;\n }\n if (STANDARD_OPERATIONS.includes(operation)) {\n return `/${configuredPath}/[id]`;\n }\n return `/${configuredPath}/${operation}`;\n}\n\nfunction apiMethod(operation: string, route?: ApiCustomRoute): string {\n if (route) return route.method;\n switch (operation) {\n case 'list':\n case 'get':\n return 'GET';\n case 'create':\n return 'POST';\n case 'update':\n return 'PATCH';\n case 'delete':\n return 'DELETE';\n default:\n return 'POST';\n }\n}\n\nfunction relationshipFeatures(\n object: SmartObjectDefinition,\n fields: DomainKnowledgeField[],\n): string[] {\n const features = new Set<string>();\n for (const field of fields) {\n if (field.type === 'foreignKey') features.add('foreignKey');\n if (field.type === 'crossPackageRef') features.add('crossPackageRef');\n if (field.type === 'oneToMany') features.add('oneToMany');\n if (field.type === 'manyToMany') features.add('manyToMany');\n }\n if (object.extends === 'SmrtJunction') features.add('SmrtJunction');\n if (object.extends === 'SmrtHierarchical') features.add('SmrtHierarchical');\n if (\n object.extends === 'SmrtPolymorphicAssociation' ||\n fields.some((field) => field.name === 'metaType') ||\n fields.some((field) => field.name === 'metaId')\n ) {\n features.add('SmrtPolymorphicAssociation');\n }\n if (\n Object.keys(object.schema?.columns ?? {}).some(\n (name) => object.schema?.columns[name]?.type === 'UUID',\n )\n ) {\n features.add('uuidColumns');\n }\n return [...features].sort();\n}\n\nfunction summarizeRelationships(\n objects: DomainKnowledgeObject[],\n manifestObjects: SmartObjectDefinition[],\n) {\n const fields = objects.flatMap((object) => object.fields);\n return {\n foreignKeyFields: fields.filter((field) => field.type === 'foreignKey')\n .length,\n crossPackageRefFields: fields.filter(\n (field) => field.type === 'crossPackageRef',\n ).length,\n junctionCollections: objects.filter((object) =>\n object.relationshipFeatures.includes('SmrtJunction'),\n ).length,\n hierarchicalObjects: objects.filter((object) =>\n object.relationshipFeatures.includes('SmrtHierarchical'),\n ).length,\n polymorphicAssociations: objects.filter((object) =>\n object.relationshipFeatures.includes('SmrtPolymorphicAssociation'),\n ).length,\n uuidColumns: manifestObjects.reduce(\n (count, object) =>\n count +\n Object.values(object.schema?.columns ?? {}).filter(\n (column) => column.type === 'UUID',\n ).length,\n 0,\n ),\n };\n}\n\n/**\n * Documented default `tags` derivation for a package's domain-knowledge\n * artifact when `@smrt({ knowledge: { tags } })` is not set (#2863).\n *\n * Never invents taxonomy: tags come only from `package.json#keywords`\n * (authored by the package owner) plus a `cross-package` tag when the\n * package declares a `@happyvertical/smrt-*` dependency. This keeps the\n * derivation deterministic and traceable to an authored source, matching\n * the \"populate tags/risks from scanner output where the manifest carries\n * the data\" scope — a package that wants richer tags still sets\n * `knowledge.tags` explicitly.\n */\nfunction deriveDefaultTags(\n packageJson: PackageJsonLike,\n allDependencies: Record<string, string>,\n): string[] {\n const tags = new Set<string>();\n const keywords = packageJson.keywords;\n if (Array.isArray(keywords)) {\n for (const keyword of keywords) {\n if (typeof keyword === 'string' && keyword.trim()) {\n tags.add(keyword.trim());\n }\n }\n }\n if (\n Object.keys(allDependencies).some((dep) =>\n dep.startsWith('@happyvertical/smrt-'),\n )\n ) {\n tags.add('cross-package');\n }\n return [...tags].sort();\n}\n\n/**\n * Documented default `risks` derivation (#2863). Each entry names a\n * structural fact the manifest already carries — never freeform prose — so\n * it stays deterministic and regenerable:\n *\n * - `sensitive-fields-excluded`: generation always strips sensitive fields\n * before projecting objects (`sensitiveFieldsExcluded` is unconditionally\n * `true`), so a reviewer relying on this artifact must not treat it as a\n * complete field inventory.\n * - `cross-package-refs:<n>`: the package reads or writes another package's\n * rows through `@crossPackageRef`; a reviewer must check that package's\n * tenancy and lifecycle guarantees too.\n * - `sti-inheritance`: at least one object shares a table via\n * `tableStrategy: 'sti'`; a schema change must consider every sibling.\n * - `polymorphic-associations:<n>`: at least one\n * `SmrtPolymorphicAssociation`, whose target type is resolved at read time\n * rather than by a foreign key constraint.\n */\nfunction deriveDefaultRisks(options: {\n sensitiveFieldsExcluded: true;\n relationshipsV2: ReturnType<typeof summarizeRelationships>;\n objects: DomainKnowledgeObject[];\n}): string[] {\n const risks = new Set<string>();\n if (options.sensitiveFieldsExcluded) {\n risks.add('sensitive-fields-excluded');\n }\n if (options.relationshipsV2.crossPackageRefFields > 0) {\n risks.add(\n `cross-package-refs:${options.relationshipsV2.crossPackageRefFields}`,\n );\n }\n if (options.objects.some((object) => object.tableStrategy === 'sti')) {\n risks.add('sti-inheritance');\n }\n if (options.relationshipsV2.polymorphicAssociations > 0) {\n risks.add(\n `polymorphic-associations:${options.relationshipsV2.polymorphicAssociations}`,\n );\n }\n return [...risks].sort();\n}\n\nfunction columnType(\n object: SmartObjectDefinition,\n fieldName: string,\n): string | undefined {\n const columnName = camelToSnake(fieldName);\n return object.schema?.columns[columnName]?.type;\n}\n\nfunction readPrompts(\n rootDir: string,\n): Array<{ filePath: string; key?: string }> {\n const srcDir = join(rootDir, 'src');\n if (!existsSync(srcDir)) return [];\n const prompts: Array<{ filePath: string; key?: string }> = [];\n for (const filePath of walkFiles(srcDir)) {\n if (!filePath.endsWith('.ts')) continue;\n const content = readFileSync(filePath, 'utf8');\n if (!content.includes('definePrompt')) continue;\n const keyMatch = content.match(/definePrompt\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]/);\n prompts.push({\n filePath: relative(rootDir, filePath),\n key: keyMatch?.[1],\n });\n }\n return prompts;\n}\n\nfunction walkFiles(dir: string): string[] {\n const files: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (\n entry.name === 'node_modules' ||\n entry.name === 'dist' ||\n entry.name === '.svelte-kit'\n ) {\n continue;\n }\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...walkFiles(fullPath));\n } else if (entry.isFile()) {\n files.push(fullPath);\n }\n }\n return files;\n}\n\nfunction sourceHashes(sources: Record<string, HashSource | undefined>) {\n const hashes: Record<string, string> = {};\n for (const [name, source] of Object.entries(sources)) {\n if (!source) continue;\n const content =\n 'content' in source ? source.content : readFileSync(source.path, 'utf8');\n hashes[name] = createHash('sha256').update(content).digest('hex');\n }\n return hashes;\n}\n\ntype HashSource = { content: string } | { path: string };\n\nfunction fileHashSource(path: string | undefined): HashSource | undefined {\n return path ? { path } : undefined;\n}\n\nfunction existingPath(rootDir: string, path: string): string | undefined {\n const fullPath = join(rootDir, path);\n return existsSync(fullPath) ? fullPath : undefined;\n}\n\nfunction readPackageJson(rootDir: string): PackageJsonLike | null {\n const path = join(rootDir, 'package.json');\n if (!existsSync(path)) return null;\n return JSON.parse(readFileSync(path, 'utf8'));\n}\n\nfunction record(value: unknown): Record<string, string> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, string>)\n : {};\n}\n\nfunction exportKeys(exportsField: unknown): string[] {\n if (typeof exportsField === 'string') return ['.'];\n if (\n typeof exportsField !== 'object' ||\n exportsField === null ||\n Array.isArray(exportsField)\n ) {\n return [];\n }\n return Object.keys(exportsField).sort();\n}\n\nfunction camelToSnake(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n .replace(/[-\\s]+/g, '_')\n .toLowerCase();\n}\n\nfunction normalizeManifestForHash(manifest: SmartObjectManifest): unknown {\n const normalized = JSON.parse(JSON.stringify(manifest)) as Record<\n string,\n unknown\n >;\n delete normalized.timestamp;\n return normalized;\n}\n\nfunction stableJson(value: unknown): string {\n return JSON.stringify(sortJson(value), null, 2);\n}\n\nfunction sortJson(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortJson);\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, entry]) => [key, sortJson(entry)]),\n );\n }\n return value;\n}\n"],"mappings":"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"}
|