@jungjaehoon/mama-os 0.32.3 → 0.34.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 +15 -17
- package/dist/agent/os-agent-capabilities.md +2 -2
- package/dist/api/graph-api.d.ts +4 -4
- package/dist/api/graph-api.d.ts.map +1 -1
- package/dist/api/graph-api.js +47 -78
- package/dist/api/graph-api.js.map +1 -1
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +9 -2
- package/dist/api/index.js.map +1 -1
- package/dist/api/operator-handler.d.ts +1 -1
- package/dist/api/operator-handler.js +1 -1
- package/dist/api/runtime-status-handler.d.ts +41 -0
- package/dist/api/runtime-status-handler.d.ts.map +1 -0
- package/dist/api/runtime-status-handler.js +55 -0
- package/dist/api/runtime-status-handler.js.map +1 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +58 -23
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/runtime/api-routes-init.d.ts +2 -0
- package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-routes-init.js +62 -1
- package/dist/cli/runtime/api-routes-init.js.map +1 -1
- package/dist/cli/runtime/api-server-init.d.ts +12 -1
- package/dist/cli/runtime/api-server-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-server-init.js +54 -0
- package/dist/cli/runtime/api-server-init.js.map +1 -1
- package/dist/cli/runtime/utilities.d.ts +1 -1
- package/dist/cli/runtime/utilities.d.ts.map +1 -1
- package/dist/cli/runtime/utilities.js +3 -1
- package/dist/cli/runtime/utilities.js.map +1 -1
- package/dist/gateways/message-router.d.ts +4 -0
- package/dist/gateways/message-router.d.ts.map +1 -1
- package/dist/gateways/message-router.js +62 -13
- package/dist/gateways/message-router.js.map +1 -1
- package/dist/gateways/owner-report-inbox.d.ts +40 -0
- package/dist/gateways/owner-report-inbox.d.ts.map +1 -0
- package/dist/gateways/owner-report-inbox.js +128 -0
- package/dist/gateways/owner-report-inbox.js.map +1 -0
- package/dist/gateways/report-projection-v1.d.ts +41 -0
- package/dist/gateways/report-projection-v1.d.ts.map +1 -0
- package/dist/gateways/report-projection-v1.js +160 -0
- package/dist/gateways/report-projection-v1.js.map +1 -0
- package/dist/gateways/session-store.d.ts +22 -0
- package/dist/gateways/session-store.d.ts.map +1 -1
- package/dist/gateways/session-store.js +76 -3
- package/dist/gateways/session-store.js.map +1 -1
- package/dist/gateways/telegram-message-ledger.d.ts +10 -0
- package/dist/gateways/telegram-message-ledger.d.ts.map +1 -1
- package/dist/gateways/telegram-message-ledger.js +23 -2
- package/dist/gateways/telegram-message-ledger.js.map +1 -1
- package/dist/gateways/telegram-report-context-store.d.ts +193 -0
- package/dist/gateways/telegram-report-context-store.d.ts.map +1 -0
- package/dist/gateways/telegram-report-context-store.js +612 -0
- package/dist/gateways/telegram-report-context-store.js.map +1 -0
- package/dist/gateways/telegram.d.ts +9 -0
- package/dist/gateways/telegram.d.ts.map +1 -1
- package/dist/gateways/telegram.js +100 -0
- package/dist/gateways/telegram.js.map +1 -1
- package/dist/gateways/types.d.ts +12 -0
- package/dist/gateways/types.d.ts.map +1 -1
- package/dist/multi-agent/dashboard-agent-persona.js +2 -2
- package/dist/operator/board-slot-instructions.d.ts +1 -1
- package/dist/operator/board-slot-instructions.js +1 -1
- package/dist/operator/operator-trigger-loop.d.ts +17 -1
- package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
- package/dist/operator/operator-trigger-loop.js +87 -23
- package/dist/operator/operator-trigger-loop.js.map +1 -1
- package/dist/operator/report-delivery-coordinator.d.ts +82 -0
- package/dist/operator/report-delivery-coordinator.d.ts.map +1 -0
- package/dist/operator/report-delivery-coordinator.js +123 -0
- package/dist/operator/report-delivery-coordinator.js.map +1 -0
- package/dist/operator/situation-report.d.ts +7 -0
- package/dist/operator/situation-report.d.ts.map +1 -1
- package/dist/operator/situation-report.js +12 -0
- package/dist/operator/situation-report.js.map +1 -1
- package/package.json +1 -2
- package/public/viewer/js/modules/system.js +183 -0
- package/public/viewer/js/utils/ui-commands.js +4 -9
- package/public/viewer/log-viewer.html +2 -192
- package/public/viewer/operator/operator.css +1 -0
- package/public/viewer/operator/operator.js +14830 -0
- package/public/viewer/src/modules/system.ts +242 -0
- package/public/viewer/src/utils/ui-commands.ts +4 -8
- package/public/viewer/sw.js +44 -10
- package/public/viewer/viewer.css +338 -331
- package/public/viewer/viewer.html +388 -1472
- package/public/ui/assets/index-BDXDGEV6.js +0 -62
- package/public/ui/assets/index-po2tN0xq.css +0 -1
- package/public/ui/index.html +0 -14
- package/public/ui/theme-init.js +0 -20
- package/public/viewer/js/modules/agents.js +0 -1153
- package/public/viewer/js/modules/chat.js +0 -1993
- package/public/viewer/js/modules/connector-feed.js +0 -352
- package/public/viewer/js/modules/dashboard.js +0 -456
- package/public/viewer/js/modules/entity-audit.js +0 -106
- package/public/viewer/js/modules/entity-review.js +0 -66
- package/public/viewer/js/modules/settings.js +0 -1257
- package/public/viewer/src/modules/agents.ts +0 -1302
- package/public/viewer/src/modules/chat.ts +0 -2426
- package/public/viewer/src/modules/connector-feed.ts +0 -391
- package/public/viewer/src/modules/dashboard.ts +0 -498
- package/public/viewer/src/modules/entity-audit.ts +0 -154
- package/public/viewer/src/modules/entity-review.ts +0 -175
- package/public/viewer/src/modules/settings.ts +0 -1547
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TG-05/TG-06: Telegram owner-report context inbox store.
|
|
4
|
+
*
|
|
5
|
+
* The messenger SQLite database is the single report-context authority for
|
|
6
|
+
* owner-report delivery events and turn-consumption receipts
|
|
7
|
+
* (docs/development/telegram-outbound-context-inbox-design.md, Decision 4).
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.TelegramReportContextStore = void 0;
|
|
11
|
+
const node_crypto_1 = require("node:crypto");
|
|
12
|
+
const node_fs_1 = require("node:fs");
|
|
13
|
+
const untrusted_content_js_1 = require("../utils/untrusted-content.js");
|
|
14
|
+
/**
|
|
15
|
+
* TG-05 Slice K (design Decision 8): the EXACT legacy V2 prefix algorithm,
|
|
16
|
+
* including the UTF-16 `slice(0, 700)` truncation (a surrogate split at the
|
|
17
|
+
* boundary is preserved, not repaired). report-carry.ts deliberately does NOT
|
|
18
|
+
* export its builder (legacy-export cull, pinned by report-carry.test.ts), so
|
|
19
|
+
* this replica is pinned byte-for-byte against the public peek() surface by a
|
|
20
|
+
* differential test instead.
|
|
21
|
+
*/
|
|
22
|
+
const LEGACY_CARRY_SUMMARY_MAX_CHARS = 700;
|
|
23
|
+
function legacyReportCarryPrefix(record) {
|
|
24
|
+
const summary = record.text.length > LEGACY_CARRY_SUMMARY_MAX_CHARS
|
|
25
|
+
? `${record.text.slice(0, LEGACY_CARRY_SUMMARY_MAX_CHARS)}\n[... truncated - full text was delivered to the owner channel]`
|
|
26
|
+
: record.text;
|
|
27
|
+
return (`[Operator context] The last FULL situation report was delivered at ${record.deliveredAt}.\n` +
|
|
28
|
+
'If the owner asks for a report or current status, reference/refresh THIS instead of ' +
|
|
29
|
+
`reconstructing state from memory. Content:\n${(0, untrusted_content_js_1.wrapUntrustedContent)('operator-report-carry', summary)}\n---\n`);
|
|
30
|
+
}
|
|
31
|
+
/** Design Decision 5 initial limits. */
|
|
32
|
+
const DEFAULT_LIVE_ROW_CAP = 2_048;
|
|
33
|
+
const DEFAULT_LIVE_BYTE_CAP = 64 * 1024 * 1024;
|
|
34
|
+
const DEFAULT_RETAINED_ROW_CAP = 8_192;
|
|
35
|
+
const DEFAULT_RETAINED_BYTE_CAP = 256 * 1024 * 1024;
|
|
36
|
+
const TOMBSTONE_REPLAY_FLOOR_MS = 7 * 24 * 60 * 60 * 1000;
|
|
37
|
+
const TOMBSTONE_MAX_AGE_MS = 365 * 24 * 60 * 60 * 1000;
|
|
38
|
+
const DEFAULT_TOMBSTONE_CAP = 100_000;
|
|
39
|
+
/** Live = prepared or delivered-but-unconsumed (design Decision 5). */
|
|
40
|
+
const LIVE_ROW_CONDITION = `(
|
|
41
|
+
state IN ('prepared_retryable', 'prepared_definite_rejection')
|
|
42
|
+
OR (state = 'delivered' AND disposition = 'pending')
|
|
43
|
+
)`;
|
|
44
|
+
function targetIdentity(target) {
|
|
45
|
+
return JSON.stringify([target.source, target.channelId]);
|
|
46
|
+
}
|
|
47
|
+
function isLegacyCarryV2(value) {
|
|
48
|
+
if (!value || typeof value !== 'object')
|
|
49
|
+
return false;
|
|
50
|
+
const record = value;
|
|
51
|
+
const target = record.target;
|
|
52
|
+
const provenance = record.provenance;
|
|
53
|
+
return (record.version === 2 &&
|
|
54
|
+
typeof record.deliveryId === 'string' &&
|
|
55
|
+
record.deliveryId.length > 0 &&
|
|
56
|
+
typeof target === 'object' &&
|
|
57
|
+
target !== null &&
|
|
58
|
+
target.source === 'telegram' &&
|
|
59
|
+
typeof target.channelId === 'string' &&
|
|
60
|
+
typeof record.deliveredAt === 'string' &&
|
|
61
|
+
typeof record.text === 'string' &&
|
|
62
|
+
typeof provenance === 'object' &&
|
|
63
|
+
provenance !== null &&
|
|
64
|
+
(record.consumedAt === undefined || typeof record.consumedAt === 'string'));
|
|
65
|
+
}
|
|
66
|
+
class TelegramReportContextStore {
|
|
67
|
+
db;
|
|
68
|
+
nowIso;
|
|
69
|
+
liveRowCap;
|
|
70
|
+
liveByteCap;
|
|
71
|
+
retainedRowCap;
|
|
72
|
+
retainedByteCap;
|
|
73
|
+
constructor(db, options = {}) {
|
|
74
|
+
this.db = db;
|
|
75
|
+
this.nowIso = options.nowIso ?? (() => new Date().toISOString());
|
|
76
|
+
this.liveRowCap = options.liveRowCapPerTarget ?? DEFAULT_LIVE_ROW_CAP;
|
|
77
|
+
this.liveByteCap = options.liveByteCapPerTarget ?? DEFAULT_LIVE_BYTE_CAP;
|
|
78
|
+
this.retainedRowCap = options.retainedRowCapPerTarget ?? DEFAULT_RETAINED_ROW_CAP;
|
|
79
|
+
this.retainedByteCap = options.retainedByteCapPerTarget ?? DEFAULT_RETAINED_BYTE_CAP;
|
|
80
|
+
this.runMigration();
|
|
81
|
+
if (options.legacyCarryPath) {
|
|
82
|
+
this.migrateLegacyCarry(options.legacyCarryPath);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* TG-05 Slice K: migrate the legacy V2 carry file. Unconsumed -> a
|
|
87
|
+
* delivered-pending event (even past the old 24h TTL); consumed -> a
|
|
88
|
+
* target-scoped legacy restoration record carrying the EXACT old prefix
|
|
89
|
+
* bytes. Transactionally insert/verify, commit, then atomically rename the
|
|
90
|
+
* source `.migrated`. Invalid files are quarantined and never injected.
|
|
91
|
+
*/
|
|
92
|
+
migrateLegacyCarry(path) {
|
|
93
|
+
if (!(0, node_fs_1.existsSync)(path)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
let record;
|
|
97
|
+
try {
|
|
98
|
+
const parsed = JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
|
|
99
|
+
if (!isLegacyCarryV2(parsed)) {
|
|
100
|
+
throw new Error('not a V2 report carry record');
|
|
101
|
+
}
|
|
102
|
+
record = parsed;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
(0, node_fs_1.renameSync)(path, `${path}.quarantined-${Date.now()}`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const provenanceTuple = record.provenance.status === 'available'
|
|
109
|
+
? ['available', record.provenance.modelRunId]
|
|
110
|
+
: ['unavailable', record.provenance.reason];
|
|
111
|
+
const payloadIdentity = (0, node_crypto_1.createHash)('sha256')
|
|
112
|
+
.update(JSON.stringify([
|
|
113
|
+
'legacy-report-carry-v2',
|
|
114
|
+
record.deliveryId,
|
|
115
|
+
record.target.source,
|
|
116
|
+
record.target.channelId,
|
|
117
|
+
record.deliveredAt,
|
|
118
|
+
record.text,
|
|
119
|
+
provenanceTuple,
|
|
120
|
+
]), 'utf8')
|
|
121
|
+
.digest('hex');
|
|
122
|
+
this.db.transaction(() => {
|
|
123
|
+
if (record.consumedAt) {
|
|
124
|
+
const existing = this.db
|
|
125
|
+
.prepare('SELECT payload_identity FROM telegram_report_legacy_restorations WHERE delivery_id = ?')
|
|
126
|
+
.get(record.deliveryId);
|
|
127
|
+
if (existing) {
|
|
128
|
+
if (existing.payload_identity !== payloadIdentity) {
|
|
129
|
+
throw new Error(`Legacy carry ${record.deliveryId} identity conflict during migration replay`);
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const restorationText = legacyReportCarryPrefix(record);
|
|
134
|
+
this.db
|
|
135
|
+
.prepare(`INSERT INTO telegram_report_legacy_restorations
|
|
136
|
+
(delivery_id, target, channel_key, delivered_at, consumed_at,
|
|
137
|
+
restoration_text, legacy_projection_hash, payload_identity)
|
|
138
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
139
|
+
.run(record.deliveryId, targetIdentity(record.target), record.consumingChannelKey ?? null, record.deliveredAt, record.consumedAt,
|
|
140
|
+
// JSON-encoded: the legacy UTF-16 slice(0,700) can split a
|
|
141
|
+
// surrogate pair, and a lone surrogate does not survive SQLite's
|
|
142
|
+
// UTF-8 TEXT round-trip. JSON escapes it losslessly.
|
|
143
|
+
JSON.stringify(restorationText), (0, node_crypto_1.createHash)('sha256').update(restorationText, 'utf8').digest('hex'), payloadIdentity);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const existing = this.db
|
|
147
|
+
.prepare('SELECT payload_identity FROM telegram_report_context_events WHERE delivery_id = ?')
|
|
148
|
+
.get(record.deliveryId);
|
|
149
|
+
if (existing) {
|
|
150
|
+
if (existing.payload_identity !== payloadIdentity) {
|
|
151
|
+
throw new Error(`Legacy carry ${record.deliveryId} identity conflict during migration replay`);
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.db
|
|
156
|
+
.prepare(`INSERT INTO telegram_report_context_events
|
|
157
|
+
(delivery_id, target, mode, occurrence, provenance, text, payload_identity,
|
|
158
|
+
state, disposition, created_at, delivered_at)
|
|
159
|
+
VALUES (?, ?, 'full', ?, ?, ?, ?, 'delivered', 'pending', ?, ?)`)
|
|
160
|
+
.run(record.deliveryId, targetIdentity(record.target), JSON.stringify({ kind: 'legacy_v2' }), JSON.stringify(record.provenance), record.text, payloadIdentity, this.nowIso(), record.deliveredAt);
|
|
161
|
+
})();
|
|
162
|
+
(0, node_fs_1.renameSync)(path, `${path}.migrated`);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Idempotently insert the exact prepared report before any external send.
|
|
166
|
+
* A replay of the same delivery ID must carry the identical payload; any
|
|
167
|
+
* divergence is an identity conflict and never silently overwrites.
|
|
168
|
+
*/
|
|
169
|
+
reserve(input) {
|
|
170
|
+
const existing = this.db
|
|
171
|
+
.prepare(`SELECT seq, delivery_id, target, mode, occurrence, provenance, text, payload_identity, state
|
|
172
|
+
FROM telegram_report_context_events WHERE delivery_id = ?`)
|
|
173
|
+
.get(input.deliveryId);
|
|
174
|
+
if (existing) {
|
|
175
|
+
const semanticsMatch = existing.target === targetIdentity(input.target) &&
|
|
176
|
+
existing.mode === input.mode &&
|
|
177
|
+
existing.text === input.text;
|
|
178
|
+
if (semanticsMatch && existing.payload_identity !== input.payloadIdentity) {
|
|
179
|
+
// Design Decision 8: a richer pending artifact may replay a MIGRATED
|
|
180
|
+
// delivery ID; the current identity is recorded as an alias only when
|
|
181
|
+
// target, mode, exact text, and provenance all match.
|
|
182
|
+
const isMigratedRow = existing.occurrence === JSON.stringify({ kind: 'legacy_v2' });
|
|
183
|
+
const provenanceMatches = existing.provenance ===
|
|
184
|
+
(input.provenance === undefined ? null : JSON.stringify(input.provenance));
|
|
185
|
+
if (isMigratedRow && provenanceMatches) {
|
|
186
|
+
this.db
|
|
187
|
+
.prepare('UPDATE telegram_report_context_events SET payload_identity_alias = ? WHERE delivery_id = ?')
|
|
188
|
+
.run(input.payloadIdentity, input.deliveryId);
|
|
189
|
+
return { seq: existing.seq, deliveryId: existing.delivery_id, state: existing.state };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (!semanticsMatch || existing.payload_identity !== input.payloadIdentity) {
|
|
193
|
+
throw new Error(`Owner report delivery ${input.deliveryId} identity conflict: replay does not match the reserved report`);
|
|
194
|
+
}
|
|
195
|
+
return { seq: existing.seq, deliveryId: existing.delivery_id, state: existing.state };
|
|
196
|
+
}
|
|
197
|
+
// Design Decision 5: compact consumed exact records under retained
|
|
198
|
+
// pressure, then refuse the reservation outright when live data alone is
|
|
199
|
+
// full. The failure happens BEFORE any Telegram send.
|
|
200
|
+
this.compactRetained(input.target);
|
|
201
|
+
this.enforceLiveCapacity(input.target);
|
|
202
|
+
const inserted = this.db
|
|
203
|
+
.prepare(`INSERT INTO telegram_report_context_events
|
|
204
|
+
(delivery_id, target, mode, occurrence, provenance, text, payload_identity, state, created_at)
|
|
205
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 'prepared_retryable', ?)
|
|
206
|
+
RETURNING seq`)
|
|
207
|
+
.get(input.deliveryId, targetIdentity(input.target), input.mode, JSON.stringify(input.occurrence), input.provenance === undefined ? null : JSON.stringify(input.provenance), input.text, input.payloadIdentity, this.nowIso());
|
|
208
|
+
return { seq: inserted.seq, deliveryId: input.deliveryId, state: 'prepared_retryable' };
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Atomically transition a confirmed send to `delivered`. Idempotent: an
|
|
212
|
+
* already-delivered row keeps its original delivery time so crash-recovery
|
|
213
|
+
* replays converge instead of rewriting history.
|
|
214
|
+
*/
|
|
215
|
+
markDelivered(deliveryId, deliveredAtIso) {
|
|
216
|
+
const updated = this.db
|
|
217
|
+
.prepare(`UPDATE telegram_report_context_events
|
|
218
|
+
SET state = 'delivered', disposition = 'pending', delivered_at = ?
|
|
219
|
+
WHERE delivery_id = ? AND state = 'prepared_retryable'`)
|
|
220
|
+
.run(deliveredAtIso, deliveryId);
|
|
221
|
+
if (updated.changes > 0) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const existing = this.db
|
|
225
|
+
.prepare('SELECT state FROM telegram_report_context_events WHERE delivery_id = ?')
|
|
226
|
+
.get(deliveryId);
|
|
227
|
+
if (!existing) {
|
|
228
|
+
throw new Error(`Unknown owner report delivery ${deliveryId}`);
|
|
229
|
+
}
|
|
230
|
+
if (existing.state !== 'delivered') {
|
|
231
|
+
throw new Error(`Owner report delivery ${deliveryId} cannot be marked delivered from state ${existing.state}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Compare-and-swap attempt lease: exactly one holder may execute a Telegram
|
|
236
|
+
* send at a time. A live lease excludes every new claim - another worker,
|
|
237
|
+
* another tick, or the same owner - and an expired lease is recoverable
|
|
238
|
+
* after restart. Returns null when no claim is possible.
|
|
239
|
+
*/
|
|
240
|
+
claimAttempt(deliveryId, owner, nowIso, leaseUntilIso) {
|
|
241
|
+
const updated = this.db
|
|
242
|
+
.prepare(`UPDATE telegram_report_context_events
|
|
243
|
+
SET attempt_owner = ?, lease_until = ?, attempt_count = attempt_count + 1
|
|
244
|
+
WHERE delivery_id = ?
|
|
245
|
+
AND state = 'prepared_retryable'
|
|
246
|
+
AND (lease_until IS NULL OR lease_until < ?)
|
|
247
|
+
AND (next_attempt_at IS NULL OR next_attempt_at <= ?)`)
|
|
248
|
+
.run(owner, leaseUntilIso, deliveryId, nowIso, nowIso);
|
|
249
|
+
if (updated.changes === 0) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
return { deliveryId, owner, leaseUntilIso };
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Safe cancellation (design Decision 3): permitted only from
|
|
256
|
+
* prepared_definite_rejection - the one state where the Telegram ledger
|
|
257
|
+
* proves definite non-acceptance and no attempt lease is live. Ambiguous or
|
|
258
|
+
* confirmed acceptance can never be cancelled. Replay on an already
|
|
259
|
+
* cancelled row is a converging no-op that keeps the first audit record.
|
|
260
|
+
*/
|
|
261
|
+
cancel(deliveryId, reason, operatorTimeIso) {
|
|
262
|
+
const updated = this.db
|
|
263
|
+
.prepare(`UPDATE telegram_report_context_events
|
|
264
|
+
SET state = 'cancelled', cancel_reason = ?, cancelled_at = ?,
|
|
265
|
+
attempt_owner = NULL, lease_until = NULL, next_attempt_at = NULL
|
|
266
|
+
WHERE delivery_id = ? AND state = 'prepared_definite_rejection'
|
|
267
|
+
AND attempt_owner IS NULL`)
|
|
268
|
+
.run(reason, operatorTimeIso, deliveryId);
|
|
269
|
+
if (updated.changes > 0) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const existing = this.getEvent(deliveryId);
|
|
273
|
+
if (existing?.state === 'cancelled') {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
throw new Error(`Owner report delivery ${deliveryId} cannot be cancelled: only a definite rejection with no live attempt may be cancelled (state: ${existing?.state ?? 'unknown'})`);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Explicit operator reactivation of a definite rejection after conditions
|
|
280
|
+
* are corrected (for example the bot was unblocked). Same delivery ID, same
|
|
281
|
+
* immutable target; the row becomes immediately recoverable.
|
|
282
|
+
*/
|
|
283
|
+
reactivate(deliveryId) {
|
|
284
|
+
const updated = this.db
|
|
285
|
+
.prepare(`UPDATE telegram_report_context_events
|
|
286
|
+
SET state = 'prepared_retryable', next_attempt_at = NULL
|
|
287
|
+
WHERE delivery_id = ? AND state = 'prepared_definite_rejection'`)
|
|
288
|
+
.run(deliveryId);
|
|
289
|
+
if (updated.changes === 0) {
|
|
290
|
+
const existing = this.getEvent(deliveryId);
|
|
291
|
+
throw new Error(`Owner report delivery ${deliveryId} cannot be reactivated: only a definite rejection may be reactivated (state: ${existing?.state ?? 'unknown'})`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Delivered reports not yet consumed by an owner turn, for one exact
|
|
296
|
+
* target, oldest first. This is the pending-projection source; one chat can
|
|
297
|
+
* never read another target's reports.
|
|
298
|
+
*/
|
|
299
|
+
listDeliveredPending(target) {
|
|
300
|
+
const rows = this.db
|
|
301
|
+
.prepare(`SELECT seq, delivery_id, mode, delivered_at, text
|
|
302
|
+
FROM telegram_report_context_events
|
|
303
|
+
WHERE target = ? AND state = 'delivered' AND disposition = 'pending'
|
|
304
|
+
ORDER BY seq ASC`)
|
|
305
|
+
.all(targetIdentity(target));
|
|
306
|
+
return rows.map((row) => ({
|
|
307
|
+
seq: row.seq,
|
|
308
|
+
deliveryId: row.delivery_id,
|
|
309
|
+
mode: row.mode,
|
|
310
|
+
deliveredAtIso: row.delivered_at,
|
|
311
|
+
text: row.text,
|
|
312
|
+
}));
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Committed receipts for the given source-message references, in the input
|
|
316
|
+
* order. Only text-bearing receipts are returned; a compacted receipt no
|
|
317
|
+
* longer restores.
|
|
318
|
+
*/
|
|
319
|
+
listReceiptsByRefs(refs) {
|
|
320
|
+
const lookup = this.db.prepare(`SELECT source_message_ref, delivery_ids, projection_text, committed_at
|
|
321
|
+
FROM telegram_report_context_receipts WHERE source_message_ref = ?`);
|
|
322
|
+
const results = [];
|
|
323
|
+
for (const ref of refs) {
|
|
324
|
+
const row = lookup.get(ref);
|
|
325
|
+
if (!row || row.projection_text === null) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
results.push({
|
|
329
|
+
sourceMessageRef: row.source_message_ref,
|
|
330
|
+
deliveryIds: JSON.parse(row.delivery_ids),
|
|
331
|
+
projectionText: row.projection_text,
|
|
332
|
+
committedAtIso: row.committed_at,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
return results;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Legacy V2 restorations for one target, eligible for fresh-session history
|
|
339
|
+
* (30 days after consumption, design Decision 8). Restoration text is
|
|
340
|
+
* JSON-decoded back to the exact legacy prefix string.
|
|
341
|
+
*/
|
|
342
|
+
listLegacyRestorations(target, nowIso) {
|
|
343
|
+
const cutoff = new Date(new Date(nowIso).getTime() - 30 * 24 * 60 * 60 * 1000).toISOString();
|
|
344
|
+
const rows = this.db
|
|
345
|
+
.prepare(`SELECT delivery_id, consumed_at, delivered_at, restoration_text
|
|
346
|
+
FROM telegram_report_legacy_restorations
|
|
347
|
+
WHERE target = ? AND consumed_at >= ? AND restoration_text IS NOT NULL
|
|
348
|
+
ORDER BY consumed_at ASC, delivery_id ASC`)
|
|
349
|
+
.all(targetIdentity(target), cutoff);
|
|
350
|
+
return rows.map((row) => ({
|
|
351
|
+
deliveryId: row.delivery_id,
|
|
352
|
+
consumedAtIso: row.consumed_at,
|
|
353
|
+
deliveredAtIso: row.delivered_at,
|
|
354
|
+
restorationText: JSON.parse(row.restoration_text),
|
|
355
|
+
}));
|
|
356
|
+
}
|
|
357
|
+
compactRetained(target) {
|
|
358
|
+
const compactOldestConsumed = this.db.prepare(`UPDATE telegram_report_context_events
|
|
359
|
+
SET text = '', tombstone = 1
|
|
360
|
+
WHERE seq = (
|
|
361
|
+
SELECT seq FROM telegram_report_context_events
|
|
362
|
+
WHERE target = ? AND tombstone = 0
|
|
363
|
+
AND disposition IN ('consumed_turn', 'operator_archived')
|
|
364
|
+
ORDER BY seq ASC LIMIT 1
|
|
365
|
+
)`);
|
|
366
|
+
// Retained = rows still carrying exact text.
|
|
367
|
+
for (;;) {
|
|
368
|
+
const retained = this.db
|
|
369
|
+
.prepare(`SELECT COUNT(*) AS rows, COALESCE(SUM(LENGTH(CAST(text AS BLOB))), 0) AS bytes
|
|
370
|
+
FROM telegram_report_context_events WHERE target = ? AND tombstone = 0`)
|
|
371
|
+
.get(targetIdentity(target));
|
|
372
|
+
if (retained.rows < this.retainedRowCap && retained.bytes < this.retainedByteCap) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const changed = compactOldestConsumed.run(targetIdentity(target)).changes;
|
|
376
|
+
if (changed === 0) {
|
|
377
|
+
// Nothing consumed left to compact; live pressure is handled by the
|
|
378
|
+
// live-capacity check.
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
enforceLiveCapacity(target) {
|
|
384
|
+
const live = this.db
|
|
385
|
+
.prepare(`SELECT COUNT(*) AS rows, COALESCE(SUM(LENGTH(CAST(text AS BLOB))), 0) AS bytes
|
|
386
|
+
FROM telegram_report_context_events
|
|
387
|
+
WHERE target = ? AND ${LIVE_ROW_CONDITION}`)
|
|
388
|
+
.get(targetIdentity(target));
|
|
389
|
+
if (live.rows >= this.liveRowCap || live.bytes >= this.liveByteCap) {
|
|
390
|
+
throw new Error(`capacity_full: owner-report live capacity reached for target (${live.rows} rows, ${live.bytes} bytes); ` +
|
|
391
|
+
'unseen reports must be consumed or explicitly archived before new ones are accepted');
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Design Decision 5: explicit two-step operator action (token flow lives at
|
|
396
|
+
* the API layer). Archives ONLY already-delivered pending rows up to and
|
|
397
|
+
* including `throughSeq`, records the audit fields, and removes them from
|
|
398
|
+
* pending projection and live capacity. Never Telegram cancellation.
|
|
399
|
+
*/
|
|
400
|
+
archiveDelivered(target, throughSeq, actor, reason, nowIso) {
|
|
401
|
+
const rows = this.db
|
|
402
|
+
.prepare(`UPDATE telegram_report_context_events
|
|
403
|
+
SET disposition = 'operator_archived', archived_by = ?, archived_reason = ?, archived_at = ?
|
|
404
|
+
WHERE target = ? AND state = 'delivered' AND disposition = 'pending' AND seq <= ?
|
|
405
|
+
RETURNING delivery_id`)
|
|
406
|
+
.all(actor, reason, nowIso, targetIdentity(target), throughSeq);
|
|
407
|
+
return rows.map((row) => row.delivery_id);
|
|
408
|
+
}
|
|
409
|
+
/** Live usage for the status surface; warn at 80% of either bound. */
|
|
410
|
+
liveUsage(target) {
|
|
411
|
+
const live = this.db
|
|
412
|
+
.prepare(`SELECT COUNT(*) AS rows, COALESCE(SUM(LENGTH(CAST(text AS BLOB))), 0) AS bytes
|
|
413
|
+
FROM telegram_report_context_events
|
|
414
|
+
WHERE target = ? AND ${LIVE_ROW_CONDITION}`)
|
|
415
|
+
.get(targetIdentity(target));
|
|
416
|
+
return {
|
|
417
|
+
rows: live.rows,
|
|
418
|
+
bytes: live.bytes,
|
|
419
|
+
rowCap: this.liveRowCap,
|
|
420
|
+
byteCap: this.liveByteCap,
|
|
421
|
+
warn: live.rows >= this.liveRowCap * 0.8 || live.bytes >= this.liveByteCap * 0.8,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Tombstone GC (design Decision 4): identity tombstones are retained up to
|
|
426
|
+
* 365 days with a global count cap. No tombstone younger than Telegram's
|
|
427
|
+
* seven-day replay window is ever pruned; beyond that floor the oldest
|
|
428
|
+
* terminal tombstones go first. Returns the number of removed rows.
|
|
429
|
+
*/
|
|
430
|
+
pruneTombstones(nowIso, options = {}) {
|
|
431
|
+
const cap = options.maxTombstones ?? DEFAULT_TOMBSTONE_CAP;
|
|
432
|
+
const nowMs = new Date(nowIso).getTime();
|
|
433
|
+
const floorIso = new Date(nowMs - TOMBSTONE_REPLAY_FLOOR_MS).toISOString();
|
|
434
|
+
const maxAgeIso = new Date(nowMs - TOMBSTONE_MAX_AGE_MS).toISOString();
|
|
435
|
+
let removed = this.db
|
|
436
|
+
.prepare(`DELETE FROM telegram_report_context_events
|
|
437
|
+
WHERE tombstone = 1 AND COALESCE(delivered_at, created_at) < ?`)
|
|
438
|
+
.run(maxAgeIso).changes;
|
|
439
|
+
for (;;) {
|
|
440
|
+
const count = this.db
|
|
441
|
+
.prepare('SELECT COUNT(*) AS n FROM telegram_report_context_events WHERE tombstone = 1')
|
|
442
|
+
.get();
|
|
443
|
+
if (count.n <= cap) {
|
|
444
|
+
break;
|
|
445
|
+
}
|
|
446
|
+
const deleted = this.db
|
|
447
|
+
.prepare(`DELETE FROM telegram_report_context_events
|
|
448
|
+
WHERE seq = (
|
|
449
|
+
SELECT seq FROM telegram_report_context_events
|
|
450
|
+
WHERE tombstone = 1 AND COALESCE(delivered_at, created_at) < ?
|
|
451
|
+
ORDER BY seq ASC LIMIT 1
|
|
452
|
+
)`)
|
|
453
|
+
.run(floorIso).changes;
|
|
454
|
+
if (deleted === 0) {
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
removed += deleted;
|
|
458
|
+
}
|
|
459
|
+
return removed;
|
|
460
|
+
}
|
|
461
|
+
/** Read one event's attempt/terminal detail; null when unknown. */
|
|
462
|
+
getEvent(deliveryId) {
|
|
463
|
+
const row = this.db
|
|
464
|
+
.prepare(`SELECT seq, delivery_id, state, attempt_count, next_attempt_at, lease_until,
|
|
465
|
+
rejection_reason, cancel_reason
|
|
466
|
+
FROM telegram_report_context_events WHERE delivery_id = ?`)
|
|
467
|
+
.get(deliveryId);
|
|
468
|
+
if (!row) {
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
return {
|
|
472
|
+
seq: row.seq,
|
|
473
|
+
deliveryId: row.delivery_id,
|
|
474
|
+
state: row.state,
|
|
475
|
+
attemptCount: row.attempt_count,
|
|
476
|
+
nextAttemptAt: row.next_attempt_at,
|
|
477
|
+
leaseUntil: row.lease_until,
|
|
478
|
+
rejectionReason: row.rejection_reason,
|
|
479
|
+
cancelReason: row.cancel_reason,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Record a retryable send failure: keep the row nonterminal, stamp the next
|
|
484
|
+
* attempt time, and release the lease. Only the current lease holder may
|
|
485
|
+
* reshape backoff - a stale worker's outcome must not race a live one.
|
|
486
|
+
*/
|
|
487
|
+
scheduleRetry(deliveryId, owner, nextAttemptAtIso) {
|
|
488
|
+
const updated = this.db
|
|
489
|
+
.prepare(`UPDATE telegram_report_context_events
|
|
490
|
+
SET next_attempt_at = ?, attempt_owner = NULL, lease_until = NULL
|
|
491
|
+
WHERE delivery_id = ? AND state = 'prepared_retryable' AND attempt_owner = ?`)
|
|
492
|
+
.run(nextAttemptAtIso, deliveryId, owner);
|
|
493
|
+
if (updated.changes === 0) {
|
|
494
|
+
throw new Error(`Worker ${owner} does not hold the attempt lease for owner report delivery ${deliveryId}`);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Record a definite Telegram non-acceptance. The row stays pinned in the
|
|
499
|
+
* ledger (nonterminal) and is never automatically retried; only an explicit
|
|
500
|
+
* operator action may reactivate it (design Decision 3).
|
|
501
|
+
*/
|
|
502
|
+
markDefiniteRejection(deliveryId, owner, reason) {
|
|
503
|
+
const updated = this.db
|
|
504
|
+
.prepare(`UPDATE telegram_report_context_events
|
|
505
|
+
SET state = 'prepared_definite_rejection', rejection_reason = ?,
|
|
506
|
+
attempt_owner = NULL, lease_until = NULL, next_attempt_at = NULL
|
|
507
|
+
WHERE delivery_id = ? AND state = 'prepared_retryable' AND attempt_owner = ?`)
|
|
508
|
+
.run(reason, deliveryId, owner);
|
|
509
|
+
if (updated.changes === 0) {
|
|
510
|
+
throw new Error(`Worker ${owner} does not hold the attempt lease for owner report delivery ${deliveryId}`);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Startup/tick recovery: prepared_retryable rows that are due (no future
|
|
515
|
+
* retry scheduled) and not held by a live attempt lease, oldest first.
|
|
516
|
+
*/
|
|
517
|
+
listRecoverable(nowIso) {
|
|
518
|
+
const rows = this.db
|
|
519
|
+
.prepare(`SELECT seq, delivery_id, state FROM telegram_report_context_events
|
|
520
|
+
WHERE state = 'prepared_retryable'
|
|
521
|
+
AND (next_attempt_at IS NULL OR next_attempt_at <= ?)
|
|
522
|
+
AND (lease_until IS NULL OR lease_until < ?)
|
|
523
|
+
ORDER BY seq ASC`)
|
|
524
|
+
.all(nowIso, nowIso);
|
|
525
|
+
return rows.map((row) => ({ seq: row.seq, deliveryId: row.delivery_id, state: row.state }));
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Startup ledger reconciliation input: every nonterminal row must hold a
|
|
529
|
+
* Telegram-ledger pin, every terminal row must not (design Decision 2).
|
|
530
|
+
*/
|
|
531
|
+
listPinReconciliation() {
|
|
532
|
+
const rows = this.db
|
|
533
|
+
.prepare(`SELECT delivery_id, state FROM telegram_report_context_events ORDER BY seq ASC`)
|
|
534
|
+
.all();
|
|
535
|
+
const nonterminal = [];
|
|
536
|
+
const terminal = [];
|
|
537
|
+
for (const row of rows) {
|
|
538
|
+
if (row.state === 'prepared_retryable' || row.state === 'prepared_definite_rejection') {
|
|
539
|
+
nonterminal.push(row.delivery_id);
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
terminal.push(row.delivery_id);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return { nonterminal, terminal };
|
|
546
|
+
}
|
|
547
|
+
runMigration() {
|
|
548
|
+
this.db.exec(`
|
|
549
|
+
CREATE TABLE IF NOT EXISTS telegram_report_context_events (
|
|
550
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
551
|
+
delivery_id TEXT NOT NULL UNIQUE,
|
|
552
|
+
target TEXT NOT NULL,
|
|
553
|
+
mode TEXT NOT NULL CHECK (mode IN ('digest', 'full')),
|
|
554
|
+
occurrence TEXT NOT NULL,
|
|
555
|
+
provenance TEXT,
|
|
556
|
+
text TEXT NOT NULL,
|
|
557
|
+
payload_identity TEXT NOT NULL,
|
|
558
|
+
state TEXT NOT NULL CHECK (
|
|
559
|
+
state IN ('prepared_retryable', 'prepared_definite_rejection', 'delivered', 'cancelled')
|
|
560
|
+
),
|
|
561
|
+
disposition TEXT CHECK (
|
|
562
|
+
disposition IN ('pending', 'consumed_turn', 'operator_archived')
|
|
563
|
+
),
|
|
564
|
+
archived_by TEXT,
|
|
565
|
+
archived_reason TEXT,
|
|
566
|
+
archived_at TEXT,
|
|
567
|
+
created_at TEXT NOT NULL,
|
|
568
|
+
delivered_at TEXT,
|
|
569
|
+
attempt_count INTEGER NOT NULL DEFAULT 0,
|
|
570
|
+
next_attempt_at TEXT,
|
|
571
|
+
attempt_owner TEXT,
|
|
572
|
+
lease_until TEXT,
|
|
573
|
+
rejection_reason TEXT,
|
|
574
|
+
cancelled_at TEXT,
|
|
575
|
+
cancel_reason TEXT,
|
|
576
|
+
consumed_by_ref TEXT,
|
|
577
|
+
consumed_at TEXT,
|
|
578
|
+
payload_identity_alias TEXT,
|
|
579
|
+
tombstone INTEGER NOT NULL DEFAULT 0
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
CREATE INDEX IF NOT EXISTS idx_report_context_events_target_state
|
|
583
|
+
ON telegram_report_context_events(target, state);
|
|
584
|
+
|
|
585
|
+
CREATE TABLE IF NOT EXISTS telegram_report_legacy_restorations (
|
|
586
|
+
delivery_id TEXT PRIMARY KEY,
|
|
587
|
+
target TEXT NOT NULL,
|
|
588
|
+
channel_key TEXT,
|
|
589
|
+
delivered_at TEXT NOT NULL,
|
|
590
|
+
consumed_at TEXT NOT NULL,
|
|
591
|
+
restoration_text TEXT,
|
|
592
|
+
legacy_projection_hash TEXT NOT NULL,
|
|
593
|
+
payload_identity TEXT NOT NULL,
|
|
594
|
+
source_message_ref TEXT,
|
|
595
|
+
session_id TEXT
|
|
596
|
+
);
|
|
597
|
+
|
|
598
|
+
CREATE TABLE IF NOT EXISTS telegram_report_context_receipts (
|
|
599
|
+
source_message_ref TEXT PRIMARY KEY,
|
|
600
|
+
session_id TEXT NOT NULL,
|
|
601
|
+
delivery_ids TEXT NOT NULL,
|
|
602
|
+
projection_version TEXT NOT NULL,
|
|
603
|
+
projection_text TEXT,
|
|
604
|
+
projection_hash TEXT NOT NULL,
|
|
605
|
+
final_response_sha256 TEXT NOT NULL,
|
|
606
|
+
committed_at TEXT NOT NULL
|
|
607
|
+
);
|
|
608
|
+
`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
exports.TelegramReportContextStore = TelegramReportContextStore;
|
|
612
|
+
//# sourceMappingURL=telegram-report-context-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram-report-context-store.js","sourceRoot":"","sources":["../../src/gateways/telegram-report-context-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { BaseGateway } from './base-gateway.js';
|
|
13
13
|
import type { TurnProcessor } from './turn-contract.js';
|
|
14
14
|
import { type TelegramMediaDownloadRequest } from './telegram-media.js';
|
|
15
|
+
import type { TelegramReportDeliveryControl } from '../operator/report-delivery-coordinator.js';
|
|
15
16
|
/**
|
|
16
17
|
* Telegram Gateway configuration
|
|
17
18
|
*/
|
|
@@ -74,6 +75,14 @@ export declare class TelegramGateway extends BaseGateway {
|
|
|
74
75
|
sendMessage(chatId: string, text: string, idempotencyKey?: string): Promise<void>;
|
|
75
76
|
/** Detached system work must wait behind the normal per-chat delivery queue. */
|
|
76
77
|
sendSystemMessage(chatId: string, text: string, deliveryId?: string): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* TG-05/TG-06: narrow owner-report delivery surface for the report
|
|
80
|
+
* coordinator. Pins the delivery-ID-bound ledger entry before the first
|
|
81
|
+
* send so a confirmed-send proof cannot be pruned while the report-context
|
|
82
|
+
* SQLite row remains nonterminal, and classifies send failures with the
|
|
83
|
+
* gateway's own definite-rejection test.
|
|
84
|
+
*/
|
|
85
|
+
createReportDeliveryControl(): TelegramReportDeliveryControl;
|
|
77
86
|
sendMessageFromActiveTurn(chatId: string, text: string, idempotencyKey?: string): Promise<void>;
|
|
78
87
|
private sendMessageNow;
|
|
79
88
|
sendFile(chatId: string, filePath: string, caption?: string, idempotencyKey?: string): Promise<void>;
|