@openclaw/lobster 2026.9.8 → 2026.10.1-beta.2
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.
- package/README.md +10 -9
- package/dist/index.js +45 -39
- package/node_modules/@clawdbot/lobster/README.md +4 -0
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/head.js +4 -2
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/head.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/llm_invoke.js +35 -12
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/llm_invoke.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/map.js +13 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/map.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/pick.js +1 -4
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/pick.js.map +1 -1
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/table.js +3 -5
- package/node_modules/@clawdbot/lobster/dist/src/commands/stdlib/table.js.map +1 -1
- package/node_modules/@clawdbot/lobster/package.json +7 -7
- package/package.json +5 -5
- package/node_modules/@clawdbot/lobster/dist/test/approval_id.test.js +0 -171
- package/node_modules/@clawdbot/lobster/dist/test/approval_id.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/approve_preview.test.js +0 -38
- package/node_modules/@clawdbot/lobster/dist/test/approve_preview.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/bin_smoke.test.js +0 -25
- package/node_modules/@clawdbot/lobster/dist/test/bin_smoke.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/cancellation.test.js +0 -5171
- package/node_modules/@clawdbot/lobster/dist/test/cancellation.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/clawd_invoke.test.js +0 -146
- package/node_modules/@clawdbot/lobster/dist/test/clawd_invoke.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/clawd_invoke_legacy.test.js +0 -63
- package/node_modules/@clawdbot/lobster/dist/test/clawd_invoke_legacy.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/cli_run_errors.test.js +0 -53
- package/node_modules/@clawdbot/lobster/dist/test/cli_run_errors.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/cli_run_file_args_json.test.js +0 -27
- package/node_modules/@clawdbot/lobster/dist/test/cli_run_file_args_json.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/command_arguments.test.js +0 -82
- package/node_modules/@clawdbot/lobster/dist/test/command_arguments.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/commands_list.test.js +0 -44
- package/node_modules/@clawdbot/lobster/dist/test/commands_list.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/condition_comparison.test.js +0 -127
- package/node_modules/@clawdbot/lobster/dist/test/condition_comparison.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/core_tool_runtime.test.js +0 -160
- package/node_modules/@clawdbot/lobster/dist/test/core_tool_runtime.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/cost_tracker.test.js +0 -1993
- package/node_modules/@clawdbot/lobster/dist/test/cost_tracker.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/dedupe.test.js +0 -48
- package/node_modules/@clawdbot/lobster/dist/test/dedupe.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/diff_last.test.js +0 -70
- package/node_modules/@clawdbot/lobster/dist/test/diff_last.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/doctor.test.js +0 -19
- package/node_modules/@clawdbot/lobster/dist/test/doctor.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/dry_run.test.js +0 -502
- package/node_modules/@clawdbot/lobster/dist/test/dry_run.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/email_triage.test.js +0 -296
- package/node_modules/@clawdbot/lobster/dist/test/email_triage.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/exec_stdin.test.js +0 -43
- package/node_modules/@clawdbot/lobster/dist/test/exec_stdin.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/for_each.test.js +0 -482
- package/node_modules/@clawdbot/lobster/dist/test/for_each.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/github_pr_notify_format.test.js +0 -19
- package/node_modules/@clawdbot/lobster/dist/test/github_pr_notify_format.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/github_pr_summary.test.js +0 -41
- package/node_modules/@clawdbot/lobster/dist/test/github_pr_summary.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/github_pr_view.test.js +0 -176
- package/node_modules/@clawdbot/lobster/dist/test/github_pr_view.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/gog_gmail_send.test.js +0 -100
- package/node_modules/@clawdbot/lobster/dist/test/gog_gmail_send.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/group_by.test.js +0 -43
- package/node_modules/@clawdbot/lobster/dist/test/group_by.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/helpers/node_shell_fixture.js +0 -17
- package/node_modules/@clawdbot/lobster/dist/test/helpers/node_shell_fixture.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/helpers/wait_for_pid.js +0 -19
- package/node_modules/@clawdbot/lobster/dist/test/helpers/wait_for_pid.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/http_response_body_cap.test.js +0 -318
- package/node_modules/@clawdbot/lobster/dist/test/http_response_body_cap.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/llm_invoke.test.js +0 -1113
- package/node_modules/@clawdbot/lobster/dist/test/llm_invoke.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/llm_task_invoke.test.js +0 -519
- package/node_modules/@clawdbot/lobster/dist/test/llm_task_invoke.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/map.test.js +0 -41
- package/node_modules/@clawdbot/lobster/dist/test/map.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/multi_approval_resume.test.js +0 -48
- package/node_modules/@clawdbot/lobster/dist/test/multi_approval_resume.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/on_error.test.js +0 -151
- package/node_modules/@clawdbot/lobster/dist/test/on_error.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/openclaw_agent.test.js +0 -169
- package/node_modules/@clawdbot/lobster/dist/test/openclaw_agent.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/openclaw_dispatch_retry.test.js +0 -96
- package/node_modules/@clawdbot/lobster/dist/test/openclaw_dispatch_retry.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/openclaw_invoke_alias.test.js +0 -13
- package/node_modules/@clawdbot/lobster/dist/test/openclaw_invoke_alias.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/parallel.test.js +0 -184
- package/node_modules/@clawdbot/lobster/dist/test/parallel.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/parser.test.js +0 -96
- package/node_modules/@clawdbot/lobster/dist/test/parser.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/pipeline_resume_state.test.js +0 -65
- package/node_modules/@clawdbot/lobster/dist/test/pipeline_resume_state.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/process_output_limit.test.js +0 -175
- package/node_modules/@clawdbot/lobster/dist/test/process_output_limit.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/read_line.test.js +0 -79
- package/node_modules/@clawdbot/lobster/dist/test/read_line.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/release_changelog.test.js +0 -39
- package/node_modules/@clawdbot/lobster/dist/test/release_changelog.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/request_input.test.js +0 -946
- package/node_modules/@clawdbot/lobster/dist/test/request_input.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/resume.test.js +0 -82
- package/node_modules/@clawdbot/lobster/dist/test/resume.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/sdk_exec.test.js +0 -248
- package/node_modules/@clawdbot/lobster/dist/test/sdk_exec.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/sdk_lobster.test.js +0 -177
- package/node_modules/@clawdbot/lobster/dist/test/sdk_lobster.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/shell.test.js +0 -31
- package/node_modules/@clawdbot/lobster/dist/test/shell.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/sort.test.js +0 -51
- package/node_modules/@clawdbot/lobster/dist/test/sort.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/state.test.js +0 -919
- package/node_modules/@clawdbot/lobster/dist/test/state.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/step_retry.test.js +0 -254
- package/node_modules/@clawdbot/lobster/dist/test/step_retry.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/step_stdin_epipe.test.js +0 -44
- package/node_modules/@clawdbot/lobster/dist/test/step_stdin_epipe.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/step_timeout.test.js +0 -220
- package/node_modules/@clawdbot/lobster/dist/test/step_timeout.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/template.test.js +0 -46
- package/node_modules/@clawdbot/lobster/dist/test/template.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/template_filters.test.js +0 -144
- package/node_modules/@clawdbot/lobster/dist/test/template_filters.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/tool_envelope_version.test.js +0 -15
- package/node_modules/@clawdbot/lobster/dist/test/tool_envelope_version.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/tool_mode.test.js +0 -83
- package/node_modules/@clawdbot/lobster/dist/test/tool_mode.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/validation.test.js +0 -28
- package/node_modules/@clawdbot/lobster/dist/test/validation.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/where.test.js +0 -94
- package/node_modules/@clawdbot/lobster/dist/test/where.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/workflow_args_env.test.js +0 -43
- package/node_modules/@clawdbot/lobster/dist/test/workflow_args_env.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/workflow_composition.test.js +0 -238
- package/node_modules/@clawdbot/lobster/dist/test/workflow_composition.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/workflow_file.test.js +0 -2045
- package/node_modules/@clawdbot/lobster/dist/test/workflow_file.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/workflow_graph.test.js +0 -107
- package/node_modules/@clawdbot/lobster/dist/test/workflow_graph.test.js.map +0 -1
- package/node_modules/@clawdbot/lobster/dist/test/workflows.test.js +0 -32
- package/node_modules/@clawdbot/lobster/dist/test/workflows.test.js.map +0 -1
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { promises as fsp } from "node:fs";
|
|
4
|
-
import os from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { createDefaultRegistry } from "../src/commands/registry.js";
|
|
7
|
-
import { loadWorkflowFile, runWorkflowFile } from "../src/workflows/file.js";
|
|
8
|
-
async function runWorkflow(workflow) {
|
|
9
|
-
const tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), "lobster-parallel-"));
|
|
10
|
-
const stateDir = path.join(tmpDir, "state");
|
|
11
|
-
const filePath = path.join(tmpDir, "workflow.lobster");
|
|
12
|
-
await fsp.writeFile(filePath, JSON.stringify(workflow, null, 2), "utf8");
|
|
13
|
-
return runWorkflowFile({
|
|
14
|
-
filePath,
|
|
15
|
-
ctx: {
|
|
16
|
-
stdin: process.stdin,
|
|
17
|
-
stdout: process.stdout,
|
|
18
|
-
stderr: process.stderr,
|
|
19
|
-
env: { ...process.env, LOBSTER_STATE_DIR: stateDir },
|
|
20
|
-
mode: "tool",
|
|
21
|
-
registry: createDefaultRegistry(),
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
test("parallel wait=all runs all branches and merges output", async () => {
|
|
26
|
-
const result = await runWorkflow({
|
|
27
|
-
steps: [
|
|
28
|
-
{
|
|
29
|
-
id: "fetch",
|
|
30
|
-
parallel: {
|
|
31
|
-
wait: "all",
|
|
32
|
-
branches: [
|
|
33
|
-
{ id: "a", command: 'node -e "process.stdout.write(JSON.stringify({src:\\"a\\"}))"' },
|
|
34
|
-
{ id: "b", command: 'node -e "process.stdout.write(JSON.stringify({src:\\"b\\"}))"' },
|
|
35
|
-
{ id: "c", command: 'node -e "process.stdout.write(JSON.stringify({src:\\"c\\"}))"' },
|
|
36
|
-
],
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
});
|
|
41
|
-
assert.equal(result.status, "ok");
|
|
42
|
-
const output = result.output;
|
|
43
|
-
assert.equal(output[0].a.src, "a");
|
|
44
|
-
assert.equal(output[0].b.src, "b");
|
|
45
|
-
assert.equal(output[0].c.src, "c");
|
|
46
|
-
});
|
|
47
|
-
test("parallel wait=any returns first branch result", async () => {
|
|
48
|
-
const result = await runWorkflow({
|
|
49
|
-
steps: [
|
|
50
|
-
{
|
|
51
|
-
id: "race",
|
|
52
|
-
parallel: {
|
|
53
|
-
wait: "any",
|
|
54
|
-
branches: [
|
|
55
|
-
{
|
|
56
|
-
id: "fast",
|
|
57
|
-
command: 'node -e "process.stdout.write(JSON.stringify({winner:true}))"',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
id: "slow",
|
|
61
|
-
command: 'node -e "setTimeout(() => process.stdout.write(JSON.stringify({winner:false})), 5000)"',
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
});
|
|
68
|
-
assert.equal(result.status, "ok");
|
|
69
|
-
const output = result.output;
|
|
70
|
-
assert.equal(Object.keys(output[0]).length, 1);
|
|
71
|
-
assert.equal(output[0].fast.winner, true);
|
|
72
|
-
});
|
|
73
|
-
test("parallel branch results are available to later steps by branch id", async () => {
|
|
74
|
-
const result = await runWorkflow({
|
|
75
|
-
steps: [
|
|
76
|
-
{
|
|
77
|
-
id: "fetch",
|
|
78
|
-
parallel: {
|
|
79
|
-
wait: "all",
|
|
80
|
-
branches: [
|
|
81
|
-
{ id: "x", command: 'node -e "process.stdout.write(JSON.stringify({val:10}))"' },
|
|
82
|
-
{ id: "y", command: 'node -e "process.stdout.write(JSON.stringify({val:20}))"' },
|
|
83
|
-
],
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
id: "use",
|
|
88
|
-
command: 'node -e "process.stdout.write(JSON.stringify({x:$x.json.val,y:$y.json.val}))"',
|
|
89
|
-
},
|
|
90
|
-
],
|
|
91
|
-
});
|
|
92
|
-
assert.equal(result.status, "ok");
|
|
93
|
-
assert.deepEqual(result.output, [{ x: 10, y: 20 }]);
|
|
94
|
-
});
|
|
95
|
-
test("parallel wait=all propagates branch failure", async () => {
|
|
96
|
-
await assert.rejects(() => runWorkflow({
|
|
97
|
-
steps: [
|
|
98
|
-
{
|
|
99
|
-
id: "p",
|
|
100
|
-
parallel: {
|
|
101
|
-
wait: "all",
|
|
102
|
-
branches: [
|
|
103
|
-
{ id: "ok", command: "echo ok" },
|
|
104
|
-
{ id: "fail", command: 'node -e "process.exit(1)"' },
|
|
105
|
-
],
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
}), /Parallel branch failed/);
|
|
110
|
-
});
|
|
111
|
-
test("parallel pipeline branches reject command-level requestInput", async () => {
|
|
112
|
-
await assert.rejects(() => runWorkflow({
|
|
113
|
-
steps: [
|
|
114
|
-
{
|
|
115
|
-
id: "p",
|
|
116
|
-
parallel: {
|
|
117
|
-
wait: "all",
|
|
118
|
-
branches: [{ id: "review", pipeline: "ask --prompt 'Review?'" }],
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
],
|
|
122
|
-
}), /requestInput is not supported in this pipeline context/);
|
|
123
|
-
});
|
|
124
|
-
test("parallel validation rejects empty branches", async () => {
|
|
125
|
-
const tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), "lobster-parallel-"));
|
|
126
|
-
const filePath = path.join(tmpDir, "bad.lobster");
|
|
127
|
-
await fsp.writeFile(filePath, JSON.stringify({
|
|
128
|
-
steps: [{ id: "p", parallel: { branches: [] } }],
|
|
129
|
-
}), "utf8");
|
|
130
|
-
await assert.rejects(() => loadWorkflowFile(filePath), /non-empty branches/);
|
|
131
|
-
});
|
|
132
|
-
test("parallel validation rejects duplicate branch ids", async () => {
|
|
133
|
-
const tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), "lobster-parallel-"));
|
|
134
|
-
const filePath = path.join(tmpDir, "bad.lobster");
|
|
135
|
-
await fsp.writeFile(filePath, JSON.stringify({
|
|
136
|
-
steps: [
|
|
137
|
-
{
|
|
138
|
-
id: "p",
|
|
139
|
-
parallel: {
|
|
140
|
-
branches: [
|
|
141
|
-
{ id: "dup", command: "echo a" },
|
|
142
|
-
{ id: "dup", command: "echo b" },
|
|
143
|
-
],
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
}), "utf8");
|
|
148
|
-
await assert.rejects(() => loadWorkflowFile(filePath), /duplicate parallel branch id/);
|
|
149
|
-
});
|
|
150
|
-
test("parallel validation rejects branch without execution", async () => {
|
|
151
|
-
const tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), "lobster-parallel-"));
|
|
152
|
-
const filePath = path.join(tmpDir, "bad.lobster");
|
|
153
|
-
await fsp.writeFile(filePath, JSON.stringify({
|
|
154
|
-
steps: [
|
|
155
|
-
{
|
|
156
|
-
id: "p",
|
|
157
|
-
parallel: {
|
|
158
|
-
branches: [{ id: "empty" }],
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
],
|
|
162
|
-
}), "utf8");
|
|
163
|
-
await assert.rejects(() => loadWorkflowFile(filePath), /requires run, command, or pipeline/);
|
|
164
|
-
});
|
|
165
|
-
test("parallel timeout aborts block", async () => {
|
|
166
|
-
await assert.rejects(() => runWorkflow({
|
|
167
|
-
steps: [
|
|
168
|
-
{
|
|
169
|
-
id: "p",
|
|
170
|
-
parallel: {
|
|
171
|
-
wait: "all",
|
|
172
|
-
timeout_ms: 100,
|
|
173
|
-
branches: [
|
|
174
|
-
{
|
|
175
|
-
id: "slow",
|
|
176
|
-
command: "node -e \"setTimeout(() => process.stdout.write('ok'), 5000)\"",
|
|
177
|
-
},
|
|
178
|
-
],
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
}), /Parallel step p timed out after 100ms/);
|
|
183
|
-
});
|
|
184
|
-
//# sourceMappingURL=parallel.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.test.js","sourceRoot":"","sources":["../../test/parallel.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { parsePipeline } from "../src/parser.js";
|
|
4
|
-
test("parsePipeline splits stages and args", () => {
|
|
5
|
-
const p = parsePipeline("exec echo hi | where a=1 | pick id,subject");
|
|
6
|
-
assert.equal(p.length, 3);
|
|
7
|
-
assert.equal(p[0].name, "exec");
|
|
8
|
-
assert.deepEqual(p[0].args._, ["echo", "hi"]);
|
|
9
|
-
assert.equal(p[1].name, "where");
|
|
10
|
-
assert.equal(p[1].args._[0], "a=1");
|
|
11
|
-
assert.equal(p[2].name, "pick");
|
|
12
|
-
assert.equal(p[2].args._[0], "id,subject");
|
|
13
|
-
});
|
|
14
|
-
test("parsePipeline keeps quoted pipes", () => {
|
|
15
|
-
const p = parsePipeline("exec echo 'a|b' | json");
|
|
16
|
-
assert.equal(p.length, 2);
|
|
17
|
-
assert.deepEqual(p[0].args._, ["echo", "a|b"]);
|
|
18
|
-
});
|
|
19
|
-
test("parsePipeline preserves JSON escapes in double-quoted args", () => {
|
|
20
|
-
const p = parsePipeline('openclaw.invoke --tool llm-task --action json --args-json "{\\"prompt\\":\\"line1\\\\nline2\\",\\"schema\\":{\\"type\\":\\"object\\"}}"');
|
|
21
|
-
assert.equal(p.length, 1);
|
|
22
|
-
const raw = p[0].args["args-json"];
|
|
23
|
-
const parsed = JSON.parse(raw);
|
|
24
|
-
assert.equal(parsed.prompt, "line1\nline2");
|
|
25
|
-
assert.equal(parsed.schema.type, "object");
|
|
26
|
-
});
|
|
27
|
-
test("parsePipeline keeps single-quoted args literal", () => {
|
|
28
|
-
const p = parsePipeline('openclaw.invoke --args-json \'{"x":"a\\\\nb"}\'');
|
|
29
|
-
assert.equal(p.length, 1);
|
|
30
|
-
assert.equal(p[0].args["args-json"], '{"x":"a\\\\nb"}');
|
|
31
|
-
});
|
|
32
|
-
test("parsePipeline preserves escaped apostrophes in single-quoted args", () => {
|
|
33
|
-
const p = parsePipeline('openclaw.invoke --args-json \'{"prompt":"don\\\'t"}\'');
|
|
34
|
-
assert.equal(p.length, 1);
|
|
35
|
-
const raw = p[0].args["args-json"];
|
|
36
|
-
const parsed = JSON.parse(raw);
|
|
37
|
-
assert.equal(parsed.prompt, "don't");
|
|
38
|
-
});
|
|
39
|
-
test("parsePipeline parses inline --key=value arguments", () => {
|
|
40
|
-
const p = parsePipeline("where --field=name --limit=10");
|
|
41
|
-
assert.equal(p.length, 1);
|
|
42
|
-
assert.equal(p[0].args["field"], "name");
|
|
43
|
-
assert.equal(p[0].args["limit"], "10");
|
|
44
|
-
});
|
|
45
|
-
test("parsePipeline keeps an empty inline --key= value as an empty string", () => {
|
|
46
|
-
const p = parsePipeline("cmd --note=");
|
|
47
|
-
assert.equal(p[0].args["note"], "");
|
|
48
|
-
});
|
|
49
|
-
test("parsePipeline treats a trailing --flag as a boolean true", () => {
|
|
50
|
-
const p = parsePipeline("cmd --verbose");
|
|
51
|
-
assert.equal(p[0].args["verbose"], true);
|
|
52
|
-
});
|
|
53
|
-
test("parsePipeline treats --flag followed by another --flag as boolean", () => {
|
|
54
|
-
const p = parsePipeline("cmd --dry-run --out file");
|
|
55
|
-
assert.equal(p[0].args["dry-run"], true);
|
|
56
|
-
assert.equal(p[0].args["out"], "file");
|
|
57
|
-
});
|
|
58
|
-
test("parsePipeline keeps the command after exec --json", () => {
|
|
59
|
-
for (const command of ["cat rows.json", "'echo [1,2,3]'"]) {
|
|
60
|
-
const stage = parsePipeline(`exec --json ${command}`)[0];
|
|
61
|
-
assert.equal(stage.args["json"], true);
|
|
62
|
-
assert.deepEqual(stage.args._, command.startsWith("'") ? ["echo [1,2,3]"] : ["cat", "rows.json"]);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
test("parsePipeline preserves value-taking options beside exec --json", () => {
|
|
66
|
-
const stage = parsePipeline("exec --stdin json --json cat")[0];
|
|
67
|
-
assert.equal(stage.args["stdin"], "json");
|
|
68
|
-
assert.equal(stage.args["json"], true);
|
|
69
|
-
assert.deepEqual(stage.args._, ["cat"]);
|
|
70
|
-
assert.equal(parsePipeline("custom --json payload")[0].args["json"], "payload");
|
|
71
|
-
});
|
|
72
|
-
test("parsePipeline unescapes \\$ and \\` inside double quotes", () => {
|
|
73
|
-
const p = parsePipeline('echo "\\$HOME \\`id\\`"');
|
|
74
|
-
assert.deepEqual(p[0].args._, ["$HOME `id`"]);
|
|
75
|
-
});
|
|
76
|
-
test("parsePipeline joins a backslash-newline line continuation in double quotes", () => {
|
|
77
|
-
const p = parsePipeline('echo "line1\\\nline2"');
|
|
78
|
-
assert.deepEqual(p[0].args._, ["line1line2"]);
|
|
79
|
-
});
|
|
80
|
-
test("parsePipeline tolerates a trailing pipe (no empty final stage)", () => {
|
|
81
|
-
const p = parsePipeline("exec x |");
|
|
82
|
-
assert.equal(p.length, 1);
|
|
83
|
-
assert.equal(p[0].name, "exec");
|
|
84
|
-
});
|
|
85
|
-
test("parsePipeline throws on an empty or whitespace-only pipeline", () => {
|
|
86
|
-
assert.throws(() => parsePipeline(""), /Empty pipeline/);
|
|
87
|
-
assert.throws(() => parsePipeline(" "), /Empty pipeline/);
|
|
88
|
-
});
|
|
89
|
-
test("parsePipeline throws on an empty stage between pipes", () => {
|
|
90
|
-
assert.throws(() => parsePipeline("exec x | | json"), /Empty command stage/);
|
|
91
|
-
});
|
|
92
|
-
test("parsePipeline throws on an unclosed single or double quote", () => {
|
|
93
|
-
assert.throws(() => parsePipeline("exec 'unclosed"), /Unclosed quote/);
|
|
94
|
-
assert.throws(() => parsePipeline('exec "unclosed'), /Unclosed quote/);
|
|
95
|
-
});
|
|
96
|
-
//# sourceMappingURL=parser.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parser.test.js","sourceRoot":"","sources":["../../test/parser.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import os from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { mkdtemp, rm } from "node:fs/promises";
|
|
6
|
-
import { writeStateJson } from "../src/state/store.js";
|
|
7
|
-
import { loadPipelineResumeState } from "../src/pipeline_resume_state.js";
|
|
8
|
-
function validApprovalState() {
|
|
9
|
-
return {
|
|
10
|
-
pipeline: [{ name: "map", args: {}, raw: "map" }],
|
|
11
|
-
resumeAtIndex: 1,
|
|
12
|
-
items: [{ n: 1 }],
|
|
13
|
-
haltType: "approval_request",
|
|
14
|
-
prompt: "approve?",
|
|
15
|
-
createdAt: "2026-01-01T00:00:00.000Z",
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
async function loadStored(value) {
|
|
19
|
-
const dir = await mkdtemp(path.join(os.tmpdir(), "lobster-pipeline-resume-"));
|
|
20
|
-
const env = { LOBSTER_STATE_DIR: dir };
|
|
21
|
-
try {
|
|
22
|
-
await writeStateJson({ env, key: "resume", value });
|
|
23
|
-
return await loadPipelineResumeState(env, "resume");
|
|
24
|
-
}
|
|
25
|
-
finally {
|
|
26
|
-
await rm(dir, { recursive: true, force: true });
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
test("loadPipelineResumeState rejects a pipeline stage without a name", async () => {
|
|
30
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), pipeline: [{ args: {}, raw: "map" }] }), /Invalid pipeline resume state/);
|
|
31
|
-
});
|
|
32
|
-
test("loadPipelineResumeState rejects a pipeline stage whose args is an array", async () => {
|
|
33
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), pipeline: [{ name: "map", args: [], raw: "map" }] }), /Invalid pipeline resume state/);
|
|
34
|
-
});
|
|
35
|
-
test("loadPipelineResumeState rejects a resume index past the pipeline length", async () => {
|
|
36
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), resumeAtIndex: 2 }), /Invalid pipeline resume state/);
|
|
37
|
-
});
|
|
38
|
-
test("loadPipelineResumeState rejects a negative resume index", async () => {
|
|
39
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), resumeAtIndex: -1 }), /Invalid pipeline resume state/);
|
|
40
|
-
});
|
|
41
|
-
test("loadPipelineResumeState rejects non-array items", async () => {
|
|
42
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), items: "nope" }), /Invalid pipeline resume state/);
|
|
43
|
-
});
|
|
44
|
-
test("loadPipelineResumeState rejects superseded keys that are not strings", async () => {
|
|
45
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), supersededResumeStateKeys: [1] }), /Invalid pipeline resume state/);
|
|
46
|
-
});
|
|
47
|
-
test("loadPipelineResumeState rejects an unrecognized halt type", async () => {
|
|
48
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), haltType: "other" }), /Invalid pipeline resume state/);
|
|
49
|
-
});
|
|
50
|
-
test("loadPipelineResumeState rejects an unrecognized resume mode", async () => {
|
|
51
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), resumeMode: "sideways" }), /Invalid pipeline resume state/);
|
|
52
|
-
});
|
|
53
|
-
test("loadPipelineResumeState rejects an input request without a schema", async () => {
|
|
54
|
-
await assert.rejects(() => loadStored({
|
|
55
|
-
...validApprovalState(),
|
|
56
|
-
items: [],
|
|
57
|
-
haltType: "input_request",
|
|
58
|
-
resumeMode: "next_stage",
|
|
59
|
-
prompt: "enter",
|
|
60
|
-
}), /Invalid pipeline resume state/);
|
|
61
|
-
});
|
|
62
|
-
test("loadPipelineResumeState rejects command input outside a same-stage input resume", async () => {
|
|
63
|
-
await assert.rejects(() => loadStored({ ...validApprovalState(), commandInput: { history: [] } }), /Invalid pipeline resume state/);
|
|
64
|
-
});
|
|
65
|
-
//# sourceMappingURL=pipeline_resume_state.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline_resume_state.test.js","sourceRoot":"","sources":["../../test/pipeline_resume_state.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { execFile, spawn, spawnSync } from "node:child_process";
|
|
4
|
-
import { mkdtemp, writeFile, readFile, rm } from "node:fs/promises";
|
|
5
|
-
import { tmpdir } from "node:os";
|
|
6
|
-
import path from "node:path";
|
|
7
|
-
import { promisify } from "node:util";
|
|
8
|
-
import { Lobster, exec } from "../src/sdk/index.js";
|
|
9
|
-
import { runAbortableProcess } from "../src/abortable_process.js";
|
|
10
|
-
import { waitForPid } from "./helpers/wait_for_pid.js";
|
|
11
|
-
import { nodeShellFixture } from "./helpers/node_shell_fixture.js";
|
|
12
|
-
const run = promisify(execFile);
|
|
13
|
-
const large = 10 * 1024 * 1024 + 1;
|
|
14
|
-
const cli = path.resolve("bin/lobster.js");
|
|
15
|
-
const quote = (s) => JSON.stringify(s);
|
|
16
|
-
for (const stream of ["stdout", "stderr"]) {
|
|
17
|
-
test(`SDK ${stream} is unlimited by default and honors the opt-in byte limit`, async () => {
|
|
18
|
-
const dir = await mkdtemp(path.join(tmpdir(), "lobster-output-"));
|
|
19
|
-
try {
|
|
20
|
-
const file = path.join(dir, "emit.cjs");
|
|
21
|
-
await writeFile(file, `process.${stream}.write('x'.repeat(${large}));`);
|
|
22
|
-
for (const limit of ["", "1024"]) {
|
|
23
|
-
const result = await new Lobster({
|
|
24
|
-
env: { ...process.env, LOBSTER_MAX_OUTPUT_BYTES: limit },
|
|
25
|
-
})
|
|
26
|
-
.pipe(exec(`${quote(process.execPath)} ${quote(file)}`, { json: false }))
|
|
27
|
-
.run();
|
|
28
|
-
assert.equal(result.ok, limit === "");
|
|
29
|
-
if (limit)
|
|
30
|
-
assert.match(result.error.message, /Process output exceeded 1024 bytes/);
|
|
31
|
-
else
|
|
32
|
-
assert.equal(result.output[0].length, stream === "stdout" ? large : 0);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
finally {
|
|
36
|
-
await rm(dir, { recursive: true, force: true });
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
test("process caps count actual bytes and accept the exact boundary", async () => {
|
|
41
|
-
for (const bytes of [Buffer.from("😀"), Buffer.from([0xff, 0xff, 0xff, 0xff])]) {
|
|
42
|
-
const result = await runAbortableProcess({
|
|
43
|
-
command: process.execPath,
|
|
44
|
-
argv: ["-e", `process.stdout.write(Buffer.from('${bytes.toString("hex")}', 'hex'))`],
|
|
45
|
-
env: { ...process.env, LOBSTER_MAX_OUTPUT_BYTES: "4" },
|
|
46
|
-
notFoundMessage: "node missing",
|
|
47
|
-
});
|
|
48
|
-
assert.equal(result.stdout, bytes.toString("utf8"));
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
test("invalid process limits fail before spawning", async () => {
|
|
52
|
-
const dir = await mkdtemp(path.join(tmpdir(), "lobster-invalid-limit-"));
|
|
53
|
-
try {
|
|
54
|
-
const marker = path.join(dir, "started");
|
|
55
|
-
for (const value of ["0", "-1", "1.5", "Infinity", "true", "9007199254740992"]) {
|
|
56
|
-
await assert.rejects(runAbortableProcess({
|
|
57
|
-
command: process.execPath,
|
|
58
|
-
argv: ["-e", `require('node:fs').writeFileSync(${quote(marker)}, 'started')`],
|
|
59
|
-
env: { ...process.env, LOBSTER_MAX_OUTPUT_BYTES: value },
|
|
60
|
-
notFoundMessage: "node missing",
|
|
61
|
-
}), /LOBSTER_MAX_OUTPUT_BYTES must be a positive safe integer/);
|
|
62
|
-
}
|
|
63
|
-
await assert.rejects(readFile(marker), { code: "ENOENT" });
|
|
64
|
-
}
|
|
65
|
-
finally {
|
|
66
|
-
await rm(dir, { recursive: true, force: true });
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
test("built CLI exec and workflow env preserve unlimited output and enable finite limits", async () => {
|
|
70
|
-
const dir = await mkdtemp(path.join(tmpdir(), "lobster-cli-limit-"));
|
|
71
|
-
try {
|
|
72
|
-
const file = path.join(dir, "emit.cjs");
|
|
73
|
-
await writeFile(file, `process.stdout.write('x'.repeat(${large}));`);
|
|
74
|
-
const command = `${quote(process.execPath)} ${quote(file)}`;
|
|
75
|
-
for (const workflow of [false, true]) {
|
|
76
|
-
for (const limit of ["", "1024"]) {
|
|
77
|
-
const filePath = path.join(dir, "workflow.json");
|
|
78
|
-
await writeFile(filePath, JSON.stringify({
|
|
79
|
-
steps: [{ id: "emit", run: command, env: { LOBSTER_MAX_OUTPUT_BYTES: limit } }],
|
|
80
|
-
}));
|
|
81
|
-
const args = workflow ? ["--file", filePath] : [`exec ${command}`];
|
|
82
|
-
const result = await run(process.execPath, [cli, "run", "--mode", "tool", ...args], {
|
|
83
|
-
env: {
|
|
84
|
-
...process.env,
|
|
85
|
-
LOBSTER_MAX_OUTPUT_BYTES: workflow ? "" : limit,
|
|
86
|
-
LOBSTER_STATE_DIR: path.join(dir, "state"),
|
|
87
|
-
},
|
|
88
|
-
maxBuffer: 20 * 1024 * 1024,
|
|
89
|
-
}).then((r) => ({ code: 0, stdout: r.stdout }), (e) => ({ code: e.code, stdout: e.stdout }));
|
|
90
|
-
const envelope = JSON.parse(result.stdout);
|
|
91
|
-
assert.equal(envelope.ok, limit === "");
|
|
92
|
-
if (limit)
|
|
93
|
-
assert.match(envelope.error.message, /Process output exceeded 1024 bytes/);
|
|
94
|
-
else
|
|
95
|
-
assert.equal(envelope.output[0].length, large);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
finally {
|
|
100
|
-
await rm(dir, { recursive: true, force: true });
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
function isAlive(pid) {
|
|
104
|
-
const stat = spawnSync("ps", ["-o", "stat=", "-p", String(pid)], {
|
|
105
|
-
encoding: "utf8",
|
|
106
|
-
}).stdout.trim();
|
|
107
|
-
return stat !== "" && !stat.startsWith("Z");
|
|
108
|
-
}
|
|
109
|
-
for (const mode of ["overflow", "interrupt", "host-handler", "once-handler", "host-exit"]) {
|
|
110
|
-
test(`capped no-signal SDK shell cleans its background producer on ${mode}`, { skip: process.platform === "win32", timeout: 15_000 }, async () => {
|
|
111
|
-
const dir = await mkdtemp(path.join(tmpdir(), "lobster-output-tree-"));
|
|
112
|
-
let wrapper;
|
|
113
|
-
let pid;
|
|
114
|
-
try {
|
|
115
|
-
const runner = path.join(dir, "runner.mjs");
|
|
116
|
-
const marker = path.join(dir, "pid"), received = path.join(dir, "signal");
|
|
117
|
-
const fixture = await nodeShellFixture(dir, `const fs=require('node:fs');
|
|
118
|
-
process.on('SIGTERM',()=>{});
|
|
119
|
-
process.on('SIGINT',()=>fs.writeFileSync(${quote(received)}, 'SIGINT'));
|
|
120
|
-
fs.writeFileSync(${quote(marker)},String(process.pid));
|
|
121
|
-
setInterval(()=>{${mode === "overflow" ? "process.stdout.write('x'.repeat(2048));" : ""}},30);`);
|
|
122
|
-
await writeFile(runner, `import {Lobster,exec} from ${quote(new URL("../src/sdk/index.js", import.meta.url).href)};
|
|
123
|
-
${mode === "host-handler" || mode === "once-handler" ? `process.${mode === "once-handler" ? "once" : "on"}('SIGINT',()=>console.log('host handled SIGINT'));` : ""}
|
|
124
|
-
${mode === "host-exit" ? "process.on('SIGUSR2',()=>process.exit(0));" : ""}
|
|
125
|
-
const result=await new Lobster({env:{...process.env,LOBSTER_MAX_OUTPUT_BYTES:'1024'}})
|
|
126
|
-
.pipe(exec(${quote(`${fixture.command} & wait`)},{shell:true,json:false})).run();
|
|
127
|
-
console.log(JSON.stringify(result));`);
|
|
128
|
-
wrapper = spawn(process.execPath, [runner], {
|
|
129
|
-
env: { ...process.env, ...fixture.env },
|
|
130
|
-
detached: true,
|
|
131
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
132
|
-
});
|
|
133
|
-
let stdout = "", stderr = "";
|
|
134
|
-
wrapper.stdout.on("data", (x) => (stdout += x));
|
|
135
|
-
wrapper.stderr.on("data", (x) => (stderr += x));
|
|
136
|
-
const closed = new Promise((resolve) => wrapper.once("close", resolve));
|
|
137
|
-
pid = await waitForPid(marker);
|
|
138
|
-
if (mode === "interrupt" || mode === "host-handler" || mode === "once-handler")
|
|
139
|
-
wrapper.kill("SIGINT");
|
|
140
|
-
if (mode === "host-exit")
|
|
141
|
-
wrapper.kill("SIGUSR2");
|
|
142
|
-
let timer;
|
|
143
|
-
const code = await Promise.race([
|
|
144
|
-
closed,
|
|
145
|
-
new Promise((_, reject) => {
|
|
146
|
-
timer = setTimeout(() => reject(new Error(`wrapper hung: ${stderr}`)), 5000);
|
|
147
|
-
}),
|
|
148
|
-
]).finally(() => clearTimeout(timer));
|
|
149
|
-
assert.equal(code, mode === "interrupt" ? 130 : 0, stderr);
|
|
150
|
-
assert.equal(isAlive(pid), false, "producer must not survive its owner");
|
|
151
|
-
if (mode === "overflow")
|
|
152
|
-
assert.match(stdout, /Process output exceeded 1024 bytes/);
|
|
153
|
-
if (mode === "host-handler" || mode === "once-handler")
|
|
154
|
-
assert.match(stdout, /host handled SIGINT/);
|
|
155
|
-
if (mode === "interrupt" || mode === "host-handler" || mode === "once-handler")
|
|
156
|
-
assert.equal(await readFile(received, "utf8"), "SIGINT");
|
|
157
|
-
}
|
|
158
|
-
finally {
|
|
159
|
-
if (pid) {
|
|
160
|
-
try {
|
|
161
|
-
process.kill(pid, "SIGKILL");
|
|
162
|
-
}
|
|
163
|
-
catch { }
|
|
164
|
-
}
|
|
165
|
-
if (wrapper?.pid) {
|
|
166
|
-
try {
|
|
167
|
-
process.kill(-wrapper.pid, "SIGKILL");
|
|
168
|
-
}
|
|
169
|
-
catch { }
|
|
170
|
-
}
|
|
171
|
-
await rm(dir, { recursive: true, force: true });
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
//# sourceMappingURL=process_output_limit.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"process_output_limit.test.js","sourceRoot":"","sources":["../../test/process_output_limit.test.ts"],"names":[],"mappings":"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"}
|