eve-hub 0.6.45 → 0.6.47

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.47
4
+
5
+ ### Patch Changes
6
+
7
+ - The hub can ask a Mac bot's runner to compact a session, so Mac bots compact like hosted ones.
8
+
9
+ ## 0.6.46
10
+
11
+ ### Patch Changes
12
+
13
+ - The team model's human node carries the label the app shows for the workspace owner, so the Team window and the bots' team list name the same person.
14
+
3
15
  ## 0.6.45
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.45",
3
+ "version": "0.6.47",
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/team.d.mts CHANGED
@@ -19,6 +19,6 @@ export const EDGE_KINDS: readonly [string, ...string[]];
19
19
  export const SECTIONS: readonly { id: string; edge: { kind: string; from: unknown; to: unknown }; text: string }[];
20
20
  export const SECTIONS_HASH: string;
21
21
  export function teamEdges(nodes: readonly TeamNode[]): TeamEdge[];
22
- export function teamModel(input: { agents: readonly TeamAgent[]; humans?: readonly { name: string; color?: string }[]; tools?: Record<string, readonly string[] | null | undefined> }): TeamModel;
22
+ export function teamModel(input: { agents: readonly TeamAgent[]; humans?: readonly { name: string; label?: string; color?: string }[]; tools?: Record<string, readonly string[] | null | undefined> }): TeamModel;
23
23
  export function teamText(model: TeamModel): string;
24
24
  export function teamRecall(history: readonly unknown[], fetchTeam: (since?: string) => Promise<TeamModel | null>): Promise<{ messages: { id: string; content: string }[] }>;
package/team.mjs CHANGED
@@ -53,7 +53,7 @@ export function teamEdges(nodes) {
53
53
  // name -> the tool names its eve reports, absent or null when not reported.
54
54
  export function teamModel({ agents, humans = [], tools = {} }) {
55
55
  const nodes = [
56
- ...humans.map((h) => ({ id: h.name, kind: "human", label: h.name, ...(h.color ? { color: h.color } : {}) })),
56
+ ...humans.map((h) => ({ id: h.name, kind: "human", label: h.label ?? h.name, ...(h.color ? { color: h.color } : {}) })),
57
57
  ...agents.map((a) => ({
58
58
  id: a.name,
59
59
  kind: a.kind ?? "other",
package/world.mjs CHANGED
@@ -20450,6 +20450,94 @@ var MOVES = Object.freeze({
20450
20450
  });
20451
20451
  var VERDICTS = Object.freeze(["ship", "fix-first", "rethink"]);
20452
20452
 
20453
+ // ../../hosted-hub/src/domain/cron.mjs
20454
+ var MINUTE = 6e4;
20455
+ var CATCH_UP_MS = 7 * 24 * 60 * MINUTE;
20456
+
20457
+ // ../../hosted-hub/src/store/schedules.ts
20458
+ var scheduleThreadId = (agent, id) => `sch-${agent}-${id.replaceAll("/", ".")}`;
20459
+ 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() })) });
20460
+
20461
+ // ../../hosted-hub/src/domain/compact-report.mjs
20462
+ var quiet = (text) => String(text).replace(/@/g, "\uFF20");
20463
+ var count = (n) => typeof n === "number" ? n.toLocaleString("en-US") : "?";
20464
+ var link = (thread, id) => `[${quiet(String(thread?.title ?? id).replace(/[[\]]/g, ""))}](${id})`;
20465
+ 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`;
20466
+ var compactedLine = (r, thread) => `compacted: ${quiet(r.agent)} on ${link(thread, r.threadId)} \xB7 ${quiet(r.trigger)} \xB7 ${count(r.before)} input tokens before`;
20467
+ var afterLine = (r, thread, after) => `after compaction: ${quiet(r.agent)} on ${link(thread, r.threadId)} \xB7 ${count(r.before)} \u2192 ${count(after)} input tokens`;
20468
+ 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)}`;
20469
+
20470
+ // ../../hosted-hub/src/store/compactions.ts
20471
+ var ASKED = `(c.attempt_at IS NOT NULL AND c.attempt_at > COALESCE(c.settled_at, 0))`;
20472
+ var k = (tokens) => `CAST((${tokens} + 500) / 1000 AS INTEGER) || 'k'`;
20473
+ var compactedText = (after) => `'Context compacted' || CASE WHEN c.before_tokens IS NULL THEN ''
20474
+ WHEN ${after} IS NULL THEN ' at ' || ${k("c.before_tokens")} || ' input tokens'
20475
+ ELSE ': ' || ${k("c.before_tokens")} || ' \u2192 ' || ${k(after)} || ' input tokens' END`;
20476
+ function compactionStatements(type, session, event, at, messageId2, report = null) {
20477
+ const before = `COALESCE(?, (SELECT input_tokens FROM usage_steps WHERE session_id = ? ORDER BY at DESC, sequence DESC, step_index DESC LIMIT 1))`;
20478
+ if (type === "compaction.requested")
20479
+ return [s(
20480
+ `INSERT INTO compactions (session_id, before_tokens) VALUES (?, ${before}) ON CONFLICT (session_id) DO UPDATE SET before_tokens = excluded.before_tokens,
20481
+ report_phase = CASE WHEN report_phase = 'asked' THEN 'requested' ELSE report_phase END`,
20482
+ session.id,
20483
+ typeof event.usageInputTokens === "number" ? event.usageInputTokens : null,
20484
+ session.id
20485
+ )];
20486
+ if (type === "session.waiting")
20487
+ return [
20488
+ // eve took the request and went idle with no checkpoint: it kept the history (the reason is in the bot's log). A
20489
+ // session.waiting from before eve took the request (the previous turn's, folded late) is not that: only 'requested' counts.
20490
+ ...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),
20491
+ 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)
20492
+ ];
20493
+ return [
20494
+ ...eventStatements(
20495
+ session.thread,
20496
+ {
20497
+ 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 = ?)`,
20498
+ args: [session.bot, session.id]
20499
+ },
20500
+ { sql: `(SELECT ${compactedText("NULL")} FROM (SELECT 1) LEFT JOIN compactions c ON c.session_id = ?)`, args: [session.id] },
20501
+ at,
20502
+ messageId2
20503
+ ),
20504
+ s(
20505
+ `INSERT INTO compactions (session_id, completed_at, turns_at_completion, event_id) VALUES (?, ?, (SELECT turns FROM thread_totals WHERE thread_id = ? AND bot = ?), ?)
20506
+ 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`,
20507
+ session.id,
20508
+ at,
20509
+ session.thread,
20510
+ session.bot,
20511
+ messageId2
20512
+ ),
20513
+ ...reportLine(report, session, at, `${messageId2}:completed`, (r) => compactedLine(...r), `report_phase IN ('asked', 'requested', 'unanswered')`, "compacted")
20514
+ ];
20515
+ }
20516
+ var reportThread = (to) => {
20517
+ const [bot, ...id] = to.split("/");
20518
+ return scheduleThreadId(bot, id.join("/"));
20519
+ };
20520
+ var lineOf = (report, session) => [{ agent: session.bot, threadId: session.thread, trigger: report.trigger, before: report.before }, { title: report.title }];
20521
+ function reportLine(report, session, at, id, text, when, next) {
20522
+ if (!report) return [];
20523
+ const thread = reportThread(report.to), rowId = derivedMessageId(id, "report"), has = `EXISTS (SELECT 1 FROM compactions WHERE session_id = ? AND ${when})`;
20524
+ return [
20525
+ 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),
20526
+ s(`INSERT OR IGNORE INTO threads (id,title,created_at) SELECT ?, ?, ? WHERE ${has}`, thread, report.to, at, session.id),
20527
+ ...eventStatements(thread, { kind: "compaction-report", agent: session.bot }, text(lineOf(report, session)), at, rowId, { sql: has, args: [session.id] }),
20528
+ s(`UPDATE compactions SET report_phase = ? WHERE session_id = ? AND ${when}`, next, session.id)
20529
+ ];
20530
+ }
20531
+ function compactedSizeStatements(sessionId2, inputTokens) {
20532
+ const waiting = (c) => `${c}completed_at IS NOT NULL AND ${c}after_tokens IS NULL`;
20533
+ return [
20534
+ s(`UPDATE messages SET text = (SELECT ${compactedText("a")} FROM compactions c, (SELECT ? AS a) WHERE c.session_id = ? AND ${waiting("c.")})
20535
+ WHERE id = (SELECT event_id FROM compactions WHERE session_id = ? AND ${waiting("")})`, inputTokens, sessionId2, sessionId2),
20536
+ s(`UPDATE compactions SET after_tokens = ? WHERE session_id = ? AND ${waiting("")}`, inputTokens, sessionId2)
20537
+ ];
20538
+ }
20539
+ 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);
20540
+
20453
20541
  // ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/core/util.js
20454
20542
  var util_exports2 = {};
20455
20543
  __export(util_exports2, {
@@ -27156,94 +27244,6 @@ var RESTARTED_TURNS_READ = s(`SELECT t.thread_id, t.bot, r.claimed_at FROM turns
27156
27244
  WHERE r.id = 1 AND t.status IN ${OPEN_TURN_STATUSES} AND ${onLocal("t.bot")} AND t.started_at < r.claimed_at
27157
27245
  AND NOT EXISTS (SELECT 1 FROM session_folds f WHERE f.session_id = t.session_id AND f.folded_at >= r.claimed_at)`);
27158
27246
 
27159
- // ../../hosted-hub/src/domain/cron.mjs
27160
- var MINUTE = 6e4;
27161
- var CATCH_UP_MS = 7 * 24 * 60 * MINUTE;
27162
-
27163
- // ../../hosted-hub/src/store/schedules.ts
27164
- var scheduleThreadId = (agent, id) => `sch-${agent}-${id.replaceAll("/", ".")}`;
27165
- 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() })) });
27166
-
27167
- // ../../hosted-hub/src/domain/compact-report.mjs
27168
- var quiet = (text) => String(text).replace(/@/g, "\uFF20");
27169
- var count = (n) => typeof n === "number" ? n.toLocaleString("en-US") : "?";
27170
- var link = (thread, id) => `[${quiet(String(thread?.title ?? id).replace(/[[\]]/g, ""))}](${id})`;
27171
- 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`;
27172
- var compactedLine = (r, thread) => `compacted: ${quiet(r.agent)} on ${link(thread, r.threadId)} \xB7 ${quiet(r.trigger)} \xB7 ${count(r.before)} input tokens before`;
27173
- var afterLine = (r, thread, after) => `after compaction: ${quiet(r.agent)} on ${link(thread, r.threadId)} \xB7 ${count(r.before)} \u2192 ${count(after)} input tokens`;
27174
- 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)}`;
27175
-
27176
- // ../../hosted-hub/src/store/compactions.ts
27177
- var ASKED = `(c.attempt_at IS NOT NULL AND c.attempt_at > COALESCE(c.settled_at, 0))`;
27178
- var k = (tokens) => `CAST((${tokens} + 500) / 1000 AS INTEGER) || 'k'`;
27179
- var compactedText = (after) => `'Context compacted' || CASE WHEN c.before_tokens IS NULL THEN ''
27180
- WHEN ${after} IS NULL THEN ' at ' || ${k("c.before_tokens")} || ' input tokens'
27181
- ELSE ': ' || ${k("c.before_tokens")} || ' \u2192 ' || ${k(after)} || ' input tokens' END`;
27182
- function compactionStatements(type, session, event, at, messageId2, report = null) {
27183
- const before = `COALESCE(?, (SELECT input_tokens FROM usage_steps WHERE session_id = ? ORDER BY at DESC, sequence DESC, step_index DESC LIMIT 1))`;
27184
- if (type === "compaction.requested")
27185
- return [s(
27186
- `INSERT INTO compactions (session_id, before_tokens) VALUES (?, ${before}) ON CONFLICT (session_id) DO UPDATE SET before_tokens = excluded.before_tokens,
27187
- report_phase = CASE WHEN report_phase = 'asked' THEN 'requested' ELSE report_phase END`,
27188
- session.id,
27189
- typeof event.usageInputTokens === "number" ? event.usageInputTokens : null,
27190
- session.id
27191
- )];
27192
- if (type === "session.waiting")
27193
- return [
27194
- // eve took the request and went idle with no checkpoint: it kept the history (the reason is in the bot's log). A
27195
- // session.waiting from before eve took the request (the previous turn's, folded late) is not that: only 'requested' counts.
27196
- ...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),
27197
- 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)
27198
- ];
27199
- return [
27200
- ...eventStatements(
27201
- session.thread,
27202
- {
27203
- 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 = ?)`,
27204
- args: [session.bot, session.id]
27205
- },
27206
- { sql: `(SELECT ${compactedText("NULL")} FROM (SELECT 1) LEFT JOIN compactions c ON c.session_id = ?)`, args: [session.id] },
27207
- at,
27208
- messageId2
27209
- ),
27210
- s(
27211
- `INSERT INTO compactions (session_id, completed_at, turns_at_completion, event_id) VALUES (?, ?, (SELECT turns FROM thread_totals WHERE thread_id = ? AND bot = ?), ?)
27212
- 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`,
27213
- session.id,
27214
- at,
27215
- session.thread,
27216
- session.bot,
27217
- messageId2
27218
- ),
27219
- ...reportLine(report, session, at, `${messageId2}:completed`, (r) => compactedLine(...r), `report_phase IN ('asked', 'requested', 'unanswered')`, "compacted")
27220
- ];
27221
- }
27222
- var reportThread = (to) => {
27223
- const [bot, ...id] = to.split("/");
27224
- return scheduleThreadId(bot, id.join("/"));
27225
- };
27226
- var lineOf = (report, session) => [{ agent: session.bot, threadId: session.thread, trigger: report.trigger, before: report.before }, { title: report.title }];
27227
- function reportLine(report, session, at, id, text, when, next) {
27228
- if (!report) return [];
27229
- const thread = reportThread(report.to), rowId = derivedMessageId(id, "report"), has = `EXISTS (SELECT 1 FROM compactions WHERE session_id = ? AND ${when})`;
27230
- return [
27231
- 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),
27232
- s(`INSERT OR IGNORE INTO threads (id,title,created_at) SELECT ?, ?, ? WHERE ${has}`, thread, report.to, at, session.id),
27233
- ...eventStatements(thread, { kind: "compaction-report", agent: session.bot }, text(lineOf(report, session)), at, rowId, { sql: has, args: [session.id] }),
27234
- s(`UPDATE compactions SET report_phase = ? WHERE session_id = ? AND ${when}`, next, session.id)
27235
- ];
27236
- }
27237
- function compactedSizeStatements(sessionId2, inputTokens) {
27238
- const waiting = (c) => `${c}completed_at IS NOT NULL AND ${c}after_tokens IS NULL`;
27239
- return [
27240
- s(`UPDATE messages SET text = (SELECT ${compactedText("a")} FROM compactions c, (SELECT ? AS a) WHERE c.session_id = ? AND ${waiting("c.")})
27241
- WHERE id = (SELECT event_id FROM compactions WHERE session_id = ? AND ${waiting("")})`, inputTokens, sessionId2, sessionId2),
27242
- s(`UPDATE compactions SET after_tokens = ? WHERE session_id = ? AND ${waiting("")}`, inputTokens, sessionId2)
27243
- ];
27244
- }
27245
- 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);
27246
-
27247
27247
  // ../../hosted-hub/src/store/fold.ts
27248
27248
  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 WHERE ${inRoster} ORDER BY position)) AS roster,
27249
27249
  (SELECT json_group_array(bot) FROM (${PARTICIPANTS("s.thread_id")})) AS participants,