@openclaw/lobster 2026.2.22 → 2026.2.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/lobster",
3
- "version": "2026.2.22",
3
+ "version": "2026.2.24",
4
4
  "description": "Lobster workflow tool plugin (typed pipelines + resumable approvals)",
5
5
  "type": "module",
6
6
  "openclaw": {
@@ -5,6 +5,12 @@ import path from "node:path";
5
5
  import { PassThrough } from "node:stream";
6
6
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
7
7
  import type { OpenClawPluginApi, OpenClawPluginToolContext } from "../../../src/plugins/types.js";
8
+ import {
9
+ createWindowsCmdShimFixture,
10
+ restorePlatformPathEnv,
11
+ setProcessPlatform,
12
+ snapshotPlatformPathEnv,
13
+ } from "./test-helpers.js";
8
14
 
9
15
  const spawnState = vi.hoisted(() => ({
10
16
  queue: [] as Array<{ stdout: string; stderr?: string; exitCode?: number }>,
@@ -57,20 +63,9 @@ function fakeCtx(overrides: Partial<OpenClawPluginToolContext> = {}): OpenClawPl
57
63
  };
58
64
  }
59
65
 
60
- function setProcessPlatform(platform: NodeJS.Platform) {
61
- Object.defineProperty(process, "platform", {
62
- value: platform,
63
- configurable: true,
64
- });
65
- }
66
-
67
66
  describe("lobster plugin tool", () => {
68
67
  let tempDir = "";
69
- const originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
70
- const originalPath = process.env.PATH;
71
- const originalPathAlt = process.env.Path;
72
- const originalPathExt = process.env.PATHEXT;
73
- const originalPathExtAlt = process.env.Pathext;
68
+ const originalProcessState = snapshotPlatformPathEnv();
74
69
 
75
70
  beforeAll(async () => {
76
71
  ({ createLobsterTool } = await import("./lobster-tool.js"));
@@ -79,29 +74,7 @@ describe("lobster plugin tool", () => {
79
74
  });
80
75
 
81
76
  afterEach(() => {
82
- if (originalPlatform) {
83
- Object.defineProperty(process, "platform", originalPlatform);
84
- }
85
- if (originalPath === undefined) {
86
- delete process.env.PATH;
87
- } else {
88
- process.env.PATH = originalPath;
89
- }
90
- if (originalPathAlt === undefined) {
91
- delete process.env.Path;
92
- } else {
93
- process.env.Path = originalPathAlt;
94
- }
95
- if (originalPathExt === undefined) {
96
- delete process.env.PATHEXT;
97
- } else {
98
- process.env.PATHEXT = originalPathExt;
99
- }
100
- if (originalPathExtAlt === undefined) {
101
- delete process.env.Pathext;
102
- } else {
103
- process.env.Pathext = originalPathExtAlt;
104
- }
77
+ restorePlatformPathEnv(originalProcessState);
105
78
  });
106
79
 
107
80
  afterAll(async () => {
@@ -156,17 +129,6 @@ describe("lobster plugin tool", () => {
156
129
  });
157
130
  };
158
131
 
159
- const createWindowsShimFixture = async (params: {
160
- shimPath: string;
161
- scriptPath: string;
162
- scriptToken: string;
163
- }) => {
164
- await fs.mkdir(path.dirname(params.scriptPath), { recursive: true });
165
- await fs.mkdir(path.dirname(params.shimPath), { recursive: true });
166
- await fs.writeFile(params.scriptPath, "module.exports = {};\n", "utf8");
167
- await fs.writeFile(params.shimPath, `@echo off\r\n"${params.scriptToken}" %*\r\n`, "utf8");
168
- };
169
-
170
132
  it("runs lobster and returns parsed envelope in details", async () => {
171
133
  spawnState.queue.push({
172
134
  stdout: JSON.stringify({
@@ -281,10 +243,10 @@ describe("lobster plugin tool", () => {
281
243
  setProcessPlatform("win32");
282
244
  const shimScriptPath = path.join(tempDir, "shim-dist", "lobster-cli.cjs");
283
245
  const shimPath = path.join(tempDir, "shim-bin", "lobster.cmd");
284
- await createWindowsShimFixture({
246
+ await createWindowsCmdShimFixture({
285
247
  shimPath,
286
248
  scriptPath: shimScriptPath,
287
- scriptToken: "%dp0%\\..\\shim-dist\\lobster-cli.cjs",
249
+ shimLine: `"%dp0%\\..\\shim-dist\\lobster-cli.cjs" %*`,
288
250
  });
289
251
  process.env.PATHEXT = ".CMD;.EXE";
290
252
  process.env.PATH = `${path.dirname(shimPath)};${process.env.PATH ?? ""}`;
@@ -0,0 +1,56 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ type PathEnvKey = "PATH" | "Path" | "PATHEXT" | "Pathext";
5
+
6
+ const PATH_ENV_KEYS = ["PATH", "Path", "PATHEXT", "Pathext"] as const;
7
+
8
+ export type PlatformPathEnvSnapshot = {
9
+ platformDescriptor: PropertyDescriptor | undefined;
10
+ env: Record<PathEnvKey, string | undefined>;
11
+ };
12
+
13
+ export function setProcessPlatform(platform: NodeJS.Platform): void {
14
+ Object.defineProperty(process, "platform", {
15
+ value: platform,
16
+ configurable: true,
17
+ });
18
+ }
19
+
20
+ export function snapshotPlatformPathEnv(): PlatformPathEnvSnapshot {
21
+ return {
22
+ platformDescriptor: Object.getOwnPropertyDescriptor(process, "platform"),
23
+ env: {
24
+ PATH: process.env.PATH,
25
+ Path: process.env.Path,
26
+ PATHEXT: process.env.PATHEXT,
27
+ Pathext: process.env.Pathext,
28
+ },
29
+ };
30
+ }
31
+
32
+ export function restorePlatformPathEnv(snapshot: PlatformPathEnvSnapshot): void {
33
+ if (snapshot.platformDescriptor) {
34
+ Object.defineProperty(process, "platform", snapshot.platformDescriptor);
35
+ }
36
+
37
+ for (const key of PATH_ENV_KEYS) {
38
+ const value = snapshot.env[key];
39
+ if (value === undefined) {
40
+ delete process.env[key];
41
+ continue;
42
+ }
43
+ process.env[key] = value;
44
+ }
45
+ }
46
+
47
+ export async function createWindowsCmdShimFixture(params: {
48
+ shimPath: string;
49
+ scriptPath: string;
50
+ shimLine: string;
51
+ }): Promise<void> {
52
+ await fs.mkdir(path.dirname(params.scriptPath), { recursive: true });
53
+ await fs.mkdir(path.dirname(params.shimPath), { recursive: true });
54
+ await fs.writeFile(params.scriptPath, "module.exports = {};\n", "utf8");
55
+ await fs.writeFile(params.shimPath, `@echo off\r\n${params.shimLine}\r\n`, "utf8");
56
+ }
@@ -2,22 +2,17 @@ import fs from "node:fs/promises";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
+ import {
6
+ createWindowsCmdShimFixture,
7
+ restorePlatformPathEnv,
8
+ setProcessPlatform,
9
+ snapshotPlatformPathEnv,
10
+ } from "./test-helpers.js";
5
11
  import { resolveWindowsLobsterSpawn } from "./windows-spawn.js";
6
12
 
7
- function setProcessPlatform(platform: NodeJS.Platform) {
8
- Object.defineProperty(process, "platform", {
9
- value: platform,
10
- configurable: true,
11
- });
12
- }
13
-
14
13
  describe("resolveWindowsLobsterSpawn", () => {
15
14
  let tempDir = "";
16
- const originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
17
- const originalPath = process.env.PATH;
18
- const originalPathAlt = process.env.Path;
19
- const originalPathExt = process.env.PATHEXT;
20
- const originalPathExtAlt = process.env.Pathext;
15
+ const originalProcessState = snapshotPlatformPathEnv();
21
16
 
22
17
  beforeEach(async () => {
23
18
  tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-lobster-win-spawn-"));
@@ -25,29 +20,7 @@ describe("resolveWindowsLobsterSpawn", () => {
25
20
  });
26
21
 
27
22
  afterEach(async () => {
28
- if (originalPlatform) {
29
- Object.defineProperty(process, "platform", originalPlatform);
30
- }
31
- if (originalPath === undefined) {
32
- delete process.env.PATH;
33
- } else {
34
- process.env.PATH = originalPath;
35
- }
36
- if (originalPathAlt === undefined) {
37
- delete process.env.Path;
38
- } else {
39
- process.env.Path = originalPathAlt;
40
- }
41
- if (originalPathExt === undefined) {
42
- delete process.env.PATHEXT;
43
- } else {
44
- process.env.PATHEXT = originalPathExt;
45
- }
46
- if (originalPathExtAlt === undefined) {
47
- delete process.env.Pathext;
48
- } else {
49
- process.env.Pathext = originalPathExtAlt;
50
- }
23
+ restorePlatformPathEnv(originalProcessState);
51
24
  if (tempDir) {
52
25
  await fs.rm(tempDir, { recursive: true, force: true });
53
26
  tempDir = "";
@@ -57,14 +30,11 @@ describe("resolveWindowsLobsterSpawn", () => {
57
30
  it("unwraps cmd shim with %dp0% token", async () => {
58
31
  const scriptPath = path.join(tempDir, "shim-dist", "lobster-cli.cjs");
59
32
  const shimPath = path.join(tempDir, "shim", "lobster.cmd");
60
- await fs.mkdir(path.dirname(scriptPath), { recursive: true });
61
- await fs.mkdir(path.dirname(shimPath), { recursive: true });
62
- await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8");
63
- await fs.writeFile(
33
+ await createWindowsCmdShimFixture({
64
34
  shimPath,
65
- `@echo off\r\n"%dp0%\\..\\shim-dist\\lobster-cli.cjs" %*\r\n`,
66
- "utf8",
67
- );
35
+ scriptPath,
36
+ shimLine: `"%dp0%\\..\\shim-dist\\lobster-cli.cjs" %*`,
37
+ });
68
38
 
69
39
  const target = resolveWindowsLobsterSpawn(shimPath, ["run", "noop"], process.env);
70
40
  expect(target.command).toBe(process.execPath);
@@ -75,14 +45,11 @@ describe("resolveWindowsLobsterSpawn", () => {
75
45
  it("unwraps cmd shim with %~dp0% token", async () => {
76
46
  const scriptPath = path.join(tempDir, "shim-dist", "lobster-cli.cjs");
77
47
  const shimPath = path.join(tempDir, "shim", "lobster.cmd");
78
- await fs.mkdir(path.dirname(scriptPath), { recursive: true });
79
- await fs.mkdir(path.dirname(shimPath), { recursive: true });
80
- await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8");
81
- await fs.writeFile(
48
+ await createWindowsCmdShimFixture({
82
49
  shimPath,
83
- `@echo off\r\n"%~dp0%\\..\\shim-dist\\lobster-cli.cjs" %*\r\n`,
84
- "utf8",
85
- );
50
+ scriptPath,
51
+ shimLine: `"%~dp0%\\..\\shim-dist\\lobster-cli.cjs" %*`,
52
+ });
86
53
 
87
54
  const target = resolveWindowsLobsterSpawn(shimPath, ["run", "noop"], process.env);
88
55
  expect(target.command).toBe(process.execPath);