volute 0.46.0 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{activity-events-NF6VWTJQ.js → activity-events-MIOK3IOU.js} +3 -3
- package/dist/{ai-service-UODCCE4O.js → ai-service-CVZEYKTK.js} +4 -4
- package/dist/{archive-WS2L2VIQ.js → archive-6Z4GFQPH.js} +3 -3
- package/dist/{auth-CCFAU4GQ.js → auth-A4VGHADI.js} +4 -4
- package/dist/avatar-image-7S3WA77A.js +22 -0
- package/dist/{backup-TST5C2YN.js → backup-IIAFOW2L.js} +13 -13
- package/dist/channels-ITE4YC57.js +89 -0
- package/dist/{chat-ZIQQS25U.js → chat-AJLJCQ3M.js} +12 -8
- package/dist/{chunk-ZV7MFISX.js → chunk-2MJ7EOMT.js} +20 -2
- package/dist/{chunk-R77O2WMK.js → chunk-2OIYNHWO.js} +1 -1
- package/dist/{chunk-QCN24XEN.js → chunk-3YUBFTDN.js} +1 -1
- package/dist/{chunk-E3DA4HYV.js → chunk-4I72V3E5.js} +10 -10
- package/dist/{chunk-K6T43YBD.js → chunk-5IERLDUS.js} +3 -3
- package/dist/{chunk-FXORA5JG.js → chunk-5NN2VHJV.js} +3 -3
- package/dist/chunk-7KRIHYLR.js +124 -0
- package/dist/{chunk-RRNXJOKB.js → chunk-BGYHLR54.js} +2 -2
- package/dist/{chunk-QMJCNZ6C.js → chunk-C3KLHJDB.js} +1 -1
- package/dist/{chunk-TQJ6ZYVY.js → chunk-CBOIHNMR.js} +2 -2
- package/dist/{chunk-H2X54EHC.js → chunk-DGGZVZTM.js} +1 -1
- package/dist/{chunk-4JOQZPCE.js → chunk-EIQDZC43.js} +1 -1
- package/dist/{chunk-JO5IO4FH.js → chunk-F55GRIEK.js} +243 -121
- package/dist/{chunk-5ZQZDDIK.js → chunk-HPGN6XRT.js} +3 -3
- package/dist/{chunk-KGIXX4NM.js → chunk-IWJSNMSY.js} +5 -5
- package/dist/{chunk-ZDZISKCL.js → chunk-IYG4FBMP.js} +1 -1
- package/dist/{chunk-4YU7HF4L.js → chunk-JCMGDCGX.js} +4 -4
- package/dist/{chunk-PJ45FQPT.js → chunk-JSVHH32K.js} +6 -6
- package/dist/{chunk-YXSUMLTC.js → chunk-K23P5Q5N.js} +301 -77
- package/dist/{chunk-ZNMCCHCP.js → chunk-LTLFOSA4.js} +2 -2
- package/dist/{chunk-IHKGWTGT.js → chunk-LWDTP6DH.js} +1 -1
- package/dist/{chunk-JZ62SYWR.js → chunk-M3XDVS5Q.js} +1 -1
- package/dist/{chunk-BJZ4PV7R.js → chunk-M6TTZRGH.js} +9 -9
- package/dist/{chunk-KQSFTPIM.js → chunk-MTRMQFCQ.js} +1 -1
- package/dist/{chunk-OV7ZQ2GH.js → chunk-ODDGGLM6.js} +3 -3
- package/dist/{chunk-QLWG3C2Z.js → chunk-RRZ4RQQU.js} +2 -2
- package/dist/{chunk-CDPBTTZO.js → chunk-RUFLGTOT.js} +2 -2
- package/dist/{chunk-F7H6ATM4.js → chunk-SKNXMUIU.js} +1 -1
- package/dist/{chunk-RXEEYDIB.js → chunk-SZJCJVXV.js} +1 -1
- package/dist/{chunk-DRJ24GXK.js → chunk-VMCZBXF2.js} +52 -8
- package/dist/{chunk-ALKYQULU.js → chunk-WW6C3PLV.js} +1 -1
- package/dist/{chunk-A7WQZKOU.js → chunk-XHN6XBWV.js} +2 -2
- package/dist/{chunk-6EMWJZBK.js → chunk-YKA7DCVW.js} +1 -1
- package/dist/cli.js +21 -21
- package/dist/{clock-RHS2JEDL.js → clock-E6N5Y3YW.js} +3 -3
- package/dist/{cloud-sync-46RS4SDA.js → cloud-sync-LQTVDTQ3.js} +19 -18
- package/dist/{conversations-CJOOCGNW.js → conversations-C7IKYSHD.js} +4 -4
- package/dist/{create-IOV4GCRX.js → create-PQQXKTJK.js} +1 -1
- package/dist/{daemon-restart-VFEI57UO.js → daemon-restart-5F3YTLZK.js} +7 -7
- package/dist/daemon.js +217 -151
- package/dist/{db-MF2JNRUW.js → db-FO6LXYCW.js} +2 -2
- package/dist/delivery-manager-TN5KK2AP.js +34 -0
- package/dist/{delivery-router-N4A7ZC5T.js → delivery-router-3QFG2ZEX.js} +3 -3
- package/dist/{down-U2CZ23M4.js → down-ZI4S6265.js} +5 -5
- package/dist/echo-text-SEQCLGAT.js +34 -0
- package/dist/{exec-G3ZRST4Z.js → exec-QIFYZG4C.js} +3 -3
- package/dist/{export-LY723I3Z.js → export-4GVGNW54.js} +3 -3
- package/dist/{extensions-ZELQLTSR.js → extensions-PIMIQ7J3.js} +21 -18
- package/dist/{files-4LN3EN7Q.js → files-FEFZKMNM.js} +6 -6
- package/dist/{import-42YNQBF4.js → import-7MO3YTRE.js} +6 -6
- package/dist/{isolation-YMGZZ4E5.js → isolation-MCT4ZYLT.js} +3 -3
- package/dist/{login-M6OJUPQ2.js → login-OF4WXDAN.js} +5 -5
- package/dist/{logout-WQBWO77G.js → logout-ERE2BGA3.js} +5 -5
- package/dist/message-delivery-ZE3YGJDD.js +38 -0
- package/dist/{mind-LHKS55DI.js → mind-POOHFZHP.js} +13 -13
- package/dist/{mind-activity-tracker-3QRNJVR4.js → mind-activity-tracker-YVZPC4A5.js} +4 -4
- package/dist/{mind-list-4D7J4CHD.js → mind-list-KEGRGQEQ.js} +5 -4
- package/dist/mind-service-JFY7UG5E.js +40 -0
- package/dist/{mind-sleep-74TGOQBC.js → mind-sleep-IN3WPA76.js} +5 -5
- package/dist/{mind-status-UO34ASXZ.js → mind-status-SMUWJKGV.js} +20 -3
- package/dist/{package-DOD6CPO6.js → package-WPEE2HVJ.js} +2 -2
- package/dist/{registry-OUZBZ3Q4.js → registry-UMMDRPRM.js} +2 -2
- package/dist/{sandbox-ZJ7QA6Z6.js → sandbox-G4X4K3UN.js} +4 -4
- package/dist/scheduler-HQSDYJFY.js +32 -0
- package/dist/{schema-PVNG3PQM.js → schema-VEVO7HG6.js} +3 -1
- package/dist/{seed-CNYIHPOH.js → seed-VANPU43L.js} +1 -1
- package/dist/{seed-cmd-AVNUNLZV.js → seed-cmd-SYVDZKM4.js} +2 -2
- package/dist/{seed-create-ANXGYSCC.js → seed-create-3FGZPS6C.js} +3 -3
- package/dist/{seed-sprout-NIUFTX32.js → seed-sprout-H7QLFPFM.js} +12 -12
- package/dist/{send-SPE6DVNJ.js → send-HYDFGC6G.js} +7 -7
- package/dist/{service-UOCLXDWR.js → service-SYJ5G6LP.js} +4 -4
- package/dist/{service-install-4HHFDDWY.js → service-install-FQ43Z4DF.js} +5 -5
- package/dist/{setup-Y2EJI3GG.js → setup-KFYVWTXG.js} +3 -3
- package/dist/{setup-QT2A25SY.js → setup-QJHGMGSN.js} +7 -7
- package/dist/{skills-AKCFA7BN.js → skills-L2CMTW7A.js} +5 -5
- package/dist/sleep-manager-3NA7ZJP3.js +36 -0
- package/dist/{spirit-RPBLLUQ5.js → spirit-WXN4IDBF.js} +8 -8
- package/dist/{sprout-SMX42ZBP.js → sprout-LTL5P36T.js} +1 -1
- package/dist/{status-SWRVGXBI.js → status-V4RJMHJ4.js} +19 -9
- package/dist/system-chat-N2F7HVY3.js +38 -0
- package/dist/{systems-VNB5WKSS.js → systems-B5YJKMW4.js} +6 -6
- package/dist/{tailscale-3XOKOW7T.js → tailscale-MCLY5GYE.js} +2 -2
- package/dist/{template-hash-446HHH5V.js → template-hash-GSOUARW4.js} +2 -2
- package/dist/template-staleness-EMQORSGG.js +15 -0
- package/dist/{turn-tracker-FOIBNUUA.js → turn-tracker-JZRZDFWV.js} +6 -6
- package/dist/{up-PS6PFS75.js → up-J2PBPOZL.js} +6 -6
- package/dist/{update-SWAYZRWJ.js → update-ACV4SAY3.js} +5 -5
- package/dist/{update-check-PQ2MZ47K.js → update-check-266R4ZSY.js} +3 -3
- package/dist/{version-notify-C5CH7CVP.js → version-notify-XRGTEEDK.js} +37 -23
- package/dist/web-assets/assets/index-DtctoDXY.css +1 -0
- package/dist/web-assets/assets/index-Wpyb2CML.js +86 -0
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0011_drop_turn_summary_event_id.sql +3 -0
- package/drizzle/0012_channel_gates.sql +17 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +2 -2
- package/templates/_base/src/lib/startup.ts +43 -2
- package/templates/claude/src/agent.ts +28 -2
- package/templates/claude/src/lib/session-reaper.ts +32 -0
- package/templates/claude/src/server.ts +10 -1
- package/dist/avatar-image-6KY6UU4D.js +0 -16
- package/dist/delivery-manager-JINZRG2W.js +0 -33
- package/dist/echo-text-VQPB5L2X.js +0 -33
- package/dist/message-delivery-R7JSQGYX.js +0 -37
- package/dist/mind-service-NB2JMWQZ.js +0 -39
- package/dist/scheduler-WVKII3LA.js +0 -31
- package/dist/sleep-manager-G6TXSDP7.js +0 -35
- package/dist/system-chat-NDAW6YP7.js +0 -37
- package/dist/web-assets/assets/index-B1JBQv2m.css +0 -1
- package/dist/web-assets/assets/index-CU6XWICM.js +0 -86
- package/dist/{accept-N5XULCXK.js → accept-YAFP5JFJ.js} +3 -3
- package/dist/{bridge-2PO3AI5D.js → bridge-TIZGSXOD.js} +3 -3
- package/dist/{create-DF3KISTW.js → create-A7PDHIIL.js} +3 -3
- package/dist/{env-VZ4MLFQW.js → env-HRL2PWAT.js} +5 -5
- package/dist/{extension-SEID47SR.js → extension-QBY4C44L.js} +3 -3
- package/dist/{list-OXIAY3W7.js → list-LQO2DCIK.js} +3 -3
- package/dist/{login-MY6ETFYB.js → login-6TLMI2TQ.js} +3 -3
- package/dist/{logout-NCG3TMDL.js → logout-BK53HXNY.js} +3 -3
- package/dist/{mind-history-VRO5A76U.js → mind-history-47DN6ILW.js} +4 -4
- package/dist/{mind-wake-LCLGTXA2.js → mind-wake-R54BPESY.js} +3 -3
- package/dist/{read-QVAXMTPV.js → read-PWAJOQIQ.js} +3 -3
- package/dist/{register-Y2H4PY5R.js → register-7SZJFHU6.js} +3 -3
- package/dist/{reject-EV35X64Y.js → reject-6VH7N2A4.js} +3 -3
- package/dist/{restart-FJQ662XJ.js → restart-H5WJDMA7.js} +4 -4
- package/dist/{skill-FKFHIJRR.js → skill-GUKG2YVH.js} +5 -5
- package/dist/{start-5JE3TV66.js → start-X46I3GXB.js} +4 -4
- package/dist/{stop-AAMTG3TU.js → stop-HJQV4YSM.js} +4 -4
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
getPrompt
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JCMGDCGX.js";
|
|
5
5
|
import {
|
|
6
6
|
aiCompleteUtility
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LWDTP6DH.js";
|
|
8
8
|
import {
|
|
9
9
|
logger_default
|
|
10
10
|
} from "./chunk-T2TP6ZC6.js";
|
|
11
11
|
import {
|
|
12
12
|
getDb
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WW6C3PLV.js";
|
|
14
14
|
import {
|
|
15
15
|
messages,
|
|
16
16
|
mindHistory,
|
|
17
17
|
summaries,
|
|
18
18
|
turns
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-2MJ7EOMT.js";
|
|
20
20
|
|
|
21
21
|
// packages/daemon/src/lib/daemon/turn-tracker.ts
|
|
22
22
|
import { randomUUID } from "crypto";
|
|
@@ -82,10 +82,8 @@ function summarizeTool(name, input) {
|
|
|
82
82
|
return `[${name}]`;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
// packages/daemon/src/lib/
|
|
86
|
-
var
|
|
87
|
-
var SYSTEM_MIND = "_system";
|
|
88
|
-
var WEDGED_TURN_IDLE_MS = 15 * 6e4;
|
|
85
|
+
// packages/daemon/src/lib/util/period-keys.ts
|
|
86
|
+
var DATE_STR_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
89
87
|
function getPeriodKey(date, period) {
|
|
90
88
|
switch (period) {
|
|
91
89
|
case "hour": {
|
|
@@ -117,12 +115,27 @@ function getISOWeekKey(date) {
|
|
|
117
115
|
const weekNum = Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
|
|
118
116
|
return `${d.getFullYear()}-W${String(weekNum).padStart(2, "0")}`;
|
|
119
117
|
}
|
|
118
|
+
function isoWeekToDate(weekKey) {
|
|
119
|
+
const [yearStr, weekStr] = weekKey.split("-W");
|
|
120
|
+
const year = parseInt(yearStr, 10);
|
|
121
|
+
const week = parseInt(weekStr, 10);
|
|
122
|
+
const jan4 = new Date(year, 0, 4);
|
|
123
|
+
const dayOfWeek = jan4.getDay() || 7;
|
|
124
|
+
const monday = new Date(jan4);
|
|
125
|
+
monday.setDate(jan4.getDate() - dayOfWeek + 1 + (week - 1) * 7);
|
|
126
|
+
return monday;
|
|
127
|
+
}
|
|
128
|
+
function isoWeekKeyForDateStr(dateStr) {
|
|
129
|
+
if (!DATE_STR_RE.test(dateStr)) return dateStr;
|
|
130
|
+
const [y, m, d] = dateStr.split("-").map(Number);
|
|
131
|
+
return getISOWeekKey(new Date(y, m - 1, d));
|
|
132
|
+
}
|
|
120
133
|
function getPreviousPeriodKey(key2, period) {
|
|
121
134
|
switch (period) {
|
|
122
135
|
case "hour": {
|
|
123
136
|
const d = /* @__PURE__ */ new Date(`${key2.slice(0, 10)}T${key2.slice(11)}:00:00`);
|
|
124
|
-
|
|
125
|
-
return getPeriodKey(
|
|
137
|
+
const prev = new Date(d.getTime() - 36e5);
|
|
138
|
+
return getPeriodKey(prev, "hour");
|
|
126
139
|
}
|
|
127
140
|
case "day": {
|
|
128
141
|
const d = /* @__PURE__ */ new Date(`${key2}T00:00:00`);
|
|
@@ -141,16 +154,6 @@ function getPreviousPeriodKey(key2, period) {
|
|
|
141
154
|
}
|
|
142
155
|
}
|
|
143
156
|
}
|
|
144
|
-
function isoWeekToDate(weekKey) {
|
|
145
|
-
const [yearStr, weekStr] = weekKey.split("-W");
|
|
146
|
-
const year = parseInt(yearStr, 10);
|
|
147
|
-
const week = parseInt(weekStr, 10);
|
|
148
|
-
const jan4 = new Date(year, 0, 4);
|
|
149
|
-
const dayOfWeek = jan4.getDay() || 7;
|
|
150
|
-
const monday = new Date(jan4);
|
|
151
|
-
monday.setDate(jan4.getDate() - dayOfWeek + 1 + (week - 1) * 7);
|
|
152
|
-
return monday;
|
|
153
|
-
}
|
|
154
157
|
function localDateStr(d) {
|
|
155
158
|
const y = d.getFullYear();
|
|
156
159
|
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
@@ -160,6 +163,9 @@ function localDateStr(d) {
|
|
|
160
163
|
function utcDateTimeStr(d) {
|
|
161
164
|
return d.toISOString().replace("T", " ").slice(0, 19);
|
|
162
165
|
}
|
|
166
|
+
function parseUtcDateTime(s) {
|
|
167
|
+
return /* @__PURE__ */ new Date(`${s.replace(" ", "T")}Z`);
|
|
168
|
+
}
|
|
163
169
|
function getTimeRange(periodKey, period) {
|
|
164
170
|
switch (period) {
|
|
165
171
|
case "hour": {
|
|
@@ -188,6 +194,11 @@ function getTimeRange(periodKey, period) {
|
|
|
188
194
|
}
|
|
189
195
|
}
|
|
190
196
|
}
|
|
197
|
+
|
|
198
|
+
// packages/daemon/src/lib/daemon/summarizer.ts
|
|
199
|
+
var sLog = logger_default.child("summarizer");
|
|
200
|
+
var SYSTEM_MIND = "_system";
|
|
201
|
+
var WEDGED_TURN_IDLE_MS = 15 * 6e4;
|
|
191
202
|
async function gatherTurnEvents(mind, session, doneId) {
|
|
192
203
|
const db = await getDb();
|
|
193
204
|
const subConditions = [
|
|
@@ -210,6 +221,7 @@ async function gatherTurnEvents(mind, session, doneId) {
|
|
|
210
221
|
session: mindHistory.session,
|
|
211
222
|
content: mindHistory.content,
|
|
212
223
|
metadata: mindHistory.metadata,
|
|
224
|
+
turn_id: mindHistory.turn_id,
|
|
213
225
|
created_at: mindHistory.created_at
|
|
214
226
|
}).from(mindHistory).where(and(...turnConditions)).orderBy(mindHistory.id);
|
|
215
227
|
return {
|
|
@@ -227,6 +239,7 @@ async function gatherTurnEventsByTurnId(turnId) {
|
|
|
227
239
|
session: mindHistory.session,
|
|
228
240
|
content: mindHistory.content,
|
|
229
241
|
metadata: mindHistory.metadata,
|
|
242
|
+
turn_id: mindHistory.turn_id,
|
|
230
243
|
created_at: mindHistory.created_at
|
|
231
244
|
}).from(mindHistory).where(eq(mindHistory.turn_id, turnId)).orderBy(mindHistory.id);
|
|
232
245
|
return {
|
|
@@ -321,19 +334,22 @@ function buildTranscript(events, parsedMeta) {
|
|
|
321
334
|
async function summarizeTurn(mind, session, channel, doneId, turnId) {
|
|
322
335
|
const { events, fromId, toId } = turnId ? await gatherTurnEventsByTurnId(turnId) : await gatherTurnEvents(mind, session, doneId);
|
|
323
336
|
if (events.length === 0) return;
|
|
337
|
+
const effectiveTurnId = turnId ?? events.find((ev) => ev.turn_id)?.turn_id ?? void 0;
|
|
338
|
+
if (effectiveTurnId && await summaryExists(mind, "turn", effectiveTurnId)) return;
|
|
324
339
|
const substantiveTypes = /* @__PURE__ */ new Set(["text", "outbound", "tool_use", "tool_result", "thinking"]);
|
|
325
340
|
const hasSubstantiveOutput = events.some((ev) => substantiveTypes.has(ev.type));
|
|
326
341
|
if (!hasSubstantiveOutput) {
|
|
327
342
|
sLog.info(
|
|
328
|
-
`skipping summary for interrupted turn ${
|
|
343
|
+
`skipping summary for interrupted turn ${effectiveTurnId ?? "(no turn)"} (no substantive output)`
|
|
329
344
|
);
|
|
330
|
-
if (
|
|
345
|
+
if (effectiveTurnId) {
|
|
331
346
|
try {
|
|
332
347
|
const db2 = await getDb();
|
|
333
|
-
await db2.update(mindHistory).set({ turn_id: null }).where(and(eq(mindHistory.turn_id,
|
|
334
|
-
await db2.update(messages).set({ turn_id: null }).where(eq(messages.turn_id,
|
|
348
|
+
await db2.update(mindHistory).set({ turn_id: null }).where(and(eq(mindHistory.turn_id, effectiveTurnId), eq(mindHistory.type, "inbound")));
|
|
349
|
+
await db2.update(messages).set({ turn_id: null }).where(eq(messages.turn_id, effectiveTurnId));
|
|
350
|
+
await db2.delete(turns).where(eq(turns.id, effectiveTurnId));
|
|
335
351
|
} catch (err) {
|
|
336
|
-
sLog.error(`failed to
|
|
352
|
+
sLog.error(`failed to clean up interrupted turn ${effectiveTurnId}`, logger_default.errorData(err));
|
|
337
353
|
}
|
|
338
354
|
}
|
|
339
355
|
return;
|
|
@@ -374,7 +390,7 @@ async function summarizeTurn(mind, session, channel, doneId, turnId) {
|
|
|
374
390
|
from_time: fromTime,
|
|
375
391
|
to_time: toTime
|
|
376
392
|
};
|
|
377
|
-
const periodKey =
|
|
393
|
+
const periodKey = effectiveTurnId ?? `${mind}-${doneId}`;
|
|
378
394
|
const db = await getDb();
|
|
379
395
|
let summaryId;
|
|
380
396
|
try {
|
|
@@ -403,9 +419,9 @@ async function summarizeTurn(mind, session, channel, doneId, turnId) {
|
|
|
403
419
|
);
|
|
404
420
|
return;
|
|
405
421
|
}
|
|
406
|
-
if (
|
|
407
|
-
setSummaryId(
|
|
408
|
-
sLog.error(`failed to link summary to turn ${
|
|
422
|
+
if (effectiveTurnId && summaryId != null) {
|
|
423
|
+
setSummaryId(effectiveTurnId, summaryId).catch((err) => {
|
|
424
|
+
sLog.error(`failed to link summary to turn ${effectiveTurnId}`, logger_default.errorData(err));
|
|
409
425
|
});
|
|
410
426
|
}
|
|
411
427
|
publish(mind, {
|
|
@@ -415,7 +431,7 @@ async function summarizeTurn(mind, session, channel, doneId, turnId) {
|
|
|
415
431
|
channel,
|
|
416
432
|
content: summaryText,
|
|
417
433
|
metadata,
|
|
418
|
-
turnId
|
|
434
|
+
turnId: effectiveTurnId
|
|
419
435
|
});
|
|
420
436
|
}
|
|
421
437
|
async function setSummaryId(turnId, summaryId) {
|
|
@@ -439,31 +455,86 @@ function getScopeInstruction(mind) {
|
|
|
439
455
|
}
|
|
440
456
|
return 'Write in first person as the mind who performed the actions (e.g. "I explored...", "I worked on...").';
|
|
441
457
|
}
|
|
442
|
-
|
|
443
|
-
|
|
458
|
+
var DIGEST_CHILD_CHARS = 200;
|
|
459
|
+
var DIGEST_MAX_CHARS = 4e3;
|
|
460
|
+
var DIGEST_NOTICE = "(auto-generated digest \u2014 AI summary pending)";
|
|
461
|
+
var ROLLUP_CHILD_CHARS = 2e3;
|
|
462
|
+
var PROVISIONAL_MAX_ATTEMPTS = 5;
|
|
463
|
+
var PROVISIONAL_WINDOW_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
464
|
+
var PROVISIONAL_RETRY_BACKOFF_MS = PROVISIONAL_WINDOW_MS / PROVISIONAL_MAX_ATTEMPTS;
|
|
465
|
+
function truncateChars(text, max) {
|
|
466
|
+
const t = text.trim();
|
|
467
|
+
return t.length > max ? `${t.slice(0, max).trimEnd()}\u2026` : t;
|
|
468
|
+
}
|
|
469
|
+
function digestLine(text) {
|
|
470
|
+
const flat = text.trim().replace(/\s+/g, " ");
|
|
471
|
+
const match = flat.match(/^.*?[.!?](?=\s|$)/);
|
|
472
|
+
const line = match ? match[0] : flat;
|
|
473
|
+
return line.length > DIGEST_CHILD_CHARS ? `${line.slice(0, DIGEST_CHILD_CHARS).trimEnd()}\u2026` : line;
|
|
474
|
+
}
|
|
475
|
+
function buildBoundedDigest(entries, period, periodKey) {
|
|
476
|
+
const label = period === "week" ? `Week ${periodKey}` : periodKey;
|
|
477
|
+
const header = `${label} ${DIGEST_NOTICE}`;
|
|
478
|
+
const lines = [];
|
|
479
|
+
let total = header.length + 2;
|
|
480
|
+
for (let i = 0; i < entries.length; i++) {
|
|
481
|
+
const line = `${entries[i].key}: ${digestLine(entries[i].text)}`;
|
|
482
|
+
if (lines.length > 0 && total + line.length + 1 > DIGEST_MAX_CHARS) {
|
|
483
|
+
lines.push(`\u2026and ${entries.length - i} more`);
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
lines.push(line);
|
|
487
|
+
total += line.length + 1;
|
|
488
|
+
}
|
|
489
|
+
return `${header}
|
|
490
|
+
|
|
491
|
+
${lines.join("\n")}`;
|
|
492
|
+
}
|
|
493
|
+
function buildPeriodicDeterministicSummary(entries, period, periodKey) {
|
|
494
|
+
if (entries.length === 0) return "";
|
|
444
495
|
switch (period) {
|
|
445
496
|
case "hour":
|
|
446
|
-
return `Activity during ${periodKey.slice(11)}:00: ${
|
|
497
|
+
return `Activity during ${periodKey.slice(11)}:00: ${entries.map((e) => e.text).join(" ")}`;
|
|
447
498
|
case "day":
|
|
448
499
|
return `Activity on ${periodKey}:
|
|
449
500
|
|
|
450
|
-
${
|
|
501
|
+
${entries.map((e) => e.text).join("\n\n")}`;
|
|
451
502
|
case "week":
|
|
452
|
-
return `Week ${periodKey} summary:
|
|
453
|
-
|
|
454
|
-
${sources.join("\n\n")}`;
|
|
455
503
|
case "month":
|
|
456
|
-
return
|
|
457
|
-
|
|
458
|
-
${sources.join("\n\n")}`;
|
|
504
|
+
return buildBoundedDigest(entries, period, periodKey);
|
|
459
505
|
}
|
|
460
506
|
}
|
|
507
|
+
function parseMeta(raw) {
|
|
508
|
+
if (!raw) return {};
|
|
509
|
+
try {
|
|
510
|
+
return JSON.parse(raw);
|
|
511
|
+
} catch {
|
|
512
|
+
return {};
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
function shouldRetry(period, meta) {
|
|
516
|
+
if (period !== "week" && period !== "month") return false;
|
|
517
|
+
if (meta.deterministic !== true) return false;
|
|
518
|
+
const attempts = typeof meta.attempts === "number" ? meta.attempts : 0;
|
|
519
|
+
if (attempts >= PROVISIONAL_MAX_ATTEMPTS) return false;
|
|
520
|
+
const first = typeof meta.first_attempt_at === "string" ? Date.parse(meta.first_attempt_at) : NaN;
|
|
521
|
+
if (!Number.isNaN(first) && Date.now() - first > PROVISIONAL_WINDOW_MS) return false;
|
|
522
|
+
const last = typeof meta.last_attempt_at === "string" ? Date.parse(meta.last_attempt_at) : NaN;
|
|
523
|
+
if (!Number.isNaN(last) && Date.now() - last < PROVISIONAL_RETRY_BACKOFF_MS) return false;
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
function trackProvisionalAttempt(metadata, prev) {
|
|
527
|
+
const prevAttempts = prev && typeof prev.attempts === "number" ? prev.attempts : 0;
|
|
528
|
+
metadata.attempts = prevAttempts + 1;
|
|
529
|
+
metadata.first_attempt_at = prev && typeof prev.first_attempt_at === "string" ? prev.first_attempt_at : (/* @__PURE__ */ new Date()).toISOString();
|
|
530
|
+
metadata.last_attempt_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
531
|
+
}
|
|
461
532
|
async function gatherChildSummaries(mind, period, periodKey) {
|
|
462
533
|
const db = await getDb();
|
|
463
534
|
const childPeriod = getChildPeriod(period);
|
|
464
535
|
if (period === "hour") {
|
|
465
536
|
const { start: start2, end: end2 } = getTimeRange(periodKey, "hour");
|
|
466
|
-
const rows2 = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
|
|
537
|
+
const rows2 = await db.select({ id: summaries.id, content: summaries.content, key: summaries.period_key }).from(summaries).where(
|
|
467
538
|
and(
|
|
468
539
|
eq(summaries.mind, mind),
|
|
469
540
|
eq(summaries.period, childPeriod),
|
|
@@ -473,11 +544,12 @@ async function gatherChildSummaries(mind, period, periodKey) {
|
|
|
473
544
|
).orderBy(summaries.created_at);
|
|
474
545
|
return {
|
|
475
546
|
texts: rows2.map((r) => r.content),
|
|
476
|
-
sourceIds: rows2.map((r) => r.id)
|
|
547
|
+
sourceIds: rows2.map((r) => r.id),
|
|
548
|
+
keys: rows2.map((r) => r.key)
|
|
477
549
|
};
|
|
478
550
|
}
|
|
479
551
|
if (period === "day") {
|
|
480
|
-
const rows2 = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
|
|
552
|
+
const rows2 = await db.select({ id: summaries.id, content: summaries.content, key: summaries.period_key }).from(summaries).where(
|
|
481
553
|
and(
|
|
482
554
|
eq(summaries.mind, mind),
|
|
483
555
|
eq(summaries.period, childPeriod),
|
|
@@ -486,13 +558,14 @@ async function gatherChildSummaries(mind, period, periodKey) {
|
|
|
486
558
|
).orderBy(summaries.period_key);
|
|
487
559
|
return {
|
|
488
560
|
texts: rows2.map((r) => r.content),
|
|
489
|
-
sourceIds: rows2.map((r) => r.id)
|
|
561
|
+
sourceIds: rows2.map((r) => r.id),
|
|
562
|
+
keys: rows2.map((r) => r.key)
|
|
490
563
|
};
|
|
491
564
|
}
|
|
492
565
|
const { start, end } = getTimeRange(periodKey, period);
|
|
493
566
|
const startKey = start.slice(0, 10);
|
|
494
567
|
const endKey = end.slice(0, 10);
|
|
495
|
-
const rows = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
|
|
568
|
+
const rows = await db.select({ id: summaries.id, content: summaries.content, key: summaries.period_key }).from(summaries).where(
|
|
496
569
|
and(
|
|
497
570
|
eq(summaries.mind, mind),
|
|
498
571
|
eq(summaries.period, childPeriod),
|
|
@@ -502,15 +575,24 @@ async function gatherChildSummaries(mind, period, periodKey) {
|
|
|
502
575
|
).orderBy(summaries.period_key);
|
|
503
576
|
return {
|
|
504
577
|
texts: rows.map((r) => r.content),
|
|
505
|
-
sourceIds: rows.map((r) => r.id)
|
|
578
|
+
sourceIds: rows.map((r) => r.id),
|
|
579
|
+
keys: rows.map((r) => r.key)
|
|
506
580
|
};
|
|
507
581
|
}
|
|
508
|
-
async function summarizePeriod(mind, period, periodKey) {
|
|
509
|
-
if (await summaryExists(mind, period, periodKey)) return false;
|
|
582
|
+
async function summarizePeriod(mind, period, periodKey, complete = aiCompleteUtility) {
|
|
510
583
|
const db = await getDb();
|
|
584
|
+
const existing = await db.select({ id: summaries.id, metadata: summaries.metadata }).from(summaries).where(
|
|
585
|
+
and(
|
|
586
|
+
eq(summaries.mind, mind),
|
|
587
|
+
eq(summaries.period, period),
|
|
588
|
+
eq(summaries.period_key, periodKey)
|
|
589
|
+
)
|
|
590
|
+
).get();
|
|
591
|
+
const existingMeta = existing ? parseMeta(existing.metadata) : null;
|
|
592
|
+
if (existing && !shouldRetry(period, existingMeta)) return false;
|
|
511
593
|
const sources = await gatherChildSummaries(mind, period, periodKey);
|
|
512
594
|
if (sources.texts.length === 0) return false;
|
|
513
|
-
if (sources.texts.length === 1) {
|
|
595
|
+
if (!existing && sources.texts.length === 1) {
|
|
514
596
|
try {
|
|
515
597
|
await db.insert(summaries).values({
|
|
516
598
|
mind,
|
|
@@ -534,33 +616,39 @@ async function summarizePeriod(mind, period, periodKey) {
|
|
|
534
616
|
sLog.info(`promoted single-child ${period} summary for ${mind} (${periodKey})`);
|
|
535
617
|
return true;
|
|
536
618
|
}
|
|
619
|
+
const entries = sources.texts.map((text, i) => ({ key: sources.keys[i], text }));
|
|
537
620
|
const promptKey = `meta_summary_${period}`;
|
|
538
621
|
const scopeInstruction = getScopeInstruction(mind);
|
|
539
622
|
const systemPrompt = await getPrompt(promptKey, { scope_instruction: scopeInstruction });
|
|
540
623
|
const userMessage = sources.texts.join("\n\n---\n\n");
|
|
541
624
|
let content;
|
|
542
625
|
let deterministic;
|
|
543
|
-
const
|
|
626
|
+
const metadata = {
|
|
627
|
+
source_count: sources.texts.length,
|
|
628
|
+
source_ids: sources.sourceIds
|
|
629
|
+
};
|
|
630
|
+
const aiResult = await complete(systemPrompt, userMessage);
|
|
544
631
|
if (aiResult) {
|
|
545
632
|
content = aiResult;
|
|
546
633
|
deterministic = false;
|
|
547
634
|
} else {
|
|
548
|
-
content = buildPeriodicDeterministicSummary(
|
|
635
|
+
content = buildPeriodicDeterministicSummary(entries, period, periodKey);
|
|
549
636
|
deterministic = true;
|
|
637
|
+
if (period === "week" || period === "month") trackProvisionalAttempt(metadata, existingMeta);
|
|
550
638
|
}
|
|
551
|
-
|
|
552
|
-
deterministic,
|
|
553
|
-
source_count: sources.texts.length,
|
|
554
|
-
source_ids: sources.sourceIds
|
|
555
|
-
};
|
|
639
|
+
metadata.deterministic = deterministic;
|
|
556
640
|
try {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
641
|
+
if (existing) {
|
|
642
|
+
await db.update(summaries).set({ content, metadata: JSON.stringify(metadata) }).where(eq(summaries.id, existing.id));
|
|
643
|
+
} else {
|
|
644
|
+
await db.insert(summaries).values({
|
|
645
|
+
mind,
|
|
646
|
+
period,
|
|
647
|
+
period_key: periodKey,
|
|
648
|
+
content,
|
|
649
|
+
metadata: JSON.stringify(metadata)
|
|
650
|
+
}).onConflictDoNothing();
|
|
651
|
+
}
|
|
564
652
|
} catch (err) {
|
|
565
653
|
sLog.error(
|
|
566
654
|
`failed to persist ${period} summary for ${mind} (${periodKey})`,
|
|
@@ -573,9 +661,17 @@ async function summarizePeriod(mind, period, periodKey) {
|
|
|
573
661
|
);
|
|
574
662
|
return true;
|
|
575
663
|
}
|
|
576
|
-
async function summarizeSystem(period, periodKey) {
|
|
577
|
-
if (await summaryExists(SYSTEM_MIND, period, periodKey)) return;
|
|
664
|
+
async function summarizeSystem(period, periodKey, complete = aiCompleteUtility) {
|
|
578
665
|
const db = await getDb();
|
|
666
|
+
const existing = await db.select({ id: summaries.id, metadata: summaries.metadata }).from(summaries).where(
|
|
667
|
+
and(
|
|
668
|
+
eq(summaries.mind, SYSTEM_MIND),
|
|
669
|
+
eq(summaries.period, period),
|
|
670
|
+
eq(summaries.period_key, periodKey)
|
|
671
|
+
)
|
|
672
|
+
).get();
|
|
673
|
+
const existingMeta = existing ? parseMeta(existing.metadata) : null;
|
|
674
|
+
if (existing && !shouldRetry(period, existingMeta)) return;
|
|
579
675
|
const rows = await db.select({ mind: summaries.mind, content: summaries.content }).from(summaries).where(
|
|
580
676
|
and(
|
|
581
677
|
eq(summaries.period, period),
|
|
@@ -585,33 +681,69 @@ async function summarizeSystem(period, periodKey) {
|
|
|
585
681
|
).orderBy(summaries.mind);
|
|
586
682
|
if (rows.length === 0) return;
|
|
587
683
|
const minds = [...new Set(rows.map((r) => r.mind))];
|
|
588
|
-
const
|
|
684
|
+
const entries = rows.map((r) => ({
|
|
685
|
+
key: r.mind,
|
|
686
|
+
text: truncateChars(r.content, ROLLUP_CHILD_CHARS)
|
|
687
|
+
}));
|
|
688
|
+
const texts = entries.map((e) => `[${e.key}] ${e.text}`);
|
|
589
689
|
const promptKey = `meta_summary_${period}`;
|
|
590
690
|
const scopeInstruction = getScopeInstruction(SYSTEM_MIND);
|
|
591
691
|
const systemPrompt = await getPrompt(promptKey, { scope_instruction: scopeInstruction });
|
|
592
692
|
const userMessage = texts.join("\n\n---\n\n");
|
|
593
693
|
let content;
|
|
594
694
|
let deterministic;
|
|
595
|
-
const
|
|
695
|
+
const metadata = { minds, source_count: rows.length };
|
|
696
|
+
const aiResult = await complete(systemPrompt, userMessage);
|
|
596
697
|
if (aiResult) {
|
|
597
698
|
content = aiResult;
|
|
598
699
|
deterministic = false;
|
|
599
700
|
} else {
|
|
600
|
-
content = buildPeriodicDeterministicSummary(
|
|
701
|
+
content = buildPeriodicDeterministicSummary(entries, period, periodKey);
|
|
601
702
|
deterministic = true;
|
|
703
|
+
if (period === "week" || period === "month") trackProvisionalAttempt(metadata, existingMeta);
|
|
602
704
|
}
|
|
705
|
+
metadata.deterministic = deterministic;
|
|
603
706
|
try {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
707
|
+
if (existing) {
|
|
708
|
+
await db.update(summaries).set({ content, metadata: JSON.stringify(metadata) }).where(eq(summaries.id, existing.id));
|
|
709
|
+
} else {
|
|
710
|
+
await db.insert(summaries).values({
|
|
711
|
+
mind: SYSTEM_MIND,
|
|
712
|
+
period,
|
|
713
|
+
period_key: periodKey,
|
|
714
|
+
content,
|
|
715
|
+
metadata: JSON.stringify(metadata)
|
|
716
|
+
}).onConflictDoNothing();
|
|
717
|
+
}
|
|
611
718
|
} catch (err) {
|
|
612
719
|
sLog.error(`failed to persist system ${period} summary (${periodKey})`, logger_default.errorData(err));
|
|
613
720
|
}
|
|
614
721
|
}
|
|
722
|
+
async function repairProvisionalSummaries(complete = aiCompleteUtility) {
|
|
723
|
+
const db = await getDb();
|
|
724
|
+
const rows = await db.select({
|
|
725
|
+
mind: summaries.mind,
|
|
726
|
+
period: summaries.period,
|
|
727
|
+
period_key: summaries.period_key,
|
|
728
|
+
metadata: summaries.metadata
|
|
729
|
+
}).from(summaries).where(inArray(summaries.period, ["week", "month"]));
|
|
730
|
+
const due = rows.filter((r) => shouldRetry(r.period, parseMeta(r.metadata)));
|
|
731
|
+
due.sort((a, b) => (a.mind === SYSTEM_MIND ? 1 : 0) - (b.mind === SYSTEM_MIND ? 1 : 0));
|
|
732
|
+
for (const r of due) {
|
|
733
|
+
try {
|
|
734
|
+
if (r.mind === SYSTEM_MIND) {
|
|
735
|
+
await summarizeSystem(r.period, r.period_key, complete);
|
|
736
|
+
} else {
|
|
737
|
+
await summarizePeriod(r.mind, r.period, r.period_key, complete);
|
|
738
|
+
}
|
|
739
|
+
} catch (err) {
|
|
740
|
+
sLog.error(
|
|
741
|
+
`failed to repair provisional ${r.period} summary for ${r.mind} (${r.period_key})`,
|
|
742
|
+
logger_default.errorData(err)
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
615
747
|
async function mindsWithTurnSummaries(start, end) {
|
|
616
748
|
const db = await getDb();
|
|
617
749
|
const rows = await db.select({ mind: summaries.mind }).from(summaries).where(
|
|
@@ -756,6 +888,95 @@ async function backfill() {
|
|
|
756
888
|
}
|
|
757
889
|
}
|
|
758
890
|
}
|
|
891
|
+
async function healMissing(period, needed, process) {
|
|
892
|
+
if (needed.size === 0) return;
|
|
893
|
+
const db = await getDb();
|
|
894
|
+
const keys = [...needed.keys()];
|
|
895
|
+
const existing = await db.select({ mind: summaries.mind, period_key: summaries.period_key }).from(summaries).where(and(eq(summaries.period, period), inArray(summaries.period_key, keys)));
|
|
896
|
+
const have = new Set(existing.map((r) => `${r.mind}|${r.period_key}`));
|
|
897
|
+
for (const [key2, minds] of needed) {
|
|
898
|
+
let gap = !have.has(`${SYSTEM_MIND}|${key2}`);
|
|
899
|
+
if (!gap) {
|
|
900
|
+
for (const mind of minds) {
|
|
901
|
+
if (!have.has(`${mind}|${key2}`)) {
|
|
902
|
+
gap = true;
|
|
903
|
+
break;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
if (!gap) continue;
|
|
908
|
+
try {
|
|
909
|
+
await process(key2);
|
|
910
|
+
} catch (err) {
|
|
911
|
+
sLog.error(`reconcile ${period} ${key2} failed`, logger_default.errorData(err));
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
function addNeeded(map, key2, mind) {
|
|
916
|
+
let set = map.get(key2);
|
|
917
|
+
if (!set) {
|
|
918
|
+
set = /* @__PURE__ */ new Set();
|
|
919
|
+
map.set(key2, set);
|
|
920
|
+
}
|
|
921
|
+
set.add(mind);
|
|
922
|
+
}
|
|
923
|
+
async function reconcileMissingSummaries(lookbackDays = 7) {
|
|
924
|
+
const db = await getDb();
|
|
925
|
+
const now = /* @__PURE__ */ new Date();
|
|
926
|
+
const windowStart = new Date(now);
|
|
927
|
+
windowStart.setDate(windowStart.getDate() - lookbackDays);
|
|
928
|
+
const currentHourKey = getPeriodKey(now, "hour");
|
|
929
|
+
const currentDayKey = getPeriodKey(now, "day");
|
|
930
|
+
const currentWeekKey = getPeriodKey(now, "week");
|
|
931
|
+
const currentMonthKey = getPeriodKey(now, "month");
|
|
932
|
+
const cutoffDayKey = getPeriodKey(windowStart, "day");
|
|
933
|
+
const turnRows = await db.select({ mind: summaries.mind, created_at: summaries.created_at }).from(summaries).where(
|
|
934
|
+
and(
|
|
935
|
+
eq(summaries.period, "turn"),
|
|
936
|
+
gte(summaries.created_at, utcDateTimeStr(windowStart)),
|
|
937
|
+
sql`${summaries.mind} != ${SYSTEM_MIND}`
|
|
938
|
+
)
|
|
939
|
+
);
|
|
940
|
+
const neededHours = /* @__PURE__ */ new Map();
|
|
941
|
+
for (const r of turnRows) {
|
|
942
|
+
const key2 = getPeriodKey(parseUtcDateTime(r.created_at), "hour");
|
|
943
|
+
if (key2 === currentHourKey) continue;
|
|
944
|
+
addNeeded(neededHours, key2, r.mind);
|
|
945
|
+
}
|
|
946
|
+
await healMissing("hour", neededHours, processHour);
|
|
947
|
+
const hourRows = await db.select({ mind: summaries.mind, period_key: summaries.period_key }).from(summaries).where(
|
|
948
|
+
and(
|
|
949
|
+
eq(summaries.period, "hour"),
|
|
950
|
+
gte(summaries.period_key, cutoffDayKey),
|
|
951
|
+
sql`${summaries.mind} != ${SYSTEM_MIND}`
|
|
952
|
+
)
|
|
953
|
+
);
|
|
954
|
+
const neededDays = /* @__PURE__ */ new Map();
|
|
955
|
+
for (const r of hourRows) {
|
|
956
|
+
const key2 = r.period_key.slice(0, 10);
|
|
957
|
+
if (key2 === currentDayKey) continue;
|
|
958
|
+
addNeeded(neededDays, key2, r.mind);
|
|
959
|
+
}
|
|
960
|
+
await healMissing("day", neededDays, processDay);
|
|
961
|
+
const dayRows = await db.select({ mind: summaries.mind, period_key: summaries.period_key }).from(summaries).where(
|
|
962
|
+
and(
|
|
963
|
+
eq(summaries.period, "day"),
|
|
964
|
+
gte(summaries.period_key, cutoffDayKey),
|
|
965
|
+
sql`${summaries.mind} != ${SYSTEM_MIND}`
|
|
966
|
+
)
|
|
967
|
+
);
|
|
968
|
+
const neededWeeks = /* @__PURE__ */ new Map();
|
|
969
|
+
const neededMonths = /* @__PURE__ */ new Map();
|
|
970
|
+
for (const r of dayRows) {
|
|
971
|
+
const d = /* @__PURE__ */ new Date(`${r.period_key}T00:00:00`);
|
|
972
|
+
const weekKey = getPeriodKey(d, "week");
|
|
973
|
+
if (weekKey !== currentWeekKey) addNeeded(neededWeeks, weekKey, r.mind);
|
|
974
|
+
const monthKey = r.period_key.slice(0, 7);
|
|
975
|
+
if (monthKey !== currentMonthKey) addNeeded(neededMonths, monthKey, r.mind);
|
|
976
|
+
}
|
|
977
|
+
await healMissing("week", neededWeeks, processWeek);
|
|
978
|
+
await healMissing("month", neededMonths, processMonth);
|
|
979
|
+
}
|
|
759
980
|
var Summarizer = class {
|
|
760
981
|
interval = null;
|
|
761
982
|
lastHourKey = null;
|
|
@@ -777,6 +998,7 @@ var Summarizer = class {
|
|
|
777
998
|
this.hasBackfilled = true;
|
|
778
999
|
}
|
|
779
1000
|
await reconcileWedgedTurns(WEDGED_TURN_IDLE_MS);
|
|
1001
|
+
await reconcileMissingSummaries();
|
|
780
1002
|
const now = /* @__PURE__ */ new Date();
|
|
781
1003
|
const currentHourKey = getPeriodKey(now, "hour");
|
|
782
1004
|
if (this.lastHourKey && this.lastHourKey !== currentHourKey) {
|
|
@@ -799,17 +1021,18 @@ var Summarizer = class {
|
|
|
799
1021
|
if (!await summaryExists(SYSTEM_MIND, "month", prevMonthKey)) {
|
|
800
1022
|
await processMonth(prevMonthKey);
|
|
801
1023
|
}
|
|
1024
|
+
await repairProvisionalSummaries();
|
|
802
1025
|
} catch (err) {
|
|
803
1026
|
sLog.error("tick failed", logger_default.errorData(err));
|
|
804
1027
|
}
|
|
805
1028
|
}
|
|
806
1029
|
};
|
|
807
1030
|
async function reconcileWedgedTurns(idleMs) {
|
|
808
|
-
const { sweepWedgedTurns: sweepWedgedTurns2, summarizeOrphanedTurns: summarizeOrphanedTurns2 } = await import("./turn-tracker-
|
|
1031
|
+
const { sweepWedgedTurns: sweepWedgedTurns2, summarizeOrphanedTurns: summarizeOrphanedTurns2 } = await import("./turn-tracker-JZRZDFWV.js");
|
|
809
1032
|
const wedged = await sweepWedgedTurns2(idleMs);
|
|
810
1033
|
if (wedged.length === 0) return;
|
|
811
1034
|
summarizeOrphanedTurns2(wedged);
|
|
812
|
-
const { tryGetDeliveryManager } = await import("./delivery-manager-
|
|
1035
|
+
const { tryGetDeliveryManager } = await import("./delivery-manager-TN5KK2AP.js");
|
|
813
1036
|
const dm = tryGetDeliveryManager();
|
|
814
1037
|
if (!dm) return;
|
|
815
1038
|
for (const t of wedged) {
|
|
@@ -1010,6 +1233,7 @@ export {
|
|
|
1010
1233
|
subscribe,
|
|
1011
1234
|
subscribeAll,
|
|
1012
1235
|
publish,
|
|
1236
|
+
isoWeekKeyForDateStr,
|
|
1013
1237
|
summarizeTurn,
|
|
1014
1238
|
initSummarizer,
|
|
1015
1239
|
markErrored,
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
} from "./chunk-T2TP6ZC6.js";
|
|
5
5
|
import {
|
|
6
6
|
getDb
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WW6C3PLV.js";
|
|
8
8
|
import {
|
|
9
9
|
activity
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2MJ7EOMT.js";
|
|
11
11
|
|
|
12
12
|
// packages/daemon/src/lib/events/event-sequencer.ts
|
|
13
13
|
var BUFFER_SIZE = 1e3;
|