@aspectlylabs/mikka 0.0.65 → 0.0.66

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
@@ -2212,8 +2212,8 @@ var EventQueue = class {
2212
2212
  if (next.type === "exit") return;
2213
2213
  continue;
2214
2214
  }
2215
- await new Promise((resolve11) => {
2216
- this.waiter = resolve11;
2215
+ await new Promise((resolve12) => {
2216
+ this.waiter = resolve12;
2217
2217
  });
2218
2218
  }
2219
2219
  }
@@ -2284,13 +2284,13 @@ async function spawnCli(sandbox, argv, options) {
2284
2284
  stderr = (stderr + data).slice(-STDERR_TAIL * 4);
2285
2285
  });
2286
2286
  const exited = new Promise(
2287
- (resolve11) => {
2287
+ (resolve12) => {
2288
2288
  child.once("error", (error) => {
2289
2289
  stderr += `
2290
2290
  ${error.message}`;
2291
- resolve11({ code: null, signal: null });
2291
+ resolve12({ code: null, signal: null });
2292
2292
  });
2293
- child.once("exit", (code, signal) => resolve11({ code, signal }));
2293
+ child.once("exit", (code, signal) => resolve12({ code, signal }));
2294
2294
  }
2295
2295
  ).finally(() => {
2296
2296
  signalGroup(pgid, "SIGKILL");
@@ -2307,8 +2307,8 @@ ${error.message}`;
2307
2307
  let timer;
2308
2308
  await Promise.race([
2309
2309
  exited,
2310
- new Promise((resolve11) => {
2311
- timer = setTimeout(resolve11, graceMs);
2310
+ new Promise((resolve12) => {
2311
+ timer = setTimeout(resolve12, graceMs);
2312
2312
  })
2313
2313
  ]);
2314
2314
  clearTimeout(timer);
@@ -2389,11 +2389,11 @@ var JsonlWriter = class extends AbstractMessageWriter {
2389
2389
  }
2390
2390
  stream;
2391
2391
  write(message) {
2392
- return new Promise((resolve11, reject) => {
2392
+ return new Promise((resolve12, reject) => {
2393
2393
  this.stream.write(
2394
2394
  `${JSON.stringify(message)}
2395
2395
  `,
2396
- (error) => error ? reject(error) : resolve11()
2396
+ (error) => error ? reject(error) : resolve12()
2397
2397
  );
2398
2398
  });
2399
2399
  }
@@ -3728,7 +3728,7 @@ import { join as join5 } from "node:path";
3728
3728
  // package.json
3729
3729
  var package_default = {
3730
3730
  name: "@mikka/daemon",
3731
- version: "0.0.65",
3731
+ version: "0.0.66",
3732
3732
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3733
3733
  type: "module",
3734
3734
  private: true,
@@ -3787,7 +3787,7 @@ var package_default = {
3787
3787
  engines: {
3788
3788
  node: ">=24"
3789
3789
  },
3790
- gitHead: "f566198f5cee77ff3a0ba56f6923a0cf0b005b0e"
3790
+ gitHead: "362a5415cfca1dae687f81b235450908b4412153"
3791
3791
  };
3792
3792
 
3793
3793
  // src/paths.ts
@@ -6181,8 +6181,8 @@ async function runCodexCoordinator(input, host) {
6181
6181
  const messages = /* @__PURE__ */ new Map();
6182
6182
  let resolveEnd;
6183
6183
  let rejectEnd;
6184
- const ended = new Promise((resolve11, reject) => {
6185
- resolveEnd = resolve11;
6184
+ const ended = new Promise((resolve12, reject) => {
6185
+ resolveEnd = resolve12;
6186
6186
  rejectEnd = reject;
6187
6187
  });
6188
6188
  void ended.catch(() => void 0);
@@ -6363,10 +6363,10 @@ import {
6363
6363
  mkdirSync as mkdirSync16,
6364
6364
  readFileSync as readFileSync11,
6365
6365
  rmSync as rmSync17,
6366
- realpathSync as realpathSync12
6366
+ realpathSync as realpathSync13
6367
6367
  } from "node:fs";
6368
6368
  import { arch, hostname, platform as platform2 } from "node:os";
6369
- import { join as join27 } from "node:path";
6369
+ import { join as join28 } from "node:path";
6370
6370
  import { fileURLToPath as fileURLToPath3 } from "node:url";
6371
6371
 
6372
6372
  // src/adapters/claude.ts
@@ -6492,8 +6492,8 @@ function spawnRunSandbox(options) {
6492
6492
  let outcome;
6493
6493
  let hardStop;
6494
6494
  let settle;
6495
- const exited = new Promise((resolve11) => {
6496
- settle = resolve11;
6495
+ const exited = new Promise((resolve12) => {
6496
+ settle = resolve12;
6497
6497
  });
6498
6498
  function send(message) {
6499
6499
  if (!child.connected || gone) return;
@@ -6766,9 +6766,9 @@ async function createNativeSubscriptionBroker(host) {
6766
6766
  }
6767
6767
  });
6768
6768
  try {
6769
- await new Promise((resolve11, reject) => {
6769
+ await new Promise((resolve12, reject) => {
6770
6770
  server.once("error", reject);
6771
- server.listen(socket, resolve11);
6771
+ server.listen(socket, resolve12);
6772
6772
  });
6773
6773
  chmodSync(socket, 384);
6774
6774
  } catch {
@@ -6781,7 +6781,7 @@ async function createNativeSubscriptionBroker(host) {
6781
6781
  halted = true;
6782
6782
  for (const abort of pending) abort.abort();
6783
6783
  server.closeAllConnections();
6784
- await new Promise((resolve11) => server.close(() => resolve11()));
6784
+ await new Promise((resolve12) => server.close(() => resolve12()));
6785
6785
  rmSync9(dir, { recursive: true, force: true });
6786
6786
  }
6787
6787
  };
@@ -6945,8 +6945,8 @@ var PromptQueue = class {
6945
6945
  continue;
6946
6946
  }
6947
6947
  if (this.closed) return;
6948
- await new Promise((resolve11) => {
6949
- this.waiter = resolve11;
6948
+ await new Promise((resolve12) => {
6949
+ this.waiter = resolve12;
6950
6950
  });
6951
6951
  }
6952
6952
  }
@@ -6960,8 +6960,8 @@ async function untilSpoken(spoken) {
6960
6960
  try {
6961
6961
  return await Promise.race([
6962
6962
  spoken,
6963
- new Promise((resolve11) => {
6964
- timer = setTimeout(() => resolve11(true), CONTINUE_SILENCE_MS);
6963
+ new Promise((resolve12) => {
6964
+ timer = setTimeout(() => resolve12(true), CONTINUE_SILENCE_MS);
6965
6965
  })
6966
6966
  ]);
6967
6967
  } finally {
@@ -7098,9 +7098,9 @@ var ClaudeAdapter = class {
7098
7098
  let stderr = "";
7099
7099
  const stderrTail = () => stderr.slice(-STDERR_TAIL2).trim() || "no output";
7100
7100
  let spoke = () => void 0;
7101
- const spoken = new Promise((resolve11) => spoke = resolve11);
7101
+ const spoken = new Promise((resolve12) => spoke = resolve12);
7102
7102
  let finished = () => void 0;
7103
- const gone = new Promise((resolve11) => finished = resolve11);
7103
+ const gone = new Promise((resolve12) => finished = resolve12);
7104
7104
  if (externalAuth && this.options.onHostedSession) {
7105
7105
  try {
7106
7106
  await this.options.onHostedSession(sessionId);
@@ -8451,7 +8451,7 @@ var MockAdapter = class {
8451
8451
  if (line.hang) {
8452
8452
  if (!abort.signal.aborted) {
8453
8453
  await new Promise(
8454
- (resolve11) => abort.signal.addEventListener("abort", resolve11, { once: true })
8454
+ (resolve12) => abort.signal.addEventListener("abort", resolve12, { once: true })
8455
8455
  );
8456
8456
  }
8457
8457
  yield { type: "exit", outcome: "cancelled" };
@@ -8815,35 +8815,71 @@ async function verifyExpectedOrigin(path, expected) {
8815
8815
  }
8816
8816
  }
8817
8817
 
8818
- // src/service.ts
8818
+ // src/auto-update.ts
8819
8819
  import { execFile as execFile2 } from "node:child_process";
8820
- import { promisify as promisify2 } from "node:util";
8821
- import { mkdir, writeFile, rm } from "node:fs/promises";
8820
+ import { realpathSync as realpathSync10 } from "node:fs";
8822
8821
  import { homedir as homedir6 } from "node:os";
8823
8822
  import { dirname as dirname9, join as join17, resolve as resolve8 } from "node:path";
8823
+ import { promisify as promisify2 } from "node:util";
8824
8824
  var exec = promisify2(execFile2);
8825
+ var DAY = 24 * 60 * 60 * 1e3;
8826
+ function newerStableVersion(candidate, current) {
8827
+ const stable = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
8828
+ if (typeof candidate !== "string" || !stable.test(candidate) || !stable.test(current)) return false;
8829
+ const a = candidate.split(".").map(BigInt), b = current.split(".").map(BigInt);
8830
+ for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] > b[i];
8831
+ return false;
8832
+ }
8833
+ async function runServiceNpm(args) {
8834
+ const npm = realpathSync10(join17(dirname9(process.execPath), "npm"));
8835
+ const { stdout } = await exec(process.execPath, [npm, ...args], {
8836
+ cwd: homedir6(),
8837
+ timeout: 3e5,
8838
+ maxBuffer: 1024 * 1024,
8839
+ env: { ...process.env, PATH: `${dirname9(process.execPath)}:${process.env.PATH ?? ""}` }
8840
+ });
8841
+ return stdout.trim();
8842
+ }
8843
+ async function checkLatestVersion(file, current, runtime, now = Date.now()) {
8844
+ const state = readJson(file);
8845
+ if (typeof state?.lastAttemptAt === "number" && now - state.lastAttemptAt < DAY) return;
8846
+ writeJsonAtomic(file, { lastAttemptAt: now });
8847
+ const latest = await runtime.latest();
8848
+ return newerStableVersion(latest, current) ? latest : void 0;
8849
+ }
8850
+
8851
+ // src/service.ts
8852
+ import { execFile as execFile3 } from "node:child_process";
8853
+ import { promisify as promisify3 } from "node:util";
8854
+ import { mkdir, writeFile, rm } from "node:fs/promises";
8855
+ import { homedir as homedir7 } from "node:os";
8856
+ import { dirname as dirname10, join as join18, resolve as resolve9 } from "node:path";
8857
+ var exec2 = promisify3(execFile3);
8825
8858
  var label = "com.aspectlylabs.mikka.daemon";
8826
8859
  async function restartService(update, beforeRestart, dependencies = {
8827
8860
  manager: process.env.MIKKA_SERVICE,
8828
8861
  update: async () => {
8829
- await exec("npm", ["install", "--global", "@aspectlylabs/mikka"], { timeout: 3e5, maxBuffer: 1024 * 1024 });
8862
+ await runServiceNpm(["install", "--global", "--engine-strict", "@aspectlylabs/mikka"]);
8830
8863
  },
8831
8864
  restart: () => {
8832
- setImmediate(() => process.kill(process.pid, "SIGUSR2"));
8865
+ setImmediate(() => {
8866
+ if (canRestart()) process.kill(process.pid, "SIGUSR2");
8867
+ });
8833
8868
  }
8834
- }) {
8869
+ }, canRestart = () => true) {
8835
8870
  const manager = dependencies.manager;
8836
8871
  if (manager !== "systemd" && manager !== "launchd") throw new Error("Daemon is not running as a managed service");
8837
8872
  if (update) await dependencies.update();
8873
+ if (!canRestart()) return;
8838
8874
  beforeRestart();
8839
8875
  dependencies.restart();
8840
8876
  }
8841
8877
  async function uninstallService(clearCredential, dependencies = {
8842
8878
  manager: process.env.MIKKA_SERVICE,
8843
- home: homedir6(),
8879
+ home: homedir7(),
8844
8880
  uid: process.getuid?.() ?? 0,
8845
8881
  run: async (program, args) => {
8846
- await exec(program, args, { timeout: 1e4 });
8882
+ await exec2(program, args, { timeout: 1e4 });
8847
8883
  },
8848
8884
  exit: () => {
8849
8885
  process.exit(0);
@@ -8852,10 +8888,10 @@ async function uninstallService(clearCredential, dependencies = {
8852
8888
  try {
8853
8889
  if (dependencies.manager === "systemd") {
8854
8890
  await dependencies.run("systemctl", ["--user", "disable", "mikka-daemon.service"]);
8855
- await rm(join17(dependencies.home, ".config/systemd/user/mikka-daemon.service"), { force: true });
8891
+ await rm(join18(dependencies.home, ".config/systemd/user/mikka-daemon.service"), { force: true });
8856
8892
  await dependencies.run("systemctl", ["--user", "daemon-reload"]);
8857
8893
  } else if (dependencies.manager === "launchd") {
8858
- await rm(join17(dependencies.home, "Library/LaunchAgents", `${label}.plist`), { force: true });
8894
+ await rm(join18(dependencies.home, "Library/LaunchAgents", `${label}.plist`), { force: true });
8859
8895
  }
8860
8896
  } finally {
8861
8897
  clearCredential();
@@ -9086,7 +9122,7 @@ async function detectHarnesses() {
9086
9122
  // src/lock.ts
9087
9123
  import { mkdirSync as mkdirSync12, readFileSync as readFileSync9, rmSync as rmSync11 } from "node:fs";
9088
9124
  import { createConnection } from "node:net";
9089
- import { join as join18 } from "node:path";
9125
+ import { join as join19 } from "node:path";
9090
9126
  import { setTimeout as sleep2 } from "node:timers/promises";
9091
9127
  import lockfile from "proper-lockfile";
9092
9128
  var DaemonAlreadyRunningError = class extends Error {
@@ -9101,7 +9137,7 @@ var LOCK_STALE_MS = 5 * 6e4;
9101
9137
  var LOCK_UPDATE_MS = 3e4;
9102
9138
  var LOCK_TAKEOVER_MS = 6e3;
9103
9139
  function pidFile(dataDir) {
9104
- return join18(dataDir, "daemon.pid");
9140
+ return join19(dataDir, "daemon.pid");
9105
9141
  }
9106
9142
  function holderPid(dataDir) {
9107
9143
  try {
@@ -9120,11 +9156,11 @@ function processAlive(pid) {
9120
9156
  }
9121
9157
  }
9122
9158
  function socketAnswers(socketPath) {
9123
- return new Promise((resolve11) => {
9159
+ return new Promise((resolve12) => {
9124
9160
  const socket = createConnection(socketPath);
9125
9161
  const done = (alive) => {
9126
9162
  socket.destroy();
9127
- resolve11(alive);
9163
+ resolve12(alive);
9128
9164
  };
9129
9165
  socket.once("connect", () => done(true));
9130
9166
  socket.once("error", () => done(false));
@@ -9233,7 +9269,7 @@ function closeLogger(logger) {
9233
9269
  const file = files.get(logger);
9234
9270
  if (!file) return Promise.resolve();
9235
9271
  files.delete(logger);
9236
- return new Promise((resolve11) => file.end(resolve11));
9272
+ return new Promise((resolve12) => file.end(resolve12));
9237
9273
  }
9238
9274
 
9239
9275
  // src/outbox.ts
@@ -9245,7 +9281,7 @@ import {
9245
9281
  rmSync as rmSync12,
9246
9282
  truncateSync
9247
9283
  } from "node:fs";
9248
- import { join as join19 } from "node:path";
9284
+ import { join as join20 } from "node:path";
9249
9285
  var Outbox = class {
9250
9286
  constructor(dir, link, log, retryMs = 1e3, onUndeliverable = () => void 0, retainResources = false) {
9251
9287
  this.dir = dir;
@@ -9268,10 +9304,10 @@ var Outbox = class {
9268
9304
  /** Runs whose file was checked for a torn tail since this process started. */
9269
9305
  repaired = /* @__PURE__ */ new Set();
9270
9306
  file(runId) {
9271
- return join19(this.dir, `${assertSafeId("run id", runId)}.jsonl`);
9307
+ return join20(this.dir, `${assertSafeId("run id", runId)}.jsonl`);
9272
9308
  }
9273
9309
  ackFile(runId) {
9274
- return join19(this.dir, `${assertSafeId("run id", runId)}.ack.json`);
9310
+ return join20(this.dir, `${assertSafeId("run id", runId)}.ack.json`);
9275
9311
  }
9276
9312
  parse(runId) {
9277
9313
  let data;
@@ -9455,16 +9491,16 @@ var Outbox = class {
9455
9491
  };
9456
9492
 
9457
9493
  // src/quota/local-credentials.ts
9458
- import { homedir as homedir7 } from "node:os";
9459
- import { join as join21 } from "node:path";
9494
+ import { homedir as homedir8 } from "node:os";
9495
+ import { join as join22 } from "node:path";
9460
9496
 
9461
9497
  // src/quota/files.ts
9462
- import { execFile as execFile3 } from "node:child_process";
9498
+ import { execFile as execFile4 } from "node:child_process";
9463
9499
  import { constants as constants2 } from "node:fs";
9464
9500
  import { lstat as lstat2, open } from "node:fs/promises";
9465
- import { promisify as promisify3 } from "node:util";
9501
+ import { promisify as promisify4 } from "node:util";
9466
9502
  var NOFOLLOW = constants2.O_NOFOLLOW ?? 0;
9467
- var execFileAsync = promisify3(execFile3);
9503
+ var execFileAsync = promisify4(execFile4);
9468
9504
  var KEYCHAIN_TIMEOUT_MS = 3e4;
9469
9505
  var MAX_CREDENTIAL_BYTES = 64 * 1024;
9470
9506
  function sanitizeError(error) {
@@ -9490,8 +9526,8 @@ function classifyKeychainError(error) {
9490
9526
  function safeAccount(account) {
9491
9527
  return /^[A-Za-z0-9._-]{1,64}$/.test(account);
9492
9528
  }
9493
- async function readKeychainPassword(service, accounts = [null], exec4 = execFileAsync) {
9494
- if (process.platform !== "darwin" && exec4 === execFileAsync) {
9529
+ async function readKeychainPassword(service, accounts = [null], exec5 = execFileAsync) {
9530
+ if (process.platform !== "darwin" && exec5 === execFileAsync) {
9495
9531
  return { status: "notFound" };
9496
9532
  }
9497
9533
  let denied = false;
@@ -9505,7 +9541,7 @@ async function readKeychainPassword(service, accounts = [null], exec4 = execFile
9505
9541
  "-w"
9506
9542
  ];
9507
9543
  try {
9508
- const { stdout } = await exec4("/usr/bin/security", args, {
9544
+ const { stdout } = await exec5("/usr/bin/security", args, {
9509
9545
  timeout: KEYCHAIN_TIMEOUT_MS,
9510
9546
  maxBuffer: MAX_CREDENTIAL_BYTES
9511
9547
  });
@@ -9954,12 +9990,12 @@ async function readCodexQuota(options) {
9954
9990
 
9955
9991
  // src/quota/cursor.ts
9956
9992
  import { lstat as lstat3 } from "node:fs/promises";
9957
- import { join as join20 } from "node:path";
9993
+ import { join as join21 } from "node:path";
9958
9994
  var ENDPOINT3 = "https://cursor.com/api/usage-summary";
9959
9995
  var ACCESS_TOKEN_KEY = "cursorAuth/accessToken";
9960
9996
  function cursorDatabasePath(platform3, home) {
9961
9997
  if (platform3 === "darwin") {
9962
- return join20(
9998
+ return join21(
9963
9999
  home,
9964
10000
  "Library",
9965
10001
  "Application Support",
@@ -9970,7 +10006,7 @@ function cursorDatabasePath(platform3, home) {
9970
10006
  );
9971
10007
  }
9972
10008
  if (platform3 === "win32") {
9973
- return join20(
10009
+ return join21(
9974
10010
  home,
9975
10011
  "AppData",
9976
10012
  "Roaming",
@@ -9980,7 +10016,7 @@ function cursorDatabasePath(platform3, home) {
9980
10016
  "state.vscdb"
9981
10017
  );
9982
10018
  }
9983
- return join20(home, ".config", "Cursor", "User", "globalStorage", "state.vscdb");
10019
+ return join21(home, ".config", "Cursor", "User", "globalStorage", "state.vscdb");
9984
10020
  }
9985
10021
  var CURSOR_PLANS = {
9986
10022
  pro: "Pro",
@@ -10152,10 +10188,10 @@ async function readCursorQuota(options) {
10152
10188
  // src/quota/local-credentials.ts
10153
10189
  var KEYCHAIN_SERVICE = "Claude Code-credentials";
10154
10190
  function claudeCredentialPath(home) {
10155
- return join21(home, ".claude", ".credentials.json");
10191
+ return join22(home, ".claude", ".credentials.json");
10156
10192
  }
10157
10193
  function codexAuthPath(home) {
10158
- return join21(home, ".codex", "auth.json");
10194
+ return join22(home, ".codex", "auth.json");
10159
10195
  }
10160
10196
  function unknown2(vendor, observedAt) {
10161
10197
  return {
@@ -10174,7 +10210,7 @@ var LocalCredentialsSource = class {
10174
10210
  options;
10175
10211
  id = "local_credentials";
10176
10212
  async read(signal) {
10177
- const home = this.options.home ?? homedir7();
10213
+ const home = this.options.home ?? homedir8();
10178
10214
  const platform3 = this.options.platform ?? process.platform;
10179
10215
  const fetchImpl = this.options.fetch ?? globalThis.fetch;
10180
10216
  const now = this.options.now ?? Date.now;
@@ -10350,9 +10386,9 @@ var RpcServer = class {
10350
10386
  const { socketPath } = this.options;
10351
10387
  rmSync13(socketPath, { force: true });
10352
10388
  const server = createServer2((socket) => this.accept(socket));
10353
- await new Promise((resolve11, reject) => {
10389
+ await new Promise((resolve12, reject) => {
10354
10390
  server.once("error", reject);
10355
- server.listen(socketPath, () => resolve11());
10391
+ server.listen(socketPath, () => resolve12());
10356
10392
  });
10357
10393
  chmodSync2(socketPath, 384);
10358
10394
  this.server = server;
@@ -10416,9 +10452,9 @@ var RpcServer = class {
10416
10452
  }
10417
10453
  async close() {
10418
10454
  for (const socket of this.sockets) socket.destroy();
10419
- await new Promise((resolve11) => {
10420
- if (!this.server) return resolve11();
10421
- this.server.close(() => resolve11());
10455
+ await new Promise((resolve12) => {
10456
+ if (!this.server) return resolve12();
10457
+ this.server.close(() => resolve12());
10422
10458
  });
10423
10459
  this.server = null;
10424
10460
  rmSync13(this.options.socketPath, { force: true });
@@ -10644,13 +10680,13 @@ function createRunMasker(secrets) {
10644
10680
 
10645
10681
  // src/runs/supervisor.ts
10646
10682
  import { createHash as createHash4, randomUUID as randomUUID5 } from "node:crypto";
10647
- import { join as join23, resolve as resolve9 } from "node:path";
10683
+ import { join as join24, resolve as resolve10 } from "node:path";
10648
10684
  import { execa as execa12 } from "execa";
10649
10685
 
10650
10686
  // src/agents/checkpoint.ts
10651
10687
  import { mkdtempSync as mkdtempSync6, rmSync as rmSync14, writeFileSync as writeFileSync7 } from "node:fs";
10652
10688
  import { tmpdir as tmpdir2 } from "node:os";
10653
- import { join as join22 } from "node:path";
10689
+ import { join as join23 } from "node:path";
10654
10690
  import { gunzipSync as gunzipSync2, gzipSync as gzipSync2 } from "node:zlib";
10655
10691
  import { execa as execa11 } from "execa";
10656
10692
  var CheckpointRecoveryError = class extends Error {
@@ -10697,8 +10733,8 @@ async function takeCheckpoint(options) {
10697
10733
  }
10698
10734
  async function applyCheckpoint(options) {
10699
10735
  const git2 = await pinnedGit(options.repoPath, options.worktree);
10700
- const dir = mkdtempSync6(join22(tmpdir2(), "mikka-checkpoint-"));
10701
- const file = join22(dir, "checkpoint.patch");
10736
+ const dir = mkdtempSync6(join23(tmpdir2(), "mikka-checkpoint-"));
10737
+ const file = join23(dir, "checkpoint.patch");
10702
10738
  try {
10703
10739
  const patch = gunzipSync2(Buffer.from(options.checkpoint.patch, "base64"));
10704
10740
  if (!patch.length && options.checkpoint.files === 0) return true;
@@ -10946,12 +10982,12 @@ var MemoryServer = class {
10946
10982
  this.check();
10947
10983
  let pending = this.pendingCommands(deviceId, skip);
10948
10984
  if (pending.length === 0 && waitSeconds > 0 && !signal?.aborted) {
10949
- await new Promise((resolve11) => {
10950
- const timer = setTimeout(resolve11, waitSeconds * 1e3);
10951
- signal?.addEventListener("abort", () => resolve11(), { once: true });
10985
+ await new Promise((resolve12) => {
10986
+ const timer = setTimeout(resolve12, waitSeconds * 1e3);
10987
+ signal?.addEventListener("abort", () => resolve12(), { once: true });
10952
10988
  this.wakeCommands.push(() => {
10953
10989
  clearTimeout(timer);
10954
- resolve11();
10990
+ resolve12();
10955
10991
  });
10956
10992
  });
10957
10993
  this.check();
@@ -11359,9 +11395,9 @@ var RunSupervisor = class {
11359
11395
  run2.abort.abort();
11360
11396
  }
11361
11397
  let timer;
11362
- const grace = new Promise((resolve11) => {
11398
+ const grace = new Promise((resolve12) => {
11363
11399
  timer = setTimeout(
11364
- resolve11,
11400
+ resolve12,
11365
11401
  this.deps.stopGraceMs ?? DEFAULT_STOP_GRACE_MS
11366
11402
  );
11367
11403
  });
@@ -11553,8 +11589,8 @@ var RunSupervisor = class {
11553
11589
  let timer;
11554
11590
  await Promise.race([
11555
11591
  this.deps.captures.flush(runId),
11556
- new Promise((resolve11) => {
11557
- timer = setTimeout(resolve11, 6e4);
11592
+ new Promise((resolve12) => {
11593
+ timer = setTimeout(resolve12, 6e4);
11558
11594
  })
11559
11595
  ]).finally(() => clearTimeout(timer));
11560
11596
  }
@@ -11888,7 +11924,7 @@ var RunSupervisor = class {
11888
11924
  mailbox
11889
11925
  };
11890
11926
  const resuming = entry.sessionId !== null && adapter.capabilities.supportsResume;
11891
- const inEarlierWorktree = continued !== null || entry.worktree !== null && resolve9(entry.worktree) !== resolve9(this.deps.worktrees.pathFor(runId));
11927
+ const inEarlierWorktree = continued !== null || entry.worktree !== null && resolve10(entry.worktree) !== resolve10(this.deps.worktrees.pathFor(runId));
11892
11928
  const continueSession = !resuming && assignment.resumeSessionId && assignment.continuesRunId && inEarlierWorktree && adapter.capabilities.supportsResume ? {
11893
11929
  sessionId: assignment.resumeSessionId,
11894
11930
  runId: assignment.continuesRunId,
@@ -11935,7 +11971,7 @@ var RunSupervisor = class {
11935
11971
  if (!this.deps.adapterStateDir || assignment.harness === "mock" || !session.sessionId || resuming && session.sessionId !== entry.sessionId || assignment.requireSessionResume && session.sessionId !== assignment.resumeSessionId)
11936
11972
  throw new Error("Skill mount requires the actual original harness session");
11937
11973
  verifySkillAssignment(assignment);
11938
- const file = join23(
11974
+ const file = join24(
11939
11975
  runPaths(this.deps.adapterStateDir, runId).runDir,
11940
11976
  SKILLS_DIR,
11941
11977
  skillSlug(assignment.skills[0].name),
@@ -12117,10 +12153,10 @@ function trackParts(open2, chunk) {
12117
12153
  }
12118
12154
  var ABORTED = /* @__PURE__ */ Symbol("aborted");
12119
12155
  function abortPromise(signal) {
12120
- return new Promise((resolve11) => {
12121
- if (signal.aborted) resolve11(ABORTED);
12156
+ return new Promise((resolve12) => {
12157
+ if (signal.aborted) resolve12(ABORTED);
12122
12158
  else
12123
- signal.addEventListener("abort", () => resolve11(ABORTED), { once: true });
12159
+ signal.addEventListener("abort", () => resolve12(ABORTED), { once: true });
12124
12160
  });
12125
12161
  }
12126
12162
  function pickAgentReport(agent) {
@@ -12211,8 +12247,8 @@ var SessionRejectedError = class extends DaemonError {
12211
12247
 
12212
12248
  // src/repositories.ts
12213
12249
  import { createHash as createHash5, randomUUID as randomUUID6 } from "node:crypto";
12214
- import { existsSync as existsSync5, lstatSync as lstatSync8, mkdirSync as mkdirSync14, readdirSync as readdirSync5, realpathSync as realpathSync10, renameSync as renameSync2, rmSync as rmSync15 } from "node:fs";
12215
- import { dirname as dirname10, join as join24, resolve as resolve10 } from "node:path";
12250
+ import { existsSync as existsSync5, lstatSync as lstatSync8, mkdirSync as mkdirSync14, readdirSync as readdirSync5, realpathSync as realpathSync11, renameSync as renameSync2, rmSync as rmSync15 } from "node:fs";
12251
+ import { dirname as dirname11, join as join25, resolve as resolve11 } from "node:path";
12216
12252
  import { setTimeout as delay2 } from "node:timers/promises";
12217
12253
  import { execa as execa13 } from "execa";
12218
12254
  import lockfile2 from "proper-lockfile";
@@ -12227,8 +12263,8 @@ var RepositoryCache = class {
12227
12263
  retainResources;
12228
12264
  pathFor(remoteUrl) {
12229
12265
  const { key: key2 } = normalizeRepository(remoteUrl, { allowFile: this.allowFile });
12230
- const path = resolve10(this.root, "v2", createHash5("sha256").update(key2).digest("hex"));
12231
- if (!isInside(resolve10(this.root), path) || path === resolve10(this.root)) throw new Error("Invalid repository cache path");
12266
+ const path = resolve11(this.root, "v2", createHash5("sha256").update(key2).digest("hex"));
12267
+ if (!isInside(resolve11(this.root), path) || path === resolve11(this.root)) throw new Error("Invalid repository cache path");
12232
12268
  return path;
12233
12269
  }
12234
12270
  /** Serialize clone/fetch against the same cache, including other processes. */
@@ -12236,7 +12272,7 @@ var RepositoryCache = class {
12236
12272
  signal?.throwIfAborted();
12237
12273
  const { remoteUrl: remote } = normalizeRepository(remoteUrl, { allowFile: this.allowFile });
12238
12274
  const path = this.pathFor(remote);
12239
- this.ensureParents(dirname10(path));
12275
+ this.ensureParents(dirname11(path));
12240
12276
  const release = await this.lock(path, signal);
12241
12277
  try {
12242
12278
  signal?.throwIfAborted();
@@ -12280,29 +12316,29 @@ var RepositoryCache = class {
12280
12316
  paths() {
12281
12317
  const visit = (path) => {
12282
12318
  if (!existsSync5(path) || lstatSync8(path).isSymbolicLink()) return [];
12283
- if (existsSync5(join24(path, ".git"))) {
12319
+ if (existsSync5(join25(path, ".git"))) {
12284
12320
  this.assertClone(path);
12285
12321
  return [path];
12286
12322
  }
12287
- return readdirSync5(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join24(path, entry.name)) : []);
12323
+ return readdirSync5(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join25(path, entry.name)) : []);
12288
12324
  };
12289
- return visit(resolve10(this.root));
12325
+ return visit(resolve11(this.root));
12290
12326
  }
12291
12327
  ensureParents(path) {
12292
12328
  mkdirSync14(this.root, { recursive: true, mode: 448 });
12293
12329
  if (lstatSync8(this.root).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
12294
- const root = realpathSync10(this.root);
12295
- let current = resolve10(this.root);
12330
+ const root = realpathSync11(this.root);
12331
+ let current = resolve11(this.root);
12296
12332
  for (const part of path.slice(current.length + 1).split("/").filter(Boolean)) {
12297
- current = join24(current, part);
12333
+ current = join25(current, part);
12298
12334
  if (existsSync5(current) && lstatSync8(current).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
12299
12335
  mkdirSync14(current, { recursive: true, mode: 448 });
12300
- if (!isInside(root, realpathSync10(current))) throw new Error("Repository cache escapes its directory");
12336
+ if (!isInside(root, realpathSync11(current))) throw new Error("Repository cache escapes its directory");
12301
12337
  }
12302
12338
  }
12303
12339
  assertClone(path) {
12304
- if (lstatSync8(path).isSymbolicLink() || !lstatSync8(join24(path, ".git")).isDirectory() || lstatSync8(join24(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
12305
- if (!isInside(realpathSync10(this.root), realpathSync10(path))) throw new Error("Repository cache escapes its directory");
12340
+ if (lstatSync8(path).isSymbolicLink() || !lstatSync8(join25(path, ".git")).isDirectory() || lstatSync8(join25(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
12341
+ if (!isInside(realpathSync11(this.root), realpathSync11(path))) throw new Error("Repository cache escapes its directory");
12306
12342
  }
12307
12343
  async lock(path, signal) {
12308
12344
  const deadline = Date.now() + 12e4;
@@ -12319,7 +12355,7 @@ var RepositoryCache = class {
12319
12355
  };
12320
12356
 
12321
12357
  // src/subscription-hosted-runner.ts
12322
- import { execFile as execFile4, spawn as spawn4 } from "node:child_process";
12358
+ import { execFile as execFile5, spawn as spawn4 } from "node:child_process";
12323
12359
  import { randomUUID as randomUUID7 } from "node:crypto";
12324
12360
  import {
12325
12361
  existsSync as existsSync6,
@@ -12327,13 +12363,13 @@ import {
12327
12363
  mkdirSync as mkdirSync15,
12328
12364
  mkdtempSync as mkdtempSync7,
12329
12365
  readdirSync as readdirSync6,
12330
- realpathSync as realpathSync11,
12366
+ realpathSync as realpathSync12,
12331
12367
  rmSync as rmSync16
12332
12368
  } from "node:fs";
12333
12369
  import { createRequire } from "node:module";
12334
- import { delimiter as delimiter2, dirname as dirname11, join as join26 } from "node:path";
12370
+ import { delimiter as delimiter2, dirname as dirname12, join as join27 } from "node:path";
12335
12371
  import { fileURLToPath as fileURLToPath2 } from "node:url";
12336
- import { promisify as promisify4 } from "node:util";
12372
+ import { promisify as promisify5 } from "node:util";
12337
12373
 
12338
12374
  // src/agents/public-egress.ts
12339
12375
  import { lookup } from "node:dns/promises";
@@ -12341,7 +12377,7 @@ import { chmod, mkdtemp, rm as rm2 } from "node:fs/promises";
12341
12377
  import { createServer as createServer3, request as httpRequest } from "node:http";
12342
12378
  import { connect, isIP as isIP3 } from "node:net";
12343
12379
  import { tmpdir as tmpdir3 } from "node:os";
12344
- import { join as join25 } from "node:path";
12380
+ import { join as join26 } from "node:path";
12345
12381
 
12346
12382
  // ../../lib/search/url-policy.ts
12347
12383
  import { BlockList, isIP as isIP2 } from "node:net";
@@ -12410,9 +12446,9 @@ function endToEndHeaders(input) {
12410
12446
  }
12411
12447
  async function startPublicEgress(options) {
12412
12448
  options.signal.throwIfAborted();
12413
- const directory = await mkdtemp(join25(tmpdir3(), "mikka-egress-"));
12449
+ const directory = await mkdtemp(join26(tmpdir3(), "mikka-egress-"));
12414
12450
  await chmod(directory, 448);
12415
- const socketPath = join25(directory, "egress.sock");
12451
+ const socketPath = join26(directory, "egress.sock");
12416
12452
  const lifetime = new AbortController();
12417
12453
  const signal = AbortSignal.any([options.signal, lifetime.signal]);
12418
12454
  const sockets = /* @__PURE__ */ new Set();
@@ -12517,9 +12553,9 @@ async function startPublicEgress(options) {
12517
12553
  if (closing) return closing;
12518
12554
  lifetime.abort();
12519
12555
  for (const socket of sockets) socket.destroy();
12520
- closing = new Promise((resolve11, reject) => server.close((error) => {
12556
+ closing = new Promise((resolve12, reject) => server.close((error) => {
12521
12557
  options.signal.removeEventListener("abort", onAbort);
12522
- void rm2(directory, { recursive: true, force: true }).then(() => error && error.code !== "ERR_SERVER_NOT_RUNNING" ? reject(error) : resolve11(), reject);
12558
+ void rm2(directory, { recursive: true, force: true }).then(() => error && error.code !== "ERR_SERVER_NOT_RUNNING" ? reject(error) : resolve12(), reject);
12523
12559
  }));
12524
12560
  return closing;
12525
12561
  };
@@ -12528,11 +12564,11 @@ async function startPublicEgress(options) {
12528
12564
  };
12529
12565
  options.signal.addEventListener("abort", onAbort, { once: true });
12530
12566
  try {
12531
- await new Promise((resolve11, reject) => {
12567
+ await new Promise((resolve12, reject) => {
12532
12568
  server.once("error", reject);
12533
12569
  server.listen(socketPath, () => {
12534
12570
  server.removeListener("error", reject);
12535
- resolve11();
12571
+ resolve12();
12536
12572
  });
12537
12573
  });
12538
12574
  await chmod(socketPath, 384);
@@ -12545,7 +12581,7 @@ async function startPublicEgress(options) {
12545
12581
  }
12546
12582
 
12547
12583
  // src/subscription-hosted-runner.ts
12548
- var exec2 = promisify4(execFile4);
12584
+ var exec3 = promisify5(execFile5);
12549
12585
  var image = HOSTED_NATIVE_IMAGE;
12550
12586
  var bootstrap = fileURLToPath2(
12551
12587
  new URL("./agents/native-container.mjs", import.meta.url)
@@ -12563,20 +12599,20 @@ async function createHostedBotRunner(host) {
12563
12599
  throw unavailable2();
12564
12600
  if (host.dockerSocket !== void 0 && host.dockerSocket !== "unix:///run/mikka-container/docker.sock") throw unavailable2();
12565
12601
  const bareEnv = { PATH: process.env.PATH, LANG: "C.UTF-8", ...host.dockerSocket ? { DOCKER_HOST: host.dockerSocket } : {} };
12566
- await exec2("docker", ["image", "inspect", image, "--format", "{{.Id}}"], {
12602
+ await exec3("docker", ["image", "inspect", image, "--format", "{{.Id}}"], {
12567
12603
  env: bareEnv,
12568
12604
  timeout: 1e4
12569
12605
  }).catch(() => {
12570
12606
  throw unavailable2();
12571
12607
  });
12572
- const resources = join26(host.stateDir, "native-resources");
12608
+ const resources = join27(host.stateDir, "native-resources");
12573
12609
  mkdirSync15(resources, { recursive: true, mode: 448 });
12574
12610
  const removeResource = async (file, record) => {
12575
12611
  if (!/^mikka-native-(?:verify-)?[a-f0-9-]{36}$/.test(record.name) || !/^[a-f0-9-]{36}$/.test(record.nonce))
12576
12612
  throw unavailable2();
12577
12613
  let described;
12578
12614
  try {
12579
- described = await exec2(
12615
+ described = await exec3(
12580
12616
  "docker",
12581
12617
  [
12582
12618
  "inspect",
@@ -12590,7 +12626,7 @@ async function createHostedBotRunner(host) {
12590
12626
  if (record.state === "created" && /No such (?:container|object)/i.test(
12591
12627
  String(error.stderr)
12592
12628
  )) {
12593
- if (record.assets?.startsWith(join26(host.stateDir, "native-verify-git-")))
12629
+ if (record.assets?.startsWith(join27(host.stateDir, "native-verify-git-")))
12594
12630
  rmSync16(record.assets, { recursive: true, force: true });
12595
12631
  rmSync16(file, { force: true });
12596
12632
  return;
@@ -12600,14 +12636,14 @@ async function createHostedBotRunner(host) {
12600
12636
  const [id4, labels] = described.stdout.trim().split("|").map((part) => JSON.parse(part));
12601
12637
  if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id4)
12602
12638
  throw unavailable2();
12603
- await exec2("docker", ["rm", "-f", id4], { env: bareEnv, timeout: 3e4 });
12604
- if (record.assets?.startsWith(join26(host.stateDir, "native-verify-git-")))
12639
+ await exec3("docker", ["rm", "-f", id4], { env: bareEnv, timeout: 3e4 });
12640
+ if (record.assets?.startsWith(join27(host.stateDir, "native-verify-git-")))
12605
12641
  rmSync16(record.assets, { recursive: true, force: true });
12606
12642
  rmSync16(file, { force: true });
12607
12643
  };
12608
12644
  for (const name of readdirSync6(resources))
12609
12645
  if (name.endsWith(".json")) {
12610
- const file = join26(resources, name);
12646
+ const file = join27(resources, name);
12611
12647
  const record = readJson(file);
12612
12648
  if (!record) throw unavailable2();
12613
12649
  await removeResource(file, record);
@@ -12618,8 +12654,8 @@ async function createHostedBotRunner(host) {
12618
12654
  const bundled = createRequire(
12619
12655
  require2.resolve("@anthropic-ai/claude-agent-sdk")
12620
12656
  );
12621
- claude ??= join26(
12622
- dirname11(
12657
+ claude ??= join27(
12658
+ dirname12(
12623
12659
  bundled.resolve(
12624
12660
  "@anthropic-ai/claude-agent-sdk-linux-x64/package.json"
12625
12661
  )
@@ -12628,12 +12664,12 @@ async function createHostedBotRunner(host) {
12628
12664
  );
12629
12665
  } catch {
12630
12666
  }
12631
- const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter2).map((dir) => join26(dir, "codex")).find((path) => existsSync6(path));
12667
+ const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter2).map((dir) => join27(dir, "codex")).find((path) => existsSync6(path));
12632
12668
  const binaries = { codex, claude_code: claude };
12633
12669
  for (const kind of ["codex", "claude_code"])
12634
12670
  if (binaries[kind]) {
12635
12671
  try {
12636
- binaries[kind] = realpathSync11(binaries[kind]);
12672
+ binaries[kind] = realpathSync12(binaries[kind]);
12637
12673
  if (!lstatSync9(binaries[kind]).isFile()) delete binaries[kind];
12638
12674
  } catch {
12639
12675
  delete binaries[kind];
@@ -12642,16 +12678,16 @@ async function createHostedBotRunner(host) {
12642
12678
  if (!binaries.codex && !binaries.claude_code) throw unavailable2();
12643
12679
  const command = async (worktree, script, readOnly, timeoutMs, signal) => {
12644
12680
  const name = `mikka-native-verify-${randomUUID7()}`;
12645
- const file = join26(resources, name + ".json");
12681
+ const file = join27(resources, name + ".json");
12646
12682
  const resource = { name, nonce: randomUUID7(), state: "creating" };
12647
12683
  const timing = { createMs: 0, runMs: 0 };
12648
12684
  let phase = "create";
12649
12685
  let began = performance.now();
12650
- const gitCopy = mkdtempSync7(join26(host.stateDir, "native-verify-git-"));
12686
+ const gitCopy = mkdtempSync7(join27(host.stateDir, "native-verify-git-"));
12651
12687
  resource.assets = gitCopy;
12652
12688
  try {
12653
- const cwd = realpathSync11(worktree);
12654
- await exec2(
12689
+ const cwd = realpathSync12(worktree);
12690
+ await exec3(
12655
12691
  "git",
12656
12692
  [
12657
12693
  "-c",
@@ -12663,7 +12699,7 @@ async function createHostedBotRunner(host) {
12663
12699
  "--no-checkout",
12664
12700
  "--",
12665
12701
  cwd,
12666
- join26(gitCopy, "repo")
12702
+ join27(gitCopy, "repo")
12667
12703
  ],
12668
12704
  {
12669
12705
  env: {
@@ -12678,10 +12714,10 @@ async function createHostedBotRunner(host) {
12678
12714
  maxBuffer: 1024 * 1024
12679
12715
  }
12680
12716
  );
12681
- const safeGit = join26(gitCopy, "repo", ".git");
12682
- const protectedGit = lstatSync9(join26(cwd, ".git")).isFile() ? join26(cwd, ".git") : safeGit;
12717
+ const safeGit = join27(gitCopy, "repo", ".git");
12718
+ const protectedGit = lstatSync9(join27(cwd, ".git")).isFile() ? join27(cwd, ".git") : safeGit;
12683
12719
  writeJsonAtomic(file, resource);
12684
- const created = await exec2(
12720
+ const created = await exec3(
12685
12721
  "docker",
12686
12722
  [
12687
12723
  "create",
@@ -12739,7 +12775,7 @@ async function createHostedBotRunner(host) {
12739
12775
  timing.createMs = Math.round(performance.now() - began);
12740
12776
  phase = "run";
12741
12777
  began = performance.now();
12742
- const result = await exec2("docker", ["start", "-a", resource.id], {
12778
+ const result = await exec3("docker", ["start", "-a", resource.id], {
12743
12779
  env: bareEnv,
12744
12780
  timeout: timeoutMs,
12745
12781
  signal,
@@ -12783,7 +12819,7 @@ async function createHostedBotRunner(host) {
12783
12819
  throw unavailable2();
12784
12820
  const name = `mikka-native-${randomUUID7()}`;
12785
12821
  const nonce = randomUUID7();
12786
- const resourceFile = join26(resources, name + ".json");
12822
+ const resourceFile = join27(resources, name + ".json");
12787
12823
  const resource = { name, nonce, state: "creating" };
12788
12824
  const lifetime = new AbortController();
12789
12825
  let closed = false;
@@ -12856,11 +12892,11 @@ async function createHostedBotRunner(host) {
12856
12892
  };
12857
12893
  const paths = runPaths(host.stateDir, assignment.runId);
12858
12894
  mkdirSync15(paths.runDir, { recursive: true, mode: 448 });
12859
- const shadow = join26(paths.runDir, "runtime-git");
12860
- const emptyHome = join26(paths.runDir, "git-bootstrap-home");
12895
+ const shadow = join27(paths.runDir, "runtime-git");
12896
+ const emptyHome = join27(paths.runDir, "git-bootstrap-home");
12861
12897
  mkdirSync15(emptyHome, { recursive: true, mode: 448 });
12862
12898
  if (!existsSync6(shadow))
12863
- await exec2(
12899
+ await exec3(
12864
12900
  "git",
12865
12901
  [
12866
12902
  "-c",
@@ -12871,7 +12907,7 @@ async function createHostedBotRunner(host) {
12871
12907
  "--no-hardlinks",
12872
12908
  "--no-checkout",
12873
12909
  "--",
12874
- realpathSync11(options.cwd),
12910
+ realpathSync12(options.cwd),
12875
12911
  shadow
12876
12912
  ],
12877
12913
  {
@@ -12888,9 +12924,9 @@ async function createHostedBotRunner(host) {
12888
12924
  }
12889
12925
  );
12890
12926
  await live();
12891
- if (!lstatSync9(shadow).isDirectory() || !lstatSync9(join26(shadow, ".git")).isDirectory() || !realpathSync11(shadow).startsWith(realpathSync11(paths.runDir) + "/"))
12927
+ if (!lstatSync9(shadow).isDirectory() || !lstatSync9(join27(shadow, ".git")).isDirectory() || !realpathSync12(shadow).startsWith(realpathSync12(paths.runDir) + "/"))
12892
12928
  throw unavailable2();
12893
- const ledger = join26(
12929
+ const ledger = join27(
12894
12930
  host.stateDir,
12895
12931
  "native-ledgers",
12896
12932
  assignment.runId + ".json"
@@ -12909,13 +12945,13 @@ async function createHostedBotRunner(host) {
12909
12945
  const previous = readJson(ledger);
12910
12946
  if (existsSync6(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
12911
12947
  throw unavailable2();
12912
- mkdirSync15(dirname11(ledger), { recursive: true, mode: 448 });
12948
+ mkdirSync15(dirname12(ledger), { recursive: true, mode: 448 });
12913
12949
  const record = async (sessionId) => {
12914
12950
  assertOpen();
12915
12951
  writeJsonAtomic(ledger, { scope, sessionId });
12916
12952
  };
12917
12953
  brokerStarting = createNativeSubscriptionBroker({
12918
- root: join26(host.stateDir, "native-brokers"),
12954
+ root: join27(host.stateDir, "native-brokers"),
12919
12955
  revision,
12920
12956
  check,
12921
12957
  worker: {
@@ -12942,7 +12978,7 @@ async function createHostedBotRunner(host) {
12942
12978
  });
12943
12979
  const readyBroker = await brokerStarting;
12944
12980
  await live();
12945
- const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter2).map((dir) => join26(dir, "gh")).find((file) => existsSync6(file)) : void 0;
12981
+ const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter2).map((dir) => join27(dir, "gh")).find((file) => existsSync6(file)) : void 0;
12946
12982
  if (options.github && !githubCli) throw new Error("Install GitHub CLI (gh) in the cloud worker image");
12947
12983
  const githubDomains = options.github ? ["github.com", "api.github.com", new URL(options.github.endpoint).host] : [];
12948
12984
  const egressMaximum = runDomains(runPolicy(options.policy), [...options.networkAllow ?? [], ...githubDomains]);
@@ -12957,10 +12993,10 @@ async function createHostedBotRunner(host) {
12957
12993
  await egressStarting;
12958
12994
  await live();
12959
12995
  }
12960
- const cwd = realpathSync11(options.cwd);
12961
- const runDir = realpathSync11(paths.runDir);
12962
- const protectedGit = lstatSync9(join26(cwd, ".git")).isFile() ? join26(cwd, ".git") : join26(shadow, ".git");
12963
- if (!lstatSync9(runDir).isDirectory() || !runDir.startsWith(realpathSync11(host.stateDir) + "/runs/")) {
12996
+ const cwd = realpathSync12(options.cwd);
12997
+ const runDir = realpathSync12(paths.runDir);
12998
+ const protectedGit = lstatSync9(join27(cwd, ".git")).isFile() ? join27(cwd, ".git") : join27(shadow, ".git");
12999
+ if (!lstatSync9(runDir).isDirectory() || !runDir.startsWith(realpathSync12(host.stateDir) + "/runs/")) {
12964
13000
  await close();
12965
13001
  throw unavailable2();
12966
13002
  }
@@ -13013,7 +13049,7 @@ async function createHostedBotRunner(host) {
13013
13049
  `${MCP_SERVER_SCRIPT}:${MCP_SERVER_SCRIPT}:ro`,
13014
13050
  ...githubCli ? ["-v", `${githubCli}:/usr/local/bin/mikka-gh:ro`, "-v", `${GITHUB_CREDENTIAL_SCRIPT}:${GITHUB_CREDENTIAL_SCRIPT}:ro`] : [],
13015
13051
  "-v",
13016
- `${join26(dirname11(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join26(dirname11(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
13052
+ `${join27(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join27(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
13017
13053
  "-v",
13018
13054
  `${readyBroker.socket}:/run/mikka-native.sock:ro`,
13019
13055
  ...computerGrant ? [
@@ -13039,7 +13075,7 @@ async function createHostedBotRunner(host) {
13039
13075
  await live();
13040
13076
  writeJsonAtomic(resourceFile, resource);
13041
13077
  try {
13042
- creating = exec2("docker", containerArgs, {
13078
+ creating = exec3("docker", containerArgs, {
13043
13079
  env: bareEnv,
13044
13080
  timeout: 3e4
13045
13081
  }).then((created) => {
@@ -13056,13 +13092,13 @@ async function createHostedBotRunner(host) {
13056
13092
  }
13057
13093
  const spawnHosted = (config) => {
13058
13094
  assertOpen();
13059
- const home = join26(runDir, "runtime-home");
13095
+ const home = join27(runDir, "runtime-home");
13060
13096
  mkdirSync15(home, { recursive: true, mode: 448 });
13061
13097
  const env = {
13062
13098
  ...config.env,
13063
13099
  HOME: kind === "claude_code" ? config.env.HOME ?? home : home,
13064
- PATH: `${options.github ? join26(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
13065
- GIT_DIR: join26(shadow, ".git"),
13100
+ PATH: `${options.github ? join27(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
13101
+ GIT_DIR: join27(shadow, ".git"),
13066
13102
  GIT_WORK_TREE: cwd,
13067
13103
  GIT_CONFIG_GLOBAL: "/dev/null",
13068
13104
  GIT_CONFIG_SYSTEM: "/dev/null",
@@ -13081,7 +13117,7 @@ async function createHostedBotRunner(host) {
13081
13117
  signal: AbortSignal.any([lifetime.signal, ...config.signal ? [config.signal] : []])
13082
13118
  });
13083
13119
  child.stdin.write(
13084
- JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join26(runDir, "github", "bin") } : {} }) + "\n"
13120
+ JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join27(runDir, "github", "bin") } : {} }) + "\n"
13085
13121
  );
13086
13122
  return child;
13087
13123
  };
@@ -13095,9 +13131,9 @@ async function createHostedBotRunner(host) {
13095
13131
  signal: new AbortController().signal
13096
13132
  });
13097
13133
  child.stderr?.resume();
13098
- const exited = new Promise((resolve11) => {
13099
- child.once("exit", (code, signal) => resolve11({ code, signal }));
13100
- child.once("error", () => resolve11({ code: null, signal: null }));
13134
+ const exited = new Promise((resolve12) => {
13135
+ child.once("exit", (code, signal) => resolve12({ code, signal }));
13136
+ child.once("error", () => resolve12({ code: null, signal: null }));
13101
13137
  });
13102
13138
  return {
13103
13139
  process: child,
@@ -13221,19 +13257,19 @@ import { createServer as createServer4 } from "node:net";
13221
13257
 
13222
13258
  // src/computer/driver.mjs
13223
13259
  import { spawn as spawn5 } from "node:child_process";
13224
- import { execFile as execFile5 } from "node:child_process";
13225
- import { promisify as promisify5 } from "node:util";
13260
+ import { execFile as execFile6 } from "node:child_process";
13261
+ import { promisify as promisify6 } from "node:util";
13226
13262
  import { createHash as createHash6 } from "node:crypto";
13227
13263
  import { readFile as readFile2, realpath as realpath2 } from "node:fs/promises";
13228
13264
  import { createInterface } from "node:readline";
13229
- var exec3 = promisify5(execFile5);
13265
+ var exec4 = promisify6(execFile6);
13230
13266
  async function detectComputerDriver(binary = "cua-driver") {
13231
13267
  try {
13232
- const { stdout: located } = await exec3("which", [binary], {
13268
+ const { stdout: located } = await exec4("which", [binary], {
13233
13269
  timeout: 5e3
13234
13270
  });
13235
13271
  const path = await realpath2(located.trim());
13236
- const { stdout } = await exec3(path, ["--version"], { timeout: 5e3 });
13272
+ const { stdout } = await exec4(path, ["--version"], { timeout: 5e3 });
13237
13273
  const version = stdout.trim().split("\n")[0];
13238
13274
  if (!/^cua-driver\s+0\.38\.0\b/.test(version)) return null;
13239
13275
  return {
@@ -13357,9 +13393,9 @@ async function executeDriver(driver, input, display, leaseGuard, assertLive = ()
13357
13393
  )
13358
13394
  )
13359
13395
  );
13360
- const request = (method, params) => new Promise((resolve11, reject) => {
13396
+ const request = (method, params) => new Promise((resolve12, reject) => {
13361
13397
  const n = ++id4;
13362
- pending.set(n, { resolve: resolve11, reject });
13398
+ pending.set(n, { resolve: resolve12, reject });
13363
13399
  child.stdin.write(
13364
13400
  JSON.stringify({ jsonrpc: "2.0", id: n, method, params }) + "\n"
13365
13401
  );
@@ -13460,10 +13496,10 @@ var ComputerBroker = class {
13460
13496
  })();
13461
13497
  });
13462
13498
  });
13463
- await new Promise((resolve11, reject) => {
13499
+ await new Promise((resolve12, reject) => {
13464
13500
  this.server.once("error", reject);
13465
- if (this.transport === "tcp") this.server.listen({ host: "127.0.0.1", port: 0 }, resolve11);
13466
- else this.server.listen(this.socketPath, resolve11);
13501
+ if (this.transport === "tcp") this.server.listen({ host: "127.0.0.1", port: 0 }, resolve12);
13502
+ else this.server.listen(this.socketPath, resolve12);
13467
13503
  });
13468
13504
  if (this.transport === "tcp") this.socketPath = `tcp://127.0.0.1:${this.server.address().port}`;
13469
13505
  else chmodSync3(this.socketPath, 384);
@@ -13494,7 +13530,7 @@ var ComputerBroker = class {
13494
13530
  expiresAt: this.now() + this.ttl
13495
13531
  };
13496
13532
  const digest2 = createHash7("sha256").update(JSON.stringify(request)).digest("hex");
13497
- return new Promise((resolve11, reject) => {
13533
+ return new Promise((resolve12, reject) => {
13498
13534
  const timer = setTimeout(() => {
13499
13535
  this.pending.delete(request.id);
13500
13536
  signal?.removeEventListener("abort", cancel);
@@ -13511,7 +13547,7 @@ var ComputerBroker = class {
13511
13547
  assertLive,
13512
13548
  cleanup: () => signal?.removeEventListener("abort", cancel),
13513
13549
  request: { ...request, digest: digest2 },
13514
- resolve: resolve11,
13550
+ resolve: resolve12,
13515
13551
  reject,
13516
13552
  timer
13517
13553
  });
@@ -13588,7 +13624,7 @@ var ComputerBroker = class {
13588
13624
  async close() {
13589
13625
  this.suspend();
13590
13626
  for (const socket of this.sockets) socket.destroy();
13591
- if (this.server?.listening) await new Promise((resolve11) => this.server.close(resolve11));
13627
+ if (this.server?.listening) await new Promise((resolve12) => this.server.close(resolve12));
13592
13628
  }
13593
13629
  };
13594
13630
 
@@ -13657,11 +13693,11 @@ async function pollWebComputerReviews(broker, deviceId, link, signal, intervalMs
13657
13693
  } catch {
13658
13694
  }
13659
13695
  if (signal.aborted) break;
13660
- await new Promise((resolve11) => {
13696
+ await new Promise((resolve12) => {
13661
13697
  const done = () => {
13662
13698
  clearTimeout(timer);
13663
13699
  signal.removeEventListener("abort", done);
13664
- resolve11();
13700
+ resolve12();
13665
13701
  };
13666
13702
  const timer = setTimeout(done, intervalMs);
13667
13703
  signal.addEventListener("abort", done, { once: true });
@@ -13712,6 +13748,11 @@ var Daemon = class {
13712
13748
  server = "unregistered";
13713
13749
  timer = null;
13714
13750
  tick = Promise.resolve();
13751
+ updating = false;
13752
+ claimsInFlight = 0;
13753
+ updateCheck = null;
13754
+ maintenance = null;
13755
+ updateVersion;
13715
13756
  draining = false;
13716
13757
  stopped = false;
13717
13758
  stopPromise = null;
@@ -13770,7 +13811,7 @@ var Daemon = class {
13770
13811
  if (this.options.credential)
13771
13812
  this.saveDevice({ credential: this.options.credential });
13772
13813
  this.journal = new RunJournal(paths.journal);
13773
- this.captureUploader = new CaptureUploader((runId) => join27(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join27(paths.dataDir, "capture-pending"));
13814
+ this.captureUploader = new CaptureUploader((runId) => join28(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join28(paths.dataDir, "capture-pending"));
13774
13815
  this.outbox = new Outbox(
13775
13816
  paths.outbox,
13776
13817
  this.options.link,
@@ -13787,7 +13828,7 @@ var Daemon = class {
13787
13828
  if (this.localComputerDriver && this.options.link.syncComputerReviews && this.options.link.localComputerAuthority) {
13788
13829
  this.localComputerBroker = new ComputerBroker({
13789
13830
  driver: this.localComputerDriver,
13790
- socketPath: join27(paths.dataDir, "local-computer.sock"),
13831
+ socketPath: join28(paths.dataDir, "local-computer.sock"),
13791
13832
  transport: "tcp",
13792
13833
  permitted: (runId) => {
13793
13834
  const assignment = this.journal.get(runId)?.assignment;
@@ -13829,7 +13870,7 @@ var Daemon = class {
13829
13870
  };
13830
13871
  this.cloudComputerBroker = new ComputerBroker({
13831
13872
  driver,
13832
- socketPath: join27(paths.dataDir, "computer.sock"),
13873
+ socketPath: join28(paths.dataDir, "computer.sock"),
13833
13874
  permitted: (runId) => {
13834
13875
  const entry = this.journal.get(runId);
13835
13876
  return Boolean(!this.stopped && this.registered && entry?.assignment.computer && this.supervisor?.computerRunAllowed(runId));
@@ -13952,7 +13993,7 @@ var Daemon = class {
13952
13993
  worktree,
13953
13994
  tree,
13954
13995
  github: { ...assignment.github, runToken: assignment.mcp.token, issueId: assignment.issueId },
13955
- privateDir: join27(paths.adapterState, "pids"),
13996
+ privateDir: join28(paths.adapterState, "pids"),
13956
13997
  ...hosted ? { hosted: true } : {},
13957
13998
  env: githubReceiptEnvironment()
13958
13999
  }) : publishRun({
@@ -14130,12 +14171,12 @@ var Daemon = class {
14130
14171
  /** Waits `ms`, or less if the daemon stops or the device registers. */
14131
14172
  pauseCommands(ms, signal) {
14132
14173
  if (signal.aborted) return Promise.resolve();
14133
- return new Promise((resolve11) => {
14174
+ return new Promise((resolve12) => {
14134
14175
  const done = () => {
14135
14176
  clearTimeout(timer);
14136
14177
  signal.removeEventListener("abort", done);
14137
14178
  this.wakeCommands = null;
14138
- resolve11();
14179
+ resolve12();
14139
14180
  };
14140
14181
  const timer = setTimeout(done, ms);
14141
14182
  signal.addEventListener("abort", done, { once: true });
@@ -14235,12 +14276,12 @@ var Daemon = class {
14235
14276
  const paths = runPaths(this.paths.adapterState, runId);
14236
14277
  return runVerify(sandbox, {
14237
14278
  command,
14238
- worktree: realpathSync12(worktree),
14239
- tmpRoot: join27(this.paths.adapterState, "verify", runId),
14279
+ worktree: realpathSync13(worktree),
14280
+ tmpRoot: join28(this.paths.adapterState, "verify", runId),
14240
14281
  privateDir: paths.privateDir,
14241
14282
  pidFile: paths.pidFile.replace(/\.pgid$/, ".verify.pgid"),
14242
14283
  networkAllow: repo.networkAllow,
14243
- env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join27(paths.runDir, "handoff.json") },
14284
+ env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join28(paths.runDir, "handoff.json") },
14244
14285
  timeoutMs,
14245
14286
  signal,
14246
14287
  readOnly
@@ -14352,6 +14393,8 @@ var Daemon = class {
14352
14393
  return pass;
14353
14394
  }
14354
14395
  async syncPass() {
14396
+ if (this.stopped) return;
14397
+ this.checkAutoUpdate();
14355
14398
  const { link } = this.options;
14356
14399
  const { credential, workspaceId } = this.device;
14357
14400
  if (!credential) {
@@ -14403,7 +14446,7 @@ var Daemon = class {
14403
14446
  return;
14404
14447
  }
14405
14448
  if (command && !this.device.completedDeviceCommands?.includes(command.id) && !this.device.failedDeviceCommands?.some((failure) => failure.id === command.id)) {
14406
- if (command.kind === "redetect" || this.supervisor.heartbeatRuns().length === 0) {
14449
+ if (command.kind === "redetect" || this.maintenanceIdle()) {
14407
14450
  try {
14408
14451
  if (command.kind === "redetect") {
14409
14452
  const detected = await detectHarnesses();
@@ -14414,8 +14457,13 @@ var Daemon = class {
14414
14457
  this.saveDevice({ completedDeviceCommands: [command.id], failedDeviceCommands: [] });
14415
14458
  void this.syncWithServer().catch(() => void 0);
14416
14459
  } else {
14417
- await restartService(command.kind === "update", () => {
14418
- this.saveDevice({ completedDeviceCommands: [command.id], failedDeviceCommands: [] });
14460
+ this.startMaintenance(async () => {
14461
+ await restartService(command.kind === "update", () => {
14462
+ if (this.stopped) throw new Error("Daemon stopped during update");
14463
+ this.saveDevice({ completedDeviceCommands: [command.id], failedDeviceCommands: [] });
14464
+ }, void 0, () => !this.stopped);
14465
+ }, () => {
14466
+ this.saveDevice({ completedDeviceCommands: [], failedDeviceCommands: [{ id: command.id, error: "Device command failed; check daemon service logs." }] });
14419
14467
  });
14420
14468
  }
14421
14469
  } catch {
@@ -14430,7 +14478,7 @@ var Daemon = class {
14430
14478
  this.server = "online";
14431
14479
  await this.outbox.flushAll();
14432
14480
  for (const entry of this.journal.all()) if (isTerminalRunState(entry.state)) void this.captureUploader.flush(entry.assignment.runId, true);
14433
- if (!this.draining) {
14481
+ if (!this.draining && !this.updating && !this.stopped) {
14434
14482
  await this.supervisor.resumeAll(true);
14435
14483
  this.startCoordinatorPass(deviceId);
14436
14484
  for (const runId of await link.pendingRuns(deviceId)) {
@@ -14468,6 +14516,17 @@ var Daemon = class {
14468
14516
  this.log.warn("server refused the device session; sign in again");
14469
14517
  }
14470
14518
  async claimAndStart(runId) {
14519
+ if (this.draining || this.updating || this.stopped) {
14520
+ throw new DaemonError(DAEMON_RPC_ERRORS.draining, "Daemon is draining");
14521
+ }
14522
+ this.claimsInFlight++;
14523
+ try {
14524
+ return await this.claimAndStartInternal(runId);
14525
+ } finally {
14526
+ this.claimsInFlight--;
14527
+ }
14528
+ }
14529
+ async claimAndStartInternal(runId) {
14471
14530
  if (this.draining) {
14472
14531
  throw new DaemonError(DAEMON_RPC_ERRORS.draining, "Daemon is draining");
14473
14532
  }
@@ -14501,7 +14560,7 @@ var Daemon = class {
14501
14560
  }
14502
14561
  }
14503
14562
  if (assignment.computer && (!this.cloudComputerBroker || !assignment.subscriptionBinding || assignment.computer.ownerId !== assignment.subscriptionBinding.ownerId)) throw new Error("Cloud computer runtime unavailable");
14504
- return this.supervisor.start(assignment);
14563
+ return await this.supervisor.start(assignment);
14505
14564
  }
14506
14565
  /**
14507
14566
  * A run id that could escape the daemon's dirs never reaches the
@@ -14699,7 +14758,7 @@ var Daemon = class {
14699
14758
  startCoordinatorPass(deviceId) {
14700
14759
  const link = this.options.link;
14701
14760
  const sandbox = this.agentSandbox();
14702
- if (this.nativeCoordinator || !link.claimCoordinator || !sandbox || this.stopped || !this.harnesses.some((info) => info.coordinator)) return;
14761
+ if (this.updating || this.draining || this.nativeCoordinator || !link.claimCoordinator || !sandbox || this.stopped || !this.harnesses.some((info) => info.coordinator)) return;
14703
14762
  const controller = new AbortController();
14704
14763
  this.nativeAbort = controller;
14705
14764
  this.nativeCoordinator = (async () => {
@@ -14707,7 +14766,7 @@ var Daemon = class {
14707
14766
  if (!job || controller.signal.aborted) return;
14708
14767
  await runNativeCoordinatorJob(job, {
14709
14768
  deviceId,
14710
- stateDir: join27(this.paths.dataDir, "coordinator"),
14769
+ stateDir: join28(this.paths.dataDir, "coordinator"),
14711
14770
  link,
14712
14771
  signal: controller.signal,
14713
14772
  sandbox,
@@ -14722,6 +14781,43 @@ var Daemon = class {
14722
14781
  this.nativeAbort = null;
14723
14782
  });
14724
14783
  }
14784
+ maintenanceIdle() {
14785
+ return !this.stopped && !this.draining && !this.updating && !this.nativeCoordinator && this.claimsInFlight === 0 && this.supervisor.heartbeatRuns().length === 0;
14786
+ }
14787
+ startMaintenance(work, failed = () => {
14788
+ }) {
14789
+ if (!this.maintenanceIdle()) return;
14790
+ this.updating = true;
14791
+ this.maintenance = work().catch(() => {
14792
+ this.updating = false;
14793
+ failed();
14794
+ this.log.warn("Daemon update or restart failed; check service installation and npm configuration");
14795
+ }).finally(() => {
14796
+ this.maintenance = null;
14797
+ });
14798
+ }
14799
+ checkAutoUpdate() {
14800
+ const runtime = this.options.autoUpdate;
14801
+ if (!runtime || this.draining || this.updating) return;
14802
+ if (this.updateVersion && this.maintenanceIdle()) {
14803
+ const version = this.updateVersion;
14804
+ this.updateVersion = void 0;
14805
+ this.startMaintenance(async () => {
14806
+ await runtime.install(version);
14807
+ if (this.stopped) return;
14808
+ await restartService(false, () => {
14809
+ }, void 0, () => !this.stopped);
14810
+ });
14811
+ } else if (!this.updateCheck && !this.updateVersion) {
14812
+ this.updateCheck = checkLatestVersion(join28(this.paths.dataDir, "auto-update.json"), DAEMON_VERSION, runtime).then((version) => {
14813
+ this.updateVersion = version;
14814
+ }).catch(() => {
14815
+ this.log.warn("Daemon automatic update check failed");
14816
+ }).finally(() => {
14817
+ this.updateCheck = null;
14818
+ });
14819
+ }
14820
+ }
14725
14821
  stop() {
14726
14822
  return this.stopPromise ??= this.stopInternal();
14727
14823
  }
@@ -14729,6 +14825,8 @@ var Daemon = class {
14729
14825
  this.stopped = true;
14730
14826
  this.localComputerBroker?.suspend();
14731
14827
  await this.starting?.catch(() => void 0);
14828
+ await this.updateCheck;
14829
+ await this.maintenance;
14732
14830
  this.nativeAbort?.abort();
14733
14831
  await this.nativeCoordinator;
14734
14832
  if (this.timer) clearTimeout(this.timer);