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