@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
|
@@ -77,6 +77,7 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
77
77
|
getCommands,
|
|
78
78
|
getThinkingLevel,
|
|
79
79
|
sendUserMessage,
|
|
80
|
+
registerCommand,
|
|
80
81
|
setActiveTools,
|
|
81
82
|
setModel,
|
|
82
83
|
setThinkingLevel,
|
|
@@ -237,6 +238,26 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
237
238
|
canReset: lockRuntime.owns,
|
|
238
239
|
commitReset: lockRuntime.commitIfOwned,
|
|
239
240
|
});
|
|
241
|
+
const sessionActionAssembly = Commands.createTelegramSessionActionAssembly({
|
|
242
|
+
registerCommand,
|
|
243
|
+
sendUserMessage,
|
|
244
|
+
store: threadStore,
|
|
245
|
+
getProfileName: configStore.getActiveProfileName,
|
|
246
|
+
ownsPersistence: lockRuntime.owns,
|
|
247
|
+
async sendResult(target, html) {
|
|
248
|
+
const delivery = await Delivery.sendTelegramView(
|
|
249
|
+
{ text: html, parseMode: "html", replyMarkup: { inline_keyboard: [] } },
|
|
250
|
+
{ scope: { kind: "target", target } },
|
|
251
|
+
);
|
|
252
|
+
return delivery.ok ? { ok: true } : { ok: false,
|
|
253
|
+
retryable: delivery.reason === "runtime-unavailable" ||
|
|
254
|
+
delivery.reason === "target-unavailable" ||
|
|
255
|
+
delivery.reason === "transport-retryable" };
|
|
256
|
+
},
|
|
257
|
+
handoffTtlMs: Threads.TELEGRAM_LEADER_SESSION_HANDOFF_TTL_MS,
|
|
258
|
+
recordRuntimeEvent,
|
|
259
|
+
});
|
|
260
|
+
const sessionActionsRuntime = sessionActionAssembly.action;
|
|
240
261
|
const lockOwnershipGuard =
|
|
241
262
|
Locks.createTelegramLockOwnershipGuard(lockRuntime);
|
|
242
263
|
const getCurrentLeaderEpoch = lockRuntime.getOwnedLeaderEpoch;
|
|
@@ -851,6 +872,24 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
851
872
|
updateStatusMessage: menuActions.updateStatusMessage,
|
|
852
873
|
updateStatus,
|
|
853
874
|
});
|
|
875
|
+
const threadDisplaySettingsRuntime =
|
|
876
|
+
ThreadDisplay.createTelegramThreadDisplaySettingsRuntime({
|
|
877
|
+
getTarget() {
|
|
878
|
+
return telegramBusFollowerRegistrationState.getTarget() ??
|
|
879
|
+
telegramBusLeaderState.getTarget();
|
|
880
|
+
},
|
|
881
|
+
getBinding(target) { return threadStore.getWorkspaceBindingByTarget(target); },
|
|
882
|
+
apply(mode) {
|
|
883
|
+
return ThreadDisplay.applyTelegramThreadDisplaySetting(mode, {
|
|
884
|
+
getProfileKey: configStore.getActiveProfileName,
|
|
885
|
+
ownsLeader() { return getCurrentLeaderEpoch() !== undefined; },
|
|
886
|
+
getLeaderSetter() { return telegramBusLeaderRuntime.setThreadDisplayMode; },
|
|
887
|
+
getFollowerSetter() { return telegramBusFollowerRegistration.setThreadDisplayMode; },
|
|
888
|
+
reloadConfig: configStore.load,
|
|
889
|
+
});
|
|
890
|
+
},
|
|
891
|
+
reset(target) { return telegramThreadDisplayNameResetBinding.reset(target); },
|
|
892
|
+
});
|
|
854
893
|
const settingsMenuRuntime = MenuSettings.createTelegramSettingsMenuRuntime(
|
|
855
894
|
{
|
|
856
895
|
reloadConfig: configStore.load,
|
|
@@ -866,16 +905,10 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
866
905
|
return threadStore.getBotState().threadMode === "enabled"
|
|
867
906
|
? Config.resolveTelegramThreadDisplayMode(configStore.get()) : undefined;
|
|
868
907
|
},
|
|
908
|
+
isThreadDisplayCustom: threadDisplaySettingsRuntime.isCustom,
|
|
869
909
|
async setThreadDisplayMode(mode) {
|
|
870
|
-
try {
|
|
871
|
-
|
|
872
|
-
getProfileKey: configStore.getActiveProfileName,
|
|
873
|
-
ownsLeader() { return getCurrentLeaderEpoch() !== undefined; },
|
|
874
|
-
getLeaderSetter() { return telegramBusLeaderRuntime.setThreadDisplayMode; },
|
|
875
|
-
getFollowerSetter() { return telegramBusFollowerRegistration.setThreadDisplayMode; },
|
|
876
|
-
reloadConfig: configStore.load,
|
|
877
|
-
});
|
|
878
|
-
} catch (error) {
|
|
910
|
+
try { await threadDisplaySettingsRuntime.setMode(mode); }
|
|
911
|
+
catch (error) {
|
|
879
912
|
recordRuntimeEvent("bus", error, { phase: "thread-display-setting" });
|
|
880
913
|
throw error;
|
|
881
914
|
}
|
|
@@ -959,6 +992,36 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
959
992
|
foreignOwnedUpdateForwarder,
|
|
960
993
|
replaceFollowerThreadTarget: restoreFollowerThreadTarget,
|
|
961
994
|
bridgeRuntime,
|
|
995
|
+
requestNewSession(source) {
|
|
996
|
+
const updateId = Updates.getTelegramUpdateExecutionFence(source)?.updateId;
|
|
997
|
+
if (updateId === undefined) {
|
|
998
|
+
throw new Error("Telegram session replacement requires durable update authority.");
|
|
999
|
+
}
|
|
1000
|
+
const callbackMessage = source && typeof source === "object" && "message" in source
|
|
1001
|
+
? (source as { message?: unknown }).message
|
|
1002
|
+
: source;
|
|
1003
|
+
const messageTarget = callbackMessage as {
|
|
1004
|
+
chat?: { id?: unknown };
|
|
1005
|
+
message_id?: unknown;
|
|
1006
|
+
message_thread_id?: unknown;
|
|
1007
|
+
} | undefined;
|
|
1008
|
+
const target = typeof messageTarget?.chat?.id === "number" &&
|
|
1009
|
+
typeof messageTarget.message_id === "number"
|
|
1010
|
+
? {
|
|
1011
|
+
chatId: messageTarget.chat.id,
|
|
1012
|
+
messageId: messageTarget.message_id,
|
|
1013
|
+
...(typeof messageTarget.message_thread_id === "number"
|
|
1014
|
+
? { threadId: messageTarget.message_thread_id }
|
|
1015
|
+
: {}),
|
|
1016
|
+
}
|
|
1017
|
+
: undefined;
|
|
1018
|
+
if (!target) {
|
|
1019
|
+
throw new Error("Telegram session replacement target is unavailable.");
|
|
1020
|
+
}
|
|
1021
|
+
if (!sessionActionsRuntime.scheduleAfterUpdate(updateId, target)) {
|
|
1022
|
+
throw new Error("A Telegram session replacement is already pending.");
|
|
1023
|
+
}
|
|
1024
|
+
},
|
|
962
1025
|
activeTurnRuntime,
|
|
963
1026
|
mediaGroupRuntime,
|
|
964
1027
|
textGroupRuntime,
|
|
@@ -1066,6 +1129,7 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
1066
1129
|
dispatchNext: dispatchNextQueuedTelegramTurn,
|
|
1067
1130
|
requestQueueHandoffReconciliation:
|
|
1068
1131
|
queueHandoffReconciliationBinding.request,
|
|
1132
|
+
afterUpdateCompleted: sessionActionsRuntime.onUpdateCompleted,
|
|
1069
1133
|
},
|
|
1070
1134
|
worker: {
|
|
1071
1135
|
defaultHandle: inboundRouteRuntime.handleUpdate,
|
|
@@ -1638,6 +1702,7 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
1638
1702
|
}
|
|
1639
1703
|
},
|
|
1640
1704
|
}.reset);
|
|
1705
|
+
sessionActionsRuntime.register();
|
|
1641
1706
|
Bindings.registerTelegramCommandsAndTools({
|
|
1642
1707
|
pi,
|
|
1643
1708
|
agentDir: Paths.resolveAgentDir(),
|
|
@@ -1840,6 +1905,9 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
1840
1905
|
shutdownGenerativeAppLiveSurfaces: generativeAppLiveSurfaceBinding.shutdown,
|
|
1841
1906
|
resolveAutomaticThreadCleanupEnabled:
|
|
1842
1907
|
configControls.resolveAutomaticThreadCleanupEnabled,
|
|
1908
|
+
onSessionStarted(_event, ctx) {
|
|
1909
|
+
sessionActionAssembly.settlement.onSessionStart(ctx);
|
|
1910
|
+
},
|
|
1843
1911
|
buttonActionStore,
|
|
1844
1912
|
callMultipart,
|
|
1845
1913
|
sendChatAction,
|
|
@@ -23,6 +23,7 @@ export type TelegramSettingsMenuReplyMarkup = TelegramInlineKeyboardMarkup;
|
|
|
23
23
|
|
|
24
24
|
export interface TelegramSettingsStateDeps {
|
|
25
25
|
getThreadDisplayMode?: () => TelegramThreadDisplayMode | undefined;
|
|
26
|
+
isThreadDisplayCustom?: () => boolean;
|
|
26
27
|
areDraftPreviewsEnabled: () => boolean;
|
|
27
28
|
getAssistantRenderingMode: () => TelegramAssistantRenderingMode;
|
|
28
29
|
getActivityVerbosity: () => TelegramActivityVerbosity;
|
|
@@ -177,12 +178,15 @@ export function buildTelegramSettingsMenuText(): string {
|
|
|
177
178
|
|
|
178
179
|
export function buildThreadDisplaySettingsText(
|
|
179
180
|
mode: TelegramThreadDisplayMode,
|
|
181
|
+
custom = false,
|
|
180
182
|
): string {
|
|
181
183
|
return [
|
|
182
|
-
`${THREAD_DISPLAY_SETTINGS_TITLE} <code>${threadDisplayModeLabel(mode)}</code>`,
|
|
184
|
+
`${THREAD_DISPLAY_SETTINGS_TITLE} <code>${custom ? "custom" : threadDisplayModeLabel(mode)}</code>`,
|
|
183
185
|
"",
|
|
184
186
|
"Choose how this bot profile labels Telegram tabs and Pi terminal status. Each slot is unique across this bot profile.",
|
|
185
187
|
"",
|
|
188
|
+
"Set a manual name for the current Thread with /name <code>Name</code>.",
|
|
189
|
+
"",
|
|
186
190
|
"<code>-</code> <code>letters</code> (default): show the unique slot, such as <b><i>A</i></b> or <b><i>B</i></b>.",
|
|
187
191
|
"<code>-</code> <code>names</code>: show the generated dictionary name for the slot, such as <b><i>Anchor</i></b> or <b><i>Briar</i></b>.",
|
|
188
192
|
"<code>-</code> <code>directory-title</code>: humanize the distinguishing directory path, such as <b><i>Api Tools</i></b> or <b><i>Frontend / Extensions A</i></b>.",
|
|
@@ -311,6 +315,7 @@ export function buildTelegramSettingsMenuReplyMarkup(
|
|
|
311
315
|
automaticThreadCleanupEnabled = true,
|
|
312
316
|
activityVerbosity: TelegramActivityVerbosity = "quiet",
|
|
313
317
|
threadDisplayMode?: TelegramThreadDisplayMode,
|
|
318
|
+
threadDisplayCustom = false,
|
|
314
319
|
): TelegramSettingsMenuReplyMarkup {
|
|
315
320
|
const hasRenderingMode =
|
|
316
321
|
assistantRenderingModeOrVoiceReplyMode === "rich" ||
|
|
@@ -364,15 +369,17 @@ export function buildTelegramSettingsMenuReplyMarkup(
|
|
|
364
369
|
text: `🕒 Time injection: ${getTelegramSettingsStateValueLabel(timeInjectionMode)}`,
|
|
365
370
|
callback_data: "settings:open:time-injection",
|
|
366
371
|
},
|
|
372
|
+
];
|
|
373
|
+
if (threadDisplayMode) settingsButtons.push(
|
|
367
374
|
{
|
|
368
375
|
text: `🧹 Thread cleanup: ${automaticThreadCleanupEnabled ? "on" : "off"}`,
|
|
369
376
|
callback_data: "settings:open:automatic-thread-cleanup",
|
|
370
377
|
},
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
378
|
+
{
|
|
379
|
+
text: `🧵 Thread display: ${threadDisplayCustom ? "custom" : threadDisplayMode}`,
|
|
380
|
+
callback_data: "settings:open:thread-display",
|
|
381
|
+
},
|
|
382
|
+
);
|
|
376
383
|
if (sectionRegistry) {
|
|
377
384
|
const extensionRows = getTelegramExtensionSettingsRows(sectionRegistry);
|
|
378
385
|
settingsButtons.push(
|
|
@@ -406,6 +413,7 @@ export async function openTelegramSettingsMenu<
|
|
|
406
413
|
deps.isAutomaticThreadCleanupEnabled(),
|
|
407
414
|
deps.getActivityVerbosity(),
|
|
408
415
|
deps.getThreadDisplayMode?.(),
|
|
416
|
+
deps.isThreadDisplayCustom?.() ?? false,
|
|
409
417
|
),
|
|
410
418
|
);
|
|
411
419
|
if (messageId === undefined) return;
|
|
@@ -424,11 +432,14 @@ function threadDisplayModeLabel(mode: TelegramThreadDisplayMode): string {
|
|
|
424
432
|
}
|
|
425
433
|
}
|
|
426
434
|
|
|
427
|
-
export function buildThreadDisplaySettingsReplyMarkup(
|
|
435
|
+
export function buildThreadDisplaySettingsReplyMarkup(
|
|
436
|
+
mode: TelegramThreadDisplayMode,
|
|
437
|
+
custom = false,
|
|
438
|
+
): TelegramSettingsMenuReplyMarkup {
|
|
428
439
|
return { inline_keyboard: [
|
|
429
440
|
[{ text: "⬆️ Back", callback_data: "settings:list" }],
|
|
430
441
|
...(["letters", "names", "directory-title", "directory-snake"] as const).map((value) => [{
|
|
431
|
-
text: `${mode === value ? "🟢 " : ""}${threadDisplayModeLabel(value)}`,
|
|
442
|
+
text: `${!custom && mode === value ? "🟢 " : ""}${threadDisplayModeLabel(value)}`,
|
|
432
443
|
callback_data: `settings:set:thread-display:${value}`,
|
|
433
444
|
}]),
|
|
434
445
|
] };
|
|
@@ -565,6 +576,7 @@ export async function updateTelegramSettingsMenuMessage(
|
|
|
565
576
|
deps.isAutomaticThreadCleanupEnabled(),
|
|
566
577
|
deps.getActivityVerbosity(),
|
|
567
578
|
deps.getThreadDisplayMode?.(),
|
|
579
|
+
deps.isThreadDisplayCustom?.() ?? false,
|
|
568
580
|
),
|
|
569
581
|
);
|
|
570
582
|
}
|
|
@@ -661,8 +673,8 @@ export async function handleTelegramSettingsMenuCallbackAction(
|
|
|
661
673
|
return true;
|
|
662
674
|
}
|
|
663
675
|
await deps.updateSettingsMessage(
|
|
664
|
-
buildThreadDisplaySettingsText(mode),
|
|
665
|
-
buildThreadDisplaySettingsReplyMarkup(mode),
|
|
676
|
+
buildThreadDisplaySettingsText(mode, deps.isThreadDisplayCustom?.() ?? false),
|
|
677
|
+
buildThreadDisplaySettingsReplyMarkup(mode, deps.isThreadDisplayCustom?.() ?? false),
|
|
666
678
|
);
|
|
667
679
|
await deps.answerCallbackQuery(callbackQueryId);
|
|
668
680
|
return true;
|
|
@@ -877,6 +889,7 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
877
889
|
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
878
890
|
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
879
891
|
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
892
|
+
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
880
893
|
sendSettingsMenu: (state, text, replyMarkup) =>
|
|
881
894
|
deps.sendInteractiveMessage(
|
|
882
895
|
state.chatId,
|
|
@@ -901,6 +914,7 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
901
914
|
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
902
915
|
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
903
916
|
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
917
|
+
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
904
918
|
updateSettingsMessage: (text, replyMarkup) =>
|
|
905
919
|
deps.editInteractiveMessage(
|
|
906
920
|
state.chatId,
|
|
@@ -945,6 +959,7 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
945
959
|
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
946
960
|
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
947
961
|
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
962
|
+
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
948
963
|
setThreadDisplayMode: deps.setThreadDisplayMode,
|
|
949
964
|
setDraftPreviewsEnabled: deps.setDraftPreviewsEnabled,
|
|
950
965
|
setAssistantRenderingMode: deps.setAssistantRenderingMode,
|
|
@@ -138,6 +138,7 @@ export interface PiExtensionApiRuntimePorts {
|
|
|
138
138
|
getActiveTools: ExtensionAPI["getActiveTools"];
|
|
139
139
|
setActiveTools: ExtensionAPI["setActiveTools"];
|
|
140
140
|
setModel: ExtensionAPI["setModel"];
|
|
141
|
+
registerCommand: ExtensionAPI["registerCommand"];
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
export function createExtensionApiRuntimePorts(
|
|
@@ -151,6 +152,7 @@ export function createExtensionApiRuntimePorts(
|
|
|
151
152
|
| "getActiveTools"
|
|
152
153
|
| "setActiveTools"
|
|
153
154
|
| "setModel"
|
|
155
|
+
| "registerCommand"
|
|
154
156
|
>,
|
|
155
157
|
): PiExtensionApiRuntimePorts {
|
|
156
158
|
return {
|
|
@@ -163,6 +165,7 @@ export function createExtensionApiRuntimePorts(
|
|
|
163
165
|
getActiveTools: () => api.getActiveTools(),
|
|
164
166
|
setActiveTools: (names) => api.setActiveTools(names),
|
|
165
167
|
setModel: (model) => api.setModel(model),
|
|
168
|
+
registerCommand: (name, options) => api.registerCommand(name, options),
|
|
166
169
|
};
|
|
167
170
|
}
|
|
168
171
|
|
|
@@ -698,6 +698,7 @@ export interface TelegramInboundRouteRuntimeDeps<
|
|
|
698
698
|
) => void;
|
|
699
699
|
isIdle: (ctx: TContext) => boolean;
|
|
700
700
|
hasPendingMessages: (ctx: TContext) => boolean;
|
|
701
|
+
requestNewSession?: (source: unknown) => void;
|
|
701
702
|
compact: (
|
|
702
703
|
ctx: TContext,
|
|
703
704
|
callbacks: { onComplete: () => void; onError: (error: unknown) => void },
|
|
@@ -721,6 +722,7 @@ const TELEGRAM_OWNED_CALLBACK_PREFIXES = [
|
|
|
721
722
|
"compact:",
|
|
722
723
|
"menu:",
|
|
723
724
|
"model:",
|
|
725
|
+
"new:",
|
|
724
726
|
"queue:",
|
|
725
727
|
"section:",
|
|
726
728
|
"settings:",
|
|
@@ -1970,7 +1972,7 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1970
1972
|
await deps.editInteractiveMessage?.(
|
|
1971
1973
|
chatId,
|
|
1972
1974
|
dialogMessageId,
|
|
1973
|
-
"<b>✖ Rename cancelled
|
|
1975
|
+
"<b>✖ Rename cancelled.</b>",
|
|
1974
1976
|
"html",
|
|
1975
1977
|
{ inline_keyboard: [] },
|
|
1976
1978
|
);
|
|
@@ -2005,6 +2007,42 @@ export function createTelegramInboundRouteRuntime<
|
|
|
2005
2007
|
}
|
|
2006
2008
|
return;
|
|
2007
2009
|
}
|
|
2010
|
+
const handledByNew =
|
|
2011
|
+
await Commands.handleTelegramNewConfirmationCallback(query, {
|
|
2012
|
+
ctx,
|
|
2013
|
+
answerCallbackQuery: deps.answerCallbackQuery,
|
|
2014
|
+
editInteractiveMessage: deps.editInteractiveMessage ?? (async () => {}),
|
|
2015
|
+
deleteMessage: deps.deleteMessage ?? (async () => {}),
|
|
2016
|
+
runNew: async (newCtx) => {
|
|
2017
|
+
await Commands.handleTelegramNewCommand({
|
|
2018
|
+
isIdle: () => deps.isIdle(newCtx),
|
|
2019
|
+
hasPendingMessages: () => deps.hasPendingMessages(newCtx),
|
|
2020
|
+
hasActiveTelegramTurn: deps.activeTurnRuntime.has,
|
|
2021
|
+
hasDispatchPending: deps.bridgeRuntime.lifecycle.hasDispatchPending,
|
|
2022
|
+
hasQueuedTelegramItems: deps.telegramQueueStore.hasQueuedItems,
|
|
2023
|
+
isCompactionInProgress:
|
|
2024
|
+
deps.bridgeRuntime.lifecycle.isCompactionInProgress,
|
|
2025
|
+
requestNewSession: deps.requestNewSession
|
|
2026
|
+
? () => deps.requestNewSession!(query)
|
|
2027
|
+
: undefined,
|
|
2028
|
+
sendTextReply: async (text) => {
|
|
2029
|
+
const chatId = query.message?.chat?.id;
|
|
2030
|
+
const messageId = query.message?.message_id;
|
|
2031
|
+
if (typeof chatId !== "number" || typeof messageId !== "number") return;
|
|
2032
|
+
await deps.editInteractiveMessage?.(
|
|
2033
|
+
chatId,
|
|
2034
|
+
messageId,
|
|
2035
|
+
text,
|
|
2036
|
+
"html",
|
|
2037
|
+
{ inline_keyboard: [] },
|
|
2038
|
+
);
|
|
2039
|
+
},
|
|
2040
|
+
recordRuntimeEvent: deps.recordRuntimeEvent,
|
|
2041
|
+
});
|
|
2042
|
+
},
|
|
2043
|
+
});
|
|
2044
|
+
assertExecutionCurrent();
|
|
2045
|
+
if (handledByNew) return;
|
|
2008
2046
|
const handledByCompact =
|
|
2009
2047
|
await Commands.handleTelegramCompactConfirmationCallback(query, {
|
|
2010
2048
|
ctx,
|
|
@@ -2190,6 +2228,7 @@ export function createTelegramInboundRouteRuntime<
|
|
|
2190
2228
|
stopTypingLoop: deps.stopTypingLoop,
|
|
2191
2229
|
enqueueContinueTurn,
|
|
2192
2230
|
compact: deps.compact,
|
|
2231
|
+
requestNewSession: deps.requestNewSession,
|
|
2193
2232
|
allocateItemOrder: deps.bridgeRuntime.queue.allocateItemOrder,
|
|
2194
2233
|
allocateControlOrder: deps.bridgeRuntime.queue.allocateControlOrder,
|
|
2195
2234
|
appendControlItem: deps.queueMutationRuntime.append,
|
|
@@ -2519,17 +2558,31 @@ export function createTelegramInboundRouteRuntime<
|
|
|
2519
2558
|
dialogMessageId: candidate.dialogMessageId,
|
|
2520
2559
|
});
|
|
2521
2560
|
}
|
|
2561
|
+
const replyText = result.ok && !result.message
|
|
2562
|
+
? Commands.formatTelegramAutomaticThreadDisplayNameRestoredHeading(
|
|
2563
|
+
result.threadName ?? name,
|
|
2564
|
+
)
|
|
2565
|
+
: Commands.formatTelegramInformationHeading(
|
|
2566
|
+
result.ok ? "✅" : "⚠️",
|
|
2567
|
+
result.message ?? "Thread display name reset failed.",
|
|
2568
|
+
);
|
|
2569
|
+
if (result.ok) {
|
|
2570
|
+
Updates.assertTelegramUpdateExecutionCurrent(message);
|
|
2571
|
+
Updates.reportTelegramUpdateCompleted(message);
|
|
2572
|
+
void deps.sendTextReply(
|
|
2573
|
+
target.chatId,
|
|
2574
|
+
message.message_id,
|
|
2575
|
+
replyText,
|
|
2576
|
+
{ parseMode: "HTML", target },
|
|
2577
|
+
).catch((error) => deps.recordRuntimeEvent?.("telegram-command", error, {
|
|
2578
|
+
command: "name", phase: "reset-result",
|
|
2579
|
+
}));
|
|
2580
|
+
return true;
|
|
2581
|
+
}
|
|
2522
2582
|
await deps.sendTextReply(
|
|
2523
2583
|
target.chatId,
|
|
2524
2584
|
message.message_id,
|
|
2525
|
-
|
|
2526
|
-
? Commands.formatTelegramAutomaticThreadDisplayNameRestoredHeading(
|
|
2527
|
-
result.threadName ?? name,
|
|
2528
|
-
)
|
|
2529
|
-
: Commands.formatTelegramInformationHeading(
|
|
2530
|
-
result.ok ? "✅" : "⚠️",
|
|
2531
|
-
result.message ?? "Thread display name reset failed.",
|
|
2532
|
-
),
|
|
2585
|
+
replyText,
|
|
2533
2586
|
{ parseMode: "HTML", target },
|
|
2534
2587
|
);
|
|
2535
2588
|
return true;
|
|
@@ -2561,17 +2614,31 @@ export function createTelegramInboundRouteRuntime<
|
|
|
2561
2614
|
dialogMessageId: candidate.dialogMessageId,
|
|
2562
2615
|
});
|
|
2563
2616
|
}
|
|
2617
|
+
const replyText = result?.ok && !result.message
|
|
2618
|
+
? Commands.formatTelegramThreadDisplayNameSavedHeading(
|
|
2619
|
+
result.threadName ?? consumed.name,
|
|
2620
|
+
)
|
|
2621
|
+
: Commands.formatTelegramInformationHeading(
|
|
2622
|
+
result?.ok ? "✅" : "⚠️",
|
|
2623
|
+
result?.message ?? "Thread display name update failed.",
|
|
2624
|
+
);
|
|
2625
|
+
if (result?.ok) {
|
|
2626
|
+
Updates.assertTelegramUpdateExecutionCurrent(message);
|
|
2627
|
+
Updates.reportTelegramUpdateCompleted(message);
|
|
2628
|
+
void deps.sendTextReply(
|
|
2629
|
+
target.chatId,
|
|
2630
|
+
message.message_id,
|
|
2631
|
+
replyText,
|
|
2632
|
+
{ parseMode: "HTML", target },
|
|
2633
|
+
).catch((error) => deps.recordRuntimeEvent?.("telegram-command", error, {
|
|
2634
|
+
command: "name", phase: "rename-result",
|
|
2635
|
+
}));
|
|
2636
|
+
return true;
|
|
2637
|
+
}
|
|
2564
2638
|
await deps.sendTextReply(
|
|
2565
2639
|
target.chatId,
|
|
2566
2640
|
message.message_id,
|
|
2567
|
-
|
|
2568
|
-
? Commands.formatTelegramThreadDisplayNameSavedHeading(
|
|
2569
|
-
result.threadName ?? consumed.name,
|
|
2570
|
-
)
|
|
2571
|
-
: Commands.formatTelegramInformationHeading(
|
|
2572
|
-
result?.ok ? "✅" : "⚠️",
|
|
2573
|
-
result?.message ?? "Thread display name update failed.",
|
|
2574
|
-
),
|
|
2641
|
+
replyText,
|
|
2575
2642
|
{ parseMode: "HTML", target },
|
|
2576
2643
|
);
|
|
2577
2644
|
return true;
|
|
@@ -239,6 +239,36 @@ export interface TelegramThreadDisplayReconcilerDeps {
|
|
|
239
239
|
): Promise<TResponse>;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
export function createTelegramThreadDisplaySettingsRuntime(deps: {
|
|
243
|
+
getTarget(): { chatId: number; threadId?: number } | undefined;
|
|
244
|
+
getBinding(target: { chatId: number; threadId?: number }):
|
|
245
|
+
{ manualThreadName?: string } | undefined;
|
|
246
|
+
apply(mode: TelegramThreadDisplayMode): Promise<void>;
|
|
247
|
+
reset(target: { chatId: number; threadId?: number }):
|
|
248
|
+
Promise<{ ok: boolean; message?: string }>;
|
|
249
|
+
}): {
|
|
250
|
+
isCustom(): boolean;
|
|
251
|
+
setMode(mode: TelegramThreadDisplayMode): Promise<void>;
|
|
252
|
+
} {
|
|
253
|
+
return {
|
|
254
|
+
isCustom() {
|
|
255
|
+
const target = deps.getTarget();
|
|
256
|
+
return !!target && typeof deps.getBinding(target)?.manualThreadName === "string";
|
|
257
|
+
},
|
|
258
|
+
async setMode(mode) {
|
|
259
|
+
const target = deps.getTarget();
|
|
260
|
+
const hadManualName = !!target &&
|
|
261
|
+
typeof deps.getBinding(target)?.manualThreadName === "string";
|
|
262
|
+
await deps.apply(mode);
|
|
263
|
+
if (!hadManualName || !target) return;
|
|
264
|
+
const reset = await deps.reset(target);
|
|
265
|
+
if (!reset.ok) {
|
|
266
|
+
throw new Error(reset.message ?? "Telegram Thread display override reset failed.");
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
242
272
|
/** Caller owns triggering and reporting; no timer or background retry is created. */
|
|
243
273
|
export function createTelegramThreadDisplayReconciler(
|
|
244
274
|
deps: TelegramThreadDisplayReconcilerDeps,
|