eve-hub 0.6.43 → 0.6.45
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 +12 -0
- package/mention-gate.mjs +3 -63
- package/mention-tokens.mjs +64 -1
- package/package.json +1 -1
- package/world.mjs +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# eve-hub
|
|
2
2
|
|
|
3
|
+
## 0.6.45
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- A Mac bot whose workspace setup is failing is out of the roster: a reply's @-mention, a schedule post and `agent_send` no longer wake it, and it is left out of the bots' team list. It comes back when setup works or its runner goes quiet.
|
|
8
|
+
|
|
9
|
+
## 0.6.44
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- The mention rule (mentionTokens and codeRanges) lives in mention-tokens.mjs with no imports, so the composer's fuzz harness loads the server's own source; mention-gate re-exports codeRanges.
|
|
14
|
+
|
|
3
15
|
## 0.6.43
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/mention-gate.mjs
CHANGED
|
@@ -20,11 +20,14 @@
|
|
|
20
20
|
// overridden by HUB_MENTION_GATE (on|off), HUB_MENTION_GATE_MODEL,
|
|
21
21
|
// HUB_MENTION_GATE_REASONING, HUB_MENTION_GATE_TIMEOUT_MS and
|
|
22
22
|
// HUB_MENTION_GATE_URL (tests).
|
|
23
|
+
import { codeRanges } from "./mention-tokens.mjs";
|
|
23
24
|
import { registryHeaders } from "./registry-fetch.mjs";
|
|
24
25
|
import { existsSync, readFileSync } from "node:fs";
|
|
25
26
|
import { join } from "node:path";
|
|
26
27
|
import { pathToFileURL } from "node:url";
|
|
27
28
|
|
|
29
|
+
export { codeRanges };
|
|
30
|
+
|
|
28
31
|
export const GATE_DEFAULTS = {
|
|
29
32
|
enabled: true,
|
|
30
33
|
model: "openai/gpt-6-luna-decisions",
|
|
@@ -194,69 +197,6 @@ export function triggerText(envelope) {
|
|
|
194
197
|
return next < 0 ? rest : rest.slice(0, next);
|
|
195
198
|
}
|
|
196
199
|
|
|
197
|
-
// The character ranges of a message that are code, by CommonMark's rules:
|
|
198
|
-
// fenced blocks (``` or ~~~, closed by the same character, at least as
|
|
199
|
-
// long), and code spans (a run of n backticks closed by the next run of
|
|
200
|
-
// exactly n on the same line; an opener can't be backslash-escaped).
|
|
201
|
-
// Anything ambiguous stays text: an unclosed fence or an unmatched run is
|
|
202
|
-
// literal, so a handle next to it counts as live.
|
|
203
|
-
export function codeRanges(text) {
|
|
204
|
-
const s = String(text ?? "");
|
|
205
|
-
const ranges = [];
|
|
206
|
-
const lines = [];
|
|
207
|
-
for (let at = 0; at <= s.length; ) {
|
|
208
|
-
const nl = s.indexOf("\n", at);
|
|
209
|
-
const end = nl < 0 ? s.length : nl;
|
|
210
|
-
lines.push({ start: at, end, text: s.slice(at, end) });
|
|
211
|
-
if (nl < 0) break;
|
|
212
|
-
at = nl + 1;
|
|
213
|
-
}
|
|
214
|
-
// Fences first: only closed ones are code.
|
|
215
|
-
const fenced = new Set();
|
|
216
|
-
for (let i = 0; i < lines.length; i++) {
|
|
217
|
-
const open = lines[i].text.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
|
|
218
|
-
if (!open || (open[1][0] === "`" && open[2].includes("`"))) continue;
|
|
219
|
-
const close = new RegExp(`^ {0,3}${open[1][0] === "`" ? "`" : "~"}{${open[1].length},}\\s*$`);
|
|
220
|
-
const j = lines.findIndex((l, k) => k > i && close.test(l.text));
|
|
221
|
-
if (j < 0) continue;
|
|
222
|
-
ranges.push([lines[i].start, lines[j].end]);
|
|
223
|
-
for (let k = i; k <= j; k++) fenced.add(k);
|
|
224
|
-
i = j;
|
|
225
|
-
}
|
|
226
|
-
// Code spans.
|
|
227
|
-
let para = [];
|
|
228
|
-
const flush = () => {
|
|
229
|
-
if (!para.length) return;
|
|
230
|
-
const from = para[0].start;
|
|
231
|
-
const t = s.slice(from, para.at(-1).end);
|
|
232
|
-
const runs = [...t.matchAll(/`+/g)].map((m) => ({ at: m.index, n: m[0].length }));
|
|
233
|
-
for (let i = 0; i < runs.length; i++) {
|
|
234
|
-
let { at, n } = runs[i];
|
|
235
|
-
let slash = 0;
|
|
236
|
-
for (let b = at - 1; b >= 0 && t[b] === "\\"; b--) slash++;
|
|
237
|
-
if (slash % 2 === 1) {
|
|
238
|
-
// An escaped backtick is literal; the rest of the run can still open.
|
|
239
|
-
at++;
|
|
240
|
-
n--;
|
|
241
|
-
if (!n) continue;
|
|
242
|
-
}
|
|
243
|
-
const j = runs.findIndex((r, k) => k > i && r.n === n);
|
|
244
|
-
if (j < 0) continue;
|
|
245
|
-
ranges.push([from + at, from + runs[j].at + n]);
|
|
246
|
-
i = j;
|
|
247
|
-
}
|
|
248
|
-
para = [];
|
|
249
|
-
};
|
|
250
|
-
// One line at a time: a span that would cross lines might cross a block
|
|
251
|
-
// boundary (a heading or a list item interrupts a paragraph without a
|
|
252
|
-
// blank line), so it stays text.
|
|
253
|
-
lines.forEach((l, i) => {
|
|
254
|
-
if (!fenced.has(i) && l.text.trim()) para.push(l);
|
|
255
|
-
flush();
|
|
256
|
-
});
|
|
257
|
-
return ranges;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
200
|
// Where the bot's @handle sits in a message, by parsing its markdown: in
|
|
261
201
|
// code (codeRanges), on a > quote line, or live (anywhere else).
|
|
262
202
|
export function mentionSites(text, agent) {
|
package/mention-tokens.mjs
CHANGED
|
@@ -1,4 +1,67 @@
|
|
|
1
|
-
|
|
1
|
+
// The mention rule: what counts as `@handle` in a message. No imports, so the
|
|
2
|
+
// native editor checks load this one file as is.
|
|
3
|
+
// The character ranges of a message that are code, by CommonMark's rules:
|
|
4
|
+
// fenced blocks (``` or ~~~, closed by the same character, at least as
|
|
5
|
+
// long), and code spans (a run of n backticks closed by the next run of
|
|
6
|
+
// exactly n on the same line; an opener can't be backslash-escaped).
|
|
7
|
+
// Anything ambiguous stays text: an unclosed fence or an unmatched run is
|
|
8
|
+
// literal, so a handle next to it counts as live.
|
|
9
|
+
export function codeRanges(text) {
|
|
10
|
+
const s = String(text ?? "");
|
|
11
|
+
const ranges = [];
|
|
12
|
+
const lines = [];
|
|
13
|
+
for (let at = 0; at <= s.length; ) {
|
|
14
|
+
const nl = s.indexOf("\n", at);
|
|
15
|
+
const end = nl < 0 ? s.length : nl;
|
|
16
|
+
lines.push({ start: at, end, text: s.slice(at, end) });
|
|
17
|
+
if (nl < 0) break;
|
|
18
|
+
at = nl + 1;
|
|
19
|
+
}
|
|
20
|
+
// Fences first: only closed ones are code.
|
|
21
|
+
const fenced = new Set();
|
|
22
|
+
for (let i = 0; i < lines.length; i++) {
|
|
23
|
+
const open = lines[i].text.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
|
|
24
|
+
if (!open || (open[1][0] === "`" && open[2].includes("`"))) continue;
|
|
25
|
+
const close = new RegExp(`^ {0,3}${open[1][0] === "`" ? "`" : "~"}{${open[1].length},}\\s*$`);
|
|
26
|
+
const j = lines.findIndex((l, k) => k > i && close.test(l.text));
|
|
27
|
+
if (j < 0) continue;
|
|
28
|
+
ranges.push([lines[i].start, lines[j].end]);
|
|
29
|
+
for (let k = i; k <= j; k++) fenced.add(k);
|
|
30
|
+
i = j;
|
|
31
|
+
}
|
|
32
|
+
// Code spans.
|
|
33
|
+
let para = [];
|
|
34
|
+
const flush = () => {
|
|
35
|
+
if (!para.length) return;
|
|
36
|
+
const from = para[0].start;
|
|
37
|
+
const t = s.slice(from, para.at(-1).end);
|
|
38
|
+
const runs = [...t.matchAll(/`+/g)].map((m) => ({ at: m.index, n: m[0].length }));
|
|
39
|
+
for (let i = 0; i < runs.length; i++) {
|
|
40
|
+
let { at, n } = runs[i];
|
|
41
|
+
let slash = 0;
|
|
42
|
+
for (let b = at - 1; b >= 0 && t[b] === "\\"; b--) slash++;
|
|
43
|
+
if (slash % 2 === 1) {
|
|
44
|
+
// An escaped backtick is literal; the rest of the run can still open.
|
|
45
|
+
at++;
|
|
46
|
+
n--;
|
|
47
|
+
if (!n) continue;
|
|
48
|
+
}
|
|
49
|
+
const j = runs.findIndex((r, k) => k > i && r.n === n);
|
|
50
|
+
if (j < 0) continue;
|
|
51
|
+
ranges.push([from + at, from + runs[j].at + n]);
|
|
52
|
+
i = j;
|
|
53
|
+
}
|
|
54
|
+
para = [];
|
|
55
|
+
};
|
|
56
|
+
// One line at a time: a span that would cross lines might cross a block
|
|
57
|
+
// boundary (a heading or a list item interrupts a paragraph without a
|
|
58
|
+
// blank line), so it stays text.
|
|
59
|
+
lines.forEach((l, i) => {
|
|
60
|
+
if (!fenced.has(i) && l.text.trim()) para.push(l);
|
|
61
|
+
flush();
|
|
62
|
+
});
|
|
63
|
+
return ranges;
|
|
64
|
+
}
|
|
2
65
|
|
|
3
66
|
// The one definition of an actual mention: `@handle` at a word boundary (not
|
|
4
67
|
// foo@bar, @@x, \@x or a URL's /@x) and outside code (codeRanges). Every reader of
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve-hub",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.45",
|
|
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/world.mjs
CHANGED
|
@@ -20232,6 +20232,13 @@ var HOP_LIMIT = "(SELECT json_extract(metadata, '$.workspace.hopLimit') FROM wor
|
|
|
20232
20232
|
var heldByHopLimit = (m) => `(${m}.author_kind = 'agent' AND ${HOP_LIMIT} IS NOT NULL AND ${m}.hop >= ${HOP_LIMIT})`;
|
|
20233
20233
|
var ToolInfo = external_exports.object({ tools: external_exports.object({ static: external_exports.array(external_exports.object({ name: external_exports.string().min(1) })) }) });
|
|
20234
20234
|
|
|
20235
|
+
// ../../hosted-hub/src/store/mentionable.ts
|
|
20236
|
+
var NOW_MS = `(CAST(strftime('%s', 'now') AS INTEGER) * 1000)`;
|
|
20237
|
+
var inRoster = `NOT (runs_on = 'local' AND EXISTS (SELECT 1 FROM local_runner l, workspace_repo w
|
|
20238
|
+
WHERE l.id = 1 AND w.id = 1 AND l.setup_failed_commit = json_extract(w.metadata, '$.commit') AND l.setup_failed_until > ${NOW_MS}))`;
|
|
20239
|
+
var LEASE_LEFT = `SELECT l.setup_failed_until - ${NOW_MS} AS ms FROM local_runner l, workspace_repo w
|
|
20240
|
+
WHERE l.id = 1 AND w.id = 1 AND l.setup_failed_commit = json_extract(w.metadata, '$.commit') AND l.setup_failed_until > ${NOW_MS}`;
|
|
20241
|
+
|
|
20235
20242
|
// ../../hosted-hub/src/store/schema.ts
|
|
20236
20243
|
var OPEN_TURN_STATUSES = "('streaming','cancelling')";
|
|
20237
20244
|
|
|
@@ -20271,7 +20278,7 @@ function stepValues(sessionId2, step) {
|
|
|
20271
20278
|
return [sessionId2, step.sequence, step.stepIndex, Date.parse(step.at), b.inputTokens, b.outputTokens, b.cacheReadTokens, b.cacheWriteTokens, b.costUsd];
|
|
20272
20279
|
}
|
|
20273
20280
|
|
|
20274
|
-
// mention-
|
|
20281
|
+
// mention-tokens.mjs
|
|
20275
20282
|
function codeRanges(text) {
|
|
20276
20283
|
const s2 = String(text ?? "");
|
|
20277
20284
|
const ranges = [];
|
|
@@ -20322,8 +20329,6 @@ function codeRanges(text) {
|
|
|
20322
20329
|
});
|
|
20323
20330
|
return ranges;
|
|
20324
20331
|
}
|
|
20325
|
-
|
|
20326
|
-
// mention-tokens.mjs
|
|
20327
20332
|
function mentionTokens(text) {
|
|
20328
20333
|
const s2 = String(text ?? "");
|
|
20329
20334
|
const code = codeRanges(s2);
|
|
@@ -27240,7 +27245,7 @@ function compactedSizeStatements(sessionId2, inputTokens) {
|
|
|
27240
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);
|
|
27241
27246
|
|
|
27242
27247
|
// ../../hosted-hub/src/store/fold.ts
|
|
27243
|
-
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,
|
|
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,
|
|
27244
27249
|
(SELECT json_group_array(bot) FROM (${PARTICIPANTS("s.thread_id")})) AS participants,
|
|
27245
27250
|
(SELECT d.message_id FROM deliveries d WHERE d.bot = s.bot AND d.held_at IS NOT NULL AND d.held_paused IS NOT 1 AND d.accepted_at IS NULL AND d.failed_at IS NULL AND d.revoked_at IS NULL ORDER BY d.rowid LIMIT 1) AS held,
|
|
27246
27251
|
(SELECT json_object('person', person, 'names', json(names)) FROM human_notify) AS notify,
|