eve-hub 0.6.37 → 0.6.39

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # eve-hub
2
2
 
3
+ ## 0.6.39
4
+
5
+ ### Patch Changes
6
+
7
+ - The compact schedule reads each session's last input tokens and prompt-cache gaps from the hub's snapshot, and a compaction's report lines go to the schedule's thread.
8
+
9
+ ## 0.6.38
10
+
11
+ ### Patch Changes
12
+
13
+ - The Dash schedule picks eve's `decide` or `evaluate` by what the installed eve exports, so a workspace on eve 0.81 and one on the hosted bots' older eve both build.
14
+
3
15
  ## 0.6.37
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve-hub",
3
- "version": "0.6.37",
3
+ "version": "0.6.39",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Bot-side code shared by every hub agent: registry tools, the roster hook, the eve channel, the host sandbox and browser, and model helpers.",
6
6
  "type": "module",
package/schedules/dash.js CHANGED
@@ -6,12 +6,15 @@
6
6
  // (anthropic/claude-sonnet-5.5 through the AI SDK). The pass: runPass in
7
7
  // ./dash-pass.mjs.
8
8
  import { defineSchedule } from "eve/schedules";
9
- import { decide as evaluate } from "eve/ai";
9
+ import * as eveAi from "eve/ai";
10
10
  import { generateText } from "ai";
11
11
  import { createHub } from "./hub.mjs";
12
12
  import { modelClassify } from "./dash-classify.mjs";
13
13
  import { dashPass } from "./dash-pass.mjs";
14
14
  import { modelSummarize } from "./track-summaries.mjs";
15
+ // eve 0.80 renamed `evaluate` to `decide`. The Mac bots run 0.81; the hosted bots' eve build is a
16
+ // 0.69-based branch with `evaluate` only, and a named import of the missing one fails that build.
17
+ const evaluate = eveAi.decide ?? eveAi.evaluate;
15
18
  export default defineSchedule({
16
19
  cron: "*/8 * * * *",
17
20
  async run() {
@@ -1,7 +1,7 @@
1
1
  // The decisions behind main's compact schedule (schedules/compact.ts), pure:
2
2
  // each takes the registry's /api/state snapshot (`snap`), the schedule's
3
3
  // and the time. No I/O here; schedules/hub.mjs does that. The report lines
4
- // for the compactions themselves are the hub's (registry/compact-report.mjs).
4
+ // for the compactions themselves are the hub's (hosted-hub/src/domain/compact-report.mjs).
5
5
  //
6
6
  // Plain JS on purpose: the schedule (TypeScript, bundled by eve) and the
7
7
  // tests (plain node) import the same module.
package/world.mjs CHANGED
@@ -442,14 +442,16 @@ var turnId = (session, chunkIndex) => `trn_${session}_${chunkIndex}`;
442
442
 
443
443
  // ../../hosted-hub/src/store/events.ts
444
444
  function eventStatements(threadId2, event, text, at, id = eventId(), only) {
445
+ const expr = (v) => typeof v === "string" ? { sql: "?", args: [v] } : "sql" in v && "args" in v ? v : { sql: "?", args: [JSON.stringify(v)] };
446
+ const [t, e] = [expr(text), expr(event)];
445
447
  return [
446
448
  s(
447
- `INSERT OR IGNORE INTO messages (id, thread_id, author, author_kind, text, created_at, event) SELECT ?, ?, 'system', 'event', ?, ?, ? WHERE ${only?.sql ?? "1"}`,
449
+ `INSERT OR IGNORE INTO messages (id, thread_id, author, author_kind, text, created_at, event) SELECT ?, ?, 'system', 'event', ${t.sql}, ?, ${e.sql} WHERE ${only?.sql ?? "1"}`,
448
450
  id,
449
451
  threadId2,
450
- text,
452
+ ...t.args,
451
453
  at,
452
- JSON.stringify(event),
454
+ ...e.args,
453
455
  ...only?.args ?? []
454
456
  ),
455
457
  s(`INSERT INTO log (thread_id,type,data,at) SELECT ?, 'message.created', ?, ? WHERE changes() > 0`, threadId2, JSON.stringify({ threadId: threadId2, messageId: id, author: "system", authorKind: "event" }), at)
@@ -467,11 +469,11 @@ var PARTICIPANTS = (thread, except = "''") => `SELECT DISTINCT p.bot FROM (
467
469
  AND json_extract(l.event, '$.kind') = 'leave' AND json_extract(l.event, '$.agent') = p.bot), -1)`;
468
470
  var hasJoins = (threadId2) => !threadId2.startsWith("dm-") && !threadId2.startsWith("sch-");
469
471
  function routingStatements(messageId2, threadId2, bots, now, { by, joins }, held = {}, steer = false) {
470
- const quiet = !joins || !hasJoins(threadId2);
472
+ const quiet2 = !joins || !hasJoins(threadId2);
471
473
  const fresh = "EXISTS (SELECT 1 FROM messages WHERE id = ?)";
472
474
  return [
473
475
  ...bots.flatMap((bot) => [
474
- ...quiet ? [] : eventStatements(
476
+ ...quiet2 ? [] : eventStatements(
475
477
  threadId2,
476
478
  { kind: "join", agent: bot, by, message: messageId2 },
477
479
  `@${bot} joined${by !== bot ? ` (added by @${by})` : ""}`,
@@ -545,7 +547,7 @@ function addUsage(bucket, usage = {}) {
545
547
  var HOURS_KEPT_MS = 35 * 24 * 36e5;
546
548
 
547
549
  // ../../hosted-hub/src/store/usage.ts
548
- var STEP_INSERT = "INSERT OR IGNORE INTO usage_steps (session_id, sequence, step_index, at, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_usd, turn_id)";
550
+ var STEP_INSERT = "INSERT OR IGNORE INTO usage_steps (session_id, sequence, step_index, at, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_usd, turn_id, model)";
549
551
  function stepValues(sessionId2, step) {
550
552
  const b = addUsage(emptyBucket(), step.usage);
551
553
  return [sessionId2, step.sequence, step.stepIndex, Date.parse(step.at), b.inputTokens, b.outputTokens, b.cacheReadTokens, b.cacheWriteTokens, b.costUsd];
@@ -568,10 +570,10 @@ function codeRanges(text) {
568
570
  const open3 = lines[i].text.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
569
571
  if (!open3 || open3[1][0] === "`" && open3[2].includes("`")) continue;
570
572
  const close = new RegExp(`^ {0,3}${open3[1][0] === "`" ? "`" : "~"}{${open3[1].length},}\\s*$`);
571
- const j = lines.findIndex((l, k) => k > i && close.test(l.text));
573
+ const j = lines.findIndex((l, k2) => k2 > i && close.test(l.text));
572
574
  if (j < 0) continue;
573
575
  ranges.push([lines[i].start, lines[j].end]);
574
- for (let k = i; k <= j; k++) fenced.add(k);
576
+ for (let k2 = i; k2 <= j; k2++) fenced.add(k2);
575
577
  i = j;
576
578
  }
577
579
  let para = [];
@@ -589,7 +591,7 @@ function codeRanges(text) {
589
591
  n--;
590
592
  if (!n) continue;
591
593
  }
592
- const j = runs.findIndex((r, k) => k > i && r.n === n);
594
+ const j = runs.findIndex((r, k2) => k2 > i && r.n === n);
593
595
  if (j < 0) continue;
594
596
  ranges.push([from + at, from + runs[j].at + n]);
595
597
  i = j;
@@ -629,7 +631,7 @@ var UP = `up(session_id, parent) AS (
629
631
  SELECT session_id, parent FROM subagent_links WHERE session_id = ?
630
632
  UNION SELECT c.session_id, c.parent FROM subagent_links c JOIN up ON c.session_id = up.parent)`;
631
633
  var ROOT = "SELECT t.id, t.thread_id, t.bot FROM up JOIN turns t ON t.id = up.parent";
632
- var subagentStep = (sessionId2, step) => s(`WITH RECURSIVE ${UP} ${STEP_INSERT} SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, (SELECT id FROM (${ROOT}))`, sessionId2, ...stepValues(sessionId2, step));
634
+ var subagentStep = (sessionId2, step) => s(`WITH RECURSIVE ${UP} ${STEP_INSERT} SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, (SELECT id FROM (${ROOT})), NULL`, sessionId2, ...stepValues(sessionId2, step));
633
635
  var rootLog = (sessionId2, type, at) => s(`WITH RECURSIVE ${UP} INSERT INTO log (thread_id, type, data, at)
634
636
  SELECT thread_id, ?, json_object('threadId', thread_id, 'agent', bot, 'turnId', id), ? FROM (${ROOT})`, sessionId2, type, at);
635
637
  function linkStatements(sessionId2, parent, callId) {
@@ -1400,7 +1402,7 @@ function assert(_) {
1400
1402
  }
1401
1403
  function getEnumValues(entries) {
1402
1404
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
1403
- const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
1405
+ const values = Object.entries(entries).filter(([k2, _]) => numericValues.indexOf(+k2) === -1).map(([_, v]) => v);
1404
1406
  return values;
1405
1407
  }
1406
1408
  function joinValues(array3, separator = "|") {
@@ -1744,8 +1746,8 @@ function stringifyPrimitive(value) {
1744
1746
  return `${value}`;
1745
1747
  }
1746
1748
  function optionalKeys(shape) {
1747
- return Object.keys(shape).filter((k) => {
1748
- return shape[k]._zod.optin !== void 0 && shape[k]._zod.optout === "optional";
1749
+ return Object.keys(shape).filter((k2) => {
1750
+ return shape[k2]._zod.optin !== void 0 && shape[k2]._zod.optout === "optional";
1749
1751
  });
1750
1752
  }
1751
1753
  var NUMBER_FORMAT_RANGES = /* @__PURE__ */ (() => ({
@@ -1923,10 +1925,10 @@ function finalizeIssue(iss, ctx, config3) {
1923
1925
  const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : void 0;
1924
1926
  const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config3.customError?.(iss)) ?? unwrapMessage(config3.localeError?.(iss)) ?? "Invalid input";
1925
1927
  const full = {};
1926
- for (const k of Object.keys(iss)) {
1927
- if (k === "inst" || k === "schema" || k === "continue" || k === "input" || k === "__proto__")
1928
+ for (const k2 of Object.keys(iss)) {
1929
+ if (k2 === "inst" || k2 === "schema" || k2 === "continue" || k2 === "input" || k2 === "__proto__")
1928
1930
  continue;
1929
- full[k] = iss[k];
1931
+ full[k2] = iss[k2];
1930
1932
  }
1931
1933
  full.path ?? (full.path = []);
1932
1934
  full.message = message;
@@ -1949,14 +1951,14 @@ function codePointLength(str) {
1949
1951
  const units = str.length;
1950
1952
  if (!highSurrogate.test(str))
1951
1953
  return units;
1952
- let count = units;
1954
+ let count2 = units;
1953
1955
  for (let i = 0; i < units - 1; i++) {
1954
1956
  if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
1955
- count--;
1957
+ count2--;
1956
1958
  i++;
1957
1959
  }
1958
1960
  }
1959
- return count;
1961
+ return count2;
1960
1962
  }
1961
1963
  function getLengthableOrigin(input2) {
1962
1964
  if (Array.isArray(input2))
@@ -1999,8 +2001,8 @@ function issue(...args) {
1999
2001
  return { ...iss };
2000
2002
  }
2001
2003
  function cleanEnum(obj) {
2002
- return Object.entries(obj).filter(([k, _]) => {
2003
- return Number.isNaN(Number.parseInt(k, 10));
2004
+ return Object.entries(obj).filter(([k2, _]) => {
2005
+ return Number.isNaN(Number.parseInt(k2, 10));
2004
2006
  }).map((el) => el[1]);
2005
2007
  }
2006
2008
  function base64ToUint8Array(base644) {
@@ -2222,11 +2224,11 @@ function $constructor(name, initializer5, proto, params) {
2222
2224
  }
2223
2225
  }
2224
2226
  const proto2 = _.prototype;
2225
- for (const k in proto2) {
2226
- if (!Object.prototype.hasOwnProperty.call(proto2, k))
2227
+ for (const k2 in proto2) {
2228
+ if (!Object.prototype.hasOwnProperty.call(proto2, k2))
2227
2229
  continue;
2228
- if (!(k in inst)) {
2229
- inst[k] = proto2[k].bind(inst);
2230
+ if (!(k2 in inst)) {
2231
+ inst[k2] = proto2[k2].bind(inst);
2230
2232
  }
2231
2233
  }
2232
2234
  }
@@ -4188,9 +4190,9 @@ function normalizeDef(def) {
4188
4190
  const ownSymbols = Object.getOwnPropertySymbols(def.shape);
4189
4191
  const symbolKeys = ownSymbols.length ? ownSymbols : NO_SYMBOL_KEYS;
4190
4192
  const allKeys = symbolKeys.length ? [...keys, ...symbolKeys] : keys;
4191
- for (const k of allKeys) {
4192
- if (!def.shape?.[k]?._zod?.traits?.has("$ZodType")) {
4193
- throw new Error(`Invalid element at key "${String(k)}": expected a Zod schema`);
4193
+ for (const k2 of allKeys) {
4194
+ if (!def.shape?.[k2]?._zod?.traits?.has("$ZodType")) {
4195
+ throw new Error(`Invalid element at key "${String(k2)}": expected a Zod schema`);
4194
4196
  }
4195
4197
  }
4196
4198
  const okeys = optionalKeys(def.shape);
@@ -4339,12 +4341,12 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
4339
4341
  const normalized = _normalized.value;
4340
4342
  const syms = normalized.symbolKeys;
4341
4343
  const doc = new Doc(["payload", "ctx"], { shape, inst, memo: memo3, syms });
4342
- const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
4343
- const prefixStr = (id, k) => `
4344
+ const parseStr = (k2) => `shape[${k2}]._zod.run({ value: input[${k2}], issues: [] }, ctx)`;
4345
+ const prefixStr = (id, k2) => `
4344
4346
  let ${id}_ab = false;
4345
4347
  for (let i = 0; i < ${id}.issues.length; i++) {
4346
4348
  const iss = ${id}.issues[i];
4347
- iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
4349
+ iss.path = iss.path ? [${k2}, ...iss.path] : [${k2}];
4348
4350
  payload.issues.push(iss);
4349
4351
  if (iss.continue !== true) ${id}_ab = true;
4350
4352
  }
@@ -4363,23 +4365,23 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
4363
4365
  if (key === "__proto__")
4364
4366
  continue;
4365
4367
  const id = ids[key];
4366
- const k = typeof key === "symbol" ? `syms[${syms.indexOf(key)}]` : esc(key);
4367
- const isPresent = `${k} in input`;
4368
+ const k2 = typeof key === "symbol" ? `syms[${syms.indexOf(key)}]` : esc(key);
4369
+ const isPresent = `${k2} in input`;
4368
4370
  const schema = shape[key];
4369
4371
  const optin = schema?._zod?.optin;
4370
4372
  const isOptionalIn = optin !== void 0;
4371
4373
  const isOptionalOut = schema?._zod?.optout === "optional";
4372
- doc.write(`const ${id} = ${parseStr(k)};`);
4374
+ doc.write(`const ${id} = ${parseStr(k2)};`);
4373
4375
  if (isOptionalIn && isOptionalOut) {
4374
4376
  const assign = optin === "optional" ? `${id}_present` : `${id}.value !== undefined || ${id}_present`;
4375
4377
  doc.write(`
4376
4378
  const ${id}_present = ${isPresent};
4377
4379
  if (!${id}.issues.length || ${id}_present) {
4378
- if (${id}.issues.length) {${prefixStr(id, k)}
4380
+ if (${id}.issues.length) {${prefixStr(id, k2)}
4379
4381
  }
4380
4382
 
4381
4383
  if (${assign}) {
4382
- newResult[${k}] = ${id}.value;
4384
+ newResult[${k2}] = ${id}.value;
4383
4385
  }
4384
4386
  }
4385
4387
 
@@ -4387,14 +4389,14 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
4387
4389
  } else if (!isOptionalIn) {
4388
4390
  doc.write(`
4389
4391
  const ${id}_present = ${isPresent};
4390
- if (${id}.issues.length) {${prefixStr(id, k)}
4392
+ if (${id}.issues.length) {${prefixStr(id, k2)}
4391
4393
  }
4392
4394
  if (!${id}_present && !${id}.issues.length) {
4393
4395
  payload.issues.push({
4394
4396
  code: "invalid_type",
4395
4397
  expected: "nonoptional",
4396
4398
  input: undefined,
4397
- path: [${k}]
4399
+ path: [${k2}]
4398
4400
  });
4399
4401
  if (ctx && ctx.abortEarly) {
4400
4402
  payload.value = newResult;
@@ -4403,21 +4405,21 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
4403
4405
  }
4404
4406
 
4405
4407
  if (${id}_present) {
4406
- newResult[${k}] = ${id}.value;
4408
+ newResult[${k2}] = ${id}.value;
4407
4409
  }
4408
4410
 
4409
4411
  `);
4410
4412
  } else {
4411
4413
  doc.write(`
4412
- if (${id}.issues.length) {${prefixStr(id, k)}
4414
+ if (${id}.issues.length) {${prefixStr(id, k2)}
4413
4415
  }
4414
4416
  `);
4415
4417
  if (optin === "defaulted") {
4416
- doc.write(`newResult[${k}] = ${id}.value;`);
4418
+ doc.write(`newResult[${k2}] = ${id}.value;`);
4417
4419
  } else {
4418
4420
  doc.write(`
4419
4421
  if (${id}.value !== undefined || ${isPresent}) {
4420
- newResult[${k}] = ${id}.value;
4422
+ newResult[${k2}] = ${id}.value;
4421
4423
  }
4422
4424
  `);
4423
4425
  }
@@ -4623,12 +4625,12 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
4623
4625
  throw new Error(`Invalid discriminated union option at index "${zod.def.options.indexOf(option)}"`);
4624
4626
  if (pv[zod.def.discriminator]?.has(void 0))
4625
4627
  undefinedCount++;
4626
- for (const [k, v] of Object.entries(pv)) {
4627
- if (!Object.prototype.hasOwnProperty.call(propValues, k)) {
4628
- assignProp(propValues, k, /* @__PURE__ */ new Set());
4628
+ for (const [k2, v] of Object.entries(pv)) {
4629
+ if (!Object.prototype.hasOwnProperty.call(propValues, k2)) {
4630
+ assignProp(propValues, k2, /* @__PURE__ */ new Set());
4629
4631
  }
4630
4632
  for (const val of v) {
4631
- propValues[k].add(val);
4633
+ propValues[k2].add(val);
4632
4634
  }
4633
4635
  }
4634
4636
  }
@@ -4748,17 +4750,17 @@ function handleIntersectionResults(result, left, right) {
4748
4750
  unrecIssue ?? (unrecIssue = iss);
4749
4751
  keys = iss.keys;
4750
4752
  } else if (iss.code === "invalid_key" && iss.origin === "record" && iss.path?.length === 1) {
4751
- const k = String(iss.path[0]);
4752
- if (!keyIssues.has(k))
4753
- keyIssues.set(k, iss);
4754
- keys = [k];
4753
+ const k2 = String(iss.path[0]);
4754
+ if (!keyIssues.has(k2))
4755
+ keyIssues.set(k2, iss);
4756
+ keys = [k2];
4755
4757
  } else {
4756
4758
  return false;
4757
4759
  }
4758
- for (const k of keys) {
4759
- if (!unrecKeys.has(k))
4760
- unrecKeys.set(k, {});
4761
- unrecKeys.get(k)[side] = true;
4760
+ for (const k2 of keys) {
4761
+ if (!unrecKeys.has(k2))
4762
+ unrecKeys.set(k2, {});
4763
+ unrecKeys.get(k2)[side] = true;
4762
4764
  }
4763
4765
  return true;
4764
4766
  };
@@ -4770,14 +4772,14 @@ function handleIntersectionResults(result, left, right) {
4770
4772
  if (!collect(iss, "r"))
4771
4773
  result.issues.push(iss);
4772
4774
  }
4773
- const bothKeys = [...unrecKeys].filter(([, f]) => f.l && f.r).map(([k]) => k);
4775
+ const bothKeys = [...unrecKeys].filter(([, f]) => f.l && f.r).map(([k2]) => k2);
4774
4776
  if (bothKeys.length) {
4775
- const aggregated = unrecIssue ? bothKeys.filter((k) => unrecIssue.keys.includes(k)) : [];
4777
+ const aggregated = unrecIssue ? bothKeys.filter((k2) => unrecIssue.keys.includes(k2)) : [];
4776
4778
  if (aggregated.length)
4777
4779
  result.issues.push({ ...unrecIssue, keys: aggregated });
4778
- for (const k of bothKeys) {
4779
- if (!aggregated.includes(k) && keyIssues.has(k))
4780
- result.issues.push(keyIssues.get(k));
4780
+ for (const k2 of bothKeys) {
4781
+ if (!aggregated.includes(k2) && keyIssues.has(k2))
4782
+ result.issues.push(keyIssues.get(k2));
4781
4783
  }
4782
4784
  }
4783
4785
  const merged = mergeValues(left.value, right.value);
@@ -5187,7 +5189,7 @@ var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
5187
5189
  const valuesSet = new Set(values);
5188
5190
  inst._zod.values = valuesSet;
5189
5191
  defineLazyInternal(inst, "pattern", (zod) => {
5190
- const patternValues = getEnumValues(zod.def.entries).filter((k) => propertyKeyTypes.has(typeof k));
5192
+ const patternValues = getEnumValues(zod.def.entries).filter((k2) => propertyKeyTypes.has(typeof k2));
5191
5193
  return new RegExp(patternValues.length ? `^(${patternValues.map((o) => escapeRegex(o.toString())).join("|")})$` : "^[^\\s\\S]$");
5192
5194
  });
5193
5195
  inst._zod.parse = (payload, _ctx) => {
@@ -6339,8 +6341,8 @@ function az_default() {
6339
6341
  }
6340
6342
 
6341
6343
  // ../../hosted-hub/node_modules/zod/v4/locales/be.js
6342
- function getBelarusianPlural(count, one, few, many) {
6343
- const absCount = Math.abs(count);
6344
+ function getBelarusianPlural(count2, one, few, many) {
6345
+ const absCount = Math.abs(count2);
6344
6346
  const lastDigit = absCount % 10;
6345
6347
  const lastTwoDigits = absCount % 100;
6346
6348
  if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
@@ -8987,8 +8989,8 @@ function hu_default() {
8987
8989
  }
8988
8990
 
8989
8991
  // ../../hosted-hub/node_modules/zod/v4/locales/hy.js
8990
- function getArmenianPlural(count, one, many) {
8991
- return Math.abs(count) === 1 ? one : many;
8992
+ function getArmenianPlural(count2, one, many) {
8993
+ return Math.abs(count2) === 1 ? one : many;
8992
8994
  }
8993
8995
  function withDefiniteArticle(word) {
8994
8996
  if (!word)
@@ -11726,8 +11728,8 @@ function ro_default() {
11726
11728
  }
11727
11729
 
11728
11730
  // ../../hosted-hub/node_modules/zod/v4/locales/ru.js
11729
- function getRussianPlural(count, one, few, many) {
11730
- const absCount = Math.abs(count);
11731
+ function getRussianPlural(count2, one, few, many) {
11732
+ const absCount = Math.abs(count2);
11731
11733
  const lastDigit = absCount % 10;
11732
11734
  const lastTwoDigits = absCount % 100;
11733
11735
  if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
@@ -13830,8 +13832,8 @@ function compileChild(doc, ctx, schema, accessor, needsValue = true) {
13830
13832
  doc.content.length = contentLen;
13831
13833
  if (ctx.constants.size > constantCount) {
13832
13834
  const trailing = Array.from(ctx.constants.keys()).slice(constantCount);
13833
- for (const k of trailing)
13834
- ctx.constants.delete(k);
13835
+ for (const k2 of trailing)
13836
+ ctx.constants.delete(k2);
13835
13837
  }
13836
13838
  ctx.constantCounter = constantCounter;
13837
13839
  ctx.varCounter = varCounter;
@@ -14427,8 +14429,8 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
14427
14429
  const keys = Object.keys(shape);
14428
14430
  const symbolKeys = Object.getOwnPropertySymbols(shape);
14429
14431
  const allKeys = symbolKeys.length ? [...keys, ...symbolKeys] : keys;
14430
- const keyExpr = (k) => typeof k === "symbol" ? addConstant(ctx, k) : esc(k);
14431
- const propKey = (k) => typeof k === "symbol" ? `[${keyExpr(k)}]` : esc(k);
14432
+ const keyExpr = (k2) => typeof k2 === "symbol" ? addConstant(ctx, k2) : esc(k2);
14433
+ const propKey = (k2) => typeof k2 === "symbol" ? `[${keyExpr(k2)}]` : esc(k2);
14432
14434
  const propShape = shape;
14433
14435
  if (keys.includes("__proto__")) {
14434
14436
  throw new ZodCompileUnsupportedError('object shape key "__proto__"');
@@ -14472,7 +14474,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
14472
14474
  if (catchall) {
14473
14475
  const catchallType = catchall._zod.def.type;
14474
14476
  if (catchallType === "never") {
14475
- const condition = keys.map((k) => `k !== ${esc(k)}`).join(" && ") || "true";
14477
+ const condition = keys.map((k2) => `k !== ${esc(k2)}`).join(" && ") || "true";
14476
14478
  doc.write(`for (const k in ${accessor}) {`);
14477
14479
  doc.indented((d) => {
14478
14480
  d.write(`if (${condition}) return INVALID;`);
@@ -14485,7 +14487,7 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
14485
14487
  }
14486
14488
  }
14487
14489
  const outputVar = newVar(ctx);
14488
- const hasConditionalKeys = allKeys.some((k) => mayOmitUndefined(propShape[k]) || dropsWhenAbsent(propShape[k]));
14490
+ const hasConditionalKeys = allKeys.some((k2) => mayOmitUndefined(propShape[k2]) || dropsWhenAbsent(propShape[k2]));
14489
14491
  if (!buildsValue) {
14490
14492
  if (unknownKeysMode === "schema") {
14491
14493
  const knownSet = keys.length > 0 ? addConstant(ctx, new Set(keys)) : null;
@@ -14503,16 +14505,16 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
14503
14505
  return null;
14504
14506
  }
14505
14507
  if (!hasConditionalKeys) {
14506
- const propLiterals = allKeys.map((k) => `${propKey(k)}: ${propOutputs.get(k)}`).join(", ");
14508
+ const propLiterals = allKeys.map((k2) => `${propKey(k2)}: ${propOutputs.get(k2)}`).join(", ");
14507
14509
  doc.write(`const ${outputVar} = { ${propLiterals} };`);
14508
14510
  } else {
14509
14511
  doc.write(`const ${outputVar} = {};`);
14510
- for (const k of allKeys) {
14511
- const kx = keyExpr(k);
14512
- const out = propOutputs.get(k);
14513
- if (dropsWhenAbsent(propShape[k])) {
14512
+ for (const k2 of allKeys) {
14513
+ const kx = keyExpr(k2);
14514
+ const out = propOutputs.get(k2);
14515
+ if (dropsWhenAbsent(propShape[k2])) {
14514
14516
  doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
14515
- } else if (mayOmitUndefined(propShape[k])) {
14517
+ } else if (mayOmitUndefined(propShape[k2])) {
14516
14518
  doc.write(`if (${out} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out};`);
14517
14519
  } else {
14518
14520
  doc.write(`${outputVar}[${kx}] = ${out};`);
@@ -16618,13 +16620,13 @@ function foldIntersection(json2) {
16618
16620
  for (const key of FOLDABLE_KEYS)
16619
16621
  if (key in json2)
16620
16622
  return;
16621
- const unions = allOf.filter((m) => UNION_KEYS.some((k) => Array.isArray(m[k])));
16623
+ const unions = allOf.filter((m) => UNION_KEYS.some((k2) => Array.isArray(m[k2])));
16622
16624
  let folded = null;
16623
16625
  if (!unions.length) {
16624
16626
  folded = foldObjects(allOf);
16625
16627
  } else {
16626
16628
  const union3 = unions[0];
16627
- const keyword = UNION_KEYS.find((k) => Array.isArray(union3[k]));
16629
+ const keyword = UNION_KEYS.find((k2) => Array.isArray(union3[k2]));
16628
16630
  if (Object.keys(union3).length !== 1)
16629
16631
  return;
16630
16632
  const rest = allOf.filter((m) => m !== union3);
@@ -19672,11 +19674,11 @@ function canonicalKey(value, seen) {
19672
19674
  }
19673
19675
  const keys = Object.keys(value).sort();
19674
19676
  const parts = [];
19675
- for (const k of keys) {
19676
- const key = canonicalKey(value[k], seen);
19677
+ for (const k2 of keys) {
19678
+ const key = canonicalKey(value[k2], seen);
19677
19679
  if (key === null)
19678
19680
  return null;
19679
- parts.push(`${k.length}:${k}=${key}`);
19681
+ parts.push(`${k2.length}:${k2}=${key}`);
19680
19682
  }
19681
19683
  return `o${parts.length}:{${parts.join(",")}}`;
19682
19684
  } finally {
@@ -20250,11 +20252,11 @@ function visit(schema, fnOrHandlers) {
20250
20252
  const keys = Object.keys(oldShape);
20251
20253
  let changed = false;
20252
20254
  const newShape = {};
20253
- for (const k of keys) {
20254
- const mapped = run(oldShape[k]);
20255
- if (mapped !== oldShape[k])
20255
+ for (const k2 of keys) {
20256
+ const mapped = run(oldShape[k2]);
20257
+ if (mapped !== oldShape[k2])
20256
20258
  changed = true;
20257
- newShape[k] = mapped;
20259
+ newShape[k2] = mapped;
20258
20260
  }
20259
20261
  let newCatchall = def.catchall;
20260
20262
  if (def.catchall) {
@@ -20534,7 +20536,7 @@ function assert2(_) {
20534
20536
  }
20535
20537
  function getEnumValues2(entries) {
20536
20538
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
20537
- const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
20539
+ const values = Object.entries(entries).filter(([k2, _]) => numericValues.indexOf(+k2) === -1).map(([_, v]) => v);
20538
20540
  return values;
20539
20541
  }
20540
20542
  function joinValues2(array3, separator = "|") {
@@ -20824,8 +20826,8 @@ function stringifyPrimitive2(value) {
20824
20826
  return `${value}`;
20825
20827
  }
20826
20828
  function optionalKeys2(shape) {
20827
- return Object.keys(shape).filter((k) => {
20828
- return shape[k]._zod.optin !== void 0 && shape[k]._zod.optout === "optional";
20829
+ return Object.keys(shape).filter((k2) => {
20830
+ return shape[k2]._zod.optin !== void 0 && shape[k2]._zod.optout === "optional";
20829
20831
  });
20830
20832
  }
20831
20833
  var NUMBER_FORMAT_RANGES2 = /* @__PURE__ */ (() => ({
@@ -21084,14 +21086,14 @@ function codePointLength2(str) {
21084
21086
  const units = str.length;
21085
21087
  if (!highSurrogate2.test(str))
21086
21088
  return units;
21087
- let count = units;
21089
+ let count2 = units;
21088
21090
  for (let i = 0; i < units - 1; i++) {
21089
21091
  if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
21090
- count--;
21092
+ count2--;
21091
21093
  i++;
21092
21094
  }
21093
21095
  }
21094
- return count;
21096
+ return count2;
21095
21097
  }
21096
21098
  function getLengthableOrigin2(input2) {
21097
21099
  if (Array.isArray(input2))
@@ -21134,8 +21136,8 @@ function issue2(...args) {
21134
21136
  return { ...iss };
21135
21137
  }
21136
21138
  function cleanEnum2(obj) {
21137
- return Object.entries(obj).filter(([k, _]) => {
21138
- return Number.isNaN(Number.parseInt(k, 10));
21139
+ return Object.entries(obj).filter(([k2, _]) => {
21140
+ return Number.isNaN(Number.parseInt(k2, 10));
21139
21141
  }).map((el) => el[1]);
21140
21142
  }
21141
21143
  function base64ToUint8Array2(base644) {
@@ -21338,11 +21340,11 @@ function $constructor2(name, initializer5, proto, params) {
21338
21340
  }
21339
21341
  }
21340
21342
  const proto2 = _.prototype;
21341
- for (const k in proto2) {
21342
- if (!Object.prototype.hasOwnProperty.call(proto2, k))
21343
+ for (const k2 in proto2) {
21344
+ if (!Object.prototype.hasOwnProperty.call(proto2, k2))
21343
21345
  continue;
21344
- if (!(k in inst)) {
21345
- inst[k] = proto2[k].bind(inst);
21346
+ if (!(k2 in inst)) {
21347
+ inst[k2] = proto2[k2].bind(inst);
21346
21348
  }
21347
21349
  }
21348
21350
  }
@@ -22726,9 +22728,9 @@ function normalizeDef2(def) {
22726
22728
  const ownSymbols = Object.getOwnPropertySymbols(def.shape);
22727
22729
  const symbolKeys = ownSymbols.length ? ownSymbols : NO_SYMBOL_KEYS2;
22728
22730
  const allKeys = symbolKeys.length ? [...keys, ...symbolKeys] : keys;
22729
- for (const k of allKeys) {
22730
- if (!def.shape?.[k]?._zod?.traits?.has("$ZodType")) {
22731
- throw new Error(`Invalid element at key "${String(k)}": expected a Zod schema`);
22731
+ for (const k2 of allKeys) {
22732
+ if (!def.shape?.[k2]?._zod?.traits?.has("$ZodType")) {
22733
+ throw new Error(`Invalid element at key "${String(k2)}": expected a Zod schema`);
22732
22734
  }
22733
22735
  }
22734
22736
  const okeys = optionalKeys2(def.shape);
@@ -22868,11 +22870,11 @@ var $ZodObjectJIT2 = /* @__PURE__ */ $constructor2("$ZodObjectJIT", (inst, def)
22868
22870
  const normalized = _normalized.value;
22869
22871
  const syms = normalized.symbolKeys;
22870
22872
  const doc = new Doc2(["payload", "ctx"], { shape, inst, memo: memo3, syms });
22871
- const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
22872
- const prefixStr = (id, k) => `
22873
+ const parseStr = (k2) => `shape[${k2}]._zod.run({ value: input[${k2}], issues: [] }, ctx)`;
22874
+ const prefixStr = (id, k2) => `
22873
22875
  for (let i = 0; i < ${id}.issues.length; i++) {
22874
22876
  const iss = ${id}.issues[i];
22875
- iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
22877
+ iss.path = iss.path ? [${k2}, ...iss.path] : [${k2}];
22876
22878
  payload.issues.push(iss);
22877
22879
  }`;
22878
22880
  doc.write(`const input = payload.value;`);
@@ -22886,23 +22888,23 @@ var $ZodObjectJIT2 = /* @__PURE__ */ $constructor2("$ZodObjectJIT", (inst, def)
22886
22888
  if (key === "__proto__")
22887
22889
  continue;
22888
22890
  const id = ids[key];
22889
- const k = typeof key === "symbol" ? `syms[${syms.indexOf(key)}]` : esc2(key);
22890
- const isPresent = `${k} in input`;
22891
+ const k2 = typeof key === "symbol" ? `syms[${syms.indexOf(key)}]` : esc2(key);
22892
+ const isPresent = `${k2} in input`;
22891
22893
  const schema = shape[key];
22892
22894
  const optin = schema?._zod?.optin;
22893
22895
  const isOptionalIn = optin !== void 0;
22894
22896
  const isOptionalOut = schema?._zod?.optout === "optional";
22895
- doc.write(`const ${id} = ${parseStr(k)};`);
22897
+ doc.write(`const ${id} = ${parseStr(k2)};`);
22896
22898
  if (isOptionalIn && isOptionalOut) {
22897
22899
  const assign = optin === "optional" ? `${id}_present` : `${id}.value !== undefined || ${id}_present`;
22898
22900
  doc.write(`
22899
22901
  const ${id}_present = ${isPresent};
22900
22902
  if (!${id}.issues.length || ${id}_present) {
22901
- if (${id}.issues.length) {${prefixStr(id, k)}
22903
+ if (${id}.issues.length) {${prefixStr(id, k2)}
22902
22904
  }
22903
22905
 
22904
22906
  if (${assign}) {
22905
- newResult[${k}] = ${id}.value;
22907
+ newResult[${k2}] = ${id}.value;
22906
22908
  }
22907
22909
  }
22908
22910
 
@@ -22910,33 +22912,33 @@ var $ZodObjectJIT2 = /* @__PURE__ */ $constructor2("$ZodObjectJIT", (inst, def)
22910
22912
  } else if (!isOptionalIn) {
22911
22913
  doc.write(`
22912
22914
  const ${id}_present = ${isPresent};
22913
- if (${id}.issues.length) {${prefixStr(id, k)}
22915
+ if (${id}.issues.length) {${prefixStr(id, k2)}
22914
22916
  }
22915
22917
  if (!${id}_present && !${id}.issues.length) {
22916
22918
  payload.issues.push({
22917
22919
  code: "invalid_type",
22918
22920
  expected: "nonoptional",
22919
22921
  input: undefined,
22920
- path: [${k}]
22922
+ path: [${k2}]
22921
22923
  });
22922
22924
  }
22923
22925
 
22924
22926
  if (${id}_present) {
22925
- newResult[${k}] = ${id}.value;
22927
+ newResult[${k2}] = ${id}.value;
22926
22928
  }
22927
22929
 
22928
22930
  `);
22929
22931
  } else {
22930
22932
  doc.write(`
22931
- if (${id}.issues.length) {${prefixStr(id, k)}
22933
+ if (${id}.issues.length) {${prefixStr(id, k2)}
22932
22934
  }
22933
22935
 
22934
22936
  if (${id}.value === undefined) {
22935
22937
  if (${isPresent}) {
22936
- newResult[${k}] = undefined;
22938
+ newResult[${k2}] = undefined;
22937
22939
  }
22938
22940
  } else {
22939
- newResult[${k}] = ${id}.value;
22941
+ newResult[${k2}] = ${id}.value;
22940
22942
  }
22941
22943
 
22942
22944
  `);
@@ -23114,17 +23116,17 @@ function handleIntersectionResults2(result, left, right) {
23114
23116
  unrecIssue ?? (unrecIssue = iss);
23115
23117
  keys = iss.keys;
23116
23118
  } else if (iss.code === "invalid_key" && iss.origin === "record" && iss.path?.length === 1) {
23117
- const k = String(iss.path[0]);
23118
- if (!keyIssues.has(k))
23119
- keyIssues.set(k, iss);
23120
- keys = [k];
23119
+ const k2 = String(iss.path[0]);
23120
+ if (!keyIssues.has(k2))
23121
+ keyIssues.set(k2, iss);
23122
+ keys = [k2];
23121
23123
  } else {
23122
23124
  return false;
23123
23125
  }
23124
- for (const k of keys) {
23125
- if (!unrecKeys.has(k))
23126
- unrecKeys.set(k, {});
23127
- unrecKeys.get(k)[side] = true;
23126
+ for (const k2 of keys) {
23127
+ if (!unrecKeys.has(k2))
23128
+ unrecKeys.set(k2, {});
23129
+ unrecKeys.get(k2)[side] = true;
23128
23130
  }
23129
23131
  return true;
23130
23132
  };
@@ -23136,14 +23138,14 @@ function handleIntersectionResults2(result, left, right) {
23136
23138
  if (!collect(iss, "r"))
23137
23139
  result.issues.push(iss);
23138
23140
  }
23139
- const bothKeys = [...unrecKeys].filter(([, f]) => f.l && f.r).map(([k]) => k);
23141
+ const bothKeys = [...unrecKeys].filter(([, f]) => f.l && f.r).map(([k2]) => k2);
23140
23142
  if (bothKeys.length) {
23141
- const aggregated = unrecIssue ? bothKeys.filter((k) => unrecIssue.keys.includes(k)) : [];
23143
+ const aggregated = unrecIssue ? bothKeys.filter((k2) => unrecIssue.keys.includes(k2)) : [];
23142
23144
  if (aggregated.length)
23143
23145
  result.issues.push({ ...unrecIssue, keys: aggregated });
23144
- for (const k of bothKeys) {
23145
- if (!aggregated.includes(k) && keyIssues.has(k))
23146
- result.issues.push(keyIssues.get(k));
23146
+ for (const k2 of bothKeys) {
23147
+ if (!aggregated.includes(k2) && keyIssues.has(k2))
23148
+ result.issues.push(keyIssues.get(k2));
23147
23149
  }
23148
23150
  }
23149
23151
  const merged = mergeValues2(left.value, right.value);
@@ -23315,7 +23317,7 @@ var $ZodEnum2 = /* @__PURE__ */ $constructor2("$ZodEnum", (inst, def) => {
23315
23317
  const values = getEnumValues2(def.entries);
23316
23318
  const valuesSet = new Set(values);
23317
23319
  inst._zod.values = valuesSet;
23318
- const patternValues = values.filter((k) => propertyKeyTypes2.has(typeof k));
23320
+ const patternValues = values.filter((k2) => propertyKeyTypes2.has(typeof k2));
23319
23321
  inst._zod.pattern = new RegExp(patternValues.length ? `^(${patternValues.map((o) => escapeRegex2(o.toString())).join("|")})$` : "^[^\\s\\S]$");
23320
23322
  inst._zod.parse = (payload, _ctx) => {
23321
23323
  const input2 = payload.value;
@@ -24829,13 +24831,13 @@ function foldIntersection2(json2) {
24829
24831
  for (const key of FOLDABLE_KEYS2)
24830
24832
  if (key in json2)
24831
24833
  return;
24832
- const unions = allOf.filter((m) => UNION_KEYS2.some((k) => Array.isArray(m[k])));
24834
+ const unions = allOf.filter((m) => UNION_KEYS2.some((k2) => Array.isArray(m[k2])));
24833
24835
  let folded = null;
24834
24836
  if (!unions.length) {
24835
24837
  folded = foldObjects2(allOf);
24836
24838
  } else {
24837
24839
  const union3 = unions[0];
24838
- const keyword = UNION_KEYS2.find((k) => Array.isArray(union3[k]));
24840
+ const keyword = UNION_KEYS2.find((k2) => Array.isArray(union3[k2]));
24839
24841
  if (Object.keys(union3).length !== 1)
24840
24842
  return;
24841
24843
  const rest = allOf.filter((m) => m !== union3);
@@ -27072,6 +27074,8 @@ var Snapshot = object2({
27072
27074
  /** Spend per UTC hour ("2026-10-05T14:00:00.000Z") and bot, last two days. */
27073
27075
  usageHours: maybe(map2("UsageHours", map2("UsageHourRow", Usage))),
27074
27076
  usageHoursSince: maybe(string5()),
27077
+ /** Per model, the newest [gap in ms, cache hit ratio] pairs of its calls a minute or more after the session's previous one: main's compact schedule measures the prompt-cache TTL from them. */
27078
+ cacheGaps: maybe(map2("CacheGaps", array2(array2(number5())))),
27075
27079
  server: maybe(ServerID),
27076
27080
  /** Track summaries by path; the web client reads them (the app doesn't), the hosted hub sends them. */
27077
27081
  pathSummaries: maybe(map2("PathSummaries", object2({ text: string5(), by: string5(), at: string5() }).meta({ id: "PathSummary" })))
@@ -27141,6 +27145,94 @@ var RESTARTED_TURNS_READ = s(`SELECT t.thread_id, t.bot, r.claimed_at FROM turns
27141
27145
  WHERE r.id = 1 AND t.status IN ${OPEN_TURN_STATUSES} AND ${onLocal("t.bot")} AND t.started_at < r.claimed_at
27142
27146
  AND NOT EXISTS (SELECT 1 FROM session_folds f WHERE f.session_id = t.session_id AND f.folded_at >= r.claimed_at)`);
27143
27147
 
27148
+ // ../../hosted-hub/src/domain/cron.mjs
27149
+ var MINUTE = 6e4;
27150
+ var CATCH_UP_MS = 7 * 24 * 60 * MINUTE;
27151
+
27152
+ // ../../hosted-hub/src/store/schedules.ts
27153
+ var scheduleThreadId = (agent, id) => `sch-${agent}-${id.replaceAll("/", ".")}`;
27154
+ var Info = external_exports.object({ schedules: external_exports.array(external_exports.object({ name: external_exports.string().min(1), cron: external_exports.string().min(1), hasRun: external_exports.boolean() })) });
27155
+
27156
+ // ../../hosted-hub/src/domain/compact-report.mjs
27157
+ var quiet = (text) => String(text).replace(/@/g, "\uFF20");
27158
+ var count = (n) => typeof n === "number" ? n.toLocaleString("en-US") : "?";
27159
+ var link = (thread, id) => `[${quiet(String(thread?.title ?? id).replace(/[[\]]/g, ""))}](${id})`;
27160
+ var nextTry = (agent) => `next try: after ${quiet(agent)}'s next turn there, once idle 10+ min (or at 40 turns) with its prompt cache gone cold`;
27161
+ var compactedLine = (r, thread) => `compacted: ${quiet(r.agent)} on ${link(thread, r.threadId)} \xB7 ${quiet(r.trigger)} \xB7 ${count(r.before)} input tokens before`;
27162
+ var afterLine = (r, thread, after) => `after compaction: ${quiet(r.agent)} on ${link(thread, r.threadId)} \xB7 ${count(r.before)} \u2192 ${count(after)} input tokens`;
27163
+ var failureLine = (r, thread, reason) => `compact failed: ${quiet(r.agent)} on ${link(thread, r.threadId)} \xB7 ${quiet(r.trigger)} \xB7 ${quiet(reason)}; ${nextTry(r.agent)}`;
27164
+
27165
+ // ../../hosted-hub/src/store/compactions.ts
27166
+ var ASKED = `(c.attempt_at IS NOT NULL AND c.attempt_at > COALESCE(c.settled_at, 0))`;
27167
+ var k = (tokens) => `CAST((${tokens} + 500) / 1000 AS INTEGER) || 'k'`;
27168
+ var compactedText = (after) => `'Context compacted' || CASE WHEN c.before_tokens IS NULL THEN ''
27169
+ WHEN ${after} IS NULL THEN ' at ' || ${k("c.before_tokens")} || ' input tokens'
27170
+ ELSE ': ' || ${k("c.before_tokens")} || ' \u2192 ' || ${k(after)} || ' input tokens' END`;
27171
+ function compactionStatements(type, session, event, at, messageId2, report = null) {
27172
+ const before = `COALESCE(?, (SELECT input_tokens FROM usage_steps WHERE session_id = ? ORDER BY at DESC, sequence DESC, step_index DESC LIMIT 1))`;
27173
+ if (type === "compaction.requested")
27174
+ return [s(
27175
+ `INSERT INTO compactions (session_id, before_tokens) VALUES (?, ${before}) ON CONFLICT (session_id) DO UPDATE SET before_tokens = excluded.before_tokens,
27176
+ report_phase = CASE WHEN report_phase = 'asked' THEN 'requested' ELSE report_phase END`,
27177
+ session.id,
27178
+ typeof event.usageInputTokens === "number" ? event.usageInputTokens : null,
27179
+ session.id
27180
+ )];
27181
+ if (type === "session.waiting")
27182
+ return [
27183
+ // eve took the request and went idle with no checkpoint: it kept the history (the reason is in the bot's log). A
27184
+ // session.waiting from before eve took the request (the previous turn's, folded late) is not that: only 'requested' counts.
27185
+ ...reportLine(report, session, at, `${messageId2}:waiting`, (r) => failureLine(...r, `eve ended it without a checkpoint and kept the history (the reason is in ${session.bot}'s log)`), `report_phase = 'requested'`, null),
27186
+ s("UPDATE compactions SET settled_at = ? WHERE session_id = ? AND attempt_at IS NOT NULL AND attempt_at > COALESCE(settled_at, 0)", at, session.id)
27187
+ ];
27188
+ return [
27189
+ ...eventStatements(
27190
+ session.thread,
27191
+ {
27192
+ sql: `(SELECT json_object('kind', 'compaction', 'agent', ?, 'by', CASE WHEN ${ASKED} THEN c.attempt_by ELSE 'eve' END) FROM (SELECT 1) LEFT JOIN compactions c ON c.session_id = ?)`,
27193
+ args: [session.bot, session.id]
27194
+ },
27195
+ { sql: `(SELECT ${compactedText("NULL")} FROM (SELECT 1) LEFT JOIN compactions c ON c.session_id = ?)`, args: [session.id] },
27196
+ at,
27197
+ messageId2
27198
+ ),
27199
+ s(
27200
+ `INSERT INTO compactions (session_id, completed_at, turns_at_completion, event_id) VALUES (?, ?, (SELECT turns FROM thread_totals WHERE thread_id = ? AND bot = ?), ?)
27201
+ ON CONFLICT (session_id) DO UPDATE SET completed_at = excluded.completed_at, turns_at_completion = excluded.turns_at_completion, after_tokens = NULL, event_id = excluded.event_id`,
27202
+ session.id,
27203
+ at,
27204
+ session.thread,
27205
+ session.bot,
27206
+ messageId2
27207
+ ),
27208
+ ...reportLine(report, session, at, `${messageId2}:completed`, (r) => compactedLine(...r), `report_phase IN ('asked', 'requested', 'unanswered')`, "compacted")
27209
+ ];
27210
+ }
27211
+ var reportThread = (to) => {
27212
+ const [bot, ...id] = to.split("/");
27213
+ return scheduleThreadId(bot, id.join("/"));
27214
+ };
27215
+ var lineOf = (report, session) => [{ agent: session.bot, threadId: session.thread, trigger: report.trigger, before: report.before }, { title: report.title }];
27216
+ function reportLine(report, session, at, id, text, when, next) {
27217
+ if (!report) return [];
27218
+ const thread = reportThread(report.to), rowId = derivedMessageId(id, "report"), has = `EXISTS (SELECT 1 FROM compactions WHERE session_id = ? AND ${when})`;
27219
+ return [
27220
+ s(`INSERT INTO log (thread_id,type,data,at) SELECT ?, 'thread.created', ?, ? WHERE ${has} AND NOT EXISTS (SELECT 1 FROM threads WHERE id = ?)`, thread, JSON.stringify({ threadId: thread }), at, session.id, thread),
27221
+ s(`INSERT OR IGNORE INTO threads (id,title,created_at) SELECT ?, ?, ? WHERE ${has}`, thread, report.to, at, session.id),
27222
+ ...eventStatements(thread, { kind: "compaction-report", agent: session.bot }, text(lineOf(report, session)), at, rowId, { sql: has, args: [session.id] }),
27223
+ s(`UPDATE compactions SET report_phase = ? WHERE session_id = ? AND ${when}`, next, session.id)
27224
+ ];
27225
+ }
27226
+ function compactedSizeStatements(sessionId2, inputTokens) {
27227
+ const waiting = (c) => `${c}completed_at IS NOT NULL AND ${c}after_tokens IS NULL`;
27228
+ return [
27229
+ s(`UPDATE messages SET text = (SELECT ${compactedText("a")} FROM compactions c, (SELECT ? AS a) WHERE c.session_id = ? AND ${waiting("c.")})
27230
+ WHERE id = (SELECT event_id FROM compactions WHERE session_id = ? AND ${waiting("")})`, inputTokens, sessionId2, sessionId2),
27231
+ s(`UPDATE compactions SET after_tokens = ? WHERE session_id = ? AND ${waiting("")}`, inputTokens, sessionId2)
27232
+ ];
27233
+ }
27234
+ var reportAfterStatements = (report, session, inputTokens, at, id) => reportLine(report, session, at, `${id}:after`, ([r, thread]) => afterLine(r, thread, inputTokens), `report_phase = 'compacted' AND completed_at IS NOT NULL AND after_tokens IS NULL`, null);
27235
+
27144
27236
  // ../../hosted-hub/src/store/fold.ts
27145
27237
  var FOLD_STATE_SQL = `SELECT s.id, s.thread_id, s.bot, COALESCE(f.folded_index, -1) AS folded_index, (SELECT json_group_array(name) FROM (SELECT name FROM bots ORDER BY position)) AS roster,
27146
27238
  (SELECT json_group_array(bot) FROM (${PARTICIPANTS("s.thread_id")})) AS participants,
@@ -27148,7 +27240,9 @@ var FOLD_STATE_SQL = `SELECT s.id, s.thread_id, s.bot, COALESCE(f.folded_index,
27148
27240
  (SELECT json_object('person', person, 'names', json(names)) FROM human_notify) AS notify,
27149
27241
  (SELECT json_object('status', t.status, 'id', t.id, 'text', t.reply_text, 'lastStep', json(t.last_step), 'activity', json(t.activity),
27150
27242
  'trigger', ${triggerOf("t")}) FROM turns t WHERE t.session_id = s.id AND t.status IN ${OPEN_TURN_STATUSES}
27151
- ORDER BY t.started_at DESC LIMIT 1) AS open_turn
27243
+ ORDER BY t.started_at DESC LIMIT 1) AS open_turn,
27244
+ (SELECT json_object('to', c.report_to, 'trigger', c.report_trigger, 'before', c.report_before, 'title', (SELECT title FROM threads WHERE id = s.thread_id))
27245
+ FROM compactions c WHERE c.session_id = s.id AND c.report_to IS NOT NULL) AS report
27152
27246
  FROM sessions s LEFT JOIN session_folds f ON f.session_id = s.id WHERE s.id = ?`;
27153
27247
  function foldState(row) {
27154
27248
  if (!row) return void 0;
@@ -27159,7 +27253,8 @@ function foldState(row) {
27159
27253
  held: row.held == null ? null : String(row.held),
27160
27254
  notify: row.notify ? JSON.parse(String(row.notify)) : null,
27161
27255
  foldedIndex: Number(row.folded_index),
27162
- open: row.open_turn ? JSON.parse(String(row.open_turn)) : null
27256
+ open: row.open_turn ? JSON.parse(String(row.open_turn)) : null,
27257
+ report: row.report ? JSON.parse(String(row.report)) : null
27163
27258
  };
27164
27259
  }
27165
27260
  var REVOKED_TURN = `EXISTS (SELECT 1 FROM turn_deliveries td JOIN deliveries d ON d.id = td.delivery_id
@@ -27216,6 +27311,8 @@ function fold(state, chunks, now = Date.now()) {
27216
27311
  WHERE id = ? AND session_id = ? AND status = 'pending'`, r.outcome ?? "answered", at, r.response?.text ?? null, r.response?.optionId ?? null, r.response?.optionId ?? null, r.requestId, session.id));
27217
27312
  log("request.updated", { requestIds: (data.resolutions ?? []).map((r) => r.requestId) });
27218
27313
  }
27314
+ if (event.type === "compaction.requested" || event.type === "compaction.completed" || event.type === "session.waiting")
27315
+ stmts.push(...compactionStatements(event.type, session, data, at, derivedMessageId(session.id, index, eventIndex), state.report));
27219
27316
  if (event.type === "turn.started") {
27220
27317
  if (!data.turnId) throw new Error("turn.started must name eve turnId");
27221
27318
  flush();
@@ -27240,9 +27337,14 @@ function fold(state, chunks, now = Date.now()) {
27240
27337
  if (event.type === "agent.started" && data.sessionId && data.callId)
27241
27338
  stmts.push(...linkStatements(data.sessionId, open3.id, data.callId));
27242
27339
  switch (event.type) {
27340
+ case "step.started": {
27341
+ if (typeof data.modelId === "string") stmts.push(s("UPDATE sessions SET step_model = ? WHERE id = ?", data.modelId, session.id));
27342
+ break;
27343
+ }
27243
27344
  case "step.completed": {
27244
27345
  if (data.sequence === void 0 || data.stepIndex === void 0) break;
27245
- stmts.push(s(`${STEP_INSERT} VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, ...stepValues(session.id, { sequence: data.sequence, stepIndex: data.stepIndex, at: new Date(at).toISOString(), usage: data.usage ?? {} }), open3.id));
27346
+ stmts.push(s(`${STEP_INSERT} VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, (SELECT step_model FROM sessions WHERE id = ?))`, ...stepValues(session.id, { sequence: data.sequence, stepIndex: data.stepIndex, at: new Date(at).toISOString(), usage: data.usage ?? {} }), open3.id, session.id));
27347
+ if (typeof data.usage?.inputTokens === "number") stmts.push(...reportAfterStatements(state.report, session, data.usage.inputTokens, at, derivedMessageId(session.id, index, eventIndex)), ...compactedSizeStatements(session.id, data.usage.inputTokens));
27246
27348
  break;
27247
27349
  }
27248
27350
  case "message.appended": {
@@ -27399,7 +27501,7 @@ function foldSubagent(state, chunks, now = Date.now()) {
27399
27501
  // ../../hosted-hub/bots/world.ts
27400
27502
  async function foldAppend(tx, { runId, name, chunks, firstIndex }) {
27401
27503
  if (name !== sessionCodec.streamName(runId)) return;
27402
- const decoded = await Promise.all(chunks.map(async (c, k) => ({ index: firstIndex + k, events: await sessionCodec.decode(c) })));
27504
+ const decoded = await Promise.all(chunks.map(async (c, k2) => ({ index: firstIndex + k2, events: await sessionCodec.decode(c) })));
27403
27505
  return foldInTx(tx, runId, decoded);
27404
27506
  }
27405
27507
  async function createWorld() {