@llblab/pi-telegram 0.24.0 → 0.24.2
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/AGENTS.md +3 -2
- package/BACKLOG.md +5 -19
- package/CHANGELOG.md +128 -274
- package/docs/architecture.md +13 -1
- package/docs/multi-instance-bus.md +3 -3
- package/docs/public-api.md +2 -0
- package/lib/bus-transport.ts +7 -14
- package/lib/bus.ts +48 -19
- package/lib/command-templates.ts +36 -20
- package/lib/config.ts +6 -34
- package/lib/inbound.ts +22 -26
- package/lib/lifecycle.ts +0 -13
- package/lib/locks.ts +46 -26
- package/lib/logs.ts +76 -18
- package/lib/media.ts +0 -9
- package/lib/menu-model.ts +5 -12
- package/lib/menu.ts +0 -19
- package/lib/outbound.ts +2 -12
- package/lib/pi.ts +0 -4
- package/lib/queue.ts +0 -5
- package/lib/replies.ts +0 -23
- package/lib/runtime.ts +1 -2
- package/lib/sections.ts +1 -48
- package/lib/status.ts +14 -8
- package/lib/telegram-api.ts +0 -4
- package/lib/threads.ts +41 -8
- package/package.json +1 -1
package/lib/threads.ts
CHANGED
|
@@ -443,8 +443,7 @@ export function getTelegramTopicTargetsPath(
|
|
|
443
443
|
return getTelegramStatePath(agentDir, profileName);
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
-
const TELEGRAM_LEADER_SESSION_HANDOFF_KEY =
|
|
447
|
-
"__piTelegramLeaderSessionHandoff";
|
|
446
|
+
const TELEGRAM_LEADER_SESSION_HANDOFF_KEY = "__piTelegramLeaderSessionHandoff";
|
|
448
447
|
export const TELEGRAM_LEADER_SESSION_HANDOFF_TTL_MS = 30_000;
|
|
449
448
|
|
|
450
449
|
export interface TelegramLeaderSessionHandoff {
|
|
@@ -458,8 +457,7 @@ export interface TelegramLeaderSessionHandoff {
|
|
|
458
457
|
}
|
|
459
458
|
|
|
460
459
|
export function getTelegramLeaderSessionHandoff():
|
|
461
|
-
|
|
|
462
|
-
| undefined {
|
|
460
|
+
TelegramLeaderSessionHandoff | undefined {
|
|
463
461
|
const value = (globalThis as Record<string, unknown>)[
|
|
464
462
|
TELEGRAM_LEADER_SESSION_HANDOFF_KEY
|
|
465
463
|
];
|
|
@@ -981,6 +979,18 @@ function parseTopicTargetFile(value: unknown): TelegramTopicTargetFile {
|
|
|
981
979
|
};
|
|
982
980
|
}
|
|
983
981
|
|
|
982
|
+
function serializeTelegramStateSemanticSnapshot(
|
|
983
|
+
value: unknown,
|
|
984
|
+
): string | undefined {
|
|
985
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
986
|
+
return undefined;
|
|
987
|
+
const { writtenAtMs: _writtenAtMs, ...semantic } = value as Record<
|
|
988
|
+
string,
|
|
989
|
+
unknown
|
|
990
|
+
>;
|
|
991
|
+
return JSON.stringify(semantic);
|
|
992
|
+
}
|
|
993
|
+
|
|
984
994
|
function targetMatches(left: TelegramTarget, right: TelegramTarget): boolean {
|
|
985
995
|
return left.chatId === right.chatId && left.threadId === right.threadId;
|
|
986
996
|
}
|
|
@@ -1083,6 +1093,7 @@ export function createTelegramTopicTargetStore(
|
|
|
1083
1093
|
let loadedPath: string | undefined;
|
|
1084
1094
|
let dirty = false;
|
|
1085
1095
|
let mutationRevision = 0;
|
|
1096
|
+
let statusRevision = 0;
|
|
1086
1097
|
let persistQueue: Promise<void> = Promise.resolve();
|
|
1087
1098
|
let statusSnapshot: {
|
|
1088
1099
|
runtime?: Record<string, unknown>;
|
|
@@ -1245,6 +1256,7 @@ export function createTelegramTopicTargetStore(
|
|
|
1245
1256
|
]),
|
|
1246
1257
|
);
|
|
1247
1258
|
const persistedRevision = mutationRevision;
|
|
1259
|
+
const persistedStatusRevision = statusRevision;
|
|
1248
1260
|
const file = {
|
|
1249
1261
|
version: 1,
|
|
1250
1262
|
source: "snapshot",
|
|
@@ -1266,6 +1278,24 @@ export function createTelegramTopicTargetStore(
|
|
|
1266
1278
|
return serialized;
|
|
1267
1279
|
}),
|
|
1268
1280
|
};
|
|
1281
|
+
let persistedSemanticSnapshot: string | undefined;
|
|
1282
|
+
try {
|
|
1283
|
+
persistedSemanticSnapshot = serializeTelegramStateSemanticSnapshot(
|
|
1284
|
+
JSON.parse(await readFile(path, "utf8")),
|
|
1285
|
+
);
|
|
1286
|
+
} catch {
|
|
1287
|
+
/* missing or invalid snapshots must be replaced */
|
|
1288
|
+
}
|
|
1289
|
+
if (
|
|
1290
|
+
persistedSemanticSnapshot ===
|
|
1291
|
+
serializeTelegramStateSemanticSnapshot(file) &&
|
|
1292
|
+
mutationRevision === persistedRevision &&
|
|
1293
|
+
statusRevision === persistedStatusRevision
|
|
1294
|
+
) {
|
|
1295
|
+
loaded = true;
|
|
1296
|
+
dirty = false;
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1269
1299
|
await writeFile(tempPath, `${JSON.stringify(file, null, 2)}\n`, {
|
|
1270
1300
|
encoding: "utf8",
|
|
1271
1301
|
mode: 0o600,
|
|
@@ -1407,6 +1437,7 @@ export function createTelegramTopicTargetStore(
|
|
|
1407
1437
|
setStatusSnapshot(snapshot) {
|
|
1408
1438
|
if (!loadedPath) loadedPath = getPath();
|
|
1409
1439
|
statusSnapshot = { ...snapshot };
|
|
1440
|
+
statusRevision += 1;
|
|
1410
1441
|
},
|
|
1411
1442
|
getByProfileKey(profileKey) {
|
|
1412
1443
|
const ownerKey = getTelegramThreadOwnerKey(
|
|
@@ -2025,13 +2056,16 @@ export async function provisionOwnBusTopic(
|
|
|
2025
2056
|
) {
|
|
2026
2057
|
const existingHandoffRecord = deps.store
|
|
2027
2058
|
.list()
|
|
2028
|
-
.find((record) =>
|
|
2059
|
+
.find((record) =>
|
|
2060
|
+
targetMatches(record.target, leaderSessionHandoff.target),
|
|
2061
|
+
);
|
|
2029
2062
|
deps.store.upsert({
|
|
2030
2063
|
profileKey,
|
|
2031
2064
|
owner: currentLeaderOwner,
|
|
2032
2065
|
target: { ...leaderSessionHandoff.target },
|
|
2033
2066
|
status: "active",
|
|
2034
|
-
createdAtMs:
|
|
2067
|
+
createdAtMs:
|
|
2068
|
+
existingHandoffRecord?.createdAtMs ?? leaderSessionHandoff.createdAtMs,
|
|
2035
2069
|
updatedAtMs: nowMs,
|
|
2036
2070
|
threadName:
|
|
2037
2071
|
existingHandoffRecord?.threadName ?? leaderSessionHandoff.threadName,
|
|
@@ -2042,8 +2076,7 @@ export async function provisionOwnBusTopic(
|
|
|
2042
2076
|
: {}),
|
|
2043
2077
|
...(existingHandoffRecord?.lastSyncObservedAtMs !== undefined
|
|
2044
2078
|
? {
|
|
2045
|
-
lastSyncObservedAtMs:
|
|
2046
|
-
existingHandoffRecord.lastSyncObservedAtMs,
|
|
2079
|
+
lastSyncObservedAtMs: existingHandoffRecord.lastSyncObservedAtMs,
|
|
2047
2080
|
}
|
|
2048
2081
|
: {}),
|
|
2049
2082
|
lastReconcileAction: "leader-session-handoff-restored",
|