@llblab/pi-kit 0.15.0 → 0.17.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/CHANGELOG.md +12 -0
- package/README.md +2 -2
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +12 -12
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +2 -13
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +31 -0
- package/node_modules/@llblab/pi-state-flow/README.md +11 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +5 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +17 -16
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +8 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +24 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +4 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +2 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +15 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/episode.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/episode.js +4 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +7 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +124 -274
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +20 -23
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +8 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/json.js +29 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +18 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +44 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.js +55 -21
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +7 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +65 -17
- package/node_modules/@llblab/pi-state-flow/dist/lib/publication.d.ts +17 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/publication.js +102 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +43 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +268 -10
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +34 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.d.ts +17 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/session.js +38 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +5 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +20 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +11 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +14 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.d.ts +2 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.js +55 -20
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.d.ts +9 -6
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +10 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +8 -3
- package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +79 -0
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +23 -121
- package/node_modules/@llblab/pi-state-flow/docs/README.md +1 -0
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +27 -20
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +1 -1
- package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +3 -2
- package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +513 -0
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +13 -10
- package/node_modules/@llblab/pi-state-flow/lib/config.ts +18 -15
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +24 -0
- package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +4 -3
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +14 -5
- package/node_modules/@llblab/pi-state-flow/lib/episode.ts +5 -0
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +119 -262
- package/node_modules/@llblab/pi-state-flow/lib/git.ts +23 -22
- package/node_modules/@llblab/pi-state-flow/lib/history.ts +8 -4
- package/node_modules/@llblab/pi-state-flow/lib/json.ts +31 -3
- package/node_modules/@llblab/pi-state-flow/lib/logging.ts +53 -1
- package/node_modules/@llblab/pi-state-flow/lib/migration.ts +51 -20
- package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +61 -17
- package/node_modules/@llblab/pi-state-flow/lib/publication.ts +96 -0
- package/node_modules/@llblab/pi-state-flow/lib/query.ts +261 -9
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +32 -4
- package/node_modules/@llblab/pi-state-flow/lib/session.ts +45 -0
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +22 -25
- package/node_modules/@llblab/pi-state-flow/lib/state.ts +22 -6
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/lib/storage.ts +46 -18
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +20 -6
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +8 -3
- package/node_modules/@llblab/pi-state-flow/package.json +1 -1
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +79 -0
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +23 -121
- package/node_modules/@llblab/pi-telegram/AGENTS.md +1 -1
- package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -0
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +7 -0
- package/node_modules/@llblab/pi-telegram/README.md +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +134 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +297 -16
- package/node_modules/@llblab/pi-telegram/dist/lib/delivery.d.ts +2 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/delivery.js +11 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +68 -8
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.d.ts +4 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.js +17 -13
- package/node_modules/@llblab/pi-telegram/dist/lib/pi.d.ts +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/pi.js +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/routing.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/routing.js +55 -5
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.d.ts +23 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.js +20 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +18 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +152 -6
- package/node_modules/@llblab/pi-telegram/dist/lib/updates.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/updates.js +5 -3
- package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +3 -3
- package/node_modules/@llblab/pi-telegram/docs/callback-namespaces.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +4 -3
- package/node_modules/@llblab/pi-telegram/docs/sections.md +2 -2
- package/node_modules/@llblab/pi-telegram/docs/ui-style.md +2 -1
- package/node_modules/@llblab/pi-telegram/docs/updates.md +1 -1
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +3 -0
- package/node_modules/@llblab/pi-telegram/lib/commands.ts +466 -21
- package/node_modules/@llblab/pi-telegram/lib/delivery.ts +15 -0
- package/node_modules/@llblab/pi-telegram/lib/extension.ts +77 -9
- package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +25 -10
- package/node_modules/@llblab/pi-telegram/lib/pi.ts +3 -0
- package/node_modules/@llblab/pi-telegram/lib/routing.ts +84 -17
- package/node_modules/@llblab/pi-telegram/lib/thread-display.ts +30 -0
- package/node_modules/@llblab/pi-telegram/lib/threads.ts +199 -6
- package/node_modules/@llblab/pi-telegram/lib/updates.ts +5 -2
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/package.json +3 -3
|
@@ -358,6 +358,20 @@ export interface TelegramBotStateSnapshot {
|
|
|
358
358
|
lastReconcileAction?: string;
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
+
export interface TelegramSessionReplacementIntent {
|
|
362
|
+
continuity: "workspace-thread" | "classic-chat";
|
|
363
|
+
cwd: string;
|
|
364
|
+
profileName: string;
|
|
365
|
+
sourceSessionId: string;
|
|
366
|
+
sourceUpdateId: number;
|
|
367
|
+
target: TelegramTarget;
|
|
368
|
+
messageId: number;
|
|
369
|
+
slot?: string;
|
|
370
|
+
threadName?: string;
|
|
371
|
+
createdAtMs: number;
|
|
372
|
+
expiresAtMs: number;
|
|
373
|
+
}
|
|
374
|
+
|
|
361
375
|
export interface TelegramTopicTargetFile {
|
|
362
376
|
version: 1;
|
|
363
377
|
source: "snapshot";
|
|
@@ -370,6 +384,7 @@ export interface TelegramTopicTargetFile {
|
|
|
370
384
|
identities?: TelegramThreadIdentityRecord[];
|
|
371
385
|
workspaceBindings?: TelegramWorkspaceThreadBinding[];
|
|
372
386
|
workspaceRetirements?: TelegramWorkspaceRetirementIntent[];
|
|
387
|
+
sessionReplacement?: TelegramSessionReplacementIntent;
|
|
373
388
|
reservations?: TelegramThreadReservation[];
|
|
374
389
|
pendingProvisions?: TelegramThreadPendingProvision[];
|
|
375
390
|
pendingCleanups?: TelegramThreadCleanupIntent[];
|
|
@@ -478,6 +493,19 @@ export interface TelegramTopicTargetStore {
|
|
|
478
493
|
) => TelegramThreadIdentityRecord | undefined;
|
|
479
494
|
forgetIdentityByProfileKey: (profileKey: string) => boolean;
|
|
480
495
|
listWorkspaceBindings: () => TelegramWorkspaceThreadBinding[];
|
|
496
|
+
getWorkspaceBindingByTarget: (
|
|
497
|
+
target: TelegramTarget,
|
|
498
|
+
sessionId?: string,
|
|
499
|
+
) => TelegramWorkspaceThreadBinding | undefined;
|
|
500
|
+
getSessionReplacementIntent: () => TelegramSessionReplacementIntent | undefined;
|
|
501
|
+
commitSessionReplacementIntent: (
|
|
502
|
+
intent: TelegramSessionReplacementIntent,
|
|
503
|
+
isCurrent: () => boolean,
|
|
504
|
+
) => Promise<boolean>;
|
|
505
|
+
removeSessionReplacementIntent: (
|
|
506
|
+
expected: TelegramSessionReplacementIntent,
|
|
507
|
+
isCurrent: () => boolean,
|
|
508
|
+
) => Promise<boolean>;
|
|
481
509
|
listWorkspaceRetirementIntents: () => TelegramWorkspaceRetirementIntent[];
|
|
482
510
|
commitWorkspaceJournalEvidence: (
|
|
483
511
|
expected: TelegramWorkspaceThreadBinding,
|
|
@@ -1289,6 +1317,56 @@ function cloneWorkspaceBinding(
|
|
|
1289
1317
|
return { ...binding, target: { ...binding.target } };
|
|
1290
1318
|
}
|
|
1291
1319
|
|
|
1320
|
+
function cloneSessionReplacementIntent(
|
|
1321
|
+
intent: TelegramSessionReplacementIntent,
|
|
1322
|
+
): TelegramSessionReplacementIntent {
|
|
1323
|
+
return { ...intent, target: { ...intent.target } };
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
function normalizeSessionReplacementIntent(
|
|
1327
|
+
value: unknown,
|
|
1328
|
+
): TelegramSessionReplacementIntent | undefined {
|
|
1329
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
|
1330
|
+
const record = value as Record<string, unknown>;
|
|
1331
|
+
const target = record.target as Record<string, unknown> | undefined;
|
|
1332
|
+
if (
|
|
1333
|
+
typeof record.cwd !== "string" || !normalizeTelegramWorkspacePath(record.cwd) ||
|
|
1334
|
+
typeof record.profileName !== "string" || !record.profileName ||
|
|
1335
|
+
typeof record.sourceSessionId !== "string" || !normalizeTelegramSessionId(record.sourceSessionId) ||
|
|
1336
|
+
typeof record.sourceUpdateId !== "number" || !Number.isSafeInteger(record.sourceUpdateId) ||
|
|
1337
|
+
!target || typeof target.chatId !== "number" ||
|
|
1338
|
+
(target.threadId !== undefined &&
|
|
1339
|
+
(typeof target.threadId !== "number" || !Number.isSafeInteger(target.threadId))) ||
|
|
1340
|
+
typeof record.messageId !== "number" || !Number.isSafeInteger(record.messageId) ||
|
|
1341
|
+
typeof record.createdAtMs !== "number" || !Number.isSafeInteger(record.createdAtMs) ||
|
|
1342
|
+
typeof record.expiresAtMs !== "number" || !Number.isSafeInteger(record.expiresAtMs) ||
|
|
1343
|
+
record.expiresAtMs <= record.createdAtMs
|
|
1344
|
+
) return undefined;
|
|
1345
|
+
const continuity = record.continuity === "workspace-thread" ||
|
|
1346
|
+
record.continuity === "classic-chat"
|
|
1347
|
+
? record.continuity
|
|
1348
|
+
: target.threadId !== undefined ? "workspace-thread" : "classic-chat";
|
|
1349
|
+
if ((continuity === "workspace-thread") !== (target.threadId !== undefined)) {
|
|
1350
|
+
return undefined;
|
|
1351
|
+
}
|
|
1352
|
+
return {
|
|
1353
|
+
continuity,
|
|
1354
|
+
cwd: normalizeTelegramWorkspacePath(record.cwd)!,
|
|
1355
|
+
profileName: record.profileName,
|
|
1356
|
+
sourceSessionId: normalizeTelegramSessionId(record.sourceSessionId)!,
|
|
1357
|
+
sourceUpdateId: record.sourceUpdateId,
|
|
1358
|
+
target: {
|
|
1359
|
+
chatId: target.chatId,
|
|
1360
|
+
...(typeof target.threadId === "number" ? { threadId: target.threadId } : {}),
|
|
1361
|
+
},
|
|
1362
|
+
messageId: record.messageId,
|
|
1363
|
+
...(typeof record.slot === "string" ? { slot: record.slot } : {}),
|
|
1364
|
+
...(typeof record.threadName === "string" ? { threadName: record.threadName } : {}),
|
|
1365
|
+
createdAtMs: record.createdAtMs,
|
|
1366
|
+
expiresAtMs: record.expiresAtMs,
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1292
1370
|
function normalizeWorkspaceRetirementIntent(
|
|
1293
1371
|
value: unknown,
|
|
1294
1372
|
): TelegramWorkspaceRetirementIntent | undefined {
|
|
@@ -1596,6 +1674,7 @@ function parseTopicTargetFile(value: unknown): TelegramTopicTargetFile {
|
|
|
1596
1674
|
return normalized ? [normalized] : [];
|
|
1597
1675
|
})
|
|
1598
1676
|
: [],
|
|
1677
|
+
sessionReplacement: normalizeSessionReplacementIntent(file.sessionReplacement),
|
|
1599
1678
|
reservations: Array.isArray(file.reservations)
|
|
1600
1679
|
? file.reservations.flatMap((reservation) => {
|
|
1601
1680
|
const normalized = normalizeReservation(reservation);
|
|
@@ -1740,6 +1819,7 @@ export function createTelegramTopicTargetStore(
|
|
|
1740
1819
|
let identities = new Map<string, TelegramThreadIdentityRecord>();
|
|
1741
1820
|
let workspaceBindings = new Map<string, TelegramWorkspaceThreadBinding>();
|
|
1742
1821
|
let workspaceRetirements: TelegramWorkspaceRetirementIntent[] = [];
|
|
1822
|
+
let sessionReplacement: TelegramSessionReplacementIntent | undefined;
|
|
1743
1823
|
let workspaceRetirementCommitInFlight = false;
|
|
1744
1824
|
const hasWorkspaceRetirementConflict = (input: {
|
|
1745
1825
|
bindingKey?: string;
|
|
@@ -1906,6 +1986,7 @@ export function createTelegramTopicTargetStore(
|
|
|
1906
1986
|
identities = new Map();
|
|
1907
1987
|
workspaceBindings = new Map();
|
|
1908
1988
|
workspaceRetirements = [];
|
|
1989
|
+
sessionReplacement = undefined;
|
|
1909
1990
|
workspaceRetirementCommitInFlight = false;
|
|
1910
1991
|
workspaceClaims = new Map();
|
|
1911
1992
|
reservations = [];
|
|
@@ -1928,6 +2009,7 @@ export function createTelegramTopicTargetStore(
|
|
|
1928
2009
|
identities = new Map();
|
|
1929
2010
|
workspaceBindings = new Map();
|
|
1930
2011
|
workspaceRetirements = [];
|
|
2012
|
+
sessionReplacement = undefined;
|
|
1931
2013
|
workspaceRetirementCommitInFlight = false;
|
|
1932
2014
|
reservations = [];
|
|
1933
2015
|
pendingProvisions = [];
|
|
@@ -1976,6 +2058,9 @@ export function createTelegramTopicTargetStore(
|
|
|
1976
2058
|
workspaceRetirements = (file.workspaceRetirements ?? []).map(
|
|
1977
2059
|
cloneWorkspaceRetirementIntent,
|
|
1978
2060
|
);
|
|
2061
|
+
sessionReplacement = file.sessionReplacement
|
|
2062
|
+
? cloneSessionReplacementIntent(file.sessionReplacement)
|
|
2063
|
+
: undefined;
|
|
1979
2064
|
reconcileWorkspaceSuffixExposure();
|
|
1980
2065
|
for (const record of records.values()) rememberIdentity(record);
|
|
1981
2066
|
const nowMs = getNowMs();
|
|
@@ -2070,6 +2155,9 @@ export function createTelegramTopicTargetStore(
|
|
|
2070
2155
|
workspaceRetirements: workspaceRetirements.map(
|
|
2071
2156
|
cloneWorkspaceRetirementIntent,
|
|
2072
2157
|
),
|
|
2158
|
+
...(sessionReplacement
|
|
2159
|
+
? { sessionReplacement: cloneSessionReplacementIntent(sessionReplacement) }
|
|
2160
|
+
: {}),
|
|
2073
2161
|
reservations: reservations.map((reservation) => ({ ...reservation })),
|
|
2074
2162
|
pendingProvisions: pendingProvisions.map((provision) => ({
|
|
2075
2163
|
...provision,
|
|
@@ -2366,6 +2454,38 @@ export function createTelegramTopicTargetStore(
|
|
|
2366
2454
|
listWorkspaceBindings() {
|
|
2367
2455
|
return Array.from(workspaceBindings.values()).map(cloneWorkspaceBinding);
|
|
2368
2456
|
},
|
|
2457
|
+
getWorkspaceBindingByTarget(target, sessionId) {
|
|
2458
|
+
const binding = Array.from(workspaceBindings.values()).find((candidate) =>
|
|
2459
|
+
targetMatches(candidate.target, target) &&
|
|
2460
|
+
(sessionId === undefined || candidate.sessionId === sessionId)
|
|
2461
|
+
);
|
|
2462
|
+
return binding ? cloneWorkspaceBinding(binding) : undefined;
|
|
2463
|
+
},
|
|
2464
|
+
getSessionReplacementIntent() {
|
|
2465
|
+
return sessionReplacement
|
|
2466
|
+
? cloneSessionReplacementIntent(sessionReplacement)
|
|
2467
|
+
: undefined;
|
|
2468
|
+
},
|
|
2469
|
+
async commitSessionReplacementIntent(intent, isCurrent) {
|
|
2470
|
+
const next = normalizeSessionReplacementIntent(intent);
|
|
2471
|
+
if (!next || !isCurrent()) return false;
|
|
2472
|
+
await loadFromDisk();
|
|
2473
|
+
if (!isCurrent()) return false;
|
|
2474
|
+
const existing = sessionReplacement;
|
|
2475
|
+
if (existing && existing.expiresAtMs > getNowMs() &&
|
|
2476
|
+
!isDeepStrictEqual(existing, next)) return false;
|
|
2477
|
+
sessionReplacement = cloneSessionReplacementIntent(next);
|
|
2478
|
+
markDirty();
|
|
2479
|
+
return await persistSnapshot() && isCurrent();
|
|
2480
|
+
},
|
|
2481
|
+
async removeSessionReplacementIntent(expected, isCurrent) {
|
|
2482
|
+
await loadFromDisk();
|
|
2483
|
+
if (!isCurrent() || !sessionReplacement ||
|
|
2484
|
+
!isDeepStrictEqual(sessionReplacement, expected)) return false;
|
|
2485
|
+
sessionReplacement = undefined;
|
|
2486
|
+
markDirty();
|
|
2487
|
+
return await persistSnapshot() && isCurrent();
|
|
2488
|
+
},
|
|
2369
2489
|
listWorkspaceRetirementIntents() {
|
|
2370
2490
|
return workspaceRetirements.map(cloneWorkspaceRetirementIntent);
|
|
2371
2491
|
},
|
|
@@ -2764,6 +2884,47 @@ export function createTelegramTopicTargetStore(
|
|
|
2764
2884
|
if (!normalizedCwd || !instanceId ||
|
|
2765
2885
|
(options?.sessionId !== undefined && !normalizedSessionId) ||
|
|
2766
2886
|
hasWorkspaceRetirementConflict({ cwd: normalizedCwd })) return undefined;
|
|
2887
|
+
let replacementPreviousInstanceId: string | undefined;
|
|
2888
|
+
const replacement = sessionReplacement;
|
|
2889
|
+
if (
|
|
2890
|
+
replacement?.continuity === "workspace-thread" && normalizedSessionId &&
|
|
2891
|
+
replacement.expiresAtMs > getNowMs() &&
|
|
2892
|
+
replacement.profileName === (getTelegramProfile() ?? "default") &&
|
|
2893
|
+
replacement.cwd === normalizedCwd &&
|
|
2894
|
+
replacement.sourceSessionId !== normalizedSessionId
|
|
2895
|
+
) {
|
|
2896
|
+
const sourceEntry = Array.from(workspaceBindings.entries()).find(([, binding]) =>
|
|
2897
|
+
binding.cwd === normalizedCwd &&
|
|
2898
|
+
binding.sessionId === replacement.sourceSessionId &&
|
|
2899
|
+
targetMatches(binding.target, replacement.target)
|
|
2900
|
+
);
|
|
2901
|
+
if (sourceEntry) {
|
|
2902
|
+
const [sourceKey, sourceBinding] = sourceEntry;
|
|
2903
|
+
const replacementIdentity = Array.from({ length: TELEGRAM_WORKSPACE_SLOTS.length })
|
|
2904
|
+
.map((_, ordinal) => createTelegramWorkspaceBindingIdentityWithKey(
|
|
2905
|
+
sourceBinding.cwd,
|
|
2906
|
+
sourceBinding.workspaceKey,
|
|
2907
|
+
ordinal,
|
|
2908
|
+
normalizedSessionId,
|
|
2909
|
+
))
|
|
2910
|
+
.find((identity) => identity?.instanceSlot === sourceBinding.instanceSlot);
|
|
2911
|
+
if (replacementIdentity &&
|
|
2912
|
+
replacementIdentity.instanceSlot === sourceBinding.instanceSlot) {
|
|
2913
|
+
const existingTargetRecord = Array.from(records.values()).find((record) =>
|
|
2914
|
+
targetMatches(record.target, replacement.target)
|
|
2915
|
+
);
|
|
2916
|
+
replacementPreviousInstanceId = existingTargetRecord?.instanceId;
|
|
2917
|
+
workspaceBindings.delete(sourceKey);
|
|
2918
|
+
workspaceBindings.set(getWorkspaceBindingMapKey(replacementIdentity), {
|
|
2919
|
+
...sourceBinding,
|
|
2920
|
+
...replacementIdentity,
|
|
2921
|
+
updatedAtMs: getNowMs(),
|
|
2922
|
+
});
|
|
2923
|
+
markDirty();
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
const effectivePreviousInstanceId = previousInstanceId ?? replacementPreviousInstanceId;
|
|
2767
2928
|
const externalReservedSlots = captureExternalReservedSlots();
|
|
2768
2929
|
if (!externalReservedSlots) {
|
|
2769
2930
|
options?.onCapacityUnavailable?.();
|
|
@@ -2810,9 +2971,15 @@ export function createTelegramTopicTargetStore(
|
|
|
2810
2971
|
const mapKey = getWorkspaceBindingMapKey(identity);
|
|
2811
2972
|
const existingClaim = workspaceClaims.get(mapKey);
|
|
2812
2973
|
if (existingClaim) {
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2974
|
+
if (existingClaim.instanceId === instanceId) {
|
|
2975
|
+
return { ...existingClaim.identity };
|
|
2976
|
+
}
|
|
2977
|
+
if (existingClaim.instanceId !== effectivePreviousInstanceId) return undefined;
|
|
2978
|
+
workspaceClaims.set(mapKey, {
|
|
2979
|
+
identity: existingClaim.identity,
|
|
2980
|
+
instanceId,
|
|
2981
|
+
});
|
|
2982
|
+
return { ...existingClaim.identity };
|
|
2816
2983
|
}
|
|
2817
2984
|
const binding = workspaceBindings.get(mapKey);
|
|
2818
2985
|
const liveRecord = binding
|
|
@@ -2821,7 +2988,7 @@ export function createTelegramTopicTargetStore(
|
|
|
2821
2988
|
if (
|
|
2822
2989
|
liveRecord &&
|
|
2823
2990
|
liveRecord.instanceId !== instanceId &&
|
|
2824
|
-
liveRecord.instanceId !==
|
|
2991
|
+
liveRecord.instanceId !== effectivePreviousInstanceId
|
|
2825
2992
|
) {
|
|
2826
2993
|
return undefined;
|
|
2827
2994
|
}
|
|
@@ -2963,9 +3130,35 @@ export function createTelegramTopicTargetStore(
|
|
|
2963
3130
|
if (next && hasWorkspaceRetirementConflict(next)) return undefined;
|
|
2964
3131
|
if (!next) return undefined;
|
|
2965
3132
|
const nextMapKey = getWorkspaceBindingMapKey(next);
|
|
2966
|
-
|
|
3133
|
+
let claim = workspaceClaims.get(nextMapKey);
|
|
3134
|
+
const replacedTargetBinding = Array.from(workspaceBindings.values()).find(
|
|
3135
|
+
(existing) =>
|
|
3136
|
+
existing.bindingKey !== next.bindingKey &&
|
|
3137
|
+
targetMatches(existing.target, next.target),
|
|
3138
|
+
);
|
|
3139
|
+
if (
|
|
3140
|
+
claimInstanceId && claim?.instanceId === claimInstanceId &&
|
|
3141
|
+
replacedTargetBinding?.slot
|
|
3142
|
+
) {
|
|
3143
|
+
claim = {
|
|
3144
|
+
...claim,
|
|
3145
|
+
identity: { ...claim.identity, slot: replacedTargetBinding.slot },
|
|
3146
|
+
};
|
|
3147
|
+
workspaceClaims.set(nextMapKey, claim);
|
|
3148
|
+
next.slot = replacedTargetBinding.slot;
|
|
3149
|
+
if (replacedTargetBinding.threadName && !next.threadName) {
|
|
3150
|
+
next.threadName = replacedTargetBinding.threadName;
|
|
3151
|
+
}
|
|
3152
|
+
if (replacedTargetBinding.manualThreadName && !next.manualThreadName) {
|
|
3153
|
+
next.manualThreadName = replacedTargetBinding.manualThreadName;
|
|
3154
|
+
}
|
|
3155
|
+
if (replacedTargetBinding.displayTitle && !next.displayTitle) {
|
|
3156
|
+
next.displayTitle = replacedTargetBinding.displayTitle;
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
2967
3159
|
if (next.slot && Array.from(workspaceBindings.values()).some((existing) =>
|
|
2968
|
-
existing.bindingKey !== next.bindingKey && existing.slot === next.slot
|
|
3160
|
+
existing.bindingKey !== next.bindingKey && existing.slot === next.slot &&
|
|
3161
|
+
!targetMatches(existing.target, next.target),
|
|
2969
3162
|
)) return undefined;
|
|
2970
3163
|
for (const existing of workspaceBindings.values()) {
|
|
2971
3164
|
if (
|
|
@@ -5517,6 +5517,7 @@ export interface TelegramUpdateWorkerOwnerRuntimeDeps<TContext> {
|
|
|
5517
5517
|
isContextCurrent: (ctx: TContext) => boolean;
|
|
5518
5518
|
dispatchNext: (ctx: TContext) => void;
|
|
5519
5519
|
requestQueueHandoffReconciliation: (ctx: TContext) => void;
|
|
5520
|
+
afterUpdateCompleted?: (updateId: number) => void;
|
|
5520
5521
|
}
|
|
5521
5522
|
|
|
5522
5523
|
export function createTelegramUpdateWorkerOwnerRuntime<TContext>(
|
|
@@ -5536,8 +5537,10 @@ export function createTelegramUpdateWorkerOwnerRuntime<TContext>(
|
|
|
5536
5537
|
deps.dispatchNext(ctx);
|
|
5537
5538
|
deps.requestQueueHandoffReconciliation(ctx);
|
|
5538
5539
|
},
|
|
5539
|
-
onUpdateCompleted(
|
|
5540
|
-
if (deps.isContextCurrent(ctx))
|
|
5540
|
+
onUpdateCompleted(updateId, ctx) {
|
|
5541
|
+
if (!deps.isContextCurrent(ctx)) return;
|
|
5542
|
+
deps.dispatchNext(ctx);
|
|
5543
|
+
deps.afterUpdateCompleted?.(updateId);
|
|
5541
5544
|
},
|
|
5542
5545
|
};
|
|
5543
5546
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"@llblab/pi-clean-room": "0.1.1",
|
|
45
45
|
"@llblab/pi-codex-usage": "0.10.0",
|
|
46
46
|
"@llblab/pi-grow-loop": "0.8.1",
|
|
47
|
-
"@llblab/pi-state-flow": "0.
|
|
48
|
-
"@llblab/pi-telegram": "0.
|
|
47
|
+
"@llblab/pi-state-flow": "0.16.0",
|
|
48
|
+
"@llblab/pi-telegram": "0.49.0",
|
|
49
49
|
"@llblab/skills": "1.15.0"
|
|
50
50
|
},
|
|
51
51
|
"bundledDependencies": [
|