@sensigo/realm-cli 0.1.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 (190) hide show
  1. package/README.md +109 -0
  2. package/dist/agent/agent-utils.d.ts +27 -0
  3. package/dist/agent/agent-utils.d.ts.map +1 -0
  4. package/dist/agent/agent-utils.js +79 -0
  5. package/dist/agent/agent-utils.js.map +1 -0
  6. package/dist/agent/anthropic-provider.d.ts +23 -0
  7. package/dist/agent/anthropic-provider.d.ts.map +1 -0
  8. package/dist/agent/anthropic-provider.js +245 -0
  9. package/dist/agent/anthropic-provider.js.map +1 -0
  10. package/dist/agent/gate/slack-gate-notifier.d.ts +80 -0
  11. package/dist/agent/gate/slack-gate-notifier.d.ts.map +1 -0
  12. package/dist/agent/gate/slack-gate-notifier.js +315 -0
  13. package/dist/agent/gate/slack-gate-notifier.js.map +1 -0
  14. package/dist/agent/gate/slack-gate-server.d.ts +30 -0
  15. package/dist/agent/gate/slack-gate-server.d.ts.map +1 -0
  16. package/dist/agent/gate/slack-gate-server.js +99 -0
  17. package/dist/agent/gate/slack-gate-server.js.map +1 -0
  18. package/dist/agent/gate/slack-socket-client.d.ts +20 -0
  19. package/dist/agent/gate/slack-socket-client.d.ts.map +1 -0
  20. package/dist/agent/gate/slack-socket-client.js +141 -0
  21. package/dist/agent/gate/slack-socket-client.js.map +1 -0
  22. package/dist/agent/gate-intent-interpreter.d.ts +29 -0
  23. package/dist/agent/gate-intent-interpreter.d.ts.map +1 -0
  24. package/dist/agent/gate-intent-interpreter.js +33 -0
  25. package/dist/agent/gate-intent-interpreter.js.map +1 -0
  26. package/dist/agent/index.d.ts +4 -0
  27. package/dist/agent/index.d.ts.map +1 -0
  28. package/dist/agent/index.js +4 -0
  29. package/dist/agent/index.js.map +1 -0
  30. package/dist/agent/llm-provider.d.ts +46 -0
  31. package/dist/agent/llm-provider.d.ts.map +1 -0
  32. package/dist/agent/llm-provider.js +55 -0
  33. package/dist/agent/llm-provider.js.map +1 -0
  34. package/dist/agent/mcp/mcp-client.d.ts +18 -0
  35. package/dist/agent/mcp/mcp-client.d.ts.map +1 -0
  36. package/dist/agent/mcp/mcp-client.js +108 -0
  37. package/dist/agent/mcp/mcp-client.js.map +1 -0
  38. package/dist/agent/mcp/mcp-extensions.d.ts +40 -0
  39. package/dist/agent/mcp/mcp-extensions.d.ts.map +1 -0
  40. package/dist/agent/mcp/mcp-extensions.js +2 -0
  41. package/dist/agent/mcp/mcp-extensions.js.map +1 -0
  42. package/dist/agent/mcp-client.d.ts +18 -0
  43. package/dist/agent/mcp-client.d.ts.map +1 -0
  44. package/dist/agent/mcp-client.js +108 -0
  45. package/dist/agent/mcp-client.js.map +1 -0
  46. package/dist/agent/mcp-types.d.ts +40 -0
  47. package/dist/agent/mcp-types.d.ts.map +1 -0
  48. package/dist/agent/mcp-types.js +2 -0
  49. package/dist/agent/mcp-types.js.map +1 -0
  50. package/dist/agent/openai-provider.d.ts +30 -0
  51. package/dist/agent/openai-provider.d.ts.map +1 -0
  52. package/dist/agent/openai-provider.js +253 -0
  53. package/dist/agent/openai-provider.js.map +1 -0
  54. package/dist/agent/openai-reasoning-provider.d.ts +18 -0
  55. package/dist/agent/openai-reasoning-provider.d.ts.map +1 -0
  56. package/dist/agent/openai-reasoning-provider.js +76 -0
  57. package/dist/agent/openai-reasoning-provider.js.map +1 -0
  58. package/dist/agent/preflight.d.ts +36 -0
  59. package/dist/agent/preflight.d.ts.map +1 -0
  60. package/dist/agent/preflight.js +81 -0
  61. package/dist/agent/preflight.js.map +1 -0
  62. package/dist/agent/providers/agent-utils.d.ts +27 -0
  63. package/dist/agent/providers/agent-utils.d.ts.map +1 -0
  64. package/dist/agent/providers/agent-utils.js +79 -0
  65. package/dist/agent/providers/agent-utils.js.map +1 -0
  66. package/dist/agent/providers/anthropic-provider.d.ts +23 -0
  67. package/dist/agent/providers/anthropic-provider.d.ts.map +1 -0
  68. package/dist/agent/providers/anthropic-provider.js +257 -0
  69. package/dist/agent/providers/anthropic-provider.js.map +1 -0
  70. package/dist/agent/providers/llm-provider.d.ts +46 -0
  71. package/dist/agent/providers/llm-provider.d.ts.map +1 -0
  72. package/dist/agent/providers/llm-provider.js +56 -0
  73. package/dist/agent/providers/llm-provider.js.map +1 -0
  74. package/dist/agent/providers/openai-provider.d.ts +30 -0
  75. package/dist/agent/providers/openai-provider.d.ts.map +1 -0
  76. package/dist/agent/providers/openai-provider.js +253 -0
  77. package/dist/agent/providers/openai-provider.js.map +1 -0
  78. package/dist/agent/providers/openai-reasoning-provider.d.ts +19 -0
  79. package/dist/agent/providers/openai-reasoning-provider.d.ts.map +1 -0
  80. package/dist/agent/providers/openai-reasoning-provider.js +89 -0
  81. package/dist/agent/providers/openai-reasoning-provider.js.map +1 -0
  82. package/dist/agent/run-agent.d.ts +50 -0
  83. package/dist/agent/run-agent.d.ts.map +1 -0
  84. package/dist/agent/run-agent.js +327 -0
  85. package/dist/agent/run-agent.js.map +1 -0
  86. package/dist/agent/slack-gate-notifier.d.ts +80 -0
  87. package/dist/agent/slack-gate-notifier.d.ts.map +1 -0
  88. package/dist/agent/slack-gate-notifier.js +315 -0
  89. package/dist/agent/slack-gate-notifier.js.map +1 -0
  90. package/dist/agent/slack-gate-poller.d.ts +28 -0
  91. package/dist/agent/slack-gate-poller.d.ts.map +1 -0
  92. package/dist/agent/slack-gate-poller.js +66 -0
  93. package/dist/agent/slack-gate-poller.js.map +1 -0
  94. package/dist/agent/slack-gate-server.d.ts +30 -0
  95. package/dist/agent/slack-gate-server.d.ts.map +1 -0
  96. package/dist/agent/slack-gate-server.js +99 -0
  97. package/dist/agent/slack-gate-server.js.map +1 -0
  98. package/dist/agent/slack-socket-client.d.ts +20 -0
  99. package/dist/agent/slack-socket-client.d.ts.map +1 -0
  100. package/dist/agent/slack-socket-client.js +141 -0
  101. package/dist/agent/slack-socket-client.js.map +1 -0
  102. package/dist/commands/agent.d.ts +3 -0
  103. package/dist/commands/agent.d.ts.map +1 -0
  104. package/dist/commands/agent.js +183 -0
  105. package/dist/commands/agent.js.map +1 -0
  106. package/dist/commands/cleanup.d.ts +16 -0
  107. package/dist/commands/cleanup.d.ts.map +1 -0
  108. package/dist/commands/cleanup.js +79 -0
  109. package/dist/commands/cleanup.js.map +1 -0
  110. package/dist/commands/diff.d.ts +41 -0
  111. package/dist/commands/diff.d.ts.map +1 -0
  112. package/dist/commands/diff.js +203 -0
  113. package/dist/commands/diff.js.map +1 -0
  114. package/dist/commands/init.d.ts +10 -0
  115. package/dist/commands/init.d.ts.map +1 -0
  116. package/dist/commands/init.js +97 -0
  117. package/dist/commands/init.js.map +1 -0
  118. package/dist/commands/inspect.d.ts +14 -0
  119. package/dist/commands/inspect.d.ts.map +1 -0
  120. package/dist/commands/inspect.js +224 -0
  121. package/dist/commands/inspect.js.map +1 -0
  122. package/dist/commands/list.d.ts +18 -0
  123. package/dist/commands/list.d.ts.map +1 -0
  124. package/dist/commands/list.js +88 -0
  125. package/dist/commands/list.js.map +1 -0
  126. package/dist/commands/mcp.d.ts +8 -0
  127. package/dist/commands/mcp.d.ts.map +1 -0
  128. package/dist/commands/mcp.js +22 -0
  129. package/dist/commands/mcp.js.map +1 -0
  130. package/dist/commands/migrate.d.ts +3 -0
  131. package/dist/commands/migrate.d.ts.map +1 -0
  132. package/dist/commands/migrate.js +42 -0
  133. package/dist/commands/migrate.js.map +1 -0
  134. package/dist/commands/register.d.ts +6 -0
  135. package/dist/commands/register.d.ts.map +1 -0
  136. package/dist/commands/register.js +51 -0
  137. package/dist/commands/register.js.map +1 -0
  138. package/dist/commands/replay-format.d.ts +3 -0
  139. package/dist/commands/replay-format.d.ts.map +1 -0
  140. package/dist/commands/replay-format.js +10 -0
  141. package/dist/commands/replay-format.js.map +1 -0
  142. package/dist/commands/replay.d.ts +38 -0
  143. package/dist/commands/replay.d.ts.map +1 -0
  144. package/dist/commands/replay.js +173 -0
  145. package/dist/commands/replay.js.map +1 -0
  146. package/dist/commands/respond.d.ts +20 -0
  147. package/dist/commands/respond.d.ts.map +1 -0
  148. package/dist/commands/respond.js +49 -0
  149. package/dist/commands/respond.js.map +1 -0
  150. package/dist/commands/resume.d.ts +15 -0
  151. package/dist/commands/resume.d.ts.map +1 -0
  152. package/dist/commands/resume.js +63 -0
  153. package/dist/commands/resume.js.map +1 -0
  154. package/dist/commands/run.d.ts +3 -0
  155. package/dist/commands/run.d.ts.map +1 -0
  156. package/dist/commands/run.js +127 -0
  157. package/dist/commands/run.js.map +1 -0
  158. package/dist/commands/serve.d.ts +33 -0
  159. package/dist/commands/serve.d.ts.map +1 -0
  160. package/dist/commands/serve.js +144 -0
  161. package/dist/commands/serve.js.map +1 -0
  162. package/dist/commands/test.d.ts +12 -0
  163. package/dist/commands/test.d.ts.map +1 -0
  164. package/dist/commands/test.js +58 -0
  165. package/dist/commands/test.js.map +1 -0
  166. package/dist/commands/validate.d.ts +3 -0
  167. package/dist/commands/validate.d.ts.map +1 -0
  168. package/dist/commands/validate.js +35 -0
  169. package/dist/commands/validate.js.map +1 -0
  170. package/dist/commands/watch.d.ts +18 -0
  171. package/dist/commands/watch.d.ts.map +1 -0
  172. package/dist/commands/watch.js +112 -0
  173. package/dist/commands/watch.js.map +1 -0
  174. package/dist/commands/webhook.d.ts +51 -0
  175. package/dist/commands/webhook.d.ts.map +1 -0
  176. package/dist/commands/webhook.js +227 -0
  177. package/dist/commands/webhook.js.map +1 -0
  178. package/dist/commands-registry.d.ts +7 -0
  179. package/dist/commands-registry.d.ts.map +1 -0
  180. package/dist/commands-registry.js +44 -0
  181. package/dist/commands-registry.js.map +1 -0
  182. package/dist/index.d.ts +3 -0
  183. package/dist/index.d.ts.map +1 -0
  184. package/dist/index.js +21 -0
  185. package/dist/index.js.map +1 -0
  186. package/dist/store/replay-store.d.ts +29 -0
  187. package/dist/store/replay-store.d.ts.map +1 -0
  188. package/dist/store/replay-store.js +31 -0
  189. package/dist/store/replay-store.js.map +1 -0
  190. package/package.json +83 -0
@@ -0,0 +1,88 @@
1
+ // list command — displays all runs in the store, sorted by most recent first.
2
+ import chalk from 'chalk';
3
+ import { Command } from 'commander';
4
+ /** Returns a chalk-coloured phase label. */
5
+ function colorState(run) {
6
+ if (run.run_phase === 'completed')
7
+ return chalk.green(run.run_phase);
8
+ if (run.run_phase === 'failed' || run.run_phase === 'abandoned')
9
+ return chalk.red(run.run_phase);
10
+ if (run.run_phase === 'gate_waiting')
11
+ return chalk.cyan(run.run_phase);
12
+ return chalk.yellow(run.run_phase);
13
+ }
14
+ /**
15
+ * Formats elapsed time since a gate was opened as a compact human-readable duration.
16
+ * @param openedAt ISO 8601 timestamp of when the gate was opened.
17
+ * @param now Current time — injectable for testing. Defaults to `new Date()`.
18
+ */
19
+ export function formatGateAge(openedAt, now = new Date()) {
20
+ const elapsedMs = now.getTime() - new Date(openedAt).getTime();
21
+ const totalMinutes = Math.floor(elapsedMs / 60_000);
22
+ const totalHours = Math.floor(totalMinutes / 60);
23
+ const totalDays = Math.floor(totalHours / 24);
24
+ if (totalMinutes < 60)
25
+ return `${totalMinutes}m`;
26
+ if (totalHours < 24) {
27
+ const remainingMinutes = totalMinutes % 60;
28
+ return `${totalHours}h ${remainingMinutes}m`;
29
+ }
30
+ const remainingHours = totalHours % 24;
31
+ return `${totalDays}d ${remainingHours}h`;
32
+ }
33
+ const VALID_PHASES = ['running', 'gate_waiting', 'completed', 'failed', 'abandoned'];
34
+ /**
35
+ * Lists runs from the store, sorted by updated_at descending.
36
+ * @param workflowId Optional filter — only show runs from this workflow.
37
+ * @param store Store holding run records.
38
+ * @param statusFilter Optional filter — only show runs with this run_phase.
39
+ * @returns Formatted output string.
40
+ */
41
+ export async function listRuns(workflowId, store, statusFilter) {
42
+ const runs = await store.list(workflowId);
43
+ const filtered = statusFilter !== undefined ? runs.filter((r) => r.run_phase === statusFilter) : runs;
44
+ if (filtered.length === 0) {
45
+ return workflowId !== undefined
46
+ ? `No runs found for workflow '${workflowId}'.`
47
+ : 'No runs found.';
48
+ }
49
+ filtered.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
50
+ const lines = [];
51
+ for (const run of filtered) {
52
+ const state = colorState(run);
53
+ const updated = new Date(run.updated_at).toLocaleString();
54
+ const steps = new Set(run.evidence.filter((e) => e.kind !== 'gate_response').map((e) => e.step_id)).size;
55
+ let line = `${chalk.dim(run.id)} ${chalk.bold(run.workflow_id)} v${run.workflow_version} ${state} ${updated} ${steps} step(s)`;
56
+ if (run.run_phase === 'gate_waiting' && run.pending_gate !== undefined) {
57
+ const age = formatGateAge(run.pending_gate.opened_at);
58
+ line += ` gate: ${run.pending_gate.step_name} (${age})`;
59
+ }
60
+ lines.push(line);
61
+ }
62
+ return lines.join('\n');
63
+ }
64
+ export const listCommand = new Command('list')
65
+ .description('List all runs, sorted by most recent first')
66
+ .option('--workflow <id>', 'Filter by workflow ID')
67
+ .option('--status <phase>', `Filter by run phase (${VALID_PHASES.join(', ')})`)
68
+ .action(async (opts) => {
69
+ const { JsonFileStore } = await import('@sensigo/realm');
70
+ const store = new JsonFileStore();
71
+ let statusFilter;
72
+ if (opts.status !== undefined) {
73
+ if (!VALID_PHASES.includes(opts.status)) {
74
+ console.error(`Invalid --status value '${opts.status}'. Valid values: ${VALID_PHASES.join(', ')}`);
75
+ process.exit(1);
76
+ }
77
+ statusFilter = opts.status;
78
+ }
79
+ try {
80
+ const output = await listRuns(opts.workflow, store, statusFilter);
81
+ console.log(output);
82
+ }
83
+ catch (err) {
84
+ console.error(err instanceof Error ? err.message : String(err));
85
+ process.exit(1);
86
+ }
87
+ });
88
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Starts the Realm MCP server using the global workflow store (~/.realm/workflows/).
4
+ * All workflows registered via `realm workflow register` are immediately available.
5
+ * Built-in adapters (FileSystemAdapter etc.) are included automatically.
6
+ */
7
+ export declare const mcpCommand: Command;
8
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC;;;;GAIG;AACH,eAAO,MAAM,UAAU,SAOnB,CAAC"}
@@ -0,0 +1,22 @@
1
+ // realm mcp — starts the global Realm MCP server.
2
+ // Serves all workflows registered via `realm workflow register`.
3
+ // For custom handlers or adapters, build a small mcp-server.ts that calls
4
+ // createRealmMcpServer({ workflowStore, registry }) with your extended registry.
5
+ import { Command } from 'commander';
6
+ import { JsonWorkflowStore } from '@sensigo/realm';
7
+ import { createRealmMcpServer } from '@sensigo/realm-mcp';
8
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ /**
10
+ * Starts the Realm MCP server using the global workflow store (~/.realm/workflows/).
11
+ * All workflows registered via `realm workflow register` are immediately available.
12
+ * Built-in adapters (FileSystemAdapter etc.) are included automatically.
13
+ */
14
+ export const mcpCommand = new Command('mcp')
15
+ .description('Start the Realm MCP server (serves all registered workflows via stdio)')
16
+ .action(async () => {
17
+ const workflowStore = new JsonWorkflowStore();
18
+ const server = createRealmMcpServer({ workflowStore });
19
+ const transport = new StdioServerTransport();
20
+ await server.connect(transport);
21
+ });
22
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,iEAAiE;AACjE,0EAA0E;AAC1E,iFAAiF;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC;KACzC,WAAW,CAAC,wEAAwE,CAAC;KACrF,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,aAAa,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG,oBAAoB,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const migrateCommand: Command;
3
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,cAAc,SA4CvB,CAAC"}
@@ -0,0 +1,42 @@
1
+ // realm workflow migrate — back-fills origin: 'human' on local workflow JSON files.
2
+ import { Command } from 'commander';
3
+ import { readFileSync, writeFileSync, readdirSync, existsSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { homedir } from 'node:os';
6
+ export const migrateCommand = new Command('migrate')
7
+ .description('Back-fill origin field on local workflow definitions that predate provenance tracking')
8
+ .action(() => {
9
+ const workflowsDir = join(homedir(), '.realm', 'workflows');
10
+ if (!existsSync(workflowsDir)) {
11
+ console.log('No local workflow store found. Nothing to migrate.');
12
+ return;
13
+ }
14
+ const files = readdirSync(workflowsDir).filter((f) => f.endsWith('.json'));
15
+ if (files.length === 0) {
16
+ console.log('No workflow files found. Nothing to migrate.');
17
+ return;
18
+ }
19
+ let migrated = 0;
20
+ let skipped = 0;
21
+ for (const file of files) {
22
+ const filePath = join(workflowsDir, file);
23
+ let definition;
24
+ try {
25
+ definition = JSON.parse(readFileSync(filePath, 'utf8'));
26
+ }
27
+ catch (err) {
28
+ console.warn(`Skipping ${file}: could not parse JSON — ${err instanceof Error ? err.message : String(err)}`);
29
+ continue;
30
+ }
31
+ if ('origin' in definition) {
32
+ skipped++;
33
+ continue;
34
+ }
35
+ definition.origin = 'human';
36
+ writeFileSync(filePath, JSON.stringify(definition, null, 2), 'utf8');
37
+ console.log(`Migrated: ${file}`);
38
+ migrated++;
39
+ }
40
+ console.log(`Done. ${migrated} migrated, ${skipped} already up to date.`);
41
+ });
42
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CACV,uFAAuF,CACxF;KACA,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAC1C,IAAI,UAAmC,CAAC;QACxC,IAAI,CAAC;YACH,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAA4B,CAAC;QACrF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CACV,YAAY,IAAI,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC/F,CAAC;YACF,SAAS;QACX,CAAC;QAED,IAAI,QAAQ,IAAI,UAAU,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QAED,UAAU,CAAC,MAAM,GAAG,OAAO,CAAC;QAC5B,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QACjC,QAAQ,EAAE,CAAC;IACb,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,QAAQ,cAAc,OAAO,sBAAsB,CAAC,CAAC;AAC5E,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ import type { WorkflowDefinition } from '@sensigo/realm';
3
+ export declare const registerCommand: Command;
4
+ /** @internal Exported for testing only. */
5
+ export declare function lintWorkflowContext(definition: WorkflowDefinition): string[];
6
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,eAAO,MAAM,eAAe,SAyBxB,CAAC;AAEL,2CAA2C;AAC3C,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM,EAAE,CA4B5E"}
@@ -0,0 +1,51 @@
1
+ // realm register <path> — validates and registers a workflow from a YAML file.
2
+ import { Command } from 'commander';
3
+ import { join } from 'node:path';
4
+ import { loadWorkflowFromFile, JsonWorkflowStore } from '@sensigo/realm';
5
+ export const registerCommand = new Command('register')
6
+ .argument('<path>', 'Path to workflow directory or workflow.yaml file')
7
+ .description('Register a workflow definition')
8
+ .action(async (inputPath) => {
9
+ const filePath = inputPath.endsWith('.yaml') || inputPath.endsWith('.yml')
10
+ ? inputPath
11
+ : join(inputPath, 'workflow.yaml');
12
+ try {
13
+ const definition = loadWorkflowFromFile(filePath);
14
+ const store = new JsonWorkflowStore();
15
+ await store.register(definition);
16
+ const contextWarnings = lintWorkflowContext(definition);
17
+ for (const warning of contextWarnings) {
18
+ console.warn(`⚠ ${warning}`);
19
+ }
20
+ console.log(`Registered: ${definition.id} v${definition.version} (${Object.keys(definition.steps).length} steps)`);
21
+ }
22
+ catch (err) {
23
+ const message = err instanceof Error ? err.message : String(err);
24
+ console.error(`Error: ${message}`);
25
+ process.exit(1);
26
+ }
27
+ });
28
+ /** @internal Exported for testing only. */
29
+ export function lintWorkflowContext(definition) {
30
+ const contextEntries = Object.keys(definition.workflow_context ?? {});
31
+ if (contextEntries.length === 0)
32
+ return [];
33
+ // Only lint agent steps that have a prompt — auto steps have no agent-visible prompt.
34
+ const agentStepsWithPrompt = Object.values(definition.steps).filter((s) => s.execution === 'agent' && typeof s.prompt === 'string');
35
+ // Need at least 2 agent steps for a proportion warning to be meaningful.
36
+ if (agentStepsWithPrompt.length < 2)
37
+ return [];
38
+ const threshold = Math.floor(agentStepsWithPrompt.length / 2);
39
+ const warnings = [];
40
+ for (const name of contextEntries) {
41
+ const refPattern = `workflow.context.${name}`;
42
+ const refCount = agentStepsWithPrompt.filter((s) => s.prompt.includes(refPattern)).length;
43
+ if (refCount > threshold) {
44
+ warnings.push(`workflow.context.${name} is referenced in ${refCount} of ${agentStepsWithPrompt.length} ` +
45
+ `agent step prompts. If this context applies universally, that is intentional — ` +
46
+ `otherwise consider whether all steps truly need it.`);
47
+ }
48
+ }
49
+ return warnings;
50
+ }
51
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Formats a precondition comparison column for replay output tables. */
2
+ export declare function formatPrecondColumn(originalPass: boolean, replayPass: boolean, hasPreconditions: boolean): string;
3
+ //# sourceMappingURL=replay-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-format.d.ts","sourceRoot":"","sources":["../../src/commands/replay-format.ts"],"names":[],"mappings":"AAEA,yEAAyE;AACzE,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,OAAO,EACrB,UAAU,EAAE,OAAO,EACnB,gBAAgB,EAAE,OAAO,GACxB,MAAM,CAKR"}
@@ -0,0 +1,10 @@
1
+ // replay-format.ts — shared formatting helper for precondition columns in replay output tables.
2
+ /** Formats a precondition comparison column for replay output tables. */
3
+ export function formatPrecondColumn(originalPass, replayPass, hasPreconditions) {
4
+ if (!hasPreconditions)
5
+ return 'none';
6
+ const orig = originalPass ? 'PASS' : 'BLOCKED';
7
+ const replay = replayPass ? 'PASS' : 'BLOCKED';
8
+ return `${orig} \u2192 ${replay}`;
9
+ }
10
+ //# sourceMappingURL=replay-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-format.js","sourceRoot":"","sources":["../../src/commands/replay-format.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAEhG,yEAAyE;AACzE,MAAM,UAAU,mBAAmB,CACjC,YAAqB,EACrB,UAAmB,EACnB,gBAAyB;IAEzB,IAAI,CAAC,gBAAgB;QAAE,OAAO,MAAM,CAAC;IACrC,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,OAAO,GAAG,IAAI,WAAW,MAAM,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { Command } from 'commander';
2
+ import type { RunRecord, WorkflowDefinition } from '@sensigo/realm';
3
+ import type { ReplayStore } from '../store/replay-store.js';
4
+ export interface ReplayOverride {
5
+ step: string;
6
+ field: string;
7
+ value: unknown;
8
+ }
9
+ export interface ReplayStepResult {
10
+ step_id: string;
11
+ /** All preconditions passed in the original run? */
12
+ preconditions_original: boolean;
13
+ /** All preconditions pass with overridden evidence? */
14
+ preconditions_replay: boolean;
15
+ changed: boolean;
16
+ /** True when the step has at least one precondition defined. */
17
+ has_preconditions: boolean;
18
+ }
19
+ /**
20
+ * Parses a --with override expression of the form "step.field=value".
21
+ * @throws Error if the expression is missing '.' or '='.
22
+ */
23
+ export declare function parseOverride(expr: string): ReplayOverride;
24
+ /**
25
+ * Re-evaluates workflow preconditions with modified step outputs (read-only).
26
+ * Returns a result for each step in definition order.
27
+ * @param run The run whose evidence to replay.
28
+ * @param definition The workflow definition providing step order and preconditions.
29
+ * @param overrides Output field overrides to inject before re-evaluation.
30
+ */
31
+ export declare function replayRun(run: RunRecord, definition: WorkflowDefinition, overrides: ReplayOverride[]): ReplayStepResult[];
32
+ /**
33
+ * Persists a replay result to the store and returns the assigned replay ID.
34
+ * Extracted for testability — tests inject a mock ReplayStore.
35
+ */
36
+ export declare function saveReplay(store: ReplayStore, runId: string, run: RunRecord, withExprs: string[], results: ReplayStepResult[]): Promise<string>;
37
+ export declare const replayCommand: Command;
38
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/commands/replay.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,sBAAsB,EAAE,OAAO,CAAC;IAChC,uDAAuD;IACvD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAgCD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAW1D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,cAAc,EAAE,GAC1B,gBAAgB,EAAE,CAkCpB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,SAAS,EACd,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,eAAO,MAAM,aAAa,SA0EtB,CAAC"}
@@ -0,0 +1,173 @@
1
+ // replay command — re-evaluates preconditions with modified step outputs (read-only simulation).
2
+ import { Command } from 'commander';
3
+ import { checkPreconditions } from '@sensigo/realm';
4
+ import { formatPrecondColumn } from './replay-format.js';
5
+ /** Parses a literal string into a typed value (number, boolean, or string). */
6
+ function parseLiteralValue(raw) {
7
+ const t = raw.trim();
8
+ if (t === 'true')
9
+ return true;
10
+ if (t === 'false')
11
+ return false;
12
+ const n = Number(t);
13
+ if (!Number.isNaN(n) && t !== '')
14
+ return n;
15
+ if ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'"))) {
16
+ return t.slice(1, -1);
17
+ }
18
+ return t;
19
+ }
20
+ /**
21
+ * Sets a value at a dot-separated path within an object, creating
22
+ * intermediate objects as needed.
23
+ */
24
+ function deepSet(obj, path, value) {
25
+ const parts = path.split('.');
26
+ let current = obj;
27
+ for (let i = 0; i < parts.length - 1; i++) {
28
+ const part = parts[i];
29
+ if (typeof current[part] !== 'object' || current[part] === null) {
30
+ current[part] = {};
31
+ }
32
+ current = current[part];
33
+ }
34
+ current[parts.at(-1)] = value;
35
+ }
36
+ /**
37
+ * Parses a --with override expression of the form "step.field=value".
38
+ * @throws Error if the expression is missing '.' or '='.
39
+ */
40
+ export function parseOverride(expr) {
41
+ const eqIdx = expr.indexOf('=');
42
+ if (eqIdx === -1)
43
+ throw new Error(`Invalid override '${expr}': missing '='`);
44
+ const left = expr.slice(0, eqIdx);
45
+ const right = expr.slice(eqIdx + 1);
46
+ const dotIdx = left.indexOf('.');
47
+ if (dotIdx === -1)
48
+ throw new Error(`Invalid override '${expr}': missing '.'`);
49
+ const step = left.slice(0, dotIdx);
50
+ const field = left.slice(dotIdx + 1);
51
+ const value = parseLiteralValue(right);
52
+ return { step, field, value };
53
+ }
54
+ /**
55
+ * Re-evaluates workflow preconditions with modified step outputs (read-only).
56
+ * Returns a result for each step in definition order.
57
+ * @param run The run whose evidence to replay.
58
+ * @param definition The workflow definition providing step order and preconditions.
59
+ * @param overrides Output field overrides to inject before re-evaluation.
60
+ */
61
+ export function replayRun(run, definition, overrides) {
62
+ // Build evidence map from run (last non-gate_response snapshot per step_id).
63
+ const evidenceByStep = {};
64
+ for (const snap of run.evidence) {
65
+ if (snap.kind === 'gate_response')
66
+ continue;
67
+ evidenceByStep[snap.step_id] = snap.output_summary;
68
+ }
69
+ // Build replay evidence as a deep clone, then apply overrides.
70
+ // structuredClone prevents nested object mutations from affecting the original evidence map.
71
+ const replayEvidenceByStep = {};
72
+ for (const [stepId, output] of Object.entries(evidenceByStep)) {
73
+ replayEvidenceByStep[stepId] = structuredClone(output);
74
+ }
75
+ for (const override of overrides) {
76
+ if (replayEvidenceByStep[override.step] === undefined) {
77
+ replayEvidenceByStep[override.step] = {};
78
+ }
79
+ deepSet(replayEvidenceByStep[override.step], override.field, override.value);
80
+ }
81
+ // Evaluate preconditions for each step in definition order.
82
+ return Object.entries(definition.steps).map(([stepId, step]) => {
83
+ const preconditions = step.preconditions ?? [];
84
+ const originalPass = checkPreconditions(preconditions, evidenceByStep) === null;
85
+ const replayPass = checkPreconditions(preconditions, replayEvidenceByStep) === null;
86
+ return {
87
+ step_id: stepId,
88
+ preconditions_original: originalPass,
89
+ preconditions_replay: replayPass,
90
+ changed: originalPass !== replayPass,
91
+ has_preconditions: preconditions.length > 0,
92
+ };
93
+ });
94
+ }
95
+ /**
96
+ * Persists a replay result to the store and returns the assigned replay ID.
97
+ * Extracted for testability — tests inject a mock ReplayStore.
98
+ */
99
+ export async function saveReplay(store, runId, run, withExprs, results) {
100
+ const record = await store.save({
101
+ origin_run_id: runId,
102
+ workflow_id: run.workflow_id,
103
+ overrides: withExprs,
104
+ results,
105
+ });
106
+ return record.id;
107
+ }
108
+ export const replayCommand = new Command('replay')
109
+ .argument('<run-id>', 'ID of the completed run to replay')
110
+ .option('--with <override...>', 'Override a step output field: step.field=value')
111
+ .option('--save', 'Persist the replay result and print the replay ID')
112
+ .description('Re-evaluate preconditions with modified step outputs (read-only)')
113
+ .action(async (runId, opts) => {
114
+ const { JsonFileStore, JsonWorkflowStore } = await import('@sensigo/realm');
115
+ const runStore = new JsonFileStore();
116
+ const workflowStore = new JsonWorkflowStore();
117
+ let run;
118
+ try {
119
+ run = await runStore.get(runId);
120
+ }
121
+ catch (err) {
122
+ console.error(err instanceof Error ? err.message : String(err));
123
+ process.exit(1);
124
+ }
125
+ if (!run.terminal_state) {
126
+ console.warn(`Warning: run ${runId} is not in a terminal state. Partial replay.`);
127
+ }
128
+ let definition;
129
+ try {
130
+ definition = await workflowStore.get(run.workflow_id);
131
+ }
132
+ catch (err) {
133
+ console.error(err instanceof Error ? err.message : String(err));
134
+ process.exit(1);
135
+ }
136
+ const withExprs = opts['with'] ?? [];
137
+ const overrides = [];
138
+ for (const expr of withExprs) {
139
+ try {
140
+ overrides.push(parseOverride(expr));
141
+ }
142
+ catch (err) {
143
+ console.error(err instanceof Error ? err.message : String(err));
144
+ process.exit(1);
145
+ }
146
+ }
147
+ const results = replayRun(run, definition, overrides);
148
+ console.log(`Replay of ${runId}`);
149
+ for (const override of overrides) {
150
+ console.log(`Override: ${override.step}.${override.field} = ${String(override.value)}`);
151
+ }
152
+ console.log('');
153
+ const col1 = 22;
154
+ const col2 = 38;
155
+ const header = `${'Step'.padEnd(col1)} ${'Preconditions (original \u2192 replay)'.padEnd(col2)} Changed?`;
156
+ const sep = `${'\u2500'.repeat(col1 - 1)} ${'\u2500'.repeat(col2 - 1)} ${'\u2500'.repeat(8)}`;
157
+ console.log(header);
158
+ console.log(sep);
159
+ for (const row of results) {
160
+ const step = definition.steps[row.step_id];
161
+ const hasPreconditions = (step?.preconditions ?? []).length > 0;
162
+ const precondCol = formatPrecondColumn(row.preconditions_original, row.preconditions_replay, hasPreconditions);
163
+ const changedCol = row.changed ? 'YES \u26A0' : 'no';
164
+ console.log(`${row.step_id.padEnd(col1)} ${precondCol.padEnd(col2)} ${changedCol}`);
165
+ }
166
+ if (opts.save) {
167
+ const { JsonFileReplayStore } = await import('../store/replay-store.js');
168
+ const replayStore = new JsonFileReplayStore();
169
+ const replayId = await saveReplay(replayStore, runId, run, withExprs, results);
170
+ console.log(`\nSaved replay: ${replayId}`);
171
+ }
172
+ });
173
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/commands/replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { Command } from 'commander';
2
+ import type { RunStore } from '@sensigo/realm';
3
+ import type { WorkflowRegistrar } from '@sensigo/realm';
4
+ /**
5
+ * Submits a human choice response for a gate-waiting run.
6
+ * @param runId The run awaiting a gate response.
7
+ * @param options `gate` is the gate_id; `choice` is the selected option.
8
+ * @param runStore Store holding run records.
9
+ * @param workflowStore Registrar for workflow definitions.
10
+ * @returns The choice submitted and the new run state after the gate advances.
11
+ */
12
+ export declare function respondToGate(runId: string, options: {
13
+ gate: string;
14
+ choice: string;
15
+ }, runStore: RunStore, workflowStore: WorkflowRegistrar): Promise<{
16
+ choice: string;
17
+ newState: string;
18
+ }>;
19
+ export declare const respondCommand: Command;
20
+ //# sourceMappingURL=respond.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"respond.d.ts","sourceRoot":"","sources":["../../src/commands/respond.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACzC,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,iBAAiB,GAC/B,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB/C;AAED,eAAO,MAAM,cAAc,SAgBvB,CAAC"}
@@ -0,0 +1,49 @@
1
+ // respond command — submits a human gate response for a gate-waiting run.
2
+ import { Command } from 'commander';
3
+ import { WorkflowError, submitHumanResponse } from '@sensigo/realm';
4
+ /**
5
+ * Submits a human choice response for a gate-waiting run.
6
+ * @param runId The run awaiting a gate response.
7
+ * @param options `gate` is the gate_id; `choice` is the selected option.
8
+ * @param runStore Store holding run records.
9
+ * @param workflowStore Registrar for workflow definitions.
10
+ * @returns The choice submitted and the new run state after the gate advances.
11
+ */
12
+ export async function respondToGate(runId, options, runStore, workflowStore) {
13
+ const run = await runStore.get(runId);
14
+ const workflow = await workflowStore.get(run.workflow_id);
15
+ const result = await submitHumanResponse(runStore, workflow, {
16
+ runId,
17
+ gateId: options.gate,
18
+ choice: options.choice,
19
+ });
20
+ if (result.status !== 'ok') {
21
+ throw new WorkflowError(result.errors[0] ?? 'Gate response failed', {
22
+ code: 'STATE_BLOCKED',
23
+ category: 'STATE',
24
+ agentAction: 'report_to_user',
25
+ retryable: false,
26
+ });
27
+ }
28
+ const updatedRun = await runStore.get(runId);
29
+ return { choice: options.choice, newState: updatedRun.run_phase };
30
+ }
31
+ export const respondCommand = new Command('respond')
32
+ .description('Submit a human gate response to advance a gate-waiting run')
33
+ .argument('<run-id>', 'ID of the run waiting at a gate')
34
+ .requiredOption('--gate <gate-id>', 'Gate ID from the confirm_required response')
35
+ .requiredOption('--choice <choice>', 'The choice to submit (e.g. approve, reject)')
36
+ .action(async (runId, opts) => {
37
+ const { JsonFileStore, JsonWorkflowStore } = await import('@sensigo/realm');
38
+ const runStore = new JsonFileStore();
39
+ const workflowStore = new JsonWorkflowStore();
40
+ try {
41
+ const { choice, newState } = await respondToGate(runId, opts, runStore, workflowStore);
42
+ console.log(`Responded: ${runId} | choice '${choice}' | new state '${newState}'`);
43
+ }
44
+ catch (err) {
45
+ console.error(err instanceof Error ? err.message : String(err));
46
+ process.exit(1);
47
+ }
48
+ });
49
+ //# sourceMappingURL=respond.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"respond.js","sourceRoot":"","sources":["../../src/commands/respond.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAEpE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa,EACb,OAAyC,EACzC,QAAkB,EAClB,aAAgC;IAEhC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE;QAC3D,KAAK;QACL,MAAM,EAAE,OAAO,CAAC,IAAI;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,sBAAsB,EAAE;YAClE,IAAI,EAAE,eAAe;YACrB,QAAQ,EAAE,OAAO;YACjB,WAAW,EAAE,gBAAgB;YAC7B,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,4DAA4D,CAAC;KACzE,QAAQ,CAAC,UAAU,EAAE,iCAAiC,CAAC;KACvD,cAAc,CAAC,kBAAkB,EAAE,4CAA4C,CAAC;KAChF,cAAc,CAAC,mBAAmB,EAAE,6CAA6C,CAAC;KAClF,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,IAAsC,EAAE,EAAE;IACtE,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IACrC,MAAM,aAAa,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QACvF,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,cAAc,MAAM,kBAAkB,QAAQ,GAAG,CAAC,CAAC;IACpF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { Command } from 'commander';
2
+ import type { RunStore } from '@sensigo/realm';
3
+ import type { WorkflowRegistrar } from '@sensigo/realm';
4
+ /**
5
+ * Removes `stepName` from `failed_steps` so the DAG engine can re-evaluate its
6
+ * eligibility on the next execute-step call.
7
+ *
8
+ * @param runId The run to resume.
9
+ * @param stepName The failed step to re-enable.
10
+ * @param runStore Store holding run records.
11
+ * @param workflowStore Registrar for workflow definitions.
12
+ */
13
+ export declare function resumeRun(runId: string, stepName: string, runStore: RunStore, workflowStore: WorkflowRegistrar): Promise<void>;
14
+ export declare const resumeCommand: Command;
15
+ //# sourceMappingURL=resume.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../src/commands/resume.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIxD;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,iBAAiB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAuCf;AAED,eAAO,MAAM,aAAa,SAetB,CAAC"}