blun-king-cli 9.1.612 → 9.1.613

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/blun.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // BLUN_BUILD_INPUT_SHA256:f9f2527561c5e5ec1afc53eef27313667c4d323a444532439e73a66865340f69
2
+ // BLUN_BUILD_INPUT_SHA256:5c7277a864ffcc0a6909494ad5ada6956f900fe23735200c5aca26b1e7d78834
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);
@@ -1211,7 +1211,7 @@ function normalizeBlunToolSchema(schema) {
1211
1211
  }
1212
1212
  function ensureBlunPropertyTypes(schema) {
1213
1213
  const normalized = cloneJsonValue(schema);
1214
- if (!isRecord$29(normalized)) throw new Error("JSON Schema root must normalize to an object.");
1214
+ if (!isRecord$33(normalized)) throw new Error("JSON Schema root must normalize to an object.");
1215
1215
  recurseSchema(normalized);
1216
1216
  return normalized;
1217
1217
  }
@@ -1272,7 +1272,7 @@ function resolveLocalJsonPointer(root, ref) {
1272
1272
  let current = root;
1273
1273
  for (const rawPart of ref.slice(2).split("/")) {
1274
1274
  const part = unescapeJsonPointerPart(rawPart);
1275
- if (isRecord$29(current)) {
1275
+ if (isRecord$33(current)) {
1276
1276
  if (!hasOwn(current, part)) return { found: false };
1277
1277
  current = current[part];
1278
1278
  } else if (Array.isArray(current)) {
@@ -1294,20 +1294,20 @@ function parseJsonPointerArrayIndex(part) {
1294
1294
  return Number(part);
1295
1295
  }
1296
1296
  function recurseSchema(node) {
1297
- if (!isRecord$29(node)) return;
1297
+ if (!isRecord$33(node)) return;
1298
1298
  visitChildSchemas(node, normalizeProperty);
1299
1299
  }
1300
1300
  function visitChildSchemas(node, visit) {
1301
1301
  for (const { key, kind } of CHILD_SCHEMA_SLOTS) {
1302
1302
  const value = node[key];
1303
1303
  if (kind === "single") {
1304
- if (isRecord$29(value)) visit(value);
1304
+ if (isRecord$33(value)) visit(value);
1305
1305
  } else if (kind === "array") {
1306
1306
  if (Array.isArray(value)) for (const item of value) visit(item);
1307
1307
  } else if (kind === "map") {
1308
- if (isRecord$29(value)) for (const item of Object.values(value)) visit(item);
1308
+ if (isRecord$33(value)) for (const item of Object.values(value)) visit(item);
1309
1309
  } else if (kind === "schema-or-array") {
1310
- if (isRecord$29(value)) visit(value);
1310
+ if (isRecord$33(value)) visit(value);
1311
1311
  else if (Array.isArray(value)) for (const item of value) visit(item);
1312
1312
  }
1313
1313
  }
@@ -1319,7 +1319,7 @@ function childSchemaKeysForParentType(parentType) {
1319
1319
  });
1320
1320
  }
1321
1321
  function normalizeProperty(node) {
1322
- if (!isRecord$29(node)) return;
1322
+ if (!isRecord$33(node)) return;
1323
1323
  if (!hasOwn(node, "type") && !hasAnyKey(node, TYPE_COMPLETION_SKIP_KEYS)) {
1324
1324
  const enumValues = node["enum"];
1325
1325
  if (Array.isArray(enumValues) && enumValues.length > 0) node["type"] = inferTypeFromValues(enumValues);
@@ -1403,14 +1403,14 @@ function hasAnyKey(obj, keys) {
1403
1403
  }
1404
1404
  function cloneJsonValue(value) {
1405
1405
  if (Array.isArray(value)) return value.map((item) => cloneJsonValue(item));
1406
- if (isRecord$29(value)) {
1406
+ if (isRecord$33(value)) {
1407
1407
  const cloned = {};
1408
1408
  for (const [key, child] of Object.entries(value)) cloned[key] = cloneJsonValue(child);
1409
1409
  return cloned;
1410
1410
  }
1411
1411
  return value;
1412
1412
  }
1413
- function isRecord$29(value) {
1413
+ function isRecord$33(value) {
1414
1414
  return typeof value === "object" && value !== null && !Array.isArray(value);
1415
1415
  }
1416
1416
  function hasOwn(obj, key) {
@@ -1819,16 +1819,6 @@ function measureSerializedRequest(body, requestBytes) {
1819
1819
  const payload = parsed;
1820
1820
  const messages = Array.isArray(payload["messages"]) ? payload["messages"] : [];
1821
1821
  const tools = Array.isArray(payload["tools"]) ? payload["tools"] : void 0;
1822
- let systemMessageBytes = 0;
1823
- let conversationMessageBytes = 0;
1824
- let toolResultMessageBytes = 0;
1825
- for (const message of messages) {
1826
- const size = Buffer.byteLength(JSON.stringify(message), "utf8");
1827
- const role = message !== null && typeof message === "object" ? message["role"] : void 0;
1828
- if (role === "system" || role === "developer") systemMessageBytes += size;
1829
- else if (role === "tool") toolResultMessageBytes += size;
1830
- else conversationMessageBytes += size;
1831
- }
1832
1822
  const toolDefinitions = Object.freeze((tools ?? []).map((tool, index) => {
1833
1823
  const entry = tool !== null && typeof tool === "object" ? tool : void 0;
1834
1824
  const fn = entry?.["function"];
@@ -1839,6 +1829,44 @@ function measureSerializedRequest(body, requestBytes) {
1839
1829
  ...typeof name === "string" && name.length > 0 && name.length <= 128 ? { name } : {}
1840
1830
  });
1841
1831
  }));
1832
+ const declaredNames = new Set(toolDefinitions.flatMap((tool) => tool.name === void 0 ? [] : [tool.name]));
1833
+ const callNames = /* @__PURE__ */ new Map();
1834
+ for (const message of messages) {
1835
+ if (message === null || typeof message !== "object" || message["role"] !== "assistant") continue;
1836
+ const calls = message["tool_calls"];
1837
+ if (!Array.isArray(calls)) continue;
1838
+ for (const call of calls) {
1839
+ if (call === null || typeof call !== "object") continue;
1840
+ const entry = call;
1841
+ const fn = entry["function"];
1842
+ const name = fn !== null && typeof fn === "object" ? fn["name"] : void 0;
1843
+ const id = entry["id"];
1844
+ if (typeof id !== "string" || id.length === 0) continue;
1845
+ callNames.set(id, callNames.has(id) ? void 0 : typeof name === "string" && declaredNames.has(name) ? name : void 0);
1846
+ }
1847
+ }
1848
+ let systemMessageBytes = 0;
1849
+ let conversationMessageBytes = 0;
1850
+ let toolResultMessageBytes = 0;
1851
+ const results = /* @__PURE__ */ new Map();
1852
+ for (const message of messages) {
1853
+ const size = Buffer.byteLength(JSON.stringify(message), "utf8");
1854
+ const role = message !== null && typeof message === "object" ? message["role"] : void 0;
1855
+ if (role === "system" || role === "developer") systemMessageBytes += size;
1856
+ else if (role === "tool") {
1857
+ toolResultMessageBytes += size;
1858
+ const id = message["tool_call_id"];
1859
+ const name = typeof id === "string" ? callNames.get(id) : void 0;
1860
+ const key = name ?? "";
1861
+ const previous = results.get(key);
1862
+ results.set(key, {
1863
+ ...name === void 0 ? {} : { name },
1864
+ count: (previous?.count ?? 0) + 1,
1865
+ bytes: (previous?.bytes ?? 0) + size
1866
+ });
1867
+ } else conversationMessageBytes += size;
1868
+ }
1869
+ const toolResultByTool = Object.freeze(Array.from(results.values(), (entry) => Object.freeze(entry)));
1842
1870
  const toolArrayOverheadBytes = tools === void 0 ? 0 : 2 + Math.max(0, tools.length - 1);
1843
1871
  const toolSchemaBytes = toolDefinitions.reduce((sum, tool) => sum + tool.bytes, toolArrayOverheadBytes);
1844
1872
  return Object.freeze({
@@ -1848,6 +1876,7 @@ function measureSerializedRequest(body, requestBytes) {
1848
1876
  systemMessageBytes,
1849
1877
  conversationMessageBytes,
1850
1878
  toolResultMessageBytes,
1879
+ ...toolResultByTool.length === 0 ? {} : { toolResultByTool },
1851
1880
  toolSchemaBytes,
1852
1881
  toolDefinitions,
1853
1882
  toolArrayOverheadBytes,
@@ -2350,6 +2379,9 @@ function extractChatCompletionUsage(usage) {
2350
2379
  const value = usage;
2351
2380
  const promptTokens = typeof value["prompt_tokens"] === "number" ? value["prompt_tokens"] : 0;
2352
2381
  const completionTokens = typeof value["completion_tokens"] === "number" ? value["completion_tokens"] : 0;
2382
+ const completionDetails = value["completion_tokens_details"];
2383
+ const reportedReasoning = completionDetails !== null && typeof completionDetails === "object" ? completionDetails["reasoning_tokens"] : void 0;
2384
+ const outputReasoning = typeof reportedReasoning === "number" && Number.isSafeInteger(reportedReasoning) && reportedReasoning >= 0 && reportedReasoning <= completionTokens ? reportedReasoning : void 0;
2353
2385
  let cachedTokens = 0;
2354
2386
  if (typeof value["cached_tokens"] === "number") cachedTokens = value["cached_tokens"];
2355
2387
  else if (value["prompt_tokens_details"] !== null && typeof value["prompt_tokens_details"] === "object") {
@@ -2359,6 +2391,7 @@ function extractChatCompletionUsage(usage) {
2359
2391
  return {
2360
2392
  inputOther: promptTokens - cachedTokens,
2361
2393
  output: completionTokens,
2394
+ ...outputReasoning === void 0 ? {} : { outputReasoning },
2362
2395
  inputCacheRead: cachedTokens,
2363
2396
  inputCacheCreation: 0
2364
2397
  };
@@ -3373,9 +3406,11 @@ function emptyUsage() {
3373
3406
  * Sum two TokenUsage values.
3374
3407
  */
3375
3408
  function addUsage$1(a, b) {
3409
+ const outputReasoning = a.outputReasoning !== void 0 && b.outputReasoning !== void 0 ? a.outputReasoning + b.outputReasoning : a.output === 0 ? b.outputReasoning : b.output === 0 ? a.outputReasoning : void 0;
3376
3410
  return {
3377
3411
  inputOther: a.inputOther + b.inputOther,
3378
3412
  output: a.output + b.output,
3413
+ ...outputReasoning === void 0 ? {} : { outputReasoning },
3379
3414
  inputCacheRead: a.inputCacheRead + b.inputCacheRead,
3380
3415
  inputCacheCreation: a.inputCacheCreation + b.inputCacheCreation
3381
3416
  };
@@ -10153,6 +10188,8 @@ var init_schema = __esmMin((() => {
10153
10188
  ProviderConfigSchema = object$1({
10154
10189
  type: ProviderTypeSchema,
10155
10190
  apiKey: string().optional(),
10191
+ memoryWorkspaceId: string().regex(/^blun-[0-9a-f]{64}$/u).optional(),
10192
+ memoryApiKeyHash: string().regex(/^[0-9a-f]{64}$/u).optional(),
10156
10193
  baseUrl: string().optional(),
10157
10194
  defaultModel: string().optional(),
10158
10195
  oauth: OAuthRefSchema.optional(),
@@ -10643,7 +10680,8 @@ function tokenToWire(token) {
10643
10680
  expires_at: token.expiresAt,
10644
10681
  scope: token.scope,
10645
10682
  token_type: token.tokenType,
10646
- expires_in: token.expiresIn
10683
+ expires_in: token.expiresIn,
10684
+ ...token.memoryWorkspaceId === void 0 ? {} : { memory_workspace_id: token.memoryWorkspaceId }
10647
10685
  };
10648
10686
  }
10649
10687
  function tokenFromWire(wire) {
@@ -10653,13 +10691,14 @@ function tokenFromWire(wire) {
10653
10691
  expiresAt: typeof wire.expires_at === "number" ? wire.expires_at : 0,
10654
10692
  scope: wire.scope ?? "",
10655
10693
  tokenType: wire.token_type ?? "",
10656
- expiresIn: typeof wire.expires_in === "number" ? wire.expires_in : 0
10694
+ expiresIn: typeof wire.expires_in === "number" ? wire.expires_in : 0,
10695
+ ...typeof wire.memory_workspace_id === "string" && wire.memory_workspace_id.length > 0 ? { memoryWorkspaceId: wire.memory_workspace_id } : {}
10657
10696
  };
10658
10697
  }
10659
10698
  var init_types$17 = __esmMin((() => {}));
10660
10699
  //#endregion
10661
10700
  //#region ../../packages/oauth/src/utils.ts
10662
- function isRecord$28(value) {
10701
+ function isRecord$32(value) {
10663
10702
  return typeof value === "object" && value !== null && !Array.isArray(value);
10664
10703
  }
10665
10704
  var init_utils$1 = __esmMin((() => {}));
@@ -11242,7 +11281,7 @@ var init_storage = __esmMin((() => {
11242
11281
  } catch {
11243
11282
  return;
11244
11283
  }
11245
- if (!isRecord$28(parsed)) return void 0;
11284
+ if (!isRecord$32(parsed)) return void 0;
11246
11285
  return tokenFromWire(parsed);
11247
11286
  }
11248
11287
  async save(name, token) {
@@ -11336,7 +11375,7 @@ function extractApiErrorMessage(value) {
11336
11375
  }
11337
11376
  return;
11338
11377
  }
11339
- if (!isRecord$28(value)) return void 0;
11378
+ if (!isRecord$32(value)) return void 0;
11340
11379
  for (const key of DIRECT_ERROR_KEYS) {
11341
11380
  const message = stringField$4(value, key);
11342
11381
  if (message !== void 0) return message;
@@ -11344,7 +11383,7 @@ function extractApiErrorMessage(value) {
11344
11383
  const error = value["error"];
11345
11384
  const errorString = nonEmptyString$7(error);
11346
11385
  if (errorString !== void 0) return errorString;
11347
- if (isRecord$28(error)) for (const key of NESTED_ERROR_KEYS) {
11386
+ if (isRecord$32(error)) for (const key of NESTED_ERROR_KEYS) {
11348
11387
  const message = stringField$4(error, key);
11349
11388
  if (message !== void 0) return message;
11350
11389
  }
@@ -11434,7 +11473,7 @@ async function postForm(url, params, deviceHeaders, options) {
11434
11473
  let data = {};
11435
11474
  try {
11436
11475
  const parsed = await response.json();
11437
- if (isRecord$28(parsed)) data = parsed;
11476
+ if (isRecord$32(parsed)) data = parsed;
11438
11477
  } catch {}
11439
11478
  return {
11440
11479
  status,
@@ -13064,6 +13103,27 @@ var init_oauth_manager = __esmMin((() => {
13064
13103
  const state = await this.loadState();
13065
13104
  return state.kind === "valid" ? state.token.accessToken : void 0;
13066
13105
  }
13106
+ async getCachedMemoryWorkspaceId() {
13107
+ const state = await this.loadState();
13108
+ return state.kind === "valid" && state.token.expiresAt > this.now() ? state.token.memoryWorkspaceId : void 0;
13109
+ }
13110
+ async cacheMemoryWorkspaceId(workspaceId) {
13111
+ if (workspaceId.length === 0) return false;
13112
+ const release = await this.acquireRefreshLock();
13113
+ try {
13114
+ const state = await this.loadState();
13115
+ if (state.kind !== "valid" || state.token.expiresAt <= this.now()) return false;
13116
+ if (state.token.memoryWorkspaceId === workspaceId) return true;
13117
+ if (state.token.memoryWorkspaceId !== void 0) return false;
13118
+ await this.storage.save(this.config.name, {
13119
+ ...state.token,
13120
+ memoryWorkspaceId: workspaceId
13121
+ });
13122
+ return true;
13123
+ } finally {
13124
+ await release();
13125
+ }
13126
+ }
13067
13127
  async logout() {
13068
13128
  await this.inFlightRefresh?.promise.catch(() => void 0);
13069
13129
  const release = await this.acquireRefreshLock();
@@ -13131,7 +13191,10 @@ var init_oauth_manager = __esmMin((() => {
13131
13191
  if (activeToken.refreshToken.length === 0) throw new OAuthUnauthorizedError(`Token for "${this.config.name}" has no refresh_token; re-login required.`);
13132
13192
  try {
13133
13193
  const refreshed = await this.refreshImpl(this.config, activeToken.refreshToken);
13134
- await this.storage.save(this.config.name, refreshed);
13194
+ await this.storage.save(this.config.name, {
13195
+ ...refreshed,
13196
+ memoryWorkspaceId: activeToken.memoryWorkspaceId
13197
+ });
13135
13198
  this.notifyRefresh({ success: true });
13136
13199
  return refreshed.accessToken;
13137
13200
  } catch (error) {
@@ -13346,9 +13409,9 @@ function blunContextWindowsUrl(oauthHost) {
13346
13409
  return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}/api/verbrauch/tarife`;
13347
13410
  }
13348
13411
  function parseManagedContextWindow(payload, plan) {
13349
- if (!isRecord$28(payload)) return void 0;
13412
+ if (!isRecord$32(payload)) return void 0;
13350
13413
  const contextWindows = payload["kontext"];
13351
- if (!isRecord$28(contextWindows)) return void 0;
13414
+ if (!isRecord$32(contextWindows)) return void 0;
13352
13415
  const value = contextWindows[plan];
13353
13416
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
13354
13417
  }
@@ -13383,7 +13446,7 @@ function parseManagedUsagePayload(payload) {
13383
13446
  const plan = typeof rec["plan"] === "string" && rec["plan"].trim().length > 0 ? rec["plan"].trim() : void 0;
13384
13447
  const contextWindowTokens = managedContextWindowFrom(rec);
13385
13448
  const unlimited = rec["unlimited"] === true;
13386
- const stand = isRecord$28(rec["stand"]) ? rec["stand"] : void 0;
13449
+ const stand = isRecord$32(rec["stand"]) ? rec["stand"] : void 0;
13387
13450
  if (stand !== void 0) for (const [sourceKey, id, label] of ACCOUNT_USAGE_WINDOWS) {
13388
13451
  const row = toAccountUsageRow(stand[sourceKey], id, label, unlimited);
13389
13452
  if (row !== null) limits.push(row);
@@ -13393,9 +13456,9 @@ function parseManagedUsagePayload(payload) {
13393
13456
  const item = rawLimits[idx];
13394
13457
  if (!item || typeof item !== "object") continue;
13395
13458
  const detailRaw = item["detail"];
13396
- const detail = isRecord$28(detailRaw) ? detailRaw : item;
13459
+ const detail = isRecord$32(detailRaw) ? detailRaw : item;
13397
13460
  const windowRaw = item["window"];
13398
- const row = toUsageRow(detail, limitLabel(item, detail, isRecord$28(windowRaw) ? windowRaw : {}, idx));
13461
+ const row = toUsageRow(detail, limitLabel(item, detail, isRecord$32(windowRaw) ? windowRaw : {}, idx));
13399
13462
  if (row !== null) limits.push(row);
13400
13463
  }
13401
13464
  return {
@@ -13419,7 +13482,7 @@ function managedContextWindowFrom(payload) {
13419
13482
  return values.every((value) => value === first) ? first : void 0;
13420
13483
  }
13421
13484
  function toAccountUsageRow(raw, id, label, accountUnlimited) {
13422
- if (!isRecord$28(raw)) return null;
13485
+ if (!isRecord$32(raw)) return null;
13423
13486
  const used = toInt(raw["verbraucht"]);
13424
13487
  const unlimited = accountUnlimited || raw["unlimited"] === true;
13425
13488
  const fraction = raw["anteil"];
@@ -13452,7 +13515,7 @@ function toAccountUsageRow(raw, id, label, accountUnlimited) {
13452
13515
  };
13453
13516
  }
13454
13517
  function toUsageRow(raw, defaultLabel) {
13455
- if (!isRecord$28(raw)) return null;
13518
+ if (!isRecord$32(raw)) return null;
13456
13519
  const unlimited = raw["unlimited"] === true;
13457
13520
  const limit = toInt(raw["limit"]);
13458
13521
  let used = toInt(raw["used"]);
@@ -13573,7 +13636,7 @@ function isManagedQuotaErrorMessage(message) {
13573
13636
  return /you(?:'|’)?ve reached your usage limit/.test(normalized) && /billing cycle|quota will be (?:refreshed|reset)|purchase extra usage/.test(normalized);
13574
13637
  }
13575
13638
  function hasManagedUsageShape(payload) {
13576
- if (!isRecord$28(payload)) return false;
13639
+ if (!isRecord$32(payload)) return false;
13577
13640
  let recognized = false;
13578
13641
  if ("context_window_tokens" in payload || "contextWindowTokens" in payload) {
13579
13642
  recognized = true;
@@ -13589,15 +13652,15 @@ function hasManagedUsageShape(payload) {
13589
13652
  if (!Array.isArray(limits)) return false;
13590
13653
  for (let index = 0; index < limits.length; index++) {
13591
13654
  const item = limits[index];
13592
- if (!isRecord$28(item)) return false;
13593
- const detail = isRecord$28(item["detail"]) ? item["detail"] : item;
13594
- if (toUsageRow(detail, limitLabel(item, detail, isRecord$28(item["window"]) ? item["window"] : {}, index)) === null) return false;
13655
+ if (!isRecord$32(item)) return false;
13656
+ const detail = isRecord$32(item["detail"]) ? item["detail"] : item;
13657
+ if (toUsageRow(detail, limitLabel(item, detail, isRecord$32(item["window"]) ? item["window"] : {}, index)) === null) return false;
13595
13658
  }
13596
13659
  }
13597
13660
  if ("stand" in payload) {
13598
13661
  recognized = true;
13599
13662
  const stand = payload["stand"];
13600
- if (!isRecord$28(stand)) return false;
13663
+ if (!isRecord$32(stand)) return false;
13601
13664
  const windows = ACCOUNT_USAGE_WINDOWS.filter(([sourceKey]) => sourceKey in stand);
13602
13665
  if (windows.length === 0) return false;
13603
13666
  const unlimited = payload["unlimited"] === true;
@@ -13693,8 +13756,8 @@ function userExtras(existing, remoteOwnedFields) {
13693
13756
  return out;
13694
13757
  }
13695
13758
  function mergeRefreshedModelAlias(existing, remote, remoteOwnedFields) {
13696
- const current = isRecord$28(existing) ? existing : {};
13697
- const overrides = cloneOverrides(isRecord$28(current["overrides"]) ? current["overrides"] : void 0);
13759
+ const current = isRecord$32(existing) ? existing : {};
13760
+ const overrides = cloneOverrides(isRecord$32(current["overrides"]) ? current["overrides"] : void 0);
13698
13761
  return {
13699
13762
  ...userExtras(current, remoteOwnedFields),
13700
13763
  ...remote,
@@ -13883,7 +13946,7 @@ function parseModelContextLength(item, modelId) {
13883
13946
  return values[0];
13884
13947
  }
13885
13948
  function toModelInfo(item) {
13886
- if (!isRecord$28(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
13949
+ if (!isRecord$32(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
13887
13950
  const contextLength = parseModelContextLength(item, item["id"]);
13888
13951
  const displayName = item["display_name"];
13889
13952
  const normalizedDisplayName = typeof displayName === "string" && displayName.length > 0 ? displayName : void 0;
@@ -13970,7 +14033,7 @@ async function fetchManagedBlunCodeModels(options) {
13970
14033
  throw new Error(message);
13971
14034
  }
13972
14035
  const payload = await response.json();
13973
- if (!isRecord$28(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
14036
+ if (!isRecord$32(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
13974
14037
  return payload["data"].map((item) => toModelInfo(item)).filter((item) => item !== void 0);
13975
14038
  }
13976
14039
  throw new Error(`Failed to list BLUN models for ${baseUrl}.`);
@@ -14013,11 +14076,11 @@ function applyManagedBlunCodeConfig(config, options) {
14013
14076
  apiKey
14014
14077
  };
14015
14078
  const upstreamKeys = new Set(options.models.map((m) => managedModelKey(m.id)));
14016
- for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$28(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
14079
+ for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$32(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
14017
14080
  for (const model of options.models) {
14018
14081
  const capabilities = capabilitiesForModel(model);
14019
14082
  const key = managedModelKey(model.id);
14020
- const existing = isRecord$28(existingModels[key]) ? existingModels[key] : {};
14083
+ const existing = isRecord$32(existingModels[key]) ? existingModels[key] : {};
14021
14084
  const supportsAdaptiveThinking = capabilities?.includes("thinking") === true || capabilities?.includes("always_thinking") === true;
14022
14085
  existingModels[key] = mergeRefreshedModelAlias(existing, {
14023
14086
  provider: BLUN_PROVIDER_NAME$1,
@@ -14065,7 +14128,7 @@ function applyManagedBlunCodeLogoutConfig(config) {
14065
14128
  let removedDefaultModel = false;
14066
14129
  const existingModels = config.models ?? {};
14067
14130
  for (const [key, model] of Object.entries(existingModels)) {
14068
- if (!isRecord$28(model) || model["provider"] !== "managed:blun") continue;
14131
+ if (!isRecord$32(model) || model["provider"] !== "managed:blun") continue;
14069
14132
  delete existingModels[key];
14070
14133
  if (config.defaultModel === key) removedDefaultModel = true;
14071
14134
  }
@@ -14105,7 +14168,7 @@ function selectDefaultModel(config, models, options) {
14105
14168
  function canPreserveDefaultModel(existingModels, defaultModel, managedModels) {
14106
14169
  if (managedModels.has(defaultModel)) return true;
14107
14170
  const existing = existingModels[defaultModel];
14108
- return isRecord$28(existing) && existing["provider"] !== "managed:blun";
14171
+ return isRecord$32(existing) && existing["provider"] !== "managed:blun";
14109
14172
  }
14110
14173
  function assertPositiveContextLength(model) {
14111
14174
  if (!Number.isInteger(model.contextLength) || model.contextLength <= 0) throw new Error(`BLUN model "${model.id}" must include a positive context_length.`);
@@ -14181,13 +14244,13 @@ function blunManagedQuotaUrl(oauthHost) {
14181
14244
  return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}${MANAGED_QUOTA_PATH}`;
14182
14245
  }
14183
14246
  function parseManagedQuotaPayload(payload) {
14184
- if (!isRecord$28(payload)) return void 0;
14247
+ if (!isRecord$32(payload)) return void 0;
14185
14248
  const plan = nonEmptyString$6(payload["plan"]);
14186
14249
  const paid = payload["bezahlt"];
14187
14250
  const creditCents = payload["guthaben_cent"];
14188
14251
  const billingKind = nonEmptyString$6(payload["art"]);
14189
14252
  const globalUnlimited = payload["unlimited"];
14190
- if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$28(payload["stand"])) return;
14253
+ if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$32(payload["stand"])) return;
14191
14254
  if (!hasStrictQuotaStand(payload["stand"], globalUnlimited === true)) return void 0;
14192
14255
  const limits = parseManagedUsagePayload(payload).limits;
14193
14256
  if (limits.length !== REQUIRED_WINDOWS.length || REQUIRED_WINDOWS.some(([, id]) => limits.filter((row) => row.id === id).length !== 1)) return;
@@ -14257,7 +14320,7 @@ function nonEmptyString$6(value) {
14257
14320
  function hasStrictQuotaStand(stand, globalUnlimited) {
14258
14321
  return REQUIRED_WINDOWS.every(([sourceKey]) => {
14259
14322
  const row = stand[sourceKey];
14260
- if (!isRecord$28(row)) return false;
14323
+ if (!isRecord$32(row)) return false;
14261
14324
  const used = row["verbraucht"];
14262
14325
  const rowUnlimited = row["unlimited"];
14263
14326
  if (rowUnlimited !== void 0 && typeof rowUnlimited !== "boolean") return false;
@@ -14547,6 +14610,16 @@ var init_toolkit = __esmMin((() => {
14547
14610
  hasToken: await this.managerFor(name, oauthKey, oauthHost).hasToken()
14548
14611
  }] };
14549
14612
  }
14613
+ async getCachedMemoryWorkspaceId(oauthRef) {
14614
+ const oauthHost = this.oauthHostFor(oauthRef);
14615
+ const oauthKey = oauthRef?.key ?? this.defaultOAuthKey(void 0, oauthHost);
14616
+ return this.managerFor(BLUN_PROVIDER_NAME$1, oauthKey, oauthHost).getCachedMemoryWorkspaceId();
14617
+ }
14618
+ async cacheMemoryWorkspaceId(workspaceId, oauthRef) {
14619
+ const oauthHost = this.oauthHostFor(oauthRef);
14620
+ const oauthKey = oauthRef?.key ?? this.defaultOAuthKey(void 0, oauthHost);
14621
+ return this.managerFor(BLUN_PROVIDER_NAME$1, oauthKey, oauthHost).cacheMemoryWorkspaceId(workspaceId);
14622
+ }
14550
14623
  async login(providerName, options = {}) {
14551
14624
  const name = providerName ?? "managed:blun";
14552
14625
  const oauthHost = this.oauthHostFor(options.oauthRef, options.oauthHost);
@@ -16687,6 +16760,8 @@ function providerToToml(provider, rawProvider) {
16687
16760
  for (const key of [
16688
16761
  "type",
16689
16762
  "apiKey",
16763
+ "memoryWorkspaceId",
16764
+ "memoryApiKeyHash",
16690
16765
  "baseUrl",
16691
16766
  "defaultModel",
16692
16767
  "oauth",
@@ -21772,7 +21847,7 @@ function parseSkillText(options) {
21772
21847
  throw error;
21773
21848
  }
21774
21849
  const frontmatter = parsed.data ?? {};
21775
- if (!isRecord$27(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
21850
+ if (!isRecord$31(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
21776
21851
  const metadata = normalizeMetadata(frontmatter);
21777
21852
  if (!isSupportedSkillType(metadata.type)) throw new UnsupportedSkillTypeError(metadata.type ?? String(frontmatter["type"]));
21778
21853
  const name = nonEmptyString$4(metadata.name);
@@ -21885,7 +21960,7 @@ function tokenizeArgs(raw) {
21885
21960
  function nonEmptyString$4(value) {
21886
21961
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
21887
21962
  }
21888
- function isRecord$27(value) {
21963
+ function isRecord$31(value) {
21889
21964
  return typeof value === "object" && value !== null && !Array.isArray(value);
21890
21965
  }
21891
21966
  var import_regexp_escape, FrontmatterError, SkillParseError, UnsupportedSkillTypeError, FENCE, METADATA_ALIASES;
@@ -21934,7 +22009,7 @@ var init_parser$1 = __esmMin((() => {
21934
22009
  function parseCommandText(input) {
21935
22010
  const { text, commandPath, pluginId } = input;
21936
22011
  const parsed = parseFrontmatter(text);
21937
- const frontmatter = isRecord$26(parsed.data) ? parsed.data : {};
22012
+ const frontmatter = isRecord$30(parsed.data) ? parsed.data : {};
21938
22013
  const baseName = input.fallbackName ?? path.basename(commandPath).replace(/\.md$/i, "");
21939
22014
  const name = nonEmptyString$3(frontmatter["name"]) ?? baseName;
21940
22015
  const body = parsed.body.trim();
@@ -21976,7 +22051,7 @@ function descriptionFromBody(body) {
21976
22051
  if (firstLine === void 0) return "No description provided.";
21977
22052
  return firstLine.length > 240 ? `${firstLine.slice(0, 239)}…` : firstLine;
21978
22053
  }
21979
- function isRecord$26(value) {
22054
+ function isRecord$30(value) {
21980
22055
  return typeof value === "object" && value !== null && !Array.isArray(value);
21981
22056
  }
21982
22057
  var init_commands = __esmMin((() => {
@@ -29835,7 +29910,7 @@ var init_per_id_json_store = __esmMin((() => {
29835
29910
  }));
29836
29911
  //#endregion
29837
29912
  //#region ../../packages/agent-core/src/agent/background/resume-store.ts
29838
- var BACKGROUND_TASK_ID, id, digest$2, timestamp$2, ResumeIntentSchema, hash$3, isRecord$25, TaskResumeStore;
29913
+ var BACKGROUND_TASK_ID, id, digest$2, timestamp$2, ResumeIntentSchema, hash$3, isRecord$29, TaskResumeStore;
29839
29914
  var init_resume_store = __esmMin((() => {
29840
29915
  init_zod$1();
29841
29916
  BACKGROUND_TASK_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*-[0-9a-z]{8}$/;
@@ -29860,7 +29935,7 @@ var init_resume_store = __esmMin((() => {
29860
29935
  startedAt: timestamp$2.nullable()
29861
29936
  }).strict();
29862
29937
  hash$3 = (value) => createHash("sha256").update(value).digest("hex");
29863
- isRecord$25 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
29938
+ isRecord$29 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
29864
29939
  TaskResumeStore = class {
29865
29940
  home;
29866
29941
  constructor(home) {
@@ -29915,9 +29990,9 @@ var init_resume_store = __esmMin((() => {
29915
29990
  }
29916
29991
  async readOwnedTask(taskId) {
29917
29992
  const task = await this.read("tasks", taskId);
29918
- if (!isRecord$25(task)) throw new Error("Task has no persisted local record.");
29993
+ if (!isRecord$29(task)) throw new Error("Task has no persisted local record.");
29919
29994
  const owner = task["resumeOwnership"];
29920
- if (!isRecord$25(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.");
29995
+ if (!isRecord$29(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.");
29921
29996
  const { resumeOwnership: _ownership, ...info } = task;
29922
29997
  return info;
29923
29998
  }
@@ -30038,12 +30113,12 @@ function legacyStatusToCurrent$1(task) {
30038
30113
  return task.status;
30039
30114
  }
30040
30115
  function isReadablePersistedTask$1(obj) {
30041
- return isRecord$24(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
30116
+ return isRecord$28(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
30042
30117
  }
30043
30118
  function isLegacyPersistedTask$1(task) {
30044
30119
  return "task_id" in task;
30045
30120
  }
30046
- function isRecord$24(value) {
30121
+ function isRecord$28(value) {
30047
30122
  return typeof value === "object" && value !== null;
30048
30123
  }
30049
30124
  function optionalNonEmptyString$2(value) {
@@ -229641,7 +229716,7 @@ function escapeXml(value) {
229641
229716
  function locationKey(messageIndex, partIndex) {
229642
229717
  return `${String(messageIndex)}:${String(partIndex)}`;
229643
229718
  }
229644
- function isRecord$23(value) {
229719
+ function isRecord$27(value) {
229645
229720
  return value !== null && typeof value === "object" && !Array.isArray(value);
229646
229721
  }
229647
229722
  function isNonNegativeInteger$1(value) {
@@ -229842,7 +229917,7 @@ var init_vision_reader = __esmMin((() => {
229842
229917
  reason: "malformed"
229843
229918
  };
229844
229919
  }
229845
- if (!isRecord$23(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger$1(payload["prompt_eval_count"]) || !isNonNegativeInteger$1(payload["eval_count"])) return {
229920
+ if (!isRecord$27(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger$1(payload["prompt_eval_count"]) || !isNonNegativeInteger$1(payload["eval_count"])) return {
229846
229921
  ok: false,
229847
229922
  reason: "malformed"
229848
229923
  };
@@ -231074,7 +231149,7 @@ var init_full = __esmMin((() => {
231074
231149
  }
231075
231150
  requestBodyByteBudget(messages, context) {
231076
231151
  const limit = this.agent.blunConfig?.loopControl?.maxRequestHistoryBytes;
231077
- if (!this.agent.config.hasProvider || this.strategy.compactionBudgetTokens === void 0 || limit === void 0 || !Number.isSafeInteger(limit) || limit <= 0) return void 0;
231152
+ if (!this.agent.config.hasProvider || this.strategy.compactionBudgetTokens === void 0 || limit !== void 0 && (!Number.isSafeInteger(limit) || limit <= 0)) return void 0;
231078
231153
  const model = this.agent.activeResponderModel ?? this.agent.config.modelAlias;
231079
231154
  if (model === void 0 || this.agent.config.runtimeModel(model).provider.name !== "blun") return void 0;
231080
231155
  const systemPrompt = context.systemPrompt ?? this.agent.effectiveSystemPrompt;
@@ -231092,7 +231167,7 @@ var init_full = __esmMin((() => {
231092
231167
  if (Buffer.byteLength(JSON.stringify({
231093
231168
  systemPrompt,
231094
231169
  messages: []
231095
- }), "utf8") + extraBytes.toolsBytes >= BLUN_COMPACTION_REQUEST_BUDGET_BYTES) return void 0;
231170
+ }), "utf8") >= BLUN_COMPACTION_REQUEST_BUDGET_BYTES) return void 0;
231096
231171
  return {
231097
231172
  usedRequestBytesEstimate: Buffer.byteLength(JSON.stringify({
231098
231173
  systemPrompt,
@@ -231452,7 +231527,10 @@ var init_full = __esmMin((() => {
231452
231527
  dropOrphanResults: true
231453
231528
  }), createUserMessage(requestInstruction)], capability));
231454
231529
  };
231455
- const estimateRequestBytes = (messages) => Buffer.byteLength(JSON.stringify(messages), "utf8") + Buffer.byteLength(this.agent.config.systemPrompt, "utf8");
231530
+ const estimateRequestBytes = (messages) => Buffer.byteLength(JSON.stringify({
231531
+ systemPrompt: this.agent.effectiveSystemPrompt,
231532
+ messages
231533
+ }), "utf8");
231456
231534
  while (true) {
231457
231535
  signal.throwIfAborted();
231458
231536
  if (hierarchicalPassCount >= MAX_HIERARCHICAL_COMPACTION_PASSES) throw new BlunError(ErrorCodes.COMPACTION_FAILED, `Compaction stopped after ${String(MAX_HIERARCHICAL_COMPACTION_PASSES)} staged requests without reaching a final summary. The conversation history was not changed.`, { details: {
@@ -236173,7 +236251,7 @@ function structuredOutput(stdout, input) {
236173
236251
  return {
236174
236252
  ...result,
236175
236253
  additionalContext: input["hook_event_name"] === "UserPromptSubmit" && hookSpecificOutput?.hookEventName === "UserPromptSubmit" ? hookSpecificOutput.additionalContext : void 0,
236176
- updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$22(hookSpecificOutput.updatedInput) ? hookSpecificOutput.updatedInput : void 0
236254
+ updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$26(hookSpecificOutput.updatedInput) ? hookSpecificOutput.updatedInput : void 0
236177
236255
  };
236178
236256
  }
236179
236257
  return {
@@ -236242,7 +236320,7 @@ function killProcessTreeWindows(child, force) {
236242
236320
  } catch {}
236243
236321
  }
236244
236322
  }
236245
- function isRecord$22(value) {
236323
+ function isRecord$26(value) {
236246
236324
  return typeof value === "object" && value !== null && !Array.isArray(value);
236247
236325
  }
236248
236326
  function errorMessage$12(error) {
@@ -236259,7 +236337,7 @@ var init_runner = __esmMin((() => {
236259
236337
  if (typeof value === "string") return value;
236260
236338
  if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
236261
236339
  }, string().optional());
236262
- HookSpecificOutputSchema = preprocess((value) => isRecord$22(value) ? value : void 0, looseObject({
236340
+ HookSpecificOutputSchema = preprocess((value) => isRecord$26(value) ? value : void 0, looseObject({
236263
236341
  message: OptionalStringSchema,
236264
236342
  additionalContext: OptionalStringSchema,
236265
236343
  permissionDecision: unknown().optional(),
@@ -237547,7 +237625,7 @@ function parsePersonalMemoryRecall(output) {
237547
237625
  } catch {
237548
237626
  return { kind: "invalid" };
237549
237627
  }
237550
- if (!isRecord$21(parsed) || !isRecord$21(parsed["personal_memory"])) return { kind: "invalid" };
237628
+ if (!isRecord$25(parsed) || !isRecord$25(parsed["personal_memory"])) return { kind: "invalid" };
237551
237629
  const memory = parsed["personal_memory"];
237552
237630
  const savedRaw = memory["saved"];
237553
237631
  const threadsRaw = memory["threads"];
@@ -237556,7 +237634,7 @@ function parsePersonalMemoryRecall(output) {
237556
237634
  if (savedRaw.length > MAX_SAVED_MEMORIES || threadsRaw.length > MAX_THREADS || historyRaw.length > 0) return { kind: "invalid" };
237557
237635
  const saved = [];
237558
237636
  for (const value of savedRaw) {
237559
- if (!isRecord$21(value)) return { kind: "invalid" };
237637
+ if (!isRecord$25(value)) return { kind: "invalid" };
237560
237638
  const text = boundedTrimmedString(value["text"], MAX_MEMORY_TEXT_CHARS);
237561
237639
  const confidence = value["confidence"];
237562
237640
  if (text === void 0 || typeof confidence !== "string" || !CONFIDENCE_VALUES.has(confidence)) return { kind: "invalid" };
@@ -237567,7 +237645,7 @@ function parsePersonalMemoryRecall(output) {
237567
237645
  }
237568
237646
  const threads = [];
237569
237647
  for (const value of threadsRaw) {
237570
- if (!isRecord$21(value)) return { kind: "invalid" };
237648
+ if (!isRecord$25(value)) return { kind: "invalid" };
237571
237649
  const title = boundedTrimmedString(value["title"], MAX_THREAD_TITLE_CHARS);
237572
237650
  const summary = boundedTrimmedString(value["summary"], MAX_THREAD_SUMMARY_CHARS);
237573
237651
  if (title === void 0 || summary === void 0) return { kind: "invalid" };
@@ -237621,7 +237699,7 @@ function boundedTrimmedString(value, maxChars) {
237621
237699
  const trimmed = value.trim();
237622
237700
  return trimmed.length > 0 ? trimmed : void 0;
237623
237701
  }
237624
- function isRecord$21(value) {
237702
+ function isRecord$25(value) {
237625
237703
  return typeof value === "object" && value !== null && !Array.isArray(value);
237626
237704
  }
237627
237705
  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;
@@ -240076,10 +240154,27 @@ var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((expor
240076
240154
  function relatedSearchTerms(token) {
240077
240155
  return TOOL_SEARCH_RELATED_TERM_GROUPS.find((terms) => terms.includes(token)) || [token];
240078
240156
  }
240157
+ function withoutFencedCode(value) {
240158
+ const visibleLines = [];
240159
+ let fence = null;
240160
+ for (const line of String(value || "").split(/\r?\n/)) {
240161
+ const marker = line.match(/^ {0,3}(`{3,}|~{3,})/u)?.[1];
240162
+ if (fence) {
240163
+ if (marker?.[0] === fence[0] && marker.length >= fence.length && /^ {0,3}(?:`{3,}|~{3,})[ \t]*$/u.test(line)) fence = null;
240164
+ continue;
240165
+ }
240166
+ if (marker) {
240167
+ fence = marker;
240168
+ continue;
240169
+ }
240170
+ visibleLines.push(line);
240171
+ }
240172
+ return visibleLines.join("\n");
240173
+ }
240079
240174
  function rankingIntentTexts(value) {
240080
240175
  const text = String(value || "");
240081
240176
  const channelBodies = [...text.matchAll(/(?:^|\r?\n)<channel\b[^>]*>\r?\n([\s\S]*?)\r?\n<\/channel>(?=\r?\n|$)/giu)].map((match) => match[1]);
240082
- return (channelBodies.length > 0 ? channelBodies : [text]).map((intentText) => normalizeDeferredToolQuery(intentText.replace(TOOL_RANK_EMBEDDED_CONTENT_RE, " ")));
240177
+ return (channelBodies.length > 0 ? channelBodies : [text]).map((intentText) => normalizeDeferredToolQuery(withoutFencedCode(intentText.replace(TOOL_RANK_EMBEDDED_CONTENT_RE, " "))));
240083
240178
  }
240084
240179
  function rankingTokens(value) {
240085
240180
  return [...new Set(String(value || "").normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]{3,}/gu) || [])].filter((token) => !TOOL_RANK_STOP_WORDS.has(token));
@@ -251175,7 +251270,8 @@ function logStepTiming(log, turnId, step, response) {
251175
251270
  inputOtherTokens: response.usage.inputOther,
251176
251271
  cacheReadTokens: response.usage.inputCacheRead,
251177
251272
  cacheCreationTokens: response.usage.inputCacheCreation,
251178
- outputTokens: response.usage.output
251273
+ outputTokens: response.usage.output,
251274
+ ...response.usage.outputReasoning === void 0 ? {} : { outputReasoningTokens: response.usage.outputReasoning }
251179
251275
  });
251180
251276
  }
251181
251277
  function deriveStepStopReason(response) {
@@ -252249,6 +252345,7 @@ var init_events$1 = __esmMin((() => {
252249
252345
  tokenUsageSchema = object$1({
252250
252346
  inputOther: number$1(),
252251
252347
  output: number$1(),
252348
+ outputReasoning: number$1().optional(),
252252
252349
  inputCacheRead: number$1(),
252253
252350
  inputCacheCreation: number$1()
252254
252351
  });
@@ -253429,7 +253526,7 @@ function createAsyncApiDocument(options = {}) {
253429
253526
  function buildMessages() {
253430
253527
  const messages = {};
253431
253528
  for (const operation of ASYNCAPI_OPERATIONS) {
253432
- const id = messageId$1(operation.type);
253529
+ const id = messageId$2(operation.type);
253433
253530
  messages[id] = asyncApiMessage(operation.type, operation.description, operation.messageSchema);
253434
253531
  if (operation.ackSchema !== void 0) {
253435
253532
  const ackId = `${id}_ack`;
@@ -253439,10 +253536,10 @@ function buildMessages() {
253439
253536
  return messages;
253440
253537
  }
253441
253538
  function operationMessageRefs(direction) {
253442
- return ASYNCAPI_OPERATIONS.filter((operation) => operation.direction === direction).map((operation) => ({ $ref: `#/components/messages/${messageId$1(operation.type)}` }));
253539
+ return ASYNCAPI_OPERATIONS.filter((operation) => operation.direction === direction).map((operation) => ({ $ref: `#/components/messages/${messageId$2(operation.type)}` }));
253443
253540
  }
253444
253541
  function ackMessageRefs() {
253445
- return ASYNCAPI_OPERATIONS.filter((operation) => operation.ackSchema !== void 0).map((operation) => ({ $ref: `#/components/messages/${messageId$1(operation.type)}_ack` }));
253542
+ return ASYNCAPI_OPERATIONS.filter((operation) => operation.ackSchema !== void 0).map((operation) => ({ $ref: `#/components/messages/${messageId$2(operation.type)}_ack` }));
253446
253543
  }
253447
253544
  function asyncApiMessage(name, summary, schema) {
253448
253545
  return {
@@ -253462,7 +253559,7 @@ function jsonSchema$1(schema) {
253462
253559
  delete converted["$schema"];
253463
253560
  return converted;
253464
253561
  }
253465
- function messageId$1(type) {
253562
+ function messageId$2(type) {
253466
253563
  return type.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
253467
253564
  }
253468
253565
  function titleFromName(name) {
@@ -269056,6 +269153,10 @@ var init_turn = __esmMin((() => {
269056
269153
  signal.throwIfAborted();
269057
269154
  const blockResult = renderUserPromptHookBlockResult(promptHookResults);
269058
269155
  if (blockResult !== void 0) {
269156
+ this.agent.log.warn("turn blocked by UserPromptSubmit hook", {
269157
+ turnId,
269158
+ reason: blockResult.message
269159
+ });
269059
269160
  this.agent.context.appendMessage({
269060
269161
  role: "assistant",
269061
269162
  content: [{
@@ -269273,6 +269374,17 @@ var init_turn = __esmMin((() => {
269273
269374
  signal.throwIfAborted();
269274
269375
  if (stopBlock !== void 0) {
269275
269376
  stopHookContinuationUsed = true;
269377
+ this.agent.log.warn("turn continuation blocked by Stop hook", {
269378
+ turnId,
269379
+ reason: stopBlock.reason
269380
+ });
269381
+ this.agent.emitEvent({
269382
+ type: "hook.result",
269383
+ turnId,
269384
+ hookEvent: "Stop",
269385
+ content: stopBlock.reason,
269386
+ blocked: true
269387
+ });
269276
269388
  this.agent.context.appendUserMessage([{
269277
269389
  type: "text",
269278
269390
  text: stopBlock.reason
@@ -272739,6 +272851,7 @@ var init_fallback_llm = __esmMin((() => {
272739
272851
  throw new Error("Fallback request preparation requires a fresh request boundary.");
272740
272852
  }
272741
272853
  let requestParams = params;
272854
+ let messagesReady = false;
272742
272855
  const rebuildRequestMessages = async () => {
272743
272856
  const messages = await rebuildMessages();
272744
272857
  const suffix = requestParams.boundaryMessageSuffix;
@@ -272747,7 +272860,14 @@ var init_fallback_llm = __esmMin((() => {
272747
272860
  while (true) {
272748
272861
  const candidate = this.current;
272749
272862
  try {
272750
- requestParams = await this.prepareRequest?.(candidate, requestParams, rebuildRequestMessages) ?? requestParams;
272863
+ const prepared = await this.prepareRequest?.(candidate, requestParams, rebuildRequestMessages);
272864
+ if (prepared !== void 0) if ("messagesReady" in prepared) {
272865
+ requestParams = prepared.params;
272866
+ messagesReady = true;
272867
+ } else {
272868
+ requestParams = prepared;
272869
+ messagesReady = false;
272870
+ }
272751
272871
  } catch (error) {
272752
272872
  if (!isFallbackCandidateError(error) && !isUnavailableFallbackCandidate(error)) throw error;
272753
272873
  const nextIndex = this.findNextCandidateIndex();
@@ -272757,13 +272877,14 @@ var init_fallback_llm = __esmMin((() => {
272757
272877
  ...requestParams,
272758
272878
  messages: await rebuildRequestMessages()
272759
272879
  };
272880
+ messagesReady = false;
272760
272881
  requestParams.signal.throwIfAborted();
272761
272882
  this.currentIndex = nextIndex;
272762
272883
  this.onModelChanged(this.current.alias);
272763
272884
  continue;
272764
272885
  }
272765
272886
  requestParams.signal.throwIfAborted();
272766
- const messages = await rebuildRequestMessages();
272887
+ const messages = messagesReady ? requestParams.messages : await rebuildRequestMessages();
272767
272888
  requestParams.signal.throwIfAborted();
272768
272889
  return {
272769
272890
  ...requestParams,
@@ -273088,6 +273209,11 @@ var init_llm_request_logger = __esmMin((() => {
273088
273209
  systemMessageBytes: breakdown.systemMessageBytes,
273089
273210
  conversationMessageBytes: breakdown.conversationMessageBytes,
273090
273211
  toolResultMessageBytes: breakdown.toolResultMessageBytes,
273212
+ ...breakdown.toolResultByTool === void 0 ? {} : { toolResultByTool: breakdown.toolResultByTool.map((tool) => ({
273213
+ count: tool.count,
273214
+ bytes: tool.bytes,
273215
+ ...tool.name === void 0 ? {} : { name: tool.name }
273216
+ })) },
273091
273217
  toolSchemaBytes: breakdown.toolSchemaBytes,
273092
273218
  otherBytes: breakdown.otherBytes,
273093
273219
  ...breakdown.toolArrayOverheadBytes === void 0 ? {} : { toolArrayOverheadBytes: breakdown.toolArrayOverheadBytes },
@@ -273393,11 +273519,18 @@ var init_agent = __esmMin((() => {
273393
273519
  systemPrompt,
273394
273520
  tools: params.tools
273395
273521
  }).eligible ? params.tools.filter((tool) => tool.name !== "CompactConversation") : params.tools;
273396
- this.turn.commitPendingSteers(steers);
273397
- return {
273522
+ const steersCommitted = this.turn.commitPendingSteers(steers);
273523
+ if (compacted || steersCommitted) params = {
273398
273524
  ...params,
273399
- systemPrompt,
273400
- tools
273525
+ messages: await rebuildMessages()
273526
+ };
273527
+ return {
273528
+ params: {
273529
+ ...params,
273530
+ systemPrompt,
273531
+ tools
273532
+ },
273533
+ messagesReady: true
273401
273534
  };
273402
273535
  }, (candidate, _params, error) => {
273403
273536
  this.fullCompaction.observeContextOverflow(error, candidate.alias);
@@ -304778,9 +304911,9 @@ function projectAgentSpinePrompt(input) {
304778
304911
  if (typeof input["hook_event_name"] !== "string" || !PROMPT_EVENTS.has(input["hook_event_name"]) || !Array.isArray(input["prompt"])) return input;
304779
304912
  let changed = false;
304780
304913
  const prompt = input["prompt"].map((part) => {
304781
- if (!isRecord$20(part)) return part;
304914
+ if (!isRecord$24(part)) return part;
304782
304915
  const field = part["type"] === "image_url" ? "imageUrl" : part["type"] === "audio_url" ? "audioUrl" : part["type"] === "video_url" ? "videoUrl" : void 0;
304783
- if (field === void 0 || !isRecord$20(part[field]) || typeof part[field]["url"] !== "string") return part;
304916
+ if (field === void 0 || !isRecord$24(part[field]) || typeof part[field]["url"] !== "string") return part;
304784
304917
  const serialized = JSON.stringify(part);
304785
304918
  changed = true;
304786
304919
  return {
@@ -304795,7 +304928,7 @@ function projectAgentSpinePrompt(input) {
304795
304928
  prompt
304796
304929
  } : input;
304797
304930
  }
304798
- function isRecord$20(value) {
304931
+ function isRecord$24(value) {
304799
304932
  return typeof value === "object" && value !== null && !Array.isArray(value);
304800
304933
  }
304801
304934
  var PROMPT_EVENTS, EMPTY_RUNTIME, AgentSpineSessionRuntime;
@@ -339213,10 +339346,10 @@ async function appendForkedMarkers(state) {
339213
339346
  time: Date.now()
339214
339347
  };
339215
339348
  const agents = state["agents"];
339216
- if (!isRecord$19(agents)) return;
339349
+ if (!isRecord$23(agents)) return;
339217
339350
  const paths = /* @__PURE__ */ new Set();
339218
339351
  for (const agentMeta of Object.values(agents)) {
339219
- if (!isRecord$19(agentMeta)) continue;
339352
+ if (!isRecord$23(agentMeta)) continue;
339220
339353
  const homedir = agentMeta["homedir"];
339221
339354
  if (typeof homedir !== "string") continue;
339222
339355
  paths.add(join$4(homedir, "wire.jsonl"));
@@ -339228,7 +339361,7 @@ async function appendForkedMarkers(state) {
339228
339361
  }));
339229
339362
  }
339230
339363
  function customMetadataForFork(value) {
339231
- if (!isRecord$19(value)) return {};
339364
+ if (!isRecord$23(value)) return {};
339232
339365
  const custom = {};
339233
339366
  for (const [key, entry] of Object.entries(value)) {
339234
339367
  if (key === "goal" || key === "managedQuotaWarningThreshold") continue;
@@ -339283,10 +339416,10 @@ function normalizeForkTitle(title, fallback) {
339283
339416
  return typeof fallback === "string" && fallback.trim().length > 0 ? fallback : "New Session";
339284
339417
  }
339285
339418
  function rewriteAgentHomedirs(value, sourceDir, targetDir) {
339286
- if (!isRecord$19(value)) return {};
339419
+ if (!isRecord$23(value)) return {};
339287
339420
  const agents = {};
339288
339421
  for (const [agentId, agentMeta] of Object.entries(value)) {
339289
- if (!isRecord$19(agentMeta)) {
339422
+ if (!isRecord$23(agentMeta)) {
339290
339423
  agents[agentId] = agentMeta;
339291
339424
  continue;
339292
339425
  }
@@ -339304,7 +339437,7 @@ function remapSessionPath(value, sourceDir, targetDir) {
339304
339437
  if (rel.startsWith("..") || isAbsolute$2(rel)) return value;
339305
339438
  return join$4(targetDir, rel);
339306
339439
  }
339307
- function isRecord$19(value) {
339440
+ function isRecord$23(value) {
339308
339441
  return typeof value === "object" && value !== null && !Array.isArray(value);
339309
339442
  }
339310
339443
  async function statIfExists(path) {
@@ -339568,7 +339701,7 @@ var init_session_store$1 = __esmMin((() => {
339568
339701
  } catch (error) {
339569
339702
  throw new BlunError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${input.sourceId}" state.json was not found`, { cause: error });
339570
339703
  }
339571
- if (!isRecord$19(parsed)) throw new BlunError(ErrorCodes.SESSION_STATE_INVALID, `Session "${input.sourceId}" state.json is invalid`);
339704
+ if (!isRecord$23(parsed)) throw new BlunError(ErrorCodes.SESSION_STATE_INVALID, `Session "${input.sourceId}" state.json is invalid`);
339572
339705
  const title = normalizeForkTitle(input.title, parsed["title"]);
339573
339706
  const now = (/* @__PURE__ */ new Date()).toISOString();
339574
339707
  const next = {
@@ -350893,6 +351026,39 @@ var BlunAuthFacade = class {
350893
351026
  }
350894
351027
  return this.toolkit.status(providerName, this.resolveRuntimeManagedAuth(providerName).oauthRef);
350895
351028
  }
351029
+ async getCachedMemoryWorkspaceId() {
351030
+ const apiKey = nonEmpty(this.resolveManagedAuth(BLUN_PROVIDER_NAME$1).apiKey);
351031
+ if (apiKey !== void 0) {
351032
+ const provider = readConfigFileForUpdate(this.options.configPath).providers[BLUN_PROVIDER_NAME$1];
351033
+ if (provider?.apiKey !== apiKey || provider.memoryApiKeyHash !== memoryApiKeyHash(apiKey)) return;
351034
+ return provider.memoryWorkspaceId;
351035
+ }
351036
+ return this.toolkit.getCachedMemoryWorkspaceId(this.resolveRuntimeManagedAuth(BLUN_PROVIDER_NAME$1).oauthRef);
351037
+ }
351038
+ async cacheMemoryWorkspaceId(workspaceId) {
351039
+ const apiKey = nonEmpty(this.resolveManagedAuth(BLUN_PROVIDER_NAME$1).apiKey);
351040
+ if (apiKey !== void 0) {
351041
+ const hash = memoryApiKeyHash(apiKey);
351042
+ return mutateConfigFile(this.options.configPath, (config) => {
351043
+ const provider = config.providers[BLUN_PROVIDER_NAME$1];
351044
+ if (provider?.apiKey !== apiKey) return {
351045
+ config,
351046
+ result: false
351047
+ };
351048
+ if (provider.memoryApiKeyHash === hash && provider.memoryWorkspaceId !== void 0 && provider.memoryWorkspaceId !== workspaceId) return {
351049
+ config,
351050
+ result: false
351051
+ };
351052
+ provider.memoryApiKeyHash = hash;
351053
+ provider.memoryWorkspaceId = workspaceId;
351054
+ return {
351055
+ config,
351056
+ result: true
351057
+ };
351058
+ });
351059
+ }
351060
+ return this.toolkit.cacheMemoryWorkspaceId(workspaceId, this.resolveRuntimeManagedAuth(BLUN_PROVIDER_NAME$1).oauthRef);
351061
+ }
350896
351062
  async login(providerName = BLUN_PROVIDER_NAME$1, options = {}) {
350897
351063
  const auth = this.resolveManagedAuth(providerName);
350898
351064
  const loginAuth = resolveBlunCodeLoginAuth({
@@ -351198,6 +351364,9 @@ function nonEmpty(value) {
351198
351364
  const normalized = value?.trim();
351199
351365
  return normalized === void 0 || normalized.length === 0 ? void 0 : normalized;
351200
351366
  }
351367
+ function memoryApiKeyHash(apiKey) {
351368
+ return createHash("sha256").update(apiKey).digest("hex");
351369
+ }
351201
351370
  function transitionAggregateError(message, primary, secondary) {
351202
351371
  return new AggregateError([primary, secondary], message, { cause: primary });
351203
351372
  }
@@ -361563,6 +361732,30 @@ var AcpSession = class {
361563
361732
  }, event.message));
361564
361733
  return;
361565
361734
  }
361735
+ if (event.type === "hook.result") {
361736
+ if (!isFromMainAgent(event) || event.content.trim().length === 0) return;
361737
+ if (event.blocked === true) log.warn("acp: turn blocked by hook", {
361738
+ sessionId,
361739
+ hookEvent: event.hookEvent,
361740
+ reason: event.content
361741
+ });
361742
+ conn.sessionUpdate({
361743
+ sessionId,
361744
+ update: {
361745
+ sessionUpdate: "agent_message_chunk",
361746
+ content: {
361747
+ type: "text",
361748
+ text: `${event.content}\n`
361749
+ }
361750
+ }
361751
+ }).catch((err) => {
361752
+ log.warn("acp: failed to push hook result", {
361753
+ sessionId,
361754
+ error: err instanceof Error ? err.message : String(err)
361755
+ });
361756
+ });
361757
+ return;
361758
+ }
361566
361759
  if (event.type === "assistant.delta") {
361567
361760
  if (!isFromMainAgent(event)) return;
361568
361761
  conn.sessionUpdate(assistantDeltaToSessionUpdate(sessionId, event)).catch((err) => {
@@ -364331,8 +364524,8 @@ function createAccountMemoryClient(auth, options = {}) {
364331
364524
  }
364332
364525
  function readAccountMemoryConsentStatus(payload) {
364333
364526
  const settings = unwrapPayload(payload)?.["settings"];
364334
- const dataControls = isRecord$18(settings) ? settings["data_controls"] : void 0;
364335
- if (!isRecord$18(dataControls)) throw new Error("Account memory returned an invalid response.");
364527
+ const dataControls = isRecord$22(settings) ? settings["data_controls"] : void 0;
364528
+ if (!isRecord$22(dataControls)) throw new Error("Account memory returned an invalid response.");
364336
364529
  if (dataControls["memory_consent_asked"] !== true) return "never_asked";
364337
364530
  if (dataControls["allow_memory"] === true) return "enabled";
364338
364531
  if (dataControls["allow_memory"] === false) return "disabled";
@@ -364455,8 +364648,8 @@ function memoryContextSummary(facts, included) {
364455
364648
  })}`;
364456
364649
  }
364457
364650
  function unwrapPayload(value) {
364458
- if (!isRecord$18(value)) return void 0;
364459
- return isRecord$18(value["data"]) ? value["data"] : value;
364651
+ if (!isRecord$22(value)) return void 0;
364652
+ return isRecord$22(value["data"]) ? value["data"] : value;
364460
364653
  }
364461
364654
  function readFacts(root) {
364462
364655
  let rawFacts = [];
@@ -364464,7 +364657,7 @@ function readFacts(root) {
364464
364657
  else {
364465
364658
  const factsJson = parseFactsJson(root["facts_json"]);
364466
364659
  if (Array.isArray(factsJson)) rawFacts = factsJson;
364467
- else if (isRecord$18(factsJson) && Array.isArray(factsJson["facts"])) rawFacts = factsJson["facts"];
364660
+ else if (isRecord$22(factsJson) && Array.isArray(factsJson["facts"])) rawFacts = factsJson["facts"];
364468
364661
  }
364469
364662
  const facts = [];
364470
364663
  const seen = /* @__PURE__ */ new Set();
@@ -364493,7 +364686,7 @@ function parseFactsJson(value) {
364493
364686
  }
364494
364687
  }
364495
364688
  function normalizeFact(value) {
364496
- const raw = typeof value === "string" ? value : isRecord$18(value) && typeof value["text"] === "string" ? value["text"] : void 0;
364689
+ const raw = typeof value === "string" ? value : isRecord$22(value) && typeof value["text"] === "string" ? value["text"] : void 0;
364497
364690
  if (raw === void 0) return void 0;
364498
364691
  const normalized = raw.replaceAll(/\s+/gu, " ").trim();
364499
364692
  if (normalized.length === 0) return void 0;
@@ -364504,7 +364697,7 @@ function normalizeFact(value) {
364504
364697
  truncated: normalized.length > ACCOUNT_MEMORY_MAX_FACT_CHARS
364505
364698
  };
364506
364699
  }
364507
- function isRecord$18(value) {
364700
+ function isRecord$22(value) {
364508
364701
  return typeof value === "object" && value !== null && !Array.isArray(value);
364509
364702
  }
364510
364703
  //#endregion
@@ -364731,6 +364924,8 @@ registerUiCatalogFragment({
364731
364924
  "auth.logout.selectTitle": "Select a provider to log out",
364732
364925
  "auth.logout.none": "Nothing to log out.",
364733
364926
  "auth.logout.complete": "Logged out from {provider}.",
364927
+ "auth.warning.memoryRetractionOAuthPending": "Deletion has not been sent yet. It will be sent at your next sign-in.",
364928
+ "auth.warning.memoryRetractionApiKeyPending": "Deletion has not been sent yet. It will be sent once you reconnect.",
364734
364929
  "auth.warning.remoteRevokeFailed": "The local OAuth credentials were removed, but remote revocation could not be confirmed.",
364735
364930
  "auth.warning.oauthCleanupFailed": "The API key is active, but the previous OAuth credentials could not be fully removed."
364736
364931
  },
@@ -364763,6 +364958,8 @@ registerUiCatalogFragment({
364763
364958
  "auth.logout.selectTitle": "Anbieter zum Abmelden auswählen",
364764
364959
  "auth.logout.none": "Es gibt keine aktive Anmeldung.",
364765
364960
  "auth.logout.complete": "Von {provider} abgemeldet.",
364961
+ "auth.warning.memoryRetractionOAuthPending": "Löschen noch nicht übertragen – folgt bei deiner nächsten Anmeldung.",
364962
+ "auth.warning.memoryRetractionApiKeyPending": "Löschen noch nicht übertragen – folgt, sobald du wieder verbunden bist.",
364766
364963
  "auth.warning.remoteRevokeFailed": "Die lokalen OAuth-Zugangsdaten wurden entfernt, aber der Widerruf auf dem Server konnte nicht bestätigt werden.",
364767
364964
  "auth.warning.oauthCleanupFailed": "Der API-Schlüssel ist aktiv, aber die vorherigen OAuth-Zugangsdaten konnten nicht vollständig entfernt werden."
364768
364965
  },
@@ -364795,6 +364992,8 @@ registerUiCatalogFragment({
364795
364992
  "auth.logout.selectTitle": "Selecciona el proveedor cuya sesión quieres cerrar",
364796
364993
  "auth.logout.none": "No hay ninguna sesión que cerrar.",
364797
364994
  "auth.logout.complete": "Sesión cerrada en {provider}.",
364995
+ "auth.warning.memoryRetractionOAuthPending": "La eliminación aún no se ha enviado: se enviará en tu próximo inicio de sesión.",
364996
+ "auth.warning.memoryRetractionApiKeyPending": "La eliminación aún no se ha enviado: se enviará cuando se restablezca la conexión.",
364798
364997
  "auth.warning.remoteRevokeFailed": "Las credenciales OAuth locales se han eliminado, pero no se pudo confirmar su revocación en el servidor.",
364799
364998
  "auth.warning.oauthCleanupFailed": "La clave de API está activa, pero no se pudieron eliminar por completo las credenciales OAuth anteriores."
364800
364999
  },
@@ -364827,6 +365026,8 @@ registerUiCatalogFragment({
364827
365026
  "auth.logout.selectTitle": "Sélectionnez le fournisseur dont vous souhaitez vous déconnecter",
364828
365027
  "auth.logout.none": "Aucune session à fermer.",
364829
365028
  "auth.logout.complete": "Déconnexion de {provider} effectuée.",
365029
+ "auth.warning.memoryRetractionOAuthPending": "Suppression pas encore transmise – elle le sera à ta prochaine connexion.",
365030
+ "auth.warning.memoryRetractionApiKeyPending": "Suppression pas encore transmise – elle le sera dès que la connexion sera rétablie.",
364830
365031
  "auth.warning.remoteRevokeFailed": "Les identifiants OAuth locaux ont été supprimés, mais leur révocation sur le serveur n’a pas pu être confirmée.",
364831
365032
  "auth.warning.oauthCleanupFailed": "La clé API est active, mais les identifiants OAuth précédents n’ont pas pu être entièrement supprimés."
364832
365033
  },
@@ -364859,6 +365060,8 @@ registerUiCatalogFragment({
364859
365060
  "auth.logout.selectTitle": "Välj en leverantör att logga ut från",
364860
365061
  "auth.logout.none": "Det finns inget att logga ut från.",
364861
365062
  "auth.logout.complete": "Utloggad från {provider}.",
365063
+ "auth.warning.memoryRetractionOAuthPending": "Raderingen har inte överförts än – sker vid din nästa inloggning.",
365064
+ "auth.warning.memoryRetractionApiKeyPending": "Raderingen har inte överförts än – sker så snart du är ansluten igen.",
364862
365065
  "auth.warning.remoteRevokeFailed": "De lokala OAuth-uppgifterna har tagits bort, men det gick inte att bekräfta återkallelsen på servern.",
364863
365066
  "auth.warning.oauthCleanupFailed": "API-nyckeln är aktiv, men de tidigare OAuth-uppgifterna kunde inte tas bort helt."
364864
365067
  },
@@ -364891,6 +365094,8 @@ registerUiCatalogFragment({
364891
365094
  "auth.logout.selectTitle": "Vyberte poskytovatele, od kterého se chcete odhlásit",
364892
365095
  "auth.logout.none": "Nic k odhlášení.",
364893
365096
  "auth.logout.complete": "Odhlášeno od {provider}.",
365097
+ "auth.warning.memoryRetractionOAuthPending": "Smazání zatím nebylo přeneseno – proběhne při tvém příštím přihlášení.",
365098
+ "auth.warning.memoryRetractionApiKeyPending": "Smazání zatím nebylo přeneseno – proběhne, jakmile se obnoví připojení.",
364894
365099
  "auth.warning.remoteRevokeFailed": "Místní přihlašovací údaje OAuth byly odstraněny, ale jejich zneplatnění na serveru se nepodařilo potvrdit.",
364895
365100
  "auth.warning.oauthCleanupFailed": "Klíč API je aktivní, ale předchozí přihlašovací údaje OAuth nebyly zcela odstraněny."
364896
365101
  }
@@ -366022,7 +366227,7 @@ function formatErrorMessage$4(error, filePath) {
366022
366227
  function findValidationIssues(error) {
366023
366228
  if (!(error instanceof Error)) return void 0;
366024
366229
  const details = "details" in error ? error.details : void 0;
366025
- if (!isRecord$17(details)) return void 0;
366230
+ if (!isRecord$21(details)) return void 0;
366026
366231
  const validationIssues = details["validationIssues"];
366027
366232
  return isValidationIssueArray(validationIssues) ? validationIssues : void 0;
366028
366233
  }
@@ -366030,11 +366235,11 @@ function isValidationIssueArray(value) {
366030
366235
  return Array.isArray(value) && value.every(isValidationIssue);
366031
366236
  }
366032
366237
  function isValidationIssue(value) {
366033
- if (!isRecord$17(value) || typeof value["message"] !== "string") return false;
366238
+ if (!isRecord$21(value) || typeof value["message"] !== "string") return false;
366034
366239
  const path = value["path"];
366035
366240
  return Array.isArray(path) && path.every((segment) => typeof segment === "string" || typeof segment === "number");
366036
366241
  }
366037
- function isRecord$17(value) {
366242
+ function isRecord$21(value) {
366038
366243
  return typeof value === "object" && value !== null;
366039
366244
  }
366040
366245
  function findZodError(error) {
@@ -366529,7 +366734,7 @@ function assertEntryCount(value) {
366529
366734
  return value;
366530
366735
  }
366531
366736
  function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
366532
- if (!isRecord$16(value) || !hasOnlyKeys(value, [
366737
+ if (!isRecord$20(value) || !hasOnlyKeys(value, [
366533
366738
  "version",
366534
366739
  "records",
366535
366740
  "relations"
@@ -366542,7 +366747,7 @@ function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
366542
366747
  return {
366543
366748
  version: 1,
366544
366749
  records: value["records"].map((candidate, index) => {
366545
- if (!isRecord$16(candidate) || !hasOnlyKeys(candidate, [
366750
+ if (!isRecord$20(candidate) || !hasOnlyKeys(candidate, [
366546
366751
  "source_record_id",
366547
366752
  "type",
366548
366753
  "raw_locator"
@@ -366562,7 +366767,7 @@ function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
366562
366767
  };
366563
366768
  }),
366564
366769
  relations: value["relations"].map((candidate, index) => {
366565
- if (!isRecord$16(candidate) || !hasOnlyKeys(candidate, [
366770
+ if (!isRecord$20(candidate) || !hasOnlyKeys(candidate, [
366566
366771
  "from_source_record_id",
366567
366772
  "type",
366568
366773
  "to"
@@ -366572,7 +366777,7 @@ function parseMistakeRecordDeclarations(value, sourceId, declaredRecordTypes) {
366572
366777
  const target = candidate["to"];
366573
366778
  if (typeof fromRecordId !== "string" || !isValidRecordId(fromRecordId) || !recordIds.has(fromRecordId)) throw new Error(`record relation ${index} must start at a declared local record`);
366574
366779
  if (typeof type !== "string" || !MISTAKE_RELATION_TYPES.includes(type)) throw new Error(`record relation ${index} has an invalid relation type`);
366575
- if (!isRecord$16(target) || !hasOnlyKeys(target, ["source_id", "source_record_id"])) throw new Error(`record relation ${index} has an invalid target`);
366780
+ if (!isRecord$20(target) || !hasOnlyKeys(target, ["source_id", "source_record_id"])) throw new Error(`record relation ${index} has an invalid target`);
366576
366781
  const targetSourceId = target["source_id"];
366577
366782
  const targetRecordId = target["source_record_id"];
366578
366783
  if (typeof targetSourceId !== "string" || !isNormalizedSourceId(targetSourceId)) throw new Error(`record relation ${index} has an invalid target source id`);
@@ -366842,7 +367047,7 @@ function receiptsEqual(left, right) {
366842
367047
  return left.version === right.version && left.accepted === right.accepted && left.event_id === right.event_id && left.client_event_id === right.client_event_id && left.source_id === right.source_id && left.canonical_agent_id === right.canonical_agent_id && left.received_at === right.received_at && left.raw_count === right.raw_count && left.accepted_count === right.accepted_count && left.rejected_count === right.rejected_count && left.raw_bytes === right.raw_bytes && left.raw_sha256 === right.raw_sha256 && left.declared_entry_count === right.declared_entry_count;
366843
367048
  }
366844
367049
  function isStateActionReceipt(value) {
366845
- if (!isRecord$16(value) || !hasOnlyKeys(value, STATE_ACTION_KEYS)) return false;
367050
+ if (!isRecord$20(value) || !hasOnlyKeys(value, STATE_ACTION_KEYS)) return false;
366846
367051
  const reason = value["reason"];
366847
367052
  return value["version"] === 1 && typeof value["action_id"] === "string" && UUID_RE$1.test(value["action_id"]) && (value["action"] === "remove" || value["action"] === "restore") && typeof value["target_event_id"] === "string" && UUID_RE$1.test(value["target_event_id"]) && typeof value["acted_at"] === "string" && isIsoTimestamp(value["acted_at"]) && Number.isSafeInteger(value["server_sequence"]) && value["server_sequence"] >= 1 && typeof value["principal_id"] === "string" && isNormalizedSourceId(value["principal_id"]) && typeof reason === "string" && reason.trim() === reason && reason.length >= 3 && reason.length <= 500;
366848
367053
  }
@@ -366945,7 +367150,7 @@ function assertInventoryInvariants(bestandsstatus, aktualitaetsstatus, declaredE
366945
367150
  if (aktualitaetsstatus === "fresh" && lastRawObservedAt === null) throw new Error("fresh inventory requires a last raw observed timestamp");
366946
367151
  if (capturedAt !== void 0 && lastRawObservedAt !== null && Date.parse(lastRawObservedAt) > Date.parse(capturedAt)) throw new Error("last raw observed timestamp must not be later than captured at");
366947
367152
  }
366948
- function isRecord$16(value) {
367153
+ function isRecord$20(value) {
366949
367154
  return typeof value === "object" && value !== null && !Array.isArray(value);
366950
367155
  }
366951
367156
  function hasOnlyKeys(value, allowedKeys) {
@@ -367889,12 +368094,14 @@ const PERSONAL_MEMORY_EXPLICIT_CATEGORY = "user_explicit";
367889
368094
  const SAFE_BROKER_ERROR_CODES = new Set([
367890
368095
  "AUTHENTICATION_REQUIRED",
367891
368096
  "EXPLICIT_CONSENT_REQUIRED",
368097
+ "FORGET_GENERATION_CHANGED",
367892
368098
  "INTERNAL_ERROR",
367893
368099
  "INTERACTIVE_CONFIRMATION_REQUIRED",
367894
368100
  "INSUFFICIENT_SCOPE",
367895
368101
  "INVALID_PAYLOAD",
367896
368102
  "MEMORY_NOT_FOUND",
367897
368103
  "MEMORY_WRITE_DISABLED",
368104
+ "PAYLOAD_TOO_LARGE",
367898
368105
  "SECRET_REJECTED",
367899
368106
  "UNAVAILABLE"
367900
368107
  ]);
@@ -367909,7 +368116,7 @@ var PersonalMemoryBrokerError = class extends Error {
367909
368116
  }
367910
368117
  };
367911
368118
  function parsePersonalMemorySettings(payload) {
367912
- if (!isRecord$15(payload)) return void 0;
368119
+ if (!isRecord$19(payload)) return void 0;
367913
368120
  const status = payload["status"];
367914
368121
  if (status !== "configured" && status !== "never_asked") return void 0;
367915
368122
  const memoryEnabled = payload["memory_enabled"];
@@ -368018,21 +368225,23 @@ async function brokerHttpError(response) {
368018
368225
  const responseCode = await safeBrokerResponseCode(response);
368019
368226
  if (responseCode !== void 0) return new PersonalMemoryBrokerError(responseCode, status);
368020
368227
  if (status === 401) return new PersonalMemoryBrokerError("AUTHENTICATION_REQUIRED", status);
368228
+ if (status === 409) return new PersonalMemoryBrokerError("FORGET_GENERATION_CHANGED", status);
368229
+ if (status === 413) return new PersonalMemoryBrokerError("PAYLOAD_TOO_LARGE", status);
368021
368230
  if (status === 403) return new PersonalMemoryBrokerError("INSUFFICIENT_SCOPE", status);
368022
368231
  return new PersonalMemoryBrokerError("UNAVAILABLE", status);
368023
368232
  }
368024
368233
  async function safeBrokerResponseCode(response) {
368025
368234
  try {
368026
368235
  const payload = await response.json();
368027
- if (!isRecord$15(payload)) return void 0;
368028
- const nested = isRecord$15(payload["error"]) ? payload["error"]["code"] : void 0;
368236
+ if (!isRecord$19(payload)) return void 0;
368237
+ const nested = isRecord$19(payload["error"]) ? payload["error"]["code"] : void 0;
368029
368238
  const candidate = payload["code"] ?? payload["error_code"] ?? nested;
368030
368239
  return typeof candidate === "string" && SAFE_BROKER_ERROR_CODES.has(candidate) ? candidate : void 0;
368031
368240
  } catch {
368032
368241
  return;
368033
368242
  }
368034
368243
  }
368035
- function isRecord$15(value) {
368244
+ function isRecord$19(value) {
368036
368245
  return typeof value === "object" && value !== null && !Array.isArray(value);
368037
368246
  }
368038
368247
  function isAllowedBrokerRequest(method, path) {
@@ -368043,13 +368252,17 @@ function isAllowedBrokerRequest(method, path) {
368043
368252
  return false;
368044
368253
  }
368045
368254
  if (url.origin !== "https://personal-memory.invalid") return false;
368046
- if (url.search.length > 0 || url.hash.length > 0) return false;
368255
+ if (url.hash.length > 0) return false;
368256
+ if (url.pathname === "/api/memory/workspace" && url.search.length > 0) return method === "GET" && url.searchParams.size === 2 && url.searchParams.get("source") === "tui" && url.searchParams.has("sessionId") && (url.searchParams.get("sessionId")?.length ?? 0) > 0 && (url.searchParams.get("sessionId")?.length ?? 0) <= 200;
368257
+ if (url.search.length > 0) return false;
368047
368258
  const pathname = url.pathname;
368048
368259
  if (pathname === PERSONAL_MEMORY_SETTINGS_PATH) return method === "GET" || method === "PUT";
368049
368260
  if (pathname === "/api/account/consent") return method === "POST";
368050
368261
  if (pathname === PERSONAL_MEMORY_MEMORIES_PATH) return method === "GET" || method === "POST";
368051
368262
  if (/^\/v1\/me\/memories\/[0-9a-f-]{36}$/i.test(pathname)) return false;
368052
368263
  if (pathname === PERSONAL_MEMORY_RECALL_PATH) return method === PERSONAL_MEMORY_RECALL_METHOD;
368264
+ if (pathname === "/api/memory/workspace") return method === "GET";
368265
+ if (pathname === "/api/memory/capture" || pathname === "/api/memory/recall" || pathname === "/api/memory/search" || pathname === "/api/memory/retract") return method === "POST";
368053
368266
  return false;
368054
368267
  }
368055
368268
  //#endregion
@@ -368739,7 +368952,7 @@ function createAttestation(value, createdAt) {
368739
368952
  };
368740
368953
  }
368741
368954
  function parseProof(value) {
368742
- if (!isRecord$14(value) || value["schema"] !== "blun.proof" || value["schemaVersion"] !== 1) throw new Error("Unsupported proof document.");
368955
+ if (!isRecord$18(value) || value["schema"] !== "blun.proof" || value["schemaVersion"] !== 1) throw new Error("Unsupported proof document.");
368743
368956
  assertObjectKeys(value, [
368744
368957
  "schema",
368745
368958
  "schemaVersion",
@@ -368759,12 +368972,12 @@ function parseProof(value) {
368759
368972
  "incomplete",
368760
368973
  "failed"
368761
368974
  ].includes(proof.outcome)) throw new Error("Invalid proof outcome.");
368762
- if (!isRecord$14(proof.source) || proof.source.kind !== "workspace") throw new Error("Invalid proof source.");
368975
+ if (!isRecord$18(proof.source) || proof.source.kind !== "workspace") throw new Error("Invalid proof source.");
368763
368976
  assertObjectKeys(proof.source, ["kind"], ["git"], "proof source");
368764
368977
  if (proof.source.git !== void 0) validateGitSnapshot(proof.source.git);
368765
368978
  if (!Array.isArray(proof.checks) || !Array.isArray(proof.artifacts)) throw new TypeError("Invalid proof collections.");
368766
368979
  if (proof.checks.length > MAX_COMMANDS || proof.artifacts.length > MAX_ARTIFACTS) throw new Error("Proof collections exceed their limits.");
368767
- if (!isRecord$14(proof.attestation) || proof.attestation.algorithm !== "SHA-256" || proof.attestation.scope !== "content-integrity-only" || !SHA256_PATTERN.test(proof.attestation.hash)) throw new Error("Invalid proof attestation.");
368980
+ if (!isRecord$18(proof.attestation) || proof.attestation.algorithm !== "SHA-256" || proof.attestation.scope !== "content-integrity-only" || !SHA256_PATTERN.test(proof.attestation.hash)) throw new Error("Invalid proof attestation.");
368768
368981
  assertObjectKeys(proof.attestation, [
368769
368982
  "algorithm",
368770
368983
  "scope",
@@ -368779,7 +368992,7 @@ function parseProof(value) {
368779
368992
  screenshot: 0
368780
368993
  };
368781
368994
  for (const artifact of proof.artifacts) {
368782
- if (!isRecord$14(artifact) || artifact.kind !== "file" && artifact.kind !== "screenshot" || typeof artifact.id !== "string" || typeof artifact.size !== "number" || !Number.isSafeInteger(artifact.size) || artifact.size < 0 || typeof artifact.sha256 !== "string" || !SHA256_PATTERN.test(artifact.sha256)) throw new Error("Invalid proof artifact.");
368995
+ if (!isRecord$18(artifact) || artifact.kind !== "file" && artifact.kind !== "screenshot" || typeof artifact.id !== "string" || typeof artifact.size !== "number" || !Number.isSafeInteger(artifact.size) || artifact.size < 0 || typeof artifact.sha256 !== "string" || !SHA256_PATTERN.test(artifact.sha256)) throw new Error("Invalid proof artifact.");
368783
368996
  assertObjectKeys(artifact, [
368784
368997
  "id",
368785
368998
  "kind",
@@ -368796,14 +369009,14 @@ function parseProof(value) {
368796
369009
  return proof;
368797
369010
  }
368798
369011
  function validateGitSnapshot(value) {
368799
- if (!isRecord$14(value)) throw new Error("Invalid proof git snapshot.");
369012
+ if (!isRecord$18(value)) throw new Error("Invalid proof git snapshot.");
368800
369013
  assertObjectKeys(value, ["dirty", "changedCount"], [], "proof git snapshot");
368801
369014
  if (typeof value["dirty"] !== "boolean") throw new TypeError("Invalid proof git dirty flag.");
368802
369015
  if (typeof value["changedCount"] !== "number" || !Number.isSafeInteger(value["changedCount"]) || value["changedCount"] < 0) throw new Error("Invalid proof git changed count.");
368803
369016
  if (value["dirty"] !== value["changedCount"] > 0) throw new Error("Inconsistent proof git state.");
368804
369017
  }
368805
369018
  function validateProofCheck(value, index) {
368806
- if (!isRecord$14(value)) throw new Error("Invalid proof check.");
369019
+ if (!isRecord$18(value)) throw new Error("Invalid proof check.");
368807
369020
  assertObjectKeys(value, [
368808
369021
  "id",
368809
369022
  "outcome",
@@ -368815,13 +369028,13 @@ function validateProofCheck(value, index) {
368815
369028
  if (value["outcome"] !== expectedOutcome) throw new Error("Invalid proof check outcome.");
368816
369029
  }
368817
369030
  function attestedContent(value) {
368818
- if (!isRecord$14(value)) return value;
369031
+ if (!isRecord$18(value)) return value;
368819
369032
  const { attestation: _attestation, createdAt: _createdAt, ...content } = value;
368820
369033
  return content;
368821
369034
  }
368822
369035
  function canonicalize(value) {
368823
369036
  if (Array.isArray(value)) return value.map(canonicalize);
368824
- if (!isRecord$14(value)) return value;
369037
+ if (!isRecord$18(value)) return value;
368825
369038
  return Object.keys(value).toSorted().reduce((result, key) => {
368826
369039
  result[key] = canonicalize(value[key]);
368827
369040
  return result;
@@ -368898,7 +369111,7 @@ function sameFileIdentity$1(left, right) {
368898
369111
  function sameFileSnapshot(left, right) {
368899
369112
  return sameFileIdentity$1(left, right) && left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs;
368900
369113
  }
368901
- function isRecord$14(value) {
369114
+ function isRecord$18(value) {
368902
369115
  return typeof value === "object" && value !== null && !Array.isArray(value);
368903
369116
  }
368904
369117
  //#endregion
@@ -423773,12 +423986,12 @@ function legacyStatusToCurrent(task) {
423773
423986
  return task.status;
423774
423987
  }
423775
423988
  function isReadablePersistedTask(obj) {
423776
- return isRecord$13(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
423989
+ return isRecord$17(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
423777
423990
  }
423778
423991
  function isLegacyPersistedTask(task) {
423779
423992
  return "task_id" in task;
423780
423993
  }
423781
- function isRecord$13(value) {
423994
+ function isRecord$17(value) {
423782
423995
  return typeof value === "object" && value !== null;
423783
423996
  }
423784
423997
  function optionalNonEmptyString(value) {
@@ -424187,11 +424400,11 @@ const WINDOWS_RESERVED_NAMES = new Set([
424187
424400
  ...Array.from({ length: 9 }, (_value, index) => `COM${String(index + 1)}`),
424188
424401
  ...Array.from({ length: 9 }, (_value, index) => `LPT${String(index + 1)}`)
424189
424402
  ]);
424190
- function isRecord$12(value) {
424403
+ function isRecord$16(value) {
424191
424404
  return typeof value === "object" && value !== null && !Array.isArray(value);
424192
424405
  }
424193
424406
  function assertRecord(value, label) {
424194
- if (!isRecord$12(value)) throw new Error(`${label} must be an object.`);
424407
+ if (!isRecord$16(value)) throw new Error(`${label} must be an object.`);
424195
424408
  }
424196
424409
  function assertExactKeys(value, required, optional, label) {
424197
424410
  const allowed = new Set([...required, ...optional]);
@@ -424482,7 +424695,7 @@ function currentArtifactRecord(artifacts) {
424482
424695
  return result;
424483
424696
  }
424484
424697
  function readAttestationHash(value) {
424485
- if (!isRecord$12(value) || !isRecord$12(value["attestation"])) return null;
424698
+ if (!isRecord$16(value) || !isRecord$16(value["attestation"])) return null;
424486
424699
  const hash = value["attestation"]["hash"];
424487
424700
  return typeof hash === "string" && /^[a-f0-9]{64}$/.test(hash) ? hash : null;
424488
424701
  }
@@ -425254,21 +425467,21 @@ async function ensureSafeDirectory(path, create, recursive) {
425254
425467
  return true;
425255
425468
  }
425256
425469
  function validateRegistry(value, context) {
425257
- if (!isRecord$11(value) || value["version"] !== 1) throw new WorkspaceError("registry_invalid", "Unsupported workspace registry version.");
425470
+ if (!isRecord$15(value) || value["version"] !== 1) throw new WorkspaceError("registry_invalid", "Unsupported workspace registry version.");
425258
425471
  if (!hasExactKeys(value, REGISTRY_KEYS)) throw new WorkspaceError("registry_invalid", "Workspace registry contains unknown fields.");
425259
- if (value["repoFingerprint"] !== context.repoFingerprint || value["primaryRoot"] !== context.primaryRoot || !isRecord$11(value["workspaces"])) throw new WorkspaceError("registry_invalid", "Workspace registry does not match this repository.");
425472
+ if (value["repoFingerprint"] !== context.repoFingerprint || value["primaryRoot"] !== context.primaryRoot || !isRecord$15(value["workspaces"])) throw new WorkspaceError("registry_invalid", "Workspace registry does not match this repository.");
425260
425473
  for (const [name, record] of Object.entries(value["workspaces"])) if (!isWorkspaceRecord(record) || record.name !== name) throw new WorkspaceError("registry_invalid", "Workspace registry contains an invalid entry.");
425261
425474
  return value;
425262
425475
  }
425263
425476
  function isWorkspaceRecord(value) {
425264
- if (!isRecord$11(value) || !hasExactKeys(value, WORKSPACE_RECORD_KEYS)) return false;
425477
+ if (!isRecord$15(value) || !hasExactKeys(value, WORKSPACE_RECORD_KEYS)) return false;
425265
425478
  return typeof value["name"] === "string" && typeof value["path"] === "string" && typeof value["branch"] === "string" && typeof value["baseCommit"] === "string" && typeof value["repoFingerprint"] === "string" && isCanonicalIsoTimestamp(value["createdAt"]);
425266
425479
  }
425267
425480
  function isCanonicalIsoTimestamp(value) {
425268
425481
  if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(value)) return false;
425269
425482
  return new Date(value).toISOString() === value;
425270
425483
  }
425271
- function isRecord$11(value) {
425484
+ function isRecord$15(value) {
425272
425485
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
425273
425486
  const prototype = Object.getPrototypeOf(value);
425274
425487
  return prototype === Object.prototype || prototype === null;
@@ -425359,7 +425572,7 @@ async function readRegistryLockMetadata(lockPath) {
425359
425572
  if (error.code !== void 0) throw error;
425360
425573
  return;
425361
425574
  }
425362
- if (!isRecord$11(value) || !hasExactKeys(value, [
425575
+ if (!isRecord$15(value) || !hasExactKeys(value, [
425363
425576
  "version",
425364
425577
  "pid",
425365
425578
  "createdAt",
@@ -426068,7 +426281,7 @@ async function searchLocalWorkHistory(homeDir, sessions, query, limit = 8) {
426068
426281
  let skippedRecords = 0;
426069
426282
  for (const session of sessions) {
426070
426283
  const sessionDir = await realpath(session.sessionDir).catch(() => void 0);
426071
- if (sessionDir === void 0 || path.basename(sessionDir) !== session.id || !isInside(sessionsRoot, sessionDir)) {
426284
+ if (sessionDir === void 0 || path.basename(sessionDir) !== session.id || !isInside$1(sessionsRoot, sessionDir)) {
426072
426285
  skippedSessions++;
426073
426286
  continue;
426074
426287
  }
@@ -426090,7 +426303,7 @@ async function searchLocalWorkHistory(homeDir, sessions, query, limit = 8) {
426090
426303
  continue;
426091
426304
  }
426092
426305
  const canonicalWire = await realpath(wirePath).catch(() => void 0);
426093
- if (canonicalWire === void 0 || !isInside(sessionDir, canonicalWire)) {
426306
+ if (canonicalWire === void 0 || !isInside$1(sessionDir, canonicalWire)) {
426094
426307
  skippedSessions++;
426095
426308
  continue;
426096
426309
  }
@@ -426108,7 +426321,7 @@ async function searchLocalWorkHistory(homeDir, sessions, query, limit = 8) {
426108
426321
  skippedRecords++;
426109
426322
  continue;
426110
426323
  }
426111
- const event = isRecord$10(record) && record["type"] === "context.append_loop_event" && isRecord$10(record["event"]) ? record["event"] : void 0;
426324
+ const event = isRecord$14(record) && record["type"] === "context.append_loop_event" && isRecord$14(record["event"]) ? record["event"] : void 0;
426112
426325
  if (event?.["type"] === "step.end" && typeof event["uuid"] === "string") assistantSteps.delete(event["uuid"]);
426113
426326
  else if (event?.["type"] === "content.part" && typeof event["stepUuid"] === "string" && isTextPart(event["part"])) {
426114
426327
  const stepId = event["stepUuid"];
@@ -426185,11 +426398,11 @@ async function* boundedWireLines(wirePath, size) {
426185
426398
  }
426186
426399
  }
426187
426400
  function searchableText(record) {
426188
- if (!isRecord$10(record)) return void 0;
426189
- if (record["type"] === "context.append_message" && isRecord$10(record["message"])) {
426401
+ if (!isRecord$14(record)) return void 0;
426402
+ if (record["type"] === "context.append_message" && isRecord$14(record["message"])) {
426190
426403
  const message = record["message"];
426191
426404
  const origin = message["origin"];
426192
- if (message["role"] !== "user" && message["role"] !== "assistant" || message["role"] === "assistant" && origin !== void 0 || message["role"] === "user" && origin !== void 0 && (!isRecord$10(origin) || origin["kind"] !== "user")) return;
426405
+ if (message["role"] !== "user" && message["role"] !== "assistant" || message["role"] === "assistant" && origin !== void 0 || message["role"] === "user" && origin !== void 0 && (!isRecord$14(origin) || origin["kind"] !== "user")) return;
426193
426406
  const content = message["content"];
426194
426407
  if (!Array.isArray(content)) return void 0;
426195
426408
  const text = content.filter(isTextPart).map((part) => part.text).join(" ");
@@ -426211,12 +426424,12 @@ function snippet(text, firstTerm) {
426211
426424
  return `${start > 0 ? "..." : ""}${flattened.slice(start, end)}${end < flattened.length ? "..." : ""}`;
426212
426425
  }
426213
426426
  function isTextPart(value) {
426214
- return isRecord$10(value) && value["type"] === "text" && typeof value["text"] === "string";
426427
+ return isRecord$14(value) && value["type"] === "text" && typeof value["text"] === "string";
426215
426428
  }
426216
- function isRecord$10(value) {
426429
+ function isRecord$14(value) {
426217
426430
  return typeof value === "object" && value !== null && !Array.isArray(value);
426218
426431
  }
426219
- function isInside(parent, child) {
426432
+ function isInside$1(parent, child) {
426220
426433
  const relative = path.relative(parent, child);
426221
426434
  return relative !== "" && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
426222
426435
  }
@@ -426309,7 +426522,7 @@ async function searchLocalToolEvents(homeDir, sessions, query, limit = 8) {
426309
426522
  };
426310
426523
  }
426311
426524
  function parseSavedEvent(value, sessionId) {
426312
- if (!isRecord$9(value) || value["version"] !== 1 || value["sessionId"] !== sessionId || typeof value["agentId"] !== "string" || !TOOL_NAME.test(value["agentId"]) || typeof value["tool"] !== "string" || !TOOL_NAME.test(value["tool"]) || typeof value["at"] !== "number" || !Number.isSafeInteger(value["at"]) || value["at"] < 0 || value["status"] !== "ok" && value["status"] !== "error" && value["status"] !== "synthetic") return;
426525
+ if (!isRecord$13(value) || value["version"] !== 1 || value["sessionId"] !== sessionId || typeof value["agentId"] !== "string" || !TOOL_NAME.test(value["agentId"]) || typeof value["tool"] !== "string" || !TOOL_NAME.test(value["tool"]) || typeof value["at"] !== "number" || !Number.isSafeInteger(value["at"]) || value["at"] < 0 || value["status"] !== "ok" && value["status"] !== "error" && value["status"] !== "synthetic") return;
426313
426526
  const filePath = value["filePath"];
426314
426527
  if (filePath !== void 0 && (typeof filePath !== "string" || filePath.length > 1024 || /[\u0000-\u001F\u007F]/u.test(filePath))) return void 0;
426315
426528
  return {
@@ -426341,7 +426554,7 @@ function localToolEventRecordingEnabled(homeDir) {
426341
426554
  }
426342
426555
  if (!info.isFile() || info.isSymbolicLink() || info.size > 1024) return false;
426343
426556
  const parsed = JSON.parse(readFileSync(settingsPath, "utf8"));
426344
- return isRecord$9(parsed) && parsed["version"] === 1 && parsed["enabled"] === true;
426557
+ return isRecord$13(parsed) && parsed["version"] === 1 && parsed["enabled"] === true;
426345
426558
  } catch {
426346
426559
  return false;
426347
426560
  }
@@ -426452,7 +426665,7 @@ function createLocalToolEventRecorder(homeDir, sessionId, enabled = localToolEve
426452
426665
  };
426453
426666
  }
426454
426667
  function filePathFor(tool, args) {
426455
- if (!FILE_TOOLS.has(tool) || !isRecord$9(args)) return {};
426668
+ if (!FILE_TOOLS.has(tool) || !isRecord$13(args)) return {};
426456
426669
  const value = args["path"];
426457
426670
  if (typeof value !== "string" || value.length === 0 || value.length > 1024 || /[\u0000-\u001F\u007F]/u.test(value)) return {};
426458
426671
  return { filePath: value };
@@ -426495,11 +426708,11 @@ async function assertPlainDirectory(directory) {
426495
426708
  function samePath(a, b) {
426496
426709
  return process.platform === "win32" ? path.resolve(a).toLocaleLowerCase() === path.resolve(b).toLocaleLowerCase() : path.resolve(a) === path.resolve(b);
426497
426710
  }
426498
- function isRecord$9(value) {
426711
+ function isRecord$13(value) {
426499
426712
  return typeof value === "object" && value !== null && !Array.isArray(value);
426500
426713
  }
426501
426714
  function isErrno$1(error, code) {
426502
- return isRecord$9(error) && error["code"] === code;
426715
+ return isRecord$13(error) && error["code"] === code;
426503
426716
  }
426504
426717
  //#endregion
426505
426718
  //#region src/personal-memory/session-mcp.ts
@@ -426681,12 +426894,12 @@ function isPersonalMemoryToolName(name) {
426681
426894
  return PERSONAL_MEMORY_TOOL_NAMES.includes(name);
426682
426895
  }
426683
426896
  function normalizePhaseOneRecall(payload, limit) {
426684
- if (!isRecord$8(payload) || !Array.isArray(payload["ergebnis"])) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
426897
+ if (!isRecord$12(payload) || !Array.isArray(payload["ergebnis"])) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
426685
426898
  const results = payload["ergebnis"];
426686
426899
  if (results.length > 100) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
426687
426900
  return { personal_memory: {
426688
426901
  saved: results.map((entry) => {
426689
- if (!isRecord$8(entry)) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
426902
+ if (!isRecord$12(entry)) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
426690
426903
  const text = entry["inhalt"];
426691
426904
  if (typeof text !== "string" || text.trim().length === 0 || text.length > 4e3) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
426692
426905
  return {
@@ -426698,7 +426911,46 @@ function normalizePhaseOneRecall(payload, limit) {
426698
426911
  chat_history_context: []
426699
426912
  } };
426700
426913
  }
426701
- function isRecord$8(value) {
426914
+ function isRecord$12(value) {
426915
+ return typeof value === "object" && value !== null && !Array.isArray(value);
426916
+ }
426917
+ //#endregion
426918
+ //#region src/personal-memory/account-memory-recall.ts
426919
+ function mergeAccountMemoryRecall(phaseOne, account) {
426920
+ const existing = parsePhaseOne(phaseOne);
426921
+ if (existing === void 0 && account === void 0) throw new PersonalMemoryBrokerError("UNAVAILABLE");
426922
+ const saved = [...(existing?.personal_memory.saved ?? []).slice(0, 4), ...(account?.profile.card ?? []).slice(0, 4).map((text) => ({
426923
+ text: text.slice(0, 1e3),
426924
+ confidence: "medium"
426925
+ }))];
426926
+ const threads = (existing?.personal_memory.threads ?? []).slice(0, 4);
426927
+ if (account?.profile.representation.trim()) threads.push({
426928
+ title: "Account memory profile",
426929
+ summary: account.profile.representation.slice(0, 1e3)
426930
+ });
426931
+ for (const item of account?.items ?? []) {
426932
+ if (threads.length >= 8) break;
426933
+ threads.push({
426934
+ title: `${item.source} / ${item.sessionId}`.slice(0, 200),
426935
+ summary: item.text.slice(0, 1e3)
426936
+ });
426937
+ }
426938
+ return { personal_memory: {
426939
+ saved,
426940
+ threads,
426941
+ chat_history_context: []
426942
+ } };
426943
+ }
426944
+ function parsePhaseOne(value) {
426945
+ if (!isRecord$11(value) || !isRecord$11(value["personal_memory"])) return void 0;
426946
+ const memory = value["personal_memory"];
426947
+ if (!Array.isArray(memory["saved"]) || !Array.isArray(memory["threads"]) || !Array.isArray(memory["chat_history_context"]) || memory["chat_history_context"].length > 0) return void 0;
426948
+ const saved = memory["saved"];
426949
+ const threads = memory["threads"];
426950
+ if (saved.length > 8 || threads.length > 8 || !saved.every((item) => isRecord$11(item) && typeof item["text"] === "string" && item["text"].length <= 1e3 && item["confidence"] === "medium") || !threads.every((item) => isRecord$11(item) && typeof item["title"] === "string" && item["title"].length <= 200 && typeof item["summary"] === "string" && item["summary"].length <= 1e3)) return void 0;
426951
+ return value;
426952
+ }
426953
+ function isRecord$11(value) {
426702
426954
  return typeof value === "object" && value !== null && !Array.isArray(value);
426703
426955
  }
426704
426956
  //#endregion
@@ -426817,7 +427069,7 @@ async function bindPersonalMemoryHostTools(session, harness, options = {}) {
426817
427069
  if (localHistory === void 0 || !savedSearchEnabled && !localOnlyEnabled) return;
426818
427070
  const searchClient = savedSearchEnabled ? options.client ?? createPersonalMemoryBrokerClient(harness) : void 0;
426819
427071
  try {
426820
- await registerPersonalMemorySearchTool(session, localHistory, searchClient, binding, savedSearchEnabled, localOnlyEnabled);
427072
+ await registerPersonalMemorySearchTool(session, localHistory, searchClient, binding, savedSearchEnabled, localOnlyEnabled, savedSearchEnabled ? options.accountMemory : void 0);
426821
427073
  } catch (error) {
426822
427074
  await session.unregisterToolAndWait(PERSONAL_MEMORY_SEARCH_TOOL).catch(() => {});
426823
427075
  throw error;
@@ -426835,10 +427087,10 @@ async function bindPersonalMemoryHostTools(session, harness, options = {}) {
426835
427087
  for (const name of binding === void 0 ? [] : personalMemoryToolNames(binding.mode, binding.capabilities)) {
426836
427088
  if (name === "memory_recall") continue;
426837
427089
  const definition = personalMemoryToolDefinition(name);
426838
- await session.registerToolAndWait(qualifiedPersonalMemoryToolName(name), definition.description, definition.parameters, createHostHandler(client, name, context, name === "memory_settings_update" ? () => refreshPersonalMemoryBinding(session, harness, client, localHistory) : void 0));
427090
+ await session.registerToolAndWait(qualifiedPersonalMemoryToolName(name), definition.description, definition.parameters, createHostHandler(client, name, context, name === "memory_settings_update" ? () => refreshPersonalMemoryBinding(session, harness, client, localHistory, options.accountMemory) : void 0));
426839
427091
  }
426840
- if (savedSearchEnabled) session.setHostToolCallHandler(PERSONAL_MEMORY_HOST_RECALL_HANDLER, createHostHandler(client, "memory_recall", context));
426841
- if (localHistory !== void 0 && (savedSearchEnabled || localOnlyEnabled)) await registerPersonalMemorySearchTool(session, localHistory, client, binding, savedSearchEnabled, localOnlyEnabled);
427092
+ if (savedSearchEnabled) session.setHostToolCallHandler(PERSONAL_MEMORY_HOST_RECALL_HANDLER, createHostHandler(client, "memory_recall", context, void 0, options.accountMemory));
427093
+ if (localHistory !== void 0 && (savedSearchEnabled || localOnlyEnabled)) await registerPersonalMemorySearchTool(session, localHistory, client, binding, savedSearchEnabled, localOnlyEnabled, savedSearchEnabled ? options.accountMemory : void 0);
426842
427094
  if (binding !== void 0) await session.setPersonalMemoryHostCapability(true);
426843
427095
  } catch (error) {
426844
427096
  resetPersonalMemorySession();
@@ -426846,7 +427098,7 @@ async function bindPersonalMemoryHostTools(session, harness, options = {}) {
426846
427098
  throw error;
426847
427099
  }
426848
427100
  }
426849
- async function registerPersonalMemorySearchTool(session, localHistory, client, binding, savedSearchEnabled, localOnlyEnabled) {
427101
+ async function registerPersonalMemorySearchTool(session, localHistory, client, binding, savedSearchEnabled, localOnlyEnabled, accountMemory) {
426850
427102
  const context = binding === void 0 ? void 0 : {
426851
427103
  mode: binding.mode,
426852
427104
  capabilities: binding.capabilities
@@ -426859,14 +427111,15 @@ async function registerPersonalMemorySearchTool(session, localHistory, client, b
426859
427111
  };
426860
427112
  try {
426861
427113
  const sessions = localHistory.listSessions({ includeArchive: true });
426862
- const [savedResult, workHistoryResult, toolEventsResult] = await Promise.allSettled([
427114
+ const [savedResult, workHistoryResult, toolEventsResult, accountResult] = await Promise.allSettled([
426863
427115
  savedSearchEnabled ? invokePersonalMemoryTool(client, "memory_recall", parsed.data, context) : Promise.resolve(void 0),
426864
427116
  sessions.then((list) => searchLocalWorkHistory(localHistory.homeDir, list, parsed.data.query, parsed.data.limit)),
426865
- sessions.then((list) => searchLocalToolEvents(localHistory.homeDir, list, parsed.data.query, parsed.data.limit))
427117
+ sessions.then((list) => searchLocalToolEvents(localHistory.homeDir, list, parsed.data.query, parsed.data.limit)),
427118
+ accountMemory?.search(parsed.data.query, Math.min(20, parsed.data.limit)) ?? Promise.resolve(void 0)
426866
427119
  ]);
426867
427120
  const saved = savedSearchEnabled && savedResult.status === "fulfilled" ? savedSearchResultSchema.safeParse(savedResult.value) : void 0;
426868
427121
  const savedAvailable = saved?.success === true;
426869
- if (!savedAvailable && workHistoryResult.status === "rejected" && toolEventsResult.status === "rejected") return {
427122
+ if (!savedAvailable && workHistoryResult.status === "rejected" && toolEventsResult.status === "rejected" && (accountResult.status === "rejected" || accountResult.value === void 0)) return {
426870
427123
  output: "MEMORY_SEARCH_UNAVAILABLE",
426871
427124
  isError: true
426872
427125
  };
@@ -426877,6 +427130,13 @@ async function registerPersonalMemorySearchTool(session, localHistory, client, b
426877
427130
  workHistoryAvailable: workHistoryResult.status === "fulfilled",
426878
427131
  toolEvents: toolEventsResult.status === "fulfilled" ? toolEventsResult.value : null,
426879
427132
  toolEventsAvailable: toolEventsResult.status === "fulfilled",
427133
+ accountHistory: accountResult.status === "fulfilled" ? accountResult.value?.items.slice(0, 8).map((item) => ({
427134
+ source: item.source,
427135
+ sessionId: item.sessionId,
427136
+ at: item.at,
427137
+ text: item.text.slice(0, 600)
427138
+ })) ?? null : null,
427139
+ accountHistoryAvailable: accountResult.status === "fulfilled" && accountResult.value !== void 0,
426880
427140
  toolEventRecordingEnabled: localOnlyEnabled
426881
427141
  }) };
426882
427142
  } catch {
@@ -426946,13 +427206,20 @@ function supportsPersonalMemoryHostTools(session) {
426946
427206
  function qualifiedPersonalMemoryToolName(name) {
426947
427207
  return `${PERSONAL_MEMORY_QUALIFIED_PREFIX}${name}`;
426948
427208
  }
426949
- function createHostHandler(client, name, context, afterSettingsUpdate) {
427209
+ function createHostHandler(client, name, context, afterSettingsUpdate, accountMemory) {
426950
427210
  return async (request) => {
426951
427211
  try {
426952
- const result = await invokePersonalMemoryTool(client, name, request.args, {
427212
+ const original = () => invokePersonalMemoryTool(client, name, request.args, {
426953
427213
  ...context,
426954
427214
  explicitRememberAttested: name === "memory_remember" ? consumePersonalMemoryRememberIntent(request) : void 0
426955
427215
  });
427216
+ let result;
427217
+ if (name === "memory_recall" && accountMemory !== void 0) {
427218
+ const parsed = searchInputSchema.safeParse(request.args);
427219
+ if (!parsed.success) throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
427220
+ const [phaseOne, account] = await Promise.all([original().catch(() => void 0), accountMemory.recall(parsed.data.query)]);
427221
+ result = mergeAccountMemoryRecall(phaseOne, account);
427222
+ } else result = await original();
426956
427223
  if (name === "memory_settings_update") await afterSettingsUpdate?.();
426957
427224
  return { output: JSON.stringify(result ?? null) };
426958
427225
  } catch (error) {
@@ -426963,7 +427230,7 @@ function createHostHandler(client, name, context, afterSettingsUpdate) {
426963
427230
  }
426964
427231
  };
426965
427232
  }
426966
- async function refreshPersonalMemoryBinding(session, harness, client, localHistory) {
427233
+ async function refreshPersonalMemoryBinding(session, harness, client, localHistory, accountMemory) {
426967
427234
  resetPersonalMemorySession();
426968
427235
  await clearPersonalMemoryHostTools(session);
426969
427236
  try {
@@ -426975,7 +427242,8 @@ async function refreshPersonalMemoryBinding(session, harness, client, localHisto
426975
427242
  await bindPersonalMemoryHostTools(session, harness, {
426976
427243
  binding,
426977
427244
  client,
426978
- localHistory
427245
+ localHistory,
427246
+ accountMemory
426979
427247
  });
426980
427248
  } catch (error) {
426981
427249
  resetPersonalMemorySession();
@@ -438706,6 +438974,148 @@ function sanitizeTerminalText(value) {
438706
438974
  return value.replaceAll(OSC_SEQUENCE$1, "").replaceAll(CSI_SEQUENCE$1, "").replaceAll(ESC_SEQUENCE$1, "").replaceAll(CONTROL_CHARACTERS$1, " ");
438707
438975
  }
438708
438976
  //#endregion
438977
+ //#region src/tui/utils/export-markdown.copy.ts
438978
+ registerUiCatalogFragment({
438979
+ en: {
438980
+ "export.thinking": "Thinking",
438981
+ "export.image": "image",
438982
+ "export.audio": "audio",
438983
+ "export.video": "video",
438984
+ "export.toolCall": "Tool Call: {name}",
438985
+ "export.toolResult": "Tool Result: {name}",
438986
+ "export.turn": "Turn {number}",
438987
+ "export.user": "User",
438988
+ "export.assistant": "Assistant",
438989
+ "export.system": "System",
438990
+ "export.unknownTool": "unknown",
438991
+ "export.overview": "Overview",
438992
+ "export.topic": "Topic",
438993
+ "export.labelSeparator": ":",
438994
+ "export.empty": "empty",
438995
+ "export.conversation": "Conversation",
438996
+ "export.turnCount.one": "{count} turn",
438997
+ "export.turnCount.other": "{count} turns",
438998
+ "export.toolCallCount.one": "{count} tool call",
438999
+ "export.toolCallCount.other": "{count} tool calls",
439000
+ "export.title": "King Session Export"
439001
+ },
439002
+ de: {
439003
+ "export.thinking": "Denken",
439004
+ "export.image": "Bild",
439005
+ "export.audio": "Audio",
439006
+ "export.video": "Video",
439007
+ "export.toolCall": "Werkzeugaufruf: {name}",
439008
+ "export.toolResult": "Werkzeugergebnis: {name}",
439009
+ "export.turn": "Durchlauf {number}",
439010
+ "export.user": "Benutzer",
439011
+ "export.assistant": "Assistent",
439012
+ "export.system": "System",
439013
+ "export.unknownTool": "unbekannt",
439014
+ "export.overview": "Übersicht",
439015
+ "export.topic": "Thema",
439016
+ "export.labelSeparator": ":",
439017
+ "export.empty": "leer",
439018
+ "export.conversation": "Gespräch",
439019
+ "export.turnCount.one": "{count} Durchlauf",
439020
+ "export.turnCount.other": "{count} Durchläufe",
439021
+ "export.toolCallCount.one": "{count} Werkzeugaufruf",
439022
+ "export.toolCallCount.other": "{count} Werkzeugaufrufe",
439023
+ "export.title": "King-Sitzungsexport"
439024
+ },
439025
+ es: {
439026
+ "export.thinking": "Razonamiento",
439027
+ "export.image": "imagen",
439028
+ "export.audio": "audio",
439029
+ "export.video": "vídeo",
439030
+ "export.toolCall": "Llamada a herramienta: {name}",
439031
+ "export.toolResult": "Resultado de la herramienta: {name}",
439032
+ "export.turn": "Turno {number}",
439033
+ "export.user": "Usuario",
439034
+ "export.assistant": "Asistente",
439035
+ "export.system": "Sistema",
439036
+ "export.unknownTool": "desconocida",
439037
+ "export.overview": "Resumen",
439038
+ "export.topic": "Tema",
439039
+ "export.labelSeparator": ":",
439040
+ "export.empty": "vacío",
439041
+ "export.conversation": "Conversación",
439042
+ "export.turnCount.one": "{count} turno",
439043
+ "export.turnCount.other": "{count} turnos",
439044
+ "export.toolCallCount.one": "{count} llamada a herramienta",
439045
+ "export.toolCallCount.other": "{count} llamadas a herramientas",
439046
+ "export.title": "Exportación de la sesión de King"
439047
+ },
439048
+ fr: {
439049
+ "export.thinking": "Réflexion",
439050
+ "export.image": "image",
439051
+ "export.audio": "audio",
439052
+ "export.video": "vidéo",
439053
+ "export.toolCall": "Appel d’outil\xA0: {name}",
439054
+ "export.toolResult": "Résultat de l’outil\xA0: {name}",
439055
+ "export.turn": "Tour {number}",
439056
+ "export.user": "Utilisateur",
439057
+ "export.assistant": "Assistant",
439058
+ "export.system": "Système",
439059
+ "export.unknownTool": "inconnu",
439060
+ "export.overview": "Vue d’ensemble",
439061
+ "export.topic": "Sujet",
439062
+ "export.labelSeparator": "\xA0:",
439063
+ "export.empty": "vide",
439064
+ "export.conversation": "Conversation",
439065
+ "export.turnCount.one": "{count} tour",
439066
+ "export.turnCount.other": "{count} tours",
439067
+ "export.toolCallCount.one": "{count} appel d’outil",
439068
+ "export.toolCallCount.other": "{count} appels d’outil",
439069
+ "export.title": "Export de la session King"
439070
+ },
439071
+ sv: {
439072
+ "export.thinking": "Resonemang",
439073
+ "export.image": "bild",
439074
+ "export.audio": "ljud",
439075
+ "export.video": "video",
439076
+ "export.toolCall": "Verktygsanrop: {name}",
439077
+ "export.toolResult": "Verktygsresultat: {name}",
439078
+ "export.turn": "Omgång {number}",
439079
+ "export.user": "Användare",
439080
+ "export.assistant": "Assistent",
439081
+ "export.system": "System",
439082
+ "export.unknownTool": "okänt",
439083
+ "export.overview": "Översikt",
439084
+ "export.topic": "Ämne",
439085
+ "export.labelSeparator": ":",
439086
+ "export.empty": "tomt",
439087
+ "export.conversation": "Konversation",
439088
+ "export.turnCount.one": "{count} omgång",
439089
+ "export.turnCount.other": "{count} omgångar",
439090
+ "export.toolCallCount.one": "{count} verktygsanrop",
439091
+ "export.toolCallCount.other": "{count} verktygsanrop",
439092
+ "export.title": "Export av King-session"
439093
+ },
439094
+ cs: {
439095
+ "export.thinking": "Uvažování",
439096
+ "export.image": "obrázek",
439097
+ "export.audio": "zvuk",
439098
+ "export.video": "video",
439099
+ "export.toolCall": "Volání nástroje: {name}",
439100
+ "export.toolResult": "Výsledek nástroje: {name}",
439101
+ "export.turn": "Kolo {number}",
439102
+ "export.user": "Uživatel",
439103
+ "export.assistant": "Asistent",
439104
+ "export.system": "Systém",
439105
+ "export.unknownTool": "neznámý",
439106
+ "export.overview": "Přehled",
439107
+ "export.topic": "Téma",
439108
+ "export.labelSeparator": ":",
439109
+ "export.empty": "prázdné",
439110
+ "export.conversation": "Konverzace",
439111
+ "export.turnCount.one": "Kola: {count}",
439112
+ "export.turnCount.other": "Kola: {count}",
439113
+ "export.toolCallCount.one": "{count} volání nástroje",
439114
+ "export.toolCallCount.other": "{count} volání nástrojů",
439115
+ "export.title": "Export relace King"
439116
+ }
439117
+ });
439118
+ //#endregion
438709
439119
  //#region src/tui/components/messages/usage-panel.ts
438710
439120
  registerUiCatalogFragment({
438711
439121
  en: {
@@ -438874,6 +439284,11 @@ function usageNumber(value) {
438874
439284
  function usageInputTotal$2(usage) {
438875
439285
  return usageNumber(usage.inputOther) + usageNumber(usage.inputCacheRead) + usageNumber(usage.inputCacheCreation);
438876
439286
  }
439287
+ function knownReasoningTokens(usage) {
439288
+ const value = usage.outputReasoning;
439289
+ const output = usageNumber(usage.output);
439290
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= output ? value : void 0;
439291
+ }
438877
439292
  function managedUsageLabel(row) {
438878
439293
  switch (row.id) {
438879
439294
  case "five_hours": return uiText("usage.plan.window.fiveHours");
@@ -438922,14 +439337,23 @@ function buildSessionUsageSection(usage, error, value, muted, errorStyle) {
438922
439337
  const locale = getCurrentUiLocale();
438923
439338
  let totalInput = 0;
438924
439339
  let totalOutput = 0;
439340
+ let totalReasoning = 0;
439341
+ let reasoningComplete = true;
438925
439342
  for (const [model, row] of entries) {
438926
439343
  const input = usageInputTotal$2(row);
438927
439344
  const output = usageNumber(row.output);
439345
+ const reasoning = knownReasoningTokens(row);
438928
439346
  totalInput += input;
438929
439347
  totalOutput += output;
438930
- lines.push(` ${muted(sanitizeTerminalText(model))} ${uiText("usage.input")} ${value(formatExactTokenCount(input, locale))} ${uiText("usage.output")} ${value(formatExactTokenCount(output, locale))} ${uiText("usage.total")} ${value(formatExactTokenCount(input + output, locale))}`);
439348
+ if (reasoning !== void 0) totalReasoning += reasoning;
439349
+ else if (output > 0) reasoningComplete = false;
439350
+ const reasoningPart = reasoning === void 0 ? "" : ` ${uiText("export.thinking")} ${value(formatExactTokenCount(reasoning, locale))}`;
439351
+ lines.push(` ${muted(sanitizeTerminalText(model))} ${uiText("usage.input")} ${value(formatExactTokenCount(input, locale))} ${uiText("usage.output")} ${value(formatExactTokenCount(output, locale))}${reasoningPart} ${uiText("usage.total")} ${value(formatExactTokenCount(input + output, locale))}`);
439352
+ }
439353
+ if (entries.length > 1) {
439354
+ const reasoningPart = reasoningComplete && totalOutput > 0 ? ` ${uiText("export.thinking")} ${value(formatExactTokenCount(totalReasoning, locale))}` : "";
439355
+ lines.push(` ${muted(uiText("usage.total"))} ${uiText("usage.input")} ${value(formatExactTokenCount(totalInput, locale))} ${uiText("usage.output")} ${value(formatExactTokenCount(totalOutput, locale))}${reasoningPart} ${uiText("usage.total")} ${value(formatExactTokenCount(totalInput + totalOutput, locale))}`);
438931
439356
  }
438932
- if (entries.length > 1) lines.push(` ${muted(uiText("usage.total"))} ${uiText("usage.input")} ${value(formatExactTokenCount(totalInput, locale))} ${uiText("usage.output")} ${value(formatExactTokenCount(totalOutput, locale))} ${uiText("usage.total")} ${value(formatExactTokenCount(totalInput + totalOutput, locale))}`);
438933
439357
  return lines;
438934
439358
  }
438935
439359
  function buildManagedUsageSection(usage, error, accent, value, muted, errorStyle) {
@@ -502978,7 +503402,7 @@ function parsePluginMarketplace(raw, location) {
502978
503402
  } catch (error) {
502979
503403
  throw new Error(`Plugin marketplace is not valid JSON: ${formatParseError(error)}`, { cause: error });
502980
503404
  }
502981
- if (!isRecord$7(parsed)) throw new TypeError("Plugin marketplace must be an object.");
503405
+ if (!isRecord$10(parsed)) throw new TypeError("Plugin marketplace must be an object.");
502982
503406
  const rawPlugins = parsed["plugins"];
502983
503407
  if (!Array.isArray(rawPlugins)) throw new TypeError("Plugin marketplace must contain a \"plugins\" array.");
502984
503408
  return {
@@ -503022,7 +503446,7 @@ async function readMarketplaceText(location, fetchImpl) {
503022
503446
  return response.text();
503023
503447
  }
503024
503448
  function parseMarketplaceEntry(value, index, location) {
503025
- if (!isRecord$7(value)) throw new TypeError(`Plugin marketplace entry ${index + 1} must be an object.`);
503449
+ if (!isRecord$10(value)) throw new TypeError(`Plugin marketplace entry ${index + 1} must be an object.`);
503026
503450
  const id = requiredString(value, "id", index);
503027
503451
  validateMarketplaceEntryType(value, id);
503028
503452
  const source = stringField$2(value, "source") ?? stringField$2(value, "url") ?? stringField$2(value, "downloadUrl");
@@ -503158,7 +503582,7 @@ function stringArrayField(value, field) {
503158
503582
  const out = raw.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0);
503159
503583
  return out.length > 0 ? out : void 0;
503160
503584
  }
503161
- function isRecord$7(value) {
503585
+ function isRecord$10(value) {
503162
503586
  return typeof value === "object" && value !== null && !Array.isArray(value);
503163
503587
  }
503164
503588
  function formatParseError(error) {
@@ -505260,6 +505684,7 @@ async function handleBlunApiKeyLogin(host, options, promptOptions) {
505260
505684
  provider: DEFAULT_OAUTH_PROVIDER_NAME,
505261
505685
  method: "api_key"
505262
505686
  });
505687
+ host.accountMemoryRuntime?.retryPending().catch(() => {});
505263
505688
  host.showStatus(uiText("auth.login.success"));
505264
505689
  return "authenticated";
505265
505690
  }
@@ -505302,6 +505727,7 @@ async function handleBlunCodeOAuthLogin(host, options = {}) {
505302
505727
  method: "oauth",
505303
505728
  already_logged_in: alreadyLoggedIn
505304
505729
  });
505730
+ host.accountMemoryRuntime?.retryPending().catch(() => {});
505305
505731
  if (alreadyLoggedIn) host.showStatus(uiText("auth.login.already"));
505306
505732
  return "authenticated";
505307
505733
  } catch (error) {
@@ -505346,11 +505772,16 @@ async function handleLogoutCommand(host) {
505346
505772
  const currentProvider = host.state.appState.availableModels[currentModel]?.provider;
505347
505773
  const target = await promptLogoutProviderSelection(host, options, currentProvider);
505348
505774
  if (target === void 0) return;
505775
+ const memoryRetractionPending = await host.accountMemoryRuntime?.flushRetractionsBeforeLogout() ?? false;
505349
505776
  showAuthWarnings(host, (await host.harness.auth.logout(DEFAULT_OAUTH_PROVIDER_NAME)).warnings);
505350
505777
  await host.authFlow.refreshConfigAfterLogout({ clearCustomerAccount: true });
505351
505778
  await host.authFlow.clearActiveSessionAfterLogout({ clearCustomerAccount: true });
505352
505779
  host.track("logout", { provider: target });
505353
505780
  host.showStatus(uiText("auth.logout.complete", { provider: PRODUCT_NAME }));
505781
+ if (memoryRetractionPending) {
505782
+ const key = hasManagedApiKey ? "auth.warning.memoryRetractionApiKeyPending" : "auth.warning.memoryRetractionOAuthPending";
505783
+ host.showStatus(uiText(key), "warning");
505784
+ }
505354
505785
  }
505355
505786
  function showAuthWarnings(host, warnings) {
505356
505787
  if (warnings?.some((warning) => warning.code === "remote_revoke_failed") === true) host.showStatus(uiText("auth.warning.remoteRevokeFailed"), "warning");
@@ -505782,6 +506213,11 @@ async function showContextReport(host, detailed) {
505782
506213
  name: tool.name === void 0 ? void 0 : diagnosticLabel(tool.name),
505783
506214
  bytes: validTextSize(tool.bytes)
505784
506215
  })) : void 0,
506216
+ toolResults: detailed === true ? breakdown?.toolResultByTool?.map((tool) => ({
506217
+ name: tool.name === void 0 ? void 0 : diagnosticLabel(tool.name),
506218
+ count: validTextSize(tool.count),
506219
+ bytes: validTextSize(tool.bytes)
506220
+ })) : void 0,
505785
506221
  toolArrayOverheadBytes: validTextSize(breakdown?.toolArrayOverheadBytes),
505786
506222
  historyOrigins: origins === void 0 ? void 0 : {
505787
506223
  totalBytes: validTextSize(origins.totalBytes),
@@ -505849,6 +506285,15 @@ async function showContextReport(host, detailed) {
505849
506285
  if (lastRequest.tools.length > 20) lines.push(`... (+${String(lastRequest.tools.length - 20)})`);
505850
506286
  lines.push(row("context.otherPart", lastRequest.toolArrayOverheadBytes));
505851
506287
  }
506288
+ if (lastRequest.toolResults !== void 0) {
506289
+ lines.push("", currentTheme.boldFg("primary", uiText("context.toolResultsPart")));
506290
+ for (const tool of lastRequest.toolResults.toSorted((a, b) => (b.bytes ?? -1) - (a.bytes ?? -1)).slice(0, 20)) {
506291
+ const count = tool.count === void 0 ? "?" : formatExactTokenCount(tool.count, getCurrentUiLocale());
506292
+ const size = tool.bytes === void 0 ? uiText("context.unavailable") : formatExactTokenCount(tool.bytes, getCurrentUiLocale());
506293
+ lines.push(`${tool.name ?? "?"} (${count}): ${size}`);
506294
+ }
506295
+ if (lastRequest.toolResults.length > 20) lines.push(`... (+${String(lastRequest.toolResults.length - 20)})`);
506296
+ }
505852
506297
  lines.push("", currentTheme.boldFg("primary", uiText("context.promptTextBytes")), currentTheme.fg("textDim", uiText("context.sourceNote")), row("context.instructionPart", lastRequest.sources[0]), row("context.skillListingPart", lastRequest.sources[1]), row("context.runtimeMemoryPart", lastRequest.sources[2]), row("context.templatePart", lastRequest.sources[3]), row("context.totalPart", lastRequest.sources[4]), "", currentTheme.boldFg("primary", uiText("context.sourceFilesPart")), row("context.generatedPart", lastRequest.sources[5]));
505853
506298
  if (lastRequest.files === void 0) lines.push(uiText("context.unavailable"));
505854
506299
  else {
@@ -506235,7 +506680,7 @@ var ChannelCommandController = class {
506235
506680
  function requireValid(condition) {
506236
506681
  if (!condition) throw new Error("Invalid Telegram session queue state or transition");
506237
506682
  }
506238
- function isRecord$6(value) {
506683
+ function isRecord$9(value) {
506239
506684
  return typeof value === "object" && value !== null && !Array.isArray(value);
506240
506685
  }
506241
506686
  function isId(value) {
@@ -506245,7 +506690,7 @@ function isOffset(value) {
506245
506690
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
506246
506691
  }
506247
506692
  function readSpan(value) {
506248
- requireValid(isRecord$6(value));
506693
+ requireValid(isRecord$9(value));
506249
506694
  const { start, end } = value;
506250
506695
  requireValid(isOffset(start) && isOffset(end) && start < end);
506251
506696
  return {
@@ -506258,7 +506703,7 @@ function ownsRange(state, sessionId, span) {
506258
506703
  }
506259
506704
  /** Reject incompatible or corrupt state; never silently fall back to the profile cursor. */
506260
506705
  function parseSessionQueue(value) {
506261
- requireValid(isRecord$6(value));
506706
+ requireValid(isRecord$9(value));
506262
506707
  const { version, fileId, frontier, activeSessionId, sessions, spans, acknowledged } = value;
506263
506708
  requireValid(version === 1 && isId(fileId) && isOffset(frontier) && isId(activeSessionId));
506264
506709
  requireValid(Array.isArray(sessions) && sessions.every(isId));
@@ -506267,7 +506712,7 @@ function parseSessionQueue(value) {
506267
506712
  requireValid(Array.isArray(spans) && Array.isArray(acknowledged));
506268
506713
  const owned = spans.map((raw) => {
506269
506714
  const span = readSpan(raw);
506270
- requireValid(isRecord$6(raw));
506715
+ requireValid(isRecord$9(raw));
506271
506716
  const sessionId = raw["sessionId"];
506272
506717
  requireValid(sessionId === null || isId(sessionId) && known.has(sessionId));
506273
506718
  return {
@@ -508758,14 +509203,14 @@ function findGoalIndex(file, goalId) {
508758
509203
  return index;
508759
509204
  }
508760
509205
  function isGoalQueueFile(value) {
508761
- if (!isRecord$5(value)) return false;
509206
+ if (!isRecord$8(value)) return false;
508762
509207
  return value["version"] === GOAL_QUEUE_VERSION && Array.isArray(value["goals"]) && value["goals"].every(isUpcomingGoal);
508763
509208
  }
508764
509209
  function isUpcomingGoal(value) {
508765
- if (!isRecord$5(value)) return false;
509210
+ if (!isRecord$8(value)) return false;
508766
509211
  return isNonEmptyString(value["id"]) && isNonEmptyString(value["objective"]) && isNonEmptyString(value["createdAt"]) && isNonEmptyString(value["updatedAt"]);
508767
509212
  }
508768
- function isRecord$5(value) {
509213
+ function isRecord$8(value) {
508769
509214
  return typeof value === "object" && value !== null && !Array.isArray(value);
508770
509215
  }
508771
509216
  function isNonEmptyString(value) {
@@ -508778,7 +509223,7 @@ function timestampAfter(previous) {
508778
509223
  return now.toISOString();
508779
509224
  }
508780
509225
  function isErrno(error, code) {
508781
- return isRecord$5(error) && error["code"] === code;
509226
+ return isRecord$8(error) && error["code"] === code;
508782
509227
  }
508783
509228
  function describeError(error) {
508784
509229
  return error instanceof Error ? error.message : String(error);
@@ -513549,148 +513994,6 @@ function isAbortError$1(error) {
513549
513994
  return isAbortMessage(String(error));
513550
513995
  }
513551
513996
  //#endregion
513552
- //#region src/tui/utils/export-markdown.copy.ts
513553
- registerUiCatalogFragment({
513554
- en: {
513555
- "export.thinking": "Thinking",
513556
- "export.image": "image",
513557
- "export.audio": "audio",
513558
- "export.video": "video",
513559
- "export.toolCall": "Tool Call: {name}",
513560
- "export.toolResult": "Tool Result: {name}",
513561
- "export.turn": "Turn {number}",
513562
- "export.user": "User",
513563
- "export.assistant": "Assistant",
513564
- "export.system": "System",
513565
- "export.unknownTool": "unknown",
513566
- "export.overview": "Overview",
513567
- "export.topic": "Topic",
513568
- "export.labelSeparator": ":",
513569
- "export.empty": "empty",
513570
- "export.conversation": "Conversation",
513571
- "export.turnCount.one": "{count} turn",
513572
- "export.turnCount.other": "{count} turns",
513573
- "export.toolCallCount.one": "{count} tool call",
513574
- "export.toolCallCount.other": "{count} tool calls",
513575
- "export.title": "King Session Export"
513576
- },
513577
- de: {
513578
- "export.thinking": "Denken",
513579
- "export.image": "Bild",
513580
- "export.audio": "Audio",
513581
- "export.video": "Video",
513582
- "export.toolCall": "Werkzeugaufruf: {name}",
513583
- "export.toolResult": "Werkzeugergebnis: {name}",
513584
- "export.turn": "Durchlauf {number}",
513585
- "export.user": "Benutzer",
513586
- "export.assistant": "Assistent",
513587
- "export.system": "System",
513588
- "export.unknownTool": "unbekannt",
513589
- "export.overview": "Übersicht",
513590
- "export.topic": "Thema",
513591
- "export.labelSeparator": ":",
513592
- "export.empty": "leer",
513593
- "export.conversation": "Gespräch",
513594
- "export.turnCount.one": "{count} Durchlauf",
513595
- "export.turnCount.other": "{count} Durchläufe",
513596
- "export.toolCallCount.one": "{count} Werkzeugaufruf",
513597
- "export.toolCallCount.other": "{count} Werkzeugaufrufe",
513598
- "export.title": "King-Sitzungsexport"
513599
- },
513600
- es: {
513601
- "export.thinking": "Razonamiento",
513602
- "export.image": "imagen",
513603
- "export.audio": "audio",
513604
- "export.video": "vídeo",
513605
- "export.toolCall": "Llamada a herramienta: {name}",
513606
- "export.toolResult": "Resultado de la herramienta: {name}",
513607
- "export.turn": "Turno {number}",
513608
- "export.user": "Usuario",
513609
- "export.assistant": "Asistente",
513610
- "export.system": "Sistema",
513611
- "export.unknownTool": "desconocida",
513612
- "export.overview": "Resumen",
513613
- "export.topic": "Tema",
513614
- "export.labelSeparator": ":",
513615
- "export.empty": "vacío",
513616
- "export.conversation": "Conversación",
513617
- "export.turnCount.one": "{count} turno",
513618
- "export.turnCount.other": "{count} turnos",
513619
- "export.toolCallCount.one": "{count} llamada a herramienta",
513620
- "export.toolCallCount.other": "{count} llamadas a herramientas",
513621
- "export.title": "Exportación de la sesión de King"
513622
- },
513623
- fr: {
513624
- "export.thinking": "Réflexion",
513625
- "export.image": "image",
513626
- "export.audio": "audio",
513627
- "export.video": "vidéo",
513628
- "export.toolCall": "Appel d’outil\xA0: {name}",
513629
- "export.toolResult": "Résultat de l’outil\xA0: {name}",
513630
- "export.turn": "Tour {number}",
513631
- "export.user": "Utilisateur",
513632
- "export.assistant": "Assistant",
513633
- "export.system": "Système",
513634
- "export.unknownTool": "inconnu",
513635
- "export.overview": "Vue d’ensemble",
513636
- "export.topic": "Sujet",
513637
- "export.labelSeparator": "\xA0:",
513638
- "export.empty": "vide",
513639
- "export.conversation": "Conversation",
513640
- "export.turnCount.one": "{count} tour",
513641
- "export.turnCount.other": "{count} tours",
513642
- "export.toolCallCount.one": "{count} appel d’outil",
513643
- "export.toolCallCount.other": "{count} appels d’outil",
513644
- "export.title": "Export de la session King"
513645
- },
513646
- sv: {
513647
- "export.thinking": "Resonemang",
513648
- "export.image": "bild",
513649
- "export.audio": "ljud",
513650
- "export.video": "video",
513651
- "export.toolCall": "Verktygsanrop: {name}",
513652
- "export.toolResult": "Verktygsresultat: {name}",
513653
- "export.turn": "Omgång {number}",
513654
- "export.user": "Användare",
513655
- "export.assistant": "Assistent",
513656
- "export.system": "System",
513657
- "export.unknownTool": "okänt",
513658
- "export.overview": "Översikt",
513659
- "export.topic": "Ämne",
513660
- "export.labelSeparator": ":",
513661
- "export.empty": "tomt",
513662
- "export.conversation": "Konversation",
513663
- "export.turnCount.one": "{count} omgång",
513664
- "export.turnCount.other": "{count} omgångar",
513665
- "export.toolCallCount.one": "{count} verktygsanrop",
513666
- "export.toolCallCount.other": "{count} verktygsanrop",
513667
- "export.title": "Export av King-session"
513668
- },
513669
- cs: {
513670
- "export.thinking": "Uvažování",
513671
- "export.image": "obrázek",
513672
- "export.audio": "zvuk",
513673
- "export.video": "video",
513674
- "export.toolCall": "Volání nástroje: {name}",
513675
- "export.toolResult": "Výsledek nástroje: {name}",
513676
- "export.turn": "Kolo {number}",
513677
- "export.user": "Uživatel",
513678
- "export.assistant": "Asistent",
513679
- "export.system": "Systém",
513680
- "export.unknownTool": "neznámý",
513681
- "export.overview": "Přehled",
513682
- "export.topic": "Téma",
513683
- "export.labelSeparator": ":",
513684
- "export.empty": "prázdné",
513685
- "export.conversation": "Konverzace",
513686
- "export.turnCount.one": "Kola: {count}",
513687
- "export.turnCount.other": "Kola: {count}",
513688
- "export.toolCallCount.one": "{count} volání nástroje",
513689
- "export.toolCallCount.other": "{count} volání nástrojů",
513690
- "export.title": "Export relace King"
513691
- }
513692
- });
513693
- //#endregion
513694
513997
  //#region src/tui/utils/export-markdown.ts
513695
513998
  const HINT_KEYS = [
513696
513999
  "path",
@@ -520695,10 +520998,10 @@ function parseGoalValue(output) {
520695
520998
  } catch {
520696
520999
  return;
520697
521000
  }
520698
- if (!isRecord$4(parsed) || !("goal" in parsed)) return void 0;
521001
+ if (!isRecord$7(parsed) || !("goal" in parsed)) return void 0;
520699
521002
  const goal = parsed["goal"];
520700
521003
  if (goal === null) return null;
520701
- if (!isRecord$4(goal)) return void 0;
521004
+ if (!isRecord$7(goal)) return void 0;
520702
521005
  return goal;
520703
521006
  }
520704
521007
  function formatGoalStats(goal) {
@@ -520720,7 +521023,7 @@ function stringArg(args, key) {
520720
521023
  const value = args[key];
520721
521024
  return typeof value === "string" && value.length > 0 ? value : void 0;
520722
521025
  }
520723
- function isRecord$4(value) {
521026
+ function isRecord$7(value) {
520724
521027
  return typeof value === "object" && value !== null && !Array.isArray(value);
520725
521028
  }
520726
521029
  function stringField$1(record, key) {
@@ -524772,10 +525075,10 @@ var CustomerMistakeBrokerError = class extends Error {
524772
525075
  }
524773
525076
  };
524774
525077
  function parseMistakeConsent(payload) {
524775
- if (!isRecord$3(payload)) return void 0;
524776
- const settings = (isRecord$3(payload["data"]) ? payload["data"] : payload)["settings"];
524777
- const dataControls = isRecord$3(settings) ? settings["data_controls"] : void 0;
524778
- if (!isRecord$3(dataControls)) return void 0;
525078
+ if (!isRecord$6(payload)) return void 0;
525079
+ const settings = (isRecord$6(payload["data"]) ? payload["data"] : payload)["settings"];
525080
+ const dataControls = isRecord$6(settings) ? settings["data_controls"] : void 0;
525081
+ if (!isRecord$6(dataControls)) return void 0;
524779
525082
  const asked = dataControls["mistake_consent_asked"];
524780
525083
  const allowed = dataControls["allow_mistake"];
524781
525084
  if (typeof asked !== "boolean" || typeof allowed !== "boolean") return void 0;
@@ -524889,7 +525192,7 @@ function normalizeBaseUrl(value) {
524889
525192
  if (url.protocol !== "https:" || url.username.length > 0 || url.password.length > 0 || url.search.length > 0 || url.hash.length > 0 || url.pathname !== "/" && url.pathname !== "") throw new CustomerMistakeBrokerError("INVALID_PAYLOAD");
524890
525193
  return url.origin;
524891
525194
  }
524892
- function isRecord$3(value) {
525195
+ function isRecord$6(value) {
524893
525196
  return typeof value === "object" && value !== null && !Array.isArray(value);
524894
525197
  }
524895
525198
  //#endregion
@@ -524981,6 +525284,902 @@ var CustomerMistakeHostController = class {
524981
525284
  }
524982
525285
  };
524983
525286
  //#endregion
525287
+ //#region src/personal-memory/account-memory-broker.ts
525288
+ const MAX_CAPTURE_BYTES = 1e6;
525289
+ const UUID_V4$1 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
525290
+ var AccountMemoryBroker = class {
525291
+ client;
525292
+ constructor(client) {
525293
+ this.client = client;
525294
+ }
525295
+ async workspace(sessionId) {
525296
+ if (sessionId !== void 0 && (!sessionId.trim() || sessionId.length > 200)) invalid();
525297
+ const path = sessionId === void 0 ? "/api/memory/workspace" : `/api/memory/workspace?source=tui&sessionId=${encodeURIComponent(sessionId)}`;
525298
+ const value = await this.client.request("GET", path);
525299
+ if (!isRecord$5(value) || typeof value["workspaceId"] !== "string" || !/^blun-[0-9a-f]{64}$/iu.test(value["workspaceId"]) || !generation(value["forgetGeneration"]) || sessionId !== void 0 && !generation(value["sessionEpoch"]) || value["forgetCutoff"] !== null && !isoTime$1(value["forgetCutoff"])) invalid();
525300
+ return {
525301
+ workspaceId: value["workspaceId"],
525302
+ forgetGeneration: value["forgetGeneration"],
525303
+ forgetCutoff: value["forgetCutoff"],
525304
+ sessionEpoch: sessionId === void 0 ? null : value["sessionEpoch"]
525305
+ };
525306
+ }
525307
+ async capture(input) {
525308
+ if (!UUID_V4$1.test(input.captureId) || !input.sessionId.trim() || !generation(input.forgetGeneration) || input.sessionEpoch !== null && !generation(input.sessionEpoch) || input.messages.length === 0 || input.messages.length > 200 || input.messages.some((message) => !messageId$1(message.id) || !["user", "assistant"].includes(message.role) || !message.content.trim() || !isoTime$1(message.at))) invalid();
525309
+ if (new Set(input.messages.map((message) => message.id)).size !== input.messages.length) invalid();
525310
+ const body = {
525311
+ captureId: input.captureId,
525312
+ source: "tui",
525313
+ sessionId: input.sessionId,
525314
+ forgetGeneration: input.forgetGeneration,
525315
+ sessionEpoch: input.sessionEpoch,
525316
+ messages: input.messages.map((message) => ({
525317
+ id: message.id,
525318
+ role: message.role,
525319
+ content: message.content,
525320
+ at: message.at
525321
+ }))
525322
+ };
525323
+ if (Buffer.byteLength(JSON.stringify(body), "utf8") > MAX_CAPTURE_BYTES) invalid();
525324
+ const value = await this.client.request("POST", "/api/memory/capture", body);
525325
+ if (isRecord$5(value) && value["accepted"] === 0 && value["reason"] === "memory_disabled") return {
525326
+ accepted: 0,
525327
+ reason: "memory_disabled"
525328
+ };
525329
+ if (isRecord$5(value) && value["accepted"] === 0 && value["reason"] === "session_retracted" && generation(value["skipped"]) && generation(value["sessionEpoch"])) return {
525330
+ accepted: 0,
525331
+ skipped: value["skipped"],
525332
+ reason: "session_retracted",
525333
+ sessionEpoch: value["sessionEpoch"]
525334
+ };
525335
+ if (!isRecord$5(value) || !generation(value["accepted"]) || !generation(value["skipped"]) || typeof value["duplicate"] !== "boolean" || !generation(value["forgetGeneration"]) || !generation(value["sessionEpoch"])) invalid();
525336
+ return {
525337
+ accepted: value["accepted"],
525338
+ skipped: value["skipped"],
525339
+ duplicate: value["duplicate"],
525340
+ forgetGeneration: value["forgetGeneration"],
525341
+ sessionEpoch: value["sessionEpoch"]
525342
+ };
525343
+ }
525344
+ async retract(input) {
525345
+ if (!UUID_V4$1.test(input.retractId) || !input.sessionId.trim() || input.sessionId.length > 200 || "wholeSession" in input && input.expectedEpoch !== null && !generation(input.expectedEpoch)) invalid();
525346
+ const body = "wholeSession" in input ? {
525347
+ retractId: input.retractId,
525348
+ source: "tui",
525349
+ sessionId: input.sessionId,
525350
+ wholeSession: true,
525351
+ expectedEpoch: input.expectedEpoch
525352
+ } : {
525353
+ retractId: input.retractId,
525354
+ source: "tui",
525355
+ sessionId: input.sessionId,
525356
+ messageIds: input.messageIds
525357
+ };
525358
+ if (!("wholeSession" in input) && (input.messageIds.length === 0 || input.messageIds.length > 200 || input.messageIds.some((id) => !messageId$1(id)) || new Set(input.messageIds).size !== input.messageIds.length)) invalid();
525359
+ const value = await this.client.request("POST", "/api/memory/retract", body);
525360
+ if ("wholeSession" in input && isRecord$5(value) && value["retracted"] === 0 && value["rederive"] === false && value["reason"] === "already_retracted" && generation(value["sessionEpoch"]) && input.expectedEpoch !== null && value["sessionEpoch"] >= input.expectedEpoch) return {
525361
+ retracted: 0,
525362
+ rederive: false,
525363
+ reason: "already_retracted",
525364
+ sessionEpoch: value["sessionEpoch"]
525365
+ };
525366
+ if (!isRecord$5(value) || !generation(value["retracted"]) || value["rederive"] !== "queued" || "wholeSession" in input && !generation(value["sessionEpoch"]) || value["sessionEpoch"] !== void 0 && !generation(value["sessionEpoch"])) invalid();
525367
+ return {
525368
+ retracted: value["retracted"],
525369
+ rederive: "queued",
525370
+ ...value["sessionEpoch"] === void 0 ? {} : { sessionEpoch: value["sessionEpoch"] }
525371
+ };
525372
+ }
525373
+ async recall(query, limit = 8, sources) {
525374
+ const body = queryBody(query, limit, sources);
525375
+ const value = await this.client.request("POST", "/api/memory/recall", body);
525376
+ if (!isRecord$5(value) || !isRecord$5(value["profile"]) || !Array.isArray(value["items"]) || !generation(value["forgetGeneration"])) invalid();
525377
+ const profile = value["profile"];
525378
+ if (!Array.isArray(profile["card"]) || profile["card"].length > 20 || !profile["card"].every((item) => typeof item === "string" && item.length <= 1e3) || typeof profile["representation"] !== "string" || profile["representation"].length > 4e3) invalid();
525379
+ return {
525380
+ profile: {
525381
+ card: profile["card"],
525382
+ representation: profile["representation"]
525383
+ },
525384
+ items: parseItems(value["items"]),
525385
+ forgetGeneration: value["forgetGeneration"]
525386
+ };
525387
+ }
525388
+ async search(query, options = {}) {
525389
+ const body = queryBody(query, options.limit ?? 20, options.sources);
525390
+ if (options.after !== void 0 && !isoTime$1(options.after) || options.before !== void 0 && !isoTime$1(options.before)) invalid();
525391
+ const value = await this.client.request("POST", "/api/memory/search", {
525392
+ ...body,
525393
+ ...options.after === void 0 ? {} : { after: options.after },
525394
+ ...options.before === void 0 ? {} : { before: options.before }
525395
+ });
525396
+ if (!isRecord$5(value) || !Array.isArray(value["items"]) || !generation(value["forgetGeneration"])) invalid();
525397
+ return {
525398
+ items: parseItems(value["items"]),
525399
+ forgetGeneration: value["forgetGeneration"]
525400
+ };
525401
+ }
525402
+ };
525403
+ function queryBody(query, limit, sources) {
525404
+ if (!query.trim() || query.length > 1e3 || !Number.isInteger(limit) || limit < 1 || limit > 20 || sources !== void 0 && (!Array.isArray(sources) || sources.some((source) => !/^(?:chat|tui|plugin:[a-z0-9_-]+)$/iu.test(source)))) invalid();
525405
+ return {
525406
+ query,
525407
+ limit,
525408
+ ...sources === void 0 ? {} : { sources }
525409
+ };
525410
+ }
525411
+ function parseItems(value) {
525412
+ if (value.length > 20) invalid();
525413
+ return value.map((item) => {
525414
+ if (!isRecord$5(item) || typeof item["id"] !== "string" || item["id"].length > 200 || typeof item["text"] !== "string" || item["text"].length > 2e3 || typeof item["source"] !== "string" || !/^(?:chat|tui|plugin:[a-z0-9_-]+)$/iu.test(item["source"]) || typeof item["sessionId"] !== "string" || item["sessionId"].length > 200 || !isoTime$1(item["at"]) || typeof item["score"] !== "number" || !Number.isFinite(item["score"]) || item["role"] !== void 0 && item["role"] !== "user" && item["role"] !== "assistant") invalid();
525415
+ return item;
525416
+ });
525417
+ }
525418
+ function generation(value) {
525419
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
525420
+ }
525421
+ function messageId$1(value) {
525422
+ return typeof value === "string" && value.length > 0 && value.length <= 200 && /^[a-z0-9][a-z0-9._:-]*$/iu.test(value);
525423
+ }
525424
+ function isoTime$1(value) {
525425
+ return typeof value === "string" && Number.isFinite(Date.parse(value)) && /(?:Z|[+-]\d\d:\d\d)$/u.test(value);
525426
+ }
525427
+ function isRecord$5(value) {
525428
+ return typeof value === "object" && value !== null && !Array.isArray(value);
525429
+ }
525430
+ function invalid() {
525431
+ throw new PersonalMemoryBrokerError("INVALID_PAYLOAD");
525432
+ }
525433
+ //#endregion
525434
+ //#region src/personal-memory/honcho-capture-source.ts
525435
+ const SECRET_PATTERN = /\b(?:password|passwort|api[-_ ]?key|secret|bearer|credential|cvv|cvc|iban)\b|sk-[a-z0-9_-]{20,}|ghp_[a-z0-9]{20,}|\b(?:\d[ -]?){13,19}\b/iu;
525436
+ const GROUP_MARKER = /^\[tg\s+(?:group|supergroup)\b/im;
525437
+ const MAX_WIRE_RECORD_CHARS = 4 * 1024 * 1024;
525438
+ async function readCompletedHonchoTurn(homeDir, session, turnId) {
525439
+ const sessionsRoot = await realpath(path.join(homeDir, "sessions"));
525440
+ const sessionDir = await realpath(session.sessionDir);
525441
+ if (path.basename(sessionDir) !== session.id || !isInside(sessionsRoot, sessionDir)) throw new Error("Honcho session path is outside this profile.");
525442
+ const canonicalWire = await realpath(path.join(sessionDir, "agents", "main", "wire.jsonl"));
525443
+ if (!isInside(sessionDir, canonicalWire)) throw new Error("Honcho Wire path escapes the session.");
525444
+ const wireStat = await stat(canonicalWire);
525445
+ if (!wireStat.isFile() || wireStat.size === 0) return void 0;
525446
+ const scanner = createTurnScanner(turnId);
525447
+ for await (const line of boundedLines(canonicalWire, wireStat.size)) scanner.accept(JSON.parse(line));
525448
+ return scanner.finish();
525449
+ }
525450
+ function createTurnScanner(completedTurnId) {
525451
+ let latestUserText;
525452
+ let latestUserTime;
525453
+ let userText;
525454
+ let occurredAt;
525455
+ let assistantText = "";
525456
+ let finalStepEnded = false;
525457
+ const targetTurnId = String(completedTurnId);
525458
+ const accept = (raw) => {
525459
+ if (!isRecord$4(raw)) return;
525460
+ if (raw["type"] === "turn.prompt") {
525461
+ const origin = raw["origin"];
525462
+ const input = raw["input"];
525463
+ const text = isRecord$4(origin) && origin["kind"] === "user" && Array.isArray(input) && input.every((part) => isRecord$4(part) && part["type"] === "text") ? textParts(input) : void 0;
525464
+ latestUserText = text && !GROUP_MARKER.test(text) && !SECRET_PATTERN.test(text) ? text : void 0;
525465
+ latestUserTime = latestUserText === void 0 ? void 0 : isoTime(raw["time"]);
525466
+ return;
525467
+ }
525468
+ if (raw["type"] !== "context.append_loop_event" || !isRecord$4(raw["event"])) return;
525469
+ const event = raw["event"];
525470
+ if (event["type"] === "step.begin" && event["turnId"] === targetTurnId) {
525471
+ userText ??= latestUserText;
525472
+ occurredAt ??= latestUserTime;
525473
+ assistantText = "";
525474
+ finalStepEnded = false;
525475
+ return;
525476
+ }
525477
+ if (event["type"] === "content.part" && event["turnId"] === targetTurnId && userText !== void 0 && isRecord$4(event["part"]) && event["part"]["type"] === "text" && typeof event["part"]["text"] === "string") {
525478
+ assistantText += event["part"]["text"];
525479
+ return;
525480
+ }
525481
+ if (event["type"] === "step.end" && event["turnId"] === targetTurnId) finalStepEnded = event["finishReason"] === "end_turn";
525482
+ };
525483
+ return {
525484
+ accept,
525485
+ finish: () => {
525486
+ const answer = assistantText.trim();
525487
+ return finalStepEnded && userText !== void 0 && occurredAt !== void 0 && answer.length > 0 && !SECRET_PATTERN.test(answer) ? {
525488
+ userText,
525489
+ assistantText: answer,
525490
+ occurredAt
525491
+ } : void 0;
525492
+ }
525493
+ };
525494
+ }
525495
+ function isoTime(value) {
525496
+ if (typeof value !== "string") return void 0;
525497
+ const timestamp = Date.parse(value);
525498
+ return Number.isFinite(timestamp) && new Date(timestamp).toISOString() === value ? value : void 0;
525499
+ }
525500
+ function textParts(parts) {
525501
+ return parts.filter((part) => isRecord$4(part) && part["type"] === "text" && typeof part["text"] === "string").map((part) => part.text).join("\n").trim() || void 0;
525502
+ }
525503
+ function isRecord$4(value) {
525504
+ return typeof value === "object" && value !== null && !Array.isArray(value);
525505
+ }
525506
+ function isInside(root, candidate) {
525507
+ const relative = path.relative(root, candidate);
525508
+ return relative !== "" && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
525509
+ }
525510
+ async function* boundedLines(wirePath, size) {
525511
+ const stream = createReadStream(wirePath, {
525512
+ encoding: "utf8",
525513
+ end: size - 1
525514
+ });
525515
+ let pending = "";
525516
+ try {
525517
+ for await (const chunk of stream) {
525518
+ let offset = 0;
525519
+ while (offset < chunk.length) {
525520
+ const newline = chunk.indexOf("\n", offset);
525521
+ const end = newline < 0 ? chunk.length : newline;
525522
+ pending += chunk.slice(offset, end);
525523
+ if (pending.length > MAX_WIRE_RECORD_CHARS) throw new Error("Honcho Wire record is too large.");
525524
+ if (newline < 0) break;
525525
+ if (pending.length > 0) yield pending.replace(/\r$/u, "");
525526
+ pending = "";
525527
+ offset = newline + 1;
525528
+ }
525529
+ }
525530
+ } finally {
525531
+ stream.destroy();
525532
+ }
525533
+ }
525534
+ //#endregion
525535
+ //#region src/personal-memory/account-memory-capture.ts
525536
+ const MAX_PENDING = 2e3;
525537
+ const MAX_COMPLETED = 1e4;
525538
+ const MAX_RETRACTIONS = 2e3;
525539
+ const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
525540
+ var AccountMemoryCaptureQueue = class {
525541
+ homeDir;
525542
+ broker;
525543
+ readTurn;
525544
+ workspaceCache;
525545
+ work = Promise.resolve();
525546
+ constructor(homeDir, broker, readTurn = readCompletedHonchoTurn, workspaceCache) {
525547
+ this.homeDir = homeDir;
525548
+ this.broker = broker;
525549
+ this.readTurn = readTurn;
525550
+ this.workspaceCache = workspaceCache;
525551
+ }
525552
+ captureCompletedTurn(session, turnId) {
525553
+ return this.serial(async () => {
525554
+ if (!Number.isSafeInteger(turnId) || turnId < 0) return "unavailable";
525555
+ let state;
525556
+ try {
525557
+ state = await this.readSessionState(session.id);
525558
+ if (turnId <= state.blockedThroughTurnId) return "skipped";
525559
+ if (turnId > state.highestObservedTurnId) {
525560
+ state = {
525561
+ ...state,
525562
+ highestObservedTurnId: turnId
525563
+ };
525564
+ await this.writeSessionState(state);
525565
+ }
525566
+ } catch {
525567
+ return "unavailable";
525568
+ }
525569
+ let workspace;
525570
+ let turn;
525571
+ try {
525572
+ workspace = await this.broker.workspace(session.id);
525573
+ turn = await this.readTurn(this.homeDir, session, turnId);
525574
+ } catch {
525575
+ return "unavailable";
525576
+ }
525577
+ if (state.workspaceId !== null && state.workspaceId !== workspace.workspaceId) return "unavailable";
525578
+ if (state.workspaceId === null || state.sessionEpoch !== workspace.sessionEpoch) try {
525579
+ await this.writeSessionState({
525580
+ ...state,
525581
+ workspaceId: workspace.workspaceId,
525582
+ sessionEpoch: workspace.sessionEpoch
525583
+ });
525584
+ } catch {
525585
+ return "unavailable";
525586
+ }
525587
+ if (this.workspaceCache !== void 0) try {
525588
+ if (!await this.workspaceCache.set(workspace.workspaceId)) return "unavailable";
525589
+ } catch {
525590
+ return "unavailable";
525591
+ }
525592
+ if (turn === void 0 || beforeCutoff(turn.occurredAt, workspace.forgetCutoff)) return "skipped";
525593
+ const journalPath = this.journalPath(workspace.workspaceId);
525594
+ let journal;
525595
+ try {
525596
+ journal = await this.readJournal(journalPath, workspace.workspaceId);
525597
+ } catch {
525598
+ return "unavailable";
525599
+ }
525600
+ if (journal.suppressedTurns.includes(turnKey(session.id, turnId))) return "skipped";
525601
+ if (journal.known.some((entry) => entry.sessionId === session.id && entry.turnId === turnId)) return "skipped";
525602
+ const revision = journal.revisions[turnKey(session.id, turnId)] ?? 0;
525603
+ const messageIds = turnMessageIds(session.id, turnId, turn, revision);
525604
+ const key = captureKey(session.id, turnId, turn.occurredAt, messageIds);
525605
+ if (journal.completed.includes(key)) return "skipped";
525606
+ const old = journal.pending.find((entry) => entry.sessionId === session.id && entry.turnId === turnId);
525607
+ if (old !== void 0 && (old.occurredAt !== turn.occurredAt || old.messageIds.some((id, index) => id !== messageIds[index]))) return "skipped";
525608
+ if (old === void 0) {
525609
+ if (journal.pending.length >= MAX_PENDING) return "unavailable";
525610
+ journal = {
525611
+ ...journal,
525612
+ pending: [...journal.pending, {
525613
+ captureId: randomUUID(),
525614
+ sessionId: session.id,
525615
+ sessionDir: session.sessionDir,
525616
+ turnId,
525617
+ occurredAt: turn.occurredAt,
525618
+ messageIds,
525619
+ sessionEpoch: workspace.sessionEpoch,
525620
+ awaitingSessionRetract: journal.retractions.some((entry) => entry.sessionId === session.id && "wholeSession" in entry)
525621
+ }]
525622
+ };
525623
+ try {
525624
+ await this.writeJournal(journalPath, journal);
525625
+ } catch {
525626
+ return "unavailable";
525627
+ }
525628
+ }
525629
+ if (!await this.flushRetractions(journalPath, journal)) return "queued";
525630
+ journal = await this.readJournal(journalPath, workspace.workspaceId);
525631
+ return this.flushJournal(journalPath, journal, workspace, {
525632
+ sessionId: session.id,
525633
+ turnId,
525634
+ turn
525635
+ });
525636
+ });
525637
+ }
525638
+ retryPending() {
525639
+ return this.serial(async () => {
525640
+ try {
525641
+ const workspace = await this.broker.workspace();
525642
+ const journalPath = this.journalPath(workspace.workspaceId);
525643
+ let journal = await this.readJournal(journalPath, workspace.workspaceId);
525644
+ if (!await this.flushRetractions(journalPath, journal)) return "queued";
525645
+ journal = await this.readJournal(journalPath, workspace.workspaceId);
525646
+ return await this.flushJournal(journalPath, journal, workspace);
525647
+ } catch {
525648
+ return "unavailable";
525649
+ }
525650
+ });
525651
+ }
525652
+ retryRetractions() {
525653
+ return this.serial(async () => {
525654
+ try {
525655
+ const workspace = await this.broker.workspace();
525656
+ const journalPath = this.journalPath(workspace.workspaceId);
525657
+ const journal = await this.readJournal(journalPath, workspace.workspaceId);
525658
+ if (journal.retractions.length === 0) return "skipped";
525659
+ return await this.flushRetractions(journalPath, journal) ? "retracted" : "queued";
525660
+ } catch {
525661
+ return "unavailable";
525662
+ }
525663
+ });
525664
+ }
525665
+ flushRetractionsBeforeLogout() {
525666
+ return this.serial(async () => {
525667
+ try {
525668
+ const cachedWorkspaceId = await this.workspaceCache?.get();
525669
+ if (cachedWorkspaceId === void 0) return false;
525670
+ const journalPath = this.journalPath(cachedWorkspaceId);
525671
+ const journal = await this.readJournal(journalPath, cachedWorkspaceId);
525672
+ if (journal.retractions.length === 0) return false;
525673
+ if ((await this.broker.workspace()).workspaceId !== cachedWorkspaceId) return true;
525674
+ return !await this.flushRetractions(journalPath, journal);
525675
+ } catch {
525676
+ return true;
525677
+ }
525678
+ });
525679
+ }
525680
+ retractTurn(sessionId, turnId) {
525681
+ return this.serial(async () => {
525682
+ try {
525683
+ const workspace = await this.broker.workspace();
525684
+ const journalPath = this.journalPath(workspace.workspaceId);
525685
+ const journal = await this.readJournal(journalPath, workspace.workspaceId);
525686
+ const matching = [...journal.pending, ...journal.known].filter((entry) => entry.sessionId === sessionId && entry.turnId === turnId);
525687
+ const messageIds = [...new Set(matching.flatMap((entry) => entry.messageIds))];
525688
+ if (messageIds.length === 0) return "skipped";
525689
+ if (journal.retractions.length >= MAX_RETRACTIONS) return "unavailable";
525690
+ const next = {
525691
+ ...journal,
525692
+ pending: journal.pending.filter((entry) => entry.sessionId !== sessionId || entry.turnId !== turnId),
525693
+ known: journal.known.filter((entry) => entry.sessionId !== sessionId || entry.turnId !== turnId),
525694
+ retractions: [...journal.retractions, {
525695
+ retractId: randomUUID(),
525696
+ sessionId,
525697
+ messageIds
525698
+ }],
525699
+ revisions: {
525700
+ ...journal.revisions,
525701
+ [turnKey(sessionId, turnId)]: (journal.revisions[turnKey(sessionId, turnId)] ?? 0) + 1
525702
+ }
525703
+ };
525704
+ await this.writeJournal(journalPath, next);
525705
+ return await this.flushRetractions(journalPath, next) ? "retracted" : "queued";
525706
+ } catch {
525707
+ return "unavailable";
525708
+ }
525709
+ });
525710
+ }
525711
+ retractSession(sessionId, throughTurnId) {
525712
+ return this.serial(async () => {
525713
+ if (throughTurnId !== void 0 && (!Number.isSafeInteger(throughTurnId) || throughTurnId < 0)) return "unavailable";
525714
+ let state;
525715
+ try {
525716
+ state = await this.readSessionState(sessionId);
525717
+ } catch {
525718
+ return "unavailable";
525719
+ }
525720
+ let workspace;
525721
+ try {
525722
+ workspace = await this.broker.workspace(sessionId);
525723
+ } catch {
525724
+ if (state.workspaceId !== null) {
525725
+ let cachedWorkspaceId;
525726
+ try {
525727
+ cachedWorkspaceId = await this.workspaceCache?.get();
525728
+ } catch {
525729
+ return "unavailable";
525730
+ }
525731
+ if (cachedWorkspaceId !== state.workspaceId) {
525732
+ try {
525733
+ await this.writeSessionState({
525734
+ ...state,
525735
+ highestObservedTurnId: Math.max(state.highestObservedTurnId, throughTurnId ?? -1),
525736
+ blockedThroughTurnId: Math.max(state.blockedThroughTurnId, state.highestObservedTurnId, throughTurnId ?? -1)
525737
+ });
525738
+ } catch {
525739
+ return "unavailable";
525740
+ }
525741
+ return "unavailable";
525742
+ }
525743
+ return this.queueSessionRetraction(sessionId, state, cachedWorkspaceId, state.sessionEpoch, throughTurnId, false);
525744
+ }
525745
+ try {
525746
+ await this.writeSessionState({
525747
+ ...state,
525748
+ highestObservedTurnId: Math.max(state.highestObservedTurnId, throughTurnId ?? -1),
525749
+ blockedThroughTurnId: Math.max(state.blockedThroughTurnId, state.highestObservedTurnId, throughTurnId ?? -1)
525750
+ });
525751
+ return "retracted";
525752
+ } catch {
525753
+ return "unavailable";
525754
+ }
525755
+ }
525756
+ if (workspace.sessionEpoch === null) return "unavailable";
525757
+ if (state.workspaceId !== null && state.workspaceId !== workspace.workspaceId) return "unavailable";
525758
+ if (this.workspaceCache !== void 0) try {
525759
+ if (!await this.workspaceCache.set(workspace.workspaceId)) return "unavailable";
525760
+ } catch {
525761
+ return "unavailable";
525762
+ }
525763
+ return this.queueSessionRetraction(sessionId, state, workspace.workspaceId, workspace.sessionEpoch, throughTurnId, true);
525764
+ });
525765
+ }
525766
+ async queueSessionRetraction(sessionId, state, workspaceId, expectedEpoch, throughTurnId, sendNow) {
525767
+ try {
525768
+ const journalPath = this.journalPath(workspaceId);
525769
+ const journal = await this.readJournal(journalPath, workspaceId);
525770
+ if (journal.retractions.length >= MAX_RETRACTIONS) return "unavailable";
525771
+ const next = {
525772
+ ...journal,
525773
+ pending: journal.pending.filter((entry) => entry.sessionId !== sessionId),
525774
+ known: journal.known.filter((entry) => entry.sessionId !== sessionId),
525775
+ retractions: [...journal.retractions, {
525776
+ retractId: randomUUID(),
525777
+ sessionId,
525778
+ wholeSession: true,
525779
+ expectedEpoch
525780
+ }],
525781
+ suppressedTurns: [...new Set([...journal.suppressedTurns, ...[...journal.pending, ...journal.known].filter((entry) => entry.sessionId === sessionId).map((entry) => turnKey(entry.sessionId, entry.turnId))])].slice(-MAX_COMPLETED)
525782
+ };
525783
+ await this.writeJournal(journalPath, next);
525784
+ await this.writeSessionState({
525785
+ ...state,
525786
+ highestObservedTurnId: Math.max(state.highestObservedTurnId, throughTurnId ?? -1),
525787
+ blockedThroughTurnId: Math.max(state.blockedThroughTurnId, state.highestObservedTurnId, throughTurnId ?? -1),
525788
+ workspaceId,
525789
+ sessionEpoch: expectedEpoch
525790
+ });
525791
+ return sendNow && await this.flushRetractions(journalPath, next) ? "retracted" : "queued";
525792
+ } catch {
525793
+ return "unavailable";
525794
+ }
525795
+ }
525796
+ async flushRetractions(journalPath, journal) {
525797
+ if (this.broker.retract === void 0) return journal.retractions.length === 0;
525798
+ let current = journal;
525799
+ for (const entry of journal.retractions) {
525800
+ let response;
525801
+ try {
525802
+ response = await this.broker.retract(entry);
525803
+ } catch {
525804
+ return false;
525805
+ }
525806
+ if ("wholeSession" in entry && response.sessionEpoch !== void 0) try {
525807
+ const state = await this.readSessionState(entry.sessionId);
525808
+ await this.writeSessionState({
525809
+ ...state,
525810
+ sessionEpoch: response.sessionEpoch
525811
+ });
525812
+ } catch {
525813
+ return false;
525814
+ }
525815
+ current = {
525816
+ ...current,
525817
+ retractions: current.retractions.filter((item) => item !== entry),
525818
+ pending: "wholeSession" in entry && response.sessionEpoch !== void 0 ? response.rederive === false ? current.pending.filter((item) => item.sessionId !== entry.sessionId || !item.awaitingSessionRetract) : current.pending.map((item) => item.sessionId === entry.sessionId && item.awaitingSessionRetract ? {
525819
+ ...item,
525820
+ sessionEpoch: response.sessionEpoch,
525821
+ awaitingSessionRetract: false
525822
+ } : item) : current.pending
525823
+ };
525824
+ await this.writeJournal(journalPath, current);
525825
+ }
525826
+ return true;
525827
+ }
525828
+ discardPending() {
525829
+ return this.serial(async () => {
525830
+ const directory = path.join(this.homeDir, "memory");
525831
+ let names;
525832
+ try {
525833
+ names = await readdir(directory);
525834
+ } catch (error) {
525835
+ if (isMissing(error)) return;
525836
+ throw error;
525837
+ }
525838
+ for (const name of names) {
525839
+ if (!/^honcho-pending-[0-9a-f]{64}\.json$/u.test(name)) continue;
525840
+ const journalPath = path.join(directory, name);
525841
+ if (!(await lstat(journalPath)).isFile()) continue;
525842
+ const value = JSON.parse(await readFile(journalPath, "utf8"));
525843
+ if (!isRecord$3(value) || typeof value["workspaceId"] !== "string") continue;
525844
+ const journal = await this.readJournal(journalPath, value["workspaceId"]);
525845
+ if (journal.pending.length > 0) await this.writeJournal(journalPath, {
525846
+ ...journal,
525847
+ pending: []
525848
+ });
525849
+ }
525850
+ });
525851
+ }
525852
+ async flushJournal(journalPath, journal, workspace, fresh) {
525853
+ if (journal.pending.length === 0) return "skipped";
525854
+ let pending = [...journal.pending];
525855
+ let completed = [...journal.completed];
525856
+ let known = [...journal.known];
525857
+ let result = "skipped";
525858
+ for (const entry of journal.pending) {
525859
+ if (entry.awaitingSessionRetract) return "queued";
525860
+ const session = {
525861
+ id: entry.sessionId,
525862
+ sessionDir: entry.sessionDir
525863
+ };
525864
+ let turn;
525865
+ try {
525866
+ turn = fresh?.sessionId === entry.sessionId && fresh.turnId === entry.turnId ? fresh.turn : await this.readTurn(this.homeDir, session, entry.turnId);
525867
+ } catch {
525868
+ return "queued";
525869
+ }
525870
+ if (turn === void 0 || turn.occurredAt !== entry.occurredAt || beforeCutoff(entry.occurredAt, workspace.forgetCutoff)) {
525871
+ pending = pending.filter((item) => item.captureId !== entry.captureId);
525872
+ await this.writeJournal(journalPath, {
525873
+ ...journal,
525874
+ pending,
525875
+ completed,
525876
+ known
525877
+ });
525878
+ continue;
525879
+ }
525880
+ const revision = journal.revisions[turnKey(entry.sessionId, entry.turnId)] ?? 0;
525881
+ if (turnMessageIds(entry.sessionId, entry.turnId, turn, revision).some((id, index) => id !== entry.messageIds[index])) {
525882
+ pending = pending.filter((item) => item.captureId !== entry.captureId);
525883
+ await this.writeJournal(journalPath, {
525884
+ ...journal,
525885
+ pending,
525886
+ completed,
525887
+ known
525888
+ });
525889
+ continue;
525890
+ }
525891
+ try {
525892
+ const response = await this.broker.capture({
525893
+ captureId: entry.captureId,
525894
+ sessionId: entry.sessionId,
525895
+ forgetGeneration: workspace.forgetGeneration,
525896
+ sessionEpoch: entry.sessionEpoch,
525897
+ messages: [{
525898
+ id: entry.messageIds[0],
525899
+ role: "user",
525900
+ content: turn.userText,
525901
+ at: turn.occurredAt
525902
+ }, {
525903
+ id: entry.messageIds[1],
525904
+ role: "assistant",
525905
+ content: turn.assistantText,
525906
+ at: turn.occurredAt
525907
+ }]
525908
+ });
525909
+ const key = captureKey(entry.sessionId, entry.turnId, entry.occurredAt, entry.messageIds);
525910
+ if ("reason" in response && response.reason === "memory_disabled") {
525911
+ completed = [...completed, key].slice(-MAX_COMPLETED);
525912
+ await this.writeJournal(journalPath, {
525913
+ ...journal,
525914
+ pending: [],
525915
+ completed
525916
+ });
525917
+ return "skipped";
525918
+ }
525919
+ if ("reason" in response && response.reason === "session_retracted") {
525920
+ pending = pending.filter((item) => item.sessionId !== entry.sessionId || item.sessionEpoch !== entry.sessionEpoch);
525921
+ await this.writeJournal(journalPath, {
525922
+ ...journal,
525923
+ pending,
525924
+ completed,
525925
+ known
525926
+ });
525927
+ return "skipped";
525928
+ }
525929
+ pending = pending.filter((item) => item.captureId !== entry.captureId);
525930
+ completed = [...completed, key].slice(-MAX_COMPLETED);
525931
+ known = [...known, {
525932
+ key,
525933
+ sessionId: entry.sessionId,
525934
+ turnId: entry.turnId,
525935
+ occurredAt: entry.occurredAt,
525936
+ messageIds: entry.messageIds
525937
+ }].slice(-MAX_COMPLETED);
525938
+ await this.writeJournal(journalPath, {
525939
+ ...journal,
525940
+ pending,
525941
+ completed,
525942
+ known
525943
+ });
525944
+ result = "captured";
525945
+ } catch (error) {
525946
+ if (error instanceof PersonalMemoryBrokerError && error.status === 403) {
525947
+ const suppressedTurns = [...new Set([...journal.suppressedTurns, ...pending.map((item) => turnKey(item.sessionId, item.turnId))])].slice(-MAX_COMPLETED);
525948
+ try {
525949
+ await this.writeJournal(journalPath, {
525950
+ ...journal,
525951
+ pending: [],
525952
+ completed,
525953
+ known,
525954
+ suppressedTurns
525955
+ });
525956
+ } catch {
525957
+ return "unavailable";
525958
+ }
525959
+ return "skipped";
525960
+ }
525961
+ if (error instanceof PersonalMemoryBrokerError && (error.code === "INVALID_PAYLOAD" || error.code === "PAYLOAD_TOO_LARGE" || error.code === "SECRET_REJECTED")) {
525962
+ pending = pending.filter((item) => item.captureId !== entry.captureId);
525963
+ await this.writeJournal(journalPath, {
525964
+ ...journal,
525965
+ pending,
525966
+ completed,
525967
+ known
525968
+ });
525969
+ continue;
525970
+ }
525971
+ if (error instanceof PersonalMemoryBrokerError && error.code === "FORGET_GENERATION_CHANGED") return "queued";
525972
+ return "queued";
525973
+ }
525974
+ }
525975
+ return result;
525976
+ }
525977
+ journalPath(workspaceId) {
525978
+ const name = createHash("sha256").update(workspaceId).digest("hex");
525979
+ return path.join(this.homeDir, "memory", `honcho-pending-${name}.json`);
525980
+ }
525981
+ sessionStatePath(sessionId) {
525982
+ const name = createHash("sha256").update(sessionId).digest("hex");
525983
+ return path.join(this.homeDir, "memory", `honcho-session-${name}.json`);
525984
+ }
525985
+ async readSessionState(sessionId) {
525986
+ let value;
525987
+ try {
525988
+ value = JSON.parse(await readFile(this.sessionStatePath(sessionId), "utf8"));
525989
+ } catch (error) {
525990
+ if (isMissing(error)) return {
525991
+ version: 1,
525992
+ sessionId,
525993
+ highestObservedTurnId: -1,
525994
+ blockedThroughTurnId: -1,
525995
+ workspaceId: null,
525996
+ sessionEpoch: null
525997
+ };
525998
+ throw error;
525999
+ }
526000
+ if (!isRecord$3(value) || value["version"] !== 1 || value["sessionId"] !== sessionId || !Number.isSafeInteger(value["highestObservedTurnId"]) || value["highestObservedTurnId"] < -1 || !Number.isSafeInteger(value["blockedThroughTurnId"]) || value["blockedThroughTurnId"] < -1 || value["blockedThroughTurnId"] > value["highestObservedTurnId"] || value["workspaceId"] !== null && (typeof value["workspaceId"] !== "string" || value["workspaceId"].length === 0) || value["sessionEpoch"] !== null && (!Number.isSafeInteger(value["sessionEpoch"]) || value["sessionEpoch"] < 0)) throw new Error("Invalid account memory session state.");
526001
+ return value;
526002
+ }
526003
+ async writeSessionState(state) {
526004
+ const statePath = this.sessionStatePath(state.sessionId);
526005
+ const directory = path.dirname(statePath);
526006
+ await mkdir(directory, {
526007
+ recursive: true,
526008
+ mode: 448
526009
+ });
526010
+ const root = await realpath(this.homeDir);
526011
+ if (path.dirname(await realpath(directory)) !== root) throw new Error("Account memory session state escapes the BLUN profile.");
526012
+ const temporary = `${statePath}.${randomUUID()}.tmp`;
526013
+ try {
526014
+ await writeFile(temporary, JSON.stringify(state), {
526015
+ encoding: "utf8",
526016
+ mode: 384,
526017
+ flag: "wx"
526018
+ });
526019
+ await rename(temporary, statePath);
526020
+ } finally {
526021
+ await unlink(temporary).catch(() => {});
526022
+ }
526023
+ }
526024
+ async readJournal(journalPath, workspaceId) {
526025
+ let text;
526026
+ try {
526027
+ text = await readFile(journalPath, "utf8");
526028
+ } catch (error) {
526029
+ if (isMissing(error)) return {
526030
+ version: 2,
526031
+ workspaceId,
526032
+ pending: [],
526033
+ completed: [],
526034
+ known: [],
526035
+ retractions: [],
526036
+ suppressedTurns: [],
526037
+ revisions: {}
526038
+ };
526039
+ throw error;
526040
+ }
526041
+ const value = JSON.parse(text);
526042
+ if (!isRecord$3(value) || value["version"] !== 2 || value["workspaceId"] !== workspaceId || !Array.isArray(value["pending"]) || value["pending"].length > MAX_PENDING || !value["pending"].every(validPending) || !Array.isArray(value["completed"]) || value["completed"].length > MAX_COMPLETED || !value["completed"].every((item) => typeof item === "string" && /^[0-9a-f]{64}$/u.test(item)) || !Array.isArray(value["known"]) || value["known"].length > MAX_COMPLETED || !value["known"].every(validKnown) || !Array.isArray(value["retractions"]) || value["retractions"].length > MAX_RETRACTIONS || !value["retractions"].every(validRetraction) || !Array.isArray(value["suppressedTurns"]) || value["suppressedTurns"].length > MAX_COMPLETED || !value["suppressedTurns"].every((item) => typeof item === "string" && /^[0-9a-f]{64}$/u.test(item)) || !isRecord$3(value["revisions"]) || Object.keys(value["revisions"]).length > MAX_COMPLETED || !Object.entries(value["revisions"]).every(([key, revision]) => /^[0-9a-f]{64}$/u.test(key) && Number.isSafeInteger(revision) && revision >= 0)) throw new Error("Invalid account memory journal.");
526043
+ return value;
526044
+ }
526045
+ async writeJournal(journalPath, journal) {
526046
+ const directory = path.dirname(journalPath);
526047
+ await mkdir(directory, {
526048
+ recursive: true,
526049
+ mode: 448
526050
+ });
526051
+ const root = await realpath(this.homeDir);
526052
+ if (path.dirname(await realpath(directory)) !== root) throw new Error("Account memory journal escapes the BLUN profile.");
526053
+ const temporary = `${journalPath}.${randomUUID()}.tmp`;
526054
+ try {
526055
+ await writeFile(temporary, JSON.stringify(journal), {
526056
+ encoding: "utf8",
526057
+ mode: 384,
526058
+ flag: "wx"
526059
+ });
526060
+ await rename(temporary, journalPath);
526061
+ } finally {
526062
+ await unlink(temporary).catch(() => {});
526063
+ }
526064
+ }
526065
+ serial(run) {
526066
+ const task = this.work.then(run, run);
526067
+ this.work = task.then(() => void 0, () => void 0);
526068
+ return task;
526069
+ }
526070
+ };
526071
+ function beforeCutoff(occurredAt, cutoff) {
526072
+ return cutoff !== null && Date.parse(occurredAt) <= Date.parse(cutoff);
526073
+ }
526074
+ function captureKey(sessionId, turnId, occurredAt, messageIds) {
526075
+ return createHash("sha256").update(`${sessionId}\0${turnId}\0${occurredAt}\0${messageIds.join("\0")}`).digest("hex");
526076
+ }
526077
+ function turnKey(sessionId, turnId) {
526078
+ return createHash("sha256").update(`${sessionId}\0${turnId}`).digest("hex");
526079
+ }
526080
+ function turnMessageIds(sessionId, turnId, turn, revision) {
526081
+ return [stableMessageId(sessionId, turnId, revision, "user", turn.userText), stableMessageId(sessionId, turnId, revision, "assistant", turn.assistantText)];
526082
+ }
526083
+ function stableMessageId(sessionId, turnId, revision, role, content) {
526084
+ return `tui-${createHash("sha256").update(`${sessionId}\0${turnId}\0${revision}\0${role}\0${content}`).digest("hex")}`;
526085
+ }
526086
+ function validPending(value) {
526087
+ return isRecord$3(value) && typeof value["captureId"] === "string" && UUID_V4.test(value["captureId"]) && typeof value["sessionId"] === "string" && typeof value["sessionDir"] === "string" && Number.isSafeInteger(value["turnId"]) && value["turnId"] >= 0 && typeof value["occurredAt"] === "string" && Number.isFinite(Date.parse(value["occurredAt"])) && validMessageIds(value["messageIds"]) && typeof value["awaitingSessionRetract"] === "boolean" && (value["sessionEpoch"] === null || Number.isSafeInteger(value["sessionEpoch"]) && value["sessionEpoch"] >= 0);
526088
+ }
526089
+ function validKnown(value) {
526090
+ return isRecord$3(value) && typeof value["key"] === "string" && /^[0-9a-f]{64}$/u.test(value["key"]) && typeof value["sessionId"] === "string" && Number.isSafeInteger(value["turnId"]) && typeof value["occurredAt"] === "string" && Number.isFinite(Date.parse(value["occurredAt"])) && validMessageIds(value["messageIds"]);
526091
+ }
526092
+ function validRetraction(value) {
526093
+ return isRecord$3(value) && typeof value["retractId"] === "string" && UUID_V4.test(value["retractId"]) && typeof value["sessionId"] === "string" && value["sessionId"].length > 0 && (value["wholeSession"] === true && (value["expectedEpoch"] === null || Number.isSafeInteger(value["expectedEpoch"]) && value["expectedEpoch"] >= 0) || Array.isArray(value["messageIds"]) && value["messageIds"].length > 0 && value["messageIds"].length <= 200 && value["messageIds"].every(validMessageId));
526094
+ }
526095
+ function validMessageIds(value) {
526096
+ return Array.isArray(value) && value.length === 2 && value.every(validMessageId);
526097
+ }
526098
+ function validMessageId(value) {
526099
+ return typeof value === "string" && /^tui-[0-9a-f]{64}$/u.test(value);
526100
+ }
526101
+ function isRecord$3(value) {
526102
+ return typeof value === "object" && value !== null && !Array.isArray(value);
526103
+ }
526104
+ function isMissing(error) {
526105
+ return isRecord$3(error) && error["code"] === "ENOENT";
526106
+ }
526107
+ //#endregion
526108
+ //#region src/personal-memory/account-memory-runtime.ts
526109
+ var TuiAccountMemoryRuntime = class {
526110
+ client;
526111
+ broker;
526112
+ queue;
526113
+ getManagedQuota;
526114
+ constructor(client, broker, queue, getManagedQuota) {
526115
+ this.client = client;
526116
+ this.broker = broker;
526117
+ this.queue = queue;
526118
+ this.getManagedQuota = getManagedQuota;
526119
+ }
526120
+ async captureCompletedTurn(session, turnId) {
526121
+ const permission = await this.permission("write");
526122
+ if (permission === "unavailable") return "unavailable";
526123
+ if (permission === "denied") {
526124
+ await this.queue.discardPending().catch(() => {});
526125
+ return "skipped";
526126
+ }
526127
+ return this.queue.captureCompletedTurn(session, turnId).catch(() => "unavailable");
526128
+ }
526129
+ async retryPending() {
526130
+ const permission = await this.permission("write");
526131
+ if (permission === "denied") await this.queue.discardPending().catch(() => {});
526132
+ const retractions = await this.queue.retryRetractions().catch(() => "unavailable");
526133
+ if (retractions === "queued") return "queued";
526134
+ if (permission === "denied") return "skipped";
526135
+ if (permission === "unavailable" || retractions === "unavailable") return "unavailable";
526136
+ return this.queue.retryPending().catch(() => "unavailable");
526137
+ }
526138
+ retractTurn(sessionId, turnId) {
526139
+ return this.queue.retractTurn(sessionId, turnId).catch(() => "unavailable");
526140
+ }
526141
+ retractSession(sessionId, throughTurnId) {
526142
+ return (throughTurnId === void 0 ? this.queue.retractSession(sessionId) : this.queue.retractSession(sessionId, throughTurnId)).catch(() => "unavailable");
526143
+ }
526144
+ flushRetractionsBeforeLogout() {
526145
+ return this.queue.flushRetractionsBeforeLogout().catch(() => true);
526146
+ }
526147
+ async recall(query) {
526148
+ if (await this.permission("read") !== "allowed") return void 0;
526149
+ return this.broker.recall(query, 8).catch(() => void 0);
526150
+ }
526151
+ async search(query, limit = 20) {
526152
+ if (await this.permission("read") !== "allowed") return void 0;
526153
+ return this.broker.search(query, { limit }).catch(() => void 0);
526154
+ }
526155
+ async permission(operation) {
526156
+ let settings;
526157
+ try {
526158
+ const quota = await this.getManagedQuota();
526159
+ if (quota.kind !== "ok") return "unavailable";
526160
+ if (quota.paid !== true) return "denied";
526161
+ settings = await this.client.getSettings();
526162
+ } catch {
526163
+ return "unavailable";
526164
+ }
526165
+ if (settings.consentStatus !== "enabled" || !settings.memoryEnabled || !settings.useChatHistory) return "denied";
526166
+ return operation === "write" ? settings.allowNewMemories ? "allowed" : "denied" : settings.useSavedMemories ? "allowed" : "denied";
526167
+ }
526168
+ };
526169
+ function createTuiAccountMemoryRuntime(harness, env = process.env) {
526170
+ if (env["BLUN_ACCOUNT_MEMORY_BROKER_ENABLED"] !== "1") return void 0;
526171
+ try {
526172
+ const client = createPersonalMemoryBrokerClient(harness);
526173
+ const broker = new AccountMemoryBroker(client);
526174
+ return new TuiAccountMemoryRuntime(client, broker, new AccountMemoryCaptureQueue(harness.homeDir, broker, void 0, {
526175
+ get: () => harness.auth.getCachedMemoryWorkspaceId(),
526176
+ set: (workspaceId) => harness.auth.cacheMemoryWorkspaceId(workspaceId)
526177
+ }), () => harness.auth.getManagedQuota(DEFAULT_OAUTH_PROVIDER_NAME));
526178
+ } catch {
526179
+ return;
526180
+ }
526181
+ }
526182
+ //#endregion
524984
526183
  //#region src/utils/persistence.ts
524985
526184
  /**
524986
526185
  * Small persistence helpers for CLI-owned data files.
@@ -532899,7 +534098,8 @@ var PersonalMemoryController = class {
532899
534098
  await this.dependencies.bindTools(session, this.host.harness, {
532900
534099
  binding: personalMemoryHostBinding(),
532901
534100
  localHistory: this.host.harness,
532902
- searchOnly: true
534101
+ searchOnly: true,
534102
+ accountMemory: this.host.accountMemoryRuntime
532903
534103
  });
532904
534104
  return this.isCurrent(generation, session) ? "ready" : "stale";
532905
534105
  } catch {
@@ -532981,7 +534181,8 @@ var PersonalMemoryController = class {
532981
534181
  await this.dependencies.bindTools(session, this.host.harness, {
532982
534182
  binding,
532983
534183
  client,
532984
- localHistory: this.host.harness
534184
+ localHistory: this.host.harness,
534185
+ accountMemory: this.host.accountMemoryRuntime
532985
534186
  });
532986
534187
  return "ready";
532987
534188
  } catch {
@@ -535804,7 +537005,10 @@ var SessionEventHandler = class {
535804
537005
  this.showPendingCompactionRetry();
535805
537006
  this.goalCompletionTurnEnded = true;
535806
537007
  this.scheduleQueuedGoalPromotion();
535807
- if (event.reason === "completed") this.host.refreshManagedQuotaWindows();
537008
+ if (event.reason === "completed") {
537009
+ this.host.refreshManagedQuotaWindows();
537010
+ this.host.recordAccountMemoryTurn?.(event);
537011
+ }
535808
537012
  }
535809
537013
  handleStepBegin(event) {
535810
537014
  this.host.commitQueuedSteerAtStepStart(event.turnId);
@@ -543069,6 +544273,7 @@ var BlunTUI = class {
543069
544273
  editorKeyboard;
543070
544274
  scrollbackController;
543071
544275
  personalMemoryController;
544276
+ accountMemoryRuntime;
543072
544277
  customerMistakeController;
543073
544278
  managedQuotaWarningController;
543074
544279
  managedQuotaWarningPersistence = Promise.resolve();
@@ -543153,6 +544358,7 @@ var BlunTUI = class {
543153
544358
  this.loopCountdown = new LoopCountdownController(() => this.state.ui.requestRender());
543154
544359
  this.authFlow = new AuthFlowController(this);
543155
544360
  this.personalMemoryController = new PersonalMemoryController(this);
544361
+ this.accountMemoryRuntime = createTuiAccountMemoryRuntime(harness);
543156
544362
  this.customerMistakeController = new CustomerMistakeHostController();
543157
544363
  this.btwPanelController = new BtwPanelController(this);
543158
544364
  this.sessionEventHandler = new SessionEventHandler(this);
@@ -544846,6 +546052,15 @@ var BlunTUI = class {
544846
546052
  refreshManagedQuotaWindows() {
544847
546053
  this.authFlow.refreshManagedQuotaWindows();
544848
546054
  }
546055
+ recordAccountMemoryTurn(event) {
546056
+ const session = this.session;
546057
+ const sessionDir = session?.summary?.sessionDir;
546058
+ if (session === void 0 || sessionDir === void 0) return;
546059
+ this.accountMemoryRuntime?.captureCompletedTurn({
546060
+ id: session.id,
546061
+ sessionDir
546062
+ }, event.turnId).catch(() => {});
546063
+ }
544849
546064
  async refreshPersonalMemory(promptIfNeverAsked = false) {
544850
546065
  await this.personalMemoryController.refresh({ promptIfNeverAsked });
544851
546066
  }
@@ -544987,6 +546202,7 @@ var BlunTUI = class {
544987
546202
  await this.refreshManagedImageReaderAvailability(session);
544988
546203
  await this.authFlow.applyManagedAccountContextToSession();
544989
546204
  await this.personalMemoryController.refresh();
546205
+ this.accountMemoryRuntime?.retryPending().catch(() => {});
544990
546206
  this.telegramSessionScope = queueScope;
544991
546207
  this.telegramChannel?.bindSessionQueue(queueScope);
544992
546208
  if (selectionScope !== void 0 && this.session === session) {
@@ -545270,6 +546486,7 @@ var BlunTUI = class {
545270
546486
  this.registerSessionHandlers(session);
545271
546487
  await this.refreshManagedImageReaderAvailability(session);
545272
546488
  await this.personalMemoryController.refresh();
546489
+ this.accountMemoryRuntime?.retryPending().catch(() => {});
545273
546490
  await this.syncRuntimeState(session);
545274
546491
  this.updateTerminalTitle();
545275
546492
  try {