@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
|
@@ -65,7 +65,7 @@ const telegramBusProtocolIdentity = Bus.createTelegramCurrentBusProtocolIdentity
|
|
|
65
65
|
export default function (pi) {
|
|
66
66
|
Skills.registerTelegramSkillDiscovery(pi);
|
|
67
67
|
const piRuntime = Pi.createExtensionApiRuntimePorts(pi);
|
|
68
|
-
const { getActiveTools, getCommands, getThinkingLevel, sendUserMessage, setActiveTools, setModel, setThinkingLevel, } = piRuntime;
|
|
68
|
+
const { getActiveTools, getCommands, getThinkingLevel, sendUserMessage, registerCommand, setActiveTools, setModel, setThinkingLevel, } = piRuntime;
|
|
69
69
|
const bridgeRuntime = Runtime.createTelegramBridgeRuntime();
|
|
70
70
|
const runtimeDiagnostics = Logging.createTelegramRuntimeDiagnosticsRuntime();
|
|
71
71
|
const runtimeEvents = runtimeDiagnostics.events;
|
|
@@ -185,6 +185,23 @@ export default function (pi) {
|
|
|
185
185
|
canReset: lockRuntime.owns,
|
|
186
186
|
commitReset: lockRuntime.commitIfOwned,
|
|
187
187
|
});
|
|
188
|
+
const sessionActionAssembly = Commands.createTelegramSessionActionAssembly({
|
|
189
|
+
registerCommand,
|
|
190
|
+
sendUserMessage,
|
|
191
|
+
store: threadStore,
|
|
192
|
+
getProfileName: configStore.getActiveProfileName,
|
|
193
|
+
ownsPersistence: lockRuntime.owns,
|
|
194
|
+
async sendResult(target, html) {
|
|
195
|
+
const delivery = await Delivery.sendTelegramView({ text: html, parseMode: "html", replyMarkup: { inline_keyboard: [] } }, { scope: { kind: "target", target } });
|
|
196
|
+
return delivery.ok ? { ok: true } : { ok: false,
|
|
197
|
+
retryable: delivery.reason === "runtime-unavailable" ||
|
|
198
|
+
delivery.reason === "target-unavailable" ||
|
|
199
|
+
delivery.reason === "transport-retryable" };
|
|
200
|
+
},
|
|
201
|
+
handoffTtlMs: Threads.TELEGRAM_LEADER_SESSION_HANDOFF_TTL_MS,
|
|
202
|
+
recordRuntimeEvent,
|
|
203
|
+
});
|
|
204
|
+
const sessionActionsRuntime = sessionActionAssembly.action;
|
|
188
205
|
const lockOwnershipGuard = Locks.createTelegramLockOwnershipGuard(lockRuntime);
|
|
189
206
|
const getCurrentLeaderEpoch = lockRuntime.getOwnedLeaderEpoch;
|
|
190
207
|
const telegramSessionContextStore = Lifecycle.createTelegramSessionContextStore({
|
|
@@ -673,6 +690,23 @@ export default function (pi) {
|
|
|
673
690
|
updateStatusMessage: menuActions.updateStatusMessage,
|
|
674
691
|
updateStatus,
|
|
675
692
|
});
|
|
693
|
+
const threadDisplaySettingsRuntime = ThreadDisplay.createTelegramThreadDisplaySettingsRuntime({
|
|
694
|
+
getTarget() {
|
|
695
|
+
return telegramBusFollowerRegistrationState.getTarget() ??
|
|
696
|
+
telegramBusLeaderState.getTarget();
|
|
697
|
+
},
|
|
698
|
+
getBinding(target) { return threadStore.getWorkspaceBindingByTarget(target); },
|
|
699
|
+
apply(mode) {
|
|
700
|
+
return ThreadDisplay.applyTelegramThreadDisplaySetting(mode, {
|
|
701
|
+
getProfileKey: configStore.getActiveProfileName,
|
|
702
|
+
ownsLeader() { return getCurrentLeaderEpoch() !== undefined; },
|
|
703
|
+
getLeaderSetter() { return telegramBusLeaderRuntime.setThreadDisplayMode; },
|
|
704
|
+
getFollowerSetter() { return telegramBusFollowerRegistration.setThreadDisplayMode; },
|
|
705
|
+
reloadConfig: configStore.load,
|
|
706
|
+
});
|
|
707
|
+
},
|
|
708
|
+
reset(target) { return telegramThreadDisplayNameResetBinding.reset(target); },
|
|
709
|
+
});
|
|
676
710
|
const settingsMenuRuntime = MenuSettings.createTelegramSettingsMenuRuntime({
|
|
677
711
|
reloadConfig: configStore.load,
|
|
678
712
|
getModelMenuState: getQueueMenuState,
|
|
@@ -687,15 +721,10 @@ export default function (pi) {
|
|
|
687
721
|
return threadStore.getBotState().threadMode === "enabled"
|
|
688
722
|
? Config.resolveTelegramThreadDisplayMode(configStore.get()) : undefined;
|
|
689
723
|
},
|
|
724
|
+
isThreadDisplayCustom: threadDisplaySettingsRuntime.isCustom,
|
|
690
725
|
async setThreadDisplayMode(mode) {
|
|
691
726
|
try {
|
|
692
|
-
await
|
|
693
|
-
getProfileKey: configStore.getActiveProfileName,
|
|
694
|
-
ownsLeader() { return getCurrentLeaderEpoch() !== undefined; },
|
|
695
|
-
getLeaderSetter() { return telegramBusLeaderRuntime.setThreadDisplayMode; },
|
|
696
|
-
getFollowerSetter() { return telegramBusFollowerRegistration.setThreadDisplayMode; },
|
|
697
|
-
reloadConfig: configStore.load,
|
|
698
|
-
});
|
|
727
|
+
await threadDisplaySettingsRuntime.setMode(mode);
|
|
699
728
|
}
|
|
700
729
|
catch (error) {
|
|
701
730
|
recordRuntimeEvent("bus", error, { phase: "thread-display-setting" });
|
|
@@ -767,6 +796,32 @@ export default function (pi) {
|
|
|
767
796
|
foreignOwnedUpdateForwarder,
|
|
768
797
|
replaceFollowerThreadTarget: restoreFollowerThreadTarget,
|
|
769
798
|
bridgeRuntime,
|
|
799
|
+
requestNewSession(source) {
|
|
800
|
+
const updateId = Updates.getTelegramUpdateExecutionFence(source)?.updateId;
|
|
801
|
+
if (updateId === undefined) {
|
|
802
|
+
throw new Error("Telegram session replacement requires durable update authority.");
|
|
803
|
+
}
|
|
804
|
+
const callbackMessage = source && typeof source === "object" && "message" in source
|
|
805
|
+
? source.message
|
|
806
|
+
: source;
|
|
807
|
+
const messageTarget = callbackMessage;
|
|
808
|
+
const target = typeof messageTarget?.chat?.id === "number" &&
|
|
809
|
+
typeof messageTarget.message_id === "number"
|
|
810
|
+
? {
|
|
811
|
+
chatId: messageTarget.chat.id,
|
|
812
|
+
messageId: messageTarget.message_id,
|
|
813
|
+
...(typeof messageTarget.message_thread_id === "number"
|
|
814
|
+
? { threadId: messageTarget.message_thread_id }
|
|
815
|
+
: {}),
|
|
816
|
+
}
|
|
817
|
+
: undefined;
|
|
818
|
+
if (!target) {
|
|
819
|
+
throw new Error("Telegram session replacement target is unavailable.");
|
|
820
|
+
}
|
|
821
|
+
if (!sessionActionsRuntime.scheduleAfterUpdate(updateId, target)) {
|
|
822
|
+
throw new Error("A Telegram session replacement is already pending.");
|
|
823
|
+
}
|
|
824
|
+
},
|
|
770
825
|
activeTurnRuntime,
|
|
771
826
|
mediaGroupRuntime,
|
|
772
827
|
textGroupRuntime,
|
|
@@ -856,6 +911,7 @@ export default function (pi) {
|
|
|
856
911
|
isContextCurrent: telegramSessionContextStore.isCurrent,
|
|
857
912
|
dispatchNext: dispatchNextQueuedTelegramTurn,
|
|
858
913
|
requestQueueHandoffReconciliation: queueHandoffReconciliationBinding.request,
|
|
914
|
+
afterUpdateCompleted: sessionActionsRuntime.onUpdateCompleted,
|
|
859
915
|
},
|
|
860
916
|
worker: {
|
|
861
917
|
defaultHandle: inboundRouteRuntime.handleUpdate,
|
|
@@ -1366,6 +1422,7 @@ export default function (pi) {
|
|
|
1366
1422
|
}
|
|
1367
1423
|
},
|
|
1368
1424
|
}.reset);
|
|
1425
|
+
sessionActionsRuntime.register();
|
|
1369
1426
|
Bindings.registerTelegramCommandsAndTools({
|
|
1370
1427
|
pi,
|
|
1371
1428
|
agentDir: Paths.resolveAgentDir(),
|
|
@@ -1566,6 +1623,9 @@ export default function (pi) {
|
|
|
1566
1623
|
disconnectOnQuit: cleanupTelegramThreadForSessionRestart,
|
|
1567
1624
|
shutdownGenerativeAppLiveSurfaces: generativeAppLiveSurfaceBinding.shutdown,
|
|
1568
1625
|
resolveAutomaticThreadCleanupEnabled: configControls.resolveAutomaticThreadCleanupEnabled,
|
|
1626
|
+
onSessionStarted(_event, ctx) {
|
|
1627
|
+
sessionActionAssembly.settlement.onSessionStart(ctx);
|
|
1628
|
+
},
|
|
1569
1629
|
buttonActionStore,
|
|
1570
1630
|
callMultipart,
|
|
1571
1631
|
sendChatAction,
|
|
@@ -12,6 +12,7 @@ import type { TelegramVoiceReplyMode } from "./voice.ts";
|
|
|
12
12
|
export type TelegramSettingsMenuReplyMarkup = TelegramInlineKeyboardMarkup;
|
|
13
13
|
export interface TelegramSettingsStateDeps {
|
|
14
14
|
getThreadDisplayMode?: () => TelegramThreadDisplayMode | undefined;
|
|
15
|
+
isThreadDisplayCustom?: () => boolean;
|
|
15
16
|
areDraftPreviewsEnabled: () => boolean;
|
|
16
17
|
getAssistantRenderingMode: () => TelegramAssistantRenderingMode;
|
|
17
18
|
getActivityVerbosity: () => TelegramActivityVerbosity;
|
|
@@ -86,7 +87,7 @@ export declare const TIME_INJECTION_MODE_SETTINGS_TITLE = "<b>\uD83D\uDD52 Time
|
|
|
86
87
|
export declare const VOICE_REPLY_MODE_SETTINGS_TITLE = "<b>\uD83D\uDC44 Voice reply mode:</b>";
|
|
87
88
|
export declare const THREAD_DISPLAY_SETTINGS_TITLE = "<b>\uD83E\uDDF5 Thread display:</b>";
|
|
88
89
|
export declare function buildTelegramSettingsMenuText(): string;
|
|
89
|
-
export declare function buildThreadDisplaySettingsText(mode: TelegramThreadDisplayMode): string;
|
|
90
|
+
export declare function buildThreadDisplaySettingsText(mode: TelegramThreadDisplayMode, custom?: boolean): string;
|
|
90
91
|
export declare function buildAutomaticThreadCleanupSettingsText(enabled: boolean): string;
|
|
91
92
|
export declare function buildInactiveThreadReviewText(count: number): string;
|
|
92
93
|
export declare function buildInactiveThreadReviewReplyMarkup(operationId?: string, canCleanInactiveThreads?: boolean): TelegramSettingsMenuReplyMarkup;
|
|
@@ -95,9 +96,9 @@ export declare function buildAssistantRenderingSettingsText(mode: TelegramAssist
|
|
|
95
96
|
export declare function buildActivityVerbositySettingsText(verbosity: TelegramActivityVerbosity): string;
|
|
96
97
|
export declare function buildVoiceReplyModeSettingsText(mode: TelegramVoiceReplyMode, configured?: boolean): string;
|
|
97
98
|
export declare function buildTimeInjectionModeSettingsText(mode: TelegramTimeMode): string;
|
|
98
|
-
export declare function buildTelegramSettingsMenuReplyMarkup(draftPreviewsEnabled: boolean, assistantRenderingModeOrVoiceReplyMode: TelegramAssistantRenderingMode | TelegramVoiceReplyMode, voiceReplyModeOrTimeInjectionMode: TelegramVoiceReplyMode | TelegramTimeMode, timeInjectionModeOrSectionRegistry?: TelegramTimeMode | TelegramSectionRegistry, sectionRegistryOrVoiceReplyModeConfigured?: TelegramSectionRegistry | boolean, voiceReplyModeConfigured?: boolean, automaticThreadCleanupEnabled?: boolean, activityVerbosity?: TelegramActivityVerbosity, threadDisplayMode?: TelegramThreadDisplayMode): TelegramSettingsMenuReplyMarkup;
|
|
99
|
+
export declare function buildTelegramSettingsMenuReplyMarkup(draftPreviewsEnabled: boolean, assistantRenderingModeOrVoiceReplyMode: TelegramAssistantRenderingMode | TelegramVoiceReplyMode, voiceReplyModeOrTimeInjectionMode: TelegramVoiceReplyMode | TelegramTimeMode, timeInjectionModeOrSectionRegistry?: TelegramTimeMode | TelegramSectionRegistry, sectionRegistryOrVoiceReplyModeConfigured?: TelegramSectionRegistry | boolean, voiceReplyModeConfigured?: boolean, automaticThreadCleanupEnabled?: boolean, activityVerbosity?: TelegramActivityVerbosity, threadDisplayMode?: TelegramThreadDisplayMode, threadDisplayCustom?: boolean): TelegramSettingsMenuReplyMarkup;
|
|
99
100
|
export declare function openTelegramSettingsMenu<TModel extends MenuModel = MenuModel>(deps: TelegramSettingsMenuOpenDeps<TModel>, sectionRegistry?: TelegramSectionRegistry): Promise<void>;
|
|
100
|
-
export declare function buildThreadDisplaySettingsReplyMarkup(mode: TelegramThreadDisplayMode): TelegramSettingsMenuReplyMarkup;
|
|
101
|
+
export declare function buildThreadDisplaySettingsReplyMarkup(mode: TelegramThreadDisplayMode, custom?: boolean): TelegramSettingsMenuReplyMarkup;
|
|
101
102
|
export declare function buildAutomaticThreadCleanupSettingsReplyMarkup(enabled: boolean, canReviewInactiveThreads?: boolean): TelegramSettingsMenuReplyMarkup;
|
|
102
103
|
export declare function buildDraftPreviewsSettingsReplyMarkup(enabled: boolean): TelegramSettingsMenuReplyMarkup;
|
|
103
104
|
export declare function buildAssistantRenderingSettingsReplyMarkup(mode: TelegramAssistantRenderingMode): TelegramSettingsMenuReplyMarkup;
|
|
@@ -25,12 +25,14 @@ function getVoiceReplyModeSetting(mode, configured) {
|
|
|
25
25
|
export function buildTelegramSettingsMenuText() {
|
|
26
26
|
return SETTINGS_MENU_TITLE;
|
|
27
27
|
}
|
|
28
|
-
export function buildThreadDisplaySettingsText(mode) {
|
|
28
|
+
export function buildThreadDisplaySettingsText(mode, custom = false) {
|
|
29
29
|
return [
|
|
30
|
-
`${THREAD_DISPLAY_SETTINGS_TITLE} <code>${threadDisplayModeLabel(mode)}</code>`,
|
|
30
|
+
`${THREAD_DISPLAY_SETTINGS_TITLE} <code>${custom ? "custom" : threadDisplayModeLabel(mode)}</code>`,
|
|
31
31
|
"",
|
|
32
32
|
"Choose how this bot profile labels Telegram tabs and Pi terminal status. Each slot is unique across this bot profile.",
|
|
33
33
|
"",
|
|
34
|
+
"Set a manual name for the current Thread with /name <code>Name</code>.",
|
|
35
|
+
"",
|
|
34
36
|
"<code>-</code> <code>letters</code> (default): show the unique slot, such as <b><i>A</i></b> or <b><i>B</i></b>.",
|
|
35
37
|
"<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>.",
|
|
36
38
|
"<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>.",
|
|
@@ -122,7 +124,7 @@ export function buildTimeInjectionModeSettingsText(mode) {
|
|
|
122
124
|
"<code>-</code> <code>interval</code> (default): add time at most once per chat interval (1 hour unless configured).",
|
|
123
125
|
].join("\n");
|
|
124
126
|
}
|
|
125
|
-
export function buildTelegramSettingsMenuReplyMarkup(draftPreviewsEnabled, assistantRenderingModeOrVoiceReplyMode, voiceReplyModeOrTimeInjectionMode, timeInjectionModeOrSectionRegistry, sectionRegistryOrVoiceReplyModeConfigured, voiceReplyModeConfigured = true, automaticThreadCleanupEnabled = true, activityVerbosity = "quiet", threadDisplayMode) {
|
|
127
|
+
export function buildTelegramSettingsMenuReplyMarkup(draftPreviewsEnabled, assistantRenderingModeOrVoiceReplyMode, voiceReplyModeOrTimeInjectionMode, timeInjectionModeOrSectionRegistry, sectionRegistryOrVoiceReplyModeConfigured, voiceReplyModeConfigured = true, automaticThreadCleanupEnabled = true, activityVerbosity = "quiet", threadDisplayMode, threadDisplayCustom = false) {
|
|
126
128
|
const hasRenderingMode = assistantRenderingModeOrVoiceReplyMode === "rich" ||
|
|
127
129
|
assistantRenderingModeOrVoiceReplyMode === "html";
|
|
128
130
|
const assistantRenderingMode = hasRenderingMode ? assistantRenderingModeOrVoiceReplyMode : "rich";
|
|
@@ -164,14 +166,13 @@ export function buildTelegramSettingsMenuReplyMarkup(draftPreviewsEnabled, assis
|
|
|
164
166
|
text: `🕒 Time injection: ${getTelegramSettingsStateValueLabel(timeInjectionMode)}`,
|
|
165
167
|
callback_data: "settings:open:time-injection",
|
|
166
168
|
},
|
|
167
|
-
{
|
|
168
|
-
text: `🧹 Thread cleanup: ${automaticThreadCleanupEnabled ? "on" : "off"}`,
|
|
169
|
-
callback_data: "settings:open:automatic-thread-cleanup",
|
|
170
|
-
},
|
|
171
169
|
];
|
|
172
170
|
if (threadDisplayMode)
|
|
173
171
|
settingsButtons.push({
|
|
174
|
-
text:
|
|
172
|
+
text: `🧹 Thread cleanup: ${automaticThreadCleanupEnabled ? "on" : "off"}`,
|
|
173
|
+
callback_data: "settings:open:automatic-thread-cleanup",
|
|
174
|
+
}, {
|
|
175
|
+
text: `🧵 Thread display: ${threadDisplayCustom ? "custom" : threadDisplayMode}`,
|
|
175
176
|
callback_data: "settings:open:thread-display",
|
|
176
177
|
});
|
|
177
178
|
if (sectionRegistry) {
|
|
@@ -186,7 +187,7 @@ export function buildTelegramSettingsMenuReplyMarkup(draftPreviewsEnabled, assis
|
|
|
186
187
|
}
|
|
187
188
|
export async function openTelegramSettingsMenu(deps, sectionRegistry) {
|
|
188
189
|
const state = await deps.getModelMenuState();
|
|
189
|
-
const messageId = await deps.sendSettingsMenu(state, buildTelegramSettingsMenuText(), buildTelegramSettingsMenuReplyMarkup(deps.areDraftPreviewsEnabled(), deps.getAssistantRenderingMode(), deps.getVoiceReplyMode(), deps.getTimeInjectionMode(), sectionRegistry, deps.isVoiceReplyModeConfigured(), deps.isAutomaticThreadCleanupEnabled(), deps.getActivityVerbosity(), deps.getThreadDisplayMode?.()));
|
|
190
|
+
const messageId = await deps.sendSettingsMenu(state, buildTelegramSettingsMenuText(), buildTelegramSettingsMenuReplyMarkup(deps.areDraftPreviewsEnabled(), deps.getAssistantRenderingMode(), deps.getVoiceReplyMode(), deps.getTimeInjectionMode(), sectionRegistry, deps.isVoiceReplyModeConfigured(), deps.isAutomaticThreadCleanupEnabled(), deps.getActivityVerbosity(), deps.getThreadDisplayMode?.(), deps.isThreadDisplayCustom?.() ?? false));
|
|
190
191
|
if (messageId === undefined)
|
|
191
192
|
return;
|
|
192
193
|
state.messageId = messageId;
|
|
@@ -202,11 +203,11 @@ function threadDisplayModeLabel(mode) {
|
|
|
202
203
|
default: return "letters";
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
|
-
export function buildThreadDisplaySettingsReplyMarkup(mode) {
|
|
206
|
+
export function buildThreadDisplaySettingsReplyMarkup(mode, custom = false) {
|
|
206
207
|
return { inline_keyboard: [
|
|
207
208
|
[{ text: "⬆️ Back", callback_data: "settings:list" }],
|
|
208
209
|
...["letters", "names", "directory-title", "directory-snake"].map((value) => [{
|
|
209
|
-
text: `${mode === value ? "🟢 " : ""}${threadDisplayModeLabel(value)}`,
|
|
210
|
+
text: `${!custom && mode === value ? "🟢 " : ""}${threadDisplayModeLabel(value)}`,
|
|
210
211
|
callback_data: `settings:set:thread-display:${value}`,
|
|
211
212
|
}]),
|
|
212
213
|
] };
|
|
@@ -307,7 +308,7 @@ export function buildVoiceReplyModeSettingsReplyMarkup(mode, configured = true)
|
|
|
307
308
|
};
|
|
308
309
|
}
|
|
309
310
|
export async function updateTelegramSettingsMenuMessage(deps, sectionRegistry) {
|
|
310
|
-
await deps.updateSettingsMessage(buildTelegramSettingsMenuText(), buildTelegramSettingsMenuReplyMarkup(deps.areDraftPreviewsEnabled(), deps.getAssistantRenderingMode(), deps.getVoiceReplyMode(), deps.getTimeInjectionMode(), sectionRegistry, deps.isVoiceReplyModeConfigured(), deps.isAutomaticThreadCleanupEnabled(), deps.getActivityVerbosity(), deps.getThreadDisplayMode?.()));
|
|
311
|
+
await deps.updateSettingsMessage(buildTelegramSettingsMenuText(), buildTelegramSettingsMenuReplyMarkup(deps.areDraftPreviewsEnabled(), deps.getAssistantRenderingMode(), deps.getVoiceReplyMode(), deps.getTimeInjectionMode(), sectionRegistry, deps.isVoiceReplyModeConfigured(), deps.isAutomaticThreadCleanupEnabled(), deps.getActivityVerbosity(), deps.getThreadDisplayMode?.(), deps.isThreadDisplayCustom?.() ?? false));
|
|
311
312
|
}
|
|
312
313
|
export async function updateAutomaticThreadCleanupSettingsMessage(deps) {
|
|
313
314
|
const enabled = deps.isAutomaticThreadCleanupEnabled();
|
|
@@ -362,7 +363,7 @@ export async function handleTelegramSettingsMenuCallbackAction(callbackQueryId,
|
|
|
362
363
|
await deps.answerCallbackQuery(callbackQueryId, "Threaded Mode is no longer available.");
|
|
363
364
|
return true;
|
|
364
365
|
}
|
|
365
|
-
await deps.updateSettingsMessage(buildThreadDisplaySettingsText(mode), buildThreadDisplaySettingsReplyMarkup(mode));
|
|
366
|
+
await deps.updateSettingsMessage(buildThreadDisplaySettingsText(mode, deps.isThreadDisplayCustom?.() ?? false), buildThreadDisplaySettingsReplyMarkup(mode, deps.isThreadDisplayCustom?.() ?? false));
|
|
366
367
|
await deps.answerCallbackQuery(callbackQueryId);
|
|
367
368
|
return true;
|
|
368
369
|
}
|
|
@@ -533,6 +534,7 @@ export function createTelegramSettingsMenuRuntime(deps, sectionRegistry) {
|
|
|
533
534
|
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
534
535
|
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
535
536
|
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
537
|
+
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
536
538
|
sendSettingsMenu: (state, text, replyMarkup) => deps.sendInteractiveMessage(state.chatId, text, "html", replyMarkup),
|
|
537
539
|
storeModelMenuState: deps.storeModelMenuState,
|
|
538
540
|
}, sectionRegistry);
|
|
@@ -548,6 +550,7 @@ export function createTelegramSettingsMenuRuntime(deps, sectionRegistry) {
|
|
|
548
550
|
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
549
551
|
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
550
552
|
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
553
|
+
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
551
554
|
updateSettingsMessage: (text, replyMarkup) => deps.editInteractiveMessage(state.chatId, state.messageId, text, "html", replyMarkup),
|
|
552
555
|
}, sectionRegistry);
|
|
553
556
|
},
|
|
@@ -577,6 +580,7 @@ export function createTelegramSettingsMenuRuntime(deps, sectionRegistry) {
|
|
|
577
580
|
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
578
581
|
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
579
582
|
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
583
|
+
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
580
584
|
setThreadDisplayMode: deps.setThreadDisplayMode,
|
|
581
585
|
setDraftPreviewsEnabled: deps.setDraftPreviewsEnabled,
|
|
582
586
|
setAssistantRenderingMode: deps.setAssistantRenderingMode,
|
|
@@ -56,8 +56,9 @@ export interface PiExtensionApiRuntimePorts {
|
|
|
56
56
|
getActiveTools: ExtensionAPI["getActiveTools"];
|
|
57
57
|
setActiveTools: ExtensionAPI["setActiveTools"];
|
|
58
58
|
setModel: ExtensionAPI["setModel"];
|
|
59
|
+
registerCommand: ExtensionAPI["registerCommand"];
|
|
59
60
|
}
|
|
60
|
-
export declare function createExtensionApiRuntimePorts(api: Pick<ExtensionAPI, "sendUserMessage" | "exec" | "getCommands" | "getThinkingLevel" | "setThinkingLevel" | "getActiveTools" | "setActiveTools" | "setModel">): PiExtensionApiRuntimePorts;
|
|
61
|
+
export declare function createExtensionApiRuntimePorts(api: Pick<ExtensionAPI, "sendUserMessage" | "exec" | "getCommands" | "getThinkingLevel" | "setThinkingLevel" | "getActiveTools" | "setActiveTools" | "setModel" | "registerCommand">): PiExtensionApiRuntimePorts;
|
|
61
62
|
export declare function normalizeSettingsManager(manager: unknown): PiSettingsManager;
|
|
62
63
|
export declare function createSettingsManager(cwd: string): Promise<PiSettingsManager>;
|
|
63
64
|
export declare function createScopedModelPatternPersister(deps: {
|
|
@@ -44,6 +44,7 @@ export function createExtensionApiRuntimePorts(api) {
|
|
|
44
44
|
getActiveTools: () => api.getActiveTools(),
|
|
45
45
|
setActiveTools: (names) => api.setActiveTools(names),
|
|
46
46
|
setModel: (model) => api.setModel(model),
|
|
47
|
+
registerCommand: (name, options) => api.registerCommand(name, options),
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
function readEnabledModels(value) {
|
|
@@ -164,6 +164,7 @@ export interface TelegramInboundRouteRuntimeDeps<TMessage extends TelegramRouted
|
|
|
164
164
|
sendUserMessage?: (message: string, options?: Queue.TelegramPromptDeliveryOptions) => void;
|
|
165
165
|
isIdle: (ctx: TContext) => boolean;
|
|
166
166
|
hasPendingMessages: (ctx: TContext) => boolean;
|
|
167
|
+
requestNewSession?: (source: unknown) => void;
|
|
167
168
|
compact: (ctx: TContext, callbacks: {
|
|
168
169
|
onComplete: () => void;
|
|
169
170
|
onError: (error: unknown) => void;
|
|
@@ -322,6 +322,7 @@ const TELEGRAM_OWNED_CALLBACK_PREFIXES = [
|
|
|
322
322
|
"compact:",
|
|
323
323
|
"menu:",
|
|
324
324
|
"model:",
|
|
325
|
+
"new:",
|
|
325
326
|
"queue:",
|
|
326
327
|
"section:",
|
|
327
328
|
"settings:",
|
|
@@ -1216,7 +1217,7 @@ export function createTelegramInboundRouteRuntime(deps) {
|
|
|
1216
1217
|
return;
|
|
1217
1218
|
}
|
|
1218
1219
|
if (selected.kind === "cancel") {
|
|
1219
|
-
await deps.editInteractiveMessage?.(chatId, dialogMessageId, "<b>✖ Rename cancelled
|
|
1220
|
+
await deps.editInteractiveMessage?.(chatId, dialogMessageId, "<b>✖ Rename cancelled.</b>", "html", { inline_keyboard: [] });
|
|
1220
1221
|
await deps.answerCallbackQuery(query.id);
|
|
1221
1222
|
return;
|
|
1222
1223
|
}
|
|
@@ -1241,6 +1242,36 @@ export function createTelegramInboundRouteRuntime(deps) {
|
|
|
1241
1242
|
}
|
|
1242
1243
|
return;
|
|
1243
1244
|
}
|
|
1245
|
+
const handledByNew = await Commands.handleTelegramNewConfirmationCallback(query, {
|
|
1246
|
+
ctx,
|
|
1247
|
+
answerCallbackQuery: deps.answerCallbackQuery,
|
|
1248
|
+
editInteractiveMessage: deps.editInteractiveMessage ?? (async () => { }),
|
|
1249
|
+
deleteMessage: deps.deleteMessage ?? (async () => { }),
|
|
1250
|
+
runNew: async (newCtx) => {
|
|
1251
|
+
await Commands.handleTelegramNewCommand({
|
|
1252
|
+
isIdle: () => deps.isIdle(newCtx),
|
|
1253
|
+
hasPendingMessages: () => deps.hasPendingMessages(newCtx),
|
|
1254
|
+
hasActiveTelegramTurn: deps.activeTurnRuntime.has,
|
|
1255
|
+
hasDispatchPending: deps.bridgeRuntime.lifecycle.hasDispatchPending,
|
|
1256
|
+
hasQueuedTelegramItems: deps.telegramQueueStore.hasQueuedItems,
|
|
1257
|
+
isCompactionInProgress: deps.bridgeRuntime.lifecycle.isCompactionInProgress,
|
|
1258
|
+
requestNewSession: deps.requestNewSession
|
|
1259
|
+
? () => deps.requestNewSession(query)
|
|
1260
|
+
: undefined,
|
|
1261
|
+
sendTextReply: async (text) => {
|
|
1262
|
+
const chatId = query.message?.chat?.id;
|
|
1263
|
+
const messageId = query.message?.message_id;
|
|
1264
|
+
if (typeof chatId !== "number" || typeof messageId !== "number")
|
|
1265
|
+
return;
|
|
1266
|
+
await deps.editInteractiveMessage?.(chatId, messageId, text, "html", { inline_keyboard: [] });
|
|
1267
|
+
},
|
|
1268
|
+
recordRuntimeEvent: deps.recordRuntimeEvent,
|
|
1269
|
+
});
|
|
1270
|
+
},
|
|
1271
|
+
});
|
|
1272
|
+
assertExecutionCurrent();
|
|
1273
|
+
if (handledByNew)
|
|
1274
|
+
return;
|
|
1244
1275
|
const handledByCompact = await Commands.handleTelegramCompactConfirmationCallback(query, {
|
|
1245
1276
|
ctx,
|
|
1246
1277
|
answerCallbackQuery: deps.answerCallbackQuery,
|
|
@@ -1392,6 +1423,7 @@ export function createTelegramInboundRouteRuntime(deps) {
|
|
|
1392
1423
|
stopTypingLoop: deps.stopTypingLoop,
|
|
1393
1424
|
enqueueContinueTurn,
|
|
1394
1425
|
compact: deps.compact,
|
|
1426
|
+
requestNewSession: deps.requestNewSession,
|
|
1395
1427
|
allocateItemOrder: deps.bridgeRuntime.queue.allocateItemOrder,
|
|
1396
1428
|
allocateControlOrder: deps.bridgeRuntime.queue.allocateControlOrder,
|
|
1397
1429
|
appendControlItem: deps.queueMutationRuntime.append,
|
|
@@ -1652,9 +1684,18 @@ export function createTelegramInboundRouteRuntime(deps) {
|
|
|
1652
1684
|
dialogMessageId: candidate.dialogMessageId,
|
|
1653
1685
|
});
|
|
1654
1686
|
}
|
|
1655
|
-
|
|
1687
|
+
const replyText = result.ok && !result.message
|
|
1656
1688
|
? Commands.formatTelegramAutomaticThreadDisplayNameRestoredHeading(result.threadName ?? name)
|
|
1657
|
-
: Commands.formatTelegramInformationHeading(result.ok ? "✅" : "⚠️", result.message ?? "Thread display name reset failed.")
|
|
1689
|
+
: Commands.formatTelegramInformationHeading(result.ok ? "✅" : "⚠️", result.message ?? "Thread display name reset failed.");
|
|
1690
|
+
if (result.ok) {
|
|
1691
|
+
Updates.assertTelegramUpdateExecutionCurrent(message);
|
|
1692
|
+
Updates.reportTelegramUpdateCompleted(message);
|
|
1693
|
+
void deps.sendTextReply(target.chatId, message.message_id, replyText, { parseMode: "HTML", target }).catch((error) => deps.recordRuntimeEvent?.("telegram-command", error, {
|
|
1694
|
+
command: "name", phase: "reset-result",
|
|
1695
|
+
}));
|
|
1696
|
+
return true;
|
|
1697
|
+
}
|
|
1698
|
+
await deps.sendTextReply(target.chatId, message.message_id, replyText, { parseMode: "HTML", target });
|
|
1658
1699
|
return true;
|
|
1659
1700
|
}
|
|
1660
1701
|
const validationError = deps.validateThreadName?.(name);
|
|
@@ -1677,9 +1718,18 @@ export function createTelegramInboundRouteRuntime(deps) {
|
|
|
1677
1718
|
dialogMessageId: candidate.dialogMessageId,
|
|
1678
1719
|
});
|
|
1679
1720
|
}
|
|
1680
|
-
|
|
1721
|
+
const replyText = result?.ok && !result.message
|
|
1681
1722
|
? Commands.formatTelegramThreadDisplayNameSavedHeading(result.threadName ?? consumed.name)
|
|
1682
|
-
: Commands.formatTelegramInformationHeading(result?.ok ? "✅" : "⚠️", result?.message ?? "Thread display name update failed.")
|
|
1723
|
+
: Commands.formatTelegramInformationHeading(result?.ok ? "✅" : "⚠️", result?.message ?? "Thread display name update failed.");
|
|
1724
|
+
if (result?.ok) {
|
|
1725
|
+
Updates.assertTelegramUpdateExecutionCurrent(message);
|
|
1726
|
+
Updates.reportTelegramUpdateCompleted(message);
|
|
1727
|
+
void deps.sendTextReply(target.chatId, message.message_id, replyText, { parseMode: "HTML", target }).catch((error) => deps.recordRuntimeEvent?.("telegram-command", error, {
|
|
1728
|
+
command: "name", phase: "rename-result",
|
|
1729
|
+
}));
|
|
1730
|
+
return true;
|
|
1731
|
+
}
|
|
1732
|
+
await deps.sendTextReply(target.chatId, message.message_id, replyText, { parseMode: "HTML", target });
|
|
1683
1733
|
return true;
|
|
1684
1734
|
},
|
|
1685
1735
|
handleCommand: commandHandler,
|
|
@@ -38,6 +38,29 @@ export interface TelegramThreadDisplayReconcilerDeps {
|
|
|
38
38
|
captureLiveBindingKeys(bindings: readonly TelegramWorkspaceThreadBinding[]): ReadonlySet<string>;
|
|
39
39
|
callApi<TResponse>(method: string, body: Record<string, unknown>, options?: TelegramApiCallOptions): Promise<TResponse>;
|
|
40
40
|
}
|
|
41
|
+
export declare function createTelegramThreadDisplaySettingsRuntime(deps: {
|
|
42
|
+
getTarget(): {
|
|
43
|
+
chatId: number;
|
|
44
|
+
threadId?: number;
|
|
45
|
+
} | undefined;
|
|
46
|
+
getBinding(target: {
|
|
47
|
+
chatId: number;
|
|
48
|
+
threadId?: number;
|
|
49
|
+
}): {
|
|
50
|
+
manualThreadName?: string;
|
|
51
|
+
} | undefined;
|
|
52
|
+
apply(mode: TelegramThreadDisplayMode): Promise<void>;
|
|
53
|
+
reset(target: {
|
|
54
|
+
chatId: number;
|
|
55
|
+
threadId?: number;
|
|
56
|
+
}): Promise<{
|
|
57
|
+
ok: boolean;
|
|
58
|
+
message?: string;
|
|
59
|
+
}>;
|
|
60
|
+
}): {
|
|
61
|
+
isCustom(): boolean;
|
|
62
|
+
setMode(mode: TelegramThreadDisplayMode): Promise<void>;
|
|
63
|
+
};
|
|
41
64
|
/** Caller owns triggering and reporting; no timer or background retry is created. */
|
|
42
65
|
export declare function createTelegramThreadDisplayReconciler(deps: TelegramThreadDisplayReconcilerDeps): {
|
|
43
66
|
reconcile(): Promise<{
|
|
@@ -192,6 +192,26 @@ export async function applyTelegramThreadDisplaySetting(mode, deps) {
|
|
|
192
192
|
if (deps.getProfileKey() !== profile)
|
|
193
193
|
throw new Error("Telegram Thread display setting changed profile.");
|
|
194
194
|
}
|
|
195
|
+
export function createTelegramThreadDisplaySettingsRuntime(deps) {
|
|
196
|
+
return {
|
|
197
|
+
isCustom() {
|
|
198
|
+
const target = deps.getTarget();
|
|
199
|
+
return !!target && typeof deps.getBinding(target)?.manualThreadName === "string";
|
|
200
|
+
},
|
|
201
|
+
async setMode(mode) {
|
|
202
|
+
const target = deps.getTarget();
|
|
203
|
+
const hadManualName = !!target &&
|
|
204
|
+
typeof deps.getBinding(target)?.manualThreadName === "string";
|
|
205
|
+
await deps.apply(mode);
|
|
206
|
+
if (!hadManualName || !target)
|
|
207
|
+
return;
|
|
208
|
+
const reset = await deps.reset(target);
|
|
209
|
+
if (!reset.ok) {
|
|
210
|
+
throw new Error(reset.message ?? "Telegram Thread display override reset failed.");
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
195
215
|
/** Caller owns triggering and reporting; no timer or background retry is created. */
|
|
196
216
|
export function createTelegramThreadDisplayReconciler(deps) {
|
|
197
217
|
let tail = Promise.resolve();
|
|
@@ -175,6 +175,19 @@ export interface TelegramBotStateSnapshot {
|
|
|
175
175
|
lastSlot?: string;
|
|
176
176
|
lastReconcileAction?: string;
|
|
177
177
|
}
|
|
178
|
+
export interface TelegramSessionReplacementIntent {
|
|
179
|
+
continuity: "workspace-thread" | "classic-chat";
|
|
180
|
+
cwd: string;
|
|
181
|
+
profileName: string;
|
|
182
|
+
sourceSessionId: string;
|
|
183
|
+
sourceUpdateId: number;
|
|
184
|
+
target: TelegramTarget;
|
|
185
|
+
messageId: number;
|
|
186
|
+
slot?: string;
|
|
187
|
+
threadName?: string;
|
|
188
|
+
createdAtMs: number;
|
|
189
|
+
expiresAtMs: number;
|
|
190
|
+
}
|
|
178
191
|
export interface TelegramTopicTargetFile {
|
|
179
192
|
version: 1;
|
|
180
193
|
source: "snapshot";
|
|
@@ -187,6 +200,7 @@ export interface TelegramTopicTargetFile {
|
|
|
187
200
|
identities?: TelegramThreadIdentityRecord[];
|
|
188
201
|
workspaceBindings?: TelegramWorkspaceThreadBinding[];
|
|
189
202
|
workspaceRetirements?: TelegramWorkspaceRetirementIntent[];
|
|
203
|
+
sessionReplacement?: TelegramSessionReplacementIntent;
|
|
190
204
|
reservations?: TelegramThreadReservation[];
|
|
191
205
|
pendingProvisions?: TelegramThreadPendingProvision[];
|
|
192
206
|
pendingCleanups?: TelegramThreadCleanupIntent[];
|
|
@@ -227,6 +241,10 @@ export interface TelegramTopicTargetStore {
|
|
|
227
241
|
getIdentityByProfileKey: (profileKey: string) => TelegramThreadIdentityRecord | undefined;
|
|
228
242
|
forgetIdentityByProfileKey: (profileKey: string) => boolean;
|
|
229
243
|
listWorkspaceBindings: () => TelegramWorkspaceThreadBinding[];
|
|
244
|
+
getWorkspaceBindingByTarget: (target: TelegramTarget, sessionId?: string) => TelegramWorkspaceThreadBinding | undefined;
|
|
245
|
+
getSessionReplacementIntent: () => TelegramSessionReplacementIntent | undefined;
|
|
246
|
+
commitSessionReplacementIntent: (intent: TelegramSessionReplacementIntent, isCurrent: () => boolean) => Promise<boolean>;
|
|
247
|
+
removeSessionReplacementIntent: (expected: TelegramSessionReplacementIntent, isCurrent: () => boolean) => Promise<boolean>;
|
|
230
248
|
listWorkspaceRetirementIntents: () => TelegramWorkspaceRetirementIntent[];
|
|
231
249
|
commitWorkspaceJournalEvidence: (expected: TelegramWorkspaceThreadBinding, journalBindingKeys: readonly string[], complete: boolean) => TelegramWorkspaceThreadBinding | undefined;
|
|
232
250
|
upsertWorkspaceRetirementIntent: (intent: TelegramWorkspaceRetirementIntent) => boolean;
|