@specverse/engines 4.1.20 → 4.1.22

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.
@@ -0,0 +1,24 @@
1
+ /**
2
+ * AI Behavior Regeneration
3
+ *
4
+ * Thin wrapper around the ai-behaviors-generator's regenerateAiBehaviors
5
+ * helper. Published via @specverse/engines/ai so the generated CLI can
6
+ * call it without reaching into libs/ paths.
7
+ *
8
+ * Used by `specverse ai regenerate <Owner.fn>`.
9
+ */
10
+ export interface RegenerateBehaviorOptions {
11
+ spec: any;
12
+ ownerName: string;
13
+ targetFunction: string | null;
14
+ outputDir: string;
15
+ allFunctions?: boolean;
16
+ }
17
+ export interface RegenerateBehaviorResult {
18
+ filePath: string;
19
+ targetFound: boolean;
20
+ unmatchedCount: number;
21
+ cacheCleared: number;
22
+ }
23
+ export declare function regenerateBehavior(opts: RegenerateBehaviorOptions): Promise<RegenerateBehaviorResult>;
24
+ //# sourceMappingURL=behavior-regenerate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior-regenerate.d.ts","sourceRoot":"","sources":["../../src/ai/behavior-regenerate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,GAAG,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAuBD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,wBAAwB,CAAC,CASnC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * AI Behavior Regeneration
3
+ *
4
+ * Thin wrapper around the ai-behaviors-generator's regenerateAiBehaviors
5
+ * helper. Published via @specverse/engines/ai so the generated CLI can
6
+ * call it without reaching into libs/ paths.
7
+ *
8
+ * Used by `specverse ai regenerate <Owner.fn>`.
9
+ */
10
+ import { existsSync } from 'fs';
11
+ import { join, dirname } from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ /**
14
+ * Load the AI behaviors generator module dynamically — it lives under
15
+ * engines/libs/ (not src/) and has to be loaded from the compiled .js in
16
+ * dist/libs/ at runtime because the template is compiled separately.
17
+ */
18
+ async function loadGenerator() {
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ // dist/ai/ → dist/libs/instance-factories/services/templates/prisma/
21
+ const candidates = [
22
+ join(__dirname, '..', 'libs', 'instance-factories', 'services', 'templates', 'prisma', 'ai-behaviors-generator.js'),
23
+ // Fallback: uncompiled .ts source (only works in dev)
24
+ join(__dirname, '..', '..', 'libs', 'instance-factories', 'services', 'templates', 'prisma', 'ai-behaviors-generator.ts'),
25
+ ];
26
+ for (const path of candidates) {
27
+ if (existsSync(path)) {
28
+ return await import(path);
29
+ }
30
+ }
31
+ throw new Error('ai-behaviors-generator not found — is @specverse/engines installed correctly?');
32
+ }
33
+ export async function regenerateBehavior(opts) {
34
+ const mod = await loadGenerator();
35
+ if (typeof mod.regenerateAiBehaviors !== 'function') {
36
+ throw new Error('regenerateAiBehaviors helper not found in @specverse/engines. ' +
37
+ 'Upgrade to engines >= 4.1.21.');
38
+ }
39
+ return mod.regenerateAiBehaviors(opts);
40
+ }
41
+ //# sourceMappingURL=behavior-regenerate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavior-regenerate.js","sourceRoot":"","sources":["../../src/ai/behavior-regenerate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAiBpC;;;;GAIG;AACH,KAAK,UAAU,aAAa;IAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,qEAAqE;IACrE,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,2BAA2B,CAAC;QACnH,sDAAsD;QACtD,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,2BAA2B,CAAC;KAC1H,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAA+B;IAE/B,MAAM,GAAG,GAAG,MAAM,aAAa,EAAE,CAAC;IAClC,IAAI,OAAO,GAAG,CAAC,qBAAqB,KAAK,UAAU,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACb,gEAAgE;YAChE,+BAA+B,CAChC,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC"}
@@ -10,6 +10,8 @@ export { SessionManager } from './session/session-manager.js';
10
10
  export type { SessionInfo, JobRequest, JobStatus, CreateSessionOptions } from './session/types.js';
11
11
  export { BehaviorAIService } from './behavior-ai-service.js';
12
12
  export type { BehaviorAIServiceOptions, BehaviorGenerateContext } from './behavior-ai-service.js';
13
+ export { regenerateBehavior } from './behavior-regenerate.js';
14
+ export type { RegenerateBehaviorOptions, RegenerateBehaviorResult } from './behavior-regenerate.js';
13
15
  export { LLMProvider, LLMProviderRegistry } from './providers/llm-provider.js';
14
16
  export type { LLMMessage, LLMCompletionOptions, LLMCompletionResponse, LLMProviderConfig, LLMStreamChunk } from './providers/llm-provider.js';
15
17
  export { ProviderFactory } from './providers/provider-factory.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"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"}
package/dist/ai/index.js CHANGED
@@ -9,6 +9,9 @@ export * from './config-loader.js';
9
9
  export { SessionManager } from './session/session-manager.js';
10
10
  // Behavior AI service — session-based Claude conversation for realize-time code generation
11
11
  export { BehaviorAIService } from './behavior-ai-service.js';
12
+ // Regenerate a single owner's AI behaviors file on demand.
13
+ // Used by `specverse ai regenerate <Owner.fn>`.
14
+ export { regenerateBehavior } from './behavior-regenerate.js';
12
15
  // Providers — LLM execution layer
13
16
  export { LLMProvider, LLMProviderRegistry } from './providers/llm-provider.js';
14
17
  export { ProviderFactory } from './providers/provider-factory.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,oCAAoC,CAAC;AACnD,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,2FAA2F;AAC3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,kCAAkC;AAClC,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAE/E,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAE1E,4CAA4C;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAE7E,+CAA+C;AAC/C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAgC/D,MAAM,iBAAiB;IACrB,IAAI,GAAG,IAAI,CAAC;IACZ,OAAO,GAAG,OAAO,CAAC;IAClB,YAAY,GAAG,CAAC,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,kBAAkB,EAAE,cAAc,CAAC,CAAC;IAE5F,OAAO,GAAQ,IAAI,CAAC;IAE5B,KAAK,CAAC,UAAU,CAAC,MAAoD;QACnE,IAAI,CAAC;YACH,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAC;YACtF,IAAI,CAAC,OAAO,GAAG,IAAI,sBAAsB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,6BAA6B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACtG,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;IACrF,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,IAAS,EAAE,QAAc;QAC5C,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAC;QACzG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,iBAAiB,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9C,IAAI,SAAS,CAAC,WAAW;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;YACpE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEf,SAAS;YACT,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC5C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC3B,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;oBACjC,IAAI,KAAK,CAAC,WAAW;wBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;oBACrD,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;oBACrC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACrB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;wBACf,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;wBACvD,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;wBACvD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;4BACzB,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,IAAI,QAAQ,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;wBAC9H,CAAC;oBACH,CAAC;oBACD,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC;oBACvC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACpB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;wBACf,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;wBACjC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;4BACvB,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;wBACzD,CAAC;oBACH,CAAC;oBACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACjB,CAAC;YACH,CAAC;YAED,cAAc;YACd,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC;YAChD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,KAAK,CAAC,IAAI,CAAC,oBAAoB,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;gBACtD,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;oBAC/B,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAC;gBAC7F,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;YAED,WAAW;YACX,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC;YAC1C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,iBAAiB,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;gBAChD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;oBAC3B,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC;oBAChC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;wBACnB,KAAK,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAiC,CAAC,EAAE,CAAC;4BACjF,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,KAAK,EAAE,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC,CAAC;wBACvD,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;YAED,SAAS;YACT,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC5C,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;oBACzB,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC;gBAClC,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;QAC/F,KAAK,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;QACvE,KAAK,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;QAC9E,KAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;QACnE,KAAK,CAAC,IAAI,CAAC,mHAAmH,CAAC,CAAC;QAChI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAS,EAAE,QAAiB;QACxC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;QACpE,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,gBAAgB,CAAC,IAAY,EAAE,OAA2B;QAC9D,IAAI,CAAC;YACH,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;YACvE,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,WAAW;gBAAE,OAAO,IAAI,CAAC;YACtC,OAAO,MAAM,OAAO,CAAC,gBAAgB,CAAC;gBACpC,IAAI;gBACJ,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,EAAE;gBAC9C,IAAI,EAAE,OAAO,CAAC,IAAI;aACnB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,OAAa;QAC7C,IAAI,CAAC;YACH,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;YAC/D,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,SAAgB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC;YACvF,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBAC/B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;gBACtC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;YACD,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChD,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC3B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YAClE,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,4EAA4E;YAC5E,OAAO,eAAe,SAAS,0FAA0F,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACpL,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;AAC9C,eAAe,MAAM,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"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"}
@@ -304,6 +304,22 @@ export async function executeOperation(
304
304
  return apiRequest<ApiResponse>(method, path, Object.keys(params).length > 0 ? params : null);
305
305
  }
306
306
 
307
+ /**
308
+ * Execute a service operation
309
+ * Services are RPC-style under /services/{serviceName}/{operationName}
310
+ */
311
+ export async function executeServiceOperation(
312
+ serviceName: string,
313
+ operationName: string,
314
+ params: Record<string, any>
315
+ ): Promise<ApiResponse> {
316
+ return apiRequest<ApiResponse>(
317
+ 'POST',
318
+ \`/services/\${serviceName}/\${operationName}\`,
319
+ params
320
+ );
321
+ }
322
+
307
323
  /**
308
324
  * Transition entity lifecycle state
309
325
  */
@@ -395,6 +411,22 @@ export async function executeOperation(
395
411
  );
396
412
  }
397
413
 
414
+ /**
415
+ * Execute a service operation
416
+ * Services are RPC-style under /services/{serviceName}/{operationName}
417
+ */
418
+ export async function executeServiceOperation(
419
+ serviceName: string,
420
+ operationName: string,
421
+ params: Record<string, any>
422
+ ): Promise<ApiResponse> {
423
+ return apiRequest<ApiResponse>(
424
+ 'POST',
425
+ \`/services/\${serviceName}/\${operationName}\`,
426
+ params
427
+ );
428
+ }
429
+
398
430
  /**
399
431
  * Transition entity lifecycle state
400
432
  */
@@ -1,10 +1,10 @@
1
1
  function generateRuntimeAppTsx(context) {
2
2
  const { spec } = context;
3
3
  const appName = spec?.metadata?.name || spec?.name || "SpecVerse App";
4
- return `import { useState, useEffect, useMemo } from 'react';
5
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4
+ return `import { useState, useEffect, useMemo, useCallback } from 'react';
5
+ import { QueryClient, QueryClientProvider, useQueryClient } from '@tanstack/react-query';
6
6
  import yaml from 'js-yaml';
7
- import { RuntimeViewProvider } from '@specverse/runtime/views/react';
7
+ import { RuntimeViewProvider, useEntitySync } from '@specverse/runtime/views/react';
8
8
  import { DevShell } from '@specverse/runtime/views/react';
9
9
  import {
10
10
  useEntitiesQuery,
@@ -12,6 +12,7 @@ import {
12
12
  useExecuteOperationMutation,
13
13
  useTransitionStateMutation,
14
14
  } from './hooks/useApi';
15
+ import { listEntities, getRuntimeInfo } from './lib/apiClient';
15
16
  import devSpecRaw from './dev.specly?raw';
16
17
 
17
18
  // Parse YAML spec
@@ -64,6 +65,40 @@ function AppContent() {
64
65
  .catch(() => {});
65
66
  }, []);
66
67
 
68
+ // State-sync contract: WebSocket entity events \u2192 React Query cache
69
+ // invalidation. This is what guarantees "delete in one view is visible
70
+ // in every other view within one WS round-trip" \u2014 it runs at the App
71
+ // level so it's always on, regardless of which tab is active.
72
+ const queryClient = useQueryClient();
73
+ const invalidateEntities = useCallback((modelName: string) => {
74
+ queryClient.invalidateQueries({ queryKey: ['entities', modelName] });
75
+ }, [queryClient]);
76
+ useEntitySync({ invalidateEntities, apiBaseUrl: '/api' });
77
+
78
+ // Name resolver for OperationResultView. Kept in the host so runtime
79
+ // view components never issue raw fetch() calls \u2014 all HTTP goes
80
+ // through apiClient's canonical layer.
81
+ const resolveEntityNames = useCallback(async (ids: string[]): Promise<Record<string, string>> => {
82
+ const names: Record<string, string> = {};
83
+ try {
84
+ const info = await getRuntimeInfo();
85
+ const models = info?.models || [];
86
+ await Promise.all(models.map(async (model: string) => {
87
+ try {
88
+ const entities = await listEntities(model + 'Controller');
89
+ for (const entity of entities) {
90
+ const id = (entity as any)?.id;
91
+ const dataId = (entity as any)?.data?.id;
92
+ const display = (entity as any)?.name || (entity as any)?.title || (entity as any)?.label || id;
93
+ if (id && ids.includes(id)) names[id] = String(display);
94
+ if (dataId && ids.includes(dataId)) names[dataId] = String(display);
95
+ }
96
+ } catch { /* skip this model */ }
97
+ }));
98
+ } catch { /* ignore \u2014 caller falls back to raw IDs */ }
99
+ return names;
100
+ }, []);
101
+
67
102
  const runtimeValue = useMemo(() => ({
68
103
  useEntitiesQuery,
69
104
  useModelSchemaQuery,
@@ -74,7 +109,9 @@ function AppContent() {
74
109
  views: [],
75
110
  spec: appSpec,
76
111
  apiBaseUrl: '/api',
77
- }), [appSpec]);
112
+ invalidateEntities,
113
+ resolveEntityNames,
114
+ }), [appSpec, invalidateEntities, resolveEntityNames]);
78
115
 
79
116
  return (
80
117
  <RuntimeViewProvider value={runtimeValue}>
@@ -11,6 +11,7 @@ import {
11
11
  getModelSchema,
12
12
  listEntities,
13
13
  executeOperation,
14
+ executeServiceOperation,
14
15
  transitionState
15
16
  } from '../lib/apiClient';
16
17
  import type { ModelSchema, Entity, ApiResponse } from '../types/api';
@@ -49,9 +50,14 @@ export function useEntitiesQuery(controllerName: string | null, modelName: strin
49
50
  }
50
51
 
51
52
  /**
52
- * Mutation hook for executing operations
53
- * Matches RuntimeViewProviderValue.useExecuteOperationMutation contract:
54
- * { controllerName, operationName, data, entityId? }
53
+ * Mutation hook for executing operations \u2014 handles both controllers
54
+ * and services. Pass either \`controllerName\` (for CRUD or custom
55
+ * controller actions) or \`serviceName\` (for RPC-style service ops).
56
+ *
57
+ * Matches RuntimeViewProviderValue.useExecuteOperationMutation contract.
58
+ * Service operations invalidate the \`services\` query key; controller
59
+ * operations invalidate the corresponding model's \`entities\` key so
60
+ * all mounted views refetch automatically.
55
61
  */
56
62
  export function useExecuteOperationMutation() {
57
63
  const queryClient = useQueryClient();
@@ -59,12 +65,14 @@ export function useExecuteOperationMutation() {
59
65
  return useMutation({
60
66
  mutationFn: ({
61
67
  controllerName,
68
+ serviceName,
62
69
  operationName,
63
70
  data,
64
71
  params,
65
72
  entityId
66
73
  }: {
67
- controllerName: string;
74
+ controllerName?: string;
75
+ serviceName?: string;
68
76
  operationName: string;
69
77
  data?: Record<string, any>;
70
78
  params?: Record<string, any>;
@@ -73,11 +81,23 @@ export function useExecuteOperationMutation() {
73
81
  // Merge: accept both 'data' and 'params' for compatibility
74
82
  const mergedParams = { ...(data || params || {}) };
75
83
  if (entityId) mergedParams.id = entityId;
76
- return executeOperation(controllerName, operationName, mergedParams);
84
+ if (serviceName) {
85
+ return executeServiceOperation(serviceName, operationName, mergedParams);
86
+ }
87
+ if (controllerName) {
88
+ return executeOperation(controllerName, operationName, mergedParams);
89
+ }
90
+ throw new Error('useExecuteOperationMutation: either controllerName or serviceName is required');
77
91
  },
78
92
  onSuccess: (_data, variables) => {
79
- const modelName = variables.controllerName.replace(/Controller$/, '');
80
- queryClient.invalidateQueries({ queryKey: ['entities', modelName] });
93
+ if (variables.controllerName) {
94
+ const modelName = variables.controllerName.replace(/Controller$/, '');
95
+ queryClient.invalidateQueries({ queryKey: ['entities', modelName] });
96
+ }
97
+ // Service operations aren't tied to a single entity type; no
98
+ // cache key to invalidate here. If a service mutation affects
99
+ // entities, the backend should publish an event that
100
+ // useEntitySync picks up via WebSocket.
81
101
  }
82
102
  });
83
103
  }
@@ -788,6 +788,87 @@ import { EngineRegistry } from '@specverse/entities';`,
788
788
  console.log(template);
789
789
  }`
790
790
  },
791
+ "ai.regenerate": {
792
+ imports: `import { readFileSync, existsSync } from 'fs';
793
+ import { resolve } from 'path';
794
+ import { EngineRegistry } from '@specverse/entities';
795
+ import type { ParserEngine } from '@specverse/types';`,
796
+ handler: `// Parse Owner.functionName \u2014 or just Owner with --all
797
+ const target = fn;
798
+ const dotIdx = target.indexOf('.');
799
+ const ownerName = dotIdx >= 0 ? target.slice(0, dotIdx) : target;
800
+ const functionName = dotIdx >= 0 ? target.slice(dotIdx + 1) : null;
801
+ if (!functionName && !options.all) {
802
+ console.error('Function must be specified as Owner.functionName, or use --all to regenerate every AI function in the owner.');
803
+ process.exit(1);
804
+ }
805
+
806
+ // Resolve spec file \u2014 default to specs/main-inferred.specly next to cwd
807
+ const userCwd = process.env.SPECVERSE_USER_CWD || process.cwd();
808
+ const specCandidates = options.spec
809
+ ? [resolve(userCwd, options.spec)]
810
+ : [resolve(userCwd, 'specs/main-inferred.specly'), resolve(userCwd, 'specs/main.specly')];
811
+ const specPath = specCandidates.find(p => existsSync(p));
812
+ if (!specPath) {
813
+ console.error('Spec not found. Tried: ' + specCandidates.join(', '));
814
+ console.error('Pass --spec <file> or run from a project root with specs/main.specly.');
815
+ process.exit(1);
816
+ }
817
+ console.log('Using spec: ' + specPath);
818
+
819
+ const registry = new EngineRegistry();
820
+ await registry.discover();
821
+ const parser = registry.getEngineForCapability('parse') as ParserEngine;
822
+ if (!parser) { console.error('No parser engine found.'); process.exit(1); }
823
+ await parser.initialize();
824
+
825
+ const specContent = readFileSync(specPath, 'utf8');
826
+ const parseResult = parser.parseContent(specContent, specPath);
827
+ if (parseResult.errors.length > 0) {
828
+ console.error('Invalid spec:');
829
+ parseResult.errors.forEach((e: string) => console.error(' ' + e));
830
+ process.exit(1);
831
+ }
832
+
833
+ // Flatten components down to a realize-shaped spec
834
+ // (controllers, services, models at top level) \u2014 matches what
835
+ // regenerateBehavior expects. Collections may be arrays (parser
836
+ // output) or objects (inferred spec); preserve the incoming shape.
837
+ const ast: any = parseResult.ast;
838
+ const flat: any = { ...ast };
839
+ const components = ast?.components || {};
840
+ for (const comp of Object.values(components) as any[]) {
841
+ for (const key of ['models', 'controllers', 'services']) {
842
+ const collection = comp?.[key];
843
+ if (!collection) continue;
844
+ if (Array.isArray(collection)) {
845
+ flat[key] = [...(Array.isArray(flat[key]) ? flat[key] : []), ...collection];
846
+ } else {
847
+ flat[key] = { ...(flat[key] && !Array.isArray(flat[key]) ? flat[key] : {}), ...collection };
848
+ }
849
+ }
850
+ }
851
+
852
+ const { regenerateBehavior } = await import('@specverse/engines/ai');
853
+ const outputDir = resolve(userCwd, options.output || 'generated/code');
854
+ try {
855
+ const result = await regenerateBehavior({
856
+ spec: flat,
857
+ ownerName,
858
+ targetFunction: options.all ? null : functionName,
859
+ outputDir,
860
+ allFunctions: !!options.all,
861
+ });
862
+ console.log(\`\u2705 Regenerated \${result.filePath}\`);
863
+ console.log(\` Owner: \${ownerName}\`);
864
+ console.log(\` Unmatched functions: \${result.unmatchedCount}\`);
865
+ console.log(\` Target: \${options.all ? 'all' : functionName}\`);
866
+ console.log(\` Cache entries cleared: \${result.cacheCleared}\`);
867
+ } catch (err: any) {
868
+ console.error('Regeneration failed: ' + (err?.message || err));
869
+ process.exit(1);
870
+ }`
871
+ },
791
872
  // === session subcommands ===
792
873
  "session.create": {
793
874
  imports: `import { EngineRegistry } from '@specverse/entities';`,
@@ -1,7 +1,7 @@
1
1
  import { matchStep } from "./step-conventions.js";
2
2
  import { createHash } from "crypto";
3
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
4
- import { join } from "path";
3
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from "fs";
4
+ import { dirname, join } from "path";
5
5
  async function validateTypeScript(code) {
6
6
  try {
7
7
  const esbuild = await import("esbuild");
@@ -243,7 +243,157 @@ const prisma = new PrismaClient();
243
243
  ${functions.join("\n\n")}
244
244
  `;
245
245
  }
246
+ async function regenerateAiBehaviors(opts) {
247
+ const { spec, ownerName, targetFunction, outputDir, allFunctions } = opts;
248
+ const findOwner = (collection) => {
249
+ if (!collection) return null;
250
+ if (Array.isArray(collection)) return collection.find((c) => c?.name === ownerName) || null;
251
+ return collection[ownerName] || null;
252
+ };
253
+ const controller = findOwner(spec.controllers);
254
+ const service = findOwner(spec.services);
255
+ if (!controller && !service) {
256
+ throw new Error(
257
+ `Owner '${ownerName}' not found in spec. Looked in controllers and services \u2014 check that the name matches exactly (case-sensitive) and that you're pointing at an inferred spec (try 'specs/main-inferred.specly').`
258
+ );
259
+ }
260
+ const unmatched = [];
261
+ const allModels = Object.keys(spec.models || {});
262
+ if (controller) {
263
+ const modelName = controller.model || controller.modelReference || ownerName.replace(/Controller$/, "");
264
+ const modelVar = modelName.charAt(0).toLowerCase() + modelName.slice(1);
265
+ const actions = controller.actions || {};
266
+ for (const [actionName, action] of Object.entries(actions)) {
267
+ const steps = action.steps || [];
268
+ const parameterNames = Object.keys(action.parameters || {});
269
+ const declaredVars = /* @__PURE__ */ new Set();
270
+ const preconditions = action.requires || action.preconditions || [];
271
+ for (const pc of preconditions) {
272
+ const m = typeof pc === "string" ? pc.match(/^(\w+)\s+(?:exists|is\s+\w+)$/i) : null;
273
+ if (m) declaredVars.add(m[1].charAt(0).toLowerCase() + m[1].slice(1));
274
+ }
275
+ for (let i = 0; i < steps.length; i++) {
276
+ const stepInput = steps[i];
277
+ const stepText = typeof stepInput === "string" ? stepInput : stepInput?.step;
278
+ const stepReturns = typeof stepInput === "object" ? stepInput?.returns : void 0;
279
+ if (typeof stepText !== "string") continue;
280
+ const ctx = {
281
+ modelName,
282
+ prismaModel: modelVar,
283
+ serviceName: ownerName,
284
+ operationName: actionName,
285
+ stepNum: i + 1,
286
+ parameterNames,
287
+ declaredVars,
288
+ resultName: typeof stepInput === "object" ? stepInput?.as : void 0
289
+ };
290
+ const result = matchStep(stepText, ctx);
291
+ if (!result.matched && result.functionName) {
292
+ if (!unmatched.find((f) => f.functionName === result.functionName)) {
293
+ unmatched.push({
294
+ functionName: result.functionName,
295
+ step: stepText,
296
+ operationName: actionName,
297
+ parameterNames,
298
+ inputs: result.inputs || [],
299
+ returns: stepReturns,
300
+ modelName
301
+ });
302
+ }
303
+ }
304
+ }
305
+ }
306
+ } else if (service) {
307
+ const modelName = service.name?.replace(/Service$/, "") || ownerName;
308
+ const operations = service.operations || {};
309
+ const opEntries = Array.isArray(operations) ? operations.map((op) => [op.name, op]) : Object.entries(operations);
310
+ for (const [opName, operation] of opEntries) {
311
+ const steps = operation.steps || operation.implementation?.steps || [];
312
+ const parameterNames = Object.keys(operation.parameters || {});
313
+ const declaredVars = /* @__PURE__ */ new Set();
314
+ const preconditions = operation.requires || operation.preconditions || [];
315
+ for (const pc of preconditions) {
316
+ const m = typeof pc === "string" ? pc.match(/^(\w+)\s+(?:exists|is\s+\w+)$/i) : null;
317
+ if (m) declaredVars.add(m[1].charAt(0).toLowerCase() + m[1].slice(1));
318
+ }
319
+ for (let i = 0; i < steps.length; i++) {
320
+ const stepInput = steps[i];
321
+ const stepText = typeof stepInput === "string" ? stepInput : stepInput?.step;
322
+ const stepReturns = typeof stepInput === "object" ? stepInput?.returns : void 0;
323
+ if (typeof stepText !== "string") continue;
324
+ const ctx = {
325
+ modelName,
326
+ prismaModel: modelName.charAt(0).toLowerCase() + modelName.slice(1),
327
+ serviceName: ownerName,
328
+ operationName: opName,
329
+ stepNum: i + 1,
330
+ parameterNames,
331
+ declaredVars,
332
+ resultName: typeof stepInput === "object" ? stepInput?.as : void 0
333
+ };
334
+ const result = matchStep(stepText, ctx);
335
+ if (!result.matched && result.functionName) {
336
+ if (!unmatched.find((f) => f.functionName === result.functionName)) {
337
+ unmatched.push({
338
+ functionName: result.functionName,
339
+ step: stepText,
340
+ operationName: opName,
341
+ parameterNames,
342
+ inputs: result.inputs || [],
343
+ returns: stepReturns,
344
+ modelName: ownerName
345
+ });
346
+ }
347
+ }
348
+ }
349
+ }
350
+ }
351
+ if (unmatched.length === 0) {
352
+ throw new Error(
353
+ `No AI behaviors to regenerate for '${ownerName}'. All of its steps match built-in convention patterns (see step-conventions.ts). If you expected an AI-generated function, double-check the spec step text.`
354
+ );
355
+ }
356
+ const targetFound = !targetFunction || unmatched.some((f) => f.functionName === targetFunction);
357
+ if (targetFunction && !targetFound) {
358
+ const known = unmatched.map((f) => f.functionName).join(", ");
359
+ throw new Error(
360
+ `Function '${targetFunction}' not found among '${ownerName}' unmatched functions. Known: ${known || "(none)"}.`
361
+ );
362
+ }
363
+ let cacheCleared = 0;
364
+ const functionsToInvalidate = allFunctions ? unmatched.map((f) => f.functionName) : targetFunction ? [targetFunction] : [];
365
+ for (const fnName of functionsToInvalidate) {
366
+ const fn = unmatched.find((f) => f.functionName === fnName);
367
+ const key = cacheKey(fn.step, fn.modelName, fn.operationName, fn.functionName, fn.inputs);
368
+ const path = join(cacheDir(), `${key}.ts`);
369
+ if (existsSync(path)) {
370
+ try {
371
+ unlinkSync(path);
372
+ cacheCleared++;
373
+ } catch (err) {
374
+ console.warn(` [ai-cache] failed to delete ${path}: ${err?.message || err}`);
375
+ }
376
+ }
377
+ }
378
+ const code = await generateAiBehaviorsFile({
379
+ ownerName,
380
+ unmatchedFunctions: unmatched,
381
+ availableModels: allModels,
382
+ spec
383
+ });
384
+ const filePath = join(outputDir, "backend", "src", "behaviors", `${ownerName}.ai.ts`);
385
+ const dir = dirname(filePath);
386
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
387
+ writeFileSync(filePath, code, "utf8");
388
+ return {
389
+ filePath,
390
+ targetFound,
391
+ unmatchedCount: unmatched.length,
392
+ cacheCleared
393
+ };
394
+ }
246
395
  export {
247
396
  generateAiBehaviors as default,
248
- generateAiBehaviorsFile
397
+ generateAiBehaviorsFile,
398
+ regenerateAiBehaviors
249
399
  };
@@ -340,6 +340,22 @@ export async function executeOperation(
340
340
  return apiRequest<ApiResponse>(method, path, Object.keys(params).length > 0 ? params : null);
341
341
  }
342
342
 
343
+ /**
344
+ * Execute a service operation
345
+ * Services are RPC-style under /services/{serviceName}/{operationName}
346
+ */
347
+ export async function executeServiceOperation(
348
+ serviceName: string,
349
+ operationName: string,
350
+ params: Record<string, any>
351
+ ): Promise<ApiResponse> {
352
+ return apiRequest<ApiResponse>(
353
+ 'POST',
354
+ \`/services/\${serviceName}/\${operationName}\`,
355
+ params
356
+ );
357
+ }
358
+
343
359
  /**
344
360
  * Transition entity lifecycle state
345
361
  */
@@ -432,6 +448,22 @@ export async function executeOperation(
432
448
  );
433
449
  }
434
450
 
451
+ /**
452
+ * Execute a service operation
453
+ * Services are RPC-style under /services/{serviceName}/{operationName}
454
+ */
455
+ export async function executeServiceOperation(
456
+ serviceName: string,
457
+ operationName: string,
458
+ params: Record<string, any>
459
+ ): Promise<ApiResponse> {
460
+ return apiRequest<ApiResponse>(
461
+ 'POST',
462
+ \`/services/\${serviceName}/\${operationName}\`,
463
+ params
464
+ );
465
+ }
466
+
435
467
  /**
436
468
  * Transition entity lifecycle state
437
469
  */
@@ -13,10 +13,10 @@ export default function generateRuntimeAppTsx(context: TemplateContext): string
13
13
  const { spec } = context;
14
14
  const appName = (spec as any)?.metadata?.name || (spec as any)?.name || 'SpecVerse App';
15
15
 
16
- return `import { useState, useEffect, useMemo } from 'react';
17
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
16
+ return `import { useState, useEffect, useMemo, useCallback } from 'react';
17
+ import { QueryClient, QueryClientProvider, useQueryClient } from '@tanstack/react-query';
18
18
  import yaml from 'js-yaml';
19
- import { RuntimeViewProvider } from '@specverse/runtime/views/react';
19
+ import { RuntimeViewProvider, useEntitySync } from '@specverse/runtime/views/react';
20
20
  import { DevShell } from '@specverse/runtime/views/react';
21
21
  import {
22
22
  useEntitiesQuery,
@@ -24,6 +24,7 @@ import {
24
24
  useExecuteOperationMutation,
25
25
  useTransitionStateMutation,
26
26
  } from './hooks/useApi';
27
+ import { listEntities, getRuntimeInfo } from './lib/apiClient';
27
28
  import devSpecRaw from './dev.specly?raw';
28
29
 
29
30
  // Parse YAML spec
@@ -76,6 +77,40 @@ function AppContent() {
76
77
  .catch(() => {});
77
78
  }, []);
78
79
 
80
+ // State-sync contract: WebSocket entity events → React Query cache
81
+ // invalidation. This is what guarantees "delete in one view is visible
82
+ // in every other view within one WS round-trip" — it runs at the App
83
+ // level so it's always on, regardless of which tab is active.
84
+ const queryClient = useQueryClient();
85
+ const invalidateEntities = useCallback((modelName: string) => {
86
+ queryClient.invalidateQueries({ queryKey: ['entities', modelName] });
87
+ }, [queryClient]);
88
+ useEntitySync({ invalidateEntities, apiBaseUrl: '/api' });
89
+
90
+ // Name resolver for OperationResultView. Kept in the host so runtime
91
+ // view components never issue raw fetch() calls — all HTTP goes
92
+ // through apiClient's canonical layer.
93
+ const resolveEntityNames = useCallback(async (ids: string[]): Promise<Record<string, string>> => {
94
+ const names: Record<string, string> = {};
95
+ try {
96
+ const info = await getRuntimeInfo();
97
+ const models = info?.models || [];
98
+ await Promise.all(models.map(async (model: string) => {
99
+ try {
100
+ const entities = await listEntities(model + 'Controller');
101
+ for (const entity of entities) {
102
+ const id = (entity as any)?.id;
103
+ const dataId = (entity as any)?.data?.id;
104
+ const display = (entity as any)?.name || (entity as any)?.title || (entity as any)?.label || id;
105
+ if (id && ids.includes(id)) names[id] = String(display);
106
+ if (dataId && ids.includes(dataId)) names[dataId] = String(display);
107
+ }
108
+ } catch { /* skip this model */ }
109
+ }));
110
+ } catch { /* ignore — caller falls back to raw IDs */ }
111
+ return names;
112
+ }, []);
113
+
79
114
  const runtimeValue = useMemo(() => ({
80
115
  useEntitiesQuery,
81
116
  useModelSchemaQuery,
@@ -86,7 +121,9 @@ function AppContent() {
86
121
  views: [],
87
122
  spec: appSpec,
88
123
  apiBaseUrl: '/api',
89
- }), [appSpec]);
124
+ invalidateEntities,
125
+ resolveEntityNames,
126
+ }), [appSpec, invalidateEntities, resolveEntityNames]);
90
127
 
91
128
  return (
92
129
  <RuntimeViewProvider value={runtimeValue}>
@@ -21,6 +21,7 @@ import {
21
21
  getModelSchema,
22
22
  listEntities,
23
23
  executeOperation,
24
+ executeServiceOperation,
24
25
  transitionState
25
26
  } from '../lib/apiClient';
26
27
  import type { ModelSchema, Entity, ApiResponse } from '../types/api';
@@ -59,9 +60,14 @@ export function useEntitiesQuery(controllerName: string | null, modelName: strin
59
60
  }
60
61
 
61
62
  /**
62
- * Mutation hook for executing operations
63
- * Matches RuntimeViewProviderValue.useExecuteOperationMutation contract:
64
- * { controllerName, operationName, data, entityId? }
63
+ * Mutation hook for executing operations — handles both controllers
64
+ * and services. Pass either \`controllerName\` (for CRUD or custom
65
+ * controller actions) or \`serviceName\` (for RPC-style service ops).
66
+ *
67
+ * Matches RuntimeViewProviderValue.useExecuteOperationMutation contract.
68
+ * Service operations invalidate the \`services\` query key; controller
69
+ * operations invalidate the corresponding model's \`entities\` key so
70
+ * all mounted views refetch automatically.
65
71
  */
66
72
  export function useExecuteOperationMutation() {
67
73
  const queryClient = useQueryClient();
@@ -69,12 +75,14 @@ export function useExecuteOperationMutation() {
69
75
  return useMutation({
70
76
  mutationFn: ({
71
77
  controllerName,
78
+ serviceName,
72
79
  operationName,
73
80
  data,
74
81
  params,
75
82
  entityId
76
83
  }: {
77
- controllerName: string;
84
+ controllerName?: string;
85
+ serviceName?: string;
78
86
  operationName: string;
79
87
  data?: Record<string, any>;
80
88
  params?: Record<string, any>;
@@ -83,11 +91,23 @@ export function useExecuteOperationMutation() {
83
91
  // Merge: accept both 'data' and 'params' for compatibility
84
92
  const mergedParams = { ...(data || params || {}) };
85
93
  if (entityId) mergedParams.id = entityId;
86
- return executeOperation(controllerName, operationName, mergedParams);
94
+ if (serviceName) {
95
+ return executeServiceOperation(serviceName, operationName, mergedParams);
96
+ }
97
+ if (controllerName) {
98
+ return executeOperation(controllerName, operationName, mergedParams);
99
+ }
100
+ throw new Error('useExecuteOperationMutation: either controllerName or serviceName is required');
87
101
  },
88
102
  onSuccess: (_data, variables) => {
89
- const modelName = variables.controllerName.replace(/Controller$/, '');
90
- queryClient.invalidateQueries({ queryKey: ['entities', modelName] });
103
+ if (variables.controllerName) {
104
+ const modelName = variables.controllerName.replace(/Controller$/, '');
105
+ queryClient.invalidateQueries({ queryKey: ['entities', modelName] });
106
+ }
107
+ // Service operations aren't tied to a single entity type; no
108
+ // cache key to invalidate here. If a service mutation affects
109
+ // entities, the backend should publish an event that
110
+ // useEntitySync picks up via WebSocket.
91
111
  }
92
112
  });
93
113
  }
@@ -843,6 +843,87 @@ import { EngineRegistry } from '@specverse/entities';`,
843
843
  console.log(template);
844
844
  }`
845
845
  },
846
+ 'ai.regenerate': {
847
+ imports: `import { readFileSync, existsSync } from 'fs';
848
+ import { resolve } from 'path';
849
+ import { EngineRegistry } from '@specverse/entities';
850
+ import type { ParserEngine } from '@specverse/types';`,
851
+ handler: `// Parse Owner.functionName — or just Owner with --all
852
+ const target = fn;
853
+ const dotIdx = target.indexOf('.');
854
+ const ownerName = dotIdx >= 0 ? target.slice(0, dotIdx) : target;
855
+ const functionName = dotIdx >= 0 ? target.slice(dotIdx + 1) : null;
856
+ if (!functionName && !options.all) {
857
+ console.error('Function must be specified as Owner.functionName, or use --all to regenerate every AI function in the owner.');
858
+ process.exit(1);
859
+ }
860
+
861
+ // Resolve spec file — default to specs/main-inferred.specly next to cwd
862
+ const userCwd = process.env.SPECVERSE_USER_CWD || process.cwd();
863
+ const specCandidates = options.spec
864
+ ? [resolve(userCwd, options.spec)]
865
+ : [resolve(userCwd, 'specs/main-inferred.specly'), resolve(userCwd, 'specs/main.specly')];
866
+ const specPath = specCandidates.find(p => existsSync(p));
867
+ if (!specPath) {
868
+ console.error('Spec not found. Tried: ' + specCandidates.join(', '));
869
+ console.error('Pass --spec <file> or run from a project root with specs/main.specly.');
870
+ process.exit(1);
871
+ }
872
+ console.log('Using spec: ' + specPath);
873
+
874
+ const registry = new EngineRegistry();
875
+ await registry.discover();
876
+ const parser = registry.getEngineForCapability('parse') as ParserEngine;
877
+ if (!parser) { console.error('No parser engine found.'); process.exit(1); }
878
+ await parser.initialize();
879
+
880
+ const specContent = readFileSync(specPath, 'utf8');
881
+ const parseResult = parser.parseContent(specContent, specPath);
882
+ if (parseResult.errors.length > 0) {
883
+ console.error('Invalid spec:');
884
+ parseResult.errors.forEach((e: string) => console.error(' ' + e));
885
+ process.exit(1);
886
+ }
887
+
888
+ // Flatten components down to a realize-shaped spec
889
+ // (controllers, services, models at top level) — matches what
890
+ // regenerateBehavior expects. Collections may be arrays (parser
891
+ // output) or objects (inferred spec); preserve the incoming shape.
892
+ const ast: any = parseResult.ast;
893
+ const flat: any = { ...ast };
894
+ const components = ast?.components || {};
895
+ for (const comp of Object.values(components) as any[]) {
896
+ for (const key of ['models', 'controllers', 'services']) {
897
+ const collection = comp?.[key];
898
+ if (!collection) continue;
899
+ if (Array.isArray(collection)) {
900
+ flat[key] = [...(Array.isArray(flat[key]) ? flat[key] : []), ...collection];
901
+ } else {
902
+ flat[key] = { ...(flat[key] && !Array.isArray(flat[key]) ? flat[key] : {}), ...collection };
903
+ }
904
+ }
905
+ }
906
+
907
+ const { regenerateBehavior } = await import('@specverse/engines/ai');
908
+ const outputDir = resolve(userCwd, options.output || 'generated/code');
909
+ try {
910
+ const result = await regenerateBehavior({
911
+ spec: flat,
912
+ ownerName,
913
+ targetFunction: options.all ? null : functionName,
914
+ outputDir,
915
+ allFunctions: !!options.all,
916
+ });
917
+ console.log(\`✅ Regenerated \${result.filePath}\`);
918
+ console.log(\` Owner: \${ownerName}\`);
919
+ console.log(\` Unmatched functions: \${result.unmatchedCount}\`);
920
+ console.log(\` Target: \${options.all ? 'all' : functionName}\`);
921
+ console.log(\` Cache entries cleared: \${result.cacheCleared}\`);
922
+ } catch (err: any) {
923
+ console.error('Regeneration failed: ' + (err?.message || err));
924
+ process.exit(1);
925
+ }`
926
+ },
846
927
  // === session subcommands ===
847
928
  'session.create': {
848
929
  imports: `import { EngineRegistry } from '@specverse/entities';`,
@@ -20,8 +20,8 @@
20
20
  import type { TemplateContext } from '@specverse/types';
21
21
  import { matchStep, type StepContext } from './step-conventions.js';
22
22
  import { createHash } from 'crypto';
23
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
24
- import { join } from 'path';
23
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from 'fs';
24
+ import { dirname, join } from 'path';
25
25
 
26
26
  /**
27
27
  * Validate generated TypeScript using esbuild's transform.
@@ -374,3 +374,214 @@ const prisma = new PrismaClient();
374
374
  ${functions.join('\n\n')}
375
375
  `;
376
376
  }
377
+
378
+ /**
379
+ * Regenerate a single owner's AI behaviors file, optionally targeting one
380
+ * function for cache bypass.
381
+ *
382
+ * Used by `specverse ai regenerate <Owner.fn>`. Works on both controllers
383
+ * (actions) and services (operations). When `targetFunction` is provided,
384
+ * its cache entry is deleted before regeneration so Claude is re-consulted
385
+ * for that one function; all other functions in the owner reuse their
386
+ * cache. When `targetFunction` is null, the whole file is rebuilt without
387
+ * touching the cache.
388
+ *
389
+ * `spec` should be the inferred spec (normalized shape: `controllers` and
390
+ * `services` are either objects keyed by name or arrays with `.name`).
391
+ */
392
+ export async function regenerateAiBehaviors(opts: {
393
+ spec: any;
394
+ ownerName: string;
395
+ targetFunction: string | null;
396
+ outputDir: string;
397
+ allFunctions?: boolean;
398
+ }): Promise<{
399
+ filePath: string;
400
+ targetFound: boolean;
401
+ unmatchedCount: number;
402
+ cacheCleared: number;
403
+ }> {
404
+ const { spec, ownerName, targetFunction, outputDir, allFunctions } = opts;
405
+
406
+ // Resolve the owner — could be a controller (has .actions) or a service (has .operations).
407
+ // Accept both the "object keyed by name" and "array with .name" shapes.
408
+ const findOwner = (collection: any): any => {
409
+ if (!collection) return null;
410
+ if (Array.isArray(collection)) return collection.find((c: any) => c?.name === ownerName) || null;
411
+ return collection[ownerName] || null;
412
+ };
413
+ const controller = findOwner(spec.controllers);
414
+ const service = findOwner(spec.services);
415
+ if (!controller && !service) {
416
+ throw new Error(
417
+ `Owner '${ownerName}' not found in spec. Looked in controllers and services — ` +
418
+ `check that the name matches exactly (case-sensitive) and that you're pointing ` +
419
+ `at an inferred spec (try 'specs/main-inferred.specly').`
420
+ );
421
+ }
422
+
423
+ // Build the unmatched-function list the same way realize does.
424
+ type UnmatchedFn = {
425
+ functionName: string;
426
+ step: string;
427
+ operationName: string;
428
+ parameterNames: string[];
429
+ inputs: string[];
430
+ returns?: Record<string, string> | string;
431
+ modelName: string;
432
+ };
433
+ const unmatched: UnmatchedFn[] = [];
434
+ const allModels: string[] = Object.keys(spec.models || {});
435
+
436
+ if (controller) {
437
+ const modelName = controller.model || controller.modelReference || ownerName.replace(/Controller$/, '');
438
+ const modelVar = modelName.charAt(0).toLowerCase() + modelName.slice(1);
439
+ const actions = controller.actions || {};
440
+ for (const [actionName, action] of Object.entries(actions) as [string, any][]) {
441
+ const steps = action.steps || [];
442
+ const parameterNames = Object.keys(action.parameters || {});
443
+ const declaredVars = new Set<string>();
444
+ const preconditions = action.requires || action.preconditions || [];
445
+ for (const pc of preconditions) {
446
+ const m = typeof pc === 'string' ? pc.match(/^(\w+)\s+(?:exists|is\s+\w+)$/i) : null;
447
+ if (m) declaredVars.add(m[1].charAt(0).toLowerCase() + m[1].slice(1));
448
+ }
449
+ for (let i = 0; i < steps.length; i++) {
450
+ const stepInput = steps[i];
451
+ const stepText = typeof stepInput === 'string' ? stepInput : stepInput?.step;
452
+ const stepReturns = typeof stepInput === 'object' ? stepInput?.returns : undefined;
453
+ if (typeof stepText !== 'string') continue;
454
+ const ctx: StepContext = {
455
+ modelName,
456
+ prismaModel: modelVar,
457
+ serviceName: ownerName,
458
+ operationName: actionName,
459
+ stepNum: i + 1,
460
+ parameterNames,
461
+ declaredVars,
462
+ resultName: typeof stepInput === 'object' ? stepInput?.as : undefined,
463
+ };
464
+ const result = matchStep(stepText, ctx);
465
+ if (!result.matched && result.functionName) {
466
+ if (!unmatched.find(f => f.functionName === result.functionName)) {
467
+ unmatched.push({
468
+ functionName: result.functionName,
469
+ step: stepText,
470
+ operationName: actionName,
471
+ parameterNames,
472
+ inputs: result.inputs || [],
473
+ returns: stepReturns,
474
+ modelName,
475
+ });
476
+ }
477
+ }
478
+ }
479
+ }
480
+ } else if (service) {
481
+ // Service operations share the same matchStep logic but without a model prefix.
482
+ const modelName = service.name?.replace(/Service$/, '') || ownerName;
483
+ const operations = service.operations || {};
484
+ const opEntries: [string, any][] = Array.isArray(operations)
485
+ ? operations.map((op: any) => [op.name, op])
486
+ : Object.entries(operations);
487
+ for (const [opName, operation] of opEntries) {
488
+ const steps = operation.steps || operation.implementation?.steps || [];
489
+ const parameterNames = Object.keys(operation.parameters || {});
490
+ const declaredVars = new Set<string>();
491
+ const preconditions = operation.requires || operation.preconditions || [];
492
+ for (const pc of preconditions) {
493
+ const m = typeof pc === 'string' ? pc.match(/^(\w+)\s+(?:exists|is\s+\w+)$/i) : null;
494
+ if (m) declaredVars.add(m[1].charAt(0).toLowerCase() + m[1].slice(1));
495
+ }
496
+ for (let i = 0; i < steps.length; i++) {
497
+ const stepInput = steps[i];
498
+ const stepText = typeof stepInput === 'string' ? stepInput : stepInput?.step;
499
+ const stepReturns = typeof stepInput === 'object' ? stepInput?.returns : undefined;
500
+ if (typeof stepText !== 'string') continue;
501
+ const ctx: StepContext = {
502
+ modelName,
503
+ prismaModel: modelName.charAt(0).toLowerCase() + modelName.slice(1),
504
+ serviceName: ownerName,
505
+ operationName: opName,
506
+ stepNum: i + 1,
507
+ parameterNames,
508
+ declaredVars,
509
+ resultName: typeof stepInput === 'object' ? stepInput?.as : undefined,
510
+ };
511
+ const result = matchStep(stepText, ctx);
512
+ if (!result.matched && result.functionName) {
513
+ if (!unmatched.find(f => f.functionName === result.functionName)) {
514
+ unmatched.push({
515
+ functionName: result.functionName,
516
+ step: stepText,
517
+ operationName: opName,
518
+ parameterNames,
519
+ inputs: result.inputs || [],
520
+ returns: stepReturns,
521
+ modelName: ownerName,
522
+ });
523
+ }
524
+ }
525
+ }
526
+ }
527
+ }
528
+
529
+ if (unmatched.length === 0) {
530
+ throw new Error(
531
+ `No AI behaviors to regenerate for '${ownerName}'. All of its steps match ` +
532
+ `built-in convention patterns (see step-conventions.ts). If you expected an ` +
533
+ `AI-generated function, double-check the spec step text.`
534
+ );
535
+ }
536
+
537
+ // Find the target function (unless regenerating the whole owner)
538
+ const targetFound = !targetFunction || unmatched.some(f => f.functionName === targetFunction);
539
+ if (targetFunction && !targetFound) {
540
+ const known = unmatched.map(f => f.functionName).join(', ');
541
+ throw new Error(
542
+ `Function '${targetFunction}' not found among '${ownerName}' unmatched functions. ` +
543
+ `Known: ${known || '(none)'}.`
544
+ );
545
+ }
546
+
547
+ // Delete the cache entry for the target function (or all of them if --all)
548
+ // so Claude is re-consulted. Other cache entries are untouched so other
549
+ // functions reuse their previous output.
550
+ let cacheCleared = 0;
551
+ const functionsToInvalidate = allFunctions
552
+ ? unmatched.map(f => f.functionName)
553
+ : targetFunction ? [targetFunction] : [];
554
+ for (const fnName of functionsToInvalidate) {
555
+ const fn = unmatched.find(f => f.functionName === fnName)!;
556
+ const key = cacheKey(fn.step, fn.modelName, fn.operationName, fn.functionName, fn.inputs);
557
+ const path = join(cacheDir(), `${key}.ts`);
558
+ if (existsSync(path)) {
559
+ try {
560
+ unlinkSync(path);
561
+ cacheCleared++;
562
+ } catch (err: any) {
563
+ console.warn(` [ai-cache] failed to delete ${path}: ${err?.message || err}`);
564
+ }
565
+ }
566
+ }
567
+
568
+ // Regenerate the full file (cache hits reuse output for non-target functions)
569
+ const code = await generateAiBehaviorsFile({
570
+ ownerName,
571
+ unmatchedFunctions: unmatched,
572
+ availableModels: allModels,
573
+ spec,
574
+ });
575
+
576
+ const filePath = join(outputDir, 'backend', 'src', 'behaviors', `${ownerName}.ai.ts`);
577
+ const dir = dirname(filePath);
578
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
579
+ writeFileSync(filePath, code, 'utf8');
580
+
581
+ return {
582
+ filePath,
583
+ targetFound,
584
+ unmatchedCount: unmatched.length,
585
+ cacheCleared,
586
+ };
587
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specverse/engines",
3
- "version": "4.1.20",
3
+ "version": "4.1.22",
4
4
  "description": "SpecVerse toolchain — parser, inference, realize, generators, AI, registry",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",