@exaudeus/workrail 3.15.0 → 3.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/dist/application/services/workflow-service.d.ts +2 -0
  2. package/dist/application/services/workflow-service.js +3 -0
  3. package/dist/application/use-cases/raw-workflow-file-scanner.js +10 -13
  4. package/dist/cli/commands/index.d.ts +1 -1
  5. package/dist/cli/commands/index.js +2 -1
  6. package/dist/cli/commands/init.d.ts +10 -0
  7. package/dist/cli/commands/init.js +72 -0
  8. package/dist/cli.js +13 -1
  9. package/dist/config/config-file.d.ts +8 -0
  10. package/dist/config/config-file.js +141 -0
  11. package/dist/config/feature-flags.js +8 -0
  12. package/dist/console/assets/index-BZNM03t1.css +1 -0
  13. package/dist/console/assets/index-BwJelCXK.js +28 -0
  14. package/dist/console/index.html +2 -2
  15. package/dist/di/container.d.ts +1 -0
  16. package/dist/di/container.js +24 -7
  17. package/dist/infrastructure/session/HttpServer.d.ts +3 -4
  18. package/dist/infrastructure/session/HttpServer.js +58 -106
  19. package/dist/infrastructure/storage/caching-workflow-storage.d.ts +2 -0
  20. package/dist/infrastructure/storage/caching-workflow-storage.js +15 -6
  21. package/dist/infrastructure/storage/file-workflow-storage.js +3 -4
  22. package/dist/infrastructure/storage/schema-validating-workflow-storage.js +9 -8
  23. package/dist/manifest.json +303 -247
  24. package/dist/mcp/assert-output.d.ts +37 -0
  25. package/dist/mcp/assert-output.js +53 -0
  26. package/dist/mcp/boundary-coercion.d.ts +1 -0
  27. package/dist/mcp/boundary-coercion.js +44 -0
  28. package/dist/mcp/dev-mode.d.ts +2 -0
  29. package/dist/mcp/dev-mode.js +16 -0
  30. package/dist/mcp/handler-factory.d.ts +1 -1
  31. package/dist/mcp/handler-factory.js +20 -16
  32. package/dist/mcp/handlers/session.js +8 -9
  33. package/dist/mcp/handlers/shared/request-workflow-reader.d.ts +1 -0
  34. package/dist/mcp/handlers/shared/request-workflow-reader.js +90 -20
  35. package/dist/mcp/handlers/v2-advance-core/event-builders.d.ts +2 -0
  36. package/dist/mcp/handlers/v2-advance-core/event-builders.js +6 -6
  37. package/dist/mcp/handlers/v2-advance-core/index.d.ts +2 -0
  38. package/dist/mcp/handlers/v2-advance-core/index.js +4 -3
  39. package/dist/mcp/handlers/v2-advance-core/input-validation.d.ts +2 -0
  40. package/dist/mcp/handlers/v2-advance-core/input-validation.js +32 -9
  41. package/dist/mcp/handlers/v2-advance-core/outcome-blocked.d.ts +2 -0
  42. package/dist/mcp/handlers/v2-advance-core/outcome-blocked.js +1 -1
  43. package/dist/mcp/handlers/v2-advance-core/outcome-success.d.ts +2 -0
  44. package/dist/mcp/handlers/v2-advance-core/outcome-success.js +1 -1
  45. package/dist/mcp/handlers/v2-checkpoint.d.ts +1 -1
  46. package/dist/mcp/handlers/v2-checkpoint.js +5 -6
  47. package/dist/mcp/handlers/v2-execution/advance.d.ts +4 -2
  48. package/dist/mcp/handlers/v2-execution/advance.js +5 -7
  49. package/dist/mcp/handlers/v2-execution/continue-advance.d.ts +1 -0
  50. package/dist/mcp/handlers/v2-execution/continue-advance.js +59 -27
  51. package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +2 -1
  52. package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +11 -10
  53. package/dist/mcp/handlers/v2-execution/index.js +2 -0
  54. package/dist/mcp/handlers/v2-execution/replay.d.ts +8 -4
  55. package/dist/mcp/handlers/v2-execution/replay.js +50 -30
  56. package/dist/mcp/handlers/v2-execution/start.d.ts +2 -3
  57. package/dist/mcp/handlers/v2-execution/start.js +58 -30
  58. package/dist/mcp/handlers/v2-execution/workflow-object-cache.d.ts +5 -0
  59. package/dist/mcp/handlers/v2-execution/workflow-object-cache.js +19 -0
  60. package/dist/mcp/handlers/v2-execution-helpers.d.ts +1 -0
  61. package/dist/mcp/handlers/v2-execution-helpers.js +23 -7
  62. package/dist/mcp/handlers/v2-resume.d.ts +1 -1
  63. package/dist/mcp/handlers/v2-resume.js +3 -4
  64. package/dist/mcp/handlers/v2-state-conversion.js +5 -1
  65. package/dist/mcp/handlers/v2-workflow.d.ts +80 -0
  66. package/dist/mcp/handlers/v2-workflow.js +40 -23
  67. package/dist/mcp/handlers/workflow.d.ts +2 -5
  68. package/dist/mcp/handlers/workflow.js +15 -12
  69. package/dist/mcp/output-schemas.d.ts +25 -27
  70. package/dist/mcp/output-schemas.js +7 -7
  71. package/dist/mcp/server.js +23 -4
  72. package/dist/mcp/tool-call-timing.d.ts +24 -0
  73. package/dist/mcp/tool-call-timing.js +85 -0
  74. package/dist/mcp/transports/http-entry.js +3 -2
  75. package/dist/mcp/transports/http-listener.d.ts +1 -0
  76. package/dist/mcp/transports/http-listener.js +25 -0
  77. package/dist/mcp/transports/shutdown-hooks.d.ts +4 -1
  78. package/dist/mcp/transports/shutdown-hooks.js +3 -2
  79. package/dist/mcp/transports/stdio-entry.js +6 -28
  80. package/dist/mcp/v2-response-formatter.d.ts +1 -1
  81. package/dist/mcp/v2-response-formatter.js +2 -5
  82. package/dist/mcp/validation/schema-introspection.d.ts +1 -0
  83. package/dist/mcp/validation/schema-introspection.js +15 -5
  84. package/dist/mcp/validation/suggestion-generator.js +2 -2
  85. package/dist/runtime/adapters/node-process-signals.d.ts +1 -0
  86. package/dist/runtime/adapters/node-process-signals.js +5 -0
  87. package/dist/runtime/adapters/noop-process-signals.d.ts +1 -0
  88. package/dist/runtime/adapters/noop-process-signals.js +2 -0
  89. package/dist/runtime/ports/process-signals.d.ts +1 -0
  90. package/dist/types/workflow-definition.d.ts +5 -1
  91. package/dist/types/workflow-definition.js +2 -0
  92. package/dist/types/workflow.d.ts +3 -0
  93. package/dist/types/workflow.js +35 -26
  94. package/dist/v2/durable-core/domain/context-template-resolver.js +2 -2
  95. package/dist/v2/durable-core/domain/function-definition-expander.js +2 -17
  96. package/dist/v2/durable-core/domain/prompt-renderer.d.ts +2 -0
  97. package/dist/v2/durable-core/domain/prompt-renderer.js +22 -18
  98. package/dist/v2/durable-core/domain/recap-recovery.js +23 -16
  99. package/dist/v2/durable-core/domain/retrieval-contract.js +13 -7
  100. package/dist/v2/durable-core/schemas/compiled-workflow/index.js +4 -3
  101. package/dist/v2/durable-core/session-index.d.ts +22 -0
  102. package/dist/v2/durable-core/session-index.js +58 -0
  103. package/dist/v2/durable-core/sorted-event-log.d.ts +6 -0
  104. package/dist/v2/durable-core/sorted-event-log.js +15 -0
  105. package/dist/v2/infra/local/fs/index.js +8 -8
  106. package/dist/v2/infra/local/pinned-workflow-store/index.d.ts +2 -0
  107. package/dist/v2/infra/local/pinned-workflow-store/index.js +49 -0
  108. package/dist/v2/infra/local/remembered-roots-store/index.d.ts +3 -1
  109. package/dist/v2/infra/local/remembered-roots-store/index.js +6 -3
  110. package/dist/v2/infra/local/session-store/index.d.ts +1 -1
  111. package/dist/v2/infra/local/session-store/index.js +71 -61
  112. package/dist/v2/infra/local/session-summary-provider/index.js +9 -4
  113. package/dist/v2/infra/local/snapshot-store/index.js +2 -1
  114. package/dist/v2/infra/local/workspace-anchor/index.js +4 -2
  115. package/dist/v2/ports/pinned-workflow-store.port.d.ts +2 -0
  116. package/dist/v2/ports/session-event-log-store.port.d.ts +1 -1
  117. package/dist/v2/projections/assessment-consequences.d.ts +2 -1
  118. package/dist/v2/projections/assessment-consequences.js +0 -5
  119. package/dist/v2/projections/assessments.d.ts +2 -1
  120. package/dist/v2/projections/assessments.js +2 -4
  121. package/dist/v2/projections/gaps.d.ts +2 -1
  122. package/dist/v2/projections/gaps.js +0 -5
  123. package/dist/v2/projections/preferences.d.ts +2 -1
  124. package/dist/v2/projections/preferences.js +0 -5
  125. package/dist/v2/projections/run-context.d.ts +2 -2
  126. package/dist/v2/projections/run-context.js +0 -5
  127. package/dist/v2/projections/run-dag.js +7 -1
  128. package/dist/v2/projections/run-execution-trace.d.ts +8 -0
  129. package/dist/v2/projections/run-execution-trace.js +124 -0
  130. package/dist/v2/projections/run-status-signals.d.ts +2 -2
  131. package/dist/v2/usecases/console-routes.d.ts +3 -1
  132. package/dist/v2/usecases/console-routes.js +124 -25
  133. package/dist/v2/usecases/console-service.d.ts +1 -0
  134. package/dist/v2/usecases/console-service.js +83 -25
  135. package/dist/v2/usecases/console-types.d.ts +53 -0
  136. package/dist/v2/usecases/worktree-service.js +32 -1
  137. package/package.json +6 -5
  138. package/spec/workflow.schema.json +18 -0
  139. package/workflows/adaptive-ticket-creation.json +23 -16
  140. package/workflows/architecture-scalability-audit.json +29 -22
  141. package/workflows/bug-investigation.agentic.v2.json +7 -0
  142. package/workflows/coding-task-workflow-agentic.json +7 -0
  143. package/workflows/coding-task-workflow-agentic.lean.v2.json +16 -8
  144. package/workflows/coding-task-workflow-agentic.v2.json +7 -0
  145. package/workflows/cross-platform-code-conversion.v2.json +7 -0
  146. package/workflows/document-creation-workflow.json +15 -8
  147. package/workflows/documentation-update-workflow.json +15 -8
  148. package/workflows/intelligent-test-case-generation.json +7 -0
  149. package/workflows/learner-centered-course-workflow.json +9 -2
  150. package/workflows/mr-review-workflow.agentic.v2.json +7 -0
  151. package/workflows/personal-learning-materials-creation-branched.json +15 -8
  152. package/workflows/presentation-creation.json +12 -5
  153. package/workflows/production-readiness-audit.json +7 -0
  154. package/workflows/relocation-workflow-us.json +39 -32
  155. package/workflows/scoped-documentation-workflow.json +33 -26
  156. package/workflows/ui-ux-design-workflow.json +7 -0
  157. package/workflows/workflow-diagnose-environment.json +6 -0
  158. package/workflows/workflow-for-workflows.json +7 -0
  159. package/workflows/workflow-for-workflows.v2.json +23 -11
  160. package/workflows/wr.discovery.json +8 -1
  161. package/dist/console/assets/index-BZYIjrzJ.js +0 -28
  162. package/dist/console/assets/index-OLCKbDdm.css +0 -1
  163. package/dist/mcp/handlers/v2-resolve-refs-envelope.d.ts +0 -5
  164. package/dist/mcp/handlers/v2-resolve-refs-envelope.js +0 -17
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_RING_BUFFER_CAPACITY = exports.ToolCallTimingRingBuffer = exports.noopToolCallTimingSink = void 0;
4
+ exports.createRingBufferSink = createRingBufferSink;
5
+ exports.createDevPerfSink = createDevPerfSink;
6
+ exports.composeSinks = composeSinks;
7
+ exports.withToolCallTiming = withToolCallTiming;
8
+ const noopToolCallTimingSink = () => { };
9
+ exports.noopToolCallTimingSink = noopToolCallTimingSink;
10
+ class ToolCallTimingRingBuffer {
11
+ constructor(capacity) {
12
+ this.capacity = capacity;
13
+ this.head = 0;
14
+ this.count = 0;
15
+ if (capacity < 1)
16
+ throw new Error('Ring buffer capacity must be >= 1');
17
+ this.buffer = new Array(capacity).fill(undefined);
18
+ }
19
+ push(timing) {
20
+ this.buffer[this.head] = timing;
21
+ this.head = (this.head + 1) % this.capacity;
22
+ if (this.count < this.capacity)
23
+ this.count++;
24
+ }
25
+ recent(limit) {
26
+ const n = limit !== undefined ? Math.min(limit, this.count) : this.count;
27
+ const results = [];
28
+ for (let i = 1; i <= n; i++) {
29
+ const idx = (this.head - i + this.capacity) % this.capacity;
30
+ const entry = this.buffer[idx];
31
+ if (entry !== undefined)
32
+ results.push(entry);
33
+ }
34
+ return results;
35
+ }
36
+ get size() {
37
+ return this.count;
38
+ }
39
+ }
40
+ exports.ToolCallTimingRingBuffer = ToolCallTimingRingBuffer;
41
+ exports.DEFAULT_RING_BUFFER_CAPACITY = 100;
42
+ function createRingBufferSink(buffer) {
43
+ return (timing) => {
44
+ buffer.push(timing);
45
+ };
46
+ }
47
+ function createDevPerfSink() {
48
+ return (timing) => {
49
+ const outcomeLabel = timing.outcome === 'success' ? 'OK' : timing.outcome.toUpperCase();
50
+ const line = `[PerfTrace] ${timing.toolName} ${timing.durationMs.toFixed(1)}ms [${outcomeLabel}]`;
51
+ console.error(line);
52
+ };
53
+ }
54
+ function composeSinks(...sinks) {
55
+ return (timing) => {
56
+ for (const sink of sinks) {
57
+ try {
58
+ sink(timing);
59
+ }
60
+ catch { }
61
+ }
62
+ };
63
+ }
64
+ async function withToolCallTiming(toolName, handler, sink) {
65
+ const startedAtMs = Date.now();
66
+ const startHr = performance.now();
67
+ let outcome = 'error';
68
+ try {
69
+ const result = await handler();
70
+ outcome = result?.isError === true ? 'error' : 'success';
71
+ return result;
72
+ }
73
+ catch (err) {
74
+ outcome = 'error';
75
+ throw err;
76
+ }
77
+ finally {
78
+ const durationMs = Math.round((performance.now() - startHr) * 100) / 100;
79
+ try {
80
+ sink({ toolName, startedAtMs, durationMs, outcome });
81
+ }
82
+ catch {
83
+ }
84
+ }
85
+ }
@@ -42,9 +42,11 @@ const http_listener_js_1 = require("./http-listener.js");
42
42
  const shutdown_hooks_js_1 = require("./shutdown-hooks.js");
43
43
  const crypto = __importStar(require("crypto"));
44
44
  const express_1 = __importDefault(require("express"));
45
+ const HTTP_PORT_SCAN_END = 3199;
45
46
  async function startHttpServer(port) {
46
47
  const { server, ctx } = await (0, server_js_1.composeServer)();
47
- const listener = (0, http_listener_js_1.createHttpListener)(port);
48
+ const scanEnd = Math.max(port, HTTP_PORT_SCAN_END);
49
+ const listener = await (0, http_listener_js_1.bindWithPortFallback)(port, scanEnd);
48
50
  const { StreamableHTTPServerTransport } = await Promise.resolve().then(() => __importStar(require('@modelcontextprotocol/sdk/server/streamableHttp.js')));
49
51
  const transport = new StreamableHTTPServerTransport({
50
52
  sessionIdGenerator: () => crypto.randomUUID(),
@@ -54,7 +56,6 @@ async function startHttpServer(port) {
54
56
  listener.app.post('/mcp', (req, res) => transport.handleRequest(req, res, req.body));
55
57
  listener.app.get('/mcp', (req, res) => transport.handleRequest(req, res));
56
58
  listener.app.delete('/mcp', (req, res) => transport.handleRequest(req, res));
57
- await listener.start();
58
59
  await server.connect(transport);
59
60
  const boundPort = listener.getBoundPort();
60
61
  console.error('[Transport] WorkRail MCP Server running on HTTP');
@@ -7,3 +7,4 @@ export interface HttpListener {
7
7
  stop(): Promise<void>;
8
8
  }
9
9
  export declare function createHttpListener(requestedPort: number): HttpListener;
10
+ export declare function bindWithPortFallback(startPort: number, endPort: number): Promise<HttpListener>;
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createHttpListener = createHttpListener;
7
+ exports.bindWithPortFallback = bindWithPortFallback;
7
8
  const express_1 = __importDefault(require("express"));
8
9
  const http_1 = require("http");
9
10
  function createHttpListener(requestedPort) {
@@ -62,3 +63,27 @@ function createHttpListener(requestedPort) {
62
63
  },
63
64
  };
64
65
  }
66
+ async function bindWithPortFallback(startPort, endPort) {
67
+ let lastError;
68
+ for (let port = startPort; port <= endPort; port++) {
69
+ const listener = createHttpListener(port);
70
+ try {
71
+ await listener.start();
72
+ if (port !== startPort) {
73
+ console.error(`[HttpListener] Port ${startPort} unavailable; bound to fallback port ${port}`);
74
+ }
75
+ return listener;
76
+ }
77
+ catch (err) {
78
+ const nodeErr = err;
79
+ if (nodeErr.code === 'EADDRINUSE' ||
80
+ (err instanceof Error && err.message.includes('already in use'))) {
81
+ lastError = err instanceof Error ? err : new Error(String(err));
82
+ continue;
83
+ }
84
+ throw err;
85
+ }
86
+ }
87
+ throw new Error(`[HttpListener] No available port in range ${startPort}-${endPort}. ` +
88
+ `Last error: ${lastError?.message}`);
89
+ }
@@ -2,4 +2,7 @@ export interface ShutdownHookOptions {
2
2
  readonly onBeforeTerminate: () => Promise<void>;
3
3
  }
4
4
  export declare function wireShutdownHooks(opts: ShutdownHookOptions): void;
5
- export declare function wireStdinShutdown(): void;
5
+ export interface StdinShutdownOptions {
6
+ readonly stdin?: NodeJS.ReadableStream;
7
+ }
8
+ export declare function wireStdinShutdown(opts?: StdinShutdownOptions): void;
@@ -29,9 +29,10 @@ function wireShutdownHooks(opts) {
29
29
  })();
30
30
  });
31
31
  }
32
- function wireStdinShutdown() {
32
+ function wireStdinShutdown(opts) {
33
33
  const shutdownEvents = container_js_1.container.resolve(tokens_js_1.DI.Runtime.ShutdownEvents);
34
- process.stdin.on('end', () => {
34
+ const stdin = opts?.stdin ?? process.stdin;
35
+ stdin.once('end', () => {
35
36
  console.error('[MCP] stdin closed, initiating shutdown');
36
37
  shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGHUP' });
37
38
  });
@@ -35,8 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.startStdioServer = startStdioServer;
37
37
  const server_js_1 = require("../server.js");
38
- const container_js_1 = require("../../di/container.js");
39
- const tokens_js_1 = require("../../di/tokens.js");
38
+ const shutdown_hooks_js_1 = require("./shutdown-hooks.js");
40
39
  const INITIAL_ROOTS_TIMEOUT_MS = 1000;
41
40
  async function fetchInitialRootsWithTimeout(server) {
42
41
  return Promise.race([
@@ -75,31 +74,10 @@ async function startStdioServer() {
75
74
  .catch(() => {
76
75
  console.error('[Roots] Client does not support roots/list; workspace context will use server CWD fallback');
77
76
  });
78
- const shutdownEvents = container_js_1.container.resolve(tokens_js_1.DI.Runtime.ShutdownEvents);
79
- const processSignals = container_js_1.container.resolve(tokens_js_1.DI.Runtime.ProcessSignals);
80
- const terminator = container_js_1.container.resolve(tokens_js_1.DI.Runtime.ProcessTerminator);
81
- processSignals.on('SIGINT', () => shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGINT' }));
82
- processSignals.on('SIGTERM', () => shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGTERM' }));
83
- processSignals.on('SIGHUP', () => shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGHUP' }));
84
- process.stdin.on('end', () => {
85
- console.error('[MCP] stdin closed, initiating shutdown');
86
- shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGHUP' });
87
- });
88
- let shutdownStarted = false;
89
- shutdownEvents.onShutdown((event) => {
90
- if (shutdownStarted)
91
- return;
92
- shutdownStarted = true;
93
- void (async () => {
94
- try {
95
- console.error(`[Shutdown] Requested by ${event.signal}. Stopping services...`);
96
- await ctx.httpServer?.stop();
97
- terminator.terminate({ kind: 'success' });
98
- }
99
- catch (err) {
100
- console.error('[Shutdown] Error while stopping services:', err);
101
- terminator.terminate({ kind: 'failure' });
102
- }
103
- })();
77
+ (0, shutdown_hooks_js_1.wireStdinShutdown)();
78
+ (0, shutdown_hooks_js_1.wireShutdownHooks)({
79
+ onBeforeTerminate: async () => {
80
+ await ctx.httpServer?.stop();
81
+ },
104
82
  });
105
83
  }
@@ -8,5 +8,5 @@ export interface FormattedResponse {
8
8
  readonly references?: FormattedReferences;
9
9
  readonly supplements?: readonly FormattedSupplement[];
10
10
  }
11
- export declare function formatV2ExecutionResponse(data: unknown): FormattedResponse | null;
11
+ export declare function formatV2ExecutionResponse(data: unknown, cleanResponseFormat: boolean): FormattedResponse | null;
12
12
  export declare function formatV2ResumeResponse(data: unknown): FormattedResponse | null;
@@ -216,9 +216,6 @@ function formatSuccess(data) {
216
216
  }
217
217
  return lines.join('\n');
218
218
  }
219
- function isCleanResponseFormat() {
220
- return process.env.WORKRAIL_CLEAN_RESPONSE_FORMAT === 'true';
221
- }
222
219
  const CLEAN_ADVANCE_FOOTERS = [
223
220
  'WorkRail: when done, call continue_workflow with your notes. Token:',
224
221
  'WorkRail: advance with continue_workflow when ready. Include your notes. Token:',
@@ -350,11 +347,11 @@ function renderReferencesSection(contentEnvelope, lifecycle) {
350
347
  return null;
351
348
  }
352
349
  }
353
- function formatV2ExecutionResponse(data) {
350
+ function formatV2ExecutionResponse(data, cleanResponseFormat) {
354
351
  const renderInput = deriveRenderInput(data);
355
352
  if (!renderInput)
356
353
  return null;
357
- const cleanFormat = isCleanResponseFormat();
354
+ const cleanFormat = cleanResponseFormat;
358
355
  const { response, lifecycle, contentEnvelope } = renderInput;
359
356
  const references = renderReferencesSection(contentEnvelope, lifecycle);
360
357
  if (cleanFormat) {
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ export declare function getCachedShape(schema: z.ZodObject<z.ZodRawShape>): z.ZodRawShape;
2
3
  export declare function extractExpectedKeys(schema: z.ZodType): readonly string[];
3
4
  export declare function extractRequiredKeys(schema: z.ZodType): readonly string[];
4
5
  export declare function findUnknownKeys(args: unknown, schema: z.ZodType): readonly string[];
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCachedShape = getCachedShape;
3
4
  exports.extractExpectedKeys = extractExpectedKeys;
4
5
  exports.extractRequiredKeys = extractRequiredKeys;
5
6
  exports.findUnknownKeys = findUnknownKeys;
@@ -8,9 +9,18 @@ exports.generateExampleValue = generateExampleValue;
8
9
  exports.generateTemplate = generateTemplate;
9
10
  exports.extractEnumValues = extractEnumValues;
10
11
  const zod_1 = require("zod");
12
+ const shapeCache = new WeakMap();
13
+ function getCachedShape(schema) {
14
+ const cached = shapeCache.get(schema);
15
+ if (cached !== undefined)
16
+ return cached;
17
+ const shape = schema._def.shape();
18
+ shapeCache.set(schema, shape);
19
+ return shape;
20
+ }
11
21
  function extractExpectedKeys(schema) {
12
22
  if (schema instanceof zod_1.z.ZodObject) {
13
- return Object.keys(schema._def.shape());
23
+ return Object.keys(getCachedShape(schema));
14
24
  }
15
25
  return [];
16
26
  }
@@ -18,7 +28,7 @@ function extractRequiredKeys(schema) {
18
28
  if (!(schema instanceof zod_1.z.ZodObject)) {
19
29
  return [];
20
30
  }
21
- const shape = schema._def.shape();
31
+ const shape = getCachedShape(schema);
22
32
  const required = [];
23
33
  for (const [key, value] of Object.entries(shape)) {
24
34
  const field = value;
@@ -55,7 +65,7 @@ function generateExampleValue(schema, depth = 0, maxDepth = 3, includeOptional =
55
65
  return generateExampleValue(schema._def.innerType, depth, maxDepth, includeOptional);
56
66
  }
57
67
  if (schema instanceof zod_1.z.ZodObject) {
58
- const shape = schema._def.shape();
68
+ const shape = getCachedShape(schema);
59
69
  const result = {};
60
70
  for (const [key, value] of Object.entries(shape)) {
61
71
  const field = value;
@@ -124,7 +134,7 @@ function extractEnumValues(schema, path) {
124
134
  let current = schema;
125
135
  for (const part of parts) {
126
136
  if (current instanceof zod_1.z.ZodObject) {
127
- const shape = current._def.shape();
137
+ const shape = getCachedShape(current);
128
138
  const field = shape[part];
129
139
  if (!field)
130
140
  return [];
@@ -133,7 +143,7 @@ function extractEnumValues(schema, path) {
133
143
  else if (current instanceof zod_1.z.ZodOptional) {
134
144
  current = current._def.innerType;
135
145
  if (current instanceof zod_1.z.ZodObject) {
136
- const shape = current._def.shape();
146
+ const shape = getCachedShape(current);
137
147
  const field = shape[part];
138
148
  if (!field)
139
149
  return [];
@@ -38,7 +38,7 @@ function generateMissingRequiredSuggestions(missingKeys, schema, config) {
38
38
  if (!(schema instanceof zod_1.z.ZodObject)) {
39
39
  return [];
40
40
  }
41
- const shape = schema._def.shape();
41
+ const shape = (0, schema_introspection_js_1.getCachedShape)(schema);
42
42
  const suggestions = [];
43
43
  for (const key of missingKeys) {
44
44
  const field = shape[key];
@@ -118,7 +118,7 @@ function patchTemplateForFailedOptionals(correctTemplate, args, zodErrors, schem
118
118
  if (args === null || typeof args !== 'object' || Array.isArray(args))
119
119
  return correctTemplate;
120
120
  const argsObj = args;
121
- const shape = schema._def.shape();
121
+ const shape = (0, schema_introspection_js_1.getCachedShape)(schema);
122
122
  const patched = { ...correctTemplate };
123
123
  let changed = false;
124
124
  for (const error of zodErrors) {
@@ -1,4 +1,5 @@
1
1
  import type { ProcessSignal, ProcessSignals } from '../ports/process-signals.js';
2
2
  export declare class NodeProcessSignals implements ProcessSignals {
3
3
  on(signal: ProcessSignal, handler: () => void | Promise<void>): void;
4
+ once(signal: ProcessSignal, handler: () => void | Promise<void>): void;
4
5
  }
@@ -7,5 +7,10 @@ class NodeProcessSignals {
7
7
  void handler();
8
8
  });
9
9
  }
10
+ once(signal, handler) {
11
+ process.once(signal, () => {
12
+ void handler();
13
+ });
14
+ }
10
15
  }
11
16
  exports.NodeProcessSignals = NodeProcessSignals;
@@ -1,4 +1,5 @@
1
1
  import type { ProcessSignal, ProcessSignals } from '../ports/process-signals.js';
2
2
  export declare class NoopProcessSignals implements ProcessSignals {
3
3
  on(_signal: ProcessSignal, _handler: () => void | Promise<void>): void;
4
+ once(_signal: ProcessSignal, _handler: () => void | Promise<void>): void;
4
5
  }
@@ -4,5 +4,7 @@ exports.NoopProcessSignals = void 0;
4
4
  class NoopProcessSignals {
5
5
  on(_signal, _handler) {
6
6
  }
7
+ once(_signal, _handler) {
8
+ }
7
9
  }
8
10
  exports.NoopProcessSignals = NoopProcessSignals;
@@ -1,4 +1,5 @@
1
1
  export type ProcessSignal = NodeJS.Signals | 'exit';
2
2
  export interface ProcessSignals {
3
3
  on(signal: ProcessSignal, handler: () => void | Promise<void>): void;
4
+ once(signal: ProcessSignal, handler: () => void | Promise<void>): void;
4
5
  }
@@ -110,13 +110,15 @@ export interface WorkflowRecommendedPreferences {
110
110
  readonly recommendedAutonomy?: 'guided' | 'full_auto_stop_on_user_deps' | 'full_auto_never_stop';
111
111
  readonly recommendedRiskPolicy?: 'conservative' | 'balanced' | 'aggressive';
112
112
  }
113
+ export declare const RESOLVE_FROM_VALUES: readonly ["workspace", "package"];
114
+ export type ResolveFrom = typeof RESOLVE_FROM_VALUES[number];
113
115
  export interface WorkflowReference {
114
116
  readonly id: string;
115
117
  readonly title: string;
116
118
  readonly source: string;
117
119
  readonly purpose: string;
118
120
  readonly authoritative: boolean;
119
- readonly resolveFrom?: 'workspace' | 'package';
121
+ readonly resolveFrom?: ResolveFrom;
120
122
  }
121
123
  export interface WorkflowDefinition {
122
124
  readonly id: string;
@@ -134,6 +136,8 @@ export interface WorkflowDefinition {
134
136
  readonly extensionPoints?: readonly ExtensionPoint[];
135
137
  readonly references?: readonly WorkflowReference[];
136
138
  readonly validatedAgainstSpecVersion?: number;
139
+ readonly about?: string;
140
+ readonly examples?: readonly string[];
137
141
  }
138
142
  export declare function isLoopStepDefinition(step: WorkflowStepDefinition | LoopStepDefinition): step is LoopStepDefinition;
139
143
  export declare function isWorkflowStepDefinition(step: WorkflowStepDefinition | LoopStepDefinition): step is WorkflowStepDefinition;
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RESOLVE_FROM_VALUES = void 0;
3
4
  exports.isLoopStepDefinition = isLoopStepDefinition;
4
5
  exports.isWorkflowStepDefinition = isWorkflowStepDefinition;
5
6
  exports.stepHasPromptSource = stepHasPromptSource;
6
7
  exports.hasWorkflowDefinitionShape = hasWorkflowDefinitionShape;
7
8
  exports.createWorkflowDefinition = createWorkflowDefinition;
9
+ exports.RESOLVE_FROM_VALUES = ['workspace', 'package'];
8
10
  function isLoopStepDefinition(step) {
9
11
  return 'type' in step && step.type === 'loop';
10
12
  }
@@ -3,6 +3,9 @@ import { WorkflowSource } from './workflow-source';
3
3
  export interface Workflow {
4
4
  readonly definition: WorkflowDefinition;
5
5
  readonly source: WorkflowSource;
6
+ readonly stepById: ReadonlyMap<string, WorkflowStepDefinition | LoopStepDefinition>;
7
+ readonly parentLoopByStepId: ReadonlyMap<string, LoopStepDefinition>;
8
+ readonly loopById: ReadonlyMap<string, LoopStepDefinition>;
6
9
  }
7
10
  export interface WorkflowSummary {
8
11
  readonly id: string;
@@ -9,10 +9,35 @@ exports.getAllStepIds = getAllStepIds;
9
9
  exports.isWorkflow = isWorkflow;
10
10
  exports.isWorkflowDefinition = isWorkflowDefinition;
11
11
  const workflow_source_1 = require("./workflow-source");
12
+ function buildWorkflowIndices(definition) {
13
+ const stepById = new Map();
14
+ const parentLoopByStepId = new Map();
15
+ const loopById = new Map();
16
+ function indexSteps(steps, parentLoop) {
17
+ for (const step of steps) {
18
+ stepById.set(step.id, step);
19
+ if (parentLoop !== null) {
20
+ parentLoopByStepId.set(step.id, parentLoop);
21
+ }
22
+ if ('type' in step && step.type === 'loop') {
23
+ loopById.set(step.id, step);
24
+ if (Array.isArray(step.body)) {
25
+ indexSteps(step.body, step);
26
+ }
27
+ }
28
+ }
29
+ }
30
+ indexSteps(definition.steps ?? [], null);
31
+ return { stepById, parentLoopByStepId, loopById };
32
+ }
12
33
  function createWorkflow(definition, source) {
34
+ const { stepById, parentLoopByStepId, loopById } = buildWorkflowIndices(definition);
13
35
  return Object.freeze({
14
36
  definition,
15
- source
37
+ source,
38
+ stepById,
39
+ parentLoopByStepId,
40
+ loopById,
16
41
  });
17
42
  }
18
43
  function toWorkflowSummary(workflow) {
@@ -31,32 +56,10 @@ function toWorkflowSourceInfo(source) {
31
56
  });
32
57
  }
33
58
  function getStepById(workflow, stepId) {
34
- const steps = workflow.definition.steps;
35
- for (const step of steps) {
36
- if (step.id === stepId) {
37
- return step;
38
- }
39
- if ('type' in step && step.type === 'loop' && Array.isArray(step.body)) {
40
- for (const bodyStep of step.body) {
41
- if (bodyStep.id === stepId) {
42
- return bodyStep;
43
- }
44
- }
45
- }
46
- }
47
- return null;
59
+ return workflow.stepById.get(stepId) ?? null;
48
60
  }
49
61
  function getAllStepIds(workflow) {
50
- const ids = [];
51
- for (const step of workflow.definition.steps) {
52
- ids.push(step.id);
53
- if ('type' in step && step.type === 'loop' && Array.isArray(step.body)) {
54
- for (const bodyStep of step.body) {
55
- ids.push(bodyStep.id);
56
- }
57
- }
58
- }
59
- return Object.freeze(ids);
62
+ return Object.freeze([...workflow.stepById.keys()]);
60
63
  }
61
64
  function isWorkflow(obj) {
62
65
  if (!obj || typeof obj !== 'object')
@@ -64,10 +67,16 @@ function isWorkflow(obj) {
64
67
  const candidate = obj;
65
68
  return ('definition' in candidate &&
66
69
  'source' in candidate &&
70
+ 'stepById' in candidate &&
71
+ 'parentLoopByStepId' in candidate &&
72
+ 'loopById' in candidate &&
67
73
  candidate['definition'] !== null &&
68
74
  typeof candidate['definition'] === 'object' &&
69
75
  candidate['source'] !== null &&
70
- typeof candidate['source'] === 'object');
76
+ typeof candidate['source'] === 'object' &&
77
+ candidate['stepById'] instanceof Map &&
78
+ candidate['parentLoopByStepId'] instanceof Map &&
79
+ candidate['loopById'] instanceof Map);
71
80
  }
72
81
  function isWorkflowDefinition(obj) {
73
82
  if (!obj || typeof obj !== 'object')
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CONTEXT_TOKEN_PATTERN = void 0;
4
4
  exports.resolveContextTemplates = resolveContextTemplates;
5
5
  exports.CONTEXT_TOKEN_PATTERN = /\{\{(?!wr\.)([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)\}\}/;
6
- const CONTEXT_TOKEN_RE_G = new RegExp(exports.CONTEXT_TOKEN_PATTERN.source, 'g');
7
6
  function resolveDotPath(base, path) {
8
7
  let current = base;
9
8
  for (const segment of path) {
@@ -16,7 +15,8 @@ function resolveDotPath(base, path) {
16
15
  function resolveContextTemplates(template, context) {
17
16
  if (!template.includes('{{'))
18
17
  return template;
19
- return template.replace(CONTEXT_TOKEN_RE_G, (_match, dotPath) => {
18
+ const re = new RegExp(exports.CONTEXT_TOKEN_PATTERN.source, 'g');
19
+ return template.replace(re, (_match, dotPath) => {
20
20
  const value = resolveDotPath(context, dotPath.split('.'));
21
21
  if (value === undefined || value === null) {
22
22
  return `[unset: ${dotPath}]`;
@@ -3,23 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.expandFunctionDefinitions = expandFunctionDefinitions;
4
4
  exports.formatFunctionDef = formatFunctionDef;
5
5
  const neverthrow_1 = require("neverthrow");
6
- const workflow_js_1 = require("../../../types/workflow.js");
7
6
  function findLoopById(workflow, loopId) {
8
- function searchSteps(steps) {
9
- for (const step of steps) {
10
- if (!(0, workflow_js_1.isLoopStepDefinition)(step))
11
- continue;
12
- if (step.id === loopId)
13
- return step;
14
- if (Array.isArray(step.body)) {
15
- const found = searchSteps(step.body);
16
- if (found)
17
- return found;
18
- }
19
- }
20
- return null;
21
- }
22
- return searchSteps(workflow.definition.steps);
7
+ return workflow.loopById.get(loopId) ?? null;
23
8
  }
24
9
  function getWorkflowScopeDefs(workflow) {
25
10
  return workflow.definition.functionDefinitions?.filter(f => !f.scope || f.scope === 'workflow') ?? [];
@@ -31,7 +16,7 @@ function getLoopScopeDefs(args) {
31
16
  });
32
17
  }
33
18
  function getStepScopeDefs(args) {
34
- const step = args.workflow.definition.steps.find(s => s.id === args.stepId);
19
+ const step = args.workflow.stepById.get(args.stepId);
35
20
  return step?.functionDefinitions?.filter(f => !f.scope || f.scope === 'step') ?? [];
36
21
  }
37
22
  function expandFunctionDefinitions(args) {
@@ -24,4 +24,6 @@ export declare function renderPendingPrompt(args: {
24
24
  readonly runId: RunId;
25
25
  readonly nodeId: NodeId;
26
26
  readonly rehydrateOnly: boolean;
27
+ readonly precomputedIndex?: import('../session-index.js').SessionIndex;
28
+ readonly cleanResponseFormat?: boolean;
27
29
  }): Result<StepMetadata, PromptRenderError>;