blun-king-cli 9.1.416 → 9.1.418
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/LIESMICH.txt +16 -0
- package/README.md +16 -0
- package/bin/identity-context-policy.cjs +61 -3
- package/bin/telegram-text-chunk-policy.cjs +63 -0
- package/blun.mjs +17 -12
- package/package.json +1 -1
- package/telegram-plugin/bin/telegram-text-chunk-policy.cjs +63 -0
- package/telegram-plugin/dist/bridge.mjs +19 -12
package/LIESMICH.txt
CHANGED
|
@@ -67,6 +67,22 @@ Bereinigung und Mikrokompaktierung verwenden dafür dieselbe semantische Grenze.
|
|
|
67
67
|
Erst nach der nachweislichen Auswertung darf ein Ergebnis archiviert oder
|
|
68
68
|
gekürzt werden.
|
|
69
69
|
|
|
70
|
+
Ab BLUN King 9.1.417 schneiden automatische Telegram-Rückfallantworten Texte
|
|
71
|
+
nicht mehr bei 4.096 Zeichen ab. Längere Antworten werden in
|
|
72
|
+
aufeinanderfolgenden Nachrichten vollständig zugestellt; dabei bleiben jedes
|
|
73
|
+
Zeichen und jedes Unicode-Surrogatpaar erhalten. Im Ausgangsprotokoll stehen
|
|
74
|
+
sämtliche zurückgegebenen Nachrichten-IDs zusammen mit dem vollständigen Text.
|
|
75
|
+
Schlägt ein Teil fehl, endet die Zustellung an dieser Stelle, statt die Antwort
|
|
76
|
+
fälschlich als vollständig zu melden.
|
|
77
|
+
|
|
78
|
+
Ab BLUN King 9.1.418 übernimmt der Identitätsgraph die von Telegram bestätigte
|
|
79
|
+
Unterscheidung zwischen Menschen und Bots. Bereits vorhandene
|
|
80
|
+
Telegram-Kontakte, die mangels dieses Merkmals als Menschen angelegt wurden,
|
|
81
|
+
werden bei der nächsten eindeutig als Bot bestätigten Nachricht einmalig als
|
|
82
|
+
Agent korrigiert. Alle Rollen, Zuständigkeiten, Beziehungsnotizen und sonstigen
|
|
83
|
+
Felder bleiben unverändert. Ein Agent wird niemals zu einer Person
|
|
84
|
+
zurückgestuft; Namen oder Benutzernamen dienen nicht als Beweis.
|
|
85
|
+
|
|
70
86
|
Zuverlässiger King-Start
|
|
71
87
|
-----------------------
|
|
72
88
|
Bei einer ausdrücklich als wiederholbar gekennzeichneten Serverüberlastung
|
package/README.md
CHANGED
|
@@ -82,6 +82,22 @@ Bereinigung und Mikrokompaktierung verwenden dafür dieselbe semantische Grenze.
|
|
|
82
82
|
Erst nach der nachweislichen Auswertung darf ein Ergebnis archiviert oder
|
|
83
83
|
gekürzt werden.
|
|
84
84
|
|
|
85
|
+
Ab BLUN King 9.1.417 schneiden automatische Telegram-Rückfallantworten Texte
|
|
86
|
+
nicht mehr bei 4.096 Zeichen ab. Längere Antworten werden in
|
|
87
|
+
aufeinanderfolgenden Nachrichten vollständig zugestellt; dabei bleiben jedes
|
|
88
|
+
Zeichen und jedes Unicode-Surrogatpaar erhalten. Im Ausgangsprotokoll stehen
|
|
89
|
+
sämtliche zurückgegebenen Nachrichten-IDs zusammen mit dem vollständigen Text.
|
|
90
|
+
Schlägt ein Teil fehl, endet die Zustellung an dieser Stelle, statt die Antwort
|
|
91
|
+
fälschlich als vollständig zu melden.
|
|
92
|
+
|
|
93
|
+
Ab BLUN King 9.1.418 übernimmt der Identitätsgraph die von Telegram bestätigte
|
|
94
|
+
Unterscheidung zwischen Menschen und Bots. Bereits vorhandene
|
|
95
|
+
Telegram-Kontakte, die mangels dieses Merkmals als Menschen angelegt wurden,
|
|
96
|
+
werden bei der nächsten eindeutig als Bot bestätigten Nachricht einmalig als
|
|
97
|
+
Agent korrigiert. Alle Rollen, Zuständigkeiten, Beziehungsnotizen und sonstigen
|
|
98
|
+
Felder bleiben unverändert. Ein Agent wird niemals zu einer Person
|
|
99
|
+
zurückgestuft; Namen oder Benutzernamen dienen nicht als Beweis.
|
|
100
|
+
|
|
85
101
|
`Strg+C` und `Esc` brechen einen aktiven Zug zuverlässig ab, ohne den bereits
|
|
86
102
|
geschriebenen Entwurf zu löschen. Das gilt auch bei Autovervollständigung,
|
|
87
103
|
Geistervorschlägen, Bash-Eingabe und einer noch offenen Mehrzeileneingabe.
|
|
@@ -93,6 +93,51 @@ function createJsonOnce(root, segments, value) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
function updateJsonAtomically(root, segments, update) {
|
|
97
|
+
const target = path.resolve(root, ...segments);
|
|
98
|
+
if (!isInside(root, target)) return false;
|
|
99
|
+
let handle;
|
|
100
|
+
let temp = '';
|
|
101
|
+
try {
|
|
102
|
+
const stat = fs.lstatSync(target);
|
|
103
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_FILE_BYTES) return false;
|
|
104
|
+
const original = fs.readFileSync(target, 'utf8');
|
|
105
|
+
const current = JSON.parse(original);
|
|
106
|
+
if (!current || typeof current !== 'object' || Array.isArray(current)) return false;
|
|
107
|
+
const next = update(current);
|
|
108
|
+
if (!next || typeof next !== 'object' || Array.isArray(next)) return false;
|
|
109
|
+
const serialized = `${JSON.stringify(next, null, 2)}\n`;
|
|
110
|
+
if (Buffer.byteLength(serialized, 'utf8') > MAX_FILE_BYTES) return false;
|
|
111
|
+
|
|
112
|
+
const parent = path.dirname(target);
|
|
113
|
+
const realParent = fs.realpathSync(parent);
|
|
114
|
+
if (!isInside(root, realParent)) return false;
|
|
115
|
+
temp = path.join(parent, `.${path.basename(target)}.${process.pid}.${Date.now()}.tmp`);
|
|
116
|
+
handle = fs.openSync(temp, 'wx', 0o600);
|
|
117
|
+
fs.writeFileSync(handle, serialized, 'utf8');
|
|
118
|
+
fs.fsyncSync(handle);
|
|
119
|
+
fs.closeSync(handle);
|
|
120
|
+
handle = undefined;
|
|
121
|
+
|
|
122
|
+
const currentStat = fs.lstatSync(target);
|
|
123
|
+
if (!currentStat.isFile() || currentStat.isSymbolicLink() || fs.readFileSync(target, 'utf8') !== original) return false;
|
|
124
|
+
fs.renameSync(temp, target);
|
|
125
|
+
temp = '';
|
|
126
|
+
return true;
|
|
127
|
+
} catch {
|
|
128
|
+
return false;
|
|
129
|
+
} finally {
|
|
130
|
+
if (handle !== undefined) fs.closeSync(handle);
|
|
131
|
+
if (temp) {
|
|
132
|
+
try { fs.rmSync(temp, { force: true }); } catch {}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function isExplicitTelegramBot(meta) {
|
|
138
|
+
return meta?.is_bot === true || String(meta?.is_bot ?? '').toLowerCase() === 'true';
|
|
139
|
+
}
|
|
140
|
+
|
|
96
141
|
function cleanText(value, maxChars = 240) {
|
|
97
142
|
if (typeof value !== 'string') return '';
|
|
98
143
|
return value.replace(/[\u0000-\u001f\u007f]+/gu, ' ').replace(/\s+/gu, ' ').trim().slice(0, maxChars);
|
|
@@ -485,19 +530,31 @@ function recordChannelIdentity(envelope, env = process.env) {
|
|
|
485
530
|
const firstSeenAt = trustedTimestamp(meta.ts);
|
|
486
531
|
const receivedAt = trustedTimestamp(meta.received_at) || firstSeenAt;
|
|
487
532
|
const created = [];
|
|
488
|
-
|
|
533
|
+
const updated = [];
|
|
534
|
+
const actorSegments = ['actors', `${actorId}.json`];
|
|
535
|
+
const actorCreated = createJsonOnce(root, actorSegments, {
|
|
489
536
|
version: 1,
|
|
490
537
|
actor_id: actorId,
|
|
491
538
|
provider: 'telegram',
|
|
492
539
|
provider_subject_id: subjectId,
|
|
493
540
|
display_name: displayName,
|
|
494
|
-
kind:
|
|
541
|
+
kind: isExplicitTelegramBot(meta) ? 'agent' : 'person',
|
|
495
542
|
role: '',
|
|
496
543
|
responsibilities: [],
|
|
497
544
|
traits: [],
|
|
498
545
|
aliases: [],
|
|
499
546
|
...(firstSeenAt ? { first_seen_at: firstSeenAt } : {}),
|
|
500
|
-
})
|
|
547
|
+
});
|
|
548
|
+
if (actorCreated) created.push('actor');
|
|
549
|
+
else if (isExplicitTelegramBot(meta) && updateJsonAtomically(root, actorSegments, (actor) => (
|
|
550
|
+
actor.version === 1
|
|
551
|
+
&& actor.actor_id === actorId
|
|
552
|
+
&& actor.provider === 'telegram'
|
|
553
|
+
&& actor.provider_subject_id === subjectId
|
|
554
|
+
&& actor.kind === 'person'
|
|
555
|
+
? { ...actor, kind: 'agent' }
|
|
556
|
+
: undefined
|
|
557
|
+
))) updated.push('actor_kind');
|
|
501
558
|
if (createJsonOnce(root, ['agents', agentId, 'relationships', `${actorId}.json`], {
|
|
502
559
|
version: 1,
|
|
503
560
|
actor_id: actorId,
|
|
@@ -621,6 +678,7 @@ function recordChannelIdentity(envelope, env = process.env) {
|
|
|
621
678
|
actor_id: actorId,
|
|
622
679
|
...(groupId ? { group_id: groupId } : {}),
|
|
623
680
|
created,
|
|
681
|
+
updated,
|
|
624
682
|
...(learning ? { learning } : {}),
|
|
625
683
|
...(journal ? { journal } : {}),
|
|
626
684
|
model_context: modelContext,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const TELEGRAM_TEXT_LIMIT = 4096;
|
|
4
|
+
|
|
5
|
+
function preferredCut(text, start, hardEnd) {
|
|
6
|
+
const minimum = start + Math.floor((hardEnd - start) / 2);
|
|
7
|
+
const boundaries = [
|
|
8
|
+
['\n\n', 2],
|
|
9
|
+
['\n', 1],
|
|
10
|
+
[' ', 1],
|
|
11
|
+
];
|
|
12
|
+
for (const [boundary, width] of boundaries) {
|
|
13
|
+
const index = text.lastIndexOf(boundary, hardEnd - 1);
|
|
14
|
+
if (index >= minimum) return index + width;
|
|
15
|
+
}
|
|
16
|
+
return hardEnd;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function preserveSurrogatePair(text, start, end) {
|
|
20
|
+
if (end <= start || end >= text.length) return end;
|
|
21
|
+
const before = text.charCodeAt(end - 1);
|
|
22
|
+
const after = text.charCodeAt(end);
|
|
23
|
+
const splitsPair = before >= 0xD800 && before <= 0xDBFF && after >= 0xDC00 && after <= 0xDFFF;
|
|
24
|
+
return splitsPair && end - 1 > start ? end - 1 : end;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function splitTelegramText(value, limit = TELEGRAM_TEXT_LIMIT) {
|
|
28
|
+
const text = typeof value === 'string' ? value : String(value ?? '');
|
|
29
|
+
if (text.length === 0) return [];
|
|
30
|
+
if (!Number.isSafeInteger(limit) || limit <= 0) {
|
|
31
|
+
throw new TypeError('Telegram text chunk limit must be a positive safe integer');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const chunks = [];
|
|
35
|
+
let start = 0;
|
|
36
|
+
while (start < text.length) {
|
|
37
|
+
const hardEnd = Math.min(text.length, start + limit);
|
|
38
|
+
let end = hardEnd < text.length ? preferredCut(text, start, hardEnd) : hardEnd;
|
|
39
|
+
end = preserveSurrogatePair(text, start, end);
|
|
40
|
+
if (end <= start) end = hardEnd;
|
|
41
|
+
chunks.push(text.slice(start, end));
|
|
42
|
+
start = end;
|
|
43
|
+
}
|
|
44
|
+
return chunks;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function sendTelegramTextChunks(value, sendChunk, limit = TELEGRAM_TEXT_LIMIT) {
|
|
48
|
+
if (typeof sendChunk !== 'function') {
|
|
49
|
+
throw new TypeError('Telegram chunk sender must be a function');
|
|
50
|
+
}
|
|
51
|
+
const chunks = splitTelegramText(value, limit);
|
|
52
|
+
const results = [];
|
|
53
|
+
for (let index = 0; index < chunks.length; index += 1) {
|
|
54
|
+
results.push(await sendChunk(chunks[index], index, chunks.length));
|
|
55
|
+
}
|
|
56
|
+
return { chunks, results };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
TELEGRAM_TEXT_LIMIT,
|
|
61
|
+
sendTelegramTextChunks,
|
|
62
|
+
splitTelegramText,
|
|
63
|
+
};
|
package/blun.mjs
CHANGED
|
@@ -514830,6 +514830,7 @@ var createMediaAutoRetrievalController, parseAcceptedMediaJob, validateCompleted
|
|
|
514830
514830
|
({ createMediaAutoRetrievalController, parseAcceptedMediaJob } = createRequire(import.meta.url)("./bin/media-auto-retrieval-policy.cjs"));
|
|
514831
514831
|
({ validateCompletedMedia } = createRequire(import.meta.url)("./bin/media-result-policy.cjs"));
|
|
514832
514832
|
var { findDuplicateReplyWithoutNewInbound, isPrivateInternalStatusReply, sanitizePrivateConversationReply } = createRequire(import.meta.url)("./bin/telegram-private-conversation-policy.cjs");
|
|
514833
|
+
var { sendTelegramTextChunks } = createRequire(import.meta.url)("./bin/telegram-text-chunk-policy.cjs");
|
|
514833
514834
|
const TELEGRAM_TEXT_LIMIT = 4096;
|
|
514834
514835
|
const TELEGRAM_ATTACHMENT_LIMIT = 50 * 1024 * 1024;
|
|
514835
514836
|
function mediaTelegramTarget(filePath) {
|
|
@@ -514970,25 +514971,29 @@ async function sendReplyFallback(chatId, text, contextOnly = false) {
|
|
|
514970
514971
|
}
|
|
514971
514972
|
const token = botToken();
|
|
514972
514973
|
if (token === void 0) return false;
|
|
514973
|
-
const
|
|
514974
|
+
const messageIds = [];
|
|
514974
514975
|
try {
|
|
514975
|
-
|
|
514976
|
-
|
|
514977
|
-
|
|
514978
|
-
|
|
514979
|
-
|
|
514980
|
-
|
|
514981
|
-
|
|
514982
|
-
|
|
514983
|
-
|
|
514976
|
+
await sendTelegramTextChunks(privateSafeText, async (body) => {
|
|
514977
|
+
const payload = await (await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
|
|
514978
|
+
method: "POST",
|
|
514979
|
+
headers: { "Content-Type": "application/json" },
|
|
514980
|
+
body: JSON.stringify({
|
|
514981
|
+
chat_id: chatId,
|
|
514982
|
+
text: body
|
|
514983
|
+
})
|
|
514984
|
+
})).json();
|
|
514985
|
+
if (payload.ok !== true) throw new Error("Telegram fallback chunk delivery failed");
|
|
514986
|
+
if (payload.result?.message_id !== void 0) messageIds.push(payload.result.message_id);
|
|
514987
|
+
return payload;
|
|
514988
|
+
}, TELEGRAM_TEXT_LIMIT);
|
|
514984
514989
|
try {
|
|
514985
514990
|
appendFileSync(outboxPath(), `${JSON.stringify({
|
|
514986
514991
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
514987
514992
|
direction: "out",
|
|
514988
514993
|
kind: "reply-fallback",
|
|
514989
514994
|
chat_id: String(chatId),
|
|
514990
|
-
message_ids:
|
|
514991
|
-
text:
|
|
514995
|
+
message_ids: messageIds,
|
|
514996
|
+
text: privateSafeText
|
|
514992
514997
|
})}\n`);
|
|
514993
514998
|
} catch {}
|
|
514994
514999
|
return true;
|
package/package.json
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const TELEGRAM_TEXT_LIMIT = 4096;
|
|
4
|
+
|
|
5
|
+
function preferredCut(text, start, hardEnd) {
|
|
6
|
+
const minimum = start + Math.floor((hardEnd - start) / 2);
|
|
7
|
+
const boundaries = [
|
|
8
|
+
['\n\n', 2],
|
|
9
|
+
['\n', 1],
|
|
10
|
+
[' ', 1],
|
|
11
|
+
];
|
|
12
|
+
for (const [boundary, width] of boundaries) {
|
|
13
|
+
const index = text.lastIndexOf(boundary, hardEnd - 1);
|
|
14
|
+
if (index >= minimum) return index + width;
|
|
15
|
+
}
|
|
16
|
+
return hardEnd;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function preserveSurrogatePair(text, start, end) {
|
|
20
|
+
if (end <= start || end >= text.length) return end;
|
|
21
|
+
const before = text.charCodeAt(end - 1);
|
|
22
|
+
const after = text.charCodeAt(end);
|
|
23
|
+
const splitsPair = before >= 0xD800 && before <= 0xDBFF && after >= 0xDC00 && after <= 0xDFFF;
|
|
24
|
+
return splitsPair && end - 1 > start ? end - 1 : end;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function splitTelegramText(value, limit = TELEGRAM_TEXT_LIMIT) {
|
|
28
|
+
const text = typeof value === 'string' ? value : String(value ?? '');
|
|
29
|
+
if (text.length === 0) return [];
|
|
30
|
+
if (!Number.isSafeInteger(limit) || limit <= 0) {
|
|
31
|
+
throw new TypeError('Telegram text chunk limit must be a positive safe integer');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const chunks = [];
|
|
35
|
+
let start = 0;
|
|
36
|
+
while (start < text.length) {
|
|
37
|
+
const hardEnd = Math.min(text.length, start + limit);
|
|
38
|
+
let end = hardEnd < text.length ? preferredCut(text, start, hardEnd) : hardEnd;
|
|
39
|
+
end = preserveSurrogatePair(text, start, end);
|
|
40
|
+
if (end <= start) end = hardEnd;
|
|
41
|
+
chunks.push(text.slice(start, end));
|
|
42
|
+
start = end;
|
|
43
|
+
}
|
|
44
|
+
return chunks;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function sendTelegramTextChunks(value, sendChunk, limit = TELEGRAM_TEXT_LIMIT) {
|
|
48
|
+
if (typeof sendChunk !== 'function') {
|
|
49
|
+
throw new TypeError('Telegram chunk sender must be a function');
|
|
50
|
+
}
|
|
51
|
+
const chunks = splitTelegramText(value, limit);
|
|
52
|
+
const results = [];
|
|
53
|
+
for (let index = 0; index < chunks.length; index += 1) {
|
|
54
|
+
results.push(await sendChunk(chunks[index], index, chunks.length));
|
|
55
|
+
}
|
|
56
|
+
return { chunks, results };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
TELEGRAM_TEXT_LIMIT,
|
|
61
|
+
sendTelegramTextChunks,
|
|
62
|
+
splitTelegramText,
|
|
63
|
+
};
|
|
@@ -10,10 +10,12 @@ import remoteStatusPolicy from "../../bin/telegram-remote-status-policy.cjs";
|
|
|
10
10
|
import consoleStatusPolicy from "../../bin/telegram-console-status-policy.cjs";
|
|
11
11
|
import telegramApprovalRelay from "../../bin/telegram-approval-relay.cjs";
|
|
12
12
|
import privateConversationPolicy from "../bin/telegram-private-conversation-policy.cjs";
|
|
13
|
+
import telegramTextChunkPolicy from "../bin/telegram-text-chunk-policy.cjs";
|
|
13
14
|
const { buildTelegramRemoteStatus, resolveTelegramQueueSnapshot, resolveTelegramRemoteVersion } = remoteStatusPolicy;
|
|
14
15
|
const { parseTelegramConsoleStatus } = consoleStatusPolicy;
|
|
15
16
|
const { buildTelegramApprovalCard, isAuthorizedTelegramApprovalCallback, listPendingTelegramApprovals, markTelegramApprovalSent, parseTelegramApprovalCallback, resolveTelegramApprovalTarget, wasTelegramApprovalSent, writeTelegramApprovalResponse } = telegramApprovalRelay;
|
|
16
17
|
const { findDuplicateReplyWithoutNewInbound, isPrivateInternalStatusReply, sanitizePrivateConversationReply } = privateConversationPolicy;
|
|
18
|
+
const { sendTelegramTextChunks } = telegramTextChunkPolicy;
|
|
17
19
|
//#region ../../node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
|
|
18
20
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
19
21
|
function normalizeWindowsPath(input = "") {
|
|
@@ -4223,25 +4225,29 @@ async function sendReplyFallback(chatId, rawText) {
|
|
|
4223
4225
|
return true;
|
|
4224
4226
|
}
|
|
4225
4227
|
const text = scrubSecrets(privateSafeText);
|
|
4226
|
-
const
|
|
4228
|
+
const messageIds = [];
|
|
4227
4229
|
try {
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4230
|
+
await sendTelegramTextChunks(text, async (body) => {
|
|
4231
|
+
const payload = await (await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
|
|
4232
|
+
method: "POST",
|
|
4233
|
+
headers: { "Content-Type": "application/json" },
|
|
4234
|
+
body: JSON.stringify({
|
|
4235
|
+
chat_id: chatId,
|
|
4236
|
+
text: body
|
|
4237
|
+
})
|
|
4238
|
+
})).json();
|
|
4239
|
+
if (payload.ok !== true) throw new Error("Telegram fallback chunk delivery failed");
|
|
4240
|
+
if (payload.result?.message_id !== void 0) messageIds.push(payload.result.message_id);
|
|
4241
|
+
return payload;
|
|
4242
|
+
}, TELEGRAM_TEXT_LIMIT);
|
|
4237
4243
|
try {
|
|
4238
4244
|
appendFileSync(outboxLog(), `${JSON.stringify({
|
|
4239
4245
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4240
4246
|
direction: "out",
|
|
4241
4247
|
kind: "reply-fallback",
|
|
4242
4248
|
chat_id: String(chatId),
|
|
4243
|
-
message_ids:
|
|
4244
|
-
text
|
|
4249
|
+
message_ids: messageIds,
|
|
4250
|
+
text
|
|
4245
4251
|
})}\n`);
|
|
4246
4252
|
} catch {}
|
|
4247
4253
|
return true;
|
|
@@ -4696,6 +4702,7 @@ async function handleInbound(event) {
|
|
|
4696
4702
|
...msgId !== void 0 ? { message_id: String(msgId) } : {},
|
|
4697
4703
|
addressed: String(addressed),
|
|
4698
4704
|
user: ctx.from?.username ?? String(ctx.from?.id),
|
|
4705
|
+
is_bot: String(ctx.from?.is_bot === true),
|
|
4699
4706
|
user_id: String(ctx.from?.id),
|
|
4700
4707
|
ts: (/* @__PURE__ */ new Date((ctx.date ?? 0) * 1e3)).toISOString(),
|
|
4701
4708
|
...imagePath !== void 0 ? { image_path: imagePath } : {},
|