






















@@ -134,6 +134,46 @@ describe("createEmbeddedLobsterRunner", () => {
134134});
135135});
136136137+it.each([
138+"exec --json=true cat data.json",
139+"exec --json=true cat config.yaml",
140+"exec --json=true cat flow.lobster",
141+"exec --json=true cat /tmp/missing.json",
142+"http.fetch https://example.test/workflows/flow.lobster",
143+"exec --json=true echo nested/path",
144+])("keeps inline pipeline with file-like args as a pipeline: %s", async (pipeline) => {
145+const runtime = {
146+runToolRequest: vi.fn().mockResolvedValue({
147+ok: true,
148+protocolVersion: 1,
149+status: "ok",
150+output: [],
151+requiresApproval: null,
152+}),
153+resumeToolRequest: vi.fn(),
154+};
155+156+const runner = createEmbeddedLobsterRunner({
157+loadRuntime: vi.fn().mockResolvedValue(runtime),
158+});
159+160+await runner.run({
161+action: "run",
162+ pipeline,
163+cwd: process.cwd(),
164+timeoutMs: 2000,
165+maxStdoutBytes: 4096,
166+});
167+168+expect(runtime.runToolRequest).toHaveBeenCalledOnce();
169+const request = requireRecord(
170+requireFirstCallParam(runtime.runToolRequest.mock.calls, "inline run tool request"),
171+"inline run tool request",
172+);
173+expect(request.pipeline).toBe(pipeline);
174+expect(request.filePath).toBeUndefined();
175+});
176+137177it("detects workflow files and parses argsJson", async () => {
138178const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-lobster-runner-"));
139179const workflowPath = path.join(tempDir, "workflow.lobster");
@@ -177,6 +217,80 @@ describe("createEmbeddedLobsterRunner", () => {
177217}
178218});
179219220+it("detects existing workflow file paths that contain spaces", async () => {
221+const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-lobster-runner-"));
222+const workflowPath = path.join(tempDir, "daily inbox.lobster");
223+await fs.writeFile(workflowPath, "steps: []\n", "utf8");
224+225+try {
226+const runtime = {
227+runToolRequest: vi.fn().mockResolvedValue({
228+ok: true,
229+protocolVersion: 1,
230+status: "ok",
231+output: [],
232+requiresApproval: null,
233+}),
234+resumeToolRequest: vi.fn(),
235+};
236+237+const runner = createEmbeddedLobsterRunner({
238+loadRuntime: vi.fn().mockResolvedValue(runtime),
239+});
240+241+await runner.run({
242+action: "run",
243+pipeline: "daily inbox.lobster",
244+cwd: tempDir,
245+timeoutMs: 2000,
246+maxStdoutBytes: 4096,
247+});
248+249+expect(runtime.runToolRequest).toHaveBeenCalledOnce();
250+const request = requireRecord(
251+requireFirstCallParam(runtime.runToolRequest.mock.calls, "workflow file with spaces"),
252+"workflow file with spaces",
253+);
254+expect(request.filePath).toBe(workflowPath);
255+expect(request.pipeline).toBeUndefined();
256+} finally {
257+await fs.rm(tempDir, { recursive: true, force: true });
258+}
259+});
260+261+it.each([
262+["missing.lobster", "missing.lobster"],
263+["nested/missing.yaml", path.join("nested", "missing.yaml")],
264+])("surfaces missing workflow path errors for %s", async (pipeline, expectedRelativePath) => {
265+const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-lobster-runner-"));
266+267+try {
268+const runtime = {
269+runToolRequest: vi.fn(),
270+resumeToolRequest: vi.fn(),
271+};
272+const runner = createEmbeddedLobsterRunner({
273+loadRuntime: vi.fn().mockResolvedValue(runtime),
274+});
275+276+await expect(
277+runner.run({
278+action: "run",
279+ pipeline,
280+cwd: tempDir,
281+timeoutMs: 2000,
282+maxStdoutBytes: 4096,
283+}),
284+).rejects.toMatchObject({
285+code: "ENOENT",
286+path: path.join(tempDir, expectedRelativePath),
287+});
288+expect(runtime.runToolRequest).not.toHaveBeenCalled();
289+} finally {
290+await fs.rm(tempDir, { recursive: true, force: true });
291+}
292+});
293+180294it("returns a parse error when workflow args are invalid JSON", async () => {
181295const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-lobster-runner-"));
182296const workflowPath = path.join(tempDir, "workflow.lobster");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。