blun-king-cli 9.1.597 → 9.1.600

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +17 -1
  3. package/agent-spine-plugin/CHANGELOG.md +1 -1
  4. package/agent-spine-plugin/docs/host-integration.md +1 -15
  5. package/agent-spine-plugin/docs/preflight-recall.md +1 -1
  6. package/agent-spine-plugin/scripts/check-install.js +1 -6
  7. package/agent-spine-plugin/scripts/hermetic-process.js +8 -0
  8. package/agent-spine-plugin/scripts/release-check.js +2 -3
  9. package/agent-spine-plugin/scripts/run-tests-hermetic.js +8 -11
  10. package/agent-spine-plugin/src/hook.js +40 -40
  11. package/agent-spine-plugin/src/lib/briefing.js +6 -3
  12. package/agent-spine-plugin/src/lib/hook-context.js +63 -64
  13. package/agent-spine-plugin/src/lib/hook-output.js +115 -94
  14. package/agent-spine-plugin/src/lib/hook-timeline.js +20 -11
  15. package/agent-spine-plugin/src/lib/host-instruction-budget.js +8 -14
  16. package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +0 -7
  17. package/agent-spine-plugin/src/lib/pre-answer-timeline-recall.js +104 -0
  18. package/agent-spine-plugin/src/lib/session-timeline-codex.js +0 -4
  19. package/agent-spine-plugin/src/lib/session-timeline-enrollment-source.js +0 -3
  20. package/agent-spine-plugin/src/lib/session-timeline-enrollment-storage.js +0 -4
  21. package/agent-spine-plugin/src/lib/session-timeline-enrollment-transport.js +0 -2
  22. package/agent-spine-plugin/src/lib/session-timeline-enrollment.js +0 -22
  23. package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +0 -4
  24. package/agent-spine-plugin/src/lib/session-timeline-prior.js +42 -50
  25. package/agent-spine-plugin/src/lib/session-timeline-provider.js +0 -3
  26. package/agent-spine-plugin/src/lib/session-timeline-query.js +0 -1
  27. package/agent-spine-plugin/src/lib/session-timeline-sid-acl.js +0 -4
  28. package/agent-spine-plugin/src/lib/session-timeline-source.js +0 -3
  29. package/agent-spine-plugin/src/lib/session-timeline-transport.js +0 -8
  30. package/agent-spine-plugin/src/lib/session-timeline-windows-acl.js +0 -3
  31. package/agent-spine-plugin/src/lib/session-timeline.js +370 -408
  32. package/agent-spine-plugin/src/lib/source-roots.js +26 -16
  33. package/agent-spine-plugin/src/lib/timeline-user-feedback.js +0 -1
  34. package/bin/core-bootstrap.js +18 -10
  35. package/bin/launcher-mode.js +5 -0
  36. package/bin/launcher-runtime.js +27 -0
  37. package/bin/verify-bundled-agent-sources.cjs +28 -2
  38. package/blun.mjs +798 -143
  39. package/bundled-agent-sources.json +192 -155
  40. package/package.json +1 -1
  41. package/standard-skills/translate-native/README.md +1334 -1
  42. package/standard-skills/translate-native/SKILL.md +1 -1
  43. package/standard-skills/translate-native/VERSION +1 -1
  44. package/standard-skills/translate-native/docs/PREMORTEM.md +901 -0
  45. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +208 -41
  46. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1319 -77
  47. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +66 -11
  48. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +19 -1
  49. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +24 -6
  50. package/standard-skills/translate-native/integrations/commercial_localization_profile.py +23 -0
  51. package/standard-skills/translate-native/integrations/website_localization.py +234 -10
  52. package/standard-skills/translate-native/integrations/website_localization_benchmark.py +39 -3
  53. package/standard-skills/translate-native/integrations/website_localization_cms.py +512 -10
  54. package/standard-skills/translate-native/integrations/website_localization_cms_client.py +116 -0
  55. package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +101 -11
  56. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +12 -1
  57. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +186 -24
  58. package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +64 -1
  59. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +528 -5
  60. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_auth.py +918 -0
  61. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_auth_runtime.py +609 -0
  62. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_client.py +885 -0
  63. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_http.py +1244 -0
  64. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +220 -0
  65. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_sidecar_adapter.py +331 -0
  66. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_capabilities_http.py +444 -0
  67. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_client.py +673 -0
  68. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch.py +1317 -0
  69. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_client.py +826 -0
  70. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_http.py +1152 -0
  71. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_openapi.py +896 -0
  72. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_dispatch_runtime.py +621 -0
  73. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_http.py +1180 -0
  74. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_submission_runtime.py +1479 -0
  75. package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +133 -17
  76. package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +319 -4
  77. package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +72 -2
  78. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +13 -0
  79. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +56 -13
  80. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_openapi.py +335 -0
  81. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +66 -1
  82. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +73 -7
  83. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +93 -9
  84. package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +221 -11
  85. package/standard-skills/translate-native/integrations/website_localization_health.py +6 -0
  86. package/standard-skills/translate-native/integrations/website_localization_http_provider.py +1 -1
  87. package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +350 -0
  88. package/standard-skills/translate-native/integrations/website_localization_queue.py +126 -56
  89. package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +166 -13
  90. package/standard-skills/translate-native/integrations/website_localization_release.py +423 -17
  91. package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +168 -13
  92. package/standard-skills/translate-native/integrations/website_localization_runner.py +10 -0
  93. package/standard-skills/translate-native/integrations/website_localization_worker.py +213 -9
  94. package/standard-skills/translate-native/provenance.json +2 -2
  95. package/standard-skills/translate-native/references/commercial-localization.md +96 -17
  96. package/standard-skills/translate-native/scripts/blun_language_guard.py +3 -1
  97. package/standard-skills/translate-native/scripts/check_commercial_review.py +69 -9
  98. package/standard-skills/translate-native/scripts/commercial_localization_profile.py +829 -31
  99. package/standard-tools/language-guard/VERSION +1 -1
  100. package/standard-tools/language-guard/blun_language_guard.py +3 -1
  101. package/standard-tools/language-guard/check_commercial_review.py +69 -9
  102. package/standard-tools/language-guard/commercial_localization_profile.py +829 -31
  103. package/standard-tools/language-guard/provenance.json +2 -2
  104. package/standard-tools/manifest.json +1 -1
  105. package/worker-host.mjs +215 -82
  106. package/agent-spine-plugin/scripts/check-install-king.js +0 -37
package/blun.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // BLUN_BUILD_INPUT_SHA256:631215107f223f910482352d64f8081de5c7ebb282f9e66a53e7cd6dc93ba305
2
+ // BLUN_BUILD_INPUT_SHA256:c0b3db57102f82b976cc669375212221a4788318dbd6d1bfc28e943f7bf649db
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);
@@ -1175,7 +1175,7 @@ function normalizeBlunToolSchema(schema) {
1175
1175
  }
1176
1176
  function ensureBlunPropertyTypes(schema) {
1177
1177
  const normalized = cloneJsonValue(schema);
1178
- if (!isRecord$26(normalized)) throw new Error("JSON Schema root must normalize to an object.");
1178
+ if (!isRecord$27(normalized)) throw new Error("JSON Schema root must normalize to an object.");
1179
1179
  recurseSchema(normalized);
1180
1180
  return normalized;
1181
1181
  }
@@ -1236,7 +1236,7 @@ function resolveLocalJsonPointer(root, ref) {
1236
1236
  let current = root;
1237
1237
  for (const rawPart of ref.slice(2).split("/")) {
1238
1238
  const part = unescapeJsonPointerPart(rawPart);
1239
- if (isRecord$26(current)) {
1239
+ if (isRecord$27(current)) {
1240
1240
  if (!hasOwn(current, part)) return { found: false };
1241
1241
  current = current[part];
1242
1242
  } else if (Array.isArray(current)) {
@@ -1258,20 +1258,20 @@ function parseJsonPointerArrayIndex(part) {
1258
1258
  return Number(part);
1259
1259
  }
1260
1260
  function recurseSchema(node) {
1261
- if (!isRecord$26(node)) return;
1261
+ if (!isRecord$27(node)) return;
1262
1262
  visitChildSchemas(node, normalizeProperty);
1263
1263
  }
1264
1264
  function visitChildSchemas(node, visit) {
1265
1265
  for (const { key, kind } of CHILD_SCHEMA_SLOTS) {
1266
1266
  const value = node[key];
1267
1267
  if (kind === "single") {
1268
- if (isRecord$26(value)) visit(value);
1268
+ if (isRecord$27(value)) visit(value);
1269
1269
  } else if (kind === "array") {
1270
1270
  if (Array.isArray(value)) for (const item of value) visit(item);
1271
1271
  } else if (kind === "map") {
1272
- if (isRecord$26(value)) for (const item of Object.values(value)) visit(item);
1272
+ if (isRecord$27(value)) for (const item of Object.values(value)) visit(item);
1273
1273
  } else if (kind === "schema-or-array") {
1274
- if (isRecord$26(value)) visit(value);
1274
+ if (isRecord$27(value)) visit(value);
1275
1275
  else if (Array.isArray(value)) for (const item of value) visit(item);
1276
1276
  }
1277
1277
  }
@@ -1283,7 +1283,7 @@ function childSchemaKeysForParentType(parentType) {
1283
1283
  });
1284
1284
  }
1285
1285
  function normalizeProperty(node) {
1286
- if (!isRecord$26(node)) return;
1286
+ if (!isRecord$27(node)) return;
1287
1287
  if (!hasOwn(node, "type") && !hasAnyKey(node, TYPE_COMPLETION_SKIP_KEYS)) {
1288
1288
  const enumValues = node["enum"];
1289
1289
  if (Array.isArray(enumValues) && enumValues.length > 0) node["type"] = inferTypeFromValues(enumValues);
@@ -1367,14 +1367,14 @@ function hasAnyKey(obj, keys) {
1367
1367
  }
1368
1368
  function cloneJsonValue(value) {
1369
1369
  if (Array.isArray(value)) return value.map((item) => cloneJsonValue(item));
1370
- if (isRecord$26(value)) {
1370
+ if (isRecord$27(value)) {
1371
1371
  const cloned = {};
1372
1372
  for (const [key, child] of Object.entries(value)) cloned[key] = cloneJsonValue(child);
1373
1373
  return cloned;
1374
1374
  }
1375
1375
  return value;
1376
1376
  }
1377
- function isRecord$26(value) {
1377
+ function isRecord$27(value) {
1378
1378
  return typeof value === "object" && value !== null && !Array.isArray(value);
1379
1379
  }
1380
1380
  function hasOwn(obj, key) {
@@ -2583,14 +2583,14 @@ function extractUsageFromChunk(chunk) {
2583
2583
  }
2584
2584
  function contextOverflowOutputCap(error, currentCap) {
2585
2585
  const maxContext = error.maxContextTokens;
2586
- const counts = /requested ([\d,_]+) output tokens and your prompt contains (?:at least )?([\d,_]+) input tokens/i.exec(error.message);
2586
+ const counts = /requested ([\d,_]+) output tokens and your prompt contains (at least )?([\d,_]+) input tokens/i.exec(error.message);
2587
2587
  if (maxContext === void 0 || counts === null || !Number.isSafeInteger(maxContext) || maxContext <= 0) return;
2588
2588
  const requestedOutput = Number(counts[1].replaceAll(/[,_]/g, ""));
2589
- const input = Number(counts[2].replaceAll(/[,_]/g, ""));
2589
+ const input = Number(counts[3].replaceAll(/[,_]/g, ""));
2590
2590
  if (!Number.isSafeInteger(input) || input < 0 || !Number.isSafeInteger(requestedOutput) || requestedOutput <= 0 || !Number.isSafeInteger(input + requestedOutput) || input + requestedOutput <= maxContext) return;
2591
2591
  const available = maxContext - input;
2592
2592
  const headroom = Math.min(1024, Math.max(1, Math.ceil(available * .01)));
2593
- const cap = Math.min(requestedOutput - 1, available - headroom);
2593
+ const cap = Math.min(counts[2] === void 0 ? requestedOutput - 1 : Math.floor(requestedOutput / 2), available - headroom);
2594
2594
  if (cap < 1 || currentCap !== void 0 && (typeof currentCap !== "number" || !Number.isSafeInteger(currentCap) || cap >= currentCap)) return;
2595
2595
  return cap;
2596
2596
  }
@@ -10642,7 +10642,7 @@ function tokenFromWire(wire) {
10642
10642
  var init_types$17 = __esmMin((() => {}));
10643
10643
  //#endregion
10644
10644
  //#region ../../packages/oauth/src/utils.ts
10645
- function isRecord$25(value) {
10645
+ function isRecord$26(value) {
10646
10646
  return typeof value === "object" && value !== null && !Array.isArray(value);
10647
10647
  }
10648
10648
  var init_utils$1 = __esmMin((() => {}));
@@ -10966,7 +10966,7 @@ var init_storage = __esmMin((() => {
10966
10966
  } catch {
10967
10967
  return;
10968
10968
  }
10969
- if (!isRecord$25(parsed)) return void 0;
10969
+ if (!isRecord$26(parsed)) return void 0;
10970
10970
  return tokenFromWire(parsed);
10971
10971
  }
10972
10972
  async save(name, token) {
@@ -11060,7 +11060,7 @@ function extractApiErrorMessage(value) {
11060
11060
  }
11061
11061
  return;
11062
11062
  }
11063
- if (!isRecord$25(value)) return void 0;
11063
+ if (!isRecord$26(value)) return void 0;
11064
11064
  for (const key of DIRECT_ERROR_KEYS) {
11065
11065
  const message = stringField$4(value, key);
11066
11066
  if (message !== void 0) return message;
@@ -11068,7 +11068,7 @@ function extractApiErrorMessage(value) {
11068
11068
  const error = value["error"];
11069
11069
  const errorString = nonEmptyString$7(error);
11070
11070
  if (errorString !== void 0) return errorString;
11071
- if (isRecord$25(error)) for (const key of NESTED_ERROR_KEYS) {
11071
+ if (isRecord$26(error)) for (const key of NESTED_ERROR_KEYS) {
11072
11072
  const message = stringField$4(error, key);
11073
11073
  if (message !== void 0) return message;
11074
11074
  }
@@ -11158,7 +11158,7 @@ async function postForm(url, params, deviceHeaders, options) {
11158
11158
  let data = {};
11159
11159
  try {
11160
11160
  const parsed = await response.json();
11161
- if (isRecord$25(parsed)) data = parsed;
11161
+ if (isRecord$26(parsed)) data = parsed;
11162
11162
  } catch {}
11163
11163
  return {
11164
11164
  status,
@@ -13070,9 +13070,9 @@ function blunContextWindowsUrl(oauthHost) {
13070
13070
  return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}/api/verbrauch/tarife`;
13071
13071
  }
13072
13072
  function parseManagedContextWindow(payload, plan) {
13073
- if (!isRecord$25(payload)) return void 0;
13073
+ if (!isRecord$26(payload)) return void 0;
13074
13074
  const contextWindows = payload["kontext"];
13075
- if (!isRecord$25(contextWindows)) return void 0;
13075
+ if (!isRecord$26(contextWindows)) return void 0;
13076
13076
  const value = contextWindows[plan];
13077
13077
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
13078
13078
  }
@@ -13107,7 +13107,7 @@ function parseManagedUsagePayload(payload) {
13107
13107
  const plan = typeof rec["plan"] === "string" && rec["plan"].trim().length > 0 ? rec["plan"].trim() : void 0;
13108
13108
  const contextWindowTokens = managedContextWindowFrom(rec);
13109
13109
  const unlimited = rec["unlimited"] === true;
13110
- const stand = isRecord$25(rec["stand"]) ? rec["stand"] : void 0;
13110
+ const stand = isRecord$26(rec["stand"]) ? rec["stand"] : void 0;
13111
13111
  if (stand !== void 0) for (const [sourceKey, id, label] of ACCOUNT_USAGE_WINDOWS) {
13112
13112
  const row = toAccountUsageRow(stand[sourceKey], id, label, unlimited);
13113
13113
  if (row !== null) limits.push(row);
@@ -13117,9 +13117,9 @@ function parseManagedUsagePayload(payload) {
13117
13117
  const item = rawLimits[idx];
13118
13118
  if (!item || typeof item !== "object") continue;
13119
13119
  const detailRaw = item["detail"];
13120
- const detail = isRecord$25(detailRaw) ? detailRaw : item;
13120
+ const detail = isRecord$26(detailRaw) ? detailRaw : item;
13121
13121
  const windowRaw = item["window"];
13122
- const row = toUsageRow(detail, limitLabel(item, detail, isRecord$25(windowRaw) ? windowRaw : {}, idx));
13122
+ const row = toUsageRow(detail, limitLabel(item, detail, isRecord$26(windowRaw) ? windowRaw : {}, idx));
13123
13123
  if (row !== null) limits.push(row);
13124
13124
  }
13125
13125
  return {
@@ -13143,7 +13143,7 @@ function managedContextWindowFrom(payload) {
13143
13143
  return values.every((value) => value === first) ? first : void 0;
13144
13144
  }
13145
13145
  function toAccountUsageRow(raw, id, label, accountUnlimited) {
13146
- if (!isRecord$25(raw)) return null;
13146
+ if (!isRecord$26(raw)) return null;
13147
13147
  const used = toInt(raw["verbraucht"]);
13148
13148
  const unlimited = accountUnlimited || raw["unlimited"] === true;
13149
13149
  const fraction = raw["anteil"];
@@ -13176,7 +13176,7 @@ function toAccountUsageRow(raw, id, label, accountUnlimited) {
13176
13176
  };
13177
13177
  }
13178
13178
  function toUsageRow(raw, defaultLabel) {
13179
- if (!isRecord$25(raw)) return null;
13179
+ if (!isRecord$26(raw)) return null;
13180
13180
  const unlimited = raw["unlimited"] === true;
13181
13181
  const limit = toInt(raw["limit"]);
13182
13182
  let used = toInt(raw["used"]);
@@ -13297,7 +13297,7 @@ function isManagedQuotaErrorMessage(message) {
13297
13297
  return /you(?:'|’)?ve reached your usage limit/.test(normalized) && /billing cycle|quota will be (?:refreshed|reset)|purchase extra usage/.test(normalized);
13298
13298
  }
13299
13299
  function hasManagedUsageShape(payload) {
13300
- if (!isRecord$25(payload)) return false;
13300
+ if (!isRecord$26(payload)) return false;
13301
13301
  let recognized = false;
13302
13302
  if ("context_window_tokens" in payload || "contextWindowTokens" in payload) {
13303
13303
  recognized = true;
@@ -13313,15 +13313,15 @@ function hasManagedUsageShape(payload) {
13313
13313
  if (!Array.isArray(limits)) return false;
13314
13314
  for (let index = 0; index < limits.length; index++) {
13315
13315
  const item = limits[index];
13316
- if (!isRecord$25(item)) return false;
13317
- const detail = isRecord$25(item["detail"]) ? item["detail"] : item;
13318
- if (toUsageRow(detail, limitLabel(item, detail, isRecord$25(item["window"]) ? item["window"] : {}, index)) === null) return false;
13316
+ if (!isRecord$26(item)) return false;
13317
+ const detail = isRecord$26(item["detail"]) ? item["detail"] : item;
13318
+ if (toUsageRow(detail, limitLabel(item, detail, isRecord$26(item["window"]) ? item["window"] : {}, index)) === null) return false;
13319
13319
  }
13320
13320
  }
13321
13321
  if ("stand" in payload) {
13322
13322
  recognized = true;
13323
13323
  const stand = payload["stand"];
13324
- if (!isRecord$25(stand)) return false;
13324
+ if (!isRecord$26(stand)) return false;
13325
13325
  const windows = ACCOUNT_USAGE_WINDOWS.filter(([sourceKey]) => sourceKey in stand);
13326
13326
  if (windows.length === 0) return false;
13327
13327
  const unlimited = payload["unlimited"] === true;
@@ -13417,8 +13417,8 @@ function userExtras(existing, remoteOwnedFields) {
13417
13417
  return out;
13418
13418
  }
13419
13419
  function mergeRefreshedModelAlias(existing, remote, remoteOwnedFields) {
13420
- const current = isRecord$25(existing) ? existing : {};
13421
- const overrides = cloneOverrides(isRecord$25(current["overrides"]) ? current["overrides"] : void 0);
13420
+ const current = isRecord$26(existing) ? existing : {};
13421
+ const overrides = cloneOverrides(isRecord$26(current["overrides"]) ? current["overrides"] : void 0);
13422
13422
  return {
13423
13423
  ...userExtras(current, remoteOwnedFields),
13424
13424
  ...remote,
@@ -13600,7 +13600,7 @@ function parseModelContextLength(item, modelId) {
13600
13600
  return values[0];
13601
13601
  }
13602
13602
  function toModelInfo(item) {
13603
- if (!isRecord$25(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
13603
+ if (!isRecord$26(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
13604
13604
  const contextLength = parseModelContextLength(item, item["id"]);
13605
13605
  const displayName = item["display_name"];
13606
13606
  const normalizedDisplayName = typeof displayName === "string" && displayName.length > 0 ? displayName : void 0;
@@ -13687,7 +13687,7 @@ async function fetchManagedBlunCodeModels(options) {
13687
13687
  throw new Error(message);
13688
13688
  }
13689
13689
  const payload = await response.json();
13690
- if (!isRecord$25(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
13690
+ if (!isRecord$26(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
13691
13691
  return payload["data"].map((item) => toModelInfo(item)).filter((item) => item !== void 0);
13692
13692
  }
13693
13693
  throw new Error(`Failed to list BLUN models for ${baseUrl}.`);
@@ -13730,11 +13730,11 @@ function applyManagedBlunCodeConfig(config, options) {
13730
13730
  apiKey
13731
13731
  };
13732
13732
  const upstreamKeys = new Set(options.models.map((m) => managedModelKey(m.id)));
13733
- for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$25(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
13733
+ for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$26(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
13734
13734
  for (const model of options.models) {
13735
13735
  const capabilities = capabilitiesForModel(model);
13736
13736
  const key = managedModelKey(model.id);
13737
- const existing = isRecord$25(existingModels[key]) ? existingModels[key] : {};
13737
+ const existing = isRecord$26(existingModels[key]) ? existingModels[key] : {};
13738
13738
  const supportsAdaptiveThinking = capabilities?.includes("thinking") === true || capabilities?.includes("always_thinking") === true;
13739
13739
  existingModels[key] = mergeRefreshedModelAlias(existing, {
13740
13740
  provider: BLUN_PROVIDER_NAME$1,
@@ -13782,7 +13782,7 @@ function applyManagedBlunCodeLogoutConfig(config) {
13782
13782
  let removedDefaultModel = false;
13783
13783
  const existingModels = config.models ?? {};
13784
13784
  for (const [key, model] of Object.entries(existingModels)) {
13785
- if (!isRecord$25(model) || model["provider"] !== "managed:blun") continue;
13785
+ if (!isRecord$26(model) || model["provider"] !== "managed:blun") continue;
13786
13786
  delete existingModels[key];
13787
13787
  if (config.defaultModel === key) removedDefaultModel = true;
13788
13788
  }
@@ -13822,7 +13822,7 @@ function selectDefaultModel(config, models, options) {
13822
13822
  function canPreserveDefaultModel(existingModels, defaultModel, managedModels) {
13823
13823
  if (managedModels.has(defaultModel)) return true;
13824
13824
  const existing = existingModels[defaultModel];
13825
- return isRecord$25(existing) && existing["provider"] !== "managed:blun";
13825
+ return isRecord$26(existing) && existing["provider"] !== "managed:blun";
13826
13826
  }
13827
13827
  function assertPositiveContextLength(model) {
13828
13828
  if (!Number.isInteger(model.contextLength) || model.contextLength <= 0) throw new Error(`BLUN model "${model.id}" must include a positive context_length.`);
@@ -13900,13 +13900,13 @@ function blunManagedQuotaUrl(oauthHost) {
13900
13900
  return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}${MANAGED_QUOTA_PATH}`;
13901
13901
  }
13902
13902
  function parseManagedQuotaPayload(payload) {
13903
- if (!isRecord$25(payload)) return void 0;
13903
+ if (!isRecord$26(payload)) return void 0;
13904
13904
  const plan = nonEmptyString$6(payload["plan"]);
13905
13905
  const paid = payload["bezahlt"];
13906
13906
  const creditCents = payload["guthaben_cent"];
13907
13907
  const billingKind = nonEmptyString$6(payload["art"]);
13908
13908
  const globalUnlimited = payload["unlimited"];
13909
- if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$25(payload["stand"])) return;
13909
+ if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$26(payload["stand"])) return;
13910
13910
  if (!hasStrictQuotaStand(payload["stand"], globalUnlimited === true)) return void 0;
13911
13911
  const limits = parseManagedUsagePayload(payload).limits;
13912
13912
  if (limits.length !== REQUIRED_WINDOWS.length || REQUIRED_WINDOWS.some(([, id]) => limits.filter((row) => row.id === id).length !== 1)) return;
@@ -13976,7 +13976,7 @@ function nonEmptyString$6(value) {
13976
13976
  function hasStrictQuotaStand(stand, globalUnlimited) {
13977
13977
  return REQUIRED_WINDOWS.every(([sourceKey]) => {
13978
13978
  const row = stand[sourceKey];
13979
- if (!isRecord$25(row)) return false;
13979
+ if (!isRecord$26(row)) return false;
13980
13980
  const used = row["verbraucht"];
13981
13981
  const rowUnlimited = row["unlimited"];
13982
13982
  if (rowUnlimited !== void 0 && typeof rowUnlimited !== "boolean") return false;
@@ -21163,7 +21163,7 @@ function parseSkillText(options) {
21163
21163
  throw error;
21164
21164
  }
21165
21165
  const frontmatter = parsed.data ?? {};
21166
- if (!isRecord$24(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
21166
+ if (!isRecord$25(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
21167
21167
  const metadata = normalizeMetadata(frontmatter);
21168
21168
  if (!isSupportedSkillType(metadata.type)) throw new UnsupportedSkillTypeError(metadata.type ?? String(frontmatter["type"]));
21169
21169
  const name = nonEmptyString$4(metadata.name);
@@ -21276,7 +21276,7 @@ function tokenizeArgs(raw) {
21276
21276
  function nonEmptyString$4(value) {
21277
21277
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
21278
21278
  }
21279
- function isRecord$24(value) {
21279
+ function isRecord$25(value) {
21280
21280
  return typeof value === "object" && value !== null && !Array.isArray(value);
21281
21281
  }
21282
21282
  var import_regexp_escape, FrontmatterError, SkillParseError, UnsupportedSkillTypeError, FENCE, METADATA_ALIASES;
@@ -21325,7 +21325,7 @@ var init_parser$1 = __esmMin((() => {
21325
21325
  function parseCommandText(input) {
21326
21326
  const { text, commandPath, pluginId } = input;
21327
21327
  const parsed = parseFrontmatter(text);
21328
- const frontmatter = isRecord$23(parsed.data) ? parsed.data : {};
21328
+ const frontmatter = isRecord$24(parsed.data) ? parsed.data : {};
21329
21329
  const baseName = input.fallbackName ?? path.basename(commandPath).replace(/\.md$/i, "");
21330
21330
  const name = nonEmptyString$3(frontmatter["name"]) ?? baseName;
21331
21331
  const body = parsed.body.trim();
@@ -21367,7 +21367,7 @@ function descriptionFromBody(body) {
21367
21367
  if (firstLine === void 0) return "No description provided.";
21368
21368
  return firstLine.length > 240 ? `${firstLine.slice(0, 239)}…` : firstLine;
21369
21369
  }
21370
- function isRecord$23(value) {
21370
+ function isRecord$24(value) {
21371
21371
  return typeof value === "object" && value !== null && !Array.isArray(value);
21372
21372
  }
21373
21373
  var init_commands = __esmMin((() => {
@@ -28918,7 +28918,7 @@ var init_per_id_json_store = __esmMin((() => {
28918
28918
  }));
28919
28919
  //#endregion
28920
28920
  //#region ../../packages/agent-core/src/agent/background/resume-store.ts
28921
- var BACKGROUND_TASK_ID, id, digest$2, timestamp$2, ResumeIntentSchema, hash$3, isRecord$22, TaskResumeStore;
28921
+ var BACKGROUND_TASK_ID, id, digest$2, timestamp$2, ResumeIntentSchema, hash$3, isRecord$23, TaskResumeStore;
28922
28922
  var init_resume_store = __esmMin((() => {
28923
28923
  init_zod$1();
28924
28924
  BACKGROUND_TASK_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*-[0-9a-z]{8}$/;
@@ -28943,7 +28943,7 @@ var init_resume_store = __esmMin((() => {
28943
28943
  startedAt: timestamp$2.nullable()
28944
28944
  }).strict();
28945
28945
  hash$3 = (value) => createHash("sha256").update(value).digest("hex");
28946
- isRecord$22 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
28946
+ isRecord$23 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
28947
28947
  TaskResumeStore = class {
28948
28948
  home;
28949
28949
  constructor(home) {
@@ -28998,9 +28998,9 @@ var init_resume_store = __esmMin((() => {
28998
28998
  }
28999
28999
  async readOwnedTask(taskId) {
29000
29000
  const task = await this.read("tasks", taskId);
29001
- if (!isRecord$22(task)) throw new Error("Task has no persisted local record.");
29001
+ if (!isRecord$23(task)) throw new Error("Task has no persisted local record.");
29002
29002
  const owner = task["resumeOwnership"];
29003
- if (!isRecord$22(owner) || owner["version"] !== 1 || owner["scope"] !== hash$3(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.");
29003
+ if (!isRecord$23(owner) || owner["version"] !== 1 || owner["scope"] !== hash$3(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.");
29004
29004
  const { resumeOwnership: _ownership, ...info } = task;
29005
29005
  return info;
29006
29006
  }
@@ -29121,12 +29121,12 @@ function legacyStatusToCurrent$1(task) {
29121
29121
  return task.status;
29122
29122
  }
29123
29123
  function isReadablePersistedTask$1(obj) {
29124
- return isRecord$21(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
29124
+ return isRecord$22(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
29125
29125
  }
29126
29126
  function isLegacyPersistedTask$1(task) {
29127
29127
  return "task_id" in task;
29128
29128
  }
29129
- function isRecord$21(value) {
29129
+ function isRecord$22(value) {
29130
29130
  return typeof value === "object" && value !== null;
29131
29131
  }
29132
29132
  function optionalNonEmptyString$2(value) {
@@ -228703,7 +228703,7 @@ function escapeXml(value) {
228703
228703
  function locationKey(messageIndex, partIndex) {
228704
228704
  return `${String(messageIndex)}:${String(partIndex)}`;
228705
228705
  }
228706
- function isRecord$20(value) {
228706
+ function isRecord$21(value) {
228707
228707
  return value !== null && typeof value === "object" && !Array.isArray(value);
228708
228708
  }
228709
228709
  function isNonNegativeInteger$1(value) {
@@ -228904,7 +228904,7 @@ var init_vision_reader = __esmMin((() => {
228904
228904
  reason: "malformed"
228905
228905
  };
228906
228906
  }
228907
- if (!isRecord$20(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger$1(payload["prompt_eval_count"]) || !isNonNegativeInteger$1(payload["eval_count"])) return {
228907
+ if (!isRecord$21(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger$1(payload["prompt_eval_count"]) || !isNonNegativeInteger$1(payload["eval_count"])) return {
228908
228908
  ok: false,
228909
228909
  reason: "malformed"
228910
228910
  };
@@ -230341,7 +230341,7 @@ var init_full = __esmMin((() => {
230341
230341
  this.agent.log.error("failed to refresh system prompt after compaction", { error });
230342
230342
  }
230343
230343
  await this.agent.injection.injectAfterCompaction();
230344
- this.fitRetainedInput();
230344
+ this.fitRetainedInput({}, result.keptHeadUserMessageCount !== void 0);
230345
230345
  this.lastCompactedState = {
230346
230346
  tokenCount: this.tokenCountWithPending,
230347
230347
  modelAlias: this.agent.activeResponderModel ?? this.agent.config.modelAlias,
@@ -230377,17 +230377,18 @@ var init_full = __esmMin((() => {
230377
230377
  this.agent.turn.onCompactionFinished();
230378
230378
  }
230379
230379
  }
230380
- fitRetainedInput(context = {}) {
230380
+ fitRetainedInput(context = {}, freshBudgetedSelection = false) {
230381
230381
  const budget = this.getCompactionBudgetTokens();
230382
230382
  const window = this.getEffectiveMaxContextTokens();
230383
230383
  const limit = window > 0 ? window - 1 : Infinity;
230384
+ const hardContextLimit = window > 0 && !freshBudgetedSelection ? window : void 0;
230384
230385
  const estimate = (messages) => this.estimateProjectedRequestTokens({
230385
230386
  ...context,
230386
230387
  messages
230387
230388
  });
230388
230389
  const preserveLatestUser = this.agent.turn.hasActiveTurn;
230389
- if (budget === void 0) return this.agent.context.fitCompactionPrefix(limit, estimate, preserveLatestUser);
230390
- return this.agent.context.fitCompactionPrefix(Math.min(Math.floor(budget * .8), limit), estimate, preserveLatestUser) || this.agent.context.fitCompactionPrefix(Math.min(Math.floor(budget * .9) - 1, limit), estimate, preserveLatestUser);
230390
+ if (budget === void 0) return this.agent.context.fitCompactionPrefix(limit, estimate, preserveLatestUser, hardContextLimit);
230391
+ return this.agent.context.fitCompactionPrefix(Math.min(Math.floor(budget * .8), limit), estimate, preserveLatestUser, hardContextLimit) || this.agent.context.fitCompactionPrefix(Math.min(Math.floor(budget * .9) - 1, limit), estimate, preserveLatestUser, hardContextLimit);
230391
230392
  }
230392
230393
  buildInstruction(customInstruction) {
230393
230394
  return renderPrompt(compaction_instruction_default, { customInstruction: customInstruction?.trim() ?? "" }).trimEnd();
@@ -234338,7 +234339,7 @@ var init_context$2 = __esmMin((() => {
234338
234339
  this.agent.microCompaction.reset();
234339
234340
  this.agent.emitStatusUpdated();
234340
234341
  }
234341
- fitCompactionPrefix(maxRequestTokens, estimateRequest, preserveLatestUser = false) {
234342
+ fitCompactionPrefix(maxRequestTokens, estimateRequest, preserveLatestUser = false, hardContextLimit) {
234342
234343
  const prefixLength = this._history.findIndex((message) => message.origin?.kind === "compaction_summary");
234343
234344
  if (prefixLength <= 0 || !Number.isSafeInteger(maxRequestTokens) || maxRequestTokens <= 0) return false;
234344
234345
  const suffix = this._history.slice(prefixLength);
@@ -234350,7 +234351,9 @@ var init_context$2 = __esmMin((() => {
234350
234351
  ];
234351
234352
  return Math.max(estimateTokensForMessages(messages), estimateRequest(project(messages, { dropOrphanResults: true })));
234352
234353
  };
234353
- if (estimate(this._history.slice(0, prefixLength)) <= maxRequestTokens) return false;
234354
+ const requestTokens = estimate(this._history.slice(0, prefixLength));
234355
+ if (requestTokens <= maxRequestTokens) return false;
234356
+ if (hardContextLimit !== void 0 && requestTokens >= hardContextLimit) return false;
234354
234357
  const sourceKey = Symbol("compaction source");
234355
234358
  const sources = collectCompactableUserMessages(this._history.slice(0, prefixLength)).map((message) => ({
234356
234359
  ...message,
@@ -235042,7 +235045,7 @@ function structuredOutput(stdout, input) {
235042
235045
  return {
235043
235046
  ...result,
235044
235047
  additionalContext: input["hook_event_name"] === "UserPromptSubmit" && hookSpecificOutput?.hookEventName === "UserPromptSubmit" ? hookSpecificOutput.additionalContext : void 0,
235045
- updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$19(hookSpecificOutput.updatedInput) ? hookSpecificOutput.updatedInput : void 0
235048
+ updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$20(hookSpecificOutput.updatedInput) ? hookSpecificOutput.updatedInput : void 0
235046
235049
  };
235047
235050
  }
235048
235051
  return {
@@ -235111,7 +235114,7 @@ function killProcessTreeWindows(child, force) {
235111
235114
  } catch {}
235112
235115
  }
235113
235116
  }
235114
- function isRecord$19(value) {
235117
+ function isRecord$20(value) {
235115
235118
  return typeof value === "object" && value !== null && !Array.isArray(value);
235116
235119
  }
235117
235120
  function errorMessage$12(error) {
@@ -235128,7 +235131,7 @@ var init_runner = __esmMin((() => {
235128
235131
  if (typeof value === "string") return value;
235129
235132
  if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
235130
235133
  }, string().optional());
235131
- HookSpecificOutputSchema = preprocess((value) => isRecord$19(value) ? value : void 0, looseObject({
235134
+ HookSpecificOutputSchema = preprocess((value) => isRecord$20(value) ? value : void 0, looseObject({
235132
235135
  message: OptionalStringSchema,
235133
235136
  additionalContext: OptionalStringSchema,
235134
235137
  permissionDecision: unknown().optional(),
@@ -235303,7 +235306,16 @@ var init_engine = __esmMin((() => {
235303
235306
  };
235304
235307
  }
235305
235308
  if (this.admissionClosed) return void 0;
235306
- return runHook(hook.command, inputData, {
235309
+ let hookInput;
235310
+ try {
235311
+ hookInput = this.options.runtimeInput?.(hook, inputData) ?? inputData;
235312
+ } catch {
235313
+ return {
235314
+ action: "block",
235315
+ reason: "Hook input preparation failed."
235316
+ };
235317
+ }
235318
+ return runHook(hook.command, hookInput, {
235307
235319
  timeout: hook.timeout ?? DEFAULT_HOOK_TIMEOUT_SECONDS,
235308
235320
  cwd: hook.cwd ?? (this.options.cwd === "" ? void 0 : this.options.cwd),
235309
235321
  env: hook.env,
@@ -236390,7 +236402,7 @@ function isTelegramGroupInput(input) {
236390
236402
  return chatId === void 0 || chatId.startsWith("-");
236391
236403
  });
236392
236404
  }
236393
- function isPersonalMemoryToolName$1(name) {
236405
+ function isPersonalMemoryToolName$2(name) {
236394
236406
  return name.startsWith("mcp__personal-memory__");
236395
236407
  }
236396
236408
  function isPersonalMemoryRecallToolName(name) {
@@ -236404,7 +236416,7 @@ function parsePersonalMemoryRecall(output) {
236404
236416
  } catch {
236405
236417
  return { kind: "invalid" };
236406
236418
  }
236407
- if (!isRecord$18(parsed) || !isRecord$18(parsed["personal_memory"])) return { kind: "invalid" };
236419
+ if (!isRecord$19(parsed) || !isRecord$19(parsed["personal_memory"])) return { kind: "invalid" };
236408
236420
  const memory = parsed["personal_memory"];
236409
236421
  const savedRaw = memory["saved"];
236410
236422
  const threadsRaw = memory["threads"];
@@ -236413,7 +236425,7 @@ function parsePersonalMemoryRecall(output) {
236413
236425
  if (savedRaw.length > MAX_SAVED_MEMORIES || threadsRaw.length > MAX_THREADS || historyRaw.length > 0) return { kind: "invalid" };
236414
236426
  const saved = [];
236415
236427
  for (const value of savedRaw) {
236416
- if (!isRecord$18(value)) return { kind: "invalid" };
236428
+ if (!isRecord$19(value)) return { kind: "invalid" };
236417
236429
  const text = boundedTrimmedString(value["text"], MAX_MEMORY_TEXT_CHARS);
236418
236430
  const confidence = value["confidence"];
236419
236431
  if (text === void 0 || typeof confidence !== "string" || !CONFIDENCE_VALUES.has(confidence)) return { kind: "invalid" };
@@ -236424,7 +236436,7 @@ function parsePersonalMemoryRecall(output) {
236424
236436
  }
236425
236437
  const threads = [];
236426
236438
  for (const value of threadsRaw) {
236427
- if (!isRecord$18(value)) return { kind: "invalid" };
236439
+ if (!isRecord$19(value)) return { kind: "invalid" };
236428
236440
  const title = boundedTrimmedString(value["title"], MAX_THREAD_TITLE_CHARS);
236429
236441
  const summary = boundedTrimmedString(value["summary"], MAX_THREAD_SUMMARY_CHARS);
236430
236442
  if (title === void 0 || summary === void 0) return { kind: "invalid" };
@@ -236478,7 +236490,7 @@ function boundedTrimmedString(value, maxChars) {
236478
236490
  const trimmed = value.trim();
236479
236491
  return trimmed.length > 0 ? trimmed : void 0;
236480
236492
  }
236481
- function isRecord$18(value) {
236493
+ function isRecord$19(value) {
236482
236494
  return typeof value === "object" && value !== null && !Array.isArray(value);
236483
236495
  }
236484
236496
  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;
@@ -236568,8 +236580,8 @@ var init_personal_memory_recall = __esmMin((() => {
236568
236580
  * to read, write, list, or change any personal-memory state.
236569
236581
  */
236570
236582
  filterToolsForTurn(turnId, input, origin, tools) {
236571
- if (this.toolsAllowedForTurn(turnId, input, origin)) return tools.filter((tool) => !isPersonalMemoryRecallToolName(tool.name) && (!isPersonalMemoryToolName$1(tool.name) || this.isTrustedHostTool(tool.name)));
236572
- return tools.filter((tool) => !isPersonalMemoryToolName$1(tool.name));
236583
+ if (this.toolsAllowedForTurn(turnId, input, origin)) return tools.filter((tool) => !isPersonalMemoryRecallToolName(tool.name) && (!isPersonalMemoryToolName$2(tool.name) || this.isTrustedHostTool(tool.name)));
236584
+ return tools.filter((tool) => !isPersonalMemoryToolName$2(tool.name));
236573
236585
  }
236574
236586
  isTrustedHostTool(name) {
236575
236587
  const isHostTool = this.agent.isPersonalMemoryHostTool;
@@ -265009,6 +265021,71 @@ var init_response_review_decision = __esmMin((() => {
265009
265021
  ]);
265010
265022
  }));
265011
265023
  //#endregion
265024
+ //#region ../../packages/agent-core/src/agent/response-review-deadline.ts
265025
+ function createResponseReviewDeadline(source) {
265026
+ const absoluteExpiresAt = performance.now() + ABSOLUTE_TIMEOUT_MS;
265027
+ const absolute = createDeadlineAbortSignal(source, ABSOLUTE_TIMEOUT_MS);
265028
+ const controller = new AbortController();
265029
+ const unlink = linkAbortSignal(absolute.signal, controller);
265030
+ let stage = "setup";
265031
+ let didTimeout = false;
265032
+ let closed = false;
265033
+ let idle;
265034
+ let idleExpiresAt = 0;
265035
+ const expire = () => {
265036
+ didTimeout = true;
265037
+ controller.abort(abortError$1());
265038
+ };
265039
+ const expireIfDue = () => {
265040
+ if (closed || controller.signal.aborted) return;
265041
+ const now = performance.now();
265042
+ if (now >= absoluteExpiresAt || now >= idleExpiresAt) expire();
265043
+ };
265044
+ const refresh = (timeoutMs) => {
265045
+ idleExpiresAt = performance.now() + timeoutMs;
265046
+ if (idle !== void 0) clearTimeout(idle);
265047
+ idle = setTimeout(expire, timeoutMs);
265048
+ };
265049
+ refresh(IDLE_TIMEOUT_MS);
265050
+ return {
265051
+ signal: controller.signal,
265052
+ timedOut: () => didTimeout || absolute.timedOut(),
265053
+ throwIfAborted: () => {
265054
+ expireIfDue();
265055
+ controller.signal.throwIfAborted();
265056
+ },
265057
+ progress: (event) => {
265058
+ expireIfDue();
265059
+ if (closed || controller.signal.aborted) return;
265060
+ if (event === "native.start" && stage === "setup") {
265061
+ stage = "native";
265062
+ refresh(NATIVE_FIRST_CONTENT_MS);
265063
+ } else if (event === "native.text" && stage === "native") refresh(IDLE_TIMEOUT_MS);
265064
+ else if (event === "release.start" && stage === "native") {
265065
+ stage = "release";
265066
+ refresh(IDLE_TIMEOUT_MS);
265067
+ } else if (event === "verification.start" && stage === "release") {
265068
+ stage = "verification";
265069
+ refresh(IDLE_TIMEOUT_MS);
265070
+ }
265071
+ },
265072
+ clear: () => {
265073
+ closed = true;
265074
+ if (idle !== void 0) clearTimeout(idle);
265075
+ idle = void 0;
265076
+ unlink();
265077
+ absolute.clear();
265078
+ }
265079
+ };
265080
+ }
265081
+ var IDLE_TIMEOUT_MS, NATIVE_FIRST_CONTENT_MS, ABSOLUTE_TIMEOUT_MS;
265082
+ var init_response_review_deadline = __esmMin((() => {
265083
+ init_abort();
265084
+ IDLE_TIMEOUT_MS = 3e4;
265085
+ NATIVE_FIRST_CONTENT_MS = 9e4;
265086
+ ABSOLUTE_TIMEOUT_MS = 12e4;
265087
+ }));
265088
+ //#endregion
265012
265089
  //#region ../../packages/agent-core/src/agent/response-review.ts
265013
265090
  function createReviewedOutputDispatcher(options) {
265014
265091
  let pending = [];
@@ -265094,6 +265171,7 @@ function createReviewedOutputDispatcher(options) {
265094
265171
  if (pending.length === 0) return options.dispatch(event);
265095
265172
  if (event.uuid !== stepUuid) throw new Error("Response review step mismatch");
265096
265173
  const currentEpoch = epoch;
265174
+ const isCurrentCandidate = () => epoch === currentEpoch;
265097
265175
  const parts = [...pending];
265098
265176
  reviewing = true;
265099
265177
  const text = parts.map((part) => part.part.type === "text" ? part.part.text : "").join("");
@@ -265107,8 +265185,9 @@ function createReviewedOutputDispatcher(options) {
265107
265185
  for (let attempt = 1; attempt <= MAX_REVIEW_ATTEMPTS; attempt += 1) {
265108
265186
  options.signal.throwIfAborted();
265109
265187
  if (epoch !== currentEpoch) throw new Error("Response review candidate changed during verification");
265110
- const deadline = createDeadlineAbortSignal(options.signal, REVIEW_TIMEOUT_MS);
265188
+ const deadline = createResponseReviewDeadline(options.signal);
265111
265189
  let requested;
265190
+ const pendingOperations = [];
265112
265191
  let attemptRejection;
265113
265192
  let attemptNativeRejection = false;
265114
265193
  try {
@@ -265117,6 +265196,12 @@ function createReviewedOutputDispatcher(options) {
265117
265196
  turnId: event.turnId,
265118
265197
  step: event.step,
265119
265198
  signal: deadline.signal,
265199
+ onProgress: (progress) => {
265200
+ if (isCurrentCandidate()) deadline.progress(progress);
265201
+ },
265202
+ onPendingOperation: (operation) => {
265203
+ pendingOperations.push(operation.then(() => void 0, () => void 0));
265204
+ },
265120
265205
  onRejected: (decision) => {
265121
265206
  if (!deadline.signal.aborted) {
265122
265207
  const message = rejectionMessage(decision);
@@ -265126,13 +265211,14 @@ function createReviewedOutputDispatcher(options) {
265126
265211
  }
265127
265212
  });
265128
265213
  approval = await abortable(requested, deadline.signal);
265214
+ deadline.throwIfAborted();
265129
265215
  rejection = attemptRejection;
265130
265216
  nativeRejection = attemptNativeRejection;
265131
265217
  break;
265132
265218
  } catch {
265133
265219
  options.signal.throwIfAborted();
265134
265220
  if (attemptRejection !== void 0) throw new Error(attemptRejection);
265135
- if (deadline.timedOut() && attempt < MAX_REVIEW_ATTEMPTS && requested !== void 0 && epoch === currentEpoch && await waitForCancelledReview(requested)) continue;
265221
+ if (deadline.timedOut() && attempt < MAX_REVIEW_ATTEMPTS && requested !== void 0 && epoch === currentEpoch && await waitForCancelledReview(requested, pendingOperations)) continue;
265136
265222
  throw new Error(deadline.timedOut() ? "Response review timed out" : "Response review failed");
265137
265223
  } finally {
265138
265224
  deadline.clear();
@@ -265169,10 +265255,16 @@ function createReviewedOutputDispatcher(options) {
265169
265255
  if (epoch === currentEpoch) clear();
265170
265256
  }
265171
265257
  }
265172
- async function waitForCancelledReview(requested) {
265258
+ async function waitForCancelledReview(requested, pendingOperations) {
265173
265259
  const deadline = createDeadlineAbortSignal(options.signal, REVIEW_CANCEL_SETTLE_MS);
265174
265260
  try {
265175
265261
  await abortable(requested.then(() => void 0, () => void 0), deadline.signal);
265262
+ let observed = 0;
265263
+ while (observed < pendingOperations.length) {
265264
+ const batch = pendingOperations.slice(observed);
265265
+ observed = pendingOperations.length;
265266
+ await abortable(Promise.all(batch), deadline.signal);
265267
+ }
265176
265268
  options.signal.throwIfAborted();
265177
265269
  return true;
265178
265270
  } catch {
@@ -265184,13 +265276,13 @@ function createReviewedOutputDispatcher(options) {
265184
265276
  }
265185
265277
  return dispatch;
265186
265278
  }
265187
- var MAX_CANDIDATE_BYTES, MAX_CANDIDATE_PARTS, REVIEW_TIMEOUT_MS, REVIEW_CANCEL_SETTLE_MS, MAX_REVIEW_ATTEMPTS;
265279
+ var MAX_CANDIDATE_BYTES, MAX_CANDIDATE_PARTS, REVIEW_CANCEL_SETTLE_MS, MAX_REVIEW_ATTEMPTS;
265188
265280
  var init_response_review = __esmMin((() => {
265189
265281
  init_abort();
265190
265282
  init_response_review_decision();
265283
+ init_response_review_deadline();
265191
265284
  MAX_CANDIDATE_BYTES = 1048576;
265192
265285
  MAX_CANDIDATE_PARTS = 4096;
265193
- REVIEW_TIMEOUT_MS = 3e4;
265194
265286
  REVIEW_CANCEL_SETTLE_MS = 1e3;
265195
265287
  MAX_REVIEW_ATTEMPTS = 2;
265196
265288
  }));
@@ -269309,12 +269401,14 @@ function readPayload(result, includeError = false) {
269309
269401
  /** Receipts never enter ordinary tool execution, hooks, replay or model history. */
269310
269402
  function createGuardResponseReviewer(host) {
269311
269403
  const { language, guardVersion } = host;
269312
- return async ({ text, turnId, step, signal, onRejected }) => {
269404
+ return async ({ text, turnId, step, signal, onRejected, onPendingOperation, onProgress }) => {
269313
269405
  const input = {
269314
269406
  text,
269315
269407
  turnId,
269316
269408
  step,
269317
- signal
269409
+ signal,
269410
+ onPendingOperation,
269411
+ onProgress
269318
269412
  };
269319
269413
  const targetSha256 = digest(text);
269320
269414
  let stage = "setup";
@@ -269341,6 +269435,10 @@ function createGuardResponseReviewer(host) {
269341
269435
  const blocked = (reason, findings) => {
269342
269436
  record(signal.aborted ? "cancelled" : reason, findings);
269343
269437
  };
269438
+ const track = (operation) => {
269439
+ onPendingOperation?.(operation.then(() => void 0, () => void 0));
269440
+ return operation;
269441
+ };
269344
269442
  try {
269345
269443
  if (!/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/.test(language) || /^(auto|all)$/i.test(language) || guardVersion.trim().length === 0) return blocked("invalid_settings");
269346
269444
  const resolve = () => {
@@ -269353,13 +269451,14 @@ function createGuardResponseReviewer(host) {
269353
269451
  const current = () => !signal.aborted && resolve()?.client === connection.client;
269354
269452
  if (!current()) return blocked("connection_changed");
269355
269453
  stage = "native";
269356
- const native = await abortable(host.reviewNative({ ...input }), signal);
269454
+ onProgress?.("native.start");
269455
+ const native = await abortable(track(host.reviewNative({ ...input })), signal);
269357
269456
  if (!current()) return blocked("connection_changed");
269358
269457
  if (native === void 0) return blocked("native_unavailable");
269359
269458
  if (!passed(native.nativeness) || !passed(native.orthography)) return blocked("native_rejected");
269360
269459
  const authorized = async (name) => {
269361
269460
  if (!current()) return false;
269362
- return passed(await abortable(host.authorize({
269461
+ return passed(await abortable(track(host.authorize({
269363
269462
  toolName: qualifyMcpToolName(SERVER_NAME, name),
269364
269463
  targetSha256,
269365
269464
  language,
@@ -269368,11 +269467,12 @@ function createGuardResponseReviewer(host) {
269368
269467
  turnId,
269369
269468
  step,
269370
269469
  signal
269371
- }), signal)) && current();
269470
+ })), signal)) && current();
269372
269471
  };
269373
269472
  stage = "release";
269473
+ onProgress?.("release.start");
269374
269474
  if (!await authorized("release_response")) return blocked("release_denied");
269375
- const releaseResult = await abortable(connection.client.callTool("release_response", {
269475
+ const releaseResult = await abortable(track(connection.client.callTool("release_response", {
269376
269476
  target_text: text,
269377
269477
  language,
269378
269478
  content_type: "prose",
@@ -269381,7 +269481,7 @@ function createGuardResponseReviewer(host) {
269381
269481
  nativeness: true,
269382
269482
  orthography: true
269383
269483
  }
269384
- }, signal), signal);
269484
+ }, signal)), signal);
269385
269485
  if (!current()) return blocked("connection_changed");
269386
269486
  if (releaseResult.isError) return blocked("release_rejected", rejectionFindings(readPayload(releaseResult, true)));
269387
269487
  const released = readPayload(releaseResult);
@@ -269389,8 +269489,9 @@ function createGuardResponseReviewer(host) {
269389
269489
  if (!current()) return blocked("connection_changed");
269390
269490
  if (status !== "PASS" || release_allowed !== true || blocking === true || typeof release_token !== "string" || release_token.length === 0 || release_token.length > 65536) return blocked("release_rejected", rejectionFindings(released));
269391
269491
  stage = "verification";
269492
+ onProgress?.("verification.start");
269392
269493
  if (!await authorized("verify_release_token")) return blocked("verification_denied");
269393
- const { status: verificationStatus, valid, checks, payload } = readPayload(await abortable(connection.client.callTool("verify_release_token", {
269494
+ const { status: verificationStatus, valid, checks, payload } = readPayload(await abortable(track(connection.client.callTool("verify_release_token", {
269394
269495
  release_token,
269395
269496
  source_text: "",
269396
269497
  target_text: text,
@@ -269398,7 +269499,7 @@ function createGuardResponseReviewer(host) {
269398
269499
  purpose: "response",
269399
269500
  content_type: "prose",
269400
269501
  short_text_reviewed: false
269401
- }, signal), signal)) ?? {};
269502
+ }, signal)), signal)) ?? {};
269402
269503
  if (!current()) return blocked("connection_changed");
269403
269504
  if (verificationStatus !== "PASS" || valid !== true || !isPlainRecord(checks) || !CHECK_NAMES.every((name) => checks[name] === true) || !isPlainRecord(payload)) return blocked("verification_rejected");
269404
269505
  const { v, source_sha256, target_sha256, language: verifiedLanguage, purpose, content_type, short_text_reviewed, exp, iat } = payload;
@@ -269488,6 +269589,9 @@ async function reviewNativeResponse(agent, language, input) {
269488
269589
  };
269489
269590
  const options = {
269490
269591
  signal,
269592
+ onExecution: (completion) => {
269593
+ input.onPendingOperation?.(completion.then(() => void 0, () => void 0));
269594
+ },
269491
269595
  requestLogFields: {
269492
269596
  turnStep: `review:${input.turnId}.${String(input.step)}`,
269493
269597
  attempt: `${attempt}/2`
@@ -269496,13 +269600,16 @@ async function reviewNativeResponse(agent, language, input) {
269496
269600
  const prompt = attempt === 1 ? NATIVE_REVIEW_PROMPT : `${NATIVE_REVIEW_PROMPT}\nThe previous review did not satisfy the required JSON format. Return exactly one object with the two required boolean keys nativeness and orthography, no wrapper or additional keys. Use true or false, not strings or null. Set a check to false if it fails or you are uncertain.`;
269497
269601
  try {
269498
269602
  signal.throwIfAborted();
269499
- const response = await abortable(agent.generate(provider, prompt, [], [createUserMessage(candidateMessage)], { onMessagePart: (part) => {
269603
+ const requested = agent.generate(provider, prompt, [], [createUserMessage(candidateMessage)], { onMessagePart: (part) => {
269500
269604
  if (part.type === "text") receivedBytes += Buffer.byteLength(part.text);
269501
269605
  if (receivedBytes > MAX_REVIEW_RESULT_BYTES) {
269502
269606
  outputLimitExceeded = true;
269503
269607
  throw new Error("Native review output exceeds limit");
269504
269608
  }
269505
- } }, options), signal);
269609
+ if (!signal.aborted && part.type === "text" && part.text.trim().length > 0) input.onProgress?.("native.text");
269610
+ } }, options);
269611
+ input.onPendingOperation?.(requested.then(() => void 0, () => void 0));
269612
+ const response = await abortable(requested, signal);
269506
269613
  if (response.usage !== null) agent.usage.record(modelAlias, response.usage, "turn");
269507
269614
  signal.throwIfAborted();
269508
269615
  if (response.message.toolCalls.length > 0) return invalid("tool_calls");
@@ -301524,8 +301631,38 @@ var init_mcp$1 = __esmMin((() => {
301524
301631
  }));
301525
301632
  //#endregion
301526
301633
  //#region ../../packages/agent-core/src/plugin/agent-spine-runtime.ts
301527
- var EMPTY_RUNTIME, AgentSpineSessionRuntime;
301634
+ /** AgentSpine reads prompt text; binary media stays in the original model input. */
301635
+ function projectAgentSpinePrompt(input) {
301636
+ if (typeof input["hook_event_name"] !== "string" || !PROMPT_EVENTS.has(input["hook_event_name"]) || !Array.isArray(input["prompt"])) return input;
301637
+ let changed = false;
301638
+ const prompt = input["prompt"].map((part) => {
301639
+ if (!isRecord$18(part)) return part;
301640
+ const field = part["type"] === "image_url" ? "imageUrl" : part["type"] === "audio_url" ? "audioUrl" : part["type"] === "video_url" ? "videoUrl" : void 0;
301641
+ if (field === void 0 || !isRecord$18(part[field]) || typeof part[field]["url"] !== "string") return part;
301642
+ const serialized = JSON.stringify(part);
301643
+ changed = true;
301644
+ return {
301645
+ type: "media_reference",
301646
+ media_type: part["type"],
301647
+ sha256: createHash("sha256").update(serialized).digest("hex"),
301648
+ original_bytes: Buffer.byteLength(serialized)
301649
+ };
301650
+ });
301651
+ return changed ? {
301652
+ ...input,
301653
+ prompt
301654
+ } : input;
301655
+ }
301656
+ function isRecord$18(value) {
301657
+ return typeof value === "object" && value !== null && !Array.isArray(value);
301658
+ }
301659
+ var PROMPT_EVENTS, EMPTY_RUNTIME, AgentSpineSessionRuntime;
301528
301660
  var init_agent_spine_runtime = __esmMin((() => {
301661
+ PROMPT_EVENTS = new Set([
301662
+ "UserPromptSubmit",
301663
+ "TurnStart",
301664
+ "SubagentStart"
301665
+ ]);
301529
301666
  EMPTY_RUNTIME = Object.freeze({
301530
301667
  AGENTSPINE_KING_TIMELINE_SOURCE: "",
301531
301668
  AGENTSPINE_KING_WIRE_PROTOCOL_VERSION: "",
@@ -302121,9 +302258,11 @@ var init_session$1 = __esmMin((() => {
302121
302258
  this.experimentalFlags = options.experimentalFlags ?? new FlagResolver();
302122
302259
  this.agentSpineRuntime = this.experimentalFlags.enabled("agent_spine_timeline") ? new AgentSpineSessionRuntime(options.agentSpineRuntime) : void 0;
302123
302260
  this.visionReader = (this.experimentalFlags.enabled("vision_reader") ? createVisionReader(options.config?.services?.visionReader) : void 0) ?? createManagedMediaVisionReader(options.toolServices?.media);
302261
+ const agentSpineHooks = new Set(options.agentSpineRuntime?.hooks);
302124
302262
  this.hookEngine = new HookEngine(options.hooks, {
302125
302263
  cwd: options.kaos.getcwd(),
302126
302264
  sessionId: options.id,
302265
+ runtimeInput: (hook, input) => agentSpineHooks.has(hook) ? projectAgentSpinePrompt(input) : input,
302127
302266
  runtimeEnv: (hook) => {
302128
302267
  const hostEnv = options.hookRuntimeEnv?.(hook);
302129
302268
  const timelineEnv = this.agentSpineRuntime?.forHook(hook);
@@ -338198,7 +338337,6 @@ var init_core_impl = __esmMin((() => {
338198
338337
  };
338199
338338
  }
338200
338339
  agentSpineRuntimeRecipients(pluginHooks, mcpConfig) {
338201
- if (!this.experimentalFlags.enabled("agent_spine_timeline")) return void 0;
338202
338340
  const plugin = this.plugins.get("agent-spine");
338203
338341
  if (plugin?.state !== "ok" || !plugin.enabled) return void 0;
338204
338342
  const hooks = pluginHooks.filter((hook) => hook.env?.["BLUN_PLUGIN_ROOT"] === plugin.root);
@@ -393722,7 +393860,7 @@ var require_constants$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
393722
393860
  };
393723
393861
  }));
393724
393862
  //#endregion
393725
- //#region ../../../../node_modules/node-gyp-build/node-gyp-build.js
393863
+ //#region ../../node_modules/node-gyp-build/node-gyp-build.js
393726
393864
  var require_node_gyp_build$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
393727
393865
  var fs$4 = __require("fs");
393728
393866
  var path$6 = __require("path");
@@ -393878,14 +394016,14 @@ var require_node_gyp_build$1 = /* @__PURE__ */ __commonJSMin(((exports, module)
393878
394016
  load.compareTuples = compareTuples;
393879
394017
  }));
393880
394018
  //#endregion
393881
- //#region ../../../../node_modules/node-gyp-build/index.js
394019
+ //#region ../../node_modules/node-gyp-build/index.js
393882
394020
  var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) => {
393883
394021
  const runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
393884
394022
  if (typeof runtimeRequire.addon === "function") module.exports = runtimeRequire.addon.bind(runtimeRequire);
393885
394023
  else module.exports = require_node_gyp_build$1();
393886
394024
  }));
393887
394025
  //#endregion
393888
- //#region ../../../../node_modules/bufferutil/fallback.js
394026
+ //#region ../../node_modules/bufferutil/fallback.js
393889
394027
  var require_fallback$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
393890
394028
  /**
393891
394029
  * Masks a buffer using the given mask.
@@ -393917,7 +394055,7 @@ var require_fallback$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
393917
394055
  };
393918
394056
  }));
393919
394057
  //#endregion
393920
- //#region ../../../../node_modules/bufferutil/index.js
394058
+ //#region ../../node_modules/bufferutil/index.js
393921
394059
  var require_bufferutil = /* @__PURE__ */ __commonJSMin(((exports, module) => {
393922
394060
  try {
393923
394061
  module.exports = require_node_gyp_build()(__dirname);
@@ -394410,7 +394548,7 @@ var require_permessage_deflate = /* @__PURE__ */ __commonJSMin(((exports, module
394410
394548
  }
394411
394549
  }));
394412
394550
  //#endregion
394413
- //#region ../../../../node_modules/utf-8-validate/fallback.js
394551
+ //#region ../../node_modules/utf-8-validate/fallback.js
394414
394552
  var require_fallback = /* @__PURE__ */ __commonJSMin(((exports, module) => {
394415
394553
  /**
394416
394554
  * Checks if a given buffer contains only correct UTF-8.
@@ -394440,7 +394578,7 @@ var require_fallback = /* @__PURE__ */ __commonJSMin(((exports, module) => {
394440
394578
  module.exports = isValidUTF8;
394441
394579
  }));
394442
394580
  //#endregion
394443
- //#region ../../../../node_modules/utf-8-validate/index.js
394581
+ //#region ../../node_modules/utf-8-validate/index.js
394444
394582
  var require_utf_8_validate = /* @__PURE__ */ __commonJSMin(((exports, module) => {
394445
394583
  try {
394446
394584
  module.exports = require_node_gyp_build()(__dirname);
@@ -502963,7 +503101,7 @@ const BLUN_SPINNER_FRAMES = [
502963
503101
  "▝",
502964
503102
  "▗"
502965
503103
  ];
502966
- const THINKING_WORD_INTERVAL_MS = 6e3;
503104
+ const THINKING_WORD_INTERVAL_MS = 3e3;
502967
503105
  //#endregion
502968
503106
  //#region src/tui/components/messages/goal-format.ts
502969
503107
  function formatGoalElapsed(ms) {
@@ -514521,6 +514659,321 @@ var PluginCommandComponent = class extends Container {
514521
514659
  }
514522
514660
  };
514523
514661
  //#endregion
514662
+ //#region src/tui/components/messages/thinking-activity.ts
514663
+ const THINKING_ACTIVITY_WORDS = {
514664
+ Thinking: [
514665
+ "Thinkering",
514666
+ "Reasoning",
514667
+ "Pondering",
514668
+ "Analyzing",
514669
+ "Exploring",
514670
+ "Connecting",
514671
+ "Unraveling",
514672
+ "Imagining",
514673
+ "Envisioning",
514674
+ "Strategizing",
514675
+ "Deciphering",
514676
+ "Framing",
514677
+ "Ideating",
514678
+ "Synthesizing",
514679
+ "Reflecting"
514680
+ ],
514681
+ Planning: [
514682
+ "Architecting",
514683
+ "Blueprinting",
514684
+ "Structuring",
514685
+ "Orchestrating",
514686
+ "Sequencing",
514687
+ "Scoping",
514688
+ "Prioritizing",
514689
+ "Coordinating",
514690
+ "Decomposing",
514691
+ "Aligning",
514692
+ "Roadmapping",
514693
+ "Modeling",
514694
+ "Designing",
514695
+ "Drafting",
514696
+ "Preparing"
514697
+ ],
514698
+ Researching: [
514699
+ "Searching",
514700
+ "Browsing",
514701
+ "Discovering",
514702
+ "Investigating",
514703
+ "Examining",
514704
+ "Inspecting",
514705
+ "Tracing",
514706
+ "Comparing",
514707
+ "Verifying",
514708
+ "Cross-checking",
514709
+ "Fact-finding",
514710
+ "Source-hunting",
514711
+ "Deep-diving",
514712
+ "Contextualizing",
514713
+ "Evidence-gathering"
514714
+ ],
514715
+ Building: [
514716
+ "Building",
514717
+ "Crafting",
514718
+ "Coding",
514719
+ "Engineering",
514720
+ "Assembling",
514721
+ "Integrating",
514722
+ "Implementing",
514723
+ "Wiring",
514724
+ "Configuring",
514725
+ "Compiling",
514726
+ "Rendering",
514727
+ "Generating",
514728
+ "Prototyping",
514729
+ "Shaping",
514730
+ "Forging"
514731
+ ],
514732
+ Solving: [
514733
+ "Debugging",
514734
+ "Diagnosing",
514735
+ "Troubleshooting",
514736
+ "Untangling",
514737
+ "Repairing",
514738
+ "Patching",
514739
+ "Resolving",
514740
+ "Reworking",
514741
+ "Refining",
514742
+ "Optimizing",
514743
+ "Simplifying",
514744
+ "Stabilizing",
514745
+ "Recovering",
514746
+ "Calibrating",
514747
+ "Tuning"
514748
+ ],
514749
+ Validating: [
514750
+ "Testing",
514751
+ "Validating",
514752
+ "Reviewing",
514753
+ "Auditing",
514754
+ "Proofreading",
514755
+ "Measuring",
514756
+ "Benchmarking",
514757
+ "Stress-testing",
514758
+ "Safeguarding",
514759
+ "Hardening",
514760
+ "Polishing",
514761
+ "Fine-tuning",
514762
+ "Checking",
514763
+ "Confirming",
514764
+ "Certifying"
514765
+ ],
514766
+ Processing: [
514767
+ "Reading",
514768
+ "Parsing",
514769
+ "Indexing",
514770
+ "Remembering",
514771
+ "Recalling",
514772
+ "Organizing",
514773
+ "Classifying",
514774
+ "Filtering",
514775
+ "Sorting",
514776
+ "Matching",
514777
+ "Merging",
514778
+ "Summarizing",
514779
+ "Compressing",
514780
+ "Transforming",
514781
+ "Learning"
514782
+ ],
514783
+ Collaborating: [
514784
+ "Delegating",
514785
+ "Collaborating",
514786
+ "Consulting",
514787
+ "Briefing",
514788
+ "Dispatching",
514789
+ "Synchronizing",
514790
+ "Negotiating",
514791
+ "Handshaking",
514792
+ "Queuing",
514793
+ "Routing",
514794
+ "Supervising",
514795
+ "Monitoring",
514796
+ "Reconciling",
514797
+ "Reporting",
514798
+ "Converging"
514799
+ ],
514800
+ Creating: [
514801
+ "Writing",
514802
+ "Rewriting",
514803
+ "Translating",
514804
+ "Localizing",
514805
+ "Narrating",
514806
+ "Explaining",
514807
+ "Illustrating",
514808
+ "Visualizing",
514809
+ "Formatting",
514810
+ "Styling",
514811
+ "Presenting",
514812
+ "Documenting",
514813
+ "Captioning",
514814
+ "Storyboarding",
514815
+ "Publishing"
514816
+ ],
514817
+ "BLUN Magic": [
514818
+ "BLUNing",
514819
+ "Sparkering",
514820
+ "Wondermaking",
514821
+ "Dreamweaving",
514822
+ "Futurecrafting",
514823
+ "Brightening",
514824
+ "Flowing",
514825
+ "Accelerating",
514826
+ "Automating",
514827
+ "Empowering",
514828
+ "Launching",
514829
+ "Scaling",
514830
+ "Evolving",
514831
+ "Delivering",
514832
+ "Finishing"
514833
+ ]
514834
+ };
514835
+ const EVIDENCE_KEYS = new Set([
514836
+ "command",
514837
+ "cmd",
514838
+ "description",
514839
+ "file",
514840
+ "file_path",
514841
+ "path",
514842
+ "pattern",
514843
+ "prompt",
514844
+ "query",
514845
+ "task",
514846
+ "title",
514847
+ "url"
514848
+ ]);
514849
+ function activityEvidence(toolCall) {
514850
+ if (toolCall === void 0) return "";
514851
+ const values = [toolCall.name];
514852
+ if (toolCall.args !== void 0) {
514853
+ for (const [key, value] of Object.entries(toolCall.args)) if (EVIDENCE_KEYS.has(key.toLowerCase()) && typeof value === "string") values.push(value.slice(0, 2e3));
514854
+ } else if (toolCall.argumentsText !== void 0) values.push(toolCall.argumentsText.slice(0, 2e3));
514855
+ return values.filter(Boolean).join(" ").toLowerCase();
514856
+ }
514857
+ function matchesAny(text, patterns) {
514858
+ return patterns.some((pattern) => text.includes(pattern));
514859
+ }
514860
+ function inferThinkingActivityGroup(toolCall, options = {}) {
514861
+ if (options.completing === true) return "BLUN Magic";
514862
+ if (options.retrying === true || options.failed === true) return "Solving";
514863
+ const name = toolCall?.name?.toLowerCase() ?? "";
514864
+ const evidence = activityEvidence(toolCall);
514865
+ if (!name) return "Thinking";
514866
+ if (name === "todolist" || matchesAny(evidence, [
514867
+ " plan",
514868
+ "roadmap",
514869
+ "architect",
514870
+ "scope"
514871
+ ])) return "Planning";
514872
+ if (matchesAny(name, [
514873
+ "agent",
514874
+ "swarm",
514875
+ "telegram"
514876
+ ]) || matchesAny(evidence, [
514877
+ "delegate",
514878
+ "handoff",
514879
+ "telegram",
514880
+ "report to"
514881
+ ])) return "Collaborating";
514882
+ if (matchesAny(name, [
514883
+ "mnemo",
514884
+ "memory",
514885
+ "compact"
514886
+ ]) || matchesAny(evidence, [
514887
+ "memory",
514888
+ "mnemo",
514889
+ "compact",
514890
+ "summar",
514891
+ "index"
514892
+ ])) return "Processing";
514893
+ if (matchesAny(name, [
514894
+ "grep",
514895
+ "glob",
514896
+ "search",
514897
+ "webfetch",
514898
+ "web_fetch",
514899
+ "websearch",
514900
+ "web_search",
514901
+ "ls"
514902
+ ]) || matchesAny(evidence, [
514903
+ "search",
514904
+ "find ",
514905
+ "inspect",
514906
+ "trace"
514907
+ ])) return "Researching";
514908
+ if (matchesAny(evidence, [
514909
+ "publish",
514910
+ "release",
514911
+ "deploy",
514912
+ "launch",
514913
+ "deliver",
514914
+ "finish"
514915
+ ])) return "BLUN Magic";
514916
+ if (matchesAny(evidence, [
514917
+ "error",
514918
+ "fail",
514919
+ "debug",
514920
+ "diagnos",
514921
+ "repair",
514922
+ "patch",
514923
+ "fix ",
514924
+ "recover",
514925
+ "troubleshoot"
514926
+ ])) return "Solving";
514927
+ if (matchesAny(evidence, [
514928
+ "test",
514929
+ "check",
514930
+ "verify",
514931
+ "validat",
514932
+ "audit",
514933
+ "benchmark",
514934
+ "measure",
514935
+ "compare",
514936
+ "sha256",
514937
+ "diff "
514938
+ ])) return "Validating";
514939
+ if (name === "read" || name === "readbatch") return "Processing";
514940
+ if (name === "write" || name === "edit") return matchesAny(evidence, [
514941
+ ".md",
514942
+ ".txt",
514943
+ "readme",
514944
+ "changelog",
514945
+ "document",
514946
+ "translat",
514947
+ "localiz"
514948
+ ]) ? "Creating" : "Building";
514949
+ if (matchesAny(name, [
514950
+ "bash",
514951
+ "shell",
514952
+ "programmatictool"
514953
+ ]) || matchesAny(evidence, [
514954
+ "build",
514955
+ "compile",
514956
+ "npm ",
514957
+ "node ",
514958
+ "code"
514959
+ ])) return "Building";
514960
+ return "Processing";
514961
+ }
514962
+ var ThinkingActivityRotator = class {
514963
+ currentWord;
514964
+ changedAtMs = 0;
514965
+ nextIndexByGroup = /* @__PURE__ */ new Map();
514966
+ resolve(group, now = Date.now()) {
514967
+ if (this.currentWord !== void 0 && now - this.changedAtMs < 3e3) return this.currentWord;
514968
+ const words = THINKING_ACTIVITY_WORDS[group];
514969
+ const index = this.nextIndexByGroup.get(group) ?? 0;
514970
+ this.currentWord = words[index % words.length];
514971
+ this.nextIndexByGroup.set(group, (index + 1) % words.length);
514972
+ this.changedAtMs = now;
514973
+ return this.currentWord;
514974
+ }
514975
+ };
514976
+ //#endregion
514524
514977
  //#region src/tui/components/messages/thinking.ts
514525
514978
  /**
514526
514979
  * Renders thinking content in the transcript.
@@ -514573,14 +515026,9 @@ registerUiCatalogFragment({
514573
515026
  }
514574
515027
  });
514575
515028
  function rotatingThinkingLabel(name, startedAtMs, now = Date.now()) {
514576
- const keys = [
514577
- "thinking.label",
514578
- "thinking.pondering",
514579
- "thinking.unraveling"
514580
- ];
515029
+ const words = THINKING_ACTIVITY_WORDS.Thinking;
514581
515030
  const elapsed = startedAtMs === void 0 ? 0 : Math.max(0, now - startedAtMs);
514582
- const key = keys[Math.floor(elapsed / THINKING_WORD_INTERVAL_MS) % keys.length];
514583
- return `${uiText(key, { name })}…`;
515031
+ return `${name} ${words[Math.floor(elapsed / THINKING_WORD_INTERVAL_MS) % words.length]}…`;
514584
515032
  }
514585
515033
  function liveActivityLabels(label, metrics, now = Date.now()) {
514586
515034
  const elapsed = formatLiveElapsed(metrics.startedAtMs === void 0 ? 0 : (now - metrics.startedAtMs) / 1e3);
@@ -514629,6 +515077,7 @@ function formatLiveElapsed(seconds) {
514629
515077
  return `${String(hours)}h ${String(remainingMinutes).padStart(2, "0")}m`;
514630
515078
  }
514631
515079
  var ThinkingComponent = class {
515080
+ activityLabel;
514632
515081
  text;
514633
515082
  showMarker;
514634
515083
  mode;
@@ -514640,12 +515089,14 @@ var ThinkingComponent = class {
514640
515089
  thinkStartMs = null;
514641
515090
  thinkElapsedMs = 0;
514642
515091
  thinkAborted = false;
515092
+ abortedActivityLabel;
514643
515093
  estimatedOutputTokens = 0;
514644
515094
  sessionTotalTokens;
514645
515095
  step;
514646
515096
  textComponent;
514647
515097
  renderCache;
514648
- constructor(text, showMarker = true, mode = "finalized", ui, metrics) {
515098
+ constructor(text, showMarker = true, mode = "finalized", ui, metrics, activityLabel) {
515099
+ this.activityLabel = activityLabel;
514649
515100
  this.text = text;
514650
515101
  this.showMarker = showMarker;
514651
515102
  this.mode = mode;
@@ -514712,7 +515163,7 @@ var ThinkingComponent = class {
514712
515163
  const abortMark = this.thinkAborted ? ` (${uiText("thinking.aborted")})` : "";
514713
515164
  const now = Date.now();
514714
515165
  const startedAtMs = now - this.formatElapsedSeconds() * 1e3;
514715
- const labels = liveActivityLabels(rotatingThinkingLabel(this.persona, startedAtMs, now), {
515166
+ const labels = liveActivityLabels(this.abortedActivityLabel ?? (this.activityLabel === void 0 ? rotatingThinkingLabel(this.persona, startedAtMs, now) : `${this.persona} ${this.activityLabel()}`), {
514716
515167
  startedAtMs,
514717
515168
  estimatedOutputTokens: this.estimatedOutputTokens,
514718
515169
  sessionTotalTokens: this.sessionTotalTokens,
@@ -514739,6 +515190,7 @@ var ThinkingComponent = class {
514739
515190
  }
514740
515191
  /** Called when the connection dies or the request times out. */
514741
515192
  abort() {
515193
+ this.abortedActivityLabel ??= this.activityLabel === void 0 ? rotatingThinkingLabel(this.persona, this.thinkStartMs ?? void 0) : `${this.persona} ${this.activityLabel()}`;
514742
515194
  if (this.thinkStartMs !== null) {
514743
515195
  this.thinkElapsedMs = Date.now() - this.thinkStartMs;
514744
515196
  this.thinkStartMs = null;
@@ -515194,6 +515646,184 @@ function decodeMcpToolName(name) {
515194
515646
  };
515195
515647
  }
515196
515648
  //#endregion
515649
+ //#region src/personal-memory/tool-input.ts
515650
+ init_zod$1();
515651
+ const PERSONAL_MEMORY_TOOL_NAMES = [
515652
+ "memory_status",
515653
+ "memory_settings_update",
515654
+ "memory_remember",
515655
+ "memory_list",
515656
+ "memory_recall"
515657
+ ];
515658
+ const personalMemorySettingsInputSchema = object$1({
515659
+ memoryEnabled: boolean$1().optional(),
515660
+ useSavedMemories: boolean$1().optional(),
515661
+ allowNewMemories: boolean$1().optional()
515662
+ }).strict().refine((value) => Object.keys(value).length > 0);
515663
+ const personalMemoryRememberInputSchema = object$1({ content: string().min(1).max(4e3) }).strict();
515664
+ function isPersonalMemoryToolName$1(qualifiedName) {
515665
+ return PERSONAL_MEMORY_TOOL_NAMES.some((name) => qualifiedName === `mcp__personal-memory__${name}`);
515666
+ }
515667
+ function mutationNameFromQualifiedTool(name) {
515668
+ if (name === "mcp__personal-memory__memory_settings_update") return "memory_settings_update";
515669
+ if (name === "mcp__personal-memory__memory_remember") return "memory_remember";
515670
+ }
515671
+ function parsePersonalMemoryMutation(name, input) {
515672
+ if (name === "memory_settings_update") {
515673
+ const parsed = personalMemorySettingsInputSchema.safeParse(input);
515674
+ if (!parsed.success) return { ok: false };
515675
+ const args = parsed.data;
515676
+ const body = {
515677
+ memory_enabled: args.memoryEnabled,
515678
+ use_saved_memories: args.useSavedMemories ?? (args.memoryEnabled === true ? true : void 0),
515679
+ allow_new_memories: args.allowNewMemories ?? (args.memoryEnabled === true ? true : void 0),
515680
+ use_chat_history: args.memoryEnabled === true ? false : void 0
515681
+ };
515682
+ return {
515683
+ ok: true,
515684
+ kind: "settings",
515685
+ body: Object.fromEntries(Object.entries(body).filter(([, value]) => value !== void 0))
515686
+ };
515687
+ }
515688
+ if (name === "memory_remember") {
515689
+ const parsed = personalMemoryRememberInputSchema.safeParse(input);
515690
+ if (!parsed.success) return { ok: false };
515691
+ return {
515692
+ ok: true,
515693
+ kind: "remember",
515694
+ content: parsed.data.content
515695
+ };
515696
+ }
515697
+ return { ok: false };
515698
+ }
515699
+ //#endregion
515700
+ //#region src/tui/utils/personal-memory-display.copy.ts
515701
+ registerUiCatalogFragment({
515702
+ en: {
515703
+ "personalMemoryDisplay.settingsAction": "Change personal memory settings",
515704
+ "personalMemoryDisplay.rememberAction": "Save a personal memory",
515705
+ "personalMemoryDisplay.memoryEnabled": "Personal memory",
515706
+ "personalMemoryDisplay.useSavedMemories": "Use saved memories",
515707
+ "personalMemoryDisplay.allowNewMemories": "Allow new memories",
515708
+ "personalMemoryDisplay.useChatHistory": "Use chat history",
515709
+ "personalMemoryDisplay.enabled": "On",
515710
+ "personalMemoryDisplay.disabled": "Off",
515711
+ "personalMemoryDisplay.invalidInput": "The requested memory change could not be verified.",
515712
+ "personalMemoryDisplay.settingLine": "{setting}: {value}"
515713
+ },
515714
+ de: {
515715
+ "personalMemoryDisplay.settingsAction": "Einstellungen des persönlichen Gedächtnisses ändern",
515716
+ "personalMemoryDisplay.rememberAction": "Persönliche Erinnerung speichern",
515717
+ "personalMemoryDisplay.memoryEnabled": "Persönliches Gedächtnis",
515718
+ "personalMemoryDisplay.useSavedMemories": "Gespeicherte Erinnerungen verwenden",
515719
+ "personalMemoryDisplay.allowNewMemories": "Neue Erinnerungen zulassen",
515720
+ "personalMemoryDisplay.useChatHistory": "Chatverlauf verwenden",
515721
+ "personalMemoryDisplay.enabled": "An",
515722
+ "personalMemoryDisplay.disabled": "Aus",
515723
+ "personalMemoryDisplay.invalidInput": "Die gewünschte Änderung am Gedächtnis konnte nicht überprüft werden.",
515724
+ "personalMemoryDisplay.settingLine": "{setting}: {value}"
515725
+ },
515726
+ es: {
515727
+ "personalMemoryDisplay.settingsAction": "Cambiar la configuración de la memoria personal",
515728
+ "personalMemoryDisplay.rememberAction": "Guardar un recuerdo personal",
515729
+ "personalMemoryDisplay.memoryEnabled": "Memoria personal",
515730
+ "personalMemoryDisplay.useSavedMemories": "Usar recuerdos guardados",
515731
+ "personalMemoryDisplay.allowNewMemories": "Permitir nuevos recuerdos",
515732
+ "personalMemoryDisplay.useChatHistory": "Usar el historial de chats",
515733
+ "personalMemoryDisplay.enabled": "Sí",
515734
+ "personalMemoryDisplay.disabled": "No",
515735
+ "personalMemoryDisplay.invalidInput": "No se pudo verificar el cambio solicitado en la memoria.",
515736
+ "personalMemoryDisplay.settingLine": "{setting}: {value}"
515737
+ },
515738
+ fr: {
515739
+ "personalMemoryDisplay.settingsAction": "Modifier les réglages de la mémoire personnelle",
515740
+ "personalMemoryDisplay.rememberAction": "Enregistrer un souvenir personnel",
515741
+ "personalMemoryDisplay.memoryEnabled": "Mémoire personnelle",
515742
+ "personalMemoryDisplay.useSavedMemories": "Utiliser les souvenirs enregistrés",
515743
+ "personalMemoryDisplay.allowNewMemories": "Autoriser de nouveaux souvenirs",
515744
+ "personalMemoryDisplay.useChatHistory": "Utiliser l’historique des discussions",
515745
+ "personalMemoryDisplay.enabled": "Oui",
515746
+ "personalMemoryDisplay.disabled": "Non",
515747
+ "personalMemoryDisplay.invalidInput": "La modification demandée de la mémoire n’a pas pu être vérifiée.",
515748
+ "personalMemoryDisplay.settingLine": "{setting}\xA0: {value}"
515749
+ },
515750
+ sv: {
515751
+ "personalMemoryDisplay.settingsAction": "Ändra inställningarna för det personliga minnet",
515752
+ "personalMemoryDisplay.rememberAction": "Spara ett personligt minne",
515753
+ "personalMemoryDisplay.memoryEnabled": "Personligt minne",
515754
+ "personalMemoryDisplay.useSavedMemories": "Använd sparade minnen",
515755
+ "personalMemoryDisplay.allowNewMemories": "Tillåt nya minnen",
515756
+ "personalMemoryDisplay.useChatHistory": "Använd chatthistorik",
515757
+ "personalMemoryDisplay.enabled": "På",
515758
+ "personalMemoryDisplay.disabled": "Av",
515759
+ "personalMemoryDisplay.invalidInput": "Den begärda ändringen av minnet kunde inte verifieras.",
515760
+ "personalMemoryDisplay.settingLine": "{setting}: {value}"
515761
+ },
515762
+ cs: {
515763
+ "personalMemoryDisplay.settingsAction": "Změnit nastavení osobní paměti",
515764
+ "personalMemoryDisplay.rememberAction": "Uložit osobní vzpomínku",
515765
+ "personalMemoryDisplay.memoryEnabled": "Osobní paměť",
515766
+ "personalMemoryDisplay.useSavedMemories": "Používat uložené vzpomínky",
515767
+ "personalMemoryDisplay.allowNewMemories": "Povolit nové vzpomínky",
515768
+ "personalMemoryDisplay.useChatHistory": "Používat historii chatů",
515769
+ "personalMemoryDisplay.enabled": "Ano",
515770
+ "personalMemoryDisplay.disabled": "Ne",
515771
+ "personalMemoryDisplay.invalidInput": "Požadovanou změnu paměti se nepodařilo ověřit.",
515772
+ "personalMemoryDisplay.settingLine": "{setting}: {value}"
515773
+ }
515774
+ });
515775
+ //#endregion
515776
+ //#region src/tui/utils/personal-memory-display.ts
515777
+ const settingLabels = {
515778
+ memory_enabled: "personalMemoryDisplay.memoryEnabled",
515779
+ use_saved_memories: "personalMemoryDisplay.useSavedMemories",
515780
+ allow_new_memories: "personalMemoryDisplay.allowNewMemories",
515781
+ use_chat_history: "personalMemoryDisplay.useChatHistory"
515782
+ };
515783
+ function personalMemoryApprovalDisplay(toolName, display) {
515784
+ const name = mutationNameFromQualifiedTool(toolName);
515785
+ if (name === void 0) return void 0;
515786
+ const action = personalMemoryActionLabel(toolName);
515787
+ const parsed = parsePersonalMemoryMutation(name, display.kind === "generic" ? display.detail : void 0);
515788
+ const invalid = {
515789
+ action,
515790
+ description: uiText("personalMemoryDisplay.invalidInput"),
515791
+ blocks: [],
515792
+ valid: false
515793
+ };
515794
+ if (!parsed.ok) return invalid;
515795
+ const text = parsed.kind === "remember" ? memoryContentPreview(parsed.content) : Object.keys(settingLabels).filter((key) => parsed.body[key] !== void 0).map((key) => uiText("personalMemoryDisplay.settingLine", {
515796
+ setting: uiText(settingLabels[key]),
515797
+ value: uiText(parsed.body[key] ? "personalMemoryDisplay.enabled" : "personalMemoryDisplay.disabled")
515798
+ })).join("\n");
515799
+ if (text.length === 0) return invalid;
515800
+ return {
515801
+ action,
515802
+ description: "",
515803
+ blocks: [{
515804
+ type: "brief",
515805
+ text
515806
+ }],
515807
+ valid: true
515808
+ };
515809
+ }
515810
+ function memoryContentPreview(content) {
515811
+ const controls = /[\u0000-\u0009\u000B-\u001F\u007F-\u009F\u2028-\u202E\u2066-\u2069]/gu;
515812
+ if (!controls.test(content)) return content;
515813
+ return JSON.stringify(content).replaceAll(controls, (character) => `\\u${character.codePointAt(0).toString(16).padStart(4, "0")}`);
515814
+ }
515815
+ function personalMemoryArgumentPreview(toolName, value) {
515816
+ return isPersonalMemoryToolName$1(toolName) ? memoryContentPreview(value) : value;
515817
+ }
515818
+ function personalMemoryActionLabel(toolName) {
515819
+ const name = mutationNameFromQualifiedTool(toolName);
515820
+ if (name === void 0) return void 0;
515821
+ return uiText(name === "memory_settings_update" ? "personalMemoryDisplay.settingsAction" : "personalMemoryDisplay.rememberAction");
515822
+ }
515823
+ function personalMemoryActivityLabel(toolName) {
515824
+ return isPersonalMemoryToolName$1(toolName) ? uiText("startupPersonalMemory.title") : void 0;
515825
+ }
515826
+ //#endregion
515197
515827
  //#region src/tui/utils/shell-output.copy.ts
515198
515828
  registerUiCatalogFragment({
515199
515829
  en: { "shellOutput.noOutput": "(no output)" },
@@ -516817,7 +517447,8 @@ function extractKeyArgument(toolName, args, workspaceDir) {
516817
517447
  for (const key of candidates) {
516818
517448
  const val = args[key];
516819
517449
  if (typeof val === "string" && val.length > 0) {
516820
- const firstLine = val.split("\n")[0] ?? val;
517450
+ const preview = personalMemoryArgumentPreview(toolName, val);
517451
+ const firstLine = preview.split("\n")[0] ?? preview;
516821
517452
  return formatKeyArgument(toolName, key, toolName === "Bash" && val.includes("\n") ? `${firstLine}…` : firstLine, workspaceDir);
516822
517453
  }
516823
517454
  }
@@ -517626,6 +518257,8 @@ var ToolCallComponent = class ToolCallComponent extends Container {
517626
518257
  if (phrase !== void 0) return `${bullet}${currentTheme.boldFg("primary", phrase)}${argStr}${chipStr}`;
517627
518258
  }
517628
518259
  const verbStyled = isTruncated ? currentTheme.fg("error", verb) : verb;
518260
+ const memoryLabel = personalMemoryActivityLabel(toolCall.name);
518261
+ if (memoryLabel !== void 0) return `${bullet}${isTruncated ? `${verbStyled} ` : ""}${currentTheme.boldFg("primary", memoryLabel)}${argStr}${chipStr}`;
517629
518262
  const toolLabel = decoded !== null ? `${currentTheme.boldFg("primary", decoded.toolName)}${currentTheme.dim(` · MCP/${decoded.serverName}`)}` : currentTheme.boldFg("primary", toolCall.name);
517630
518263
  return `${bullet}${verbStyled} ${toolLabel}${argStr}${chipStr}`;
517631
518264
  }
@@ -517712,15 +518345,19 @@ var ToolCallComponent = class ToolCallComponent extends Container {
517712
518345
  for (const sub of this.finishedSubCalls) {
517713
518346
  const mark = sub.isError ? currentTheme.fg("error", "✗") : currentTheme.fg("success", "•");
517714
518347
  const keyArg = extractKeyArgument(sub.name, sub.args, this.workspaceDir);
517715
- const nameCol = currentTheme.fg("primary", sub.name);
518348
+ const memoryLabel = personalMemoryActivityLabel(sub.name);
518349
+ const nameCol = currentTheme.fg("primary", memoryLabel ?? sub.name);
518350
+ const verb = memoryLabel === void 0 ? `${uiText("toolCall.activity.used")} ` : "";
517716
518351
  const argCol = keyArg ? currentTheme.dim(` (${keyArg})`) : "";
517717
- this.addChild(new Text(` ${mark} ${uiText("toolCall.activity.used")} ${nameCol}${argCol}`, 0, 0));
518352
+ this.addChild(new Text(` ${mark} ${verb}${nameCol}${argCol}`, 0, 0));
517718
518353
  }
517719
518354
  for (const [id, call] of this.ongoingSubCalls) {
517720
518355
  const keyArg = extractKeyArgument(call.name, call.args, this.workspaceDir);
517721
- const nameCol = currentTheme.fg("primary", call.name);
518356
+ const memoryLabel = personalMemoryActivityLabel(call.name);
518357
+ const nameCol = currentTheme.fg("primary", memoryLabel ?? call.name);
518358
+ const verb = memoryLabel === void 0 ? `${uiText("toolCall.activity.using")} ` : "";
517722
518359
  const argCol = keyArg ? currentTheme.dim(` (${keyArg})`) : "";
517723
- this.addChild(new Text(` ${currentTheme.dim("…")} ${uiText("toolCall.activity.using")} ${nameCol}${argCol}`, 0, 0));
518360
+ this.addChild(new Text(` ${currentTheme.dim("…")} ${verb}${nameCol}${argCol}`, 0, 0));
517724
518361
  }
517725
518362
  if (this.subagentText.length > 0) {
517726
518363
  const tailLines = this.subagentText.split("\n").slice(-3);
@@ -517890,10 +518527,11 @@ var ToolCallComponent = class ToolCallComponent extends Container {
517890
518527
  if (current === void 0) return currentTheme.dim(` · ${countLabel}`);
517891
518528
  const verb = current.phase === "ongoing" ? uiText("toolCall.activity.using") : uiText("toolCall.activity.used");
517892
518529
  const keyArg = extractKeyArgument(current.name, current.args, this.workspaceDir);
517893
- const nameCol = currentTheme.fg("primary", current.name);
518530
+ const memoryLabel = personalMemoryActivityLabel(current.name);
518531
+ const nameCol = currentTheme.fg("primary", memoryLabel ?? current.name);
517894
518532
  const argCol = keyArg ? currentTheme.dim(` (${keyArg})`) : "";
517895
518533
  const mark = current.phase === "failed" ? currentTheme.fg("error", " ✗") : current.phase === "done" ? currentTheme.fg("success", " ✓") : "";
517896
- return `${currentTheme.dim(` · ${countLabel} · `)}${verb} ${nameCol}${argCol}${mark}`;
518534
+ return `${currentTheme.dim(` · ${countLabel} · `)}${memoryLabel === void 0 ? `${verb} ` : ""}${nameCol}${argCol}${mark}`;
517897
518535
  }
517898
518536
  buildSingleSubagentActiveWindow() {
517899
518537
  const gutter = currentTheme.dim("│");
@@ -520995,7 +521633,7 @@ function renderDisplayBlock(block, s, contentWidth) {
520995
521633
  if (block.description !== void 0 && block.description.length > 0) lines.push(s.dim(truncateOneLine(block.description, 200)));
520996
521634
  return lines;
520997
521635
  }
520998
- case "brief": return block.text ? block.text.split("\n").map((line) => line.length > 0 ? s.strong(line) : "") : [];
521636
+ case "brief": return block.text ? block.text.split("\n").flatMap((line) => line.length > 0 ? wrapTextWithAnsi(s.strong(line), contentWidth) : [""]) : [];
520999
521637
  case "background_task": return [s.strong(uiText("approval.backgroundTask", {
521000
521638
  status: block.status,
521001
521639
  kind: block.kind,
@@ -521020,6 +521658,8 @@ function isDuplicateBriefBlock(block, description) {
521020
521658
  return normalizeApprovalText(blockLines.slice(1).join("\n")) === normalizedDescription;
521021
521659
  }
521022
521660
  function headerFor(toolName) {
521661
+ const memoryAction = personalMemoryActionLabel(toolName);
521662
+ if (memoryAction !== void 0) return memoryAction;
521023
521663
  switch (toolName) {
521024
521664
  case "Bash": return uiText("approval.header.runCommand");
521025
521665
  case "Write": return uiText("approval.header.writeFile");
@@ -523556,7 +524196,8 @@ function planRejectChoices() {
523556
524196
  }];
523557
524197
  }
523558
524198
  function adaptApprovalRequest(event) {
523559
- const resolved = resolveDisplay(event.toolName, event.display, event.action);
524199
+ const memory = personalMemoryApprovalDisplay(event.toolName, event.display);
524200
+ const resolved = memory ?? resolveDisplay(event.toolName, event.display, event.action);
523560
524201
  return {
523561
524202
  id: event.toolCallId,
523562
524203
  tool_call_id: event.toolCallId,
@@ -523564,7 +524205,7 @@ function adaptApprovalRequest(event) {
523564
524205
  action: resolved.action ?? event.action,
523565
524206
  description: resolved.description,
523566
524207
  display: resolved.blocks,
523567
- choices: adaptChoices(event.toolName, event.display)
524208
+ choices: memory === void 0 ? adaptChoices(event.toolName, event.display) : defaultApprovalChoices().filter((choice) => choice.response === "rejected" || memory.valid && choice.response === "approved")
523568
524209
  };
523569
524210
  }
523570
524211
  function resolveDisplay(toolName, display, action) {
@@ -527634,13 +528275,6 @@ async function preparePersonalMemorySession(options) {
527634
528275
  //#endregion
527635
528276
  //#region src/personal-memory/mcp-server.ts
527636
528277
  init_zod$1();
527637
- const PERSONAL_MEMORY_TOOL_NAMES = [
527638
- "memory_status",
527639
- "memory_settings_update",
527640
- "memory_remember",
527641
- "memory_list",
527642
- "memory_recall"
527643
- ];
527644
528278
  const MANAGEMENT_TOOL_NAMES = [
527645
528279
  "memory_status",
527646
528280
  "memory_settings_update",
@@ -527657,12 +528291,8 @@ function personalMemoryToolNames(mode, capabilities = defaultPersonalMemoryCapab
527657
528291
  const noInputSchema = object$1({}).strict();
527658
528292
  const schemas = {
527659
528293
  memory_status: noInputSchema,
527660
- memory_settings_update: object$1({
527661
- memoryEnabled: boolean$1().optional(),
527662
- useSavedMemories: boolean$1().optional(),
527663
- allowNewMemories: boolean$1().optional()
527664
- }).strict().refine((value) => Object.keys(value).length > 0),
527665
- memory_remember: object$1({ content: string().min(1).max(4e3) }).strict(),
528294
+ memory_settings_update: personalMemorySettingsInputSchema,
528295
+ memory_remember: personalMemoryRememberInputSchema,
527666
528296
  memory_list: noInputSchema,
527667
528297
  memory_recall: object$1({
527668
528298
  query: string().min(1).max(1e3),
@@ -527684,20 +528314,18 @@ function personalMemoryToolDefinition(name) {
527684
528314
  }
527685
528315
  async function invokePersonalMemoryTool(client, name, input, context) {
527686
528316
  if (!isPersonalMemoryToolName(name)) throw new Error("Unsupported personal-memory tool.");
528317
+ if (name === "memory_settings_update" || name === "memory_remember") {
528318
+ const parsed = parsePersonalMemoryMutation(name, input);
528319
+ if (!parsed.ok) throw new Error("Invalid personal-memory tool arguments.");
528320
+ if (parsed.kind === "settings") return client.request("PUT", PERSONAL_MEMORY_SETTINGS_PATH, parsed.body);
528321
+ if (context?.explicitRememberAttested !== true) throw new PersonalMemoryBrokerError("EXPLICIT_CONSENT_REQUIRED");
528322
+ return client.request(PERSONAL_MEMORY_MEMORY_CREATE_METHOD, PERSONAL_MEMORY_MEMORIES_PATH, explicitPersonalMemoryBody(parsed.content));
528323
+ }
527687
528324
  const parsed = schemas[name].safeParse(input);
527688
528325
  if (!parsed.success) throw new Error("Invalid personal-memory tool arguments.");
527689
528326
  const args = parsed.data;
527690
528327
  switch (name) {
527691
528328
  case "memory_status": return client.request("GET", PERSONAL_MEMORY_SETTINGS_PATH);
527692
- case "memory_settings_update": return await client.request("PUT", PERSONAL_MEMORY_SETTINGS_PATH, compactObject({
527693
- memory_enabled: args["memoryEnabled"],
527694
- use_saved_memories: args["useSavedMemories"] ?? (args["memoryEnabled"] === true ? true : void 0),
527695
- allow_new_memories: args["allowNewMemories"] ?? (args["memoryEnabled"] === true ? true : void 0),
527696
- use_chat_history: args["memoryEnabled"] === true ? false : void 0
527697
- }));
527698
- case "memory_remember":
527699
- if (context?.explicitRememberAttested !== true) throw new PersonalMemoryBrokerError("EXPLICIT_CONSENT_REQUIRED");
527700
- return client.request(PERSONAL_MEMORY_MEMORY_CREATE_METHOD, PERSONAL_MEMORY_MEMORIES_PATH, explicitPersonalMemoryBody(args["content"]));
527701
528329
  case "memory_list": return client.request("GET", PERSONAL_MEMORY_MEMORIES_PATH);
527702
528330
  case "memory_recall": return normalizePhaseOneRecall(await client.request(PERSONAL_MEMORY_RECALL_METHOD, PERSONAL_MEMORY_RECALL_PATH, { query: args["query"] }), args["limit"]);
527703
528331
  }
@@ -527705,9 +528333,6 @@ async function invokePersonalMemoryTool(client, name, input, context) {
527705
528333
  function isPersonalMemoryToolName(name) {
527706
528334
  return PERSONAL_MEMORY_TOOL_NAMES.includes(name);
527707
528335
  }
527708
- function compactObject(input) {
527709
- return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
527710
- }
527711
528336
  function normalizePhaseOneRecall(payload, limit) {
527712
528337
  if (!isRecord$2(payload) || !Array.isArray(payload["ergebnis"])) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
527713
528338
  const results = payload["ergebnis"];
@@ -530707,7 +531332,9 @@ var SessionEventHandler = class {
530707
531332
  this.handleStepCompleted(event);
530708
531333
  this.host.releaseChannelQueueAtSafePoint();
530709
531334
  break;
530710
- case "turn.step.retrying": break;
531335
+ case "turn.step.retrying":
531336
+ this.host.streamingUI.setActivityRetrying();
531337
+ break;
530711
531338
  case "tool.progress":
530712
531339
  this.handleToolProgress(event);
530713
531340
  break;
@@ -533490,6 +534117,9 @@ var StreamingUIController = class {
533490
534117
  _currentTurnId = void 0;
533491
534118
  _currentStep = 0;
533492
534119
  _lastToolName = "none";
534120
+ activityWords = new ThinkingActivityRotator();
534121
+ activityRetrying = false;
534122
+ activityFailed = false;
533493
534123
  _liveTurnStartedAtMs = void 0;
533494
534124
  _sessionTotalTokens;
533495
534125
  _liveOutputTokens = new LiveOutputTokenCounter();
@@ -533519,18 +534149,37 @@ var StreamingUIController = class {
533519
534149
  }
533520
534150
  setStep(step) {
533521
534151
  this._currentStep = step;
534152
+ this.activityRetrying = false;
534153
+ }
534154
+ setActivityRetrying() {
534155
+ this.activityRetrying = true;
534156
+ }
534157
+ getActivityLabel(composing = false) {
534158
+ let activeCall;
534159
+ for (const call of this._activeToolCalls.values()) if (call.result === void 0 && !call.truncated) activeCall = call;
534160
+ const group = composing && activeCall === void 0 && !this.activityRetrying ? "Creating" : inferThinkingActivityGroup(activeCall, {
534161
+ retrying: this.activityRetrying,
534162
+ failed: this.activityFailed
534163
+ });
534164
+ return `${this.activityWords.resolve(group)}…`;
533522
534165
  }
533523
534166
  getLastToolName() {
533524
534167
  return this._lastToolName;
533525
534168
  }
533526
534169
  resetSessionDiagnostics() {
533527
534170
  this._lastToolName = "none";
534171
+ this.activityWords = new ThinkingActivityRotator();
534172
+ this.activityRetrying = false;
534173
+ this.activityFailed = false;
533528
534174
  }
533529
534175
  hasActiveTurn() {
533530
534176
  return this._currentTurnId !== void 0;
533531
534177
  }
533532
534178
  beginLiveTurn() {
533533
534179
  this._liveTurnStartedAtMs = Date.now();
534180
+ this.activityWords = new ThinkingActivityRotator();
534181
+ this.activityRetrying = false;
534182
+ this.activityFailed = false;
533534
534183
  this._liveOutputTokens.reset();
533535
534184
  this._countedToolCallIds.clear();
533536
534185
  }
@@ -533746,6 +534395,8 @@ var StreamingUIController = class {
533746
534395
  * component, and returns whether the call was new (no previous entry). */
533747
534396
  registerToolCall(toolCall) {
533748
534397
  this._lastToolName = toolCall.name;
534398
+ this.activityRetrying = false;
534399
+ this.activityFailed = false;
533749
534400
  if (!this._countedToolCallIds.has(toolCall.id)) {
533750
534401
  this._countedToolCallIds.add(toolCall.id);
533751
534402
  this.recordLiveOutput(`${toolCall.name}${JSON.stringify(toolCall.args)}`);
@@ -533795,7 +534446,10 @@ var StreamingUIController = class {
533795
534446
  * Returns the matched ToolCallBlockData, or undefined if no call was tracked. */
533796
534447
  completeToolResult(toolCallId, result) {
533797
534448
  const matchedCall = this._activeToolCalls.get(toolCallId);
533798
- if (matchedCall !== void 0) this.onToolCallEnd(toolCallId, result);
534449
+ if (matchedCall !== void 0) {
534450
+ this.activityFailed = result.is_error === true;
534451
+ this.onToolCallEnd(toolCallId, result);
534452
+ }
533799
534453
  this._activeToolCalls.delete(toolCallId);
533800
534454
  this._streamingToolCallArguments.delete(toolCallId);
533801
534455
  return matchedCall;
@@ -534008,7 +534662,7 @@ var StreamingUIController = class {
534008
534662
  if (this._activeThinkingComponent === void 0) {
534009
534663
  this._pendingAgentGroup = null;
534010
534664
  this._pendingReadGroup = null;
534011
- this._activeThinkingComponent = new ThinkingComponent(fullText, true, "live", state.ui, { ...this.getLiveActivityMetrics() });
534665
+ this._activeThinkingComponent = new ThinkingComponent(fullText, true, "live", state.ui, { ...this.getLiveActivityMetrics() }, () => this.getActivityLabel());
534012
534666
  if (state.toolOutputExpanded) this._activeThinkingComponent.setExpanded(true);
534013
534667
  state.transcriptContainer.addChild(this._activeThinkingComponent);
534014
534668
  } else {
@@ -535847,6 +536501,7 @@ var ApprovalController = class extends ReverseRpcController {
535847
536501
  if (response.decision !== "approved") return void 0;
535848
536502
  if (response.scope !== "session") return void 0;
535849
536503
  if (!resolvedPayload.choices.some((choice) => choice.response === "approved_for_session")) return;
536504
+ if (!queuedPayload.choices.some((choice) => choice.response === "approved_for_session")) return;
535850
536505
  if (resolvedPayload.action !== queuedPayload.action) return void 0;
535851
536506
  return {
535852
536507
  decision: "approved",
@@ -540385,7 +541040,7 @@ var BlunTUI = class {
540385
541040
  const metrics = this.streamingUI.getLiveActivityMetrics();
540386
541041
  const startedAtMs = metrics.startedAtMs ?? this.activitySpinnerFallbackStartMs;
540387
541042
  const mode = this.resolveActivityPaneMode();
540388
- return liveActivityLabels(mode === "waiting" || mode === "thinking" ? rotatingThinkingLabel(personaName() ?? "King", startedAtMs) : this.activitySpinnerBaseLabel, {
541043
+ return liveActivityLabels(mode === "waiting" || mode === "thinking" || mode === "tool" || mode === "composing" ? `${personaName() ?? "King"} ${this.streamingUI.getActivityLabel(mode === "composing")}` : this.activitySpinnerBaseLabel, {
540389
541044
  ...metrics,
540390
541045
  startedAtMs
540391
541046
  });