blun-king-cli 9.1.597 → 9.1.599

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.597",
3
+ "version": "9.1.599",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {
package/worker-host.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // BLUN_BUILD_INPUT_SHA256:631215107f223f910482352d64f8081de5c7ebb282f9e66a53e7cd6dc93ba305
2
+ // BLUN_BUILD_INPUT_SHA256:25c271186c418490335e30ef395705d13d90d816c66cac47bb57835f2482f093
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);
@@ -1311,7 +1311,7 @@ function normalizeBlunToolSchema(schema) {
1311
1311
  }
1312
1312
  function ensureBlunPropertyTypes(schema) {
1313
1313
  const normalized = cloneJsonValue(schema);
1314
- if (!isRecord$9(normalized)) throw new Error("JSON Schema root must normalize to an object.");
1314
+ if (!isRecord$10(normalized)) throw new Error("JSON Schema root must normalize to an object.");
1315
1315
  recurseSchema(normalized);
1316
1316
  return normalized;
1317
1317
  }
@@ -1372,7 +1372,7 @@ function resolveLocalJsonPointer(root, ref) {
1372
1372
  let current = root;
1373
1373
  for (const rawPart of ref.slice(2).split("/")) {
1374
1374
  const part = unescapeJsonPointerPart(rawPart);
1375
- if (isRecord$9(current)) {
1375
+ if (isRecord$10(current)) {
1376
1376
  if (!hasOwn(current, part)) return { found: false };
1377
1377
  current = current[part];
1378
1378
  } else if (Array.isArray(current)) {
@@ -1394,20 +1394,20 @@ function parseJsonPointerArrayIndex(part) {
1394
1394
  return Number(part);
1395
1395
  }
1396
1396
  function recurseSchema(node) {
1397
- if (!isRecord$9(node)) return;
1397
+ if (!isRecord$10(node)) return;
1398
1398
  visitChildSchemas(node, normalizeProperty);
1399
1399
  }
1400
1400
  function visitChildSchemas(node, visit) {
1401
1401
  for (const { key, kind } of CHILD_SCHEMA_SLOTS) {
1402
1402
  const value = node[key];
1403
1403
  if (kind === "single") {
1404
- if (isRecord$9(value)) visit(value);
1404
+ if (isRecord$10(value)) visit(value);
1405
1405
  } else if (kind === "array") {
1406
1406
  if (Array.isArray(value)) for (const item of value) visit(item);
1407
1407
  } else if (kind === "map") {
1408
- if (isRecord$9(value)) for (const item of Object.values(value)) visit(item);
1408
+ if (isRecord$10(value)) for (const item of Object.values(value)) visit(item);
1409
1409
  } else if (kind === "schema-or-array") {
1410
- if (isRecord$9(value)) visit(value);
1410
+ if (isRecord$10(value)) visit(value);
1411
1411
  else if (Array.isArray(value)) for (const item of value) visit(item);
1412
1412
  }
1413
1413
  }
@@ -1419,7 +1419,7 @@ function childSchemaKeysForParentType(parentType) {
1419
1419
  });
1420
1420
  }
1421
1421
  function normalizeProperty(node) {
1422
- if (!isRecord$9(node)) return;
1422
+ if (!isRecord$10(node)) return;
1423
1423
  if (!hasOwn(node, "type") && !hasAnyKey(node, TYPE_COMPLETION_SKIP_KEYS)) {
1424
1424
  const enumValues = node["enum"];
1425
1425
  if (Array.isArray(enumValues) && enumValues.length > 0) node["type"] = inferTypeFromValues(enumValues);
@@ -1503,14 +1503,14 @@ function hasAnyKey(obj, keys) {
1503
1503
  }
1504
1504
  function cloneJsonValue(value) {
1505
1505
  if (Array.isArray(value)) return value.map((item) => cloneJsonValue(item));
1506
- if (isRecord$9(value)) {
1506
+ if (isRecord$10(value)) {
1507
1507
  const cloned = {};
1508
1508
  for (const [key, child] of Object.entries(value)) cloned[key] = cloneJsonValue(child);
1509
1509
  return cloned;
1510
1510
  }
1511
1511
  return value;
1512
1512
  }
1513
- function isRecord$9(value) {
1513
+ function isRecord$10(value) {
1514
1514
  return typeof value === "object" && value !== null && !Array.isArray(value);
1515
1515
  }
1516
1516
  function hasOwn(obj, key) {
@@ -2703,14 +2703,14 @@ var BlunStreamedMessage = class {
2703
2703
  };
2704
2704
  function contextOverflowOutputCap(error, currentCap) {
2705
2705
  const maxContext = error.maxContextTokens;
2706
- const counts = /requested ([\d,_]+) output tokens and your prompt contains (?:at least )?([\d,_]+) input tokens/i.exec(error.message);
2706
+ const counts = /requested ([\d,_]+) output tokens and your prompt contains (at least )?([\d,_]+) input tokens/i.exec(error.message);
2707
2707
  if (maxContext === void 0 || counts === null || !Number.isSafeInteger(maxContext) || maxContext <= 0) return;
2708
2708
  const requestedOutput = Number(counts[1].replaceAll(/[,_]/g, ""));
2709
- const input = Number(counts[2].replaceAll(/[,_]/g, ""));
2709
+ const input = Number(counts[3].replaceAll(/[,_]/g, ""));
2710
2710
  if (!Number.isSafeInteger(input) || input < 0 || !Number.isSafeInteger(requestedOutput) || requestedOutput <= 0 || !Number.isSafeInteger(input + requestedOutput) || input + requestedOutput <= maxContext) return;
2711
2711
  const available = maxContext - input;
2712
2712
  const headroom = Math.min(1024, Math.max(1, Math.ceil(available * .01)));
2713
- const cap = Math.min(requestedOutput - 1, available - headroom);
2713
+ const cap = Math.min(counts[2] === void 0 ? requestedOutput - 1 : Math.floor(requestedOutput / 2), available - headroom);
2714
2714
  if (cap < 1 || currentCap !== void 0 && (typeof currentCap !== "number" || !Number.isSafeInteger(currentCap) || cap >= currentCap)) return;
2715
2715
  return cap;
2716
2716
  }
@@ -10279,7 +10279,7 @@ function tokenFromWire(wire) {
10279
10279
  }
10280
10280
  //#endregion
10281
10281
  //#region ../../packages/oauth/src/utils.ts
10282
- function isRecord$8(value) {
10282
+ function isRecord$9(value) {
10283
10283
  return typeof value === "object" && value !== null && !Array.isArray(value);
10284
10284
  }
10285
10285
  //#endregion
@@ -10594,7 +10594,7 @@ var FileTokenStorage = class {
10594
10594
  } catch {
10595
10595
  return;
10596
10596
  }
10597
- if (!isRecord$8(parsed)) return void 0;
10597
+ if (!isRecord$9(parsed)) return void 0;
10598
10598
  return tokenFromWire(parsed);
10599
10599
  }
10600
10600
  async save(name, token) {
@@ -10699,7 +10699,7 @@ function extractApiErrorMessage(value) {
10699
10699
  }
10700
10700
  return;
10701
10701
  }
10702
- if (!isRecord$8(value)) return void 0;
10702
+ if (!isRecord$9(value)) return void 0;
10703
10703
  for (const key of DIRECT_ERROR_KEYS) {
10704
10704
  const message = stringField$1(value, key);
10705
10705
  if (message !== void 0) return message;
@@ -10707,7 +10707,7 @@ function extractApiErrorMessage(value) {
10707
10707
  const error = value["error"];
10708
10708
  const errorString = nonEmptyString$6(error);
10709
10709
  if (errorString !== void 0) return errorString;
10710
- if (isRecord$8(error)) for (const key of NESTED_ERROR_KEYS) {
10710
+ if (isRecord$9(error)) for (const key of NESTED_ERROR_KEYS) {
10711
10711
  const message = stringField$1(error, key);
10712
10712
  if (message !== void 0) return message;
10713
10713
  }
@@ -10801,7 +10801,7 @@ async function postForm(url, params, deviceHeaders, options) {
10801
10801
  let data = {};
10802
10802
  try {
10803
10803
  const parsed = await response.json();
10804
- if (isRecord$8(parsed)) data = parsed;
10804
+ if (isRecord$9(parsed)) data = parsed;
10805
10805
  } catch {}
10806
10806
  return {
10807
10807
  status,
@@ -12718,9 +12718,9 @@ function blunContextWindowsUrl(oauthHost) {
12718
12718
  return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}/api/verbrauch/tarife`;
12719
12719
  }
12720
12720
  function parseManagedContextWindow(payload, plan) {
12721
- if (!isRecord$8(payload)) return void 0;
12721
+ if (!isRecord$9(payload)) return void 0;
12722
12722
  const contextWindows = payload["kontext"];
12723
- if (!isRecord$8(contextWindows)) return void 0;
12723
+ if (!isRecord$9(contextWindows)) return void 0;
12724
12724
  const value = contextWindows[plan];
12725
12725
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
12726
12726
  }
@@ -12755,7 +12755,7 @@ function parseManagedUsagePayload(payload) {
12755
12755
  const plan = typeof rec["plan"] === "string" && rec["plan"].trim().length > 0 ? rec["plan"].trim() : void 0;
12756
12756
  const contextWindowTokens = managedContextWindowFrom(rec);
12757
12757
  const unlimited = rec["unlimited"] === true;
12758
- const stand = isRecord$8(rec["stand"]) ? rec["stand"] : void 0;
12758
+ const stand = isRecord$9(rec["stand"]) ? rec["stand"] : void 0;
12759
12759
  if (stand !== void 0) for (const [sourceKey, id, label] of ACCOUNT_USAGE_WINDOWS) {
12760
12760
  const row = toAccountUsageRow(stand[sourceKey], id, label, unlimited);
12761
12761
  if (row !== null) limits.push(row);
@@ -12765,9 +12765,9 @@ function parseManagedUsagePayload(payload) {
12765
12765
  const item = rawLimits[idx];
12766
12766
  if (!item || typeof item !== "object") continue;
12767
12767
  const detailRaw = item["detail"];
12768
- const detail = isRecord$8(detailRaw) ? detailRaw : item;
12768
+ const detail = isRecord$9(detailRaw) ? detailRaw : item;
12769
12769
  const windowRaw = item["window"];
12770
- const row = toUsageRow(detail, limitLabel(item, detail, isRecord$8(windowRaw) ? windowRaw : {}, idx));
12770
+ const row = toUsageRow(detail, limitLabel(item, detail, isRecord$9(windowRaw) ? windowRaw : {}, idx));
12771
12771
  if (row !== null) limits.push(row);
12772
12772
  }
12773
12773
  return {
@@ -12808,7 +12808,7 @@ const ACCOUNT_USAGE_WINDOWS = [
12808
12808
  ]
12809
12809
  ];
12810
12810
  function toAccountUsageRow(raw, id, label, accountUnlimited) {
12811
- if (!isRecord$8(raw)) return null;
12811
+ if (!isRecord$9(raw)) return null;
12812
12812
  const used = toInt(raw["verbraucht"]);
12813
12813
  const unlimited = accountUnlimited || raw["unlimited"] === true;
12814
12814
  const fraction = raw["anteil"];
@@ -12841,7 +12841,7 @@ function toAccountUsageRow(raw, id, label, accountUnlimited) {
12841
12841
  };
12842
12842
  }
12843
12843
  function toUsageRow(raw, defaultLabel) {
12844
- if (!isRecord$8(raw)) return null;
12844
+ if (!isRecord$9(raw)) return null;
12845
12845
  const unlimited = raw["unlimited"] === true;
12846
12846
  const limit = toInt(raw["limit"]);
12847
12847
  let used = toInt(raw["used"]);
@@ -12962,7 +12962,7 @@ function isManagedQuotaErrorMessage(message) {
12962
12962
  return /you(?:'|’)?ve reached your usage limit/.test(normalized) && /billing cycle|quota will be (?:refreshed|reset)|purchase extra usage/.test(normalized);
12963
12963
  }
12964
12964
  function hasManagedUsageShape(payload) {
12965
- if (!isRecord$8(payload)) return false;
12965
+ if (!isRecord$9(payload)) return false;
12966
12966
  let recognized = false;
12967
12967
  if ("context_window_tokens" in payload || "contextWindowTokens" in payload) {
12968
12968
  recognized = true;
@@ -12978,15 +12978,15 @@ function hasManagedUsageShape(payload) {
12978
12978
  if (!Array.isArray(limits)) return false;
12979
12979
  for (let index = 0; index < limits.length; index++) {
12980
12980
  const item = limits[index];
12981
- if (!isRecord$8(item)) return false;
12982
- const detail = isRecord$8(item["detail"]) ? item["detail"] : item;
12983
- if (toUsageRow(detail, limitLabel(item, detail, isRecord$8(item["window"]) ? item["window"] : {}, index)) === null) return false;
12981
+ if (!isRecord$9(item)) return false;
12982
+ const detail = isRecord$9(item["detail"]) ? item["detail"] : item;
12983
+ if (toUsageRow(detail, limitLabel(item, detail, isRecord$9(item["window"]) ? item["window"] : {}, index)) === null) return false;
12984
12984
  }
12985
12985
  }
12986
12986
  if ("stand" in payload) {
12987
12987
  recognized = true;
12988
12988
  const stand = payload["stand"];
12989
- if (!isRecord$8(stand)) return false;
12989
+ if (!isRecord$9(stand)) return false;
12990
12990
  const windows = ACCOUNT_USAGE_WINDOWS.filter(([sourceKey]) => sourceKey in stand);
12991
12991
  if (windows.length === 0) return false;
12992
12992
  const unlimited = payload["unlimited"] === true;
@@ -13069,8 +13069,8 @@ function userExtras(existing, remoteOwnedFields) {
13069
13069
  return out;
13070
13070
  }
13071
13071
  function mergeRefreshedModelAlias(existing, remote, remoteOwnedFields) {
13072
- const current = isRecord$8(existing) ? existing : {};
13073
- const overrides = cloneOverrides(isRecord$8(current["overrides"]) ? current["overrides"] : void 0);
13072
+ const current = isRecord$9(existing) ? existing : {};
13073
+ const overrides = cloneOverrides(isRecord$9(current["overrides"]) ? current["overrides"] : void 0);
13074
13074
  return {
13075
13075
  ...userExtras(current, remoteOwnedFields),
13076
13076
  ...remote,
@@ -13272,7 +13272,7 @@ function parseModelContextLength(item, modelId) {
13272
13272
  return values[0];
13273
13273
  }
13274
13274
  function toModelInfo(item) {
13275
- if (!isRecord$8(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
13275
+ if (!isRecord$9(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
13276
13276
  const contextLength = parseModelContextLength(item, item["id"]);
13277
13277
  const displayName = item["display_name"];
13278
13278
  const normalizedDisplayName = typeof displayName === "string" && displayName.length > 0 ? displayName : void 0;
@@ -13359,7 +13359,7 @@ async function fetchManagedBlunCodeModels(options) {
13359
13359
  throw new Error(message);
13360
13360
  }
13361
13361
  const payload = await response.json();
13362
- if (!isRecord$8(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
13362
+ if (!isRecord$9(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
13363
13363
  return payload["data"].map((item) => toModelInfo(item)).filter((item) => item !== void 0);
13364
13364
  }
13365
13365
  throw new Error(`Failed to list BLUN models for ${baseUrl}.`);
@@ -13402,11 +13402,11 @@ function applyManagedBlunCodeConfig(config, options) {
13402
13402
  apiKey
13403
13403
  };
13404
13404
  const upstreamKeys = new Set(options.models.map((m) => managedModelKey(m.id)));
13405
- for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$8(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
13405
+ for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$9(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
13406
13406
  for (const model of options.models) {
13407
13407
  const capabilities = capabilitiesForModel(model);
13408
13408
  const key = managedModelKey(model.id);
13409
- const existing = isRecord$8(existingModels[key]) ? existingModels[key] : {};
13409
+ const existing = isRecord$9(existingModels[key]) ? existingModels[key] : {};
13410
13410
  const supportsAdaptiveThinking = capabilities?.includes("thinking") === true || capabilities?.includes("always_thinking") === true;
13411
13411
  existingModels[key] = mergeRefreshedModelAlias(existing, {
13412
13412
  provider: BLUN_PROVIDER_NAME$1,
@@ -13454,7 +13454,7 @@ function applyManagedBlunCodeLogoutConfig(config) {
13454
13454
  let removedDefaultModel = false;
13455
13455
  const existingModels = config.models ?? {};
13456
13456
  for (const [key, model] of Object.entries(existingModels)) {
13457
- if (!isRecord$8(model) || model["provider"] !== "managed:blun") continue;
13457
+ if (!isRecord$9(model) || model["provider"] !== "managed:blun") continue;
13458
13458
  delete existingModels[key];
13459
13459
  if (config.defaultModel === key) removedDefaultModel = true;
13460
13460
  }
@@ -13494,7 +13494,7 @@ function selectDefaultModel(config, models, options) {
13494
13494
  function canPreserveDefaultModel(existingModels, defaultModel, managedModels) {
13495
13495
  if (managedModels.has(defaultModel)) return true;
13496
13496
  const existing = existingModels[defaultModel];
13497
- return isRecord$8(existing) && existing["provider"] !== "managed:blun";
13497
+ return isRecord$9(existing) && existing["provider"] !== "managed:blun";
13498
13498
  }
13499
13499
  function assertPositiveContextLength(model) {
13500
13500
  if (!Number.isInteger(model.contextLength) || model.contextLength <= 0) throw new Error(`BLUN model "${model.id}" must include a positive context_length.`);
@@ -13532,13 +13532,13 @@ function blunManagedQuotaUrl(oauthHost) {
13532
13532
  return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}${MANAGED_QUOTA_PATH}`;
13533
13533
  }
13534
13534
  function parseManagedQuotaPayload(payload) {
13535
- if (!isRecord$8(payload)) return void 0;
13535
+ if (!isRecord$9(payload)) return void 0;
13536
13536
  const plan = nonEmptyString$5(payload["plan"]);
13537
13537
  const paid = payload["bezahlt"];
13538
13538
  const creditCents = payload["guthaben_cent"];
13539
13539
  const billingKind = nonEmptyString$5(payload["art"]);
13540
13540
  const globalUnlimited = payload["unlimited"];
13541
- if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$8(payload["stand"])) return;
13541
+ if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$9(payload["stand"])) return;
13542
13542
  if (!hasStrictQuotaStand(payload["stand"], globalUnlimited === true)) return void 0;
13543
13543
  const limits = parseManagedUsagePayload(payload).limits;
13544
13544
  if (limits.length !== REQUIRED_WINDOWS.length || REQUIRED_WINDOWS.some(([, id]) => limits.filter((row) => row.id === id).length !== 1)) return;
@@ -13608,7 +13608,7 @@ function nonEmptyString$5(value) {
13608
13608
  function hasStrictQuotaStand(stand, globalUnlimited) {
13609
13609
  return REQUIRED_WINDOWS.every(([sourceKey]) => {
13610
13610
  const row = stand[sourceKey];
13611
- if (!isRecord$8(row)) return false;
13611
+ if (!isRecord$9(row)) return false;
13612
13612
  const used = row["verbraucht"];
13613
13613
  const rowUnlimited = row["unlimited"];
13614
13614
  if (rowUnlimited !== void 0 && typeof rowUnlimited !== "boolean") return false;
@@ -20705,7 +20705,7 @@ function parseSkillText(options) {
20705
20705
  throw error;
20706
20706
  }
20707
20707
  const frontmatter = parsed.data ?? {};
20708
- if (!isRecord$7(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
20708
+ if (!isRecord$8(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
20709
20709
  const metadata = normalizeMetadata(frontmatter);
20710
20710
  if (!isSupportedSkillType(metadata.type)) throw new UnsupportedSkillTypeError(metadata.type ?? String(frontmatter["type"]));
20711
20711
  const name = nonEmptyString$3(metadata.name);
@@ -20818,7 +20818,7 @@ function tokenizeArgs(raw) {
20818
20818
  function nonEmptyString$3(value) {
20819
20819
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
20820
20820
  }
20821
- function isRecord$7(value) {
20821
+ function isRecord$8(value) {
20822
20822
  return typeof value === "object" && value !== null && !Array.isArray(value);
20823
20823
  }
20824
20824
  //#endregion
@@ -20826,7 +20826,7 @@ function isRecord$7(value) {
20826
20826
  function parseCommandText(input) {
20827
20827
  const { text, commandPath, pluginId } = input;
20828
20828
  const parsed = parseFrontmatter(text);
20829
- const frontmatter = isRecord$6(parsed.data) ? parsed.data : {};
20829
+ const frontmatter = isRecord$7(parsed.data) ? parsed.data : {};
20830
20830
  const baseName = input.fallbackName ?? path.basename(commandPath).replace(/\.md$/i, "");
20831
20831
  const name = nonEmptyString$2(frontmatter["name"]) ?? baseName;
20832
20832
  const body = parsed.body.trim();
@@ -20868,7 +20868,7 @@ function descriptionFromBody(body) {
20868
20868
  if (firstLine === void 0) return "No description provided.";
20869
20869
  return firstLine.length > 240 ? `${firstLine.slice(0, 239)}…` : firstLine;
20870
20870
  }
20871
- function isRecord$6(value) {
20871
+ function isRecord$7(value) {
20872
20872
  return typeof value === "object" && value !== null && !Array.isArray(value);
20873
20873
  }
20874
20874
  //#endregion
@@ -28376,7 +28376,7 @@ const ResumeIntentSchema = object({
28376
28376
  startedAt: timestamp$2.nullable()
28377
28377
  }).strict();
28378
28378
  const hash$2 = (value) => createHash("sha256").update(value).digest("hex");
28379
- const isRecord$5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
28379
+ const isRecord$6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
28380
28380
  /** Explicit resume intents, isolated from ordinary task status and output files. */
28381
28381
  var TaskResumeStore = class {
28382
28382
  home;
@@ -28432,9 +28432,9 @@ var TaskResumeStore = class {
28432
28432
  }
28433
28433
  async readOwnedTask(taskId) {
28434
28434
  const task = await this.read("tasks", taskId);
28435
- if (!isRecord$5(task)) throw new Error("Task has no persisted local record.");
28435
+ if (!isRecord$6(task)) throw new Error("Task has no persisted local record.");
28436
28436
  const owner = task["resumeOwnership"];
28437
- if (!isRecord$5(owner) || owner["version"] !== 1 || owner["scope"] !== hash$2(await this.root()) || owner["taskId"] !== taskId || task["taskId"] !== taskId || task["kind"] !== "agent" || owner["agentId"] !== task["agentId"] || owner["startedAt"] !== task["startedAt"]) throw new Error("Task ownership is unverified; historical or foreign records cannot be resumed automatically.");
28437
+ if (!isRecord$6(owner) || owner["version"] !== 1 || owner["scope"] !== hash$2(await this.root()) || owner["taskId"] !== taskId || task["taskId"] !== taskId || task["kind"] !== "agent" || owner["agentId"] !== task["agentId"] || owner["startedAt"] !== task["startedAt"]) throw new Error("Task ownership is unverified; historical or foreign records cannot be resumed automatically.");
28438
28438
  const { resumeOwnership: _ownership, ...info } = task;
28439
28439
  return info;
28440
28440
  }
@@ -28686,12 +28686,12 @@ function legacyStatusToCurrent(task) {
28686
28686
  return task.status;
28687
28687
  }
28688
28688
  function isReadablePersistedTask(obj) {
28689
- return isRecord$4(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
28689
+ return isRecord$5(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
28690
28690
  }
28691
28691
  function isLegacyPersistedTask(task) {
28692
28692
  return "task_id" in task;
28693
28693
  }
28694
- function isRecord$4(value) {
28694
+ function isRecord$5(value) {
28695
28695
  return typeof value === "object" && value !== null;
28696
28696
  }
28697
28697
  function optionalNonEmptyString(value) {
@@ -228018,7 +228018,7 @@ var HttpVisionReader = class {
228018
228018
  reason: "malformed"
228019
228019
  };
228020
228020
  }
228021
- if (!isRecord$3(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger(payload["prompt_eval_count"]) || !isNonNegativeInteger(payload["eval_count"])) return {
228021
+ if (!isRecord$4(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger(payload["prompt_eval_count"]) || !isNonNegativeInteger(payload["eval_count"])) return {
228022
228022
  ok: false,
228023
228023
  reason: "malformed"
228024
228024
  };
@@ -228442,7 +228442,7 @@ function escapeXml(value) {
228442
228442
  function locationKey(messageIndex, partIndex) {
228443
228443
  return `${String(messageIndex)}:${String(partIndex)}`;
228444
228444
  }
228445
- function isRecord$3(value) {
228445
+ function isRecord$4(value) {
228446
228446
  return value !== null && typeof value === "object" && !Array.isArray(value);
228447
228447
  }
228448
228448
  function isNonNegativeInteger(value) {
@@ -234239,7 +234239,7 @@ const OptionalStringSchema = preprocess((value) => {
234239
234239
  if (typeof value === "string") return value;
234240
234240
  if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
234241
234241
  }, string().optional());
234242
- const HookSpecificOutputSchema = preprocess((value) => isRecord$2(value) ? value : void 0, looseObject({
234242
+ const HookSpecificOutputSchema = preprocess((value) => isRecord$3(value) ? value : void 0, looseObject({
234243
234243
  message: OptionalStringSchema,
234244
234244
  additionalContext: OptionalStringSchema,
234245
234245
  permissionDecision: unknown().optional(),
@@ -234391,7 +234391,7 @@ function structuredOutput(stdout, input) {
234391
234391
  return {
234392
234392
  ...result,
234393
234393
  additionalContext: input["hook_event_name"] === "UserPromptSubmit" && hookSpecificOutput?.hookEventName === "UserPromptSubmit" ? hookSpecificOutput.additionalContext : void 0,
234394
- updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$2(hookSpecificOutput.updatedInput) ? hookSpecificOutput.updatedInput : void 0
234394
+ updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$3(hookSpecificOutput.updatedInput) ? hookSpecificOutput.updatedInput : void 0
234395
234395
  };
234396
234396
  }
234397
234397
  return {
@@ -234460,7 +234460,7 @@ function killProcessTreeWindows(child, force) {
234460
234460
  } catch {}
234461
234461
  }
234462
234462
  }
234463
- function isRecord$2(value) {
234463
+ function isRecord$3(value) {
234464
234464
  return typeof value === "object" && value !== null && !Array.isArray(value);
234465
234465
  }
234466
234466
  function errorMessage$3(error) {
@@ -234581,7 +234581,16 @@ var HookEngine = class {
234581
234581
  };
234582
234582
  }
234583
234583
  if (this.admissionClosed) return void 0;
234584
- return runHook(hook.command, inputData, {
234584
+ let hookInput;
234585
+ try {
234586
+ hookInput = this.options.runtimeInput?.(hook, inputData) ?? inputData;
234587
+ } catch {
234588
+ return {
234589
+ action: "block",
234590
+ reason: "Hook input preparation failed."
234591
+ };
234592
+ }
234593
+ return runHook(hook.command, hookInput, {
234585
234594
  timeout: hook.timeout ?? DEFAULT_HOOK_TIMEOUT_SECONDS,
234586
234595
  cwd: hook.cwd ?? (this.options.cwd === "" ? void 0 : this.options.cwd),
234587
234596
  env: hook.env,
@@ -235816,7 +235825,7 @@ function parsePersonalMemoryRecall(output) {
235816
235825
  } catch {
235817
235826
  return { kind: "invalid" };
235818
235827
  }
235819
- if (!isRecord$1(parsed) || !isRecord$1(parsed["personal_memory"])) return { kind: "invalid" };
235828
+ if (!isRecord$2(parsed) || !isRecord$2(parsed["personal_memory"])) return { kind: "invalid" };
235820
235829
  const memory = parsed["personal_memory"];
235821
235830
  const savedRaw = memory["saved"];
235822
235831
  const threadsRaw = memory["threads"];
@@ -235825,7 +235834,7 @@ function parsePersonalMemoryRecall(output) {
235825
235834
  if (savedRaw.length > MAX_SAVED_MEMORIES || threadsRaw.length > MAX_THREADS || historyRaw.length > 0) return { kind: "invalid" };
235826
235835
  const saved = [];
235827
235836
  for (const value of savedRaw) {
235828
- if (!isRecord$1(value)) return { kind: "invalid" };
235837
+ if (!isRecord$2(value)) return { kind: "invalid" };
235829
235838
  const text = boundedTrimmedString(value["text"], MAX_MEMORY_TEXT_CHARS);
235830
235839
  const confidence = value["confidence"];
235831
235840
  if (text === void 0 || typeof confidence !== "string" || !CONFIDENCE_VALUES.has(confidence)) return { kind: "invalid" };
@@ -235836,7 +235845,7 @@ function parsePersonalMemoryRecall(output) {
235836
235845
  }
235837
235846
  const threads = [];
235838
235847
  for (const value of threadsRaw) {
235839
- if (!isRecord$1(value)) return { kind: "invalid" };
235848
+ if (!isRecord$2(value)) return { kind: "invalid" };
235840
235849
  const title = boundedTrimmedString(value["title"], MAX_THREAD_TITLE_CHARS);
235841
235850
  const summary = boundedTrimmedString(value["summary"], MAX_THREAD_SUMMARY_CHARS);
235842
235851
  if (title === void 0 || summary === void 0) return { kind: "invalid" };
@@ -235890,7 +235899,7 @@ function boundedTrimmedString(value, maxChars) {
235890
235899
  const trimmed = value.trim();
235891
235900
  return trimmed.length > 0 ? trimmed : void 0;
235892
235901
  }
235893
- function isRecord$1(value) {
235902
+ function isRecord$2(value) {
235894
235903
  return typeof value === "object" && value !== null && !Array.isArray(value);
235895
235904
  }
235896
235905
  //#endregion
@@ -299939,6 +299948,36 @@ function mergeCallerMcpServers(base, callerServers) {
299939
299948
  }
299940
299949
  //#endregion
299941
299950
  //#region ../../packages/agent-core/src/plugin/agent-spine-runtime.ts
299951
+ const PROMPT_EVENTS = new Set([
299952
+ "UserPromptSubmit",
299953
+ "TurnStart",
299954
+ "SubagentStart"
299955
+ ]);
299956
+ /** AgentSpine reads prompt text; binary media stays in the original model input. */
299957
+ function projectAgentSpinePrompt(input) {
299958
+ if (typeof input["hook_event_name"] !== "string" || !PROMPT_EVENTS.has(input["hook_event_name"]) || !Array.isArray(input["prompt"])) return input;
299959
+ let changed = false;
299960
+ const prompt = input["prompt"].map((part) => {
299961
+ if (!isRecord$1(part)) return part;
299962
+ const field = part["type"] === "image_url" ? "imageUrl" : part["type"] === "audio_url" ? "audioUrl" : part["type"] === "video_url" ? "videoUrl" : void 0;
299963
+ if (field === void 0 || !isRecord$1(part[field]) || typeof part[field]["url"] !== "string") return part;
299964
+ const serialized = JSON.stringify(part);
299965
+ changed = true;
299966
+ return {
299967
+ type: "media_reference",
299968
+ media_type: part["type"],
299969
+ sha256: createHash("sha256").update(serialized).digest("hex"),
299970
+ original_bytes: Buffer.byteLength(serialized)
299971
+ };
299972
+ });
299973
+ return changed ? {
299974
+ ...input,
299975
+ prompt
299976
+ } : input;
299977
+ }
299978
+ function isRecord$1(value) {
299979
+ return typeof value === "object" && value !== null && !Array.isArray(value);
299980
+ }
299942
299981
  const EMPTY_RUNTIME = Object.freeze({
299943
299982
  AGENTSPINE_KING_TIMELINE_SOURCE: "",
299944
299983
  AGENTSPINE_KING_WIRE_PROTOCOL_VERSION: "",
@@ -300485,9 +300524,11 @@ var Session$1 = class {
300485
300524
  this.experimentalFlags = options.experimentalFlags ?? new FlagResolver();
300486
300525
  this.agentSpineRuntime = this.experimentalFlags.enabled("agent_spine_timeline") ? new AgentSpineSessionRuntime(options.agentSpineRuntime) : void 0;
300487
300526
  this.visionReader = (this.experimentalFlags.enabled("vision_reader") ? createVisionReader(options.config?.services?.visionReader) : void 0) ?? createManagedMediaVisionReader(options.toolServices?.media);
300527
+ const agentSpineHooks = new Set(options.agentSpineRuntime?.hooks);
300488
300528
  this.hookEngine = new HookEngine(options.hooks, {
300489
300529
  cwd: options.kaos.getcwd(),
300490
300530
  sessionId: options.id,
300531
+ runtimeInput: (hook, input) => agentSpineHooks.has(hook) ? projectAgentSpinePrompt(input) : input,
300491
300532
  runtimeEnv: (hook) => {
300492
300533
  const hostEnv = options.hookRuntimeEnv?.(hook);
300493
300534
  const timelineEnv = this.agentSpineRuntime?.forHook(hook);
@@ -335769,7 +335810,6 @@ var BlunCore = class {
335769
335810
  };
335770
335811
  }
335771
335812
  agentSpineRuntimeRecipients(pluginHooks, mcpConfig) {
335772
- if (!this.experimentalFlags.enabled("agent_spine_timeline")) return void 0;
335773
335813
  const plugin = this.plugins.get("agent-spine");
335774
335814
  if (plugin?.state !== "ok" || !plugin.enabled) return void 0;
335775
335815
  const hooks = pluginHooks.filter((hook) => hook.env?.["BLUN_PLUGIN_ROOT"] === plugin.root);