negotium 0.6.17 → 0.7.0

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.
@@ -2053,12 +2053,12 @@ ${toolBuffer.join(`
2053
2053
  break;
2054
2054
  case "tool_use": {
2055
2055
  const u = ev;
2056
- toolBuffer.push(`<!-- Tool: ${u.name} ${truncate(JSON.stringify(u.input), 200)} -->`);
2056
+ toolBuffer.push(opts.formatToolUse?.(u) ?? `<!-- Tool: ${u.name} ${truncate(JSON.stringify(u.input), 200)} -->`);
2057
2057
  break;
2058
2058
  }
2059
2059
  case "tool_result": {
2060
2060
  const u = ev;
2061
- toolBuffer.push(`<!-- Tool result: ${truncate(u.content, 200)} -->`);
2061
+ toolBuffer.push(opts.formatToolResult?.(u) ?? `<!-- Tool result: ${truncate(u.content, 200)} -->`);
2062
2062
  break;
2063
2063
  }
2064
2064
  case "error": {
@@ -3001,7 +3001,7 @@ var init_codex = __esm(async () => {
3001
3001
  });
3002
3002
 
3003
3003
  // ../../packages/core/src/version.ts
3004
- var NEGOTIUM_VERSION = "0.6.17";
3004
+ var NEGOTIUM_VERSION = "0.7.0";
3005
3005
 
3006
3006
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
3007
3007
  import { spawn as spawn2 } from "child_process";
@@ -12123,8 +12123,117 @@ RULES:
12123
12123
  - Do NOT invent file paths or facts not present in the transcript.
12124
12124
  - Keep the entire summary under 1500 words.`, CHARS_PER_TEXT_TOKEN = 3.5, CHARS_PER_CJK_TOKEN = 0.9;
12125
12125
 
12126
- // ../../packages/core/src/storage/token-stats.ts
12126
+ // ../../packages/core/src/agents/compaction-tool-projection.ts
12127
12127
  import { createHash as createHash5 } from "crypto";
12128
+ function digest(value) {
12129
+ return createHash5("sha256").update(value).digest("hex").slice(0, 16);
12130
+ }
12131
+ function boundedEdges(value, edgeChars) {
12132
+ if (value.length <= edgeChars * 2)
12133
+ return value;
12134
+ const omitted = value.length - edgeChars * 2;
12135
+ return `${value.slice(0, edgeChars)}
12136
+ [\u2026 omitted ${omitted.toLocaleString()} chars \u2026]
12137
+ ${value.slice(-edgeChars)}`;
12138
+ }
12139
+ function quoted(value) {
12140
+ return JSON.stringify(value);
12141
+ }
12142
+ function salientLines(value) {
12143
+ const selected = [];
12144
+ let chars = 0;
12145
+ for (const line of value.split(`
12146
+ `)) {
12147
+ if (!SALIENT_LINE_RE.test(line))
12148
+ continue;
12149
+ const trimmed = line.trim();
12150
+ if (!trimmed || selected.includes(trimmed))
12151
+ continue;
12152
+ if (chars + trimmed.length + 1 > TOOL_OUTPUT_SALIENT_CHARS)
12153
+ break;
12154
+ selected.push(trimmed);
12155
+ chars += trimmed.length + 1;
12156
+ }
12157
+ return selected.join(`
12158
+ `);
12159
+ }
12160
+ function formatToolUse2(event) {
12161
+ const input = JSON.stringify(event.input ?? {});
12162
+ const projected = estimateTextTokens(input) <= MAX_TOOL_INPUT_TOKENS ? input : boundedEdges(input, TOOL_INPUT_EDGE_CHARS);
12163
+ return [
12164
+ "[Negotium tool use \u2014 quoted untrusted data]",
12165
+ `id_json: ${quoted(event.toolUseId ?? "unknown")}`,
12166
+ `name_json: ${quoted(event.name)}`,
12167
+ "quoted_untrusted_data: true",
12168
+ `input_json: ${quoted(projected)}`,
12169
+ "[/Negotium tool use]"
12170
+ ].join(`
12171
+ `);
12172
+ }
12173
+ function formatToolResult(event, hash, duplicate) {
12174
+ const metadata = event.metadata;
12175
+ const header = [
12176
+ "[Negotium tool result \u2014 quoted untrusted data]",
12177
+ `id_json: ${quoted(event.toolUseId)}`,
12178
+ `status: ${event.isError ? "error" : "success"}`,
12179
+ "quoted_untrusted_data: true",
12180
+ `hash: sha256:${hash}`,
12181
+ `original_bytes: ${metadata?.originalBytes ?? Buffer.byteLength(event.content)}`,
12182
+ ...metadata?.returnedBytes !== undefined ? [`returned_bytes: ${metadata.returnedBytes}`] : [],
12183
+ ...metadata?.omittedBytes !== undefined ? [`omitted_bytes: ${metadata.omittedBytes}`] : [],
12184
+ ...metadata?.outputPath ? [`output_path_json: ${quoted(metadata.outputPath)}`] : []
12185
+ ];
12186
+ if (duplicate) {
12187
+ return [
12188
+ ...header,
12189
+ "content: [duplicate of the most recent result with this hash]",
12190
+ "[/Negotium tool result]"
12191
+ ].join(`
12192
+ `);
12193
+ }
12194
+ if (estimateTextTokens(event.content) <= MAX_TOOL_OUTPUT_TOKENS) {
12195
+ return [...header, `content_json: ${quoted(event.content)}`, "[/Negotium tool result]"].join(`
12196
+ `);
12197
+ }
12198
+ const salient = salientLines(event.content);
12199
+ return [
12200
+ ...header,
12201
+ "content: [bounded projection; full output remains in the raw conversation log]",
12202
+ `head_tail_json: ${quoted(boundedEdges(event.content, TOOL_OUTPUT_EDGE_CHARS))}`,
12203
+ ...salient ? [`salient_lines_json: ${quoted(salient)}`] : [],
12204
+ "[/Negotium tool result]"
12205
+ ].join(`
12206
+ `);
12207
+ }
12208
+ function extractCompactionChatPairs(entries) {
12209
+ const remainingByHash = new Map;
12210
+ const hashByEvent = new WeakMap;
12211
+ for (const entry of entries) {
12212
+ if (entry.event.type !== "tool_result")
12213
+ continue;
12214
+ const hash = digest(entry.event.content);
12215
+ hashByEvent.set(entry.event, hash);
12216
+ remainingByHash.set(hash, (remainingByHash.get(hash) ?? 0) + 1);
12217
+ }
12218
+ return extractChatPairs(entries, {
12219
+ includeToolAnnotations: true,
12220
+ formatToolUse: formatToolUse2,
12221
+ formatToolResult: (event) => {
12222
+ const hash = hashByEvent.get(event) ?? digest(event.content);
12223
+ const remaining = Math.max(0, (remainingByHash.get(hash) ?? 1) - 1);
12224
+ remainingByHash.set(hash, remaining);
12225
+ return formatToolResult(event, hash, remaining > 0);
12226
+ }
12227
+ });
12228
+ }
12229
+ var MAX_TOOL_INPUT_TOKENS = 2000, MAX_TOOL_OUTPUT_TOKENS = 8000, TOOL_INPUT_EDGE_CHARS = 1000, TOOL_OUTPUT_EDGE_CHARS = 2000, TOOL_OUTPUT_SALIENT_CHARS = 2000, SALIENT_LINE_RE;
12230
+ var init_compaction_tool_projection = __esm(() => {
12231
+ init_shared();
12232
+ SALIENT_LINE_RE = /\b(error|failed?|failure|warning|exit(?:ed)?|expected|received|not found|denied|passed|tests?|assert|timeout|exception)\b/i;
12233
+ });
12234
+
12235
+ // ../../packages/core/src/storage/token-stats.ts
12236
+ import { createHash as createHash6 } from "crypto";
12128
12237
  import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync10 } from "fs";
12129
12238
  import { join as join21 } from "path";
12130
12239
  function emptyBucket() {
@@ -12139,7 +12248,7 @@ function emptyBucket() {
12139
12248
  }
12140
12249
  function tokenStatsFileId(userId) {
12141
12250
  const rawUserId = String(userId);
12142
- return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash5("sha256").update(rawUserId).digest("hex")}`;
12251
+ return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash6("sha256").update(rawUserId).digest("hex")}`;
12143
12252
  }
12144
12253
  function queriesPath(userId) {
12145
12254
  const fileId = tokenStatsFileId(userId);
@@ -12270,11 +12379,14 @@ var init_token_stats = __esm(async () => {
12270
12379
  // ../../packages/core/src/agents/idle-compact.ts
12271
12380
  function cancelIdleCompactForTopic(topicId) {
12272
12381
  const timer = timers2.get(topicId);
12273
- if (!timer)
12274
- return false;
12275
- clearTimeout(timer);
12382
+ const contextLimitTimer = contextLimitTimers.get(topicId);
12383
+ if (timer)
12384
+ clearTimeout(timer);
12385
+ if (contextLimitTimer)
12386
+ clearTimeout(contextLimitTimer);
12276
12387
  timers2.delete(topicId);
12277
- return true;
12388
+ contextLimitTimers.delete(topicId);
12389
+ return Boolean(timer || contextLimitTimer);
12278
12390
  }
12279
12391
  function envFlagEnabled2(name, fallback) {
12280
12392
  const raw = process.env[name]?.trim().toLowerCase();
@@ -12316,6 +12428,38 @@ function scheduleIdleCompactForTopic(topicId, userId) {
12316
12428
  timers2.set(topicId, timer);
12317
12429
  return "scheduled";
12318
12430
  }
12431
+ function scheduleContextLimitCompactForTopic(topicId, userId, contextTokens, contextWindow) {
12432
+ if (!idleCompactEnabled())
12433
+ return "disabled";
12434
+ if (!Number.isFinite(contextWindow) || contextWindow <= 0)
12435
+ return "below-threshold";
12436
+ const percent = contextTokens / contextWindow * 100;
12437
+ if (!Number.isFinite(percent) || percent < CONTEXT_LIMIT_COMPACT_PERCENT) {
12438
+ return "below-threshold";
12439
+ }
12440
+ const topic = getTopic(topicId);
12441
+ if (!topic)
12442
+ return "topic-not-found";
12443
+ if (!topic.agent)
12444
+ return "not-ai-invited";
12445
+ if (topic.aiMode === "mention")
12446
+ return "mention-only-channel";
12447
+ const existing = contextLimitTimers.get(topicId);
12448
+ if (existing)
12449
+ clearTimeout(existing);
12450
+ const retry = () => scheduleContextLimitCompactForTopic(topicId, userId, contextTokens, contextWindow);
12451
+ const timer = setTimeout(() => {
12452
+ contextLimitTimers.delete(topicId);
12453
+ runIdleCompactForTopic(topicId, userId, {
12454
+ minContextPercent: CONTEXT_LIMIT_COMPACT_PERCENT,
12455
+ reason: "context-limit-compact",
12456
+ onBusy: retry
12457
+ });
12458
+ }, DEFAULT_CONTEXT_LIMIT_DELAY_MS);
12459
+ timer.unref?.();
12460
+ contextLimitTimers.set(topicId, timer);
12461
+ return "scheduled";
12462
+ }
12319
12463
  async function runIdleCompactForTopic(topicId, userId, options = {}) {
12320
12464
  if (!idleCompactEnabled())
12321
12465
  return "disabled";
@@ -12354,7 +12498,7 @@ async function runIdleCompactForTopic(topicId, userId, options = {}) {
12354
12498
  return compactTopicSession(id, actorId, reason, { preemptive: false });
12355
12499
  });
12356
12500
  try {
12357
- const result = await compact(topicId, owner, "idle-compact");
12501
+ const result = await compact(topicId, owner, options.reason ?? "idle-compact");
12358
12502
  if (result.busy) {
12359
12503
  logger.debug({ topicId, percent: Math.round(percent) }, "idle-compact: topic became busy, rescheduling");
12360
12504
  if (options.onBusy)
@@ -12374,7 +12518,7 @@ async function runIdleCompactForTopic(topicId, userId, options = {}) {
12374
12518
  return "failed";
12375
12519
  }
12376
12520
  }
12377
- var DEFAULT_IDLE_DELAY_MS2, DEFAULT_MIN_CONTEXT_PERCENT = 50, timers2;
12521
+ var DEFAULT_IDLE_DELAY_MS2, DEFAULT_CONTEXT_LIMIT_DELAY_MS = 1000, CONTEXT_LIMIT_COMPACT_PERCENT = 90, DEFAULT_MIN_CONTEXT_PERCENT = 50, timers2, contextLimitTimers;
12378
12522
  var init_idle_compact = __esm(async () => {
12379
12523
  init_logger();
12380
12524
  await init_active_rooms();
@@ -12383,6 +12527,7 @@ var init_idle_compact = __esm(async () => {
12383
12527
  await init_token_stats();
12384
12528
  DEFAULT_IDLE_DELAY_MS2 = 6 * 60 * 60 * 1000;
12385
12529
  timers2 = new Map;
12530
+ contextLimitTimers = new Map;
12386
12531
  });
12387
12532
 
12388
12533
  // ../../packages/core/src/agents/topic-cleanup.ts
@@ -12907,11 +13052,13 @@ var init_runtime_turn_requests = __esm(async () => {
12907
13052
  // ../../packages/core/src/topics/session.ts
12908
13053
  var exports_session = {};
12909
13054
  __export(exports_session, {
13055
+ splitCompactionPairs: () => splitCompactionPairs,
12910
13056
  shouldUseCompactionLog: () => shouldUseCompactionLog,
12911
13057
  shouldCompactForkEntries: () => shouldCompactForkEntries,
12912
13058
  restartTopicSession: () => restartTopicSession,
12913
13059
  createCompactedRolloutEntries: () => createCompactedRolloutEntries,
12914
13060
  compactTopicSession: () => compactTopicSession,
13061
+ COMPACTION_RETAINED_TAIL_TOKENS: () => COMPACTION_RETAINED_TAIL_TOKENS,
12915
13062
  AUTO_FORK_COMPACTION_TOKENS: () => AUTO_FORK_COMPACTION_TOKENS
12916
13063
  });
12917
13064
  import { randomUUID as randomUUID11 } from "crypto";
@@ -13059,6 +13206,61 @@ The assistant response is the authoritative summary of all earlier context.` &&
13059
13206
  }
13060
13207
  return;
13061
13208
  }
13209
+ function withoutCompactionSentinels(entries) {
13210
+ const filtered = [];
13211
+ for (let index = 0;index < entries.length; index++) {
13212
+ const current2 = entries[index]?.event;
13213
+ const next = entries[index + 1]?.event;
13214
+ if (current2?.type === "user_message" && current2.synthetic === "compaction" && next?.type === "result") {
13215
+ index += 1;
13216
+ continue;
13217
+ }
13218
+ const entry = entries[index];
13219
+ if (entry)
13220
+ filtered.push(entry);
13221
+ }
13222
+ return filtered;
13223
+ }
13224
+ function pairTokens(pair) {
13225
+ return estimateConversationTokens([{ content: pair.userText }, { content: pair.assistantText }]);
13226
+ }
13227
+ function splitCompactionPairs(entries, retainedTailTokens = COMPACTION_RETAINED_TAIL_TOKENS) {
13228
+ const pairs = extractCompactionChatPairs(withoutCompactionSentinels(entries));
13229
+ let retainedStart = pairs.length;
13230
+ let retainedTokens = 0;
13231
+ for (let index = pairs.length - 1;index >= 0; index--) {
13232
+ const pair = pairs[index];
13233
+ if (!pair)
13234
+ continue;
13235
+ const tokens = pairTokens(pair);
13236
+ if (retainedTokens + tokens > retainedTailTokens)
13237
+ break;
13238
+ retainedTokens += tokens;
13239
+ retainedStart = index;
13240
+ }
13241
+ if (retainedStart === 0)
13242
+ return { summaryPairs: pairs, retainedPairs: [] };
13243
+ return {
13244
+ summaryPairs: pairs.slice(0, retainedStart),
13245
+ retainedPairs: pairs.slice(retainedStart)
13246
+ };
13247
+ }
13248
+ function retainedPairEntries(agent, pairs) {
13249
+ const entries = [];
13250
+ for (const pair of pairs) {
13251
+ const now = new Date().toISOString();
13252
+ entries.push({
13253
+ ts: now,
13254
+ agent,
13255
+ event: { type: "user_message", content: pair.userText }
13256
+ }, {
13257
+ ts: now,
13258
+ agent,
13259
+ event: { type: "result", content: pair.assistantText, stopReason: "end_turn" }
13260
+ });
13261
+ }
13262
+ return entries;
13263
+ }
13062
13264
  function fitCompactionChunk(text2, limit) {
13063
13265
  if (text2.length <= limit)
13064
13266
  return text2;
@@ -13072,7 +13274,7 @@ function fitCompactionChunk(text2, limit) {
13072
13274
  const tailChars = available - headChars;
13073
13275
  return `${text2.slice(0, headChars)}${marker}${text2.slice(-tailChars)}`;
13074
13276
  }
13075
- function buildCompactionSource(topicId, userId, entries, visibleMessages) {
13277
+ function buildCompactionSource(topicId, userId, entries, visibleMessages, providerPairs) {
13076
13278
  const sections = [];
13077
13279
  const previous = previousCompactedSummary(entries);
13078
13280
  if (previous)
@@ -13084,10 +13286,10 @@ ${previous}`);
13084
13286
  sections.push(`## Durable topic memory
13085
13287
  ${fitCompactionChunk(memory, COMPACTION_MEMORY_CHARS)}`);
13086
13288
  }
13087
- const rows = (visibleMessages ?? getAllMessagesForTopic(topicId)).filter((row) => row.author_id !== "system" && row.kind !== "system" && row.kind !== "tool" && !row.id.startsWith("tasks-") && row.text.trim());
13289
+ const rows = (previous ? [] : visibleMessages ?? getAllMessagesForTopic(topicId)).filter((row) => row.author_id !== "system" && row.kind !== "system" && row.kind !== "tool" && !row.id.startsWith("tasks-") && row.text.trim());
13088
13290
  const usedByContext = sections.reduce((sum, section) => sum + section.length + 2, 0);
13089
13291
  const conversationBudget = Math.max(0, COMPACTION_SOURCE_CHARS - usedByContext);
13090
- const pairs = extractChatPairs(entries);
13292
+ const pairs = providerPairs ?? extractCompactionChatPairs(entries);
13091
13293
  const hasVisibleRows = rows.length > 0;
13092
13294
  const providerBudget = pairs.length > 0 ? hasVisibleRows ? Math.floor(conversationBudget * 0.65) : conversationBudget : 0;
13093
13295
  const providerTranscript = [];
@@ -13400,12 +13602,14 @@ function shouldCompactForkEntries(entries, thresholdTokens = AUTO_FORK_COMPACTIO
13400
13602
  return estimateConversationTokens(messages) >= thresholdTokens;
13401
13603
  }
13402
13604
  async function createCompactedRolloutEntries(request, summarize = summarizeTopicContext) {
13403
- const source = buildCompactionSource(request.topicId, request.userId, request.entries, request.visibleMessages);
13605
+ const { summaryPairs, retainedPairs } = splitCompactionPairs(request.entries, request.retainedTailTokens);
13606
+ const source = buildCompactionSource(request.topicId, request.userId, request.entries, request.visibleMessages, summaryPairs);
13404
13607
  if (!source)
13405
13608
  throw new Error(`Nothing to compact in "${request.topicTitle}".`);
13406
13609
  const {
13407
13610
  entries: _entries,
13408
13611
  visibleMessages: _visibleMessages,
13612
+ retainedTailTokens: _retainedTailTokens,
13409
13613
  timeoutMs = shouldUseCompactionLog(source) ? COMPACTION_LOG_TIMEOUT_MS : COMPACTION_TIMEOUT_MS,
13410
13614
  summaryModel,
13411
13615
  summaryEffort,
@@ -13419,7 +13623,10 @@ async function createCompactedRolloutEntries(request, summarize = summarizeTopic
13419
13623
  }, summarize, timeoutMs)).trim();
13420
13624
  if (!summary)
13421
13625
  throw new Error("Context compaction returned an empty summary.");
13422
- return compactEntries(request.agent, summary.slice(0, COMPACTION_OUTPUT_CHARS));
13626
+ return [
13627
+ ...compactEntries(request.agent, summary.slice(0, COMPACTION_OUTPUT_CHARS)),
13628
+ ...retainedPairEntries(request.agent, retainedPairs)
13629
+ ];
13423
13630
  }
13424
13631
  async function cleanupNewRollout(agent, cwd, sessionId) {
13425
13632
  try {
@@ -13576,8 +13783,9 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
13576
13783
  maintenance.finish();
13577
13784
  }
13578
13785
  }
13579
- var RESET_TURN_WAIT_MS = 5000, RESET_MEMORY_ARCHIVE_WAIT_MS, COMPACTION_INLINE_CHARS = 1e5, COMPACTION_SOURCE_CHARS, COMPACTION_MEMORY_CHARS = 80000, COMPACTION_OUTPUT_CHARS = 30000, COMPACTION_TIMEOUT_MS, COMPACTION_LOG_TIMEOUT_MS, COMPACTION_LOG_MAX_CALLS = 12, COMPACTION_LOG_MAX_TOTAL_BYTES, COMPACTION_LOG_MAX_CHUNK_BYTES, COMPACT_CONTEXT_MARKER = "[Negotium compacted context]", AUTO_FORK_COMPACTION_TOKENS = 28000;
13786
+ var RESET_TURN_WAIT_MS = 5000, RESET_MEMORY_ARCHIVE_WAIT_MS, COMPACTION_INLINE_CHARS = 1e5, COMPACTION_SOURCE_CHARS, COMPACTION_MEMORY_CHARS = 80000, COMPACTION_OUTPUT_CHARS = 30000, COMPACTION_RETAINED_TAIL_TOKENS = 64000, COMPACTION_TIMEOUT_MS, COMPACTION_LOG_TIMEOUT_MS, COMPACTION_LOG_MAX_CALLS = 12, COMPACTION_LOG_MAX_TOTAL_BYTES, COMPACTION_LOG_MAX_CHUNK_BYTES, COMPACT_CONTEXT_MARKER = "[Negotium compacted context]", AUTO_FORK_COMPACTION_TOKENS = 28000;
13580
13787
  var init_session = __esm(async () => {
13788
+ init_compaction_tool_projection();
13581
13789
  await init_idle_archiver();
13582
13790
  await init_idle_compact();
13583
13791
  await init_agents();
@@ -13622,7 +13830,7 @@ __export(exports_derive, {
13622
13830
  TopicForkCompactionError: () => TopicForkCompactionError,
13623
13831
  TopicDeriveBusyError: () => TopicDeriveBusyError
13624
13832
  });
13625
- import { createHash as createHash6, randomUUID as randomUUID12 } from "crypto";
13833
+ import { createHash as createHash7, randomUUID as randomUUID12 } from "crypto";
13626
13834
  import { mkdirSync as mkdirSync14, rmSync as rmSync5, unlinkSync as unlinkSync13 } from "fs";
13627
13835
  function getTopics(opts = {}) {
13628
13836
  return listTopics(opts).filter((topic) => !isLegacySharedGeneral(topic.id));
@@ -13688,7 +13896,7 @@ function captureForkSnapshot(sourceTopicId, userId, topicTitle) {
13688
13896
  maxRowid: messageRows.at(-1)?.rowid ?? 0
13689
13897
  },
13690
13898
  active: isTopicRunning(sourceTopicId),
13691
- canonicalDigest: createHash6("sha256").update(entries.map((entry) => JSON.stringify(entry)).join(`
13899
+ canonicalDigest: createHash7("sha256").update(entries.map((entry) => JSON.stringify(entry)).join(`
13692
13900
  `)).digest("hex")
13693
13901
  };
13694
13902
  }
@@ -14227,7 +14435,7 @@ __export(exports_session_asks, {
14227
14435
  clearPendingAsk: () => clearPendingAsk,
14228
14436
  PENDING_ASK_TTL_MS: () => PENDING_ASK_TTL_MS
14229
14437
  });
14230
- import { createHash as createHash7 } from "crypto";
14438
+ import { createHash as createHash8 } from "crypto";
14231
14439
  import {
14232
14440
  closeSync as closeSync2,
14233
14441
  mkdirSync as mkdirSync16,
@@ -14241,15 +14449,15 @@ import {
14241
14449
  import { dirname as dirname14, join as join27 } from "path";
14242
14450
  function pendingAskDir(userId) {
14243
14451
  const rawUserId = String(userId);
14244
- const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash7("sha256").update(rawUserId).digest("hex")}`;
14452
+ const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash8("sha256").update(rawUserId).digest("hex")}`;
14245
14453
  return join27(resolveStorageSessionAsksDir(), safeUserId);
14246
14454
  }
14247
14455
  function encodeAskKey(key) {
14248
14456
  return JSON.stringify([key.from, key.to]);
14249
14457
  }
14250
14458
  function pendingAskPath(key) {
14251
- const digest = createHash7("sha256").update(encodeAskKey(key)).digest("hex");
14252
- return join27(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
14459
+ const digest2 = createHash8("sha256").update(encodeAskKey(key)).digest("hex");
14460
+ return join27(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest2}.pending`);
14253
14461
  }
14254
14462
  function v2PendingAskPath(key) {
14255
14463
  const encoded = Buffer.from(encodeAskKey(key), "utf8").toString("base64url");
@@ -16348,6 +16556,9 @@ ${JSON.stringify(event.input ?? {})}`);
16348
16556
  if (!silent) {
16349
16557
  scheduleIdleArchiveForTopic(topicId, execution?.actorUserId ?? userId);
16350
16558
  scheduleIdleCompactForTopic(topicId, execution?.actorUserId ?? userId);
16559
+ if (event.usage?.contextTokens !== undefined && event.usage.contextWindow !== undefined) {
16560
+ scheduleContextLimitCompactForTopic(topicId, execution?.actorUserId ?? userId, event.usage.contextTokens, event.usage.contextWindow);
16561
+ }
16351
16562
  hub.broadcastDone(topicId, queryId, event.usage ? {
16352
16563
  input: event.usage.inputTokens,
16353
16564
  output: event.usage.outputTokens,
@@ -19957,4 +20168,4 @@ export {
19957
20168
  DEFAULT_SELF_CONFIG_PRODUCT
19958
20169
  };
19959
20170
 
19960
- //# debugId=823FBA6C6CCA73FD64756E2164756E21
20171
+ //# debugId=5098AD5EB3D2D82464756E2164756E21