@jungjaehoon/mama-os 0.26.0 → 0.27.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 (101) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/agent-loop.d.ts.map +1 -1
  3. package/dist/agent/agent-loop.js +6 -0
  4. package/dist/agent/agent-loop.js.map +1 -1
  5. package/dist/agent/attachment-text-extractor.d.ts +2 -0
  6. package/dist/agent/attachment-text-extractor.d.ts.map +1 -0
  7. package/dist/agent/attachment-text-extractor.js +128 -0
  8. package/dist/agent/attachment-text-extractor.js.map +1 -0
  9. package/dist/agent/code-act/constants.d.ts.map +1 -1
  10. package/dist/agent/code-act/constants.js +17 -2
  11. package/dist/agent/code-act/constants.js.map +1 -1
  12. package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
  13. package/dist/agent/code-act/host-bridge.js +55 -2
  14. package/dist/agent/code-act/host-bridge.js.map +1 -1
  15. package/dist/agent/code-act/tool-policy.d.ts +7 -1
  16. package/dist/agent/code-act/tool-policy.d.ts.map +1 -1
  17. package/dist/agent/code-act/tool-policy.js +28 -1
  18. package/dist/agent/code-act/tool-policy.js.map +1 -1
  19. package/dist/agent/codex-app-server-process.d.ts +1 -0
  20. package/dist/agent/codex-app-server-process.d.ts.map +1 -1
  21. package/dist/agent/codex-app-server-process.js +16 -0
  22. package/dist/agent/codex-app-server-process.js.map +1 -1
  23. package/dist/agent/drive-tools.d.ts +2 -0
  24. package/dist/agent/drive-tools.d.ts.map +1 -1
  25. package/dist/agent/drive-tools.js +3 -1
  26. package/dist/agent/drive-tools.js.map +1 -1
  27. package/dist/agent/gateway-tool-executor.d.ts +10 -3
  28. package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
  29. package/dist/agent/gateway-tool-executor.js +207 -26
  30. package/dist/agent/gateway-tool-executor.js.map +1 -1
  31. package/dist/agent/gateway-tools.md +5 -1
  32. package/dist/agent/image-translation-tools.d.ts +48 -0
  33. package/dist/agent/image-translation-tools.d.ts.map +1 -0
  34. package/dist/agent/image-translation-tools.js +274 -0
  35. package/dist/agent/image-translation-tools.js.map +1 -0
  36. package/dist/agent/role-manager.d.ts.map +1 -1
  37. package/dist/agent/role-manager.js +9 -1
  38. package/dist/agent/role-manager.js.map +1 -1
  39. package/dist/agent/tool-registry.d.ts.map +1 -1
  40. package/dist/agent/tool-registry.js +25 -1
  41. package/dist/agent/tool-registry.js.map +1 -1
  42. package/dist/agent/types.d.ts +4 -33
  43. package/dist/agent/types.d.ts.map +1 -1
  44. package/dist/agent/types.js.map +1 -1
  45. package/dist/cli/commands/start.d.ts.map +1 -1
  46. package/dist/cli/commands/start.js +18 -8
  47. package/dist/cli/commands/start.js.map +1 -1
  48. package/dist/cli/config/types.d.ts.map +1 -1
  49. package/dist/cli/config/types.js +5 -1
  50. package/dist/cli/config/types.js.map +1 -1
  51. package/dist/cli/runtime/envelope-bootstrap.js +2 -2
  52. package/dist/cli/runtime/envelope-bootstrap.js.map +1 -1
  53. package/dist/gateways/message-router.d.ts +3 -0
  54. package/dist/gateways/message-router.d.ts.map +1 -1
  55. package/dist/gateways/message-router.js +428 -336
  56. package/dist/gateways/message-router.js.map +1 -1
  57. package/dist/gateways/session-store.d.ts +2 -0
  58. package/dist/gateways/session-store.d.ts.map +1 -1
  59. package/dist/gateways/session-store.js +41 -1
  60. package/dist/gateways/session-store.js.map +1 -1
  61. package/dist/gateways/telegram-media.d.ts +13 -0
  62. package/dist/gateways/telegram-media.d.ts.map +1 -1
  63. package/dist/gateways/telegram-media.js +77 -0
  64. package/dist/gateways/telegram-media.js.map +1 -1
  65. package/dist/gateways/telegram-message-ledger.d.ts +49 -0
  66. package/dist/gateways/telegram-message-ledger.d.ts.map +1 -0
  67. package/dist/gateways/telegram-message-ledger.js +266 -0
  68. package/dist/gateways/telegram-message-ledger.js.map +1 -0
  69. package/dist/gateways/telegram-response-presenter.d.ts +10 -0
  70. package/dist/gateways/telegram-response-presenter.d.ts.map +1 -1
  71. package/dist/gateways/telegram-response-presenter.js +129 -32
  72. package/dist/gateways/telegram-response-presenter.js.map +1 -1
  73. package/dist/gateways/telegram.d.ts +20 -4
  74. package/dist/gateways/telegram.d.ts.map +1 -1
  75. package/dist/gateways/telegram.js +300 -64
  76. package/dist/gateways/telegram.js.map +1 -1
  77. package/dist/operator/operator-interfaces.d.ts +1 -1
  78. package/dist/operator/operator-interfaces.d.ts.map +1 -1
  79. package/dist/operator/operator-trigger-loop.d.ts +12 -0
  80. package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
  81. package/dist/operator/operator-trigger-loop.js +184 -38
  82. package/dist/operator/operator-trigger-loop.js.map +1 -1
  83. package/dist/operator/pending-report-store.d.ts +35 -0
  84. package/dist/operator/pending-report-store.d.ts.map +1 -0
  85. package/dist/operator/pending-report-store.js +155 -0
  86. package/dist/operator/pending-report-store.js.map +1 -0
  87. package/dist/operator/runtime-config.d.ts +10 -0
  88. package/dist/operator/runtime-config.d.ts.map +1 -0
  89. package/dist/operator/runtime-config.js +21 -0
  90. package/dist/operator/runtime-config.js.map +1 -0
  91. package/dist/operator/situation-report.d.ts +37 -0
  92. package/dist/operator/situation-report.d.ts.map +1 -1
  93. package/dist/operator/situation-report.js +122 -9
  94. package/dist/operator/situation-report.js.map +1 -1
  95. package/package.json +3 -1
  96. package/scripts/attachment/extract-office-text.js +179 -0
  97. package/scripts/attachment/extract-pdf-text.swift +36 -0
  98. package/scripts/image/fb-overlay.py +128 -0
  99. package/scripts/image/ocr-image.py +38 -0
  100. package/scripts/setup-ocr.js +120 -0
  101. package/templates/skills/image-translate.md +17 -22
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TelegramMessageLedger = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const DEFAULT_TTL_MS = 7 * 24 * 60 * 60_000;
8
+ const DEFAULT_MAX_ENTRIES = 10_000;
9
+ const MAX_RESPONSE_CHARS = 1_000_000;
10
+ const MAX_LEDGER_FILE_BYTES = 8 * 1024 * 1024;
11
+ class TelegramMessageLedger {
12
+ path;
13
+ entries = new Map();
14
+ ttlMs;
15
+ maxEntries;
16
+ now;
17
+ log;
18
+ ownerId;
19
+ constructor(path, options = {}) {
20
+ this.path = path;
21
+ this.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
22
+ this.maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;
23
+ this.now = options.now ?? Date.now;
24
+ this.log = options.log ?? (() => { });
25
+ this.ownerId = options.ownerId ?? (0, node_crypto_1.randomUUID)();
26
+ this.load();
27
+ }
28
+ get(key) {
29
+ this.prune();
30
+ const entry = this.entries.get(key);
31
+ return entry ? { ...entry } : null;
32
+ }
33
+ has(key) {
34
+ return this.get(key) !== null;
35
+ }
36
+ listUndelivered() {
37
+ this.prune();
38
+ return [...this.entries.values()]
39
+ .filter((entry) => entry.state !== 'delivered')
40
+ .map((entry) => ({ ...entry }));
41
+ }
42
+ isOwnedByCurrentProcess(entry) {
43
+ return entry.ownerId === this.ownerId;
44
+ }
45
+ claim(key) {
46
+ this.prune();
47
+ const existing = this.entries.get(key);
48
+ if (existing)
49
+ return { claimed: false, entry: { ...existing } };
50
+ const entry = {
51
+ key,
52
+ state: 'processing',
53
+ updatedAt: this.now(),
54
+ ownerId: this.ownerId,
55
+ };
56
+ this.commit(() => {
57
+ this.entries.set(key, entry);
58
+ this.enforceEntryLimit();
59
+ });
60
+ return { claimed: true, entry: { ...entry } };
61
+ }
62
+ markReady(key, response) {
63
+ if (response.length > MAX_RESPONSE_CHARS) {
64
+ throw new Error('Telegram durable response exceeds its size limit');
65
+ }
66
+ const entry = this.requireEntry(key);
67
+ this.commit(() => {
68
+ this.entries.set(key, {
69
+ ...entry,
70
+ state: 'ready',
71
+ response,
72
+ nextChunkIndex: 0,
73
+ deliveryUncertain: false,
74
+ updatedAt: this.now(),
75
+ ownerId: this.ownerId,
76
+ });
77
+ });
78
+ }
79
+ markDeliveryProgress(key, nextChunkIndex, deliveryUncertain) {
80
+ if (!Number.isSafeInteger(nextChunkIndex) || nextChunkIndex < 0) {
81
+ throw new Error('Telegram delivery progress must be a non-negative integer');
82
+ }
83
+ const entry = this.requireEntry(key);
84
+ if (entry.state !== 'ready' || entry.response === undefined) {
85
+ throw new Error(`Telegram message ${key} is not ready for delivery`);
86
+ }
87
+ this.commit(() => {
88
+ this.entries.set(key, {
89
+ ...entry,
90
+ nextChunkIndex,
91
+ deliveryUncertain,
92
+ updatedAt: this.now(),
93
+ ownerId: this.ownerId,
94
+ });
95
+ });
96
+ }
97
+ markDelivered(key) {
98
+ this.commit(() => {
99
+ this.entries.delete(key);
100
+ this.entries.set(key, {
101
+ key,
102
+ state: 'delivered',
103
+ updatedAt: this.now(),
104
+ ownerId: this.ownerId,
105
+ });
106
+ this.enforceEntryLimit();
107
+ });
108
+ }
109
+ /** Compatibility alias for the original completed-ID ledger API. */
110
+ record(key) {
111
+ this.markDelivered(key);
112
+ }
113
+ requireEntry(key) {
114
+ const entry = this.entries.get(key);
115
+ if (!entry)
116
+ throw new Error(`Telegram message ${key} has not been claimed`);
117
+ return entry;
118
+ }
119
+ enforceEntryLimit() {
120
+ while (this.entries.size > this.maxEntries) {
121
+ if (!this.evictOldestDelivered()) {
122
+ throw new Error('Telegram message ledger entry limit is full of undelivered work');
123
+ }
124
+ }
125
+ }
126
+ load() {
127
+ if (!(0, node_fs_1.existsSync)(this.path))
128
+ return;
129
+ if ((0, node_fs_1.statSync)(this.path).size > MAX_LEDGER_FILE_BYTES) {
130
+ const error = new Error(`Telegram message ledger exceeds ${MAX_LEDGER_FILE_BYTES} bytes`);
131
+ this.log(`[Telegram] message ledger rejected without modification: ${error.message}`);
132
+ throw error;
133
+ }
134
+ try {
135
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(this.path, 'utf8'));
136
+ if (isLedgerStateV2(parsed, this.maxEntries)) {
137
+ for (const entry of parsed.entries) {
138
+ if (entry.state === 'delivered') {
139
+ const { response: _response, ...delivered } = entry;
140
+ this.entries.set(entry.key, delivered);
141
+ }
142
+ else {
143
+ this.entries.set(entry.key, entry);
144
+ }
145
+ }
146
+ }
147
+ else if (isLedgerStateV1(parsed, this.maxEntries)) {
148
+ for (const entry of parsed.entries) {
149
+ this.entries.set(entry.key, {
150
+ key: entry.key,
151
+ state: 'delivered',
152
+ updatedAt: entry.completedAt,
153
+ ownerId: 'legacy',
154
+ });
155
+ }
156
+ }
157
+ else {
158
+ throw new Error('invalid Telegram message ledger');
159
+ }
160
+ this.prune();
161
+ }
162
+ catch (error) {
163
+ const quarantinePath = `${this.path}.corrupt-${this.now()}-${process.pid}`;
164
+ (0, node_fs_1.renameSync)(this.path, quarantinePath);
165
+ this.entries.clear();
166
+ this.log(`[Telegram] invalid message ledger quarantined at ${quarantinePath}: ${error instanceof Error ? error.message : String(error)}`);
167
+ }
168
+ }
169
+ prune() {
170
+ const cutoff = this.now() - this.ttlMs;
171
+ for (const [key, entry] of this.entries) {
172
+ if (entry.state === 'delivered' && entry.updatedAt < cutoff)
173
+ this.entries.delete(key);
174
+ }
175
+ }
176
+ save() {
177
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(this.path), { recursive: true, mode: 0o700 });
178
+ const temporaryPath = `${this.path}.tmp`;
179
+ let serialized = this.serialize();
180
+ while (Buffer.byteLength(serialized, 'utf8') > MAX_LEDGER_FILE_BYTES) {
181
+ if (!this.evictOldestDelivered()) {
182
+ throw new Error('Telegram message ledger exceeds its durable size limit');
183
+ }
184
+ serialized = this.serialize();
185
+ }
186
+ (0, node_fs_1.writeFileSync)(temporaryPath, serialized, { mode: 0o600 });
187
+ (0, node_fs_1.chmodSync)(temporaryPath, 0o600);
188
+ (0, node_fs_1.renameSync)(temporaryPath, this.path);
189
+ }
190
+ serialize() {
191
+ const state = { version: 2, entries: [...this.entries.values()] };
192
+ return `${JSON.stringify(state)}\n`;
193
+ }
194
+ evictOldestDelivered() {
195
+ for (const [key, entry] of this.entries) {
196
+ if (entry.state === 'delivered') {
197
+ this.entries.delete(key);
198
+ return true;
199
+ }
200
+ }
201
+ return false;
202
+ }
203
+ commit(change) {
204
+ const snapshot = new Map(this.entries);
205
+ try {
206
+ change();
207
+ this.save();
208
+ }
209
+ catch (error) {
210
+ this.entries.clear();
211
+ for (const [key, entry] of snapshot)
212
+ this.entries.set(key, entry);
213
+ throw error;
214
+ }
215
+ }
216
+ }
217
+ exports.TelegramMessageLedger = TelegramMessageLedger;
218
+ function isLedgerStateV1(value, maxEntries) {
219
+ if (!value || typeof value !== 'object')
220
+ return false;
221
+ const record = value;
222
+ if (record.version !== 1 ||
223
+ !Array.isArray(record.entries) ||
224
+ record.entries.length > maxEntries) {
225
+ return false;
226
+ }
227
+ return record.entries.every((entry) => {
228
+ if (!entry || typeof entry !== 'object')
229
+ return false;
230
+ const item = entry;
231
+ return isKey(item.key) && isTimestamp(item.completedAt);
232
+ });
233
+ }
234
+ function isLedgerStateV2(value, maxEntries) {
235
+ if (!value || typeof value !== 'object')
236
+ return false;
237
+ const record = value;
238
+ if (record.version !== 2 ||
239
+ !Array.isArray(record.entries) ||
240
+ record.entries.length > maxEntries) {
241
+ return false;
242
+ }
243
+ return record.entries.every((entry) => {
244
+ if (!entry || typeof entry !== 'object')
245
+ return false;
246
+ const item = entry;
247
+ return (isKey(item.key) &&
248
+ (item.state === 'processing' || item.state === 'ready' || item.state === 'delivered') &&
249
+ isTimestamp(item.updatedAt) &&
250
+ typeof item.ownerId === 'string' &&
251
+ item.ownerId.length > 0 &&
252
+ item.ownerId.length <= 128 &&
253
+ (item.response === undefined ||
254
+ (typeof item.response === 'string' && item.response.length <= MAX_RESPONSE_CHARS)) &&
255
+ (item.nextChunkIndex === undefined ||
256
+ (Number.isSafeInteger(item.nextChunkIndex) && item.nextChunkIndex >= 0)) &&
257
+ (item.deliveryUncertain === undefined || typeof item.deliveryUncertain === 'boolean'));
258
+ });
259
+ }
260
+ function isKey(value) {
261
+ return typeof value === 'string' && value.length > 0 && value.length <= 256;
262
+ }
263
+ function isTimestamp(value) {
264
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
265
+ }
266
+ //# sourceMappingURL=telegram-message-ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram-message-ledger.js","sourceRoot":"","sources":["../../src/gateways/telegram-message-ledger.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,11 @@ export interface TelegramResponseAdapter {
7
7
  export interface TelegramResponsePresenterOptions {
8
8
  throttleMs?: number;
9
9
  maxLength?: number;
10
+ chunkRetryCount?: number;
11
+ resumeFromChunk?: number;
12
+ onChunkProgress?: (nextIndex: number, uncertain: boolean) => void | Promise<void>;
10
13
  }
14
+ export declare function splitTelegramMessage(text: string, maxLength: number): string[];
11
15
  export declare class TelegramResponsePresenter {
12
16
  private readonly adapter;
13
17
  private readonly throttleMs;
@@ -18,14 +22,20 @@ export declare class TelegramResponsePresenter {
18
22
  private editTimer;
19
23
  private inFlightEdit;
20
24
  private finalized;
25
+ private finalizing;
26
+ private readonly chunkRetryCount;
27
+ private readonly resumeFromChunk;
28
+ private readonly onChunkProgress?;
21
29
  constructor(adapter: TelegramResponseAdapter, options?: TelegramResponsePresenterOptions);
22
30
  start(): Promise<void>;
23
31
  callbacks(): StreamCallbacks;
32
+ markQueued(): void;
24
33
  finalize(rawResponse: string): Promise<void>;
25
34
  fail(message: string): Promise<void>;
26
35
  private scheduleEdit;
27
36
  private flushStreamingEdit;
28
37
  private cancelPendingEdit;
29
38
  private sendChunks;
39
+ private recordChunkProgress;
30
40
  }
31
41
  //# sourceMappingURL=telegram-response-presenter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telegram-response-presenter.d.ts","sourceRoot":"","sources":["../../src/gateways/telegram-response-presenter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMzD,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,gCAAgC;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsCD,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE,uBAAuB,EAAE,OAAO,GAAE,gCAAqC;IAMtF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,SAAS,IAAI,eAAe;IA0BtB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B5C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,OAAO,CAAC,YAAY;YAUN,kBAAkB;IAgBhC,OAAO,CAAC,iBAAiB;YAOX,UAAU;CAKzB"}
1
+ {"version":3,"file":"telegram-response-presenter.d.ts","sourceRoot":"","sources":["../../src/gateways/telegram-response-presenter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMzD,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,gCAAgC;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnF;AA4CD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB9E;AAED,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAsD;gBAE3E,OAAO,EAAE,uBAAuB,EAAE,OAAO,GAAE,gCAAqC;IAStF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,SAAS,IAAI,eAAe;IA0B5B,UAAU,IAAI,IAAI;IAQZ,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyD5C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,OAAO,CAAC,YAAY;YAUN,kBAAkB;IAoBhC,OAAO,CAAC,iBAAiB;YAOX,UAAU;YAqBV,mBAAmB;CAGlC"}
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TelegramResponsePresenter = void 0;
4
+ exports.splitTelegramMessage = splitTelegramMessage;
5
+ const node_os_1 = require("node:os");
6
+ const node_path_1 = require("node:path");
4
7
  const DEFAULT_THROTTLE_MS = 800;
5
8
  const DEFAULT_MAX_LENGTH = 4096;
6
9
  const EMPTY_RESPONSE_MESSAGE = 'No response was generated.';
@@ -15,21 +18,47 @@ function stripLeadingReasoningDecoration(text) {
15
18
  return text.slice(closing + 2).replace(/^\s+/, '');
16
19
  }
17
20
  function redactInboundMediaPaths(text) {
18
- return text.replace(/(?:\/[\w.@+-]+)*\/\.mama\/workspace\/media\/inbound\/[^\s]+/g, '[attachment]');
21
+ let redacted = text.replace(/(?:\/[\w.@+-]+)*\/\.mama\/workspace\/media\/inbound\/[^\s]+/g, '[attachment]');
22
+ const workspaces = new Set([process.env.MAMA_WORKSPACE, (0, node_path_1.join)((0, node_os_1.homedir)(), '.mama', 'workspace')]);
23
+ for (const workspace of workspaces) {
24
+ if (!workspace)
25
+ continue;
26
+ const inboundRoot = (0, node_path_1.join)(workspace, 'media', 'inbound');
27
+ const escapedRoot = inboundRoot.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
28
+ redacted = redacted.replace(new RegExp(`${escapedRoot}(?:/[^\\s]+)+`, 'g'), '[attachment]');
29
+ }
30
+ return redacted;
19
31
  }
20
32
  function sanitizeVisibleText(text) {
21
33
  const withoutDecoration = stripLeadingReasoningDecoration(text);
22
34
  return withoutDecoration === null ? null : redactInboundMediaPaths(withoutDecoration);
23
35
  }
24
- function splitMessage(text, maxLength) {
25
- if (text.length <= maxLength) {
36
+ function telegramErrorMessage(error) {
37
+ return error instanceof Error ? error.message : String(error);
38
+ }
39
+ function isSafeRateLimitRetry(error) {
40
+ if (error && typeof error === 'object' && 'error_code' in error && error.error_code === 429) {
41
+ return true;
42
+ }
43
+ return /(?:^|\b)429\b|too many requests/i.test(telegramErrorMessage(error));
44
+ }
45
+ function splitTelegramMessage(text, maxLength) {
46
+ const codePoints = Array.from(text);
47
+ if (codePoints.length <= maxLength) {
26
48
  return [text];
27
49
  }
28
50
  const chunks = [];
29
- let remaining = text;
51
+ let remaining = codePoints;
30
52
  while (remaining.length > 0) {
31
- chunks.push(remaining.slice(0, maxLength));
32
- remaining = remaining.slice(maxLength);
53
+ if (remaining.length <= maxLength) {
54
+ chunks.push(remaining.join(''));
55
+ break;
56
+ }
57
+ const candidate = remaining.slice(0, maxLength);
58
+ const newline = candidate.lastIndexOf('\n');
59
+ const splitAt = newline > maxLength * 0.3 ? newline + 1 : maxLength;
60
+ chunks.push(remaining.slice(0, splitAt).join(''));
61
+ remaining = remaining.slice(splitAt);
33
62
  }
34
63
  return chunks;
35
64
  }
@@ -43,13 +72,20 @@ class TelegramResponsePresenter {
43
72
  editTimer = null;
44
73
  inFlightEdit = Promise.resolve();
45
74
  finalized = false;
75
+ finalizing = false;
76
+ chunkRetryCount;
77
+ resumeFromChunk;
78
+ onChunkProgress;
46
79
  constructor(adapter, options = {}) {
47
80
  this.adapter = adapter;
48
81
  this.throttleMs = options.throttleMs ?? DEFAULT_THROTTLE_MS;
49
82
  this.maxLength = options.maxLength ?? DEFAULT_MAX_LENGTH;
83
+ this.chunkRetryCount = Math.max(1, options.chunkRetryCount ?? 3);
84
+ this.resumeFromChunk = Math.max(0, options.resumeFromChunk ?? 0);
85
+ this.onChunkProgress = options.onChunkProgress;
50
86
  }
51
87
  async start() {
52
- if (this.handle || this.finalized) {
88
+ if (this.handle || this.finalized || this.finalizing) {
53
89
  return;
54
90
  }
55
91
  try {
@@ -62,21 +98,21 @@ class TelegramResponsePresenter {
62
98
  callbacks() {
63
99
  return {
64
100
  onDelta: (text) => {
65
- if (this.finalized) {
101
+ if (this.finalized || this.finalizing) {
66
102
  return;
67
103
  }
68
104
  this.accumulatedText += text;
69
105
  this.scheduleEdit();
70
106
  },
71
107
  onToolUse: (name) => {
72
- if (this.finalized) {
108
+ if (this.finalized || this.finalizing) {
73
109
  return;
74
110
  }
75
111
  this.toolStatus = `🔧 ${name}...`;
76
112
  this.scheduleEdit();
77
113
  },
78
114
  onToolComplete: (name, _toolUseId, isError) => {
79
- if (this.finalized || this.accumulatedText) {
115
+ if (this.finalized || this.finalizing || this.accumulatedText) {
80
116
  return;
81
117
  }
82
118
  this.toolStatus = `${isError ? '❌' : '✅'} ${name}`;
@@ -84,31 +120,68 @@ class TelegramResponsePresenter {
84
120
  },
85
121
  };
86
122
  }
87
- async finalize(rawResponse) {
88
- if (this.finalized) {
123
+ markQueued() {
124
+ if (this.finalized || this.finalizing) {
89
125
  return;
90
126
  }
91
- this.finalized = true;
92
- this.cancelPendingEdit();
93
- await this.inFlightEdit;
94
- const sanitized = sanitizeVisibleText(rawResponse);
95
- const visible = (sanitized ?? '').trim() || EMPTY_RESPONSE_MESSAGE;
96
- const chunks = splitMessage(visible, this.maxLength);
97
- if (!this.handle) {
98
- await this.sendChunks(chunks);
127
+ this.toolStatus = '⏳ Waiting for the earlier task to finish.';
128
+ this.scheduleEdit();
129
+ }
130
+ async finalize(rawResponse) {
131
+ if (this.finalized || this.finalizing) {
99
132
  return;
100
133
  }
101
- const handle = this.handle;
102
- this.handle = null;
134
+ this.finalizing = true;
135
+ this.cancelPendingEdit();
103
136
  try {
104
- await this.adapter.edit(handle, chunks[0]);
137
+ await this.inFlightEdit;
138
+ const sanitized = sanitizeVisibleText(rawResponse);
139
+ const visible = (sanitized ?? '').trim() || EMPTY_RESPONSE_MESSAGE;
140
+ const chunks = splitTelegramMessage(visible, this.maxLength);
141
+ if (this.resumeFromChunk >= chunks.length) {
142
+ this.finalized = true;
143
+ return;
144
+ }
145
+ if (!this.handle || this.resumeFromChunk > 0) {
146
+ if (this.handle) {
147
+ const staleHandle = this.handle;
148
+ this.handle = null;
149
+ await this.adapter.delete(staleHandle).catch(() => { });
150
+ }
151
+ await this.sendChunks(chunks.slice(this.resumeFromChunk), this.resumeFromChunk);
152
+ this.finalized = true;
153
+ return;
154
+ }
155
+ const handle = this.handle;
156
+ this.handle = null;
157
+ try {
158
+ await this.recordChunkProgress(0, true);
159
+ await this.adapter.edit(handle, chunks[0]);
160
+ }
161
+ catch (error) {
162
+ const message = telegramErrorMessage(error);
163
+ if (/message is not modified/i.test(message)) {
164
+ // Telegram already has the desired text. Treat this as committed.
165
+ }
166
+ else if (/message to edit not found/i.test(message)) {
167
+ await this.adapter.delete(handle).catch(() => { });
168
+ await this.sendChunks(chunks);
169
+ this.finalized = true;
170
+ return;
171
+ }
172
+ else {
173
+ // A timeout/network error may mean the edit was applied remotely.
174
+ // Do not delete and resend an answer that could already be visible.
175
+ throw error;
176
+ }
177
+ }
178
+ await this.recordChunkProgress(1, false);
179
+ await this.sendChunks(chunks.slice(1), 1);
180
+ this.finalized = true;
105
181
  }
106
- catch {
107
- await this.adapter.delete(handle).catch(() => { });
108
- await this.sendChunks(chunks);
109
- return;
182
+ finally {
183
+ this.finalizing = false;
110
184
  }
111
- await this.sendChunks(chunks.slice(1));
112
185
  }
113
186
  async fail(message) {
114
187
  await this.finalize(message);
@@ -134,7 +207,10 @@ class TelegramResponsePresenter {
134
207
  if (!visible) {
135
208
  return;
136
209
  }
137
- const bounded = visible.length > this.maxLength ? visible.slice(-this.maxLength) : visible;
210
+ const visibleCodePoints = Array.from(visible);
211
+ const bounded = visibleCodePoints.length > this.maxLength
212
+ ? visibleCodePoints.slice(-this.maxLength).join('')
213
+ : visible;
138
214
  await this.adapter.edit(this.handle, bounded).catch(() => { });
139
215
  }
140
216
  cancelPendingEdit() {
@@ -143,11 +219,32 @@ class TelegramResponsePresenter {
143
219
  this.editTimer = null;
144
220
  }
145
221
  }
146
- async sendChunks(chunks) {
147
- for (const chunk of chunks) {
148
- await this.adapter.send(chunk);
222
+ async sendChunks(chunks, startIndex = 0) {
223
+ for (let offset = 0; offset < chunks.length; offset += 1) {
224
+ const chunk = chunks[offset];
225
+ const chunkIndex = startIndex + offset;
226
+ let lastError;
227
+ for (let attempt = 1; attempt <= this.chunkRetryCount; attempt += 1) {
228
+ try {
229
+ await this.recordChunkProgress(chunkIndex, true);
230
+ await this.adapter.send(chunk);
231
+ await this.recordChunkProgress(chunkIndex + 1, false);
232
+ lastError = undefined;
233
+ break;
234
+ }
235
+ catch (error) {
236
+ if (!isSafeRateLimitRetry(error))
237
+ throw error;
238
+ lastError = error;
239
+ }
240
+ }
241
+ if (lastError)
242
+ throw lastError;
149
243
  }
150
244
  }
245
+ async recordChunkProgress(nextIndex, uncertain) {
246
+ await this.onChunkProgress?.(nextIndex, uncertain);
247
+ }
151
248
  }
152
249
  exports.TelegramResponsePresenter = TelegramResponsePresenter;
153
250
  //# sourceMappingURL=telegram-response-presenter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"telegram-response-presenter.js","sourceRoot":"","sources":["../../src/gateways/telegram-response-presenter.ts"],"names":[],"mappings":";;;AAEA,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AAa5D,SAAS,+BAA+B,CAAC,IAAY;IACnD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,OAAO,CACjB,8DAA8D,EAC9D,cAAc,CACf,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,iBAAiB,GAAG,+BAA+B,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,iBAAiB,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB;IACnD,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;QAC3C,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAa,yBAAyB;IACnB,OAAO,CAA0B;IACjC,UAAU,CAAS;IACnB,SAAS,CAAS;IAC3B,MAAM,GAAkB,IAAI,CAAC;IAC7B,eAAe,GAAG,EAAE,CAAC;IACrB,UAAU,GAAG,EAAE,CAAC;IAChB,SAAS,GAAyC,IAAI,CAAC;IACvD,YAAY,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAChD,SAAS,GAAG,KAAK,CAAC;IAE1B,YAAY,OAAgC,EAAE,UAA4C,EAAE;QAC1F,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC5D,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO;YACL,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBAChB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACnB,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;gBAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;YACD,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;gBAClB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACnB,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,KAAK,CAAC;gBAClC,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;YACD,cAAc,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;gBAC5C,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC3C,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,UAAU,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;gBACnD,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,WAAmB;QAChC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,MAAM,IAAI,CAAC,YAAY,CAAC;QAExB,MAAM,SAAS,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,sBAAsB,CAAC;QACnE,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAErD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAClD,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QACD,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAe;QACxB,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAEO,YAAY;QAClB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;QAC9E,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC9B,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACnC,OAAO;QACT,CAAC;QACD,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5D,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC;QACpD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3F,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAChE,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,MAAgB;QACvC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;CACF;AA7HD,8DA6HC"}
1
+ {"version":3,"file":"telegram-response-presenter.js","sourceRoot":"","sources":["../../src/gateways/telegram-response-presenter.ts"],"names":[],"mappings":";;;AAiEA,oDAmBC;AApFD,qCAAkC;AAClC,yCAAiC;AAIjC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AAgB5D,SAAS,+BAA+B,CAAC,IAAY;IACnD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAY;IAC3C,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CACzB,8DAA8D,EAC9D,cAAc,CACf,CAAC;IACF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,IAAA,gBAAI,EAAC,IAAA,iBAAO,GAAE,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAChG,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,MAAM,WAAW,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QACvE,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,eAAe,EAAE,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,iBAAiB,GAAG,+BAA+B,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,iBAAiB,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,YAAY,IAAI,KAAK,IAAI,KAAK,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;QAC5F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,kCAAkC,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,SAAgB,oBAAoB,CAAC,IAAY,EAAE,SAAiB;IAClE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,UAAU,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,SAAS,GAAG,UAAU,CAAC;IAC3B,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,SAAS,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM;QACR,CAAC;QACD,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAClD,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAa,yBAAyB;IACnB,OAAO,CAA0B;IACjC,UAAU,CAAS;IACnB,SAAS,CAAS;IAC3B,MAAM,GAAkB,IAAI,CAAC;IAC7B,eAAe,GAAG,EAAE,CAAC;IACrB,UAAU,GAAG,EAAE,CAAC;IAChB,SAAS,GAAyC,IAAI,CAAC;IACvD,YAAY,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAChD,SAAS,GAAG,KAAK,CAAC;IAClB,UAAU,GAAG,KAAK,CAAC;IACV,eAAe,CAAS;IACxB,eAAe,CAAS;IACxB,eAAe,CAAuD;IAEvF,YAAY,OAAgC,EAAE,UAA4C,EAAE;QAC1F,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC5D,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;QACzD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrD,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO;YACL,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBAChB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACtC,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;gBAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;YACD,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;gBAClB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACtC,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,KAAK,CAAC;gBAClC,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;YACD,cAAc,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;gBAC5C,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC9D,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,UAAU,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;gBACnD,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;SACF,CAAC;IACJ,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,2CAA2C,CAAC;QAC9D,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,WAAmB;QAChC,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC;YAExB,MAAM,SAAS,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;YACnD,MAAM,OAAO,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,sBAAsB,CAAC;YACnE,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAE7D,IAAI,IAAI,CAAC,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC1C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACtB,OAAO;YACT,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;gBAC7C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;oBAChC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;oBACnB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBACzD,CAAC;gBACD,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;gBAChF,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACtB,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBACxC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;gBAC5C,IAAI,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC7C,kEAAkE;gBACpE,CAAC;qBAAM,IAAI,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBACtD,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;oBAClD,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;oBAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;oBACtB,OAAO;gBACT,CAAC;qBAAM,CAAC;oBACN,kEAAkE;oBAClE,oEAAoE;oBACpE,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YACD,MAAM,IAAI,CAAC,mBAAmB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YACzC,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAe;QACxB,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAEO,YAAY;QAClB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;QAC9E,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC9B,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACnC,OAAO;QACT,CAAC;QACD,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5D,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC;QACpD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,OAAO,GACX,iBAAiB,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS;YACvC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,CAAC,CAAC,OAAO,CAAC;QACd,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAChE,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,MAAgB,EAAE,UAAU,GAAG,CAAC;QACvD,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC;YACzD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC7B,MAAM,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;YACvC,IAAI,SAAkB,CAAC;YACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,eAAe,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;gBACpE,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;oBACjD,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC/B,MAAM,IAAI,CAAC,mBAAmB,CAAC,UAAU,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;oBACtD,SAAS,GAAG,SAAS,CAAC;oBACtB,MAAM;gBACR,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC;wBAAE,MAAM,KAAK,CAAC;oBAC9C,SAAS,GAAG,KAAK,CAAC;gBACpB,CAAC;YACH,CAAC;YACD,IAAI,SAAS;gBAAE,MAAM,SAAS,CAAC;QACjC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,SAAiB,EAAE,SAAkB;QACrE,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACrD,CAAC;CACF;AA/LD,8DA+LC"}
@@ -39,6 +39,8 @@ export interface TelegramGatewayOptions {
39
39
  mediaRoot?: string;
40
40
  /** Internal test seam for the external Telegram file request. */
41
41
  fetchImpl?: TelegramMediaDownloadRequest['fetchImpl'];
42
+ /** Internal test/operations seam for restart-safe completed-message deduplication. */
43
+ messageLedgerPath?: string;
42
44
  }
43
45
  /**
44
46
  * Telegram Gateway class
@@ -54,6 +56,9 @@ export declare class TelegramGateway extends BaseGateway {
54
56
  private lastMessageAt;
55
57
  private readonly mediaRoot;
56
58
  private readonly fetchImpl?;
59
+ private readonly messageLedger;
60
+ private readonly chatTails;
61
+ private readonly activeChat;
57
62
  private recentMessageIds;
58
63
  private rejectedChatWarnAt;
59
64
  private dedupCleanupTimer;
@@ -64,13 +69,24 @@ export declare class TelegramGateway extends BaseGateway {
64
69
  start(): Promise<void>;
65
70
  stop(): Promise<void>;
66
71
  private handleMessage;
67
- sendMessage(chatId: string, text: string): Promise<void>;
68
- sendFile(chatId: string, filePath: string, caption?: string): Promise<void>;
69
- sendImage(chatId: string, imagePath: string, caption?: string): Promise<void>;
72
+ private runInChatQueue;
73
+ private processMessage;
74
+ sendMessage(chatId: string, text: string, idempotencyKey?: string): Promise<void>;
75
+ sendMessageFromActiveTurn(chatId: string, text: string, idempotencyKey?: string): Promise<void>;
76
+ private sendMessageNow;
77
+ sendFile(chatId: string, filePath: string, caption?: string, idempotencyKey?: string): Promise<void>;
78
+ sendFileFromActiveTurn(chatId: string, filePath: string, caption?: string, idempotencyKey?: string): Promise<void>;
79
+ sendImage(chatId: string, imagePath: string, caption?: string, idempotencyKey?: string): Promise<void>;
80
+ sendImageFromActiveTurn(chatId: string, imagePath: string, caption?: string, idempotencyKey?: string): Promise<void>;
81
+ private sendOutboundOnce;
82
+ private recoverPendingInboundDeliveries;
83
+ private createResponsePresenter;
84
+ private outboundLedgerKey;
70
85
  sendSticker(chatId: string | number, emotion: string): Promise<boolean>;
86
+ sendStickerFromActiveTurn(chatId: string | number, emotion: string): Promise<boolean>;
87
+ private sendStickerNow;
71
88
  getLastError(): string | null;
72
89
  getLastMessageAt(): number | undefined;
73
- private splitMessage;
74
90
  private loadStickerSet;
75
91
  }
76
92
  //# sourceMappingURL=telegram.d.ts.map