@openclaw/lobster 2026.9.4 → 2026.9.6

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 (367) hide show
  1. package/assets/activity.svg +4 -0
  2. package/assets/icon.png +0 -0
  3. package/dist/index.js +39 -10
  4. package/node_modules/@clawdbot/lobster/README.md +129 -131
  5. package/node_modules/@clawdbot/lobster/VISION.md +15 -238
  6. package/node_modules/@clawdbot/lobster/bin/clawd.invoke.js +2 -15
  7. package/node_modules/@clawdbot/lobster/bin/invoke.js +19 -0
  8. package/node_modules/@clawdbot/lobster/bin/lobster.js +2 -21
  9. package/node_modules/@clawdbot/lobster/bin/openclaw.invoke.js +2 -18
  10. package/node_modules/@clawdbot/lobster/dist/src/abortable_process.js +297 -0
  11. package/node_modules/@clawdbot/lobster/dist/src/abortable_process.js.map +1 -0
  12. package/node_modules/@clawdbot/lobster/dist/src/cli.js +128 -296
  13. package/node_modules/@clawdbot/lobster/dist/src/cli.js.map +1 -1
  14. package/node_modules/@clawdbot/lobster/dist/src/command_tokens.js +81 -0
  15. package/node_modules/@clawdbot/lobster/dist/src/command_tokens.js.map +1 -0
  16. package/node_modules/@clawdbot/lobster/dist/src/commands/commands_list.js.map +1 -1
  17. package/node_modules/@clawdbot/lobster/dist/src/commands/registry.js +2 -0
  18. package/node_modules/@clawdbot/lobster/dist/src/commands/registry.js.map +1 -1
  19. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/approve.js +2 -0
  20. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/approve.js.map +1 -1
  21. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/ask.js +3 -1
  22. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/ask.js.map +1 -1
  23. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/dedupe.js +1 -12
  24. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/dedupe.js.map +1 -1
  25. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/diff_last.js +6 -1
  26. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/diff_last.js.map +1 -1
  27. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/email_triage.js.map +1 -1
  28. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/exec.js +30 -34
  29. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/exec.js.map +1 -1
  30. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/gog_gmail_search.js +12 -25
  31. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/gog_gmail_search.js.map +1 -1
  32. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/gog_gmail_send.js +19 -25
  33. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/gog_gmail_send.js.map +1 -1
  34. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/group_by.js +2 -14
  35. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/group_by.js.map +1 -1
  36. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/head.js.map +1 -1
  37. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/json.js.map +1 -1
  38. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/llm_invoke.js +260 -42
  39. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/llm_invoke.js.map +1 -1
  40. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/map.js +2 -13
  41. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/map.js.map +1 -1
  42. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/openclaw_agent.js +139 -0
  43. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/openclaw_agent.js.map +1 -0
  44. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/openclaw_invoke.js +20 -2
  45. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/openclaw_invoke.js.map +1 -1
  46. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/pick.js.map +1 -1
  47. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/sort.js +4 -21
  48. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/sort.js.map +1 -1
  49. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/state.js +48 -20
  50. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/state.js.map +1 -1
  51. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/table.js.map +1 -1
  52. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/template.js +2 -13
  53. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/template.js.map +1 -1
  54. package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/where.js.map +1 -1
  55. package/node_modules/@clawdbot/lobster/dist/src/commands/workflows/workflows_list.js.map +1 -1
  56. package/node_modules/@clawdbot/lobster/dist/src/commands/workflows/workflows_run.js +0 -18
  57. package/node_modules/@clawdbot/lobster/dist/src/commands/workflows/workflows_run.js.map +1 -1
  58. package/node_modules/@clawdbot/lobster/dist/src/core/cost_tracker.js +45 -3
  59. package/node_modules/@clawdbot/lobster/dist/src/core/cost_tracker.js.map +1 -1
  60. package/node_modules/@clawdbot/lobster/dist/src/core/filters.js.map +1 -1
  61. package/node_modules/@clawdbot/lobster/dist/src/core/llm_accounting.js +304 -0
  62. package/node_modules/@clawdbot/lobster/dist/src/core/llm_accounting.js.map +1 -0
  63. package/node_modules/@clawdbot/lobster/dist/src/core/retry.js.map +1 -1
  64. package/node_modules/@clawdbot/lobster/dist/src/core/tool_runtime.js +147 -21
  65. package/node_modules/@clawdbot/lobster/dist/src/core/tool_runtime.js.map +1 -1
  66. package/node_modules/@clawdbot/lobster/dist/src/core/value_path.js +11 -0
  67. package/node_modules/@clawdbot/lobster/dist/src/core/value_path.js.map +1 -0
  68. package/node_modules/@clawdbot/lobster/dist/src/input_request.js +4 -2
  69. package/node_modules/@clawdbot/lobster/dist/src/input_request.js.map +1 -1
  70. package/node_modules/@clawdbot/lobster/dist/src/parser.js +5 -69
  71. package/node_modules/@clawdbot/lobster/dist/src/parser.js.map +1 -1
  72. package/node_modules/@clawdbot/lobster/dist/src/pipeline_resume_state.js +241 -74
  73. package/node_modules/@clawdbot/lobster/dist/src/pipeline_resume_state.js.map +1 -1
  74. package/node_modules/@clawdbot/lobster/dist/src/read_line.js +52 -7
  75. package/node_modules/@clawdbot/lobster/dist/src/read_line.js.map +1 -1
  76. package/node_modules/@clawdbot/lobster/dist/src/read_response_text.js +86 -0
  77. package/node_modules/@clawdbot/lobster/dist/src/read_response_text.js.map +1 -0
  78. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/index.js +1 -1
  79. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/pr-monitor.js +9 -66
  80. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/pr-monitor.js.map +1 -1
  81. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/read_pr.js +45 -0
  82. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/read_pr.js.map +1 -0
  83. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/snapshot.js +45 -0
  84. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/snapshot.js.map +1 -0
  85. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/stages/pr-view.js +13 -65
  86. package/node_modules/@clawdbot/lobster/dist/src/recipes/github/stages/pr-view.js.map +1 -1
  87. package/node_modules/@clawdbot/lobster/dist/src/recipes/registry.js.map +1 -1
  88. package/node_modules/@clawdbot/lobster/dist/src/renderers/json.js.map +1 -1
  89. package/node_modules/@clawdbot/lobster/dist/src/resume.js.map +1 -1
  90. package/node_modules/@clawdbot/lobster/dist/src/runtime.js +187 -17
  91. package/node_modules/@clawdbot/lobster/dist/src/runtime.js.map +1 -1
  92. package/node_modules/@clawdbot/lobster/dist/src/sdk/Lobster.js +25 -134
  93. package/node_modules/@clawdbot/lobster/dist/src/sdk/Lobster.js.map +1 -1
  94. package/node_modules/@clawdbot/lobster/dist/src/sdk/index.js +1 -1
  95. package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/approve.js +1 -2
  96. package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/approve.js.map +1 -1
  97. package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/diff.js +11 -86
  98. package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/diff.js.map +1 -1
  99. package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/exec.js +20 -96
  100. package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/exec.js.map +1 -1
  101. package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/state.js +8 -106
  102. package/node_modules/@clawdbot/lobster/dist/src/sdk/primitives/state.js.map +1 -1
  103. package/node_modules/@clawdbot/lobster/dist/src/sdk/runtime.js +2 -13
  104. package/node_modules/@clawdbot/lobster/dist/src/sdk/runtime.js.map +1 -1
  105. package/node_modules/@clawdbot/lobster/dist/src/sdk/state_env.js +6 -0
  106. package/node_modules/@clawdbot/lobster/dist/src/sdk/state_env.js.map +1 -0
  107. package/node_modules/@clawdbot/lobster/dist/src/shell.js.map +1 -1
  108. package/node_modules/@clawdbot/lobster/dist/src/state/atomic_file.js +192 -0
  109. package/node_modules/@clawdbot/lobster/dist/src/state/atomic_file.js.map +1 -0
  110. package/node_modules/@clawdbot/lobster/dist/src/state/store.js +550 -136
  111. package/node_modules/@clawdbot/lobster/dist/src/state/store.js.map +1 -1
  112. package/node_modules/@clawdbot/lobster/dist/src/token.js.map +1 -1
  113. package/node_modules/@clawdbot/lobster/dist/src/validation.js.map +1 -1
  114. package/node_modules/@clawdbot/lobster/dist/src/workflows/dry_run.js +262 -0
  115. package/node_modules/@clawdbot/lobster/dist/src/workflows/dry_run.js.map +1 -0
  116. package/node_modules/@clawdbot/lobster/dist/src/workflows/expressions.js +345 -0
  117. package/node_modules/@clawdbot/lobster/dist/src/workflows/expressions.js.map +1 -0
  118. package/node_modules/@clawdbot/lobster/dist/src/workflows/file.js +950 -1285
  119. package/node_modules/@clawdbot/lobster/dist/src/workflows/file.js.map +1 -1
  120. package/node_modules/@clawdbot/lobster/dist/src/workflows/github_pr_monitor.js +20 -90
  121. package/node_modules/@clawdbot/lobster/dist/src/workflows/github_pr_monitor.js.map +1 -1
  122. package/node_modules/@clawdbot/lobster/dist/src/workflows/graph.js +9 -8
  123. package/node_modules/@clawdbot/lobster/dist/src/workflows/graph.js.map +1 -1
  124. package/node_modules/@clawdbot/lobster/dist/src/workflows/load.js +347 -0
  125. package/node_modules/@clawdbot/lobster/dist/src/workflows/load.js.map +1 -0
  126. package/node_modules/@clawdbot/lobster/dist/src/workflows/registry.js.map +1 -1
  127. package/node_modules/@clawdbot/lobster/dist/src/workflows/types.js +2 -0
  128. package/node_modules/@clawdbot/lobster/dist/src/workflows/types.js.map +1 -0
  129. package/node_modules/@clawdbot/lobster/dist/src/workflows/values.js +93 -0
  130. package/node_modules/@clawdbot/lobster/dist/src/workflows/values.js.map +1 -0
  131. package/node_modules/@clawdbot/lobster/dist/test/approval_id.test.js.map +1 -1
  132. package/node_modules/@clawdbot/lobster/dist/test/approve_preview.test.js.map +1 -1
  133. package/node_modules/@clawdbot/lobster/dist/test/bin_smoke.test.js +25 -0
  134. package/node_modules/@clawdbot/lobster/dist/test/bin_smoke.test.js.map +1 -0
  135. package/node_modules/@clawdbot/lobster/dist/test/cancellation.test.js +5171 -0
  136. package/node_modules/@clawdbot/lobster/dist/test/cancellation.test.js.map +1 -0
  137. package/node_modules/@clawdbot/lobster/dist/test/clawd_invoke.test.js +22 -0
  138. package/node_modules/@clawdbot/lobster/dist/test/clawd_invoke.test.js.map +1 -1
  139. package/node_modules/@clawdbot/lobster/dist/test/clawd_invoke_legacy.test.js.map +1 -1
  140. package/node_modules/@clawdbot/lobster/dist/test/cli_run_errors.test.js +53 -0
  141. package/node_modules/@clawdbot/lobster/dist/test/cli_run_errors.test.js.map +1 -0
  142. package/node_modules/@clawdbot/lobster/dist/test/cli_run_file_args_json.test.js.map +1 -1
  143. package/node_modules/@clawdbot/lobster/dist/test/command_arguments.test.js +82 -0
  144. package/node_modules/@clawdbot/lobster/dist/test/command_arguments.test.js.map +1 -0
  145. package/node_modules/@clawdbot/lobster/dist/test/commands_list.test.js.map +1 -1
  146. package/node_modules/@clawdbot/lobster/dist/test/condition_comparison.test.js.map +1 -1
  147. package/node_modules/@clawdbot/lobster/dist/test/core_tool_runtime.test.js.map +1 -1
  148. package/node_modules/@clawdbot/lobster/dist/test/cost_tracker.test.js +1774 -12
  149. package/node_modules/@clawdbot/lobster/dist/test/cost_tracker.test.js.map +1 -1
  150. package/node_modules/@clawdbot/lobster/dist/test/dedupe.test.js.map +1 -1
  151. package/node_modules/@clawdbot/lobster/dist/test/diff_last.test.js.map +1 -1
  152. package/node_modules/@clawdbot/lobster/dist/test/doctor.test.js.map +1 -1
  153. package/node_modules/@clawdbot/lobster/dist/test/dry_run.test.js.map +1 -1
  154. package/node_modules/@clawdbot/lobster/dist/test/email_triage.test.js.map +1 -1
  155. package/node_modules/@clawdbot/lobster/dist/test/exec_stdin.test.js.map +1 -1
  156. package/node_modules/@clawdbot/lobster/dist/test/for_each.test.js +254 -0
  157. package/node_modules/@clawdbot/lobster/dist/test/for_each.test.js.map +1 -1
  158. package/node_modules/@clawdbot/lobster/dist/test/github_pr_notify_format.test.js.map +1 -1
  159. package/node_modules/@clawdbot/lobster/dist/test/github_pr_summary.test.js.map +1 -1
  160. package/node_modules/@clawdbot/lobster/dist/test/github_pr_view.test.js +176 -0
  161. package/node_modules/@clawdbot/lobster/dist/test/github_pr_view.test.js.map +1 -0
  162. package/node_modules/@clawdbot/lobster/dist/test/gog_gmail_send.test.js +100 -0
  163. package/node_modules/@clawdbot/lobster/dist/test/gog_gmail_send.test.js.map +1 -0
  164. package/node_modules/@clawdbot/lobster/dist/test/group_by.test.js.map +1 -1
  165. package/node_modules/@clawdbot/lobster/dist/test/helpers/node_shell_fixture.js +17 -0
  166. package/node_modules/@clawdbot/lobster/dist/test/helpers/node_shell_fixture.js.map +1 -0
  167. package/node_modules/@clawdbot/lobster/dist/test/helpers/wait_for_pid.js +19 -0
  168. package/node_modules/@clawdbot/lobster/dist/test/helpers/wait_for_pid.js.map +1 -0
  169. package/node_modules/@clawdbot/lobster/dist/test/http_response_body_cap.test.js +318 -0
  170. package/node_modules/@clawdbot/lobster/dist/test/http_response_body_cap.test.js.map +1 -0
  171. package/node_modules/@clawdbot/lobster/dist/test/llm_invoke.test.js +948 -1
  172. package/node_modules/@clawdbot/lobster/dist/test/llm_invoke.test.js.map +1 -1
  173. package/node_modules/@clawdbot/lobster/dist/test/llm_task_invoke.test.js +103 -0
  174. package/node_modules/@clawdbot/lobster/dist/test/llm_task_invoke.test.js.map +1 -1
  175. package/node_modules/@clawdbot/lobster/dist/test/map.test.js.map +1 -1
  176. package/node_modules/@clawdbot/lobster/dist/test/multi_approval_resume.test.js.map +1 -1
  177. package/node_modules/@clawdbot/lobster/dist/test/on_error.test.js.map +1 -1
  178. package/node_modules/@clawdbot/lobster/dist/test/openclaw_agent.test.js +169 -0
  179. package/node_modules/@clawdbot/lobster/dist/test/openclaw_agent.test.js.map +1 -0
  180. package/node_modules/@clawdbot/lobster/dist/test/openclaw_dispatch_retry.test.js +96 -0
  181. package/node_modules/@clawdbot/lobster/dist/test/openclaw_dispatch_retry.test.js.map +1 -0
  182. package/node_modules/@clawdbot/lobster/dist/test/openclaw_invoke_alias.test.js.map +1 -1
  183. package/node_modules/@clawdbot/lobster/dist/test/parallel.test.js.map +1 -1
  184. package/node_modules/@clawdbot/lobster/dist/test/parser.test.js +57 -0
  185. package/node_modules/@clawdbot/lobster/dist/test/parser.test.js.map +1 -1
  186. package/node_modules/@clawdbot/lobster/dist/test/pipeline_resume_state.test.js +65 -0
  187. package/node_modules/@clawdbot/lobster/dist/test/pipeline_resume_state.test.js.map +1 -0
  188. package/node_modules/@clawdbot/lobster/dist/test/process_output_limit.test.js +175 -0
  189. package/node_modules/@clawdbot/lobster/dist/test/process_output_limit.test.js.map +1 -0
  190. package/node_modules/@clawdbot/lobster/dist/test/read_line.test.js +54 -0
  191. package/node_modules/@clawdbot/lobster/dist/test/read_line.test.js.map +1 -1
  192. package/node_modules/@clawdbot/lobster/dist/test/release_changelog.test.js +39 -0
  193. package/node_modules/@clawdbot/lobster/dist/test/release_changelog.test.js.map +1 -0
  194. package/node_modules/@clawdbot/lobster/dist/test/request_input.test.js +1 -1
  195. package/node_modules/@clawdbot/lobster/dist/test/request_input.test.js.map +1 -1
  196. package/node_modules/@clawdbot/lobster/dist/test/resume.test.js.map +1 -1
  197. package/node_modules/@clawdbot/lobster/dist/test/sdk_exec.test.js +248 -0
  198. package/node_modules/@clawdbot/lobster/dist/test/sdk_exec.test.js.map +1 -0
  199. package/node_modules/@clawdbot/lobster/dist/test/sdk_lobster.test.js.map +1 -1
  200. package/node_modules/@clawdbot/lobster/dist/test/shell.test.js.map +1 -1
  201. package/node_modules/@clawdbot/lobster/dist/test/sort.test.js.map +1 -1
  202. package/node_modules/@clawdbot/lobster/dist/test/state.test.js +584 -1
  203. package/node_modules/@clawdbot/lobster/dist/test/state.test.js.map +1 -1
  204. package/node_modules/@clawdbot/lobster/dist/test/step_retry.test.js.map +1 -1
  205. package/node_modules/@clawdbot/lobster/dist/test/step_stdin_epipe.test.js +44 -0
  206. package/node_modules/@clawdbot/lobster/dist/test/step_stdin_epipe.test.js.map +1 -0
  207. package/node_modules/@clawdbot/lobster/dist/test/step_timeout.test.js +67 -1
  208. package/node_modules/@clawdbot/lobster/dist/test/step_timeout.test.js.map +1 -1
  209. package/node_modules/@clawdbot/lobster/dist/test/template.test.js.map +1 -1
  210. package/node_modules/@clawdbot/lobster/dist/test/template_filters.test.js +37 -0
  211. package/node_modules/@clawdbot/lobster/dist/test/template_filters.test.js.map +1 -1
  212. package/node_modules/@clawdbot/lobster/dist/test/tool_envelope_version.test.js.map +1 -1
  213. package/node_modules/@clawdbot/lobster/dist/test/tool_mode.test.js.map +1 -1
  214. package/node_modules/@clawdbot/lobster/dist/test/validation.test.js.map +1 -1
  215. package/node_modules/@clawdbot/lobster/dist/test/where.test.js +94 -0
  216. package/node_modules/@clawdbot/lobster/dist/test/where.test.js.map +1 -0
  217. package/node_modules/@clawdbot/lobster/dist/test/workflow_args_env.test.js +5 -3
  218. package/node_modules/@clawdbot/lobster/dist/test/workflow_args_env.test.js.map +1 -1
  219. package/node_modules/@clawdbot/lobster/dist/test/workflow_composition.test.js.map +1 -1
  220. package/node_modules/@clawdbot/lobster/dist/test/workflow_file.test.js +647 -1
  221. package/node_modules/@clawdbot/lobster/dist/test/workflow_file.test.js.map +1 -1
  222. package/node_modules/@clawdbot/lobster/dist/test/workflow_graph.test.js +13 -3
  223. package/node_modules/@clawdbot/lobster/dist/test/workflow_graph.test.js.map +1 -1
  224. package/node_modules/@clawdbot/lobster/dist/test/workflows.test.js.map +1 -1
  225. package/node_modules/@clawdbot/lobster/package.json +72 -73
  226. package/node_modules/typebox/build/compile/validator.d.mts +1 -1
  227. package/node_modules/typebox/build/compile/validator.mjs +1 -1
  228. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +7 -5
  229. package/node_modules/typebox/build/format/iri.mjs +5 -1
  230. package/node_modules/typebox/build/guard/emit.mjs +2 -4
  231. package/node_modules/typebox/build/guard/guard.mjs +6 -18
  232. package/node_modules/typebox/build/guard/string.mjs +16 -24
  233. package/node_modules/typebox/build/schema/build.mjs +2 -2
  234. package/node_modules/typebox/build/schema/check.mjs +1 -1
  235. package/node_modules/typebox/build/schema/compile.d.mts +3 -2
  236. package/node_modules/typebox/build/schema/compile.mjs +8 -8
  237. package/node_modules/typebox/build/schema/engine/_context.d.mts +6 -7
  238. package/node_modules/typebox/build/schema/engine/_context.mjs +23 -15
  239. package/node_modules/typebox/build/schema/engine/_functions.d.mts +2 -2
  240. package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -1
  241. package/node_modules/typebox/build/schema/engine/_reducer.d.mts +3 -3
  242. package/node_modules/typebox/build/schema/engine/_refine.d.mts +5 -5
  243. package/node_modules/typebox/build/schema/engine/_refine.mjs +4 -7
  244. package/node_modules/typebox/build/schema/engine/_stack.d.mts +34 -16
  245. package/node_modules/typebox/build/schema/engine/_stack.mjs +148 -104
  246. package/node_modules/typebox/build/schema/engine/additionalItems.d.mts +4 -4
  247. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +8 -8
  248. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +26 -18
  249. package/node_modules/typebox/build/schema/engine/allOf.d.mts +4 -4
  250. package/node_modules/typebox/build/schema/engine/allOf.mjs +3 -3
  251. package/node_modules/typebox/build/schema/engine/anyOf.d.mts +4 -4
  252. package/node_modules/typebox/build/schema/engine/anyOf.mjs +5 -10
  253. package/node_modules/typebox/build/schema/engine/boolean.d.mts +4 -4
  254. package/node_modules/typebox/build/schema/engine/boolean.mjs +2 -6
  255. package/node_modules/typebox/build/schema/engine/const.d.mts +4 -4
  256. package/node_modules/typebox/build/schema/engine/const.mjs +2 -6
  257. package/node_modules/typebox/build/schema/engine/contains.d.mts +4 -4
  258. package/node_modules/typebox/build/schema/engine/contains.mjs +2 -6
  259. package/node_modules/typebox/build/schema/engine/dependencies.d.mts +4 -4
  260. package/node_modules/typebox/build/schema/engine/dependencies.mjs +3 -6
  261. package/node_modules/typebox/build/schema/engine/dependentRequired.d.mts +4 -4
  262. package/node_modules/typebox/build/schema/engine/dependentRequired.mjs +2 -6
  263. package/node_modules/typebox/build/schema/engine/dependentSchemas.d.mts +4 -4
  264. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +4 -4
  265. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +11 -7
  266. package/node_modules/typebox/build/schema/engine/enum.d.mts +4 -4
  267. package/node_modules/typebox/build/schema/engine/enum.mjs +2 -6
  268. package/node_modules/typebox/build/schema/engine/exclusiveMaximum.d.mts +4 -4
  269. package/node_modules/typebox/build/schema/engine/exclusiveMaximum.mjs +2 -6
  270. package/node_modules/typebox/build/schema/engine/exclusiveMinimum.d.mts +4 -4
  271. package/node_modules/typebox/build/schema/engine/exclusiveMinimum.mjs +2 -6
  272. package/node_modules/typebox/build/schema/engine/format.d.mts +4 -4
  273. package/node_modules/typebox/build/schema/engine/format.mjs +2 -6
  274. package/node_modules/typebox/build/schema/engine/if.d.mts +4 -4
  275. package/node_modules/typebox/build/schema/engine/if.mjs +7 -15
  276. package/node_modules/typebox/build/schema/engine/items.d.mts +4 -4
  277. package/node_modules/typebox/build/schema/engine/items.mjs +1 -1
  278. package/node_modules/typebox/build/schema/engine/maxContains.d.mts +4 -4
  279. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -6
  280. package/node_modules/typebox/build/schema/engine/maxItems.d.mts +4 -4
  281. package/node_modules/typebox/build/schema/engine/maxItems.mjs +2 -6
  282. package/node_modules/typebox/build/schema/engine/maxLength.d.mts +4 -4
  283. package/node_modules/typebox/build/schema/engine/maxLength.mjs +2 -6
  284. package/node_modules/typebox/build/schema/engine/maxProperties.d.mts +4 -4
  285. package/node_modules/typebox/build/schema/engine/maxProperties.mjs +2 -6
  286. package/node_modules/typebox/build/schema/engine/maximum.d.mts +4 -4
  287. package/node_modules/typebox/build/schema/engine/maximum.mjs +2 -6
  288. package/node_modules/typebox/build/schema/engine/minContains.d.mts +4 -4
  289. package/node_modules/typebox/build/schema/engine/minContains.mjs +2 -6
  290. package/node_modules/typebox/build/schema/engine/minItems.d.mts +5 -5
  291. package/node_modules/typebox/build/schema/engine/minItems.mjs +2 -6
  292. package/node_modules/typebox/build/schema/engine/minLength.d.mts +4 -4
  293. package/node_modules/typebox/build/schema/engine/minLength.mjs +2 -6
  294. package/node_modules/typebox/build/schema/engine/minProperties.d.mts +4 -4
  295. package/node_modules/typebox/build/schema/engine/minProperties.mjs +2 -6
  296. package/node_modules/typebox/build/schema/engine/minimum.d.mts +4 -4
  297. package/node_modules/typebox/build/schema/engine/minimum.mjs +2 -6
  298. package/node_modules/typebox/build/schema/engine/multipleOf.d.mts +4 -4
  299. package/node_modules/typebox/build/schema/engine/multipleOf.mjs +2 -6
  300. package/node_modules/typebox/build/schema/engine/not.d.mts +4 -4
  301. package/node_modules/typebox/build/schema/engine/not.mjs +4 -8
  302. package/node_modules/typebox/build/schema/engine/oneOf.d.mts +4 -4
  303. package/node_modules/typebox/build/schema/engine/oneOf.mjs +6 -11
  304. package/node_modules/typebox/build/schema/engine/pattern.d.mts +4 -4
  305. package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -7
  306. package/node_modules/typebox/build/schema/engine/patternProperties.d.mts +4 -4
  307. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +1 -1
  308. package/node_modules/typebox/build/schema/engine/prefixItems.d.mts +4 -4
  309. package/node_modules/typebox/build/schema/engine/prefixItems.mjs +1 -1
  310. package/node_modules/typebox/build/schema/engine/properties.d.mts +4 -4
  311. package/node_modules/typebox/build/schema/engine/properties.mjs +1 -1
  312. package/node_modules/typebox/build/schema/engine/propertyNames.d.mts +4 -4
  313. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +4 -10
  314. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +4 -4
  315. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +11 -7
  316. package/node_modules/typebox/build/schema/engine/ref.d.mts +4 -4
  317. package/node_modules/typebox/build/schema/engine/ref.mjs +19 -15
  318. package/node_modules/typebox/build/schema/engine/required.d.mts +4 -4
  319. package/node_modules/typebox/build/schema/engine/required.mjs +2 -6
  320. package/node_modules/typebox/build/schema/engine/schema.d.mts +7 -7
  321. package/node_modules/typebox/build/schema/engine/schema.mjs +137 -133
  322. package/node_modules/typebox/build/schema/engine/type.d.mts +4 -4
  323. package/node_modules/typebox/build/schema/engine/type.mjs +2 -6
  324. package/node_modules/typebox/build/schema/engine/unevaluatedItems.d.mts +4 -4
  325. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +5 -9
  326. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.d.mts +4 -4
  327. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +5 -9
  328. package/node_modules/typebox/build/schema/engine/uniqueItems.d.mts +4 -4
  329. package/node_modules/typebox/build/schema/engine/uniqueItems.mjs +2 -6
  330. package/node_modules/typebox/build/schema/errors.d.mts +2 -2
  331. package/node_modules/typebox/build/schema/errors.mjs +8 -14
  332. package/node_modules/typebox/build/schema/intern/index.d.mts +1 -0
  333. package/node_modules/typebox/build/schema/intern/index.mjs +1 -0
  334. package/node_modules/typebox/build/schema/intern/intern.d.mts +11 -0
  335. package/node_modules/typebox/build/schema/intern/intern.mjs +293 -0
  336. package/node_modules/typebox/build/schema/meta/draft_2019_09.d.mts +2 -0
  337. package/node_modules/typebox/build/schema/meta/draft_2019_09.mjs +288 -0
  338. package/node_modules/typebox/build/schema/meta/draft_2020_12.d.mts +2 -0
  339. package/node_modules/typebox/build/schema/meta/draft_2020_12.mjs +300 -0
  340. package/node_modules/typebox/build/schema/meta/draft_3.d.mts +2 -0
  341. package/node_modules/typebox/build/schema/meta/draft_3.mjs +143 -0
  342. package/node_modules/typebox/build/schema/meta/draft_4.d.mts +2 -0
  343. package/node_modules/typebox/build/schema/meta/draft_4.mjs +149 -0
  344. package/node_modules/typebox/build/schema/meta/draft_6.d.mts +2 -0
  345. package/node_modules/typebox/build/schema/meta/draft_6.mjs +155 -0
  346. package/node_modules/typebox/build/schema/meta/draft_7.d.mts +2 -0
  347. package/node_modules/typebox/build/schema/meta/draft_7.mjs +172 -0
  348. package/node_modules/typebox/build/schema/meta/index.d.mts +2 -0
  349. package/node_modules/typebox/build/schema/meta/index.mjs +2 -0
  350. package/node_modules/typebox/build/schema/meta/meta.d.mts +9 -0
  351. package/node_modules/typebox/build/schema/meta/meta.mjs +15 -0
  352. package/node_modules/typebox/build/schema/meta/schema.d.mts +6 -0
  353. package/node_modules/typebox/build/schema/meta/schema.mjs +1 -0
  354. package/node_modules/typebox/build/schema/parse.d.mts +1 -0
  355. package/node_modules/typebox/build/schema/parse.mjs +10 -5
  356. package/node_modules/typebox/build/schema/resolve/resolve.d.mts +8 -3
  357. package/node_modules/typebox/build/schema/resolve/resolve.mjs +268 -139
  358. package/node_modules/typebox/build/schema/schema.d.mts +2 -0
  359. package/node_modules/typebox/build/schema/schema.mjs +2 -0
  360. package/node_modules/typebox/build/value/errors/errors.d.mts +2 -12
  361. package/node_modules/typebox/build/value/errors/errors.mjs +2 -7
  362. package/node_modules/typebox/package.json +1 -1
  363. package/node_modules/typebox/readme.md +59 -89
  364. package/openclaw.plugin.json +1 -1
  365. package/package.json +10 -7
  366. package/node_modules/@clawdbot/lobster/dist/src/sdk/token.js +0 -9
  367. package/node_modules/@clawdbot/lobster/dist/src/sdk/token.js.map +0 -1
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
2
+ <path fill="currentColor" stroke="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8.2 10 A5.2 5.2 0 1 0 8.2 20.4 A5.2 5.2 0 0 0 8.2 10 Z M10.2 20 C14.5 20.8 19 18.6 22.3 13.2 C21 12.9 19.7 12.7 18.4 12.8 L17.5 14.6 L16 12.9 L14.3 14.5 L13.5 13 L11.5 14.2 Z" />
3
+ <path fill="currentColor" stroke="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" transform="rotate(-10 8.6 11)" d="M5.6 12.2 C5.2 5.6 10.4 1.4 15.6 2 C19.4 2.6 21.8 5.2 22.6 8.2 C20.9 7.7 19.2 7.6 17.6 7.9 L16.9 6.3 L15.2 8.5 C13.6 9.4 12.2 10.9 11.6 12.4 L6.8 13 Z" />
4
+ </svg>
Binary file
package/dist/index.js CHANGED
@@ -219,18 +219,18 @@ async function executeManagedLobsterFlow(params, flow) {
219
219
  if (!envelope.ok) return {
220
220
  ok: false,
221
221
  flow,
222
- mutation: params.taskFlow.fail(flowMutation),
222
+ mutation: await params.taskFlow.fail(flowMutation),
223
223
  error: new Error(envelope.error.message)
224
224
  };
225
225
  return {
226
226
  ok: true,
227
227
  envelope,
228
228
  flow,
229
- mutation: envelope.status === "needs_approval" ? params.taskFlow.setWaiting({
229
+ mutation: envelope.status === "needs_approval" ? await params.taskFlow.setWaiting({
230
230
  ...flowMutation,
231
231
  currentStep: params.waitingStep ?? "await_lobster_approval",
232
232
  waitJson: buildApprovalWaitState(envelope)
233
- }) : params.taskFlow.finish(flowMutation)
233
+ }) : await params.taskFlow.finish(flowMutation)
234
234
  };
235
235
  } catch (error) {
236
236
  const err = error instanceof Error ? error : new Error(String(error));
@@ -238,7 +238,7 @@ async function executeManagedLobsterFlow(params, flow) {
238
238
  return {
239
239
  ok: false,
240
240
  flow,
241
- mutation: params.taskFlow.fail({
241
+ mutation: await params.taskFlow.fail({
242
242
  flowId: flow.flowId,
243
243
  expectedRevision: flow.revision
244
244
  }),
@@ -260,7 +260,7 @@ async function runManagedLobsterFlow(params) {
260
260
  currentStep: params.currentStep ?? "run_lobster",
261
261
  ...params.stateJson !== void 0 ? { stateJson: params.stateJson } : {}
262
262
  };
263
- const flow = params.taskFlow.tryCreateManaged ? params.taskFlow.tryCreateManaged(createFlowParams) : params.taskFlow.createManaged(createFlowParams);
263
+ const flow = await params.taskFlow.tryCreateManaged(createFlowParams);
264
264
  if (!flow) return {
265
265
  ok: false,
266
266
  error: /* @__PURE__ */ new Error("TaskFlow persistence failed.")
@@ -268,7 +268,31 @@ async function runManagedLobsterFlow(params) {
268
268
  return await executeManagedLobsterFlow(params, flow);
269
269
  }
270
270
  async function resumeManagedLobsterFlow(params) {
271
- const resumed = params.taskFlow.resume({
271
+ const saved = await params.taskFlow.get(params.flowId);
272
+ if (!saved || saved.syncMode !== "managed" || saved.endedAt !== void 0 || saved.cancelRequestedAt !== void 0 || saved.status !== "waiting" && saved.status !== "blocked") return {
273
+ ok: false,
274
+ error: /* @__PURE__ */ new Error("TaskFlow has no resumable Lobster checkpoint.")
275
+ };
276
+ const wait = saved.waitJson;
277
+ if (!wait || typeof wait !== "object" || Array.isArray(wait) || wait.kind !== "lobster_approval") return {
278
+ ok: false,
279
+ error: /* @__PURE__ */ new Error("TaskFlow is not waiting for Lobster approval.")
280
+ };
281
+ const token = typeof wait.resumeToken === "string" ? wait.resumeToken : void 0;
282
+ const approvalId = typeof wait.approvalId === "string" ? wait.approvalId : void 0;
283
+ if (!token && !approvalId || params.runnerParams.token !== void 0 && params.runnerParams.token.trim() !== token || params.runnerParams.approvalId !== void 0 && params.runnerParams.approvalId.trim() !== approvalId) return {
284
+ ok: false,
285
+ error: /* @__PURE__ */ new Error("Lobster checkpoint does not match the selected TaskFlow.")
286
+ };
287
+ const runnerParams = {
288
+ ...params.runnerParams,
289
+ ...params.runnerParams.token || params.runnerParams.approvalId ? {} : token ? { token } : { approvalId }
290
+ };
291
+ if (saved.revision !== params.expectedRevision) return {
292
+ ok: false,
293
+ error: /* @__PURE__ */ new Error("TaskFlow resume failed: revision_conflict")
294
+ };
295
+ const resumed = await params.taskFlow.resume({
272
296
  flowId: params.flowId,
273
297
  expectedRevision: params.expectedRevision,
274
298
  status: "running",
@@ -279,7 +303,10 @@ async function resumeManagedLobsterFlow(params) {
279
303
  mutation: resumed,
280
304
  error: /* @__PURE__ */ new Error(`TaskFlow resume failed: ${resumed.code}`)
281
305
  };
282
- return await executeManagedLobsterFlow(params, resumed.flow);
306
+ return await executeManagedLobsterFlow({
307
+ ...params,
308
+ runnerParams
309
+ }, resumed.flow);
283
310
  }
284
311
  //#endregion
285
312
  //#region extensions/lobster/src/lobster-tool.ts
@@ -350,7 +377,6 @@ function parseManagedFlowParams(action, params, runnerParams) {
350
377
  if (!flowId) throw new Error("flowId required when using managed TaskFlow resume mode");
351
378
  if (expectedRevision === void 0) throw new Error("flowExpectedRevision required when using managed TaskFlow resume mode");
352
379
  const credentialParams = token ? { token: runnerParams.token ?? token } : approvalId ? { approvalId: runnerParams.approvalId ?? approvalId } : null;
353
- if (!credentialParams) throw new Error("token or approvalId required when using managed TaskFlow resume mode");
354
380
  if (approve === void 0) throw new Error("approve required when using managed TaskFlow resume mode");
355
381
  return {
356
382
  action,
@@ -397,7 +423,7 @@ function createLobsterTool(api, options) {
397
423
  flowControllerId: Type.Optional(Type.String()),
398
424
  flowGoal: Type.Optional(Type.String()),
399
425
  flowStateJson: Type.Optional(Type.String()),
400
- flowId: Type.Optional(Type.String()),
426
+ flowId: Type.Optional(Type.String({ description: "Managed flow to resume. Its saved approval checkpoint is used when token and approvalId are omitted." })),
401
427
  flowExpectedRevision: optionalNonNegativeIntegerSchema(),
402
428
  flowCurrentStep: Type.Optional(Type.String()),
403
429
  flowWaitingStep: Type.Optional(Type.String())
@@ -459,7 +485,10 @@ var lobster_default = definePluginEntry({
459
485
  register(api) {
460
486
  api.registerTool(((ctx) => {
461
487
  if (ctx.sandboxed) return null;
462
- return createLobsterTool(api, { taskFlow: api.runtime?.tasks.managedFlows && ctx.sessionKey ? api.runtime.tasks.managedFlows.fromToolContext(ctx) : void 0 });
488
+ return createLobsterTool(api, { taskFlow: api.runtime && ctx.sessionKey ? {
489
+ ...api.runtime.tasks.async.managedFlows.fromToolContext(ctx),
490
+ cancel: api.runtime.tasks.managedFlows.fromToolContext(ctx).cancel
491
+ } : void 0 });
463
492
  }), { optional: true });
464
493
  }
465
494
  });
@@ -2,139 +2,20 @@
2
2
 
3
3
  ![Lobster banner](docs/assets/readme-banner.jpg)
4
4
 
5
- An OpenClaw-native workflow shell: typed (JSON-first) pipelines, jobs, and approval gates.
5
+ An OpenClaw-native workflow shell: typed (JSON-first) pipelines and approval gates.
6
6
 
7
+ ## Example
7
8
 
8
- ## Example of Lobster at work
9
- OpenClaw (or any other AI agent) can use `lobster` as a workflow engine and avoid re-planning every step — saving tokens while improving determinism and resumability.
9
+ A named workflow fetches a pull request with `gh`, compares it with the saved snapshot, and returns a notification only when it changes:
10
10
 
11
- ### Watching a PR that hasn't had changes
12
- ```
13
- node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo\":\"openclaw/openclaw\",\"pr\":1152}'"
14
- [
15
- {
16
- "kind": "github.pr.monitor",
17
- "repo": "openclaw/openclaw",
18
- "prNumber": 1152,
19
- "key": "github.pr:openclaw/openclaw#1152",
20
- "changed": false,
21
- "summary": {
22
- "changedFields": [],
23
- "changes": {}
24
- },
25
- "prSnapshot": {
26
- "author": {
27
- "id": "MDQ6VXNlcjE0MzY4NTM=",
28
- "is_bot": false,
29
- "login": "vignesh07",
30
- "name": "Vignesh"
31
- },
32
- "baseRefName": "main",
33
- "headRefName": "feat/lobster-plugin",
34
- "isDraft": false,
35
- "mergeable": "MERGEABLE",
36
- "number": 1152,
37
- "reviewDecision": "",
38
- "state": "OPEN",
39
- "title": "feat: Add optional lobster plugin tool (typed workflows, approvals/resume)",
40
- "updatedAt": "2026-01-18T20:16:56Z",
41
- "url": "https://github.com/openclaw/openclaw/pull/1152"
42
- }
43
- }
44
- ]
11
+ ```bash
12
+ node bin/lobster.js run --mode tool "workflows.run --name github.pr.monitor.notify --args-json '{\"repo\":\"openclaw/lobster\",\"pr\":167}'"
45
13
  ```
46
- ### And a PR that has a state change (in this case an approved PR)
47
14
 
48
- ```
49
- node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo\":\"openclaw/openclaw\",\"pr\":1200}'"
50
- [
51
- {
52
- "kind": "github.pr.monitor",
53
- "repo": "openclaw/openclaw",
54
- "prNumber": 1200,
55
- "key": "github.pr:openclaw/openclaw#1200",
56
- "changed": true,
57
- "summary": {
58
- "changedFields": [
59
- "number",
60
- "title",
61
- "url",
62
- "state",
63
- "isDraft",
64
- "mergeable",
65
- "reviewDecision",
66
- "updatedAt",
67
- "baseRefName",
68
- "headRefName"
69
- ],
70
- "changes": {
71
- "number": {
72
- "from": null,
73
- "to": 1200
74
- },
75
- "title": {
76
- "from": null,
77
- "to": "feat(tui): add syntax highlighting for code blocks"
78
- },
79
- "url": {
80
- "from": null,
81
- "to": "https://github.com/openclaw/openclaw/pull/1200"
82
- },
83
- "state": {
84
- "from": null,
85
- "to": "MERGED"
86
- },
87
- "isDraft": {
88
- "from": null,
89
- "to": false
90
- },
91
- "mergeable": {
92
- "from": null,
93
- "to": "UNKNOWN"
94
- },
95
- "reviewDecision": {
96
- "from": null,
97
- "to": ""
98
- },
99
- "updatedAt": {
100
- "from": null,
101
- "to": "2026-01-19T05:06:09Z"
102
- },
103
- "baseRefName": {
104
- "from": null,
105
- "to": "main"
106
- },
107
- "headRefName": {
108
- "from": null,
109
- "to": "feat/tui-syntax-highlighting"
110
- }
111
- }
112
- },
113
- "prSnapshot": {
114
- "author": {
115
- "id": "MDQ6VXNlcjE0MzY4NTM=",
116
- "is_bot": false,
117
- "login": "vignesh07",
118
- "name": "Vignesh"
119
- },
120
- "baseRefName": "main",
121
- "headRefName": "feat/tui-syntax-highlighting",
122
- "isDraft": false,
123
- "mergeable": "UNKNOWN",
124
- "number": 1200,
125
- "reviewDecision": "",
126
- "state": "MERGED",
127
- "title": "feat(tui): add syntax highlighting for code blocks",
128
- "updatedAt": "2026-01-19T05:06:09Z",
129
- "url": "https://github.com/openclaw/openclaw/pull/1200"
130
- }
131
- }
132
- ]
133
- ```
15
+ For repeatable automation, put shell commands, native pipeline steps, and explicit approval/input gates in a workflow file. OpenClaw presents the gate to the user and resumes with their decision.
134
16
 
135
17
  ## Goals
136
18
 
137
-
138
19
  - Typed pipelines (objects/arrays), not text pipes.
139
20
  - Local-first execution.
140
21
  - No new auth surface: Lobster must not own OAuth/tokens.
@@ -142,9 +23,10 @@ node bin/lobster.js "workflows.run --name github.pr.monitor --args-json '{\"repo
142
23
 
143
24
  ## Quick start
144
25
 
145
- From this folder:
26
+ Requires Node.js 22 or newer and the pnpm version pinned in `package.json`. From this folder:
146
27
 
147
- - `pnpm install`
28
+ - `pnpm install --frozen-lockfile`
29
+ - `pnpm build`
148
30
  - `pnpm test`
149
31
  - `pnpm lint`
150
32
  - `node ./bin/lobster.js --help`
@@ -154,18 +36,85 @@ From this folder:
154
36
  ### Notes
155
37
 
156
38
  - `pnpm test` runs `tsc` and then executes tests against `dist/`.
157
- - `bin/lobster.js` prefers the compiled entrypoint in `dist/` when present.
39
+ - `bin/lobster.js` runs the compiled entrypoint in `dist/`; build after changing source files.
40
+ Invalid explicit workflow file paths are reported as input errors (exit code 2). In `--mode tool`, these failures use the same JSON error envelope as other parsing errors.
41
+
42
+ ## Process output limits
43
+
44
+ Captured process stdout and stderr remain unlimited by default. Set
45
+ `LOBSTER_MAX_OUTPUT_BYTES` to a positive integer to opt into a byte limit **per
46
+ stream, per process**. Unset or empty means unlimited; zero, negative, fractional,
47
+ and non-numeric values are rejected before a process starts. This applies to
48
+ CLI `exec`, workflow shell steps, SDK `exec`/shell calls, GitHub recipes, and Gog
49
+ commands. The existing `openclaw.agent` 10 MiB limit remains in place; an opted-in
50
+ limit can lower it.
51
+
52
+ ```bash
53
+ LOBSTER_MAX_OUTPUT_BYTES=1048576 lobster run --mode tool 'exec my-command'
54
+ ```
55
+
56
+ Use workflow or step `env` to scope the limit:
57
+
58
+ ```yaml
59
+ steps:
60
+ - id: bounded
61
+ env:
62
+ LOBSTER_MAX_OUTPUT_BYTES: "1048576"
63
+ run: my-command
64
+ ```
65
+
66
+ SDK callers set the same variable in `new Lobster({ env: { ...process.env,
67
+ LOBSTER_MAX_OUTPUT_BYTES: "1048576" } })`. Values exactly at the limit succeed;
68
+ overflow terminates the process tree and returns an error without partial
69
+ output. POSIX capped calls own a process group so background producers cannot
70
+ keep pipes open after overflow. Calls without an AbortSignal relay terminal
71
+ interrupts to that group and retain the host's existing signal handlers or
72
+ conventional interrupt exit status.
73
+
158
74
  ## Commands
159
75
 
160
76
  - `exec`: run OS commands
77
+ - `exec --json <command...>`: parse subprocess stdout as JSON before the next stage
161
78
  - `exec --stdin raw|json|jsonl`: feed pipeline input into subprocess stdin
79
+ - Explicit quoted empty arguments are retained by both pipeline `exec` and SDK `exec`. Invocation shims preserve argument punctuation without shell expansion.
162
80
  - `where`, `pick`, `head`: data shaping
163
81
  - `json`, `table`: renderers
164
82
  - `approve`: approval gate (TTY prompt or `--emit` for OpenClaw integration)
165
83
 
166
- ## Next steps
84
+ ## SDK cancellation
85
+
86
+ Pass an `AbortSignal` to `new Lobster({ signal })` to cancel SDK `exec()` stages,
87
+ including `exec(command, { shell: true })`. The signal is retained by `clone()`
88
+ and forwarded when a pipeline resumes. Aborting terminates the running child
89
+ process tree before `run()` or `resume()` returns an error result containing the
90
+ abort reason. A signal that is already aborted prevents the command from starting.
91
+
92
+ ```js
93
+ import { Lobster, exec } from '@clawdbot/lobster';
94
+
95
+ const controller = new AbortController();
96
+ const pending = new Lobster({ signal: controller.signal })
97
+ .pipe(exec('node long-task.js', { json: false }))
98
+ .run();
99
+ // When the host needs to stop the command:
100
+ controller.abort(new Error('Host cancelled the command'));
101
+ const result = await pending;
102
+ ```
103
+
104
+ Custom stages receive the signal as `ctx.signal` and must cooperate with it to
105
+ cancel their own work.
106
+
107
+ ## GitHub recipe cancellation
108
+
109
+ The SDK GitHub recipes accept an `AbortSignal` in both
110
+ `prMonitor({ repo, pr, signal })` and `prMonitorNotify({ repo, pr, signal })`.
111
+ Aborting stops the running GitHub CLI child before the recipe returns an error
112
+ result containing the abort reason. A cancelled fetch does not update the saved
113
+ PR snapshot or emit a notification.
167
114
 
168
- - OpenClaw integration: ship as an optional OpenClaw plugin tool.
115
+ For a manually composed pipeline, pass the signal to
116
+ `new Lobster({ signal }).pipe(ghPrView({ repo, pr }))`. Custom stages receive
117
+ `ctx.signal` and must cooperate with it to cancel their own work.
169
118
 
170
119
  ## Workflow files
171
120
 
@@ -211,6 +160,7 @@ Notes:
211
160
  - If you need a human checkpoint before an LLM call, use a dedicated `approval:` step in the workflow file rather than `approve` inside the nested pipeline.
212
161
  - `cwd`, `env`, `stdin`, `when`, and `condition` work for both shell and pipeline steps.
213
162
  - Use `retry`, `timeout_ms`, and `on_error` per step to control transient-failure behavior and recovery.
163
+ - On `for_each`, these policies cover the entire loop: each attempt gets one timeout budget (including batch pauses), and retry restarts at the first item. Previously completed children may run again, so only enable loop retries for work that is safe to repeat. A `cost_limit` stop or an attempted OpenClaw dispatch prevents retries; paid LLM usage is checked even when a later pipeline command fails. `on_error: continue` records `$loop.error` and proceeds to the next workflow step; `skip_rest` skips the remaining workflow steps.
214
164
  - Approval steps can optionally enforce identity constraints:
215
165
  - `approval.required_approver` (or `requiredApprover`) requires an exact approver id.
216
166
  - `approval.require_different_approver` (or `requireDifferentApprover`) requires approver id to differ from initiator.
@@ -218,6 +168,10 @@ Notes:
218
168
  - `LOBSTER_APPROVAL_INITIATED_BY` can provide a default initiator id at run time.
219
169
  - `LOBSTER_APPROVAL_APPROVED_BY` is used at resume/approval time for identity checks.
220
170
 
171
+ ### Retries after OpenClaw dispatch
172
+
173
+ `openclaw.invoke` (including `clawd.invoke`) and `openclaw.agent` suppress automatic workflow-step retries once dispatch is attempted. This applies to timeouts, HTTP or process failures, and errors in later commands of the same pipeline step, even when `retry.max` is greater than one. A failed local request cannot establish whether a remote action already completed. Read-only and dry-run requests use the same conservative rule: Lobster does not know the remote tool’s retry guarantees, and the [OpenClaw gateway currently ignores `dryRun`](https://docs.openclaw.ai/gateway/tools-invoke-http-api#request-body). The flag does not prevent tool execution. Check the remote outcome before manually running the step again. `llm.invoke` retains its existing retry policy.
174
+
221
175
  ### Command-level input requests
222
176
 
223
177
  Pipeline commands can call `ctx.requestInput({ prompt, responseSchema, defaults, subject, suspendedState })` to pause in tool mode, workflows, or the SDK and resume the same command after a structured response. CLI/tool resume tokens store only a state key; the persisted state validates the suspended request metadata before returning the submitted response to the command. SDK same-command resumes store the command frame in the configured SDK state directory.
@@ -229,6 +183,7 @@ Commands are re-run on resume, so they must be idempotent until `requestInput` r
229
183
  Use `lobster graph` to inspect workflow structure before execution.
230
184
 
231
185
  ```bash
186
+ lobster graph --help
232
187
  lobster graph --file path/to/workflow.lobster
233
188
  lobster graph --file path/to/workflow.lobster --format mermaid
234
189
  lobster graph --file path/to/workflow.lobster --format dot
@@ -271,13 +226,28 @@ Built-in providers today:
271
226
  - `pi` via `LOBSTER_PI_LLM_ADAPTER_URL` (typically supplied by the Pi extension)
272
227
  - `http` via `LOBSTER_LLM_ADAPTER_URL`
273
228
 
229
+ A host embedding Lobster can supply its own adapters through `ctx.llmAdapters`. Step `timeout_ms` and workflow cancellation reach an adapter as `ctx.signal`: Lobster stops waiting as soon as that signal aborts, so the step fails or retries on time either way, but it cannot cancel work an adapter has already started. An injected adapter should observe `ctx.signal` and abort its own request — otherwise a timed-out step can leave a model call running, and billed, in the background.
230
+
274
231
  Workflow `_meta.cost` and `cost_limit` use a static pricing table plus optional overrides from `LOBSTER_LLM_PRICING_JSON`, for example `{"my-model":{"input":1.0,"output":2.0}}` in USD per million tokens. Unknown or missing model IDs still record token counts with zero estimated cost, but Lobster warns on stderr so stale or missing pricing does not fail silently.
275
232
 
233
+ A cached or replayed answer is not billed again: a model call is counted once, in the run that made it, however many later steps re-emit its answer. This holds while the answer stays inside Lobster: through pipelines, renderers, projections, run state, `workflow:` steps and a resume. It does not survive a stage that hands the items to an external process and reads them back — `exec --stdin json --json ...` — because what comes back is whatever that process printed, and Lobster cannot tell a faithful copy of a replay from a fresh claim to have made the call. Such a step is billed as a call, which is what earlier versions did everywhere. A `workflow:` step counts what its sub-workflow spent, and a replay the sub-workflow returned is not billed a second time by the run that composed it. Spend also survives a pause — a workflow that stops at an approval or `input` gate keeps what it has recorded, so `_meta.cost` covers the whole run after a resume and `cost_limit` applies to the whole run rather than to the steps after the last gate.
234
+
276
235
  `llm_task.invoke` remains available as a backward-compatible alias for the OpenClaw provider.
277
236
 
237
+ ### Calling configured OpenClaw agents
238
+
239
+ Use `openclaw.agent` when a workflow needs a configured OpenClaw agent rather than a direct model call:
240
+
241
+ ```bash
242
+ openclaw.agent --agent ops --prompt 'Summarize these logs'
243
+ openclaw.agent --agent ops --session-key incident-42 --model openai/gpt-5.4 --prompt 'Continue the investigation'
244
+ ```
245
+
246
+ The command delegates agent identity, model defaults and overrides, sessions, authentication, and execution to the installed `openclaw agent` CLI. It accepts `--agent`, `--session-key`, `--session-id`, `--model`, `--thinking`, `--timeout`, and `--local`, and returns OpenClaw's structured `--json` response. Pipeline input is appended to the prompt as labeled JSONL.
247
+
278
248
  ### `pipeline:` vs `run:` for LLM calls
279
249
 
280
- - Use `pipeline:` for `llm.invoke` and `llm_task.invoke` (they are Lobster pipeline stages, not shell executables).
250
+ - Use `pipeline:` for `openclaw.agent`, `llm.invoke`, and `llm_task.invoke` (they are Lobster pipeline stages, not shell executables).
281
251
  - Use `run:` only for real binaries in your shell (for example `openclaw.invoke`).
282
252
 
283
253
  Example (`stdin` from a prior step is passed to the LLM as artifacts):
@@ -351,3 +321,31 @@ steps:
351
321
  command: |
352
322
  jq -n --arg text "$TEXT" '{"result": $text}'
353
323
  ```
324
+
325
+ ## HTTP response limits
326
+
327
+ HTTP response bodies remain unlimited by default. Set
328
+ `LOBSTER_MAX_HTTP_RESPONSE_BYTES` to a positive integer to opt into a per-response
329
+ byte limit for `openclaw.invoke`/`clawd.invoke` and the built-in OpenClaw, HTTP,
330
+ and Pi `llm.invoke` adapters. Unset or empty means unlimited; invalid or non-positive
331
+ values fail before dispatch. Host-injected adapters own their transport limits.
332
+
333
+ ```bash
334
+ LOBSTER_MAX_HTTP_RESPONSE_BYTES=1048576 lobster run --mode tool 'openclaw.invoke --tool example --action read'
335
+ ```
336
+
337
+ Workflow and step `env` can set the same variable. SDK integrations pass it in
338
+ their environment (`new Lobster({ env: { ...process.env,
339
+ LOBSTER_MAX_HTTP_RESPONSE_BYTES: "1048576" } })` or the tool-runtime context).
340
+ Responses exactly at the limit succeed. Oversized declared or streamed bodies
341
+ are cancelled and rejected before JSON parsing; no partial response is returned.
342
+ The limit counts bytes read from the response stream, including decompressed
343
+ content. A declared Content-Length over the limit is also rejected immediately.
344
+ Tool dispatch remains non-retryable after an overflow, as with other
345
+ post-dispatch errors; `llm.invoke` retains its existing retry policy.
346
+
347
+ ## Development
348
+
349
+ The source is one TypeScript package. `src/core` contains the embeddable tool API, cost tracking, and LLM accounting; `src/sdk` provides pipeline composition; `src/commands` holds the command registry and standard library. Workflow loading, expressions, dry-run rendering, and execution live under `src/workflows`. `src/state` owns atomic file persistence, locks, and resume capabilities. GitHub SDK recipes and built-in workflows share transport and snapshot helpers.
350
+
351
+ Run `pnpm test`, `pnpm typecheck`, and `pnpm lint` before submitting changes. Tests compile into `dist/test` and use Node's test runner; platform-specific process tests run only where their OS primitives exist. Dependencies observe the two-day release-age policy in `pnpm-workspace.yaml`.