@rubytech/create-realagent-code 0.1.603 → 0.1.605
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/dist/__tests__/email-sampler-unit.test.js +22 -0
- package/dist/index.js +3 -0
- package/dist/port-resolution.js +9 -1
- package/package.json +1 -1
- package/payload/platform/lib/routine-templates/dist/roster.d.ts +46 -2
- package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -1
- package/payload/platform/lib/routine-templates/dist/roster.js +84 -32
- package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -1
- package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +0 -0
- package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +48 -2
- package/payload/platform/lib/routine-templates/src/roster.ts +133 -35
- package/payload/platform/lib/telegram-store-read/dist/index.d.ts +59 -0
- package/payload/platform/lib/telegram-store-read/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/telegram-store-read/dist/index.js +219 -0
- package/payload/platform/lib/telegram-store-read/dist/index.js.map +1 -0
- package/payload/platform/lib/telegram-store-read/src/__tests__/fold.test.ts +124 -0
- package/payload/platform/lib/telegram-store-read/src/index.ts +262 -0
- package/payload/platform/lib/telegram-store-read/tsconfig.json +9 -0
- package/payload/platform/lib/telegram-store-read/vitest.config.ts +9 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +39 -6
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +11 -0
- package/payload/platform/plugins/connector/PLUGIN.md +9 -1
- package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.d.ts +2 -0
- package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.d.ts.map +1 -0
- package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.js +67 -0
- package/payload/platform/plugins/connector/mcp/dist/__tests__/queue-descriptor.test.js.map +1 -0
- package/payload/platform/plugins/connector/mcp/dist/index.js +36 -5
- package/payload/platform/plugins/connector/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/connector/mcp/dist/lib/store.d.ts +35 -0
- package/payload/platform/plugins/connector/mcp/dist/lib/store.d.ts.map +1 -1
- package/payload/platform/plugins/connector/mcp/dist/lib/store.js +33 -0
- package/payload/platform/plugins/connector/mcp/dist/lib/store.js.map +1 -1
- package/payload/platform/plugins/connector/mcp/package.json +4 -2
- package/payload/platform/plugins/connector/mcp/vitest.config.ts +8 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/plugins/docs/references/outlook-guide.md +21 -2
- package/payload/platform/plugins/docs/references/telegram-guide.md +15 -1
- package/payload/platform/plugins/email/PLUGIN.md +14 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.js +233 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/retention.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js +30 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/main.js +68 -3
- package/payload/platform/plugins/email/mcp/dist/sampler/main.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.d.ts +3 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.js +146 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention-sources.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention.d.ts +150 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention.js +199 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/retention.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts +5 -0
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js +10 -5
- package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js +11 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +8 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.js +324 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sample-outlook-mailbox.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.js +102 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-cursor.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.js +125 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/sampler-enumerate.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.js +109 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/arm.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.d.ts +25 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.js +94 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/cursor.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.d.ts +41 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.js +122 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/enumerate.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.d.ts +73 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.js +162 -0
- package/payload/platform/plugins/outlook/mcp/dist/sampler/sample-outlook-mailbox.js.map +1 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +8 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.js +90 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-flag.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js +26 -4
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.d.ts +78 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.js +76 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate-flag.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +8 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js +9 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js +15 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +12 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +34 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +9 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js +40 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +435 -5
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +21 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts +294 -6
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +553 -11
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/public/operator.html +1 -1
- package/payload/server/server.js +69 -5
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* routine's prompt only when the stored `routineTemplateVersion` is BELOW this
|
|
36
36
|
* and no operator has edited the row, so an unbumped edit ships to new installs
|
|
37
37
|
* and never reaches existing ones — bump it in the same commit as the edit. */
|
|
38
|
-
export const ROUTINE_TEMPLATE_VERSION =
|
|
38
|
+
export const ROUTINE_TEMPLATE_VERSION = 10;
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Task 2379 — the check shapes a shipped template may name.
|
|
@@ -78,13 +78,61 @@ export interface RoutineGraphCheck {
|
|
|
78
78
|
readonly type: "graph";
|
|
79
79
|
readonly scope: "appointments";
|
|
80
80
|
}
|
|
81
|
+
/** Task 2684 — nodes of one label this routine has not yet flagged processed.
|
|
82
|
+
*
|
|
83
|
+
* The other graph check compares one stored timestamp, which can skip a node
|
|
84
|
+
* written between the probe and the promote. This one holds no position at all:
|
|
85
|
+
* "outstanding for this routine" is an exact set, so a node the probe missed is
|
|
86
|
+
* simply still unflagged next fire.
|
|
87
|
+
*
|
|
88
|
+
* `label` is a closed pair rather than a free string because a Cypher label
|
|
89
|
+
* cannot be a parameter. `Section` and `ConversationArchive` are different
|
|
90
|
+
* grains: sections are written per ingest, so new content always arrives
|
|
91
|
+
* unflagged, while an archive is MERGEd per thread, so a reply into a thread
|
|
92
|
+
* this routine already flagged leaves that node flagged. */
|
|
93
|
+
export interface RoutineGraphUnflaggedCheck {
|
|
94
|
+
readonly type: "graph-unflagged";
|
|
95
|
+
readonly label: "ConversationArchive" | "Section";
|
|
96
|
+
}
|
|
97
|
+
/** Task 2689 — the memory sweep's own state: its two review queues, and whether
|
|
98
|
+
* it has stopped running. No fields, because an account has exactly one sweep
|
|
99
|
+
* and one of each queue. What is compared is a digest, so the routine wakes
|
|
100
|
+
* when a queue moves or the sweep goes silent, never merely because the sweep
|
|
101
|
+
* ran again — it runs hourly and this routine is weekly. */
|
|
102
|
+
/** Task 2688 — records changed in a connector this account registered, since
|
|
103
|
+
* the routine last woke.
|
|
104
|
+
*
|
|
105
|
+
* `scope` is a KIND of connector, never a name: the account describes the
|
|
106
|
+
* queue once, on the connector's own registry record, and the template names
|
|
107
|
+
* only which kind it watches. That is what lets a shipped template gate on a
|
|
108
|
+
* third-party system at all, since it can carry no per-account value (Task
|
|
109
|
+
* 2389). A connector that is not registered, or whose credential is refused,
|
|
110
|
+
* answers quiet, so the routine no-ops rather than erroring every fire. */
|
|
111
|
+
export interface RoutineConnectorCheck {
|
|
112
|
+
readonly type: "connector";
|
|
113
|
+
readonly scope: "operational" | "accounting";
|
|
114
|
+
}
|
|
115
|
+
export interface RoutineSweepCheck {
|
|
116
|
+
readonly type: "sweep";
|
|
117
|
+
}
|
|
118
|
+
/** Task 2689 — growth under the account's own directory since the last accepted
|
|
119
|
+
* wake. `minGrowthBytes` is a size rather than per-account data, so a shipped
|
|
120
|
+
* template may name it and still be correct on every install. */
|
|
121
|
+
export interface RoutineFilesystemCheck {
|
|
122
|
+
readonly type: "filesystem";
|
|
123
|
+
readonly minGrowthBytes?: number;
|
|
124
|
+
}
|
|
81
125
|
export type RoutineGateCheck =
|
|
82
126
|
| RoutineMailCheck
|
|
83
127
|
| RoutineD1Check
|
|
84
128
|
| RoutineWhatsappCheck
|
|
85
129
|
| RoutineCalendarCheck
|
|
86
130
|
| RoutineTelegramCheck
|
|
87
|
-
| RoutineGraphCheck
|
|
131
|
+
| RoutineGraphCheck
|
|
132
|
+
| RoutineGraphUnflaggedCheck
|
|
133
|
+
| RoutineConnectorCheck
|
|
134
|
+
| RoutineSweepCheck
|
|
135
|
+
| RoutineFilesystemCheck;
|
|
88
136
|
|
|
89
137
|
/** The plugin and the tool are constants for every roster gate, so a template
|
|
90
138
|
* carries neither. `hasWork` is true when ANY check is true. */
|
|
@@ -115,13 +163,34 @@ export interface RoutineGate {
|
|
|
115
163
|
* on every fire exactly as a commitless mail gate does. */
|
|
116
164
|
export function isWatermarkedCheck(check: RoutineGateCheck): boolean {
|
|
117
165
|
if (check.type === "whatsapp") return check.scope === "inbound";
|
|
166
|
+
// Task 2684 — `graph-unflagged` is NOT watermarked, and it is the first check
|
|
167
|
+
// that is neither watermarked nor stateless. Its state is a flag on each node,
|
|
168
|
+
// written by the dispatcher on an accepted wake, so it needs no stored
|
|
169
|
+
// position and a routine gated only on it needs no commit line. It is listed
|
|
170
|
+
// by omission from the set below, and a test pins that: a later edit that
|
|
171
|
+
// added it here would make `gateNeedsCommit` demand a commit for a check that
|
|
172
|
+
// has no mark to advance.
|
|
173
|
+
//
|
|
118
174
|
// Task 2681 — `graph` compares an ISO `updatedAt` against a stored one, so a
|
|
119
175
|
// commitless graph gate reports work on every fire exactly as a mail one does.
|
|
176
|
+
//
|
|
177
|
+
// Task 2688 — `connector` holds one position PER registered connector, and
|
|
178
|
+
// compares each against the instant that connector's queue was last read, so
|
|
179
|
+
// it is watermarked for the same reason.
|
|
180
|
+
//
|
|
181
|
+
// Task 2689 — `sweep` compares a digest and `filesystem` compares a byte
|
|
182
|
+
// count, both against a stored value, so both belong here for the same
|
|
183
|
+
// reason. Their positions are promoted by the dispatcher on an accepted wake,
|
|
184
|
+
// which is what makes "since the last report" literal rather than "since the
|
|
185
|
+
// last fire".
|
|
120
186
|
return (
|
|
121
187
|
check.type === "mail" ||
|
|
122
188
|
check.type === "calendar" ||
|
|
123
189
|
check.type === "telegram" ||
|
|
124
|
-
check.type === "graph"
|
|
190
|
+
check.type === "graph" ||
|
|
191
|
+
check.type === "connector" ||
|
|
192
|
+
check.type === "sweep" ||
|
|
193
|
+
check.type === "filesystem"
|
|
125
194
|
);
|
|
126
195
|
}
|
|
127
196
|
|
|
@@ -224,18 +293,6 @@ Say what is unfinished and what tomorrow looks like, in that order, in plain sen
|
|
|
224
293
|
|
|
225
294
|
If nothing is waiting, nothing is overdue and tomorrow is empty, end the turn without replying.`;
|
|
226
295
|
|
|
227
|
-
const APPOINTMENT_REMINDER = `Remind the people attending an appointment that is coming up, so nobody is reminded twice and nobody is missed.
|
|
228
|
-
|
|
229
|
-
Call capabilities-here first. If neither a mail plugin nor a messaging channel is enabled, end the turn without replying.
|
|
230
|
-
|
|
231
|
-
Find appointments starting within the next reminder window with schedule-list, and read each one's attendees. Resolve each attendee to a person and a contact route with contact-lookup. An attendee you cannot resolve to a route is not a failure to work around: leave them, and say so at the end.
|
|
232
|
-
|
|
233
|
-
Send each attendee one reminder on the route they are already reachable on: email-send for a mailbox, whatsapp-reply or the Telegram message tool for a messaging thread that already exists. Carry the time, the place and what the appointment is about. Do not open a new conversation with someone who has never messaged the business.
|
|
234
|
-
|
|
235
|
-
Send at most one reminder per attendee per appointment. Before sending, check the appointment's notes for a reminder already recorded, and record the one you send there.
|
|
236
|
-
|
|
237
|
-
Reply with one line naming who was reminded and who could not be reached. If no appointment falls in the window, end the turn without replying.`;
|
|
238
|
-
|
|
239
296
|
const COMMITMENT_CHASE = `Find the promises the business has made and not kept, and the promises made to it that nobody has kept.
|
|
240
297
|
|
|
241
298
|
Call capabilities-here first and use only the surfaces it reports.
|
|
@@ -362,7 +419,20 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
362
419
|
"Sends one morning message covering what needs a decision, what is time-bound and what changed overnight; stays silent when there is nothing worth saying.",
|
|
363
420
|
recurrence: "30 7 * * 1-5",
|
|
364
421
|
prompt: START_OF_DAY,
|
|
365
|
-
|
|
422
|
+
// Task 2686 — the briefing's two gateable arms. `Section` rather than
|
|
423
|
+
// `ConversationArchive` on every email-driven row here: sections are written
|
|
424
|
+
// per ingest, so a reply into a thread this routine already flagged arrives
|
|
425
|
+
// as a fresh unflagged node, while the archive is MERGEd per thread and
|
|
426
|
+
// would stay flagged — muting the routine on the traffic it exists to read.
|
|
427
|
+
// The check names a label and not a source, so any ingested content wakes
|
|
428
|
+
// these rows, which over-wakes and never mutes. The briefing's third arm,
|
|
429
|
+
// open and overdue work, has no check type: Task 2714.
|
|
430
|
+
gate: {
|
|
431
|
+
checks: [
|
|
432
|
+
{ type: "graph-unflagged", label: "Section" },
|
|
433
|
+
{ type: "graph", scope: "appointments" },
|
|
434
|
+
],
|
|
435
|
+
},
|
|
366
436
|
},
|
|
367
437
|
{
|
|
368
438
|
key: "inbound-check",
|
|
@@ -371,7 +441,10 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
371
441
|
"Triages mail that arrived since the last check and writes replies for you to approve; it never sends anything itself.",
|
|
372
442
|
recurrence: "*/30 9-17 * * 1-5",
|
|
373
443
|
prompt: INBOUND_CHECK,
|
|
374
|
-
|
|
444
|
+
// Task 2686 — the mail check still cannot name a mailbox, but the sampler
|
|
445
|
+
// puts every inbound message in the graph, so the unflagged-section check
|
|
446
|
+
// reaches the same mail without per-account data.
|
|
447
|
+
gate: { checks: [{ type: "graph-unflagged", label: "Section" }] },
|
|
375
448
|
},
|
|
376
449
|
{
|
|
377
450
|
key: "telegram-inbound-check",
|
|
@@ -386,19 +459,18 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
386
459
|
key: "end-of-day",
|
|
387
460
|
name: "End of day wrap-up",
|
|
388
461
|
description:
|
|
389
|
-
"Closes the day with your unsent drafts, overdue work and tomorrow's diary
|
|
462
|
+
"Closes the day with your unsent drafts, overdue work and tomorrow's diary, once new mail or a diary change has woken it.",
|
|
390
463
|
recurrence: "0 18 * * 1-5",
|
|
391
464
|
prompt: END_OF_DAY,
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
gateless: "Conditional on an appointment falling in the window, but no check type reads appointments held in the graph (Task 2389).",
|
|
465
|
+
// Task 2686 — the wrap-up wakes on new mail or a diary change. Its other two
|
|
466
|
+
// surfaces, unsent drafts and overdue work, have no check type, so a day
|
|
467
|
+
// whose only outstanding item is one of those is silent until Task 2714.
|
|
468
|
+
gate: {
|
|
469
|
+
checks: [
|
|
470
|
+
{ type: "graph-unflagged", label: "Section" },
|
|
471
|
+
{ type: "graph", scope: "appointments" },
|
|
472
|
+
],
|
|
473
|
+
},
|
|
402
474
|
},
|
|
403
475
|
{
|
|
404
476
|
key: "commitment-chase",
|
|
@@ -407,7 +479,11 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
407
479
|
"Surfaces promises the business made and did not keep, and promises made to it that nobody kept; it reports them rather than chasing them.",
|
|
408
480
|
recurrence: "0 10 * * 2",
|
|
409
481
|
prompt: COMMITMENT_CHASE,
|
|
410
|
-
|
|
482
|
+
// Task 2686 — a dropped promise is a judgement, but the correspondence it
|
|
483
|
+
// judges is not: this wakes when inbound mail it has not read is in the
|
|
484
|
+
// graph. Its outbound arm reads sent mail, which the sampler does not ingest
|
|
485
|
+
// and no shipped template can name a mailbox for: Task 2715.
|
|
486
|
+
gate: { checks: [{ type: "graph-unflagged", label: "Section" }] },
|
|
411
487
|
},
|
|
412
488
|
{
|
|
413
489
|
key: "calendar-reconcile",
|
|
@@ -427,7 +503,9 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
427
503
|
"Reconciles the people you correspond with against the people on record, creating and updating contacts; it never merges two records that might be two people.",
|
|
428
504
|
recurrence: "45 6 * * 1-5",
|
|
429
505
|
prompt: CONTACT_RECONCILE,
|
|
430
|
-
|
|
506
|
+
// Task 2686 — correspondence is readable now: the sampler writes it and the
|
|
507
|
+
// unflagged-section check counts what this routine has not reconciled.
|
|
508
|
+
gate: { checks: [{ type: "graph-unflagged", label: "Section" }] },
|
|
431
509
|
},
|
|
432
510
|
{
|
|
433
511
|
key: "crm-reconcile",
|
|
@@ -436,7 +514,9 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
436
514
|
"Brings across what changed in whichever operational system this business runs; it reads only and never writes back to that system.",
|
|
437
515
|
recurrence: "0 3 * * *",
|
|
438
516
|
prompt: CRM_RECONCILE,
|
|
439
|
-
|
|
517
|
+
// Task 2688 — wakes when a connector the account registered as its
|
|
518
|
+
// operational system holds records changed since the last accepted wake.
|
|
519
|
+
gate: { checks: [{ type: "connector", scope: "operational" }] },
|
|
440
520
|
},
|
|
441
521
|
{
|
|
442
522
|
key: "finance-reconcile",
|
|
@@ -445,7 +525,10 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
445
525
|
"Reconciles the accounting system against the internal ledger and reports what does not agree; it never adjusts an entry to make the two sides match.",
|
|
446
526
|
recurrence: "0 4 * * 1",
|
|
447
527
|
prompt: FINANCE_RECONCILE,
|
|
448
|
-
|
|
528
|
+
// Task 2688 — wakes on movement in the connector the account registered as
|
|
529
|
+
// its accounting system. A connector that is absent or whose credential is
|
|
530
|
+
// refused answers quiet, so this no-ops rather than erroring every fire.
|
|
531
|
+
gate: { checks: [{ type: "connector", scope: "accounting" }] },
|
|
449
532
|
},
|
|
450
533
|
{
|
|
451
534
|
key: "weekly-digest",
|
|
@@ -454,7 +537,15 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
454
537
|
"Writes the week in three paragraphs at most: what changed, what is stuck, and what next week turns on.",
|
|
455
538
|
recurrence: "0 16 * * 5",
|
|
456
539
|
prompt: WEEKLY_DIGEST,
|
|
457
|
-
|
|
540
|
+
// Task 2686 — a week with no correspondence and no diary movement has
|
|
541
|
+
// nothing to report movement on, so the digest is silent rather than
|
|
542
|
+
// writing three paragraphs about a week in which nothing happened.
|
|
543
|
+
gate: {
|
|
544
|
+
checks: [
|
|
545
|
+
{ type: "graph-unflagged", label: "Section" },
|
|
546
|
+
{ type: "graph", scope: "appointments" },
|
|
547
|
+
],
|
|
548
|
+
},
|
|
458
549
|
},
|
|
459
550
|
{
|
|
460
551
|
key: "channel-link-check",
|
|
@@ -472,7 +563,11 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
472
563
|
"Reports what the hourly graph sweep last did and what is waiting for review; it reads only and never runs the sweep itself.",
|
|
473
564
|
recurrence: "0 9 * * 1",
|
|
474
565
|
prompt: GRAPH_HEALTH,
|
|
475
|
-
|
|
566
|
+
// Task 2689 — the sweep's state IS the delta. The digest carries the two
|
|
567
|
+
// review-queue counts and whether the sweep has stopped writing reports,
|
|
568
|
+
// never the newest report's identity: the sweep runs hourly, so a digest
|
|
569
|
+
// that moved on every run would make this weekly routine wake every fire.
|
|
570
|
+
gate: { checks: [{ type: "sweep" }] },
|
|
476
571
|
},
|
|
477
572
|
{
|
|
478
573
|
key: "filesystem-health",
|
|
@@ -481,7 +576,10 @@ export const ROUTINE_ROSTER: readonly RoutineTemplate[] = [
|
|
|
481
576
|
"Reports what has grown under the account directory and which paths are worth attention; it deletes nothing.",
|
|
482
577
|
recurrence: "0 9 * * 1",
|
|
483
578
|
prompt: FILESYSTEM_HEALTH,
|
|
484
|
-
|
|
579
|
+
// Task 2689 — 64 MiB of growth under the account directory since the last
|
|
580
|
+
// report. What has ACCUMULATED is the question, so an account that is large
|
|
581
|
+
// and stable has nothing new to say and the routine stays silent.
|
|
582
|
+
gate: { checks: [{ type: "filesystem", minGrowthBytes: 67108864 }] },
|
|
485
583
|
},
|
|
486
584
|
];
|
|
487
585
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** One stored message with every patch that names it already applied. */
|
|
2
|
+
export interface FoldedMessage {
|
|
3
|
+
messageId: string;
|
|
4
|
+
/** ISO 8601, this install's clock at write time — NOT Telegram's own second. */
|
|
5
|
+
dateSent: string;
|
|
6
|
+
/** The patched body when an update replaced it, else the row's own. */
|
|
7
|
+
body: string;
|
|
8
|
+
/** 'inbound' | 'agent' | 'operator-manual'. Kept as the string the store
|
|
9
|
+
* holds: a reader that meets an origin this build does not know should show
|
|
10
|
+
* it, not drop the message. */
|
|
11
|
+
origin: string;
|
|
12
|
+
fromMe: boolean;
|
|
13
|
+
senderId: string;
|
|
14
|
+
senderName: string | null;
|
|
15
|
+
/** The sender withdrew this at their end. The body is KEPT: Telegram sends
|
|
16
|
+
* none on a deletion, so the stored body is the only account anywhere of what
|
|
17
|
+
* was withdrawn. */
|
|
18
|
+
deleted: boolean;
|
|
19
|
+
/** Servable attachment ids in arrival order, de-duplicated. Raw ids, never
|
|
20
|
+
* resolved metadata — see the file header. */
|
|
21
|
+
attachmentIds: string[];
|
|
22
|
+
/** A card's inline-keyboard labels. Null on an ordinary message that never
|
|
23
|
+
* carried a keyboard; an EMPTY ARRAY when an edit removed the one it had.
|
|
24
|
+
* The two are different facts and the distinction is the route's, kept here
|
|
25
|
+
* so the agent and the operator cannot read one card two ways. */
|
|
26
|
+
buttons: {
|
|
27
|
+
text: string;
|
|
28
|
+
data: string | null;
|
|
29
|
+
}[] | null;
|
|
30
|
+
}
|
|
31
|
+
export interface ConversationCensus {
|
|
32
|
+
/** Store files in this directory holding a storable channel key. */
|
|
33
|
+
conversations: number;
|
|
34
|
+
/** Message rows across all of them. Update rows are patches, not messages, and
|
|
35
|
+
* counting them would inflate the total. */
|
|
36
|
+
rows: number;
|
|
37
|
+
/** Newest `dateSent` anywhere in the directory, or null when empty. */
|
|
38
|
+
newest: string | null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One conversation, oldest first, with every patch applied.
|
|
42
|
+
*
|
|
43
|
+
* Empty for an unstorable key, a missing directory and a conversation with no
|
|
44
|
+
* file. Those are three different facts, and none of them is an error the caller
|
|
45
|
+
* can act on differently: all three mean there is nothing stored to show.
|
|
46
|
+
*/
|
|
47
|
+
export declare function readFoldedConversation(storeDir: string, channelKey: string): FoldedMessage[];
|
|
48
|
+
/**
|
|
49
|
+
* What this account's store actually holds.
|
|
50
|
+
*
|
|
51
|
+
* `conversations` beside `rows` is load-bearing. A tool that returns nothing
|
|
52
|
+
* looks identical to a conversation that is empty, and `conversations=0
|
|
53
|
+
* rows=0` is also exactly what a reader pointed at the wrong directory prints —
|
|
54
|
+
* which is the failure Task 2644 shipped and Task 2557 named. With both numbers,
|
|
55
|
+
* a zero result on an account showing `conversations>0` is a wrong chat id, and
|
|
56
|
+
* `conversations=0` on a live account is a dead reader.
|
|
57
|
+
*/
|
|
58
|
+
export declare function conversationCensus(storeDir: string): ConversationCensus;
|
|
59
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwCA,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb;;oCAEgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;yBAEqB;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB;mDAC+C;IAC/C,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB;;;uEAGmE;IACnE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,GAAG,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB;iDAC6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAsGD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa,EAAE,CAiC5F;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CA+BvE"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readFoldedConversation = readFoldedConversation;
|
|
4
|
+
exports.conversationCensus = conversationCensus;
|
|
5
|
+
/**
|
|
6
|
+
* Task 2709 — reading one Telegram conversation back off disk, patches folded.
|
|
7
|
+
*
|
|
8
|
+
* The store is the only complete record of a Telegram conversation. No platform
|
|
9
|
+
* path writes a `:Message` node for Telegram: `persistMessage` in
|
|
10
|
+
* `ui/app/lib/neo4j-store.ts` has one caller, the webchat customer-inbound path,
|
|
11
|
+
* so a `:Message` carrying `channel:'telegram'` was written by an agent calling
|
|
12
|
+
* `memory-write` and records only what that agent chose to save. On 2026-08-13
|
|
13
|
+
* that was every inbound and one of ten outbound, and the agent read it back as
|
|
14
|
+
* the whole conversation.
|
|
15
|
+
*
|
|
16
|
+
* A message row is never rewritten once appended — `telegram-reader.ts` streams
|
|
17
|
+
* byte offsets as SSE resume ids, so a read-modify-write would invalidate every
|
|
18
|
+
* offset behind it. A correction is therefore a SECOND line, a
|
|
19
|
+
* `TelegramUpdateRecord`, naming its target. Reading the message rows alone
|
|
20
|
+
* yields the pre-patch text: a voice note's placeholder instead of its
|
|
21
|
+
* transcript, an edited message's original wording, and a withdrawn message with
|
|
22
|
+
* nothing saying it was withdrawn. Folding is what makes the read truthful,
|
|
23
|
+
* which is why this is a library and not four lines at the call site.
|
|
24
|
+
*
|
|
25
|
+
* Attachment ids come back RAW. `telegram-reader.ts` resolves each one to
|
|
26
|
+
* servable metadata against an uploads directory, because it is answering a
|
|
27
|
+
* browser; an agent has no use for that URL, and importing the uploads directory
|
|
28
|
+
* into the MCP would drag an HTTP concern across the plugin boundary. The three
|
|
29
|
+
* rules that ARE shared — body last-write-wins, buttons last-write-wins, deleted
|
|
30
|
+
* sticky-true — are pinned against the route by
|
|
31
|
+
* `ui/app/lib/telegram/__tests__/store-read-boundary.test.ts`.
|
|
32
|
+
*
|
|
33
|
+
* The key and filename rules are imported from `telegram-reach` rather than
|
|
34
|
+
* restated. That module is already the one derivation the store writer uses, and
|
|
35
|
+
* Task 2644 is the record of what a second derivation costs.
|
|
36
|
+
*/
|
|
37
|
+
const node_fs_1 = require("node:fs");
|
|
38
|
+
const node_path_1 = require("node:path");
|
|
39
|
+
const index_js_1 = require("../../telegram-reach/dist/index.js");
|
|
40
|
+
function parseLines(raw) {
|
|
41
|
+
const out = [];
|
|
42
|
+
for (const line of raw.split("\n")) {
|
|
43
|
+
if (!line.trim())
|
|
44
|
+
continue;
|
|
45
|
+
try {
|
|
46
|
+
out.push(JSON.parse(line));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// A partial write from a crash mid-append is skipped, never fatal: one
|
|
50
|
+
// corrupt line must not hide every other message in the conversation.
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
function isUpdateRow(row) {
|
|
56
|
+
return row.kind === "update";
|
|
57
|
+
}
|
|
58
|
+
function readButtons(value) {
|
|
59
|
+
if (!Array.isArray(value))
|
|
60
|
+
return null;
|
|
61
|
+
const out = [];
|
|
62
|
+
for (const b of value) {
|
|
63
|
+
if (!b || typeof b !== "object")
|
|
64
|
+
continue;
|
|
65
|
+
const { text, data } = b;
|
|
66
|
+
if (typeof text !== "string")
|
|
67
|
+
continue;
|
|
68
|
+
out.push({ text, data: typeof data === "string" ? data : null });
|
|
69
|
+
}
|
|
70
|
+
return out.length > 0 ? out : null;
|
|
71
|
+
}
|
|
72
|
+
/** Fold every update row into one patch per target id.
|
|
73
|
+
*
|
|
74
|
+
* Mirrors `telegram-reader.ts:77-106`. Later rows win for the body and the
|
|
75
|
+
* buttons. Attachment ids accumulate in arrival order and are de-duplicated per
|
|
76
|
+
* target, because two rows can legitimately name the same id: `appendMessage`
|
|
77
|
+
* dedupes a Telegram redelivery, but the route does not read that result — it
|
|
78
|
+
* downloads again, resolves the SAME deterministic id, and patches again.
|
|
79
|
+
* `deleted` is sticky: a withdrawal is not undone by a later transcript or
|
|
80
|
+
* media patch, and letting one clear it would hide the withdrawal. */
|
|
81
|
+
function foldPatches(rows) {
|
|
82
|
+
const out = new Map();
|
|
83
|
+
for (const row of rows) {
|
|
84
|
+
if (!isUpdateRow(row))
|
|
85
|
+
continue;
|
|
86
|
+
if (typeof row.targetMessageId !== "string")
|
|
87
|
+
continue;
|
|
88
|
+
const patch = out.get(row.targetMessageId) ?? { attachmentIds: [] };
|
|
89
|
+
if (Array.isArray(row.attachmentIds)) {
|
|
90
|
+
for (const id of row.attachmentIds) {
|
|
91
|
+
if (typeof id !== "string")
|
|
92
|
+
continue;
|
|
93
|
+
if (patch.attachmentIds.includes(id))
|
|
94
|
+
continue;
|
|
95
|
+
patch.attachmentIds.push(id);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (typeof row.body === "string")
|
|
99
|
+
patch.body = row.body;
|
|
100
|
+
// Keyed on the field BEING an array, not on it holding anything. An operator
|
|
101
|
+
// editing a card down to no buttons produces `buttons: []`, and that is a
|
|
102
|
+
// removal: the route reads it as one, because an empty array is truthy
|
|
103
|
+
// there. Treating it as "no patch" would keep showing the agent buttons the
|
|
104
|
+
// customer can no longer see, with nothing failing while the two surfaces
|
|
105
|
+
// disagreed.
|
|
106
|
+
if (Array.isArray(row.buttons))
|
|
107
|
+
patch.buttons = readButtons(row.buttons) ?? [];
|
|
108
|
+
if (row.deleted === true)
|
|
109
|
+
patch.deleted = true;
|
|
110
|
+
out.set(row.targetMessageId, patch);
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
function conversationFile(storeDir, channelKey) {
|
|
115
|
+
// The guard, not the path. Both halves of a key are Telegram numeric ids
|
|
116
|
+
// around an optional literal `biz`, so a key that passes cannot carry a `.`,
|
|
117
|
+
// `/` or `\`, and one that fails is refused rather than sanitised into a path
|
|
118
|
+
// nobody asked for.
|
|
119
|
+
if (!(0, index_js_1.isStorableChannelKey)(channelKey))
|
|
120
|
+
return null;
|
|
121
|
+
return (0, node_path_1.join)(storeDir, `${(0, index_js_1.channelKeyToFileStem)(channelKey)}.jsonl`);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* One conversation, oldest first, with every patch applied.
|
|
125
|
+
*
|
|
126
|
+
* Empty for an unstorable key, a missing directory and a conversation with no
|
|
127
|
+
* file. Those are three different facts, and none of them is an error the caller
|
|
128
|
+
* can act on differently: all three mean there is nothing stored to show.
|
|
129
|
+
*/
|
|
130
|
+
function readFoldedConversation(storeDir, channelKey) {
|
|
131
|
+
const file = conversationFile(storeDir, channelKey);
|
|
132
|
+
if (file === null || !(0, node_fs_1.existsSync)(file))
|
|
133
|
+
return [];
|
|
134
|
+
let raw;
|
|
135
|
+
try {
|
|
136
|
+
raw = (0, node_fs_1.readFileSync)(file, "utf8");
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
const rows = parseLines(raw);
|
|
142
|
+
const patches = foldPatches(rows);
|
|
143
|
+
const out = [];
|
|
144
|
+
for (const row of rows) {
|
|
145
|
+
if (isUpdateRow(row))
|
|
146
|
+
continue;
|
|
147
|
+
if (typeof row.messageId !== "string")
|
|
148
|
+
continue;
|
|
149
|
+
if (typeof row.dateSent !== "string")
|
|
150
|
+
continue;
|
|
151
|
+
const patch = patches.get(row.messageId);
|
|
152
|
+
out.push({
|
|
153
|
+
messageId: row.messageId,
|
|
154
|
+
dateSent: row.dateSent,
|
|
155
|
+
body: patch?.body ?? (typeof row.body === "string" ? row.body : ""),
|
|
156
|
+
origin: typeof row.origin === "string" ? row.origin : "inbound",
|
|
157
|
+
fromMe: row.fromMe === true,
|
|
158
|
+
senderId: typeof row.senderId === "string" ? row.senderId : "",
|
|
159
|
+
senderName: typeof row.senderName === "string" ? row.senderName : null,
|
|
160
|
+
deleted: patch?.deleted === true,
|
|
161
|
+
attachmentIds: patch?.attachmentIds ?? [],
|
|
162
|
+
buttons: patch?.buttons ?? readButtons(row.buttons),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// Sort AFTER folding, so a patch that arrived before its target in file order
|
|
166
|
+
// still lands on it. Ties keep file order, which is arrival order.
|
|
167
|
+
return out.sort((a, b) => a.dateSent.localeCompare(b.dateSent));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* What this account's store actually holds.
|
|
171
|
+
*
|
|
172
|
+
* `conversations` beside `rows` is load-bearing. A tool that returns nothing
|
|
173
|
+
* looks identical to a conversation that is empty, and `conversations=0
|
|
174
|
+
* rows=0` is also exactly what a reader pointed at the wrong directory prints —
|
|
175
|
+
* which is the failure Task 2644 shipped and Task 2557 named. With both numbers,
|
|
176
|
+
* a zero result on an account showing `conversations>0` is a wrong chat id, and
|
|
177
|
+
* `conversations=0` on a live account is a dead reader.
|
|
178
|
+
*/
|
|
179
|
+
function conversationCensus(storeDir) {
|
|
180
|
+
const empty = { conversations: 0, rows: 0, newest: null };
|
|
181
|
+
if (!storeDir || !(0, node_fs_1.existsSync)(storeDir))
|
|
182
|
+
return empty;
|
|
183
|
+
let entries;
|
|
184
|
+
try {
|
|
185
|
+
entries = (0, node_fs_1.readdirSync)(storeDir);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return empty;
|
|
189
|
+
}
|
|
190
|
+
let conversations = 0;
|
|
191
|
+
let rows = 0;
|
|
192
|
+
let newest = null;
|
|
193
|
+
for (const entry of entries) {
|
|
194
|
+
if (!entry.endsWith(".jsonl"))
|
|
195
|
+
continue;
|
|
196
|
+
const channelKey = (0, index_js_1.fileStemToChannelKey)(entry.slice(0, -".jsonl".length));
|
|
197
|
+
if (!(0, index_js_1.isStorableChannelKey)(channelKey))
|
|
198
|
+
continue;
|
|
199
|
+
conversations += 1;
|
|
200
|
+
let raw;
|
|
201
|
+
try {
|
|
202
|
+
raw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(storeDir, entry), "utf8");
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
for (const row of parseLines(raw)) {
|
|
208
|
+
if (isUpdateRow(row))
|
|
209
|
+
continue;
|
|
210
|
+
rows += 1;
|
|
211
|
+
if (typeof row.dateSent !== "string")
|
|
212
|
+
continue;
|
|
213
|
+
if (newest === null || newest.localeCompare(row.dateSent) < 0)
|
|
214
|
+
newest = row.dateSent;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return { conversations, rows, newest };
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|