@aspectlylabs/mikka 0.0.96 → 0.0.109

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/main.js CHANGED
@@ -2714,6 +2714,17 @@ function isInside(parent, child) {
2714
2714
  const rel = relative(parent, child);
2715
2715
  return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
2716
2716
  }
2717
+ var configWriters = /* @__PURE__ */ new Map();
2718
+ function withRepoConfig(repoPath, work) {
2719
+ const key2 = resolve(repoPath);
2720
+ const result = (configWriters.get(key2) ?? Promise.resolve()).then(work, work);
2721
+ const settled = result.then(() => void 0, () => void 0);
2722
+ configWriters.set(key2, settled);
2723
+ void settled.then(() => {
2724
+ if (configWriters.get(key2) === settled) configWriters.delete(key2);
2725
+ });
2726
+ return result;
2727
+ }
2717
2728
  var WorktreeManager = class {
2718
2729
  constructor(root, retainResources = false) {
2719
2730
  this.root = root;
@@ -2741,16 +2752,19 @@ var WorktreeManager = class {
2741
2752
  const path = this.pathFor(runId);
2742
2753
  if (existsSync2(join2(path, ".git"))) return path;
2743
2754
  mkdirSync3(this.root, { recursive: true });
2744
- await simpleGit(repoPath).raw([
2745
- "worktree",
2746
- "add",
2747
- "-B",
2748
- runBranch(runId),
2749
- path,
2750
- // The base branch comes from the server: never let it read as an option.
2751
- "--end-of-options",
2752
- baseBranch
2753
- ]);
2755
+ await withRepoConfig(
2756
+ repoPath,
2757
+ () => simpleGit(repoPath).raw([
2758
+ "worktree",
2759
+ "add",
2760
+ "-B",
2761
+ runBranch(runId),
2762
+ path,
2763
+ // The base branch comes from the server: never let it read as an option.
2764
+ "--end-of-options",
2765
+ baseBranch
2766
+ ])
2767
+ );
2754
2768
  return path;
2755
2769
  }
2756
2770
  /**
@@ -2915,8 +2929,10 @@ var WorktreeManager = class {
2915
2929
  branches.push(branch);
2916
2930
  }
2917
2931
  if (path) await this.removePath(path, repoPath);
2918
- for (const branch of branches)
2919
- await git2.raw(["branch", "-D", "--", branch]).catch(() => void 0);
2932
+ await withRepoConfig(repoPath, async () => {
2933
+ for (const branch of branches)
2934
+ await git2.raw(["branch", "-D", "--", branch]).catch(() => void 0);
2935
+ });
2920
2936
  return true;
2921
2937
  }
2922
2938
  /**
@@ -3748,7 +3764,7 @@ import { join as join5 } from "node:path";
3748
3764
  // package.json
3749
3765
  var package_default = {
3750
3766
  name: "@mikka/daemon",
3751
- version: "0.0.96",
3767
+ version: "0.0.109",
3752
3768
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3753
3769
  type: "module",
3754
3770
  private: true,
@@ -3807,7 +3823,7 @@ var package_default = {
3807
3823
  engines: {
3808
3824
  node: ">=24"
3809
3825
  },
3810
- gitHead: "3b9c8125df35c63178333a7a0320a9f9ac5b7e5e"
3826
+ gitHead: "2675c9f904834c207516585c65544830763423d7"
3811
3827
  };
3812
3828
 
3813
3829
  // src/paths.ts
@@ -6393,14 +6409,14 @@ sandbox_mode = "read-only"
6393
6409
  import { randomBytes as randomBytes3, randomUUID as randomUUID9 } from "node:crypto";
6394
6410
  import {
6395
6411
  chmodSync as chmodSync5,
6396
- existsSync as existsSync8,
6412
+ existsSync as existsSync9,
6397
6413
  mkdirSync as mkdirSync17,
6398
6414
  readFileSync as readFileSync12,
6399
- rmSync as rmSync18,
6415
+ rmSync as rmSync19,
6400
6416
  realpathSync as realpathSync13
6401
6417
  } from "node:fs";
6402
6418
  import { arch, hostname, platform as platform2 } from "node:os";
6403
- import { join as join32 } from "node:path";
6419
+ import { join as join33 } from "node:path";
6404
6420
  import { fileURLToPath as fileURLToPath3 } from "node:url";
6405
6421
 
6406
6422
  // src/adapters/claude.ts
@@ -8643,31 +8659,49 @@ var MockAdapter = class {
8643
8659
  };
8644
8660
 
8645
8661
  // src/agents/verify.ts
8646
- import { mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync5, realpathSync as realpathSync9, rmSync as rmSync10 } from "node:fs";
8662
+ import { existsSync as existsSync5, mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync5, realpathSync as realpathSync9, rmSync as rmSync10 } from "node:fs";
8647
8663
  import { join as join16 } from "node:path";
8648
8664
  var OUTPUT_TAIL = 4e3;
8665
+ var SETUP_ATTEMPTS = 3;
8649
8666
  async function runVerify(sandbox, options) {
8650
8667
  mkdirSync11(options.tmpRoot, { recursive: true, mode: 448 });
8651
8668
  const tmpDir = mkdtempSync5(join16(realpathSync9(options.tmpRoot), "verify-"));
8652
- const child = await spawnCli(sandbox, ["/bin/sh", "-c", options.command], {
8653
- cwd: options.worktree,
8654
- env: { ...options.env, TMPDIR: tmpDir },
8655
- policy: {
8656
- allowWrite: options.readOnly ? [tmpDir] : [options.worktree, tmpDir],
8657
- denyWrite: [
8658
- join16(options.worktree, ".git"),
8659
- ...options.readOnly ? [options.worktree] : []
8660
- ],
8661
- denyRead: [
8662
- ...credentialDenyRead(null),
8663
- ...daemonSecrets(options.privateDir)
8664
- ],
8665
- allowDomains: [...options.networkAllow ?? []]
8666
- },
8667
- pidFile: options.pidFile,
8668
- // Every verify of this run carries the temp root in its profile.
8669
- marker: realpathSync9(options.tmpRoot)
8670
- });
8669
+ const deadline = Date.now() + options.timeoutMs;
8670
+ try {
8671
+ for (let attempt = 1; ; attempt++) {
8672
+ const started = join16(tmpDir, `.started-${attempt}`);
8673
+ const result = await attemptVerify(sandbox, options, tmpDir, started, deadline - Date.now());
8674
+ if (result.exitCode === 0 || result.timedOut || options.signal?.aborted || existsSync5(started) || attempt >= SETUP_ATTEMPTS)
8675
+ return result;
8676
+ }
8677
+ } finally {
8678
+ rmSync10(tmpDir, { recursive: true, force: true });
8679
+ }
8680
+ }
8681
+ async function attemptVerify(sandbox, options, tmpDir, started, timeoutMs) {
8682
+ const child = await spawnCli(
8683
+ sandbox,
8684
+ ["/bin/sh", "-c", ': > "$0" && exec /bin/sh -c "$1"', started, options.command],
8685
+ {
8686
+ cwd: options.worktree,
8687
+ env: { ...options.env, TMPDIR: tmpDir },
8688
+ policy: {
8689
+ allowWrite: options.readOnly ? [tmpDir] : [options.worktree, tmpDir],
8690
+ denyWrite: [
8691
+ join16(options.worktree, ".git"),
8692
+ ...options.readOnly ? [options.worktree] : []
8693
+ ],
8694
+ denyRead: [
8695
+ ...credentialDenyRead(null),
8696
+ ...daemonSecrets(options.privateDir)
8697
+ ],
8698
+ allowDomains: [...options.networkAllow ?? []]
8699
+ },
8700
+ pidFile: options.pidFile,
8701
+ // Every verify of this run carries the temp root in its profile.
8702
+ marker: realpathSync9(options.tmpRoot)
8703
+ }
8704
+ );
8671
8705
  child.process.stdin.end();
8672
8706
  let output = "";
8673
8707
  for (const stream of [child.process.stdout, child.process.stderr]) {
@@ -8680,7 +8714,7 @@ async function runVerify(sandbox, options) {
8680
8714
  const timer = setTimeout(() => {
8681
8715
  timedOut = true;
8682
8716
  void child.kill();
8683
- }, options.timeoutMs);
8717
+ }, Math.max(0, timeoutMs));
8684
8718
  const abort = () => void child.kill();
8685
8719
  options.signal?.addEventListener("abort", abort, { once: true });
8686
8720
  try {
@@ -8696,7 +8730,6 @@ async function runVerify(sandbox, options) {
8696
8730
  ].join("\n")
8697
8731
  };
8698
8732
  } finally {
8699
- rmSync10(tmpDir, { recursive: true, force: true });
8700
8733
  clearTimeout(timer);
8701
8734
  options.signal?.removeEventListener("abort", abort);
8702
8735
  }
@@ -9328,7 +9361,7 @@ async function detectHarnesses() {
9328
9361
  }
9329
9362
 
9330
9363
  // src/sandbox-tools.ts
9331
- import { chmodSync as chmodSync2, existsSync as existsSync5, lstatSync as lstatSync8, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync6, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync11, writeFileSync as writeFileSync7 } from "node:fs";
9364
+ import { chmodSync as chmodSync2, existsSync as existsSync6, lstatSync as lstatSync8, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync6, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync11, writeFileSync as writeFileSync7 } from "node:fs";
9332
9365
  import { join as join22 } from "node:path";
9333
9366
  import { execa as execa10 } from "execa";
9334
9367
  var TOOLS = [
@@ -9412,11 +9445,11 @@ LD_LIBRARY_PATH=${shellQuote2(libDir)} exec ${shellQuote2(join22(realDir, tool2.
9412
9445
  renameSync2(launcher, join22(binDir, tool2.command));
9413
9446
  }
9414
9447
  function moveSharedLibraries(directory, libDir) {
9415
- if (!existsSync5(directory)) return;
9448
+ if (!existsSync6(directory)) return;
9416
9449
  for (const entry of readdirSync5(directory)) {
9417
9450
  const path = join22(directory, entry);
9418
9451
  if (lstatSync8(path).isDirectory()) moveSharedLibraries(path, libDir);
9419
- else if (entry.includes(".so") && !existsSync5(join22(libDir, entry))) renameSync2(path, join22(libDir, entry));
9452
+ else if (entry.includes(".so") && !existsSync6(join22(libDir, entry))) renameSync2(path, join22(libDir, entry));
9420
9453
  }
9421
9454
  }
9422
9455
  function shellQuote2(value) {
@@ -10877,6 +10910,47 @@ async function fixedCheckSnapshot(repoPath, worktree, sha) {
10877
10910
  return { sha, tree: await git2("rev-parse", `${sha}^{tree}`) };
10878
10911
  }
10879
10912
 
10913
+ // src/run-scratch.ts
10914
+ import { rmSync as rmSync15 } from "node:fs";
10915
+ import { join as join27 } from "node:path";
10916
+
10917
+ // src/credential-globs.ts
10918
+ var CLOUD_WORKER_STATE_DIR = "/home/mikka-runner/.mikka/worker/adapters";
10919
+ var RUN_CREDENTIAL_PATHS = [
10920
+ // GitHub token config and gh wrapper (agents/github-runtime.ts).
10921
+ "github",
10922
+ // Coding-CLI homes inside a run: only placeholders today, but a real login must never be kept.
10923
+ "runtime-home/.claude/.credentials.json",
10924
+ "runtime-home/.codex/auth.json",
10925
+ // Per-run harness homes on a device runner (agents/harness-home.ts).
10926
+ "codex-home/auth.json",
10927
+ "native-home/.claude/.credentials.json",
10928
+ "native-home/.codex/auth.json"
10929
+ ];
10930
+ function runCredentialGlobs(stateDir) {
10931
+ return [
10932
+ ...RUN_CREDENTIAL_PATHS.map((path) => `${stateDir}/runs/*/${path}`),
10933
+ // Live native subscription brokers (subscription-native-broker.ts).
10934
+ `${stateDir}/native-brokers/*`
10935
+ ];
10936
+ }
10937
+ var SNAPSHOT_CREDENTIAL_GLOBS = [
10938
+ "/root/.claude/.credentials.json",
10939
+ "/root/.codex/auth.json",
10940
+ "/home/*/.claude/.credentials.json",
10941
+ "/home/*/.codex/auth.json",
10942
+ "/home/*/.config/gh/hosts.yml",
10943
+ "/home/*/.git-credentials",
10944
+ "/root/.git-credentials",
10945
+ ...runCredentialGlobs(CLOUD_WORKER_STATE_DIR)
10946
+ ];
10947
+
10948
+ // src/run-scratch.ts
10949
+ function removeRunCredentials(stateDir, runId) {
10950
+ const { runDir } = runPaths(stateDir, runId);
10951
+ for (const path of RUN_CREDENTIAL_PATHS) rmSync15(join27(runDir, path), { recursive: true, force: true });
10952
+ }
10953
+
10880
10954
  // src/secret-mask.ts
10881
10955
  import { gunzipSync, gzipSync } from "node:zlib";
10882
10956
  var MASK_MIN_LENGTH = 8;
@@ -11008,13 +11082,13 @@ function createRunMasker(secrets) {
11008
11082
 
11009
11083
  // src/runs/supervisor.ts
11010
11084
  import { createHash as createHash4, randomUUID as randomUUID5 } from "node:crypto";
11011
- import { join as join28, resolve as resolve10 } from "node:path";
11085
+ import { join as join29, resolve as resolve10 } from "node:path";
11012
11086
  import { execa as execa13 } from "execa";
11013
11087
 
11014
11088
  // src/agents/checkpoint.ts
11015
- import { mkdtempSync as mkdtempSync7, rmSync as rmSync15, writeFileSync as writeFileSync8 } from "node:fs";
11089
+ import { mkdtempSync as mkdtempSync7, rmSync as rmSync16, writeFileSync as writeFileSync8 } from "node:fs";
11016
11090
  import { tmpdir as tmpdir2 } from "node:os";
11017
- import { join as join27 } from "node:path";
11091
+ import { join as join28 } from "node:path";
11018
11092
  import { gunzipSync as gunzipSync2, gzipSync as gzipSync2 } from "node:zlib";
11019
11093
  import { execa as execa12 } from "execa";
11020
11094
  var CheckpointRecoveryError = class extends Error {
@@ -11061,8 +11135,8 @@ async function takeCheckpoint(options) {
11061
11135
  }
11062
11136
  async function applyCheckpoint(options) {
11063
11137
  const git2 = await pinnedGit(options.repoPath, options.worktree);
11064
- const dir = mkdtempSync7(join27(tmpdir2(), "mikka-checkpoint-"));
11065
- const file = join27(dir, "checkpoint.patch");
11138
+ const dir = mkdtempSync7(join28(tmpdir2(), "mikka-checkpoint-"));
11139
+ const file = join28(dir, "checkpoint.patch");
11066
11140
  try {
11067
11141
  const patch = gunzipSync2(Buffer.from(options.checkpoint.patch, "base64"));
11068
11142
  if (!patch.length && options.checkpoint.files === 0) return true;
@@ -11079,7 +11153,7 @@ async function applyCheckpoint(options) {
11079
11153
  }
11080
11154
  return false;
11081
11155
  } finally {
11082
- rmSync15(dir, { recursive: true, force: true });
11156
+ rmSync16(dir, { recursive: true, force: true });
11083
11157
  }
11084
11158
  }
11085
11159
  async function hasCommit(repoPath, commit) {
@@ -11887,6 +11961,13 @@ var RunSupervisor = class {
11887
11961
  const run2 = this.active.get(runId);
11888
11962
  if (run2) void this.closeMailbox(run2).catch(() => this.deps.log.warn("Run mailbox shutdown failed"));
11889
11963
  this.leases.delete(runId);
11964
+ if (this.deps.adapterStateDir) {
11965
+ try {
11966
+ removeRunCredentials(this.deps.adapterStateDir, runId);
11967
+ } catch (err) {
11968
+ this.deps.log.warn({ run_id: runId, err }, "run credential cleanup failed");
11969
+ }
11970
+ }
11890
11971
  this.deps.outbox.compact(runId).catch((err) => {
11891
11972
  this.deps.log.error({ run_id: runId, err }, "outbox compaction failed");
11892
11973
  });
@@ -12300,7 +12381,7 @@ var RunSupervisor = class {
12300
12381
  if (!this.deps.adapterStateDir || assignment.harness === "mock" || !session.sessionId || resuming && session.sessionId !== entry.sessionId || assignment.requireSessionResume && session.sessionId !== assignment.resumeSessionId)
12301
12382
  throw new Error("Skill mount requires the actual original harness session");
12302
12383
  verifySkillAssignment(assignment);
12303
- const file = join28(
12384
+ const file = join29(
12304
12385
  runPaths(this.deps.adapterStateDir, runId).runDir,
12305
12386
  SKILLS_DIR,
12306
12387
  skillSlug(assignment.skills[0].name),
@@ -12576,8 +12657,8 @@ var SessionRejectedError = class extends DaemonError {
12576
12657
 
12577
12658
  // src/repositories.ts
12578
12659
  import { createHash as createHash5, randomUUID as randomUUID6 } from "node:crypto";
12579
- 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";
12580
- import { dirname as dirname11, join as join29, resolve as resolve11 } from "node:path";
12660
+ 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";
12661
+ import { dirname as dirname11, join as join30, resolve as resolve11 } from "node:path";
12581
12662
  import { setTimeout as delay2 } from "node:timers/promises";
12582
12663
  import { execa as execa14 } from "execa";
12583
12664
  import lockfile2 from "proper-lockfile";
@@ -12604,33 +12685,36 @@ var RepositoryCache = class {
12604
12685
  this.ensureParents(dirname11(path));
12605
12686
  const release = await this.lock(path, signal);
12606
12687
  try {
12607
- signal?.throwIfAborted();
12608
- const git2 = (args, cwd) => execa14("git", [
12609
- ...FETCH_GIT,
12610
- "-c",
12611
- `protocol.file.allow=${this.allowFile ? "always" : "never"}`,
12612
- ...args
12613
- ], { cwd, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }, stdin: "ignore", timeout: FETCH_TIMEOUT_MS, cancelSignal: signal, killDescendants: true });
12614
- if (!existsSync6(path)) {
12615
- const temporary = `${path}.clone-${randomUUID6()}`;
12616
- try {
12617
- await git2(["clone", "--no-checkout", "--no-hardlinks", "--no-recurse-submodules", "--", remote, temporary]);
12618
- renameSync3(temporary, path);
12619
- } finally {
12620
- if (!this.retainResources) rmSync16(temporary, { recursive: true, force: true });
12621
- }
12622
- } else {
12623
- this.assertClone(path);
12624
- await git2(["remote", "set-url", "origin", remote], path);
12625
- await git2(["fetch", ...this.retainResources ? [] : ["--prune"], "--no-tags", "--no-recurse-submodules", "--no-write-fetch-head", "origin"], path);
12626
- }
12627
- this.assertClone(path);
12628
- await git2(["remote", "set-head", "origin", "-a"], path);
12629
- return path;
12688
+ return await withRepoConfig(path, () => this.update(path, remote, signal));
12630
12689
  } finally {
12631
12690
  await release();
12632
12691
  }
12633
12692
  }
12693
+ async update(path, remote, signal) {
12694
+ signal?.throwIfAborted();
12695
+ const git2 = (args, cwd) => execa14("git", [
12696
+ ...FETCH_GIT,
12697
+ "-c",
12698
+ `protocol.file.allow=${this.allowFile ? "always" : "never"}`,
12699
+ ...args
12700
+ ], { cwd, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }, stdin: "ignore", timeout: FETCH_TIMEOUT_MS, cancelSignal: signal, killDescendants: true });
12701
+ if (!existsSync7(path)) {
12702
+ const temporary = `${path}.clone-${randomUUID6()}`;
12703
+ try {
12704
+ await git2(["clone", "--no-checkout", "--no-hardlinks", "--no-recurse-submodules", "--", remote, temporary]);
12705
+ renameSync3(temporary, path);
12706
+ } finally {
12707
+ if (!this.retainResources) rmSync17(temporary, { recursive: true, force: true });
12708
+ }
12709
+ } else {
12710
+ this.assertClone(path);
12711
+ await git2(["remote", "set-url", "origin", remote], path);
12712
+ await git2(["fetch", ...this.retainResources ? [] : ["--prune"], "--no-tags", "--no-recurse-submodules", "--no-write-fetch-head", "origin"], path);
12713
+ }
12714
+ this.assertClone(path);
12715
+ await git2(["remote", "set-head", "origin", "-a"], path);
12716
+ return path;
12717
+ }
12634
12718
  async baseRef(remoteUrl, baseBranch) {
12635
12719
  const path = this.pathFor(remoteUrl);
12636
12720
  if (baseBranch && baseBranch !== "HEAD") {
@@ -12644,12 +12728,12 @@ var RepositoryCache = class {
12644
12728
  /** Cache paths for retention/orphan cleanup; never consult user checkouts. */
12645
12729
  paths() {
12646
12730
  const visit = (path) => {
12647
- if (!existsSync6(path) || lstatSync9(path).isSymbolicLink()) return [];
12648
- if (existsSync6(join29(path, ".git"))) {
12731
+ if (!existsSync7(path) || lstatSync9(path).isSymbolicLink()) return [];
12732
+ if (existsSync7(join30(path, ".git"))) {
12649
12733
  this.assertClone(path);
12650
12734
  return [path];
12651
12735
  }
12652
- return readdirSync7(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join29(path, entry.name)) : []);
12736
+ return readdirSync7(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join30(path, entry.name)) : []);
12653
12737
  };
12654
12738
  return visit(resolve11(this.root));
12655
12739
  }
@@ -12659,14 +12743,14 @@ var RepositoryCache = class {
12659
12743
  const root = realpathSync11(this.root);
12660
12744
  let current = resolve11(this.root);
12661
12745
  for (const part of path.slice(current.length + 1).split("/").filter(Boolean)) {
12662
- current = join29(current, part);
12663
- if (existsSync6(current) && lstatSync9(current).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
12746
+ current = join30(current, part);
12747
+ if (existsSync7(current) && lstatSync9(current).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
12664
12748
  mkdirSync15(current, { recursive: true, mode: 448 });
12665
12749
  if (!isInside(root, realpathSync11(current))) throw new Error("Repository cache escapes its directory");
12666
12750
  }
12667
12751
  }
12668
12752
  assertClone(path) {
12669
- if (lstatSync9(path).isSymbolicLink() || !lstatSync9(join29(path, ".git")).isDirectory() || lstatSync9(join29(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
12753
+ if (lstatSync9(path).isSymbolicLink() || !lstatSync9(join30(path, ".git")).isDirectory() || lstatSync9(join30(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
12670
12754
  if (!isInside(realpathSync11(this.root), realpathSync11(path))) throw new Error("Repository cache escapes its directory");
12671
12755
  }
12672
12756
  async lock(path, signal) {
@@ -12687,16 +12771,16 @@ var RepositoryCache = class {
12687
12771
  import { execFile as execFile5, spawn as spawn4 } from "node:child_process";
12688
12772
  import { randomUUID as randomUUID7 } from "node:crypto";
12689
12773
  import {
12690
- existsSync as existsSync7,
12774
+ existsSync as existsSync8,
12691
12775
  lstatSync as lstatSync10,
12692
12776
  mkdirSync as mkdirSync16,
12693
12777
  mkdtempSync as mkdtempSync8,
12694
12778
  readdirSync as readdirSync8,
12695
12779
  realpathSync as realpathSync12,
12696
- rmSync as rmSync17
12780
+ rmSync as rmSync18
12697
12781
  } from "node:fs";
12698
12782
  import { createRequire } from "node:module";
12699
- import { delimiter as delimiter4, dirname as dirname12, join as join31 } from "node:path";
12783
+ import { delimiter as delimiter4, dirname as dirname12, join as join32 } from "node:path";
12700
12784
  import { fileURLToPath as fileURLToPath2 } from "node:url";
12701
12785
  import { promisify as promisify5 } from "node:util";
12702
12786
 
@@ -12706,7 +12790,7 @@ import { chmod, mkdtemp, rm as rm2 } from "node:fs/promises";
12706
12790
  import { createServer as createServer3, request as httpRequest } from "node:http";
12707
12791
  import { connect, isIP as isIP3 } from "node:net";
12708
12792
  import { tmpdir as tmpdir3 } from "node:os";
12709
- import { join as join30 } from "node:path";
12793
+ import { join as join31 } from "node:path";
12710
12794
 
12711
12795
  // ../../lib/search/url-policy.ts
12712
12796
  import { BlockList, isIP as isIP2 } from "node:net";
@@ -12775,9 +12859,9 @@ function endToEndHeaders(input) {
12775
12859
  }
12776
12860
  async function startPublicEgress(options) {
12777
12861
  options.signal.throwIfAborted();
12778
- const directory = await mkdtemp(join30(tmpdir3(), "mikka-egress-"));
12862
+ const directory = await mkdtemp(join31(tmpdir3(), "mikka-egress-"));
12779
12863
  await chmod(directory, 448);
12780
- const socketPath = join30(directory, "egress.sock");
12864
+ const socketPath = join31(directory, "egress.sock");
12781
12865
  const lifetime = new AbortController();
12782
12866
  const signal = AbortSignal.any([options.signal, lifetime.signal]);
12783
12867
  const sockets = /* @__PURE__ */ new Set();
@@ -12934,7 +13018,7 @@ async function createHostedBotRunner(host) {
12934
13018
  }).catch(() => {
12935
13019
  throw unavailable2();
12936
13020
  });
12937
- const resources = join31(host.stateDir, "native-resources");
13021
+ const resources = join32(host.stateDir, "native-resources");
12938
13022
  mkdirSync16(resources, { recursive: true, mode: 448 });
12939
13023
  const removeResource = async (file, record) => {
12940
13024
  if (!/^mikka-native-(?:verify-)?[a-f0-9-]{36}$/.test(record.name) || !/^[a-f0-9-]{36}$/.test(record.nonce))
@@ -12955,9 +13039,9 @@ async function createHostedBotRunner(host) {
12955
13039
  if (record.state === "created" && /No such (?:container|object)/i.test(
12956
13040
  String(error.stderr)
12957
13041
  )) {
12958
- if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
12959
- rmSync17(record.assets, { recursive: true, force: true });
12960
- rmSync17(file, { force: true });
13042
+ if (record.assets?.startsWith(join32(host.stateDir, "native-verify-git-")))
13043
+ rmSync18(record.assets, { recursive: true, force: true });
13044
+ rmSync18(file, { force: true });
12961
13045
  return;
12962
13046
  }
12963
13047
  throw new Error("native_runtime_cleanup_unconfirmed");
@@ -12966,13 +13050,13 @@ async function createHostedBotRunner(host) {
12966
13050
  if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id4)
12967
13051
  throw unavailable2();
12968
13052
  await exec3("docker", ["rm", "-f", id4], { env: bareEnv, timeout: 3e4 });
12969
- if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
12970
- rmSync17(record.assets, { recursive: true, force: true });
12971
- rmSync17(file, { force: true });
13053
+ if (record.assets?.startsWith(join32(host.stateDir, "native-verify-git-")))
13054
+ rmSync18(record.assets, { recursive: true, force: true });
13055
+ rmSync18(file, { force: true });
12972
13056
  };
12973
13057
  for (const name of readdirSync8(resources))
12974
13058
  if (name.endsWith(".json")) {
12975
- const file = join31(resources, name);
13059
+ const file = join32(resources, name);
12976
13060
  const record = readJson(file);
12977
13061
  if (!record) throw unavailable2();
12978
13062
  await removeResource(file, record);
@@ -12983,7 +13067,7 @@ async function createHostedBotRunner(host) {
12983
13067
  const bundled = createRequire(
12984
13068
  require2.resolve("@anthropic-ai/claude-agent-sdk")
12985
13069
  );
12986
- claude ??= join31(
13070
+ claude ??= join32(
12987
13071
  dirname12(
12988
13072
  bundled.resolve(
12989
13073
  "@anthropic-ai/claude-agent-sdk-linux-x64/package.json"
@@ -12993,7 +13077,7 @@ async function createHostedBotRunner(host) {
12993
13077
  );
12994
13078
  } catch {
12995
13079
  }
12996
- const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter4).map((dir) => join31(dir, "codex")).find((path) => existsSync7(path));
13080
+ const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter4).map((dir) => join32(dir, "codex")).find((path) => existsSync8(path));
12997
13081
  const binaries = { codex, claude_code: claude };
12998
13082
  for (const kind of ["codex", "claude_code"])
12999
13083
  if (binaries[kind]) {
@@ -13007,12 +13091,12 @@ async function createHostedBotRunner(host) {
13007
13091
  if (!binaries.codex && !binaries.claude_code) throw unavailable2();
13008
13092
  const command = async (worktree, script, readOnly, timeoutMs, signal) => {
13009
13093
  const name = `mikka-native-verify-${randomUUID7()}`;
13010
- const file = join31(resources, name + ".json");
13094
+ const file = join32(resources, name + ".json");
13011
13095
  const resource = { name, nonce: randomUUID7(), state: "creating" };
13012
13096
  const timing = { createMs: 0, runMs: 0 };
13013
13097
  let phase = "create";
13014
13098
  let began = performance.now();
13015
- const gitCopy = mkdtempSync8(join31(host.stateDir, "native-verify-git-"));
13099
+ const gitCopy = mkdtempSync8(join32(host.stateDir, "native-verify-git-"));
13016
13100
  resource.assets = gitCopy;
13017
13101
  try {
13018
13102
  const cwd = realpathSync12(worktree);
@@ -13028,7 +13112,7 @@ async function createHostedBotRunner(host) {
13028
13112
  "--no-checkout",
13029
13113
  "--",
13030
13114
  cwd,
13031
- join31(gitCopy, "repo")
13115
+ join32(gitCopy, "repo")
13032
13116
  ],
13033
13117
  {
13034
13118
  env: {
@@ -13043,8 +13127,8 @@ async function createHostedBotRunner(host) {
13043
13127
  maxBuffer: 1024 * 1024
13044
13128
  }
13045
13129
  );
13046
- const safeGit = join31(gitCopy, "repo", ".git");
13047
- const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : safeGit;
13130
+ const safeGit = join32(gitCopy, "repo", ".git");
13131
+ const protectedGit = lstatSync10(join32(cwd, ".git")).isFile() ? join32(cwd, ".git") : safeGit;
13048
13132
  writeJsonAtomic(file, resource);
13049
13133
  const created = await exec3(
13050
13134
  "docker",
@@ -13131,8 +13215,8 @@ async function createHostedBotRunner(host) {
13131
13215
  timing
13132
13216
  };
13133
13217
  } finally {
13134
- if (existsSync7(file)) await removeResource(file, resource);
13135
- else rmSync17(gitCopy, { recursive: true, force: true });
13218
+ if (existsSync8(file)) await removeResource(file, resource);
13219
+ else rmSync18(gitCopy, { recursive: true, force: true });
13136
13220
  }
13137
13221
  };
13138
13222
  return {
@@ -13148,7 +13232,7 @@ async function createHostedBotRunner(host) {
13148
13232
  throw unavailable2();
13149
13233
  const name = `mikka-native-${randomUUID7()}`;
13150
13234
  const nonce = randomUUID7();
13151
- const resourceFile = join31(resources, name + ".json");
13235
+ const resourceFile = join32(resources, name + ".json");
13152
13236
  const resource = { name, nonce, state: "creating" };
13153
13237
  const lifetime = new AbortController();
13154
13238
  let closed = false;
@@ -13187,12 +13271,13 @@ async function createHostedBotRunner(host) {
13187
13271
  void brokerClosed.catch(() => void 0);
13188
13272
  try {
13189
13273
  await creating?.catch(() => void 0);
13190
- if (existsSync7(resourceFile)) await removeResource(resourceFile, resource);
13274
+ if (existsSync8(resourceFile)) await removeResource(resourceFile, resource);
13191
13275
  } finally {
13192
13276
  try {
13193
13277
  await brokerClosed;
13194
13278
  } finally {
13195
13279
  offRevoke();
13280
+ removeRunCredentials(host.stateDir, assignment.runId);
13196
13281
  }
13197
13282
  }
13198
13283
  });
@@ -13221,10 +13306,10 @@ async function createHostedBotRunner(host) {
13221
13306
  };
13222
13307
  const paths = runPaths(host.stateDir, assignment.runId);
13223
13308
  mkdirSync16(paths.runDir, { recursive: true, mode: 448 });
13224
- const shadow = join31(paths.runDir, "runtime-git");
13225
- const emptyHome = join31(paths.runDir, "git-bootstrap-home");
13309
+ const shadow = join32(paths.runDir, "runtime-git");
13310
+ const emptyHome = join32(paths.runDir, "git-bootstrap-home");
13226
13311
  mkdirSync16(emptyHome, { recursive: true, mode: 448 });
13227
- if (!existsSync7(shadow))
13312
+ if (!existsSync8(shadow))
13228
13313
  await exec3(
13229
13314
  "git",
13230
13315
  [
@@ -13253,9 +13338,9 @@ async function createHostedBotRunner(host) {
13253
13338
  }
13254
13339
  );
13255
13340
  await live();
13256
- if (!lstatSync10(shadow).isDirectory() || !lstatSync10(join31(shadow, ".git")).isDirectory() || !realpathSync12(shadow).startsWith(realpathSync12(paths.runDir) + "/"))
13341
+ if (!lstatSync10(shadow).isDirectory() || !lstatSync10(join32(shadow, ".git")).isDirectory() || !realpathSync12(shadow).startsWith(realpathSync12(paths.runDir) + "/"))
13257
13342
  throw unavailable2();
13258
- const ledger = join31(
13343
+ const ledger = join32(
13259
13344
  host.stateDir,
13260
13345
  "native-ledgers",
13261
13346
  assignment.runId + ".json"
@@ -13272,7 +13357,7 @@ async function createHostedBotRunner(host) {
13272
13357
  modelId: first.modelId
13273
13358
  };
13274
13359
  const previous = readJson(ledger);
13275
- if (existsSync7(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
13360
+ if (existsSync8(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
13276
13361
  throw unavailable2();
13277
13362
  mkdirSync16(dirname12(ledger), { recursive: true, mode: 448 });
13278
13363
  const record = async (sessionId) => {
@@ -13280,7 +13365,7 @@ async function createHostedBotRunner(host) {
13280
13365
  writeJsonAtomic(ledger, { scope, sessionId });
13281
13366
  };
13282
13367
  brokerStarting = createNativeSubscriptionBroker({
13283
- root: join31(host.stateDir, "native-brokers"),
13368
+ root: join32(host.stateDir, "native-brokers"),
13284
13369
  revision,
13285
13370
  check,
13286
13371
  worker: {
@@ -13307,7 +13392,7 @@ async function createHostedBotRunner(host) {
13307
13392
  });
13308
13393
  const readyBroker = await brokerStarting;
13309
13394
  await live();
13310
- const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter4).map((dir) => join31(dir, "gh")).find((file) => existsSync7(file)) : void 0;
13395
+ const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter4).map((dir) => join32(dir, "gh")).find((file) => existsSync8(file)) : void 0;
13311
13396
  if (options.github && !githubCli) throw new Error("Install GitHub CLI (gh) in the cloud worker image");
13312
13397
  const githubDomains = options.github ? ["github.com", "api.github.com", new URL(options.github.endpoint).host] : [];
13313
13398
  const egressMaximum = runDomains(runPolicy(options.policy), [...options.networkAllow ?? [], ...githubDomains]);
@@ -13324,7 +13409,7 @@ async function createHostedBotRunner(host) {
13324
13409
  }
13325
13410
  const cwd = realpathSync12(options.cwd);
13326
13411
  const runDir = realpathSync12(paths.runDir);
13327
- const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : join31(shadow, ".git");
13412
+ const protectedGit = lstatSync10(join32(cwd, ".git")).isFile() ? join32(cwd, ".git") : join32(shadow, ".git");
13328
13413
  if (!lstatSync10(runDir).isDirectory() || !runDir.startsWith(realpathSync12(host.stateDir) + "/runs/")) {
13329
13414
  await close();
13330
13415
  throw unavailable2();
@@ -13378,7 +13463,7 @@ async function createHostedBotRunner(host) {
13378
13463
  `${MCP_SERVER_SCRIPT}:${MCP_SERVER_SCRIPT}:ro`,
13379
13464
  ...githubCli ? ["-v", `${githubCli}:/usr/local/bin/mikka-gh:ro`, "-v", `${GITHUB_CREDENTIAL_SCRIPT}:${GITHUB_CREDENTIAL_SCRIPT}:ro`] : [],
13380
13465
  "-v",
13381
- `${join31(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join31(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
13466
+ `${join32(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join32(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
13382
13467
  "-v",
13383
13468
  `${readyBroker.socket}:/run/mikka-native.sock:ro`,
13384
13469
  ...computerGrant ? [
@@ -13421,13 +13506,13 @@ async function createHostedBotRunner(host) {
13421
13506
  }
13422
13507
  const spawnHosted = (config) => {
13423
13508
  assertOpen();
13424
- const home = join31(runDir, "runtime-home");
13509
+ const home = join32(runDir, "runtime-home");
13425
13510
  mkdirSync16(home, { recursive: true, mode: 448 });
13426
13511
  const env = {
13427
13512
  ...config.env,
13428
13513
  HOME: kind === "claude_code" ? config.env.HOME ?? home : home,
13429
- PATH: `${options.github ? join31(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
13430
- GIT_DIR: join31(shadow, ".git"),
13514
+ PATH: `${options.github ? join32(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
13515
+ GIT_DIR: join32(shadow, ".git"),
13431
13516
  GIT_WORK_TREE: cwd,
13432
13517
  GIT_CONFIG_GLOBAL: "/dev/null",
13433
13518
  GIT_CONFIG_SYSTEM: "/dev/null",
@@ -13446,7 +13531,7 @@ async function createHostedBotRunner(host) {
13446
13531
  signal: AbortSignal.any([lifetime.signal, ...config.signal ? [config.signal] : []])
13447
13532
  });
13448
13533
  child.stdin.write(
13449
- JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join31(runDir, "github", "bin") } : {} }) + "\n"
13534
+ JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join32(runDir, "github", "bin") } : {} }) + "\n"
13450
13535
  );
13451
13536
  return child;
13452
13537
  };
@@ -14145,7 +14230,7 @@ var Daemon = class {
14145
14230
  if (this.options.credential)
14146
14231
  this.saveDevice({ credential: this.options.credential });
14147
14232
  this.journal = new RunJournal(paths.journal);
14148
- this.captureUploader = new CaptureUploader((runId) => join32(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join32(paths.dataDir, "capture-pending"));
14233
+ this.captureUploader = new CaptureUploader((runId) => join33(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join33(paths.dataDir, "capture-pending"));
14149
14234
  this.outbox = new Outbox(
14150
14235
  paths.outbox,
14151
14236
  this.options.link,
@@ -14162,7 +14247,7 @@ var Daemon = class {
14162
14247
  if (this.localComputerDriver && this.options.link.syncComputerReviews && this.options.link.localComputerAuthority) {
14163
14248
  this.localComputerBroker = new ComputerBroker({
14164
14249
  driver: this.localComputerDriver,
14165
- socketPath: join32(paths.dataDir, "local-computer.sock"),
14250
+ socketPath: join33(paths.dataDir, "local-computer.sock"),
14166
14251
  transport: "tcp",
14167
14252
  permitted: (runId) => {
14168
14253
  const assignment = this.journal.get(runId)?.assignment;
@@ -14204,7 +14289,7 @@ var Daemon = class {
14204
14289
  };
14205
14290
  this.cloudComputerBroker = new ComputerBroker({
14206
14291
  driver,
14207
- socketPath: join32(paths.dataDir, "computer.sock"),
14292
+ socketPath: join33(paths.dataDir, "computer.sock"),
14208
14293
  permitted: (runId) => {
14209
14294
  const entry = this.journal.get(runId);
14210
14295
  return Boolean(!this.stopped && this.registered && entry?.assignment.computer && this.supervisor?.computerRunAllowed(runId));
@@ -14327,7 +14412,7 @@ var Daemon = class {
14327
14412
  worktree,
14328
14413
  tree,
14329
14414
  github: { ...assignment.github, runToken: assignment.mcp.token, issueId: assignment.issueId },
14330
- privateDir: join32(paths.adapterState, "pids"),
14415
+ privateDir: join33(paths.adapterState, "pids"),
14331
14416
  ...hosted ? { hosted: true } : {},
14332
14417
  env: githubReceiptEnvironment()
14333
14418
  }) : publishRun({
@@ -14621,7 +14706,7 @@ var Daemon = class {
14621
14706
  }
14622
14707
  async createAgentSandbox() {
14623
14708
  if (this.options.agentSandbox !== void 0) return this.options.agentSandbox;
14624
- const missing = await ensureSandboxTools({ dataDir: this.paths.dataDir, log: this.log });
14709
+ const missing = daemonTestMode(process.env) ? missingSandboxTools() : await ensureSandboxTools({ dataDir: this.paths.dataDir, log: this.log });
14625
14710
  if (!SandboxRuntime.supported()) {
14626
14711
  this.log.warn({ missing }, "agent sandbox unavailable: platform or dependencies unsupported");
14627
14712
  this.sandboxIssue = { missing };
@@ -14665,11 +14750,11 @@ var Daemon = class {
14665
14750
  return runVerify(sandbox, {
14666
14751
  command,
14667
14752
  worktree: realpathSync13(worktree),
14668
- tmpRoot: join32(this.paths.adapterState, "verify", runId),
14753
+ tmpRoot: join33(this.paths.adapterState, "verify", runId),
14669
14754
  privateDir: paths.privateDir,
14670
14755
  pidFile: paths.pidFile.replace(/\.pgid$/, ".verify.pgid"),
14671
14756
  networkAllow: repo.networkAllow,
14672
- env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join32(paths.runDir, "handoff.json") },
14757
+ env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join33(paths.runDir, "handoff.json") },
14673
14758
  timeoutMs,
14674
14759
  signal,
14675
14760
  readOnly
@@ -14714,7 +14799,7 @@ var Daemon = class {
14714
14799
  void this.stop().finally(() => this.options.onLockLost?.(error));
14715
14800
  }
14716
14801
  ensureSecret() {
14717
- if (existsSync8(this.paths.secret)) {
14802
+ if (existsSync9(this.paths.secret)) {
14718
14803
  return readFileSync12(this.paths.secret, "utf8").trim();
14719
14804
  }
14720
14805
  const secret = randomBytes3(32).toString("hex");
@@ -14826,7 +14911,7 @@ var Daemon = class {
14826
14911
  setImmediate(() => {
14827
14912
  void this.stop().then(() => uninstallService(() => {
14828
14913
  this.saveDevice({ credential: void 0 });
14829
- rmSync18(this.paths.secret, { force: true });
14914
+ rmSync19(this.paths.secret, { force: true });
14830
14915
  })).catch(() => {
14831
14916
  this.options.onDrained?.();
14832
14917
  });
@@ -15151,7 +15236,7 @@ var Daemon = class {
15151
15236
  if (!job || controller.signal.aborted) return;
15152
15237
  await runNativeCoordinatorJob(job, {
15153
15238
  deviceId,
15154
- stateDir: join32(this.paths.dataDir, "coordinator"),
15239
+ stateDir: join33(this.paths.dataDir, "coordinator"),
15155
15240
  link,
15156
15241
  signal: controller.signal,
15157
15242
  sandbox,
@@ -15194,7 +15279,7 @@ var Daemon = class {
15194
15279
  }, void 0, () => !this.stopped);
15195
15280
  });
15196
15281
  } else if (!this.updateCheck && !this.updateVersion) {
15197
- this.updateCheck = checkLatestVersion(join32(this.paths.dataDir, "auto-update.json"), DAEMON_VERSION, runtime).then((version) => {
15282
+ this.updateCheck = checkLatestVersion(join33(this.paths.dataDir, "auto-update.json"), DAEMON_VERSION, runtime).then((version) => {
15198
15283
  this.updateVersion = version;
15199
15284
  }).catch(() => {
15200
15285
  this.log.warn("Daemon automatic update check failed");