blun-king-cli 9.1.19 → 9.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/blun.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // BLUN_BUILD_INPUT_SHA256:b991ad9b5744a4c7edb806fc71b837f5d58205791bc5979c4e05b6b5f3564456
2
+ // BLUN_BUILD_INPUT_SHA256:18b6ba1c5baca9739e0e2b5c280d073bac714589178a987d0bc9fd63d56020f0
3
3
  import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
4
4
  import { dirname as __cjsShimDirname } from 'node:path';
5
5
  const __filename = __cjsShimFileURLToPath(import.meta.url);
@@ -1167,7 +1167,7 @@ function normalizeBlunToolSchema(schema) {
1167
1167
  }
1168
1168
  function ensureBlunPropertyTypes(schema) {
1169
1169
  const normalized = cloneJsonValue(schema);
1170
- if (!isRecord$22(normalized)) throw new Error("JSON Schema root must normalize to an object.");
1170
+ if (!isRecord$23(normalized)) throw new Error("JSON Schema root must normalize to an object.");
1171
1171
  recurseSchema(normalized);
1172
1172
  return normalized;
1173
1173
  }
@@ -1228,7 +1228,7 @@ function resolveLocalJsonPointer(root, ref) {
1228
1228
  let current = root;
1229
1229
  for (const rawPart of ref.slice(2).split("/")) {
1230
1230
  const part = unescapeJsonPointerPart(rawPart);
1231
- if (isRecord$22(current)) {
1231
+ if (isRecord$23(current)) {
1232
1232
  if (!hasOwn(current, part)) return { found: false };
1233
1233
  current = current[part];
1234
1234
  } else if (Array.isArray(current)) {
@@ -1250,20 +1250,20 @@ function parseJsonPointerArrayIndex(part) {
1250
1250
  return Number(part);
1251
1251
  }
1252
1252
  function recurseSchema(node) {
1253
- if (!isRecord$22(node)) return;
1253
+ if (!isRecord$23(node)) return;
1254
1254
  visitChildSchemas(node, normalizeProperty);
1255
1255
  }
1256
1256
  function visitChildSchemas(node, visit) {
1257
1257
  for (const { key, kind } of CHILD_SCHEMA_SLOTS) {
1258
1258
  const value = node[key];
1259
1259
  if (kind === "single") {
1260
- if (isRecord$22(value)) visit(value);
1260
+ if (isRecord$23(value)) visit(value);
1261
1261
  } else if (kind === "array") {
1262
1262
  if (Array.isArray(value)) for (const item of value) visit(item);
1263
1263
  } else if (kind === "map") {
1264
- if (isRecord$22(value)) for (const item of Object.values(value)) visit(item);
1264
+ if (isRecord$23(value)) for (const item of Object.values(value)) visit(item);
1265
1265
  } else if (kind === "schema-or-array") {
1266
- if (isRecord$22(value)) visit(value);
1266
+ if (isRecord$23(value)) visit(value);
1267
1267
  else if (Array.isArray(value)) for (const item of value) visit(item);
1268
1268
  }
1269
1269
  }
@@ -1275,7 +1275,7 @@ function childSchemaKeysForParentType(parentType) {
1275
1275
  });
1276
1276
  }
1277
1277
  function normalizeProperty(node) {
1278
- if (!isRecord$22(node)) return;
1278
+ if (!isRecord$23(node)) return;
1279
1279
  if (!hasOwn(node, "type") && !hasAnyKey(node, TYPE_COMPLETION_SKIP_KEYS)) {
1280
1280
  const enumValues = node["enum"];
1281
1281
  if (Array.isArray(enumValues) && enumValues.length > 0) node["type"] = inferTypeFromValues(enumValues);
@@ -1359,14 +1359,14 @@ function hasAnyKey(obj, keys) {
1359
1359
  }
1360
1360
  function cloneJsonValue(value) {
1361
1361
  if (Array.isArray(value)) return value.map((item) => cloneJsonValue(item));
1362
- if (isRecord$22(value)) {
1362
+ if (isRecord$23(value)) {
1363
1363
  const cloned = {};
1364
1364
  for (const [key, child] of Object.entries(value)) cloned[key] = cloneJsonValue(child);
1365
1365
  return cloned;
1366
1366
  }
1367
1367
  return value;
1368
1368
  }
1369
- function isRecord$22(value) {
1369
+ function isRecord$23(value) {
1370
1370
  return typeof value === "object" && value !== null && !Array.isArray(value);
1371
1371
  }
1372
1372
  function hasOwn(obj, key) {
@@ -1587,7 +1587,7 @@ function isProviderRateLimitError(error) {
1587
1587
  if (error instanceof APIProviderRateLimitError) return true;
1588
1588
  const statusCode = getStatusCode(error);
1589
1589
  if (statusCode !== void 0) return statusCode === 429;
1590
- const lowerMessage = errorMessage$9(error).toLowerCase();
1590
+ const lowerMessage = errorMessage$13(error).toLowerCase();
1591
1591
  return PROVIDER_RATE_LIMIT_MESSAGE_PATTERNS.some((pattern) => pattern.test(lowerMessage));
1592
1592
  }
1593
1593
  function getStatusCode(error) {
@@ -1605,7 +1605,7 @@ function getStatusCode(error) {
1605
1605
  const responseStatus = responseRecord["status"];
1606
1606
  return typeof responseStatus === "number" ? responseStatus : void 0;
1607
1607
  }
1608
- function errorMessage$9(error) {
1608
+ function errorMessage$13(error) {
1609
1609
  return error instanceof Error ? error.message : String(error);
1610
1610
  }
1611
1611
  var ChatProviderError, APIConnectionError, APITimeoutError, APIStatusError, APIContextOverflowError, APIProviderRateLimitError, APIPaymentRequiredError, APIEmptyResponseError, CompactionStallError$1, NETWORK_RE, TIMEOUT_RE, CONTEXT_OVERFLOW_MESSAGE_PATTERNS, PROVIDER_RATE_LIMIT_MESSAGE_PATTERNS, PROVIDER_QUOTA_EXHAUSTED_MESSAGE_PATTERN, PROVIDER_QUOTA_EXHAUSTED_CONTEXT_PATTERNS, TOOL_EXCHANGE_ADJACENCY_MESSAGE_PATTERNS, STRUCTURAL_REQUEST_MESSAGE_PATTERNS;
@@ -1824,7 +1824,7 @@ function retryAfterHeaderMs(headers) {
1824
1824
  const fromDate = Math.max(0, retryAt - Date.now());
1825
1825
  return fromDate <= MAX_RETRY_DELAY_MS ? fromDate : null;
1826
1826
  }
1827
- async function readJson(response) {
1827
+ async function readJson$1(response) {
1828
1828
  const body = await response.text();
1829
1829
  if (body.trim().length === 0) throw new ChatProviderError("Provider returned an empty JSON response.");
1830
1830
  try {
@@ -1924,7 +1924,7 @@ var init_fetch_http_client = __esmMin((() => {
1924
1924
  signal: options?.signal
1925
1925
  }, options?.maxRetries);
1926
1926
  if (isStream) return parseServerSentJson(response);
1927
- return readJson(response);
1927
+ return readJson$1(response);
1928
1928
  }
1929
1929
  async uploadFile(params, options) {
1930
1930
  const form = new FormData();
@@ -1932,7 +1932,7 @@ var init_fetch_http_client = __esmMin((() => {
1932
1932
  form.append("file", params.file);
1933
1933
  const headers = this.requestHeaders();
1934
1934
  headers.delete("content-type");
1935
- const uploaded = await readJson(await this.fetchWithRetries("/files", {
1935
+ const uploaded = await readJson$1(await this.fetchWithRetries("/files", {
1936
1936
  method: "POST",
1937
1937
  headers,
1938
1938
  body: form,
@@ -5436,16 +5436,16 @@ function esc(str) {
5436
5436
  function slugify(input) {
5437
5437
  return input.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
5438
5438
  }
5439
- function isObject$4(data) {
5439
+ function isObject$5(data) {
5440
5440
  return typeof data === "object" && data !== null && !Array.isArray(data);
5441
5441
  }
5442
5442
  function isPlainObject$4(o) {
5443
- if (isObject$4(o) === false) return false;
5443
+ if (isObject$5(o) === false) return false;
5444
5444
  const ctor = o.constructor;
5445
5445
  if (ctor === void 0) return true;
5446
5446
  if (typeof ctor !== "function") return true;
5447
5447
  const prot = ctor.prototype;
5448
- if (isObject$4(prot) === false) return false;
5448
+ if (isObject$5(prot) === false) return false;
5449
5449
  if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) return false;
5450
5450
  return true;
5451
5451
  }
@@ -5454,7 +5454,7 @@ function shallowClone(o) {
5454
5454
  if (Array.isArray(o)) return [...o];
5455
5455
  return o;
5456
5456
  }
5457
- function escapeRegex$2(str) {
5457
+ function escapeRegex$3(str) {
5458
5458
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5459
5459
  }
5460
5460
  function clone$1(inst, def, params) {
@@ -6201,7 +6201,7 @@ var init_checks$2 = __esmMin((() => {
6201
6201
  });
6202
6202
  $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (inst, def) => {
6203
6203
  $ZodCheck.init(inst, def);
6204
- const escapedRegex = escapeRegex$2(def.includes);
6204
+ const escapedRegex = escapeRegex$3(def.includes);
6205
6205
  const pattern = new RegExp(typeof def.position === "number" ? `^.{${def.position}}${escapedRegex}` : escapedRegex);
6206
6206
  def.pattern = pattern;
6207
6207
  inst._zod.onattach.push((inst) => {
@@ -6224,7 +6224,7 @@ var init_checks$2 = __esmMin((() => {
6224
6224
  });
6225
6225
  $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith", (inst, def) => {
6226
6226
  $ZodCheck.init(inst, def);
6227
- const pattern = new RegExp(`^${escapeRegex$2(def.prefix)}.*`);
6227
+ const pattern = new RegExp(`^${escapeRegex$3(def.prefix)}.*`);
6228
6228
  def.pattern ?? (def.pattern = pattern);
6229
6229
  inst._zod.onattach.push((inst) => {
6230
6230
  const bag = inst._zod.bag;
@@ -6246,7 +6246,7 @@ var init_checks$2 = __esmMin((() => {
6246
6246
  });
6247
6247
  $ZodCheckEndsWith = /* @__PURE__ */ $constructor("$ZodCheckEndsWith", (inst, def) => {
6248
6248
  $ZodCheck.init(inst, def);
6249
- const pattern = new RegExp(`.*${escapeRegex$2(def.suffix)}$`);
6249
+ const pattern = new RegExp(`.*${escapeRegex$3(def.suffix)}$`);
6250
6250
  def.pattern ?? (def.pattern = pattern);
6251
6251
  inst._zod.onattach.push((inst) => {
6252
6252
  const bag = inst._zod.bag;
@@ -7008,7 +7008,7 @@ var init_schemas$2 = __esmMin((() => {
7008
7008
  }
7009
7009
  return propValues;
7010
7010
  });
7011
- const isObject = isObject$4;
7011
+ const isObject = isObject$5;
7012
7012
  const catchall = def.catchall;
7013
7013
  let value;
7014
7014
  inst._zod.parse = (payload, ctx) => {
@@ -7108,7 +7108,7 @@ var init_schemas$2 = __esmMin((() => {
7108
7108
  return (payload, ctx) => fn(shape, payload, ctx);
7109
7109
  };
7110
7110
  let fastpass;
7111
- const isObject = isObject$4;
7111
+ const isObject = isObject$5;
7112
7112
  const jit = !globalConfig.jitless;
7113
7113
  const fastEnabled = jit && allowsEval.value;
7114
7114
  const catchall = def.catchall;
@@ -7203,7 +7203,7 @@ var init_schemas$2 = __esmMin((() => {
7203
7203
  });
7204
7204
  inst._zod.parse = (payload, ctx) => {
7205
7205
  const input = payload.value;
7206
- if (!isObject$4(input)) {
7206
+ if (!isObject$5(input)) {
7207
7207
  payload.issues.push({
7208
7208
  code: "invalid_type",
7209
7209
  expected: "object",
@@ -7341,7 +7341,7 @@ var init_schemas$2 = __esmMin((() => {
7341
7341
  const values = getEnumValues(def.entries);
7342
7342
  const valuesSet = new Set(values);
7343
7343
  inst._zod.values = valuesSet;
7344
- inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o) => typeof o === "string" ? escapeRegex$2(o) : o.toString()).join("|")})$`);
7344
+ inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o) => typeof o === "string" ? escapeRegex$3(o) : o.toString()).join("|")})$`);
7345
7345
  inst._zod.parse = (payload, _ctx) => {
7346
7346
  const input = payload.value;
7347
7347
  if (valuesSet.has(input)) return payload;
@@ -7359,7 +7359,7 @@ var init_schemas$2 = __esmMin((() => {
7359
7359
  if (def.values.length === 0) throw new Error("Cannot create literal schema with no valid values");
7360
7360
  const values = new Set(def.values);
7361
7361
  inst._zod.values = values;
7362
- inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex$2(o) : o ? escapeRegex$2(o.toString()) : String(o)).join("|")})$`);
7362
+ inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex$3(o) : o ? escapeRegex$3(o.toString()) : String(o)).join("|")})$`);
7363
7363
  inst._zod.parse = (payload, _ctx) => {
7364
7364
  const input = payload.value;
7365
7365
  if (values.has(input)) return payload;
@@ -9987,6 +9987,7 @@ var init_schema = __esmMin((() => {
9987
9987
  ServicesConfigSchema = object({
9988
9988
  blunSearch: BlunServiceConfigSchema.optional(),
9989
9989
  blunFetch: BlunServiceConfigSchema.optional(),
9990
+ blunMedia: BlunServiceConfigSchema.optional(),
9990
9991
  visionReader: VisionReaderConfigSchema.optional()
9991
9992
  });
9992
9993
  McpServerCommonFields = {
@@ -10081,6 +10082,7 @@ var init_schema = __esmMin((() => {
10081
10082
  ServicesConfigPatchSchema = object({
10082
10083
  blunSearch: BlunServiceConfigPatchSchema.optional(),
10083
10084
  blunFetch: BlunServiceConfigPatchSchema.optional(),
10085
+ blunMedia: BlunServiceConfigPatchSchema.optional(),
10084
10086
  visionReader: VisionReaderConfigPatchSchema.optional()
10085
10087
  });
10086
10088
  BlunConfigPatchSchema = object({
@@ -10431,7 +10433,7 @@ function tokenFromWire(wire) {
10431
10433
  var init_types$17 = __esmMin((() => {}));
10432
10434
  //#endregion
10433
10435
  //#region ../../packages/oauth/src/utils.ts
10434
- function isRecord$21(value) {
10436
+ function isRecord$22(value) {
10435
10437
  return typeof value === "object" && value !== null && !Array.isArray(value);
10436
10438
  }
10437
10439
  var init_utils$1 = __esmMin((() => {}));
@@ -10755,7 +10757,7 @@ var init_storage = __esmMin((() => {
10755
10757
  } catch {
10756
10758
  return;
10757
10759
  }
10758
- if (!isRecord$21(parsed)) return void 0;
10760
+ if (!isRecord$22(parsed)) return void 0;
10759
10761
  return tokenFromWire(parsed);
10760
10762
  }
10761
10763
  async save(name, token) {
@@ -10849,15 +10851,15 @@ function extractApiErrorMessage(value) {
10849
10851
  }
10850
10852
  return;
10851
10853
  }
10852
- if (!isRecord$21(value)) return void 0;
10854
+ if (!isRecord$22(value)) return void 0;
10853
10855
  for (const key of DIRECT_ERROR_KEYS) {
10854
10856
  const message = stringField$4(value, key);
10855
10857
  if (message !== void 0) return message;
10856
10858
  }
10857
10859
  const error = value["error"];
10858
- const errorString = nonEmptyString$6(error);
10860
+ const errorString = nonEmptyString$7(error);
10859
10861
  if (errorString !== void 0) return errorString;
10860
- if (isRecord$21(error)) for (const key of NESTED_ERROR_KEYS) {
10862
+ if (isRecord$22(error)) for (const key of NESTED_ERROR_KEYS) {
10861
10863
  const message = stringField$4(error, key);
10862
10864
  if (message !== void 0) return message;
10863
10865
  }
@@ -10877,9 +10879,9 @@ async function readApiErrorMessage(response, fallback) {
10877
10879
  return extractApiErrorMessage(parsed) ?? fallback;
10878
10880
  }
10879
10881
  function stringField$4(record, key) {
10880
- return nonEmptyString$6(record[key]);
10882
+ return nonEmptyString$7(record[key]);
10881
10883
  }
10882
- function nonEmptyString$6(value) {
10884
+ function nonEmptyString$7(value) {
10883
10885
  if (typeof value !== "string") return void 0;
10884
10886
  const trimmed = value.trim();
10885
10887
  return trimmed.length > 0 ? trimmed : void 0;
@@ -10947,7 +10949,7 @@ async function postForm(url, params, deviceHeaders, options) {
10947
10949
  let data = {};
10948
10950
  try {
10949
10951
  const parsed = await response.json();
10950
- if (isRecord$21(parsed)) data = parsed;
10952
+ if (isRecord$22(parsed)) data = parsed;
10951
10953
  } catch {}
10952
10954
  return {
10953
10955
  status,
@@ -12859,9 +12861,9 @@ function blunContextWindowsUrl(oauthHost) {
12859
12861
  return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}/api/verbrauch/tarife`;
12860
12862
  }
12861
12863
  function parseManagedContextWindow(payload, plan) {
12862
- if (!isRecord$21(payload)) return void 0;
12864
+ if (!isRecord$22(payload)) return void 0;
12863
12865
  const contextWindows = payload["kontext"];
12864
- if (!isRecord$21(contextWindows)) return void 0;
12866
+ if (!isRecord$22(contextWindows)) return void 0;
12865
12867
  const value = contextWindows[plan];
12866
12868
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
12867
12869
  }
@@ -12896,7 +12898,7 @@ function parseManagedUsagePayload(payload) {
12896
12898
  const plan = typeof rec["plan"] === "string" && rec["plan"].trim().length > 0 ? rec["plan"].trim() : void 0;
12897
12899
  const contextWindowTokens = managedContextWindowFrom(rec);
12898
12900
  const unlimited = rec["unlimited"] === true;
12899
- const stand = isRecord$21(rec["stand"]) ? rec["stand"] : void 0;
12901
+ const stand = isRecord$22(rec["stand"]) ? rec["stand"] : void 0;
12900
12902
  if (stand !== void 0) for (const [sourceKey, id, label] of ACCOUNT_USAGE_WINDOWS) {
12901
12903
  const row = toAccountUsageRow(stand[sourceKey], id, label, unlimited);
12902
12904
  if (row !== null) limits.push(row);
@@ -12906,9 +12908,9 @@ function parseManagedUsagePayload(payload) {
12906
12908
  const item = rawLimits[idx];
12907
12909
  if (!item || typeof item !== "object") continue;
12908
12910
  const detailRaw = item["detail"];
12909
- const detail = isRecord$21(detailRaw) ? detailRaw : item;
12911
+ const detail = isRecord$22(detailRaw) ? detailRaw : item;
12910
12912
  const windowRaw = item["window"];
12911
- const row = toUsageRow(detail, limitLabel(item, detail, isRecord$21(windowRaw) ? windowRaw : {}, idx));
12913
+ const row = toUsageRow(detail, limitLabel(item, detail, isRecord$22(windowRaw) ? windowRaw : {}, idx));
12912
12914
  if (row !== null) limits.push(row);
12913
12915
  }
12914
12916
  return {
@@ -12932,7 +12934,7 @@ function managedContextWindowFrom(payload) {
12932
12934
  return values.every((value) => value === first) ? first : void 0;
12933
12935
  }
12934
12936
  function toAccountUsageRow(raw, id, label, accountUnlimited) {
12935
- if (!isRecord$21(raw)) return null;
12937
+ if (!isRecord$22(raw)) return null;
12936
12938
  const used = toInt(raw["verbraucht"]);
12937
12939
  const unlimited = accountUnlimited || raw["unlimited"] === true;
12938
12940
  const fraction = raw["anteil"];
@@ -12965,7 +12967,7 @@ function toAccountUsageRow(raw, id, label, accountUnlimited) {
12965
12967
  };
12966
12968
  }
12967
12969
  function toUsageRow(raw, defaultLabel) {
12968
- if (!isRecord$21(raw)) return null;
12970
+ if (!isRecord$22(raw)) return null;
12969
12971
  const unlimited = raw["unlimited"] === true;
12970
12972
  const limit = toInt(raw["limit"]);
12971
12973
  let used = toInt(raw["used"]);
@@ -13086,7 +13088,7 @@ function isManagedQuotaErrorMessage(message) {
13086
13088
  return /you(?:'|’)?ve reached your usage limit/.test(normalized) && /billing cycle|quota will be (?:refreshed|reset)|purchase extra usage/.test(normalized);
13087
13089
  }
13088
13090
  function hasManagedUsageShape(payload) {
13089
- if (!isRecord$21(payload)) return false;
13091
+ if (!isRecord$22(payload)) return false;
13090
13092
  let recognized = false;
13091
13093
  if ("context_window_tokens" in payload || "contextWindowTokens" in payload) {
13092
13094
  recognized = true;
@@ -13102,15 +13104,15 @@ function hasManagedUsageShape(payload) {
13102
13104
  if (!Array.isArray(limits)) return false;
13103
13105
  for (let index = 0; index < limits.length; index++) {
13104
13106
  const item = limits[index];
13105
- if (!isRecord$21(item)) return false;
13106
- const detail = isRecord$21(item["detail"]) ? item["detail"] : item;
13107
- if (toUsageRow(detail, limitLabel(item, detail, isRecord$21(item["window"]) ? item["window"] : {}, index)) === null) return false;
13107
+ if (!isRecord$22(item)) return false;
13108
+ const detail = isRecord$22(item["detail"]) ? item["detail"] : item;
13109
+ if (toUsageRow(detail, limitLabel(item, detail, isRecord$22(item["window"]) ? item["window"] : {}, index)) === null) return false;
13108
13110
  }
13109
13111
  }
13110
13112
  if ("stand" in payload) {
13111
13113
  recognized = true;
13112
13114
  const stand = payload["stand"];
13113
- if (!isRecord$21(stand)) return false;
13115
+ if (!isRecord$22(stand)) return false;
13114
13116
  const windows = ACCOUNT_USAGE_WINDOWS.filter(([sourceKey]) => sourceKey in stand);
13115
13117
  if (windows.length === 0) return false;
13116
13118
  const unlimited = payload["unlimited"] === true;
@@ -13206,8 +13208,8 @@ function userExtras(existing, remoteOwnedFields) {
13206
13208
  return out;
13207
13209
  }
13208
13210
  function mergeRefreshedModelAlias(existing, remote, remoteOwnedFields) {
13209
- const current = isRecord$21(existing) ? existing : {};
13210
- const overrides = cloneOverrides(isRecord$21(current["overrides"]) ? current["overrides"] : void 0);
13211
+ const current = isRecord$22(existing) ? existing : {};
13212
+ const overrides = cloneOverrides(isRecord$22(current["overrides"]) ? current["overrides"] : void 0);
13211
13213
  return {
13212
13214
  ...userExtras(current, remoteOwnedFields),
13213
13215
  ...remote,
@@ -13389,7 +13391,7 @@ function parseModelContextLength(item, modelId) {
13389
13391
  return values[0];
13390
13392
  }
13391
13393
  function toModelInfo(item) {
13392
- if (!isRecord$21(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
13394
+ if (!isRecord$22(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
13393
13395
  const contextLength = parseModelContextLength(item, item["id"]);
13394
13396
  const displayName = item["display_name"];
13395
13397
  const normalizedDisplayName = typeof displayName === "string" && displayName.length > 0 ? displayName : void 0;
@@ -13476,7 +13478,7 @@ async function fetchManagedBlunCodeModels(options) {
13476
13478
  throw new Error(message);
13477
13479
  }
13478
13480
  const payload = await response.json();
13479
- if (!isRecord$21(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
13481
+ if (!isRecord$22(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
13480
13482
  return payload["data"].map((item) => toModelInfo(item)).filter((item) => item !== void 0);
13481
13483
  }
13482
13484
  throw new Error(`Failed to list BLUN models for ${baseUrl}.`);
@@ -13519,11 +13521,11 @@ function applyManagedBlunCodeConfig(config, options) {
13519
13521
  apiKey
13520
13522
  };
13521
13523
  const upstreamKeys = new Set(options.models.map((m) => managedModelKey(m.id)));
13522
- for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$21(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
13524
+ for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$22(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
13523
13525
  for (const model of options.models) {
13524
13526
  const capabilities = capabilitiesForModel(model);
13525
13527
  const key = managedModelKey(model.id);
13526
- const existing = isRecord$21(existingModels[key]) ? existingModels[key] : {};
13528
+ const existing = isRecord$22(existingModels[key]) ? existingModels[key] : {};
13527
13529
  const supportsAdaptiveThinking = capabilities?.includes("thinking") === true || capabilities?.includes("always_thinking") === true;
13528
13530
  existingModels[key] = mergeRefreshedModelAlias(existing, {
13529
13531
  provider: BLUN_PROVIDER_NAME$1,
@@ -13555,6 +13557,10 @@ function applyManagedBlunCodeConfig(config, options) {
13555
13557
  blunFetch: {
13556
13558
  baseUrl: `${auxiliaryBaseUrl}/fetch`,
13557
13559
  ...serviceCredential
13560
+ },
13561
+ blunMedia: {
13562
+ baseUrl,
13563
+ ...serviceCredential
13558
13564
  }
13559
13565
  };
13560
13566
  return {
@@ -13567,7 +13573,7 @@ function applyManagedBlunCodeLogoutConfig(config) {
13567
13573
  let removedDefaultModel = false;
13568
13574
  const existingModels = config.models ?? {};
13569
13575
  for (const [key, model] of Object.entries(existingModels)) {
13570
- if (!isRecord$21(model) || model["provider"] !== "managed:blun") continue;
13576
+ if (!isRecord$22(model) || model["provider"] !== "managed:blun") continue;
13571
13577
  delete existingModels[key];
13572
13578
  if (config.defaultModel === key) removedDefaultModel = true;
13573
13579
  }
@@ -13577,6 +13583,7 @@ function applyManagedBlunCodeLogoutConfig(config) {
13577
13583
  if (config.services !== void 0) {
13578
13584
  delete config.services.blunSearch;
13579
13585
  delete config.services.blunFetch;
13586
+ delete config.services.blunMedia;
13580
13587
  if (Object.keys(config.services).length === 0) config.services = void 0;
13581
13588
  }
13582
13589
  }
@@ -13606,7 +13613,7 @@ function selectDefaultModel(config, models, options) {
13606
13613
  function canPreserveDefaultModel(existingModels, defaultModel, managedModels) {
13607
13614
  if (managedModels.has(defaultModel)) return true;
13608
13615
  const existing = existingModels[defaultModel];
13609
- return isRecord$21(existing) && existing["provider"] !== "managed:blun";
13616
+ return isRecord$22(existing) && existing["provider"] !== "managed:blun";
13610
13617
  }
13611
13618
  function assertPositiveContextLength(model) {
13612
13619
  if (!Number.isInteger(model.contextLength) || model.contextLength <= 0) throw new Error(`BLUN model "${model.id}" must include a positive context_length.`);
@@ -13684,13 +13691,13 @@ function blunManagedQuotaUrl(oauthHost) {
13684
13691
  return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}${MANAGED_QUOTA_PATH}`;
13685
13692
  }
13686
13693
  function parseManagedQuotaPayload(payload) {
13687
- if (!isRecord$21(payload)) return void 0;
13688
- const plan = nonEmptyString$5(payload["plan"]);
13694
+ if (!isRecord$22(payload)) return void 0;
13695
+ const plan = nonEmptyString$6(payload["plan"]);
13689
13696
  const paid = payload["bezahlt"];
13690
13697
  const creditCents = payload["guthaben_cent"];
13691
- const billingKind = nonEmptyString$5(payload["art"]);
13698
+ const billingKind = nonEmptyString$6(payload["art"]);
13692
13699
  const globalUnlimited = payload["unlimited"];
13693
- if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$21(payload["stand"])) return;
13700
+ if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$22(payload["stand"])) return;
13694
13701
  if (!hasStrictQuotaStand(payload["stand"], globalUnlimited === true)) return void 0;
13695
13702
  const limits = parseManagedUsagePayload(payload).limits;
13696
13703
  if (limits.length !== REQUIRED_WINDOWS.length || REQUIRED_WINDOWS.some(([, id]) => limits.filter((row) => row.id === id).length !== 1)) return;
@@ -13752,7 +13759,7 @@ async function managedQuotaErrorCode(response) {
13752
13759
  if (response.status !== 403) return "unavailable";
13753
13760
  return isManagedQuotaErrorMessage(await readApiErrorMessage(response, "")) ? "unavailable" : "unauthenticated";
13754
13761
  }
13755
- function nonEmptyString$5(value) {
13762
+ function nonEmptyString$6(value) {
13756
13763
  if (typeof value !== "string") return void 0;
13757
13764
  const normalized = value.trim();
13758
13765
  return normalized.length === 0 ? void 0 : normalized;
@@ -13760,7 +13767,7 @@ function nonEmptyString$5(value) {
13760
13767
  function hasStrictQuotaStand(stand, globalUnlimited) {
13761
13768
  return REQUIRED_WINDOWS.every(([sourceKey]) => {
13762
13769
  const row = stand[sourceKey];
13763
- if (!isRecord$21(row)) return false;
13770
+ if (!isRecord$22(row)) return false;
13764
13771
  const used = row["verbraucht"];
13765
13772
  const rowUnlimited = row["unlimited"];
13766
13773
  if (rowUnlimited !== void 0 && typeof rowUnlimited !== "boolean") return false;
@@ -14312,15 +14319,15 @@ function readModel(config, alias) {
14312
14319
  const model = config.models?.[alias];
14313
14320
  return model === void 0 ? void 0 : model;
14314
14321
  }
14315
- function nonEmptyString$4(value) {
14322
+ function nonEmptyString$5(value) {
14316
14323
  const trimmed = value?.trim();
14317
14324
  return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
14318
14325
  }
14319
14326
  function providerApiKey$1(provider) {
14320
- return nonEmptyString$4(provider.apiKey) ?? nonEmptyString$4(provider.env?.["BLUN_API_KEY"]);
14327
+ return nonEmptyString$5(provider.apiKey) ?? nonEmptyString$5(provider.env?.["BLUN_API_KEY"]);
14321
14328
  }
14322
14329
  function providerBaseUrl(provider) {
14323
- return nonEmptyString$4(provider.baseUrl) ?? nonEmptyString$4(provider.env?.["BLUN_BASE_URL"]);
14330
+ return nonEmptyString$5(provider.baseUrl) ?? nonEmptyString$5(provider.env?.["BLUN_BASE_URL"]);
14324
14331
  }
14325
14332
  function collectModelIdsForAliases(config, aliasKeys) {
14326
14333
  const ids = /* @__PURE__ */ new Set();
@@ -14367,6 +14374,14 @@ function providerModelsEqual(config, nextConfig, providerId, aliasKeys) {
14367
14374
  function providerConfigEqual(config, nextConfig, providerId) {
14368
14375
  return JSON.stringify(config.providers[providerId] ?? null) === JSON.stringify(nextConfig.providers[providerId] ?? null);
14369
14376
  }
14377
+ function managedServicesEqual(config, nextConfig) {
14378
+ const snapshot = (candidate) => JSON.stringify({
14379
+ blunSearch: candidate.services?.blunSearch ?? null,
14380
+ blunFetch: candidate.services?.blunFetch ?? null,
14381
+ blunMedia: candidate.services?.blunMedia ?? null
14382
+ });
14383
+ return snapshot(config) === snapshot(nextConfig);
14384
+ }
14370
14385
  async function refreshProviderModels(host, options = {}) {
14371
14386
  const changed = [];
14372
14387
  const unchanged = [];
@@ -14386,7 +14401,7 @@ async function refreshProviderModels(host, options = {}) {
14386
14401
  failed
14387
14402
  };
14388
14403
  }
14389
- const managedApiKey = nonEmptyString$4(managedProvider?.apiKey);
14404
+ const managedApiKey = nonEmptyString$5(managedProvider?.apiKey);
14390
14405
  const managedHasOAuth = managedProvider?.oauth !== void 0;
14391
14406
  if (managedWanted && managedProvider !== void 0 && managedProvider.type === "blun" && (managedApiKey !== void 0 || managedHasOAuth)) try {
14392
14407
  if (managedApiKey !== void 0 && managedHasOAuth) throw new Error("Managed BLUN OAuth and API key credentials are mutually exclusive.");
@@ -14414,7 +14429,7 @@ async function refreshProviderModels(host, options = {}) {
14414
14429
  });
14415
14430
  const refreshedAliasKeys = providerAliasKeys(config, BLUN_PROVIDER_NAME$1);
14416
14431
  for (const alias of providerAliasKeys(next, BLUN_PROVIDER_NAME$1)) refreshedAliasKeys.add(alias);
14417
- if (providerModelsEqual(config, next, "managed:blun", refreshedAliasKeys) && config.defaultModel === next.defaultModel) unchanged.push(BLUN_PROVIDER_NAME$1);
14432
+ if (providerModelsEqual(config, next, "managed:blun", refreshedAliasKeys) && config.defaultModel === next.defaultModel && managedServicesEqual(config, next)) unchanged.push(BLUN_PROVIDER_NAME$1);
14418
14433
  else {
14419
14434
  const { added, removed } = computeChanges(collectModelIdsForAliases(config, refreshedAliasKeys), collectModelIdsForAliases(next, refreshedAliasKeys));
14420
14435
  await host.removeProvider(BLUN_PROVIDER_NAME$1);
@@ -14422,7 +14437,8 @@ async function refreshProviderModels(host, options = {}) {
14422
14437
  providers: next.providers,
14423
14438
  models: next.models,
14424
14439
  defaultModel: next.defaultModel,
14425
- thinking: next.thinking
14440
+ thinking: next.thinking,
14441
+ services: next.services
14426
14442
  });
14427
14443
  changed.push({
14428
14444
  providerId: BLUN_PROVIDER_NAME$1,
@@ -16051,6 +16067,8 @@ function servicesToToml(services, rawServices) {
16051
16067
  else delete out["blun_search"];
16052
16068
  if (services.blunFetch !== void 0) out["blun_fetch"] = serviceToToml(services.blunFetch);
16053
16069
  else delete out["blun_fetch"];
16070
+ if (services.blunMedia !== void 0) out["blun_media"] = serviceToToml(services.blunMedia);
16071
+ else delete out["blun_media"];
16054
16072
  if (services.visionReader !== void 0) out["vision_reader"] = visionReaderToToml(services.visionReader);
16055
16073
  else delete out["vision_reader"];
16056
16074
  return out;
@@ -20925,11 +20943,11 @@ function parseSkillText(options) {
20925
20943
  throw error;
20926
20944
  }
20927
20945
  const frontmatter = parsed.data ?? {};
20928
- if (!isRecord$20(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
20946
+ if (!isRecord$21(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
20929
20947
  const metadata = normalizeMetadata(frontmatter);
20930
20948
  if (!isSupportedSkillType(metadata.type)) throw new UnsupportedSkillTypeError(metadata.type ?? String(frontmatter["type"]));
20931
- const name = nonEmptyString$3(metadata.name);
20932
- const description = nonEmptyString$3(metadata.description);
20949
+ const name = nonEmptyString$4(metadata.name);
20950
+ const description = nonEmptyString$4(metadata.description);
20933
20951
  if (isDirectorySkill && (name === void 0 || description === void 0)) throw new SkillParseError(`Missing required frontmatter field ${name === void 0 ? "\"name\"" : "\"description\""} in ${options.skillMdPath}`);
20934
20952
  const skillPath = posix$2.resolve(options.skillMdPath);
20935
20953
  const content = parsed.body.trim();
@@ -20989,11 +21007,11 @@ function normalizeMetadata(raw) {
20989
21007
  const key = METADATA_ALIASES[rawKey] ?? rawKey;
20990
21008
  out[key] = value;
20991
21009
  }
20992
- const type = nonEmptyString$3(out["type"]);
21010
+ const type = nonEmptyString$4(out["type"]);
20993
21011
  if (type !== void 0) out["type"] = type;
20994
- const name = nonEmptyString$3(out["name"]);
21012
+ const name = nonEmptyString$4(out["name"]);
20995
21013
  if (name !== void 0) out["name"] = name;
20996
- const description = nonEmptyString$3(out["description"]);
21014
+ const description = nonEmptyString$4(out["description"]);
20997
21015
  if (description !== void 0) out["description"] = description;
20998
21016
  return out;
20999
21017
  }
@@ -21035,10 +21053,10 @@ function tokenizeArgs(raw) {
21035
21053
  if (hasContent) out.push(current);
21036
21054
  return out;
21037
21055
  }
21038
- function nonEmptyString$3(value) {
21056
+ function nonEmptyString$4(value) {
21039
21057
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
21040
21058
  }
21041
- function isRecord$20(value) {
21059
+ function isRecord$21(value) {
21042
21060
  return typeof value === "object" && value !== null && !Array.isArray(value);
21043
21061
  }
21044
21062
  var import_regexp_escape, FrontmatterError, SkillParseError, UnsupportedSkillTypeError, FENCE, METADATA_ALIASES;
@@ -21087,14 +21105,14 @@ var init_parser$1 = __esmMin((() => {
21087
21105
  function parseCommandText(input) {
21088
21106
  const { text, commandPath, pluginId } = input;
21089
21107
  const parsed = parseFrontmatter(text);
21090
- const frontmatter = isRecord$19(parsed.data) ? parsed.data : {};
21108
+ const frontmatter = isRecord$20(parsed.data) ? parsed.data : {};
21091
21109
  const baseName = input.fallbackName ?? path.basename(commandPath).replace(/\.md$/i, "");
21092
- const name = nonEmptyString$2(frontmatter["name"]) ?? baseName;
21110
+ const name = nonEmptyString$3(frontmatter["name"]) ?? baseName;
21093
21111
  const body = parsed.body.trim();
21094
21112
  return {
21095
21113
  pluginId,
21096
21114
  name,
21097
- description: nonEmptyString$2(frontmatter["description"]) ?? descriptionFromBody(body),
21115
+ description: nonEmptyString$3(frontmatter["description"]) ?? descriptionFromBody(body),
21098
21116
  body,
21099
21117
  path: path.resolve(commandPath)
21100
21118
  };
@@ -21121,7 +21139,7 @@ function expandCommandArguments(body, args) {
21121
21139
  if (!body.includes("$ARGUMENTS") && args.length > 0) return `${replaced}\n\nARGUMENTS: ${args}`;
21122
21140
  return replaced;
21123
21141
  }
21124
- function nonEmptyString$2(value) {
21142
+ function nonEmptyString$3(value) {
21125
21143
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
21126
21144
  }
21127
21145
  function descriptionFromBody(body) {
@@ -21129,7 +21147,7 @@ function descriptionFromBody(body) {
21129
21147
  if (firstLine === void 0) return "No description provided.";
21130
21148
  return firstLine.length > 240 ? `${firstLine.slice(0, 239)}…` : firstLine;
21131
21149
  }
21132
- function isRecord$19(value) {
21150
+ function isRecord$20(value) {
21133
21151
  return typeof value === "object" && value !== null && !Array.isArray(value);
21134
21152
  }
21135
21153
  var init_commands = __esmMin((() => {
@@ -28340,7 +28358,7 @@ var init_load = __esmMin((() => {
28340
28358
  //#region ../../packages/agent-core/src/profile/default/agent.yaml?raw
28341
28359
  var agent_default$1;
28342
28360
  var init_agent$3 = __esmMin((() => {
28343
- agent_default$1 = "name: agent\ndescription: Default BLUN King agent\n\nsystemPromptPath: ./system.md\npromptVars:\n roleAdditional: ''\n\ntools:\n - Read\n - Write\n - Edit\n - Grep\n - Glob\n - Bash\n - TaskList\n - TaskOutput\n - TaskStop\n - CronCreate\n - CronList\n - CronDelete\n - ReadMediaFile\n - TodoList\n - Skill\n - WebSearch\n - Agent\n - AgentSwarm\n - FetchURL\n - AskUserQuestion\n - MistakeRecord\n - CodebaseSearch\n - EnterPlanMode\n - ExitPlanMode\n - CreateGoal\n - GetGoal\n - SetGoalBudget\n - UpdateGoal\n - mcp__*\n\nsubagents:\n coder:\n description: General software engineering agent — the only subagent type with file-editing tools; use it for any delegated task that must modify code.\n explore:\n description: Fast codebase exploration with prompt-enforced read-only behavior.\n plan:\n description: Read-only implementation planning and architecture design.\n";
28361
+ agent_default$1 = "name: agent\ndescription: Default BLUN King agent\n\nsystemPromptPath: ./system.md\npromptVars:\n roleAdditional: ''\n\ntools:\n - Read\n - Write\n - Edit\n - Grep\n - Glob\n - Bash\n - TaskList\n - TaskOutput\n - TaskStop\n - CronCreate\n - CronList\n - CronDelete\n - ReadMediaFile\n - TodoList\n - Skill\n - WebSearch\n - Agent\n - AgentSwarm\n - FetchURL\n - GenerateImage\n - GenerateVideo\n - GenerateSpeech\n - GetMedia\n - AskUserQuestion\n - MistakeRecord\n - CodebaseSearch\n - EnterPlanMode\n - ExitPlanMode\n - CreateGoal\n - GetGoal\n - SetGoalBudget\n - UpdateGoal\n - mcp__*\n\nsubagents:\n coder:\n description: General software engineering agent — the only subagent type with file-editing tools; use it for any delegated task that must modify code.\n explore:\n description: Fast codebase exploration with prompt-enforced read-only behavior.\n plan:\n description: Read-only implementation planning and architecture design.\n";
28344
28362
  }));
28345
28363
  //#endregion
28346
28364
  //#region ../../packages/agent-core/src/profile/default/coder.yaml?raw
@@ -28476,7 +28494,7 @@ function isAbortError$4(err) {
28476
28494
  if (err instanceof Error) return err.name === "AbortError";
28477
28495
  return false;
28478
28496
  }
28479
- function errorMessage$8(err) {
28497
+ function errorMessage$12(err) {
28480
28498
  if (err instanceof Error) return err.message;
28481
28499
  return String(err);
28482
28500
  }
@@ -28700,7 +28718,7 @@ function normalizePersistedTask$1(task) {
28700
28718
  }
28701
28719
  function legacyPersistedTaskToInfo$1(task) {
28702
28720
  const status = legacyStatusToCurrent$1(task);
28703
- const stopReason = optionalNonEmptyString$1(task.stop_reason);
28721
+ const stopReason = optionalNonEmptyString$2(task.stop_reason);
28704
28722
  const timeoutMs = typeof task.timeout_ms === "number" ? task.timeout_ms : void 0;
28705
28723
  const base = {
28706
28724
  taskId: task.task_id,
@@ -28715,8 +28733,8 @@ function legacyPersistedTaskToInfo$1(task) {
28715
28733
  if (task.task_id.startsWith("agent-")) return {
28716
28734
  ...base,
28717
28735
  kind: "agent",
28718
- agentId: optionalNonEmptyString$1(task.agent_id),
28719
- subagentType: optionalNonEmptyString$1(task.subagent_type)
28736
+ agentId: optionalNonEmptyString$2(task.agent_id),
28737
+ subagentType: optionalNonEmptyString$2(task.subagent_type)
28720
28738
  };
28721
28739
  return {
28722
28740
  ...base,
@@ -28732,15 +28750,15 @@ function legacyStatusToCurrent$1(task) {
28732
28750
  return task.status;
28733
28751
  }
28734
28752
  function isReadablePersistedTask$1(obj) {
28735
- return isRecord$18(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
28753
+ return isRecord$19(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
28736
28754
  }
28737
28755
  function isLegacyPersistedTask$1(task) {
28738
28756
  return "task_id" in task;
28739
28757
  }
28740
- function isRecord$18(value) {
28758
+ function isRecord$19(value) {
28741
28759
  return typeof value === "object" && value !== null;
28742
28760
  }
28743
- function optionalNonEmptyString$1(value) {
28761
+ function optionalNonEmptyString$2(value) {
28744
28762
  if (value === void 0) return void 0;
28745
28763
  const trimmed = value.trim();
28746
28764
  return trimmed.length > 0 ? trimmed : void 0;
@@ -28914,7 +28932,7 @@ var init_agent_task = __esmMin((() => {
28914
28932
  }
28915
28933
  await sink.settle({
28916
28934
  status: "failed",
28917
- stopReason: errorMessage$8(error)
28935
+ stopReason: errorMessage$12(error)
28918
28936
  });
28919
28937
  } finally {
28920
28938
  sink.signal.removeEventListener("abort", requestAbort);
@@ -29040,7 +29058,7 @@ var init_process_task = __esmMin((() => {
29040
29058
  this.exitCode = this.proc.exitCode;
29041
29059
  settlement = {
29042
29060
  status: sink.signal.aborted ? "killed" : "failed",
29043
- stopReason: sink.signal.aborted ? void 0 : errorMessage$8(error)
29061
+ stopReason: sink.signal.aborted ? void 0 : errorMessage$12(error)
29044
29062
  };
29045
29063
  } finally {
29046
29064
  sink.signal.removeEventListener("abort", requestStop);
@@ -29114,7 +29132,7 @@ var init_question_task = __esmMin((() => {
29114
29132
  }
29115
29133
  await sink.settle({
29116
29134
  status: "failed",
29117
- stopReason: errorMessage$8(error)
29135
+ stopReason: errorMessage$12(error)
29118
29136
  });
29119
29137
  }
29120
29138
  }
@@ -29676,7 +29694,7 @@ var init_background = __esmMin((() => {
29676
29694
  })).catch((error) => {
29677
29695
  settleWorker({
29678
29696
  status: entry.abortController.signal.aborted ? "killed" : "failed",
29679
- stopReason: entry.abortController.signal.aborted ? void 0 : errorMessage$8(error)
29697
+ stopReason: entry.abortController.signal.aborted ? void 0 : errorMessage$12(error)
29680
29698
  });
29681
29699
  });
29682
29700
  const timeout = resettableTimeoutOutcome(entry.options.timeoutMs, { kind: "timeout" });
@@ -73836,10 +73854,10 @@ function escapeXml(value) {
73836
73854
  function locationKey(messageIndex, partIndex) {
73837
73855
  return `${String(messageIndex)}:${String(partIndex)}`;
73838
73856
  }
73839
- function isRecord$17(value) {
73857
+ function isRecord$18(value) {
73840
73858
  return value !== null && typeof value === "object" && !Array.isArray(value);
73841
73859
  }
73842
- function isNonNegativeInteger(value) {
73860
+ function isNonNegativeInteger$1(value) {
73843
73861
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
73844
73862
  }
73845
73863
  function abortReason(signal) {
@@ -74035,7 +74053,7 @@ var init_vision_reader = __esmMin((() => {
74035
74053
  reason: "malformed"
74036
74054
  };
74037
74055
  }
74038
- if (!isRecord$17(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger(payload["prompt_eval_count"]) || !isNonNegativeInteger(payload["eval_count"])) return {
74056
+ if (!isRecord$18(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger$1(payload["prompt_eval_count"]) || !isNonNegativeInteger$1(payload["eval_count"])) return {
74039
74057
  ok: false,
74040
74058
  reason: "malformed"
74041
74059
  };
@@ -229699,7 +229717,7 @@ async function runHook(command, input, options) {
229699
229717
  } : void 0
229700
229718
  });
229701
229719
  } catch (error) {
229702
- return allowResult({ stderr: errorMessage$7(error) });
229720
+ return allowResult({ stderr: errorMessage$11(error) });
229703
229721
  }
229704
229722
  return new Promise((resolve) => {
229705
229723
  let stdout = "";
@@ -229747,7 +229765,7 @@ async function runHook(command, input, options) {
229747
229765
  child.on("error", (error) => {
229748
229766
  settle(allowResult({
229749
229767
  stdout,
229750
- stderr: stderr + errorMessage$7(error)
229768
+ stderr: stderr + errorMessage$11(error)
229751
229769
  }));
229752
229770
  });
229753
229771
  child.on("close", (code) => {
@@ -229867,10 +229885,10 @@ function killProcessTreeWindows(child, force) {
229867
229885
  } catch {}
229868
229886
  }
229869
229887
  }
229870
- function isRecord$16(value) {
229888
+ function isRecord$17(value) {
229871
229889
  return typeof value === "object" && value !== null && !Array.isArray(value);
229872
229890
  }
229873
- function errorMessage$7(error) {
229891
+ function errorMessage$11(error) {
229874
229892
  return error instanceof Error ? error.message : String(error);
229875
229893
  }
229876
229894
  var DEFAULT_TIMEOUT_SECONDS, KILL_GRACE_MS$2, OptionalStringSchema, HookSpecificOutputSchema, HookJsonOutputSchema;
@@ -229883,7 +229901,7 @@ var init_runner = __esmMin((() => {
229883
229901
  if (typeof value === "string") return value;
229884
229902
  if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
229885
229903
  }, string().optional());
229886
- HookSpecificOutputSchema = preprocess((value) => isRecord$16(value) ? value : void 0, looseObject({
229904
+ HookSpecificOutputSchema = preprocess((value) => isRecord$17(value) ? value : void 0, looseObject({
229887
229905
  message: OptionalStringSchema,
229888
229906
  permissionDecision: unknown().optional(),
229889
229907
  permissionDecisionReason: OptionalStringSchema
@@ -230793,7 +230811,7 @@ function parsePersonalMemoryRecall(output) {
230793
230811
  } catch {
230794
230812
  return { kind: "invalid" };
230795
230813
  }
230796
- if (!isRecord$15(parsed) || !isRecord$15(parsed["personal_memory"])) return { kind: "invalid" };
230814
+ if (!isRecord$16(parsed) || !isRecord$16(parsed["personal_memory"])) return { kind: "invalid" };
230797
230815
  const memory = parsed["personal_memory"];
230798
230816
  const savedRaw = memory["saved"];
230799
230817
  const threadsRaw = memory["threads"];
@@ -230802,7 +230820,7 @@ function parsePersonalMemoryRecall(output) {
230802
230820
  if (savedRaw.length > MAX_SAVED_MEMORIES || threadsRaw.length > MAX_THREADS || historyRaw.length > 0) return { kind: "invalid" };
230803
230821
  const saved = [];
230804
230822
  for (const value of savedRaw) {
230805
- if (!isRecord$15(value)) return { kind: "invalid" };
230823
+ if (!isRecord$16(value)) return { kind: "invalid" };
230806
230824
  const text = boundedTrimmedString(value["text"], MAX_MEMORY_TEXT_CHARS);
230807
230825
  const confidence = value["confidence"];
230808
230826
  if (text === void 0 || typeof confidence !== "string" || !CONFIDENCE_VALUES.has(confidence)) return { kind: "invalid" };
@@ -230813,7 +230831,7 @@ function parsePersonalMemoryRecall(output) {
230813
230831
  }
230814
230832
  const threads = [];
230815
230833
  for (const value of threadsRaw) {
230816
- if (!isRecord$15(value)) return { kind: "invalid" };
230834
+ if (!isRecord$16(value)) return { kind: "invalid" };
230817
230835
  const title = boundedTrimmedString(value["title"], MAX_THREAD_TITLE_CHARS);
230818
230836
  const summary = boundedTrimmedString(value["summary"], MAX_THREAD_SUMMARY_CHARS);
230819
230837
  if (title === void 0 || summary === void 0) return { kind: "invalid" };
@@ -230867,7 +230885,7 @@ function boundedTrimmedString(value, maxChars) {
230867
230885
  const trimmed = value.trim();
230868
230886
  return trimmed.length > 0 ? trimmed : void 0;
230869
230887
  }
230870
- function isRecord$15(value) {
230888
+ function isRecord$16(value) {
230871
230889
  return typeof value === "object" && value !== null && !Array.isArray(value);
230872
230890
  }
230873
230891
  var PERSONAL_MEMORY_HOST_RECALL_HANDLER$1, RECALL_LIMIT, RECALL_TIMEOUT_MS, MAX_QUERY_CHARS, MAX_WIRE_CHARS, MAX_SAVED_MEMORIES, MAX_THREADS, MAX_MEMORY_TEXT_CHARS, MAX_THREAD_TITLE_CHARS, MAX_THREAD_SUMMARY_CHARS, CONFIDENCE_VALUES, TELEGRAM_GROUP_MARKER_RE, TELEGRAM_MARKER_RE, TELEGRAM_CHANNEL_RE, TELEGRAM_SOURCE_RE, TELEGRAM_CHAT_ID_RE, TELEGRAM_SENDER_LINE_RE, TELEGRAM_ATTACHMENT_BLOCK_RE, TELEGRAM_ATTACHMENT_NOTICE_RE, TELEGRAM_IMAGE_ATTACHMENT_RE, GENERIC_IMAGE_QUERY, GENERIC_FILE_QUERY, GENERIC_EMPTY_QUERY, PERSONAL_MEMORY_RECALL_VARIANT, PersonalMemoryRecallInjector;
@@ -231657,7 +231675,7 @@ function createEvidenceApi(dependencies) {
231657
231675
  var init_mission_contract_evidence = __esmMin((() => {}));
231658
231676
  //#endregion
231659
231677
  //#region ../../packages/agent-core/src/agent/injection/mission-contract.js
231660
- var missionContractApi, SCHEMA_VERSION, CONTRACT_STATUSES, REQUIREMENT_TYPES, normalize$2, createDraft, validate$1, publicContract, contractPrompt, redact, createEvidenceState, recordToolStart, recordToolResult, recordFile, recordUrl, recordScreenshot, recordSecurity, recordDecision, recordCheckpoint, evaluateCriteria, canonicalString$1, sha256$3, finalizeEvidence;
231678
+ var missionContractApi, SCHEMA_VERSION, CONTRACT_STATUSES, REQUIREMENT_TYPES, normalize$2, createDraft, validate$1, publicContract, contractPrompt, redact, createEvidenceState, recordToolStart, recordToolResult, recordFile, recordUrl, recordScreenshot, recordSecurity, recordDecision, recordCheckpoint, evaluateCriteria, canonicalString$1, sha256$4, finalizeEvidence;
231661
231679
  var init_mission_contract = __esmMin((() => {
231662
231680
  init_mission_contract_evidence();
231663
231681
  missionContractApi = (function(root, factory) {
@@ -231935,7 +231953,7 @@ var init_mission_contract = __esmMin((() => {
231935
231953
  })
231936
231954
  };
231937
231955
  });
231938
- ({SCHEMA_VERSION, CONTRACT_STATUSES, REQUIREMENT_TYPES, normalize: normalize$2, createDraft, validate: validate$1, publicContract, contractPrompt, redact, createEvidenceState, recordToolStart, recordToolResult, recordFile, recordUrl, recordScreenshot, recordSecurity, recordDecision, recordCheckpoint, evaluateCriteria, canonicalString: canonicalString$1, sha256: sha256$3, finalizeEvidence} = missionContractApi);
231956
+ ({SCHEMA_VERSION, CONTRACT_STATUSES, REQUIREMENT_TYPES, normalize: normalize$2, createDraft, validate: validate$1, publicContract, contractPrompt, redact, createEvidenceState, recordToolStart, recordToolResult, recordFile, recordUrl, recordScreenshot, recordSecurity, recordDecision, recordCheckpoint, evaluateCriteria, canonicalString: canonicalString$1, sha256: sha256$4, finalizeEvidence} = missionContractApi);
231939
231957
  }));
231940
231958
  //#endregion
231941
231959
  //#region ../../packages/agent-core/src/agent/injection/mission-contract-bridge.ts
@@ -242727,7 +242745,7 @@ function parseToolCallArguments$1(raw) {
242727
242745
  success: true,
242728
242746
  data: {},
242729
242747
  parseFailed: true,
242730
- error: errorMessage$8(error)
242748
+ error: errorMessage$12(error)
242731
242749
  };
242732
242750
  }
242733
242751
  }
@@ -242914,7 +242932,7 @@ async function prepareToolCall(step, call) {
242914
242932
  toolCallId: call.toolCall.id,
242915
242933
  error
242916
242934
  });
242917
- return settleError(effectiveArgs, error instanceof PathSecurityError ? error.message : `Tool "${call.toolName}" failed to resolve execution: ${errorMessage$8(error)}`);
242935
+ return settleError(effectiveArgs, error instanceof PathSecurityError ? error.message : `Tool "${call.toolName}" failed to resolve execution: ${errorMessage$12(error)}`);
242918
242936
  }
242919
242937
  const displayFields = toolCallDisplayFieldsFromExecution(execution);
242920
242938
  const settleAborted = () => settleError(effectiveArgs, abortedToolOutput(call.toolName, step.signal), displayFields);
@@ -242977,7 +242995,7 @@ async function runPrepareToolExecutionHook(step, call) {
242977
242995
  return {
242978
242996
  kind: "hookFailed",
242979
242997
  args,
242980
- output: `prepareToolExecution hook failed for "${call.toolName}": ${errorMessage$8(error)}`
242998
+ output: `prepareToolExecution hook failed for "${call.toolName}": ${errorMessage$12(error)}`
242981
242999
  };
242982
243000
  }
242983
243001
  const effectiveArgs = hookResult?.updatedArgs ?? args;
@@ -243019,7 +243037,7 @@ async function runAuthorizeToolExecutionHook(step, call, args, execution) {
243019
243037
  };
243020
243038
  return {
243021
243039
  block: true,
243022
- reason: `authorizeToolExecution hook failed for "${call.toolName}": ${errorMessage$8(error)}`
243040
+ reason: `authorizeToolExecution hook failed for "${call.toolName}": ${errorMessage$12(error)}`
243023
243041
  };
243024
243042
  }
243025
243043
  }
@@ -243046,7 +243064,7 @@ async function runRunnableToolCall(step, call, effectiveArgs, metadata, executio
243046
243064
  toolCallId: toolCall.id,
243047
243065
  error
243048
243066
  });
243049
- return makeErrorToolResult(call, effectiveArgs, aborted ? abortedToolOutput(toolName, signal) : `Tool "${toolName}" failed: ${errorMessage$8(error)}`);
243067
+ return makeErrorToolResult(call, effectiveArgs, aborted ? abortedToolOutput(toolName, signal) : `Tool "${toolName}" failed: ${errorMessage$12(error)}`);
243050
243068
  }
243051
243069
  return makeToolResult(call, effectiveArgs, toolResult);
243052
243070
  }
@@ -243079,7 +243097,7 @@ async function finalizePendingToolResult(step, pendingResult) {
243079
243097
  toolCallId: pendingResult.toolCall.id,
243080
243098
  error
243081
243099
  });
243082
- const output = aborted ? `Tool "${pendingResult.toolName}" aborted during finalizeToolResult hook.` : `finalizeToolResult hook failed for "${pendingResult.toolName}": ${errorMessage$8(error)}`;
243100
+ const output = aborted ? `Tool "${pendingResult.toolName}" aborted during finalizeToolResult hook.` : `finalizeToolResult hook failed for "${pendingResult.toolName}": ${errorMessage$12(error)}`;
243083
243101
  return {
243084
243102
  ...pendingResult,
243085
243103
  stopTurn: pendingResult.stopTurn,
@@ -243338,8 +243356,8 @@ async function executeLoopStep(deps) {
243338
243356
  log?.error("strict resend still rejected by provider; request remains wire-invalid", {
243339
243357
  turnStep: `${turnId}.${String(currentStep)}`,
243340
243358
  model: llm.modelName,
243341
- originalError: errorMessage$8(error),
243342
- strictError: errorMessage$8(strictError)
243359
+ originalError: errorMessage$12(error),
243360
+ strictError: errorMessage$12(strictError)
243343
243361
  });
243344
243362
  throw strictError;
243345
243363
  }
@@ -243591,7 +243609,7 @@ async function runTurn(input) {
243591
243609
  usage
243592
243610
  };
243593
243611
  }
243594
- dispatchEvent(makeInterruptedEvent(isMaxStepsExceededError(error) ? "max_steps" : "error", steps, activeStep, errorMessage$8(error)));
243612
+ dispatchEvent(makeInterruptedEvent(isMaxStepsExceededError(error) ? "max_steps" : "error", steps, activeStep, errorMessage$12(error)));
243595
243613
  throw error;
243596
243614
  }
243597
243615
  return {
@@ -247004,7 +247022,7 @@ var init_classic = __esmMin((() => {
247004
247022
  //#region ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/index.js
247005
247023
  var init_v4 = __esmMin((() => {
247006
247024
  init_classic();
247007
- })), LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, RELATED_TASK_META_KEY, AssertObjectSchema, ProgressTokenSchema, CursorSchema, TaskMetadataSchema, RelatedTaskMetadataSchema, RequestMetaSchema, BaseRequestParamsSchema, TaskAugmentedRequestParamsSchema, isTaskAugmentedRequestParams, RequestSchema, NotificationsParamsSchema, NotificationSchema, ResultSchema, RequestIdSchema, JSONRPCRequestSchema, isJSONRPCRequest, JSONRPCNotificationSchema, isJSONRPCNotification, JSONRPCResultResponseSchema, isJSONRPCResultResponse, ErrorCode, JSONRPCErrorResponseSchema, isJSONRPCErrorResponse, JSONRPCMessageSchema, EmptyResultSchema, CancelledNotificationParamsSchema, CancelledNotificationSchema, IconSchema, IconsSchema, BaseMetadataSchema, ImplementationSchema, FormElicitationCapabilitySchema, ElicitationCapabilitySchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema, ClientCapabilitiesSchema, InitializeRequestParamsSchema, InitializeRequestSchema, ServerCapabilitiesSchema, InitializeResultSchema, InitializedNotificationSchema, isInitializedNotification, PingRequestSchema, ProgressSchema, ProgressNotificationParamsSchema, ProgressNotificationSchema, PaginatedRequestParamsSchema, PaginatedRequestSchema, PaginatedResultSchema, TaskStatusSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ResourceContentsSchema, TextResourceContentsSchema, Base64Schema, BlobResourceContentsSchema, RoleSchema, AnnotationsSchema, ResourceSchema, ResourceTemplateSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListResourceTemplatesRequestSchema, ListResourceTemplatesResultSchema, ResourceRequestParamsSchema, ReadResourceRequestParamsSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SubscribeRequestParamsSchema, SubscribeRequestSchema, UnsubscribeRequestParamsSchema, UnsubscribeRequestSchema, ResourceUpdatedNotificationParamsSchema, ResourceUpdatedNotificationSchema, PromptArgumentSchema, PromptSchema, ListPromptsRequestSchema, ListPromptsResultSchema, GetPromptRequestParamsSchema, GetPromptRequestSchema, TextContentSchema, ImageContentSchema, AudioContentSchema, ToolUseContentSchema, EmbeddedResourceSchema, ResourceLinkSchema, ContentBlockSchema, PromptMessageSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ToolAnnotationsSchema, ToolExecutionSchema, ToolSchema, ListToolsRequestSchema, ListToolsResultSchema, CallToolResultSchema, CallToolRequestParamsSchema, CallToolRequestSchema, ToolListChangedNotificationSchema, ListChangedOptionsBaseSchema, LoggingLevelSchema, SetLevelRequestParamsSchema, SetLevelRequestSchema, LoggingMessageNotificationParamsSchema, LoggingMessageNotificationSchema, ModelHintSchema, ModelPreferencesSchema, ToolChoiceSchema, ToolResultContentSchema, SamplingContentSchema, SamplingMessageContentBlockSchema, SamplingMessageSchema, CreateMessageRequestParamsSchema, CreateMessageRequestSchema, CreateMessageResultSchema, CreateMessageResultWithToolsSchema, BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema, LegacyTitledEnumSchemaSchema, SingleSelectEnumSchemaSchema, UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema, MultiSelectEnumSchemaSchema, EnumSchemaSchema, PrimitiveSchemaDefinitionSchema, ElicitRequestFormParamsSchema, ElicitRequestURLParamsSchema, ElicitRequestParamsSchema, ElicitRequestSchema, ElicitationCompleteNotificationParamsSchema, ElicitationCompleteNotificationSchema, ElicitResultSchema, ResourceTemplateReferenceSchema, PromptReferenceSchema, CompleteRequestParamsSchema, CompleteRequestSchema, CompleteResultSchema, RootSchema, ListRootsRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, McpError, UrlElicitationRequiredError;
247025
+ })), LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, RELATED_TASK_META_KEY, AssertObjectSchema, ProgressTokenSchema, CursorSchema, TaskMetadataSchema, RelatedTaskMetadataSchema, RequestMetaSchema, BaseRequestParamsSchema, TaskAugmentedRequestParamsSchema, isTaskAugmentedRequestParams, RequestSchema, NotificationsParamsSchema, NotificationSchema, ResultSchema, RequestIdSchema, JSONRPCRequestSchema, isJSONRPCRequest, JSONRPCNotificationSchema, isJSONRPCNotification, JSONRPCResultResponseSchema, isJSONRPCResultResponse, ErrorCode, JSONRPCErrorResponseSchema, isJSONRPCErrorResponse, JSONRPCMessageSchema, EmptyResultSchema, CancelledNotificationParamsSchema, CancelledNotificationSchema, IconSchema, IconsSchema, BaseMetadataSchema, ImplementationSchema, FormElicitationCapabilitySchema, ElicitationCapabilitySchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema, ClientCapabilitiesSchema, InitializeRequestParamsSchema, InitializeRequestSchema, ServerCapabilitiesSchema, InitializeResultSchema, InitializedNotificationSchema, isInitializedNotification, PingRequestSchema, ProgressSchema, ProgressNotificationParamsSchema, ProgressNotificationSchema, PaginatedRequestParamsSchema, PaginatedRequestSchema, PaginatedResultSchema, TaskStatusSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ResourceContentsSchema, TextResourceContentsSchema, Base64Schema, BlobResourceContentsSchema, RoleSchema, AnnotationsSchema, ResourceSchema, ResourceTemplateSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListResourceTemplatesRequestSchema, ListResourceTemplatesResultSchema, ResourceRequestParamsSchema, ReadResourceRequestParamsSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SubscribeRequestParamsSchema, SubscribeRequestSchema, UnsubscribeRequestParamsSchema, UnsubscribeRequestSchema, ResourceUpdatedNotificationParamsSchema, ResourceUpdatedNotificationSchema, PromptArgumentSchema, PromptSchema$1, ListPromptsRequestSchema, ListPromptsResultSchema, GetPromptRequestParamsSchema, GetPromptRequestSchema, TextContentSchema, ImageContentSchema, AudioContentSchema, ToolUseContentSchema, EmbeddedResourceSchema, ResourceLinkSchema, ContentBlockSchema, PromptMessageSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ToolAnnotationsSchema, ToolExecutionSchema, ToolSchema, ListToolsRequestSchema, ListToolsResultSchema, CallToolResultSchema, CallToolRequestParamsSchema, CallToolRequestSchema, ToolListChangedNotificationSchema, ListChangedOptionsBaseSchema, LoggingLevelSchema, SetLevelRequestParamsSchema, SetLevelRequestSchema, LoggingMessageNotificationParamsSchema, LoggingMessageNotificationSchema, ModelHintSchema, ModelPreferencesSchema, ToolChoiceSchema, ToolResultContentSchema, SamplingContentSchema, SamplingMessageContentBlockSchema, SamplingMessageSchema, CreateMessageRequestParamsSchema, CreateMessageRequestSchema, CreateMessageResultSchema, CreateMessageResultWithToolsSchema, BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema, LegacyTitledEnumSchemaSchema, SingleSelectEnumSchemaSchema, UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema, MultiSelectEnumSchemaSchema, EnumSchemaSchema, PrimitiveSchemaDefinitionSchema, ElicitRequestFormParamsSchema, ElicitRequestURLParamsSchema, ElicitRequestParamsSchema, ElicitRequestSchema, ElicitationCompleteNotificationParamsSchema, ElicitationCompleteNotificationSchema, ElicitResultSchema, ResourceTemplateReferenceSchema, PromptReferenceSchema, CompleteRequestParamsSchema, CompleteRequestSchema, CompleteResultSchema, RootSchema, ListRootsRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, McpError, UrlElicitationRequiredError;
247008
247026
  var init_types$4 = __esmMin((() => {
247009
247027
  init_v4();
247010
247028
  LATEST_PROTOCOL_VERSION = "2025-11-25";
@@ -247646,7 +247664,7 @@ uri: string() });
247646
247664
  */
247647
247665
  required: optional(boolean$1())
247648
247666
  });
247649
- PromptSchema = object({
247667
+ PromptSchema$1 = object({
247650
247668
  ...BaseMetadataSchema.shape,
247651
247669
  ...IconsSchema.shape,
247652
247670
  /**
@@ -247664,7 +247682,7 @@ uri: string() });
247664
247682
  _meta: optional(looseObject({}))
247665
247683
  });
247666
247684
  ListPromptsRequestSchema = PaginatedRequestSchema.extend({ method: literal("prompts/list") });
247667
- ListPromptsResultSchema = PaginatedResultSchema.extend({ prompts: array(PromptSchema) });
247685
+ ListPromptsResultSchema = PaginatedResultSchema.extend({ prompts: array(PromptSchema$1) });
247668
247686
  GetPromptRequestParamsSchema = BaseRequestParamsSchema.extend({
247669
247687
  /**
247670
247688
  * The name of the prompt or prompt template.
@@ -251881,7 +251899,7 @@ var init_ask_user = __esmMin((() => {
251881
251899
  } catch (error) {
251882
251900
  return {
251883
251901
  isError: true,
251884
- output: errorMessage$8(error)
251902
+ output: errorMessage$12(error)
251885
251903
  };
251886
251904
  }
251887
251905
  const status = backgroundManager.getTask(taskId)?.status ?? "running";
@@ -261057,6 +261075,163 @@ var init_mistake_record = __esmMin((() => {
261057
261075
  };
261058
261076
  }));
261059
261077
  //#endregion
261078
+ //#region ../../packages/agent-core/src/tools/builtin/media/blun-media.ts
261079
+ function contentPartFor(mimeType, url) {
261080
+ if (mimeType.startsWith("image/")) return {
261081
+ type: "image_url",
261082
+ imageUrl: { url }
261083
+ };
261084
+ if (mimeType.startsWith("audio/")) return {
261085
+ type: "audio_url",
261086
+ audioUrl: { url }
261087
+ };
261088
+ if (mimeType.startsWith("video/")) return {
261089
+ type: "video_url",
261090
+ videoUrl: { url }
261091
+ };
261092
+ }
261093
+ function errorMessage$10(error) {
261094
+ return error instanceof Error ? error.message : String(error);
261095
+ }
261096
+ var PromptSchema, MediaIdSchema, GenerateImageInputSchema, GenerateVideoInputSchema, GenerateSpeechInputSchema, GetMediaInputSchema, REQUEST_NOTE, MediaGenerationTool, GenerateImageTool, GenerateVideoTool, GenerateSpeechTool, GetMediaTool;
261097
+ var init_blun_media$1 = __esmMin((() => {
261098
+ init_zod$1();
261099
+ init_tool_access();
261100
+ init_input_schema();
261101
+ init_rule_match();
261102
+ PromptSchema = string().trim().min(1).max(2e4);
261103
+ MediaIdSchema = string().trim().min(1).max(200).regex(/^[A-Za-z0-9_-]+$/);
261104
+ GenerateImageInputSchema = object({ prompt: PromptSchema.describe("A complete visual description of the image to generate.") });
261105
+ GenerateVideoInputSchema = object({ prompt: PromptSchema.describe("A complete visual description of the video to generate.") });
261106
+ GenerateSpeechInputSchema = object({ input: PromptSchema.describe("The exact text to synthesize as speech.") });
261107
+ GetMediaInputSchema = object({ id: MediaIdSchema.describe("The media job id returned by a generation tool.") });
261108
+ REQUEST_NOTE = "The request is asynchronous. Use GetMedia with the returned id to check progress and retrieve the result.";
261109
+ MediaGenerationTool = class {
261110
+ provider;
261111
+ constructor(provider) {
261112
+ this.provider = provider;
261113
+ }
261114
+ resolveExecution(args) {
261115
+ const subject = this.subject(args);
261116
+ const preview = subject.length > 60 ? `${subject.slice(0, 60)}...` : subject;
261117
+ return {
261118
+ accesses: ToolAccesses.all(),
261119
+ description: `${this.name}: ${preview}`,
261120
+ approvalRule: literalRulePattern(this.name, subject),
261121
+ matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, subject),
261122
+ execute: (ctx) => this.execution(args, ctx)
261123
+ };
261124
+ }
261125
+ async execution(args, ctx) {
261126
+ try {
261127
+ const job = await this.submit(args, {
261128
+ signal: ctx.signal,
261129
+ toolCallId: ctx.toolCallId
261130
+ });
261131
+ return {
261132
+ output: `Media job ${job.id} accepted with status ${job.status}. ${REQUEST_NOTE}`,
261133
+ isError: false
261134
+ };
261135
+ } catch (error) {
261136
+ return {
261137
+ isError: true,
261138
+ output: `Media request failed: ${errorMessage$10(error)}`
261139
+ };
261140
+ }
261141
+ }
261142
+ };
261143
+ GenerateImageTool = class extends MediaGenerationTool {
261144
+ name = "GenerateImage";
261145
+ description = "Generate a new image from text with BLUN IMAGINE. Use this when the user asks to create an image, illustration, logo, or visual. This starts a billed asynchronous media job.";
261146
+ parameters = toInputJsonSchema(GenerateImageInputSchema);
261147
+ subject(args) {
261148
+ return args.prompt;
261149
+ }
261150
+ submit(args, options) {
261151
+ return this.provider.generateImage(args.prompt, options);
261152
+ }
261153
+ };
261154
+ GenerateVideoTool = class extends MediaGenerationTool {
261155
+ name = "GenerateVideo";
261156
+ description = "Generate a new video from text with BLUN media models. Use this for motion or text-to-video requests, not for understanding an existing video. This starts a billed asynchronous media job.";
261157
+ parameters = toInputJsonSchema(GenerateVideoInputSchema);
261158
+ subject(args) {
261159
+ return args.prompt;
261160
+ }
261161
+ submit(args, options) {
261162
+ return this.provider.generateVideo(args.prompt, options);
261163
+ }
261164
+ };
261165
+ GenerateSpeechTool = class extends MediaGenerationTool {
261166
+ name = "GenerateSpeech";
261167
+ description = "Synthesize spoken audio from exact text with BLUN VOICE. Use this for voice or speech generation. This starts a billed asynchronous media job.";
261168
+ parameters = toInputJsonSchema(GenerateSpeechInputSchema);
261169
+ subject(args) {
261170
+ return args.input;
261171
+ }
261172
+ submit(args, options) {
261173
+ return this.provider.generateSpeech(args.input, options);
261174
+ }
261175
+ };
261176
+ GetMediaTool = class {
261177
+ provider;
261178
+ name = "GetMedia";
261179
+ description = "Check a BLUN media job. If it is complete, return the generated image, audio, or video. Use only ids returned by GenerateImage, GenerateVideo, or GenerateSpeech.";
261180
+ parameters = toInputJsonSchema(GetMediaInputSchema);
261181
+ constructor(provider) {
261182
+ this.provider = provider;
261183
+ }
261184
+ resolveExecution(args) {
261185
+ return {
261186
+ accesses: ToolAccesses.all(),
261187
+ description: `GetMedia: ${args.id}`,
261188
+ approvalRule: literalRulePattern(this.name, args.id),
261189
+ matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.id),
261190
+ execute: (ctx) => this.execution(args, ctx)
261191
+ };
261192
+ }
261193
+ async execution(args, ctx) {
261194
+ try {
261195
+ const result = await this.provider.getMedia(args.id, {
261196
+ signal: ctx.signal,
261197
+ toolCallId: ctx.toolCallId
261198
+ });
261199
+ if (result.kind === "status") {
261200
+ const terminalError = [
261201
+ "failed",
261202
+ "expired",
261203
+ "blocked"
261204
+ ].includes(result.status.trim().toLowerCase());
261205
+ const source = result.sourceId === void 0 ? "" : ` Source job ${result.sourceId}${result.sourceStatus === void 0 ? "" : ` status: ${result.sourceStatus}`}.`;
261206
+ const retryable = result.retryable === void 0 ? "" : ` Retryable: ${result.retryable ? "yes" : "no"}.`;
261207
+ return {
261208
+ output: `Media job ${result.id} status: ${result.status}.${source}${retryable}`,
261209
+ isError: terminalError
261210
+ };
261211
+ }
261212
+ const url = `data:${result.mimeType};base64,${Buffer.from(result.data).toString("base64")}`;
261213
+ const mediaPart = contentPartFor(result.mimeType, url);
261214
+ if (mediaPart === void 0) return {
261215
+ isError: true,
261216
+ output: `Media job ${result.id} returned unsupported content type ${result.mimeType}.`
261217
+ };
261218
+ return {
261219
+ output: [{
261220
+ type: "text",
261221
+ text: `Media job ${result.id} is complete.`
261222
+ }, mediaPart],
261223
+ isError: false
261224
+ };
261225
+ } catch (error) {
261226
+ return {
261227
+ isError: true,
261228
+ output: `Media lookup failed: ${errorMessage$10(error)}`
261229
+ };
261230
+ }
261231
+ }
261232
+ };
261233
+ }));
261234
+ //#endregion
261060
261235
  //#region ../../packages/agent-core/src/tools/builtin/index.ts
261061
261236
  var init_builtin = __esmMin((() => {
261062
261237
  init_task_list();
@@ -261087,6 +261262,7 @@ var init_builtin = __esmMin((() => {
261087
261262
  init_web_search();
261088
261263
  init_codebase_search();
261089
261264
  init_mistake_record();
261265
+ init_blun_media$1();
261090
261266
  }));
261091
261267
  //#endregion
261092
261268
  //#region ../../packages/agent-core/src/agent/tool/types.ts
@@ -261511,6 +261687,10 @@ var init_tool$1 = __esmMin((() => {
261511
261687
  this.agent.subagentHost && new AgentSwarmTool(this.agent.subagentHost, this.agent.swarmMode),
261512
261688
  toolServices?.webSearcher && new WebSearchTool(toolServices.webSearcher),
261513
261689
  toolServices?.urlFetcher && new FetchURLTool(toolServices.urlFetcher),
261690
+ toolServices?.media && new GenerateImageTool(toolServices.media),
261691
+ toolServices?.media && new GenerateVideoTool(toolServices.media),
261692
+ toolServices?.media && new GenerateSpeechTool(toolServices.media),
261693
+ toolServices?.media && new GetMediaTool(toolServices.media),
261514
261694
  new MistakeRecordTool(this.agent),
261515
261695
  new CodebaseSearchTool(cwd)
261516
261696
  ].filter((tool) => !!tool).map((tool) => [tool.name, tool]));
@@ -294283,7 +294463,7 @@ async function parseManifest(pluginRoot) {
294283
294463
  }]
294284
294464
  };
294285
294465
  }
294286
- if (!isObject$3(raw)) return {
294466
+ if (!isObject$4(raw)) return {
294287
294467
  manifestKind,
294288
294468
  manifestPath,
294289
294469
  shadowedManifestPath,
@@ -294430,7 +294610,7 @@ async function resolvePluginPathField(input) {
294430
294610
  }
294431
294611
  function readSessionStart(raw, diagnostics) {
294432
294612
  if (raw === void 0) return void 0;
294433
- if (!isObject$3(raw)) {
294613
+ if (!isObject$4(raw)) {
294434
294614
  diagnostics.push({
294435
294615
  severity: "warn",
294436
294616
  message: "\"sessionStart\" must be an object"
@@ -294449,7 +294629,7 @@ function readSessionStart(raw, diagnostics) {
294449
294629
  }
294450
294630
  async function readMcpServers(pluginRoot, raw, diagnostics) {
294451
294631
  if (raw === void 0) return void 0;
294452
- if (!isObject$3(raw)) {
294632
+ if (!isObject$4(raw)) {
294453
294633
  diagnostics.push({
294454
294634
  severity: "warn",
294455
294635
  message: "\"mcpServers\" must be an object"
@@ -294600,7 +294780,7 @@ async function normalizePluginMcpServer(input) {
294600
294780
  }
294601
294781
  function readAuthor(raw) {
294602
294782
  if (typeof raw === "string") return { name: raw };
294603
- if (!isObject$3(raw)) return void 0;
294783
+ if (!isObject$4(raw)) return void 0;
294604
294784
  const name = stringField$3(raw, "name");
294605
294785
  const email = stringField$3(raw, "email");
294606
294786
  if (name === void 0 && email === void 0) return void 0;
@@ -294610,7 +294790,7 @@ function readAuthor(raw) {
294610
294790
  };
294611
294791
  }
294612
294792
  function readInterface(raw) {
294613
- if (!isObject$3(raw)) return void 0;
294793
+ if (!isObject$4(raw)) return void 0;
294614
294794
  const out = {
294615
294795
  displayName: stringField$3(raw, "displayName"),
294616
294796
  shortDescription: stringField$3(raw, "shortDescription"),
@@ -294631,7 +294811,7 @@ function stringArrayField$1(raw, key) {
294631
294811
  if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) return;
294632
294812
  return value;
294633
294813
  }
294634
- function isObject$3(value) {
294814
+ function isObject$4(value) {
294635
294815
  return typeof value === "object" && value !== null && !Array.isArray(value);
294636
294816
  }
294637
294817
  function isWithin$1(child, parent) {
@@ -302337,7 +302517,7 @@ var init_sort = __esmMin((() => {
302337
302517
  }));
302338
302518
  //#endregion
302339
302519
  //#region ../../node_modules/.pnpm/css-select@5.2.2/node_modules/css-select/lib/esm/attributes.js
302340
- function escapeRegex$1(value) {
302520
+ function escapeRegex$2(value) {
302341
302521
  return value.replace(reChars, "\\$&");
302342
302522
  }
302343
302523
  function shouldIgnoreCase(selector, options) {
@@ -302430,7 +302610,7 @@ var init_attributes = __esmMin((() => {
302430
302610
  const { adapter } = options;
302431
302611
  const { name, value } = data;
302432
302612
  if (/\s/.test(value)) return import_boolbase$5.default.falseFunc;
302433
- const regex = new RegExp(`(?:^|\\s)${escapeRegex$1(value)}(?:$|\\s)`, shouldIgnoreCase(data, options) ? "i" : "");
302613
+ const regex = new RegExp(`(?:^|\\s)${escapeRegex$2(value)}(?:$|\\s)`, shouldIgnoreCase(data, options) ? "i" : "");
302434
302614
  return function element(elem) {
302435
302615
  const attr = adapter.getAttributeValue(elem, name);
302436
302616
  return attr != null && attr.length >= value.length && regex.test(attr) && next(elem);
@@ -302480,7 +302660,7 @@ var init_attributes = __esmMin((() => {
302480
302660
  const { name, value } = data;
302481
302661
  if (value === "") return import_boolbase$5.default.falseFunc;
302482
302662
  if (shouldIgnoreCase(data, options)) {
302483
- const regex = new RegExp(escapeRegex$1(value), "i");
302663
+ const regex = new RegExp(escapeRegex$2(value), "i");
302484
302664
  return function anyIC(elem) {
302485
302665
  const attr = adapter.getAttributeValue(elem, name);
302486
302666
  return attr != null && attr.length >= value.length && regex.test(attr) && next(elem);
@@ -308946,6 +309126,137 @@ var init_blun_web_search = __esmMin((() => {
308946
309126
  };
308947
309127
  }));
308948
309128
  //#endregion
309129
+ //#region ../../packages/agent-core/src/tools/providers/blun-media.ts
309130
+ async function parseBlockedStatus(response, id) {
309131
+ let payload = {};
309132
+ try {
309133
+ payload = await response.json();
309134
+ } catch {}
309135
+ const sourceId = payload["source_id"];
309136
+ const sourceStatus = payload["source_status"];
309137
+ const retryable = payload["retryable"];
309138
+ return {
309139
+ kind: "status",
309140
+ id,
309141
+ status: "blocked",
309142
+ ...typeof sourceId === "string" && sourceId.length > 0 ? { sourceId } : {},
309143
+ ...typeof sourceStatus === "string" && sourceStatus.length > 0 ? { sourceStatus } : {},
309144
+ ...typeof retryable === "boolean" ? { retryable } : {}
309145
+ };
309146
+ }
309147
+ function parseJob(payload) {
309148
+ const id = payload["id"];
309149
+ const status = payload["status"];
309150
+ if (typeof id !== "string" || id.length === 0 || typeof status !== "string" || status.length === 0) throw new Error("Media request returned an invalid job response.");
309151
+ return {
309152
+ id,
309153
+ status
309154
+ };
309155
+ }
309156
+ function parseStatus(payload, expectedId) {
309157
+ const id = typeof payload["id"] === "string" && payload["id"].length > 0 ? payload["id"] : expectedId;
309158
+ const status = payload["status"];
309159
+ if (typeof status !== "string" || status.length === 0) throw new Error("Media lookup returned an invalid status response.");
309160
+ return {
309161
+ kind: "status",
309162
+ id,
309163
+ status
309164
+ };
309165
+ }
309166
+ async function assertSuccess(response, operation) {
309167
+ if (response.ok) return;
309168
+ let detail = "";
309169
+ try {
309170
+ detail = (await response.text()).trim();
309171
+ } catch {}
309172
+ throw new Error(`${operation} failed: HTTP ${String(response.status)}${detail ? `: ${detail}` : ""}`);
309173
+ }
309174
+ var BlunMediaService;
309175
+ var init_blun_media = __esmMin((() => {
309176
+ BlunMediaService = class {
309177
+ tokenProvider;
309178
+ apiKey;
309179
+ baseUrl;
309180
+ defaultHeaders;
309181
+ customHeaders;
309182
+ fetchImpl;
309183
+ constructor(options) {
309184
+ this.tokenProvider = options.tokenProvider;
309185
+ this.apiKey = options.apiKey;
309186
+ this.baseUrl = options.baseUrl.replace(/\/+$/, "");
309187
+ this.defaultHeaders = options.defaultHeaders ?? {};
309188
+ this.customHeaders = options.customHeaders ?? {};
309189
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
309190
+ }
309191
+ generateImage(prompt, options) {
309192
+ return this.submit("/images/generations", { prompt }, options);
309193
+ }
309194
+ generateVideo(prompt, options) {
309195
+ return this.submit("/videos/generations", { prompt }, options);
309196
+ }
309197
+ generateSpeech(input, options) {
309198
+ return this.submit("/audio/speech", { input }, options);
309199
+ }
309200
+ async getMedia(id, options) {
309201
+ const response = await this.request(`/media/${encodeURIComponent(id)}`, { method: "GET" }, options);
309202
+ if (response.status === 409) return parseBlockedStatus(response, id);
309203
+ if (response.status === 410) return {
309204
+ kind: "status",
309205
+ id,
309206
+ status: "expired"
309207
+ };
309208
+ await assertSuccess(response, "Media lookup");
309209
+ const mimeType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
309210
+ if (mimeType === "application/json" || mimeType.endsWith("+json")) return parseStatus(await response.json(), id);
309211
+ if (!mimeType.startsWith("image/") && !mimeType.startsWith("audio/") && !mimeType.startsWith("video/")) throw new Error(`Media lookup returned unsupported content type ${mimeType || "(missing)"}`);
309212
+ return {
309213
+ kind: "file",
309214
+ id,
309215
+ mimeType,
309216
+ data: new Uint8Array(await response.arrayBuffer())
309217
+ };
309218
+ }
309219
+ async submit(path, body, options) {
309220
+ const response = await this.request(path, {
309221
+ method: "POST",
309222
+ body: JSON.stringify(body)
309223
+ }, options);
309224
+ await assertSuccess(response, "Media request");
309225
+ return parseJob(await response.json());
309226
+ }
309227
+ async request(path, init, options) {
309228
+ const firstToken = await this.resolveToken(false);
309229
+ const first = await this.fetchWithToken(path, init, options, firstToken);
309230
+ if (first.status !== 401 || this.tokenProvider === void 0) return first;
309231
+ const refreshed = await this.resolveToken(true);
309232
+ return this.fetchWithToken(path, init, options, refreshed);
309233
+ }
309234
+ fetchWithToken(path, init, options, token) {
309235
+ return this.fetchImpl(`${this.baseUrl}${path}`, {
309236
+ ...init,
309237
+ signal: options?.signal,
309238
+ headers: {
309239
+ ...this.defaultHeaders,
309240
+ Authorization: `Bearer ${token}`,
309241
+ ...init.body === void 0 ? {} : { "Content-Type": "application/json" },
309242
+ ...options?.toolCallId === void 0 ? {} : { "X-Msh-Tool-Call-Id": options.toolCallId },
309243
+ ...this.customHeaders
309244
+ }
309245
+ });
309246
+ }
309247
+ async resolveToken(force) {
309248
+ if (this.tokenProvider !== void 0) try {
309249
+ return force ? await this.tokenProvider.getAccessToken({ force: true }) : await this.tokenProvider.getAccessToken();
309250
+ } catch (error) {
309251
+ if (this.apiKey !== void 0 && this.apiKey.length > 0) return this.apiKey;
309252
+ throw error;
309253
+ }
309254
+ if (this.apiKey !== void 0 && this.apiKey.length > 0) return this.apiKey;
309255
+ throw new Error("BLUN media service is not configured: missing API key or OAuth token provider.");
309256
+ }
309257
+ };
309258
+ }));
309259
+ //#endregion
308949
309260
  //#region ../../packages/agent-core/src/session/export/manifest.ts
308950
309261
  function buildExportManifest(args) {
308951
309262
  return {
@@ -310046,12 +310357,12 @@ function assertBlunProviderType(provider) {
310046
310357
  if (provider.type !== "blun") throw new BlunError(ErrorCodes.MODEL_CONFIG_INVALID, "Only the BLUN provider type is supported.");
310047
310358
  }
310048
310359
  function providerValue(configured, env, envKey) {
310049
- return nonEmptyString$1(configured) ?? envValue(env, envKey);
310360
+ return nonEmptyString$2(configured) ?? envValue(env, envKey);
310050
310361
  }
310051
310362
  function envValue(env, key) {
310052
- return nonEmptyString$1(env?.[key]);
310363
+ return nonEmptyString$2(env?.[key]);
310053
310364
  }
310054
- function nonEmptyString$1(value) {
310365
+ function nonEmptyString$2(value) {
310055
310366
  const trimmed = value?.trim();
310056
310367
  return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
310057
310368
  }
@@ -310682,10 +310993,10 @@ async function appendForkedMarkers(state) {
310682
310993
  time: Date.now()
310683
310994
  };
310684
310995
  const agents = state["agents"];
310685
- if (!isRecord$14(agents)) return;
310996
+ if (!isRecord$15(agents)) return;
310686
310997
  const paths = /* @__PURE__ */ new Set();
310687
310998
  for (const agentMeta of Object.values(agents)) {
310688
- if (!isRecord$14(agentMeta)) continue;
310999
+ if (!isRecord$15(agentMeta)) continue;
310689
311000
  const homedir = agentMeta["homedir"];
310690
311001
  if (typeof homedir !== "string") continue;
310691
311002
  paths.add(join$4(homedir, "wire.jsonl"));
@@ -310697,7 +311008,7 @@ async function appendForkedMarkers(state) {
310697
311008
  }));
310698
311009
  }
310699
311010
  function customMetadataForFork(value) {
310700
- if (!isRecord$14(value)) return {};
311011
+ if (!isRecord$15(value)) return {};
310701
311012
  const custom = {};
310702
311013
  for (const [key, entry] of Object.entries(value)) {
310703
311014
  if (key === "goal" || key === "managedQuotaWarningThreshold") continue;
@@ -310752,10 +311063,10 @@ function normalizeForkTitle(title, fallback) {
310752
311063
  return typeof fallback === "string" && fallback.trim().length > 0 ? fallback : "New Session";
310753
311064
  }
310754
311065
  function rewriteAgentHomedirs(value, sourceDir, targetDir) {
310755
- if (!isRecord$14(value)) return {};
311066
+ if (!isRecord$15(value)) return {};
310756
311067
  const agents = {};
310757
311068
  for (const [agentId, agentMeta] of Object.entries(value)) {
310758
- if (!isRecord$14(agentMeta)) {
311069
+ if (!isRecord$15(agentMeta)) {
310759
311070
  agents[agentId] = agentMeta;
310760
311071
  continue;
310761
311072
  }
@@ -310773,7 +311084,7 @@ function remapSessionPath(value, sourceDir, targetDir) {
310773
311084
  if (rel.startsWith("..") || isAbsolute$2(rel)) return value;
310774
311085
  return join$4(targetDir, rel);
310775
311086
  }
310776
- function isRecord$14(value) {
311087
+ function isRecord$15(value) {
310777
311088
  return typeof value === "object" && value !== null && !Array.isArray(value);
310778
311089
  }
310779
311090
  async function statIfExists(path) {
@@ -311021,7 +311332,7 @@ var init_session_store$1 = __esmMin((() => {
311021
311332
  } catch (error) {
311022
311333
  throw new BlunError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${input.sourceId}" state.json was not found`, { cause: error });
311023
311334
  }
311024
- if (!isRecord$14(parsed)) throw new BlunError(ErrorCodes.SESSION_STATE_INVALID, `Session "${input.sourceId}" state.json is invalid`);
311335
+ if (!isRecord$15(parsed)) throw new BlunError(ErrorCodes.SESSION_STATE_INVALID, `Session "${input.sourceId}" state.json is invalid`);
311025
311336
  const title = normalizeForkTitle(input.title, parsed["title"]);
311026
311337
  const now = (/* @__PURE__ */ new Date()).toISOString();
311027
311338
  const next = {
@@ -312204,6 +312515,7 @@ async function createRuntimeConfig(input) {
312204
312515
  const localFetcher = new LocalFetchURLProvider();
312205
312516
  const searchService = input.config.services?.blunSearch;
312206
312517
  const fetchService = input.config.services?.blunFetch;
312518
+ const mediaService = input.config.services?.blunMedia ?? managedBlunMediaService(input.config);
312207
312519
  return {
312208
312520
  urlFetcher: fetchService?.baseUrl === void 0 ? localFetcher : new BlunFetchURLProvider({
312209
312521
  baseUrl: fetchService.baseUrl,
@@ -312215,17 +312527,33 @@ async function createRuntimeConfig(input) {
312215
312527
  baseUrl: searchService.baseUrl,
312216
312528
  defaultHeaders: input.blunRequestHeaders,
312217
312529
  ...serviceCredentials(searchService, input.resolveOAuthTokenProvider)
312530
+ }),
312531
+ media: mediaService?.baseUrl === void 0 ? void 0 : new BlunMediaService({
312532
+ baseUrl: mediaService.baseUrl,
312533
+ defaultHeaders: input.blunRequestHeaders,
312534
+ ...serviceCredentials(mediaService, input.resolveOAuthTokenProvider)
312218
312535
  })
312219
312536
  };
312220
312537
  }
312538
+ function managedBlunMediaService(config) {
312539
+ const provider = config.providers[BLUN_PROVIDER_NAME];
312540
+ if (provider?.type !== "blun") return void 0;
312541
+ const baseUrl = nonEmptyString$1(provider.baseUrl);
312542
+ if (baseUrl === void 0) return void 0;
312543
+ return {
312544
+ baseUrl,
312545
+ apiKey: provider.apiKey,
312546
+ oauth: provider.oauth
312547
+ };
312548
+ }
312221
312549
  function serviceCredentials(service, resolveOAuthTokenProvider) {
312222
312550
  return {
312223
- apiKey: nonEmptyString(service.apiKey),
312551
+ apiKey: nonEmptyString$1(service.apiKey),
312224
312552
  tokenProvider: service.oauth !== void 0 ? resolveOAuthTokenProvider?.(BLUN_PROVIDER_NAME, service.oauth) : void 0,
312225
312553
  customHeaders: service.customHeaders
312226
312554
  };
312227
312555
  }
312228
- function nonEmptyString(value) {
312556
+ function nonEmptyString$1(value) {
312229
312557
  const trimmed = value?.trim();
312230
312558
  return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
312231
312559
  }
@@ -312309,6 +312637,7 @@ var init_core_impl = __esmMin((() => {
312309
312637
  init_local_fetch_url();
312310
312638
  init_blun_fetch_url();
312311
312639
  init_blun_web_search();
312640
+ init_blun_media();
312312
312641
  init_version();
312313
312642
  init_thinking();
312314
312643
  init_agent();
@@ -324034,7 +324363,7 @@ var SDKRpcClientBase = class {
324034
324363
  type: "error",
324035
324364
  sessionId: request.sessionId,
324036
324365
  agentId: request.agentId,
324037
- ...makeErrorPayload(ErrorCodes.SESSION_APPROVAL_HANDLER_ERROR, errorMessage$6(error))
324366
+ ...makeErrorPayload(ErrorCodes.SESSION_APPROVAL_HANDLER_ERROR, errorMessage$9(error))
324038
324367
  });
324039
324368
  return {
324040
324369
  decision: "cancelled",
@@ -324052,7 +324381,7 @@ var SDKRpcClientBase = class {
324052
324381
  type: "error",
324053
324382
  sessionId: request.sessionId,
324054
324383
  agentId: request.agentId,
324055
- ...makeErrorPayload(ErrorCodes.SESSION_QUESTION_HANDLER_ERROR, errorMessage$6(error))
324384
+ ...makeErrorPayload(ErrorCodes.SESSION_QUESTION_HANDLER_ERROR, errorMessage$9(error))
324056
324385
  });
324057
324386
  return null;
324058
324387
  }
@@ -324072,7 +324401,7 @@ var SDKRpcClientBase = class {
324072
324401
  return await handler(request);
324073
324402
  } catch (error) {
324074
324403
  return {
324075
- output: `Tool handler error for "${request.toolName ?? "(unknown)"}": ${errorMessage$6(error)}`,
324404
+ output: `Tool handler error for "${request.toolName ?? "(unknown)"}": ${errorMessage$9(error)}`,
324076
324405
  isError: true
324077
324406
  };
324078
324407
  }
@@ -324096,7 +324425,7 @@ var ClientAPI = class {
324096
324425
  return this.client.toolCall(request);
324097
324426
  }
324098
324427
  };
324099
- function errorMessage$6(error) {
324428
+ function errorMessage$9(error) {
324100
324429
  return error instanceof Error ? error.message : String(error);
324101
324430
  }
324102
324431
  //#endregion
@@ -333628,7 +333957,7 @@ var AcpSession = class {
333628
333957
  break;
333629
333958
  }
333630
333959
  } catch (error) {
333631
- await this.emitLocalCommandMessage(`/${name} failed: ${errorMessage$5(error)}`);
333960
+ await this.emitLocalCommandMessage(`/${name} failed: ${errorMessage$8(error)}`);
333632
333961
  }
333633
333962
  return { stopReason: "end_turn" };
333634
333963
  }
@@ -334019,7 +334348,7 @@ var AcpSession = class {
334019
334348
  }
334020
334349
  }
334021
334350
  };
334022
- function errorMessage$5(error) {
334351
+ function errorMessage$8(error) {
334023
334352
  return error instanceof Error ? error.message : String(error);
334024
334353
  }
334025
334354
  function formatHelpReport(commands) {
@@ -336508,8 +336837,8 @@ function createAccountMemoryClient(auth, options = {}) {
336508
336837
  }
336509
336838
  function readAccountMemoryConsentStatus(payload) {
336510
336839
  const settings = unwrapPayload(payload)?.["settings"];
336511
- const dataControls = isRecord$13(settings) ? settings["data_controls"] : void 0;
336512
- if (!isRecord$13(dataControls)) throw new Error("Account memory returned an invalid response.");
336840
+ const dataControls = isRecord$14(settings) ? settings["data_controls"] : void 0;
336841
+ if (!isRecord$14(dataControls)) throw new Error("Account memory returned an invalid response.");
336513
336842
  if (dataControls["memory_consent_asked"] !== true) return "never_asked";
336514
336843
  if (dataControls["allow_memory"] === true) return "enabled";
336515
336844
  if (dataControls["allow_memory"] === false) return "disabled";
@@ -336632,8 +336961,8 @@ function memoryContextSummary(facts, included) {
336632
336961
  })}`;
336633
336962
  }
336634
336963
  function unwrapPayload(value) {
336635
- if (!isRecord$13(value)) return void 0;
336636
- return isRecord$13(value["data"]) ? value["data"] : value;
336964
+ if (!isRecord$14(value)) return void 0;
336965
+ return isRecord$14(value["data"]) ? value["data"] : value;
336637
336966
  }
336638
336967
  function readFacts(root) {
336639
336968
  let rawFacts = [];
@@ -336641,7 +336970,7 @@ function readFacts(root) {
336641
336970
  else {
336642
336971
  const factsJson = parseFactsJson(root["facts_json"]);
336643
336972
  if (Array.isArray(factsJson)) rawFacts = factsJson;
336644
- else if (isRecord$13(factsJson) && Array.isArray(factsJson["facts"])) rawFacts = factsJson["facts"];
336973
+ else if (isRecord$14(factsJson) && Array.isArray(factsJson["facts"])) rawFacts = factsJson["facts"];
336645
336974
  }
336646
336975
  const facts = [];
336647
336976
  const seen = /* @__PURE__ */ new Set();
@@ -336670,7 +336999,7 @@ function parseFactsJson(value) {
336670
336999
  }
336671
337000
  }
336672
337001
  function normalizeFact(value) {
336673
- const raw = typeof value === "string" ? value : isRecord$13(value) && typeof value["text"] === "string" ? value["text"] : void 0;
337002
+ const raw = typeof value === "string" ? value : isRecord$14(value) && typeof value["text"] === "string" ? value["text"] : void 0;
336674
337003
  if (raw === void 0) return void 0;
336675
337004
  const normalized = raw.replaceAll(/\s+/gu, " ").trim();
336676
337005
  if (normalized.length === 0) return void 0;
@@ -336679,7 +337008,7 @@ function normalizeFact(value) {
336679
337008
  truncated: normalized.length > ACCOUNT_MEMORY_MAX_FACT_CHARS
336680
337009
  };
336681
337010
  }
336682
- function isRecord$13(value) {
337011
+ function isRecord$14(value) {
336683
337012
  return typeof value === "object" && value !== null && !Array.isArray(value);
336684
337013
  }
336685
337014
  //#endregion
@@ -337848,7 +338177,7 @@ async function updateTuiAppearance(appearance, filePath = getTuiConfigPath()) {
337848
338177
  throw new TuiConfigParseError(DEFAULT_TUI_CONFIG);
337849
338178
  }
337850
338179
  } catch (error) {
337851
- if (!isNotFound$1(error)) throw error;
338180
+ if (!isNotFound$3(error)) throw error;
337852
338181
  }
337853
338182
  const next = TuiConfigSchema.parse({
337854
338183
  ...current,
@@ -337946,7 +338275,7 @@ async function writeTuiConfigAtomic(config, filePath) {
337946
338275
  throw error;
337947
338276
  }
337948
338277
  }
337949
- function isNotFound$1(error) {
338278
+ function isNotFound$3(error) {
337950
338279
  return typeof error === "object" && error !== null && error.code === "ENOENT";
337951
338280
  }
337952
338281
  function renderAppearanceConfig(appearance) {
@@ -337966,7 +338295,7 @@ function escapeTomlBasicString(value) {
337966
338295
  //#region src/cli/sub/doctor.ts
337967
338296
  init_zod$1();
337968
338297
  async function handleDoctor(deps, options) {
337969
- const resolved = resolveDeps(deps);
338298
+ const resolved = resolveDeps$1(deps);
337970
338299
  const specs = await buildCheckSpecs(resolved, options, resolved.cwd());
337971
338300
  const results = await Promise.all(specs.map((spec) => checkTomlFile(resolved, spec)));
337972
338301
  const issueCount = results.filter((result) => result.status === "ERROR").length;
@@ -337993,11 +338322,11 @@ function registerDoctorCommand(parent, deps) {
337993
338322
  });
337994
338323
  }
337995
338324
  async function runDoctorCommand(deps, options) {
337996
- const resolved = resolveDeps(deps);
338325
+ const resolved = resolveDeps$1(deps);
337997
338326
  const code = await handleDoctor(resolved, options);
337998
338327
  if (code !== 0) resolved.exit(code);
337999
338328
  }
338000
- function resolveDeps(deps) {
338329
+ function resolveDeps$1(deps) {
338001
338330
  let configRpc = deps?.configRpc;
338002
338331
  const getConfigRpc = () => {
338003
338332
  configRpc ??= createBlunConfigRpc();
@@ -338120,7 +338449,7 @@ function formatErrorMessage$4(error, filePath) {
338120
338449
  function findValidationIssues(error) {
338121
338450
  if (!(error instanceof Error)) return void 0;
338122
338451
  const details = "details" in error ? error.details : void 0;
338123
- if (!isRecord$12(details)) return void 0;
338452
+ if (!isRecord$13(details)) return void 0;
338124
338453
  const validationIssues = details["validationIssues"];
338125
338454
  return isValidationIssueArray(validationIssues) ? validationIssues : void 0;
338126
338455
  }
@@ -338128,11 +338457,11 @@ function isValidationIssueArray(value) {
338128
338457
  return Array.isArray(value) && value.every(isValidationIssue);
338129
338458
  }
338130
338459
  function isValidationIssue(value) {
338131
- if (!isRecord$12(value) || typeof value["message"] !== "string") return false;
338460
+ if (!isRecord$13(value) || typeof value["message"] !== "string") return false;
338132
338461
  const path = value["path"];
338133
338462
  return Array.isArray(path) && path.every((segment) => typeof segment === "string" || typeof segment === "number");
338134
338463
  }
338135
- function isRecord$12(value) {
338464
+ function isRecord$13(value) {
338136
338465
  return typeof value === "object" && value !== null;
338137
338466
  }
338138
338467
  function findZodError(error) {
@@ -338397,7 +338726,7 @@ async function handleExport(deps, sessionId, output, opts) {
338397
338726
  });
338398
338727
  deps.stdout.write(`${result.zipPath}\n`);
338399
338728
  } catch (error) {
338400
- deps.stderr.write(`${errorMessage$4(error)}\n`);
338729
+ deps.stderr.write(`${errorMessage$7(error)}\n`);
338401
338730
  deps.exit(1);
338402
338731
  }
338403
338732
  }
@@ -338500,7 +338829,7 @@ async function confirmPreviousSession(summary) {
338500
338829
  rl.close();
338501
338830
  }
338502
338831
  }
338503
- function errorMessage$4(error) {
338832
+ function errorMessage$7(error) {
338504
338833
  return error instanceof Error ? error.message : String(error);
338505
338834
  }
338506
338835
  //#endregion
@@ -338511,6 +338840,1444 @@ function registerLoginCommand(parent) {
338511
338840
  });
338512
338841
  }
338513
338842
  //#endregion
338843
+ //#region src/mistakes/inflow-client.ts
338844
+ const MISTAKE_INVENTORY_STATUSES = [
338845
+ "counted",
338846
+ "uncounted",
338847
+ "unverified"
338848
+ ];
338849
+ const MISTAKE_ACTUALITY_STATUSES = [
338850
+ "fresh",
338851
+ "stale",
338852
+ "unverified"
338853
+ ];
338854
+ const MISTAKE_SOURCE_FORMS = [
338855
+ "case_collection",
338856
+ "class_collection",
338857
+ "finding_collection",
338858
+ "lesson_collection",
338859
+ "state_collection",
338860
+ "mixed",
338861
+ "unknown"
338862
+ ];
338863
+ const MISTAKE_RECORD_TYPES = [
338864
+ "case",
338865
+ "class",
338866
+ "finding",
338867
+ "lesson",
338868
+ "state",
338869
+ "unknown"
338870
+ ];
338871
+ const MISTAKE_RELATION_TYPES = [
338872
+ "instance_of",
338873
+ "lesson_from",
338874
+ "state_of",
338875
+ "independently_corroborates"
338876
+ ];
338877
+ const MISTAKE_WATCHDOG_STATUSES = [
338878
+ "disabled",
338879
+ "green",
338880
+ "yellow",
338881
+ "red"
338882
+ ];
338883
+ const DEFAULT_DEPS$2 = {
338884
+ fetch: globalThis.fetch,
338885
+ now: () => /* @__PURE__ */ new Date(),
338886
+ randomUUID
338887
+ };
338888
+ const SOURCE_ID_RE = /^[a-z0-9][a-z0-9._-]{0,79}$/;
338889
+ const SHA256_RE = /^[a-f0-9]{64}$/;
338890
+ const UUID_RE$1 = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i;
338891
+ const ENVELOPE_KEYS = [
338892
+ "version",
338893
+ "client_event_id",
338894
+ "source_id",
338895
+ "source_form",
338896
+ "declared_record_types",
338897
+ "original_name",
338898
+ "captured_at",
338899
+ "inventory",
338900
+ "declared_raw_bytes",
338901
+ "declared_raw_sha256",
338902
+ "payload_base64",
338903
+ "declarations"
338904
+ ];
338905
+ const INVENTORY_KEYS = [
338906
+ "scope",
338907
+ "bestandsstatus",
338908
+ "aktualitaetsstatus",
338909
+ "declared_entry_count",
338910
+ "last_raw_observed_at"
338911
+ ];
338912
+ const STATE_ACTION_KEYS = [
338913
+ "version",
338914
+ "action_id",
338915
+ "action",
338916
+ "target_event_id",
338917
+ "acted_at",
338918
+ "server_sequence",
338919
+ "principal_id",
338920
+ "reason"
338921
+ ];
338922
+ const MAX_MISTAKE_SOURCE_BYTES = 20 * 1024 * 1024;
338923
+ function normalizeMistakeSourceId(value) {
338924
+ const normalized = value.normalize("NFKC").trim().toLocaleLowerCase("en-US");
338925
+ if (!SOURCE_ID_RE.test(normalized)) throw new Error("source id must use 1-80 lowercase letters, digits, dots, underscores, or hyphens");
338926
+ return normalized;
338927
+ }
338928
+ function assertSafeMistakeInflowEndpoint(value) {
338929
+ let url;
338930
+ try {
338931
+ url = new URL(value);
338932
+ } catch {
338933
+ throw new Error("mistake inflow endpoint is not a valid URL");
338934
+ }
338935
+ if (url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "") throw new Error("mistake inflow endpoint must not contain credentials, a query, or a fragment");
338936
+ if (url.pathname !== "/" && url.pathname !== "") throw new Error("mistake inflow endpoint must not include a path");
338937
+ if (url.protocol === "https:") return url;
338938
+ if (url.protocol !== "http:" || !isPrivateHttpHost(url.hostname)) throw new Error("plain HTTP mistake inflow is allowed only on loopback or Tailscale addresses");
338939
+ return url;
338940
+ }
338941
+ function isPrivateHttpHost(hostname) {
338942
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]") return true;
338943
+ const parts = hostname.split(".").map(Number);
338944
+ const first = parts[0];
338945
+ const second = parts[1];
338946
+ return parts.length === 4 && parts.every((part) => Number.isInteger(part) && part >= 0 && part <= 255) && first === 100 && second !== void 0 && second >= 64 && second <= 127;
338947
+ }
338948
+ function assertIsoTimestamp$2(value, label) {
338949
+ const parsed = new Date(value);
338950
+ if (!Number.isFinite(parsed.valueOf()) || !/(?:Z|[+-]\d{2}:\d{2})$/.test(value)) throw new Error(`${label} must be an ISO-8601 timestamp with a timezone`);
338951
+ return value;
338952
+ }
338953
+ function assertEntryCount(value) {
338954
+ if (value === void 0) return null;
338955
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error("declared entry count must be a non-negative safe integer");
338956
+ return value;
338957
+ }
338958
+ function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
338959
+ if (!isRecord$12(value) || !hasOnlyKeys(value, [
338960
+ "version",
338961
+ "records",
338962
+ "relations"
338963
+ ]) || value["version"] !== 1) throw new Error("record declarations must use version 1 and contain only records and relations");
338964
+ if (!Array.isArray(value["records"]) || value["records"].length > 1e5 || !Array.isArray(value["relations"]) || value["relations"].length > 1e5) throw new Error("record declarations require records and relations arrays of at most 100000 items");
338965
+ normalizeMistakeSourceId(sourceId);
338966
+ const allowedRecordTypes = new Set(declaredRecordTypes);
338967
+ if (allowedRecordTypes.size === 0 || [...allowedRecordTypes].some((type) => !MISTAKE_RECORD_TYPES.includes(type))) throw new Error("declared source record types are invalid");
338968
+ const recordIds = /* @__PURE__ */ new Set();
338969
+ return {
338970
+ version: 1,
338971
+ records: value["records"].map((candidate, index) => {
338972
+ if (!isRecord$12(candidate) || !hasOnlyKeys(candidate, [
338973
+ "source_record_id",
338974
+ "type",
338975
+ "raw_locator"
338976
+ ])) throw new Error(`record declaration ${index} is invalid`);
338977
+ const recordId = candidate["source_record_id"];
338978
+ const type = candidate["type"];
338979
+ const rawLocator = candidate["raw_locator"];
338980
+ if (typeof recordId !== "string" || !isValidRecordId(recordId)) throw new Error(`record declaration ${index} has an invalid record id`);
338981
+ if (recordIds.has(recordId)) throw new Error(`duplicate record id: ${recordId}`);
338982
+ if (typeof type !== "string" || !MISTAKE_RECORD_TYPES.includes(type) || !allowedRecordTypes.has(type)) throw new Error(`record ${recordId} uses a type not declared by its source`);
338983
+ if (typeof rawLocator !== "string" || !isSafeRawLocator(rawLocator)) throw new Error(`record ${recordId} has an invalid raw locator`);
338984
+ recordIds.add(recordId);
338985
+ return {
338986
+ source_record_id: recordId,
338987
+ type,
338988
+ raw_locator: rawLocator
338989
+ };
338990
+ }),
338991
+ relations: value["relations"].map((candidate, index) => {
338992
+ if (!isRecord$12(candidate) || !hasOnlyKeys(candidate, [
338993
+ "from_source_record_id",
338994
+ "type",
338995
+ "to"
338996
+ ])) throw new Error(`record relation ${index} is invalid`);
338997
+ const fromRecordId = candidate["from_source_record_id"];
338998
+ const type = candidate["type"];
338999
+ const target = candidate["to"];
339000
+ if (typeof fromRecordId !== "string" || !isValidRecordId(fromRecordId) || !recordIds.has(fromRecordId)) throw new Error(`record relation ${index} must start at a declared local record`);
339001
+ if (typeof type !== "string" || !MISTAKE_RELATION_TYPES.includes(type)) throw new Error(`record relation ${index} has an invalid relation type`);
339002
+ if (!isRecord$12(target) || !hasOnlyKeys(target, ["source_id", "source_record_id"])) throw new Error(`record relation ${index} has an invalid target`);
339003
+ const targetSourceId = target["source_id"];
339004
+ const targetRecordId = target["source_record_id"];
339005
+ if (typeof targetSourceId !== "string" || !isNormalizedSourceId(targetSourceId)) throw new Error(`record relation ${index} has an invalid target source id`);
339006
+ if (typeof targetRecordId !== "string" || !isValidRecordId(targetRecordId)) throw new Error(`record relation ${index} has an invalid target record id`);
339007
+ return {
339008
+ from_source_record_id: fromRecordId,
339009
+ type,
339010
+ to: {
339011
+ source_id: targetSourceId,
339012
+ source_record_id: targetRecordId
339013
+ }
339014
+ };
339015
+ })
339016
+ };
339017
+ }
339018
+ async function queueMistakeObservation(input, outboxDir, deps = DEFAULT_DEPS$2) {
339019
+ const sourceStat = await lstat(input.filePath);
339020
+ if (sourceStat.isSymbolicLink()) throw new Error("mistake source must not be a symbolic link");
339021
+ if (!sourceStat.isFile()) throw new Error("mistake source must be a regular file");
339022
+ if (sourceStat.size > 20971520) throw new Error(`mistake source exceeds ${MAX_MISTAKE_SOURCE_BYTES} bytes`);
339023
+ const sourceHandle = await open(input.filePath, "r");
339024
+ let raw;
339025
+ try {
339026
+ const openedStat = await sourceHandle.stat();
339027
+ if (!openedStat.isFile() || openedStat.dev !== sourceStat.dev || openedStat.ino !== sourceStat.ino) throw new Error("mistake source changed while it was being opened");
339028
+ raw = await sourceHandle.readFile();
339029
+ } finally {
339030
+ await sourceHandle.close();
339031
+ }
339032
+ if (raw.byteLength > 20971520) throw new Error(`mistake source exceeds ${MAX_MISTAKE_SOURCE_BYTES} bytes`);
339033
+ const clientEventId = input.clientEventId ?? deps.randomUUID();
339034
+ if (!UUID_RE$1.test(clientEventId)) throw new Error("client event id must be a UUID");
339035
+ const capturedAt = assertIsoTimestamp$2(input.capturedAt ?? deps.now().toISOString(), "captured at");
339036
+ const lastRawObservedAt = input.lastRawObservedAt === void 0 ? null : assertIsoTimestamp$2(input.lastRawObservedAt, "last raw observed at");
339037
+ const recordTypes = [...new Set(input.recordTypes)];
339038
+ if (recordTypes.length === 0 || recordTypes.some((type) => !MISTAKE_RECORD_TYPES.includes(type))) throw new Error("at least one valid declared record type is required");
339039
+ if (!MISTAKE_SOURCE_FORMS.includes(input.sourceForm)) throw new Error("invalid source form");
339040
+ if (!MISTAKE_INVENTORY_STATUSES.includes(input.bestandsstatus)) throw new Error("invalid bestandsstatus");
339041
+ if (!MISTAKE_ACTUALITY_STATUSES.includes(input.aktualitaetsstatus)) throw new Error("invalid aktualitaetsstatus");
339042
+ const declaredEntryCount = assertEntryCount(input.declaredEntryCount);
339043
+ assertInventoryInvariants(input.bestandsstatus, input.aktualitaetsstatus, declaredEntryCount, lastRawObservedAt, capturedAt);
339044
+ const sourceId = normalizeMistakeSourceId(input.sourceId);
339045
+ const declarations = input.declarations === void 0 ? void 0 : parseMistakeRecordDeclarations(input.declarations, sourceId, recordTypes);
339046
+ const envelope = {
339047
+ version: 1,
339048
+ client_event_id: clientEventId,
339049
+ source_id: sourceId,
339050
+ source_form: input.sourceForm,
339051
+ declared_record_types: recordTypes,
339052
+ original_name: basename(input.filePath),
339053
+ captured_at: capturedAt,
339054
+ inventory: {
339055
+ scope: "lower_bound",
339056
+ bestandsstatus: input.bestandsstatus,
339057
+ aktualitaetsstatus: input.aktualitaetsstatus,
339058
+ declared_entry_count: declaredEntryCount,
339059
+ last_raw_observed_at: lastRawObservedAt
339060
+ },
339061
+ declared_raw_bytes: raw.byteLength,
339062
+ declared_raw_sha256: createHash("sha256").update(raw).digest("hex"),
339063
+ payload_base64: raw.toString("base64"),
339064
+ declarations
339065
+ };
339066
+ const eventsDir = join(outboxDir, "events");
339067
+ await ensureDurableMistakeDirectory(eventsDir);
339068
+ await durableExclusiveWrite(join(eventsDir, `${clientEventId}.json`), `${JSON.stringify(envelope)}\n`);
339069
+ return envelope;
339070
+ }
339071
+ function endpointUrl(endpoint, path) {
339072
+ const base = assertSafeMistakeInflowEndpoint(endpoint);
339073
+ return new URL(path, base);
339074
+ }
339075
+ async function readJsonResponse(response) {
339076
+ const text = await response.text();
339077
+ try {
339078
+ return JSON.parse(text);
339079
+ } catch {
339080
+ throw new Error(`mistake inflow returned non-JSON HTTP ${response.status}`);
339081
+ }
339082
+ }
339083
+ function isReceipt(value) {
339084
+ if (typeof value !== "object" || value === null) return false;
339085
+ const item = value;
339086
+ return item["version"] === 1 && item["accepted"] === true && typeof item["event_id"] === "string" && UUID_RE$1.test(item["event_id"]) && typeof item["client_event_id"] === "string" && UUID_RE$1.test(item["client_event_id"]) && typeof item["source_id"] === "string" && isNormalizedSourceId(item["source_id"]) && typeof item["canonical_agent_id"] === "string" && isNormalizedSourceId(item["canonical_agent_id"]) && typeof item["received_at"] === "string" && isIsoTimestamp(item["received_at"]) && item["raw_count"] === 1 && item["accepted_count"] === 1 && item["rejected_count"] === 0 && Number.isSafeInteger(item["raw_bytes"]) && item["raw_bytes"] >= 0 && typeof item["raw_sha256"] === "string" && SHA256_RE.test(item["raw_sha256"]) && isNullableEntryCount(item["declared_entry_count"]);
339087
+ }
339088
+ async function deliverQueuedObservation(clientEventId, options, deps = DEFAULT_DEPS$2) {
339089
+ if (!UUID_RE$1.test(clientEventId)) throw new Error("client event id must be a UUID");
339090
+ const envelope = parseQueuedEnvelope(await readFile(join(options.outboxDir, "events", `${clientEventId}.json`), "utf8"), clientEventId);
339091
+ const controller = new AbortController();
339092
+ const timeout = setTimeout(() => {
339093
+ controller.abort();
339094
+ }, 15e3);
339095
+ let response;
339096
+ try {
339097
+ response = await deps.fetch(endpointUrl(options.endpoint, "/v1/observations"), {
339098
+ method: "POST",
339099
+ headers: {
339100
+ authorization: `Bearer ${options.token}`,
339101
+ "content-type": "application/json"
339102
+ },
339103
+ body: JSON.stringify(envelope),
339104
+ signal: controller.signal,
339105
+ redirect: "error"
339106
+ });
339107
+ } finally {
339108
+ clearTimeout(timeout);
339109
+ }
339110
+ const body = await readJsonResponse(response);
339111
+ if (response.status !== 202 || !isReceipt(body)) {
339112
+ const bodyError = typeof body === "object" && body !== null ? body["error"] : void 0;
339113
+ const message = typeof bodyError === "string" ? bodyError : `HTTP ${response.status}`;
339114
+ throw new Error(`mistake inflow rejected ${clientEventId}: ${message}`);
339115
+ }
339116
+ if (!receiptMatchesEnvelope(body, envelope)) throw new Error(`mistake inflow receipt mismatch for ${clientEventId}`);
339117
+ const receiptsDir = join(options.outboxDir, "receipts", clientEventId);
339118
+ await ensureDurableMistakeDirectory(receiptsDir);
339119
+ const receiptPath = join(receiptsDir, `${body.event_id}.json`);
339120
+ try {
339121
+ await durableExclusiveWrite(receiptPath, `${JSON.stringify(body)}\n`);
339122
+ } catch (error) {
339123
+ if (!isAlreadyExists$1(error)) throw error;
339124
+ const existing = await readReceipt(receiptPath);
339125
+ if (existing !== null && existing.event_id === body.event_id && receiptMatchesEnvelope(existing, envelope)) {
339126
+ if (!receiptsEqual(existing, body)) throw new Error(`conflicting local receipt for ${clientEventId}`, { cause: error });
339127
+ } else await durableExclusiveWrite(join(receiptsDir, `${body.event_id}.${randomUUID()}.json`), `${JSON.stringify(body)}\n`);
339128
+ }
339129
+ return body;
339130
+ }
339131
+ async function uploadMistakeObservation(input, options, deps = DEFAULT_DEPS$2) {
339132
+ return deliverQueuedObservation((await queueMistakeObservation(input, options.outboxDir, deps)).client_event_id, options, deps);
339133
+ }
339134
+ async function drainMistakeOutbox(options, deps = DEFAULT_DEPS$2) {
339135
+ const eventsDir = join(options.outboxDir, "events");
339136
+ await ensureDurableMistakeDirectory(eventsDir);
339137
+ const names = (await readdir(eventsDir)).filter((name) => UUID_RE$1.test(name.replace(/\.json$/, "")) && name.endsWith(".json")).toSorted();
339138
+ const delivered = [];
339139
+ const failed = [];
339140
+ const pending = [];
339141
+ for (const name of names) {
339142
+ const clientEventId = name.slice(0, -5);
339143
+ try {
339144
+ const envelope = parseQueuedEnvelope(await readFile(join(eventsDir, name), "utf8"), clientEventId);
339145
+ if (await findVerifiedLocalReceipt(envelope, options.outboxDir) !== null) continue;
339146
+ pending.push(envelope);
339147
+ } catch (error) {
339148
+ failed.push({
339149
+ clientEventId,
339150
+ error: errorMessage$6(error)
339151
+ });
339152
+ }
339153
+ }
339154
+ pending.sort(compareObservationOrder);
339155
+ for (const envelope of pending) try {
339156
+ delivered.push(await deliverQueuedObservation(envelope.client_event_id, options, deps));
339157
+ } catch (error) {
339158
+ failed.push({
339159
+ clientEventId: envelope.client_event_id,
339160
+ error: errorMessage$6(error)
339161
+ });
339162
+ }
339163
+ return {
339164
+ delivered,
339165
+ failed
339166
+ };
339167
+ }
339168
+ async function getMistakeInflowStatus(endpoint, token, deps = DEFAULT_DEPS$2) {
339169
+ const response = await deps.fetch(endpointUrl(endpoint, "/v1/status"), {
339170
+ headers: { authorization: `Bearer ${token}` },
339171
+ redirect: "error"
339172
+ });
339173
+ const body = await readJsonResponse(response);
339174
+ if (response.status !== 200) throw new Error(`mistake inflow status failed: HTTP ${response.status}`);
339175
+ if (!isMistakeInflowStatus(body)) throw new Error("mistake inflow status returned an invalid payload");
339176
+ return body;
339177
+ }
339178
+ async function changeMistakeObservationState(action, eventId, reason, endpoint, token, deps = DEFAULT_DEPS$2) {
339179
+ if (!UUID_RE$1.test(eventId)) throw new Error("event id must be a UUID");
339180
+ const trimmedReason = reason.trim();
339181
+ if (trimmedReason.length < 3 || trimmedReason.length > 500) throw new Error("reason must contain 3-500 characters");
339182
+ const actionId = deps.randomUUID();
339183
+ if (!UUID_RE$1.test(actionId)) throw new Error("generated action id must be a UUID");
339184
+ const response = await deps.fetch(endpointUrl(endpoint, `/v1/observations/${eventId}:${action}`), {
339185
+ method: "POST",
339186
+ headers: {
339187
+ authorization: `Bearer ${token}`,
339188
+ "content-type": "application/json"
339189
+ },
339190
+ body: JSON.stringify({
339191
+ action_id: actionId,
339192
+ reason: trimmedReason
339193
+ }),
339194
+ redirect: "error"
339195
+ });
339196
+ const body = await readJsonResponse(response);
339197
+ if (response.status !== 201) {
339198
+ const bodyError = typeof body === "object" && body !== null ? body["error"] : void 0;
339199
+ const detail = typeof bodyError === "string" ? bodyError : `HTTP ${response.status}`;
339200
+ throw new Error(`mistake inflow ${action} failed: ${detail}`);
339201
+ }
339202
+ if (!isStateActionReceipt(body) || body.action_id !== actionId || body.action !== action || body.target_event_id !== eventId || body.reason !== trimmedReason) throw new Error(`mistake inflow ${action} returned a mismatched action receipt`);
339203
+ return body;
339204
+ }
339205
+ function parseQueuedEnvelope(text, expectedClientEventId) {
339206
+ let value;
339207
+ try {
339208
+ value = JSON.parse(text);
339209
+ } catch {
339210
+ throw new Error(`queued mistake event ${expectedClientEventId} is not valid JSON`);
339211
+ }
339212
+ if (typeof value !== "object" || value === null) throw new Error(`queued mistake event ${expectedClientEventId} is invalid`);
339213
+ const item = value;
339214
+ if (!hasOnlyKeys(item, ENVELOPE_KEYS) || item["version"] !== 1 || item["client_event_id"] !== expectedClientEventId || !UUID_RE$1.test(expectedClientEventId)) throw new Error(`queued mistake event ${expectedClientEventId} has an invalid identity`);
339215
+ if (typeof item["source_id"] !== "string" || !isNormalizedSourceId(item["source_id"])) throw new Error(`queued mistake event ${expectedClientEventId} has an invalid source`);
339216
+ if (typeof item["source_form"] !== "string" || !MISTAKE_SOURCE_FORMS.includes(item["source_form"])) throw new Error(`queued mistake event ${expectedClientEventId} has an invalid source form`);
339217
+ const recordTypes = item["declared_record_types"];
339218
+ if (!Array.isArray(recordTypes) || recordTypes.length === 0 || new Set(recordTypes).size !== recordTypes.length || recordTypes.some((type) => typeof type !== "string" || !MISTAKE_RECORD_TYPES.includes(type))) throw new Error(`queued mistake event ${expectedClientEventId} has invalid record types`);
339219
+ if (typeof item["original_name"] !== "string" || item["original_name"] === "" || basename(item["original_name"]) !== item["original_name"]) throw new Error(`queued mistake event ${expectedClientEventId} has an invalid original name`);
339220
+ if (typeof item["captured_at"] !== "string" || !isIsoTimestamp(item["captured_at"])) throw new Error(`queued mistake event ${expectedClientEventId} has an invalid capture time`);
339221
+ const inventory = item["inventory"];
339222
+ if (typeof inventory !== "object" || inventory === null) throw new Error(`queued mistake event ${expectedClientEventId} has invalid inventory metadata`);
339223
+ const inventoryItem = inventory;
339224
+ if (!hasOnlyKeys(inventoryItem, INVENTORY_KEYS) || inventoryItem["scope"] !== "lower_bound" || typeof inventoryItem["bestandsstatus"] !== "string" || !MISTAKE_INVENTORY_STATUSES.includes(inventoryItem["bestandsstatus"]) || typeof inventoryItem["aktualitaetsstatus"] !== "string" || !MISTAKE_ACTUALITY_STATUSES.includes(inventoryItem["aktualitaetsstatus"]) || !isNullableEntryCount(inventoryItem["declared_entry_count"]) || inventoryItem["last_raw_observed_at"] !== null && (typeof inventoryItem["last_raw_observed_at"] !== "string" || !isIsoTimestamp(inventoryItem["last_raw_observed_at"]))) throw new Error(`queued mistake event ${expectedClientEventId} has invalid inventory metadata`);
339225
+ try {
339226
+ assertInventoryInvariants(inventoryItem["bestandsstatus"], inventoryItem["aktualitaetsstatus"], inventoryItem["declared_entry_count"], inventoryItem["last_raw_observed_at"], item["captured_at"]);
339227
+ } catch (error) {
339228
+ throw new Error(`queued mistake event ${expectedClientEventId} has contradictory inventory metadata`, { cause: error });
339229
+ }
339230
+ if (!Number.isSafeInteger(item["declared_raw_bytes"]) || item["declared_raw_bytes"] < 0 || item["declared_raw_bytes"] > 20971520 || typeof item["declared_raw_sha256"] !== "string" || !SHA256_RE.test(item["declared_raw_sha256"]) || typeof item["payload_base64"] !== "string") throw new Error(`queued mistake event ${expectedClientEventId} has invalid payload metadata`);
339231
+ const payload = Buffer.from(item["payload_base64"], "base64");
339232
+ if (payload.toString("base64") !== item["payload_base64"] || payload.byteLength !== item["declared_raw_bytes"] || createHash("sha256").update(payload).digest("hex") !== item["declared_raw_sha256"]) throw new Error(`queued mistake event ${expectedClientEventId} failed payload integrity verification`);
339233
+ if (item["declarations"] !== void 0) try {
339234
+ parseMistakeRecordDeclarations(item["declarations"], item["source_id"], recordTypes);
339235
+ } catch (error) {
339236
+ throw new Error(`queued mistake event ${expectedClientEventId} has invalid record declarations`, { cause: error });
339237
+ }
339238
+ return value;
339239
+ }
339240
+ async function findVerifiedLocalReceipt(envelope, outboxDir) {
339241
+ const receiptRoot = join(outboxDir, "receipts");
339242
+ const paths = [join(receiptRoot, `${envelope.client_event_id}.json`)];
339243
+ const eventReceiptDir = join(receiptRoot, envelope.client_event_id);
339244
+ try {
339245
+ const names = (await readdir(eventReceiptDir)).filter((name) => name.endsWith(".json")).toSorted();
339246
+ paths.push(...names.map((name) => join(eventReceiptDir, name)));
339247
+ } catch (error) {
339248
+ if (!isNotFound$2(error)) throw error;
339249
+ }
339250
+ for (const path of paths) {
339251
+ const candidate = await readReceipt(path);
339252
+ if (candidate !== null && receiptMatchesEnvelope(candidate, envelope)) return candidate;
339253
+ }
339254
+ return null;
339255
+ }
339256
+ async function readReceipt(path) {
339257
+ try {
339258
+ const value = JSON.parse(await readFile(path, "utf8"));
339259
+ return isReceipt(value) ? value : null;
339260
+ } catch (error) {
339261
+ if (isNotFound$2(error) || error instanceof SyntaxError) return null;
339262
+ throw error;
339263
+ }
339264
+ }
339265
+ function receiptMatchesEnvelope(receipt, envelope) {
339266
+ return receipt.client_event_id === envelope.client_event_id && receipt.source_id === envelope.source_id && receipt.raw_bytes === envelope.declared_raw_bytes && receipt.raw_sha256 === envelope.declared_raw_sha256 && receipt.declared_entry_count === envelope.inventory.declared_entry_count;
339267
+ }
339268
+ function receiptsEqual(left, right) {
339269
+ return left.version === right.version && left.accepted === right.accepted && left.event_id === right.event_id && left.client_event_id === right.client_event_id && left.source_id === right.source_id && left.canonical_agent_id === right.canonical_agent_id && left.received_at === right.received_at && left.raw_count === right.raw_count && left.accepted_count === right.accepted_count && left.rejected_count === right.rejected_count && left.raw_bytes === right.raw_bytes && left.raw_sha256 === right.raw_sha256 && left.declared_entry_count === right.declared_entry_count;
339270
+ }
339271
+ function isStateActionReceipt(value) {
339272
+ if (!isRecord$12(value) || !hasOnlyKeys(value, STATE_ACTION_KEYS)) return false;
339273
+ const reason = value["reason"];
339274
+ return value["version"] === 1 && typeof value["action_id"] === "string" && UUID_RE$1.test(value["action_id"]) && (value["action"] === "remove" || value["action"] === "restore") && typeof value["target_event_id"] === "string" && UUID_RE$1.test(value["target_event_id"]) && typeof value["acted_at"] === "string" && isIsoTimestamp(value["acted_at"]) && Number.isSafeInteger(value["server_sequence"]) && value["server_sequence"] >= 1 && typeof value["principal_id"] === "string" && isNormalizedSourceId(value["principal_id"]) && typeof reason === "string" && reason.trim() === reason && reason.length >= 3 && reason.length <= 500;
339275
+ }
339276
+ function compareObservationOrder(left, right) {
339277
+ const leftObservedAt = left.inventory.last_raw_observed_at ?? left.captured_at;
339278
+ const rightObservedAt = right.inventory.last_raw_observed_at ?? right.captured_at;
339279
+ return Date.parse(leftObservedAt) - Date.parse(rightObservedAt) || Date.parse(left.captured_at) - Date.parse(right.captured_at) || left.source_id.localeCompare(right.source_id) || left.client_event_id.localeCompare(right.client_event_id);
339280
+ }
339281
+ async function ensureDurableMistakeDirectory(path, deps) {
339282
+ const io = deps ?? {
339283
+ lstat,
339284
+ mkdir,
339285
+ syncDirectory
339286
+ };
339287
+ const missing = [];
339288
+ let cursor = resolve(path);
339289
+ while (true) try {
339290
+ const existing = await io.lstat(cursor);
339291
+ if (existing.isSymbolicLink() || !existing.isDirectory()) throw new Error(`mistake outbox path is not a real directory: ${cursor}`);
339292
+ break;
339293
+ } catch (error) {
339294
+ if (!isNotFound$2(error)) throw error;
339295
+ missing.push(cursor);
339296
+ const parent = dirname(cursor);
339297
+ if (parent === cursor) throw new Error(`mistake outbox has no existing parent: ${path}`, { cause: error });
339298
+ cursor = parent;
339299
+ }
339300
+ for (const directory of missing.toReversed()) {
339301
+ try {
339302
+ await io.mkdir(directory, { mode: 448 });
339303
+ } catch (error) {
339304
+ if (!isAlreadyExists$1(error)) throw error;
339305
+ const raced = await io.lstat(directory);
339306
+ if (raced.isSymbolicLink() || !raced.isDirectory()) throw new Error(`mistake outbox path is not a real directory: ${directory}`, { cause: error });
339307
+ }
339308
+ await io.syncDirectory(dirname(directory));
339309
+ }
339310
+ }
339311
+ async function durableExclusiveWrite(path, contents) {
339312
+ const directory = dirname(path);
339313
+ const temporaryPath = join(directory, `.${basename(path)}.${process.pid}.${randomUUID()}.tmp`);
339314
+ let handle;
339315
+ let failure;
339316
+ try {
339317
+ handle = await open(temporaryPath, "wx", 384);
339318
+ await handle.writeFile(contents, "utf8");
339319
+ await handle.sync();
339320
+ await handle.close();
339321
+ handle = void 0;
339322
+ await link(temporaryPath, path);
339323
+ await syncDirectory(directory);
339324
+ } catch (error) {
339325
+ failure = error;
339326
+ }
339327
+ if (handle !== void 0) try {
339328
+ await handle.close();
339329
+ } catch (error) {
339330
+ failure ??= error;
339331
+ }
339332
+ try {
339333
+ await unlink(temporaryPath);
339334
+ await syncDirectory(directory);
339335
+ } catch (error) {
339336
+ if (!isNotFound$2(error)) failure ??= error;
339337
+ }
339338
+ if (failure !== void 0) throw failure;
339339
+ }
339340
+ async function syncDirectory(path) {
339341
+ let handle;
339342
+ try {
339343
+ handle = await open(path, "r");
339344
+ await handle.sync();
339345
+ } catch (error) {
339346
+ if (process.platform !== "win32" || !isUnsupportedDirectorySync(error)) throw error;
339347
+ } finally {
339348
+ await handle?.close().catch(() => void 0);
339349
+ }
339350
+ }
339351
+ function isNormalizedSourceId(value) {
339352
+ try {
339353
+ return normalizeMistakeSourceId(value) === value;
339354
+ } catch {
339355
+ return false;
339356
+ }
339357
+ }
339358
+ function isIsoTimestamp(value) {
339359
+ try {
339360
+ assertIsoTimestamp$2(value, "timestamp");
339361
+ return true;
339362
+ } catch {
339363
+ return false;
339364
+ }
339365
+ }
339366
+ function isNullableEntryCount(value) {
339367
+ return value === null || Number.isSafeInteger(value) && value >= 0;
339368
+ }
339369
+ function assertInventoryInvariants(bestandsstatus, aktualitaetsstatus, declaredEntryCount, lastRawObservedAt, capturedAt) {
339370
+ if (bestandsstatus === "counted" && declaredEntryCount === null) throw new Error("counted inventory requires a declared entry count");
339371
+ if (bestandsstatus !== "counted" && declaredEntryCount !== null) throw new Error(`${bestandsstatus} inventory must not declare an entry count`);
339372
+ if (aktualitaetsstatus === "fresh" && lastRawObservedAt === null) throw new Error("fresh inventory requires a last raw observed timestamp");
339373
+ if (capturedAt !== void 0 && lastRawObservedAt !== null && Date.parse(lastRawObservedAt) > Date.parse(capturedAt)) throw new Error("last raw observed timestamp must not be later than captured at");
339374
+ }
339375
+ function isRecord$12(value) {
339376
+ return typeof value === "object" && value !== null && !Array.isArray(value);
339377
+ }
339378
+ function hasOnlyKeys(value, allowedKeys) {
339379
+ return Object.keys(value).every((key) => allowedKeys.includes(key));
339380
+ }
339381
+ function isValidRecordId(value) {
339382
+ const length = [...value].length;
339383
+ return length >= 1 && length <= 200 && value.normalize("NFKC").trim() === value && !hasControlCharacter(value);
339384
+ }
339385
+ function isSafeRawLocator(value) {
339386
+ const length = [...value].length;
339387
+ return length >= 1 && length <= 1e3 && !hasControlCharacter(value);
339388
+ }
339389
+ function hasControlCharacter(value) {
339390
+ return [...value].some((character) => {
339391
+ const codePoint = character.codePointAt(0);
339392
+ return codePoint !== void 0 && (codePoint < 32 || codePoint === 127);
339393
+ });
339394
+ }
339395
+ function isMistakeInflowStatus(value) {
339396
+ if (typeof value !== "object" || value === null) return false;
339397
+ const item = value;
339398
+ if (item["version"] !== 1 || item["scope"] !== "lower_bound" || typeof item["generated_at"] !== "string" || !isIsoTimestamp(item["generated_at"]) || !isNonNegativeInteger(item["stale_after_seconds"]) || !Array.isArray(item["sources"])) return false;
339399
+ const sourceIds = /* @__PURE__ */ new Set();
339400
+ for (const source of item["sources"]) {
339401
+ if (!isMistakeSourceStatus(source)) return false;
339402
+ const sourceId = source["source_id"];
339403
+ if (sourceIds.has(sourceId)) return false;
339404
+ sourceIds.add(sourceId);
339405
+ }
339406
+ return true;
339407
+ }
339408
+ function isMistakeSourceStatus(value) {
339409
+ if (typeof value !== "object" || value === null) return false;
339410
+ const item = value;
339411
+ const recordTypes = item["record_types"];
339412
+ const watchdogReasons = item["watchdog_reasons"];
339413
+ if (!(typeof item["source_id"] === "string" && isNormalizedSourceId(item["source_id"]) && typeof item["raw_agent_id"] === "string" && item["raw_agent_id"].trim() !== "" && typeof item["canonical_agent_id"] === "string" && isNormalizedSourceId(item["canonical_agent_id"]) && typeof item["source_form"] === "string" && MISTAKE_SOURCE_FORMS.includes(item["source_form"]) && Array.isArray(recordTypes) && recordTypes.length > 0 && new Set(recordTypes).size === recordTypes.length && recordTypes.every((type) => typeof type === "string" && MISTAKE_RECORD_TYPES.includes(type)) && typeof item["bestandsstatus"] === "string" && MISTAKE_INVENTORY_STATUSES.includes(item["bestandsstatus"]) && typeof item["aktualitaetsstatus"] === "string" && MISTAKE_ACTUALITY_STATUSES.includes(item["aktualitaetsstatus"]) && isNullableEntryCount(item["declared_entry_count"]) && isNullableIsoTimestamp(item["last_raw_observed_at"]) && isNullableIsoTimestamp(item["last_attempt_at"]) && isNullableIsoTimestamp(item["last_success_at"]) && isNonNegativeInteger(item["successful_observations"]) && isNonNegativeInteger(item["active_observations"]) && isNonNegativeInteger(item["rejected_attempts"]) && isNonNegativeInteger(item["seconds_since_success_or_monitor_start"]) && typeof item["watchdog"] === "string" && MISTAKE_WATCHDOG_STATUSES.includes(item["watchdog"]) && Array.isArray(watchdogReasons) && watchdogReasons.every((reason) => typeof reason === "string" && reason.trim() !== ""))) return false;
339414
+ try {
339415
+ assertInventoryInvariants(item["bestandsstatus"], item["aktualitaetsstatus"], item["declared_entry_count"], item["last_raw_observed_at"]);
339416
+ return true;
339417
+ } catch {
339418
+ return false;
339419
+ }
339420
+ }
339421
+ function isNullableIsoTimestamp(value) {
339422
+ return value === null || typeof value === "string" && isIsoTimestamp(value);
339423
+ }
339424
+ function isNonNegativeInteger(value) {
339425
+ return Number.isSafeInteger(value) && value >= 0;
339426
+ }
339427
+ function isAlreadyExists$1(error) {
339428
+ return typeof error === "object" && error !== null && error.code === "EEXIST";
339429
+ }
339430
+ function isNotFound$2(error) {
339431
+ return typeof error === "object" && error !== null && error.code === "ENOENT";
339432
+ }
339433
+ function isUnsupportedDirectorySync(error) {
339434
+ if (typeof error !== "object" || error === null) return false;
339435
+ return [
339436
+ "EACCES",
339437
+ "EBADF",
339438
+ "EINVAL",
339439
+ "EPERM"
339440
+ ].includes(error.code ?? "");
339441
+ }
339442
+ function errorMessage$6(error) {
339443
+ return error instanceof Error ? error.message : String(error);
339444
+ }
339445
+ //#endregion
339446
+ //#region src/mistakes/source-sync.ts
339447
+ const DIRECTORY_SNAPSHOT_FORMAT = "blun.mistakes.directory-snapshot.v1";
339448
+ const TOKEN_ENV_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
339449
+ const UUID_RE = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i;
339450
+ const TRANSPORT_STALE_AFTER_SECONDS = 1440 * 60;
339451
+ const DEFAULT_DEPS$1 = {
339452
+ drain: (options) => drainMistakeOutbox(options),
339453
+ upload: (input, options) => uploadMistakeObservation(input, options),
339454
+ now: () => /* @__PURE__ */ new Date()
339455
+ };
339456
+ async function loadMistakeSourceSyncConfig(configPath) {
339457
+ const absolutePath = resolve(configPath);
339458
+ const fileStat = await lstat(absolutePath);
339459
+ if (fileStat.isSymbolicLink() || !fileStat.isFile()) throw new Error("mistake source config must be a regular, non-symlink file");
339460
+ let value;
339461
+ try {
339462
+ value = JSON.parse(await readFile(absolutePath, "utf8"));
339463
+ } catch (error) {
339464
+ if (error instanceof SyntaxError) throw new Error("mistake source config is not valid JSON", { cause: error });
339465
+ throw error;
339466
+ }
339467
+ return parseConfig(value, dirname(absolutePath));
339468
+ }
339469
+ async function buildSourceSnapshot(adapter) {
339470
+ return adapter.type === "file" ? buildFileSnapshot(adapter.path) : buildDirectorySnapshot(adapter.path, {
339471
+ include: adapter.include,
339472
+ recursive: adapter.recursive
339473
+ });
339474
+ }
339475
+ async function buildDirectorySnapshot(path, options = {}) {
339476
+ const root = resolve(path);
339477
+ const rootStat = await lstat(root);
339478
+ if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) throw new Error(`directory source must be a regular, non-symlink directory: ${root}`);
339479
+ const canonicalRoot = await realpath(root);
339480
+ const include = options.include === void 0 ? void 0 : validateIncludePatterns(options.include, "directory include");
339481
+ const recursive = options.recursive ?? true;
339482
+ const files = await readDirectoryFiles(root, canonicalRoot, recursive, include === void 0 ? void 0 : compileIncludePatterns(include));
339483
+ if (include !== void 0 && files.length === 0) throw new Error(`directory include matched no regular files: ${include.join(", ")}`);
339484
+ const orderedFiles = files.toSorted((left, right) => Buffer.compare(Buffer.from(left.path), Buffer.from(right.path)));
339485
+ const totalBytes = orderedFiles.reduce((sum, file) => sum + file.bytes, 0);
339486
+ const latestMtimeMs = orderedFiles.reduce((latest, file) => latest === null || file.mtimeMs > latest ? file.mtimeMs : latest, null);
339487
+ const document = {
339488
+ format: DIRECTORY_SNAPSHOT_FORMAT,
339489
+ version: 1,
339490
+ file_count: orderedFiles.length,
339491
+ total_bytes: totalBytes,
339492
+ latest_mtime: latestMtimeMs === null ? null : new Date(Math.trunc(latestMtimeMs)).toISOString(),
339493
+ selection: {
339494
+ include: include === void 0 ? null : include.toSorted(compareUtf8),
339495
+ recursive
339496
+ },
339497
+ files: orderedFiles.map(({ mtimeMs: _mtimeMs, ...file }) => file)
339498
+ };
339499
+ const payload = Buffer.from(`${JSON.stringify(document)}\n`, "utf8");
339500
+ assertSnapshotSize(payload);
339501
+ return snapshotResult("directory", "directory-snapshot.json", payload, orderedFiles.length, totalBytes, document.latest_mtime);
339502
+ }
339503
+ async function syncMistakeSources(options, deps = DEFAULT_DEPS$1) {
339504
+ const configPath = resolve(options.configPath);
339505
+ const config = await loadMistakeSourceSyncConfig(configPath);
339506
+ const baseOutbox = resolve(options.outboxDir ?? config.outbox ?? join(dirname(configPath), ".mistake-inflow-outbox"));
339507
+ const startedAt = deps.now().toISOString();
339508
+ const results = [];
339509
+ for (const source of config.sources.toSorted((left, right) => compareUtf8(left.sourceId, right.sourceId))) {
339510
+ if (source.adapter.type === "unsupported") {
339511
+ results.push({
339512
+ source_id: source.sourceId,
339513
+ agent_id: source.agentId,
339514
+ adapter: "unsupported",
339515
+ bestandsstatus: source.bestandsstatus,
339516
+ aktualitaetsstatus: source.aktualitaetsstatus,
339517
+ status: "blocked",
339518
+ retry: null,
339519
+ entry_count: entryCountResult(source),
339520
+ snapshot: null,
339521
+ reason: source.adapter.reason
339522
+ });
339523
+ continue;
339524
+ }
339525
+ const sourceOutbox = join(baseOutbox, "sources", source.sourceId);
339526
+ let retry = null;
339527
+ try {
339528
+ await assertOutboxOutsideSource(source.adapter, sourceOutbox);
339529
+ const endpoint = options.endpoint ?? source.endpoint ?? config.endpoint;
339530
+ if (!endpoint) throw new Error("no endpoint configured");
339531
+ const tokenEnv = source.tokenEnv;
339532
+ if (!tokenEnv) throw new Error("supported source has no token_env");
339533
+ const token = options.env[tokenEnv];
339534
+ if (!token || token.trim() === "") throw new Error(`missing bearer token in ${tokenEnv}`);
339535
+ const connection = {
339536
+ endpoint,
339537
+ token,
339538
+ outboxDir: sourceOutbox
339539
+ };
339540
+ retry = await deps.drain(connection);
339541
+ if (retry.failed.length > 0) throw new Error(`retry failed for ${retry.failed.length} queued observation(s)`);
339542
+ const snapshot = await buildSourceSnapshot(source.adapter);
339543
+ assertEntryCountBasis(source, snapshot);
339544
+ const declarations = source.declarationsPath === void 0 ? void 0 : await readExplicitDeclarations(source.declarationsPath, source.sourceId, source.recordTypes);
339545
+ const capturedAt = deps.now().toISOString();
339546
+ const input = observationInput(source, snapshot, capturedAt, declarations);
339547
+ const existing = await findVerifiedSnapshotReceipt(source, snapshot, input, sourceOutbox);
339548
+ const heartbeatIntervalSeconds = source.heartbeatIntervalSeconds ?? config.heartbeatIntervalSeconds;
339549
+ if (existing !== null && receiptIsWithinHeartbeat(existing, capturedAt, heartbeatIntervalSeconds)) {
339550
+ results.push(resultForSnapshot(source, snapshot, "unchanged", retry, existing));
339551
+ continue;
339552
+ }
339553
+ const materializedPath = await materializeSnapshot(snapshot, sourceOutbox);
339554
+ const receipt = await deps.upload({
339555
+ ...input,
339556
+ filePath: materializedPath
339557
+ }, connection);
339558
+ assertReceiptIdentity(receipt, source, snapshot, input.declaredEntryCount);
339559
+ results.push(resultForSnapshot(source, snapshot, existing === null ? "uploaded" : "heartbeat", retry, receipt, existing ?? void 0));
339560
+ } catch (error) {
339561
+ results.push({
339562
+ source_id: source.sourceId,
339563
+ agent_id: source.agentId,
339564
+ adapter: source.adapter.type,
339565
+ bestandsstatus: source.bestandsstatus,
339566
+ aktualitaetsstatus: source.aktualitaetsstatus,
339567
+ status: "failed",
339568
+ retry: retry === null ? null : {
339569
+ delivered: retry.delivered.length,
339570
+ failed: retry.failed.length
339571
+ },
339572
+ entry_count: entryCountResult(source, false),
339573
+ snapshot: null,
339574
+ reason: errorMessage$5(error)
339575
+ });
339576
+ }
339577
+ }
339578
+ return {
339579
+ version: 1,
339580
+ config_path: configPath,
339581
+ started_at: startedAt,
339582
+ finished_at: deps.now().toISOString(),
339583
+ results
339584
+ };
339585
+ }
339586
+ async function watchMistakeSources(options, deps = DEFAULT_DEPS$1) {
339587
+ if (!Number.isSafeInteger(options.intervalMs) || options.intervalMs < 1e3) throw new Error("watch interval must be at least 1000 milliseconds");
339588
+ while (!options.signal?.aborted) {
339589
+ await options.onRun(await syncMistakeSources(options, deps));
339590
+ await waitForInterval(options.intervalMs, options.signal);
339591
+ }
339592
+ }
339593
+ function parseConfig(value, configDir) {
339594
+ const root = objectValue(value, "config");
339595
+ exactKeys(root, [
339596
+ "version",
339597
+ "endpoint",
339598
+ "outbox",
339599
+ "heartbeat_interval_seconds",
339600
+ "sources"
339601
+ ], "config");
339602
+ if (root["version"] !== 1) throw new Error("mistake source config version must be 1");
339603
+ const endpoint = optionalNonEmptyString$1(root["endpoint"], "config.endpoint");
339604
+ const outboxValue = optionalNonEmptyString$1(root["outbox"], "config.outbox");
339605
+ const heartbeatIntervalSeconds = heartbeatInterval(root["heartbeat_interval_seconds"], "config.heartbeat_interval_seconds") ?? 43200;
339606
+ const sourcesValue = root["sources"];
339607
+ if (!Array.isArray(sourcesValue) || sourcesValue.length === 0) throw new Error("config.sources must be a non-empty array");
339608
+ const sources = sourcesValue.map((source, index) => parseSource(source, index, configDir));
339609
+ const sourceIds = sources.map((source) => source.sourceId);
339610
+ if (new Set(sourceIds).size !== sourceIds.length) throw new Error("config contains duplicate normalized source ids");
339611
+ const tokenEnvs = sources.flatMap((source) => source.tokenEnv === void 0 ? [] : [source.tokenEnv]);
339612
+ if (new Set(tokenEnvs).size !== tokenEnvs.length) throw new Error("each supported source must use its own token_env");
339613
+ return {
339614
+ version: 1,
339615
+ endpoint,
339616
+ outbox: outboxValue === void 0 ? void 0 : configuredPath(outboxValue, configDir, "config.outbox"),
339617
+ heartbeatIntervalSeconds,
339618
+ sources
339619
+ };
339620
+ }
339621
+ function parseSource(value, index, configDir) {
339622
+ const label = `config.sources[${index}]`;
339623
+ const source = objectValue(value, label);
339624
+ exactKeys(source, [
339625
+ "source_id",
339626
+ "agent_id",
339627
+ "endpoint",
339628
+ "token_env",
339629
+ "heartbeat_interval_seconds",
339630
+ "source_form",
339631
+ "record_types",
339632
+ "bestandsstatus",
339633
+ "aktualitaetsstatus",
339634
+ "declared_entry_count",
339635
+ "entry_count_basis",
339636
+ "declarations_path",
339637
+ "adapter"
339638
+ ], label);
339639
+ const sourceId = normalizeMistakeSourceId(nonEmptyString(source["source_id"], `${label}.source_id`));
339640
+ const agentId = normalizeMistakeSourceId(nonEmptyString(source["agent_id"], `${label}.agent_id`));
339641
+ const sourceForm = enumValue(source["source_form"], MISTAKE_SOURCE_FORMS, `${label}.source_form`);
339642
+ const recordTypes = enumArray(source["record_types"], MISTAKE_RECORD_TYPES, `${label}.record_types`);
339643
+ const bestandsstatus = enumValue(source["bestandsstatus"], MISTAKE_INVENTORY_STATUSES, `${label}.bestandsstatus`);
339644
+ const aktualitaetsstatus = enumValue(source["aktualitaetsstatus"], MISTAKE_ACTUALITY_STATUSES, `${label}.aktualitaetsstatus`);
339645
+ const endpoint = optionalNonEmptyString$1(source["endpoint"], `${label}.endpoint`);
339646
+ const tokenEnv = optionalNonEmptyString$1(source["token_env"], `${label}.token_env`);
339647
+ const heartbeatIntervalSeconds = heartbeatInterval(source["heartbeat_interval_seconds"], `${label}.heartbeat_interval_seconds`);
339648
+ const declaredEntryCount = optionalCount(source["declared_entry_count"], `${label}.declared_entry_count`);
339649
+ const entryCountBasis = optionalEnumValue(source["entry_count_basis"], ["files", "declared"], `${label}.entry_count_basis`);
339650
+ const declarationsValue = optionalNonEmptyString$1(source["declarations_path"], `${label}.declarations_path`);
339651
+ const declarationsPath = declarationsValue === void 0 ? void 0 : configuredPath(declarationsValue, configDir, `${label}.declarations_path`);
339652
+ const adapter = parseAdapter(source["adapter"], label, configDir);
339653
+ if (bestandsstatus === "counted" && declaredEntryCount === void 0) throw new Error(`${label}.declared_entry_count is required when bestandsstatus is counted`);
339654
+ if (bestandsstatus === "counted" && entryCountBasis === void 0) throw new Error(`${label}.entry_count_basis is required when bestandsstatus is counted`);
339655
+ if (bestandsstatus !== "counted" && declaredEntryCount !== void 0) throw new Error(`${label}.declared_entry_count is forbidden unless bestandsstatus is counted`);
339656
+ if (bestandsstatus !== "counted" && entryCountBasis !== void 0) throw new Error(`${label}.entry_count_basis is forbidden unless bestandsstatus is counted`);
339657
+ if (adapter.type === "unsupported") {
339658
+ if (bestandsstatus !== "unverified" || aktualitaetsstatus !== "unverified") throw new Error(`${label} unsupported adapters must use unverified inventory and actuality statuses`);
339659
+ if (tokenEnv !== void 0 || endpoint !== void 0 || heartbeatIntervalSeconds !== void 0 || declarationsPath !== void 0) throw new Error(`${label} unsupported adapters must not declare endpoint, token_env, heartbeat_interval_seconds, or declarations_path`);
339660
+ } else if (tokenEnv === void 0 || !TOKEN_ENV_RE.test(tokenEnv)) throw new Error(`${label}.token_env must name a dedicated environment variable`);
339661
+ return {
339662
+ sourceId,
339663
+ agentId,
339664
+ endpoint,
339665
+ tokenEnv,
339666
+ heartbeatIntervalSeconds,
339667
+ sourceForm,
339668
+ recordTypes,
339669
+ bestandsstatus,
339670
+ aktualitaetsstatus,
339671
+ declaredEntryCount,
339672
+ entryCountBasis,
339673
+ declarationsPath,
339674
+ adapter
339675
+ };
339676
+ }
339677
+ function parseAdapter(value, sourceLabel, configDir) {
339678
+ const label = `${sourceLabel}.adapter`;
339679
+ const adapter = objectValue(value, label);
339680
+ const type = adapter["type"];
339681
+ if (type === "file" || type === "directory") {
339682
+ if (type === "file") {
339683
+ exactKeys(adapter, ["type", "path"], label);
339684
+ return {
339685
+ type,
339686
+ path: configuredPath(nonEmptyString(adapter["path"], `${label}.path`), configDir, `${label}.path`)
339687
+ };
339688
+ }
339689
+ exactKeys(adapter, [
339690
+ "type",
339691
+ "path",
339692
+ "include",
339693
+ "recursive"
339694
+ ], label);
339695
+ const include = adapter["include"] === void 0 ? void 0 : validateIncludePatterns(adapter["include"], `${label}.include`);
339696
+ const recursive = adapter["recursive"] === void 0 ? true : booleanValue(adapter["recursive"], `${label}.recursive`);
339697
+ return {
339698
+ type,
339699
+ path: configuredPath(nonEmptyString(adapter["path"], `${label}.path`), configDir, `${label}.path`),
339700
+ include,
339701
+ recursive
339702
+ };
339703
+ }
339704
+ if (type === "unsupported") {
339705
+ exactKeys(adapter, [
339706
+ "type",
339707
+ "kind",
339708
+ "reason"
339709
+ ], label);
339710
+ return {
339711
+ type,
339712
+ kind: nonEmptyString(adapter["kind"], `${label}.kind`),
339713
+ reason: nonEmptyString(adapter["reason"], `${label}.reason`)
339714
+ };
339715
+ }
339716
+ throw new Error(`${label}.type must be file, directory, or unsupported`);
339717
+ }
339718
+ async function buildFileSnapshot(path) {
339719
+ const absolutePath = resolve(path);
339720
+ const before = await lstat(absolutePath);
339721
+ if (before.isSymbolicLink() || !before.isFile()) throw new Error(`file source must be a regular, non-symlink file: ${absolutePath}`);
339722
+ const handle = await openWithoutFollowing(absolutePath);
339723
+ let payload;
339724
+ try {
339725
+ const opened = await handle.stat();
339726
+ if (!opened.isFile()) throw new Error(`file source changed while reading: ${absolutePath}`);
339727
+ if (before.size !== opened.size || before.mtimeMs !== opened.mtimeMs) throw new Error(`file source changed while opening: ${absolutePath}`);
339728
+ payload = await handle.readFile();
339729
+ const after = await handle.stat();
339730
+ if (opened.size !== after.size || opened.mtimeMs !== after.mtimeMs) throw new Error(`file source changed while reading: ${absolutePath}`);
339731
+ } finally {
339732
+ await handle.close();
339733
+ }
339734
+ assertSnapshotSize(payload);
339735
+ return snapshotResult("file", basename(absolutePath), payload, 1, payload.byteLength, new Date(Math.trunc(before.mtimeMs)).toISOString());
339736
+ }
339737
+ async function readDirectoryFiles(root, canonicalRoot, recursive, matches) {
339738
+ const files = [];
339739
+ async function visit(directory) {
339740
+ const entries = (await readdir(directory, { withFileTypes: true })).toSorted((left, right) => Buffer.compare(Buffer.from(left.name), Buffer.from(right.name)));
339741
+ for (const entry of entries) {
339742
+ const absolutePath = join(directory, entry.name);
339743
+ const entryStat = await lstat(absolutePath);
339744
+ if (entry.isSymbolicLink() || entryStat.isSymbolicLink()) throw new Error(`directory source contains a symlink: ${absolutePath}`);
339745
+ const relativePath = canonicalRelativePath(root, absolutePath);
339746
+ assertContained(canonicalRoot, await realpath(absolutePath), absolutePath);
339747
+ if (entryStat.isDirectory()) {
339748
+ if (recursive) await visit(absolutePath);
339749
+ continue;
339750
+ }
339751
+ if (!entryStat.isFile()) throw new Error(`directory source contains a non-regular entry: ${absolutePath}`);
339752
+ if (matches !== void 0 && !matches(relativePath)) continue;
339753
+ const handle = await openWithoutFollowing(absolutePath);
339754
+ let content;
339755
+ try {
339756
+ const before = await handle.stat();
339757
+ if (!before.isFile()) throw new Error(`directory source entry changed while reading: ${absolutePath}`);
339758
+ if (entryStat.size !== before.size || entryStat.mtimeMs !== before.mtimeMs) throw new Error(`directory source entry changed while opening: ${absolutePath}`);
339759
+ content = await handle.readFile();
339760
+ const after = await handle.stat();
339761
+ if (before.size !== after.size || before.mtimeMs !== after.mtimeMs) throw new Error(`directory source entry changed while reading: ${absolutePath}`);
339762
+ } finally {
339763
+ await handle.close();
339764
+ }
339765
+ files.push({
339766
+ path: relativePath,
339767
+ bytes: content.byteLength,
339768
+ sha256: sha256$3(content),
339769
+ mtime: new Date(Math.trunc(entryStat.mtimeMs)).toISOString(),
339770
+ content_base64: content.toString("base64"),
339771
+ mtimeMs: entryStat.mtimeMs
339772
+ });
339773
+ }
339774
+ }
339775
+ await visit(root);
339776
+ const secondScan = await scanDirectoryMetadata(root, canonicalRoot, recursive, matches);
339777
+ const firstScan = files.map((file) => ({
339778
+ path: file.path,
339779
+ bytes: file.bytes,
339780
+ mtimeMs: file.mtimeMs
339781
+ })).toSorted(compareMetadata);
339782
+ if (JSON.stringify(firstScan) !== JSON.stringify(secondScan)) throw new Error("directory source changed while snapshotting");
339783
+ return files;
339784
+ }
339785
+ async function scanDirectoryMetadata(root, canonicalRoot, recursive, matches) {
339786
+ const files = [];
339787
+ async function visit(directory) {
339788
+ const entries = (await readdir(directory, { withFileTypes: true })).toSorted((left, right) => Buffer.compare(Buffer.from(left.name), Buffer.from(right.name)));
339789
+ for (const entry of entries) {
339790
+ const absolutePath = join(directory, entry.name);
339791
+ const entryStat = await lstat(absolutePath);
339792
+ if (entry.isSymbolicLink() || entryStat.isSymbolicLink()) throw new Error(`directory source contains a symlink: ${absolutePath}`);
339793
+ const relativePath = canonicalRelativePath(root, absolutePath);
339794
+ assertContained(canonicalRoot, await realpath(absolutePath), absolutePath);
339795
+ if (entryStat.isDirectory()) {
339796
+ if (recursive) await visit(absolutePath);
339797
+ continue;
339798
+ }
339799
+ if (!entryStat.isFile()) throw new Error(`directory source contains a non-regular entry: ${absolutePath}`);
339800
+ if (matches === void 0 || matches(relativePath)) files.push({
339801
+ path: relativePath,
339802
+ bytes: entryStat.size,
339803
+ mtimeMs: entryStat.mtimeMs
339804
+ });
339805
+ }
339806
+ }
339807
+ await visit(root);
339808
+ return files.toSorted(compareMetadata);
339809
+ }
339810
+ function compareMetadata(left, right) {
339811
+ return compareUtf8(left.path, right.path) || left.bytes - right.bytes || left.mtimeMs - right.mtimeMs;
339812
+ }
339813
+ async function openWithoutFollowing(path) {
339814
+ const noFollow = typeof constants.O_NOFOLLOW === "number" ? constants.O_NOFOLLOW : 0;
339815
+ try {
339816
+ return await open(path, constants.O_RDONLY | noFollow);
339817
+ } catch (error) {
339818
+ if (isSymlinkOpenError(error)) throw new Error(`refusing to follow source symlink: ${path}`, { cause: error });
339819
+ throw error;
339820
+ }
339821
+ }
339822
+ function canonicalRelativePath(root, path) {
339823
+ const value = relative(root, path);
339824
+ const segments = value.split(sep);
339825
+ if (value === "" || isAbsolute(value) || segments.some((segment) => segment === "" || segment === "." || segment === "..")) throw new Error(`source entry escapes its configured directory: ${path}`);
339826
+ const canonical = segments.join("/");
339827
+ if (canonical.startsWith("/") || canonical.includes("/../") || canonical.includes("\\")) throw new Error(`source entry has an unsafe relative path: ${path}`);
339828
+ return canonical;
339829
+ }
339830
+ function assertContained(root, candidate, originalPath) {
339831
+ const value = relative(root, candidate);
339832
+ if (value === ".." || value.startsWith(`..${sep}`) || isAbsolute(value)) throw new Error(`source entry resolves outside its configured directory: ${originalPath}`);
339833
+ }
339834
+ function snapshotResult(adapterType, originalName, payload, fileCount, totalBytes, latestMtime) {
339835
+ return {
339836
+ adapterType,
339837
+ originalName,
339838
+ payload,
339839
+ rawBytes: payload.byteLength,
339840
+ rawSha256: sha256$3(payload),
339841
+ fileCount,
339842
+ totalBytes,
339843
+ latestMtime
339844
+ };
339845
+ }
339846
+ function observationInput(source, snapshot, capturedAt, declarations) {
339847
+ return {
339848
+ sourceId: source.sourceId,
339849
+ sourceForm: source.sourceForm,
339850
+ recordTypes: source.recordTypes,
339851
+ bestandsstatus: source.bestandsstatus,
339852
+ aktualitaetsstatus: source.aktualitaetsstatus,
339853
+ declaredEntryCount: source.declaredEntryCount,
339854
+ lastRawObservedAt: snapshot.latestMtime ?? void 0,
339855
+ capturedAt,
339856
+ declarations
339857
+ };
339858
+ }
339859
+ async function readExplicitDeclarations(path, sourceId, recordTypes) {
339860
+ const fileStat = await lstat(path);
339861
+ if (fileStat.isSymbolicLink() || !fileStat.isFile()) throw new Error(`declarations_path must be a regular, non-symlink file: ${path}`);
339862
+ const handle = await openWithoutFollowing(path);
339863
+ let text;
339864
+ try {
339865
+ const opened = await handle.stat();
339866
+ if (fileStat.size !== opened.size || fileStat.mtimeMs !== opened.mtimeMs) throw new Error(`declarations_path changed while opening: ${path}`);
339867
+ text = await handle.readFile("utf8");
339868
+ const after = await handle.stat();
339869
+ if (opened.size !== after.size || opened.mtimeMs !== after.mtimeMs) throw new Error(`declarations_path changed while reading: ${path}`);
339870
+ } finally {
339871
+ await handle.close();
339872
+ }
339873
+ let value;
339874
+ try {
339875
+ value = JSON.parse(text);
339876
+ } catch (error) {
339877
+ throw new Error(`declarations_path is not valid JSON: ${path}`, { cause: error });
339878
+ }
339879
+ return parseMistakeRecordDeclarations(value, sourceId, recordTypes);
339880
+ }
339881
+ async function materializeSnapshot(snapshot, outboxDir) {
339882
+ const directory = join(outboxDir, "snapshots", snapshot.rawSha256);
339883
+ await mkdir(directory, {
339884
+ recursive: true,
339885
+ mode: 448
339886
+ });
339887
+ const path = join(directory, snapshot.originalName);
339888
+ try {
339889
+ await writeFile(path, snapshot.payload, {
339890
+ flag: "wx",
339891
+ mode: 384
339892
+ });
339893
+ } catch (error) {
339894
+ if (!isAlreadyExists(error)) throw error;
339895
+ if (!(await readFile(path)).equals(snapshot.payload)) throw new Error(`snapshot cache conflict for ${snapshot.rawSha256}`, { cause: error });
339896
+ }
339897
+ return path;
339898
+ }
339899
+ async function findVerifiedSnapshotReceipt(source, snapshot, input, outboxDir) {
339900
+ const eventsDir = join(outboxDir, "events");
339901
+ let names;
339902
+ try {
339903
+ names = (await readdir(eventsDir)).filter((name) => name.endsWith(".json")).toSorted();
339904
+ } catch (error) {
339905
+ if (isNotFound$1(error)) return null;
339906
+ throw error;
339907
+ }
339908
+ let newest = null;
339909
+ for (const name of names) {
339910
+ const event = await readJson(join(eventsDir, name));
339911
+ if (!eventMatchesSnapshot(event, source, snapshot, input)) continue;
339912
+ const clientEventId = event.client_event_id;
339913
+ const paths = [join(outboxDir, "receipts", `${clientEventId}.json`)];
339914
+ try {
339915
+ const receiptNames = (await readdir(join(outboxDir, "receipts", clientEventId))).filter((receiptName) => receiptName.endsWith(".json")).toSorted();
339916
+ paths.push(...receiptNames.map((receiptName) => join(outboxDir, "receipts", clientEventId, receiptName)));
339917
+ } catch (error) {
339918
+ if (!isNotFound$1(error)) throw error;
339919
+ }
339920
+ for (const path of paths) {
339921
+ const receipt = await readJson(path);
339922
+ if (receiptMatchesSnapshot(receipt, source, snapshot, event.inventory.declared_entry_count, event.client_event_id)) {
339923
+ if (newest === null || compareReceiptsByReceivedAt(receipt, newest) > 0) newest = receipt;
339924
+ }
339925
+ }
339926
+ }
339927
+ return newest;
339928
+ }
339929
+ function compareReceiptsByReceivedAt(left, right) {
339930
+ return Date.parse(left.received_at) - Date.parse(right.received_at) || compareUtf8(left.event_id, right.event_id);
339931
+ }
339932
+ function receiptIsWithinHeartbeat(receipt, nowIso, heartbeatIntervalSeconds) {
339933
+ const ageMilliseconds = Date.parse(nowIso) - Date.parse(receipt.received_at);
339934
+ return ageMilliseconds >= 0 && ageMilliseconds < heartbeatIntervalSeconds * 1e3;
339935
+ }
339936
+ function eventMatchesSnapshot(value, source, snapshot, input) {
339937
+ if (!isObject$3(value)) return false;
339938
+ const inventory = value["inventory"];
339939
+ if (!isObject$3(inventory)) return false;
339940
+ const payloadBase64 = value["payload_base64"];
339941
+ if (typeof payloadBase64 !== "string") return false;
339942
+ const payload = Buffer.from(payloadBase64, "base64");
339943
+ return payload.toString("base64") === payloadBase64 && payload.equals(snapshot.payload) && value["version"] === 1 && value["source_id"] === source.sourceId && value["source_form"] === source.sourceForm && arraysEqual(value["declared_record_types"], source.recordTypes) && value["declared_raw_bytes"] === snapshot.rawBytes && value["declared_raw_sha256"] === snapshot.rawSha256 && sha256$3(payload) === snapshot.rawSha256 && inventory["scope"] === "lower_bound" && inventory["bestandsstatus"] === source.bestandsstatus && inventory["aktualitaetsstatus"] === source.aktualitaetsstatus && inventory["declared_entry_count"] === (input.declaredEntryCount ?? null) && inventory["last_raw_observed_at"] === (input.lastRawObservedAt ?? null) && declarationsEqual(value["declarations"], input.declarations) && typeof value["client_event_id"] === "string" && UUID_RE.test(value["client_event_id"]);
339944
+ }
339945
+ function receiptMatchesSnapshot(value, source, snapshot, declaredEntryCount, expectedClientEventId) {
339946
+ if (!isObject$3(value)) return false;
339947
+ return value["version"] === 1 && value["accepted"] === true && value["source_id"] === source.sourceId && value["canonical_agent_id"] === source.agentId && value["raw_count"] === 1 && value["accepted_count"] === 1 && value["rejected_count"] === 0 && value["raw_bytes"] === snapshot.rawBytes && value["raw_sha256"] === snapshot.rawSha256 && value["declared_entry_count"] === declaredEntryCount && typeof value["event_id"] === "string" && UUID_RE.test(value["event_id"]) && typeof value["client_event_id"] === "string" && UUID_RE.test(value["client_event_id"]) && (expectedClientEventId === void 0 || value["client_event_id"] === expectedClientEventId) && typeof value["received_at"] === "string" && Number.isFinite(Date.parse(value["received_at"]));
339948
+ }
339949
+ function assertReceiptIdentity(receipt, source, snapshot, declaredEntryCount) {
339950
+ if (!receiptMatchesSnapshot(receipt, source, snapshot, declaredEntryCount ?? null, receipt.client_event_id)) throw new Error(`receipt identity mismatch for ${source.sourceId}`);
339951
+ }
339952
+ function resultForSnapshot(source, snapshot, status, retry, receipt, previousReceipt) {
339953
+ return {
339954
+ source_id: source.sourceId,
339955
+ agent_id: source.agentId,
339956
+ adapter: source.adapter.type,
339957
+ bestandsstatus: source.bestandsstatus,
339958
+ aktualitaetsstatus: source.aktualitaetsstatus,
339959
+ status,
339960
+ retry: {
339961
+ delivered: retry.delivered.length,
339962
+ failed: retry.failed.length
339963
+ },
339964
+ entry_count: entryCountResult(source),
339965
+ snapshot: {
339966
+ file_count: snapshot.fileCount,
339967
+ total_bytes: snapshot.totalBytes,
339968
+ raw_bytes: snapshot.rawBytes,
339969
+ raw_sha256: snapshot.rawSha256,
339970
+ latest_mtime: snapshot.latestMtime
339971
+ },
339972
+ receipt,
339973
+ ...previousReceipt === void 0 ? {} : { previous_receipt_received_at: previousReceipt.received_at }
339974
+ };
339975
+ }
339976
+ function configuredPath(value, configDir, label) {
339977
+ if (isAbsolute(value)) return resolve(value);
339978
+ if (value.replaceAll("\\", "/").split("/").some((segment) => segment === "..")) throw new Error(`${label} must not traverse above the config directory; use an absolute path instead`);
339979
+ return resolve(configDir, value);
339980
+ }
339981
+ async function assertOutboxOutsideSource(adapter, outboxDir) {
339982
+ if (adapter.type !== "directory") return;
339983
+ const sourceStat = await lstat(adapter.path);
339984
+ if (sourceStat.isSymbolicLink() || !sourceStat.isDirectory()) throw new Error(`directory source must be a regular, non-symlink directory: ${adapter.path}`);
339985
+ const position = relative(await realpath(adapter.path), await canonicalProspectivePath(outboxDir));
339986
+ if (position === "" || !isAbsolute(position) && position !== ".." && !position.startsWith(`..${sep}`)) throw new Error(`outbox must not be the directory source or be contained by it: ${adapter.path}`);
339987
+ }
339988
+ async function canonicalProspectivePath(path) {
339989
+ let cursor = resolve(path);
339990
+ const tail = [];
339991
+ while (true) try {
339992
+ await lstat(cursor);
339993
+ return resolve(await realpath(cursor), ...tail.toReversed());
339994
+ } catch (error) {
339995
+ if (!isNotFound$1(error)) throw error;
339996
+ const parent = dirname(cursor);
339997
+ if (parent === cursor) throw error;
339998
+ tail.push(basename(cursor));
339999
+ cursor = parent;
340000
+ }
340001
+ }
340002
+ function objectValue(value, label) {
340003
+ if (!isObject$3(value) || Array.isArray(value)) throw new Error(`${label} must be an object`);
340004
+ return value;
340005
+ }
340006
+ function exactKeys(value, keys, label) {
340007
+ const allowed = new Set(keys);
340008
+ const unknown = Object.keys(value).filter((key) => !allowed.has(key));
340009
+ if (unknown.length > 0) throw new Error(`${label} contains unknown fields: ${unknown.join(", ")}`);
340010
+ }
340011
+ function nonEmptyString(value, label) {
340012
+ if (typeof value !== "string" || value.trim() === "") throw new Error(`${label} must be a non-empty string`);
340013
+ return value.trim();
340014
+ }
340015
+ function optionalNonEmptyString$1(value, label) {
340016
+ return value === void 0 ? void 0 : nonEmptyString(value, label);
340017
+ }
340018
+ function optionalCount(value, label) {
340019
+ if (value === void 0) return void 0;
340020
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${label} must be a non-negative integer`);
340021
+ return value;
340022
+ }
340023
+ function heartbeatInterval(value, label) {
340024
+ if (value === void 0) return void 0;
340025
+ if (!Number.isSafeInteger(value) || value < 60 || value >= TRANSPORT_STALE_AFTER_SECONDS) throw new Error(`${label} must be an integer from 60 through 86399 seconds`);
340026
+ return value;
340027
+ }
340028
+ function optionalEnumValue(value, allowed, label) {
340029
+ return value === void 0 ? void 0 : enumValue(value, allowed, label);
340030
+ }
340031
+ function enumValue(value, allowed, label) {
340032
+ if (typeof value !== "string" || !allowed.includes(value)) throw new Error(`${label} must be one of: ${allowed.join(", ")}`);
340033
+ return value;
340034
+ }
340035
+ function enumArray(value, allowed, label) {
340036
+ if (!Array.isArray(value) || value.length === 0 || value.some((item) => typeof item !== "string" || !allowed.includes(item))) throw new Error(`${label} must contain one or more of: ${allowed.join(", ")}`);
340037
+ const unique = [...new Set(value)];
340038
+ if (unique.length !== value.length) throw new Error(`${label} must not contain duplicates`);
340039
+ return unique;
340040
+ }
340041
+ function arraysEqual(value, expected) {
340042
+ return Array.isArray(value) && value.length === expected.length && value.every((item, index) => item === expected[index]);
340043
+ }
340044
+ function booleanValue(value, label) {
340045
+ if (typeof value !== "boolean") throw new Error(`${label} must be a boolean`);
340046
+ return value;
340047
+ }
340048
+ function validateIncludePatterns(value, label) {
340049
+ if (!Array.isArray(value) || value.length === 0) throw new Error(`${label} must be a non-empty array`);
340050
+ const patterns = value.map((candidate, index) => {
340051
+ if (typeof candidate !== "string" || candidate === "" || candidate.startsWith("/") || candidate.includes("\\") || candidate.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) throw new Error(`${label}[${index}] must be a safe relative glob using forward slashes`);
340052
+ if ([...candidate].length > 300 || candidate.includes("\0")) throw new Error(`${label}[${index}] is too long or unsafe`);
340053
+ return candidate;
340054
+ });
340055
+ if (new Set(patterns).size !== patterns.length) throw new Error(`${label} must not contain duplicates`);
340056
+ return patterns;
340057
+ }
340058
+ function compileIncludePatterns(patterns) {
340059
+ const expressions = patterns.map((pattern) => new RegExp(`^${globExpression(pattern)}$`, "u"));
340060
+ return (path) => expressions.some((expression) => expression.test(path));
340061
+ }
340062
+ function globExpression(pattern) {
340063
+ let expression = "";
340064
+ for (let index = 0; index < pattern.length; index += 1) {
340065
+ const character = pattern[index];
340066
+ if (character === "*" && pattern[index + 1] === "*") if (pattern[index + 2] === "/") {
340067
+ expression += "(?:.*/)?";
340068
+ index += 2;
340069
+ } else {
340070
+ expression += ".*";
340071
+ index += 1;
340072
+ }
340073
+ else if (character === "*") expression += "[^/]*";
340074
+ else if (character === "?") expression += "[^/]";
340075
+ else expression += escapeRegex$1(character);
340076
+ }
340077
+ return expression;
340078
+ }
340079
+ function escapeRegex$1(value) {
340080
+ return /[\\^$.*+?()[\]{}|]/.test(value) ? `\\${value}` : value;
340081
+ }
340082
+ function compareUtf8(left, right) {
340083
+ return Buffer.compare(Buffer.from(left), Buffer.from(right));
340084
+ }
340085
+ function assertEntryCountBasis(source, snapshot) {
340086
+ if (source.entryCountBasis === "files" && source.declaredEntryCount !== snapshot.fileCount) throw new Error(`declared entry count ${source.declaredEntryCount} does not match snapshot file count ${snapshot.fileCount}`);
340087
+ }
340088
+ function entryCountResult(source, checked = true) {
340089
+ return {
340090
+ declared: source.declaredEntryCount ?? null,
340091
+ basis: source.entryCountBasis ?? null,
340092
+ verification: source.entryCountBasis === "files" ? checked ? "matched_file_count" : "not_checked" : source.entryCountBasis === "declared" ? "not_derivable_from_raw_files" : "not_declared"
340093
+ };
340094
+ }
340095
+ function declarationsEqual(value, expected) {
340096
+ return expected === void 0 ? value === void 0 : JSON.stringify(value) === JSON.stringify(expected);
340097
+ }
340098
+ async function readJson(path) {
340099
+ try {
340100
+ return JSON.parse(await readFile(path, "utf8"));
340101
+ } catch (error) {
340102
+ if (isNotFound$1(error) || error instanceof SyntaxError) return null;
340103
+ throw error;
340104
+ }
340105
+ }
340106
+ function assertSnapshotSize(payload) {
340107
+ if (payload.byteLength > 20971520) throw new Error(`source snapshot exceeds ${MAX_MISTAKE_SOURCE_BYTES} bytes`);
340108
+ }
340109
+ function sha256$3(value) {
340110
+ return createHash("sha256").update(value).digest("hex");
340111
+ }
340112
+ function isObject$3(value) {
340113
+ return typeof value === "object" && value !== null;
340114
+ }
340115
+ function isAlreadyExists(error) {
340116
+ return isObject$3(error) && error["code"] === "EEXIST";
340117
+ }
340118
+ function isNotFound$1(error) {
340119
+ return isObject$3(error) && error["code"] === "ENOENT";
340120
+ }
340121
+ function isSymlinkOpenError(error) {
340122
+ return isObject$3(error) && ["ELOOP", "EMLINK"].includes(String(error["code"]));
340123
+ }
340124
+ function errorMessage$5(error) {
340125
+ return error instanceof Error ? error.message : String(error);
340126
+ }
340127
+ function waitForInterval(milliseconds, signal) {
340128
+ if (signal?.aborted) return Promise.resolve();
340129
+ let timeout;
340130
+ const delay = new Promise((resolveDelay) => {
340131
+ timeout = setTimeout(resolveDelay, milliseconds);
340132
+ });
340133
+ if (signal === void 0) return delay;
340134
+ let stop;
340135
+ const aborted = new Promise((resolveAbort) => {
340136
+ stop = resolveAbort;
340137
+ signal.addEventListener("abort", stop, { once: true });
340138
+ });
340139
+ return Promise.race([delay, aborted]).finally(() => {
340140
+ if (timeout !== void 0) clearTimeout(timeout);
340141
+ if (stop !== void 0) signal.removeEventListener("abort", stop);
340142
+ });
340143
+ }
340144
+ //#endregion
340145
+ //#region src/cli/sub/mistakes.ts
340146
+ const DEFAULT_TOKEN_ENV = "BLUN_MISTAKE_INFLOW_TOKEN";
340147
+ const DEFAULT_ENDPOINT_ENV = "BLUN_MISTAKE_INFLOW_URL";
340148
+ function registerMistakesCommand(parent, overrides = {}) {
340149
+ const deps = resolveDeps(overrides);
340150
+ const mistakes = parent.command("mistakes").description("Upload and inspect append-only mistake source snapshots.");
340151
+ mistakes.command("upload").description("Queue a source snapshot locally, then upload it.").argument("<path>", "Source file to upload.").requiredOption("--source <id>", "Registered source id.").addOption(choiceOption("--form <form>", "Source form.", MISTAKE_SOURCE_FORMS, "unknown")).option("--record-types <types>", "Comma-separated declared record types.", "unknown").option("--entries <count>", "Declared logical entry count.", parseNonNegativeInteger).addOption(choiceOption("--bestandsstatus <status>", "Inventory status.", MISTAKE_INVENTORY_STATUSES, "unverified")).addOption(choiceOption("--aktualitaetsstatus <status>", "Actuality status.", MISTAKE_ACTUALITY_STATUSES, "unverified")).option("--last-entry-at <timestamp>", "Timestamp of the newest raw entry.").option("--endpoint <url>", `Inflow URL (or ${DEFAULT_ENDPOINT_ENV}).`).option("--token-env <name>", "Environment variable containing the bearer token.", DEFAULT_TOKEN_ENV).option("--outbox <path>", "Local durable outbox directory.").action(async (path, options) => {
340152
+ await run$1(deps, async () => {
340153
+ const connection = connectionOptions(deps, options);
340154
+ const receipt = await uploadMistakeObservation({
340155
+ filePath: resolve(path),
340156
+ sourceId: options.source,
340157
+ sourceForm: options.form,
340158
+ recordTypes: parseRecordTypes(options.recordTypes),
340159
+ bestandsstatus: options.bestandsstatus,
340160
+ aktualitaetsstatus: options.aktualitaetsstatus,
340161
+ declaredEntryCount: options.entries,
340162
+ lastRawObservedAt: options.lastEntryAt,
340163
+ capturedAt: deps.now().toISOString()
340164
+ }, connection);
340165
+ deps.stdout.write(`${JSON.stringify(receipt)}\n`);
340166
+ });
340167
+ });
340168
+ mistakes.command("retry").description("Retry every queued snapshot that has no verified receipt.").option("--endpoint <url>", `Inflow URL (or ${DEFAULT_ENDPOINT_ENV}).`).option("--token-env <name>", "Environment variable containing the bearer token.", DEFAULT_TOKEN_ENV).option("--outbox <path>", "Local durable outbox directory.").action(async (options) => {
340169
+ await run$1(deps, async () => {
340170
+ const result = await drainMistakeOutbox(connectionOptions(deps, options));
340171
+ deps.stdout.write(`${JSON.stringify(result)}\n`);
340172
+ if (result.failed.length > 0) deps.exit(1);
340173
+ });
340174
+ });
340175
+ mistakes.command("sync").description("Retry and upload every configured file or directory source once.").requiredOption("--config <path>", "Source registry JSON file.").option("--endpoint <url>", "Override the configured inflow URL for every supported source.").option("--outbox <path>", "Override the configured local outbox root.").action(async (options) => {
340176
+ await run$1(deps, async () => {
340177
+ const result = await syncMistakeSources({
340178
+ configPath: resolve(options.config),
340179
+ env: deps.env,
340180
+ endpoint: options.endpoint,
340181
+ outboxDir: options.outbox === void 0 ? void 0 : resolve(options.outbox)
340182
+ });
340183
+ deps.stdout.write(`${JSON.stringify(result)}\n`);
340184
+ if (result.results.some((item) => item.status === "failed" || item.status === "blocked")) deps.exit(2);
340185
+ });
340186
+ });
340187
+ mistakes.command("watch").description("Run source sync repeatedly in the foreground until interrupted.").requiredOption("--config <path>", "Source registry JSON file.").option("--endpoint <url>", "Override the configured inflow URL for every supported source.").option("--outbox <path>", "Override the configured local outbox root.").option("--interval <seconds>", "Foreground sync interval in seconds.", parseWatchInterval, 300).action(async (options) => {
340188
+ await run$1(deps, async () => {
340189
+ const controller = new AbortController();
340190
+ const stop = () => controller.abort();
340191
+ process.once("SIGINT", stop);
340192
+ process.once("SIGTERM", stop);
340193
+ try {
340194
+ await watchMistakeSources({
340195
+ configPath: resolve(options.config),
340196
+ env: deps.env,
340197
+ endpoint: options.endpoint,
340198
+ outboxDir: options.outbox === void 0 ? void 0 : resolve(options.outbox),
340199
+ intervalMs: options.interval * 1e3,
340200
+ signal: controller.signal,
340201
+ onRun: (result) => {
340202
+ deps.stdout.write(`${JSON.stringify(result)}\n`);
340203
+ }
340204
+ });
340205
+ } finally {
340206
+ process.off("SIGINT", stop);
340207
+ process.off("SIGTERM", stop);
340208
+ }
340209
+ });
340210
+ });
340211
+ mistakes.command("status").description("Show per-source inventory, actuality, and 24-hour watchdog state.").option("--endpoint <url>", `Inflow URL (or ${DEFAULT_ENDPOINT_ENV}).`).option("--token-env <name>", "Environment variable containing the bearer token.", DEFAULT_TOKEN_ENV).option("--no-fail-on-red", "Return success even when one or more sources are red.").action(async (options) => {
340212
+ await run$1(deps, async () => {
340213
+ const connection = connectionOptions(deps, options);
340214
+ const status = await getMistakeInflowStatus(connection.endpoint, connection.token);
340215
+ deps.stdout.write(`${JSON.stringify(status)}\n`);
340216
+ if (options.failOnRed && hasRedSource(status)) deps.exit(2);
340217
+ });
340218
+ });
340219
+ for (const action of ["remove", "restore"]) mistakes.command(action).description(action === "remove" ? "Append a manual removal marker without deleting raw data." : "Append a restore marker for a previously removed observation.").argument("<eventId>", "Observation event id.").requiredOption("--reason <text>", "Auditable reason for the state change.").option("--endpoint <url>", `Inflow URL (or ${DEFAULT_ENDPOINT_ENV}).`).option("--token-env <name>", "Environment variable containing the bearer token.", DEFAULT_TOKEN_ENV).action(async (eventId, options) => {
340220
+ await run$1(deps, async () => {
340221
+ const connection = connectionOptions(deps, options);
340222
+ const result = await changeMistakeObservationState(action, eventId, options.reason, connection.endpoint, connection.token);
340223
+ deps.stdout.write(`${JSON.stringify(result)}\n`);
340224
+ });
340225
+ });
340226
+ }
340227
+ async function run$1(deps, operation) {
340228
+ try {
340229
+ await operation();
340230
+ } catch (error) {
340231
+ deps.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
340232
+ deps.exit(1);
340233
+ }
340234
+ }
340235
+ function connectionOptions(deps, options) {
340236
+ const endpoint = options.endpoint ?? deps.env[DEFAULT_ENDPOINT_ENV];
340237
+ if (!endpoint) throw new Error(`missing --endpoint or ${DEFAULT_ENDPOINT_ENV}`);
340238
+ const token = deps.env[options.tokenEnv];
340239
+ if (!token || token.trim() === "") throw new Error(`missing bearer token in ${options.tokenEnv}`);
340240
+ return {
340241
+ endpoint,
340242
+ token,
340243
+ outboxDir: resolve(options.outbox ?? join(resolveBlunHome$1(), "mistake", "inflow-outbox"))
340244
+ };
340245
+ }
340246
+ function parseRecordTypes(value) {
340247
+ const values = [...new Set(value.split(",").map((item) => item.trim()).filter(Boolean))];
340248
+ if (values.length === 0 || values.some((value) => !MISTAKE_RECORD_TYPES.includes(value))) throw new Error(`record types must be one or more of: ${MISTAKE_RECORD_TYPES.join(", ")}`);
340249
+ return values;
340250
+ }
340251
+ function parseNonNegativeInteger(value) {
340252
+ if (!/^\d+$/.test(value)) throw new Error("entry count must be a non-negative integer");
340253
+ const parsed = Number(value);
340254
+ if (!Number.isSafeInteger(parsed)) throw new Error("entry count is too large");
340255
+ return parsed;
340256
+ }
340257
+ function parseWatchInterval(value) {
340258
+ if (!/^\d+$/.test(value)) throw new Error("watch interval must be a positive integer");
340259
+ const parsed = Number(value);
340260
+ if (!Number.isSafeInteger(parsed) || parsed < 1) throw new Error("watch interval must be at least one second");
340261
+ return parsed;
340262
+ }
340263
+ function hasRedSource(value) {
340264
+ if (typeof value !== "object" || value === null) return false;
340265
+ const sources = value["sources"];
340266
+ return Array.isArray(sources) && sources.some((source) => typeof source === "object" && source !== null && source["watchdog"] === "red");
340267
+ }
340268
+ function choiceOption(flags, description, choices, defaultValue) {
340269
+ return new Option(flags, description).choices([...choices]).default(defaultValue);
340270
+ }
340271
+ function resolveDeps(overrides) {
340272
+ return {
340273
+ env: overrides.env ?? process.env,
340274
+ now: overrides.now ?? (() => /* @__PURE__ */ new Date()),
340275
+ stdout: overrides.stdout ?? process.stdout,
340276
+ stderr: overrides.stderr ?? process.stderr,
340277
+ exit: overrides.exit ?? ((code) => process.exit(code))
340278
+ };
340279
+ }
340280
+ //#endregion
338514
340281
  //#region src/personal-memory/phase1-contract.json
338515
340282
  var clientOperations = {
338516
340283
  "settingsRead": {
@@ -338829,9 +340596,9 @@ function isErrno$1(error, code) {
338829
340596
  return error.code === code;
338830
340597
  }
338831
340598
  function outputFailure(error, cleanupError) {
338832
- return new Error(`${errorMessage$3(error)} Output reservation cleanup failed: ${errorMessage$3(cleanupError)}`, { cause: new AggregateError([error, cleanupError], "Output reservation cleanup failed.") });
340599
+ return new Error(`${errorMessage$4(error)} Output reservation cleanup failed: ${errorMessage$4(cleanupError)}`, { cause: new AggregateError([error, cleanupError], "Output reservation cleanup failed.") });
338833
340600
  }
338834
- function errorMessage$3(error) {
340601
+ function errorMessage$4(error) {
338835
340602
  return error instanceof Error ? error.message : String(error);
338836
340603
  }
338837
340604
  //#endregion
@@ -339445,7 +341212,7 @@ async function handleProof(deps, options) {
339445
341212
  await reservation.write(proof);
339446
341213
  } catch (error) {
339447
341214
  await reservation?.abort().catch(() => void 0);
339448
- deps.stderr.write(`${errorMessage$2(error)}\n`);
341215
+ deps.stderr.write(`${errorMessage$3(error)}\n`);
339449
341216
  deps.exit(1);
339450
341217
  }
339451
341218
  deps.stdout.write(`${outputPath}\n`);
@@ -339477,7 +341244,7 @@ function createDefaultProofDeps(overrides = {}) {
339477
341244
  function defaultProofFilename(now) {
339478
341245
  return `proof-${now.toISOString().replaceAll(/[:.]/g, "-")}.json`;
339479
341246
  }
339480
- function errorMessage$2(error) {
341247
+ function errorMessage$3(error) {
339481
341248
  return error instanceof Error ? error.message : String(error);
339482
341249
  }
339483
341250
  function samePath$2(left, right) {
@@ -395793,7 +397560,7 @@ async function abortAndFail(deps, reservation, error) {
395793
397560
  if (reservation !== void 0) try {
395794
397561
  await reservation.abort();
395795
397562
  } catch (cleanupError) {
395796
- fail(deps, new Error(`${errorMessage$1(error)} Output reservation cleanup failed: ${errorMessage$1(cleanupError)}`, { cause: new AggregateError([error, cleanupError], "Output reservation cleanup failed.") }));
397563
+ fail(deps, new Error(`${errorMessage$2(error)} Output reservation cleanup failed: ${errorMessage$2(cleanupError)}`, { cause: new AggregateError([error, cleanupError], "Output reservation cleanup failed.") }));
395797
397564
  }
395798
397565
  fail(deps, error);
395799
397566
  }
@@ -395804,10 +397571,10 @@ function stringArray(value) {
395804
397571
  return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
395805
397572
  }
395806
397573
  function fail(deps, error) {
395807
- deps.stderr.write(`${errorMessage$1(error)}\n`);
397574
+ deps.stderr.write(`${errorMessage$2(error)}\n`);
395808
397575
  return deps.exit(1);
395809
397576
  }
395810
- function errorMessage$1(error) {
397577
+ function errorMessage$2(error) {
395811
397578
  return error instanceof Error ? error.message : String(error);
395812
397579
  }
395813
397580
  //#endregion
@@ -396534,14 +398301,14 @@ async function run(deps, operation) {
396534
398301
  try {
396535
398302
  await operation();
396536
398303
  } catch (error) {
396537
- deps.stderr.write(`${errorMessage(error)}\n`);
398304
+ deps.stderr.write(`${errorMessage$1(error)}\n`);
396538
398305
  deps.exit(1);
396539
398306
  }
396540
398307
  }
396541
398308
  function writeJson(deps, value) {
396542
398309
  deps.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
396543
398310
  }
396544
- function errorMessage(error) {
398311
+ function errorMessage$1(error) {
396545
398312
  return error instanceof Error ? error.message : String(error);
396546
398313
  }
396547
398314
  //#endregion
@@ -396574,6 +398341,7 @@ function createProgram(version, onMain, onPluginNodeRunner = () => {}, onUpgrade
396574
398341
  registerAcpCommand(program);
396575
398342
  registerServerCommand(program);
396576
398343
  registerLoginCommand(program);
398344
+ registerMistakesCommand(program);
396577
398345
  registerPersonalMemoryCommand(program);
396578
398346
  registerDoctorCommand(program);
396579
398347
  registerVisCommand(program);
@@ -414339,7 +416107,7 @@ function appearanceSelectorCopy() {
414339
416107
  surface: uiText("appearance.surface"),
414340
416108
  preview: uiText("appearance.preview"),
414341
416109
  colorHint: uiText("appearance.colorHint"),
414342
- contrastHint: uiText("appearance.contrastHint"),
416110
+ contrastHint: uiText("appearance.contrastHint", { ratio: "{ratio}" }),
414343
416111
  footer: uiText("appearance.footer")
414344
416112
  };
414345
416113
  }
@@ -414491,7 +416259,6 @@ function showSettingsSelector(host) {
414491
416259
  }));
414492
416260
  }
414493
416261
  function handleSettingsSelection(host, value) {
414494
- host.restoreEditor();
414495
416262
  switch (value) {
414496
416263
  case "effort":
414497
416264
  handleEffortCommand(host, "");
@@ -414515,9 +416282,11 @@ function handleSettingsSelection(host, value) {
414515
416282
  showExperimentsPanel(host);
414516
416283
  return;
414517
416284
  case "usage":
416285
+ host.restoreEditor();
414518
416286
  showUsage(host);
414519
416287
  return;
414520
416288
  case "inline-suggest":
416289
+ host.restoreEditor();
414521
416290
  showInlineSuggestStatus(host);
414522
416291
  return;
414523
416292
  }
@@ -509766,7 +511535,11 @@ var BlunTUI = class {
509766
511535
  this.applyStartupPermissionAndPlanToAppState();
509767
511536
  }
509768
511537
  this.hideSessionPicker();
509769
- if (applyStartupModes) await this.promptStartupResumeGoalIfNeeded();
511538
+ if (applyStartupModes) {
511539
+ await this.refreshPersonalMemory(true);
511540
+ await this.authFlow.refreshManagedQuotaWindows();
511541
+ await this.promptStartupResumeGoalIfNeeded();
511542
+ }
509770
511543
  }
509771
511544
  showApprovalPanel(payload) {
509772
511545
  this.patchLivePane({ pendingApproval: { data: payload } });
@@ -511439,6 +513212,103 @@ function runNativeAssetSmokeIfRequested() {
511439
513212
  return true;
511440
513213
  }
511441
513214
  //#endregion
513215
+ //#region src/mistakes/automatic-sync.ts
513216
+ const AUTOMATIC_MISTAKE_SYNC_CONFIG_ENV = "BLUN_MISTAKE_SYNC_CONFIG";
513217
+ const DEFAULT_DEPS = {
513218
+ lstat,
513219
+ lock: (path) => import_proper_lockfile.default.lock(path, {
513220
+ realpath: false,
513221
+ retries: 0,
513222
+ stale: 3e4,
513223
+ update: 1e4
513224
+ }),
513225
+ watch: (options) => watchMistakeSources(options),
513226
+ logger: log
513227
+ };
513228
+ async function startAutomaticMistakeSync(options, deps = DEFAULT_DEPS) {
513229
+ const env = options.env ?? process.env;
513230
+ const configuredPath = env[AUTOMATIC_MISTAKE_SYNC_CONFIG_ENV]?.trim();
513231
+ const configPath = resolve(configuredPath && configuredPath.length > 0 ? configuredPath : join(options.homeDir, "mistake", "source-sync.json"));
513232
+ const inactive = () => ({
513233
+ active: false,
513234
+ configPath,
513235
+ stop: async () => {}
513236
+ });
513237
+ try {
513238
+ const stat = await deps.lstat(configPath);
513239
+ if (stat.isSymbolicLink() || !stat.isFile()) {
513240
+ deps.logger.warn("automatic mistake sync config is not a regular file", { configPath });
513241
+ return inactive();
513242
+ }
513243
+ } catch (error) {
513244
+ if (isErrorCode(error, "ENOENT")) return inactive();
513245
+ deps.logger.warn("automatic mistake sync config is unavailable", {
513246
+ configPath,
513247
+ error: errorMessage(error)
513248
+ });
513249
+ return inactive();
513250
+ }
513251
+ let release;
513252
+ try {
513253
+ release = await deps.lock(configPath);
513254
+ } catch (error) {
513255
+ if (isErrorCode(error, "ELOCKED")) return inactive();
513256
+ deps.logger.warn("automatic mistake sync lock failed", {
513257
+ configPath,
513258
+ error: errorMessage(error)
513259
+ });
513260
+ return inactive();
513261
+ }
513262
+ const controller = new AbortController();
513263
+ let released = false;
513264
+ const releaseOnce = async () => {
513265
+ if (released) return;
513266
+ released = true;
513267
+ try {
513268
+ await release();
513269
+ } catch {}
513270
+ };
513271
+ const watchPromise = deps.watch({
513272
+ configPath,
513273
+ env,
513274
+ intervalMs: options.intervalMs ?? 3e5,
513275
+ signal: controller.signal,
513276
+ onRun: (run) => logRun(deps.logger, run)
513277
+ }).catch((error) => {
513278
+ deps.logger.warn("automatic mistake sync stopped", {
513279
+ configPath,
513280
+ error: errorMessage(error)
513281
+ });
513282
+ }).finally(releaseOnce);
513283
+ return {
513284
+ active: true,
513285
+ configPath,
513286
+ stop: async () => {
513287
+ controller.abort();
513288
+ await watchPromise;
513289
+ }
513290
+ };
513291
+ }
513292
+ function logRun(logger, run) {
513293
+ const counts = Object.fromEntries([
513294
+ "uploaded",
513295
+ "heartbeat",
513296
+ "unchanged",
513297
+ "blocked",
513298
+ "failed"
513299
+ ].map((status) => [status, run.results.filter((result) => result.status === status).length]));
513300
+ logger.info("automatic mistake sync completed", {
513301
+ configPath: run.config_path,
513302
+ ...counts
513303
+ });
513304
+ }
513305
+ function isErrorCode(error, code) {
513306
+ return typeof error === "object" && error !== null && error.code === code;
513307
+ }
513308
+ function errorMessage(error) {
513309
+ return error instanceof Error ? error.message : String(error);
513310
+ }
513311
+ //#endregion
511442
513312
  //#region src/main.ts
511443
513313
  /**
511444
513314
  * BLUN King entry point.
@@ -511471,9 +513341,15 @@ async function handleMainCommand(opts, version) {
511471
513341
  } : { track });
511472
513342
  if (preflightResult === "exit") process.exit(0);
511473
513343
  const updateStartupNotice = typeof preflightResult === "object" ? preflightResult.startupNotice : void 0;
511474
- if (validated.uiMode === "print") {
513344
+ const mistakeSync = await startAutomaticMistakeSync({
513345
+ homeDir: resolveBlunHome$1(),
513346
+ env: process.env
513347
+ });
513348
+ if (validated.uiMode === "print") try {
511475
513349
  await runPrompt(validated.options, version);
511476
513350
  return { headlessCompleted: true };
513351
+ } finally {
513352
+ await mistakeSync.stop();
511477
513353
  }
511478
513354
  await runShell(validated.options, version, updateStartupNotice);
511479
513355
  return { headlessCompleted: false };