@aspectlylabs/mikka 0.0.95 → 0.0.106

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/cli.js CHANGED
@@ -4437,7 +4437,7 @@ import { join as join4 } from "node:path";
4437
4437
  // package.json
4438
4438
  var package_default = {
4439
4439
  name: "@mikka/daemon",
4440
- version: "0.0.95",
4440
+ version: "0.0.106",
4441
4441
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4442
4442
  type: "module",
4443
4443
  private: true,
@@ -4496,7 +4496,7 @@ var package_default = {
4496
4496
  engines: {
4497
4497
  node: ">=24"
4498
4498
  },
4499
- gitHead: "7d6aed6c8e04f8a8b251b1367cf59c6a6ab362e2"
4499
+ gitHead: "60d54a4163812afb5b37883730f64669afc9db4a"
4500
4500
  };
4501
4501
 
4502
4502
  // src/paths.ts
@@ -6111,6 +6111,17 @@ function isInside(parent, child) {
6111
6111
  const rel = relative2(parent, child);
6112
6112
  return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
6113
6113
  }
6114
+ var configWriters = /* @__PURE__ */ new Map();
6115
+ function withRepoConfig(repoPath, work) {
6116
+ const key2 = resolve4(repoPath);
6117
+ const result = (configWriters.get(key2) ?? Promise.resolve()).then(work, work);
6118
+ const settled = result.then(() => void 0, () => void 0);
6119
+ configWriters.set(key2, settled);
6120
+ void settled.then(() => {
6121
+ if (configWriters.get(key2) === settled) configWriters.delete(key2);
6122
+ });
6123
+ return result;
6124
+ }
6114
6125
  var WorktreeManager = class {
6115
6126
  constructor(root, retainResources = false) {
6116
6127
  this.root = root;
@@ -6138,16 +6149,19 @@ var WorktreeManager = class {
6138
6149
  const path = this.pathFor(runId);
6139
6150
  if (existsSync3(join7(path, ".git"))) return path;
6140
6151
  mkdirSync5(this.root, { recursive: true });
6141
- await simpleGit(repoPath).raw([
6142
- "worktree",
6143
- "add",
6144
- "-B",
6145
- runBranch(runId),
6146
- path,
6147
- // The base branch comes from the server: never let it read as an option.
6148
- "--end-of-options",
6149
- baseBranch
6150
- ]);
6152
+ await withRepoConfig(
6153
+ repoPath,
6154
+ () => simpleGit(repoPath).raw([
6155
+ "worktree",
6156
+ "add",
6157
+ "-B",
6158
+ runBranch(runId),
6159
+ path,
6160
+ // The base branch comes from the server: never let it read as an option.
6161
+ "--end-of-options",
6162
+ baseBranch
6163
+ ])
6164
+ );
6151
6165
  return path;
6152
6166
  }
6153
6167
  /**
@@ -6312,8 +6326,10 @@ var WorktreeManager = class {
6312
6326
  branches.push(branch);
6313
6327
  }
6314
6328
  if (path) await this.removePath(path, repoPath);
6315
- for (const branch of branches)
6316
- await git2.raw(["branch", "-D", "--", branch]).catch(() => void 0);
6329
+ await withRepoConfig(repoPath, async () => {
6330
+ for (const branch of branches)
6331
+ await git2.raw(["branch", "-D", "--", branch]).catch(() => void 0);
6332
+ });
6317
6333
  return true;
6318
6334
  }
6319
6335
  /**
@@ -7603,14 +7619,14 @@ sandbox_mode = "read-only"
7603
7619
  import { randomBytes as randomBytes3, randomUUID as randomUUID10 } from "node:crypto";
7604
7620
  import {
7605
7621
  chmodSync as chmodSync5,
7606
- existsSync as existsSync8,
7622
+ existsSync as existsSync9,
7607
7623
  mkdirSync as mkdirSync17,
7608
7624
  readFileSync as readFileSync12,
7609
- rmSync as rmSync18,
7625
+ rmSync as rmSync19,
7610
7626
  realpathSync as realpathSync13
7611
7627
  } from "node:fs";
7612
7628
  import { arch, hostname, platform as platform2 } from "node:os";
7613
- import { join as join32 } from "node:path";
7629
+ import { join as join33 } from "node:path";
7614
7630
  import { fileURLToPath as fileURLToPath3 } from "node:url";
7615
7631
 
7616
7632
  // src/adapters/claude.ts
@@ -9818,31 +9834,49 @@ var MockAdapter = class {
9818
9834
  };
9819
9835
 
9820
9836
  // src/agents/verify.ts
9821
- import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync5, realpathSync as realpathSync10, rmSync as rmSync11 } from "node:fs";
9837
+ import { existsSync as existsSync5, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync5, realpathSync as realpathSync10, rmSync as rmSync11 } from "node:fs";
9822
9838
  import { join as join19 } from "node:path";
9823
9839
  var OUTPUT_TAIL = 4e3;
9840
+ var SETUP_ATTEMPTS = 3;
9824
9841
  async function runVerify(sandbox, options) {
9825
9842
  mkdirSync12(options.tmpRoot, { recursive: true, mode: 448 });
9826
9843
  const tmpDir = mkdtempSync5(join19(realpathSync10(options.tmpRoot), "verify-"));
9827
- const child = await spawnCli(sandbox, ["/bin/sh", "-c", options.command], {
9828
- cwd: options.worktree,
9829
- env: { ...options.env, TMPDIR: tmpDir },
9830
- policy: {
9831
- allowWrite: options.readOnly ? [tmpDir] : [options.worktree, tmpDir],
9832
- denyWrite: [
9833
- join19(options.worktree, ".git"),
9834
- ...options.readOnly ? [options.worktree] : []
9835
- ],
9836
- denyRead: [
9837
- ...credentialDenyRead(null),
9838
- ...daemonSecrets(options.privateDir)
9839
- ],
9840
- allowDomains: [...options.networkAllow ?? []]
9841
- },
9842
- pidFile: options.pidFile,
9843
- // Every verify of this run carries the temp root in its profile.
9844
- marker: realpathSync10(options.tmpRoot)
9845
- });
9844
+ const deadline = Date.now() + options.timeoutMs;
9845
+ try {
9846
+ for (let attempt = 1; ; attempt++) {
9847
+ const started = join19(tmpDir, `.started-${attempt}`);
9848
+ const result = await attemptVerify(sandbox, options, tmpDir, started, deadline - Date.now());
9849
+ if (result.exitCode === 0 || result.timedOut || options.signal?.aborted || existsSync5(started) || attempt >= SETUP_ATTEMPTS)
9850
+ return result;
9851
+ }
9852
+ } finally {
9853
+ rmSync11(tmpDir, { recursive: true, force: true });
9854
+ }
9855
+ }
9856
+ async function attemptVerify(sandbox, options, tmpDir, started, timeoutMs) {
9857
+ const child = await spawnCli(
9858
+ sandbox,
9859
+ ["/bin/sh", "-c", ': > "$0" && exec /bin/sh -c "$1"', started, options.command],
9860
+ {
9861
+ cwd: options.worktree,
9862
+ env: { ...options.env, TMPDIR: tmpDir },
9863
+ policy: {
9864
+ allowWrite: options.readOnly ? [tmpDir] : [options.worktree, tmpDir],
9865
+ denyWrite: [
9866
+ join19(options.worktree, ".git"),
9867
+ ...options.readOnly ? [options.worktree] : []
9868
+ ],
9869
+ denyRead: [
9870
+ ...credentialDenyRead(null),
9871
+ ...daemonSecrets(options.privateDir)
9872
+ ],
9873
+ allowDomains: [...options.networkAllow ?? []]
9874
+ },
9875
+ pidFile: options.pidFile,
9876
+ // Every verify of this run carries the temp root in its profile.
9877
+ marker: realpathSync10(options.tmpRoot)
9878
+ }
9879
+ );
9846
9880
  child.process.stdin.end();
9847
9881
  let output = "";
9848
9882
  for (const stream of [child.process.stdout, child.process.stderr]) {
@@ -9855,7 +9889,7 @@ async function runVerify(sandbox, options) {
9855
9889
  const timer = setTimeout(() => {
9856
9890
  timedOut = true;
9857
9891
  void child.kill();
9858
- }, options.timeoutMs);
9892
+ }, Math.max(0, timeoutMs));
9859
9893
  const abort = () => void child.kill();
9860
9894
  options.signal?.addEventListener("abort", abort, { once: true });
9861
9895
  try {
@@ -9871,7 +9905,6 @@ async function runVerify(sandbox, options) {
9871
9905
  ].join("\n")
9872
9906
  };
9873
9907
  } finally {
9874
- rmSync11(tmpDir, { recursive: true, force: true });
9875
9908
  clearTimeout(timer);
9876
9909
  options.signal?.removeEventListener("abort", abort);
9877
9910
  }
@@ -10415,7 +10448,7 @@ async function detectHarnesses() {
10415
10448
  }
10416
10449
 
10417
10450
  // src/sandbox-tools.ts
10418
- import { chmodSync as chmodSync2, existsSync as existsSync5, lstatSync as lstatSync8, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync6, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync12, writeFileSync as writeFileSync7 } from "node:fs";
10451
+ import { chmodSync as chmodSync2, existsSync as existsSync6, lstatSync as lstatSync8, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync6, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync12, writeFileSync as writeFileSync7 } from "node:fs";
10419
10452
  import { join as join23 } from "node:path";
10420
10453
  import { execa as execa10 } from "execa";
10421
10454
  var TOOLS = [
@@ -10499,11 +10532,11 @@ LD_LIBRARY_PATH=${shellQuote2(libDir)} exec ${shellQuote2(join23(realDir, tool2.
10499
10532
  renameSync2(launcher, join23(binDir, tool2.command));
10500
10533
  }
10501
10534
  function moveSharedLibraries(directory, libDir) {
10502
- if (!existsSync5(directory)) return;
10535
+ if (!existsSync6(directory)) return;
10503
10536
  for (const entry of readdirSync5(directory)) {
10504
10537
  const path = join23(directory, entry);
10505
10538
  if (lstatSync8(path).isDirectory()) moveSharedLibraries(path, libDir);
10506
- else if (entry.includes(".so") && !existsSync5(join23(libDir, entry))) renameSync2(path, join23(libDir, entry));
10539
+ else if (entry.includes(".so") && !existsSync6(join23(libDir, entry))) renameSync2(path, join23(libDir, entry));
10507
10540
  }
10508
10541
  }
10509
10542
  function shellQuote2(value) {
@@ -11811,6 +11844,47 @@ async function fixedCheckSnapshot(repoPath, worktree, sha) {
11811
11844
  return { sha, tree: await git2("rev-parse", `${sha}^{tree}`) };
11812
11845
  }
11813
11846
 
11847
+ // src/run-scratch.ts
11848
+ import { rmSync as rmSync15 } from "node:fs";
11849
+ import { join as join27 } from "node:path";
11850
+
11851
+ // src/credential-globs.ts
11852
+ var CLOUD_WORKER_STATE_DIR = "/home/mikka-runner/.mikka/worker/adapters";
11853
+ var RUN_CREDENTIAL_PATHS = [
11854
+ // GitHub token config and gh wrapper (agents/github-runtime.ts).
11855
+ "github",
11856
+ // Coding-CLI homes inside a run: only placeholders today, but a real login must never be kept.
11857
+ "runtime-home/.claude/.credentials.json",
11858
+ "runtime-home/.codex/auth.json",
11859
+ // Per-run harness homes on a device runner (agents/harness-home.ts).
11860
+ "codex-home/auth.json",
11861
+ "native-home/.claude/.credentials.json",
11862
+ "native-home/.codex/auth.json"
11863
+ ];
11864
+ function runCredentialGlobs(stateDir) {
11865
+ return [
11866
+ ...RUN_CREDENTIAL_PATHS.map((path) => `${stateDir}/runs/*/${path}`),
11867
+ // Live native subscription brokers (subscription-native-broker.ts).
11868
+ `${stateDir}/native-brokers/*`
11869
+ ];
11870
+ }
11871
+ var SNAPSHOT_CREDENTIAL_GLOBS = [
11872
+ "/root/.claude/.credentials.json",
11873
+ "/root/.codex/auth.json",
11874
+ "/home/*/.claude/.credentials.json",
11875
+ "/home/*/.codex/auth.json",
11876
+ "/home/*/.config/gh/hosts.yml",
11877
+ "/home/*/.git-credentials",
11878
+ "/root/.git-credentials",
11879
+ ...runCredentialGlobs(CLOUD_WORKER_STATE_DIR)
11880
+ ];
11881
+
11882
+ // src/run-scratch.ts
11883
+ function removeRunCredentials(stateDir, runId) {
11884
+ const { runDir } = runPaths(stateDir, runId);
11885
+ for (const path of RUN_CREDENTIAL_PATHS) rmSync15(join27(runDir, path), { recursive: true, force: true });
11886
+ }
11887
+
11814
11888
  // src/secret-mask.ts
11815
11889
  import { gunzipSync, gzipSync } from "node:zlib";
11816
11890
  var MASK_MIN_LENGTH = 8;
@@ -11942,13 +12016,13 @@ function createRunMasker(secrets) {
11942
12016
 
11943
12017
  // src/runs/supervisor.ts
11944
12018
  import { createHash as createHash4, randomUUID as randomUUID6 } from "node:crypto";
11945
- import { join as join28, resolve as resolve10 } from "node:path";
12019
+ import { join as join29, resolve as resolve10 } from "node:path";
11946
12020
  import { execa as execa13 } from "execa";
11947
12021
 
11948
12022
  // src/agents/checkpoint.ts
11949
- import { mkdtempSync as mkdtempSync7, rmSync as rmSync15, writeFileSync as writeFileSync8 } from "node:fs";
12023
+ import { mkdtempSync as mkdtempSync7, rmSync as rmSync16, writeFileSync as writeFileSync8 } from "node:fs";
11950
12024
  import { tmpdir as tmpdir2 } from "node:os";
11951
- import { join as join27 } from "node:path";
12025
+ import { join as join28 } from "node:path";
11952
12026
  import { gunzipSync as gunzipSync2, gzipSync as gzipSync2 } from "node:zlib";
11953
12027
  import { execa as execa12 } from "execa";
11954
12028
  var CheckpointRecoveryError = class extends Error {
@@ -11995,8 +12069,8 @@ async function takeCheckpoint(options) {
11995
12069
  }
11996
12070
  async function applyCheckpoint(options) {
11997
12071
  const git2 = await pinnedGit(options.repoPath, options.worktree);
11998
- const dir = mkdtempSync7(join27(tmpdir2(), "mikka-checkpoint-"));
11999
- const file = join27(dir, "checkpoint.patch");
12072
+ const dir = mkdtempSync7(join28(tmpdir2(), "mikka-checkpoint-"));
12073
+ const file = join28(dir, "checkpoint.patch");
12000
12074
  try {
12001
12075
  const patch = gunzipSync2(Buffer.from(options.checkpoint.patch, "base64"));
12002
12076
  if (!patch.length && options.checkpoint.files === 0) return true;
@@ -12013,7 +12087,7 @@ async function applyCheckpoint(options) {
12013
12087
  }
12014
12088
  return false;
12015
12089
  } finally {
12016
- rmSync15(dir, { recursive: true, force: true });
12090
+ rmSync16(dir, { recursive: true, force: true });
12017
12091
  }
12018
12092
  }
12019
12093
  async function hasCommit(repoPath, commit) {
@@ -12821,6 +12895,13 @@ var RunSupervisor = class {
12821
12895
  const run2 = this.active.get(runId);
12822
12896
  if (run2) void this.closeMailbox(run2).catch(() => this.deps.log.warn("Run mailbox shutdown failed"));
12823
12897
  this.leases.delete(runId);
12898
+ if (this.deps.adapterStateDir) {
12899
+ try {
12900
+ removeRunCredentials(this.deps.adapterStateDir, runId);
12901
+ } catch (err) {
12902
+ this.deps.log.warn({ run_id: runId, err }, "run credential cleanup failed");
12903
+ }
12904
+ }
12824
12905
  this.deps.outbox.compact(runId).catch((err) => {
12825
12906
  this.deps.log.error({ run_id: runId, err }, "outbox compaction failed");
12826
12907
  });
@@ -13234,7 +13315,7 @@ var RunSupervisor = class {
13234
13315
  if (!this.deps.adapterStateDir || assignment.harness === "mock" || !session.sessionId || resuming && session.sessionId !== entry.sessionId || assignment.requireSessionResume && session.sessionId !== assignment.resumeSessionId)
13235
13316
  throw new Error("Skill mount requires the actual original harness session");
13236
13317
  verifySkillAssignment(assignment);
13237
- const file = join28(
13318
+ const file = join29(
13238
13319
  runPaths(this.deps.adapterStateDir, runId).runDir,
13239
13320
  SKILLS_DIR,
13240
13321
  skillSlug(assignment.skills[0].name),
@@ -13498,8 +13579,8 @@ function fixedCandidateCheck(assignment) {
13498
13579
 
13499
13580
  // src/repositories.ts
13500
13581
  import { createHash as createHash5, randomUUID as randomUUID7 } from "node:crypto";
13501
- import { existsSync as existsSync6, lstatSync as lstatSync9, mkdirSync as mkdirSync15, readdirSync as readdirSync7, realpathSync as realpathSync11, renameSync as renameSync3, rmSync as rmSync16 } from "node:fs";
13502
- import { dirname as dirname11, join as join29, resolve as resolve11 } from "node:path";
13582
+ import { existsSync as existsSync7, lstatSync as lstatSync9, mkdirSync as mkdirSync15, readdirSync as readdirSync7, realpathSync as realpathSync11, renameSync as renameSync3, rmSync as rmSync17 } from "node:fs";
13583
+ import { dirname as dirname11, join as join30, resolve as resolve11 } from "node:path";
13503
13584
  import { setTimeout as delay2 } from "node:timers/promises";
13504
13585
  import { execa as execa14 } from "execa";
13505
13586
  import lockfile2 from "proper-lockfile";
@@ -13526,33 +13607,36 @@ var RepositoryCache = class {
13526
13607
  this.ensureParents(dirname11(path));
13527
13608
  const release = await this.lock(path, signal);
13528
13609
  try {
13529
- signal?.throwIfAborted();
13530
- const git2 = (args, cwd) => execa14("git", [
13531
- ...FETCH_GIT,
13532
- "-c",
13533
- `protocol.file.allow=${this.allowFile ? "always" : "never"}`,
13534
- ...args
13535
- ], { cwd, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }, stdin: "ignore", timeout: FETCH_TIMEOUT_MS, cancelSignal: signal, killDescendants: true });
13536
- if (!existsSync6(path)) {
13537
- const temporary = `${path}.clone-${randomUUID7()}`;
13538
- try {
13539
- await git2(["clone", "--no-checkout", "--no-hardlinks", "--no-recurse-submodules", "--", remote, temporary]);
13540
- renameSync3(temporary, path);
13541
- } finally {
13542
- if (!this.retainResources) rmSync16(temporary, { recursive: true, force: true });
13543
- }
13544
- } else {
13545
- this.assertClone(path);
13546
- await git2(["remote", "set-url", "origin", remote], path);
13547
- await git2(["fetch", ...this.retainResources ? [] : ["--prune"], "--no-tags", "--no-recurse-submodules", "--no-write-fetch-head", "origin"], path);
13548
- }
13549
- this.assertClone(path);
13550
- await git2(["remote", "set-head", "origin", "-a"], path);
13551
- return path;
13610
+ return await withRepoConfig(path, () => this.update(path, remote, signal));
13552
13611
  } finally {
13553
13612
  await release();
13554
13613
  }
13555
13614
  }
13615
+ async update(path, remote, signal) {
13616
+ signal?.throwIfAborted();
13617
+ const git2 = (args, cwd) => execa14("git", [
13618
+ ...FETCH_GIT,
13619
+ "-c",
13620
+ `protocol.file.allow=${this.allowFile ? "always" : "never"}`,
13621
+ ...args
13622
+ ], { cwd, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }, stdin: "ignore", timeout: FETCH_TIMEOUT_MS, cancelSignal: signal, killDescendants: true });
13623
+ if (!existsSync7(path)) {
13624
+ const temporary = `${path}.clone-${randomUUID7()}`;
13625
+ try {
13626
+ await git2(["clone", "--no-checkout", "--no-hardlinks", "--no-recurse-submodules", "--", remote, temporary]);
13627
+ renameSync3(temporary, path);
13628
+ } finally {
13629
+ if (!this.retainResources) rmSync17(temporary, { recursive: true, force: true });
13630
+ }
13631
+ } else {
13632
+ this.assertClone(path);
13633
+ await git2(["remote", "set-url", "origin", remote], path);
13634
+ await git2(["fetch", ...this.retainResources ? [] : ["--prune"], "--no-tags", "--no-recurse-submodules", "--no-write-fetch-head", "origin"], path);
13635
+ }
13636
+ this.assertClone(path);
13637
+ await git2(["remote", "set-head", "origin", "-a"], path);
13638
+ return path;
13639
+ }
13556
13640
  async baseRef(remoteUrl, baseBranch) {
13557
13641
  const path = this.pathFor(remoteUrl);
13558
13642
  if (baseBranch && baseBranch !== "HEAD") {
@@ -13566,12 +13650,12 @@ var RepositoryCache = class {
13566
13650
  /** Cache paths for retention/orphan cleanup; never consult user checkouts. */
13567
13651
  paths() {
13568
13652
  const visit = (path) => {
13569
- if (!existsSync6(path) || lstatSync9(path).isSymbolicLink()) return [];
13570
- if (existsSync6(join29(path, ".git"))) {
13653
+ if (!existsSync7(path) || lstatSync9(path).isSymbolicLink()) return [];
13654
+ if (existsSync7(join30(path, ".git"))) {
13571
13655
  this.assertClone(path);
13572
13656
  return [path];
13573
13657
  }
13574
- return readdirSync7(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join29(path, entry.name)) : []);
13658
+ return readdirSync7(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join30(path, entry.name)) : []);
13575
13659
  };
13576
13660
  return visit(resolve11(this.root));
13577
13661
  }
@@ -13581,14 +13665,14 @@ var RepositoryCache = class {
13581
13665
  const root = realpathSync11(this.root);
13582
13666
  let current = resolve11(this.root);
13583
13667
  for (const part of path.slice(current.length + 1).split("/").filter(Boolean)) {
13584
- current = join29(current, part);
13585
- if (existsSync6(current) && lstatSync9(current).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
13668
+ current = join30(current, part);
13669
+ if (existsSync7(current) && lstatSync9(current).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
13586
13670
  mkdirSync15(current, { recursive: true, mode: 448 });
13587
13671
  if (!isInside(root, realpathSync11(current))) throw new Error("Repository cache escapes its directory");
13588
13672
  }
13589
13673
  }
13590
13674
  assertClone(path) {
13591
- if (lstatSync9(path).isSymbolicLink() || !lstatSync9(join29(path, ".git")).isDirectory() || lstatSync9(join29(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
13675
+ if (lstatSync9(path).isSymbolicLink() || !lstatSync9(join30(path, ".git")).isDirectory() || lstatSync9(join30(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
13592
13676
  if (!isInside(realpathSync11(this.root), realpathSync11(path))) throw new Error("Repository cache escapes its directory");
13593
13677
  }
13594
13678
  async lock(path, signal) {
@@ -13609,16 +13693,16 @@ var RepositoryCache = class {
13609
13693
  import { execFile as execFile5, spawn as spawn4 } from "node:child_process";
13610
13694
  import { randomUUID as randomUUID8 } from "node:crypto";
13611
13695
  import {
13612
- existsSync as existsSync7,
13696
+ existsSync as existsSync8,
13613
13697
  lstatSync as lstatSync10,
13614
13698
  mkdirSync as mkdirSync16,
13615
13699
  mkdtempSync as mkdtempSync8,
13616
13700
  readdirSync as readdirSync8,
13617
13701
  realpathSync as realpathSync12,
13618
- rmSync as rmSync17
13702
+ rmSync as rmSync18
13619
13703
  } from "node:fs";
13620
13704
  import { createRequire } from "node:module";
13621
- import { delimiter as delimiter4, dirname as dirname12, join as join31 } from "node:path";
13705
+ import { delimiter as delimiter4, dirname as dirname12, join as join32 } from "node:path";
13622
13706
  import { fileURLToPath as fileURLToPath2 } from "node:url";
13623
13707
  import { promisify as promisify5 } from "node:util";
13624
13708
 
@@ -13628,7 +13712,7 @@ import { chmod, mkdtemp, rm as rm2 } from "node:fs/promises";
13628
13712
  import { createServer as createServer3, request as httpRequest } from "node:http";
13629
13713
  import { connect, isIP as isIP3 } from "node:net";
13630
13714
  import { tmpdir as tmpdir3 } from "node:os";
13631
- import { join as join30 } from "node:path";
13715
+ import { join as join31 } from "node:path";
13632
13716
 
13633
13717
  // ../../lib/search/url-policy.ts
13634
13718
  import { BlockList, isIP as isIP2 } from "node:net";
@@ -13697,9 +13781,9 @@ function endToEndHeaders(input) {
13697
13781
  }
13698
13782
  async function startPublicEgress(options) {
13699
13783
  options.signal.throwIfAborted();
13700
- const directory = await mkdtemp(join30(tmpdir3(), "mikka-egress-"));
13784
+ const directory = await mkdtemp(join31(tmpdir3(), "mikka-egress-"));
13701
13785
  await chmod(directory, 448);
13702
- const socketPath = join30(directory, "egress.sock");
13786
+ const socketPath = join31(directory, "egress.sock");
13703
13787
  const lifetime = new AbortController();
13704
13788
  const signal = AbortSignal.any([options.signal, lifetime.signal]);
13705
13789
  const sockets = /* @__PURE__ */ new Set();
@@ -13856,7 +13940,7 @@ async function createHostedBotRunner(host) {
13856
13940
  }).catch(() => {
13857
13941
  throw unavailable2();
13858
13942
  });
13859
- const resources = join31(host.stateDir, "native-resources");
13943
+ const resources = join32(host.stateDir, "native-resources");
13860
13944
  mkdirSync16(resources, { recursive: true, mode: 448 });
13861
13945
  const removeResource = async (file, record) => {
13862
13946
  if (!/^mikka-native-(?:verify-)?[a-f0-9-]{36}$/.test(record.name) || !/^[a-f0-9-]{36}$/.test(record.nonce))
@@ -13877,9 +13961,9 @@ async function createHostedBotRunner(host) {
13877
13961
  if (record.state === "created" && /No such (?:container|object)/i.test(
13878
13962
  String(error.stderr)
13879
13963
  )) {
13880
- if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
13881
- rmSync17(record.assets, { recursive: true, force: true });
13882
- rmSync17(file, { force: true });
13964
+ if (record.assets?.startsWith(join32(host.stateDir, "native-verify-git-")))
13965
+ rmSync18(record.assets, { recursive: true, force: true });
13966
+ rmSync18(file, { force: true });
13883
13967
  return;
13884
13968
  }
13885
13969
  throw new Error("native_runtime_cleanup_unconfirmed");
@@ -13888,13 +13972,13 @@ async function createHostedBotRunner(host) {
13888
13972
  if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id4)
13889
13973
  throw unavailable2();
13890
13974
  await exec3("docker", ["rm", "-f", id4], { env: bareEnv, timeout: 3e4 });
13891
- if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
13892
- rmSync17(record.assets, { recursive: true, force: true });
13893
- rmSync17(file, { force: true });
13975
+ if (record.assets?.startsWith(join32(host.stateDir, "native-verify-git-")))
13976
+ rmSync18(record.assets, { recursive: true, force: true });
13977
+ rmSync18(file, { force: true });
13894
13978
  };
13895
13979
  for (const name of readdirSync8(resources))
13896
13980
  if (name.endsWith(".json")) {
13897
- const file = join31(resources, name);
13981
+ const file = join32(resources, name);
13898
13982
  const record = readJson(file);
13899
13983
  if (!record) throw unavailable2();
13900
13984
  await removeResource(file, record);
@@ -13905,7 +13989,7 @@ async function createHostedBotRunner(host) {
13905
13989
  const bundled = createRequire(
13906
13990
  require2.resolve("@anthropic-ai/claude-agent-sdk")
13907
13991
  );
13908
- claude ??= join31(
13992
+ claude ??= join32(
13909
13993
  dirname12(
13910
13994
  bundled.resolve(
13911
13995
  "@anthropic-ai/claude-agent-sdk-linux-x64/package.json"
@@ -13915,7 +13999,7 @@ async function createHostedBotRunner(host) {
13915
13999
  );
13916
14000
  } catch {
13917
14001
  }
13918
- const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter4).map((dir) => join31(dir, "codex")).find((path) => existsSync7(path));
14002
+ const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter4).map((dir) => join32(dir, "codex")).find((path) => existsSync8(path));
13919
14003
  const binaries = { codex, claude_code: claude };
13920
14004
  for (const kind of ["codex", "claude_code"])
13921
14005
  if (binaries[kind]) {
@@ -13929,12 +14013,12 @@ async function createHostedBotRunner(host) {
13929
14013
  if (!binaries.codex && !binaries.claude_code) throw unavailable2();
13930
14014
  const command = async (worktree, script, readOnly, timeoutMs, signal) => {
13931
14015
  const name = `mikka-native-verify-${randomUUID8()}`;
13932
- const file = join31(resources, name + ".json");
14016
+ const file = join32(resources, name + ".json");
13933
14017
  const resource = { name, nonce: randomUUID8(), state: "creating" };
13934
14018
  const timing = { createMs: 0, runMs: 0 };
13935
14019
  let phase = "create";
13936
14020
  let began = performance.now();
13937
- const gitCopy = mkdtempSync8(join31(host.stateDir, "native-verify-git-"));
14021
+ const gitCopy = mkdtempSync8(join32(host.stateDir, "native-verify-git-"));
13938
14022
  resource.assets = gitCopy;
13939
14023
  try {
13940
14024
  const cwd = realpathSync12(worktree);
@@ -13950,7 +14034,7 @@ async function createHostedBotRunner(host) {
13950
14034
  "--no-checkout",
13951
14035
  "--",
13952
14036
  cwd,
13953
- join31(gitCopy, "repo")
14037
+ join32(gitCopy, "repo")
13954
14038
  ],
13955
14039
  {
13956
14040
  env: {
@@ -13965,8 +14049,8 @@ async function createHostedBotRunner(host) {
13965
14049
  maxBuffer: 1024 * 1024
13966
14050
  }
13967
14051
  );
13968
- const safeGit = join31(gitCopy, "repo", ".git");
13969
- const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : safeGit;
14052
+ const safeGit = join32(gitCopy, "repo", ".git");
14053
+ const protectedGit = lstatSync10(join32(cwd, ".git")).isFile() ? join32(cwd, ".git") : safeGit;
13970
14054
  writeJsonAtomic(file, resource);
13971
14055
  const created = await exec3(
13972
14056
  "docker",
@@ -14053,8 +14137,8 @@ async function createHostedBotRunner(host) {
14053
14137
  timing
14054
14138
  };
14055
14139
  } finally {
14056
- if (existsSync7(file)) await removeResource(file, resource);
14057
- else rmSync17(gitCopy, { recursive: true, force: true });
14140
+ if (existsSync8(file)) await removeResource(file, resource);
14141
+ else rmSync18(gitCopy, { recursive: true, force: true });
14058
14142
  }
14059
14143
  };
14060
14144
  return {
@@ -14070,7 +14154,7 @@ async function createHostedBotRunner(host) {
14070
14154
  throw unavailable2();
14071
14155
  const name = `mikka-native-${randomUUID8()}`;
14072
14156
  const nonce = randomUUID8();
14073
- const resourceFile = join31(resources, name + ".json");
14157
+ const resourceFile = join32(resources, name + ".json");
14074
14158
  const resource = { name, nonce, state: "creating" };
14075
14159
  const lifetime = new AbortController();
14076
14160
  let closed = false;
@@ -14109,12 +14193,13 @@ async function createHostedBotRunner(host) {
14109
14193
  void brokerClosed.catch(() => void 0);
14110
14194
  try {
14111
14195
  await creating?.catch(() => void 0);
14112
- if (existsSync7(resourceFile)) await removeResource(resourceFile, resource);
14196
+ if (existsSync8(resourceFile)) await removeResource(resourceFile, resource);
14113
14197
  } finally {
14114
14198
  try {
14115
14199
  await brokerClosed;
14116
14200
  } finally {
14117
14201
  offRevoke();
14202
+ removeRunCredentials(host.stateDir, assignment.runId);
14118
14203
  }
14119
14204
  }
14120
14205
  });
@@ -14143,10 +14228,10 @@ async function createHostedBotRunner(host) {
14143
14228
  };
14144
14229
  const paths = runPaths(host.stateDir, assignment.runId);
14145
14230
  mkdirSync16(paths.runDir, { recursive: true, mode: 448 });
14146
- const shadow = join31(paths.runDir, "runtime-git");
14147
- const emptyHome = join31(paths.runDir, "git-bootstrap-home");
14231
+ const shadow = join32(paths.runDir, "runtime-git");
14232
+ const emptyHome = join32(paths.runDir, "git-bootstrap-home");
14148
14233
  mkdirSync16(emptyHome, { recursive: true, mode: 448 });
14149
- if (!existsSync7(shadow))
14234
+ if (!existsSync8(shadow))
14150
14235
  await exec3(
14151
14236
  "git",
14152
14237
  [
@@ -14175,9 +14260,9 @@ async function createHostedBotRunner(host) {
14175
14260
  }
14176
14261
  );
14177
14262
  await live();
14178
- if (!lstatSync10(shadow).isDirectory() || !lstatSync10(join31(shadow, ".git")).isDirectory() || !realpathSync12(shadow).startsWith(realpathSync12(paths.runDir) + "/"))
14263
+ if (!lstatSync10(shadow).isDirectory() || !lstatSync10(join32(shadow, ".git")).isDirectory() || !realpathSync12(shadow).startsWith(realpathSync12(paths.runDir) + "/"))
14179
14264
  throw unavailable2();
14180
- const ledger = join31(
14265
+ const ledger = join32(
14181
14266
  host.stateDir,
14182
14267
  "native-ledgers",
14183
14268
  assignment.runId + ".json"
@@ -14194,7 +14279,7 @@ async function createHostedBotRunner(host) {
14194
14279
  modelId: first.modelId
14195
14280
  };
14196
14281
  const previous = readJson(ledger);
14197
- if (existsSync7(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
14282
+ if (existsSync8(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
14198
14283
  throw unavailable2();
14199
14284
  mkdirSync16(dirname12(ledger), { recursive: true, mode: 448 });
14200
14285
  const record = async (sessionId) => {
@@ -14202,7 +14287,7 @@ async function createHostedBotRunner(host) {
14202
14287
  writeJsonAtomic(ledger, { scope, sessionId });
14203
14288
  };
14204
14289
  brokerStarting = createNativeSubscriptionBroker({
14205
- root: join31(host.stateDir, "native-brokers"),
14290
+ root: join32(host.stateDir, "native-brokers"),
14206
14291
  revision,
14207
14292
  check,
14208
14293
  worker: {
@@ -14229,7 +14314,7 @@ async function createHostedBotRunner(host) {
14229
14314
  });
14230
14315
  const readyBroker = await brokerStarting;
14231
14316
  await live();
14232
- const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter4).map((dir) => join31(dir, "gh")).find((file) => existsSync7(file)) : void 0;
14317
+ const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter4).map((dir) => join32(dir, "gh")).find((file) => existsSync8(file)) : void 0;
14233
14318
  if (options.github && !githubCli) throw new Error("Install GitHub CLI (gh) in the cloud worker image");
14234
14319
  const githubDomains = options.github ? ["github.com", "api.github.com", new URL(options.github.endpoint).host] : [];
14235
14320
  const egressMaximum = runDomains(runPolicy(options.policy), [...options.networkAllow ?? [], ...githubDomains]);
@@ -14246,7 +14331,7 @@ async function createHostedBotRunner(host) {
14246
14331
  }
14247
14332
  const cwd = realpathSync12(options.cwd);
14248
14333
  const runDir = realpathSync12(paths.runDir);
14249
- const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : join31(shadow, ".git");
14334
+ const protectedGit = lstatSync10(join32(cwd, ".git")).isFile() ? join32(cwd, ".git") : join32(shadow, ".git");
14250
14335
  if (!lstatSync10(runDir).isDirectory() || !runDir.startsWith(realpathSync12(host.stateDir) + "/runs/")) {
14251
14336
  await close();
14252
14337
  throw unavailable2();
@@ -14300,7 +14385,7 @@ async function createHostedBotRunner(host) {
14300
14385
  `${MCP_SERVER_SCRIPT}:${MCP_SERVER_SCRIPT}:ro`,
14301
14386
  ...githubCli ? ["-v", `${githubCli}:/usr/local/bin/mikka-gh:ro`, "-v", `${GITHUB_CREDENTIAL_SCRIPT}:${GITHUB_CREDENTIAL_SCRIPT}:ro`] : [],
14302
14387
  "-v",
14303
- `${join31(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join31(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
14388
+ `${join32(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join32(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
14304
14389
  "-v",
14305
14390
  `${readyBroker.socket}:/run/mikka-native.sock:ro`,
14306
14391
  ...computerGrant ? [
@@ -14343,13 +14428,13 @@ async function createHostedBotRunner(host) {
14343
14428
  }
14344
14429
  const spawnHosted = (config) => {
14345
14430
  assertOpen();
14346
- const home = join31(runDir, "runtime-home");
14431
+ const home = join32(runDir, "runtime-home");
14347
14432
  mkdirSync16(home, { recursive: true, mode: 448 });
14348
14433
  const env = {
14349
14434
  ...config.env,
14350
14435
  HOME: kind === "claude_code" ? config.env.HOME ?? home : home,
14351
- PATH: `${options.github ? join31(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
14352
- GIT_DIR: join31(shadow, ".git"),
14436
+ PATH: `${options.github ? join32(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
14437
+ GIT_DIR: join32(shadow, ".git"),
14353
14438
  GIT_WORK_TREE: cwd,
14354
14439
  GIT_CONFIG_GLOBAL: "/dev/null",
14355
14440
  GIT_CONFIG_SYSTEM: "/dev/null",
@@ -14368,7 +14453,7 @@ async function createHostedBotRunner(host) {
14368
14453
  signal: AbortSignal.any([lifetime.signal, ...config.signal ? [config.signal] : []])
14369
14454
  });
14370
14455
  child.stdin.write(
14371
- JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join31(runDir, "github", "bin") } : {} }) + "\n"
14456
+ JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join32(runDir, "github", "bin") } : {} }) + "\n"
14372
14457
  );
14373
14458
  return child;
14374
14459
  };
@@ -15067,7 +15152,7 @@ var Daemon = class {
15067
15152
  if (this.options.credential)
15068
15153
  this.saveDevice({ credential: this.options.credential });
15069
15154
  this.journal = new RunJournal(paths.journal);
15070
- this.captureUploader = new CaptureUploader((runId) => join32(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join32(paths.dataDir, "capture-pending"));
15155
+ this.captureUploader = new CaptureUploader((runId) => join33(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join33(paths.dataDir, "capture-pending"));
15071
15156
  this.outbox = new Outbox(
15072
15157
  paths.outbox,
15073
15158
  this.options.link,
@@ -15084,7 +15169,7 @@ var Daemon = class {
15084
15169
  if (this.localComputerDriver && this.options.link.syncComputerReviews && this.options.link.localComputerAuthority) {
15085
15170
  this.localComputerBroker = new ComputerBroker({
15086
15171
  driver: this.localComputerDriver,
15087
- socketPath: join32(paths.dataDir, "local-computer.sock"),
15172
+ socketPath: join33(paths.dataDir, "local-computer.sock"),
15088
15173
  transport: "tcp",
15089
15174
  permitted: (runId) => {
15090
15175
  const assignment = this.journal.get(runId)?.assignment;
@@ -15126,7 +15211,7 @@ var Daemon = class {
15126
15211
  };
15127
15212
  this.cloudComputerBroker = new ComputerBroker({
15128
15213
  driver,
15129
- socketPath: join32(paths.dataDir, "computer.sock"),
15214
+ socketPath: join33(paths.dataDir, "computer.sock"),
15130
15215
  permitted: (runId) => {
15131
15216
  const entry = this.journal.get(runId);
15132
15217
  return Boolean(!this.stopped && this.registered && entry?.assignment.computer && this.supervisor?.computerRunAllowed(runId));
@@ -15249,7 +15334,7 @@ var Daemon = class {
15249
15334
  worktree,
15250
15335
  tree,
15251
15336
  github: { ...assignment.github, runToken: assignment.mcp.token, issueId: assignment.issueId },
15252
- privateDir: join32(paths.adapterState, "pids"),
15337
+ privateDir: join33(paths.adapterState, "pids"),
15253
15338
  ...hosted ? { hosted: true } : {},
15254
15339
  env: githubReceiptEnvironment()
15255
15340
  }) : publishRun({
@@ -15543,7 +15628,7 @@ var Daemon = class {
15543
15628
  }
15544
15629
  async createAgentSandbox() {
15545
15630
  if (this.options.agentSandbox !== void 0) return this.options.agentSandbox;
15546
- const missing = await ensureSandboxTools({ dataDir: this.paths.dataDir, log: this.log });
15631
+ const missing = daemonTestMode(process.env) ? missingSandboxTools() : await ensureSandboxTools({ dataDir: this.paths.dataDir, log: this.log });
15547
15632
  if (!SandboxRuntime.supported()) {
15548
15633
  this.log.warn({ missing }, "agent sandbox unavailable: platform or dependencies unsupported");
15549
15634
  this.sandboxIssue = { missing };
@@ -15587,11 +15672,11 @@ var Daemon = class {
15587
15672
  return runVerify(sandbox, {
15588
15673
  command,
15589
15674
  worktree: realpathSync13(worktree),
15590
- tmpRoot: join32(this.paths.adapterState, "verify", runId),
15675
+ tmpRoot: join33(this.paths.adapterState, "verify", runId),
15591
15676
  privateDir: paths.privateDir,
15592
15677
  pidFile: paths.pidFile.replace(/\.pgid$/, ".verify.pgid"),
15593
15678
  networkAllow: repo.networkAllow,
15594
- env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join32(paths.runDir, "handoff.json") },
15679
+ env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join33(paths.runDir, "handoff.json") },
15595
15680
  timeoutMs,
15596
15681
  signal,
15597
15682
  readOnly
@@ -15636,7 +15721,7 @@ var Daemon = class {
15636
15721
  void this.stop().finally(() => this.options.onLockLost?.(error));
15637
15722
  }
15638
15723
  ensureSecret() {
15639
- if (existsSync8(this.paths.secret)) {
15724
+ if (existsSync9(this.paths.secret)) {
15640
15725
  return readFileSync12(this.paths.secret, "utf8").trim();
15641
15726
  }
15642
15727
  const secret = randomBytes3(32).toString("hex");
@@ -15748,7 +15833,7 @@ var Daemon = class {
15748
15833
  setImmediate(() => {
15749
15834
  void this.stop().then(() => uninstallService(() => {
15750
15835
  this.saveDevice({ credential: void 0 });
15751
- rmSync18(this.paths.secret, { force: true });
15836
+ rmSync19(this.paths.secret, { force: true });
15752
15837
  })).catch(() => {
15753
15838
  this.options.onDrained?.();
15754
15839
  });
@@ -16073,7 +16158,7 @@ var Daemon = class {
16073
16158
  if (!job || controller.signal.aborted) return;
16074
16159
  await runNativeCoordinatorJob(job, {
16075
16160
  deviceId,
16076
- stateDir: join32(this.paths.dataDir, "coordinator"),
16161
+ stateDir: join33(this.paths.dataDir, "coordinator"),
16077
16162
  link,
16078
16163
  signal: controller.signal,
16079
16164
  sandbox,
@@ -16116,7 +16201,7 @@ var Daemon = class {
16116
16201
  }, void 0, () => !this.stopped);
16117
16202
  });
16118
16203
  } else if (!this.updateCheck && !this.updateVersion) {
16119
- this.updateCheck = checkLatestVersion(join32(this.paths.dataDir, "auto-update.json"), DAEMON_VERSION, runtime).then((version) => {
16204
+ this.updateCheck = checkLatestVersion(join33(this.paths.dataDir, "auto-update.json"), DAEMON_VERSION, runtime).then((version) => {
16120
16205
  this.updateVersion = version;
16121
16206
  }).catch(() => {
16122
16207
  this.log.warn("Daemon automatic update check failed");