@aspectlylabs/mikka 0.0.1 → 0.0.4

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
@@ -2208,8 +2208,8 @@ var EventQueue = class {
2208
2208
  if (next.type === "exit") return;
2209
2209
  continue;
2210
2210
  }
2211
- await new Promise((resolve9) => {
2212
- this.waiter = resolve9;
2211
+ await new Promise((resolve10) => {
2212
+ this.waiter = resolve10;
2213
2213
  });
2214
2214
  }
2215
2215
  }
@@ -2280,13 +2280,13 @@ async function spawnCli(sandbox, argv, options) {
2280
2280
  stderr = (stderr + data).slice(-STDERR_TAIL * 4);
2281
2281
  });
2282
2282
  const exited = new Promise(
2283
- (resolve9) => {
2283
+ (resolve10) => {
2284
2284
  child.once("error", (error) => {
2285
2285
  stderr += `
2286
2286
  ${error.message}`;
2287
- resolve9({ code: null, signal: null });
2287
+ resolve10({ code: null, signal: null });
2288
2288
  });
2289
- child.once("exit", (code, signal) => resolve9({ code, signal }));
2289
+ child.once("exit", (code, signal) => resolve10({ code, signal }));
2290
2290
  }
2291
2291
  ).finally(() => {
2292
2292
  signalGroup(pgid, "SIGKILL");
@@ -2303,8 +2303,8 @@ ${error.message}`;
2303
2303
  let timer;
2304
2304
  await Promise.race([
2305
2305
  exited,
2306
- new Promise((resolve9) => {
2307
- timer = setTimeout(resolve9, graceMs);
2306
+ new Promise((resolve10) => {
2307
+ timer = setTimeout(resolve10, graceMs);
2308
2308
  })
2309
2309
  ]);
2310
2310
  clearTimeout(timer);
@@ -2313,17 +2313,17 @@ ${error.message}`;
2313
2313
  }
2314
2314
  };
2315
2315
  }
2316
- async function untilReady(child, step, label, ms = 12e4) {
2316
+ async function untilReady(child, step, label2, ms = 12e4) {
2317
2317
  let timer;
2318
2318
  try {
2319
2319
  return await Promise.race([
2320
2320
  step,
2321
2321
  child.exited.then(({ code, signal }) => {
2322
- throw new Error(`${label}: the CLI exited (${signal ?? code})`);
2322
+ throw new Error(`${label2}: the CLI exited (${signal ?? code})`);
2323
2323
  }),
2324
2324
  new Promise((_, reject) => {
2325
2325
  timer = setTimeout(
2326
- () => reject(new Error(`${label}: no answer after ${ms / 1e3} s`)),
2326
+ () => reject(new Error(`${label2}: no answer after ${ms / 1e3} s`)),
2327
2327
  ms
2328
2328
  );
2329
2329
  })
@@ -2385,11 +2385,11 @@ var JsonlWriter = class extends AbstractMessageWriter {
2385
2385
  }
2386
2386
  stream;
2387
2387
  write(message) {
2388
- return new Promise((resolve9, reject) => {
2388
+ return new Promise((resolve10, reject) => {
2389
2389
  this.stream.write(
2390
2390
  `${JSON.stringify(message)}
2391
2391
  `,
2392
- (error) => error ? reject(error) : resolve9()
2392
+ (error) => error ? reject(error) : resolve10()
2393
2393
  );
2394
2394
  });
2395
2395
  }
@@ -2625,13 +2625,18 @@ var runReport = z2.object({
2625
2625
  sha: z2.string().regex(/^[a-f0-9]{40}$/),
2626
2626
  readOnly: z2.literal(true)
2627
2627
  }).optional(),
2628
+ /** Preview branch created or used by the producing run; descriptive metadata only. */
2629
+ previewDatabaseBranch: z2.string().trim().min(1).max(500).optional(),
2628
2630
  /** Acceptance criteria the agent checked, with evidence. */
2629
2631
  criteria: z2.array(
2630
2632
  z2.object({
2631
2633
  criterionId: z2.uuid().optional(),
2632
2634
  text: z2.string().max(2e3).optional(),
2633
2635
  passed: z2.boolean(),
2634
- evidence: z2.string().max(1e4).optional()
2636
+ evidence: z2.string().max(1e4).optional(),
2637
+ /** Agent-reported criterion check; the daemon-owned verify remains authoritative. */
2638
+ command: z2.string().trim().min(1).max(2e3).optional(),
2639
+ exitCode: z2.number().int().nullable().optional()
2635
2640
  })
2636
2641
  ).max(200).optional(),
2637
2642
  /**
@@ -2821,7 +2826,7 @@ import { join as join2 } from "node:path";
2821
2826
  // package.json
2822
2827
  var package_default = {
2823
2828
  name: "@mikka/daemon",
2824
- version: "0.0.1",
2829
+ version: "0.0.4",
2825
2830
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
2826
2831
  type: "module",
2827
2832
  private: true,
@@ -2878,7 +2883,8 @@ var package_default = {
2878
2883
  },
2879
2884
  engines: {
2880
2885
  node: ">=24"
2881
- }
2886
+ },
2887
+ gitHead: "4c5f80747928d60ea3e03ed6a3de5ca2dc2216df"
2882
2888
  };
2883
2889
 
2884
2890
  // src/paths.ts
@@ -3837,7 +3843,7 @@ var heartbeatRunSchema = z14.object({
3837
3843
  /** Last tool call, turn boundary or file change (not raw output). */
3838
3844
  lastProgressAt: isoTime
3839
3845
  });
3840
- var deviceManagementCommand = z14.object({ id: z14.uuid(), kind: z14.enum(["redetect", "restart", "update"]) });
3846
+ var deviceManagementCommand = z14.object({ id: z14.uuid(), kind: z14.enum(["redetect", "restart", "update", "uninstall"]) });
3841
3847
  var deviceHeartbeatSchema = z14.object({
3842
3848
  completedDeviceCommands: z14.array(z14.uuid()).max(100).optional(),
3843
3849
  failedDeviceCommands: z14.array(z14.object({ id: z14.uuid(), error: z14.string().max(500) })).max(100).optional(),
@@ -5157,6 +5163,7 @@ var RunContext = class {
5157
5163
  nextStep: file.nextStep ?? null,
5158
5164
  ...file.blockedOn ? { blockedOn: file.blockedOn } : {},
5159
5165
  ...plan ? { plan } : {},
5166
+ ...typeof file.previewDatabaseBranch === "string" ? { previewDatabaseBranch: file.previewDatabaseBranch } : {},
5160
5167
  ...Array.isArray(file.criteria) ? { criteria: file.criteria } : {},
5161
5168
  ...runQuestion.safeParse(file.question).success ? { question: runQuestion.parse(file.question) } : {}
5162
5169
  };
@@ -5418,8 +5425,8 @@ async function runCodexCoordinator(input, host) {
5418
5425
  const messages = /* @__PURE__ */ new Map();
5419
5426
  let resolveEnd;
5420
5427
  let rejectEnd;
5421
- const ended = new Promise((resolve9, reject) => {
5422
- resolveEnd = resolve9;
5428
+ const ended = new Promise((resolve10, reject) => {
5429
+ resolveEnd = resolve10;
5423
5430
  rejectEnd = reject;
5424
5431
  });
5425
5432
  void ended.catch(() => void 0);
@@ -5599,10 +5606,11 @@ import {
5599
5606
  existsSync as existsSync6,
5600
5607
  mkdirSync as mkdirSync15,
5601
5608
  readFileSync as readFileSync11,
5609
+ rmSync as rmSync16,
5602
5610
  realpathSync as realpathSync11
5603
5611
  } from "node:fs";
5604
5612
  import { arch, hostname, platform as platform2 } from "node:os";
5605
- import { join as join25 } from "node:path";
5613
+ import { join as join26 } from "node:path";
5606
5614
  import { fileURLToPath as fileURLToPath3 } from "node:url";
5607
5615
 
5608
5616
  // src/adapters/claude.ts
@@ -5728,8 +5736,8 @@ function spawnRunSandbox(options) {
5728
5736
  let outcome;
5729
5737
  let hardStop;
5730
5738
  let settle;
5731
- const exited = new Promise((resolve9) => {
5732
- settle = resolve9;
5739
+ const exited = new Promise((resolve10) => {
5740
+ settle = resolve10;
5733
5741
  });
5734
5742
  function send(message) {
5735
5743
  if (!child.connected || gone) return;
@@ -6002,9 +6010,9 @@ async function createNativeSubscriptionBroker(host) {
6002
6010
  }
6003
6011
  });
6004
6012
  try {
6005
- await new Promise((resolve9, reject) => {
6013
+ await new Promise((resolve10, reject) => {
6006
6014
  server.once("error", reject);
6007
- server.listen(socket, resolve9);
6015
+ server.listen(socket, resolve10);
6008
6016
  });
6009
6017
  chmodSync(socket, 384);
6010
6018
  } catch {
@@ -6017,7 +6025,7 @@ async function createNativeSubscriptionBroker(host) {
6017
6025
  halted = true;
6018
6026
  for (const abort of pending) abort.abort();
6019
6027
  server.closeAllConnections();
6020
- await new Promise((resolve9) => server.close(() => resolve9()));
6028
+ await new Promise((resolve10) => server.close(() => resolve10()));
6021
6029
  rmSync6(dir, { recursive: true, force: true });
6022
6030
  }
6023
6031
  };
@@ -6181,8 +6189,8 @@ var PromptQueue = class {
6181
6189
  continue;
6182
6190
  }
6183
6191
  if (this.closed) return;
6184
- await new Promise((resolve9) => {
6185
- this.waiter = resolve9;
6192
+ await new Promise((resolve10) => {
6193
+ this.waiter = resolve10;
6186
6194
  });
6187
6195
  }
6188
6196
  }
@@ -6196,8 +6204,8 @@ async function untilSpoken(spoken) {
6196
6204
  try {
6197
6205
  return await Promise.race([
6198
6206
  spoken,
6199
- new Promise((resolve9) => {
6200
- timer = setTimeout(() => resolve9(true), CONTINUE_SILENCE_MS);
6207
+ new Promise((resolve10) => {
6208
+ timer = setTimeout(() => resolve10(true), CONTINUE_SILENCE_MS);
6201
6209
  })
6202
6210
  ]);
6203
6211
  } finally {
@@ -6330,9 +6338,9 @@ var ClaudeAdapter = class {
6330
6338
  let stderr = "";
6331
6339
  const stderrTail = () => stderr.slice(-STDERR_TAIL2).trim() || "no output";
6332
6340
  let spoke = () => void 0;
6333
- const spoken = new Promise((resolve9) => spoke = resolve9);
6341
+ const spoken = new Promise((resolve10) => spoke = resolve10);
6334
6342
  let finished = () => void 0;
6335
- const gone = new Promise((resolve9) => finished = resolve9);
6343
+ const gone = new Promise((resolve10) => finished = resolve10);
6336
6344
  if (externalAuth && this.options.onHostedSession) {
6337
6345
  try {
6338
6346
  await this.options.onHostedSession(sessionId);
@@ -7033,7 +7041,7 @@ var CodexAdapter = class {
7033
7041
  error: externalAuth ? SUBSCRIPTION_EXECUTION_ERROR2 : `codex app-server exited (${signal ?? code}): ${child.stderrTail() || "no output"}`
7034
7042
  });
7035
7043
  });
7036
- const ready = (step, label) => untilReady(child, step, `codex ${label}`);
7044
+ const ready = (step, label2) => untilReady(child, step, `codex ${label2}`);
7037
7045
  try {
7038
7046
  const initialized = await ready(
7039
7047
  rpc.sendRequest("initialize", {
@@ -7452,7 +7460,7 @@ var CursorAdapter = class {
7452
7460
  env: Object.entries(computerMcp.env).map(([name, value]) => ({ name, value }))
7453
7461
  }] : []
7454
7462
  ];
7455
- const ready = (step, label) => untilReady(child, step, `cursor ${label}`);
7463
+ const ready = (step, label2) => untilReady(child, step, `cursor ${label2}`);
7456
7464
  try {
7457
7465
  await ready(
7458
7466
  conn.initialize({
@@ -7669,7 +7677,7 @@ var MockAdapter = class {
7669
7677
  if (line.hang) {
7670
7678
  if (!abort.signal.aborted) {
7671
7679
  await new Promise(
7672
- (resolve9) => abort.signal.addEventListener("abort", resolve9, { once: true })
7680
+ (resolve10) => abort.signal.addEventListener("abort", resolve10, { once: true })
7673
7681
  );
7674
7682
  }
7675
7683
  yield { type: "exit", outcome: "cancelled" };
@@ -8593,7 +8601,11 @@ async function verifyExpectedOrigin(path, expected) {
8593
8601
  // src/service.ts
8594
8602
  import { execFile as execFile2 } from "node:child_process";
8595
8603
  import { promisify as promisify2 } from "node:util";
8604
+ import { mkdir, writeFile, rm } from "node:fs/promises";
8605
+ import { homedir as homedir6 } from "node:os";
8606
+ import { dirname as dirname9, join as join16, resolve as resolve7 } from "node:path";
8596
8607
  var exec = promisify2(execFile2);
8608
+ var label = "com.aspectlylabs.mikka.daemon";
8597
8609
  async function restartService(update, beforeRestart, dependencies = {
8598
8610
  manager: process.env.MIKKA_SERVICE,
8599
8611
  update: async () => {
@@ -8609,6 +8621,34 @@ async function restartService(update, beforeRestart, dependencies = {
8609
8621
  beforeRestart();
8610
8622
  dependencies.restart();
8611
8623
  }
8624
+ async function uninstallService(clearCredential, dependencies = {
8625
+ manager: process.env.MIKKA_SERVICE,
8626
+ home: homedir6(),
8627
+ uid: process.getuid?.() ?? 0,
8628
+ run: async (program, args) => {
8629
+ await exec(program, args, { timeout: 1e4 });
8630
+ },
8631
+ exit: () => {
8632
+ process.exit(0);
8633
+ }
8634
+ }) {
8635
+ try {
8636
+ if (dependencies.manager === "systemd") {
8637
+ await dependencies.run("systemctl", ["--user", "disable", "mikka-daemon.service"]);
8638
+ await rm(join16(dependencies.home, ".config/systemd/user/mikka-daemon.service"), { force: true });
8639
+ await dependencies.run("systemctl", ["--user", "daemon-reload"]);
8640
+ } else if (dependencies.manager === "launchd") {
8641
+ await rm(join16(dependencies.home, "Library/LaunchAgents", `${label}.plist`), { force: true });
8642
+ }
8643
+ } finally {
8644
+ clearCredential();
8645
+ try {
8646
+ if (dependencies.manager === "launchd") await dependencies.run("launchctl", ["bootout", `gui/${dependencies.uid}/${label}`]);
8647
+ } finally {
8648
+ dependencies.exit();
8649
+ }
8650
+ }
8651
+ }
8612
8652
 
8613
8653
  // src/device-type.ts
8614
8654
  import { readdir as readdir3, readFile } from "node:fs/promises";
@@ -8765,7 +8805,7 @@ async function detectHarnesses() {
8765
8805
  // src/lock.ts
8766
8806
  import { mkdirSync as mkdirSync11, readFileSync as readFileSync9, rmSync as rmSync10 } from "node:fs";
8767
8807
  import { createConnection } from "node:net";
8768
- import { join as join16 } from "node:path";
8808
+ import { join as join17 } from "node:path";
8769
8809
  import { setTimeout as sleep2 } from "node:timers/promises";
8770
8810
  import lockfile from "proper-lockfile";
8771
8811
  var DaemonAlreadyRunningError = class extends Error {
@@ -8780,7 +8820,7 @@ var LOCK_STALE_MS = 5 * 6e4;
8780
8820
  var LOCK_UPDATE_MS = 3e4;
8781
8821
  var LOCK_TAKEOVER_MS = 6e3;
8782
8822
  function pidFile(dataDir) {
8783
- return join16(dataDir, "daemon.pid");
8823
+ return join17(dataDir, "daemon.pid");
8784
8824
  }
8785
8825
  function holderPid(dataDir) {
8786
8826
  try {
@@ -8799,11 +8839,11 @@ function processAlive(pid) {
8799
8839
  }
8800
8840
  }
8801
8841
  function socketAnswers(socketPath) {
8802
- return new Promise((resolve9) => {
8842
+ return new Promise((resolve10) => {
8803
8843
  const socket = createConnection(socketPath);
8804
8844
  const done = (alive) => {
8805
8845
  socket.destroy();
8806
- resolve9(alive);
8846
+ resolve10(alive);
8807
8847
  };
8808
8848
  socket.once("connect", () => done(true));
8809
8849
  socket.once("error", () => done(false));
@@ -8912,7 +8952,7 @@ function closeLogger(logger) {
8912
8952
  const file = files.get(logger);
8913
8953
  if (!file) return Promise.resolve();
8914
8954
  files.delete(logger);
8915
- return new Promise((resolve9) => file.end(resolve9));
8955
+ return new Promise((resolve10) => file.end(resolve10));
8916
8956
  }
8917
8957
 
8918
8958
  // src/outbox.ts
@@ -8924,7 +8964,7 @@ import {
8924
8964
  rmSync as rmSync11,
8925
8965
  truncateSync
8926
8966
  } from "node:fs";
8927
- import { join as join17 } from "node:path";
8967
+ import { join as join18 } from "node:path";
8928
8968
  var Outbox = class {
8929
8969
  constructor(dir, link, log, retryMs = 1e3, onUndeliverable = () => void 0, retainResources = false) {
8930
8970
  this.dir = dir;
@@ -8947,10 +8987,10 @@ var Outbox = class {
8947
8987
  /** Runs whose file was checked for a torn tail since this process started. */
8948
8988
  repaired = /* @__PURE__ */ new Set();
8949
8989
  file(runId) {
8950
- return join17(this.dir, `${assertSafeId("run id", runId)}.jsonl`);
8990
+ return join18(this.dir, `${assertSafeId("run id", runId)}.jsonl`);
8951
8991
  }
8952
8992
  ackFile(runId) {
8953
- return join17(this.dir, `${assertSafeId("run id", runId)}.ack.json`);
8993
+ return join18(this.dir, `${assertSafeId("run id", runId)}.ack.json`);
8954
8994
  }
8955
8995
  parse(runId) {
8956
8996
  let data;
@@ -9134,8 +9174,8 @@ var Outbox = class {
9134
9174
  };
9135
9175
 
9136
9176
  // src/quota/local-credentials.ts
9137
- import { homedir as homedir6 } from "node:os";
9138
- import { join as join19 } from "node:path";
9177
+ import { homedir as homedir7 } from "node:os";
9178
+ import { join as join20 } from "node:path";
9139
9179
 
9140
9180
  // src/quota/files.ts
9141
9181
  import { execFile as execFile3 } from "node:child_process";
@@ -9321,17 +9361,17 @@ function claudePlanLabel(credential) {
9321
9361
  const tier = credential.rateLimitTier?.toLowerCase() ?? "";
9322
9362
  const hasMax20 = tier.includes("max_20x") || tier.includes("max20x") || tier.includes("max-20x");
9323
9363
  const hasMax = tier.includes("max");
9324
- let label = "Subscription";
9364
+ let label2 = "Subscription";
9325
9365
  if (subscriptionType === "team" || subscriptionType === "" && tier.includes("team")) {
9326
- label = hasMax ? "Team Premium" : "Team";
9366
+ label2 = hasMax ? "Team Premium" : "Team";
9327
9367
  } else if (subscriptionType === "enterprise" || subscriptionType === "" && tier.includes("enterprise")) {
9328
- label = hasMax ? "Enterprise Premium" : "Enterprise";
9368
+ label2 = hasMax ? "Enterprise Premium" : "Enterprise";
9329
9369
  } else if (subscriptionType === "max" || hasMax) {
9330
- label = hasMax20 ? "Max 20x" : "Max 5x";
9370
+ label2 = hasMax20 ? "Max 20x" : "Max 5x";
9331
9371
  } else if (subscriptionType === "pro" || tier.includes("pro")) {
9332
- label = "Pro";
9372
+ label2 = "Pro";
9333
9373
  }
9334
- return cleanText(label);
9374
+ return cleanText(label2);
9335
9375
  }
9336
9376
  function windowFrom(kind, value, model) {
9337
9377
  if (!value || typeof value !== "object") return null;
@@ -9633,12 +9673,12 @@ async function readCodexQuota(options) {
9633
9673
 
9634
9674
  // src/quota/cursor.ts
9635
9675
  import { lstat as lstat3 } from "node:fs/promises";
9636
- import { join as join18 } from "node:path";
9676
+ import { join as join19 } from "node:path";
9637
9677
  var ENDPOINT3 = "https://cursor.com/api/usage-summary";
9638
9678
  var ACCESS_TOKEN_KEY = "cursorAuth/accessToken";
9639
9679
  function cursorDatabasePath(platform3, home) {
9640
9680
  if (platform3 === "darwin") {
9641
- return join18(
9681
+ return join19(
9642
9682
  home,
9643
9683
  "Library",
9644
9684
  "Application Support",
@@ -9649,7 +9689,7 @@ function cursorDatabasePath(platform3, home) {
9649
9689
  );
9650
9690
  }
9651
9691
  if (platform3 === "win32") {
9652
- return join18(
9692
+ return join19(
9653
9693
  home,
9654
9694
  "AppData",
9655
9695
  "Roaming",
@@ -9659,7 +9699,7 @@ function cursorDatabasePath(platform3, home) {
9659
9699
  "state.vscdb"
9660
9700
  );
9661
9701
  }
9662
- return join18(home, ".config", "Cursor", "User", "globalStorage", "state.vscdb");
9702
+ return join19(home, ".config", "Cursor", "User", "globalStorage", "state.vscdb");
9663
9703
  }
9664
9704
  var CURSOR_PLANS = {
9665
9705
  pro: "Pro",
@@ -9831,10 +9871,10 @@ async function readCursorQuota(options) {
9831
9871
  // src/quota/local-credentials.ts
9832
9872
  var KEYCHAIN_SERVICE = "Claude Code-credentials";
9833
9873
  function claudeCredentialPath(home) {
9834
- return join19(home, ".claude", ".credentials.json");
9874
+ return join20(home, ".claude", ".credentials.json");
9835
9875
  }
9836
9876
  function codexAuthPath(home) {
9837
- return join19(home, ".codex", "auth.json");
9877
+ return join20(home, ".codex", "auth.json");
9838
9878
  }
9839
9879
  function unknown2(vendor, observedAt) {
9840
9880
  return {
@@ -9853,7 +9893,7 @@ var LocalCredentialsSource = class {
9853
9893
  options;
9854
9894
  id = "local_credentials";
9855
9895
  async read(signal) {
9856
- const home = this.options.home ?? homedir6();
9896
+ const home = this.options.home ?? homedir7();
9857
9897
  const platform3 = this.options.platform ?? process.platform;
9858
9898
  const fetchImpl = this.options.fetch ?? globalThis.fetch;
9859
9899
  const now = this.options.now ?? Date.now;
@@ -10029,9 +10069,9 @@ var RpcServer = class {
10029
10069
  const { socketPath } = this.options;
10030
10070
  rmSync12(socketPath, { force: true });
10031
10071
  const server = createServer2((socket) => this.accept(socket));
10032
- await new Promise((resolve9, reject) => {
10072
+ await new Promise((resolve10, reject) => {
10033
10073
  server.once("error", reject);
10034
- server.listen(socketPath, () => resolve9());
10074
+ server.listen(socketPath, () => resolve10());
10035
10075
  });
10036
10076
  chmodSync2(socketPath, 384);
10037
10077
  this.server = server;
@@ -10095,9 +10135,9 @@ var RpcServer = class {
10095
10135
  }
10096
10136
  async close() {
10097
10137
  for (const socket of this.sockets) socket.destroy();
10098
- await new Promise((resolve9) => {
10099
- if (!this.server) return resolve9();
10100
- this.server.close(() => resolve9());
10138
+ await new Promise((resolve10) => {
10139
+ if (!this.server) return resolve10();
10140
+ this.server.close(() => resolve10());
10101
10141
  });
10102
10142
  this.server = null;
10103
10143
  rmSync12(this.options.socketPath, { force: true });
@@ -10225,7 +10265,7 @@ function createRunMasker(secrets) {
10225
10265
  let pending = /* @__PURE__ */ new Map();
10226
10266
  const text3 = (value) => {
10227
10267
  let out = value;
10228
- for (const [needle, label] of needles) if (out.includes(needle)) out = out.split(needle).join(label);
10268
+ for (const [needle, label2] of needles) if (out.includes(needle)) out = out.split(needle).join(label2);
10229
10269
  return out;
10230
10270
  };
10231
10271
  const holdback = (value) => {
@@ -10323,13 +10363,13 @@ function createRunMasker(secrets) {
10323
10363
 
10324
10364
  // src/runs/supervisor.ts
10325
10365
  import { createHash as createHash3, randomUUID as randomUUID5 } from "node:crypto";
10326
- import { join as join21, resolve as resolve7 } from "node:path";
10366
+ import { join as join22, resolve as resolve8 } from "node:path";
10327
10367
  import { execa as execa11 } from "execa";
10328
10368
 
10329
10369
  // src/agents/checkpoint.ts
10330
10370
  import { mkdtempSync as mkdtempSync5, rmSync as rmSync13, writeFileSync as writeFileSync6 } from "node:fs";
10331
10371
  import { tmpdir as tmpdir2 } from "node:os";
10332
- import { join as join20 } from "node:path";
10372
+ import { join as join21 } from "node:path";
10333
10373
  import { gunzipSync as gunzipSync2, gzipSync as gzipSync2 } from "node:zlib";
10334
10374
  import { execa as execa10 } from "execa";
10335
10375
  async function headCommit(repoPath, worktree) {
@@ -10363,8 +10403,8 @@ async function takeCheckpoint(options) {
10363
10403
  }
10364
10404
  async function applyCheckpoint(options) {
10365
10405
  const git2 = await pinnedGit(options.repoPath, options.worktree);
10366
- const dir = mkdtempSync5(join20(tmpdir2(), "mikka-checkpoint-"));
10367
- const file = join20(dir, "checkpoint.patch");
10406
+ const dir = mkdtempSync5(join21(tmpdir2(), "mikka-checkpoint-"));
10407
+ const file = join21(dir, "checkpoint.patch");
10368
10408
  try {
10369
10409
  writeFileSync6(
10370
10410
  file,
@@ -10613,12 +10653,12 @@ var MemoryServer = class {
10613
10653
  this.check();
10614
10654
  let pending = this.pendingCommands(deviceId, skip);
10615
10655
  if (pending.length === 0 && waitSeconds > 0 && !signal?.aborted) {
10616
- await new Promise((resolve9) => {
10617
- const timer = setTimeout(resolve9, waitSeconds * 1e3);
10618
- signal?.addEventListener("abort", () => resolve9(), { once: true });
10656
+ await new Promise((resolve10) => {
10657
+ const timer = setTimeout(resolve10, waitSeconds * 1e3);
10658
+ signal?.addEventListener("abort", () => resolve10(), { once: true });
10619
10659
  this.wakeCommands.push(() => {
10620
10660
  clearTimeout(timer);
10621
- resolve9();
10661
+ resolve10();
10622
10662
  });
10623
10663
  });
10624
10664
  this.check();
@@ -11026,9 +11066,9 @@ var RunSupervisor = class {
11026
11066
  run2.abort.abort();
11027
11067
  }
11028
11068
  let timer;
11029
- const grace = new Promise((resolve9) => {
11069
+ const grace = new Promise((resolve10) => {
11030
11070
  timer = setTimeout(
11031
- resolve9,
11071
+ resolve10,
11032
11072
  this.deps.stopGraceMs ?? DEFAULT_STOP_GRACE_MS
11033
11073
  );
11034
11074
  });
@@ -11220,8 +11260,8 @@ var RunSupervisor = class {
11220
11260
  let timer;
11221
11261
  await Promise.race([
11222
11262
  this.deps.captures.flush(runId),
11223
- new Promise((resolve9) => {
11224
- timer = setTimeout(resolve9, 6e4);
11263
+ new Promise((resolve10) => {
11264
+ timer = setTimeout(resolve10, 6e4);
11225
11265
  })
11226
11266
  ]).finally(() => clearTimeout(timer));
11227
11267
  }
@@ -11474,7 +11514,7 @@ var RunSupervisor = class {
11474
11514
  const current = this.deps.journal.get(runId);
11475
11515
  assertMailboxRunAuthority({ held: this.active.get(runId) === run2, state: current?.state, stopped: this.stopping || run2.cancelRequested || run2.abort.signal.aborted, lease });
11476
11516
  };
11477
- const mailbox = await this.deps.prepareRunMailbox?.(assignment, run2.abort.signal, checkMailbox);
11517
+ let mailbox = await this.deps.prepareRunMailbox?.(assignment, run2.abort.signal, checkMailbox);
11478
11518
  run2.mailbox = mailbox;
11479
11519
  if (this.stopping) return;
11480
11520
  if (run2.cancelRequested) {
@@ -11484,6 +11524,14 @@ var RunSupervisor = class {
11484
11524
  if (mailbox) checkMailbox();
11485
11525
  const toolApproval = await this.deps.prepareRunToolApproval?.(assignment, run2.abort.signal, checkMailbox, worktree);
11486
11526
  run2.toolApproval = toolApproval;
11527
+ if (mailbox && toolApproval) {
11528
+ const original = mailbox;
11529
+ mailbox = { tools: original.tools, close: () => original.close(), request: async (body, signal) => {
11530
+ if (!await toolApproval.checkLive()) throw new Error("Run tool approval unavailable");
11531
+ return original.request(body, signal);
11532
+ } };
11533
+ run2.mailbox = mailbox;
11534
+ }
11487
11535
  if (this.stopping) {
11488
11536
  toolApproval?.revoke();
11489
11537
  return;
@@ -11531,7 +11579,7 @@ var RunSupervisor = class {
11531
11579
  mailbox
11532
11580
  };
11533
11581
  const resuming = entry.sessionId !== null && adapter.capabilities.supportsResume;
11534
- const inEarlierWorktree = continued !== null || entry.worktree !== null && resolve7(entry.worktree) !== resolve7(this.deps.worktrees.pathFor(runId));
11582
+ const inEarlierWorktree = continued !== null || entry.worktree !== null && resolve8(entry.worktree) !== resolve8(this.deps.worktrees.pathFor(runId));
11535
11583
  const continueSession = !resuming && assignment.resumeSessionId && assignment.continuesRunId && inEarlierWorktree && adapter.capabilities.supportsResume ? {
11536
11584
  sessionId: assignment.resumeSessionId,
11537
11585
  runId: assignment.continuesRunId,
@@ -11578,7 +11626,7 @@ var RunSupervisor = class {
11578
11626
  if (!this.deps.adapterStateDir || assignment.harness === "mock" || !session.sessionId || resuming && session.sessionId !== entry.sessionId || assignment.requireSessionResume && session.sessionId !== assignment.resumeSessionId)
11579
11627
  throw new Error("Skill mount requires the actual original harness session");
11580
11628
  verifySkillAssignment(assignment);
11581
- const file = join21(
11629
+ const file = join22(
11582
11630
  runPaths(this.deps.adapterStateDir, runId).runDir,
11583
11631
  SKILLS_DIR,
11584
11632
  skillSlug(assignment.skills[0].name),
@@ -11756,10 +11804,10 @@ function trackParts(open2, chunk) {
11756
11804
  }
11757
11805
  var ABORTED = /* @__PURE__ */ Symbol("aborted");
11758
11806
  function abortPromise(signal) {
11759
- return new Promise((resolve9) => {
11760
- if (signal.aborted) resolve9(ABORTED);
11807
+ return new Promise((resolve10) => {
11808
+ if (signal.aborted) resolve10(ABORTED);
11761
11809
  else
11762
- signal.addEventListener("abort", () => resolve9(ABORTED), { once: true });
11810
+ signal.addEventListener("abort", () => resolve10(ABORTED), { once: true });
11763
11811
  });
11764
11812
  }
11765
11813
  function pickAgentReport(agent) {
@@ -11777,18 +11825,21 @@ function pickAgentReport(agent) {
11777
11825
  const question = runQuestion.safeParse(agent.question);
11778
11826
  if (question.success) picked.question = question.data;
11779
11827
  if (agent.plan) picked.plan = agent.plan;
11828
+ if (typeof agent.previewDatabaseBranch === "string" && agent.previewDatabaseBranch.trim())
11829
+ picked.previewDatabaseBranch = agent.previewDatabaseBranch.trim().slice(0, 500);
11780
11830
  if (Array.isArray(agent.criteria)) {
11781
11831
  const criteria = [];
11782
11832
  for (const entry of agent.criteria) {
11783
11833
  if (criteria.length >= MAX_REPORTED_CRITERIA) break;
11784
11834
  if (!entry || typeof entry !== "object") continue;
11785
- const { criterionId, passed, evidence } = entry;
11835
+ const { criterionId, passed, evidence, command, exitCode } = entry;
11786
11836
  if (typeof criterionId !== "string" || !UUID_RE.test(criterionId))
11787
11837
  continue;
11788
11838
  if (typeof passed !== "boolean") continue;
11789
11839
  criteria.push({
11790
11840
  criterionId,
11791
11841
  passed,
11842
+ ...typeof command === "string" && command.trim() ? { command: command.trim().slice(0, 2e3), ...exitCode === null || typeof exitCode === "number" && Number.isSafeInteger(exitCode) ? { exitCode } : {} } : {},
11792
11843
  ...typeof evidence === "string" ? { evidence: evidence.slice(0, 1e4) } : {}
11793
11844
  });
11794
11845
  }
@@ -11848,7 +11899,7 @@ var SessionRejectedError = class extends DaemonError {
11848
11899
  // src/repositories.ts
11849
11900
  import { createHash as createHash4, randomUUID as randomUUID6 } from "node:crypto";
11850
11901
  import { existsSync as existsSync4, lstatSync as lstatSync7, mkdirSync as mkdirSync13, readdirSync as readdirSync5, realpathSync as realpathSync9, renameSync as renameSync2, rmSync as rmSync14 } from "node:fs";
11851
- import { dirname as dirname9, join as join22, resolve as resolve8 } from "node:path";
11902
+ import { dirname as dirname10, join as join23, resolve as resolve9 } from "node:path";
11852
11903
  import { setTimeout as delay2 } from "node:timers/promises";
11853
11904
  import { execa as execa12 } from "execa";
11854
11905
  import lockfile2 from "proper-lockfile";
@@ -11863,8 +11914,8 @@ var RepositoryCache = class {
11863
11914
  retainResources;
11864
11915
  pathFor(remoteUrl) {
11865
11916
  const { key: key2 } = normalizeRepository(remoteUrl, { allowFile: this.allowFile });
11866
- const path = resolve8(this.root, "v2", createHash4("sha256").update(key2).digest("hex"));
11867
- if (!isInside(resolve8(this.root), path) || path === resolve8(this.root)) throw new Error("Invalid repository cache path");
11917
+ const path = resolve9(this.root, "v2", createHash4("sha256").update(key2).digest("hex"));
11918
+ if (!isInside(resolve9(this.root), path) || path === resolve9(this.root)) throw new Error("Invalid repository cache path");
11868
11919
  return path;
11869
11920
  }
11870
11921
  /** Serialize clone/fetch against the same cache, including other processes. */
@@ -11872,7 +11923,7 @@ var RepositoryCache = class {
11872
11923
  signal?.throwIfAborted();
11873
11924
  const { remoteUrl: remote } = normalizeRepository(remoteUrl, { allowFile: this.allowFile });
11874
11925
  const path = this.pathFor(remote);
11875
- this.ensureParents(dirname9(path));
11926
+ this.ensureParents(dirname10(path));
11876
11927
  const release = await this.lock(path, signal);
11877
11928
  try {
11878
11929
  signal?.throwIfAborted();
@@ -11916,28 +11967,28 @@ var RepositoryCache = class {
11916
11967
  paths() {
11917
11968
  const visit = (path) => {
11918
11969
  if (!existsSync4(path) || lstatSync7(path).isSymbolicLink()) return [];
11919
- if (existsSync4(join22(path, ".git"))) {
11970
+ if (existsSync4(join23(path, ".git"))) {
11920
11971
  this.assertClone(path);
11921
11972
  return [path];
11922
11973
  }
11923
- return readdirSync5(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join22(path, entry.name)) : []);
11974
+ return readdirSync5(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join23(path, entry.name)) : []);
11924
11975
  };
11925
- return visit(resolve8(this.root));
11976
+ return visit(resolve9(this.root));
11926
11977
  }
11927
11978
  ensureParents(path) {
11928
11979
  mkdirSync13(this.root, { recursive: true, mode: 448 });
11929
11980
  if (lstatSync7(this.root).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
11930
11981
  const root = realpathSync9(this.root);
11931
- let current = resolve8(this.root);
11982
+ let current = resolve9(this.root);
11932
11983
  for (const part of path.slice(current.length + 1).split("/").filter(Boolean)) {
11933
- current = join22(current, part);
11984
+ current = join23(current, part);
11934
11985
  if (existsSync4(current) && lstatSync7(current).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
11935
11986
  mkdirSync13(current, { recursive: true, mode: 448 });
11936
11987
  if (!isInside(root, realpathSync9(current))) throw new Error("Repository cache escapes its directory");
11937
11988
  }
11938
11989
  }
11939
11990
  assertClone(path) {
11940
- if (lstatSync7(path).isSymbolicLink() || !lstatSync7(join22(path, ".git")).isDirectory() || lstatSync7(join22(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
11991
+ if (lstatSync7(path).isSymbolicLink() || !lstatSync7(join23(path, ".git")).isDirectory() || lstatSync7(join23(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
11941
11992
  if (!isInside(realpathSync9(this.root), realpathSync9(path))) throw new Error("Repository cache escapes its directory");
11942
11993
  }
11943
11994
  async lock(path, signal) {
@@ -11967,17 +12018,17 @@ import {
11967
12018
  rmSync as rmSync15
11968
12019
  } from "node:fs";
11969
12020
  import { createRequire } from "node:module";
11970
- import { delimiter, dirname as dirname10, join as join24 } from "node:path";
12021
+ import { delimiter, dirname as dirname11, join as join25 } from "node:path";
11971
12022
  import { fileURLToPath as fileURLToPath2 } from "node:url";
11972
12023
  import { promisify as promisify4 } from "node:util";
11973
12024
 
11974
12025
  // src/agents/public-egress.ts
11975
12026
  import { lookup } from "node:dns/promises";
11976
- import { chmod, mkdtemp, rm } from "node:fs/promises";
12027
+ import { chmod, mkdtemp, rm as rm2 } from "node:fs/promises";
11977
12028
  import { createServer as createServer3, request as httpRequest } from "node:http";
11978
12029
  import { connect, isIP as isIP3 } from "node:net";
11979
12030
  import { tmpdir as tmpdir3 } from "node:os";
11980
- import { join as join23 } from "node:path";
12031
+ import { join as join24 } from "node:path";
11981
12032
 
11982
12033
  // ../../lib/search/url-policy.ts
11983
12034
  import { BlockList, isIP as isIP2 } from "node:net";
@@ -12046,9 +12097,9 @@ function endToEndHeaders(input) {
12046
12097
  }
12047
12098
  async function startPublicEgress(options) {
12048
12099
  options.signal.throwIfAborted();
12049
- const directory = await mkdtemp(join23(tmpdir3(), "mikka-egress-"));
12100
+ const directory = await mkdtemp(join24(tmpdir3(), "mikka-egress-"));
12050
12101
  await chmod(directory, 448);
12051
- const socketPath = join23(directory, "egress.sock");
12102
+ const socketPath = join24(directory, "egress.sock");
12052
12103
  const lifetime = new AbortController();
12053
12104
  const signal = AbortSignal.any([options.signal, lifetime.signal]);
12054
12105
  const sockets = /* @__PURE__ */ new Set();
@@ -12153,9 +12204,9 @@ async function startPublicEgress(options) {
12153
12204
  if (closing) return closing;
12154
12205
  lifetime.abort();
12155
12206
  for (const socket of sockets) socket.destroy();
12156
- closing = new Promise((resolve9, reject) => server.close((error) => {
12207
+ closing = new Promise((resolve10, reject) => server.close((error) => {
12157
12208
  options.signal.removeEventListener("abort", onAbort);
12158
- void rm(directory, { recursive: true, force: true }).then(() => error && error.code !== "ERR_SERVER_NOT_RUNNING" ? reject(error) : resolve9(), reject);
12209
+ void rm2(directory, { recursive: true, force: true }).then(() => error && error.code !== "ERR_SERVER_NOT_RUNNING" ? reject(error) : resolve10(), reject);
12159
12210
  }));
12160
12211
  return closing;
12161
12212
  };
@@ -12164,11 +12215,11 @@ async function startPublicEgress(options) {
12164
12215
  };
12165
12216
  options.signal.addEventListener("abort", onAbort, { once: true });
12166
12217
  try {
12167
- await new Promise((resolve9, reject) => {
12218
+ await new Promise((resolve10, reject) => {
12168
12219
  server.once("error", reject);
12169
12220
  server.listen(socketPath, () => {
12170
12221
  server.removeListener("error", reject);
12171
- resolve9();
12222
+ resolve10();
12172
12223
  });
12173
12224
  });
12174
12225
  await chmod(socketPath, 384);
@@ -12205,7 +12256,7 @@ async function createHostedBotRunner(host) {
12205
12256
  }).catch(() => {
12206
12257
  throw unavailable2();
12207
12258
  });
12208
- const resources = join24(host.stateDir, "native-resources");
12259
+ const resources = join25(host.stateDir, "native-resources");
12209
12260
  mkdirSync14(resources, { recursive: true, mode: 448 });
12210
12261
  const removeResource = async (file, record) => {
12211
12262
  if (!/^mikka-native-(?:verify-)?[a-f0-9-]{36}$/.test(record.name) || !/^[a-f0-9-]{36}$/.test(record.nonce))
@@ -12226,7 +12277,7 @@ async function createHostedBotRunner(host) {
12226
12277
  if (record.state === "created" && /No such (?:container|object)/i.test(
12227
12278
  String(error.stderr)
12228
12279
  )) {
12229
- if (record.assets?.startsWith(join24(host.stateDir, "native-verify-git-")))
12280
+ if (record.assets?.startsWith(join25(host.stateDir, "native-verify-git-")))
12230
12281
  rmSync15(record.assets, { recursive: true, force: true });
12231
12282
  rmSync15(file, { force: true });
12232
12283
  return;
@@ -12237,13 +12288,13 @@ async function createHostedBotRunner(host) {
12237
12288
  if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id3)
12238
12289
  throw unavailable2();
12239
12290
  await exec2("docker", ["rm", "-f", id3], { env: bareEnv, timeout: 3e4 });
12240
- if (record.assets?.startsWith(join24(host.stateDir, "native-verify-git-")))
12291
+ if (record.assets?.startsWith(join25(host.stateDir, "native-verify-git-")))
12241
12292
  rmSync15(record.assets, { recursive: true, force: true });
12242
12293
  rmSync15(file, { force: true });
12243
12294
  };
12244
12295
  for (const name of readdirSync6(resources))
12245
12296
  if (name.endsWith(".json")) {
12246
- const file = join24(resources, name);
12297
+ const file = join25(resources, name);
12247
12298
  const record = readJson(file);
12248
12299
  if (!record) throw unavailable2();
12249
12300
  await removeResource(file, record);
@@ -12254,8 +12305,8 @@ async function createHostedBotRunner(host) {
12254
12305
  const bundled = createRequire(
12255
12306
  require2.resolve("@anthropic-ai/claude-agent-sdk")
12256
12307
  );
12257
- claude ??= join24(
12258
- dirname10(
12308
+ claude ??= join25(
12309
+ dirname11(
12259
12310
  bundled.resolve(
12260
12311
  "@anthropic-ai/claude-agent-sdk-linux-x64/package.json"
12261
12312
  )
@@ -12264,7 +12315,7 @@ async function createHostedBotRunner(host) {
12264
12315
  );
12265
12316
  } catch {
12266
12317
  }
12267
- const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter).map((dir) => join24(dir, "codex")).find((path) => existsSync5(path));
12318
+ const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter).map((dir) => join25(dir, "codex")).find((path) => existsSync5(path));
12268
12319
  const binaries = { codex, claude_code: claude };
12269
12320
  for (const kind of ["codex", "claude_code"])
12270
12321
  if (binaries[kind]) {
@@ -12278,12 +12329,12 @@ async function createHostedBotRunner(host) {
12278
12329
  if (!binaries.codex && !binaries.claude_code) throw unavailable2();
12279
12330
  const command = async (worktree, script, readOnly, timeoutMs, signal) => {
12280
12331
  const name = `mikka-native-verify-${randomUUID7()}`;
12281
- const file = join24(resources, name + ".json");
12332
+ const file = join25(resources, name + ".json");
12282
12333
  const resource = { name, nonce: randomUUID7(), state: "creating" };
12283
12334
  const timing = { createMs: 0, runMs: 0 };
12284
12335
  let phase = "create";
12285
12336
  let began = performance.now();
12286
- const gitCopy = mkdtempSync6(join24(host.stateDir, "native-verify-git-"));
12337
+ const gitCopy = mkdtempSync6(join25(host.stateDir, "native-verify-git-"));
12287
12338
  resource.assets = gitCopy;
12288
12339
  try {
12289
12340
  const cwd = realpathSync10(worktree);
@@ -12299,7 +12350,7 @@ async function createHostedBotRunner(host) {
12299
12350
  "--no-checkout",
12300
12351
  "--",
12301
12352
  cwd,
12302
- join24(gitCopy, "repo")
12353
+ join25(gitCopy, "repo")
12303
12354
  ],
12304
12355
  {
12305
12356
  env: {
@@ -12314,8 +12365,8 @@ async function createHostedBotRunner(host) {
12314
12365
  maxBuffer: 1024 * 1024
12315
12366
  }
12316
12367
  );
12317
- const safeGit = join24(gitCopy, "repo", ".git");
12318
- const protectedGit = lstatSync8(join24(cwd, ".git")).isFile() ? join24(cwd, ".git") : safeGit;
12368
+ const safeGit = join25(gitCopy, "repo", ".git");
12369
+ const protectedGit = lstatSync8(join25(cwd, ".git")).isFile() ? join25(cwd, ".git") : safeGit;
12319
12370
  writeJsonAtomic(file, resource);
12320
12371
  const created = await exec2(
12321
12372
  "docker",
@@ -12419,7 +12470,7 @@ async function createHostedBotRunner(host) {
12419
12470
  throw unavailable2();
12420
12471
  const name = `mikka-native-${randomUUID7()}`;
12421
12472
  const nonce = randomUUID7();
12422
- const resourceFile = join24(resources, name + ".json");
12473
+ const resourceFile = join25(resources, name + ".json");
12423
12474
  const resource = { name, nonce, state: "creating" };
12424
12475
  const lifetime = new AbortController();
12425
12476
  let closed = false;
@@ -12492,8 +12543,8 @@ async function createHostedBotRunner(host) {
12492
12543
  };
12493
12544
  const paths = runPaths(host.stateDir, assignment.runId);
12494
12545
  mkdirSync14(paths.runDir, { recursive: true, mode: 448 });
12495
- const shadow = join24(paths.runDir, "runtime-git");
12496
- const emptyHome = join24(paths.runDir, "git-bootstrap-home");
12546
+ const shadow = join25(paths.runDir, "runtime-git");
12547
+ const emptyHome = join25(paths.runDir, "git-bootstrap-home");
12497
12548
  mkdirSync14(emptyHome, { recursive: true, mode: 448 });
12498
12549
  if (!existsSync5(shadow))
12499
12550
  await exec2(
@@ -12524,9 +12575,9 @@ async function createHostedBotRunner(host) {
12524
12575
  }
12525
12576
  );
12526
12577
  await live();
12527
- if (!lstatSync8(shadow).isDirectory() || !lstatSync8(join24(shadow, ".git")).isDirectory() || !realpathSync10(shadow).startsWith(realpathSync10(paths.runDir) + "/"))
12578
+ if (!lstatSync8(shadow).isDirectory() || !lstatSync8(join25(shadow, ".git")).isDirectory() || !realpathSync10(shadow).startsWith(realpathSync10(paths.runDir) + "/"))
12528
12579
  throw unavailable2();
12529
- const ledger = join24(
12580
+ const ledger = join25(
12530
12581
  host.stateDir,
12531
12582
  "native-ledgers",
12532
12583
  assignment.runId + ".json"
@@ -12545,13 +12596,13 @@ async function createHostedBotRunner(host) {
12545
12596
  const previous = readJson(ledger);
12546
12597
  if (existsSync5(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
12547
12598
  throw unavailable2();
12548
- mkdirSync14(dirname10(ledger), { recursive: true, mode: 448 });
12599
+ mkdirSync14(dirname11(ledger), { recursive: true, mode: 448 });
12549
12600
  const record = async (sessionId) => {
12550
12601
  assertOpen();
12551
12602
  writeJsonAtomic(ledger, { scope, sessionId });
12552
12603
  };
12553
12604
  brokerStarting = createNativeSubscriptionBroker({
12554
- root: join24(host.stateDir, "native-brokers"),
12605
+ root: join25(host.stateDir, "native-brokers"),
12555
12606
  revision,
12556
12607
  check,
12557
12608
  worker: {
@@ -12592,7 +12643,7 @@ async function createHostedBotRunner(host) {
12592
12643
  }
12593
12644
  const cwd = realpathSync10(options.cwd);
12594
12645
  const runDir = realpathSync10(paths.runDir);
12595
- const protectedGit = lstatSync8(join24(cwd, ".git")).isFile() ? join24(cwd, ".git") : join24(shadow, ".git");
12646
+ const protectedGit = lstatSync8(join25(cwd, ".git")).isFile() ? join25(cwd, ".git") : join25(shadow, ".git");
12596
12647
  if (!lstatSync8(runDir).isDirectory() || !runDir.startsWith(realpathSync10(host.stateDir) + "/runs/")) {
12597
12648
  await close();
12598
12649
  throw unavailable2();
@@ -12645,7 +12696,7 @@ async function createHostedBotRunner(host) {
12645
12696
  "-v",
12646
12697
  `${MCP_SERVER_SCRIPT}:${MCP_SERVER_SCRIPT}:ro`,
12647
12698
  "-v",
12648
- `${join24(dirname10(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join24(dirname10(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
12699
+ `${join25(dirname11(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join25(dirname11(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
12649
12700
  "-v",
12650
12701
  `${readyBroker.socket}:/run/mikka-native.sock:ro`,
12651
12702
  ...computerGrant ? [
@@ -12688,13 +12739,13 @@ async function createHostedBotRunner(host) {
12688
12739
  }
12689
12740
  const spawnHosted = (config) => {
12690
12741
  assertOpen();
12691
- const home = join24(runDir, "runtime-home");
12742
+ const home = join25(runDir, "runtime-home");
12692
12743
  mkdirSync14(home, { recursive: true, mode: 448 });
12693
12744
  const env = {
12694
12745
  ...config.env,
12695
12746
  HOME: kind === "claude_code" ? config.env.HOME ?? home : home,
12696
12747
  PATH: "/usr/local/bin:/usr/bin:/bin",
12697
- GIT_DIR: join24(shadow, ".git"),
12748
+ GIT_DIR: join25(shadow, ".git"),
12698
12749
  GIT_WORK_TREE: cwd,
12699
12750
  GIT_CONFIG_GLOBAL: "/dev/null",
12700
12751
  GIT_CONFIG_SYSTEM: "/dev/null",
@@ -12727,9 +12778,9 @@ async function createHostedBotRunner(host) {
12727
12778
  signal: new AbortController().signal
12728
12779
  });
12729
12780
  child.stderr?.resume();
12730
- const exited = new Promise((resolve9) => {
12731
- child.once("exit", (code, signal) => resolve9({ code, signal }));
12732
- child.once("error", () => resolve9({ code: null, signal: null }));
12781
+ const exited = new Promise((resolve10) => {
12782
+ child.once("exit", (code, signal) => resolve10({ code, signal }));
12783
+ child.once("error", () => resolve10({ code: null, signal: null }));
12733
12784
  });
12734
12785
  return {
12735
12786
  process: child,
@@ -12988,9 +13039,9 @@ async function executeDriver(driver, input, display, leaseGuard, assertLive = ()
12988
13039
  )
12989
13040
  )
12990
13041
  );
12991
- const request = (method, params) => new Promise((resolve9, reject) => {
13042
+ const request = (method, params) => new Promise((resolve10, reject) => {
12992
13043
  const n = ++id3;
12993
- pending.set(n, { resolve: resolve9, reject });
13044
+ pending.set(n, { resolve: resolve10, reject });
12994
13045
  child.stdin.write(
12995
13046
  JSON.stringify({ jsonrpc: "2.0", id: n, method, params }) + "\n"
12996
13047
  );
@@ -13091,10 +13142,10 @@ var ComputerBroker = class {
13091
13142
  })();
13092
13143
  });
13093
13144
  });
13094
- await new Promise((resolve9, reject) => {
13145
+ await new Promise((resolve10, reject) => {
13095
13146
  this.server.once("error", reject);
13096
- if (this.transport === "tcp") this.server.listen({ host: "127.0.0.1", port: 0 }, resolve9);
13097
- else this.server.listen(this.socketPath, resolve9);
13147
+ if (this.transport === "tcp") this.server.listen({ host: "127.0.0.1", port: 0 }, resolve10);
13148
+ else this.server.listen(this.socketPath, resolve10);
13098
13149
  });
13099
13150
  if (this.transport === "tcp") this.socketPath = `tcp://127.0.0.1:${this.server.address().port}`;
13100
13151
  else chmodSync3(this.socketPath, 384);
@@ -13125,7 +13176,7 @@ var ComputerBroker = class {
13125
13176
  expiresAt: this.now() + this.ttl
13126
13177
  };
13127
13178
  const digest = createHash6("sha256").update(JSON.stringify(request)).digest("hex");
13128
- return new Promise((resolve9, reject) => {
13179
+ return new Promise((resolve10, reject) => {
13129
13180
  const timer = setTimeout(() => {
13130
13181
  this.pending.delete(request.id);
13131
13182
  signal?.removeEventListener("abort", cancel);
@@ -13142,7 +13193,7 @@ var ComputerBroker = class {
13142
13193
  assertLive,
13143
13194
  cleanup: () => signal?.removeEventListener("abort", cancel),
13144
13195
  request: { ...request, digest },
13145
- resolve: resolve9,
13196
+ resolve: resolve10,
13146
13197
  reject,
13147
13198
  timer
13148
13199
  });
@@ -13219,7 +13270,7 @@ var ComputerBroker = class {
13219
13270
  async close() {
13220
13271
  this.suspend();
13221
13272
  for (const socket of this.sockets) socket.destroy();
13222
- if (this.server?.listening) await new Promise((resolve9) => this.server.close(resolve9));
13273
+ if (this.server?.listening) await new Promise((resolve10) => this.server.close(resolve10));
13223
13274
  }
13224
13275
  };
13225
13276
 
@@ -13288,11 +13339,11 @@ async function pollWebComputerReviews(broker, deviceId, link, signal, intervalMs
13288
13339
  } catch {
13289
13340
  }
13290
13341
  if (signal.aborted) break;
13291
- await new Promise((resolve9) => {
13342
+ await new Promise((resolve10) => {
13292
13343
  const done = () => {
13293
13344
  clearTimeout(timer);
13294
13345
  signal.removeEventListener("abort", done);
13295
- resolve9();
13346
+ resolve10();
13296
13347
  };
13297
13348
  const timer = setTimeout(done, intervalMs);
13298
13349
  signal.addEventListener("abort", done, { once: true });
@@ -13401,7 +13452,7 @@ var Daemon = class {
13401
13452
  if (this.options.credential)
13402
13453
  this.saveDevice({ credential: this.options.credential });
13403
13454
  this.journal = new RunJournal(paths.journal);
13404
- this.captureUploader = new CaptureUploader((runId) => join25(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join25(paths.dataDir, "capture-pending"));
13455
+ this.captureUploader = new CaptureUploader((runId) => join26(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join26(paths.dataDir, "capture-pending"));
13405
13456
  this.outbox = new Outbox(
13406
13457
  paths.outbox,
13407
13458
  this.options.link,
@@ -13418,7 +13469,7 @@ var Daemon = class {
13418
13469
  if (this.localComputerDriver && this.options.link.syncComputerReviews && this.options.link.localComputerAuthority) {
13419
13470
  this.localComputerBroker = new ComputerBroker({
13420
13471
  driver: this.localComputerDriver,
13421
- socketPath: join25(paths.dataDir, "local-computer.sock"),
13472
+ socketPath: join26(paths.dataDir, "local-computer.sock"),
13422
13473
  transport: "tcp",
13423
13474
  permitted: (runId) => {
13424
13475
  const assignment = this.journal.get(runId)?.assignment;
@@ -13460,7 +13511,7 @@ var Daemon = class {
13460
13511
  };
13461
13512
  this.cloudComputerBroker = new ComputerBroker({
13462
13513
  driver,
13463
- socketPath: join25(paths.dataDir, "computer.sock"),
13514
+ socketPath: join26(paths.dataDir, "computer.sock"),
13464
13515
  permitted: (runId) => {
13465
13516
  const entry = this.journal.get(runId);
13466
13517
  return Boolean(!this.stopped && this.registered && entry?.assignment.computer && this.supervisor?.computerRunAllowed(runId));
@@ -13729,12 +13780,12 @@ var Daemon = class {
13729
13780
  }
13730
13781
  /** Waits `ms`, or less if the daemon stops or the device registers. */
13731
13782
  pauseCommands(ms, signal) {
13732
- return new Promise((resolve9) => {
13783
+ return new Promise((resolve10) => {
13733
13784
  const done = () => {
13734
13785
  clearTimeout(timer);
13735
13786
  signal.removeEventListener("abort", done);
13736
13787
  this.wakeCommands = null;
13737
- resolve9();
13788
+ resolve10();
13738
13789
  };
13739
13790
  const timer = setTimeout(done, ms);
13740
13791
  signal.addEventListener("abort", done, { once: true });
@@ -13835,11 +13886,11 @@ var Daemon = class {
13835
13886
  return runVerify(sandbox, {
13836
13887
  command,
13837
13888
  worktree: realpathSync11(worktree),
13838
- tmpRoot: join25(this.paths.adapterState, "verify", runId),
13889
+ tmpRoot: join26(this.paths.adapterState, "verify", runId),
13839
13890
  privateDir: paths.privateDir,
13840
13891
  pidFile: paths.pidFile.replace(/\.pgid$/, ".verify.pgid"),
13841
13892
  networkAllow: repo.networkAllow,
13842
- env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join25(paths.runDir, "handoff.json") },
13893
+ env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join26(paths.runDir, "handoff.json") },
13843
13894
  timeoutMs,
13844
13895
  signal,
13845
13896
  readOnly
@@ -13961,7 +14012,7 @@ var Daemon = class {
13961
14012
  }
13962
14013
  const deviceId = this.device.deviceId;
13963
14014
  const quotas = this.quota?.snapshot().quotas;
13964
- const { leases, revoked, cloudCredential, deviceCommands } = await link.heartbeat(deviceId, {
14015
+ const heartbeat = {
13965
14016
  completedDeviceCommands: this.device.completedDeviceCommands,
13966
14017
  failedDeviceCommands: this.device.failedDeviceCommands,
13967
14018
  harnesses: this.harnesses,
@@ -13969,7 +14020,8 @@ var Daemon = class {
13969
14020
  runs: this.supervisor.heartbeatRuns(),
13970
14021
  worktreeDiskBytes: await this.worktrees.diskUsage(),
13971
14022
  ...quotas ? { quotas } : {}
13972
- });
14023
+ };
14024
+ const { leases, revoked, cloudCredential, deviceCommands } = await link.heartbeat(deviceId, heartbeat);
13973
14025
  this.supervisor.renewLeases(leases);
13974
14026
  if (revoked) this.supervisor.revokeLeases(revoked);
13975
14027
  if (this.options.cloudComputer && cloudCredential && this.device.credential === credential) {
@@ -13978,6 +14030,26 @@ var Daemon = class {
13978
14030
  this.registered = false;
13979
14031
  }
13980
14032
  const command = deviceCommands?.[0];
14033
+ if (command?.kind === "uninstall") {
14034
+ this.draining = true;
14035
+ if (this.supervisor.heartbeatRuns().length === 0) {
14036
+ this.saveDevice({ completedDeviceCommands: [command.id], failedDeviceCommands: [] });
14037
+ try {
14038
+ await link.heartbeat(deviceId, { ...heartbeat, runs: [], completedDeviceCommands: [command.id], failedDeviceCommands: [] });
14039
+ } catch {
14040
+ this.log.warn("Could not confirm uninstall receipt");
14041
+ }
14042
+ setImmediate(() => {
14043
+ void this.stop().then(() => uninstallService(() => {
14044
+ this.saveDevice({ credential: void 0 });
14045
+ rmSync16(this.paths.secret, { force: true });
14046
+ })).catch(() => {
14047
+ this.options.onDrained?.();
14048
+ });
14049
+ });
14050
+ }
14051
+ return;
14052
+ }
13981
14053
  if (command && !this.device.completedDeviceCommands?.includes(command.id) && !this.device.failedDeviceCommands?.some((failure) => failure.id === command.id)) {
13982
14054
  if (command.kind === "redetect" || this.supervisor.heartbeatRuns().length === 0) {
13983
14055
  try {
@@ -14273,7 +14345,7 @@ var Daemon = class {
14273
14345
  if (!job || controller.signal.aborted) return;
14274
14346
  await runNativeCoordinatorJob(job, {
14275
14347
  deviceId,
14276
- stateDir: join25(this.paths.dataDir, "coordinator"),
14348
+ stateDir: join26(this.paths.dataDir, "coordinator"),
14277
14349
  link,
14278
14350
  signal: controller.signal,
14279
14351
  sandbox,