@openclaw/lobster 2026.3.13 → 2026.5.2-beta.1
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 +1 -2
- package/index.ts +22 -16
- package/openclaw.plugin.json +6 -0
- package/package.json +27 -3
- package/runtime-api.ts +12 -0
- package/src/lobster-ajv-cache.ts +142 -0
- package/src/lobster-core.d.ts +60 -0
- package/src/lobster-runner.test.ts +572 -0
- package/src/lobster-runner.ts +395 -0
- package/src/lobster-taskflow.test.ts +227 -0
- package/src/lobster-taskflow.ts +279 -0
- package/src/lobster-tool.test.ts +250 -208
- package/src/lobster-tool.ts +245 -191
- package/src/taskflow-test-helpers.ts +48 -0
- package/tsconfig.json +16 -0
- package/src/test-helpers.ts +0 -43
- package/src/windows-spawn.test.ts +0 -118
- package/src/windows-spawn.ts +0 -36
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
5
|
-
import {
|
|
6
|
-
createWindowsCmdShimFixture,
|
|
7
|
-
restorePlatformPathEnv,
|
|
8
|
-
setProcessPlatform,
|
|
9
|
-
snapshotPlatformPathEnv,
|
|
10
|
-
} from "./test-helpers.js";
|
|
11
|
-
import { resolveWindowsLobsterSpawn } from "./windows-spawn.js";
|
|
12
|
-
|
|
13
|
-
describe("resolveWindowsLobsterSpawn", () => {
|
|
14
|
-
let tempDir = "";
|
|
15
|
-
const originalProcessState = snapshotPlatformPathEnv();
|
|
16
|
-
|
|
17
|
-
async function expectUnwrappedShim(params: {
|
|
18
|
-
scriptPath: string;
|
|
19
|
-
shimPath: string;
|
|
20
|
-
shimLine: string;
|
|
21
|
-
}) {
|
|
22
|
-
await createWindowsCmdShimFixture(params);
|
|
23
|
-
|
|
24
|
-
const target = resolveWindowsLobsterSpawn(params.shimPath, ["run", "noop"], process.env);
|
|
25
|
-
expect(target.command).toBe(process.execPath);
|
|
26
|
-
expect(target.argv).toEqual([params.scriptPath, "run", "noop"]);
|
|
27
|
-
expect(target.windowsHide).toBe(true);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
beforeEach(async () => {
|
|
31
|
-
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-lobster-win-spawn-"));
|
|
32
|
-
setProcessPlatform("win32");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
afterEach(async () => {
|
|
36
|
-
restorePlatformPathEnv(originalProcessState);
|
|
37
|
-
if (tempDir) {
|
|
38
|
-
await fs.rm(tempDir, { recursive: true, force: true });
|
|
39
|
-
tempDir = "";
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("unwraps cmd shim with %dp0% token", async () => {
|
|
44
|
-
const scriptPath = path.join(tempDir, "shim-dist", "lobster-cli.cjs");
|
|
45
|
-
const shimPath = path.join(tempDir, "shim", "lobster.cmd");
|
|
46
|
-
await expectUnwrappedShim({
|
|
47
|
-
shimPath,
|
|
48
|
-
scriptPath,
|
|
49
|
-
shimLine: `"%dp0%\\..\\shim-dist\\lobster-cli.cjs" %*`,
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("unwraps cmd shim with %~dp0% token", async () => {
|
|
54
|
-
const scriptPath = path.join(tempDir, "shim-dist", "lobster-cli.cjs");
|
|
55
|
-
const shimPath = path.join(tempDir, "shim", "lobster.cmd");
|
|
56
|
-
await expectUnwrappedShim({
|
|
57
|
-
shimPath,
|
|
58
|
-
scriptPath,
|
|
59
|
-
shimLine: `"%~dp0%\\..\\shim-dist\\lobster-cli.cjs" %*`,
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("ignores node.exe shim entries and picks lobster script", async () => {
|
|
64
|
-
const shimDir = path.join(tempDir, "shim-with-node");
|
|
65
|
-
const scriptPath = path.join(tempDir, "shim-dist-node", "lobster-cli.cjs");
|
|
66
|
-
const shimPath = path.join(shimDir, "lobster.cmd");
|
|
67
|
-
await fs.mkdir(path.dirname(scriptPath), { recursive: true });
|
|
68
|
-
await fs.mkdir(shimDir, { recursive: true });
|
|
69
|
-
await fs.writeFile(path.join(shimDir, "node.exe"), "", "utf8");
|
|
70
|
-
await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8");
|
|
71
|
-
await fs.writeFile(
|
|
72
|
-
shimPath,
|
|
73
|
-
`@echo off\r\n"%~dp0%\\node.exe" "%~dp0%\\..\\shim-dist-node\\lobster-cli.cjs" %*\r\n`,
|
|
74
|
-
"utf8",
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
const target = resolveWindowsLobsterSpawn(shimPath, ["run", "noop"], process.env);
|
|
78
|
-
expect(target.command).toBe(process.execPath);
|
|
79
|
-
expect(target.argv).toEqual([scriptPath, "run", "noop"]);
|
|
80
|
-
expect(target.windowsHide).toBe(true);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("resolves lobster.cmd from PATH and unwraps npm layout shim", async () => {
|
|
84
|
-
const binDir = path.join(tempDir, "node_modules", ".bin");
|
|
85
|
-
const packageDir = path.join(tempDir, "node_modules", "lobster");
|
|
86
|
-
const scriptPath = path.join(packageDir, "dist", "cli.js");
|
|
87
|
-
const shimPath = path.join(binDir, "lobster.cmd");
|
|
88
|
-
await fs.mkdir(path.dirname(scriptPath), { recursive: true });
|
|
89
|
-
await fs.mkdir(binDir, { recursive: true });
|
|
90
|
-
await fs.writeFile(shimPath, "@echo off\r\n", "utf8");
|
|
91
|
-
await fs.writeFile(
|
|
92
|
-
path.join(packageDir, "package.json"),
|
|
93
|
-
JSON.stringify({ name: "lobster", version: "0.0.0", bin: { lobster: "dist/cli.js" } }),
|
|
94
|
-
"utf8",
|
|
95
|
-
);
|
|
96
|
-
await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8");
|
|
97
|
-
|
|
98
|
-
const env = {
|
|
99
|
-
...process.env,
|
|
100
|
-
PATH: `${binDir};${process.env.PATH ?? ""}`,
|
|
101
|
-
PATHEXT: ".CMD;.EXE",
|
|
102
|
-
};
|
|
103
|
-
const target = resolveWindowsLobsterSpawn("lobster", ["run", "noop"], env);
|
|
104
|
-
expect(target.command).toBe(process.execPath);
|
|
105
|
-
expect(target.argv).toEqual([scriptPath, "run", "noop"]);
|
|
106
|
-
expect(target.windowsHide).toBe(true);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("fails fast when wrapper cannot be resolved without shell execution", async () => {
|
|
110
|
-
const badShimPath = path.join(tempDir, "bad-shim", "lobster.cmd");
|
|
111
|
-
await fs.mkdir(path.dirname(badShimPath), { recursive: true });
|
|
112
|
-
await fs.writeFile(badShimPath, "@echo off\r\nREM no entrypoint\r\n", "utf8");
|
|
113
|
-
|
|
114
|
-
expect(() => resolveWindowsLobsterSpawn(badShimPath, ["run", "noop"], process.env)).toThrow(
|
|
115
|
-
/without shell execution/,
|
|
116
|
-
);
|
|
117
|
-
});
|
|
118
|
-
});
|
package/src/windows-spawn.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
applyWindowsSpawnProgramPolicy,
|
|
3
|
-
materializeWindowsSpawnProgram,
|
|
4
|
-
resolveWindowsSpawnProgramCandidate,
|
|
5
|
-
} from "openclaw/plugin-sdk/lobster";
|
|
6
|
-
|
|
7
|
-
type SpawnTarget = {
|
|
8
|
-
command: string;
|
|
9
|
-
argv: string[];
|
|
10
|
-
windowsHide?: boolean;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export function resolveWindowsLobsterSpawn(
|
|
14
|
-
execPath: string,
|
|
15
|
-
argv: string[],
|
|
16
|
-
env: NodeJS.ProcessEnv,
|
|
17
|
-
): SpawnTarget {
|
|
18
|
-
const candidate = resolveWindowsSpawnProgramCandidate({
|
|
19
|
-
command: execPath,
|
|
20
|
-
env,
|
|
21
|
-
packageName: "lobster",
|
|
22
|
-
});
|
|
23
|
-
const program = applyWindowsSpawnProgramPolicy({
|
|
24
|
-
candidate,
|
|
25
|
-
allowShellFallback: false,
|
|
26
|
-
});
|
|
27
|
-
const resolved = materializeWindowsSpawnProgram(program, argv);
|
|
28
|
-
if (resolved.shell) {
|
|
29
|
-
throw new Error("lobster wrapper resolved to shell fallback unexpectedly");
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
command: resolved.command,
|
|
33
|
-
argv: resolved.argv,
|
|
34
|
-
windowsHide: resolved.windowsHide,
|
|
35
|
-
};
|
|
36
|
-
}
|