@elizaos/app-core 2.0.3-beta.4 → 2.0.3-beta.6

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 (97) hide show
  1. package/api/i18n-locale-routes.d.ts +7 -0
  2. package/api/i18n-locale-routes.d.ts.map +1 -0
  3. package/api/i18n-locale-routes.js +58 -0
  4. package/api/ios-local-agent-transport.d.ts +3 -0
  5. package/api/ios-local-agent-transport.d.ts.map +1 -1
  6. package/api/ios-local-agent-transport.js +22 -1
  7. package/api/server.d.ts.map +1 -1
  8. package/api/server.js +5 -0
  9. package/benchmark/cerebras-autowire.d.ts.map +1 -1
  10. package/benchmark/cerebras-autowire.js +9 -2
  11. package/package.json +36 -36
  12. package/packaging/debian/rules +1 -1
  13. package/packaging/flatpak/generate-sources.sh +6 -1
  14. package/packaging/snap/snapcraft.yaml +15 -11
  15. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAgentService.java +2 -1
  16. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaNativeBridge.java +5 -0
  17. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaStartupTrace.java +28 -0
  18. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoicePlugin.java +1 -1
  19. package/platforms/android/app/src/main/java/ai/elizaos/app/MainActivity.java +1 -0
  20. package/platforms/electrobun/electrobun.config.ts +31 -1
  21. package/platforms/electrobun/package.json +10 -10
  22. package/platforms/electrobun/remotes/local-model/README.md +2 -5
  23. package/platforms/electrobun/remotes/local-model/src/bun/eliza1-catalog.ts +0 -16
  24. package/platforms/electrobun/remotes/local-model/src/dev/phase8-smoke.ts +0 -2
  25. package/platforms/electrobun/scripts/smoke-test.sh +8 -2
  26. package/platforms/electrobun/scripts/stage-macos-release-artifacts.sh +8 -2
  27. package/platforms/electrobun/scripts/sync-web-assets.mjs +31 -2
  28. package/platforms/electrobun/src/bridge/electrobun-boot-config.ts +8 -0
  29. package/platforms/electrobun/src/bridge/electrobun-crypto-ready.ts +5 -1
  30. package/platforms/electrobun/src/bridge/electrobun-direct-rpc.ts +5 -11
  31. package/platforms/electrobun/src/preload.js +1 -1
  32. package/platforms/ios/App/App/Base.lproj/Main.storyboard +1 -1
  33. package/platforms/ios/App/App/ElizaBridgeViewController.swift +22 -0
  34. package/platforms/ios/App/App/ElizaStartupTrace.swift +12 -0
  35. package/platforms/ios/App/App.xcodeproj/project.pbxproj +8 -0
  36. package/runtime/eliza.d.ts.map +1 -1
  37. package/runtime/eliza.js +18 -0
  38. package/runtime/voice-warmup.d.ts +4 -4
  39. package/runtime/voice-warmup.d.ts.map +1 -1
  40. package/runtime/voice-warmup.js +4 -4
  41. package/scripts/aosp/compile-libllama.mjs +25 -5
  42. package/scripts/aosp/compile-libllama.test.mjs +17 -1
  43. package/scripts/assert-required-bundled-packages.test.ts +24 -2
  44. package/scripts/benchmark-preflight.mjs +31 -2
  45. package/scripts/build-bundled-agent-skills-artifact.mjs +32 -8
  46. package/scripts/build-bundled-orchestrator-artifact.mjs +34 -12
  47. package/scripts/build-llama-cpp-mtp.mjs +27 -3
  48. package/scripts/build-patched-electrobun-cli.mjs +30 -2
  49. package/scripts/bun-riscv64/bun-version.json +1 -1
  50. package/scripts/bun-riscv64/validate.sh +21 -8
  51. package/scripts/check-real-local-reset.ts +13 -1
  52. package/scripts/check-sms-gateway-completion-audit.mjs +96 -31
  53. package/scripts/check-sms-gateway-readiness.mjs +54 -17
  54. package/scripts/clean-repo.mjs +21 -3
  55. package/scripts/copy-runtime-node-modules.ts +68 -63
  56. package/scripts/desktop-build.mjs +46 -5
  57. package/scripts/dev-platform-no-install.test.mjs +19 -0
  58. package/scripts/dev-platform.mjs +6 -2
  59. package/scripts/disable-local-eliza-workspace.mjs +23 -1
  60. package/scripts/docker-ci-smoke.sh +6 -5
  61. package/scripts/ensure-avatars.mjs +18 -5
  62. package/scripts/ensure-bundled-workspaces.mjs +4 -15
  63. package/scripts/ensure-type-package-aliases.mjs +47 -3
  64. package/scripts/ffi-stub/Makefile +5 -2
  65. package/scripts/ios-xcframework/build-xcframework.mjs +22 -11
  66. package/scripts/ios-xcframework/run-physical-device-smoke.mjs +99 -6
  67. package/scripts/ios-xcframework/runtime-symbol-shim.c +560 -105
  68. package/scripts/lib/agent-source-watcher.test.mjs +24 -4
  69. package/scripts/lib/apple-entitlement-audit.test.mjs +19 -2
  70. package/scripts/lib/artifact-staleness.test.mts +18 -1
  71. package/scripts/lib/patch-bun-exports.mjs +20 -2
  72. package/scripts/lib/patch-bun-exports.test.mjs +108 -4
  73. package/scripts/lib/renderer-build-manifest.test.mts +18 -1
  74. package/scripts/lib/stage-android-agent.mjs +16 -3
  75. package/scripts/lib/verify-ondevice-artifact.test.mts +18 -1
  76. package/scripts/link-docker-local-app-packages.mjs +26 -1
  77. package/scripts/mas-smoke.test.mjs +25 -9
  78. package/scripts/omnivoice-fuse/prepare.mjs +27 -4
  79. package/scripts/package-electrobun-linux.mjs +22 -7
  80. package/scripts/patch-deps.mjs +18 -5
  81. package/scripts/playwright-ui-live-stack.ts +16 -3
  82. package/scripts/playwright-ui-smoke-api-stub.mjs +167 -2
  83. package/scripts/prepare-ios-cocoapods.sh +5 -1
  84. package/scripts/prune-cdn-local-assets.mjs +52 -5
  85. package/scripts/run-mobile-build-android-app-actions.test.mjs +19 -1
  86. package/scripts/run-mobile-build-mtp-staleness.test.mts +20 -4
  87. package/scripts/run-mobile-build.mjs +74 -16
  88. package/scripts/stage-android-agent.test.mjs +19 -1
  89. package/scripts/stage-desktop-fused-lib.mjs +26 -1
  90. package/scripts/sync-desktop-renderer.mjs +53 -12
  91. package/scripts/test-sms-gateway-software.mjs +20 -4
  92. package/cli/command-format.d.ts +0 -2
  93. package/cli/command-format.d.ts.map +0 -1
  94. package/cli/command-format.js +0 -20
  95. package/register-runtime-hooks.d.ts +0 -2
  96. package/register-runtime-hooks.d.ts.map +0 -1
  97. package/register-runtime-hooks.js +0 -19
@@ -1,4 +1,5 @@
1
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
1
+ import { execFileSync } from "node:child_process";
2
+ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
2
3
  import { tmpdir } from "node:os";
3
4
  import path from "node:path";
4
5
  import { afterEach, describe, expect, it } from "vitest";
@@ -8,6 +9,22 @@ import {
8
9
  isReloadableChangePath,
9
10
  startAgentSourceWatcher,
10
11
  } from "./agent-source-watcher.mjs";
12
+ import { resolveRepoRootFromImportMeta } from "./repo-root.mjs";
13
+
14
+ const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
15
+ const cleanupHelperScript = path.join(
16
+ repoRoot,
17
+ "packages",
18
+ "scripts",
19
+ "rm-path-recursive.mjs",
20
+ );
21
+
22
+ function removePathRecursive(targetPath) {
23
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
24
+ cwd: repoRoot,
25
+ stdio: "inherit",
26
+ });
27
+ }
11
28
 
12
29
  const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
13
30
 
@@ -23,7 +40,7 @@ async function waitUntil(predicate, timeoutMs) {
23
40
  describe("collectAgentSourceDirs", () => {
24
41
  let root = null;
25
42
  afterEach(() => {
26
- if (root) rmSync(root, { recursive: true, force: true });
43
+ if (root) removePathRecursive(root);
27
44
  root = null;
28
45
  });
29
46
 
@@ -117,7 +134,7 @@ describe("startAgentSourceWatcher (integration)", () => {
117
134
  afterEach(() => {
118
135
  if (handle) handle.close();
119
136
  handle = null;
120
- if (root) rmSync(root, { recursive: true, force: true });
137
+ if (root) removePathRecursive(root);
121
138
  root = null;
122
139
  });
123
140
 
@@ -154,7 +171,10 @@ describe("startAgentSourceWatcher (integration)", () => {
154
171
  const srcDir = path.join(root, "plugins", "plugin-x", "src");
155
172
  mkdirSync(srcDir, { recursive: true });
156
173
  for (let i = 0; i < 20; i++) {
157
- writeFileSync(path.join(srcDir, `mod-${i}.ts`), `export const v${i}=0;\n`);
174
+ writeFileSync(
175
+ path.join(srcDir, `mod-${i}.ts`),
176
+ `export const v${i}=0;\n`,
177
+ );
158
178
  }
159
179
 
160
180
  const calls = [];
@@ -1,5 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { execFileSync } from "node:child_process";
3
+ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
3
4
  import os from "node:os";
4
5
  import path from "node:path";
5
6
  import { describe, it } from "vitest";
@@ -10,6 +11,22 @@ import {
10
11
  scanAppleAppBundleForNativeRuntimeSignals,
11
12
  validateEntitlementsAgainstTarget,
12
13
  } from "./apple-entitlement-audit.mjs";
14
+ import { resolveRepoRootFromImportMeta } from "./repo-root.mjs";
15
+
16
+ const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
17
+ const cleanupHelperScript = path.join(
18
+ repoRoot,
19
+ "packages",
20
+ "scripts",
21
+ "rm-path-recursive.mjs",
22
+ );
23
+
24
+ function removePathRecursive(targetPath) {
25
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
26
+ cwd: repoRoot,
27
+ stdio: "inherit",
28
+ });
29
+ }
13
30
 
14
31
  describe("apple entitlement audit", () => {
15
32
  it("accepts the reviewed App Store entitlement sources", () => {
@@ -121,7 +138,7 @@ describe("apple entitlement audit", () => {
121
138
  }),
122
139
  );
123
140
  } finally {
124
- rmSync(tmp, { recursive: true, force: true });
141
+ removePathRecursive(tmp);
125
142
  }
126
143
  });
127
144
 
@@ -1,3 +1,4 @@
1
+ import { execFileSync } from "node:child_process";
1
2
  import fs from "node:fs";
2
3
  import os from "node:os";
3
4
  import path from "node:path";
@@ -8,6 +9,22 @@ import {
8
9
  fileMtime,
9
10
  maxMtimeUnder,
10
11
  } from "./artifact-staleness.mjs";
12
+ import { resolveRepoRootFromImportMeta } from "./repo-root.mjs";
13
+
14
+ const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
15
+ const cleanupHelperScript = path.join(
16
+ repoRoot,
17
+ "packages",
18
+ "scripts",
19
+ "rm-path-recursive.mjs",
20
+ );
21
+
22
+ function removePathRecursive(targetPath: string) {
23
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
24
+ cwd: repoRoot,
25
+ stdio: "inherit",
26
+ });
27
+ }
11
28
 
12
29
  let tmp: string;
13
30
 
@@ -16,7 +33,7 @@ beforeEach(() => {
16
33
  });
17
34
 
18
35
  afterEach(() => {
19
- fs.rmSync(tmp, { recursive: true, force: true });
36
+ removePathRecursive(tmp);
20
37
  });
21
38
 
22
39
  function touch(file: string, mtimeMs: number) {
@@ -3,6 +3,8 @@
3
3
  * (missing in published tarball). Exported for use by patch-deps.mjs and tests.
4
4
  * See docs/plugin-resolution-and-node-path.md "Bun and published package exports".
5
5
  */
6
+
7
+ import { execFileSync } from "node:child_process";
6
8
  import {
7
9
  cpSync,
8
10
  existsSync,
@@ -15,6 +17,7 @@ import {
15
17
  } from "node:fs";
16
18
  import { dirname, resolve } from "node:path";
17
19
  import ts from "typescript";
20
+ import { resolveRepoRootFromImportMeta } from "./repo-root.mjs";
18
21
 
19
22
  const ELIZA_CORE_RUNTIME_FILES = [
20
23
  "dist/index.js",
@@ -22,6 +25,21 @@ const ELIZA_CORE_RUNTIME_FILES = [
22
25
  "dist/node/index.node.js",
23
26
  ];
24
27
 
28
+ const REPO_ROOT = resolveRepoRootFromImportMeta(import.meta.url);
29
+ const CLEANUP_HELPER_SCRIPT = resolve(
30
+ REPO_ROOT,
31
+ "packages",
32
+ "scripts",
33
+ "rm-path-recursive.mjs",
34
+ );
35
+
36
+ function removePathRecursive(targetPath) {
37
+ execFileSync(process.execPath, [CLEANUP_HELPER_SCRIPT, targetPath], {
38
+ cwd: REPO_ROOT,
39
+ stdio: "ignore",
40
+ });
41
+ }
42
+
25
43
  function dedupeRealPaths(paths) {
26
44
  const seen = new Set();
27
45
  const unique = [];
@@ -113,7 +131,7 @@ export function repairElizaCoreRuntimeDist(targetPkgDir, sourcePkgDir) {
113
131
  const sourceDist = resolve(sourcePkgDir, "dist");
114
132
  const targetDist = resolve(targetPkgDir, "dist");
115
133
 
116
- rmSync(targetDist, { recursive: true, force: true });
134
+ removePathRecursive(targetDist);
117
135
  cpSync(sourceDist, targetDist, { recursive: true });
118
136
  return true;
119
137
  }
@@ -241,7 +259,7 @@ export function pruneNestedElizaPluginCoreCopies(root, log = console.log) {
241
259
  // Fall back to the directory path when package.json cannot be read.
242
260
  }
243
261
 
244
- rmSync(nestedCoreDir, { recursive: true, force: true });
262
+ removePathRecursive(nestedCoreDir);
245
263
  patched = true;
246
264
  log(
247
265
  `[patch-deps] Removed nested @elizaos/core from ${pluginName}; plugin imports now resolve the root core.`,
@@ -1,17 +1,41 @@
1
+ import { execFileSync } from "node:child_process";
1
2
  import {
3
+ existsSync,
2
4
  mkdirSync,
3
5
  mkdtempSync,
4
6
  readFileSync,
5
- rmSync,
6
7
  writeFileSync,
7
8
  } from "node:fs";
8
9
  import { tmpdir } from "node:os";
9
- import { join } from "node:path";
10
+ import { dirname, join } from "node:path";
10
11
  import { describe, expect, it } from "vitest";
11
12
  import {
12
13
  applyEsmDynamicRequireCompat,
13
14
  patchGitWorkspaceServiceEsmRequireCompat,
15
+ pruneNestedElizaPluginCoreCopies,
16
+ repairElizaCoreRuntimeDist,
14
17
  } from "./patch-bun-exports.mjs";
18
+ import { resolveRepoRootFromImportMeta } from "./repo-root.mjs";
19
+
20
+ const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
21
+ const cleanupHelperScript = join(
22
+ repoRoot,
23
+ "packages",
24
+ "scripts",
25
+ "rm-path-recursive.mjs",
26
+ );
27
+
28
+ function removePathRecursive(targetPath) {
29
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
30
+ cwd: repoRoot,
31
+ stdio: "inherit",
32
+ });
33
+ }
34
+
35
+ function writeFixtureFile(filePath, contents = "export {};\n") {
36
+ mkdirSync(dirname(filePath), { recursive: true });
37
+ writeFileSync(filePath, contents, "utf8");
38
+ }
15
39
 
16
40
  describe("patch-bun-exports", () => {
17
41
  it("applyEsmDynamicRequireCompat replaces generated require shims", () => {
@@ -40,7 +64,7 @@ describe("patch-bun-exports", () => {
40
64
  );
41
65
  expect(updated).not.toContain("Dynamic require of");
42
66
  } finally {
43
- rmSync(tmp, { recursive: true, force: true });
67
+ removePathRecursive(tmp);
44
68
  }
45
69
  });
46
70
 
@@ -73,7 +97,87 @@ describe("patch-bun-exports", () => {
73
97
  expect(logs).toHaveLength(1);
74
98
  expect(logs[0]).toContain("git-workspace-service");
75
99
  } finally {
76
- rmSync(tmp, { recursive: true, force: true });
100
+ removePathRecursive(tmp);
101
+ }
102
+ });
103
+
104
+ it("repairElizaCoreRuntimeDist replaces an incomplete runtime dist", () => {
105
+ const tmp = mkdtempSync(join(tmpdir(), "patch-bun-exports-test-"));
106
+ try {
107
+ const sourcePkgDir = join(tmp, "source-core");
108
+ const targetPkgDir = join(tmp, "target-core");
109
+ for (const relativePath of [
110
+ "dist/index.js",
111
+ "dist/browser/index.browser.js",
112
+ "dist/node/index.node.js",
113
+ ]) {
114
+ writeFixtureFile(
115
+ join(sourcePkgDir, relativePath),
116
+ `// healthy ${relativePath}\n`,
117
+ );
118
+ }
119
+ writeFixtureFile(join(targetPkgDir, "dist/testing/index.js"));
120
+ writeFixtureFile(join(targetPkgDir, "dist/stale.js"), "// stale\n");
121
+
122
+ expect(repairElizaCoreRuntimeDist(targetPkgDir, sourcePkgDir)).toBe(true);
123
+ expect(readFileSync(join(targetPkgDir, "dist/index.js"), "utf8")).toBe(
124
+ "// healthy dist/index.js\n",
125
+ );
126
+ expect(
127
+ existsSync(join(targetPkgDir, "dist/browser/index.browser.js")),
128
+ ).toBe(true);
129
+ expect(existsSync(join(targetPkgDir, "dist/node/index.node.js"))).toBe(
130
+ true,
131
+ );
132
+ expect(existsSync(join(targetPkgDir, "dist/stale.js"))).toBe(false);
133
+ } finally {
134
+ removePathRecursive(tmp);
135
+ }
136
+ });
137
+
138
+ it("pruneNestedElizaPluginCoreCopies removes plugin-local core copies", () => {
139
+ const tmp = mkdtempSync(join(tmpdir(), "patch-bun-exports-test-"));
140
+ try {
141
+ const rootCorePkg = join(
142
+ tmp,
143
+ "node_modules",
144
+ "@elizaos",
145
+ "core",
146
+ "package.json",
147
+ );
148
+ const pluginPkg = join(
149
+ tmp,
150
+ "node_modules",
151
+ "@elizaos",
152
+ "plugin-demo",
153
+ "package.json",
154
+ );
155
+ const nestedCoreDir = join(
156
+ tmp,
157
+ "node_modules",
158
+ "@elizaos",
159
+ "plugin-demo",
160
+ "node_modules",
161
+ "@elizaos",
162
+ "core",
163
+ );
164
+
165
+ writeFixtureFile(rootCorePkg, '{"name":"@elizaos/core"}\n');
166
+ writeFixtureFile(pluginPkg, '{"name":"@elizaos/plugin-demo"}\n');
167
+ writeFixtureFile(
168
+ join(nestedCoreDir, "package.json"),
169
+ '{"name":"@elizaos/core"}\n',
170
+ );
171
+
172
+ const logs = [];
173
+ expect(
174
+ pruneNestedElizaPluginCoreCopies(tmp, (msg) => logs.push(msg)),
175
+ ).toBe(true);
176
+ expect(existsSync(nestedCoreDir)).toBe(false);
177
+ expect(logs).toHaveLength(1);
178
+ expect(logs[0]).toContain("@elizaos/plugin-demo");
179
+ } finally {
180
+ removePathRecursive(tmp);
77
181
  }
78
182
  });
79
183
  });
@@ -1,3 +1,4 @@
1
+ import { execFileSync } from "node:child_process";
1
2
  import fs from "node:fs";
2
3
  import os from "node:os";
3
4
  import path from "node:path";
@@ -13,6 +14,22 @@ import {
13
14
  readRendererBuildManifest,
14
15
  writeRendererBuildManifest,
15
16
  } from "./renderer-build-manifest.mjs";
17
+ import { resolveRepoRootFromImportMeta } from "./repo-root.mjs";
18
+
19
+ const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
20
+ const cleanupHelperScript = path.join(
21
+ repoRoot,
22
+ "packages",
23
+ "scripts",
24
+ "rm-path-recursive.mjs",
25
+ );
26
+
27
+ function removePathRecursive(targetPath: string) {
28
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
29
+ cwd: repoRoot,
30
+ stdio: "inherit",
31
+ });
32
+ }
16
33
 
17
34
  let tmp: string;
18
35
 
@@ -21,7 +38,7 @@ beforeEach(() => {
21
38
  });
22
39
 
23
40
  afterEach(() => {
24
- fs.rmSync(tmp, { recursive: true, force: true });
41
+ removePathRecursive(tmp);
25
42
  });
26
43
 
27
44
  /**
@@ -39,7 +39,7 @@
39
39
  * The ABI-independent `launch.sh` is the packaged production launcher;
40
40
  * `agent-bundle.js` is produced by `bun run --cwd packages/agent build:mobile`.
41
41
  */
42
- import { spawn } from "node:child_process";
42
+ import { execFileSync, spawn } from "node:child_process";
43
43
  import crypto from "node:crypto";
44
44
  import fs from "node:fs";
45
45
  import os from "node:os";
@@ -49,6 +49,12 @@ import { fileURLToPath } from "node:url";
49
49
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
50
50
  const APP_CORE_ROOT = path.resolve(__dirname, "..", "..");
51
51
  const ELIZA_REPO_ROOT = path.resolve(APP_CORE_ROOT, "..", "..");
52
+ const CLEANUP_HELPER_SCRIPT = path.join(
53
+ ELIZA_REPO_ROOT,
54
+ "packages",
55
+ "scripts",
56
+ "rm-path-recursive.mjs",
57
+ );
52
58
 
53
59
  const BUN_VERSION = "1.3.14";
54
60
  // Bun 1.3.13 had a segfault during inference on Cuttlefish at peak
@@ -304,6 +310,13 @@ function run(command, args, { cwd } = {}) {
304
310
  });
305
311
  }
306
312
 
313
+ function removePathRecursiveSync(targetPath) {
314
+ execFileSync(process.execPath, [CLEANUP_HELPER_SCRIPT, targetPath], {
315
+ cwd: ELIZA_REPO_ROOT,
316
+ stdio: "ignore",
317
+ });
318
+ }
319
+
307
320
  async function downloadFile(url, targetPath) {
308
321
  const response = await fetch(url);
309
322
  if (!response.ok) {
@@ -589,7 +602,7 @@ async function ensureBunBinary({ cacheDir, bunArch, bunChannel, log }) {
589
602
  }
590
603
  if (fs.existsSync(bunPath)) fs.unlinkSync(bunPath);
591
604
  fs.renameSync(extractedBun, bunPath);
592
- fs.rmSync(extractedDir, { recursive: true, force: true });
605
+ removePathRecursiveSync(extractedDir);
593
606
  fs.rmSync(zipPath, { force: true });
594
607
  fs.chmodSync(bunPath, 0o755);
595
608
  if (expectedRiscv64Sha256) {
@@ -645,7 +658,7 @@ async function ensureAlpineApkExtracted({ cacheDir, alpineArch, log }) {
645
658
  return extractDir;
646
659
  }
647
660
  fs.mkdirSync(archCache, { recursive: true });
648
- fs.rmSync(extractDir, { recursive: true, force: true });
661
+ removePathRecursiveSync(extractDir);
649
662
  fs.mkdirSync(extractDir, { recursive: true });
650
663
  for (const { pkg, file } of APK_PACKAGES) {
651
664
  const apkPath = path.join(archCache, file);
@@ -1,11 +1,28 @@
1
+ import { execFileSync } from "node:child_process";
1
2
  import fs from "node:fs";
2
3
  import os from "node:os";
3
4
  import path from "node:path";
4
5
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
6
 
6
7
  import { writeRendererBuildManifest } from "./renderer-build-manifest.mjs";
8
+ import { resolveRepoRootFromImportMeta } from "./repo-root.mjs";
7
9
  import { verifyStagedArtifact } from "./verify-ondevice-artifact.mjs";
8
10
 
11
+ const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
12
+ const cleanupHelperScript = path.join(
13
+ repoRoot,
14
+ "packages",
15
+ "scripts",
16
+ "rm-path-recursive.mjs",
17
+ );
18
+
19
+ function removePathRecursive(targetPath: string) {
20
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
21
+ cwd: repoRoot,
22
+ stdio: "inherit",
23
+ });
24
+ }
25
+
9
26
  let tmp: string;
10
27
 
11
28
  beforeEach(() => {
@@ -13,7 +30,7 @@ beforeEach(() => {
13
30
  });
14
31
 
15
32
  afterEach(() => {
16
- fs.rmSync(tmp, { recursive: true, force: true });
33
+ removePathRecursive(tmp);
17
34
  });
18
35
 
19
36
  function makeDist(dir: string, asset = "index-abc.js") {
@@ -1,11 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { execFileSync } from "node:child_process";
3
4
  import fs from "node:fs";
4
5
  import path from "node:path";
5
6
  import { resolveRepoRootFromImportMeta } from "./lib/repo-root.mjs";
6
7
  import { collectWorkspaceMaps } from "./lib/workspace-discovery.mjs";
7
8
 
8
9
  const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
10
+ const recursiveCleanupScript = path.join(
11
+ repoRoot,
12
+ "packages/scripts/rm-path-recursive.mjs",
13
+ );
9
14
  const rootPkg = JSON.parse(
10
15
  fs.readFileSync(path.join(repoRoot, "package.json"), "utf8"),
11
16
  );
@@ -202,6 +207,22 @@ function pathExists(filePath) {
202
207
  }
203
208
  }
204
209
 
210
+ function removeDirectoryRecursive(filePath) {
211
+ try {
212
+ execFileSync("node", [recursiveCleanupScript, filePath], {
213
+ cwd: repoRoot,
214
+ encoding: "utf8",
215
+ stdio: "pipe",
216
+ });
217
+ } catch (error) {
218
+ const detail = [error?.stdout, error?.stderr].filter(Boolean).join("\n");
219
+ throw new Error(
220
+ `Failed to remove directory ${filePath}${detail ? `: ${detail}` : ""}`,
221
+ { cause: error },
222
+ );
223
+ }
224
+ }
225
+
205
226
  function removePath(filePath) {
206
227
  try {
207
228
  const stat = fs.lstatSync(filePath);
@@ -209,7 +230,11 @@ function removePath(filePath) {
209
230
  fs.unlinkSync(filePath);
210
231
  return;
211
232
  }
212
- fs.rmSync(filePath, { force: true, recursive: stat.isDirectory() });
233
+ if (stat.isDirectory()) {
234
+ removeDirectoryRecursive(filePath);
235
+ return;
236
+ }
237
+ fs.rmSync(filePath, { force: true });
213
238
  } catch (error) {
214
239
  if (error?.code === "ENOENT") {
215
240
  return;
@@ -14,11 +14,12 @@
14
14
  */
15
15
 
16
16
  import assert from "node:assert/strict";
17
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
17
+ import { execFileSync } from "node:child_process";
18
+ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
18
19
  import { tmpdir } from "node:os";
19
20
  import path from "node:path";
20
21
  import test from "node:test";
21
-
22
+ import { resolveRepoRootFromImportMeta } from "./lib/repo-root.mjs";
22
23
  import {
23
24
  findMachOFiles,
24
25
  isMachO,
@@ -26,6 +27,21 @@ import {
26
27
  walkBundleFiles,
27
28
  } from "./mas-smoke.mjs";
28
29
 
30
+ const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
31
+ const cleanupHelperScript = path.join(
32
+ repoRoot,
33
+ "packages",
34
+ "scripts",
35
+ "rm-path-recursive.mjs",
36
+ );
37
+
38
+ function removePathRecursive(targetPath) {
39
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
40
+ cwd: repoRoot,
41
+ stdio: "inherit",
42
+ });
43
+ }
44
+
29
45
  const SAMPLE_PLIST = `<?xml version="1.0" encoding="UTF-8"?>
30
46
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
31
47
  <plist version="1.0">
@@ -106,7 +122,7 @@ test("isMachO detects 64-bit Mach-O magic", () => {
106
122
  writeFileSync(machoPath, MACHO_HEADER_64);
107
123
  assert.equal(isMachO(machoPath), true);
108
124
  } finally {
109
- rmSync(dir, { recursive: true, force: true });
125
+ removePathRecursive(dir);
110
126
  }
111
127
  });
112
128
 
@@ -117,7 +133,7 @@ test("isMachO detects fat (universal) Mach-O magic", () => {
117
133
  writeFileSync(machoPath, MACHO_HEADER_FAT);
118
134
  assert.equal(isMachO(machoPath), true);
119
135
  } finally {
120
- rmSync(dir, { recursive: true, force: true });
136
+ removePathRecursive(dir);
121
137
  }
122
138
  });
123
139
 
@@ -128,7 +144,7 @@ test("isMachO returns false on non-Mach-O files", () => {
128
144
  writeFileSync(textPath, NOT_MACHO);
129
145
  assert.equal(isMachO(textPath), false);
130
146
  } finally {
131
- rmSync(dir, { recursive: true, force: true });
147
+ removePathRecursive(dir);
132
148
  }
133
149
  });
134
150
 
@@ -139,7 +155,7 @@ test("isMachO returns false on tiny files (too small for magic)", () => {
139
155
  writeFileSync(tinyPath, Buffer.from([0xfe, 0xed])); // only 2 bytes
140
156
  assert.equal(isMachO(tinyPath), false);
141
157
  } finally {
142
- rmSync(dir, { recursive: true, force: true });
158
+ removePathRecursive(dir);
143
159
  }
144
160
  });
145
161
 
@@ -164,7 +180,7 @@ test("walkBundleFiles enumerates files recursively, skipping directories", () =>
164
180
  ],
165
181
  );
166
182
  } finally {
167
- rmSync(dir, { recursive: true, force: true });
183
+ removePathRecursive(dir);
168
184
  }
169
185
  });
170
186
 
@@ -189,7 +205,7 @@ test("findMachOFiles returns only files matching Mach-O magic", () => {
189
205
  .sort();
190
206
  assert.deepEqual(machos, ["Contents/MacOS/bun", "Contents/MacOS/launcher"]);
191
207
  } finally {
192
- rmSync(dir, { recursive: true, force: true });
208
+ removePathRecursive(dir);
193
209
  }
194
210
  });
195
211
 
@@ -215,6 +231,6 @@ test("findMachOFiles handles deeply nested binaries (e.g. Frameworks)", () => {
215
231
  "Contents/Frameworks/Foo.framework/Versions/A/Foo",
216
232
  ]);
217
233
  } finally {
218
- rmSync(dir, { recursive: true, force: true });
234
+ removePathRecursive(dir);
219
235
  }
220
236
  });
@@ -17,9 +17,10 @@
17
17
  * is no fallback path.
18
18
  */
19
19
 
20
- import { spawnSync } from "node:child_process";
20
+ import { execFileSync, spawnSync } from "node:child_process";
21
21
  import fs from "node:fs";
22
22
  import path from "node:path";
23
+ import { fileURLToPath } from "node:url";
23
24
 
24
25
  const OMNIVOICE_REPO =
25
26
  process.env.ELIZA_OMNIVOICE_REMOTE ||
@@ -36,6 +37,13 @@ export const OMNIVOICE_GGML_REF =
36
37
  process.env.ELIZA_OMNIVOICE_GGML_REF ||
37
38
  "0e3980ef205ea3639650f59e54cfeecd7d947700";
38
39
 
40
+ const SCRIPT_PATH = fileURLToPath(import.meta.url);
41
+ const SCRIPT_DIR = path.dirname(SCRIPT_PATH);
42
+ const RECURSIVE_CLEANUP_SCRIPT = path.resolve(
43
+ SCRIPT_DIR,
44
+ "../../../scripts/rm-path-recursive.mjs",
45
+ );
46
+
39
47
  // Subdirectory inside the llama.cpp checkout where omnivoice sources
40
48
  // land. Stable so the CMake graft and the symbol verifier agree.
41
49
  export const OMNIVOICE_GRAFT_SUBDIR = "omnivoice";
@@ -72,6 +80,21 @@ function run(cmd, args, opts = {}) {
72
80
  return result.stdout?.trim() ?? "";
73
81
  }
74
82
 
83
+ function removeDirectoryRecursive(targetPath) {
84
+ try {
85
+ execFileSync("node", [RECURSIVE_CLEANUP_SCRIPT, path.resolve(targetPath)], {
86
+ encoding: "utf8",
87
+ stdio: "pipe",
88
+ });
89
+ } catch (error) {
90
+ const detail = [error?.stdout, error?.stderr].filter(Boolean).join("\n");
91
+ throw new Error(
92
+ `[omnivoice-fuse] failed to remove directory ${targetPath}${detail ? `: ${detail}` : ""}`,
93
+ { cause: error },
94
+ );
95
+ }
96
+ }
97
+
75
98
  function copyDirRecursive(src, dst) {
76
99
  fs.mkdirSync(dst, { recursive: true });
77
100
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
@@ -101,7 +124,7 @@ function replaceBetween(source, startMarker, endMarker, replacement) {
101
124
  return source.slice(0, start) + replacement + source.slice(end);
102
125
  }
103
126
 
104
- function writeElizaFfiAdapter({ graftRoot, commit }) {
127
+ function writeElizaFfiAdapter({ graftRoot }) {
105
128
  const ffiHeaderSrc = new URL("./ffi.h", import.meta.url).pathname;
106
129
  const ffiHeaderDst = path.join(graftRoot, "src", "ffi.h");
107
130
  fs.copyFileSync(ffiHeaderSrc, ffiHeaderDst);
@@ -2201,7 +2224,7 @@ static struct ggml_tensor * dac_conv_t1d(struct ggml_context * ctx,
2201
2224
  `#pragma once\n#define OMNIVOICE_VERSION "${commit.slice(0, 12)} (eliza-fused)"\n`,
2202
2225
  "utf8",
2203
2226
  );
2204
- writeElizaFfiAdapter({ graftRoot, commit });
2227
+ writeElizaFfiAdapter({ graftRoot });
2205
2228
  }
2206
2229
 
2207
2230
  // Ensure a clone of omnivoice.cpp at OMNIVOICE_REF lives under
@@ -2685,7 +2708,7 @@ export function prepareOmnivoiceFusion({
2685
2708
  // If a previous run left an aborted graft behind, blow it away. The
2686
2709
  // git checkout itself remains untouched — we only own the graft
2687
2710
  // subdirectory.
2688
- fs.rmSync(graftRoot, { recursive: true, force: true });
2711
+ removeDirectoryRecursive(graftRoot);
2689
2712
  fs.mkdirSync(graftRoot, { recursive: true });
2690
2713
 
2691
2714
  for (const subdir of ["src", "tools"]) {