@openclaw-cloud/agent-controller 3.1.0 → 3.1.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.
Files changed (139) hide show
  1. package/bin/agent-controller.js +5 -9
  2. package/dist/api.d.ts +7 -0
  3. package/dist/api.js.map +1 -1
  4. package/dist/commands/agent-update-cli.js +23 -38
  5. package/dist/commands/agent-update-cli.js.map +1 -1
  6. package/dist/commands/backup-cli.js +6 -4
  7. package/dist/commands/backup-cli.js.map +1 -1
  8. package/dist/commands/bootstrap.d.ts +10 -1
  9. package/dist/commands/bootstrap.js +25 -73
  10. package/dist/commands/bootstrap.js.map +1 -1
  11. package/dist/commands/channel-server.js +4 -3
  12. package/dist/commands/channel-server.js.map +1 -1
  13. package/dist/commands/heartbeat-cli.js +2 -6
  14. package/dist/commands/heartbeat-cli.js.map +1 -1
  15. package/dist/commands/install-deps.d.ts +10 -0
  16. package/dist/commands/install-deps.js +33 -43
  17. package/dist/commands/install-deps.js.map +1 -1
  18. package/dist/commands/knowledge-sync-cli.js +6 -4
  19. package/dist/commands/knowledge-sync-cli.js.map +1 -1
  20. package/dist/commands/plugin-update-cli.js +4 -8
  21. package/dist/commands/plugin-update-cli.js.map +1 -1
  22. package/dist/commands/self-update.js +17 -34
  23. package/dist/commands/self-update.js.map +1 -1
  24. package/dist/commands/update-skills.js +7 -6
  25. package/dist/commands/update-skills.js.map +1 -1
  26. package/dist/config-file.d.ts +7 -0
  27. package/dist/config-file.js +22 -11
  28. package/dist/config-file.js.map +1 -1
  29. package/dist/handlers/agent-update.d.ts +4 -0
  30. package/dist/handlers/agent-update.js +16 -44
  31. package/dist/handlers/agent-update.js.map +1 -1
  32. package/dist/handlers/deploy.d.ts +1 -2
  33. package/dist/handlers/deploy.js +4 -20
  34. package/dist/handlers/deploy.js.map +1 -1
  35. package/dist/handlers/diagnostics.js +0 -12
  36. package/dist/handlers/diagnostics.js.map +1 -1
  37. package/dist/handlers/file-delete.js +4 -5
  38. package/dist/handlers/file-delete.js.map +1 -1
  39. package/dist/handlers/file-write.js +4 -4
  40. package/dist/handlers/file-write.js.map +1 -1
  41. package/dist/handlers/knowledge-sync.js +2 -14
  42. package/dist/handlers/knowledge-sync.js.map +1 -1
  43. package/dist/handlers/memory.d.ts +11 -1
  44. package/dist/handlers/memory.js.map +1 -1
  45. package/dist/handlers/onboarding.d.ts +1 -2
  46. package/dist/handlers/onboarding.js +3 -20
  47. package/dist/handlers/onboarding.js.map +1 -1
  48. package/dist/handlers/package-install.js +1 -1
  49. package/dist/handlers/package-install.js.map +1 -1
  50. package/dist/handlers/pair.js +0 -12
  51. package/dist/handlers/pair.js.map +1 -1
  52. package/dist/handlers/restart.d.ts +1 -2
  53. package/dist/handlers/restart.js +3 -8
  54. package/dist/handlers/restart.js.map +1 -1
  55. package/dist/handlers/stop.js +0 -7
  56. package/dist/handlers/stop.js.map +1 -1
  57. package/dist/handlers/telegram-webhook.js +3 -22
  58. package/dist/handlers/telegram-webhook.js.map +1 -1
  59. package/dist/handlers/update-config.js +4 -13
  60. package/dist/handlers/update-config.js.map +1 -1
  61. package/dist/heartbeat.js +2 -1
  62. package/dist/heartbeat.js.map +1 -1
  63. package/dist/index.d.ts +0 -8
  64. package/dist/index.js +57 -117
  65. package/dist/index.js.map +1 -1
  66. package/dist/lockfile.js +2 -1
  67. package/dist/lockfile.js.map +1 -1
  68. package/dist/platform/linux.js +6 -5
  69. package/dist/platform/linux.js.map +1 -1
  70. package/dist/platform/macos.js +3 -2
  71. package/dist/platform/macos.js.map +1 -1
  72. package/dist/platform/windows.js +3 -2
  73. package/dist/platform/windows.js.map +1 -1
  74. package/dist/providers/claude-code/channel-server.js +2 -1
  75. package/dist/providers/claude-code/channel-server.js.map +1 -1
  76. package/dist/providers/claude-code/settings-writer.d.ts +3 -2
  77. package/dist/providers/claude-code/settings-writer.js +6 -15
  78. package/dist/providers/claude-code/settings-writer.js.map +1 -1
  79. package/dist/providers/index.d.ts +13 -0
  80. package/dist/providers/index.js +25 -0
  81. package/dist/providers/index.js.map +1 -1
  82. package/dist/providers/openclaw/gateway-adapter.js +2 -0
  83. package/dist/providers/openclaw/gateway-adapter.js.map +1 -1
  84. package/dist/providers/openclaw/index.js +11 -13
  85. package/dist/providers/openclaw/index.js.map +1 -1
  86. package/dist/utils/anthropic-auth.d.ts +14 -0
  87. package/dist/utils/anthropic-auth.js +24 -0
  88. package/dist/utils/anthropic-auth.js.map +1 -1
  89. package/dist/utils/apply-config.d.ts +38 -6
  90. package/dist/utils/apply-config.js +118 -69
  91. package/dist/utils/apply-config.js.map +1 -1
  92. package/dist/utils/claude-env.d.ts +6 -0
  93. package/dist/utils/claude-env.js +29 -28
  94. package/dist/utils/claude-env.js.map +1 -1
  95. package/dist/utils/deploy-type.d.ts +16 -0
  96. package/dist/utils/deploy-type.js +34 -0
  97. package/dist/utils/deploy-type.js.map +1 -0
  98. package/dist/utils/env.d.ts +0 -1
  99. package/dist/utils/env.js +0 -8
  100. package/dist/utils/env.js.map +1 -1
  101. package/dist/utils/exec.d.ts +9 -0
  102. package/dist/utils/exec.js +12 -1
  103. package/dist/utils/exec.js.map +1 -1
  104. package/dist/utils/gateway-restart-handler.d.ts +6 -2
  105. package/dist/utils/gateway-restart-handler.js +11 -2
  106. package/dist/utils/gateway-restart-handler.js.map +1 -1
  107. package/dist/utils/gateway-restart.d.ts +7 -0
  108. package/dist/utils/gateway-restart.js +12 -4
  109. package/dist/utils/gateway-restart.js.map +1 -1
  110. package/dist/utils/knowledge-graph.d.ts +13 -1
  111. package/dist/utils/knowledge-graph.js +75 -29
  112. package/dist/utils/knowledge-graph.js.map +1 -1
  113. package/dist/utils/legacy-mcp-servers.d.ts +12 -0
  114. package/dist/utils/legacy-mcp-servers.js +37 -0
  115. package/dist/utils/legacy-mcp-servers.js.map +1 -0
  116. package/dist/utils/log-collector.js +2 -1
  117. package/dist/utils/log-collector.js.map +1 -1
  118. package/dist/utils/openclaw-ops.js +8 -7
  119. package/dist/utils/openclaw-ops.js.map +1 -1
  120. package/dist/utils/openclaw-stack-update.d.ts +31 -0
  121. package/dist/utils/openclaw-stack-update.js +50 -0
  122. package/dist/utils/openclaw-stack-update.js.map +1 -0
  123. package/dist/utils/package-install.js +4 -12
  124. package/dist/utils/package-install.js.map +1 -1
  125. package/dist/utils/package-version.d.ts +10 -0
  126. package/dist/utils/package-version.js +18 -0
  127. package/dist/utils/package-version.js.map +1 -0
  128. package/dist/utils/parse-id-at-version.d.ts +15 -0
  129. package/dist/utils/parse-id-at-version.js +22 -0
  130. package/dist/utils/parse-id-at-version.js.map +1 -0
  131. package/dist/utils/response.js +1 -0
  132. package/dist/utils/response.js.map +1 -1
  133. package/dist/utils/write-workspace-files.d.ts +1 -1
  134. package/dist/utils/write-workspace-files.js +19 -7
  135. package/dist/utils/write-workspace-files.js.map +1 -1
  136. package/dist/workspace.d.ts +11 -0
  137. package/dist/workspace.js +20 -0
  138. package/dist/workspace.js.map +1 -1
  139. package/package.json +9 -4
@@ -0,0 +1,50 @@
1
+ import { installOpenclaw, installPlugins } from './openclaw-ops.js';
2
+ import { restartGateway } from './gateway-restart.js';
3
+ import { logCollector } from '../connection.js';
4
+ import { toErrorMessage } from './response.js';
5
+ /**
6
+ * Throws whatever `installOpenclaw` / `installPlugins` throw — per-plugin
7
+ * failures are reported inside `pluginSummary`, not raised. A failed gateway
8
+ * restart is never thrown: the install already landed, so it is a warning.
9
+ */
10
+ export async function runOpenclawStackUpdate(opts) {
11
+ const { version, plugins, eventPrefix, meta = {} } = opts;
12
+ const push = (event, level, msg, data = {}) => {
13
+ logCollector?.push(`${eventPrefix}_${event}`, level, msg, { ...meta, ...data });
14
+ };
15
+ let runtimeChanged = false;
16
+ if (version) {
17
+ runtimeChanged = await installOpenclaw(version);
18
+ push(runtimeChanged ? 'runtime_installed' : 'runtime_skipped', 'info', runtimeChanged
19
+ ? `openclaw runtime installed at ${version}`
20
+ : `openclaw runtime already at ${version}`, { version });
21
+ }
22
+ let pluginSummary;
23
+ if (plugins?.length) {
24
+ push('plugin_install_start', 'info', `Installing ${plugins.length} plugin(s)`, {
25
+ pluginCount: plugins.length,
26
+ });
27
+ pluginSummary = await installPlugins(plugins);
28
+ push('plugin_install_done', pluginSummary.failed.length > 0 ? 'warn' : 'info', `Plugin install complete: ${pluginSummary.installed.length} installed, ` +
29
+ `${pluginSummary.skipped.length} skipped, ${pluginSummary.failed.length} failed`, {
30
+ installed: pluginSummary.installed,
31
+ skipped: pluginSummary.skipped,
32
+ failed: pluginSummary.failed,
33
+ });
34
+ }
35
+ // One restart per invocation, no matter how many things changed.
36
+ const anyChanged = runtimeChanged || (pluginSummary?.installed.length ?? 0) > 0;
37
+ if (!anyChanged)
38
+ return { runtimeChanged, pluginSummary, gatewayRestarted: false };
39
+ try {
40
+ await restartGateway();
41
+ push('gateway_restarted', 'info', 'Gateway restarted after openclaw stack update');
42
+ return { runtimeChanged, pluginSummary, gatewayRestarted: true };
43
+ }
44
+ catch (err) {
45
+ const error = toErrorMessage(err);
46
+ push('gateway_restart_failed', 'warn', `Gateway restart after openclaw stack update failed: ${error}`, { error });
47
+ return { runtimeChanged, pluginSummary, gatewayRestarted: false, restartError: error };
48
+ }
49
+ }
50
+ //# sourceMappingURL=openclaw-stack-update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-stack-update.js","sourceRoot":"","sources":["../../src/utils/openclaw-stack-update.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { exec } from 'node:child_process';
1
+ import { execAsync } from './exec.js';
2
2
  import { toErrorMessage } from './response.js';
3
3
  // ---------------------------------------------------------------------------
4
4
  // Shared package-install module — used by:
@@ -30,16 +30,6 @@ export function buildInstallCommand(manager, pkg) {
30
30
  return `pip install ${pkg}`;
31
31
  }
32
32
  }
33
- function execPackage(cmd, timeoutMs) {
34
- return new Promise((resolve, reject) => {
35
- exec(cmd, { timeout: timeoutMs }, (error) => {
36
- if (error)
37
- reject(error);
38
- else
39
- resolve();
40
- });
41
- });
42
- }
43
33
  /**
44
34
  * Install a single package via the named manager. Validates the package
45
35
  * name against the allowlist regex first; never reaches the shell with an
@@ -50,7 +40,9 @@ export async function installOnePackage(manager, pkg, timeoutMs = INSTALL_TIMEOU
50
40
  return { ok: false, error: 'Invalid package name: contains disallowed characters' };
51
41
  }
52
42
  try {
53
- await execPackage(buildInstallCommand(manager, pkg), timeoutMs);
43
+ // execAsync, not a local wrapper: its 16MB maxBuffer is what keeps a
44
+ // chatty `npm install -g` from failing with ERR_CHILD_PROCESS_STDOUT_MAXBUFFER.
45
+ await execAsync(buildInstallCommand(manager, pkg), timeoutMs);
54
46
  return { ok: true };
55
47
  }
56
48
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"package-install.js","sourceRoot":"","sources":["../../src/utils/package-install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,8EAA8E;AAC9E,2CAA2C;AAC3C,oDAAoD;AACpD,gDAAgD;AAChD,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,sEAAsE;AACtE,iEAAiE;AACjE,8EAA8E;AAE9E,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC,CAAC,kBAAkB;AAE7D;;;;GAIG;AACH,MAAM,oBAAoB,GAAG,iCAAiC,CAAC;AAI/D,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAuB,EAAE,GAAW;IACtE,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,sBAAsB,GAAG,EAAE,CAAC;QACrC,KAAK,KAAK;YACR,OAAO,kBAAkB,GAAG,EAAE,CAAC;QACjC,KAAK,KAAK;YACR,OAAO,eAAe,GAAG,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAW,EAAE,SAAiB;IACjD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1C,IAAI,KAAK;gBAAE,MAAM,CAAC,KAAK,CAAC,CAAC;;gBACpB,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAOD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAuB,EACvB,GAAW,EACX,YAAoB,kBAAkB;IAEtC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,sDAAsD,EAAE,CAAC;IACtF,CAAC;IACD,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;QAChE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;IACnD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"package-install.js","sourceRoot":"","sources":["../../src/utils/package-install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,8EAA8E;AAC9E,2CAA2C;AAC3C,oDAAoD;AACpD,gDAAgD;AAChD,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,sEAAsE;AACtE,iEAAiE;AACjE,8EAA8E;AAE9E,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC,CAAC,kBAAkB;AAE7D;;;;GAIG;AACH,MAAM,oBAAoB,GAAG,iCAAiC,CAAC;AAI/D,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAuB,EAAE,GAAW;IACtE,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,sBAAsB,GAAG,EAAE,CAAC;QACrC,KAAK,KAAK;YACR,OAAO,kBAAkB,GAAG,EAAE,CAAC;QACjC,KAAK,KAAK;YACR,OAAO,eAAe,GAAG,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAOD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAuB,EACvB,GAAW,EACX,YAAoB,kBAAkB;IAEtC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,sDAAsD,EAAE,CAAC;IACtF,CAAC;IACD,IAAI,CAAC;QACH,qEAAqE;QACrE,gFAAgF;QAChF,MAAM,SAAS,CAAC,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;QAC9D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;IACnD,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Version from the package's own package.json.
3
+ *
4
+ * Read via `createRequire` rather than a JSON import so the compiled output
5
+ * stays plain ESM. The relative depth (`../..`) is correct from both
6
+ * `dist/utils/` and `src/utils/` — three call sites used to hand-roll this with
7
+ * three different depths, which is exactly the kind of thing that breaks
8
+ * silently when a file moves.
9
+ */
10
+ export declare function getPackageVersion(): string;
@@ -0,0 +1,18 @@
1
+ import { createRequire } from 'node:module';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { dirname, join } from 'node:path';
4
+ const _require = createRequire(import.meta.url);
5
+ /**
6
+ * Version from the package's own package.json.
7
+ *
8
+ * Read via `createRequire` rather than a JSON import so the compiled output
9
+ * stays plain ESM. The relative depth (`../..`) is correct from both
10
+ * `dist/utils/` and `src/utils/` — three call sites used to hand-roll this with
11
+ * three different depths, which is exactly the kind of thing that breaks
12
+ * silently when a file moves.
13
+ */
14
+ export function getPackageVersion() {
15
+ const pkgPath = join(dirname(fileURLToPath(import.meta.url)), '../../package.json');
16
+ return _require(pkgPath).version;
17
+ }
18
+ //# sourceMappingURL=package-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.js","sourceRoot":"","sources":["../../src/utils/package-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;IACpF,OAAQ,QAAQ,CAAC,OAAO,CAAyB,CAAC,OAAO,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Split a CLI token like `@scope/pkg@1.2.3` into `{ id, version }`, or null if
3
+ * it isn't one. Splits at the LAST `@` so scoped npm names survive, and rejects
4
+ * a leading `@` so a bare `@scope/name` (no version) doesn't parse as
5
+ * `{ id: '', version: 'scope/name' }`.
6
+ *
7
+ * Shared by the `plugin-update` and `agent-update` CLIs, which each had their
8
+ * own byte-identical copy. Kept out of openclaw-ops.ts on purpose: this is a
9
+ * pure parser, and openclaw-ops is the module every test mocks wholesale
10
+ * because it shells out.
11
+ */
12
+ export declare function parseIdAtVersion(token: string): {
13
+ id: string;
14
+ version: string;
15
+ } | null;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Split a CLI token like `@scope/pkg@1.2.3` into `{ id, version }`, or null if
3
+ * it isn't one. Splits at the LAST `@` so scoped npm names survive, and rejects
4
+ * a leading `@` so a bare `@scope/name` (no version) doesn't parse as
5
+ * `{ id: '', version: 'scope/name' }`.
6
+ *
7
+ * Shared by the `plugin-update` and `agent-update` CLIs, which each had their
8
+ * own byte-identical copy. Kept out of openclaw-ops.ts on purpose: this is a
9
+ * pure parser, and openclaw-ops is the module every test mocks wholesale
10
+ * because it shells out.
11
+ */
12
+ export function parseIdAtVersion(token) {
13
+ const at = token.lastIndexOf('@');
14
+ if (at <= 0)
15
+ return null;
16
+ const id = token.slice(0, at).trim();
17
+ const version = token.slice(at + 1).trim();
18
+ if (!id || !version)
19
+ return null;
20
+ return { id, version };
21
+ }
22
+ //# sourceMappingURL=parse-id-at-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-id-at-version.js","sourceRoot":"","sources":["../../src/utils/parse-id-at-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;AACzB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export function toErrorMessage(err) {
2
+ // eslint-disable-next-line no-restricted-syntax -- this IS the one implementation
2
3
  return err instanceof Error ? err.message : String(err);
3
4
  }
4
5
  export function toErrorResponse(command, err) {
@@ -1 +1 @@
1
- {"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/utils/response.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAqB,EAAE,GAAY;IACjE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5F,CAAC"}
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/utils/response.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,kFAAkF;IAClF,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAqB,EAAE,GAAY;IACjE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5F,CAAC"}
@@ -12,4 +12,4 @@
12
12
  * command path in `applyBootstrapConfig` (propagates shared-file updates from
13
13
  * the backend without requiring a restart).
14
14
  */
15
- export declare function writeWorkspaceFiles(files: Record<string, string>, workspaceDir: string): Promise<void>;
15
+ export declare function writeWorkspaceFiles(files: Record<string, string>, workspaceDir: string): Promise<number>;
@@ -1,5 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
+ import { resolveInsideWorkspace } from '../workspace.js';
4
+ import { toErrorMessage } from './response.js';
3
5
  /**
4
6
  * Write a map of workspace-relative paths → content into `workspaceDir`.
5
7
  *
@@ -17,32 +19,42 @@ import path from 'node:path';
17
19
  export async function writeWorkspaceFiles(files, workspaceDir) {
18
20
  const fileNames = Object.keys(files);
19
21
  if (fileNames.length === 0)
20
- return;
22
+ return 0;
21
23
  await fs.mkdir(workspaceDir, { recursive: true });
24
+ const written = [];
22
25
  for (const [filePath, content] of Object.entries(files)) {
23
- const fullPath = path.join(workspaceDir, filePath);
26
+ // Reject any key that escapes the workspace — a backend-supplied key like
27
+ // "../../etc/openclaw/agent.env" or an absolute path must not write outside
28
+ // it. Same sandbox helper as the file_write / file_delete handlers.
29
+ const fullPath = resolveInsideWorkspace(workspaceDir, filePath);
30
+ if (!fullPath) {
31
+ console.error(` ✗ ${filePath}: rejected (path escapes workspace)`);
32
+ continue;
33
+ }
24
34
  await fs.mkdir(path.dirname(fullPath), { recursive: true });
25
35
  try {
26
36
  await fs.writeFile(fullPath, content);
37
+ written.push(filePath);
27
38
  console.log(` ✓ ${filePath}`);
28
39
  }
29
40
  catch (err) {
30
- console.error(` ✗ ${filePath}: ${err instanceof Error ? err.message : err}`);
41
+ console.error(` ✗ ${filePath}: ${toErrorMessage(err)}`);
31
42
  }
32
43
  }
33
- // Make .sh files executable
34
- for (const filePath of fileNames) {
44
+ // Make .sh files executable (only the ones we actually wrote)
45
+ for (const filePath of written) {
35
46
  if (filePath.endsWith('.sh')) {
36
47
  const fullPath = path.join(workspaceDir, filePath);
37
48
  await fs.chmod(fullPath, 0o755);
38
49
  }
39
50
  }
40
51
  // Summary for deployed skills (under .agents/skills/<name>/...)
41
- const skillFiles = fileNames.filter((f) => f.startsWith('.agents/skills/'));
52
+ const skillFiles = written.filter((f) => f.startsWith('.agents/skills/'));
42
53
  if (skillFiles.length > 0) {
43
54
  const skills = [...new Set(skillFiles.map((f) => f.split('/')[2]))];
44
55
  console.log(` ✓ skills deployed: ${skills.join(', ')}`);
45
56
  }
46
- console.log(` wrote ${fileNames.length} workspace files`);
57
+ console.log(` wrote ${written.length} workspace files`);
58
+ return written.length;
47
59
  }
48
60
  //# sourceMappingURL=write-workspace-files.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"write-workspace-files.js","sourceRoot":"","sources":["../../src/utils/write-workspace-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAA6B,EAC7B,YAAoB;IAEpB,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEnC,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAElD,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,OAAO,QAAQ,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAED,4BAA4B;IAC5B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YACnD,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC5E,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,WAAW,SAAS,CAAC,MAAM,kBAAkB,CAAC,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"write-workspace-files.js","sourceRoot":"","sources":["../../src/utils/write-workspace-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAA6B,EAC7B,YAAoB;IAEpB,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAErC,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAElD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,0EAA0E;QAC1E,4EAA4E;QAC5E,oEAAoE;QACpE,MAAM,QAAQ,GAAG,sBAAsB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAChE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,OAAO,QAAQ,qCAAqC,CAAC,CAAC;YACpE,SAAS;QACX,CAAC;QACD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,OAAO,QAAQ,KAAK,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YACnD,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC1E,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,MAAM,kBAAkB,CAAC,CAAC;IACzD,OAAO,OAAO,CAAC,MAAM,CAAC;AACxB,CAAC"}
@@ -10,3 +10,14 @@
10
10
  * (which used WORKSPACE_DIR) and backup/knowledge_sync (which used OPENCLAW_STATE_DIR).
11
11
  */
12
12
  export declare function getWorkspaceDir(): string;
13
+ /**
14
+ * Resolve a backend-supplied relative path inside `workspaceDir`, or null if it
15
+ * escapes. The ONE sandbox for every backend-supplied path — `file_write`,
16
+ * `file_delete` and `writeWorkspaceFiles` all route through it.
17
+ *
18
+ * Containment is checked on path *segments* (via `path.relative`), not by
19
+ * substring. The old `p.includes('..') || p.startsWith('/')` copies in the two
20
+ * handlers rejected innocent names like `notes..v2.md` and missed Windows
21
+ * absolute forms such as `C:\x` and `\\server\share`.
22
+ */
23
+ export declare function resolveInsideWorkspace(workspaceDir: string, relPath: string): string | null;
package/dist/workspace.js CHANGED
@@ -16,4 +16,24 @@ export function getWorkspaceDir() {
16
16
  return config.workspaceDir;
17
17
  return path.join(config.stateDir, 'workspace');
18
18
  }
19
+ /**
20
+ * Resolve a backend-supplied relative path inside `workspaceDir`, or null if it
21
+ * escapes. The ONE sandbox for every backend-supplied path — `file_write`,
22
+ * `file_delete` and `writeWorkspaceFiles` all route through it.
23
+ *
24
+ * Containment is checked on path *segments* (via `path.relative`), not by
25
+ * substring. The old `p.includes('..') || p.startsWith('/')` copies in the two
26
+ * handlers rejected innocent names like `notes..v2.md` and missed Windows
27
+ * absolute forms such as `C:\x` and `\\server\share`.
28
+ */
29
+ export function resolveInsideWorkspace(workspaceDir, relPath) {
30
+ if (!relPath || path.isAbsolute(relPath) || path.win32.isAbsolute(relPath))
31
+ return null;
32
+ const fullPath = path.resolve(workspaceDir, relPath);
33
+ const rel = path.relative(workspaceDir, fullPath);
34
+ if (rel === '' || rel === '..' || rel.startsWith('..' + path.sep) || path.isAbsolute(rel)) {
35
+ return null;
36
+ }
37
+ return fullPath;
38
+ }
19
39
  //# sourceMappingURL=workspace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,MAAM,CAAC,YAAY;QAAE,OAAO,MAAM,CAAC,YAAY,CAAC;IACpD,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,MAAM,CAAC,YAAY;QAAE,OAAO,MAAM,CAAC,YAAY,CAAC;IACpD,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CAAC,YAAoB,EAAE,OAAe;IAC1E,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACxF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAClD,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
package/package.json CHANGED
@@ -1,17 +1,21 @@
1
1
  {
2
2
  "name": "@openclaw-cloud/agent-controller",
3
- "version": "3.1.0",
3
+ "version": "3.1.2",
4
+ "packageManager": "pnpm@11.5.2",
4
5
  "type": "module",
6
+ "engines": {
7
+ "node": ">=22"
8
+ },
5
9
  "main": "dist/index.js",
6
10
  "bin": {
7
11
  "agent-controller": "bin/agent-controller.js"
8
12
  },
9
13
  "scripts": {
10
14
  "build": "tsc",
11
- "prepublishOnly": "npm run build",
12
- "test": "node --experimental-vm-modules node_modules/.bin/jest --forceExit",
15
+ "prepublishOnly": "pnpm run build",
16
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest --forceExit",
13
17
  "start": "node bin/agent-controller.js",
14
- "prepare": "[ -d .git ] && husky || true",
18
+ "prepare": "[ -e .git ] && husky || true",
15
19
  "lint": "eslint --fix ./src"
16
20
  },
17
21
  "files": [
@@ -25,6 +29,7 @@
25
29
  "zod": "^4.3.6"
26
30
  },
27
31
  "devDependencies": {
32
+ "@jest/globals": "^30.0.0",
28
33
  "@semantic-release/git": "^10.0.1",
29
34
  "@semantic-release/npm": "^13.1.5",
30
35
  "@types/jest": "^30.0.0",