@llblab/pi-telegram 0.52.2 → 0.53.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -7
- package/BACKLOG.md +1 -18
- package/CHANGELOG.md +15 -0
- package/README.md +7 -11
- package/api/commands.ts +3 -0
- package/dist/api/commands.d.ts +1 -1
- package/dist/lib/activity-verbosity.d.ts +1 -5
- package/dist/lib/activity-verbosity.js +15 -42
- package/dist/lib/activity.d.ts +9 -0
- package/dist/lib/activity.js +39 -10
- package/dist/lib/agent-messages.js +7 -3
- package/dist/lib/bindings.d.ts +43 -5
- package/dist/lib/bindings.js +163 -20
- package/dist/lib/bus-api.d.ts +12 -0
- package/dist/lib/bus-api.js +182 -79
- package/dist/lib/bus-follower.d.ts +111 -31
- package/dist/lib/bus-follower.js +1324 -359
- package/dist/lib/bus-leader.d.ts +41 -91
- package/dist/lib/bus-leader.js +969 -637
- package/dist/lib/bus-transport.js +16 -9
- package/dist/lib/bus.d.ts +215 -18
- package/dist/lib/bus.js +1048 -327
- package/dist/lib/channel-posts.d.ts +5 -0
- package/dist/lib/channel-posts.js +434 -261
- package/dist/lib/command-templates.d.ts +26 -5
- package/dist/lib/command-templates.js +92 -176
- package/dist/lib/commands.d.ts +168 -82
- package/dist/lib/commands.js +1409 -291
- package/dist/lib/config.d.ts +1 -8
- package/dist/lib/config.js +34 -76
- package/dist/lib/delivery.d.ts +2 -2
- package/dist/lib/delivery.js +16 -16
- package/dist/lib/extension.js +639 -171
- package/dist/lib/generative-app-worker.mjs +19 -7
- package/dist/lib/generative-apps.d.ts +0 -5
- package/dist/lib/generative-apps.js +61 -49
- package/dist/lib/inbound.d.ts +5 -0
- package/dist/lib/inbound.js +35 -59
- package/dist/lib/journal.d.ts +33 -3
- package/dist/lib/journal.js +2063 -782
- package/dist/lib/lifecycle.d.ts +2 -6
- package/dist/lib/lifecycle.js +75 -58
- package/dist/lib/locks.d.ts +29 -3
- package/dist/lib/locks.js +289 -108
- package/dist/lib/logging.js +50 -14
- package/dist/lib/media.d.ts +22 -1
- package/dist/lib/media.js +46 -28
- package/dist/lib/menu-model.d.ts +19 -5
- package/dist/lib/menu-model.js +53 -11
- package/dist/lib/menu-queue.d.ts +5 -4
- package/dist/lib/menu-queue.js +45 -63
- package/dist/lib/menu-settings.d.ts +5 -4
- package/dist/lib/menu-settings.js +114 -78
- package/dist/lib/menu-status.d.ts +1 -1
- package/dist/lib/menu-status.js +8 -25
- package/dist/lib/menu-thinking.d.ts +6 -1
- package/dist/lib/menu-thinking.js +14 -21
- package/dist/lib/menu.d.ts +8 -61
- package/dist/lib/menu.js +92 -164
- package/dist/lib/model.d.ts +1 -1
- package/dist/lib/model.js +2 -16
- package/dist/lib/outbound-attachments.d.ts +6 -27
- package/dist/lib/outbound-attachments.js +45 -38
- package/dist/lib/outbound-buttons.js +22 -16
- package/dist/lib/outbound-markup.d.ts +0 -2
- package/dist/lib/outbound-markup.js +51 -64
- package/dist/lib/outbound-voice.js +6 -3
- package/dist/lib/outbound.d.ts +6 -6
- package/dist/lib/outbound.js +65 -51
- package/dist/lib/ownership.js +6 -2
- package/dist/lib/paths.d.ts +5 -0
- package/dist/lib/paths.js +37 -21
- package/dist/lib/pi.d.ts +2 -0
- package/dist/lib/pi.js +8 -1
- package/dist/lib/polling.d.ts +21 -37
- package/dist/lib/polling.js +59 -50
- package/dist/lib/preview.js +39 -19
- package/dist/lib/process-identity.d.ts +24 -0
- package/dist/lib/process-identity.js +133 -0
- package/dist/lib/prompts.js +2 -7
- package/dist/lib/queue.d.ts +14 -16
- package/dist/lib/queue.js +252 -127
- package/dist/lib/recovery.d.ts +2 -83
- package/dist/lib/recovery.js +20 -274
- package/dist/lib/replies.d.ts +16 -24
- package/dist/lib/replies.js +99 -116
- package/dist/lib/routing.d.ts +120 -7
- package/dist/lib/routing.js +4667 -1152
- package/dist/lib/runtime.d.ts +1 -11
- package/dist/lib/sections.d.ts +4 -29
- package/dist/lib/sections.js +7 -20
- package/dist/lib/skills.js +4 -3
- package/dist/lib/status.js +86 -57
- package/dist/lib/sync.d.ts +1 -3
- package/dist/lib/sync.js +67 -43
- package/dist/lib/target.d.ts +4 -0
- package/dist/lib/target.js +18 -0
- package/dist/lib/telegram-api.d.ts +18 -13
- package/dist/lib/telegram-api.js +148 -53
- package/dist/lib/text-groups.js +4 -39
- package/dist/lib/thread-cleanup-manager.d.ts +6 -27
- package/dist/lib/thread-cleanup-manager.js +369 -186
- package/dist/lib/thread-display.d.ts +1 -2
- package/dist/lib/thread-display.js +58 -38
- package/dist/lib/thread-naming.d.ts +28 -8
- package/dist/lib/thread-naming.js +175 -66
- package/dist/lib/thread-reconciler.d.ts +42 -16
- package/dist/lib/thread-reconciler.js +90 -50
- package/dist/lib/threads.d.ts +82 -20
- package/dist/lib/threads.js +2247 -855
- package/dist/lib/time-injection.js +1 -2
- package/dist/lib/turns.js +1 -19
- package/dist/lib/updates.d.ts +169 -80
- package/dist/lib/updates.js +2418 -641
- package/dist/lib/voice.d.ts +7 -22
- package/dist/lib/voice.js +7 -22
- package/dist/lib/wire.js +1 -1
- package/dist/lib/workspace-admission.d.ts +3 -1
- package/dist/lib/workspace-admission.js +425 -211
- package/dist/lib/workspace-identity.js +8 -13
- package/dist/lib/workspace-retirement.d.ts +1 -1
- package/dist/lib/workspace-retirement.js +328 -140
- package/dist/lib/workspace-slots.js +8 -4
- package/dist/package.json +1 -1
- package/docs/architecture.md +31 -29
- package/docs/inbound.md +1 -1
- package/docs/multi-instance-bus.md +15 -3
- package/docs/outbound.md +1 -1
- package/docs/public-api.md +29 -1
- package/docs/ui-style.md +25 -8
- package/lib/activity-verbosity.ts +59 -82
- package/lib/activity.ts +146 -102
- package/lib/agent-messages.ts +12 -5
- package/lib/bindings.ts +389 -82
- package/lib/bus-api.ts +263 -102
- package/lib/bus-follower.ts +2440 -601
- package/lib/bus-leader.ts +2209 -1290
- package/lib/bus-transport.ts +46 -12
- package/lib/bus.ts +1673 -444
- package/lib/channel-posts.ts +848 -327
- package/lib/command-templates.ts +152 -265
- package/lib/commands.ts +2398 -555
- package/lib/config.ts +177 -170
- package/lib/delivery.ts +41 -29
- package/lib/extension.ts +1206 -433
- package/lib/generative-app-worker.mjs +19 -7
- package/lib/generative-apps.ts +324 -211
- package/lib/inbound.ts +95 -97
- package/lib/journal.ts +5311 -1763
- package/lib/keyboard.ts +1 -3
- package/lib/lifecycle.ts +128 -78
- package/lib/locks.ts +677 -203
- package/lib/logging.ts +147 -58
- package/lib/media.ts +82 -43
- package/lib/menu-model.ts +85 -18
- package/lib/menu-queue.ts +88 -129
- package/lib/menu-settings.ts +260 -155
- package/lib/menu-status.ts +20 -60
- package/lib/menu-thinking.ts +41 -56
- package/lib/menu.ts +112 -285
- package/lib/model.ts +8 -22
- package/lib/outbound-attachments.ts +156 -125
- package/lib/outbound-buttons.ts +76 -49
- package/lib/outbound-markup.ts +96 -94
- package/lib/outbound-voice.ts +33 -27
- package/lib/outbound.ts +128 -125
- package/lib/ownership.ts +19 -10
- package/lib/paths.ts +148 -49
- package/lib/pi.ts +35 -15
- package/lib/polling.ts +144 -147
- package/lib/preview.ts +93 -40
- package/lib/process-identity.ts +164 -0
- package/lib/prompts.ts +4 -11
- package/lib/queue.ts +516 -301
- package/lib/recovery.ts +50 -454
- package/lib/rendering.ts +1 -3
- package/lib/replies.ts +248 -209
- package/lib/routing.ts +8509 -2186
- package/lib/runtime.ts +1 -12
- package/lib/sections.ts +24 -89
- package/lib/setup.ts +1 -3
- package/lib/skills.ts +9 -4
- package/lib/status.ts +215 -110
- package/lib/sync.ts +448 -361
- package/lib/target.ts +22 -3
- package/lib/telegram-api.ts +302 -127
- package/lib/text-groups.ts +5 -39
- package/lib/thread-cleanup-manager.ts +833 -331
- package/lib/thread-display.ts +213 -97
- package/lib/thread-naming.ts +232 -87
- package/lib/thread-reconciler.ts +155 -72
- package/lib/threads.ts +5318 -1845
- package/lib/time-injection.ts +1 -4
- package/lib/turns.ts +15 -28
- package/lib/updates.ts +5184 -1612
- package/lib/voice.ts +7 -35
- package/lib/wire.ts +1 -1
- package/lib/workspace-admission.ts +996 -416
- package/lib/workspace-identity.ts +14 -17
- package/lib/workspace-retirement.ts +878 -376
- package/lib/workspace-slots.ts +22 -13
- package/package.json +1 -1
- package/scripts/check-downgrade.mjs +0 -472
- package/scripts/measure-workspace.mjs +0 -108
package/dist/lib/lifecycle.d.ts
CHANGED
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
* Transport authority, durable bindings, and queue custody remain with their owners.
|
|
6
6
|
*/
|
|
7
7
|
import * as BusFollower from "./bus-follower.ts";
|
|
8
|
-
import * as Queue from "./queue.ts";
|
|
9
8
|
import type { AgentEndEvent, AgentSettledEvent, AgentStartEvent, AssistantMessageEvent, BeforeAgentStartEvent, ExtensionAPI, ExtensionContext, InputEvent, MessageEndEvent, SessionBeforeCompactEvent, SessionCompactEvent, SessionCompactFailedEvent, SessionShutdownEvent, SessionStartEvent, ToolExecutionEndEvent, ToolExecutionStartEvent, ToolExecutionUpdateEvent, UIPromptEndEvent, UIPromptStartEvent } from "./pi.ts";
|
|
10
|
-
|
|
11
|
-
export declare function createAgentStartDedupHook(inner: (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>, schedulePublication?: (task: () => Promise<void>) => void): (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>;
|
|
9
|
+
import * as Queue from "./queue.ts";
|
|
10
|
+
export declare function createAgentStartDedupHook(inner: (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>, resetReplyDedup: () => void, schedulePublication?: (task: () => Promise<void>) => void): (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>;
|
|
12
11
|
type TelegramBeforeAgentStartEvent = Omit<BeforeAgentStartEvent, "systemPrompt"> & {
|
|
13
12
|
systemPrompt: string | string[];
|
|
14
13
|
};
|
|
@@ -202,9 +201,6 @@ export interface TelegramMessageActivityTypingDeps<TContext> {
|
|
|
202
201
|
recordRuntimeEvent?: (category: string, error: unknown, details?: Record<string, unknown>) => void;
|
|
203
202
|
}
|
|
204
203
|
export declare function createTelegramMessageActivityTypingHooks<TContext extends ExtensionContext>(deps: TelegramMessageActivityTypingDeps<TContext>): Pick<TelegramLifecycleRegistrationDeps, "onMessageStart" | "onMessageUpdate">;
|
|
205
|
-
export declare function createDedupAgentStartHook(dedup: {
|
|
206
|
-
reset(): void;
|
|
207
|
-
}, inner: (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>): (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>;
|
|
208
204
|
export interface TelegramExtraLifecycleHooks {
|
|
209
205
|
onSessionStart?: (event: SessionStartEvent, ctx: ExtensionContext) => Promise<void>;
|
|
210
206
|
onSessionShutdown?: (event: SessionShutdownEvent, ctx: ExtensionContext) => Promise<void>;
|
package/dist/lib/lifecycle.js
CHANGED
|
@@ -5,53 +5,58 @@
|
|
|
5
5
|
* Transport authority, durable bindings, and queue custody remain with their owners.
|
|
6
6
|
*/
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
|
-
import { formatTelegramConnectionFailure } from "./status.js";
|
|
9
8
|
import * as BusFollower from "./bus-follower.js";
|
|
10
9
|
import * as Queue from "./queue.js";
|
|
10
|
+
import { formatTelegramConnectionFailure } from "./status.js";
|
|
11
11
|
import * as TextGroups from "./text-groups.js";
|
|
12
|
-
|
|
13
|
-
export function setResetTransportReplyDedup(fn) {
|
|
14
|
-
resetTransportReplyDedupFn = fn;
|
|
15
|
-
}
|
|
16
|
-
export function createAgentStartDedupHook(inner, schedulePublication) {
|
|
12
|
+
export function createAgentStartDedupHook(inner, resetReplyDedup, schedulePublication) {
|
|
17
13
|
return async (event, ctx) => {
|
|
18
|
-
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
14
|
+
// A new turn must not erase the anchor of a final still ahead in the FIFO.
|
|
15
|
+
if (schedulePublication)
|
|
16
|
+
schedulePublication(async () => {
|
|
17
|
+
resetReplyDedup();
|
|
18
|
+
});
|
|
19
|
+
else
|
|
20
|
+
resetReplyDedup();
|
|
26
21
|
return inner(event, ctx);
|
|
27
22
|
};
|
|
28
23
|
}
|
|
29
24
|
const HANDOFF_KEY = Symbol.for("pi-telegram.connection-resume.v1");
|
|
30
25
|
function processHandoffStore() {
|
|
31
26
|
const globals = globalThis;
|
|
32
|
-
return globals[HANDOFF_KEY] ??= {};
|
|
27
|
+
return (globals[HANDOFF_KEY] ??= {});
|
|
33
28
|
}
|
|
34
29
|
export function createTelegramConnectionLifecycle(deps) {
|
|
35
30
|
return {
|
|
36
31
|
onSessionShutdown(event, ctx) {
|
|
37
|
-
deps.intent.suspend({
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
deps.intent.suspend({
|
|
33
|
+
reason: event.reason,
|
|
34
|
+
cwd: ctx.cwd,
|
|
35
|
+
targetSessionFile: event.targetSessionFile,
|
|
36
|
+
connected: deps.isConnected(),
|
|
37
|
+
profileName: deps.getProfileName(),
|
|
38
|
+
});
|
|
40
39
|
},
|
|
41
40
|
prepare(event, ctx) {
|
|
42
|
-
const intent = deps.intent.resume({
|
|
43
|
-
|
|
41
|
+
const intent = deps.intent.resume({
|
|
42
|
+
reason: event.reason,
|
|
43
|
+
cwd: ctx.cwd,
|
|
44
|
+
sessionFile: event.reason === "resume"
|
|
45
|
+
? ctx.sessionManager.getSessionFile()
|
|
46
|
+
: undefined,
|
|
47
|
+
});
|
|
44
48
|
if (!intent)
|
|
45
49
|
return undefined;
|
|
46
50
|
const generation = deps.getGeneration();
|
|
47
51
|
const isCurrent = () => deps.intent.isActive(intent.id) &&
|
|
48
|
-
generation === deps.getGeneration() &&
|
|
52
|
+
generation === deps.getGeneration() &&
|
|
53
|
+
deps.isCurrent(ctx);
|
|
49
54
|
return () => {
|
|
50
55
|
// Startup remains extension-owned background work; no captured command ctx crosses resume.
|
|
51
56
|
void (async () => {
|
|
52
57
|
if (!isCurrent())
|
|
53
58
|
return;
|
|
54
|
-
if (!await deps.activateProfile(intent.profileName, isCurrent)) {
|
|
59
|
+
if (!(await deps.activateProfile(intent.profileName, isCurrent))) {
|
|
55
60
|
if (isCurrent())
|
|
56
61
|
ctx.ui.notify("Telegram profile unavailable. Run /telegram-setup.", "warning");
|
|
57
62
|
return;
|
|
@@ -65,11 +70,13 @@ export function createTelegramConnectionLifecycle(deps) {
|
|
|
65
70
|
deps.recordError(new Error(result.message ?? "Telegram resume connection failed."));
|
|
66
71
|
ctx.ui.notify(formatTelegramConnectionFailure(result.message), "warning");
|
|
67
72
|
}
|
|
68
|
-
})()
|
|
73
|
+
})()
|
|
74
|
+
.catch((error) => {
|
|
69
75
|
deps.recordError(error);
|
|
70
76
|
if (isCurrent())
|
|
71
77
|
ctx.ui.notify(formatTelegramConnectionFailure(error), "warning");
|
|
72
|
-
})
|
|
78
|
+
})
|
|
79
|
+
.finally(() => deps.intent.finish(intent.id));
|
|
73
80
|
};
|
|
74
81
|
},
|
|
75
82
|
};
|
|
@@ -97,23 +104,38 @@ export function createTelegramConnectionIntentRuntime(options = {}) {
|
|
|
97
104
|
store.pending = undefined;
|
|
98
105
|
},
|
|
99
106
|
suspend(input) {
|
|
100
|
-
const intent = active ??
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
const intent = active ??
|
|
108
|
+
(input.connected
|
|
109
|
+
? { id: randomUUID(), cwd: input.cwd, profileName: input.profileName }
|
|
110
|
+
: undefined);
|
|
103
111
|
active = undefined;
|
|
104
|
-
store.pending =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
store.pending =
|
|
113
|
+
input.reason === "resume" &&
|
|
114
|
+
input.targetSessionFile &&
|
|
115
|
+
intent?.cwd === input.cwd
|
|
116
|
+
? {
|
|
117
|
+
...intent,
|
|
118
|
+
pid,
|
|
119
|
+
targetSessionFile: input.targetSessionFile,
|
|
120
|
+
expiresAtMs: now() + 30_000,
|
|
121
|
+
}
|
|
122
|
+
: undefined;
|
|
108
123
|
},
|
|
109
124
|
resume(input) {
|
|
110
125
|
const handoff = store.pending;
|
|
111
126
|
store.pending = undefined;
|
|
112
|
-
if (!handoff ||
|
|
113
|
-
|
|
127
|
+
if (!handoff ||
|
|
128
|
+
handoff.pid !== pid ||
|
|
129
|
+
now() >= handoff.expiresAtMs ||
|
|
130
|
+
input.reason !== "resume" ||
|
|
131
|
+
input.cwd !== handoff.cwd ||
|
|
114
132
|
input.sessionFile !== handoff.targetSessionFile)
|
|
115
133
|
return undefined;
|
|
116
|
-
active = {
|
|
134
|
+
active = {
|
|
135
|
+
id: randomUUID(),
|
|
136
|
+
cwd: handoff.cwd,
|
|
137
|
+
profileName: handoff.profileName,
|
|
138
|
+
};
|
|
117
139
|
return { ...active };
|
|
118
140
|
},
|
|
119
141
|
};
|
|
@@ -258,10 +280,13 @@ export function createTelegramBridgeSessionLifecycleAssembly(deps) {
|
|
|
258
280
|
let preserveThread;
|
|
259
281
|
if (event.reason === "quit") {
|
|
260
282
|
try {
|
|
261
|
-
preserveThread =
|
|
283
|
+
preserveThread =
|
|
284
|
+
deps.services.prepareThreadPreservationOnQuit?.(isCurrent);
|
|
262
285
|
}
|
|
263
286
|
catch (error) {
|
|
264
|
-
deps.follower.recordRuntimeEvent("session", error, {
|
|
287
|
+
deps.follower.recordRuntimeEvent("session", error, {
|
|
288
|
+
phase: "preserve-thread-on-quit",
|
|
289
|
+
});
|
|
265
290
|
}
|
|
266
291
|
}
|
|
267
292
|
deps.services.guestPlaceholder?.stopAll();
|
|
@@ -280,7 +305,9 @@ export function createTelegramBridgeSessionLifecycleAssembly(deps) {
|
|
|
280
305
|
await preserveThread?.();
|
|
281
306
|
}
|
|
282
307
|
catch (error) {
|
|
283
|
-
deps.follower.recordRuntimeEvent("session", error, {
|
|
308
|
+
deps.follower.recordRuntimeEvent("session", error, {
|
|
309
|
+
phase: "preserve-thread-on-quit",
|
|
310
|
+
});
|
|
284
311
|
}
|
|
285
312
|
},
|
|
286
313
|
};
|
|
@@ -316,6 +343,14 @@ export function createTelegramCompactionObserverRuntime(deps) {
|
|
|
316
343
|
clearTimer(fallbackTimer);
|
|
317
344
|
fallbackTimer = undefined;
|
|
318
345
|
};
|
|
346
|
+
// Stop only a typing loop this observer started; a pre-existing agent-owned loop is preserved.
|
|
347
|
+
const releaseCompactionPresence = (ctx) => {
|
|
348
|
+
deps.setCompactionInProgress(false);
|
|
349
|
+
if (typingStartedByObserver)
|
|
350
|
+
deps.stopTypingLoop?.();
|
|
351
|
+
typingStartedByObserver = false;
|
|
352
|
+
deps.updateStatus(ctx);
|
|
353
|
+
};
|
|
319
354
|
const requestDispatch = () => {
|
|
320
355
|
deps.requestDeferredDispatchNextQueuedTelegramTurn(deps.dispatchNextQueuedTelegramTurn);
|
|
321
356
|
};
|
|
@@ -337,11 +372,7 @@ export function createTelegramCompactionObserverRuntime(deps) {
|
|
|
337
372
|
fallbackTimer = undefined;
|
|
338
373
|
if (deps.isContextActive && !deps.isContextActive(ctx))
|
|
339
374
|
return;
|
|
340
|
-
|
|
341
|
-
if (typingStartedByObserver)
|
|
342
|
-
deps.stopTypingLoop?.();
|
|
343
|
-
typingStartedByObserver = false;
|
|
344
|
-
deps.updateStatus(ctx);
|
|
375
|
+
releaseCompactionPresence(ctx);
|
|
345
376
|
deps.recordRuntimeEvent?.("compact", new Error("Compaction observer timed out"));
|
|
346
377
|
// Observer expiry releases local presence, not Pi's eventual terminal result.
|
|
347
378
|
requestDispatch();
|
|
@@ -352,22 +383,14 @@ export function createTelegramCompactionObserverRuntime(deps) {
|
|
|
352
383
|
if (deps.isContextActive && !deps.isContextActive(ctx))
|
|
353
384
|
return;
|
|
354
385
|
clearFallbackTimer();
|
|
355
|
-
|
|
356
|
-
if (typingStartedByObserver)
|
|
357
|
-
deps.stopTypingLoop?.();
|
|
358
|
-
typingStartedByObserver = false;
|
|
359
|
-
deps.updateStatus(ctx);
|
|
386
|
+
releaseCompactionPresence(ctx);
|
|
360
387
|
requestDispatch();
|
|
361
388
|
},
|
|
362
389
|
onSessionCompactFailed: (_event, ctx) => {
|
|
363
390
|
if (deps.isContextActive && !deps.isContextActive(ctx))
|
|
364
391
|
return;
|
|
365
392
|
clearFallbackTimer();
|
|
366
|
-
|
|
367
|
-
if (typingStartedByObserver)
|
|
368
|
-
deps.stopTypingLoop?.();
|
|
369
|
-
typingStartedByObserver = false;
|
|
370
|
-
deps.updateStatus(ctx);
|
|
393
|
+
releaseCompactionPresence(ctx);
|
|
371
394
|
deps.onCompactionAbandoned?.();
|
|
372
395
|
requestDispatch();
|
|
373
396
|
},
|
|
@@ -402,12 +425,6 @@ export function createTelegramMessageActivityTypingHooks(deps) {
|
|
|
402
425
|
onMessageUpdate: (event, ctx) => handleMessageActivity("update", event, ctx, deps.onMessageUpdate),
|
|
403
426
|
};
|
|
404
427
|
}
|
|
405
|
-
export function createDedupAgentStartHook(dedup, inner) {
|
|
406
|
-
return async (event, ctx) => {
|
|
407
|
-
dedup.reset();
|
|
408
|
-
await inner(event, ctx);
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
428
|
export function appendTelegramLifecycleHooks(base, extra, isSessionActive) {
|
|
412
429
|
return {
|
|
413
430
|
onSessionStart: async (event, ctx) => {
|
package/dist/lib/locks.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ export interface TelegramLockRuntime<TContext extends TelegramLockContext> {
|
|
|
84
84
|
owns: (ctx?: TelegramLockContext) => boolean;
|
|
85
85
|
commitIfOwned: (commit: () => void) => boolean;
|
|
86
86
|
/** Consolidated-store publication; domain reducers retain their own exact payload/CAS rules. */
|
|
87
|
-
publishStateSectionIfOwned?: <T>(section: "workspace" | "runtime", mutate:
|
|
87
|
+
publishStateSectionIfOwned?: <T>(section: "workspace" | "runtime", mutate: TelegramRuntimeStateSectionReducer<T>, options: TelegramOwnedStatePublicationOptions) => TelegramOwnedStatePublicationResult<T>;
|
|
88
88
|
refresh: (ctx?: TelegramLockContext) => boolean;
|
|
89
89
|
/** The polling journal named by owners.json for this key, owned or not. */
|
|
90
90
|
getJournalPath: () => string | undefined;
|
|
@@ -135,6 +135,31 @@ interface TelegramRenameRetryOptions {
|
|
|
135
135
|
attempts?: number;
|
|
136
136
|
retryDelayMs?: number;
|
|
137
137
|
}
|
|
138
|
+
export type TelegramPrivateFileFailure = "capacity" | "unsafe" | "changed";
|
|
139
|
+
/** Typed private-file refusal; owners map the failure into their own error vocabulary. */
|
|
140
|
+
export declare class TelegramPrivateFileError extends Error {
|
|
141
|
+
readonly failure: TelegramPrivateFileFailure;
|
|
142
|
+
constructor(failure: TelegramPrivateFileFailure, message: string);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Read flags for private runtime files. Where the platform offers them, no-follow and non-blocking opens refuse a
|
|
146
|
+
* swapped link or FIFO at open time. Windows has neither flag and no FIFOs in the file namespace; there the
|
|
147
|
+
* lstat-before/fstat-after identity binding every strict reader performs is the guard, so a link swapped in after
|
|
148
|
+
* inspection opens a different file and is refused as changed.
|
|
149
|
+
*/
|
|
150
|
+
export declare const TELEGRAM_STRICT_READ_FLAGS: number;
|
|
151
|
+
/** POSIX owner and permission bits; Windows has no uid, so its ACL-protected agent directory carries privacy. */
|
|
152
|
+
export declare function isTelegramOwnerPrivate(stat: {
|
|
153
|
+
uid: bigint;
|
|
154
|
+
mode: bigint;
|
|
155
|
+
}): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Read one owner-private, single-link, bounded regular file without following links. Absence returns undefined;
|
|
158
|
+
* an inode or metadata change between inspection and open refuses as `changed`.
|
|
159
|
+
*/
|
|
160
|
+
export declare function readTelegramPrivateFile(path: string, maxBytes: number): string | undefined;
|
|
161
|
+
/** Atomically publish owner-private contents through a unique staging file; the rename consumes staging. */
|
|
162
|
+
export declare function publishTelegramPrivateFile(path: string, temporaryBasePath: string, contents: string, label: string, onBoundary?: (boundary: "after-write-before-rename" | "after-rename") => void): void;
|
|
138
163
|
/** Rename one Telegram runtime artifact with bounded Windows sharing retries. */
|
|
139
164
|
export declare function renameTelegramPathWithRetry(sourcePath: string, destinationPath: string, options?: TelegramRenameRetryOptions): boolean;
|
|
140
165
|
export interface TelegramFileTransactionOptions {
|
|
@@ -162,6 +187,8 @@ export declare function readTelegramRuntimeState(path: string): TelegramRuntimeS
|
|
|
162
187
|
* continuity. Filesystem access errors are not damage and still throw. Returns whether a reset was published.
|
|
163
188
|
*/
|
|
164
189
|
export declare function resetDamagedTelegramRuntimeState(path: string, validateProfile?: (profile: string, sections: Readonly<TelegramRuntimeStateProfile>) => void): boolean;
|
|
190
|
+
/** Pure section reducer: receives the stored section and its profile, returns the next section and result. */
|
|
191
|
+
export type TelegramRuntimeStateSectionReducer<T> = (current: unknown, observed: Readonly<TelegramRuntimeStateProfile>) => TelegramRuntimeStateMutation<T>;
|
|
165
192
|
export interface TelegramRuntimeStateMutation<T> {
|
|
166
193
|
value: unknown;
|
|
167
194
|
result: T;
|
|
@@ -183,10 +210,9 @@ export interface TelegramOwnedStatePublicationOptions extends TelegramRuntimeSta
|
|
|
183
210
|
* One physical read/check/write transaction for one named section. The caller supplies domain policy; copies expose
|
|
184
211
|
* current sibling facts without granting writes to them. No await, nested transaction, repair or legacy import.
|
|
185
212
|
*/
|
|
186
|
-
export declare function mutateTelegramRuntimeStateSection<T>(path: string, profile: string, section: TelegramRuntimeStateSection, mutate:
|
|
213
|
+
export declare function mutateTelegramRuntimeStateSection<T>(path: string, profile: string, section: TelegramRuntimeStateSection, mutate: TelegramRuntimeStateSectionReducer<T>, options: TelegramRuntimeStatePublicationOptions): T;
|
|
187
214
|
export declare function writeLocks(path: string, locks: Record<string, unknown>): void;
|
|
188
215
|
export declare function parseTelegramLockEntry(value: unknown): TelegramLockEntry | undefined;
|
|
189
|
-
export declare function isProcessAlive(pid: number): boolean;
|
|
190
216
|
export declare function createTelegramLockRuntime<TContext extends TelegramLockContext>(options?: TelegramLockRuntimeOptions): TelegramLockRuntime<TContext>;
|
|
191
217
|
export declare function createTelegramLockOwnershipGuard<TContext extends TelegramLockContext>(lock: TelegramLockRuntime<TContext>): TelegramLockOwnershipGuard<TContext>;
|
|
192
218
|
export declare function createTelegramDirectDeliveryOwnershipChecker<TContext extends TelegramLockContext>(deps: {
|