@loopstack/cli 0.17.0 → 0.18.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 (125) hide show
  1. package/README.md +14 -10
  2. package/dist/commands/answer.d.ts +3 -0
  3. package/dist/commands/answer.d.ts.map +1 -0
  4. package/dist/commands/answer.js +82 -0
  5. package/dist/commands/answer.js.map +1 -0
  6. package/dist/commands/attach.d.ts +3 -0
  7. package/dist/commands/attach.d.ts.map +1 -0
  8. package/dist/commands/attach.js +103 -0
  9. package/dist/commands/attach.js.map +1 -0
  10. package/dist/commands/run.d.ts.map +1 -1
  11. package/dist/commands/run.js +38 -13
  12. package/dist/commands/run.js.map +1 -1
  13. package/dist/commands/runs.d.ts.map +1 -1
  14. package/dist/commands/runs.js +67 -69
  15. package/dist/commands/runs.js.map +1 -1
  16. package/dist/commands/watch.d.ts.map +1 -1
  17. package/dist/commands/watch.js +3 -1
  18. package/dist/commands/watch.js.map +1 -1
  19. package/dist/hitl/discovery.d.ts +15 -7
  20. package/dist/hitl/discovery.d.ts.map +1 -1
  21. package/dist/hitl/discovery.js +85 -28
  22. package/dist/hitl/discovery.js.map +1 -1
  23. package/dist/hitl/idle-handler.d.ts +0 -1
  24. package/dist/hitl/idle-handler.d.ts.map +1 -1
  25. package/dist/hitl/idle-handler.js +49 -17
  26. package/dist/hitl/idle-handler.js.map +1 -1
  27. package/dist/hitl/pending.d.ts +16 -0
  28. package/dist/hitl/pending.d.ts.map +1 -0
  29. package/dist/hitl/pending.js +45 -0
  30. package/dist/hitl/pending.js.map +1 -0
  31. package/dist/hitl/prompt.d.ts +5 -8
  32. package/dist/hitl/prompt.d.ts.map +1 -1
  33. package/dist/hitl/prompt.js +47 -105
  34. package/dist/hitl/prompt.js.map +1 -1
  35. package/dist/main.js +4 -0
  36. package/dist/main.js.map +1 -1
  37. package/dist/output/format.d.ts +1 -1
  38. package/dist/output/format.d.ts.map +1 -1
  39. package/dist/output/format.js +16 -5
  40. package/dist/output/format.js.map +1 -1
  41. package/dist/run/documents.d.ts +13 -1
  42. package/dist/run/documents.d.ts.map +1 -1
  43. package/dist/run/documents.js +82 -22
  44. package/dist/run/documents.js.map +1 -1
  45. package/dist/run/follow.d.ts +6 -2
  46. package/dist/run/follow.d.ts.map +1 -1
  47. package/dist/run/follow.js +61 -9
  48. package/dist/run/follow.js.map +1 -1
  49. package/dist/run/retry.d.ts +5 -0
  50. package/dist/run/retry.d.ts.map +1 -0
  51. package/dist/run/retry.js +59 -0
  52. package/dist/run/retry.js.map +1 -0
  53. package/dist/run/trail.d.ts +17 -0
  54. package/dist/run/trail.d.ts.map +1 -0
  55. package/dist/run/trail.js +42 -0
  56. package/dist/run/trail.js.map +1 -0
  57. package/dist/widgets/collect/form.collect.d.ts +7 -0
  58. package/dist/widgets/collect/form.collect.d.ts.map +1 -0
  59. package/dist/widgets/collect/form.collect.js +71 -0
  60. package/dist/widgets/collect/form.collect.js.map +1 -0
  61. package/dist/widgets/collect/prompts.collect.d.ts +5 -0
  62. package/dist/widgets/collect/prompts.collect.d.ts.map +1 -0
  63. package/dist/widgets/collect/prompts.collect.js +38 -0
  64. package/dist/widgets/collect/prompts.collect.js.map +1 -0
  65. package/dist/widgets/collect/secret-input.collect.d.ts +3 -0
  66. package/dist/widgets/collect/secret-input.collect.d.ts.map +1 -0
  67. package/dist/widgets/collect/secret-input.collect.js +47 -0
  68. package/dist/widgets/collect/secret-input.collect.js.map +1 -0
  69. package/dist/widgets/collect/transition.d.ts +3 -0
  70. package/dist/widgets/collect/transition.d.ts.map +1 -0
  71. package/dist/widgets/collect/transition.js +5 -0
  72. package/dist/widgets/collect/transition.js.map +1 -0
  73. package/dist/widgets/collect/workflow.collect.d.ts +4 -0
  74. package/dist/widgets/collect/workflow.collect.d.ts.map +1 -0
  75. package/dist/widgets/collect/workflow.collect.js +24 -0
  76. package/dist/widgets/collect/workflow.collect.js.map +1 -0
  77. package/dist/widgets/document/form.widget.d.ts +3 -0
  78. package/dist/widgets/document/form.widget.d.ts.map +1 -0
  79. package/dist/widgets/document/form.widget.js +34 -0
  80. package/dist/widgets/document/form.widget.js.map +1 -0
  81. package/dist/widgets/document/json.widget.d.ts +3 -0
  82. package/dist/widgets/document/json.widget.d.ts.map +1 -0
  83. package/dist/widgets/document/json.widget.js +17 -0
  84. package/dist/widgets/document/json.widget.js.map +1 -0
  85. package/dist/widgets/document/link.widget.d.ts +3 -0
  86. package/dist/widgets/document/link.widget.d.ts.map +1 -0
  87. package/dist/widgets/document/link.widget.js +9 -0
  88. package/dist/widgets/document/link.widget.js.map +1 -0
  89. package/dist/widgets/document/llm-message.widget.d.ts +3 -0
  90. package/dist/widgets/document/llm-message.widget.d.ts.map +1 -0
  91. package/dist/widgets/document/llm-message.widget.js +67 -0
  92. package/dist/widgets/document/llm-message.widget.js.map +1 -0
  93. package/dist/widgets/document/message.widget.d.ts +5 -0
  94. package/dist/widgets/document/message.widget.d.ts.map +1 -0
  95. package/dist/widgets/document/message.widget.js +35 -0
  96. package/dist/widgets/document/message.widget.js.map +1 -0
  97. package/dist/widgets/document/oauth-prompt.widget.d.ts +4 -0
  98. package/dist/widgets/document/oauth-prompt.widget.d.ts.map +1 -0
  99. package/dist/widgets/document/oauth-prompt.widget.js +22 -0
  100. package/dist/widgets/document/oauth-prompt.widget.js.map +1 -0
  101. package/dist/widgets/document/secret-request.widget.d.ts +3 -0
  102. package/dist/widgets/document/secret-request.widget.d.ts.map +1 -0
  103. package/dist/widgets/document/secret-request.widget.js +9 -0
  104. package/dist/widgets/document/secret-request.widget.js.map +1 -0
  105. package/dist/{hitl → widgets}/editor.d.ts +0 -1
  106. package/dist/widgets/editor.d.ts.map +1 -0
  107. package/dist/{hitl → widgets}/editor.js +0 -13
  108. package/dist/widgets/editor.js.map +1 -0
  109. package/dist/widgets/field/field-widgets.d.ts +6 -0
  110. package/dist/widgets/field/field-widgets.d.ts.map +1 -0
  111. package/dist/widgets/field/field-widgets.js +64 -0
  112. package/dist/widgets/field/field-widgets.js.map +1 -0
  113. package/dist/widgets/registry.d.ts +6 -0
  114. package/dist/widgets/registry.d.ts.map +1 -0
  115. package/dist/widgets/registry.js +45 -0
  116. package/dist/widgets/registry.js.map +1 -0
  117. package/dist/widgets/types.d.ts +44 -0
  118. package/dist/widgets/types.d.ts.map +1 -0
  119. package/dist/widgets/types.js +2 -0
  120. package/dist/widgets/types.js.map +1 -0
  121. package/fixtures/app/CLAUDE.md +15 -1
  122. package/fixtures/app/src/main.ts +3 -0
  123. package/package.json +3 -3
  124. package/dist/hitl/editor.d.ts.map +0 -1
  125. package/dist/hitl/editor.js.map +0 -1
@@ -0,0 +1,67 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdirSync, writeFileSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import pc from 'picocolors';
6
+ const MAX_TOOL_RESULT_LINES = 8;
7
+ export const llmMessageWidget = (content, ctx, out) => {
8
+ const blocks = Array.isArray(content.blocks) ? content.blocks : [];
9
+ const streamed = typeof content.id === 'string' && content.id.length > 0 && !!ctx.streamedMessageIds?.has(content.id);
10
+ if (!streamed) {
11
+ const text = typeof content.text === 'string' && content.text.trim()
12
+ ? content.text
13
+ : blocks
14
+ .filter((block) => block.type === 'text' && typeof block.text === 'string')
15
+ .map((block) => block.text)
16
+ .join('\n');
17
+ if (text.trim()) {
18
+ const role = typeof content.role === 'string' ? `${pc.dim(`${content.role}:`)}\n` : '';
19
+ out.block(`${role}${text}`);
20
+ }
21
+ }
22
+ for (const block of blocks) {
23
+ if (block.type === 'tool_call') {
24
+ if (typeof block.id === 'string' && ctx.streamedToolCallIds?.has(block.id))
25
+ continue;
26
+ out.line(pc.dim(`⚒ ${block.name ?? 'tool'} ${JSON.stringify(block.args ?? {})}`));
27
+ }
28
+ else if (block.type === 'tool_result') {
29
+ const mark = block.isError ? pc.red('✗') : '→';
30
+ out.line(pc.dim(` ${mark} ${truncateToolResult(formatToolResult(block.content))}`));
31
+ }
32
+ }
33
+ };
34
+ function truncateToolResult(text) {
35
+ const lines = text.split('\n');
36
+ if (lines.length <= MAX_TOOL_RESULT_LINES)
37
+ return text;
38
+ const preview = lines.slice(0, MAX_TOOL_RESULT_LINES).join('\n');
39
+ const hidden = lines.length - MAX_TOOL_RESULT_LINES;
40
+ const file = writeFullResult(text);
41
+ const view = file ? ` — full result: ${file}` : '';
42
+ return `${preview}\n… (+${hidden} lines${view})`;
43
+ }
44
+ function writeFullResult(text) {
45
+ try {
46
+ const dir = join(tmpdir(), 'loopstack-cli');
47
+ mkdirSync(dir, { recursive: true });
48
+ const file = join(dir, `tool-result-${randomUUID()}.txt`);
49
+ writeFileSync(file, text);
50
+ return file;
51
+ }
52
+ catch {
53
+ return undefined;
54
+ }
55
+ }
56
+ function formatToolResult(content) {
57
+ if (typeof content !== 'string')
58
+ return JSON.stringify(content);
59
+ try {
60
+ const parsed = JSON.parse(content);
61
+ return typeof parsed === 'string' ? parsed : content;
62
+ }
63
+ catch {
64
+ return content;
65
+ }
66
+ }
67
+ //# sourceMappingURL=llm-message.widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-message.widget.js","sourceRoot":"","sources":["../../../src/widgets/document/llm-message.widget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { DocumentWidget } from '../types.js';
2
+ export declare const messageWidget: DocumentWidget;
3
+ export declare const markdownWidget: DocumentWidget;
4
+ export declare const errorWidget: DocumentWidget;
5
+ //# sourceMappingURL=message.widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.widget.d.ts","sourceRoot":"","sources":["../../../src/widgets/document/message.widget.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMlD,eAAO,MAAM,aAAa,EAAE,cAc3B,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,cAI5B,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,cAIzB,CAAC"}
@@ -0,0 +1,35 @@
1
+ import pc from 'picocolors';
2
+ export const messageWidget = (content, ctx, out) => {
3
+ const text = typeof content.text === 'string'
4
+ ? content.text
5
+ : typeof content.markdown === 'string'
6
+ ? content.markdown
7
+ : undefined;
8
+ if (!text?.trim())
9
+ return;
10
+ if (typeof content.role === 'string') {
11
+ out.block(`${pc.dim(`${content.role}:`)}\n${text}`);
12
+ }
13
+ else {
14
+ out.block(`${pc.dim(`document: ${ctx.documentName}`)}\n${indent(text)}`);
15
+ }
16
+ };
17
+ export const markdownWidget = (content, ctx, out) => {
18
+ const markdown = typeof content.markdown === 'string' ? content.markdown : undefined;
19
+ if (!markdown?.trim())
20
+ return;
21
+ out.block(`${pc.dim(`document: ${ctx.documentName}`)}\n${indent(markdown)}`);
22
+ };
23
+ export const errorWidget = (content, ctx, out) => {
24
+ const error = typeof content.error === 'string' ? content.error : undefined;
25
+ if (!error?.trim())
26
+ return;
27
+ out.block(`${pc.dim(`document: ${ctx.documentName}`)}\n${indent(pc.red(error))}`);
28
+ };
29
+ function indent(text) {
30
+ return text
31
+ .split('\n')
32
+ .map((line) => ` ${line}`)
33
+ .join('\n');
34
+ }
35
+ //# sourceMappingURL=message.widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.widget.js","sourceRoot":"","sources":["../../../src/widgets/document/message.widget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAO5B,MAAM,CAAC,MAAM,aAAa,GAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACjE,MAAM,IAAI,GACR,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;QAC9B,CAAC,CAAC,OAAO,CAAC,IAAI;QACd,CAAC,CAAC,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;YACpC,CAAC,CAAC,OAAO,CAAC,QAAQ;YAClB,CAAC,CAAC,SAAS,CAAC;IAClB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE;QAAE,OAAO;IAE1B,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,YAAY,EAAE,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC,CAAC;AAGF,MAAM,CAAC,MAAM,cAAc,GAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAClE,MAAM,QAAQ,GAAG,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE;QAAE,OAAO;IAC9B,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,YAAY,EAAE,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC,CAAC;AAGF,MAAM,CAAC,MAAM,WAAW,GAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAC/D,MAAM,KAAK,GAAG,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;QAAE,OAAO;IAC3B,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,YAAY,EAAE,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AACpF,CAAC,CAAC;AAEF,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAO,IAAI;SACR,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;SAC1B,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { DocumentWidget } from '../types.js';
2
+ export declare const oauthPromptWidget: DocumentWidget;
3
+ export declare function oauthHandoff(content: Record<string, unknown>): string | undefined;
4
+ //# sourceMappingURL=oauth-prompt.widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-prompt.widget.d.ts","sourceRoot":"","sources":["../../../src/widgets/document/oauth-prompt.widget.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAUlD,eAAO,MAAM,iBAAiB,EAAE,cAY/B,CAAC;AAOF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAKjF"}
@@ -0,0 +1,22 @@
1
+ import pc from 'picocolors';
2
+ export const oauthPromptWidget = (content, _ctx, out) => {
3
+ const provider = typeof content.provider === 'string' ? content.provider : 'oauth';
4
+ if (content.status === 'success') {
5
+ const message = typeof content.message === 'string' ? content.message : 'Successfully connected.';
6
+ out.block(`${pc.green('✓')} ${provider} connected — ${message}`);
7
+ return;
8
+ }
9
+ const authUrl = typeof content.authUrl === 'string' ? content.authUrl : undefined;
10
+ if (!authUrl)
11
+ return;
12
+ out.block(`⧉ sign in with ${provider}: ${authUrl}`);
13
+ };
14
+ export function oauthHandoff(content) {
15
+ if (content.status === 'success')
16
+ return undefined;
17
+ if (typeof content.authUrl !== 'string')
18
+ return undefined;
19
+ const provider = typeof content.provider === 'string' ? content.provider : 'oauth';
20
+ return `waiting for browser sign-in (${provider}) — open the sign-in link above`;
21
+ }
22
+ //# sourceMappingURL=oauth-prompt.widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-prompt.widget.js","sourceRoot":"","sources":["../../../src/widgets/document/oauth-prompt.widget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAW5B,MAAM,CAAC,MAAM,iBAAiB,GAAmB,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;IACtE,MAAM,QAAQ,GAAG,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;IAEnF,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;QAClG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,QAAQ,gBAAgB,OAAO,EAAE,CAAC,CAAC;QACjE,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAClF,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,GAAG,CAAC,KAAK,CAAC,kBAAkB,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC;AACtD,CAAC,CAAC;AAOF,MAAM,UAAU,YAAY,CAAC,OAAgC;IAC3D,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACnD,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,QAAQ,GAAG,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;IACnF,OAAO,gCAAgC,QAAQ,iCAAiC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { DocumentWidget } from '../types.js';
2
+ export declare const secretRequestWidget: DocumentWidget;
3
+ //# sourceMappingURL=secret-request.widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-request.widget.d.ts","sourceRoot":"","sources":["../../../src/widgets/document/secret-request.widget.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOlD,eAAO,MAAM,mBAAmB,EAAE,cAKjC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import pc from 'picocolors';
2
+ export const secretRequestWidget = (content, ctx, out) => {
3
+ const variables = Array.isArray(content.variables) ? content.variables : [];
4
+ const keys = variables.map((variable) => variable.key).filter((key) => typeof key === 'string');
5
+ if (keys.length === 0)
6
+ return;
7
+ out.block(`${pc.dim(`document: ${ctx.documentName}`)}\n requested secrets: ${keys.join(', ')}`);
8
+ };
9
+ //# sourceMappingURL=secret-request.widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-request.widget.js","sourceRoot":"","sources":["../../../src/widgets/document/secret-request.widget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAQ5B,MAAM,CAAC,MAAM,mBAAmB,GAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACvE,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAE,OAAO,CAAC,SAAiC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrG,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC;IAC/G,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC9B,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,YAAY,EAAE,CAAC,0BAA0B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACnG,CAAC,CAAC"}
@@ -1,4 +1,3 @@
1
1
  export declare function buildFormSkeleton(content: unknown, schema?: Record<string, unknown>): Record<string, unknown>;
2
- export declare function describeFormFields(schema?: Record<string, unknown>): string[];
3
2
  export declare function editPayloadInEditor(initial: Record<string, unknown>, out: NodeJS.WritableStream): unknown;
4
3
  //# sourceMappingURL=editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/widgets/editor.ts"],"names":[],"mappings":"AAiCA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAS7G;AAQD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,OAAO,CAqBzG"}
@@ -32,19 +32,6 @@ export function buildFormSkeleton(content, schema) {
32
32
  }
33
33
  return {};
34
34
  }
35
- export function describeFormFields(schema) {
36
- const typed = schema;
37
- if (typed?.type !== 'object' || !typed.properties)
38
- return [];
39
- const required = new Set(typed.required ?? []);
40
- return Object.entries(typed.properties).map(([key, property]) => {
41
- const parts = [property.type ?? 'any'];
42
- if (required.has(key))
43
- parts.push('required');
44
- const description = property.description ? ` — ${property.description}` : '';
45
- return ` ${key} (${parts.join(', ')})${description}`;
46
- });
47
- }
48
35
  export function editPayloadInEditor(initial, out) {
49
36
  const editor = process.env.EDITOR || process.env.VISUAL || 'vi';
50
37
  const dir = mkdtempSync(join(tmpdir(), 'loopstack-'));
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/widgets/editor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { FieldWidget } from '../types.js';
2
+ export declare function resolveFieldWidget(widgetName: string | undefined): FieldWidget;
3
+ export declare function formatEntry(key: string, value: unknown, indent: number): string[];
4
+ export declare function formatEntries(obj: Record<string, unknown>, indent: number): string[];
5
+ export declare function stripCodeFences(text: string): string;
6
+ //# sourceMappingURL=field-widgets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-widgets.d.ts","sourceRoot":"","sources":["../../../src/widgets/field/field-widgets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAqC/C,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAG9E;AAWD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBjF;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpF;AAQD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGpD"}
@@ -0,0 +1,64 @@
1
+ import pc from 'picocolors';
2
+ const defaultField = (key, value) => formatEntry(key, value, 0);
3
+ const markdownView = (key, value) => labeledBlock(key, typeof value === 'string' ? value : JSON.stringify(value));
4
+ const codeView = (key, value) => labeledBlock(key, typeof value === 'string' ? stripCodeFences(value) : JSON.stringify(value));
5
+ const jsonField = (key, value) => labeledBlock(key, JSON.stringify(value, null, 2));
6
+ const FIELD_WIDGETS = new Map([
7
+ ['input', defaultField],
8
+ ['textarea', defaultField],
9
+ ['number', defaultField],
10
+ ['checkbox', defaultField],
11
+ ['radio', defaultField],
12
+ ['switch', defaultField],
13
+ ['select', defaultField],
14
+ ['slider', defaultField],
15
+ ['markdown-view', markdownView],
16
+ ['code-view', codeView],
17
+ ]);
18
+ export function resolveFieldWidget(widgetName) {
19
+ if (!widgetName)
20
+ return defaultField;
21
+ return FIELD_WIDGETS.get(widgetName) ?? jsonField;
22
+ }
23
+ function labeledBlock(key, text) {
24
+ return [pc.dim(`${key}:`), ...text.split('\n')];
25
+ }
26
+ export function formatEntry(key, value, indent) {
27
+ const pad = ' '.repeat(indent);
28
+ if (value == null)
29
+ return [];
30
+ if (Array.isArray(value)) {
31
+ const lines = [`${pad}${pc.dim(`${key}:`)}`];
32
+ for (const item of value) {
33
+ if (item && typeof item === 'object' && !Array.isArray(item)) {
34
+ lines.push(`${pad} -`);
35
+ lines.push(...formatEntries(item, indent + 2));
36
+ }
37
+ else {
38
+ lines.push(`${pad} - ${formatScalar(item)}`);
39
+ }
40
+ }
41
+ return lines;
42
+ }
43
+ if (typeof value === 'object') {
44
+ return [`${pad}${pc.dim(`${key}:`)}`, ...formatEntries(value, indent + 1)];
45
+ }
46
+ const text = formatScalar(value);
47
+ if (text.includes('\n')) {
48
+ return [`${pad}${pc.dim(`${key}:`)}`, ...text.split('\n').map((line) => `${pad}${line}`)];
49
+ }
50
+ return [`${pad}${pc.dim(`${key}:`)} ${text}`];
51
+ }
52
+ export function formatEntries(obj, indent) {
53
+ return Object.entries(obj).flatMap(([key, value]) => formatEntry(key, value, indent));
54
+ }
55
+ function formatScalar(value) {
56
+ if (typeof value === 'string')
57
+ return stripCodeFences(value);
58
+ return JSON.stringify(value);
59
+ }
60
+ export function stripCodeFences(text) {
61
+ const match = text.trim().match(/^```[^\n]*\n([\s\S]*?)\n?```$/);
62
+ return match ? match[1] : text;
63
+ }
64
+ //# sourceMappingURL=field-widgets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-widgets.js","sourceRoot":"","sources":["../../../src/widgets/field/field-widgets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { CollectWidget, DocumentWidget } from './types.js';
2
+ export declare function resolveDocumentWidget(widgetName: string | undefined): DocumentWidget | undefined;
3
+ export declare function resolveCollectWidget(widgetName: string | undefined): CollectWidget | undefined;
4
+ export declare function isCollectable(widgetName: string | undefined): boolean;
5
+ export declare function resolveHandoff(widgetName: string | undefined, content: Record<string, unknown>): string | undefined;
6
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/widgets/registry.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAa,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAqC3E,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CAKhG;AAGD,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAE9F;AAGD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAErE;AAGD,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAEnH"}
@@ -0,0 +1,45 @@
1
+ import { collectForm } from './collect/form.collect.js';
2
+ import { collectChoices, collectConfirm, collectText } from './collect/prompts.collect.js';
3
+ import { collectSecretInput } from './collect/secret-input.collect.js';
4
+ import { collectButton, collectPromptInput } from './collect/workflow.collect.js';
5
+ import { formWidget } from './document/form.widget.js';
6
+ import { jsonWidget } from './document/json.widget.js';
7
+ import { linkWidget } from './document/link.widget.js';
8
+ import { llmMessageWidget } from './document/llm-message.widget.js';
9
+ import { errorWidget, markdownWidget, messageWidget } from './document/message.widget.js';
10
+ import { oauthHandoff, oauthPromptWidget } from './document/oauth-prompt.widget.js';
11
+ import { secretRequestWidget } from './document/secret-request.widget.js';
12
+ const WIDGETS = new Map([
13
+ ['llm-message', { render: llmMessageWidget }],
14
+ ['message', { render: messageWidget }],
15
+ ['plain', { render: messageWidget }],
16
+ ['markdown', { render: markdownWidget }],
17
+ ['error', { render: errorWidget }],
18
+ ['link', { render: linkWidget }],
19
+ ['form', { render: formWidget, collect: collectForm }],
20
+ ['secret-input', { render: secretRequestWidget, collect: collectSecretInput }],
21
+ ['oauth-prompt', { render: oauthPromptWidget, handoff: oauthHandoff }],
22
+ ['text-prompt', { collect: collectText }],
23
+ ['confirm-prompt', { collect: collectConfirm }],
24
+ ['choices', { collect: collectChoices }],
25
+ ['prompt-input', { collect: collectPromptInput }],
26
+ ['button', { collect: collectButton }],
27
+ ]);
28
+ export function resolveDocumentWidget(widgetName) {
29
+ if (!widgetName)
30
+ return undefined;
31
+ const entry = WIDGETS.get(widgetName);
32
+ if (entry)
33
+ return entry.render;
34
+ return jsonWidget;
35
+ }
36
+ export function resolveCollectWidget(widgetName) {
37
+ return widgetName ? WIDGETS.get(widgetName)?.collect : undefined;
38
+ }
39
+ export function isCollectable(widgetName) {
40
+ return resolveCollectWidget(widgetName) !== undefined;
41
+ }
42
+ export function resolveHandoff(widgetName, content) {
43
+ return widgetName ? WIDGETS.get(widgetName)?.handoff?.(content) : undefined;
44
+ }
45
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/widgets/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAU1E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAoB;IACzC,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC7C,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACtC,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACpC,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACxC,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAClC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IACtD,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAG9E,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IAGtE,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IACzC,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IAC/C,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IAGxC,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;IACjD,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;CACvC,CAAC,CAAC;AAOH,MAAM,UAAU,qBAAqB,CAAC,UAA8B;IAClE,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IAC/B,OAAO,UAAU,CAAC;AACpB,CAAC;AAGD,MAAM,UAAU,oBAAoB,CAAC,UAA8B;IACjE,OAAO,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACnE,CAAC;AAGD,MAAM,UAAU,aAAa,CAAC,UAA8B;IAC1D,OAAO,oBAAoB,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC;AACxD,CAAC;AAGD,MAAM,UAAU,cAAc,CAAC,UAA8B,EAAE,OAAgC;IAC7F,OAAO,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,44 @@
1
+ export interface WidgetContext {
2
+ documentName: string;
3
+ workflowId: string;
4
+ options?: Record<string, unknown>;
5
+ schema?: Record<string, unknown>;
6
+ streamedMessageIds?: ReadonlySet<string>;
7
+ streamedToolCallIds?: ReadonlySet<string>;
8
+ studioUrl?: (workflowId: string) => string | undefined;
9
+ }
10
+ export interface WidgetOutput {
11
+ block(text: string): void;
12
+ line(text: string): void;
13
+ }
14
+ export type DocumentWidget = (content: Record<string, unknown>, ctx: WidgetContext, out: WidgetOutput) => void;
15
+ export type FieldWidget = (key: string, value: unknown) => string[];
16
+ export interface PromptAnswer {
17
+ transitionId: string;
18
+ payload: unknown;
19
+ }
20
+ export interface CollectHttp {
21
+ get<T = unknown>(path: string): Promise<T>;
22
+ put<T = unknown>(path: string, body?: unknown): Promise<T>;
23
+ }
24
+ export interface CollectContext {
25
+ content: Record<string, unknown>;
26
+ documentName?: string;
27
+ options?: Record<string, unknown>;
28
+ schema?: Record<string, unknown>;
29
+ availableTransitions: string[];
30
+ workspaceId?: string;
31
+ http?: CollectHttp;
32
+ }
33
+ export interface CollectIo {
34
+ ask(query: string): Promise<string>;
35
+ askSecret(query: string): Promise<string>;
36
+ out: NodeJS.WritableStream;
37
+ }
38
+ export type CollectWidget = (ctx: CollectContext, io: CollectIo) => Promise<PromptAnswer | undefined>;
39
+ export interface CliWidget {
40
+ render?: DocumentWidget;
41
+ collect?: CollectWidget;
42
+ handoff?: (content: Record<string, unknown>) => string | undefined;
43
+ }
44
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/widgets/types.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IAErB,UAAU,EAAE,MAAM,CAAC;IAEnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAElC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEjC,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAEzC,mBAAmB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAE1C,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACxD;AAED,MAAM,WAAW,YAAY;IAE3B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,YAAY,KAAK,IAAI,CAAC;AAG/G,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,EAAE,CAAC;AAGpE,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB;AAOD,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3C,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC5D;AAGD,MAAM,WAAW,cAAc;IAE7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAElC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEjC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAE/B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IAExB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEpC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,GAAG,EAAE,MAAM,CAAC,cAAc,CAAC;CAC5B;AAOD,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,SAAS,KAAK,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;AAGtG,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,aAAa,CAAC;IAMxB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;CACpE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/widgets/types.ts"],"names":[],"mappings":""}
@@ -17,12 +17,16 @@ The `loopstack` CLI talks to the running backend (`npm run start:dev`, http://lo
17
17
  loopstack list # what can be run right now
18
18
  loopstack run <workflow> --arg k=v # run it, streamed live; --json for machine-readable output
19
19
  loopstack runs # recent runs, waiting-for-input first
20
- loopstack runs <run-id> --follow # audit trail; reattach to a waiting run and answer prompts
20
+ loopstack runs <run-id> # one run's audit trail (+ pendingPrompt under --json)
21
+ loopstack answer <run-id> --arg k=v # answer a waiting run's prompt non-interactively
22
+ loopstack attach <run-id> # rejoin a run live and answer its prompts interactively
21
23
  loopstack watch --json # NDJSON event firehose while you develop
22
24
  ```
23
25
 
24
26
  Exit codes: `0` completed, `1` failed, `2` connection/config error, `3` waiting for input in a non-interactive shell. After changing code, the dev server reloads automatically — rerun the workflow to verify.
25
27
 
28
+ When a run exits `3`, it parked on a human question. Close the loop instead of stopping: read the question with `loopstack runs <run-id> --json` (the `pendingPrompt` field carries the description, the expected answer schema, and the transition), ask the human for their answer, submit it with `loopstack answer <run-id> --arg key=value`, then re-check `loopstack runs <run-id>` for the outcome. Never invent an answer to a human question yourself.
29
+
26
30
  ## Writing workflows
27
31
 
28
32
  Follow `src/hello/hello.workflow.ts` as the canonical example:
@@ -33,6 +37,16 @@ Follow `src/hello/hello.workflow.ts` as the canonical example:
33
37
  - Documents are classes with `@Document({ schema })` (zod) saved via `this.documentStore.save(SomeDocument, data)` — they are what Studio renders.
34
38
  - Tools are NestJS providers with `@Tool({ name })`, implementing `protected async handle(args, ctx, options?): Promise<ToolEnvelope>`.
35
39
 
40
+ ## Testing
41
+
42
+ Tests are ordinary vitest tests that run the real engine in-process — no backend, no database:
43
+
44
+ - `runWorkflow(MyWorkflow, args, { providers, answers })` from `@loopstack/testing` executes the workflow and returns `{ status, path, result, documents, document(key) }` for assertions. Script HITL input with `answers: { waitTransitionName: payload }`; sub-workflows run inline.
45
+ - `testTool().forTool(MyTool)` unit-tests a tool's `handle()` in isolation.
46
+ - For deterministic LLM/tool regression tests, record a live run (`loopstack run <workflow> --trace`, then `loopstack runs <run-id> --record fixture.json`) and pass `replay: replay('fixture.json')` to `runWorkflow`. Omit `replay` to test against real providers — keep those assertions structural and run them on demand, not in CI.
47
+
48
+ Write workflow tests for every non-trivial workflow you build. Guide: https://loopstack.ai/docs/build/testing
49
+
36
50
  ## Learning more
37
51
 
38
52
  - Docs: https://loopstack.ai/docs — for agents, the full corpus is at https://loopstack.ai/llms.txt (route via titles, fetch what you need)
@@ -3,6 +3,9 @@ import { AppModule } from './app.module';
3
3
 
4
4
  async function bootstrap() {
5
5
  const app = await NestFactory.create(AppModule);
6
+ // Graceful shutdown: on SIGTERM/SIGINT the BullMQ worker finishes in-flight
7
+ // transitions before the process exits, instead of stalling them.
8
+ app.enableShutdownHooks();
6
9
  await app.listen(process.env.PORT ?? 3000);
7
10
  }
8
11
  void bootstrap();
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@loopstack/cli",
3
3
  "displayName": "Loopstack CLI",
4
4
  "description": "Run, trace, and watch Loopstack workflows from the terminal",
5
- "version": "0.17.0",
5
+ "version": "0.18.0",
6
6
  "license": "MIT",
7
7
  "author": {
8
8
  "name": "Jakob Klippel",
@@ -26,8 +26,8 @@
26
26
  "watch": "tsc -p tsconfig.build.json --watch"
27
27
  },
28
28
  "dependencies": {
29
- "@loopstack/client": "^0.37.1",
30
- "@loopstack/contracts": "^0.37.0",
29
+ "@loopstack/client": "^0.38.0",
30
+ "@loopstack/contracts": "^0.38.0",
31
31
  "commander": "^15.0.0",
32
32
  "picocolors": "^1.1.1"
33
33
  },
@@ -1 +0,0 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/hitl/editor.ts"],"names":[],"mappings":"AAiCA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAS7G;AAGD,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAU7E;AAQD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,OAAO,CAqBzG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/hitl/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,YAAY,CAAC;AAS5B,SAAS,UAAU,CAAC,QAA8C;IAChE,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5D,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,QAAQ;YACX,OAAO,EAAE,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS;YACZ,OAAO,CAAC,CAAC;QACX,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC;QACf,KAAK,OAAO;YACV,OAAO,EAAE,CAAC;QACZ,KAAK,QAAQ;YACX,OAAO,EAAE,CAAC;QACZ;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAGD,MAAM,UAAU,iBAAiB,CAAC,OAAgB,EAAE,MAAgC;IAClF,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9E,OAAO,OAAkC,CAAC;IAC5C,CAAC;IACD,MAAM,KAAK,GAAG,MAAoC,CAAC;IACnD,IAAI,KAAK,EAAE,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACjD,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACpH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAGD,MAAM,UAAU,kBAAkB,CAAC,MAAgC;IACjE,MAAM,KAAK,GAAG,MAAoC,CAAC;IACnD,IAAI,KAAK,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC7D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE;QAC9D,MAAM,KAAK,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;QACvC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,OAAO,KAAK,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,WAAW,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAQD,MAAM,UAAU,mBAAmB,CAAC,OAAgC,EAAE,GAA0B;IAC9F,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC;IAChE,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IACtC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAE7D,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACjG,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC1C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/C,IAAI,CAAC,IAAI;gBAAE,OAAO,SAAS,CAAC;YAC5B,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,iBAAiB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAC/G,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC"}