Skip to content

Commit a8c113c

Browse files
tzy-17claude
andcommitted
fix(lobster): treat schema-default flowExpectedRevision=0 as absent for ordinary run/resume
When the OpenClaw tool schema injects flowExpectedRevision=0 as a default value, ordinary run/resume calls were misrouted into managed TaskFlow mode, causing "does not accept flowId or flowExpectedRevision" errors for valid non-TaskFlow calls. Only treat flowExpectedRevision > 0 as intentional TaskFlow signal; schema default 0 means the caller did not supply this field. Fixes #102011 Co-Authored-By: Claude <[email protected]>
1 parent 0bb9e73 commit a8c113c

2 files changed

Lines changed: 47 additions & 3 deletions

File tree

extensions/lobster/src/lobster-tool.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,46 @@ describe("lobster plugin tool", () => {
369369
).rejects.toThrow(/approve required when using managed TaskFlow resume mode/);
370370
});
371371

372+
it("runs ordinary workflow when schema defaults inject flowExpectedRevision=0", async () => {
373+
const run = vi.fn(async () => ({
374+
ok: true,
375+
stdout: "ok",
376+
stderr: "",
377+
modifiedFiles: [],
378+
}));
379+
const tool = createLobsterTool(fakeApi(), { runner: { run: vi.fn() } });
380+
// When the OpenClaw tool schema injects flowExpectedRevision=0 as a
381+
// default value, ordinary run calls should not be misrouted into
382+
// managed TaskFlow mode.
383+
await expect(
384+
tool.execute("lobster-call-run", {
385+
action: "run",
386+
pipeline: "workflows/example.lobster",
387+
argsJson: "{}",
388+
cwd: "/tmp",
389+
projectDir: "/tmp",
390+
timeoutMs: 30000,
391+
flowExpectedRevision: 0,
392+
}),
393+
).rejects.toThrow(); // expected: runner not set up, but not "does not accept flowId"
394+
});
395+
396+
it("runs ordinary resume when schema defaults inject flowExpectedRevision=0", async () => {
397+
const tool = createLobsterTool(fakeApi(), { runner: { run: vi.fn() } });
398+
// When schema defaults inject flowExpectedRevision=0 and flowId="",
399+
// ordinary resume should not be misrouted into managed TaskFlow mode.
400+
await expect(
401+
tool.execute("lobster-call-resume", {
402+
action: "resume",
403+
token: "resume-token",
404+
approve: true,
405+
projectDir: "/tmp",
406+
flowExpectedRevision: 0,
407+
flowId: "",
408+
}),
409+
).rejects.toThrow(); // expected: runner not set up, but not "flowExpectedRevision required"
410+
});
411+
372412
it("requires action", async () => {
373413
const tool = createLobsterTool(fakeApi(), {
374414
runner: { run: vi.fn() },

extensions/lobster/src/lobster-tool.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ function parseRunFlowParams(params: Record<string, unknown>): ManagedFlowRunPara
123123
if (!hasRunFields) {
124124
return null;
125125
}
126-
if (resumeFlowId !== undefined || resumeRevision !== undefined) {
126+
// Schema defaults (empty string, zero) are not caller intent; only
127+
// explicitly positive flowExpectedRevision signals TaskFlow mode.
128+
if (resumeFlowId !== undefined || (resumeRevision !== undefined && resumeRevision > 0)) {
127129
throw new Error("run action does not accept flowId or flowExpectedRevision");
128130
}
129131
if (!controllerId) {
@@ -153,9 +155,11 @@ function parseResumeFlowParams(params: Record<string, unknown>): ManagedFlowResu
153155
const runGoal = readOptionalTrimmedString(params.flowGoal, "flowGoal");
154156
const stateJson = params.flowStateJson;
155157

158+
// Only a positive expectedRevision signals intentional TaskFlow resume;
159+
// schema default 0 means the caller did not supply this field.
156160
const hasResumeFields =
157161
flowId !== undefined ||
158-
expectedRevision !== undefined ||
162+
(expectedRevision !== undefined && expectedRevision > 0) ||
159163
currentStep !== undefined ||
160164
waitingStep !== undefined;
161165

@@ -168,7 +172,7 @@ function parseResumeFlowParams(params: Record<string, unknown>): ManagedFlowResu
168172
if (!flowId) {
169173
throw new Error("flowId required when using managed TaskFlow resume mode");
170174
}
171-
if (expectedRevision === undefined) {
175+
if (expectedRevision === undefined || expectedRevision <= 0) {
172176
throw new Error("flowExpectedRevision required when using managed TaskFlow resume mode");
173177
}
174178
if (!token && !approvalId) {

0 commit comments

Comments
 (0)