@llblab/pi-kit 0.18.1 → 0.19.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 +4 -2
- package/node_modules/@llblab/pi-state-flow/AGENTS.md +35 -37
- package/node_modules/@llblab/pi-state-flow/BACKLOG.md +5 -3
- package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +19 -1
- package/node_modules/@llblab/pi-state-flow/README.md +102 -48
- package/node_modules/@llblab/pi-state-flow/dist/index.d.ts +6 -9
- package/node_modules/@llblab/pi-state-flow/dist/index.js +6 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.d.ts +2 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/acquisition.js +21 -8
- package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.d.ts +40 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/artifact.js +93 -63
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.d.ts +4 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/compaction.js +9 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.d.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/config.js +6 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +8 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +56 -58
- package/node_modules/@llblab/pi-state-flow/dist/lib/continuation.js +12 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.d.ts +7 -18
- package/node_modules/@llblab/pi-state-flow/dist/lib/durable.js +47 -78
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.d.ts +4 -6
- package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +241 -437
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.d.ts +2 -72
- package/node_modules/@llblab/pi-state-flow/dist/lib/git.js +120 -499
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.d.ts +2 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/history.js +4 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/json.d.ts +3 -0
- package/node_modules/@llblab/pi-state-flow/dist/lib/json.js +43 -22
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.d.ts +1 -5
- package/node_modules/@llblab/pi-state-flow/dist/lib/logging.js +0 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/memory.d.ts +1 -14
- package/node_modules/@llblab/pi-state-flow/dist/lib/memory.js +5 -37
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +1 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +13 -32
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.d.ts +6 -6
- package/node_modules/@llblab/pi-state-flow/dist/lib/query.js +25 -21
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.d.ts +3 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/recovery.js +15 -12
- package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.d.ts +2 -4
- package/node_modules/@llblab/pi-state-flow/dist/lib/rehydration.js +5 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.d.ts +26 -88
- package/node_modules/@llblab/pi-state-flow/dist/lib/runtime.js +159 -255
- package/node_modules/@llblab/pi-state-flow/dist/lib/skills.d.ts +0 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/skills.js +1 -47
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.d.ts +16 -33
- package/node_modules/@llblab/pi-state-flow/dist/lib/snapshot.js +48 -137
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.d.ts +16 -11
- package/node_modules/@llblab/pi-state-flow/dist/lib/state.js +13 -14
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.d.ts +1 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/status.js +15 -43
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.d.ts +5 -9
- package/node_modules/@llblab/pi-state-flow/dist/lib/storage.js +13 -45
- package/node_modules/@llblab/pi-state-flow/dist/lib/telegram.js +1 -1
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.d.ts +15 -7
- package/node_modules/@llblab/pi-state-flow/dist/lib/temporal.js +104 -24
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.d.ts +0 -2
- package/node_modules/@llblab/pi-state-flow/dist/lib/transition.js +11 -14
- package/node_modules/@llblab/pi-state-flow/dist/package.json +9 -6
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-guide/SKILL.md +11 -17
- package/node_modules/@llblab/pi-state-flow/dist/skills/state-flow-memory/SKILL.md +8 -8
- package/node_modules/@llblab/pi-state-flow/docs/README.md +2 -2
- package/node_modules/@llblab/pi-state-flow/docs/architecture.md +64 -67
- package/node_modules/@llblab/pi-state-flow/docs/compatibility.md +24 -6
- package/node_modules/@llblab/pi-state-flow/docs/filesystem-recovery.md +12 -15
- package/node_modules/@llblab/pi-state-flow/docs/fork-contract.md +22 -27
- package/node_modules/@llblab/pi-state-flow/docs/lazy-state.md +25 -41
- package/node_modules/@llblab/pi-state-flow/docs/performance.md +38 -421
- package/node_modules/@llblab/pi-state-flow/docs/temporal-acceptance.md +33 -46
- package/node_modules/@llblab/pi-state-flow/docs/usage.md +37 -61
- package/node_modules/@llblab/pi-state-flow/index.ts +7 -71
- package/node_modules/@llblab/pi-state-flow/lib/acquisition.ts +26 -11
- package/node_modules/@llblab/pi-state-flow/lib/artifact.ts +116 -88
- package/node_modules/@llblab/pi-state-flow/lib/compaction.ts +12 -10
- package/node_modules/@llblab/pi-state-flow/lib/config.ts +6 -6
- package/node_modules/@llblab/pi-state-flow/lib/context.ts +52 -59
- package/node_modules/@llblab/pi-state-flow/lib/continuation.ts +11 -20
- package/node_modules/@llblab/pi-state-flow/lib/durable.ts +44 -86
- package/node_modules/@llblab/pi-state-flow/lib/extension.ts +237 -460
- package/node_modules/@llblab/pi-state-flow/lib/git.ts +110 -552
- package/node_modules/@llblab/pi-state-flow/lib/history.ts +4 -3
- package/node_modules/@llblab/pi-state-flow/lib/json.ts +39 -23
- package/node_modules/@llblab/pi-state-flow/lib/logging.ts +1 -7
- package/node_modules/@llblab/pi-state-flow/lib/memory.ts +5 -44
- package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +14 -25
- package/node_modules/@llblab/pi-state-flow/lib/query.ts +26 -22
- package/node_modules/@llblab/pi-state-flow/lib/recovery.ts +17 -11
- package/node_modules/@llblab/pi-state-flow/lib/rehydration.ts +7 -5
- package/node_modules/@llblab/pi-state-flow/lib/runtime.ts +154 -254
- package/node_modules/@llblab/pi-state-flow/lib/skills.ts +1 -49
- package/node_modules/@llblab/pi-state-flow/lib/snapshot.ts +58 -142
- package/node_modules/@llblab/pi-state-flow/lib/state.ts +27 -19
- package/node_modules/@llblab/pi-state-flow/lib/status.ts +16 -54
- package/node_modules/@llblab/pi-state-flow/lib/storage.ts +12 -40
- package/node_modules/@llblab/pi-state-flow/lib/telegram.ts +1 -1
- package/node_modules/@llblab/pi-state-flow/lib/temporal.ts +104 -22
- package/node_modules/@llblab/pi-state-flow/lib/transition.ts +16 -26
- package/node_modules/@llblab/pi-state-flow/package.json +9 -6
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-guide/SKILL.md +11 -17
- package/node_modules/@llblab/pi-state-flow/skills/state-flow-memory/SKILL.md +8 -8
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +7 -0
- package/node_modules/@llblab/pi-telegram/README.md +1 -2
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +1 -3
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +1 -6
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +1 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +13 -33
- package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +1 -4
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.d.ts +1 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.js +72 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/queue.d.ts +7 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/queue.js +27 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/replies.d.ts +3 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/replies.js +17 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/sync.js +8 -1
- package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +2 -0
- package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +1 -1
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +0 -10
- package/node_modules/@llblab/pi-telegram/lib/commands.ts +18 -41
- package/node_modules/@llblab/pi-telegram/lib/extension.ts +1 -8
- package/node_modules/@llblab/pi-telegram/lib/menu-queue.ts +126 -1
- package/node_modules/@llblab/pi-telegram/lib/queue.ts +46 -0
- package/node_modules/@llblab/pi-telegram/lib/replies.ts +19 -0
- package/node_modules/@llblab/pi-telegram/lib/sync.ts +8 -1
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/package.json +3 -3
- package/node_modules/@llblab/pi-state-flow/dist/lib/discovery.d.ts +0 -21
- package/node_modules/@llblab/pi-state-flow/dist/lib/discovery.js +0 -125
- package/node_modules/@llblab/pi-state-flow/dist/lib/maintenance.d.ts +0 -36
- package/node_modules/@llblab/pi-state-flow/dist/lib/maintenance.js +0 -98
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.d.ts +0 -13
- package/node_modules/@llblab/pi-state-flow/dist/lib/migration.js +0 -167
- package/node_modules/@llblab/pi-state-flow/dist/lib/publication.d.ts +0 -86
- package/node_modules/@llblab/pi-state-flow/dist/lib/publication.js +0 -437
- package/node_modules/@llblab/pi-state-flow/lib/discovery.ts +0 -133
- package/node_modules/@llblab/pi-state-flow/lib/maintenance.ts +0 -147
- package/node_modules/@llblab/pi-state-flow/lib/migration.ts +0 -171
- package/node_modules/@llblab/pi-state-flow/lib/publication.ts +0 -458
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Owns Telegram slash-command normalization, bot command metadata, pi-side command registration, and command-initiated session replacement orchestration behind runtime ports
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
|
|
7
9
|
import {
|
|
8
10
|
pairTelegramUserIfNeeded,
|
|
9
11
|
type TelegramConfigStore,
|
|
@@ -366,7 +368,6 @@ export function createTelegramBotCommandRegistrar(
|
|
|
366
368
|
export interface TelegramBridgeCommandStartPollingOptions {
|
|
367
369
|
force?: boolean;
|
|
368
370
|
forceFreshLeaderThread?: boolean;
|
|
369
|
-
requestedThreadName?: string;
|
|
370
371
|
}
|
|
371
372
|
|
|
372
373
|
export interface TelegramBridgeCommandStartPollingResult {
|
|
@@ -407,7 +408,6 @@ export interface TelegramBridgeCommandRegistrationDeps {
|
|
|
407
408
|
ctx: ExtensionCommandContext,
|
|
408
409
|
profileName: string,
|
|
409
410
|
) => Promise<boolean>;
|
|
410
|
-
validateThreadName?: (threadName: string) => string | undefined;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
413
|
export type TelegramThreadDisplayNameRenamePort = (
|
|
@@ -466,17 +466,6 @@ function parseTelegramProfileArg(args: string): string | undefined {
|
|
|
466
466
|
return word === TELEGRAM_DEFAULT_PROFILE_NAME ? undefined : word;
|
|
467
467
|
}
|
|
468
468
|
|
|
469
|
-
export function parseTelegramRequestedThreadName(
|
|
470
|
-
args: string,
|
|
471
|
-
): string | undefined {
|
|
472
|
-
const token = args
|
|
473
|
-
.trim()
|
|
474
|
-
.split(/\s+/)
|
|
475
|
-
.find((word) => /^as=/i.test(word));
|
|
476
|
-
const value = token?.slice(3).trim();
|
|
477
|
-
return value || undefined;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
469
|
function formatTelegramTakeoverTitle(ctx: ExtensionCommandContext): string {
|
|
481
470
|
return ctx.ui.theme.fg("accent", "pi-telegram");
|
|
482
471
|
}
|
|
@@ -498,7 +487,7 @@ export function registerTelegramBridgeCommands(
|
|
|
498
487
|
deps: TelegramBridgeCommandRegistrationDeps,
|
|
499
488
|
): void {
|
|
500
489
|
pi.registerCommand("telegram-setup", {
|
|
501
|
-
description: "Configure Telegram bot token
|
|
490
|
+
description: "<profile> — Configure Telegram bot token",
|
|
502
491
|
handler: async (args, ctx) => {
|
|
503
492
|
await deps.promptForConfig(ctx, parseTelegramProfileArg(args));
|
|
504
493
|
},
|
|
@@ -513,28 +502,17 @@ export function registerTelegramBridgeCommands(
|
|
|
513
502
|
},
|
|
514
503
|
});
|
|
515
504
|
pi.registerCommand("telegram-connect", {
|
|
516
|
-
description:
|
|
517
|
-
"Start the Telegram bridge. Use /telegram-connect <profile> and optional as=Name for a fresh Workspace Thread.",
|
|
505
|
+
description: "<profile> — Start Telegram bridge",
|
|
518
506
|
handler: async (args, ctx) => {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const requestedThreadName = parseTelegramRequestedThreadName(args);
|
|
525
|
-
const requestedNameError =
|
|
526
|
-
requestedNameTokens.length > 1
|
|
527
|
-
? "Specify at most one as=Name Workspace Thread name."
|
|
528
|
-
: requestedNameTokens.length === 1 && !requestedThreadName
|
|
529
|
-
? "Usage: /telegram-connect [profile] as=Flightprice"
|
|
530
|
-
: requestedThreadName
|
|
531
|
-
? deps.validateThreadName?.(requestedThreadName)
|
|
532
|
-
: undefined;
|
|
533
|
-
if (requestedNameError) {
|
|
534
|
-
ctx.ui.notify(requestedNameError, "warning");
|
|
507
|
+
if (args.trim().split(/\s+/).some((word) => /^as=/i.test(word))) {
|
|
508
|
+
ctx.ui.notify(
|
|
509
|
+
"Thread names are configured from Telegram, not from Pi commands.",
|
|
510
|
+
"warning",
|
|
511
|
+
);
|
|
535
512
|
deps.updateStatus(ctx);
|
|
536
513
|
return;
|
|
537
514
|
}
|
|
515
|
+
const profileName = parseTelegramProfileArg(args);
|
|
538
516
|
if (profileName && deps.activateProfileConfig) {
|
|
539
517
|
const ok = await deps.activateProfileConfig(ctx, profileName);
|
|
540
518
|
if (!ok) {
|
|
@@ -597,7 +575,6 @@ export function registerTelegramBridgeCommands(
|
|
|
597
575
|
};
|
|
598
576
|
let result = await startWithRecovery({
|
|
599
577
|
forceFreshLeaderThread: true,
|
|
600
|
-
...(requestedThreadName ? { requestedThreadName } : {}),
|
|
601
578
|
});
|
|
602
579
|
if (result && !result.ok && result.canTakeover) {
|
|
603
580
|
const confirmed = await ctx.ui.confirm(
|
|
@@ -612,7 +589,6 @@ export function registerTelegramBridgeCommands(
|
|
|
612
589
|
result = await startWithRecovery({
|
|
613
590
|
force: true,
|
|
614
591
|
forceFreshLeaderThread: true,
|
|
615
|
-
...(requestedThreadName ? { requestedThreadName } : {}),
|
|
616
592
|
});
|
|
617
593
|
}
|
|
618
594
|
if (result?.message) {
|
|
@@ -625,8 +601,7 @@ export function registerTelegramBridgeCommands(
|
|
|
625
601
|
},
|
|
626
602
|
});
|
|
627
603
|
pi.registerCommand("telegram-disconnect", {
|
|
628
|
-
description:
|
|
629
|
-
"Stop Telegram; in Threaded Mode, delete this instance's current thread",
|
|
604
|
+
description: "Stop Telegram and delete current thread in Threaded Mode",
|
|
630
605
|
handler: async (_args, ctx) => {
|
|
631
606
|
const threadName = deps.getDisconnectThreadName?.();
|
|
632
607
|
if (threadName) {
|
|
@@ -2337,7 +2312,7 @@ async function handleTelegramCommandRuntime<
|
|
|
2337
2312
|
|
|
2338
2313
|
export const TELEGRAM_INTERNAL_COMMAND_NAME = "telegram-internal";
|
|
2339
2314
|
export const TELEGRAM_INTERNAL_COMMAND_DESCRIPTION =
|
|
2340
|
-
"
|
|
2315
|
+
"Internal Telegram command cannot be run manually";
|
|
2341
2316
|
export const TELEGRAM_INTERNAL_MANUAL_USE_MESSAGE =
|
|
2342
2317
|
"This internal Telegram command cannot be run manually.";
|
|
2343
2318
|
|
|
@@ -2542,6 +2517,7 @@ export function createTelegramSessionActionAssembly(
|
|
|
2542
2517
|
|
|
2543
2518
|
type TelegramPendingInternalAction = {
|
|
2544
2519
|
kind: "replace-session";
|
|
2520
|
+
token: string;
|
|
2545
2521
|
updateId: number;
|
|
2546
2522
|
target: { chatId: number; threadId?: number; messageId: number };
|
|
2547
2523
|
};
|
|
@@ -2582,9 +2558,9 @@ export function createTelegramSessionActionRuntime(
|
|
|
2582
2558
|
registered = true;
|
|
2583
2559
|
deps.registerCommand(TELEGRAM_INTERNAL_COMMAND_NAME, {
|
|
2584
2560
|
description: TELEGRAM_INTERNAL_COMMAND_DESCRIPTION,
|
|
2585
|
-
handler: async (
|
|
2561
|
+
handler: async (args, ctx) => {
|
|
2586
2562
|
const action = pendingAction;
|
|
2587
|
-
if (!action) {
|
|
2563
|
+
if (!action || args.trim() !== action.token) {
|
|
2588
2564
|
ctx.ui.notify(TELEGRAM_INTERNAL_MANUAL_USE_MESSAGE, "warning");
|
|
2589
2565
|
return;
|
|
2590
2566
|
}
|
|
@@ -2616,10 +2592,11 @@ export function createTelegramSessionActionRuntime(
|
|
|
2616
2592
|
const target = pendingTarget;
|
|
2617
2593
|
pendingTarget = undefined;
|
|
2618
2594
|
if (!target) return;
|
|
2619
|
-
|
|
2595
|
+
const token = randomUUID();
|
|
2596
|
+
pendingAction = { kind: "replace-session", token, updateId, target };
|
|
2620
2597
|
void Promise.resolve()
|
|
2621
2598
|
.then(() =>
|
|
2622
|
-
deps.sendUserMessage(`/${TELEGRAM_INTERNAL_COMMAND_NAME}`, {
|
|
2599
|
+
deps.sendUserMessage(`/${TELEGRAM_INTERNAL_COMMAND_NAME} ${token}`, {
|
|
2623
2600
|
expandPromptTemplates: true,
|
|
2624
2601
|
}),
|
|
2625
2602
|
)
|
|
@@ -871,6 +871,7 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
871
871
|
storeModelMenuState: modelMenuRuntime.storeState,
|
|
872
872
|
updateStatusMessage: menuActions.updateStatusMessage,
|
|
873
873
|
updateStatus,
|
|
874
|
+
dismissGuestPlaceholder: guestPlaceholderRuntime.dismiss,
|
|
874
875
|
});
|
|
875
876
|
const threadDisplaySettingsRuntime =
|
|
876
877
|
ThreadDisplay.createTelegramThreadDisplaySettingsRuntime({
|
|
@@ -1731,14 +1732,6 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
1731
1732
|
if (!record?.target.threadId) return undefined;
|
|
1732
1733
|
return record.threadName ?? "current Telegram thread";
|
|
1733
1734
|
},
|
|
1734
|
-
setRequestedThreadNameForPollingStart:
|
|
1735
|
-
telegramThreadCapabilityState.setRequestedThreadName,
|
|
1736
|
-
validateThreadName(threadName) {
|
|
1737
|
-
return Threads.getTelegramTopicThreadNameValidationError(
|
|
1738
|
-
threadName,
|
|
1739
|
-
undefined,
|
|
1740
|
-
);
|
|
1741
|
-
},
|
|
1742
1735
|
onTransportChanged() {
|
|
1743
1736
|
deliveryLifecycleRuntime.onSessionStart();
|
|
1744
1737
|
activityVerbosityRuntime.reset();
|
|
@@ -31,6 +31,8 @@ type TelegramQueueMenuReplyMarkup = TelegramInlineKeyboardMarkup;
|
|
|
31
31
|
interface TelegramQueueMenuItem {
|
|
32
32
|
chatId: number;
|
|
33
33
|
replyToMessageId: number;
|
|
34
|
+
queueOrder: number;
|
|
35
|
+
isGuest: boolean;
|
|
34
36
|
queuePosition: number;
|
|
35
37
|
isPriority: boolean;
|
|
36
38
|
priorityEmoji?: string;
|
|
@@ -60,6 +62,8 @@ function toTelegramQueueMenuItems<Context>(
|
|
|
60
62
|
return {
|
|
61
63
|
chatId: item.chatId,
|
|
62
64
|
replyToMessageId: item.replyToMessageId,
|
|
65
|
+
queueOrder: item.queueOrder,
|
|
66
|
+
isGuest: item.kind === "prompt" && item.guestQueryId !== undefined,
|
|
63
67
|
queuePosition: index + 1,
|
|
64
68
|
isPriority: item.queueLane === "priority",
|
|
65
69
|
priorityEmoji: item.kind === "prompt" ? item.priorityEmoji : undefined,
|
|
@@ -106,7 +110,9 @@ function buildTelegramQueueMenuReplyMarkup(
|
|
|
106
110
|
return [
|
|
107
111
|
{
|
|
108
112
|
text: label,
|
|
109
|
-
callback_data:
|
|
113
|
+
callback_data: item.isGuest
|
|
114
|
+
? `queue:guest-pick:${item.queueOrder}`
|
|
115
|
+
: `queue:pick:${item.chatId}:${item.replyToMessageId}`,
|
|
110
116
|
},
|
|
111
117
|
];
|
|
112
118
|
});
|
|
@@ -178,6 +184,22 @@ function getTelegramQueueMenuItemText(item: TelegramQueueMenuItem): string {
|
|
|
178
184
|
return `${heading}\n${preview}`;
|
|
179
185
|
}
|
|
180
186
|
|
|
187
|
+
function buildTelegramGuestQueueItemSubmenuReplyMarkup(
|
|
188
|
+
queueOrder: number,
|
|
189
|
+
): TelegramQueueMenuReplyMarkup {
|
|
190
|
+
return {
|
|
191
|
+
inline_keyboard: [
|
|
192
|
+
[{ text: "⬆️ Back", callback_data: "queue:list" }],
|
|
193
|
+
[
|
|
194
|
+
{
|
|
195
|
+
text: "🔴 Skip",
|
|
196
|
+
callback_data: `queue:guest-skip:${queueOrder}`,
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
],
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
181
203
|
function buildTelegramQueueItemSubmenuReplyMarkup(
|
|
182
204
|
chatId: number,
|
|
183
205
|
replyToMessageId: number,
|
|
@@ -217,6 +239,8 @@ interface TelegramQueueMenuCallbackDeps<Context = unknown> {
|
|
|
217
239
|
chatId: number,
|
|
218
240
|
replyToMessageId: number,
|
|
219
241
|
) => TelegramQueueMenuItem | undefined;
|
|
242
|
+
findGuestItem: (queueOrder: number) => TelegramQueueMenuItem | undefined;
|
|
243
|
+
skipGuest: (queueOrder: number, ctx: Context) => Promise<boolean>;
|
|
220
244
|
togglePriority: (chatId: number, replyToMessageId: number) => boolean;
|
|
221
245
|
setPriority: (
|
|
222
246
|
chatId: number,
|
|
@@ -275,6 +299,38 @@ async function handleTelegramQueueMenuCallback<Context>(
|
|
|
275
299
|
);
|
|
276
300
|
return true;
|
|
277
301
|
}
|
|
302
|
+
const guestPickMatch = data.match(/^queue:guest-pick:(\d+)$/);
|
|
303
|
+
if (guestPickMatch) {
|
|
304
|
+
await handleTelegramGuestQueueMenuPick(
|
|
305
|
+
callbackQueryId,
|
|
306
|
+
replyChatId,
|
|
307
|
+
replyMessageId,
|
|
308
|
+
Number(guestPickMatch[1]),
|
|
309
|
+
deps,
|
|
310
|
+
);
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
const guestSkipMatch = data.match(/^queue:guest-skip:(\d+)$/);
|
|
314
|
+
if (guestSkipMatch) {
|
|
315
|
+
const skipped = await deps.skipGuest(Number(guestSkipMatch[1]), ctx);
|
|
316
|
+
if (!skipped) {
|
|
317
|
+
await refreshStaleTelegramQueueMenuItem(
|
|
318
|
+
callbackQueryId,
|
|
319
|
+
replyChatId,
|
|
320
|
+
replyMessageId,
|
|
321
|
+
deps,
|
|
322
|
+
);
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
await updateTelegramQueueMenuList(
|
|
326
|
+
callbackQueryId,
|
|
327
|
+
replyChatId,
|
|
328
|
+
replyMessageId,
|
|
329
|
+
deps,
|
|
330
|
+
"Guest prompt skipped.",
|
|
331
|
+
);
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
278
334
|
const pickMatch = data.match(/^queue:pick:(\d+):(\d+)$/);
|
|
279
335
|
if (pickMatch) {
|
|
280
336
|
await handleTelegramQueueMenuPick(
|
|
@@ -379,6 +435,31 @@ async function refreshStaleTelegramQueueMenuItem<Context>(
|
|
|
379
435
|
);
|
|
380
436
|
}
|
|
381
437
|
|
|
438
|
+
async function handleTelegramGuestQueueMenuPick<Context>(
|
|
439
|
+
callbackQueryId: string,
|
|
440
|
+
replyChatId: number,
|
|
441
|
+
replyMessageId: number,
|
|
442
|
+
queueOrder: number,
|
|
443
|
+
deps: TelegramQueueMenuCallbackDeps<Context>,
|
|
444
|
+
): Promise<void> {
|
|
445
|
+
const item = deps.findGuestItem(queueOrder);
|
|
446
|
+
if (!item) {
|
|
447
|
+
return refreshStaleTelegramQueueMenuItem(
|
|
448
|
+
callbackQueryId,
|
|
449
|
+
replyChatId,
|
|
450
|
+
replyMessageId,
|
|
451
|
+
deps,
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
await deps.updateQueueMessage(
|
|
455
|
+
replyChatId,
|
|
456
|
+
replyMessageId,
|
|
457
|
+
getTelegramQueueMenuItemText(item),
|
|
458
|
+
buildTelegramGuestQueueItemSubmenuReplyMarkup(queueOrder),
|
|
459
|
+
);
|
|
460
|
+
await deps.answerCallbackQuery(callbackQueryId);
|
|
461
|
+
}
|
|
462
|
+
|
|
382
463
|
async function handleTelegramQueueMenuPick<Context>(
|
|
383
464
|
callbackQueryId: string,
|
|
384
465
|
replyChatId: number,
|
|
@@ -606,6 +687,7 @@ export function createTelegramQueueMenuRuntime<
|
|
|
606
687
|
ctx: Context,
|
|
607
688
|
) => Promise<void>;
|
|
608
689
|
updateStatus: (ctx: Context) => void;
|
|
690
|
+
dismissGuestPlaceholder?: (inlineMessageId: string) => Promise<void>;
|
|
609
691
|
}): TelegramQueueMenuRuntime<Context> {
|
|
610
692
|
const sendQueueMenuMessage = createQueueMenuSendMessageAdapter(
|
|
611
693
|
deps.sendInteractiveMessage,
|
|
@@ -628,6 +710,7 @@ export function createTelegramQueueMenuRuntime<
|
|
|
628
710
|
updateStatusMessage: deps.updateStatusMessage,
|
|
629
711
|
answerCallbackQuery: deps.answerCallbackQuery,
|
|
630
712
|
updateStatus: deps.updateStatus,
|
|
713
|
+
dismissGuestPlaceholder: deps.dismissGuestPlaceholder,
|
|
631
714
|
}),
|
|
632
715
|
};
|
|
633
716
|
}
|
|
@@ -695,6 +778,7 @@ function createQueueMenuCallbackHandler<
|
|
|
695
778
|
text?: string,
|
|
696
779
|
) => Promise<void>;
|
|
697
780
|
updateStatus: (ctx: Context) => void;
|
|
781
|
+
dismissGuestPlaceholder?: (inlineMessageId: string) => Promise<void>;
|
|
698
782
|
}) {
|
|
699
783
|
return async (
|
|
700
784
|
query: TelegramQueueMenuCallbackQuery,
|
|
@@ -737,6 +821,11 @@ function createQueueMenuCallbackHandler<
|
|
|
737
821
|
const findItem = (cId: number, rId: number) => {
|
|
738
822
|
return findTelegramQueueMenuItem(toMenuItems(), cId, rId);
|
|
739
823
|
};
|
|
824
|
+
const findGuestItem = (queueOrder: number) => {
|
|
825
|
+
return toMenuItems().find((item) => {
|
|
826
|
+
return item.isGuest && item.queueOrder === queueOrder;
|
|
827
|
+
});
|
|
828
|
+
};
|
|
740
829
|
return handleTelegramQueueMenuCallback(
|
|
741
830
|
query.id,
|
|
742
831
|
data,
|
|
@@ -746,6 +835,14 @@ function createQueueMenuCallbackHandler<
|
|
|
746
835
|
{
|
|
747
836
|
getQueuedItems: toMenuItems,
|
|
748
837
|
findItem,
|
|
838
|
+
findGuestItem,
|
|
839
|
+
skipGuest: (queueOrder, callbackContext) => {
|
|
840
|
+
return skipQueuedTelegramGuestPrompt(queueOrder, callbackContext, {
|
|
841
|
+
getQueueSnapshot,
|
|
842
|
+
queueMutationRuntime: deps.queueMutationRuntime,
|
|
843
|
+
dismissGuestPlaceholder: deps.dismissGuestPlaceholder,
|
|
844
|
+
});
|
|
845
|
+
},
|
|
749
846
|
togglePriority: (cId, rId) => {
|
|
750
847
|
return toggleQueuedTelegramPromptPriority(cId, rId, ctx, {
|
|
751
848
|
getQueueSnapshot,
|
|
@@ -772,6 +869,34 @@ function createQueueMenuCallbackHandler<
|
|
|
772
869
|
};
|
|
773
870
|
}
|
|
774
871
|
|
|
872
|
+
async function skipQueuedTelegramGuestPrompt<Context>(
|
|
873
|
+
queueOrder: number,
|
|
874
|
+
ctx: Context,
|
|
875
|
+
deps: {
|
|
876
|
+
getQueueSnapshot: () => Queue.TelegramQueueItem<Context>[];
|
|
877
|
+
queueMutationRuntime: Queue.TelegramQueueMutationController<Context>;
|
|
878
|
+
dismissGuestPlaceholder?: (inlineMessageId: string) => Promise<void>;
|
|
879
|
+
},
|
|
880
|
+
): Promise<boolean> {
|
|
881
|
+
const item = deps.getQueueSnapshot().find((candidate) => {
|
|
882
|
+
return candidate.kind === "prompt" &&
|
|
883
|
+
candidate.guestQueryId !== undefined &&
|
|
884
|
+
candidate.queueOrder === queueOrder;
|
|
885
|
+
});
|
|
886
|
+
if (!item || !deps.queueMutationRuntime.removeGuestPromptByQueueOrder) {
|
|
887
|
+
return false;
|
|
888
|
+
}
|
|
889
|
+
const removed = deps.queueMutationRuntime.removeGuestPromptByQueueOrder(
|
|
890
|
+
queueOrder,
|
|
891
|
+
ctx,
|
|
892
|
+
);
|
|
893
|
+
if (!removed) return false;
|
|
894
|
+
if (item.guestInlineMessageId && deps.dismissGuestPlaceholder) {
|
|
895
|
+
await deps.dismissGuestPlaceholder(item.guestInlineMessageId);
|
|
896
|
+
}
|
|
897
|
+
return true;
|
|
898
|
+
}
|
|
899
|
+
|
|
775
900
|
function getQueueMenuReactionDisposition<Context>(
|
|
776
901
|
item: Queue.TelegramQueueItem<Context>,
|
|
777
902
|
priority: boolean,
|
|
@@ -922,6 +922,28 @@ export function removeTelegramQueueItemsByMessageIds<TContext = unknown>(
|
|
|
922
922
|
};
|
|
923
923
|
}
|
|
924
924
|
|
|
925
|
+
export function removeTelegramQueuedGuestPromptByOrder<TContext = unknown>(
|
|
926
|
+
items: TelegramQueueItem<TContext>[],
|
|
927
|
+
queueOrder: number,
|
|
928
|
+
): {
|
|
929
|
+
items: TelegramQueueItem<TContext>[];
|
|
930
|
+
removedItems: PendingTelegramTurn[];
|
|
931
|
+
removedCount: number;
|
|
932
|
+
} {
|
|
933
|
+
const index = items.findIndex((item) => {
|
|
934
|
+
return isPendingTelegramTurn(item) &&
|
|
935
|
+
item.guestQueryId !== undefined &&
|
|
936
|
+
item.queueOrder === queueOrder;
|
|
937
|
+
});
|
|
938
|
+
if (index < 0) return { items, removedItems: [], removedCount: 0 };
|
|
939
|
+
const removedItem = items[index] as PendingTelegramTurn;
|
|
940
|
+
return {
|
|
941
|
+
items: [...items.slice(0, index), ...items.slice(index + 1)],
|
|
942
|
+
removedItems: [removedItem],
|
|
943
|
+
removedCount: 1,
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
|
|
925
947
|
export function applyTelegramQueuePromptReactionDisposition<
|
|
926
948
|
TContext = unknown,
|
|
927
949
|
>(
|
|
@@ -2331,6 +2353,10 @@ export interface TelegramQueueMutationController<TContext> {
|
|
|
2331
2353
|
ctx: TContext,
|
|
2332
2354
|
scope?: TelegramQueueMessageScope,
|
|
2333
2355
|
) => number;
|
|
2356
|
+
removeGuestPromptByQueueOrder?: (
|
|
2357
|
+
queueOrder: number,
|
|
2358
|
+
ctx: TContext,
|
|
2359
|
+
) => boolean;
|
|
2334
2360
|
applyReactionByMessageId: (
|
|
2335
2361
|
messageId: number,
|
|
2336
2362
|
disposition: TelegramQueueReactionDisposition,
|
|
@@ -2604,6 +2630,11 @@ export function createTelegramQueueMutationController<TContext>(
|
|
|
2604
2630
|
buildRuntimeDeps(ctx),
|
|
2605
2631
|
scope,
|
|
2606
2632
|
),
|
|
2633
|
+
removeGuestPromptByQueueOrder: (queueOrder, ctx) =>
|
|
2634
|
+
removeTelegramQueuedGuestPromptByOrderRuntime(
|
|
2635
|
+
queueOrder,
|
|
2636
|
+
buildRuntimeDeps(ctx),
|
|
2637
|
+
),
|
|
2607
2638
|
applyReactionByMessageId: (messageId, disposition, ctx, scope) =>
|
|
2608
2639
|
applyTelegramQueuePromptReactionDispositionRuntime(
|
|
2609
2640
|
messageId,
|
|
@@ -2684,6 +2715,21 @@ export function removeTelegramQueueItemsByMessageIdsRuntime<TContext>(
|
|
|
2684
2715
|
return removedCount;
|
|
2685
2716
|
}
|
|
2686
2717
|
|
|
2718
|
+
export function removeTelegramQueuedGuestPromptByOrderRuntime<TContext>(
|
|
2719
|
+
queueOrder: number,
|
|
2720
|
+
deps: TelegramQueueMutationRuntimeDeps<TContext>,
|
|
2721
|
+
): boolean {
|
|
2722
|
+
const { items, removedItems, removedCount } =
|
|
2723
|
+
removeTelegramQueuedGuestPromptByOrder(deps.getQueuedItems(), queueOrder);
|
|
2724
|
+
if (removedCount === 0) return false;
|
|
2725
|
+
// A menu Skip means permanent discard, so settle durable admission before
|
|
2726
|
+
// removing the live item. A failed settlement keeps the prompt retryable.
|
|
2727
|
+
deps.onItemsDiscarded?.(removedItems, deps.ctx);
|
|
2728
|
+
deps.setQueuedItems(items);
|
|
2729
|
+
updateTelegramQueueStatusRuntime(deps);
|
|
2730
|
+
return true;
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2687
2733
|
export function applyTelegramQueuePromptReactionDispositionRuntime<TContext>(
|
|
2688
2734
|
messageId: number,
|
|
2689
2735
|
disposition: TelegramQueueReactionDisposition,
|
|
@@ -1018,6 +1018,10 @@ export const TELEGRAM_GUEST_PLACEHOLDER_FRAMES = [
|
|
|
1018
1018
|
"<b>🌏 Working on it...</b>",
|
|
1019
1019
|
] as const;
|
|
1020
1020
|
|
|
1021
|
+
// Telegram does not expose deletion for inline messages. This non-printing,
|
|
1022
|
+
// non-empty edit visually clears a guest placeholder after its query is skipped.
|
|
1023
|
+
export const TELEGRAM_DISMISSED_GUEST_PLACEHOLDER_TEXT = "\u2063";
|
|
1024
|
+
|
|
1021
1025
|
export function buildTelegramGuestPlaceholderFrame(step: number): string {
|
|
1022
1026
|
const frames: readonly string[] = TELEGRAM_GUEST_PLACEHOLDER_FRAMES;
|
|
1023
1027
|
const index = ((step % frames.length) + frames.length) % frames.length;
|
|
@@ -1052,6 +1056,8 @@ export interface TelegramGuestPlaceholderRuntime {
|
|
|
1052
1056
|
stop: (inlineMessageId: string) => Promise<void>;
|
|
1053
1057
|
/** Cancels every loop without waiting for in-flight edits (session shutdown). */
|
|
1054
1058
|
stopAll: () => void;
|
|
1059
|
+
/** Stops rotation and visually clears the inline placeholder. */
|
|
1060
|
+
dismiss: (inlineMessageId: string) => Promise<void>;
|
|
1055
1061
|
}
|
|
1056
1062
|
|
|
1057
1063
|
interface TelegramGuestPlaceholderSession {
|
|
@@ -1202,5 +1208,18 @@ export function createTelegramGuestPlaceholderRuntime(
|
|
|
1202
1208
|
}
|
|
1203
1209
|
sessions.clear();
|
|
1204
1210
|
},
|
|
1211
|
+
async dismiss(inlineMessageId) {
|
|
1212
|
+
await stop(inlineMessageId);
|
|
1213
|
+
try {
|
|
1214
|
+
await deps.editGuestInlineMessage(inlineMessageId, {
|
|
1215
|
+
text: TELEGRAM_DISMISSED_GUEST_PLACEHOLDER_TEXT,
|
|
1216
|
+
parseMode: "HTML",
|
|
1217
|
+
});
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
deps.recordRuntimeEvent?.("guest", error, {
|
|
1220
|
+
phase: "guest-placeholder-dismiss",
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
},
|
|
1205
1224
|
};
|
|
1206
1225
|
}
|
|
@@ -684,7 +684,14 @@ export async function ensureTelegramLeaderThreadBinding(
|
|
|
684
684
|
assertLeaderEpoch("before-workspace-persist");
|
|
685
685
|
await deps.topicTargetStore.persist();
|
|
686
686
|
assertLeaderEpoch("after-workspace-persist");
|
|
687
|
-
|
|
687
|
+
const { target: _target, slot: _slot, threadName: _threadName, displayTitle: _displayTitle, ...rest } = result;
|
|
688
|
+
return {
|
|
689
|
+
...rest,
|
|
690
|
+
target: { ...committed.target },
|
|
691
|
+
slot: committed.slot ?? result.slot,
|
|
692
|
+
...(committed.threadName ? { threadName: committed.threadName } : {}),
|
|
693
|
+
...(committed.displayTitle ? { displayTitle: committed.displayTitle } : {}),
|
|
694
|
+
};
|
|
688
695
|
};
|
|
689
696
|
try {
|
|
690
697
|
const unavailableTargetKeys = new Set([
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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.50.
|
|
47
|
+
"@llblab/pi-state-flow": "0.17.2",
|
|
48
|
+
"@llblab/pi-telegram": "0.50.1",
|
|
49
49
|
"@llblab/skills": "1.15.0"
|
|
50
50
|
},
|
|
51
51
|
"bundledDependencies": [
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { type ArtifactSourceIdentity } from "./artifact.ts";
|
|
2
|
-
/** Opaque source metadata discovered without decoding or retaining Markdown bodies. */
|
|
3
|
-
export interface ArtifactSourceCandidate extends ArtifactSourceIdentity {
|
|
4
|
-
/** Raw byte count used as a conservative maintenance token-budget ceiling. */
|
|
5
|
-
bytes: number;
|
|
6
|
-
}
|
|
7
|
-
export interface GlobalMarkdownDiscoveryResult {
|
|
8
|
-
sources: ArtifactSourceCandidate[];
|
|
9
|
-
removed: string[];
|
|
10
|
-
unavailable?: string;
|
|
11
|
-
}
|
|
12
|
-
export declare function getKnowledgeRoot(agentDir?: string): string;
|
|
13
|
-
/** Discover regular `*.md` files beneath a Knowledge root without following directory or file symlinks. */
|
|
14
|
-
export declare function discoverGlobalMarkdownSources(knowledgeRoot?: string): ArtifactSourceCandidate[];
|
|
15
|
-
/** Source-owner discovery; retained paths let restart/status re-observe removals until publication. */
|
|
16
|
-
export declare class GlobalMarkdownDiscovery {
|
|
17
|
-
#private;
|
|
18
|
-
readonly knowledgeRoot: string;
|
|
19
|
-
constructor(knowledgeRoot?: string);
|
|
20
|
-
refresh(retainedPaths?: Iterable<string>): GlobalMarkdownDiscoveryResult;
|
|
21
|
-
}
|