bazilion 0.20.0 → 0.21.0-beta.2

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.
Files changed (59) hide show
  1. package/dist/cli.js +430 -369
  2. package/dist/cli.js.map +1 -1
  3. package/dist/daemon.js +811 -488
  4. package/dist/daemon.js.map +1 -1
  5. package/dist/migrations/0001_init.sql +2 -1
  6. package/dist/migrations/0002_device_token_scopes.sql +8 -0
  7. package/dist/migrations/0003_web_pairing_tokens.sql +18 -0
  8. package/dist/web/client/assets/{ChatPane-CGCtAuD3.js → ChatPane--0BWZYHD.js} +1 -1
  9. package/dist/web/client/assets/{ConfirmDialog-Br19uXWH.js → ConfirmDialog-D9AiLH_Z.js} +1 -1
  10. package/dist/web/client/assets/{FieldRow-Csy3_cH5.js → FieldRow-Cd0EUpYd.js} +1 -1
  11. package/dist/web/client/assets/{ProductionTeamPolicyEditor-DG1x4Cqz.js → ProductionTeamPolicyEditor-BR5_1Wyv.js} +1 -1
  12. package/dist/web/client/assets/{ProfileCommunicationEditor-C3odNVkK.js → ProfileCommunicationEditor-K2wGbGky.js} +1 -1
  13. package/dist/web/client/assets/{ResultSourceConversation-5PFWqXTY.js → ResultSourceConversation-Y9VTd-nz.js} +1 -1
  14. package/dist/web/client/assets/{TeamTabs-BHB_COm0.js → TeamTabs-Yuc_lSZ9.js} +1 -1
  15. package/dist/web/client/assets/{TemplatesTabs-YyytjW7k.js → TemplatesTabs-Pj00chC7.js} +1 -1
  16. package/dist/web/client/assets/{UnsavedChangesGuard-CredyC3E.js → UnsavedChangesGuard-BSfJZH7E.js} +1 -1
  17. package/dist/web/client/assets/{_id-CIkPtQY0.js → _id-B4yPnTNN.js} +1 -1
  18. package/dist/web/client/assets/{_id-KXX6nuKc.js → _id-CUbb0F4l.js} +1 -1
  19. package/dist/web/client/assets/{_id-BZ_-4M4s.js → _id-D2l33vb6.js} +1 -1
  20. package/dist/web/client/assets/{_id-BLm9LVlZ.js → _id-DCFRZAJN.js} +1 -1
  21. package/dist/web/client/assets/{_id-nDbQY7f_.js → _id-UniNI3bQ.js} +1 -1
  22. package/dist/web/client/assets/{activity-BE7jG1Mz.js → activity-C5QG0Wgv.js} +1 -1
  23. package/dist/web/client/assets/{agents-S9lzXrrs.js → agents-CQo9V1lc.js} +1 -1
  24. package/dist/web/client/assets/{agents-vOPd-upn.js → agents-DVVPYxPM.js} +1 -1
  25. package/dist/web/client/assets/{approvals-BUfhlUAX.js → approvals-DQz6TJE8.js} +1 -1
  26. package/dist/web/client/assets/{attention-C3r-2GSp.js → attention-BtCLaWhZ.js} +1 -1
  27. package/dist/web/client/assets/chevron-right-BGFokHDA.js +1 -0
  28. package/dist/web/client/assets/{config-AL_EM57n.js → config-DuhKvD0X.js} +1 -1
  29. package/dist/web/client/assets/{inbox-LlCpJrMH.js → inbox-Cr7iGkrF.js} +1 -1
  30. package/dist/web/client/assets/{index-CwMw0pnV.js → index-ChXVa4eb.js} +2 -2
  31. package/dist/web/client/assets/{learning-zvTJ_9vM.js → learning-5eO_SZUP.js} +1 -1
  32. package/dist/web/client/assets/{login-BpQ54z8Y.js → login-Cn9mf44C.js} +1 -1
  33. package/dist/web/client/assets/{mcp-BD6VzXg_.js → mcp-0COajQD4.js} +1 -1
  34. package/dist/web/client/assets/{members-SEDi8SFo.js → members-9eTmy1QM.js} +1 -1
  35. package/dist/web/client/assets/{memory-zi_dPlMA.js → memory-CExQd_vP.js} +1 -1
  36. package/dist/web/client/assets/{policy-URjQAAdN.js → policy-B-zDlt_G.js} +1 -1
  37. package/dist/web/client/assets/{results-Bcuy4Flp.js → results-BUmKkuHo.js} +1 -1
  38. package/dist/web/client/assets/{review-CVH7X9-d.js → review-BUTz_zRX.js} +1 -1
  39. package/dist/web/client/assets/{routes-BJEX6yAE.js → routes-b1FscQsH.js} +1 -1
  40. package/dist/web/client/assets/{services-BTG4F5FL.js → services-D-RdMc8g.js} +1 -1
  41. package/dist/web/client/assets/{skills-DwiHS7eD.js → skills-CNbkY2ji.js} +1 -1
  42. package/dist/web/client/assets/{teams-DfpwQu1i.js → teams-Dn9o_-P-.js} +1 -1
  43. package/dist/web/client/assets/{teams-DcROmSGB.js → teams-H4OTWt8E.js} +1 -1
  44. package/dist/web/client/assets/{telegram-BLyaaUXE.js → telegram-BnM54CPN.js} +1 -1
  45. package/dist/web/client/assets/tokens-C-I23fVZ.js +1 -0
  46. package/dist/web/client/assets/{triggers-CtVhrAGA.js → triggers-DG9YoC7B.js} +1 -1
  47. package/dist/web/client/assets/{verifications-TC0ccGLY.js → verifications-CzToBSUN.js} +1 -1
  48. package/dist/web/client/assets/{welcome-DML3X1ha.js → welcome-REp-dEfY.js} +1 -1
  49. package/dist/web/client/assets/{x-D8yuCam7.js → x-C-BpLdcp.js} +1 -1
  50. package/dist/web/server/assets/{_tanstack-start-manifest_v-BGSoO6CK.js → _tanstack-start-manifest_v-BfURdqEL.js} +82 -82
  51. package/dist/web/server/assets/{router-BVhdWkwP.js → router-CyZ-GH8M.js} +1 -1
  52. package/dist/web/server/assets/{tokens-_2hptHP6.js → tokens-BFhrz5qd.js} +1 -1
  53. package/dist/web/server/assets/{tokens-DDwtO15P.js → tokens-DO_eDpv_.js} +96 -3
  54. package/dist/web/server/server.js +2 -2
  55. package/dist/worker.js +127 -90
  56. package/dist/worker.js.map +1 -1
  57. package/package.json +3 -3
  58. package/dist/web/client/assets/chevron-right-C7P3Z105.js +0 -1
  59. package/dist/web/client/assets/tokens-Dp9Vwvfx.js +0 -1
package/dist/daemon.js CHANGED
@@ -135,12 +135,12 @@ var require_isexe = __commonJS({
135
135
  if (typeof Promise !== "function") {
136
136
  throw new TypeError("callback not provided");
137
137
  }
138
- return new Promise(function(resolve8, reject2) {
138
+ return new Promise(function(resolve9, reject2) {
139
139
  isexe(path, options || {}, function(er, is) {
140
140
  if (er) {
141
141
  reject2(er);
142
142
  } else {
143
- resolve8(is);
143
+ resolve9(is);
144
144
  }
145
145
  });
146
146
  });
@@ -207,27 +207,27 @@ var require_which = __commonJS({
207
207
  opt = {};
208
208
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
209
209
  const found = [];
210
- const step = (i) => new Promise((resolve8, reject2) => {
210
+ const step = (i) => new Promise((resolve9, reject2) => {
211
211
  if (i === pathEnv.length)
212
- return opt.all && found.length ? resolve8(found) : reject2(getNotFoundError(cmd));
212
+ return opt.all && found.length ? resolve9(found) : reject2(getNotFoundError(cmd));
213
213
  const ppRaw = pathEnv[i];
214
214
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
215
215
  const pCmd = path.join(pathPart, cmd);
216
216
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
217
- resolve8(subStep(p, i, 0));
217
+ resolve9(subStep(p, i, 0));
218
218
  });
219
- const subStep = (p, i, ii) => new Promise((resolve8, reject2) => {
219
+ const subStep = (p, i, ii) => new Promise((resolve9, reject2) => {
220
220
  if (ii === pathExt.length)
221
- return resolve8(step(i + 1));
221
+ return resolve9(step(i + 1));
222
222
  const ext = pathExt[ii];
223
223
  isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
224
224
  if (!er && is) {
225
225
  if (opt.all)
226
226
  found.push(p + ext);
227
227
  else
228
- return resolve8(p + ext);
228
+ return resolve9(p + ext);
229
229
  }
230
- return resolve8(subStep(p, i, ii + 1));
230
+ return resolve9(subStep(p, i, ii + 1));
231
231
  });
232
232
  });
233
233
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -7796,7 +7796,7 @@ var init_stdio2 = __esm({
7796
7796
  if (this._process) {
7797
7797
  throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
7798
7798
  }
7799
- return new Promise((resolve8, reject2) => {
7799
+ return new Promise((resolve9, reject2) => {
7800
7800
  this._process = (0, import_cross_spawn.default)(this._serverParams.command, this._serverParams.args ?? [], {
7801
7801
  // merge default env with server env because mcp server needs some env vars
7802
7802
  env: {
@@ -7813,7 +7813,7 @@ var init_stdio2 = __esm({
7813
7813
  this.onerror?.(error2);
7814
7814
  });
7815
7815
  this._process.on("spawn", () => {
7816
- resolve8();
7816
+ resolve9();
7817
7817
  });
7818
7818
  this._process.on("close", (_code) => {
7819
7819
  this._process = void 0;
@@ -7872,22 +7872,22 @@ var init_stdio2 = __esm({
7872
7872
  if (this._process) {
7873
7873
  const processToClose = this._process;
7874
7874
  this._process = void 0;
7875
- const closePromise = new Promise((resolve8) => {
7875
+ const closePromise = new Promise((resolve9) => {
7876
7876
  processToClose.once("close", () => {
7877
- resolve8();
7877
+ resolve9();
7878
7878
  });
7879
7879
  });
7880
7880
  try {
7881
7881
  processToClose.stdin?.end();
7882
7882
  } catch {
7883
7883
  }
7884
- await Promise.race([closePromise, new Promise((resolve8) => setTimeout(resolve8, 2e3).unref())]);
7884
+ await Promise.race([closePromise, new Promise((resolve9) => setTimeout(resolve9, 2e3).unref())]);
7885
7885
  if (processToClose.exitCode === null) {
7886
7886
  try {
7887
7887
  processToClose.kill("SIGTERM");
7888
7888
  } catch {
7889
7889
  }
7890
- await Promise.race([closePromise, new Promise((resolve8) => setTimeout(resolve8, 2e3).unref())]);
7890
+ await Promise.race([closePromise, new Promise((resolve9) => setTimeout(resolve9, 2e3).unref())]);
7891
7891
  }
7892
7892
  if (processToClose.exitCode === null) {
7893
7893
  try {
@@ -7899,15 +7899,15 @@ var init_stdio2 = __esm({
7899
7899
  this._readBuffer.clear();
7900
7900
  }
7901
7901
  send(message) {
7902
- return new Promise((resolve8) => {
7902
+ return new Promise((resolve9) => {
7903
7903
  if (!this._process?.stdin) {
7904
7904
  throw new Error("Not connected");
7905
7905
  }
7906
7906
  const json = serializeMessage(message);
7907
7907
  if (this._process.stdin.write(json)) {
7908
- resolve8();
7908
+ resolve9();
7909
7909
  } else {
7910
- this._process.stdin.once("drain", resolve8);
7910
+ this._process.stdin.once("drain", resolve9);
7911
7911
  }
7912
7912
  });
7913
7913
  }
@@ -7956,8 +7956,8 @@ async function random(size) {
7956
7956
  const evenDistCutoff = Math.pow(2, 8) - Math.pow(2, 8) % mask2.length;
7957
7957
  let result = "";
7958
7958
  while (result.length < size) {
7959
- const randomBytes6 = await getRandomValues(size - result.length);
7960
- for (const randomByte of randomBytes6) {
7959
+ const randomBytes7 = await getRandomValues(size - result.length);
7960
+ for (const randomByte of randomBytes7) {
7961
7961
  if (randomByte < evenDistCutoff) {
7962
7962
  result += mask2[randomByte % mask2.length];
7963
7963
  }
@@ -9803,7 +9803,7 @@ var init_sse = __esm({
9803
9803
  }
9804
9804
  _startOrAuth() {
9805
9805
  const fetchImpl = this?._eventSourceInit?.fetch ?? this._fetch ?? fetch;
9806
- return new Promise((resolve8, reject2) => {
9806
+ return new Promise((resolve9, reject2) => {
9807
9807
  this._eventSource = new EventSource(this._url.href, {
9808
9808
  ...this._eventSourceInit,
9809
9809
  fetch: async (url2, init) => {
@@ -9824,7 +9824,7 @@ var init_sse = __esm({
9824
9824
  this._abortController = new AbortController();
9825
9825
  this._eventSource.onerror = (event2) => {
9826
9826
  if (event2.code === 401 && this._authProvider) {
9827
- this._authThenStart().then(resolve8, reject2);
9827
+ this._authThenStart().then(resolve9, reject2);
9828
9828
  return;
9829
9829
  }
9830
9830
  const error2 = new SseError(event2.code, event2.message, event2);
@@ -9846,7 +9846,7 @@ var init_sse = __esm({
9846
9846
  void this.close();
9847
9847
  return;
9848
9848
  }
9849
- resolve8();
9849
+ resolve9();
9850
9850
  });
9851
9851
  this._eventSource.onmessage = (event2) => {
9852
9852
  const messageEvent = event2;
@@ -11016,7 +11016,7 @@ var init_protocol = __esm({
11016
11016
  return;
11017
11017
  }
11018
11018
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
11019
- await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
11019
+ await new Promise((resolve9) => setTimeout(resolve9, pollInterval));
11020
11020
  options?.signal?.throwIfAborted();
11021
11021
  }
11022
11022
  } catch (error2) {
@@ -11033,7 +11033,7 @@ var init_protocol = __esm({
11033
11033
  */
11034
11034
  request(request2, resultSchema, options) {
11035
11035
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
11036
- return new Promise((resolve8, reject2) => {
11036
+ return new Promise((resolve9, reject2) => {
11037
11037
  const earlyReject = (error2) => {
11038
11038
  reject2(error2);
11039
11039
  };
@@ -11111,7 +11111,7 @@ var init_protocol = __esm({
11111
11111
  if (!parseResult.success) {
11112
11112
  reject2(parseResult.error);
11113
11113
  } else {
11114
- resolve8(parseResult.data);
11114
+ resolve9(parseResult.data);
11115
11115
  }
11116
11116
  } catch (error2) {
11117
11117
  reject2(error2);
@@ -11372,12 +11372,12 @@ var init_protocol = __esm({
11372
11372
  }
11373
11373
  } catch {
11374
11374
  }
11375
- return new Promise((resolve8, reject2) => {
11375
+ return new Promise((resolve9, reject2) => {
11376
11376
  if (signal.aborted) {
11377
11377
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
11378
11378
  return;
11379
11379
  }
11380
- const timeoutId = setTimeout(resolve8, interval);
11380
+ const timeoutId = setTimeout(resolve9, interval);
11381
11381
  signal.addEventListener("abort", () => {
11382
11382
  clearTimeout(timeoutId);
11383
11383
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -14404,7 +14404,7 @@ var require_compile = __commonJS({
14404
14404
  const schOrFunc = root.refs[ref];
14405
14405
  if (schOrFunc)
14406
14406
  return schOrFunc;
14407
- let _sch = resolve8.call(this, root, ref);
14407
+ let _sch = resolve9.call(this, root, ref);
14408
14408
  if (_sch === void 0) {
14409
14409
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
14410
14410
  const { schemaId } = this.opts;
@@ -14431,7 +14431,7 @@ var require_compile = __commonJS({
14431
14431
  function sameSchemaEnv(s1, s2) {
14432
14432
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
14433
14433
  }
14434
- function resolve8(root, ref) {
14434
+ function resolve9(root, ref) {
14435
14435
  let sch;
14436
14436
  while (typeof (sch = this.refs[ref]) == "string")
14437
14437
  ref = sch;
@@ -15062,7 +15062,7 @@ var require_fast_uri = __commonJS({
15062
15062
  }
15063
15063
  return uri;
15064
15064
  }
15065
- function resolve8(baseURI, relativeURI, options) {
15065
+ function resolve9(baseURI, relativeURI, options) {
15066
15066
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
15067
15067
  const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
15068
15068
  schemelessOptions.skipEscape = true;
@@ -15320,7 +15320,7 @@ var require_fast_uri = __commonJS({
15320
15320
  var fastUri = {
15321
15321
  SCHEMES,
15322
15322
  normalize: normalize4,
15323
- resolve: resolve8,
15323
+ resolve: resolve9,
15324
15324
  resolveComponent,
15325
15325
  equal,
15326
15326
  serialize,
@@ -18283,8 +18283,8 @@ var require_dist = __commonJS({
18283
18283
  return ajv;
18284
18284
  }
18285
18285
  const [formats, exportName] = opts.mode === "fast" ? [formats_1.fastFormats, fastName] : [formats_1.fullFormats, fullName];
18286
- const list16 = opts.formats || formats_1.formatNames;
18287
- addFormats(ajv, list16, formats, exportName);
18286
+ const list17 = opts.formats || formats_1.formatNames;
18287
+ addFormats(ajv, list17, formats, exportName);
18288
18288
  if (opts.keywords)
18289
18289
  (0, limit_1.default)(ajv);
18290
18290
  return ajv;
@@ -18296,11 +18296,11 @@ var require_dist = __commonJS({
18296
18296
  throw new Error(`Unknown format "${name}"`);
18297
18297
  return f;
18298
18298
  };
18299
- function addFormats(ajv, list16, fs, exportName) {
18299
+ function addFormats(ajv, list17, fs, exportName) {
18300
18300
  var _a3;
18301
18301
  var _b;
18302
18302
  (_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
18303
- for (const f of list16)
18303
+ for (const f of list17)
18304
18304
  ajv.addFormat(f, fs[f]);
18305
18305
  }
18306
18306
  module.exports = exports = formatsPlugin;
@@ -20988,6 +20988,7 @@ function inTx(db, fn) {
20988
20988
  // ../daemon/src/core/db/migrate.ts
20989
20989
  import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "fs";
20990
20990
  import { dirname, join as join8 } from "path";
20991
+ import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
20991
20992
  import { fileURLToPath } from "url";
20992
20993
  var migrationsDir = join8(dirname(fileURLToPath(import.meta.url)), "migrations");
20993
20994
  var schemaMigrationsSql = `
@@ -20996,23 +20997,28 @@ var schemaMigrationsSql = `
20996
20997
  applied_at INTEGER NOT NULL
20997
20998
  )
20998
20999
  `;
20999
- var INCOMPATIBLE_DATABASE_MESSAGE = "Bazilion cannot start because this home uses an incompatible alpha database schema. Preserve the entire Bazilion home directory as a filesystem backup first, keeping bazilion.db and auth.json together. Then perform the reset with `bazilion uninstall --yes` (from the repository root of a source checkout: `pnpm tsx apps/cli/src/index.ts uninstall --yes`) and start Bazilion again. Use `--all` only if you also want to remove logs and installed skills.";
21000
+ var INCOMPATIBLE_DATABASE_MESSAGE = "Bazilion cannot start because this home uses an incompatible database schema. Preserve the entire Bazilion home directory as a filesystem backup first, keeping bazilion.db and auth.json together. Then perform the reset with `bazilion uninstall --yes` (from the repository root of a source checkout: `pnpm tsx apps/cli/src/index.ts uninstall --yes`) and start Bazilion again. Use `--all` only if you also want to remove logs and installed skills.";
21000
21001
  var IncompatibleDatabaseError = class extends Error {
21001
21002
  constructor() {
21002
21003
  super(INCOMPATIBLE_DATABASE_MESSAGE);
21003
21004
  this.name = "IncompatibleDatabaseError";
21004
21005
  }
21005
21006
  };
21006
- var canonicalSchemaObjects = null;
21007
- function migrationFiles() {
21007
+ var DatabaseNewerThanBinaryError = class extends Error {
21008
+ constructor(dbVersion, supportedVersion) {
21009
+ super(
21010
+ `Bazilion cannot start because this home was written by a newer version: its database schema version (${dbVersion}) is newer than this binary supports (${supportedVersion}). Upgrade Bazilion to a release that supports this schema. Downgrades are unsupported; if you must run an older release, restore a pre-upgrade snapshot instead.`
21011
+ );
21012
+ this.name = "DatabaseNewerThanBinaryError";
21013
+ }
21014
+ };
21015
+ function listMigrations() {
21008
21016
  return readdirSync2(migrationsDir).filter((file) => file.endsWith(".sql")).sort().map((file) => ({
21009
21017
  version: file.replace(/\.sql$/, ""),
21010
21018
  sql: readFileSync5(join8(migrationsDir, file), "utf8")
21011
21019
  }));
21012
21020
  }
21013
- function normalizeSql(sql) {
21014
- return sql.replace(/\s+/g, " ").trim();
21015
- }
21021
+ var canonicalSchemaObjectsByPrefix = /* @__PURE__ */ new Map();
21016
21022
  function schemaObjects(db) {
21017
21023
  return db.raw.query(
21018
21024
  `SELECT type, name, tbl_name, sql
@@ -21024,46 +21030,61 @@ function schemaObjects(db) {
21024
21030
  function schemaPayload(rows) {
21025
21031
  return rows.map((row2) => [row2.type, row2.name, row2.tbl_name, normalizeSql(row2.sql)].join("\0")).join("\n");
21026
21032
  }
21027
- function expectedSchema(files) {
21028
- if (canonicalSchemaObjects !== null) return canonicalSchemaObjects;
21033
+ function normalizeSql(sql) {
21034
+ return sql.replace(/\s+/g, " ").trim();
21035
+ }
21036
+ function expectedSchema(files, prefixLength) {
21037
+ const cached2 = canonicalSchemaObjectsByPrefix.get(prefixLength);
21038
+ if (cached2) return cached2;
21029
21039
  const canonical = openInMemoryDb();
21030
21040
  try {
21031
21041
  canonical.raw.exec(schemaMigrationsSql);
21032
- for (const file of files) canonical.raw.exec(file.sql);
21033
- canonicalSchemaObjects = schemaObjects(canonical);
21034
- return canonicalSchemaObjects;
21042
+ for (const file of files.slice(0, prefixLength)) canonical.raw.exec(file.sql);
21043
+ const objects = schemaObjects(canonical);
21044
+ canonicalSchemaObjectsByPrefix.set(prefixLength, objects);
21045
+ return objects;
21035
21046
  } finally {
21036
21047
  canonical.close();
21037
21048
  }
21038
21049
  }
21039
21050
  function assertMigrationCompatibility(db) {
21040
- const files = migrationFiles();
21051
+ const files = listMigrations();
21041
21052
  const expectedVersions = files.map((file) => file.version);
21053
+ const dbUserVersion = userVersion(db);
21054
+ if (dbUserVersion > files.length) {
21055
+ throw new DatabaseNewerThanBinaryError(dbUserVersion, files.length);
21056
+ }
21042
21057
  let appliedVersions;
21043
21058
  try {
21044
21059
  appliedVersions = db.raw.query("SELECT version FROM schema_migrations ORDER BY version").all().map((row2) => row2.version);
21045
21060
  } catch {
21046
21061
  throw new IncompatibleDatabaseError();
21047
21062
  }
21048
- const actualObjects = schemaObjects(db);
21049
- const expectedObjects = expectedSchema(files);
21050
21063
  if (appliedVersions.length === 0) {
21051
- const migrationTable = actualObjects.filter(
21064
+ const actualObjects2 = schemaObjects(db);
21065
+ const migrationTable = actualObjects2.filter(
21052
21066
  (row2) => row2.type === "table" && row2.name === "schema_migrations"
21053
21067
  );
21054
- const expectedMigrationTable = expectedObjects.filter(
21068
+ const expectedMigrationTable = expectedSchema(files, 0).filter(
21055
21069
  (row2) => row2.type === "table" && row2.name === "schema_migrations"
21056
21070
  );
21057
- if (actualObjects.length !== 1 || migrationTable.length !== 1 || schemaPayload(migrationTable) !== schemaPayload(expectedMigrationTable)) {
21071
+ if (actualObjects2.length !== 1 || migrationTable.length !== 1 || schemaPayload(migrationTable) !== schemaPayload(expectedMigrationTable)) {
21058
21072
  throw new IncompatibleDatabaseError();
21059
21073
  }
21060
21074
  return;
21061
21075
  }
21062
- if (appliedVersions.length !== expectedVersions.length || appliedVersions.some((version2, index) => version2 !== expectedVersions[index]) || schemaPayload(actualObjects) !== schemaPayload(expectedObjects)) {
21076
+ const expectedSet = new Set(expectedVersions);
21077
+ const isPrefix = appliedVersions.every((version2) => expectedSet.has(version2)) && appliedVersions.length <= expectedVersions.length && appliedVersions.every((version2, index) => version2 === expectedVersions[index]);
21078
+ if (!isPrefix) {
21079
+ throw new IncompatibleDatabaseError();
21080
+ }
21081
+ const actualObjects = schemaObjects(db);
21082
+ const expectedObjects = expectedSchema(files, appliedVersions.length);
21083
+ if (schemaPayload(actualObjects) !== schemaPayload(expectedObjects)) {
21063
21084
  throw new IncompatibleDatabaseError();
21064
21085
  }
21065
21086
  }
21066
- function runMigrations(db) {
21087
+ function runMigrations(db, options = {}) {
21067
21088
  const existingObjects = schemaObjects(db);
21068
21089
  if (existingObjects.length > 0 && !existingObjects.some((row2) => row2.type === "table" && row2.name === "schema_migrations")) {
21069
21090
  throw new IncompatibleDatabaseError();
@@ -21073,8 +21094,13 @@ function runMigrations(db) {
21073
21094
  const applied = new Set(
21074
21095
  db.raw.query("SELECT version FROM schema_migrations").all().map((r) => r.version)
21075
21096
  );
21076
- for (const file of migrationFiles()) {
21077
- if (applied.has(file.version)) continue;
21097
+ const files = listMigrations();
21098
+ const pending = files.filter((file) => !applied.has(file.version));
21099
+ if (pending.length > 0 && applied.size > 0 && options.preMigrationSnapshotPath !== void 0) {
21100
+ db.raw.exec(`VACUUM INTO '${options.preMigrationSnapshotPath.replaceAll("'", "''")}'`);
21101
+ verifySnapshot(options.preMigrationSnapshotPath);
21102
+ }
21103
+ for (const file of pending) {
21078
21104
  const tx = db.raw.transaction(() => {
21079
21105
  db.raw.exec(file.sql);
21080
21106
  db.raw.run("INSERT INTO schema_migrations (version, applied_at) VALUES (?, ?)", [
@@ -21084,14 +21110,38 @@ function runMigrations(db) {
21084
21110
  });
21085
21111
  tx();
21086
21112
  }
21113
+ if (userVersion(db) < files.length) {
21114
+ db.raw.exec(`PRAGMA user_version = ${files.length}`);
21115
+ }
21087
21116
  assertMigrationCompatibility(db);
21088
21117
  }
21118
+ function userVersion(db) {
21119
+ const row2 = db.raw.query("PRAGMA user_version").all()[0];
21120
+ const value = row2?.user_version;
21121
+ return typeof value === "number" ? value : Number(value ?? 0);
21122
+ }
21123
+ function verifySnapshot(path) {
21124
+ const snapshot = new DatabaseSync2(path);
21125
+ try {
21126
+ const row2 = snapshot.prepare("PRAGMA integrity_check").get();
21127
+ if (row2.integrity_check !== "ok") {
21128
+ throw new Error(
21129
+ `Pre-migration snapshot failed integrity check: ${String(row2.integrity_check)}`
21130
+ );
21131
+ }
21132
+ } finally {
21133
+ snapshot.close();
21134
+ }
21135
+ }
21089
21136
 
21090
21137
  // ../daemon/src/core/paths.ts
21138
+ import { realpathSync } from "fs";
21091
21139
  import { homedir } from "os";
21092
- import { join as join9 } from "path";
21140
+ import { basename, dirname as dirname2, join as join9, resolve as resolve2 } from "path";
21093
21141
  function resolvePaths(home) {
21094
- const root = home ?? process.env.BAZILION_HOME ?? join9(homedir(), ".bazilion");
21142
+ const root = canonicalHome(
21143
+ resolve2(home ?? process.env.BAZILION_HOME ?? join9(homedir(), ".bazilion"))
21144
+ );
21095
21145
  return {
21096
21146
  home: root,
21097
21147
  db: join9(root, "bazilion.db"),
@@ -21115,6 +21165,22 @@ function resolvePaths(home) {
21115
21165
  }
21116
21166
  };
21117
21167
  }
21168
+ function canonicalHome(root) {
21169
+ let resolved = root;
21170
+ const unresolvedTail = [];
21171
+ while (true) {
21172
+ try {
21173
+ resolved = realpathSync(resolved);
21174
+ break;
21175
+ } catch {
21176
+ const parent = dirname2(resolved);
21177
+ if (parent === resolved) break;
21178
+ unresolvedTail.unshift(basename(resolved));
21179
+ resolved = parent;
21180
+ }
21181
+ }
21182
+ return join9(resolved, ...unresolvedTail);
21183
+ }
21118
21184
 
21119
21185
  // ../daemon/src/core/profile/delete.ts
21120
21186
  import { existsSync as existsSync6, rmSync as rmSync4 } from "fs";
@@ -23606,60 +23672,197 @@ function remove8(db, id) {
23606
23672
  db.raw.run("DELETE FROM agent_triggers WHERE id = ?", [id]);
23607
23673
  }
23608
23674
 
23675
+ // ../daemon/src/core/repos/webPairingTokens.ts
23676
+ var webPairingTokens_exports = {};
23677
+ __export(webPairingTokens_exports, {
23678
+ PAIRING_TOKEN_TTL_MS: () => PAIRING_TOKEN_TTL_MS,
23679
+ completeExchange: () => completeExchange,
23680
+ create: () => create2,
23681
+ exchange: () => exchange,
23682
+ list: () => list9
23683
+ });
23684
+ import { createHash as createHash3, randomBytes as randomBytes3, randomUUID as randomUUID11 } from "crypto";
23685
+
23686
+ // ../../packages/api-types/src/entities.ts
23687
+ var REASONING_LEVELS = [
23688
+ "off",
23689
+ "minimal",
23690
+ "low",
23691
+ "medium",
23692
+ "high",
23693
+ "xhigh"
23694
+ ];
23695
+ var DEVICE_TOKEN_SCOPES = ["read", "write", "approvals", "admin"];
23696
+ var ALL_DEVICE_TOKEN_SCOPES = DEVICE_TOKEN_SCOPES;
23697
+
23698
+ // ../../packages/api-types/src/git-review.ts
23699
+ var REVIEW_LIMITS = {
23700
+ files: 1e3,
23701
+ fileBytes: 1024 * 1024,
23702
+ totalBytes: 16 * 1024 * 1024,
23703
+ patchBytes: 256 * 1024
23704
+ };
23705
+
23706
+ // ../../packages/api-types/src/publication.ts
23707
+ var PUBLICATION_LIMITS = {
23708
+ repository: 200,
23709
+ branch: 200,
23710
+ commitMessage: 2e3,
23711
+ refusalDetail: 400,
23712
+ error: 400,
23713
+ /** Branches that are never published to, whatever the host says. */
23714
+ protectedBranches: ["main", "master", "trunk", "develop", "release"]
23715
+ };
23716
+
23717
+ // ../../packages/api-types/src/verification.ts
23718
+ var VERIFICATION_OUTCOME_LIMITS = [
23719
+ "Facts above are executor-owned. A non-zero exit is a result about the commands that ran, never proof about later code, and this is not an approval to publish, merge or deploy.",
23720
+ "Declared output paths are not enforced, so a change they do not cover appears above rather than being prevented."
23721
+ ];
23722
+
23723
+ // ../../packages/api-types/src/index.ts
23724
+ var PROFILE_FILES = [
23725
+ "profile.json",
23726
+ "SOUL.md",
23727
+ "IDENTITY.md",
23728
+ "BOOTSTRAP.md",
23729
+ "AGENTS.md",
23730
+ "TOOLS.md"
23731
+ ];
23732
+
23733
+ // ../daemon/src/core/repos/webPairingTokens.ts
23734
+ var PAIRING_TOKEN_TTL_MS = 10 * 6e4;
23735
+ function hashToken(token) {
23736
+ return createHash3("sha256").update(token).digest("hex");
23737
+ }
23738
+ function create2(db, opts = {}) {
23739
+ const id = randomUUID11();
23740
+ const code = randomBytes3(24).toString("hex");
23741
+ const now = Date.now();
23742
+ const scopes = (opts.scopes ?? ALL_DEVICE_TOKEN_SCOPES).join(" ");
23743
+ db.raw.run(
23744
+ `INSERT INTO web_pairing_tokens (id, token_hash, scopes, created_at, expires_at)
23745
+ VALUES (?, ?, ?, ?, ?)`,
23746
+ [id, hashToken(code), scopes, now, now + PAIRING_TOKEN_TTL_MS]
23747
+ );
23748
+ return {
23749
+ code,
23750
+ meta: {
23751
+ id,
23752
+ scopes: scopes.split(" "),
23753
+ createdAt: now,
23754
+ expiresAt: now + PAIRING_TOKEN_TTL_MS,
23755
+ usedAt: null,
23756
+ usedByTokenId: null
23757
+ }
23758
+ };
23759
+ }
23760
+ function exchange(db, code, now = Date.now()) {
23761
+ const tokenHash = hashToken(code);
23762
+ const claimed = db.raw.run(
23763
+ `UPDATE web_pairing_tokens
23764
+ SET used_at = ?, used_by_token_id = 'pending'
23765
+ WHERE token_hash = ? AND used_at IS NULL AND expires_at > ?`,
23766
+ [now, tokenHash, now]
23767
+ );
23768
+ if (claimed.changes === 0) {
23769
+ const row3 = db.raw.query(
23770
+ "SELECT expires_at, used_at FROM web_pairing_tokens WHERE token_hash = ?"
23771
+ ).get(tokenHash);
23772
+ if (!row3) return { ok: false, reason: "invalid" };
23773
+ if (row3.used_at !== null) return { ok: false, reason: "used" };
23774
+ return { ok: false, reason: "expired" };
23775
+ }
23776
+ const row2 = db.raw.query(
23777
+ "SELECT scopes, used_by_token_id FROM web_pairing_tokens WHERE token_hash = ?"
23778
+ ).get(tokenHash);
23779
+ if (!row2) return { ok: false, reason: "invalid" };
23780
+ return { ok: true, scopes: row2.scopes.split(" ") };
23781
+ }
23782
+ function completeExchange(db, code, deviceTokenId) {
23783
+ db.raw.run(
23784
+ `UPDATE web_pairing_tokens SET used_by_token_id = ?
23785
+ WHERE token_hash = ? AND used_by_token_id = 'pending'`,
23786
+ [deviceTokenId, hashToken(code)]
23787
+ );
23788
+ }
23789
+ function list9(db, opts) {
23790
+ const sql = opts?.includeUsed ? "SELECT * FROM web_pairing_tokens ORDER BY created_at DESC" : "SELECT * FROM web_pairing_tokens WHERE used_at IS NULL AND expires_at > ? ORDER BY created_at DESC";
23791
+ const rows = opts?.includeUsed ? db.raw.query(sql).all() : db.raw.query(sql).all(Date.now());
23792
+ return rows.map((r) => ({
23793
+ id: r.id,
23794
+ scopes: r.scopes.split(" "),
23795
+ createdAt: r.created_at,
23796
+ expiresAt: r.expires_at,
23797
+ usedAt: r.used_at,
23798
+ usedByTokenId: r.used_by_token_id
23799
+ }));
23800
+ }
23801
+
23609
23802
  // ../daemon/src/core/repos/webSessions.ts
23610
23803
  var webSessions_exports = {};
23611
23804
  __export(webSessions_exports, {
23612
23805
  SESSION_ABSOLUTE_MS: () => SESSION_ABSOLUTE_MS,
23613
23806
  SESSION_IDLE_MS: () => SESSION_IDLE_MS,
23614
23807
  authenticate: () => authenticate,
23615
- create: () => create3,
23808
+ create: () => create4,
23616
23809
  csrfMatches: () => csrfMatches,
23617
- list: () => list10,
23810
+ list: () => list11,
23618
23811
  revoke: () => revoke3,
23619
23812
  revokeAll: () => revokeAll,
23620
23813
  revokeForDevice: () => revokeForDevice
23621
23814
  });
23622
- import { createHash as createHash4, randomBytes as randomBytes4, randomUUID as randomUUID12 } from "crypto";
23815
+ import { createHash as createHash5, randomBytes as randomBytes5, randomUUID as randomUUID13 } from "crypto";
23623
23816
 
23624
23817
  // ../daemon/src/core/repos/webTokens.ts
23625
23818
  var webTokens_exports = {};
23626
23819
  __export(webTokens_exports, {
23627
- create: () => create2,
23820
+ create: () => create3,
23628
23821
  findActiveByToken: () => findActiveByToken,
23629
23822
  get: () => get16,
23630
- hashToken: () => hashToken,
23631
- list: () => list9,
23823
+ hashToken: () => hashToken2,
23824
+ list: () => list10,
23632
23825
  markUsed: () => markUsed,
23826
+ parseScopes: () => parseScopes,
23633
23827
  rejectionReason: () => rejectionReason,
23634
23828
  revoke: () => revoke2
23635
23829
  });
23636
- import { createHash as createHash3, randomBytes as randomBytes3, randomUUID as randomUUID11 } from "crypto";
23830
+ import { createHash as createHash4, randomBytes as randomBytes4, randomUUID as randomUUID12 } from "crypto";
23831
+ function parseScopes(raw2) {
23832
+ if (!raw2) return [...ALL_DEVICE_TOKEN_SCOPES];
23833
+ const parsed = raw2.split(/\s+/).filter(Boolean).filter(
23834
+ (s) => ALL_DEVICE_TOKEN_SCOPES.includes(s)
23835
+ );
23836
+ return parsed.length > 0 ? parsed : [...ALL_DEVICE_TOKEN_SCOPES];
23837
+ }
23637
23838
  function toToken(r) {
23638
23839
  return {
23639
23840
  id: r.id,
23640
23841
  label: r.label,
23641
23842
  kind: r.kind,
23843
+ scopes: parseScopes(r.scopes),
23642
23844
  createdAt: r.created_at,
23643
23845
  lastUsedAt: r.last_used_at,
23644
23846
  expiresAt: r.expires_at,
23645
23847
  revokedAt: r.revoked_at
23646
23848
  };
23647
23849
  }
23648
- function hashToken(token) {
23649
- return createHash3("sha256").update(token).digest("hex");
23850
+ function hashToken2(token) {
23851
+ return createHash4("sha256").update(token).digest("hex");
23650
23852
  }
23651
- function create2(db, label, opts = {}) {
23652
- const id = randomUUID11();
23653
- const token = randomBytes3(24).toString("hex");
23654
- const tokenHash = hashToken(token);
23853
+ function create3(db, label, opts = {}) {
23854
+ const id = randomUUID12();
23855
+ const token = randomBytes4(24).toString("hex");
23856
+ const tokenHash = hashToken2(token);
23655
23857
  const now = Date.now();
23656
23858
  const kind = opts.kind ?? "device";
23657
23859
  const expiresAt = kind === "bootstrap" ? null : opts.expiresAt ?? now + 90 * 864e5;
23860
+ const scopes = (kind === "bootstrap" ? ALL_DEVICE_TOKEN_SCOPES : opts.scopes ?? ALL_DEVICE_TOKEN_SCOPES).join(" ");
23658
23861
  db.raw.run(
23659
23862
  `INSERT INTO web_tokens
23660
- (id, label, kind, token_hash, created_at, last_used_at, expires_at, revoked_at)
23661
- VALUES (?, ?, ?, ?, ?, NULL, ?, NULL)`,
23662
- [id, label, kind, tokenHash, now, expiresAt]
23863
+ (id, label, kind, token_hash, scopes, created_at, last_used_at, expires_at, revoked_at)
23864
+ VALUES (?, ?, ?, ?, ?, ?, NULL, ?, NULL)`,
23865
+ [id, label, kind, tokenHash, scopes, now, expiresAt]
23663
23866
  );
23664
23867
  return {
23665
23868
  token,
@@ -23667,6 +23870,7 @@ function create2(db, label, opts = {}) {
23667
23870
  id,
23668
23871
  label,
23669
23872
  kind,
23873
+ scopes: parseScopes(scopes),
23670
23874
  createdAt: now,
23671
23875
  lastUsedAt: null,
23672
23876
  expiresAt,
@@ -23674,7 +23878,7 @@ function create2(db, label, opts = {}) {
23674
23878
  }
23675
23879
  };
23676
23880
  }
23677
- function list9(db, opts) {
23881
+ function list10(db, opts) {
23678
23882
  const sql = opts?.includeRevoked ? "SELECT * FROM web_tokens ORDER BY created_at ASC" : "SELECT * FROM web_tokens WHERE revoked_at IS NULL ORDER BY created_at ASC";
23679
23883
  return db.raw.query(sql).all().map(toToken);
23680
23884
  }
@@ -23683,7 +23887,7 @@ function get16(db, id) {
23683
23887
  return row2 ? toToken(row2) : null;
23684
23888
  }
23685
23889
  function findActiveByToken(db, token) {
23686
- const tokenHash = hashToken(token);
23890
+ const tokenHash = hashToken2(token);
23687
23891
  const row2 = db.raw.query(
23688
23892
  `SELECT * FROM web_tokens
23689
23893
  WHERE token_hash = ? AND revoked_at IS NULL
@@ -23694,7 +23898,7 @@ function findActiveByToken(db, token) {
23694
23898
  function rejectionReason(db, token, now = Date.now()) {
23695
23899
  const row2 = db.raw.query(
23696
23900
  "SELECT expires_at, revoked_at FROM web_tokens WHERE token_hash = ?"
23697
- ).get(hashToken(token));
23901
+ ).get(hashToken2(token));
23698
23902
  if (!row2) return "invalid";
23699
23903
  if (row2.revoked_at !== null) return "revoked";
23700
23904
  if (row2.expires_at !== null && row2.expires_at <= now) return "expired";
@@ -23715,7 +23919,7 @@ function revoke2(db, id, when = Date.now()) {
23715
23919
  var SESSION_IDLE_MS = 12 * 60 * 60 * 1e3;
23716
23920
  var SESSION_ABSOLUTE_MS = 7 * 24 * 60 * 60 * 1e3;
23717
23921
  function hash(value) {
23718
- return createHash4("sha256").update(value).digest("hex");
23922
+ return createHash5("sha256").update(value).digest("hex");
23719
23923
  }
23720
23924
  function toSession(row2, currentId) {
23721
23925
  return {
@@ -23730,15 +23934,15 @@ function toSession(row2, currentId) {
23730
23934
  current: row2.id === currentId
23731
23935
  };
23732
23936
  }
23733
- function create3(db, deviceTokenId, now = Date.now()) {
23937
+ function create4(db, deviceTokenId, now = Date.now()) {
23734
23938
  const token = db.raw.query(
23735
23939
  `SELECT id, label FROM web_tokens
23736
23940
  WHERE id = ? AND kind = 'device' AND revoked_at IS NULL AND expires_at > ?`
23737
23941
  ).get(deviceTokenId, now);
23738
23942
  if (!token) throw new Error("active device credential required");
23739
- const id = randomUUID12();
23740
- const secret = randomBytes4(32).toString("base64url");
23741
- const csrfToken = randomBytes4(32).toString("base64url");
23943
+ const id = randomUUID13();
23944
+ const secret = randomBytes5(32).toString("base64url");
23945
+ const csrfToken = randomBytes5(32).toString("base64url");
23742
23946
  const idleExpiresAt = now + SESSION_IDLE_MS;
23743
23947
  const absoluteExpiresAt = now + SESSION_ABSOLUTE_MS;
23744
23948
  db.raw.run(
@@ -23771,7 +23975,7 @@ function authenticate(db, cookieValue, now = Date.now()) {
23771
23975
  const secret = cookieValue.slice(separator + 1);
23772
23976
  if (!secret) return null;
23773
23977
  const row2 = db.raw.query(
23774
- `SELECT s.*, t.label AS device_label
23978
+ `SELECT s.*, t.label AS device_label, t.scopes AS device_scopes
23775
23979
  FROM web_sessions s JOIN web_tokens t ON t.id = s.device_token_id
23776
23980
  WHERE s.id = ? AND s.secret_hash = ? AND s.revoked_at IS NULL
23777
23981
  AND s.idle_expires_at > ? AND s.absolute_expires_at > ?
@@ -23788,13 +23992,14 @@ function authenticate(db, cookieValue, now = Date.now()) {
23788
23992
  id,
23789
23993
  deviceTokenId: row2.device_token_id,
23790
23994
  deviceLabel: row2.device_label,
23995
+ deviceScopes: row2.device_scopes,
23791
23996
  csrfHash: row2.csrf_hash
23792
23997
  };
23793
23998
  }
23794
23999
  function csrfMatches(session, csrf) {
23795
- return hashToken(csrf) === session.csrfHash;
24000
+ return hashToken2(csrf) === session.csrfHash;
23796
24001
  }
23797
- function list10(db, opts = {}) {
24002
+ function list11(db, opts = {}) {
23798
24003
  const where = opts.includeRevoked ? "" : "WHERE s.revoked_at IS NULL";
23799
24004
  return db.raw.query(
23800
24005
  `SELECT s.*, t.label AS device_label FROM web_sessions s
@@ -23853,7 +24058,7 @@ function mergeSecretsIntoEnv(db, password, env = process.env) {
23853
24058
  // ../daemon/src/core/skills/import.ts
23854
24059
  import { cpSync, existsSync as existsSync8, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5, statSync as statSync2 } from "fs";
23855
24060
  import { tmpdir } from "os";
23856
- import { basename, join as join11, resolve as resolve2, sep } from "path";
24061
+ import { basename as basename2, join as join11, resolve as resolve3, sep } from "path";
23857
24062
  import AdmZip from "adm-zip";
23858
24063
 
23859
24064
  // ../daemon/src/core/skills/parse.ts
@@ -23967,7 +24172,7 @@ function extractZipSafely(zipPath) {
23967
24172
  if (rawName.startsWith("/") || rawName.startsWith("\\")) {
23968
24173
  throw new Error(`zip entry has absolute path: ${rawName}`);
23969
24174
  }
23970
- const resolved = resolve2(root, rawName);
24175
+ const resolved = resolve3(root, rawName);
23971
24176
  if (resolved !== root && !resolved.startsWith(root + sep)) {
23972
24177
  throw new Error(`zip entry escapes extraction root: ${rawName}`);
23973
24178
  }
@@ -23985,7 +24190,7 @@ function extractZipSafely(zipPath) {
23985
24190
  return { root, effectiveSource };
23986
24191
  }
23987
24192
  function importSkills(paths2, input) {
23988
- const rawSource = resolve2(input.source);
24193
+ const rawSource = resolve3(input.source);
23989
24194
  if (!existsSync8(rawSource)) {
23990
24195
  throw new Error(`source does not exist: ${rawSource}`);
23991
24196
  }
@@ -24011,7 +24216,7 @@ function importSkills(paths2, input) {
24011
24216
  function importSkillsFromDir(paths2, source, input) {
24012
24217
  const candidates = [];
24013
24218
  if (existsSync8(join11(source, "SKILL.md"))) {
24014
- candidates.push({ name: basename(source), dir: source });
24219
+ candidates.push({ name: basename2(source), dir: source });
24015
24220
  } else {
24016
24221
  const entries = readdirSync3(source, { withFileTypes: true });
24017
24222
  for (const e of entries) {
@@ -24078,7 +24283,7 @@ function resolveAgentSkills(db, paths2, agentId) {
24078
24283
  }
24079
24284
 
24080
24285
  // ../daemon/src/core/team/delete.ts
24081
- import { randomUUID as randomUUID13 } from "crypto";
24286
+ import { randomUUID as randomUUID14 } from "crypto";
24082
24287
  import { existsSync as existsSync9, renameSync as renameSync2, rmSync as rmSync6 } from "fs";
24083
24288
  function deleteTeam(db, paths2, id, expectedTeamPolicyRevision) {
24084
24289
  const g2 = get3(db, id, paths2);
@@ -24097,7 +24302,7 @@ function deleteTeam(db, paths2, id, expectedTeamPolicyRevision) {
24097
24302
  `cannot delete team "${id}": ${members2.length} agent(s) still belong to it: ${names}. Move or delete them first.`
24098
24303
  );
24099
24304
  }
24100
- const stagedPath = `${g2.path}.deleting-${randomUUID13()}`;
24305
+ const stagedPath = `${g2.path}.deleting-${randomUUID14()}`;
24101
24306
  const hadSlot = existsSync9(g2.path);
24102
24307
  if (hadSlot) renameSync2(g2.path, stagedPath);
24103
24308
  try {
@@ -24121,7 +24326,7 @@ function deleteTeam(db, paths2, id, expectedTeamPolicyRevision) {
24121
24326
  }
24122
24327
 
24123
24328
  // ../daemon/src/core/team-policy/adopt.ts
24124
- import { randomUUID as randomUUID14 } from "crypto";
24329
+ import { randomUUID as randomUUID15 } from "crypto";
24125
24330
  function previewTeamPolicyAdoption(db, teamId, input) {
24126
24331
  return resolveAdoptionPlan(db, teamId, { ...input, previewEdges: [] }).resolved;
24127
24332
  }
@@ -24194,7 +24399,7 @@ function adoptTeamTemplate(db, teamId, input) {
24194
24399
  );
24195
24400
  db.raw.run("DELETE FROM template_instantiations WHERE team_id = ?", [teamId]);
24196
24401
  db.raw.run("DELETE FROM team_policy_edges WHERE team_id = ?", [teamId]);
24197
- const instantiationId = randomUUID14();
24402
+ const instantiationId = randomUUID15();
24198
24403
  db.raw.run(
24199
24404
  `INSERT INTO template_instantiations
24200
24405
  (id, team_id, template_id, template_revision, created_at)
@@ -24292,7 +24497,7 @@ function edgeKey(edge) {
24292
24497
  }
24293
24498
 
24294
24499
  // ../daemon/src/core/team-policy/authorization.ts
24295
- import { createHash as createHash5, randomUUID as randomUUID15 } from "crypto";
24500
+ import { createHash as createHash6, randomUUID as randomUUID16 } from "crypto";
24296
24501
  function denied(channel, code, reason) {
24297
24502
  return {
24298
24503
  decision: "deny",
@@ -24442,7 +24647,7 @@ function authorizeInSnapshot(db, input) {
24442
24647
  };
24443
24648
  }
24444
24649
  function authorizationFingerprint(input, operation) {
24445
- return createHash5("sha256").update(JSON.stringify({ operation, source: input.source, target: input.target })).digest("hex");
24650
+ return createHash6("sha256").update(JSON.stringify({ operation, source: input.source, target: input.target })).digest("hex");
24446
24651
  }
24447
24652
  function recordDenial(db, input, operation, result) {
24448
24653
  const fingerprint2 = authorizationFingerprint(input, operation);
@@ -24472,7 +24677,7 @@ function recordDenial(db, input, operation, result) {
24472
24677
  const sourceGroup = agentGroup(input.source) ?? agentGroup(input.target) ?? ("teamId" in input.source ? input.source.teamId : null);
24473
24678
  const targetGroup = agentGroup(input.target) ?? agentGroup(input.source) ?? ("teamId" in input.target ? input.target.teamId : null);
24474
24679
  const values = [
24475
- randomUUID15(),
24680
+ randomUUID16(),
24476
24681
  input.attemptKind,
24477
24682
  input.attemptId,
24478
24683
  operation,
@@ -24522,7 +24727,7 @@ function recordDenial(db, input, operation, result) {
24522
24727
  }
24523
24728
 
24524
24729
  // ../daemon/src/core/team-policy/source.ts
24525
- import { randomUUID as randomUUID16 } from "crypto";
24730
+ import { randomUUID as randomUUID17 } from "crypto";
24526
24731
  function diffTeamPolicy(db, teamId) {
24527
24732
  const detail3 = detail(db, teamId);
24528
24733
  if (!detail3) throw new Error(`team_policy_missing: ${teamId}`);
@@ -24590,7 +24795,7 @@ function saveTeamPolicyAsTemplate(db, paths2, teamId, input) {
24590
24795
  const team = get3(db, teamId, paths2);
24591
24796
  if (!team) throw new Error(`team not found: ${teamId}`);
24592
24797
  const members2 = list(db, { includeArchived: true }).filter((agent) => agent.teamId === teamId);
24593
- const slotByAgent = new Map(members2.map((agent) => [agent.id, randomUUID16()]));
24798
+ const slotByAgent = new Map(members2.map((agent) => [agent.id, randomUUID17()]));
24594
24799
  const stateByAgent = new Map(
24595
24800
  agentState(db, teamId).map((state3) => [state3.agentId, state3])
24596
24801
  );
@@ -24666,7 +24871,7 @@ function updateTeamPolicySource(db, teamId, input) {
24666
24871
  baselineBindings.map((binding) => [binding.agentId, binding.sourceSlotId])
24667
24872
  );
24668
24873
  for (const id of selectedIds) {
24669
- if (!slotByAgent.has(id)) slotByAgent.set(id, randomUUID16());
24874
+ if (!slotByAgent.has(id)) slotByAgent.set(id, randomUUID17());
24670
24875
  }
24671
24876
  const previousSlotById = new Map(previous.slots.map((slot) => [slot.slotId, slot]));
24672
24877
  const selectedMembers = [...selectedIds].map((id) => {
@@ -24734,7 +24939,7 @@ function pruneEmptyNonbaselineInstantiation(db, instantiationId, baselineId) {
24734
24939
  }
24735
24940
 
24736
24941
  // ../daemon/src/core/team-policy/spawn.ts
24737
- import { randomUUID as randomUUID17 } from "crypto";
24942
+ import { randomUUID as randomUUID18 } from "crypto";
24738
24943
  import { readdirSync as readdirSync4, rmSync as rmSync8 } from "fs";
24739
24944
 
24740
24945
  // ../daemon/src/core/team-policy/rm-with-retry.ts
@@ -24901,7 +25106,7 @@ async function spawnTeamTemplate(db, paths2, input) {
24901
25106
  })
24902
25107
  );
24903
25108
  }
24904
- const instantiationId = randomUUID17();
25109
+ const instantiationId = randomUUID18();
24905
25110
  db.raw.run(
24906
25111
  `INSERT INTO template_instantiations
24907
25112
  (id, team_id, template_id, template_revision, created_at)
@@ -24989,6 +25194,7 @@ function safeReaddir(path) {
24989
25194
 
24990
25195
  // ../daemon/src/lib/ctx.ts
24991
25196
  import { chmodSync, existsSync as existsSync18, mkdirSync as mkdirSync10, writeFileSync as writeFileSync14 } from "fs";
25197
+ import { dirname as dirname7, join as join30 } from "path";
24992
25198
 
24993
25199
  // ../daemon/src/core/repos/coding-commands.ts
24994
25200
  var CODING_COMMAND_TTL_MS = 7 * 864e5;
@@ -25048,7 +25254,7 @@ function interruptCodingCommands(db, turnId) {
25048
25254
  }
25049
25255
 
25050
25256
  // ../daemon/src/core/repos/notifications.ts
25051
- import { randomUUID as randomUUID18 } from "crypto";
25257
+ import { randomUUID as randomUUID19 } from "crypto";
25052
25258
  var NOTIFICATION_RECEIPT_LIMIT = 1e5;
25053
25259
  var settingsFields = `revision, enabled, restore_paused restorePaused, kinds_json kindsJson,
25054
25260
  timezone, quiet_json quietJson, destination_json destinationJson, eligible_after eligibleAfter,
@@ -25177,7 +25383,7 @@ function admit(db, item, binding, now = Date.now()) {
25177
25383
  if (existing) return decode(existing);
25178
25384
  const count3 = db.raw.query("SELECT COUNT(*) n FROM notification_receipts").get()?.n ?? 0;
25179
25385
  if (count3 >= NOTIFICATION_RECEIPT_LIMIT) throw new Error("notification_capacity_reached");
25180
- const id = randomUUID18();
25386
+ const id = randomUUID19();
25181
25387
  db.raw.run(
25182
25388
  `INSERT INTO notification_receipts (id, source_kind, source_id, agent_id, team_id,
25183
25389
  destination_id, destination_json, state, created_at, updated_at)
@@ -25197,7 +25403,7 @@ function admit(db, item, binding, now = Date.now()) {
25197
25403
  return get17(db, id);
25198
25404
  })();
25199
25405
  }
25200
- function list11(db, options = {}) {
25406
+ function list12(db, options = {}) {
25201
25407
  if (options.limit !== void 0 && !Number.isFinite(options.limit))
25202
25408
  throw new Error("notification_limit_invalid");
25203
25409
  const limit = Math.max(1, Math.min(100, Math.trunc(options.limit ?? 50)));
@@ -25271,7 +25477,7 @@ function recoverInterrupted(db, now = Date.now()) {
25271
25477
  }
25272
25478
 
25273
25479
  // ../daemon/src/core/repos/publications.ts
25274
- import { randomUUID as randomUUID19 } from "crypto";
25480
+ import { randomUUID as randomUUID20 } from "crypto";
25275
25481
  var PUBLICATION_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
25276
25482
  var PublicationError = class extends Error {
25277
25483
  constructor(code, message) {
@@ -25312,7 +25518,7 @@ function toRecord(row2) {
25312
25518
  }
25313
25519
  function createPublication(db, input) {
25314
25520
  const now = input.now ?? Date.now();
25315
- const id = randomUUID19();
25521
+ const id = randomUUID20();
25316
25522
  return inTx(db, () => {
25317
25523
  const published = db.raw.query(
25318
25524
  "SELECT id FROM publications WHERE packet_id = ? AND state = 'published'"
@@ -25465,7 +25671,7 @@ function notePublicationError(db, id, error2, now = Date.now()) {
25465
25671
  }
25466
25672
 
25467
25673
  // ../daemon/src/core/repos/questions.ts
25468
- import { createHash as createHash6, randomUUID as randomUUID20 } from "crypto";
25674
+ import { createHash as createHash7, randomUUID as randomUUID21 } from "crypto";
25469
25675
 
25470
25676
  // ../daemon/src/lib/question-input.ts
25471
25677
  var QUESTION_LIMITS = Object.freeze({
@@ -25580,7 +25786,7 @@ function get18(db, agentId, id) {
25580
25786
  ).get(agentId, id);
25581
25787
  return row2 ? decode2(row2) : null;
25582
25788
  }
25583
- function list12(db, agentId, limit = 20, conversationId) {
25789
+ function list13(db, agentId, limit = 20, conversationId) {
25584
25790
  if (!Number.isInteger(limit) || limit < 1 || limit > 100)
25585
25791
  throw new Error("Invalid question limit");
25586
25792
  return db.raw.query(
@@ -25592,7 +25798,7 @@ function required(db, agentId, id) {
25592
25798
  if (!item) throw new Error("Question unavailable");
25593
25799
  return item;
25594
25800
  }
25595
- function create4(db, input, now = Date.now()) {
25801
+ function create5(db, input, now = Date.now()) {
25596
25802
  const question = parseQuestionInput(input.question);
25597
25803
  if (!input.turnId || !input.toolCallId || input.turnId.length > 256 || input.toolCallId.length > 256)
25598
25804
  throw new Error("Invalid question identity");
@@ -25611,7 +25817,7 @@ function create4(db, input, now = Date.now()) {
25611
25817
  COALESCE(SUM(status = 'pending'), 0) AS pending, COALESCE(SUM(turn_id = ?), 0) AS turn FROM agent_questions`).get(input.turnId);
25612
25818
  if (!count3 || count3.total >= QUESTION_LIMITS.recordsPerHome || count3.pending >= QUESTION_LIMITS.pendingPerHome || count3.turn >= QUESTION_LIMITS.perTurn)
25613
25819
  throw new Error("Question capacity reached");
25614
- const id = randomUUID20();
25820
+ const id = randomUUID21();
25615
25821
  db.raw.run(
25616
25822
  `INSERT INTO agent_questions (id, agent_id, team_id, conversation_id, turn_id, tool_call_id,
25617
25823
  question_json, binding_json, status, created_at, expires_at, continuation) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?, 'waiting')`,
@@ -25733,7 +25939,7 @@ function retireClosedApprovals(db, now) {
25733
25939
  now
25734
25940
  );
25735
25941
  }
25736
- var digest2 = (value) => createHash6("sha256").update(JSON.stringify(value)).digest("hex");
25942
+ var digest2 = (value) => createHash7("sha256").update(JSON.stringify(value)).digest("hex");
25737
25943
  function approvalSnapshot(db, agentId, id) {
25738
25944
  const question = get18(db, agentId, id);
25739
25945
  if (!question) return null;
@@ -25812,9 +26018,9 @@ function ownsApproval(db, capturedId, providedId) {
25812
26018
  }
25813
26019
 
25814
26020
  // ../daemon/src/core/repos/review-packets.ts
25815
- import { randomUUID as randomUUID21 } from "crypto";
26021
+ import { randomUUID as randomUUID22 } from "crypto";
25816
26022
  var REVIEW_PACKET_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
25817
- var REVIEW_LIMITS = {
26023
+ var REVIEW_LIMITS2 = {
25818
26024
  summary: 2e3,
25819
26025
  note: 4e3,
25820
26026
  path: 1e3,
@@ -25842,8 +26048,8 @@ function assertLength(value, max, field) {
25842
26048
  }
25843
26049
  function createReviewPacket(db, input) {
25844
26050
  const now = input.now ?? Date.now();
25845
- const id = randomUUID21();
25846
- if (input.summary) assertLength(input.summary, REVIEW_LIMITS.summary, "summary");
26051
+ const id = randomUUID22();
26052
+ if (input.summary) assertLength(input.summary, REVIEW_LIMITS2.summary, "summary");
25847
26053
  db.raw.run(
25848
26054
  `INSERT INTO review_packets (
25849
26055
  id, team_id, requester_kind, requester_agent_id, reviewer_agent_id, snapshot_id,
@@ -25906,8 +26112,8 @@ function recordReviewExport(db, packetId, revision4, now = Date.now()) {
25906
26112
  return Number(result.changes) > 0;
25907
26113
  }
25908
26114
  function addReviewFinding(db, input) {
25909
- assertLength(input.path, REVIEW_LIMITS.path, "path");
25910
- assertLength(input.note, REVIEW_LIMITS.note, "note");
26115
+ assertLength(input.path, REVIEW_LIMITS2.path, "path");
26116
+ assertLength(input.note, REVIEW_LIMITS2.note, "note");
25911
26117
  if (input.note.trim() === "") {
25912
26118
  throw new ReviewPacketError("invalid_resolution", "a finding needs a note");
25913
26119
  }
@@ -25915,13 +26121,13 @@ function addReviewFinding(db, input) {
25915
26121
  const count3 = db.raw.query(
25916
26122
  "SELECT count(*) AS n FROM review_findings WHERE packet_id = ?"
25917
26123
  ).get(input.packetId)?.n;
25918
- if ((count3 ?? 0) >= REVIEW_LIMITS.findings) {
26124
+ if ((count3 ?? 0) >= REVIEW_LIMITS2.findings) {
25919
26125
  throw new ReviewPacketError(
25920
26126
  "finding_limit",
25921
- `a packet holds at most ${REVIEW_LIMITS.findings} findings`
26127
+ `a packet holds at most ${REVIEW_LIMITS2.findings} findings`
25922
26128
  );
25923
26129
  }
25924
- const id = randomUUID21();
26130
+ const id = randomUUID22();
25925
26131
  db.raw.run(
25926
26132
  `INSERT INTO review_findings (
25927
26133
  id, packet_id, author_kind, author_agent_id, path, line_start, line_end, severity, note,
@@ -25968,7 +26174,7 @@ function resolveReviewFinding(db, input) {
25968
26174
  if (input.resolutionNote.trim() === "") {
25969
26175
  throw new ReviewPacketError("invalid_resolution", "resolving a finding needs a note saying how");
25970
26176
  }
25971
- assertLength(input.resolutionNote, REVIEW_LIMITS.summary, "resolution note");
26177
+ assertLength(input.resolutionNote, REVIEW_LIMITS2.summary, "resolution note");
25972
26178
  const now = input.now ?? Date.now();
25973
26179
  db.raw.run(
25974
26180
  `UPDATE review_findings
@@ -25989,8 +26195,8 @@ function resolveReviewFinding(db, input) {
25989
26195
  return updated;
25990
26196
  }
25991
26197
  function recordReviewConclusion(db, input) {
25992
- if (input.note) assertLength(input.note, REVIEW_LIMITS.note, "conclusion note");
25993
- const id = randomUUID21();
26198
+ if (input.note) assertLength(input.note, REVIEW_LIMITS2.note, "conclusion note");
26199
+ const id = randomUUID22();
25994
26200
  db.raw.run(
25995
26201
  `INSERT INTO review_conclusions (
25996
26202
  id, packet_id, reviewer_kind, reviewer_agent_id, conclusion, note, snapshot_id, created_at
@@ -26033,7 +26239,7 @@ function claimReviewAttempt(db, input) {
26033
26239
  const next = (db.raw.query(
26034
26240
  "SELECT COALESCE(MAX(attempt_number), 0) AS n FROM review_attempts WHERE packet_id = ?"
26035
26241
  ).get(input.packetId)?.n ?? 0) + 1;
26036
- const id = randomUUID21();
26242
+ const id = randomUUID22();
26037
26243
  db.raw.run(
26038
26244
  `INSERT INTO review_attempts (
26039
26245
  id, packet_id, attempt_number, supersedes_attempt_id, state, lease_owner, lease_expires_at, created_at
@@ -26065,7 +26271,7 @@ function listReviewAttempts(db, packetId) {
26065
26271
  ).all(packetId).map(toAttempt);
26066
26272
  }
26067
26273
  function finishReviewAttempt(db, input) {
26068
- if (input.error != null) assertLength(input.error, REVIEW_LIMITS.summary, "error");
26274
+ if (input.error != null) assertLength(input.error, REVIEW_LIMITS2.summary, "error");
26069
26275
  const now = input.now ?? Date.now();
26070
26276
  return inTx(db, () => {
26071
26277
  const row2 = db.raw.query(
@@ -26156,7 +26362,7 @@ function recordReportedState(db, input) {
26156
26362
  if (!REVIEW_REPORTED_STATES.includes(input.state)) {
26157
26363
  throw new ReviewPacketError("invalid_resolution", `unknown reported state: ${input.state}`);
26158
26364
  }
26159
- if (input.reference && input.reference.length > REVIEW_LIMITS.path) {
26365
+ if (input.reference && input.reference.length > REVIEW_LIMITS2.path) {
26160
26366
  throw new ReviewPacketError("invalid_resolution", "the reported reference is too long");
26161
26367
  }
26162
26368
  const next = { ...packet.reported, [input.state]: input.reference?.trim() || null };
@@ -26216,7 +26422,7 @@ function toAttempt(row2) {
26216
26422
  }
26217
26423
 
26218
26424
  // ../daemon/src/core/repos/user-queue.ts
26219
- import { createHash as createHash7, randomUUID as randomUUID22 } from "crypto";
26425
+ import { createHash as createHash8, randomUUID as randomUUID23 } from "crypto";
26220
26426
  var QUEUE_LIMITS = Object.freeze({
26221
26427
  perAgent: 20,
26222
26428
  perHome: 100,
@@ -26233,7 +26439,7 @@ var fields2 = `id, agent_id AS agentId, team_id AS teamId, conversation_id AS co
26233
26439
  supersedes_id AS supersedesId, approval_id AS approvalId, diagnostic, created_at AS createdAt,
26234
26440
  updated_at AS updatedAt, started_at AS startedAt, finished_at AS finishedAt`;
26235
26441
  var uuid2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
26236
- var hash2 = (value) => createHash7("sha256").update(value).digest("hex");
26442
+ var hash2 = (value) => createHash8("sha256").update(value).digest("hex");
26237
26443
  var QueueConflictError = class extends Error {
26238
26444
  code = "queue_conflict";
26239
26445
  };
@@ -26299,7 +26505,7 @@ function get19(db, agentId, id) {
26299
26505
  ).get(agentId, id);
26300
26506
  return row2 ? hydrate(db, row2) : null;
26301
26507
  }
26302
- function list13(db, agentId, options = {}) {
26508
+ function list14(db, agentId, options = {}) {
26303
26509
  const { all = false, limit = 20, offset = 0 } = options;
26304
26510
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100 || !Number.isSafeInteger(offset) || offset < 0)
26305
26511
  throw new Error("Invalid queue pagination");
@@ -26404,7 +26610,7 @@ function accept(db, input, replacement) {
26404
26610
  db.raw.run(
26405
26611
  `INSERT INTO user_queue_attachments (id,item_id,ordinal,name,mime_type,byte_length,sha256,bytes) VALUES (?,?,?,?,?,?,?,?)`,
26406
26612
  [
26407
- randomUUID22(),
26613
+ randomUUID23(),
26408
26614
  input.id,
26409
26615
  ordinal,
26410
26616
  file.name,
@@ -26632,7 +26838,7 @@ function approvalReference(db, agentId, id) {
26632
26838
  }
26633
26839
 
26634
26840
  // ../daemon/src/core/repos/verification-requests.ts
26635
- import { randomUUID as randomUUID23 } from "crypto";
26841
+ import { randomUUID as randomUUID24 } from "crypto";
26636
26842
  var VERIFICATION_REQUEST_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
26637
26843
  var VERIFICATION_MAX_CHECKS = 8;
26638
26844
  var VERIFICATION_LIMITS = {
@@ -26724,7 +26930,7 @@ var VerificationRequestError = class extends Error {
26724
26930
  };
26725
26931
  function createVerificationRequest(db, input) {
26726
26932
  const now = input.now ?? Date.now();
26727
- const id = input.id ?? randomUUID23();
26933
+ const id = input.id ?? randomUUID24();
26728
26934
  if (input.checks.length < 1)
26729
26935
  throw new VerificationRequestError("a request needs at least one check");
26730
26936
  if (input.checks.length > VERIFICATION_MAX_CHECKS) {
@@ -26842,7 +27048,7 @@ function claimVerificationAttempt(db, input) {
26842
27048
  `SELECT id, attempt_number FROM verification_attempts WHERE request_id = ?
26843
27049
  ORDER BY attempt_number DESC LIMIT 1`
26844
27050
  ).get(input.requestId);
26845
- const attemptId = randomUUID23();
27051
+ const attemptId = randomUUID24();
26846
27052
  db.raw.run(
26847
27053
  `INSERT INTO verification_attempts
26848
27054
  (id, request_id, attempt_number, supersedes_attempt_id, state, lease_owner,
@@ -27030,7 +27236,7 @@ function unregisterAgent(agentId) {
27030
27236
  if (!state3.active.delete(agentId)) return;
27031
27237
  const waiters = state3.idleWaiters.get(agentId);
27032
27238
  state3.idleWaiters.delete(agentId);
27033
- for (const resolve8 of waiters ?? []) resolve8();
27239
+ for (const resolve9 of waiters ?? []) resolve9();
27034
27240
  }
27035
27241
  function cancelAgent(agentId) {
27036
27242
  const { active } = registry();
@@ -27048,9 +27254,9 @@ function ownsActiveAgent(agentId, controller) {
27048
27254
  function waitForAgentIdle(agentId) {
27049
27255
  const state3 = registry();
27050
27256
  if (!state3.active.has(agentId)) return Promise.resolve();
27051
- return new Promise((resolve8) => {
27257
+ return new Promise((resolve9) => {
27052
27258
  const waiters = state3.idleWaiters.get(agentId) ?? /* @__PURE__ */ new Set();
27053
- waiters.add(resolve8);
27259
+ waiters.add(resolve9);
27054
27260
  state3.idleWaiters.set(agentId, waiters);
27055
27261
  });
27056
27262
  }
@@ -27094,25 +27300,25 @@ function reconcilePrivateResults(db, options = {}) {
27094
27300
  }
27095
27301
 
27096
27302
  // ../daemon/src/lib/coding-environment/lifecycle.ts
27097
- import { randomUUID as randomUUID27 } from "crypto";
27303
+ import { randomUUID as randomUUID28 } from "crypto";
27098
27304
 
27099
27305
  // ../daemon/src/lib/coding-environment/resources.ts
27100
- import { randomUUID as randomUUID25 } from "crypto";
27306
+ import { randomUUID as randomUUID26 } from "crypto";
27101
27307
 
27102
27308
  // ../daemon/src/runtime/shell/docker.ts
27103
27309
  import { spawn } from "child_process";
27104
- import { randomUUID as randomUUID24 } from "crypto";
27310
+ import { randomUUID as randomUUID25 } from "crypto";
27105
27311
  import { closeSync as closeSync2, constants as constants2, mkdtempSync as mkdtempSync2, openSync as openSync2, rmSync as rmSync9, writeFileSync as writeFileSync6 } from "fs";
27106
27312
  import { access, lstat, realpath, stat } from "fs/promises";
27107
27313
  import { tmpdir as tmpdir2 } from "os";
27108
27314
  import { delimiter, isAbsolute as isAbsolute2, join as join14, relative, sep as sep2 } from "path";
27109
27315
 
27110
27316
  // ../daemon/src/runtime/coding-directory.ts
27111
- import { realpathSync as realpathSync2 } from "fs";
27317
+ import { realpathSync as realpathSync3 } from "fs";
27112
27318
  import { join as join13 } from "path";
27113
27319
 
27114
27320
  // ../daemon/src/lib/repository-context/files.ts
27115
- import { createHash as createHash8 } from "crypto";
27321
+ import { createHash as createHash9 } from "crypto";
27116
27322
  import {
27117
27323
  closeSync,
27118
27324
  constants,
@@ -27121,10 +27327,10 @@ import {
27121
27327
  opendirSync,
27122
27328
  openSync,
27123
27329
  readSync,
27124
- realpathSync
27330
+ realpathSync as realpathSync2
27125
27331
  } from "fs";
27126
27332
  import { isAbsolute, join as join12 } from "path";
27127
- var hash3 = (value) => createHash8("sha256").update(value).digest("hex");
27333
+ var hash3 = (value) => createHash9("sha256").update(value).digest("hex");
27128
27334
  var ContextReadError = class extends Error {
27129
27335
  code;
27130
27336
  constructor(code) {
@@ -27162,7 +27368,7 @@ var ContextDirectory = class _ContextDirectory {
27162
27368
  this.label = label;
27163
27369
  this.parent = parent;
27164
27370
  if (process.platform !== "linux") throw new ContextReadError("safe_reads_unavailable");
27165
- const path = parent ? join12(parent.path, registeredPath) : realpathSync(registeredPath);
27371
+ const path = parent ? join12(parent.path, registeredPath) : realpathSync2(registeredPath);
27166
27372
  this.fd = openSync(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
27167
27373
  const stat2 = fstatSync(this.fd);
27168
27374
  this.identity = hash3(identity(stat2));
@@ -27245,7 +27451,7 @@ var ContextDirectory = class _ContextDirectory {
27245
27451
  }
27246
27452
  }
27247
27453
  validate(skipGit = false, names) {
27248
- const currentPath = this.parent ? join12(this.parent.path, this.registeredPath) : realpathSync(this.registeredPath);
27454
+ const currentPath = this.parent ? join12(this.parent.path, this.registeredPath) : realpathSync2(this.registeredPath);
27249
27455
  const stat2 = lstatSync(currentPath);
27250
27456
  if (!stat2.isDirectory() || identity(stat2) !== this.originalStamp)
27251
27457
  throw new ContextReadError("root_changed");
@@ -27274,7 +27480,7 @@ function resolveCodingDirectory(root, cwd) {
27274
27480
  try {
27275
27481
  let current = directory;
27276
27482
  for (const part of relativeParts(cwd)) current = current.directory(part);
27277
- const path = realpathSync2(join13(root, cwd));
27483
+ const path = realpathSync3(join13(root, cwd));
27278
27484
  directory.validate();
27279
27485
  return { path, identity: current.identity };
27280
27486
  } finally {
@@ -27591,7 +27797,7 @@ function createPreparedDockerBashOperations(runtime, lifecycle) {
27591
27797
  }
27592
27798
  await assertDockerExecutableIdentity(runtime.dockerPath, runtime.executableIdentity);
27593
27799
  if (signal?.aborted) throw new Error("aborted");
27594
- const containerName = lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${randomUUID24().replaceAll("-", "")}`;
27800
+ const containerName = lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${randomUUID25().replaceAll("-", "")}`;
27595
27801
  const spec = buildDockerRunSpec({
27596
27802
  image: runtime.image,
27597
27803
  resolvedImage: runtime.imageId,
@@ -27640,7 +27846,7 @@ async function preflightProtectedDockerEngine(input) {
27640
27846
  }
27641
27847
  async function proveProtectedContainerCreation(engine, workspace, readOnlyMounts, lifecycle, signal) {
27642
27848
  if (signal?.aborted) throw new Error("aborted");
27643
- const containerName = lifecycle?.name("preflight") ?? `bazilion-preflight-${process.pid}-${randomUUID24().replaceAll("-", "")}`;
27849
+ const containerName = lifecycle?.name("preflight") ?? `bazilion-preflight-${process.pid}-${randomUUID25().replaceAll("-", "")}`;
27644
27850
  const dockerClientEnv = { DOCKER_HOST: engine.endpoint };
27645
27851
  const spec = buildDockerRunSpec({
27646
27852
  image: engine.image,
@@ -27701,7 +27907,7 @@ function runProtectedContainerCreate(spec, options) {
27701
27907
  )
27702
27908
  );
27703
27909
  }
27704
- return new Promise((resolve8, reject2) => {
27910
+ return new Promise((resolve9, reject2) => {
27705
27911
  let child;
27706
27912
  try {
27707
27913
  child = spawn(spec.executable, ["container", "create", ...spec.args.slice(1)], {
@@ -27727,7 +27933,7 @@ function runProtectedContainerCreate(spec, options) {
27727
27933
  if (killSettleHandle) clearTimeout(killSettleHandle);
27728
27934
  options?.signal?.removeEventListener("abort", onAbort);
27729
27935
  if (error2) reject2(error2);
27730
- else resolve8();
27936
+ else resolve9();
27731
27937
  };
27732
27938
  const commandTimeout = options?.timeoutMs !== void 0 && options.timeoutMs <= DOCKER_CREATE_TIMEOUT_MS;
27733
27939
  const timeoutError = () => commandTimeout ? new Error(`timeout:${options?.timeout}`) : new Error(
@@ -27759,7 +27965,7 @@ function runProtectedContainerCreate(spec, options) {
27759
27965
  }
27760
27966
  function runProtectedContainerProbe(spec, signal) {
27761
27967
  if (signal?.aborted) return Promise.reject(new Error("aborted"));
27762
- return new Promise((resolve8, reject2) => {
27968
+ return new Promise((resolve9, reject2) => {
27763
27969
  let child;
27764
27970
  try {
27765
27971
  child = spawn(spec.executable, ["container", "start", "--attach", spec.containerName], {
@@ -27783,7 +27989,7 @@ function runProtectedContainerProbe(spec, signal) {
27783
27989
  if (killSettleHandle) clearTimeout(killSettleHandle);
27784
27990
  signal?.removeEventListener("abort", onAbort);
27785
27991
  if (error2) reject2(error2);
27786
- else resolve8();
27992
+ else resolve9();
27787
27993
  };
27788
27994
  const timeoutError = () => new Error(
27789
27995
  `Docker sandbox could not start its protected preflight container within ${DOCKER_PROBE_START_TIMEOUT_MS}ms`
@@ -27816,7 +28022,7 @@ async function removePreflightContainer(dockerPath, containerName, processEnv, c
27816
28022
  last = await runCleanupCommand(dockerPath, args, processEnv);
27817
28023
  if (last.ok && !last.missing) return;
27818
28024
  if (attempt < CLEANUP_ATTEMPTS - 1) {
27819
- await new Promise((resolve8) => setTimeout(resolve8, CLEANUP_RETRY_DELAY_MS));
28025
+ await new Promise((resolve9) => setTimeout(resolve9, CLEANUP_RETRY_DELAY_MS));
27820
28026
  }
27821
28027
  }
27822
28028
  if (last?.missing && creationAcknowledged) return;
@@ -27972,7 +28178,7 @@ function createDockerBashOperations(options) {
27972
28178
  const dockerClientEnv = await resolveLocalDockerClientEnv(dockerPath, hostEnv);
27973
28179
  const resolvedImage = await inspectSandboxImage(dockerPath, image, dockerClientEnv);
27974
28180
  if (signal?.aborted) throw new Error("aborted");
27975
- const containerName = options.lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${randomUUID24().replaceAll("-", "")}`;
28181
+ const containerName = options.lifecycle?.name("bash") ?? `bazilion-bash-${process.pid}-${randomUUID25().replaceAll("-", "")}`;
27976
28182
  const spec = buildDockerRunSpec({
27977
28183
  image,
27978
28184
  env,
@@ -28037,7 +28243,7 @@ function executeDockerRun(spec, options) {
28037
28243
  )
28038
28244
  );
28039
28245
  }
28040
- return new Promise((resolve8, reject2) => {
28246
+ return new Promise((resolve9, reject2) => {
28041
28247
  const child = spawn(spec.executable, spec.args, {
28042
28248
  stdio: ["ignore", "pipe", "pipe", envFileFd ?? "ignore"],
28043
28249
  windowsHide: true,
@@ -28080,7 +28286,7 @@ function executeDockerRun(spec, options) {
28080
28286
  reject2(new Error(`Docker sandbox CLI for container "${spec.containerName}" was killed`));
28081
28287
  return;
28082
28288
  }
28083
- resolve8({ exitCode });
28289
+ resolve9({ exitCode });
28084
28290
  };
28085
28291
  child.stdout?.on("data", options.onData);
28086
28292
  child.stderr?.on("data", (data) => {
@@ -28249,7 +28455,7 @@ async function inspectSandboxImage(dockerPath, image, processEnv) {
28249
28455
  return id;
28250
28456
  }
28251
28457
  function runDockerInspection(dockerPath, args, processEnv, subject) {
28252
- return new Promise((resolve8, reject2) => {
28458
+ return new Promise((resolve9, reject2) => {
28253
28459
  const child = spawn(dockerPath, args, {
28254
28460
  stdio: ["ignore", "pipe", "pipe"],
28255
28461
  windowsHide: true,
@@ -28266,7 +28472,7 @@ function runDockerInspection(dockerPath, args, processEnv, subject) {
28266
28472
  reject2(error2);
28267
28473
  return;
28268
28474
  }
28269
- resolve8(stdout.trim());
28475
+ resolve9(stdout.trim());
28270
28476
  };
28271
28477
  const timeoutHandle = setTimeout(() => {
28272
28478
  child.kill("SIGKILL");
@@ -28405,7 +28611,7 @@ async function removeContainer(dockerPath, containerName, processEnv) {
28405
28611
  last = await runCleanupCommand(dockerPath, args, processEnv);
28406
28612
  if (last.ok) return;
28407
28613
  if (attempt < CLEANUP_ATTEMPTS - 1) {
28408
- await new Promise((resolve8) => setTimeout(resolve8, CLEANUP_RETRY_DELAY_MS));
28614
+ await new Promise((resolve9) => setTimeout(resolve9, CLEANUP_RETRY_DELAY_MS));
28409
28615
  }
28410
28616
  }
28411
28617
  if (last && !last.missing) {
@@ -28415,7 +28621,7 @@ async function removeContainer(dockerPath, containerName, processEnv) {
28415
28621
  }
28416
28622
  }
28417
28623
  function runCleanupCommand(dockerPath, args, processEnv) {
28418
- return new Promise((resolve8) => {
28624
+ return new Promise((resolve9) => {
28419
28625
  let done = false;
28420
28626
  let stderr = "";
28421
28627
  const child = spawn(dockerPath, args, {
@@ -28428,7 +28634,7 @@ function runCleanupCommand(dockerPath, args, processEnv) {
28428
28634
  done = true;
28429
28635
  clearTimeout(timeoutHandle);
28430
28636
  const detail3 = error2 || stderr.trim();
28431
- resolve8({
28637
+ resolve9({
28432
28638
  ok,
28433
28639
  missing: /no such container/i.test(detail3),
28434
28640
  error: detail3
@@ -28596,7 +28802,7 @@ async function terminateWorkerProcess(identity2, observedNormalExit = false) {
28596
28802
  }
28597
28803
  killed = true;
28598
28804
  }
28599
- await new Promise((resolve8) => setTimeout(resolve8, 25));
28805
+ await new Promise((resolve9) => setTimeout(resolve9, 25));
28600
28806
  }
28601
28807
  return false;
28602
28808
  } catch {
@@ -28628,7 +28834,7 @@ var WorkspaceResources = class {
28628
28834
  }
28629
28835
  register(lease, resource) {
28630
28836
  return inTx(this.db, () => {
28631
- const id = randomUUID25();
28837
+ const id = randomUUID26();
28632
28838
  lease.attach({ id, kind: resource.kind });
28633
28839
  this.db.raw.run(
28634
28840
  "INSERT INTO workspace_resources (id, writer_id, kind, identity_json) VALUES (?, ?, ?, ?)",
@@ -28666,8 +28872,8 @@ var WorkspaceResources = class {
28666
28872
  };
28667
28873
 
28668
28874
  // ../daemon/src/lib/coding-environment/workspace.ts
28669
- import { randomUUID as randomUUID26 } from "crypto";
28670
- import { realpathSync as realpathSync3 } from "fs";
28875
+ import { randomUUID as randomUUID27 } from "crypto";
28876
+ import { realpathSync as realpathSync4, statSync as statSync4 } from "fs";
28671
28877
  import { isAbsolute as isAbsolute3, relative as relative2 } from "path";
28672
28878
  var WorkspaceBusyError = class extends Error {
28673
28879
  constructor(recoveryRequired = false) {
@@ -28685,14 +28891,18 @@ function overlappingWorkspaceRoots(a, b2) {
28685
28891
  return contains(a, b2) || contains(b2, a);
28686
28892
  }
28687
28893
  function workspaceIdentity(registeredRoot) {
28688
- const directory = new ContextDirectory(registeredRoot);
28689
- try {
28690
- const root = realpathSync3(registeredRoot);
28691
- directory.validate();
28692
- return { root, rootIdentity: directory.identity };
28693
- } finally {
28694
- directory.close();
28894
+ if (process.platform === "linux") {
28895
+ const directory = new ContextDirectory(registeredRoot);
28896
+ try {
28897
+ const root2 = realpathSync4(registeredRoot);
28898
+ directory.validate();
28899
+ return { root: root2, rootIdentity: directory.identity };
28900
+ } finally {
28901
+ directory.close();
28902
+ }
28695
28903
  }
28904
+ const root = realpathSync4(registeredRoot);
28905
+ return { root, rootIdentity: hash3(identity(statSync4(root))) };
28696
28906
  }
28697
28907
  function view(row2) {
28698
28908
  return {
@@ -28710,7 +28920,7 @@ var WorkspaceCoordinator = class {
28710
28920
  this.db = db;
28711
28921
  }
28712
28922
  db;
28713
- identity = randomUUID26();
28923
+ identity = randomUUID27();
28714
28924
  leases = /* @__PURE__ */ new Set();
28715
28925
  issued = /* @__PURE__ */ new WeakSet();
28716
28926
  claim(teamId, registeredRoot, kind) {
@@ -28724,7 +28934,7 @@ var WorkspaceCoordinator = class {
28724
28934
  const recovery = row2.daemon_identity !== this.identity || row2.state === "recovery";
28725
28935
  if (recovery || exclusive || row2.exclusive === 1) throw new WorkspaceBusyError(recovery);
28726
28936
  }
28727
- const id = randomUUID26();
28937
+ const id = randomUUID27();
28728
28938
  this.db.raw.run(
28729
28939
  `INSERT INTO workspace_writers
28730
28940
  (id, team_id, root_path, root_identity, daemon_identity, kind, exclusive, state, created_at)
@@ -28843,7 +29053,7 @@ var WorkspaceLifecycle = class {
28843
29053
  const prefix = `bazilion-${lease.writer.id}-`;
28844
29054
  const records2 = /* @__PURE__ */ new Map();
28845
29055
  return {
28846
- name: (kind) => `${prefix}${kind}-${randomUUID27()}`,
29056
+ name: (kind) => `${prefix}${kind}-${randomUUID28()}`,
28847
29057
  beforeCreate: async (identity2) => {
28848
29058
  if (!identity2.containerName.startsWith(prefix) || !/^bazilion-[a-z0-9-]{1,160}$/.test(identity2.containerName) || records2.has(identity2.containerName))
28849
29059
  throw new Error("Invalid turn container identity");
@@ -28878,7 +29088,7 @@ var WorkspaceLifecycle = class {
28878
29088
  };
28879
29089
 
28880
29090
  // ../daemon/src/lib/conversation-target.ts
28881
- import { randomUUID as randomUUID29 } from "crypto";
29091
+ import { randomUUID as randomUUID30 } from "crypto";
28882
29092
 
28883
29093
  // ../daemon/src/core/repos/conversations.ts
28884
29094
  var columns = "id, agent_id AS agentId, title, title_revision AS titleRevision, created_at AS createdAt, updated_at AS updatedAt";
@@ -28919,7 +29129,7 @@ function filename(db, agentId, id) {
28919
29129
  if (!row2) throw new Error("Conversation not found");
28920
29130
  return row2.filename;
28921
29131
  }
28922
- function list14(db, agentId, limit = 20, offset = 0) {
29132
+ function list15(db, agentId, limit = 20, offset = 0) {
28923
29133
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100 || !Number.isSafeInteger(offset) || offset < 0)
28924
29134
  throw new Error("Invalid conversation pagination");
28925
29135
  const conversations = db.raw.query(
@@ -28935,7 +29145,7 @@ function title(value) {
28935
29145
  throw new Error("Conversation title must be 1\u2013200 characters without control characters");
28936
29146
  return value.trim();
28937
29147
  }
28938
- function create5(db, agentId, input, persistFile) {
29148
+ function create6(db, agentId, input, persistFile) {
28939
29149
  if (!uuid3.test(input.requestId)) throw new Error("Conversation requestId must be a UUID");
28940
29150
  if (!input.expectedSelection || !Number.isSafeInteger(input.expectedSelection.revision) || input.expectedSelection.revision < 0 || input.expectedSelection.conversationId !== null && (typeof input.expectedSelection.conversationId !== "string" || !uuid3.test(input.expectedSelection.conversationId)))
28941
29151
  throw new Error("Invalid expected conversation selection");
@@ -28955,7 +29165,7 @@ function create5(db, agentId, input, persistFile) {
28955
29165
  if (!db.raw.query("SELECT id FROM agents WHERE id = ?").get(agentId))
28956
29166
  throw new Error("Agent not found");
28957
29167
  const now = Date.now();
28958
- const displayTitle = initialTitle ?? `Conversation ${list14(db, agentId, 1).total + 1}`;
29168
+ const displayTitle = initialTitle ?? `Conversation ${list15(db, agentId, 1).total + 1}`;
28959
29169
  const file = persistFile(input.requestId);
28960
29170
  if (file !== `${input.requestId}.jsonl`)
28961
29171
  throw new Error("Invalid canonical conversation filename");
@@ -29000,14 +29210,14 @@ function rename(db, agentId, id, value, expectedRevision) {
29000
29210
  }
29001
29211
 
29002
29212
  // ../daemon/src/lib/conversation-file.ts
29003
- import { randomUUID as randomUUID28 } from "crypto";
29213
+ import { randomUUID as randomUUID29 } from "crypto";
29004
29214
  import {
29005
29215
  closeSync as closeSync4,
29006
29216
  constants as constants4,
29007
29217
  fsyncSync,
29008
29218
  linkSync,
29009
29219
  openSync as openSync4,
29010
- realpathSync as realpathSync5,
29220
+ realpathSync as realpathSync6,
29011
29221
  unlinkSync,
29012
29222
  writeFileSync as writeFileSync7
29013
29223
  } from "fs";
@@ -29015,18 +29225,21 @@ import { join as join16 } from "path";
29015
29225
  import { SessionManager } from "@earendil-works/pi-coding-agent";
29016
29226
 
29017
29227
  // ../daemon/src/lib/result-source.ts
29018
- import { closeSync as closeSync3, constants as constants3, fstatSync as fstatSync2, openSync as openSync3, readSync as readSync2, realpathSync as realpathSync4 } from "fs";
29019
- import { basename as basename2, join as join15 } from "path";
29228
+ import { closeSync as closeSync3, constants as constants3, fstatSync as fstatSync2, lstatSync as lstatSync2, openSync as openSync3, readSync as readSync2, realpathSync as realpathSync5 } from "fs";
29229
+ import { basename as basename3, join as join15 } from "path";
29020
29230
  function readResultSession(paths2, agentId, filename2, sessionId, minimumEntryOffset = 0) {
29021
- if (basename2(filename2) !== filename2) throw new Error("Invalid result session filename");
29022
- const directory = join15(realpathSync4(paths2.agentsDir), agentId, "sessions");
29231
+ if (basename3(filename2) !== filename2) throw new Error("Invalid result session filename");
29232
+ const directory = join15(realpathSync5(paths2.agentsDir), agentId, "sessions");
29023
29233
  return readCanonicalSessionFile(directory, filename2, sessionId, minimumEntryOffset);
29024
29234
  }
29025
29235
  function readCanonicalSessionFile(directory, filename2, sessionId, minimumEntryOffset = 0) {
29026
- if (basename2(filename2) !== filename2) throw new Error("Invalid session filename");
29027
- if (realpathSync4(directory) !== directory) throw new Error("Result session escaped its owner");
29236
+ if (basename3(filename2) !== filename2) throw new Error("Invalid session filename");
29237
+ if (realpathSync5(directory) !== directory) throw new Error("Result session escaped its owner");
29238
+ const target = join15(directory, filename2);
29239
+ if (lstatSync2(target).isSymbolicLink())
29240
+ throw new Error("Result session file must not be a symlink");
29028
29241
  const fd = openSync3(
29029
- join15(directory, filename2),
29242
+ target,
29030
29243
  constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK
29031
29244
  );
29032
29245
  try {
@@ -29061,11 +29274,11 @@ var uuid4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
29061
29274
  function createConversationFile(paths2, agentId, conversationId, cwd) {
29062
29275
  if (!uuid4.test(agentId) || !uuid4.test(conversationId))
29063
29276
  throw new Error("Invalid conversation identity");
29064
- const directory = join16(realpathSync5(paths2.agentsDir), agentId, "sessions");
29065
- if (realpathSync5(directory) !== directory) throw new Error("Conversation escaped its Agent");
29277
+ const directory = join16(realpathSync6(paths2.agentsDir), agentId, "sessions");
29278
+ if (realpathSync6(directory) !== directory) throw new Error("Conversation escaped its Agent");
29066
29279
  const filename2 = `${conversationId}.jsonl`;
29067
29280
  const destination = join16(directory, filename2);
29068
- const staging = join16(directory, `.conversation-${randomUUID28()}.tmp`);
29281
+ const staging = join16(directory, `.conversation-${randomUUID29()}.tmp`);
29069
29282
  const header = SessionManager.inMemory(cwd, { id: conversationId }).getHeader();
29070
29283
  const fd = openSync4(staging, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL, 384);
29071
29284
  try {
@@ -29085,6 +29298,8 @@ function createConversationFile(paths2, agentId, conversationId, cwd) {
29085
29298
  const directoryFd = openSync4(directory, constants4.O_RDONLY | constants4.O_DIRECTORY);
29086
29299
  try {
29087
29300
  fsyncSync(directoryFd);
29301
+ } catch (error2) {
29302
+ if (process.platform !== "win32") throw error2;
29088
29303
  } finally {
29089
29304
  closeSync4(directoryFd);
29090
29305
  }
@@ -29099,11 +29314,11 @@ function resolveConversationTarget(db, paths2, agentId, pinnedId) {
29099
29314
  let id = pinnedId ?? selection(db, agentId).conversationId;
29100
29315
  if (!id) {
29101
29316
  const agent = resolveAgent(db, paths2, agentId);
29102
- id = create5(
29317
+ id = create6(
29103
29318
  db,
29104
29319
  agentId,
29105
29320
  {
29106
- requestId: randomUUID29(),
29321
+ requestId: randomUUID30(),
29107
29322
  expectedSelection: { conversationId: null, revision: 0 }
29108
29323
  },
29109
29324
  (newId) => createConversationFile(paths2, agentId, newId, agent.team.path)
@@ -29135,9 +29350,9 @@ function acquireAgentLifecycleLease(agentId) {
29135
29350
  leases.held.add(agentId);
29136
29351
  return Promise.resolve(makeRelease(agentId));
29137
29352
  }
29138
- return new Promise((resolve8) => {
29353
+ return new Promise((resolve9) => {
29139
29354
  const queue = leases.waiters.get(agentId) ?? [];
29140
- queue.push({ resolve: resolve8 });
29355
+ queue.push({ resolve: resolve9 });
29141
29356
  leases.waiters.set(agentId, queue);
29142
29357
  });
29143
29358
  }
@@ -29170,7 +29385,7 @@ async function runAgentLifecycleMutation(agentId, mutation) {
29170
29385
  }
29171
29386
 
29172
29387
  // ../daemon/src/lib/agent-loop-guard.ts
29173
- import { randomUUID as randomUUID30 } from "crypto";
29388
+ import { randomUUID as randomUUID31 } from "crypto";
29174
29389
  var DEFAULT_MAX_HOPS = 8;
29175
29390
  function toEvent(row2) {
29176
29391
  return {
@@ -29222,8 +29437,8 @@ function enforceMessageCausality(db, input) {
29222
29437
  const target = agents_exports.get(db, input.to);
29223
29438
  if (!source || !target) return null;
29224
29439
  const event2 = {
29225
- id: randomUUID30(),
29226
- causalChainId: input.causality.causalChainId ?? input.causality.parentMessageId ?? randomUUID30(),
29440
+ id: randomUUID31(),
29441
+ causalChainId: input.causality.causalChainId ?? input.causality.parentMessageId ?? randomUUID31(),
29227
29442
  parentMessageId: input.causality.parentMessageId,
29228
29443
  fromAgentId: input.from,
29229
29444
  toAgentId: input.to,
@@ -29387,26 +29602,26 @@ import {
29387
29602
  readdirSync as readdirSync6,
29388
29603
  readFileSync as readFileSync9,
29389
29604
  rmSync as rmSync10,
29390
- statSync as statSync4,
29605
+ statSync as statSync5,
29391
29606
  writeFileSync as writeFileSync8
29392
29607
  } from "fs";
29393
- import { dirname as dirname2, join as join17 } from "path";
29608
+ import { dirname as dirname3, join as join17 } from "path";
29394
29609
 
29395
29610
  // ../daemon/src/runtime/memory/qmd.ts
29396
29611
  import {
29397
29612
  closeSync as closeSync5,
29398
29613
  constants as constants5,
29399
29614
  fstatSync as fstatSync3,
29400
- lstatSync as lstatSync2,
29615
+ lstatSync as lstatSync3,
29401
29616
  mkdirSync as mkdirSync5,
29402
29617
  openSync as openSync5,
29403
29618
  readdirSync as readdirSync7,
29404
29619
  readFileSync as readFileSync10,
29405
- realpathSync as realpathSync6,
29620
+ realpathSync as realpathSync7,
29406
29621
  rmSync as rmSync11,
29407
29622
  writeFileSync as writeFileSync9
29408
29623
  } from "fs";
29409
- import { dirname as dirname3, isAbsolute as isAbsolute4, join as join18, relative as relative3, resolve as resolve3, sep as sep3 } from "path";
29624
+ import { dirname as dirname4, isAbsolute as isAbsolute4, join as join18, relative as relative3, resolve as resolve4, sep as sep3 } from "path";
29410
29625
  import { createStore, extractSnippet } from "@tobilu/qmd";
29411
29626
 
29412
29627
  // ../daemon/src/lib/native-module-error.ts
@@ -29473,7 +29688,7 @@ function unsafeMemoryPath(path, reason) {
29473
29688
  }
29474
29689
  function lstatIfPresent(path) {
29475
29690
  try {
29476
- return lstatSync2(path);
29691
+ return lstatSync3(path);
29477
29692
  } catch (error2) {
29478
29693
  if (error2.code === "ENOENT") return void 0;
29479
29694
  throw error2;
@@ -29490,14 +29705,14 @@ function assertContained(root, candidate) {
29490
29705
  }
29491
29706
  function initializeSafeRoot(root) {
29492
29707
  mkdirSync5(root, { recursive: true });
29493
- const info = lstatSync2(root);
29708
+ const info = lstatSync3(root);
29494
29709
  if (info.isSymbolicLink()) {
29495
29710
  throw unsafeMemoryPath(root, "memory root must not be a symbolic link");
29496
29711
  }
29497
29712
  if (!info.isDirectory()) {
29498
29713
  throw unsafeMemoryPath(root, "memory root is not a directory");
29499
29714
  }
29500
- return realpathSync6(root);
29715
+ return realpathSync7(root);
29501
29716
  }
29502
29717
  function assertRootUnchanged(root, canonicalRoot) {
29503
29718
  const info = lstatIfPresent(root);
@@ -29508,7 +29723,7 @@ function assertRootUnchanged(root, canonicalRoot) {
29508
29723
  if (!info.isDirectory()) {
29509
29724
  throw unsafeMemoryPath(root, "memory root is not a directory");
29510
29725
  }
29511
- const current = realpathSync6(root);
29726
+ const current = realpathSync7(root);
29512
29727
  if (relative3(canonicalRoot, current) !== "" || relative3(current, canonicalRoot) !== "") {
29513
29728
  throw unsafeMemoryPath(root, "memory root changed after initialization");
29514
29729
  }
@@ -29518,7 +29733,7 @@ function safeKey(root, key3) {
29518
29733
  if (key3.length === 0 || key3.includes("\0") || isAbsolute4(key3) || /^[A-Za-z]:[\\/]/.test(key3) || key3.startsWith("\\\\") || segments.includes("..")) {
29519
29734
  throw new Error(`unsafe memory key: ${key3}`);
29520
29735
  }
29521
- const candidate = resolve3(root, key3);
29736
+ const candidate = resolve4(root, key3);
29522
29737
  if (candidate === root) throw new Error(`unsafe memory key: ${key3}`);
29523
29738
  assertContained(root, candidate);
29524
29739
  return candidate;
@@ -29538,12 +29753,12 @@ function inspectSafePath(root, path) {
29538
29753
  if (index < components.length - 1 && !info.isDirectory()) {
29539
29754
  throw unsafeMemoryPath(current, "path ancestor is not a directory");
29540
29755
  }
29541
- assertContained(root, realpathSync6(current));
29756
+ assertContained(root, realpathSync7(current));
29542
29757
  }
29543
29758
  return lstatIfPresent(path);
29544
29759
  }
29545
29760
  function ensureSafeParentDirectories(root, path) {
29546
- const parent = dirname3(path);
29761
+ const parent = dirname4(path);
29547
29762
  assertContained(root, parent);
29548
29763
  const rel = relative3(root, parent);
29549
29764
  let current = root;
@@ -29552,7 +29767,7 @@ function ensureSafeParentDirectories(root, path) {
29552
29767
  let info = lstatIfPresent(current);
29553
29768
  if (!info) {
29554
29769
  mkdirSync5(current);
29555
- info = lstatSync2(current);
29770
+ info = lstatSync3(current);
29556
29771
  }
29557
29772
  if (info.isSymbolicLink()) {
29558
29773
  throw unsafeMemoryPath(current, "symbolic-link ancestors are not allowed");
@@ -29560,7 +29775,7 @@ function ensureSafeParentDirectories(root, path) {
29560
29775
  if (!info.isDirectory()) {
29561
29776
  throw unsafeMemoryPath(current, "path ancestor is not a directory");
29562
29777
  }
29563
- assertContained(root, realpathSync6(current));
29778
+ assertContained(root, realpathSync7(current));
29564
29779
  }
29565
29780
  }
29566
29781
  function readSafeFile(root, path) {
@@ -29612,10 +29827,10 @@ function writeSafeFile(root, path, content) {
29612
29827
  }
29613
29828
  }
29614
29829
  function assertSafeTree(root, dir = root) {
29615
- assertContained(root, realpathSync6(dir));
29830
+ assertContained(root, realpathSync7(dir));
29616
29831
  for (const entry of readdirSync7(dir, { withFileTypes: true })) {
29617
29832
  const full = join18(dir, entry.name);
29618
- const info = lstatSync2(full);
29833
+ const info = lstatSync3(full);
29619
29834
  if (info.isSymbolicLink()) {
29620
29835
  throw unsafeMemoryPath(full, "symbolic links are not allowed in memory storage");
29621
29836
  }
@@ -29629,7 +29844,7 @@ function assertSafeTree(root, dir = root) {
29629
29844
  function walkMd(root, dir, prefix, out) {
29630
29845
  for (const entry of readdirSync7(dir, { withFileTypes: true })) {
29631
29846
  const full = join18(dir, entry.name);
29632
- const info = lstatSync2(full);
29847
+ const info = lstatSync3(full);
29633
29848
  if (info.isSymbolicLink()) {
29634
29849
  throw unsafeMemoryPath(full, "symbolic links are not allowed in memory storage");
29635
29850
  }
@@ -30599,7 +30814,7 @@ var keys = (value, required3, optional2 = []) => required3.every((key3) => Objec
30599
30814
  var string = (value, limit = 4096) => typeof value === "string" && value.length <= limit;
30600
30815
  var digest3 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
30601
30816
  var count2 = (value) => Number.isSafeInteger(value) && value >= 0;
30602
- var list15 = (value, limit, check) => Array.isArray(value) && value.length <= limit && value.every(check);
30817
+ var list16 = (value, limit, check) => Array.isArray(value) && value.length <= limit && value.every(check);
30603
30818
  var issue = (value) => object2(value) && keys(value, ["code", "message"], ["path"]) && string(value.code, 100) && string(value.message, 1024) && (value.path === void 0 || string(value.path));
30604
30819
  function assertRepositoryContext(value, teamId) {
30605
30820
  if (!object2(value) || !keys(value, [
@@ -30628,15 +30843,15 @@ function assertRepositoryContext(value, teamId) {
30628
30843
  "untracked",
30629
30844
  "conflicted",
30630
30845
  "issues"
30631
- ]) || !["complete", "incomplete"].includes(String(instructions.state)) || !list15(instructions.issues, 128, issue) || !list15(
30846
+ ]) || !["complete", "incomplete"].includes(String(instructions.state)) || !list16(instructions.issues, 128, issue) || !list16(
30632
30847
  instructions.files,
30633
30848
  17,
30634
30849
  (file) => object2(file) && keys(file, ["path", "scope", "precedence", "sha256", "content"]) && string(file.path) && string(file.scope) && count2(file.precedence) && digest3(file.sha256) && string(file.content, 64 * 1024) && Buffer.byteLength(file.content) <= 64 * 1024
30635
- ) || !["complete", "incomplete"].includes(String(commands.state)) || !list15(commands.issues, 128, issue) || !list15(
30850
+ ) || !["complete", "incomplete"].includes(String(commands.state)) || !list16(commands.issues, 128, issue) || !list16(
30636
30851
  commands.sources,
30637
30852
  32,
30638
30853
  (source) => object2(source) && keys(source, ["path", "sha256"]) && string(source.path) && digest3(source.sha256)
30639
- ) || !list15(
30854
+ ) || !list16(
30640
30855
  commands.candidates,
30641
30856
  32,
30642
30857
  (candidate) => object2(candidate) && keys(candidate, [
@@ -30648,7 +30863,7 @@ function assertRepositoryContext(value, teamId) {
30648
30863
  "kind",
30649
30864
  "packageManager"
30650
30865
  ]) && string(candidate.source) && digest3(candidate.sha256) && string(candidate.location) && string(candidate.cwd) && string(candidate.command) && ["script", "excerpt"].includes(String(candidate.kind)) && [null, "npm", "pnpm", "yarn"].includes(candidate.packageManager)
30651
- ) || !["available", "unavailable", "not_repository"].includes(String(git2.state)) || ![null, "branch", "detached", "unborn"].includes(git2.headState) || ![git2.root, git2.branch, git2.head].every((value2) => value2 === null || string(value2)) || ![git2.staged, git2.unstaged, git2.untracked, git2.conflicted].every(count2) || !list15(git2.issues, 128, issue))
30866
+ ) || !["available", "unavailable", "not_repository"].includes(String(git2.state)) || ![null, "branch", "detached", "unborn"].includes(git2.headState) || ![git2.root, git2.branch, git2.head].every((value2) => value2 === null || string(value2)) || ![git2.staged, git2.unstaged, git2.untracked, git2.conflicted].every(count2) || !list16(git2.issues, 128, issue))
30652
30867
  throw new Error("Invalid repository context report");
30653
30868
  const report2 = value;
30654
30869
  if (report2.instructions.files.reduce((bytes, file) => bytes + Buffer.byteLength(file.content), 0) > 128 * 1024 || report2.instructions.state === "complete" && (report2.rootIdentity === null || report2.instructions.issues.length > 0))
@@ -30741,8 +30956,8 @@ ${JSON.stringify(current.commands)}`
30741
30956
  }
30742
30957
 
30743
30958
  // ../daemon/src/runtime/pi/session.ts
30744
- import { existsSync as existsSync15, mkdirSync as mkdirSync8, statSync as statSync7, writeFileSync as writeFileSync11 } from "fs";
30745
- import { basename as basename4, join as join24 } from "path";
30959
+ import { existsSync as existsSync15, mkdirSync as mkdirSync8, statSync as statSync8, writeFileSync as writeFileSync11 } from "fs";
30960
+ import { basename as basename5, join as join24 } from "path";
30746
30961
  import {
30747
30962
  createAssistantMessageEventStream
30748
30963
  } from "@earendil-works/pi-ai";
@@ -31260,14 +31475,14 @@ function isRetryableError(err) {
31260
31475
  return false;
31261
31476
  }
31262
31477
  function sleepWithAbort(ms, signal) {
31263
- return new Promise((resolve8, reject2) => {
31478
+ return new Promise((resolve9, reject2) => {
31264
31479
  if (signal?.aborted) {
31265
31480
  reject2(new Error("aborted"));
31266
31481
  return;
31267
31482
  }
31268
31483
  const t = setTimeout(() => {
31269
31484
  if (signal) signal.removeEventListener("abort", onAbort);
31270
- resolve8();
31485
+ resolve9();
31271
31486
  }, ms);
31272
31487
  const onAbort = () => {
31273
31488
  clearTimeout(t);
@@ -31859,47 +32074,47 @@ import {
31859
32074
  closeSync as closeSync6,
31860
32075
  constants as constants6,
31861
32076
  fstatSync as fstatSync4,
31862
- lstatSync as lstatSync3,
32077
+ lstatSync as lstatSync4,
31863
32078
  mkdirSync as mkdirSync6,
31864
32079
  openSync as openSync6,
31865
32080
  readFileSync as readFileSync11,
31866
- realpathSync as realpathSync7
32081
+ realpathSync as realpathSync8
31867
32082
  } from "fs";
31868
- import { dirname as dirname4, isAbsolute as isAbsolute5, relative as relative4, resolve as resolve4 } from "path";
32083
+ import { dirname as dirname5, isAbsolute as isAbsolute5, relative as relative4, resolve as resolve5 } from "path";
31869
32084
  function resolveRealDirectory(path) {
31870
- const requested = resolve4(path);
31871
- const entry = lstatSync3(requested);
32085
+ const requested = resolve5(path);
32086
+ const entry = lstatSync4(requested);
31872
32087
  if (entry.isSymbolicLink() || !entry.isDirectory()) {
31873
32088
  throw new Error("expected a real directory");
31874
32089
  }
31875
- return realpathSync7(requested);
32090
+ return realpathSync8(requested);
31876
32091
  }
31877
32092
  function ensureContainedRealDirectory(path, root, options = {}) {
31878
- const requestedRoot = resolve4(root);
31879
- const requested = resolve4(path);
32093
+ const requestedRoot = resolve5(root);
32094
+ const requested = resolve5(path);
31880
32095
  if (!isContained2(requestedRoot, requested)) throw new Error("directory escapes its root");
31881
- const canonicalRoot = realpathSync7(requestedRoot);
32096
+ const canonicalRoot = realpathSync8(requestedRoot);
31882
32097
  try {
31883
- const entry = lstatSync3(requested);
32098
+ const entry = lstatSync4(requested);
31884
32099
  if (entry.isSymbolicLink() || !entry.isDirectory()) {
31885
32100
  throw new Error("expected a real directory");
31886
32101
  }
31887
32102
  } catch (error2) {
31888
32103
  if (error2.code !== "ENOENT" || !options.create) throw error2;
31889
- const canonicalParent = realpathSync7(dirname4(requested));
32104
+ const canonicalParent = realpathSync8(dirname5(requested));
31890
32105
  if (!isContained2(canonicalRoot, canonicalParent)) throw new Error("directory escapes its root");
31891
32106
  mkdirSync6(requested, { recursive: true, mode: 448 });
31892
- const entry = lstatSync3(requested);
32107
+ const entry = lstatSync4(requested);
31893
32108
  if (entry.isSymbolicLink() || !entry.isDirectory()) {
31894
32109
  throw new Error("expected a real directory");
31895
32110
  }
31896
32111
  }
31897
- const canonical = realpathSync7(requested);
32112
+ const canonical = realpathSync8(requested);
31898
32113
  if (!isContained2(canonicalRoot, canonical)) throw new Error("directory escapes its root");
31899
32114
  return canonical;
31900
32115
  }
31901
32116
  function readRegularFileNoFollow(path) {
31902
- const entry = lstatSync3(path);
32117
+ const entry = lstatSync4(path);
31903
32118
  if (entry.isSymbolicLink()) throw new Error("symbolic links are not allowed");
31904
32119
  if (!entry.isFile()) throw new Error("target is not a regular file");
31905
32120
  let fd;
@@ -32090,8 +32305,8 @@ function boundReviewedLessons(lessons, maxCharacters = 8e3) {
32090
32305
  }
32091
32306
 
32092
32307
  // ../daemon/src/runtime/shell/tooling.ts
32093
- import { existsSync as existsSync12, lstatSync as lstatSync4, realpathSync as realpathSync8 } from "fs";
32094
- import { dirname as dirname5, isAbsolute as isAbsolute6, join as join20, relative as relative5, sep as sep4 } from "path";
32308
+ import { existsSync as existsSync12, lstatSync as lstatSync5, realpathSync as realpathSync9 } from "fs";
32309
+ import { dirname as dirname6, isAbsolute as isAbsolute6, join as join20, relative as relative5, sep as sep4 } from "path";
32095
32310
  import {
32096
32311
  createBashToolDefinition,
32097
32312
  createLocalBashOperations as createLocalBashOperations2,
@@ -32149,9 +32364,9 @@ function createSessionShellTools(cwd, env, options = {}) {
32149
32364
  env: buildSandboxContainerEnv(env, config2.envAllowlist),
32150
32365
  readOnlyMounts: [
32151
32366
  ...existsSync12(join20(cwd, "memory")) ? [safeReadOnlyMount(join20(cwd, "memory"), SANDBOX_MEMORY_DIR, cwd)] : [],
32152
- ...options.inputsDir ? [safeReadOnlyMount(options.inputsDir, SANDBOX_INPUTS_DIR, dirname5(options.inputsDir))] : [],
32367
+ ...options.inputsDir ? [safeReadOnlyMount(options.inputsDir, SANDBOX_INPUTS_DIR, dirname6(options.inputsDir))] : [],
32153
32368
  ...(options.skillMounts ?? []).map(
32154
- (mount) => safeReadOnlyMount(mount.source, mount.target, dirname5(mount.source))
32369
+ (mount) => safeReadOnlyMount(mount.source, mount.target, dirname6(mount.source))
32155
32370
  )
32156
32371
  ]
32157
32372
  });
@@ -32165,12 +32380,12 @@ function createSessionShellTools(cwd, env, options = {}) {
32165
32380
  return { config: config2, hostToolNames: [], customBash };
32166
32381
  }
32167
32382
  function safeReadOnlyMount(source, target, expectedRoot) {
32168
- const info = lstatSync4(source);
32383
+ const info = lstatSync5(source);
32169
32384
  if (info.isSymbolicLink() || !info.isDirectory()) {
32170
32385
  throw new Error(`Docker sandbox read-only mount must be a real directory: ${source}`);
32171
32386
  }
32172
- const sourceRoot = realpathSync8(expectedRoot);
32173
- const canonicalSource = realpathSync8(source);
32387
+ const sourceRoot = realpathSync9(expectedRoot);
32388
+ const canonicalSource = realpathSync9(source);
32174
32389
  const rel = relative5(sourceRoot, canonicalSource);
32175
32390
  const contained = rel === "" || rel !== ".." && !rel.startsWith(`..${sep4}`) && !isAbsolute6(rel);
32176
32391
  if (!contained) {
@@ -32183,18 +32398,18 @@ function safeReadOnlyMount(source, target, expectedRoot) {
32183
32398
  import {
32184
32399
  constants as constants7,
32185
32400
  existsSync as existsSync13,
32186
- lstatSync as lstatSync5,
32401
+ lstatSync as lstatSync6,
32187
32402
  mkdirSync as mkdirSync7,
32188
32403
  mkdtempSync as mkdtempSync3,
32189
- realpathSync as realpathSync9,
32404
+ realpathSync as realpathSync10,
32190
32405
  rmSync as rmSync12,
32191
- statSync as statSync5
32406
+ statSync as statSync6
32192
32407
  } from "fs";
32193
32408
  import { access as access2 } from "fs/promises";
32194
32409
  import { tmpdir as tmpdir3 } from "os";
32195
32410
  import { isAbsolute as isAbsolute7, join as join21, relative as relative6, sep as sep5 } from "path";
32196
32411
  var REDACTED_VALUE = "[REDACTED]";
32197
- var REASONING_LEVELS = /* @__PURE__ */ new Set([
32412
+ var REASONING_LEVELS2 = /* @__PURE__ */ new Set([
32198
32413
  "off",
32199
32414
  "minimal",
32200
32415
  "low",
@@ -32507,7 +32722,7 @@ function assertProtectedProviderRuntime(value) {
32507
32722
  }
32508
32723
  if (!nonEmptyString(runtime.modelId))
32509
32724
  throw new Error("protected provider runtime requires a model id");
32510
- if (!REASONING_LEVELS.has(runtime.reasoningLevel)) {
32725
+ if (!REASONING_LEVELS2.has(runtime.reasoningLevel)) {
32511
32726
  throw new Error("protected provider runtime requires a valid reasoning level");
32512
32727
  }
32513
32728
  if (runtime.apiKey !== void 0 && !nonEmptyString(runtime.apiKey)) {
@@ -32874,11 +33089,11 @@ function containsUnsafeDockerArgument(value) {
32874
33089
  function requireCanonicalRealDirectory(value, name) {
32875
33090
  if (typeof value !== "string") throw new Error(`worker: ${name} must be a path`);
32876
33091
  try {
32877
- const entry = lstatSync5(value);
33092
+ const entry = lstatSync6(value);
32878
33093
  if (entry.isSymbolicLink() || !entry.isDirectory()) {
32879
33094
  throw new Error("unsafe entry");
32880
33095
  }
32881
- const canonical = realpathSync9(value);
33096
+ const canonical = realpathSync10(value);
32882
33097
  if (canonical !== value) throw new Error("non-canonical entry");
32883
33098
  return canonical;
32884
33099
  } catch {
@@ -32887,9 +33102,9 @@ function requireCanonicalRealDirectory(value, name) {
32887
33102
  }
32888
33103
  function resolveCanonicalDirectory(value, name) {
32889
33104
  try {
32890
- const entry = statSync5(value);
33105
+ const entry = statSync6(value);
32891
33106
  if (!entry.isDirectory()) throw new Error("not a directory");
32892
- return realpathSync9(value);
33107
+ return realpathSync10(value);
32893
33108
  } catch {
32894
33109
  throw new Error(`worker: ${name} is unavailable or unsafe`);
32895
33110
  }
@@ -32922,16 +33137,16 @@ function assertMinimalWorkerScratch(value) {
32922
33137
  }
32923
33138
  }
32924
33139
  function requireCanonicalWindowsDirectory(value, name) {
32925
- if (!value || !isAbsolute7(value) || !existsSync13(value) || !statSync5(value).isDirectory()) {
33140
+ if (!value || !isAbsolute7(value) || !existsSync13(value) || !statSync6(value).isDirectory()) {
32926
33141
  throw new Error(`minimal worker bootstrap requires a valid ${name} directory`);
32927
33142
  }
32928
- return realpathSync9(value);
33143
+ return realpathSync10(value);
32929
33144
  }
32930
33145
  function requireCanonicalWindowsFile(value, name) {
32931
- if (!value || !isAbsolute7(value) || !existsSync13(value) || !statSync5(value).isFile()) {
33146
+ if (!value || !isAbsolute7(value) || !existsSync13(value) || !statSync6(value).isFile()) {
32932
33147
  throw new Error(`minimal worker bootstrap requires a valid ${name} executable`);
32933
33148
  }
32934
- return realpathSync9(value);
33149
+ return realpathSync10(value);
32935
33150
  }
32936
33151
  function objectRecord(value, label) {
32937
33152
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -33183,10 +33398,10 @@ import {
33183
33398
  fstatSync as fstatSync5,
33184
33399
  openSync as openSync7,
33185
33400
  readSync as readSync3,
33186
- realpathSync as realpathSync10,
33187
- statSync as statSync6
33401
+ realpathSync as realpathSync11,
33402
+ statSync as statSync7
33188
33403
  } from "fs";
33189
- import { basename as basename3, extname, isAbsolute as isAbsolute8, relative as relative7, resolve as resolve5, sep as sep6 } from "path";
33404
+ import { basename as basename4, extname, isAbsolute as isAbsolute8, relative as relative7, resolve as resolve6, sep as sep6 } from "path";
33190
33405
  var MAX_DELIVER_BYTES = 25 * 1024 * 1024;
33191
33406
  var MIME = {
33192
33407
  ".pdf": "application/pdf",
@@ -33207,10 +33422,10 @@ function isWithin2(root, candidate) {
33207
33422
  return rel === "" || rel !== ".." && !rel.startsWith(`..${sep6}`) && !isAbsolute8(rel);
33208
33423
  }
33209
33424
  function deliverFileTool(cwd, sink, sessionId = "") {
33210
- const workspacePath = resolve5(cwd);
33425
+ const workspacePath = resolve6(cwd);
33211
33426
  let workspaceRealPath = null;
33212
33427
  try {
33213
- workspaceRealPath = realpathSync10(workspacePath);
33428
+ workspaceRealPath = realpathSync11(workspacePath);
33214
33429
  } catch {
33215
33430
  }
33216
33431
  return {
@@ -33235,7 +33450,7 @@ function deliverFileTool(cwd, sink, sessionId = "") {
33235
33450
  if (isAbsolute8(p)) {
33236
33451
  throw new Error(`deliver_file: path must stay within the workspace: ${p}`);
33237
33452
  }
33238
- const abs = resolve5(workspacePath, p);
33453
+ const abs = resolve6(workspacePath, p);
33239
33454
  if (!isWithin2(workspacePath, abs)) {
33240
33455
  throw new Error(`deliver_file: path must stay within the workspace: ${p}`);
33241
33456
  }
@@ -33245,8 +33460,8 @@ function deliverFileTool(cwd, sink, sessionId = "") {
33245
33460
  let real;
33246
33461
  let expected;
33247
33462
  try {
33248
- real = realpathSync10(abs);
33249
- expected = statSync6(real);
33463
+ real = realpathSync11(abs);
33464
+ expected = statSync7(real);
33250
33465
  } catch {
33251
33466
  throw new Error(`deliver_file: no such file: ${p}`);
33252
33467
  }
@@ -33270,7 +33485,7 @@ function deliverFileTool(cwd, sink, sessionId = "") {
33270
33485
  }
33271
33486
  let confirmedReal;
33272
33487
  try {
33273
- confirmedReal = realpathSync10(abs);
33488
+ confirmedReal = realpathSync11(abs);
33274
33489
  } catch {
33275
33490
  throw new Error(`deliver_file: path changed during validation: ${p}`);
33276
33491
  }
@@ -33279,7 +33494,7 @@ function deliverFileTool(cwd, sink, sessionId = "") {
33279
33494
  }
33280
33495
  if (stat2.size > MAX_DELIVER_BYTES) {
33281
33496
  throw new Error(
33282
- `deliver_file: "${basename3(abs)}" is too large (${(stat2.size / 1024 / 1024).toFixed(1)} MB > 25 MB)`
33497
+ `deliver_file: "${basename4(abs)}" is too large (${(stat2.size / 1024 / 1024).toFixed(1)} MB > 25 MB)`
33283
33498
  );
33284
33499
  }
33285
33500
  const buffer = Buffer.alloc(MAX_DELIVER_BYTES + 1);
@@ -33294,7 +33509,7 @@ function deliverFileTool(cwd, sink, sessionId = "") {
33294
33509
  } finally {
33295
33510
  closeSync7(fd);
33296
33511
  }
33297
- const name = basename3(abs);
33512
+ const name = basename4(abs);
33298
33513
  const mimeType = MIME[extname(abs).toLowerCase()] ?? "application/octet-stream";
33299
33514
  if (!context?.toolCallId || !sessionId)
33300
33515
  throw new Error("deliver_file: missing source operation");
@@ -33320,7 +33535,7 @@ import {
33320
33535
  closeSync as closeSync8,
33321
33536
  constants as constants9,
33322
33537
  fstatSync as fstatSync6,
33323
- lstatSync as lstatSync6,
33538
+ lstatSync as lstatSync7,
33324
33539
  openSync as openSync8,
33325
33540
  readdirSync as readdirSync9,
33326
33541
  writeFileSync as writeFileSync10
@@ -33417,7 +33632,7 @@ function homeTools(agentDir) {
33417
33632
  for (const file of HOME_FILES_READABLE) {
33418
33633
  const path = privateHomeFile(homeRoot, file);
33419
33634
  try {
33420
- const s = lstatSync6(path);
33635
+ const s = lstatSync7(path);
33421
33636
  if (s.isSymbolicLink() || !s.isFile()) continue;
33422
33637
  entries.push(`${file} (${s.size}b)`);
33423
33638
  } catch {
@@ -33449,7 +33664,7 @@ function privateHomeFile(homeRoot, file) {
33449
33664
  return join23(homeRoot, file);
33450
33665
  }
33451
33666
  function rejectSymlinkOrNonFile(path) {
33452
- const entry = lstatSync6(path);
33667
+ const entry = lstatSync7(path);
33453
33668
  if (entry.isSymbolicLink()) throw new Error("symbolic links are not allowed");
33454
33669
  if (!entry.isFile()) throw new Error("target is not a regular file");
33455
33670
  }
@@ -34793,8 +35008,8 @@ function loadSessionHead(agent, paths2, target) {
34793
35008
  const recent = target ? explicitConversationFile(sessionDir, target) : null;
34794
35009
  if (!recent) return { file: null, size: 0 };
34795
35010
  try {
34796
- const s = statSync7(recent);
34797
- return { file: basename4(recent), size: s.size };
35011
+ const s = statSync8(recent);
35012
+ return { file: basename5(recent), size: s.size };
34798
35013
  } catch {
34799
35014
  return { file: null, size: 0 };
34800
35015
  }
@@ -34962,7 +35177,7 @@ function assertSelectedProvider(requested, expected) {
34962
35177
  }
34963
35178
  function waitForRefresh(pending, signal) {
34964
35179
  if (!signal) return pending;
34965
- return new Promise((resolve8, reject2) => {
35180
+ return new Promise((resolve9, reject2) => {
34966
35181
  let settled = false;
34967
35182
  const finish = (callback) => {
34968
35183
  if (settled) return;
@@ -34977,7 +35192,7 @@ function waitForRefresh(pending, signal) {
34977
35192
  return;
34978
35193
  }
34979
35194
  pending.then(
34980
- (value) => finish(() => resolve8(value)),
35195
+ (value) => finish(() => resolve9(value)),
34981
35196
  (error2) => finish(() => reject2(error2))
34982
35197
  );
34983
35198
  });
@@ -35213,12 +35428,12 @@ async function* spawnWorker(spec, opts) {
35213
35428
  if (opts.signal?.aborted) onAbort();
35214
35429
  else opts.signal?.addEventListener("abort", onAbort);
35215
35430
  const waitForExit = new Promise(
35216
- (resolve8) => {
35431
+ (resolve9) => {
35217
35432
  if (child.exitCode !== null || child.signalCode !== null) {
35218
- resolve8({ code: child.exitCode, signal: child.signalCode });
35433
+ resolve9({ code: child.exitCode, signal: child.signalCode });
35219
35434
  return;
35220
35435
  }
35221
- child.once("close", (code, signal) => resolve8({ code, signal }));
35436
+ child.once("close", (code, signal) => resolve9({ code, signal }));
35222
35437
  }
35223
35438
  );
35224
35439
  let emittedFatal = false;
@@ -35662,7 +35877,7 @@ var AsyncFrameQueue = class {
35662
35877
  const frame = this.#frames.shift();
35663
35878
  if (frame) return Promise.resolve({ done: false, value: frame });
35664
35879
  if (this.#ended) return Promise.resolve({ done: true, value: void 0 });
35665
- return new Promise((resolve8) => this.#waiters.push(resolve8));
35880
+ return new Promise((resolve9) => this.#waiters.push(resolve9));
35666
35881
  }
35667
35882
  };
35668
35883
  }
@@ -35832,8 +36047,8 @@ var CommandApprovalRegistry = class {
35832
36047
  return { approval, decision: Promise.resolve(decision2) };
35833
36048
  }
35834
36049
  let resolveDecision;
35835
- const decision = new Promise((resolve8) => {
35836
- resolveDecision = resolve8;
36050
+ const decision = new Promise((resolve9) => {
36051
+ resolveDecision = resolve9;
35837
36052
  });
35838
36053
  const timer = setTimeout(() => {
35839
36054
  this.#settle(input.id, "deny", "timeout");
@@ -36047,11 +36262,11 @@ async function getSsrfProxy() {
36047
36262
  if (serverUrl) return serverUrl;
36048
36263
  const s = createServer(onRequest);
36049
36264
  s.on("connect", onConnect);
36050
- await new Promise((resolve8, reject2) => {
36265
+ await new Promise((resolve9, reject2) => {
36051
36266
  s.once("error", reject2);
36052
36267
  s.listen(0, "127.0.0.1", () => {
36053
36268
  s.off("error", reject2);
36054
- resolve8();
36269
+ resolve9();
36055
36270
  });
36056
36271
  });
36057
36272
  const addr = s.address();
@@ -36066,7 +36281,7 @@ async function closeSsrfProxy() {
36066
36281
  server = null;
36067
36282
  serverUrl = null;
36068
36283
  if (!s) return;
36069
- await new Promise((resolve8) => s.close(() => resolve8()));
36284
+ await new Promise((resolve9) => s.close(() => resolve9()));
36070
36285
  }
36071
36286
 
36072
36287
  // ../daemon/src/lib/resources.ts
@@ -36446,7 +36661,7 @@ function createBrowserHost(config2) {
36446
36661
  }
36447
36662
 
36448
36663
  // ../daemon/src/lib/coding-environment/agent-host.ts
36449
- import { createHash as createHash10, randomUUID as randomUUID33 } from "crypto";
36664
+ import { createHash as createHash11, randomUUID as randomUUID34 } from "crypto";
36450
36665
 
36451
36666
  // ../daemon/src/core/repos/coding-command-logs.ts
36452
36667
  var CODING_LOG_BYTES = 2 * 1024 * 1024;
@@ -36666,7 +36881,7 @@ function pruneCodingCommandLogs(db, now = Date.now(), budgetBytes = CODING_LOG_H
36666
36881
  }
36667
36882
 
36668
36883
  // ../daemon/src/lib/communication.ts
36669
- import { randomUUID as randomUUID32 } from "crypto";
36884
+ import { randomUUID as randomUUID33 } from "crypto";
36670
36885
 
36671
36886
  // ../daemon/src/lib/question-approval.ts
36672
36887
  function questionApprovalReference(snapshot, kind) {
@@ -36761,7 +36976,7 @@ function questionVisible(db, item) {
36761
36976
  }
36762
36977
 
36763
36978
  // ../daemon/src/core/repos/results.ts
36764
- import { createHash as createHash9, randomUUID as randomUUID31 } from "crypto";
36979
+ import { createHash as createHash10, randomUUID as randomUUID32 } from "crypto";
36765
36980
  var MAX_RESULT_BYTES = 25 * 1024 * 1024;
36766
36981
  var MAX_RETAINED_RESULT_BYTES = 1024 * 1024 * 1024;
36767
36982
  var columns2 = `id, team_id AS teamId, agent_id AS agentId, source_kind AS sourceKind,
@@ -36796,7 +37011,7 @@ function publish(db, input) {
36796
37011
  throw new Error("Result exceeds the 25 MiB per-file limit");
36797
37012
  }
36798
37013
  const bytes = Buffer.from(input.bytes);
36799
- const sha256 = createHash9("sha256").update(bytes).digest("hex");
37014
+ const sha256 = createHash10("sha256").update(bytes).digest("hex");
36800
37015
  return db.raw.transaction(() => {
36801
37016
  const existing = source === "session_tool" ? db.raw.query(
36802
37017
  `SELECT ${columns2} FROM agent_results
@@ -36824,7 +37039,7 @@ function publish(db, input) {
36824
37039
  "Result storage is full (1 GiB). Delete saved results before delivering more files."
36825
37040
  );
36826
37041
  }
36827
- const id = randomUUID31();
37042
+ const id = randomUUID32();
36828
37043
  db.raw.run(
36829
37044
  `INSERT INTO agent_results
36830
37045
  (id, team_id, agent_id, source_kind, session_id, tool_call_id, review_packet_id, review_revision,
@@ -36897,7 +37112,7 @@ function readCaptured(db, id) {
36897
37112
  ).get(id);
36898
37113
  if (!row2) throw new Error("Captured result is unavailable");
36899
37114
  const bytes = Buffer.from(row2.bytes);
36900
- if (bytes.byteLength !== row2.byte_length || createHash9("sha256").update(bytes).digest("hex") !== row2.sha256) {
37115
+ if (bytes.byteLength !== row2.byte_length || createHash10("sha256").update(bytes).digest("hex") !== row2.sha256) {
36901
37116
  throw new Error("Captured result failed integrity verification");
36902
37117
  }
36903
37118
  return bytes;
@@ -37144,7 +37359,7 @@ function isUserFacingFrame(frame) {
37144
37359
  }
37145
37360
  function sendAgentMessage(db, input) {
37146
37361
  const attemptKind = input.attemptKind ?? "agent_tool";
37147
- const attemptId = input.attemptId ?? randomUUID32();
37362
+ const attemptId = input.attemptId ?? randomUUID33();
37148
37363
  const outcome = db.raw.transaction(
37149
37364
  () => {
37150
37365
  const causality = resolveMessageCausality(db, input);
@@ -37576,7 +37791,7 @@ async function captureRepositoryGit(root, budgetMs = INSPECTION_BUDGET_MS) {
37576
37791
  rmSync14(scratch, { recursive: true, force: true });
37577
37792
  };
37578
37793
  try {
37579
- const rawGit = (args) => new Promise((resolve8, reject2) => {
37794
+ const rawGit = (args) => new Promise((resolve9, reject2) => {
37580
37795
  execFile(
37581
37796
  "git",
37582
37797
  args,
@@ -37597,7 +37812,7 @@ async function captureRepositoryGit(root, budgetMs = INSPECTION_BUDGET_MS) {
37597
37812
  maxBuffer: RUN_MAX_BUFFER,
37598
37813
  encoding: "utf8"
37599
37814
  },
37600
- (error2, stdout) => error2 ? reject2(error2) : resolve8(stdout)
37815
+ (error2, stdout) => error2 ? reject2(error2) : resolve9(stdout)
37601
37816
  );
37602
37817
  });
37603
37818
  const inspectionArgs = (args) => [
@@ -37726,51 +37941,6 @@ objectformat = ${value}`
37726
37941
  }
37727
37942
  }
37728
37943
 
37729
- // ../../packages/api-types/src/entities.ts
37730
- var REASONING_LEVELS2 = [
37731
- "off",
37732
- "minimal",
37733
- "low",
37734
- "medium",
37735
- "high",
37736
- "xhigh"
37737
- ];
37738
-
37739
- // ../../packages/api-types/src/git-review.ts
37740
- var REVIEW_LIMITS2 = {
37741
- files: 1e3,
37742
- fileBytes: 1024 * 1024,
37743
- totalBytes: 16 * 1024 * 1024,
37744
- patchBytes: 256 * 1024
37745
- };
37746
-
37747
- // ../../packages/api-types/src/publication.ts
37748
- var PUBLICATION_LIMITS = {
37749
- repository: 200,
37750
- branch: 200,
37751
- commitMessage: 2e3,
37752
- refusalDetail: 400,
37753
- error: 400,
37754
- /** Branches that are never published to, whatever the host says. */
37755
- protectedBranches: ["main", "master", "trunk", "develop", "release"]
37756
- };
37757
-
37758
- // ../../packages/api-types/src/verification.ts
37759
- var VERIFICATION_OUTCOME_LIMITS = [
37760
- "Facts above are executor-owned. A non-zero exit is a result about the commands that ran, never proof about later code, and this is not an approval to publish, merge or deploy.",
37761
- "Declared output paths are not enforced, so a change they do not cover appears above rather than being prevented."
37762
- ];
37763
-
37764
- // ../../packages/api-types/src/index.ts
37765
- var PROFILE_FILES = [
37766
- "profile.json",
37767
- "SOUL.md",
37768
- "IDENTITY.md",
37769
- "BOOTSTRAP.md",
37770
- "AGENTS.md",
37771
- "TOOLS.md"
37772
- ];
37773
-
37774
37944
  // ../daemon/src/lib/git-review/refs.ts
37775
37945
  var REF_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._/-]{0,254}$/;
37776
37946
  function isCommitOid(value) {
@@ -37888,7 +38058,7 @@ var CREDENTIAL_EXTENSIONS = [
37888
38058
  ];
37889
38059
  function reviewScope(path) {
37890
38060
  const segments = path.split("/");
37891
- const basename6 = segments[segments.length - 1] ?? "";
38061
+ const basename7 = segments[segments.length - 1] ?? "";
37892
38062
  for (const prefix of BAZILION_STATE_PREFIXES) {
37893
38063
  if (path === prefix.slice(0, -1) || path.startsWith(prefix)) {
37894
38064
  return { included: false, reason: "bazilion_state" };
@@ -37897,7 +38067,7 @@ function reviewScope(path) {
37897
38067
  if (segments.some((segment) => CREDENTIAL_SEGMENTS.has(segment.toLowerCase()))) {
37898
38068
  return { included: false, reason: "credential_shaped" };
37899
38069
  }
37900
- const lower = basename6.toLowerCase();
38070
+ const lower = basename7.toLowerCase();
37901
38071
  if (CREDENTIAL_BASENAME_PATTERNS.some((pattern) => pattern.test(lower))) {
37902
38072
  return { included: false, reason: "credential_shaped" };
37903
38073
  }
@@ -37908,7 +38078,7 @@ function reviewScope(path) {
37908
38078
  }
37909
38079
 
37910
38080
  // ../daemon/src/lib/git-review/changes.ts
37911
- async function listChanges(captured, base, identity2, limits = REVIEW_LIMITS2) {
38081
+ async function listChanges(captured, base, identity2, limits = REVIEW_LIMITS) {
37912
38082
  const issues = [];
37913
38083
  const raw2 = await readDiff(captured, base, [
37914
38084
  "--raw",
@@ -37997,7 +38167,7 @@ async function listChanges(captured, base, identity2, limits = REVIEW_LIMITS2) {
37997
38167
  issues
37998
38168
  };
37999
38169
  }
38000
- async function readChangePatch(captured, base, change, patchBytes = REVIEW_LIMITS2.patchBytes) {
38170
+ async function readChangePatch(captured, base, change, patchBytes = REVIEW_LIMITS.patchBytes) {
38001
38171
  if (change.excludedReason) return { patch: null, truncated: false, omitted: "excluded" };
38002
38172
  if (change.binary) return { patch: null, truncated: false, omitted: "binary" };
38003
38173
  if (change.status === "untracked") {
@@ -38029,7 +38199,7 @@ async function readChangePatch(captured, base, change, patchBytes = REVIEW_LIMIT
38029
38199
  omitted: null
38030
38200
  };
38031
38201
  }
38032
- async function attachPatches(captured, report2, limits = REVIEW_LIMITS2, onlyPath) {
38202
+ async function attachPatches(captured, report2, limits = REVIEW_LIMITS, onlyPath) {
38033
38203
  let total = 0;
38034
38204
  let tooLarge = 0;
38035
38205
  const changes = [];
@@ -38162,7 +38332,7 @@ function compareSnapshots(before, after) {
38162
38332
  return before.id === after.id ? "identical" : "changed";
38163
38333
  }
38164
38334
  async function captureSourceSnapshot(captured, base, identity2, input = {}) {
38165
- const limits = input.limits ?? REVIEW_LIMITS2;
38335
+ const limits = input.limits ?? REVIEW_LIMITS;
38166
38336
  const issues = [];
38167
38337
  const withheld = { excluded: 0, tooLarge: 0, notRegular: 0, unstable: 0 };
38168
38338
  let incomplete = false;
@@ -38825,10 +38995,18 @@ async function resolveRepositoryContext(input) {
38825
38995
  report2.fingerprint = hash3(JSON.stringify({ ...report2, capturedAt: 0, fingerprint: "" }));
38826
38996
  return report2;
38827
38997
  }
38998
+ var RepositoryContextIncompleteError = class extends Error {
38999
+ codes;
39000
+ constructor(codes) {
39001
+ super(`Repository instructions incomplete (${codes.join(", ")}). Inspect Team repository context before coding.`);
39002
+ this.name = "RepositoryContextIncompleteError";
39003
+ this.codes = codes;
39004
+ }
39005
+ };
38828
39006
  function requireCompleteRepositoryContext(report2) {
38829
39007
  if (report2.instructions.state !== "complete") {
38830
- throw new Error(
38831
- `Repository instructions incomplete (${report2.instructions.issues.map((i) => i.code).join(", ")}). Inspect Team repository context before coding.`
39008
+ throw new RepositoryContextIncompleteError(
39009
+ report2.instructions.issues.map((i) => i.code)
38832
39010
  );
38833
39011
  }
38834
39012
  }
@@ -38875,12 +39053,12 @@ function createCodingHost(input) {
38875
39053
  sources2.push([
38876
39054
  current.label,
38877
39055
  name,
38878
- value ? createHash10("sha256").update(value).digest("hex") : null
39056
+ value ? createHash11("sha256").update(value).digest("hex") : null
38879
39057
  ]);
38880
39058
  }
38881
39059
  }
38882
39060
  dir.validate();
38883
- fingerprint2 = createHash10("sha256").update(JSON.stringify(sources2)).digest("hex");
39061
+ fingerprint2 = createHash11("sha256").update(JSON.stringify(sources2)).digest("hex");
38884
39062
  } catch {
38885
39063
  } finally {
38886
39064
  dir.close();
@@ -38947,7 +39125,7 @@ function createCodingHost(input) {
38947
39125
  try {
38948
39126
  const environment2 = await snapshot(command.cwd);
38949
39127
  const receipt = {
38950
- id: randomUUID33(),
39128
+ id: randomUUID34(),
38951
39129
  agentId: input.agentId,
38952
39130
  teamId: input.teamId,
38953
39131
  turnId: input.turnId,
@@ -39282,7 +39460,7 @@ function createDbMessagingHost(db, opts = {}) {
39282
39460
  }
39283
39461
 
39284
39462
  // ../daemon/src/lib/question-service.ts
39285
- import { randomUUID as randomUUID35 } from "crypto";
39463
+ import { randomUUID as randomUUID36 } from "crypto";
39286
39464
 
39287
39465
  // ../daemon/src/lib/question-consumption.ts
39288
39466
  import { isDeepStrictEqual } from "util";
@@ -39330,13 +39508,13 @@ function verifyQuestionConsumption(paths2, question, target, turnStartEntry = 1)
39330
39508
  }
39331
39509
 
39332
39510
  // ../daemon/src/lib/question-receipt.ts
39333
- import { createHash as createHash11, createHmac, randomBytes as randomBytes5, timingSafeEqual as timingSafeEqual2 } from "crypto";
39511
+ import { createHash as createHash12, createHmac, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual2 } from "crypto";
39334
39512
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
39335
- var hash4 = (text3) => createHash11("sha256").update(text3).digest("hex");
39336
- function key(db, create7) {
39337
- if (create7)
39513
+ var hash4 = (text3) => createHash12("sha256").update(text3).digest("hex");
39514
+ function key(db, create8) {
39515
+ if (create8)
39338
39516
  db.raw.run("INSERT OR IGNORE INTO question_receipt_key (singleton, key) VALUES (1, ?)", [
39339
- randomBytes5(32)
39517
+ randomBytes6(32)
39340
39518
  ]);
39341
39519
  const row2 = db.raw.query("SELECT key FROM question_receipt_key WHERE singleton = 1").get();
39342
39520
  return row2 ? Buffer.from(row2.key) : null;
@@ -39412,7 +39590,7 @@ var QuestionWaiters = class {
39412
39590
  if ([...this.#waiting.values()].some((entry) => entry.question.turnId === current.turnId)) {
39413
39591
  throw new Error("This turn already has a waiting question");
39414
39592
  }
39415
- return new Promise((resolve8) => {
39593
+ return new Promise((resolve9) => {
39416
39594
  const abort = () => this.closeTurn(current.turnId, "cancelled");
39417
39595
  const timer = setTimeout(
39418
39596
  () => {
@@ -39422,7 +39600,7 @@ var QuestionWaiters = class {
39422
39600
  Math.max(0, current.expiresAt - this.now())
39423
39601
  );
39424
39602
  timer.unref();
39425
- this.#waiting.set(current.id, { question: current, resolve: resolve8, signal, abort, timer });
39603
+ this.#waiting.set(current.id, { question: current, resolve: resolve9, signal, abort, timer });
39426
39604
  signal.addEventListener("abort", abort, { once: true });
39427
39605
  if (signal.aborted) abort();
39428
39606
  });
@@ -39455,7 +39633,7 @@ var QuestionWaiters = class {
39455
39633
  };
39456
39634
 
39457
39635
  // ../daemon/src/lib/telegram/question-transport.ts
39458
- import { createHash as createHash13 } from "crypto";
39636
+ import { createHash as createHash14 } from "crypto";
39459
39637
 
39460
39638
  // ../daemon/src/lib/telegram/outbound-queue.ts
39461
39639
  var DEFAULT_MIN_INTERVAL_MS = Number(process.env.BAZILION_TELEGRAM_SEND_INTERVAL_MS ?? 200);
@@ -39512,7 +39690,7 @@ function sleep(ms) {
39512
39690
  }
39513
39691
 
39514
39692
  // ../daemon/src/lib/telegram/queue-binding.ts
39515
- import { createHash as createHash12 } from "crypto";
39693
+ import { createHash as createHash13 } from "crypto";
39516
39694
 
39517
39695
  // ../daemon/src/lib/telegram/ingress-attempt.ts
39518
39696
  function isTelegramIngressPayload(value) {
@@ -39598,7 +39776,7 @@ function captureTelegramQueueBinding(db, authToken, authorization, transportBotT
39598
39776
  teamId: agent.team_id,
39599
39777
  ownerGrantId: owner.grant_id,
39600
39778
  topicBindingId: agent.telegram_binding_id,
39601
- botDigest: createHash12("sha256").update(JSON.stringify([botToken, credential?.envelope ?? null])).digest("hex")
39779
+ botDigest: createHash13("sha256").update(JSON.stringify([botToken, credential?.envelope ?? null])).digest("hex")
39602
39780
  };
39603
39781
  }
39604
39782
  function requireTelegramQueueBinding(db, authToken, value) {
@@ -39762,7 +39940,7 @@ Reply to THIS message with Other text, or /answer ${question.id} your answer. Cl
39762
39940
  };
39763
39941
  }
39764
39942
  function requestId(identity2) {
39765
- const hex = createHash13("sha256").update(identity2).digest("hex");
39943
+ const hex = createHash14("sha256").update(identity2).digest("hex");
39766
39944
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-8${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
39767
39945
  }
39768
39946
  function parseTelegramQuestionReply(db, authToken, update3) {
@@ -39810,7 +39988,7 @@ function parseTelegramQuestionReply(db, authToken, update3) {
39810
39988
  }
39811
39989
 
39812
39990
  // ../daemon/src/lib/attachments.ts
39813
- import { randomUUID as randomUUID34 } from "crypto";
39991
+ import { randomUUID as randomUUID35 } from "crypto";
39814
39992
  import { closeSync as closeSync9, constants as constants10, fstatSync as fstatSync7, openSync as openSync9, writeFileSync as writeFileSync13 } from "fs";
39815
39993
  import { join as join26, posix } from "path";
39816
39994
  var MAX_FILE_BYTES = 25 * 1024 * 1024;
@@ -39837,7 +40015,7 @@ function saveInputFiles(agentDir, files, options = {}) {
39837
40015
  lines.push(`[attachment "${label}" skipped: too large (${fmtBytes(buf.byteLength)} > 25 MB)]`);
39838
40016
  continue;
39839
40017
  }
39840
- const filename2 = `${randomUUID34().slice(0, 8)}-${safeName(label)}`;
40018
+ const filename2 = `${randomUUID35().slice(0, 8)}-${safeName(label)}`;
39841
40019
  const path = join26(dir, filename2);
39842
40020
  let fd;
39843
40021
  try {
@@ -40710,7 +40888,7 @@ var QuestionService = class {
40710
40888
  turn.conversation.id
40711
40889
  ).length;
40712
40890
  this.#attached.add(turn);
40713
- const turnId = randomUUID35();
40891
+ const turnId = randomUUID36();
40714
40892
  const listeners = /* @__PURE__ */ new Set();
40715
40893
  if (onQuestion) listeners.add(onQuestion);
40716
40894
  this.#turns.set(turnId, {
@@ -40755,7 +40933,7 @@ var QuestionService = class {
40755
40933
  ask: async (toolCallId, input) => {
40756
40934
  if (closed) throw new Error("Question turn is closed");
40757
40935
  this.#validateTurn(turn);
40758
- const item = create4(this.db, {
40936
+ const item = create5(this.db, {
40759
40937
  agentId: turn.agent.agent.id,
40760
40938
  teamId: turn.agent.team.id,
40761
40939
  conversationId: turn.conversation.id,
@@ -42881,18 +43059,18 @@ var _pendingByAgent = /* @__PURE__ */ new Map();
42881
43059
  function reactSeen(agentId, chatId2, messageId) {
42882
43060
  const deps = _liveDepsResolver?.();
42883
43061
  if (!deps) return;
42884
- const list16 = _pendingByAgent.get(agentId) ?? [];
42885
- list16.push({ chatId: chatId2, messageId });
42886
- _pendingByAgent.set(agentId, list16);
43062
+ const list17 = _pendingByAgent.get(agentId) ?? [];
43063
+ list17.push({ chatId: chatId2, messageId });
43064
+ _pendingByAgent.set(agentId, list17);
42887
43065
  void deps.api.setMessageReaction(chatId2, messageId, [{ type: "emoji", emoji: SEEN_EMOJI }]).catch(() => void 0);
42888
43066
  }
42889
43067
  function clearReactionsFor(agentId) {
42890
- const list16 = _pendingByAgent.get(agentId);
42891
- if (!list16 || list16.length === 0) return;
43068
+ const list17 = _pendingByAgent.get(agentId);
43069
+ if (!list17 || list17.length === 0) return;
42892
43070
  _pendingByAgent.delete(agentId);
42893
43071
  const deps = _liveDepsResolver?.();
42894
43072
  if (!deps) return;
42895
- for (const { chatId: chatId2, messageId } of list16) {
43073
+ for (const { chatId: chatId2, messageId } of list17) {
42896
43074
  void deps.api.setMessageReaction(chatId2, messageId, []).catch(() => void 0);
42897
43075
  }
42898
43076
  }
@@ -43209,10 +43387,10 @@ function mirrorTypingStop(agentId) {
43209
43387
  }
43210
43388
 
43211
43389
  // ../daemon/src/lib/user-md-host.ts
43212
- import { createHash as createHash14 } from "crypto";
43390
+ import { createHash as createHash15 } from "crypto";
43213
43391
  var USER_MD_MAX_BYTES = 12e3;
43214
43392
  function computeEtag(content) {
43215
- return createHash14("sha256").update(content, "utf8").digest("hex").slice(0, 16);
43393
+ return createHash15("sha256").update(content, "utf8").digest("hex").slice(0, 16);
43216
43394
  }
43217
43395
  function createDbUserMdHost(db, paths2) {
43218
43396
  return {
@@ -43825,7 +44003,7 @@ function bound(value) {
43825
44003
  }
43826
44004
 
43827
44005
  // ../daemon/src/lib/review/dispatch.ts
43828
- import { randomUUID as randomUUID36 } from "crypto";
44006
+ import { randomUUID as randomUUID37 } from "crypto";
43829
44007
 
43830
44008
  // ../daemon/src/lib/review/preparation.ts
43831
44009
  async function prepareChangeReviewTurn(input) {
@@ -44188,7 +44366,7 @@ function refused(message) {
44188
44366
  }
44189
44367
 
44190
44368
  // ../daemon/src/lib/review/dispatch.ts
44191
- var REVIEW_DISPATCH_OWNER = randomUUID36();
44369
+ var REVIEW_DISPATCH_OWNER = randomUUID37();
44192
44370
  var REVIEW_LEASE_MS = 10 * 60 * 1e3;
44193
44371
  var dispatchRegistry = () => {
44194
44372
  const global2 = globalThis;
@@ -44629,9 +44807,9 @@ async function dispatchClaimableReviews(now = Date.now()) {
44629
44807
  }
44630
44808
 
44631
44809
  // ../daemon/src/lib/verification/admission.ts
44632
- import { randomUUID as randomUUID37 } from "crypto";
44810
+ import { randomUUID as randomUUID38 } from "crypto";
44633
44811
  var VERIFICATION_LEASE_MS = 10 * 60 * 1e3;
44634
- var VERIFICATION_DISPATCH_OWNER = randomUUID37();
44812
+ var VERIFICATION_DISPATCH_OWNER = randomUUID38();
44635
44813
  async function admitVerificationRequest(db, paths2, requestId2, now = Date.now()) {
44636
44814
  const request2 = getVerificationRequestById(db, requestId2, now);
44637
44815
  if (!request2) return { kind: "deferred", requestId: requestId2, reason: "unknown_or_expired" };
@@ -44769,7 +44947,7 @@ function safeTeam3(db, paths2, teamId) {
44769
44947
  }
44770
44948
 
44771
44949
  // ../daemon/src/lib/verification/executor.ts
44772
- import { randomUUID as randomUUID38 } from "crypto";
44950
+ import { randomUUID as randomUUID39 } from "crypto";
44773
44951
  import { existsSync as existsSync17 } from "fs";
44774
44952
  import { join as join28, posix as posix2, relative as relative8, sep as sep7 } from "path";
44775
44953
  import { createLocalBashOperations as createLocalBashOperations3 } from "@earendil-works/pi-coding-agent";
@@ -44800,14 +44978,14 @@ function createProtectedCheckExecutor(input) {
44800
44978
  }
44801
44979
  const container = buildContainerOperations(input, env, config2.envAllowlist, absoluteCwd);
44802
44980
  if ("blocked" in container) return blocked3("environment_unavailable", container.blocked);
44803
- const commandId = randomUUID38();
44981
+ const commandId = randomUUID39();
44804
44982
  const startedAt = Date.now();
44805
44983
  const receipt = {
44806
44984
  id: commandId,
44807
44985
  agentId: input.request.recipientAgentId,
44808
44986
  teamId: input.request.teamId,
44809
44987
  turnId: input.attemptId,
44810
- toolCallId: `verification:${input.attemptId}:${randomUUID38()}`,
44988
+ toolCallId: `verification:${input.attemptId}:${randomUUID39()}`,
44811
44989
  input: {
44812
44990
  command,
44813
44991
  cwd: relative9,
@@ -45269,7 +45447,7 @@ function abandonVerificationAttempt(db, input) {
45269
45447
  }
45270
45448
 
45271
45449
  // ../daemon/src/lib/verification/writes.ts
45272
- import { createHash as createHash15 } from "crypto";
45450
+ import { createHash as createHash16 } from "crypto";
45273
45451
  import { lstat as lstat2, readdir, readFile, readlink } from "fs/promises";
45274
45452
  import { join as join29 } from "path";
45275
45453
  var FINGERPRINT_LIMITS = {
@@ -45284,10 +45462,11 @@ var FINGERPRINT_LIMITS = {
45284
45462
  async function fingerprintPath(root, path, digest4) {
45285
45463
  const absolute = join29(root, path);
45286
45464
  const info = await lstat2(absolute);
45287
- if (info.isSymbolicLink()) return `link:${await readlink(absolute)}`;
45465
+ if (info.isSymbolicLink())
45466
+ return `link:${(await readlink(absolute)).replaceAll("\\", "/")}`;
45288
45467
  if (!info.isFile()) return `other:${info.mode}`;
45289
45468
  if (!digest4 || info.size > FINGERPRINT_LIMITS.fileBytes) return `size:${info.size}`;
45290
- return `sha256:${createHash15("sha256").update(await readFile(absolute)).digest("hex")}`;
45469
+ return `sha256:${createHash16("sha256").update(await readFile(absolute)).digest("hex")}`;
45291
45470
  }
45292
45471
  async function fingerprintWorkspace(root) {
45293
45472
  const entries = /* @__PURE__ */ new Map();
@@ -45996,7 +46175,15 @@ function bootstrap(paths2) {
45996
46175
  }
45997
46176
  const db = openDb(paths2.db);
45998
46177
  try {
45999
- runMigrations(db);
46178
+ runMigrations(db, {
46179
+ // Before the first forward migration of an existing home, preserve the
46180
+ // pre-upgrade state beside the database. A failed migration then leaves
46181
+ // a restorable copy instead of a half-migrated home.
46182
+ preMigrationSnapshotPath: join30(
46183
+ dirname7(paths2.db),
46184
+ `bazilion.pre-migration-${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:T]/g, "").replace(/\..*/, "")}.db`
46185
+ )
46186
+ });
46000
46187
  let existingAuthToken = null;
46001
46188
  if (authFileExists) {
46002
46189
  try {
@@ -46078,6 +46265,7 @@ function authenticateToken(token) {
46078
46265
  kind: match.kind,
46079
46266
  tokenId: match.id,
46080
46267
  label: match.label,
46268
+ scopes: match.scopes,
46081
46269
  sessionId: null
46082
46270
  };
46083
46271
  }
@@ -46122,8 +46310,49 @@ function isLoopbackHost(hostname2) {
46122
46310
  return hostname2 === "127.0.0.1" || hostname2 === "localhost" || hostname2 === "[::1]" || hostname2 === "::1";
46123
46311
  }
46124
46312
 
46313
+ // ../daemon/src/lib/scopes.ts
46314
+ var ADMIN_PREFIXES = [
46315
+ "/api/config",
46316
+ "/api/mcp-servers",
46317
+ "/api/backup",
46318
+ "/api/tokens",
46319
+ "/api/pair/codes",
46320
+ "/api/auth/openai",
46321
+ "/api/providers/test",
46322
+ "/api/communication"
46323
+ ];
46324
+ var APPROVALS_MUTATION_PREFIXES = ["/api/approvals", "/api/shell-approvals", "/api/notifications"];
46325
+ var APPROVALS_MUTATION_PATTERNS = [
46326
+ /\/queue(\/|$)/,
46327
+ // follow-up queue resolve/control/stop/reconcile
46328
+ /\/questions\/[^/]+\/answer$/,
46329
+ // structured question answers (BAZ-037)
46330
+ /\/acknowledge/
46331
+ // attention acknowledge / acknowledge-all (BAZ-026)
46332
+ ];
46333
+ var READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
46334
+ function requiredScope(method, path) {
46335
+ const isRead = READ_METHODS.has(method.toUpperCase());
46336
+ if (ADMIN_PREFIXES.some((p) => path === p || path.startsWith(`${p}/`))) {
46337
+ return "admin";
46338
+ }
46339
+ if (!isRead) {
46340
+ if (APPROVALS_MUTATION_PREFIXES.some((p) => path === p || path.startsWith(`${p}/`))) {
46341
+ return "approvals";
46342
+ }
46343
+ if (path.startsWith("/api/agents") || path.startsWith("/api/attention")) {
46344
+ if (APPROVALS_MUTATION_PATTERNS.some((re) => re.test(path))) return "approvals";
46345
+ }
46346
+ }
46347
+ return isRead ? "read" : "write";
46348
+ }
46349
+ function scopeAllows(scopes, method, path) {
46350
+ const required3 = requiredScope(method, path);
46351
+ return { allowed: scopes.includes(required3), required: required3 };
46352
+ }
46353
+
46125
46354
  // ../daemon/src/lib/middleware-auth.ts
46126
- var PUBLIC_PATHS = /* @__PURE__ */ new Set(["/api/login", "/api/health"]);
46355
+ var PUBLIC_PATHS = /* @__PURE__ */ new Set(["/api/login", "/api/health", "/api/pair/exchange"]);
46127
46356
  var SETUP_OPEN_PREFIXES = [
46128
46357
  "/api/config",
46129
46358
  "/api/auth",
@@ -46158,6 +46387,7 @@ async function authMiddleware(c, next) {
46158
46387
  kind: "session",
46159
46388
  tokenId: session.deviceTokenId,
46160
46389
  label: session.deviceLabel,
46390
+ scopes: parseScopes(session.deviceScopes),
46161
46391
  sessionId: session.id
46162
46392
  } : null);
46163
46393
  if (!principal) {
@@ -46176,6 +46406,19 @@ async function authMiddleware(c, next) {
46176
46406
  }
46177
46407
  c.set("authPrincipal", principal);
46178
46408
  if (session) c.set("authSession", session);
46409
+ if (principal.kind !== "bootstrap") {
46410
+ const check = scopeAllows(principal.scopes, c.req.method, path);
46411
+ if (!check.allowed) {
46412
+ return c.json(
46413
+ {
46414
+ error: `credential is missing the '${check.required}' scope`,
46415
+ code: "insufficient_scope",
46416
+ requiredScope: check.required
46417
+ },
46418
+ 403
46419
+ );
46420
+ }
46421
+ }
46179
46422
  if (!isSetupOpen(path) && !isSetupComplete(getCtx().db)) {
46180
46423
  return c.json({ error: "setup incomplete" }, 409);
46181
46424
  }
@@ -46183,9 +46426,9 @@ async function authMiddleware(c, next) {
46183
46426
  }
46184
46427
 
46185
46428
  // ../daemon/src/routes/agents.ts
46186
- import { randomUUID as randomUUID40 } from "crypto";
46429
+ import { randomUUID as randomUUID41 } from "crypto";
46187
46430
  import { existsSync as existsSync19, readFileSync as readFileSync12 } from "fs";
46188
- import { join as join30 } from "path";
46431
+ import { join as join31 } from "path";
46189
46432
  import { Hono } from "hono";
46190
46433
 
46191
46434
  // ../daemon/src/lib/agent-id.ts
@@ -46513,7 +46756,7 @@ var handle5 = async (ctx) => {
46513
46756
  try {
46514
46757
  reconcileApprovalHolds(ctx.db);
46515
46758
  if (command === "list" || command === "history") {
46516
- const state3 = list13(ctx.db, agent.id, {
46759
+ const state3 = list14(ctx.db, agent.id, {
46517
46760
  all: command === "history",
46518
46761
  offset: command === "history" && arg ? revision2(arg) : 0
46519
46762
  });
@@ -47411,7 +47654,7 @@ function errMsg(e) {
47411
47654
  }
47412
47655
 
47413
47656
  // ../daemon/src/lib/telegram/notification-transport.ts
47414
- import { createHash as createHash16 } from "crypto";
47657
+ import { createHash as createHash17 } from "crypto";
47415
47658
  var resolver = null;
47416
47659
  function notificationDestinationAllowed(chat, owner, bot) {
47417
47660
  return chat.type === "supergroup" && chat.is_forum === true && !chat.username && !chat.active_usernames?.length && owner.status !== "left" && owner.status !== "kicked" && (owner.status !== "restricted" || owner.is_member === true) && (bot.status === "creator" || bot.status === "administrator" && bot.can_manage_topics === true);
@@ -47434,8 +47677,8 @@ function capture(db, authToken) {
47434
47677
  const topicId = Number(topic?.value);
47435
47678
  if (!owner || !Number.isSafeInteger(chatId2) || chatId2 >= 0 || !Number.isSafeInteger(topicId) || topicId <= 0 || !env.TELEGRAM_BOT_TOKEN || env.TELEGRAM_BOT_TOKEN !== live2.botToken)
47436
47679
  return null;
47437
- const botDigest = createHash16("sha256").update(JSON.stringify([live2.botToken, envelope])).digest("hex");
47438
- const id = createHash16("sha256").update(JSON.stringify([chatId2, topicId, owner.grant_id, botDigest])).digest("hex");
47680
+ const botDigest = createHash17("sha256").update(JSON.stringify([live2.botToken, envelope])).digest("hex");
47681
+ const id = createHash17("sha256").update(JSON.stringify([chatId2, topicId, owner.grant_id, botDigest])).digest("hex");
47439
47682
  return {
47440
47683
  binding: { id, chatId: chatId2, topicId, ownerGrantId: owner.grant_id, botDigest },
47441
47684
  ownerId: owner.user_id,
@@ -47508,7 +47751,7 @@ async function notifyTelegramQueueStatus(db, agentId, itemId) {
47508
47751
  }
47509
47752
 
47510
47753
  // ../daemon/src/lib/user-queue-admission.ts
47511
- import { randomUUID as randomUUID39 } from "crypto";
47754
+ import { randomUUID as randomUUID40 } from "crypto";
47512
47755
  async function enqueueTelegramInput(binding, message, attachments2, context = getCtx()) {
47513
47756
  validateInput(message, attachments2);
47514
47757
  const { db, paths: paths2, authToken } = context;
@@ -47527,7 +47770,7 @@ async function enqueueTelegramInput(binding, message, attachments2, context = ge
47527
47770
  const existing = findAttempt(db, "telegram", binding.authorization.attemptId);
47528
47771
  return db.raw.transaction(() => {
47529
47772
  const item = accept(db, {
47530
- id: existing?.id ?? randomUUID39(),
47773
+ id: existing?.id ?? randomUUID40(),
47531
47774
  agentId,
47532
47775
  teamId: existing?.teamId ?? agent.team.id,
47533
47776
  conversationId,
@@ -48589,7 +48832,7 @@ agentsRouter.get("/", (c) => {
48589
48832
  const { db, paths: paths2, authToken } = getCtx();
48590
48833
  const agents = agents_exports.list(db, { includeArchived }).map((agent) => ({
48591
48834
  ...agent,
48592
- identity: loadIdentityFromFile(join30(agent.dir, "IDENTITY.md"))
48835
+ identity: loadIdentityFromFile(join31(agent.dir, "IDENTITY.md"))
48593
48836
  }));
48594
48837
  return c.json(agents);
48595
48838
  });
@@ -48611,7 +48854,7 @@ agentsRouter.post("/", async (c) => {
48611
48854
  }
48612
48855
  let reasoningLevel;
48613
48856
  if (typeof raw2.reasoningLevel === "string") {
48614
- if (!REASONING_LEVELS2.includes(raw2.reasoningLevel)) {
48857
+ if (!REASONING_LEVELS.includes(raw2.reasoningLevel)) {
48615
48858
  return c.json({ error: `invalid reasoningLevel: ${raw2.reasoningLevel}` }, 400);
48616
48859
  }
48617
48860
  reasoningLevel = raw2.reasoningLevel;
@@ -48683,7 +48926,7 @@ agentsRouter.patch("/:id", async (c) => {
48683
48926
  void syncAgentTopicIcon(db, resolvedId).catch(() => void 0);
48684
48927
  }
48685
48928
  if (body.reasoningLevel !== void 0) {
48686
- if (typeof body.reasoningLevel !== "string" || !REASONING_LEVELS2.includes(body.reasoningLevel)) {
48929
+ if (typeof body.reasoningLevel !== "string" || !REASONING_LEVELS.includes(body.reasoningLevel)) {
48687
48930
  return c.json({ error: `invalid reasoningLevel: ${body.reasoningLevel}` }, 400);
48688
48931
  }
48689
48932
  agents_exports.setReasoningLevel(db, resolvedId, body.reasoningLevel);
@@ -49014,7 +49257,7 @@ agentsRouter.patch("/:id/review-config", async (c) => {
49014
49257
  if (!Number.isInteger(everyNTurns) || everyNTurns < 1 || everyNTurns > 100) {
49015
49258
  return c.json({ error: "everyNTurns must be an integer from 1 to 100" }, 400);
49016
49259
  }
49017
- if (!REASONING_LEVELS2.includes(reasoningLevel)) {
49260
+ if (!REASONING_LEVELS.includes(reasoningLevel)) {
49018
49261
  return c.json({ error: `invalid reasoningLevel: ${reasoningLevel}` }, 400);
49019
49262
  }
49020
49263
  if (body.model !== void 0 && body.model !== null && !body.model.includes(":")) {
@@ -49121,7 +49364,7 @@ for (const decision of ["approve", "reject", "revoke"]) {
49121
49364
  if (!team) return c.json({ error: `team not found: ${agent.teamId}` }, 404);
49122
49365
  try {
49123
49366
  const proposal = await runAgentLifecycleMutation(agent.id, async () => {
49124
- const memory = qmdBackend(join30(team.path, "memory"));
49367
+ const memory = qmdBackend(join31(team.path, "memory"));
49125
49368
  if (decision === "approve")
49126
49369
  return approveLessonProposal(db, memory, current.id, body.version);
49127
49370
  if (decision === "reject") return rejectLessonProposal(db, current.id, body.version);
@@ -49347,7 +49590,7 @@ agentsRouter.post("/:id/chat", async (c) => {
49347
49590
  if (!message && attachments2.length === 0) {
49348
49591
  return c.json({ error: "message or an attachment is required" }, 400);
49349
49592
  }
49350
- const requestAttemptId = c.req.header("x-request-id") ?? randomUUID40();
49593
+ const requestAttemptId = c.req.header("x-request-id") ?? randomUUID41();
49351
49594
  let preparedTurn;
49352
49595
  try {
49353
49596
  preparedTurn = await prepareAgentTurn({
@@ -49369,6 +49612,14 @@ agentsRouter.post("/:id/chat", async (c) => {
49369
49612
  } catch (error2) {
49370
49613
  if (error2 instanceof WorkspaceBusyError)
49371
49614
  return c.json({ error: error2.message, code: error2.message }, 409);
49615
+ if (error2 instanceof ContextReadError || error2 instanceof RepositoryContextIncompleteError)
49616
+ return c.json(
49617
+ {
49618
+ error: `this turn needs repository context, which this platform cannot prepare (${error2 instanceof RepositoryContextIncompleteError ? error2.codes.join(", ") : error2.code}); agent turns currently require Linux`,
49619
+ code: error2 instanceof RepositoryContextIncompleteError ? error2.codes[0] : error2.code
49620
+ },
49621
+ 422
49622
+ );
49372
49623
  if (error2 instanceof ConversationConflictError)
49373
49624
  return c.json({ error: error2.message, code: error2.code, selection: error2.selection }, 409);
49374
49625
  if (error2 instanceof CommunicationPendingError) {
@@ -49477,7 +49728,7 @@ agentsRouter.post("/:id/chat/compact", async (c) => {
49477
49728
  );
49478
49729
  const resolved = resolveAgent(db, paths2, id);
49479
49730
  const env = mergeSecretsIntoEnv(db, authToken);
49480
- const memory = qmdBackend(join30(resolved.team.path, "memory"));
49731
+ const memory = qmdBackend(join31(resolved.team.path, "memory"));
49481
49732
  await memory.init();
49482
49733
  const apiKeyResolution = await resolveAgentApiKey(db, authToken, resolved, {
49483
49734
  withRefresher: true
@@ -49552,7 +49803,7 @@ agentsRouter.get("/:id/chat/context", async (c) => {
49552
49803
  const promptSkills = loadPromptSkills(paths2.skillsDir, resolved.skills);
49553
49804
  const files = [];
49554
49805
  for (const file of CONTEXT_FILE_ORDER2) {
49555
- const path = join30(resolved.agent.dir, file);
49806
+ const path = join31(resolved.agent.dir, file);
49556
49807
  if (!existsSync19(path)) continue;
49557
49808
  const content = readFileSync12(path, "utf8").trimEnd();
49558
49809
  if (!content) continue;
@@ -49582,7 +49833,7 @@ Read-only context about the human you're working with in this team. You cannot e
49582
49833
 
49583
49834
  ${resolved.team.userMd.trim()}`.length : 0;
49584
49835
  const memoryHintChars = "# Memory\n\nYou have a persistent memory backend. Use `memory_write` to remember things across sessions, and `memory_search` / `memory_read` / `memory_list` to recall them. Always check memory at the start of a session if the user might have told you something important before.".length;
49585
- const memory = qmdBackend(join30(resolved.team.path, "memory"));
49836
+ const memory = qmdBackend(join31(resolved.team.path, "memory"));
49586
49837
  await memory.init();
49587
49838
  const apiKeyResolution = await resolveAgentApiKey(db, authToken, resolved, {
49588
49839
  withRefresher: true
@@ -49724,7 +49975,7 @@ agentsRouter.post("/:id/chat/truncate", async (c) => {
49724
49975
  409
49725
49976
  );
49726
49977
  const resolved = resolveAgent(db, paths2, id);
49727
- const memory = qmdBackend(join30(resolved.team.path, "memory"));
49978
+ const memory = qmdBackend(join31(resolved.team.path, "memory"));
49728
49979
  await memory.init();
49729
49980
  const env = mergeSecretsIntoEnv(db, authToken);
49730
49981
  const apiKeyResolution = await resolveAgentApiKey(db, authToken, resolved, {
@@ -50167,7 +50418,7 @@ function queuedApprovalInput(agentId, itemId) {
50167
50418
  function assertQueuedApprovalReady(approval) {
50168
50419
  const { db } = getCtx();
50169
50420
  const ref = validateQueuedUserApproval(approval, queuedApprovalInput);
50170
- const head = list13(db, ref.agentId, { limit: 1 }).items[0];
50421
+ const head = list14(db, ref.agentId, { limit: 1 }).items[0];
50171
50422
  if (control(db, ref.agentId).paused || head?.id !== ref.itemId || head.status !== "held")
50172
50423
  throw new QueueConflictError("Queued approval is paused or waiting for earlier input");
50173
50424
  }
@@ -50228,7 +50479,7 @@ async function deliverQueuedApproval(approval) {
50228
50479
  });
50229
50480
  } catch (error2) {
50230
50481
  if (error2 instanceof WorkspaceBusyError && !error2.recoveryRequired) {
50231
- await new Promise((resolve8) => setTimeout(resolve8, 1e3));
50482
+ await new Promise((resolve9) => setTimeout(resolve9, 1e3));
50232
50483
  continue;
50233
50484
  }
50234
50485
  if (isAgentTurnActiveError(error2, ref.agentId)) continue;
@@ -50880,14 +51131,14 @@ function callbackUnavailable(error2, host2, port2) {
50880
51131
  }
50881
51132
  function closeServer(server3) {
50882
51133
  if (!server3.listening) return Promise.resolve();
50883
- return new Promise((resolve8) => server3.close(() => resolve8()));
51134
+ return new Promise((resolve9) => server3.close(() => resolve9()));
50884
51135
  }
50885
51136
  async function preflightOpenAICodexCallback(options) {
50886
51137
  const host2 = options?.host ?? openAICodexCallbackHost();
50887
51138
  const port2 = options?.port ?? OPENAI_CODEX_CALLBACK_PORT;
50888
51139
  const server3 = createServer2();
50889
51140
  try {
50890
- await new Promise((resolve8, reject2) => {
51141
+ await new Promise((resolve9, reject2) => {
50891
51142
  const cleanup = () => {
50892
51143
  server3.removeListener("error", onError);
50893
51144
  server3.removeListener("listening", onListening);
@@ -50898,7 +51149,7 @@ async function preflightOpenAICodexCallback(options) {
50898
51149
  };
50899
51150
  const onListening = () => {
50900
51151
  cleanup();
50901
- resolve8();
51152
+ resolve9();
50902
51153
  };
50903
51154
  server3.once("error", onError);
50904
51155
  server3.once("listening", onListening);
@@ -50984,7 +51235,7 @@ var webOpenAILoginTail = Promise.resolve();
50984
51235
  function waitForLoginTurn(turn, signal) {
50985
51236
  if (!signal) return turn;
50986
51237
  if (signal.aborted) return Promise.reject(abortReason(signal));
50987
- return new Promise((resolve8, reject2) => {
51238
+ return new Promise((resolve9, reject2) => {
50988
51239
  const onAbort = () => {
50989
51240
  signal.removeEventListener("abort", onAbort);
50990
51241
  reject2(abortReason(signal));
@@ -50992,7 +51243,7 @@ function waitForLoginTurn(turn, signal) {
50992
51243
  signal.addEventListener("abort", onAbort, { once: true });
50993
51244
  void turn.then(() => {
50994
51245
  signal.removeEventListener("abort", onAbort);
50995
- resolve8();
51246
+ resolve9();
50996
51247
  });
50997
51248
  });
50998
51249
  }
@@ -51000,8 +51251,8 @@ async function acquireWebOpenAILogin(signal) {
51000
51251
  const previous = webOpenAILoginTail;
51001
51252
  let releaseGate = () => {
51002
51253
  };
51003
- const gate = new Promise((resolve8) => {
51004
- releaseGate = resolve8;
51254
+ const gate = new Promise((resolve9) => {
51255
+ releaseGate = resolve9;
51005
51256
  });
51006
51257
  webOpenAILoginTail = previous.then(() => gate);
51007
51258
  try {
@@ -51229,6 +51480,47 @@ authRouter.delete("/sessions/:id", (c) => {
51229
51480
  }
51230
51481
  return c.body(null, 204);
51231
51482
  });
51483
+ authRouter.post("/pair/codes", async (c) => {
51484
+ const body = await c.req.json().catch(() => null);
51485
+ let scopes = [...ALL_DEVICE_TOKEN_SCOPES];
51486
+ if (body?.scopes !== void 0) {
51487
+ if (!Array.isArray(body.scopes) || body.scopes.length === 0 || body.scopes.some((s) => !DEVICE_TOKEN_SCOPES.includes(s))) {
51488
+ return c.json(
51489
+ { error: `scopes must be a non-empty subset of: ${DEVICE_TOKEN_SCOPES.join(", ")}` },
51490
+ 400
51491
+ );
51492
+ }
51493
+ scopes = [...new Set(body.scopes)];
51494
+ }
51495
+ const created = webPairingTokens_exports.create(getCtx().db, { scopes });
51496
+ const serverOrigin = process.env.BAZILION_PUBLIC_ORIGIN?.replace(/\/$/, "");
51497
+ const setupUrl = `bazilion-pair://pair?server=${encodeURIComponent(serverOrigin ?? new URL(c.req.url).origin)}&code=${encodeURIComponent(created.code)}`;
51498
+ return c.json(
51499
+ { code: created.code, meta: created.meta, setupUrl },
51500
+ 201
51501
+ );
51502
+ });
51503
+ authRouter.post("/pair/exchange", async (c) => {
51504
+ const body = await c.req.json().catch(() => null);
51505
+ if (!body || typeof body.code !== "string" || !body.code.trim()) {
51506
+ return c.json({ error: "code is required" }, 400);
51507
+ }
51508
+ const { db } = getCtx();
51509
+ const outcome = db.raw.transaction(() => {
51510
+ const result = webPairingTokens_exports.exchange(db, body.code.trim());
51511
+ if (!result.ok) return result;
51512
+ const minted = webTokens_exports.create(db, "paired device", { scopes: result.scopes });
51513
+ webPairingTokens_exports.completeExchange(db, body.code.trim(), minted.meta.id);
51514
+ return { ok: true, minted };
51515
+ })();
51516
+ if (!outcome.ok) {
51517
+ return c.json({ error: `pairing code ${outcome.reason}` }, 400);
51518
+ }
51519
+ return c.json(
51520
+ { token: outcome.minted.token, meta: outcome.minted.meta },
51521
+ 201
51522
+ );
51523
+ });
51232
51524
 
51233
51525
  // ../daemon/src/routes/communication.ts
51234
51526
  import { Hono as Hono5 } from "hono";
@@ -51446,7 +51738,7 @@ conversationsRouter.onError((error2, c) => {
51446
51738
  });
51447
51739
  conversationsRouter.get("/:agentId/conversations", (c) => {
51448
51740
  return c.json(
51449
- list14(
51741
+ list15(
51450
51742
  getCtx().db,
51451
51743
  c.req.param("agentId"),
51452
51744
  Number(c.req.query("limit") ?? 20),
@@ -51462,7 +51754,7 @@ conversationsRouter.post("/:agentId/conversations", async (c) => {
51462
51754
  return c.json({ error: "Invalid conversation request" }, 400);
51463
51755
  if (get20(db, agentId, input.requestId)) {
51464
51756
  return c.json(
51465
- create5(db, agentId, input, () => {
51757
+ create6(db, agentId, input, () => {
51466
51758
  throw new Error("Existing conversation disappeared");
51467
51759
  })
51468
51760
  );
@@ -51472,7 +51764,7 @@ conversationsRouter.post("/:agentId/conversations", async (c) => {
51472
51764
  if (pendingCount(db, agentId) > 0)
51473
51765
  throw new Error("Pending follow-ups must be resolved first");
51474
51766
  const agent = resolveAgent(db, paths2, agentId);
51475
- return create5(
51767
+ return create6(
51476
51768
  db,
51477
51769
  agentId,
51478
51770
  input,
@@ -51675,23 +51967,23 @@ messagesRouter.patch("/:id", async (c) => {
51675
51967
  // ../daemon/src/routes/misc.ts
51676
51968
  import { existsSync as existsSync20 } from "fs";
51677
51969
  import { homedir as homedir2 } from "os";
51678
- import { join as join33 } from "path";
51970
+ import { join as join34 } from "path";
51679
51971
  import { Hono as Hono10 } from "hono";
51680
51972
 
51681
51973
  // ../daemon/src/lib/backup.ts
51682
- import { createHash as createHash17 } from "crypto";
51974
+ import { createHash as createHash18 } from "crypto";
51683
51975
  import { mkdtempSync as mkdtempSync5, rmSync as rmSync15 } from "fs";
51684
51976
  import { tmpdir as tmpdir5 } from "os";
51685
- import { join as join31, resolve as resolve6 } from "path";
51686
- import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
51687
- import { create as create6 } from "tar";
51977
+ import { join as join32, resolve as resolve7 } from "path";
51978
+ import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
51979
+ import { create as create7 } from "tar";
51688
51980
  var snapshotTail = Promise.resolve();
51689
51981
  async function serializeSnapshot(work) {
51690
51982
  let release2 = () => {
51691
51983
  };
51692
51984
  const previous = snapshotTail;
51693
- snapshotTail = new Promise((resolve8) => {
51694
- release2 = resolve8;
51985
+ snapshotTail = new Promise((resolve9) => {
51986
+ release2 = resolve9;
51695
51987
  });
51696
51988
  await previous;
51697
51989
  try {
@@ -51701,7 +51993,7 @@ async function serializeSnapshot(work) {
51701
51993
  }
51702
51994
  }
51703
51995
  function assertSnapshotIntegrity(path) {
51704
- const snapshot = new DatabaseSync2(path, { readOnly: true });
51996
+ const snapshot = new DatabaseSync3(path, { readOnly: true });
51705
51997
  try {
51706
51998
  const rows = snapshot.prepare("PRAGMA integrity_check").all();
51707
51999
  if (rows.length !== 1 || rows[0]?.integrity_check !== "ok") {
@@ -51710,7 +52002,7 @@ function assertSnapshotIntegrity(path) {
51710
52002
  }
51711
52003
  for (const row2 of snapshot.prepare("SELECT id, bytes, byte_length, sha256 FROM agent_results WHERE deleted_at IS NULL").iterate()) {
51712
52004
  const bytes = row2.bytes;
51713
- if (!(bytes instanceof Uint8Array) || bytes.byteLength !== row2.byte_length || createHash17("sha256").update(bytes).digest("hex") !== row2.sha256) {
52005
+ if (!(bytes instanceof Uint8Array) || bytes.byteLength !== row2.byte_length || createHash18("sha256").update(bytes).digest("hex") !== row2.sha256) {
51714
52006
  throw new Error(`Result snapshot integrity verification failed: ${row2.id}`);
51715
52007
  }
51716
52008
  }
@@ -51726,8 +52018,8 @@ function assertSnapshotIntegrity(path) {
51726
52018
  }
51727
52019
  async function createBackupSnapshot(db) {
51728
52020
  return serializeSnapshot(async () => {
51729
- const directory = mkdtempSync5(join31(tmpdir5(), "bazilion-backup-"));
51730
- const database = join31(directory, "bazilion.snapshot");
52021
+ const directory = mkdtempSync5(join32(tmpdir5(), "bazilion-backup-"));
52022
+ const database = join32(directory, "bazilion.snapshot");
51731
52023
  let cleaned = false;
51732
52024
  const cleanup = () => {
51733
52025
  if (cleaned) return;
@@ -51748,8 +52040,8 @@ async function createBackupSnapshot(db) {
51748
52040
  });
51749
52041
  }
51750
52042
  function createBackupArchive(paths2, snapshot) {
51751
- const snapshotPath = resolve6(snapshot.database);
51752
- return create6(
52043
+ const snapshotPath = resolve7(snapshot.database);
52044
+ return create7(
51753
52045
  {
51754
52046
  cwd: paths2.home,
51755
52047
  gzip: true,
@@ -51760,7 +52052,7 @@ function createBackupArchive(paths2, snapshot) {
51760
52052
  preservePaths: true,
51761
52053
  strict: true,
51762
52054
  filter(path) {
51763
- if (resolve6(path) === snapshotPath) return true;
52055
+ if (resolve7(path) === snapshotPath) return true;
51764
52056
  const normalized = path.replaceAll("\\", "/").replace(/^\.\//, "");
51765
52057
  if (normalized === "bazilion.db" || normalized.startsWith("bazilion.db-")) return false;
51766
52058
  if (normalized === "daemon-runtime.json" || normalized.startsWith("daemon-runtime.json.reclaim-")) {
@@ -51770,7 +52062,7 @@ function createBackupArchive(paths2, snapshot) {
51770
52062
  return true;
51771
52063
  },
51772
52064
  onWriteEntry(entry) {
51773
- if (resolve6(entry.absolute) === snapshotPath) entry.path = "./bazilion.db";
52065
+ if (resolve7(entry.absolute) === snapshotPath) entry.path = "./bazilion.db";
51774
52066
  }
51775
52067
  },
51776
52068
  [".", snapshotPath]
@@ -51778,7 +52070,7 @@ function createBackupArchive(paths2, snapshot) {
51778
52070
  }
51779
52071
 
51780
52072
  // ../daemon/src/lib/daemon-liveness.ts
51781
- import { createHash as createHash18, randomUUID as randomUUID41 } from "crypto";
52073
+ import { createHash as createHash19, randomUUID as randomUUID42 } from "crypto";
51782
52074
  import {
51783
52075
  chmodSync as chmodSync2,
51784
52076
  closeSync as closeSync10,
@@ -51786,32 +52078,32 @@ import {
51786
52078
  fsyncSync as fsyncSync2,
51787
52079
  ftruncateSync,
51788
52080
  futimesSync,
51789
- lstatSync as lstatSync7,
52081
+ lstatSync as lstatSync8,
51790
52082
  mkdirSync as mkdirSync11,
51791
52083
  openSync as openSync10,
51792
52084
  readFileSync as readFileSync13,
51793
- realpathSync as realpathSync11,
52085
+ realpathSync as realpathSync12,
51794
52086
  renameSync as renameSync3,
51795
52087
  rmSync as rmSync16,
51796
52088
  writeSync
51797
52089
  } from "fs";
51798
- import { basename as basename5, dirname as dirname6, join as join32, resolve as resolve7 } from "path";
52090
+ import { basename as basename6, dirname as dirname8, join as join33, resolve as resolve8 } from "path";
51799
52091
  var HEARTBEAT_MS = 2e3;
51800
52092
  function canonicalHomeIdentity(home) {
51801
- const absolute = resolve7(home);
52093
+ const absolute = resolve8(home);
51802
52094
  try {
51803
- return realpathSync11.native(absolute);
52095
+ return realpathSync12.native(absolute);
51804
52096
  } catch (error2) {
51805
52097
  if (errorCode(error2) !== "ENOENT") throw error2;
51806
- const parent = dirname6(absolute);
52098
+ const parent = dirname8(absolute);
51807
52099
  if (parent === absolute) throw error2;
51808
- return join32(canonicalHomeIdentity(parent), basename5(absolute));
52100
+ return join33(canonicalHomeIdentity(parent), basename6(absolute));
51809
52101
  }
51810
52102
  }
51811
52103
  function daemonLivenessPath(home) {
51812
- const canonicalHome = canonicalHomeIdentity(home);
51813
- const identity2 = createHash18("sha256").update(canonicalHome).digest("hex").slice(0, 24);
51814
- return join32(dirname6(canonicalHome), `.bazilion-runtime-${identity2}.json`);
52104
+ const canonicalHome2 = canonicalHomeIdentity(home);
52105
+ const identity2 = createHash19("sha256").update(canonicalHome2).digest("hex").slice(0, 24);
52106
+ return join33(dirname8(canonicalHome2), `.bazilion-runtime-${identity2}.json`);
51815
52107
  }
51816
52108
  var activeInstanceId = null;
51817
52109
  function getDaemonInstanceId() {
@@ -51825,7 +52117,7 @@ function errorCode(error2) {
51825
52117
  }
51826
52118
  function readExisting(path) {
51827
52119
  try {
51828
- const stat2 = lstatSync7(path);
52120
+ const stat2 = lstatSync8(path);
51829
52121
  const raw2 = stat2.isFile() ? readFileSync13(path, "utf8") : "";
51830
52122
  let instanceId;
51831
52123
  let version2;
@@ -51906,7 +52198,7 @@ function pidIsAlive(pid) {
51906
52198
  }
51907
52199
  }
51908
52200
  function reclaimStaleRecord(path, existing) {
51909
- const identity2 = createHash18("sha256").update(existing.instanceId ?? existing.raw).update(`\0${existing.stat.dev}\0${existing.stat.ino}`).digest("hex").slice(0, 24);
52201
+ const identity2 = createHash19("sha256").update(existing.instanceId ?? existing.raw).update(`\0${existing.stat.dev}\0${existing.stat.ino}`).digest("hex").slice(0, 24);
51910
52202
  const claim5 = `${path}.reclaim-${identity2}`;
51911
52203
  try {
51912
52204
  mkdirSync11(claim5, { mode: 448 });
@@ -51919,7 +52211,7 @@ function reclaimStaleRecord(path, existing) {
51919
52211
  if (!current || !sameFile(current.stat, existing.stat) || current.raw !== existing.raw) {
51920
52212
  return null;
51921
52213
  }
51922
- renameSync3(path, join32(claim5, "stale-record.json"));
52214
+ renameSync3(path, join33(claim5, "stale-record.json"));
51923
52215
  return claim5;
51924
52216
  } catch (error2) {
51925
52217
  if (!["ENOENT", "EEXIST"].includes(errorCode(error2) ?? "")) throw error2;
@@ -51936,7 +52228,7 @@ function writeRecord(fd, record3) {
51936
52228
  function fsyncParentDirectory(path) {
51937
52229
  let directoryFd = null;
51938
52230
  try {
51939
- directoryFd = openSync10(dirname6(path), "r");
52231
+ directoryFd = openSync10(dirname8(path), "r");
51940
52232
  fsyncSync2(directoryFd);
51941
52233
  } catch (error2) {
51942
52234
  if (process.platform !== "win32") throw error2;
@@ -51945,10 +52237,10 @@ function fsyncParentDirectory(path) {
51945
52237
  }
51946
52238
  }
51947
52239
  function acquireDaemonLiveness(paths2) {
51948
- mkdirSync11(dirname6(resolve7(paths2.home)), { recursive: true });
52240
+ mkdirSync11(dirname8(resolve8(paths2.home)), { recursive: true });
51949
52241
  const path = daemonLivenessPath(paths2.home);
51950
- mkdirSync11(dirname6(path), { recursive: true });
51951
- const instanceId = randomUUID41();
52242
+ mkdirSync11(dirname8(path), { recursive: true });
52243
+ const instanceId = randomUUID42();
51952
52244
  const startedAt = Date.now();
51953
52245
  let fd = null;
51954
52246
  let reclaimClaim = null;
@@ -52020,7 +52312,7 @@ function acquireDaemonLiveness(paths2) {
52020
52312
  closeSync10(fd);
52021
52313
  fd = null;
52022
52314
  try {
52023
- if (sameFile(lstatSync7(path), ownedStat)) rmSync16(path, { force: true });
52315
+ if (sameFile(lstatSync8(path), ownedStat)) rmSync16(path, { force: true });
52024
52316
  } catch {
52025
52317
  }
52026
52318
  throw error2;
@@ -52029,7 +52321,7 @@ function acquireDaemonLiveness(paths2) {
52029
52321
  let stopped = false;
52030
52322
  const stillOwnsPath = () => {
52031
52323
  try {
52032
- return sameFile(lstatSync7(path), ownedStat);
52324
+ return sameFile(lstatSync8(path), ownedStat);
52033
52325
  } catch {
52034
52326
  return false;
52035
52327
  }
@@ -52072,7 +52364,18 @@ function acquireDaemonLiveness(paths2) {
52072
52364
  const ownsPath = stillOwnsPath();
52073
52365
  closeSync10(fd);
52074
52366
  fd = null;
52075
- if (ownsPath) rmSync16(path, { force: true });
52367
+ if (!ownsPath) return;
52368
+ for (let attempt = 1; attempt <= 8; attempt++) {
52369
+ try {
52370
+ rmSync16(path, { force: true });
52371
+ return;
52372
+ } catch (error2) {
52373
+ const code = error2.code;
52374
+ if (attempt === 8 || !["EPERM", "EBUSY", "ENOTEMPTY"].includes(code ?? "")) throw error2;
52375
+ const wait = attempt * 250;
52376
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, wait);
52377
+ }
52378
+ }
52076
52379
  }
52077
52380
  };
52078
52381
  }
@@ -52173,7 +52476,14 @@ var protectedDockerReadiness = createProtectedDockerReadinessCache();
52173
52476
  miscRouter.get("/health", (c) => {
52174
52477
  const instanceId = getDaemonInstanceId();
52175
52478
  if (instanceId) c.header("x-bazilion-daemon-instance", instanceId);
52176
- return c.json({ ok: true });
52479
+ return c.json({
52480
+ ok: true,
52481
+ auth: {
52482
+ required: true,
52483
+ credentialKinds: ["bootstrap", "device", "pairing-code"],
52484
+ setupComplete: isSetupComplete(getCtx().db)
52485
+ }
52486
+ });
52177
52487
  });
52178
52488
  miscRouter.get("/health/details", async (c) => {
52179
52489
  const paths2 = resolvePaths();
@@ -52239,7 +52549,7 @@ miscRouter.get("/health/details", async (c) => {
52239
52549
  }
52240
52550
  }
52241
52551
  const providerConfig = loadProviderConfigFromEnv(effectiveEnv, oauth);
52242
- const openclawSkillsDir = join33(homedir2(), ".openclaw", "skills");
52552
+ const openclawSkillsDir = join34(homedir2(), ".openclaw", "skills");
52243
52553
  const CLOUD_KEYS = [
52244
52554
  ["anthropic", "anthropic"],
52245
52555
  ["openai", "openai"],
@@ -52431,10 +52741,23 @@ miscRouter.post("/tokens", async (c) => {
52431
52741
  if (!Number.isInteger(expiresInDays) || expiresInDays < 1 || expiresInDays > 365) {
52432
52742
  return c.json({ error: "expiresInDays must be an integer from 1 to 365" }, 400);
52433
52743
  }
52744
+ let scopes = [...ALL_DEVICE_TOKEN_SCOPES];
52745
+ if (body.scopes !== void 0) {
52746
+ if (!Array.isArray(body.scopes) || body.scopes.length === 0 || body.scopes.some((s) => !DEVICE_TOKEN_SCOPES.includes(s))) {
52747
+ return c.json(
52748
+ {
52749
+ error: `scopes must be a non-empty subset of: ${DEVICE_TOKEN_SCOPES.join(", ")}`
52750
+ },
52751
+ 400
52752
+ );
52753
+ }
52754
+ scopes = [...new Set(body.scopes)];
52755
+ }
52434
52756
  const { db } = getCtx();
52435
52757
  const created = webTokens_exports.create(db, body.label.trim(), {
52436
52758
  kind: "device",
52437
- expiresAt: Date.now() + expiresInDays * 864e5
52759
+ expiresAt: Date.now() + expiresInDays * 864e5,
52760
+ scopes
52438
52761
  });
52439
52762
  return c.json({ token: created.token, meta: created.meta }, 201);
52440
52763
  });
@@ -52463,7 +52786,7 @@ import { bodyLimit } from "hono/body-limit";
52463
52786
  import { HTTPException } from "hono/http-exception";
52464
52787
 
52465
52788
  // ../daemon/src/lib/notification-control.ts
52466
- import { randomUUID as randomUUID42 } from "crypto";
52789
+ import { randomUUID as randomUUID43 } from "crypto";
52467
52790
 
52468
52791
  // ../daemon/src/lib/notification-authorization.ts
52469
52792
  function authorizeAttentionNotification(db, item, captured) {
@@ -52628,7 +52951,7 @@ var NotificationControl = class {
52628
52951
  );
52629
52952
  for (const item of items) byKind[item.kind]++;
52630
52953
  const value = {
52631
- id: randomUUID42(),
52954
+ id: randomUUID43(),
52632
52955
  settingsRevision: revision4,
52633
52956
  destinationId: binding.id,
52634
52957
  kinds,
@@ -52838,7 +53161,7 @@ var NotificationDispatcher = class {
52838
53161
  if (!settings2.enabled || settings2.restorePaused) return;
52839
53162
  const binding = destinationBinding(this.db);
52840
53163
  if (!binding || this.transport.capture()?.id !== binding.id) {
52841
- for (const item of list11(this.db, { deferredOnly: true, limit: 100 }).receipts)
53164
+ for (const item of list12(this.db, { deferredOnly: true, limit: 100 }).receipts)
52842
53165
  suppress(this.db, item.id, "destination_changed", this.now());
52843
53166
  this.diagnostic = "notification_destination_unavailable";
52844
53167
  return;
@@ -52868,7 +53191,7 @@ var NotificationDispatcher = class {
52868
53191
  suppress(this.db, receipt.id, authorization.reason, this.now());
52869
53192
  if (++admitted >= 100) break;
52870
53193
  }
52871
- for (const receipt of list11(this.db, { deferredOnly: true, limit: 10 }).receipts) {
53194
+ for (const receipt of list12(this.db, { deferredOnly: true, limit: 10 }).receipts) {
52872
53195
  if (!this.#current(receipt.id)) continue;
52873
53196
  let claimed = null;
52874
53197
  const owner = { attempt: null };
@@ -53027,7 +53350,7 @@ notificationsRouter.get("/receipts", (c) => {
53027
53350
  const cursor = c.req.query("cursor");
53028
53351
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100 || cursor && !/^[a-f0-9-]{36}$/.test(cursor))
53029
53352
  return c.json({ error: "Invalid notification receipt page" }, 400);
53030
- return c.json(list11(getCtx().db, { limit, cursor }));
53353
+ return c.json(list12(getCtx().db, { limit, cursor }));
53031
53354
  });
53032
53355
  notificationsRouter.get("/receipts/:id", (c) => {
53033
53356
  const receipt = get17(getCtx().db, c.req.param("id"));
@@ -53053,7 +53376,7 @@ notificationsRouter.post("/receipts/:id/retry", async (c) => {
53053
53376
 
53054
53377
  // ../daemon/src/routes/profiles.ts
53055
53378
  import { existsSync as existsSync21, readFileSync as readFileSync14, writeFileSync as writeFileSync15 } from "fs";
53056
- import { join as join34 } from "path";
53379
+ import { join as join35 } from "path";
53057
53380
  import { Hono as Hono12 } from "hono";
53058
53381
  var profilesRouter = new Hono12();
53059
53382
  profilesRouter.get("/", (c) => {
@@ -53205,7 +53528,7 @@ profilesRouter.put("/:id/files/:file", async (c) => {
53205
53528
  });
53206
53529
  function resolveFilePath(profilesDir, id, file) {
53207
53530
  if (!PROFILE_FILES.includes(file)) return null;
53208
- return join34(profilesDir, id, file);
53531
+ return join35(profilesDir, id, file);
53209
53532
  }
53210
53533
  function csvToArray(v2) {
53211
53534
  if (Array.isArray(v2)) return v2.filter((s) => typeof s === "string");
@@ -53257,7 +53580,7 @@ questionsRouter.get("/:agentId/questions", (c) => {
53257
53580
  const { db } = getCtx();
53258
53581
  const conversationId = c.req.query("conversationId");
53259
53582
  return c.json({
53260
- questions: list12(db, c.req.param("agentId"), 100, conversationId).filter((item) => questionVisible(db, item))
53583
+ questions: list13(db, c.req.param("agentId"), 100, conversationId).filter((item) => questionVisible(db, item))
53261
53584
  });
53262
53585
  });
53263
53586
  questionsRouter.get("/:agentId/questions/:id", (c) => {
@@ -53418,7 +53741,7 @@ shellApprovalsRouter.post("/:id", async (c) => {
53418
53741
  // ../daemon/src/routes/skills.ts
53419
53742
  import { existsSync as existsSync22, mkdtempSync as mkdtempSync6, rmSync as rmSync17, writeFileSync as writeFileSync16 } from "fs";
53420
53743
  import { homedir as homedir3, tmpdir as tmpdir6 } from "os";
53421
- import { join as join35 } from "path";
53744
+ import { join as join36 } from "path";
53422
53745
  import { Hono as Hono16 } from "hono";
53423
53746
  var MAX_ZIP_BYTES = 50 * 1024 * 1024;
53424
53747
  var skillsRouter = new Hono16();
@@ -53512,8 +53835,8 @@ async function parseImportInput(request2) {
53512
53835
  if (!filename2.toLowerCase().endsWith(".zip")) {
53513
53836
  throw new Error("uploaded file must be a .zip archive");
53514
53837
  }
53515
- const tmpDir = mkdtempSync6(join35(tmpdir6(), "bazilion-skill-upload-"));
53516
- const zipPath = join35(tmpDir, filename2.replace(/[^\w.-]+/g, "_"));
53838
+ const tmpDir = mkdtempSync6(join36(tmpdir6(), "bazilion-skill-upload-"));
53839
+ const zipPath = join36(tmpDir, filename2.replace(/[^\w.-]+/g, "_"));
53517
53840
  const buf = Buffer.from(await file.arrayBuffer());
53518
53841
  writeFileSync16(zipPath, buf);
53519
53842
  const forceField = form.get("force");
@@ -53528,7 +53851,7 @@ async function parseImportInput(request2) {
53528
53851
  if (!body) throw new Error("invalid JSON body");
53529
53852
  const from = body.source ?? body.from;
53530
53853
  if (typeof from !== "string" || !from) throw new Error("source is required");
53531
- const source = from === "openclaw" ? join35(homedir3(), ".openclaw", "skills") : from;
53854
+ const source = from === "openclaw" ? join36(homedir3(), ".openclaw", "skills") : from;
53532
53855
  return {
53533
53856
  source,
53534
53857
  force: Boolean(body.force),
@@ -53538,7 +53861,7 @@ async function parseImportInput(request2) {
53538
53861
  }
53539
53862
 
53540
53863
  // ../daemon/src/routes/team-templates.ts
53541
- import { randomUUID as randomUUID43 } from "crypto";
53864
+ import { randomUUID as randomUUID44 } from "crypto";
53542
53865
  import { Hono as Hono17 } from "hono";
53543
53866
  var teamTemplatesRouter = new Hono17();
53544
53867
  teamTemplatesRouter.get("/", (c) => {
@@ -53578,7 +53901,7 @@ teamTemplatesRouter.post("/import", async (c) => {
53578
53901
  if (!profiles_exports.get(db, parsed.profileId)) {
53579
53902
  throw new Error(`profile not found: ${parsed.profileId}`);
53580
53903
  }
53581
- const slotId = randomUUID43();
53904
+ const slotId = randomUUID44();
53582
53905
  keyToSlot.set(clientKey, slotId);
53583
53906
  return { ...parsed, slotId };
53584
53907
  });
@@ -53799,7 +54122,7 @@ function parseSlot(value, index) {
53799
54122
  throw new Error(`invalid_template_definition: slot ${index} requires profileId and agentName`);
53800
54123
  }
53801
54124
  const reasoning = slot.reasoningLevel;
53802
- if (reasoning !== void 0 && reasoning !== null && (typeof reasoning !== "string" || !REASONING_LEVELS2.includes(reasoning))) {
54125
+ if (reasoning !== void 0 && reasoning !== null && (typeof reasoning !== "string" || !REASONING_LEVELS.includes(reasoning))) {
53803
54126
  throw new Error(`invalid_template_definition: slot ${index} reasoningLevel is invalid`);
53804
54127
  }
53805
54128
  const result = {
@@ -53870,7 +54193,7 @@ function canonicalError(c, error2) {
53870
54193
  }
53871
54194
 
53872
54195
  // ../daemon/src/routes/teams.ts
53873
- import { join as join39 } from "path";
54196
+ import { join as join40 } from "path";
53874
54197
  import { Hono as Hono18 } from "hono";
53875
54198
 
53876
54199
  // ../daemon/src/lib/coding-environment/management.ts
@@ -54075,9 +54398,9 @@ function resolvePublicationTarget(db, authToken) {
54075
54398
  }
54076
54399
 
54077
54400
  // ../daemon/src/lib/publication/revision-content.ts
54078
- import { createHash as createHash19 } from "crypto";
54401
+ import { createHash as createHash20 } from "crypto";
54079
54402
  import { readFileSync as readFileSync15 } from "fs";
54080
- import { join as join36 } from "path";
54403
+ import { join as join37 } from "path";
54081
54404
  function readReviewedRevisionFiles(db, paths2, packet) {
54082
54405
  const record3 = getSourceSnapshot(db, packet.teamId, packet.snapshotId);
54083
54406
  if (!record3) {
@@ -54127,7 +54450,7 @@ function readReviewedRevisionFiles(db, paths2, packet) {
54127
54450
  }
54128
54451
  let content;
54129
54452
  try {
54130
- content = readFileSync15(join36(paths2.teamDir(packet.teamId), entry.path));
54453
+ content = readFileSync15(join37(paths2.teamDir(packet.teamId), entry.path));
54131
54454
  } catch {
54132
54455
  return {
54133
54456
  ok: false,
@@ -54135,7 +54458,7 @@ function readReviewedRevisionFiles(db, paths2, packet) {
54135
54458
  detail: `the reviewed content for ${entry.path} can no longer be read`
54136
54459
  };
54137
54460
  }
54138
- const digest4 = createHash19("sha256").update(content).digest("hex");
54461
+ const digest4 = createHash20("sha256").update(content).digest("hex");
54139
54462
  if (digest4 !== entry.digest) {
54140
54463
  return {
54141
54464
  ok: false,
@@ -54251,7 +54574,7 @@ function refused2(reason, detail3) {
54251
54574
  // ../daemon/src/lib/publication/git-publish.ts
54252
54575
  import { execFile as execFile2 } from "child_process";
54253
54576
  import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync7, rmSync as rmSync18, writeFileSync as writeFileSync17 } from "fs";
54254
- import { dirname as dirname7, join as join37 } from "path";
54577
+ import { dirname as dirname9, join as join38 } from "path";
54255
54578
  import { promisify } from "util";
54256
54579
  var execFileAsync = promisify(execFile2);
54257
54580
  var COMMAND_BUDGET_MS = 6e4;
@@ -54259,8 +54582,8 @@ var MAX_OUTPUT = 64 * 1024;
54259
54582
  var AUTHOR_NAME = "Bazilion";
54260
54583
  var AUTHOR_EMAIL = "bazilion@localhost";
54261
54584
  async function publishRevisionCommit(input) {
54262
- const scratch = mkdtempSync7(join37(input.scratchParentDir ?? "/tmp", "bazilion-publish-"));
54263
- const gitDir = join37(scratch, "repo");
54585
+ const scratch = mkdtempSync7(join38(input.scratchParentDir ?? "/tmp", "bazilion-publish-"));
54586
+ const gitDir = join38(scratch, "repo");
54264
54587
  const gitEnv = environment(scratch, input.remoteUrl, input.credential);
54265
54588
  const run = (args, cwd = scratch) => git(["-C", gitDir, ...args], cwd, gitEnv);
54266
54589
  try {
@@ -54297,8 +54620,8 @@ async function publishRevisionCommit(input) {
54297
54620
  }
54298
54621
  await run(["checkout", "--quiet", "--detach", input.baseOid]);
54299
54622
  for (const file of input.files) {
54300
- const target = join37(gitDir, file.path);
54301
- mkdirSync12(dirname7(target), { recursive: true });
54623
+ const target = join38(gitDir, file.path);
54624
+ mkdirSync12(dirname9(target), { recursive: true });
54302
54625
  writeFileSync17(target, file.content);
54303
54626
  }
54304
54627
  for (const path of input.removed) {
@@ -54883,7 +55206,7 @@ function renderExportDocument(exported) {
54883
55206
  // ../daemon/src/lib/review/file-link.ts
54884
55207
  import { execFile as execFile3 } from "child_process";
54885
55208
  import { hostname } from "os";
54886
- import { isAbsolute as isAbsolute10, join as join38 } from "path";
55209
+ import { isAbsolute as isAbsolute10, join as join39 } from "path";
54887
55210
  import { promisify as promisify2 } from "util";
54888
55211
  var execFileAsync2 = promisify2(execFile3);
54889
55212
  var EDITOR_TEMPLATE_ENV = "BAZILION_REVIEW_EDITOR";
@@ -54896,7 +55219,7 @@ function buildFileLink(input) {
54896
55219
  const known = revision4.ok && revision4.changes.some((change) => change.path === input.path);
54897
55220
  const line = input.line !== null && input.line >= 1 ? input.line : null;
54898
55221
  const copyTarget = line === null ? input.path : `${input.path}:${line}`;
54899
- const hostPath = known ? join38(team.path, input.path) : null;
55222
+ const hostPath = known ? join39(team.path, input.path) : null;
54900
55223
  const template = env[EDITOR_TEMPLATE_ENV]?.trim();
54901
55224
  const mapped = hostPath ? mapHostPath(hostPath, env[EDITOR_MAP_ENV]) : null;
54902
55225
  if (!known) {
@@ -55445,7 +55768,7 @@ teamsRouter.post("/:id/review/snapshots", async (c) => {
55445
55768
  }
55446
55769
  let includeUntracked;
55447
55770
  if (input.includeUntracked !== void 0) {
55448
- if (!Array.isArray(input.includeUntracked) || input.includeUntracked.length > REVIEW_LIMITS2.files) {
55771
+ if (!Array.isArray(input.includeUntracked) || input.includeUntracked.length > REVIEW_LIMITS.files) {
55449
55772
  return c.json({ error: "Invalid untracked selection" }, 400);
55450
55773
  }
55451
55774
  includeUntracked = [];
@@ -55779,7 +56102,7 @@ async function openMemory(rawId) {
55779
56102
  const { db, paths: paths2 } = getCtx();
55780
56103
  const team = teams_exports.get(db, rawId, paths2);
55781
56104
  if (!team) throw new TeamMemoryNotFoundError(`team not found: ${rawId}`);
55782
- const mem = qmdBackend(join39(team.path, "memory"));
56105
+ const mem = qmdBackend(join40(team.path, "memory"));
55783
56106
  await mem.init();
55784
56107
  return { mem, team };
55785
56108
  }
@@ -56392,7 +56715,7 @@ userQueueRouter.onError((error2, c) => {
56392
56715
  userQueueRouter.get(
56393
56716
  "/:agentId/queue",
56394
56717
  (c) => c.json(
56395
- list13(getCtx().db, c.req.param("agentId"), {
56718
+ list14(getCtx().db, c.req.param("agentId"), {
56396
56719
  all: c.req.query("all") === "1",
56397
56720
  limit: Number(c.req.query("limit") ?? 20),
56398
56721
  offset: Number(c.req.query("offset") ?? 0)
@@ -56633,7 +56956,7 @@ function startUserQueuePump() {
56633
56956
  stopping = true;
56634
56957
  clearInterval(timer);
56635
56958
  for (const agentId of active.keys()) {
56636
- const head = list13(db, agentId, { limit: 1 }).items[0];
56959
+ const head = list14(db, agentId, { limit: 1 }).items[0];
56637
56960
  if (head?.status === "running") cancelAgent(agentId);
56638
56961
  }
56639
56962
  await Promise.allSettled(active.values());
@@ -56662,7 +56985,7 @@ try {
56662
56985
  try {
56663
56986
  getCtx();
56664
56987
  } catch (error2) {
56665
- const detail3 = error2 instanceof IncompatibleDatabaseError || error2 instanceof IncompatibleBootstrapIdentityError ? error2.message : error2 instanceof Error ? error2.stack ?? error2.message : String(error2);
56988
+ const detail3 = error2 instanceof IncompatibleDatabaseError || error2 instanceof DatabaseNewerThanBinaryError || error2 instanceof IncompatibleBootstrapIdentityError ? error2.message : error2 instanceof Error ? error2.stack ?? error2.message : String(error2);
56666
56989
  writeSync2(process.stderr.fd, `bazilion daemon failed to start: ${detail3}
56667
56990
  `);
56668
56991
  try {