eve-hub 0.6.34 → 0.6.36
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/package.json +1 -1
- package/prepare.mjs +2 -2
- package/world.mjs +77 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# eve-hub
|
|
2
2
|
|
|
3
|
+
## 0.6.36
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- The bots' /hub/manifest reports the workspace's `hopLimit`, so the hosted hub holds bot-to-bot chains at it.
|
|
8
|
+
|
|
9
|
+
## 0.6.35
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- A bot's attach_image carries its images into its reply with their sizes; an oversized upload answers 413 naming both limits.
|
|
14
|
+
|
|
3
15
|
## 0.6.34
|
|
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.
|
|
3
|
+
"version": "0.6.36",
|
|
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/prepare.mjs
CHANGED
|
@@ -63,8 +63,8 @@ import workspace from "../../../../hub.manifest.json" with { type: "json" };
|
|
|
63
63
|
// syncs by; a deployment with none (\`vercel deploy\` uploads no git metadata)
|
|
64
64
|
// has no manifest to give.
|
|
65
65
|
const sha = process.env.VERCEL_GIT_COMMIT_SHA;
|
|
66
|
-
const { agents, humans, subagentCap } = parseWorkspace(workspace);
|
|
67
|
-
const manifest = { sha, kit: ${JSON.stringify(KIT_VERSION)}, agents, humans, subagentCap };
|
|
66
|
+
const { agents, humans, subagentCap, hopLimit } = parseWorkspace(workspace);
|
|
67
|
+
const manifest = { sha, kit: ${JSON.stringify(KIT_VERSION)}, agents, humans, subagentCap, ...(hopLimit === undefined ? {} : { hopLimit }) };
|
|
68
68
|
|
|
69
69
|
export default defineChannel({
|
|
70
70
|
routes: [
|
package/world.mjs
CHANGED
|
@@ -437,6 +437,7 @@ function derivedMessageId(...parts) {
|
|
|
437
437
|
}
|
|
438
438
|
var sessionId = () => `wrun_${ulid()}`;
|
|
439
439
|
var deliveryId = (message, bot) => `dlv_${message}_${bot}`;
|
|
440
|
+
var messageOfDelivery = (delivery, bot) => delivery.slice("dlv_".length, -`_${bot}`.length);
|
|
440
441
|
var turnId = (session, chunkIndex) => `trn_${session}_${chunkIndex}`;
|
|
441
442
|
|
|
442
443
|
// ../../hosted-hub/src/store/events.ts
|
|
@@ -495,6 +496,9 @@ function routingStatements(messageId2, threadId2, bots, now, { by, joins }, held
|
|
|
495
496
|
])
|
|
496
497
|
];
|
|
497
498
|
}
|
|
499
|
+
var hopAfter = (session) => s(`(SELECT 1 + COALESCE(MAX(m.hop), 0) FROM deliveries d JOIN messages m ON m.id = d.message_id WHERE d.session_id = ? AND (
|
|
500
|
+
EXISTS (SELECT 1 FROM turn_deliveries td WHERE td.delivery_id = d.id AND td.turn_id = (SELECT id FROM turns WHERE session_id = ? ORDER BY started_at DESC, rowid DESC LIMIT 1))
|
|
501
|
+
OR (d.accepted_at IS NOT NULL AND NOT EXISTS (SELECT 1 FROM turn_deliveries td WHERE td.delivery_id = d.id))))`, session, session);
|
|
498
502
|
|
|
499
503
|
// subagent-cap.mjs
|
|
500
504
|
var DEFAULT_SUBAGENT_CAP = Object.freeze({
|
|
@@ -505,6 +509,8 @@ var DEFAULT_SUBAGENT_CAP = Object.freeze({
|
|
|
505
509
|
|
|
506
510
|
// ../../hosted-hub/src/store/roster.ts
|
|
507
511
|
var onLocal = (bot) => `EXISTS (SELECT 1 FROM bots WHERE name = ${bot} AND runs_on = 'local')`;
|
|
512
|
+
var HOP_LIMIT = "(SELECT json_extract(metadata, '$.workspace.hopLimit') FROM workspace_repo WHERE id = 1)";
|
|
513
|
+
var heldByHopLimit = (m) => `(${m}.author_kind = 'agent' AND ${HOP_LIMIT} IS NOT NULL AND ${m}.hop >= ${HOP_LIMIT})`;
|
|
508
514
|
|
|
509
515
|
// ../../hosted-hub/src/store/schema.ts
|
|
510
516
|
var OPEN_TURN_STATUSES = "('streaming','cancelling')";
|
|
@@ -635,6 +641,29 @@ function linkStatements(sessionId2, parent, callId) {
|
|
|
635
641
|
];
|
|
636
642
|
}
|
|
637
643
|
|
|
644
|
+
// ../../hosted-hub/src/store/failures.ts
|
|
645
|
+
var STATE = "json_extract(event, '$.state')";
|
|
646
|
+
var failureId = (trigger, bot) => `evt_fail_${trigger}_${bot}`;
|
|
647
|
+
var cardLog = (idSql, now, ...args) => s(`INSERT INTO log (thread_id, type, data, at) SELECT thread_id, 'message.updated', json_object('threadId', thread_id, 'messageId', id), ? FROM messages WHERE id = (${idSql}) AND changes() > 0`, now, ...args);
|
|
648
|
+
function failureStatements(t, now) {
|
|
649
|
+
if (!t.trigger) return [];
|
|
650
|
+
const id = failureId(t.trigger, t.bot), detail = t.error ?? "unknown error";
|
|
651
|
+
const turn = (status) => s("EXISTS (SELECT 1 FROM turns WHERE id = ? AND status = ?)", t.id, status);
|
|
652
|
+
const failed = turn("failed"), settled = (status, next) => {
|
|
653
|
+
const when = turn(status);
|
|
654
|
+
return [s(`UPDATE messages SET event = json_set(event, '$.state', ?) WHERE id = ? AND ${STATE} = 'retrying' AND ${when.sql}`, next, id, ...when.args), cardLog("?", now, id)];
|
|
655
|
+
};
|
|
656
|
+
return [
|
|
657
|
+
...eventStatements(t.threadId, { kind: "turn_failed", agent: t.bot, triggerId: t.trigger, state: "failed", retries: 0, turnId: t.id, detail }, `${t.bot}'s turn failed: ${detail}`, now, id, failed),
|
|
658
|
+
s(`UPDATE messages SET text = ?, event = json_set(event, '$.state', 'failed', '$.detail', ?, '$.turnId', ?, '$.retries', json_extract(event, '$.retries') + 1)
|
|
659
|
+
WHERE id = ? AND ${STATE} = 'retrying' AND json_extract(event, '$.turnId') <> ? AND ${failed.sql}`, `${t.bot}'s turn failed: ${detail}`, detail, t.id, id, t.id, ...failed.args),
|
|
660
|
+
cardLog("?", now, id),
|
|
661
|
+
...settled("done", "resolved"),
|
|
662
|
+
...settled("cancelled", "failed")
|
|
663
|
+
];
|
|
664
|
+
}
|
|
665
|
+
var triggerOf = (t) => `(SELECT d.message_id FROM turn_deliveries td JOIN deliveries d ON d.id = td.delivery_id WHERE td.turn_id = ${t}.id ORDER BY d.rowid LIMIT 1)`;
|
|
666
|
+
|
|
638
667
|
// ../../lib/tags.mjs
|
|
639
668
|
var TAG_FIELDS = ["project", "issueType"];
|
|
640
669
|
var LABEL_FIELDS = [...TAG_FIELDS, "path"];
|
|
@@ -670,6 +699,8 @@ var PENDING_REQUESTS_READ = s(`SELECT r.id, r.session_id, r.thread_id, r.bot, r.
|
|
|
670
699
|
var LIVE_TURNS_READ = s(`SELECT thread_id,bot,started_at,reply_text,activity FROM turns WHERE status IN ${OPEN_TURN_STATUSES} ORDER BY started_at`);
|
|
671
700
|
|
|
672
701
|
// ../../hosted-hub/src/store/attachments.ts
|
|
702
|
+
var MAX_ATTACHMENTS = 10;
|
|
703
|
+
var OPEN_TURN = `(SELECT id FROM turns WHERE session_id = ? AND status IN ${OPEN_TURN_STATUSES} ORDER BY started_at DESC LIMIT 1)`;
|
|
673
704
|
var ATTACHMENTS_READ = s("SELECT message_id, upload_id, name FROM message_attachments ORDER BY message_id, position");
|
|
674
705
|
var unseenBy = (bot, thread, mid) => {
|
|
675
706
|
const end = `COALESCE((SELECT rowid FROM messages WHERE id = ${mid}), 9223372036854775807)`;
|
|
@@ -5746,7 +5777,7 @@ var $ZodCyclicError = class extends Error {
|
|
|
5746
5777
|
this.name = "ZodCyclicError";
|
|
5747
5778
|
}
|
|
5748
5779
|
};
|
|
5749
|
-
var
|
|
5780
|
+
var STATE2 = "~memo";
|
|
5750
5781
|
var NO_ISSUES = [];
|
|
5751
5782
|
function isRef(value) {
|
|
5752
5783
|
return value !== null && typeof value === "object";
|
|
@@ -5960,10 +5991,10 @@ var memo = {
|
|
|
5960
5991
|
const input2 = payload.value;
|
|
5961
5992
|
if (!isRef(input2))
|
|
5962
5993
|
return base(payload, ctx);
|
|
5963
|
-
let state = ctx[
|
|
5994
|
+
let state = ctx[STATE2];
|
|
5964
5995
|
if (!state) {
|
|
5965
5996
|
state = { buckets: /* @__PURE__ */ new WeakMap(), backEdges: void 0 };
|
|
5966
|
-
ctx[
|
|
5997
|
+
ctx[STATE2] = state;
|
|
5967
5998
|
}
|
|
5968
5999
|
let bucket;
|
|
5969
6000
|
if (lastCtx === ctx) {
|
|
@@ -6012,7 +6043,7 @@ function memoizer() {
|
|
|
6012
6043
|
return memo;
|
|
6013
6044
|
}
|
|
6014
6045
|
function isBackEdge(ctx, value) {
|
|
6015
|
-
const backEdges = ctx[
|
|
6046
|
+
const backEdges = ctx[STATE2]?.backEdges;
|
|
6016
6047
|
return backEdges !== void 0 && isRef(value) && backEdges.has(value);
|
|
6017
6048
|
}
|
|
6018
6049
|
|
|
@@ -23600,7 +23631,7 @@ var $ZodCyclicError2 = class extends Error {
|
|
|
23600
23631
|
this.name = "ZodCyclicError";
|
|
23601
23632
|
}
|
|
23602
23633
|
};
|
|
23603
|
-
var
|
|
23634
|
+
var STATE3 = "~memo";
|
|
23604
23635
|
var NO_ISSUES2 = [];
|
|
23605
23636
|
function cloneIssues2(issues) {
|
|
23606
23637
|
return issues.map((iss) => iss.path ? { ...iss, path: iss.path.slice() } : { ...iss });
|
|
@@ -23775,10 +23806,10 @@ var memo2 = {
|
|
|
23775
23806
|
const input2 = payload.value;
|
|
23776
23807
|
if (input2 === null || typeof input2 !== "object")
|
|
23777
23808
|
return base(payload, ctx);
|
|
23778
|
-
let state = ctx[
|
|
23809
|
+
let state = ctx[STATE3];
|
|
23779
23810
|
if (!state) {
|
|
23780
23811
|
state = { buckets: /* @__PURE__ */ new Map(), backEdges: void 0 };
|
|
23781
|
-
ctx[
|
|
23812
|
+
ctx[STATE3] = state;
|
|
23782
23813
|
}
|
|
23783
23814
|
let bucket;
|
|
23784
23815
|
if (lastCtx === ctx) {
|
|
@@ -23827,7 +23858,7 @@ function memoizer2() {
|
|
|
23827
23858
|
return memo2;
|
|
23828
23859
|
}
|
|
23829
23860
|
function isBackEdge2(ctx, value) {
|
|
23830
|
-
const backEdges = ctx[
|
|
23861
|
+
const backEdges = ctx[STATE3]?.backEdges;
|
|
23831
23862
|
return backEdges !== void 0 && value !== null && typeof value === "object" && backEdges.has(value);
|
|
23832
23863
|
}
|
|
23833
23864
|
|
|
@@ -27052,7 +27083,8 @@ var Cap = Requested.extend({ models: external_exports.array(external_exports.str
|
|
|
27052
27083
|
var DeployedWorkspace = external_exports.object({
|
|
27053
27084
|
agents: external_exports.array(external_exports.looseObject({ name: external_exports.string(), role: external_exports.string(), color: external_exports.string(), model: external_exports.string(), runsOn: external_exports.enum(["hosted", "local"]).optional(), subagents: external_exports.record(external_exports.string(), Requested).optional(), subagentCap: Cap.optional() })),
|
|
27054
27085
|
humans: external_exports.array(external_exports.looseObject({ name: external_exports.string(), color: external_exports.string().optional() })).optional(),
|
|
27055
|
-
subagentCap: Cap.optional()
|
|
27086
|
+
subagentCap: Cap.optional(),
|
|
27087
|
+
hopLimit: external_exports.int().min(1).nullable().optional()
|
|
27056
27088
|
});
|
|
27057
27089
|
var Upgrade = external_exports.object({
|
|
27058
27090
|
to: external_exports.string(),
|
|
@@ -27085,6 +27117,7 @@ var PENDING_FROM = `SELECT d.id, d.message_id, d.session_id, d.bot, m.thread_id,
|
|
|
27085
27117
|
s.ended_at IS NOT NULL AS session_ended, ${onLocal("d.bot")} AS on_local,
|
|
27086
27118
|
(SELECT json_group_array(json_object('id', a.upload_id, 'name', a.name, 'size', a.size)) FROM (SELECT * FROM message_attachments WHERE message_id = m.id ORDER BY position) a) AS attachments
|
|
27087
27119
|
FROM deliveries d JOIN messages m ON m.id = d.message_id JOIN threads t ON t.id = m.thread_id JOIN sessions s ON s.id = d.session_id`;
|
|
27120
|
+
var UNSETTLED = `d.accepted_at IS NULL AND d.failed_at IS NULL AND d.revoked_at IS NULL AND d.held_at IS NULL AND NOT ${heldByHopLimit("m")}`;
|
|
27088
27121
|
var TASK_CARD = `(SELECT CASE WHEN json_array_length(json_extract(t.activity, '$.taskCard.tasks')) > 0 THEN json_extract(t.activity, '$.taskCard') END
|
|
27089
27122
|
FROM turns t WHERE t.id = m.turn_id AND m.author_kind = 'agent' AND t.status NOT IN ${OPEN_TURN_STATUSES}
|
|
27090
27123
|
AND m.rowid = (SELECT MAX(x.rowid) FROM messages x WHERE x.turn_id = m.turn_id))`;
|
|
@@ -27095,7 +27128,7 @@ var DELIVERY_STATUS = `CASE WHEN d.accepted_at IS NOT NULL OR ${LINKED} THEN COA
|
|
|
27095
27128
|
WHERE r.session_id = d.session_id AND r.status = 'pending' AND rs.ended_at IS NULL
|
|
27096
27129
|
AND r.created_at <= COALESCE((SELECT t.started_at FROM turn_deliveries td JOIN turns t ON t.id = td.turn_id WHERE td.delivery_id = d.id), d.accepted_at) LIMIT 1),
|
|
27097
27130
|
CASE WHEN ${LINKED} THEN 'seen' ELSE 'delivered' END)
|
|
27098
|
-
WHEN d.failed_at IS NOT NULL THEN 'failed' WHEN d.revoked_at IS NOT NULL THEN 'skipped'
|
|
27131
|
+
WHEN d.failed_at IS NOT NULL THEN 'failed' WHEN d.revoked_at IS NOT NULL THEN 'skipped' WHEN EXISTS (SELECT 1 FROM messages hm WHERE hm.id = d.message_id AND ${heldByHopLimit("hm")}) THEN 'blocked: hop limit'
|
|
27099
27132
|
WHEN d.held_at IS NOT NULL THEN CASE d.held_scope WHEN 'bot' THEN 'queued until free' ELSE 'queued' END
|
|
27100
27133
|
WHEN ${onLocal("d.bot")} AND EXISTS (SELECT 1 FROM local_runner WHERE id = 1 AND device IS NOT NULL AND attachments = 0)
|
|
27101
27134
|
AND (EXISTS (SELECT 1 FROM message_attachments o WHERE o.message_id = d.message_id)
|
|
@@ -27103,12 +27136,18 @@ var DELIVERY_STATUS = `CASE WHEN d.accepted_at IS NOT NULL OR ${LINKED} THEN COA
|
|
|
27103
27136
|
THEN 'waiting: the Mac app running this bot is too old to carry images; update it'
|
|
27104
27137
|
ELSE 'pending' END`;
|
|
27105
27138
|
|
|
27139
|
+
// ../../hosted-hub/src/store/local-runner.ts
|
|
27140
|
+
var RESTARTED_TURNS_READ = s(`SELECT t.thread_id, t.bot, r.claimed_at FROM turns t, local_runner r
|
|
27141
|
+
WHERE r.id = 1 AND t.status IN ${OPEN_TURN_STATUSES} AND ${onLocal("t.bot")} AND t.started_at < r.claimed_at
|
|
27142
|
+
AND NOT EXISTS (SELECT 1 FROM session_folds f WHERE f.session_id = t.session_id AND f.folded_at >= r.claimed_at)`);
|
|
27143
|
+
|
|
27106
27144
|
// ../../hosted-hub/src/store/fold.ts
|
|
27107
27145
|
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,
|
|
27108
27146
|
(SELECT json_group_array(bot) FROM (${PARTICIPANTS("s.thread_id")})) AS participants,
|
|
27109
27147
|
(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,
|
|
27110
27148
|
(SELECT json_object('person', person, 'names', json(names)) FROM human_notify) AS notify,
|
|
27111
|
-
(SELECT json_object('status', t.status, 'id', t.id, 'text', t.reply_text, 'lastStep', json(t.last_step), 'activity', json(t.activity)
|
|
27149
|
+
(SELECT json_object('status', t.status, 'id', t.id, 'text', t.reply_text, 'lastStep', json(t.last_step), 'activity', json(t.activity),
|
|
27150
|
+
'trigger', ${triggerOf("t")}) FROM turns t WHERE t.session_id = s.id AND t.status IN ${OPEN_TURN_STATUSES}
|
|
27112
27151
|
ORDER BY t.started_at DESC LIMIT 1) AS open_turn
|
|
27113
27152
|
FROM sessions s LEFT JOIN session_folds f ON f.session_id = s.id WHERE s.id = ?`;
|
|
27114
27153
|
function foldState(row) {
|
|
@@ -27132,7 +27171,7 @@ function fold(state, chunks, now = Date.now()) {
|
|
|
27132
27171
|
const { session } = state;
|
|
27133
27172
|
const stmts = [], touched = /* @__PURE__ */ new Map();
|
|
27134
27173
|
const log = (type, data, when = "") => stmts.push(s(`INSERT INTO log (thread_id, type, data, at) SELECT ?, ?, ?, ? ${when}`, session.thread, type, JSON.stringify({ threadId: session.thread, agent: session.bot, ...data }), at));
|
|
27135
|
-
let open3 = state.open && { ...state.open, lastStep: state.open.lastStep ?? null, status: state.open.status, endedAt: null, error: null };
|
|
27174
|
+
let open3 = state.open && { ...state.open, trigger: state.open.trigger ?? null, lastStep: state.open.lastStep ?? null, status: state.open.status, endedAt: null, error: null };
|
|
27136
27175
|
const deliver = [];
|
|
27137
27176
|
let last = state.foldedIndex;
|
|
27138
27177
|
let at = now;
|
|
@@ -27156,6 +27195,7 @@ function fold(state, chunks, now = Date.now()) {
|
|
|
27156
27195
|
reduceActivity(open3.activity, { type: "turn.cancelled" }, at, cutOff(open3, "turn.cancelled"));
|
|
27157
27196
|
Object.assign(open3, { status: open3.status === "cancelling" ? "cancelled" : status, endedAt: at, error: error63 });
|
|
27158
27197
|
touched.set(open3.id, open3);
|
|
27198
|
+
stmts.push(s("DELETE FROM turn_attachments WHERE turn_id = ?", open3.id));
|
|
27159
27199
|
log("turn.status", { turnId: open3.id, status: open3.status });
|
|
27160
27200
|
open3 = null;
|
|
27161
27201
|
};
|
|
@@ -27180,15 +27220,17 @@ function fold(state, chunks, now = Date.now()) {
|
|
|
27180
27220
|
if (!data.turnId) throw new Error("turn.started must name eve turnId");
|
|
27181
27221
|
flush();
|
|
27182
27222
|
end("cancelled", "superseded by a new turn");
|
|
27183
|
-
open3 = { activity: initActivity(), id: turnId(session.id, index), text: "", lastStep: null, status: "streaming", endedAt: null, error: null };
|
|
27223
|
+
open3 = { activity: initActivity(), id: turnId(session.id, index), trigger: null, text: "", lastStep: null, status: "streaming", endedAt: null, error: null };
|
|
27184
27224
|
touched.set(open3.id, open3);
|
|
27185
27225
|
stmts.push(s(`INSERT OR IGNORE INTO turns (id, thread_id, session_id, eve_turn_id, bot, status, started_at)
|
|
27186
|
-
|
|
27226
|
+
SELECT ?, ?, ?, ?, ?, 'streaming', ? WHERE EXISTS (SELECT 1 FROM sessions WHERE id = ? AND ended_at IS NULL)`, open3.id, session.thread, session.id, data.turnId, session.bot, at, session.id));
|
|
27187
27227
|
log("turn.status", { turnId: open3.id, status: "streaming" });
|
|
27188
27228
|
}
|
|
27189
27229
|
if (!open3) continue;
|
|
27190
|
-
for (const deliveryId2 of event.meta?.deliveryIds ?? [])
|
|
27230
|
+
for (const deliveryId2 of event.meta?.deliveryIds ?? []) {
|
|
27231
|
+
open3.trigger ??= messageOfDelivery(deliveryId2, session.bot);
|
|
27191
27232
|
stmts.push(s("INSERT OR IGNORE INTO turn_deliveries (delivery_id, turn_id) SELECT id, ? FROM deliveries WHERE id = ? AND session_id = ?", open3.id, deliveryId2, session.id));
|
|
27233
|
+
}
|
|
27192
27234
|
if (event.meta?.deliveryIds?.length) touched.set(open3.id, open3);
|
|
27193
27235
|
const activityEvent = event.type === "message.completed" ? { ...event, data: { ...data, message: data.message ?? open3.text } } : event;
|
|
27194
27236
|
if (reduceActivity(open3.activity, activityEvent, at, cutOff(open3, event.type, data.turnId))) {
|
|
@@ -27229,6 +27271,10 @@ function fold(state, chunks, now = Date.now()) {
|
|
|
27229
27271
|
break;
|
|
27230
27272
|
}
|
|
27231
27273
|
case "action.result": {
|
|
27274
|
+
const attachment = data.result?.output?.attachment;
|
|
27275
|
+
if (data.result?.toolName === "attach_image" && data.status === "completed" && typeof attachment?.id === "string" && typeof attachment.name === "string" && typeof attachment.size === "number")
|
|
27276
|
+
stmts.push(s(`INSERT OR IGNORE INTO turn_attachments (turn_id, position, upload_id, name, size)
|
|
27277
|
+
SELECT ?, n, ?, ?, ? FROM (SELECT count(*) AS n FROM turn_attachments WHERE turn_id = ?) WHERE n < ?`, open3.id, attachment.id, attachment.name, attachment.size, open3.id, MAX_ATTACHMENTS));
|
|
27232
27278
|
const ls = open3.lastStep, callId = data.result?.callId;
|
|
27233
27279
|
if (!ls || !callId || ls.calls[callId] !== null) break;
|
|
27234
27280
|
const postOutput = data.result?.output;
|
|
@@ -27242,14 +27288,17 @@ function fold(state, chunks, now = Date.now()) {
|
|
|
27242
27288
|
break;
|
|
27243
27289
|
case "turn.completed": {
|
|
27244
27290
|
flush();
|
|
27245
|
-
const text = open3.text.trim();
|
|
27246
|
-
if (open3.status !== "cancelling"
|
|
27291
|
+
const text = lastActWasOwnPost(open3.lastStep) ? "" : open3.text.trim();
|
|
27292
|
+
if (open3.status !== "cancelling") {
|
|
27247
27293
|
const messageId2 = derivedMessageId(open3.id);
|
|
27248
|
-
|
|
27249
|
-
|
|
27250
|
-
|
|
27294
|
+
const hop = hopAfter(session.id);
|
|
27295
|
+
stmts.push(s(`INSERT OR IGNORE INTO messages (id, thread_id, author, author_kind, text, turn_id, created_at, hop)
|
|
27296
|
+
SELECT ?, ?, ?, 'agent', ?, ?, ?, ${hop.sql} WHERE (? <> '' OR EXISTS (SELECT 1 FROM turn_attachments WHERE turn_id = ?))
|
|
27297
|
+
AND EXISTS (SELECT 1 FROM turns WHERE id = ? AND status NOT IN ('cancelling','cancelled') AND NOT (${REVOKED_TURN}))`, messageId2, session.thread, session.bot, text, open3.id, at, ...hop.args, text, open3.id, open3.id));
|
|
27251
27298
|
log("message.created", { messageId: messageId2, author: session.bot, authorKind: "agent" }, IF_INSERTED);
|
|
27252
27299
|
stmts.push(...notificationFor(messageId2, "agent", text, state.notify ?? void 0));
|
|
27300
|
+
stmts.push(s(`INSERT OR IGNORE INTO message_attachments (message_id, position, upload_id, name, size)
|
|
27301
|
+
SELECT ?, position, upload_id, name, size FROM turn_attachments WHERE turn_id = ? AND EXISTS (SELECT 1 FROM messages WHERE id = ?) ORDER BY position`, messageId2, open3.id, messageId2));
|
|
27253
27302
|
const to = recipients(state.roster, text, { name: session.bot, kind: "agent" }, session.thread, state.participants);
|
|
27254
27303
|
stmts.push(...routingStatements(messageId2, session.thread, to, at, { by: session.bot, joins: true }));
|
|
27255
27304
|
deliver.push(messageId2);
|
|
@@ -27297,10 +27346,15 @@ function fold(state, chunks, now = Date.now()) {
|
|
|
27297
27346
|
JSON.stringify(t.activity),
|
|
27298
27347
|
t.id
|
|
27299
27348
|
));
|
|
27349
|
+
if (t.endedAt !== null) stmts.push(...failureStatements({ id: t.id, threadId: session.thread, bot: session.bot, trigger: t.trigger, status: t.status, error: t.error }, t.endedAt));
|
|
27350
|
+
}
|
|
27351
|
+
if (last > state.foldedIndex) {
|
|
27352
|
+
stmts.push(s(`INSERT INTO log (thread_id, type, data, at) SELECT t.thread_id, 'turn.status', json_object('turnId', t.id, 'status', t.status), ?
|
|
27353
|
+
FROM turns t, local_runner r WHERE t.session_id = ? AND r.id = 1 AND t.status IN ${OPEN_TURN_STATUSES} AND t.started_at < r.claimed_at AND ${onLocal("t.bot")}
|
|
27354
|
+
AND NOT EXISTS (SELECT 1 FROM session_folds f WHERE f.session_id = t.session_id AND f.folded_at >= r.claimed_at)`, now, session.id));
|
|
27355
|
+
stmts.push(s(`INSERT INTO session_folds (session_id, folded_index, folded_at) VALUES (?, ?, ?)
|
|
27356
|
+
ON CONFLICT (session_id) DO UPDATE SET folded_index = excluded.folded_index, folded_at = excluded.folded_at`, session.id, last, now));
|
|
27300
27357
|
}
|
|
27301
|
-
if (last > state.foldedIndex)
|
|
27302
|
-
stmts.push(s(`INSERT INTO session_folds (session_id, folded_index) VALUES (?, ?)
|
|
27303
|
-
ON CONFLICT (session_id) DO UPDATE SET folded_index = excluded.folded_index`, session.id, last));
|
|
27304
27358
|
return { statements: stmts, deliver };
|
|
27305
27359
|
}
|
|
27306
27360
|
async function foldInTx(tx, sessionId2, chunks) {
|