volute 0.46.0 → 0.48.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.
Files changed (172) hide show
  1. package/README.md +10 -10
  2. package/dist/{accept-N5XULCXK.js → accept-KYNC5X3U.js} +1 -1
  3. package/dist/{activity-events-NF6VWTJQ.js → activity-events-MIOK3IOU.js} +3 -3
  4. package/dist/{ai-service-UODCCE4O.js → ai-service-643TNFPH.js} +8 -4
  5. package/dist/{archive-WS2L2VIQ.js → archive-6Z4GFQPH.js} +3 -3
  6. package/dist/{auth-CCFAU4GQ.js → auth-A4VGHADI.js} +4 -4
  7. package/dist/avatar-image-Y45R7LW5.js +23 -0
  8. package/dist/{backup-TST5C2YN.js → backup-UDH4GMSW.js} +15 -15
  9. package/dist/{bridge-2PO3AI5D.js → bridge-3FNSWLNQ.js} +1 -1
  10. package/dist/channels-SGQZHNQJ.js +89 -0
  11. package/dist/{chat-ZIQQS25U.js → chat-X43VYHH2.js} +12 -8
  12. package/dist/{chunk-ZV7MFISX.js → chunk-2MJ7EOMT.js} +20 -2
  13. package/dist/{chunk-R77O2WMK.js → chunk-2OIYNHWO.js} +1 -1
  14. package/dist/{chunk-QCN24XEN.js → chunk-3YUBFTDN.js} +1 -1
  15. package/dist/chunk-4FCL4DVZ.js +48 -0
  16. package/dist/{chunk-F7H6ATM4.js → chunk-5KXCM5AW.js} +18 -2
  17. package/dist/chunk-7KRIHYLR.js +124 -0
  18. package/dist/{chunk-RBNMDAKB.js → chunk-BCG45AQB.js} +15 -1
  19. package/dist/{chunk-QMJCNZ6C.js → chunk-C3KLHJDB.js} +1 -1
  20. package/dist/{chunk-H2X54EHC.js → chunk-DGGZVZTM.js} +1 -1
  21. package/dist/chunk-DW4TRDOZ.js +29 -0
  22. package/dist/{chunk-4JOQZPCE.js → chunk-EIQDZC43.js} +1 -1
  23. package/dist/{chunk-TQJ6ZYVY.js → chunk-FJ2MZ5PH.js} +41 -5
  24. package/dist/{chunk-BJZ4PV7R.js → chunk-HNGFKPNS.js} +26 -10
  25. package/dist/{chunk-5ZQZDDIK.js → chunk-HPGN6XRT.js} +3 -3
  26. package/dist/{chunk-KGIXX4NM.js → chunk-HUNDXZBZ.js} +5 -5
  27. package/dist/{chunk-ZDZISKCL.js → chunk-IJPMIEVE.js} +1 -1
  28. package/dist/chunk-IYCV34IU.js +158 -0
  29. package/dist/{chunk-ZNMCCHCP.js → chunk-LTLFOSA4.js} +2 -2
  30. package/dist/{chunk-K6T43YBD.js → chunk-MJRXFUMS.js} +26 -6
  31. package/dist/{chunk-4YU7HF4L.js → chunk-MOERAQXH.js} +6 -4
  32. package/dist/{chunk-KQSFTPIM.js → chunk-MTRMQFCQ.js} +1 -1
  33. package/dist/{chunk-OV7ZQ2GH.js → chunk-ODDGGLM6.js} +3 -3
  34. package/dist/{chunk-A7WQZKOU.js → chunk-OQJMTHEH.js} +2 -2
  35. package/dist/{chunk-RRNXJOKB.js → chunk-PJVPDY2Z.js} +2 -2
  36. package/dist/{chunk-FXORA5JG.js → chunk-Q7HOAVFR.js} +3 -3
  37. package/dist/{chunk-KDLYIECM.js → chunk-R772ET2M.js} +18 -4
  38. package/dist/{chunk-QLWG3C2Z.js → chunk-RRZ4RQQU.js} +2 -2
  39. package/dist/{mind-list-4D7J4CHD.js → chunk-SHKM5RGD.js} +18 -4
  40. package/dist/{chunk-RXEEYDIB.js → chunk-SZJCJVXV.js} +1 -1
  41. package/dist/{chunk-E3DA4HYV.js → chunk-T4VS7UDW.js} +15 -15
  42. package/dist/{chunk-YXSUMLTC.js → chunk-USD45JKR.js} +322 -76
  43. package/dist/{chunk-JO5IO4FH.js → chunk-VB2QXUJQ.js} +391 -294
  44. package/dist/{chunk-JZ62SYWR.js → chunk-VZRA5TYO.js} +1 -1
  45. package/dist/{chunk-PJ45FQPT.js → chunk-WARH6GIV.js} +8 -8
  46. package/dist/{chunk-PFZBNKUH.js → chunk-WCFSBH33.js} +0 -1
  47. package/dist/{chunk-DRJ24GXK.js → chunk-WQ46E33M.js} +59 -39
  48. package/dist/{chunk-ALKYQULU.js → chunk-WW6C3PLV.js} +1 -1
  49. package/dist/{chunk-CDPBTTZO.js → chunk-XVBSFLM7.js} +2 -2
  50. package/dist/{chunk-6EMWJZBK.js → chunk-YKA7DCVW.js} +1 -1
  51. package/dist/{chunk-IHKGWTGT.js → chunk-YNBXEQAP.js} +31 -1
  52. package/dist/cli.js +34 -26
  53. package/dist/{clock-RHS2JEDL.js → clock-CNRF6F7T.js} +3 -3
  54. package/dist/{cloud-sync-46RS4SDA.js → cloud-sync-WHKCB4CD.js} +22 -19
  55. package/dist/{config-TJLYUV3U.js → config-RPSLA2HX.js} +3 -3
  56. package/dist/{conversations-CJOOCGNW.js → conversations-C7IKYSHD.js} +4 -4
  57. package/dist/{create-IOV4GCRX.js → create-GJKHABJB.js} +16 -5
  58. package/dist/{create-DF3KISTW.js → create-VIQVP3QB.js} +1 -1
  59. package/dist/{daemon-client-IYR4KCPU.js → daemon-client-ZFY5MOAL.js} +5 -3
  60. package/dist/{daemon-restart-VFEI57UO.js → daemon-restart-7KUHVZIN.js} +7 -7
  61. package/dist/daemon.js +829 -496
  62. package/dist/{db-MF2JNRUW.js → db-FO6LXYCW.js} +2 -2
  63. package/dist/{db-LZTLA7XC.js → db-IPXRJUI7.js} +1 -1
  64. package/dist/{delete-HPLC7ETU.js → delete-ESEP7NGQ.js} +1 -1
  65. package/dist/delivery-manager-HZTT5SJR.js +36 -0
  66. package/dist/{delivery-router-N4A7ZC5T.js → delivery-router-3QFG2ZEX.js} +3 -3
  67. package/dist/{down-U2CZ23M4.js → down-G6IADJXV.js} +5 -5
  68. package/dist/echo-text-H3SH337Q.js +36 -0
  69. package/dist/env-6TGPO5WG.js +18 -0
  70. package/dist/{env-VZ4MLFQW.js → env-C7Z55QCJ.js} +6 -6
  71. package/dist/{exec-G3ZRST4Z.js → exec-QIFYZG4C.js} +3 -3
  72. package/dist/{export-LY723I3Z.js → export-C2K3NIRD.js} +4 -4
  73. package/dist/{extension-SEID47SR.js → extension-J4ZQ2GHV.js} +1 -1
  74. package/dist/{extensions-ZELQLTSR.js → extensions-GEKF47A4.js} +24 -19
  75. package/dist/{files-4LN3EN7Q.js → files-LXQSQOFG.js} +4 -4
  76. package/dist/{import-42YNQBF4.js → import-SX3ZXHB4.js} +8 -8
  77. package/dist/{isolation-YMGZZ4E5.js → isolation-MCT4ZYLT.js} +3 -3
  78. package/dist/{join-ZJV7W6MO.js → join-34TR2GXQ.js} +1 -1
  79. package/dist/{list-OXIAY3W7.js → list-PMUXZNAM.js} +1 -1
  80. package/dist/{login-MY6ETFYB.js → login-ARRZ4ORJ.js} +3 -3
  81. package/dist/{login-M6OJUPQ2.js → login-CL4IT2ED.js} +14 -5
  82. package/dist/{logout-WQBWO77G.js → logout-HZYJCYCA.js} +3 -3
  83. package/dist/{logout-NCG3TMDL.js → logout-YZRMZ3O2.js} +1 -1
  84. package/dist/message-delivery-GPQ5SE5N.js +40 -0
  85. package/dist/{mind-LHKS55DI.js → mind-46AOK373.js} +23 -19
  86. package/dist/{mind-activity-tracker-3QRNJVR4.js → mind-activity-tracker-YVZPC4A5.js} +4 -4
  87. package/dist/mind-contacts-GV7XYL5D.js +64 -0
  88. package/dist/{mind-history-VRO5A76U.js → mind-history-TTGA5BHZ.js} +5 -5
  89. package/dist/mind-list-OTHV4ZO4.js +13 -0
  90. package/dist/{mind-profile-PEQYASQX.js → mind-profile-LUG353ZT.js} +1 -1
  91. package/dist/mind-service-2ARGJNKP.js +44 -0
  92. package/dist/{mind-sleep-74TGOQBC.js → mind-sleep-DV7KP255.js} +3 -3
  93. package/dist/{mind-status-UO34ASXZ.js → mind-status-BJNPGXKC.js} +23 -1
  94. package/dist/{mind-wake-LCLGTXA2.js → mind-wake-LVTZ55EZ.js} +1 -1
  95. package/dist/notices-2KU5NTRY.js +25 -0
  96. package/dist/{package-DOD6CPO6.js → package-RTN2PS7O.js} +5 -3
  97. package/dist/{read-QVAXMTPV.js → read-YSWUXYL7.js} +1 -1
  98. package/dist/{register-Y2H4PY5R.js → register-42VBJKTP.js} +3 -3
  99. package/dist/{registry-OUZBZ3Q4.js → registry-UMMDRPRM.js} +2 -2
  100. package/dist/{reject-EV35X64Y.js → reject-SXGCYN4A.js} +1 -1
  101. package/dist/{restart-FJQ662XJ.js → restart-YYEGZJDD.js} +5 -5
  102. package/dist/{sandbox-ZJ7QA6Z6.js → sandbox-5VQ454XP.js} +4 -4
  103. package/dist/scheduler-I7JZCT47.js +34 -0
  104. package/dist/{schema-PVNG3PQM.js → schema-VEVO7HG6.js} +3 -1
  105. package/dist/{seed-CNYIHPOH.js → seed-F2HXZQU4.js} +1 -1
  106. package/dist/{seed-check-VLTVILOV.js → seed-check-TYD7RRZY.js} +1 -1
  107. package/dist/{seed-cmd-AVNUNLZV.js → seed-cmd-MLCTGSX5.js} +3 -3
  108. package/dist/{seed-create-ANXGYSCC.js → seed-create-KQ7OILWB.js} +6 -4
  109. package/dist/seed-readiness-RBPGOLSZ.js +18 -0
  110. package/dist/{seed-sprout-NIUFTX32.js → seed-sprout-HVYCFJLA.js} +30 -31
  111. package/dist/{send-SPE6DVNJ.js → send-TD2X5U3K.js} +6 -6
  112. package/dist/{service-UOCLXDWR.js → service-CVZMQYK6.js} +4 -4
  113. package/dist/{service-install-4HHFDDWY.js → service-install-VCRMFWX5.js} +5 -5
  114. package/dist/{setup-Y2EJI3GG.js → setup-5ECWTYKG.js} +7 -3
  115. package/dist/{setup-QT2A25SY.js → setup-AE4CVUC4.js} +7 -7
  116. package/dist/{skill-FKFHIJRR.js → skill-UUM4JZRF.js} +5 -5
  117. package/dist/skills/dreaming/SKILL.md +5 -1
  118. package/dist/skills/dreaming/scripts/dream.ts +5 -1
  119. package/dist/skills/orientation/SKILL.md +8 -7
  120. package/dist/skills/tending/SKILL.md +51 -2
  121. package/dist/skills/volute-mind/SKILL.md +2 -0
  122. package/dist/{skills-AKCFA7BN.js → skills-B3SVDCEB.js} +5 -5
  123. package/dist/sleep-manager-Z27R3WTW.js +38 -0
  124. package/dist/spirit-WXS3HCLN.js +25 -0
  125. package/dist/{split-WBMZXBHF.js → split-SKZ4Y2D6.js} +1 -1
  126. package/dist/{sprout-SMX42ZBP.js → sprout-KQ43BWZJ.js} +1 -1
  127. package/dist/{src-OJHARHTF.js → src-WLJE73NP.js} +14 -5
  128. package/dist/{start-5JE3TV66.js → start-O6UKK7BG.js} +3 -3
  129. package/dist/{status-SWRVGXBI.js → status-F4PGREUU.js} +19 -7
  130. package/dist/{stop-AAMTG3TU.js → stop-UBX6X5RA.js} +5 -5
  131. package/dist/system-chat-63ABFF6V.js +40 -0
  132. package/dist/{systems-VNB5WKSS.js → systems-JJNGQHAO.js} +4 -4
  133. package/dist/{tailscale-3XOKOW7T.js → tailscale-MCLY5GYE.js} +2 -2
  134. package/dist/{template-hash-446HHH5V.js → template-hash-GSOUARW4.js} +2 -2
  135. package/dist/template-staleness-EMQORSGG.js +15 -0
  136. package/dist/{turn-tracker-FOIBNUUA.js → turn-tracker-KLPV3PAU.js} +6 -6
  137. package/dist/up-RVGDE6CQ.js +20 -0
  138. package/dist/{update-SWAYZRWJ.js → update-OXQEGGXD.js} +5 -5
  139. package/dist/{update-check-PQ2MZ47K.js → update-check-266R4ZSY.js} +3 -3
  140. package/dist/{upgrade-NWAZ7MLD.js → upgrade-K5FIQPQD.js} +1 -1
  141. package/dist/{version-notify-C5CH7CVP.js → version-notify-73YURTFR.js} +41 -25
  142. package/dist/web-assets/assets/index-WdZ60R6c.css +1 -0
  143. package/dist/web-assets/assets/index-taX6Ezfa.js +92 -0
  144. package/dist/web-assets/index.html +2 -2
  145. package/drizzle/0011_drop_turn_summary_event_id.sql +3 -0
  146. package/drizzle/0012_channel_gates.sql +17 -0
  147. package/drizzle/meta/_journal.json +14 -0
  148. package/package.json +5 -3
  149. package/packages/extensions/pages/dist/ui/assets/index-BuXnE-rb.css +1 -0
  150. package/packages/extensions/pages/dist/ui/assets/index-DtzftuPA.js +2 -0
  151. package/packages/extensions/pages/dist/ui/index.html +2 -2
  152. package/templates/_base/src/lib/startup.ts +59 -3
  153. package/templates/claude/src/agent.ts +37 -4
  154. package/templates/claude/src/lib/session-reaper.ts +32 -0
  155. package/templates/claude/src/server.ts +14 -3
  156. package/templates/pi/src/agent.ts +7 -10
  157. package/templates/pi/src/lib/dispatch.ts +65 -0
  158. package/dist/avatar-image-6KY6UU4D.js +0 -16
  159. package/dist/delivery-manager-JINZRG2W.js +0 -33
  160. package/dist/echo-text-VQPB5L2X.js +0 -33
  161. package/dist/message-delivery-R7JSQGYX.js +0 -37
  162. package/dist/mind-service-NB2JMWQZ.js +0 -39
  163. package/dist/scheduler-WVKII3LA.js +0 -31
  164. package/dist/sleep-manager-G6TXSDP7.js +0 -35
  165. package/dist/spirit-RPBLLUQ5.js +0 -23
  166. package/dist/system-chat-NDAW6YP7.js +0 -37
  167. package/dist/up-PS6PFS75.js +0 -18
  168. package/dist/volute-config-A52FHWKM.js +0 -14
  169. package/dist/web-assets/assets/index-B1JBQv2m.css +0 -1
  170. package/dist/web-assets/assets/index-CU6XWICM.js +0 -86
  171. package/packages/extensions/pages/dist/ui/assets/index-BcY6lnq4.css +0 -1
  172. package/packages/extensions/pages/dist/ui/assets/index-CQjEQg1r.js +0 -2
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getPrompt
4
- } from "./chunk-4YU7HF4L.js";
4
+ } from "./chunk-MOERAQXH.js";
5
5
  import {
6
6
  aiCompleteUtility
7
- } from "./chunk-IHKGWTGT.js";
7
+ } from "./chunk-YNBXEQAP.js";
8
8
  import {
9
9
  logger_default
10
10
  } from "./chunk-T2TP6ZC6.js";
11
11
  import {
12
12
  getDb
13
- } from "./chunk-ALKYQULU.js";
13
+ } from "./chunk-WW6C3PLV.js";
14
14
  import {
15
15
  messages,
16
16
  mindHistory,
17
17
  summaries,
18
18
  turns
19
- } from "./chunk-ZV7MFISX.js";
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/daemon/summarizer.ts
86
- var sLog = logger_default.child("summarizer");
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
- d.setHours(d.getHours() - 1);
125
- return getPeriodKey(d, "hour");
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 ${turnId ?? "(no turn)"} (no substantive output)`
343
+ `skipping summary for interrupted turn ${effectiveTurnId ?? "(no turn)"} (no substantive output)`
329
344
  );
330
- if (turnId) {
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, turnId), eq(mindHistory.type, "inbound")));
334
- await db2.update(messages).set({ turn_id: null }).where(eq(messages.turn_id, turnId));
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 un-tag events for interrupted turn ${turnId}`, logger_default.errorData(err));
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 = turnId ?? `${mind}-${doneId}`;
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 (turnId && summaryId != null) {
407
- setSummaryId(turnId, summaryId).catch((err) => {
408
- sLog.error(`failed to link summary to turn ${turnId}`, logger_default.errorData(err));
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,107 @@ 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
- function buildPeriodicDeterministicSummary(sources, period, periodKey) {
443
- if (sources.length === 0) return "";
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: ${sources.join(" ")}`;
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
- ${sources.join("\n\n")}`;
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 `${periodKey} summary:
504
+ return buildBoundedDigest(entries, period, periodKey);
505
+ }
506
+ }
507
+ var DIGEST_HEADER_PREFIX = new RegExp(
508
+ `^(?:Week )?\\S+ ${DIGEST_NOTICE.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\n\\n`
509
+ );
510
+ function stripPeriodPrefix(text) {
511
+ return text.replace(/^Activity during \d{2}:00: /, "").replace(/^Activity on \d{4}-\d{2}-\d{2}:\n\n/, "").replace(DIGEST_HEADER_PREFIX, "");
512
+ }
513
+ function buildSystemDeterministicSummary(entries, period, periodKey) {
514
+ if (entries.length === 0) return "";
515
+ const stripped = entries.map((e) => ({ key: e.key, text: stripPeriodPrefix(e.text) }));
516
+ switch (period) {
517
+ case "hour":
518
+ return `Activity during ${periodKey.slice(11)}:00: ${stripped.map((e) => `[${e.key}] ${e.text}`).join(" ")}`;
519
+ case "day":
520
+ return `Activity on ${periodKey}:
457
521
 
458
- ${sources.join("\n\n")}`;
522
+ ${stripped.map((e) => `[${e.key}] ${e.text}`).join("\n\n")}`;
523
+ case "week":
524
+ case "month":
525
+ return buildBoundedDigest(stripped, period, periodKey);
526
+ }
527
+ }
528
+ function parseMeta(raw) {
529
+ if (!raw) return {};
530
+ try {
531
+ return JSON.parse(raw);
532
+ } catch {
533
+ return {};
459
534
  }
460
535
  }
536
+ function shouldRetry(period, meta) {
537
+ if (period !== "week" && period !== "month") return false;
538
+ if (meta.deterministic !== true) return false;
539
+ const attempts = typeof meta.attempts === "number" ? meta.attempts : 0;
540
+ if (attempts >= PROVISIONAL_MAX_ATTEMPTS) return false;
541
+ const first = typeof meta.first_attempt_at === "string" ? Date.parse(meta.first_attempt_at) : NaN;
542
+ if (!Number.isNaN(first) && Date.now() - first > PROVISIONAL_WINDOW_MS) return false;
543
+ const last = typeof meta.last_attempt_at === "string" ? Date.parse(meta.last_attempt_at) : NaN;
544
+ if (!Number.isNaN(last) && Date.now() - last < PROVISIONAL_RETRY_BACKOFF_MS) return false;
545
+ return true;
546
+ }
547
+ function trackProvisionalAttempt(metadata, prev) {
548
+ const prevAttempts = prev && typeof prev.attempts === "number" ? prev.attempts : 0;
549
+ metadata.attempts = prevAttempts + 1;
550
+ metadata.first_attempt_at = prev && typeof prev.first_attempt_at === "string" ? prev.first_attempt_at : (/* @__PURE__ */ new Date()).toISOString();
551
+ metadata.last_attempt_at = (/* @__PURE__ */ new Date()).toISOString();
552
+ }
461
553
  async function gatherChildSummaries(mind, period, periodKey) {
462
554
  const db = await getDb();
463
555
  const childPeriod = getChildPeriod(period);
464
556
  if (period === "hour") {
465
557
  const { start: start2, end: end2 } = getTimeRange(periodKey, "hour");
466
- const rows2 = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
558
+ const rows2 = await db.select({ id: summaries.id, content: summaries.content, key: summaries.period_key }).from(summaries).where(
467
559
  and(
468
560
  eq(summaries.mind, mind),
469
561
  eq(summaries.period, childPeriod),
@@ -473,11 +565,12 @@ async function gatherChildSummaries(mind, period, periodKey) {
473
565
  ).orderBy(summaries.created_at);
474
566
  return {
475
567
  texts: rows2.map((r) => r.content),
476
- sourceIds: rows2.map((r) => r.id)
568
+ sourceIds: rows2.map((r) => r.id),
569
+ keys: rows2.map((r) => r.key)
477
570
  };
478
571
  }
479
572
  if (period === "day") {
480
- const rows2 = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
573
+ const rows2 = await db.select({ id: summaries.id, content: summaries.content, key: summaries.period_key }).from(summaries).where(
481
574
  and(
482
575
  eq(summaries.mind, mind),
483
576
  eq(summaries.period, childPeriod),
@@ -486,13 +579,14 @@ async function gatherChildSummaries(mind, period, periodKey) {
486
579
  ).orderBy(summaries.period_key);
487
580
  return {
488
581
  texts: rows2.map((r) => r.content),
489
- sourceIds: rows2.map((r) => r.id)
582
+ sourceIds: rows2.map((r) => r.id),
583
+ keys: rows2.map((r) => r.key)
490
584
  };
491
585
  }
492
586
  const { start, end } = getTimeRange(periodKey, period);
493
587
  const startKey = start.slice(0, 10);
494
588
  const endKey = end.slice(0, 10);
495
- const rows = await db.select({ id: summaries.id, content: summaries.content }).from(summaries).where(
589
+ const rows = await db.select({ id: summaries.id, content: summaries.content, key: summaries.period_key }).from(summaries).where(
496
590
  and(
497
591
  eq(summaries.mind, mind),
498
592
  eq(summaries.period, childPeriod),
@@ -502,15 +596,24 @@ async function gatherChildSummaries(mind, period, periodKey) {
502
596
  ).orderBy(summaries.period_key);
503
597
  return {
504
598
  texts: rows.map((r) => r.content),
505
- sourceIds: rows.map((r) => r.id)
599
+ sourceIds: rows.map((r) => r.id),
600
+ keys: rows.map((r) => r.key)
506
601
  };
507
602
  }
508
- async function summarizePeriod(mind, period, periodKey) {
509
- if (await summaryExists(mind, period, periodKey)) return false;
603
+ async function summarizePeriod(mind, period, periodKey, complete = aiCompleteUtility) {
510
604
  const db = await getDb();
605
+ const existing = await db.select({ id: summaries.id, metadata: summaries.metadata }).from(summaries).where(
606
+ and(
607
+ eq(summaries.mind, mind),
608
+ eq(summaries.period, period),
609
+ eq(summaries.period_key, periodKey)
610
+ )
611
+ ).get();
612
+ const existingMeta = existing ? parseMeta(existing.metadata) : null;
613
+ if (existing && !shouldRetry(period, existingMeta)) return false;
511
614
  const sources = await gatherChildSummaries(mind, period, periodKey);
512
615
  if (sources.texts.length === 0) return false;
513
- if (sources.texts.length === 1) {
616
+ if (!existing && sources.texts.length === 1) {
514
617
  try {
515
618
  await db.insert(summaries).values({
516
619
  mind,
@@ -534,33 +637,39 @@ async function summarizePeriod(mind, period, periodKey) {
534
637
  sLog.info(`promoted single-child ${period} summary for ${mind} (${periodKey})`);
535
638
  return true;
536
639
  }
640
+ const entries = sources.texts.map((text, i) => ({ key: sources.keys[i], text }));
537
641
  const promptKey = `meta_summary_${period}`;
538
642
  const scopeInstruction = getScopeInstruction(mind);
539
643
  const systemPrompt = await getPrompt(promptKey, { scope_instruction: scopeInstruction });
540
644
  const userMessage = sources.texts.join("\n\n---\n\n");
541
645
  let content;
542
646
  let deterministic;
543
- const aiResult = await aiCompleteUtility(systemPrompt, userMessage);
647
+ const metadata = {
648
+ source_count: sources.texts.length,
649
+ source_ids: sources.sourceIds
650
+ };
651
+ const aiResult = await complete(systemPrompt, userMessage);
544
652
  if (aiResult) {
545
653
  content = aiResult;
546
654
  deterministic = false;
547
655
  } else {
548
- content = buildPeriodicDeterministicSummary(sources.texts, period, periodKey);
656
+ content = buildPeriodicDeterministicSummary(entries, period, periodKey);
549
657
  deterministic = true;
658
+ if (period === "week" || period === "month") trackProvisionalAttempt(metadata, existingMeta);
550
659
  }
551
- const metadata = {
552
- deterministic,
553
- source_count: sources.texts.length,
554
- source_ids: sources.sourceIds
555
- };
660
+ metadata.deterministic = deterministic;
556
661
  try {
557
- await db.insert(summaries).values({
558
- mind,
559
- period,
560
- period_key: periodKey,
561
- content,
562
- metadata: JSON.stringify(metadata)
563
- }).onConflictDoNothing();
662
+ if (existing) {
663
+ await db.update(summaries).set({ content, metadata: JSON.stringify(metadata) }).where(eq(summaries.id, existing.id));
664
+ } else {
665
+ await db.insert(summaries).values({
666
+ mind,
667
+ period,
668
+ period_key: periodKey,
669
+ content,
670
+ metadata: JSON.stringify(metadata)
671
+ }).onConflictDoNothing();
672
+ }
564
673
  } catch (err) {
565
674
  sLog.error(
566
675
  `failed to persist ${period} summary for ${mind} (${periodKey})`,
@@ -573,9 +682,17 @@ async function summarizePeriod(mind, period, periodKey) {
573
682
  );
574
683
  return true;
575
684
  }
576
- async function summarizeSystem(period, periodKey) {
577
- if (await summaryExists(SYSTEM_MIND, period, periodKey)) return;
685
+ async function summarizeSystem(period, periodKey, complete = aiCompleteUtility) {
578
686
  const db = await getDb();
687
+ const existing = await db.select({ id: summaries.id, metadata: summaries.metadata }).from(summaries).where(
688
+ and(
689
+ eq(summaries.mind, SYSTEM_MIND),
690
+ eq(summaries.period, period),
691
+ eq(summaries.period_key, periodKey)
692
+ )
693
+ ).get();
694
+ const existingMeta = existing ? parseMeta(existing.metadata) : null;
695
+ if (existing && !shouldRetry(period, existingMeta)) return;
579
696
  const rows = await db.select({ mind: summaries.mind, content: summaries.content }).from(summaries).where(
580
697
  and(
581
698
  eq(summaries.period, period),
@@ -585,33 +702,69 @@ async function summarizeSystem(period, periodKey) {
585
702
  ).orderBy(summaries.mind);
586
703
  if (rows.length === 0) return;
587
704
  const minds = [...new Set(rows.map((r) => r.mind))];
588
- const texts = rows.map((r) => `[${r.mind}] ${r.content}`);
705
+ const entries = rows.map((r) => ({
706
+ key: r.mind,
707
+ text: truncateChars(r.content, ROLLUP_CHILD_CHARS)
708
+ }));
709
+ const texts = entries.map((e) => `[${e.key}] ${e.text}`);
589
710
  const promptKey = `meta_summary_${period}`;
590
711
  const scopeInstruction = getScopeInstruction(SYSTEM_MIND);
591
712
  const systemPrompt = await getPrompt(promptKey, { scope_instruction: scopeInstruction });
592
713
  const userMessage = texts.join("\n\n---\n\n");
593
714
  let content;
594
715
  let deterministic;
595
- const aiResult = await aiCompleteUtility(systemPrompt, userMessage);
716
+ const metadata = { minds, source_count: rows.length };
717
+ const aiResult = await complete(systemPrompt, userMessage);
596
718
  if (aiResult) {
597
719
  content = aiResult;
598
720
  deterministic = false;
599
721
  } else {
600
- content = buildPeriodicDeterministicSummary(texts, period, periodKey);
722
+ content = buildSystemDeterministicSummary(entries, period, periodKey);
601
723
  deterministic = true;
724
+ if (period === "week" || period === "month") trackProvisionalAttempt(metadata, existingMeta);
602
725
  }
726
+ metadata.deterministic = deterministic;
603
727
  try {
604
- await db.insert(summaries).values({
605
- mind: SYSTEM_MIND,
606
- period,
607
- period_key: periodKey,
608
- content,
609
- metadata: JSON.stringify({ deterministic, minds, source_count: rows.length })
610
- }).onConflictDoNothing();
728
+ if (existing) {
729
+ await db.update(summaries).set({ content, metadata: JSON.stringify(metadata) }).where(eq(summaries.id, existing.id));
730
+ } else {
731
+ await db.insert(summaries).values({
732
+ mind: SYSTEM_MIND,
733
+ period,
734
+ period_key: periodKey,
735
+ content,
736
+ metadata: JSON.stringify(metadata)
737
+ }).onConflictDoNothing();
738
+ }
611
739
  } catch (err) {
612
740
  sLog.error(`failed to persist system ${period} summary (${periodKey})`, logger_default.errorData(err));
613
741
  }
614
742
  }
743
+ async function repairProvisionalSummaries(complete = aiCompleteUtility) {
744
+ const db = await getDb();
745
+ const rows = await db.select({
746
+ mind: summaries.mind,
747
+ period: summaries.period,
748
+ period_key: summaries.period_key,
749
+ metadata: summaries.metadata
750
+ }).from(summaries).where(inArray(summaries.period, ["week", "month"]));
751
+ const due = rows.filter((r) => shouldRetry(r.period, parseMeta(r.metadata)));
752
+ due.sort((a, b) => (a.mind === SYSTEM_MIND ? 1 : 0) - (b.mind === SYSTEM_MIND ? 1 : 0));
753
+ for (const r of due) {
754
+ try {
755
+ if (r.mind === SYSTEM_MIND) {
756
+ await summarizeSystem(r.period, r.period_key, complete);
757
+ } else {
758
+ await summarizePeriod(r.mind, r.period, r.period_key, complete);
759
+ }
760
+ } catch (err) {
761
+ sLog.error(
762
+ `failed to repair provisional ${r.period} summary for ${r.mind} (${r.period_key})`,
763
+ logger_default.errorData(err)
764
+ );
765
+ }
766
+ }
767
+ }
615
768
  async function mindsWithTurnSummaries(start, end) {
616
769
  const db = await getDb();
617
770
  const rows = await db.select({ mind: summaries.mind }).from(summaries).where(
@@ -756,6 +909,95 @@ async function backfill() {
756
909
  }
757
910
  }
758
911
  }
912
+ async function healMissing(period, needed, process) {
913
+ if (needed.size === 0) return;
914
+ const db = await getDb();
915
+ const keys = [...needed.keys()];
916
+ 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)));
917
+ const have = new Set(existing.map((r) => `${r.mind}|${r.period_key}`));
918
+ for (const [key2, minds] of needed) {
919
+ let gap = !have.has(`${SYSTEM_MIND}|${key2}`);
920
+ if (!gap) {
921
+ for (const mind of minds) {
922
+ if (!have.has(`${mind}|${key2}`)) {
923
+ gap = true;
924
+ break;
925
+ }
926
+ }
927
+ }
928
+ if (!gap) continue;
929
+ try {
930
+ await process(key2);
931
+ } catch (err) {
932
+ sLog.error(`reconcile ${period} ${key2} failed`, logger_default.errorData(err));
933
+ }
934
+ }
935
+ }
936
+ function addNeeded(map, key2, mind) {
937
+ let set = map.get(key2);
938
+ if (!set) {
939
+ set = /* @__PURE__ */ new Set();
940
+ map.set(key2, set);
941
+ }
942
+ set.add(mind);
943
+ }
944
+ async function reconcileMissingSummaries(lookbackDays = 7) {
945
+ const db = await getDb();
946
+ const now = /* @__PURE__ */ new Date();
947
+ const windowStart = new Date(now);
948
+ windowStart.setDate(windowStart.getDate() - lookbackDays);
949
+ const currentHourKey = getPeriodKey(now, "hour");
950
+ const currentDayKey = getPeriodKey(now, "day");
951
+ const currentWeekKey = getPeriodKey(now, "week");
952
+ const currentMonthKey = getPeriodKey(now, "month");
953
+ const cutoffDayKey = getPeriodKey(windowStart, "day");
954
+ const turnRows = await db.select({ mind: summaries.mind, created_at: summaries.created_at }).from(summaries).where(
955
+ and(
956
+ eq(summaries.period, "turn"),
957
+ gte(summaries.created_at, utcDateTimeStr(windowStart)),
958
+ sql`${summaries.mind} != ${SYSTEM_MIND}`
959
+ )
960
+ );
961
+ const neededHours = /* @__PURE__ */ new Map();
962
+ for (const r of turnRows) {
963
+ const key2 = getPeriodKey(parseUtcDateTime(r.created_at), "hour");
964
+ if (key2 === currentHourKey) continue;
965
+ addNeeded(neededHours, key2, r.mind);
966
+ }
967
+ await healMissing("hour", neededHours, processHour);
968
+ const hourRows = await db.select({ mind: summaries.mind, period_key: summaries.period_key }).from(summaries).where(
969
+ and(
970
+ eq(summaries.period, "hour"),
971
+ gte(summaries.period_key, cutoffDayKey),
972
+ sql`${summaries.mind} != ${SYSTEM_MIND}`
973
+ )
974
+ );
975
+ const neededDays = /* @__PURE__ */ new Map();
976
+ for (const r of hourRows) {
977
+ const key2 = r.period_key.slice(0, 10);
978
+ if (key2 === currentDayKey) continue;
979
+ addNeeded(neededDays, key2, r.mind);
980
+ }
981
+ await healMissing("day", neededDays, processDay);
982
+ const dayRows = await db.select({ mind: summaries.mind, period_key: summaries.period_key }).from(summaries).where(
983
+ and(
984
+ eq(summaries.period, "day"),
985
+ gte(summaries.period_key, cutoffDayKey),
986
+ sql`${summaries.mind} != ${SYSTEM_MIND}`
987
+ )
988
+ );
989
+ const neededWeeks = /* @__PURE__ */ new Map();
990
+ const neededMonths = /* @__PURE__ */ new Map();
991
+ for (const r of dayRows) {
992
+ const d = /* @__PURE__ */ new Date(`${r.period_key}T00:00:00`);
993
+ const weekKey = getPeriodKey(d, "week");
994
+ if (weekKey !== currentWeekKey) addNeeded(neededWeeks, weekKey, r.mind);
995
+ const monthKey = r.period_key.slice(0, 7);
996
+ if (monthKey !== currentMonthKey) addNeeded(neededMonths, monthKey, r.mind);
997
+ }
998
+ await healMissing("week", neededWeeks, processWeek);
999
+ await healMissing("month", neededMonths, processMonth);
1000
+ }
759
1001
  var Summarizer = class {
760
1002
  interval = null;
761
1003
  lastHourKey = null;
@@ -777,6 +1019,7 @@ var Summarizer = class {
777
1019
  this.hasBackfilled = true;
778
1020
  }
779
1021
  await reconcileWedgedTurns(WEDGED_TURN_IDLE_MS);
1022
+ await reconcileMissingSummaries();
780
1023
  const now = /* @__PURE__ */ new Date();
781
1024
  const currentHourKey = getPeriodKey(now, "hour");
782
1025
  if (this.lastHourKey && this.lastHourKey !== currentHourKey) {
@@ -799,17 +1042,18 @@ var Summarizer = class {
799
1042
  if (!await summaryExists(SYSTEM_MIND, "month", prevMonthKey)) {
800
1043
  await processMonth(prevMonthKey);
801
1044
  }
1045
+ await repairProvisionalSummaries();
802
1046
  } catch (err) {
803
1047
  sLog.error("tick failed", logger_default.errorData(err));
804
1048
  }
805
1049
  }
806
1050
  };
807
1051
  async function reconcileWedgedTurns(idleMs) {
808
- const { sweepWedgedTurns: sweepWedgedTurns2, summarizeOrphanedTurns: summarizeOrphanedTurns2 } = await import("./turn-tracker-FOIBNUUA.js");
1052
+ const { sweepWedgedTurns: sweepWedgedTurns2, summarizeOrphanedTurns: summarizeOrphanedTurns2 } = await import("./turn-tracker-KLPV3PAU.js");
809
1053
  const wedged = await sweepWedgedTurns2(idleMs);
810
1054
  if (wedged.length === 0) return;
811
1055
  summarizeOrphanedTurns2(wedged);
812
- const { tryGetDeliveryManager } = await import("./delivery-manager-JINZRG2W.js");
1056
+ const { tryGetDeliveryManager } = await import("./delivery-manager-HZTT5SJR.js");
813
1057
  const dm = tryGetDeliveryManager();
814
1058
  if (!dm) return;
815
1059
  for (const t of wedged) {
@@ -1010,6 +1254,8 @@ export {
1010
1254
  subscribe,
1011
1255
  subscribeAll,
1012
1256
  publish,
1257
+ isoWeekKeyForDateStr,
1258
+ utcDateTimeStr,
1013
1259
  summarizeTurn,
1014
1260
  initSummarizer,
1015
1261
  markErrored,