@nodetool-ai/telegram 0.8.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/README.md +49 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/bot-api.d.ts +115 -0
- package/dist/bot-api.d.ts.map +1 -0
- package/dist/bot-api.js +145 -0
- package/dist/bot-api.js.map +1 -0
- package/dist/chunk.d.ts +36 -0
- package/dist/chunk.d.ts.map +1 -0
- package/dist/chunk.js +280 -0
- package/dist/chunk.js.map +1 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +62 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.d.ts +83 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +191 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +65 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +139 -0
- package/dist/config.js.map +1 -0
- package/dist/frame-renderer.d.ts +135 -0
- package/dist/frame-renderer.d.ts.map +1 -0
- package/dist/frame-renderer.js +407 -0
- package/dist/frame-renderer.js.map +1 -0
- package/dist/identity-client.d.ts +132 -0
- package/dist/identity-client.d.ts.map +1 -0
- package/dist/identity-client.js +204 -0
- package/dist/identity-client.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown-html.d.ts +32 -0
- package/dist/markdown-html.d.ts.map +1 -0
- package/dist/markdown-html.js +251 -0
- package/dist/markdown-html.js.map +1 -0
- package/dist/nodetool-client.d.ts +32 -0
- package/dist/nodetool-client.d.ts.map +1 -0
- package/dist/nodetool-client.js +127 -0
- package/dist/nodetool-client.js.map +1 -0
- package/dist/register-commands.d.ts +24 -0
- package/dist/register-commands.d.ts.map +1 -0
- package/dist/register-commands.js +29 -0
- package/dist/register-commands.js.map +1 -0
- package/dist/strings.d.ts +7 -0
- package/dist/strings.d.ts.map +1 -0
- package/dist/strings.js +13 -0
- package/dist/strings.js.map +1 -0
- package/dist/telegram-adapter.d.ts +100 -0
- package/dist/telegram-adapter.d.ts.map +1 -0
- package/dist/telegram-adapter.js +366 -0
- package/dist/telegram-adapter.js.map +1 -0
- package/dist/turn-router.d.ts +167 -0
- package/dist/turn-router.d.ts.map +1 -0
- package/dist/turn-router.js +360 -0
- package/dist/turn-router.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrameRenderer — the pure fold from server frames to render operations
|
|
3
|
+
* (design §6).
|
|
4
|
+
*
|
|
5
|
+
* A turn's visible state in a Telegram chat is two messages: a **status line**
|
|
6
|
+
* that reports what the agent is doing, and a **stream message** that grows as
|
|
7
|
+
* text arrives. This module owns the rules that decide when each is created,
|
|
8
|
+
* edited, rolled over and finalized. It performs no I/O, imports no Telegram
|
|
9
|
+
* types, and reads no clock — `nowMs` is a parameter — so the whole streaming
|
|
10
|
+
* UX is exercised by scripted frame sequences in tests.
|
|
11
|
+
*
|
|
12
|
+
* The adapter maps each op onto one Bot API call.
|
|
13
|
+
*/
|
|
14
|
+
import type { Message, ProcessingMessage } from "@nodetool-ai/protocol";
|
|
15
|
+
import { TELEGRAM_MESSAGE_LIMIT } from "./chunk.js";
|
|
16
|
+
/** Which of the turn's two messages an op acts on. */
|
|
17
|
+
export type RenderTarget = "status" | "stream";
|
|
18
|
+
/** How the adapter must ask Telegram to parse the text. */
|
|
19
|
+
export type ParseMode = "html" | "none";
|
|
20
|
+
/** An asset the turn produced, to be sent as a photo or document. */
|
|
21
|
+
export interface AssetAttachment {
|
|
22
|
+
/** Where the bytes live — `asset://…` or an absolute URL. */
|
|
23
|
+
readonly uri: string;
|
|
24
|
+
/** Display name, when the frame carried one. */
|
|
25
|
+
readonly name: string | null;
|
|
26
|
+
/** Content type, when the frame carried one. */
|
|
27
|
+
readonly contentType: string | null;
|
|
28
|
+
}
|
|
29
|
+
export interface TypingOp {
|
|
30
|
+
readonly kind: "typing";
|
|
31
|
+
}
|
|
32
|
+
export interface SendOp {
|
|
33
|
+
readonly kind: "send";
|
|
34
|
+
readonly target: RenderTarget;
|
|
35
|
+
readonly text: string;
|
|
36
|
+
readonly parseMode: ParseMode;
|
|
37
|
+
}
|
|
38
|
+
export interface EditOp {
|
|
39
|
+
readonly kind: "edit";
|
|
40
|
+
readonly target: RenderTarget;
|
|
41
|
+
readonly text: string;
|
|
42
|
+
readonly parseMode: ParseMode;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The message reaches its final content and stops being edited. `create` is
|
|
46
|
+
* true when no message exists yet, so the adapter sends instead of edits.
|
|
47
|
+
*/
|
|
48
|
+
export interface FinalizeOp {
|
|
49
|
+
readonly kind: "finalize";
|
|
50
|
+
readonly target: RenderTarget;
|
|
51
|
+
readonly text: string;
|
|
52
|
+
readonly parseMode: ParseMode;
|
|
53
|
+
readonly create: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface AttachOp {
|
|
56
|
+
readonly kind: "attach";
|
|
57
|
+
readonly asset: AssetAttachment;
|
|
58
|
+
}
|
|
59
|
+
export interface StopNoteOp {
|
|
60
|
+
readonly kind: "stop-note";
|
|
61
|
+
readonly text: string;
|
|
62
|
+
}
|
|
63
|
+
export type RenderOp = TypingOp | SendOp | EditOp | FinalizeOp | AttachOp | StopNoteOp;
|
|
64
|
+
/** The final assistant message the server persists at the end of a turn. */
|
|
65
|
+
export interface FinalMessageFrame extends Message {
|
|
66
|
+
readonly type: "message";
|
|
67
|
+
}
|
|
68
|
+
/** Ack for a `stop` command. */
|
|
69
|
+
export interface GenerationStoppedFrame {
|
|
70
|
+
readonly type: "generation_stopped";
|
|
71
|
+
readonly thread_id?: string | null;
|
|
72
|
+
readonly message?: string | null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Frames carry an optional monotonic sequence number. `resume_chat` replays
|
|
76
|
+
* everything after `last_seq`, and a replay that overlaps must not re-emit ops
|
|
77
|
+
* — the fold drops any frame whose seq it has already applied.
|
|
78
|
+
*/
|
|
79
|
+
export interface FrameEnvelope {
|
|
80
|
+
readonly seq?: number | null;
|
|
81
|
+
}
|
|
82
|
+
export type RenderFrame = (ProcessingMessage | FinalMessageFrame | GenerationStoppedFrame) & FrameEnvelope;
|
|
83
|
+
export interface RendererOptions {
|
|
84
|
+
/** Minimum gap between edits of the stream message. Default 1500 ms. */
|
|
85
|
+
readonly editThrottleMs?: number;
|
|
86
|
+
/** Rendered length at which the stream message rolls over. Default 3800. */
|
|
87
|
+
readonly rolloverChars?: number;
|
|
88
|
+
}
|
|
89
|
+
export interface RendererState {
|
|
90
|
+
/** Markdown for the currently open stream message. */
|
|
91
|
+
readonly carry: string;
|
|
92
|
+
/** A stream message exists in the chat. */
|
|
93
|
+
readonly streamOpen: boolean;
|
|
94
|
+
/** Length of `carry` as last rendered, so a no-op edit is skipped. */
|
|
95
|
+
readonly renderedLength: number;
|
|
96
|
+
/** `nowMs` of the last stream edit, for the throttle. */
|
|
97
|
+
readonly lastEditMs: number;
|
|
98
|
+
/** A typing action has been requested for this turn. */
|
|
99
|
+
readonly typingSent: boolean;
|
|
100
|
+
/** Latest status line, or null when nothing has been reported. */
|
|
101
|
+
readonly status: string | null;
|
|
102
|
+
/** A status message exists in the chat. */
|
|
103
|
+
readonly statusOpen: boolean;
|
|
104
|
+
/** Status text as last rendered. */
|
|
105
|
+
readonly statusRendered: string | null;
|
|
106
|
+
/** The turn has ended — later frames render nothing. */
|
|
107
|
+
readonly ended: boolean;
|
|
108
|
+
/** Highest applied sequence number, for replay suppression. */
|
|
109
|
+
readonly lastSeq: number | null;
|
|
110
|
+
readonly editThrottleMs: number;
|
|
111
|
+
readonly rolloverChars: number;
|
|
112
|
+
}
|
|
113
|
+
export declare const DEFAULT_EDIT_THROTTLE_MS = 1500;
|
|
114
|
+
export declare function createRendererState(options?: RendererOptions): RendererState;
|
|
115
|
+
export interface FoldResult {
|
|
116
|
+
readonly state: RendererState;
|
|
117
|
+
readonly ops: readonly RenderOp[];
|
|
118
|
+
}
|
|
119
|
+
/** Every asset reference nested anywhere in an `output_update` value. */
|
|
120
|
+
export declare function collectAssetRefs(value: unknown, found?: AssetAttachment[]): AssetAttachment[];
|
|
121
|
+
/**
|
|
122
|
+
* Apply one frame to the renderer state.
|
|
123
|
+
*
|
|
124
|
+
* @param state Renderer state from `createRendererState` or a previous fold.
|
|
125
|
+
* @param frame The server frame.
|
|
126
|
+
* @param nowMs Caller's clock, in milliseconds. The only time source.
|
|
127
|
+
*/
|
|
128
|
+
export declare function foldFrame(state: RendererState, frame: RenderFrame, nowMs: number): FoldResult;
|
|
129
|
+
/** Fold a whole sequence of frames, for tests and replay. */
|
|
130
|
+
export declare function foldFrames(state: RendererState, frames: readonly {
|
|
131
|
+
frame: RenderFrame;
|
|
132
|
+
nowMs: number;
|
|
133
|
+
}[]): FoldResult;
|
|
134
|
+
export { TELEGRAM_MESSAGE_LIMIT };
|
|
135
|
+
//# sourceMappingURL=frame-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-renderer.d.ts","sourceRoot":"","sources":["../src/frame-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrameRenderer — the pure fold from server frames to render operations
|
|
3
|
+
* (design §6).
|
|
4
|
+
*
|
|
5
|
+
* A turn's visible state in a Telegram chat is two messages: a **status line**
|
|
6
|
+
* that reports what the agent is doing, and a **stream message** that grows as
|
|
7
|
+
* text arrives. This module owns the rules that decide when each is created,
|
|
8
|
+
* edited, rolled over and finalized. It performs no I/O, imports no Telegram
|
|
9
|
+
* types, and reads no clock — `nowMs` is a parameter — so the whole streaming
|
|
10
|
+
* UX is exercised by scripted frame sequences in tests.
|
|
11
|
+
*
|
|
12
|
+
* The adapter maps each op onto one Bot API call.
|
|
13
|
+
*/
|
|
14
|
+
import { DEFAULT_CHUNK_MAX, TELEGRAM_MESSAGE_LIMIT, splitOnce } from "./chunk.js";
|
|
15
|
+
import { markdownToTelegramHtml } from "./markdown-html.js";
|
|
16
|
+
export const DEFAULT_EDIT_THROTTLE_MS = 1500;
|
|
17
|
+
export function createRendererState(options = {}) {
|
|
18
|
+
return {
|
|
19
|
+
carry: "",
|
|
20
|
+
streamOpen: false,
|
|
21
|
+
renderedLength: 0,
|
|
22
|
+
lastEditMs: Number.NEGATIVE_INFINITY,
|
|
23
|
+
typingSent: false,
|
|
24
|
+
status: null,
|
|
25
|
+
statusOpen: false,
|
|
26
|
+
statusRendered: null,
|
|
27
|
+
ended: false,
|
|
28
|
+
lastSeq: null,
|
|
29
|
+
editThrottleMs: options.editThrottleMs ?? DEFAULT_EDIT_THROTTLE_MS,
|
|
30
|
+
rolloverChars: options.rolloverChars ?? DEFAULT_CHUNK_MAX
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function present(markdown) {
|
|
34
|
+
const result = markdownToTelegramHtml(markdown);
|
|
35
|
+
return result.ok
|
|
36
|
+
? { text: result.html, parseMode: "html" }
|
|
37
|
+
: { text: result.text, parseMode: "none" };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Split `markdown` so the rendered head fits in `limit`. Escaping expands the
|
|
41
|
+
* text (`&` becomes five characters), so the budget is walked down by the
|
|
42
|
+
* measured expansion ratio rather than assumed.
|
|
43
|
+
*/
|
|
44
|
+
function splitForRender(markdown, limit) {
|
|
45
|
+
let budget = Math.min(markdown.length, limit);
|
|
46
|
+
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
47
|
+
const { head, rest } = splitOnce(markdown, budget);
|
|
48
|
+
if (head.length === 0) {
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
const rendered = present(head).text.length;
|
|
52
|
+
if (rendered <= limit) {
|
|
53
|
+
return { head, rest };
|
|
54
|
+
}
|
|
55
|
+
const next = Math.floor((budget * limit) / rendered) - 1;
|
|
56
|
+
if (next < 1 || next >= budget) {
|
|
57
|
+
budget = budget - 1;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
budget = next;
|
|
61
|
+
}
|
|
62
|
+
if (budget < 1) {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { head: markdown.slice(0, limit), rest: markdown.slice(limit) };
|
|
67
|
+
}
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// Status line
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
function statusOps(state, line) {
|
|
72
|
+
if (state.statusRendered === line) {
|
|
73
|
+
return { state, ops: [] };
|
|
74
|
+
}
|
|
75
|
+
const rendered = present(line);
|
|
76
|
+
const op = state.statusOpen
|
|
77
|
+
? { kind: "edit", target: "status", text: rendered.text, parseMode: rendered.parseMode }
|
|
78
|
+
: { kind: "send", target: "status", text: rendered.text, parseMode: rendered.parseMode };
|
|
79
|
+
return {
|
|
80
|
+
state: { ...state, status: line, statusOpen: true, statusRendered: line },
|
|
81
|
+
ops: [op]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function toolLine(frame) {
|
|
85
|
+
const detail = frame.message != null && frame.message.length > 0 ? ` — ${frame.message}` : "";
|
|
86
|
+
const done = /(^|\b)(completed|finished|done|success)/i.test(frame.message ?? "");
|
|
87
|
+
const failed = /(^|\b)(failed|error)/i.test(frame.message ?? "");
|
|
88
|
+
const icon = failed ? "❌" : done ? "✅" : "🔧";
|
|
89
|
+
return `${icon} ${frame.name}${detail}`;
|
|
90
|
+
}
|
|
91
|
+
function taskLine(frame) {
|
|
92
|
+
const label = frame.step?.title ?? frame.task?.title ?? frame.event;
|
|
93
|
+
return `📋 ${label}`;
|
|
94
|
+
}
|
|
95
|
+
function planningLine(frame) {
|
|
96
|
+
const detail = frame.content != null && frame.content.length > 0 ? ` — ${frame.content}` : "";
|
|
97
|
+
return `🧠 ${frame.phase} (${frame.status})${detail}`;
|
|
98
|
+
}
|
|
99
|
+
function nodeLine(frame) {
|
|
100
|
+
return `⚙️ ${frame.node_name} (${frame.status})`;
|
|
101
|
+
}
|
|
102
|
+
function jobLine(frame) {
|
|
103
|
+
return `▶️ job ${frame.status}`;
|
|
104
|
+
}
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// Text stream
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
/**
|
|
109
|
+
* Close the status message when a text message takes over as the visible
|
|
110
|
+
* surface. Only a *new* stream message replaces it — editing one that already
|
|
111
|
+
* exists changes nothing about which message the user is watching.
|
|
112
|
+
*/
|
|
113
|
+
function closeStatus(state, ops) {
|
|
114
|
+
if (!state.statusOpen || state.status === null || state.streamOpen) {
|
|
115
|
+
return state;
|
|
116
|
+
}
|
|
117
|
+
const rendered = present(state.status);
|
|
118
|
+
ops.push({
|
|
119
|
+
kind: "finalize",
|
|
120
|
+
target: "status",
|
|
121
|
+
text: rendered.text,
|
|
122
|
+
parseMode: rendered.parseMode,
|
|
123
|
+
create: false
|
|
124
|
+
});
|
|
125
|
+
return { ...state, statusOpen: false, statusRendered: null };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Finalize every full message's worth of buffered text, leaving `carry` at
|
|
129
|
+
* whatever still fits in one message.
|
|
130
|
+
*/
|
|
131
|
+
function rollOver(state, nowMs, ops) {
|
|
132
|
+
let next = state;
|
|
133
|
+
while (present(next.carry).text.length > next.rolloverChars) {
|
|
134
|
+
next = closeStatus(next, ops);
|
|
135
|
+
const { head, rest } = splitForRender(next.carry, next.rolloverChars);
|
|
136
|
+
if (head.length === 0) {
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
const rendered = present(head);
|
|
140
|
+
ops.push({
|
|
141
|
+
kind: "finalize",
|
|
142
|
+
target: "stream",
|
|
143
|
+
text: rendered.text,
|
|
144
|
+
parseMode: rendered.parseMode,
|
|
145
|
+
create: !next.streamOpen
|
|
146
|
+
});
|
|
147
|
+
next = { ...next, carry: rest, streamOpen: false, renderedLength: 0, lastEditMs: nowMs };
|
|
148
|
+
}
|
|
149
|
+
return next;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Emit whatever the accumulated text requires: rollover of anything past the
|
|
153
|
+
* message limit, then a create or a throttled edit for the remainder.
|
|
154
|
+
*/
|
|
155
|
+
function flushText(state, nowMs, force) {
|
|
156
|
+
const ops = [];
|
|
157
|
+
let next = rollOver(state, nowMs, ops);
|
|
158
|
+
if (next.carry.length === 0) {
|
|
159
|
+
return { state: next, ops };
|
|
160
|
+
}
|
|
161
|
+
if (!next.streamOpen) {
|
|
162
|
+
next = closeStatus(next, ops);
|
|
163
|
+
const rendered = present(next.carry);
|
|
164
|
+
ops.push({
|
|
165
|
+
kind: "send",
|
|
166
|
+
target: "stream",
|
|
167
|
+
text: rendered.text,
|
|
168
|
+
parseMode: rendered.parseMode
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
state: { ...next, streamOpen: true, renderedLength: next.carry.length, lastEditMs: nowMs },
|
|
172
|
+
ops
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const unchanged = next.renderedLength === next.carry.length;
|
|
176
|
+
const throttled = nowMs - next.lastEditMs < next.editThrottleMs;
|
|
177
|
+
if (unchanged || (throttled && !force)) {
|
|
178
|
+
return { state: next, ops };
|
|
179
|
+
}
|
|
180
|
+
const rendered = present(next.carry);
|
|
181
|
+
ops.push({
|
|
182
|
+
kind: "edit",
|
|
183
|
+
target: "stream",
|
|
184
|
+
text: rendered.text,
|
|
185
|
+
parseMode: rendered.parseMode
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
state: { ...next, renderedLength: next.carry.length, lastEditMs: nowMs },
|
|
189
|
+
ops
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/** Finalize the stream message and everything still buffered behind it. */
|
|
193
|
+
function finishText(state, nowMs) {
|
|
194
|
+
const ops = [];
|
|
195
|
+
let next = rollOver(state, nowMs, ops);
|
|
196
|
+
if (next.carry.length > 0) {
|
|
197
|
+
next = closeStatus(next, ops);
|
|
198
|
+
const rendered = present(next.carry);
|
|
199
|
+
ops.push({
|
|
200
|
+
kind: "finalize",
|
|
201
|
+
target: "stream",
|
|
202
|
+
text: rendered.text,
|
|
203
|
+
parseMode: rendered.parseMode,
|
|
204
|
+
create: !next.streamOpen
|
|
205
|
+
});
|
|
206
|
+
next = { ...next, streamOpen: true, renderedLength: next.carry.length, lastEditMs: nowMs };
|
|
207
|
+
}
|
|
208
|
+
return { state: next, ops };
|
|
209
|
+
}
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
// Assets
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
function isRecord(value) {
|
|
214
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
215
|
+
}
|
|
216
|
+
function stringField(record, field) {
|
|
217
|
+
const value = record[field];
|
|
218
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
219
|
+
}
|
|
220
|
+
/** Every asset reference nested anywhere in an `output_update` value. */
|
|
221
|
+
export function collectAssetRefs(value, found = []) {
|
|
222
|
+
if (typeof value === "string") {
|
|
223
|
+
if (value.startsWith("asset://")) {
|
|
224
|
+
found.push({ uri: value, name: null, contentType: null });
|
|
225
|
+
}
|
|
226
|
+
return found;
|
|
227
|
+
}
|
|
228
|
+
if (Array.isArray(value)) {
|
|
229
|
+
for (const item of value) {
|
|
230
|
+
collectAssetRefs(item, found);
|
|
231
|
+
}
|
|
232
|
+
return found;
|
|
233
|
+
}
|
|
234
|
+
if (!isRecord(value)) {
|
|
235
|
+
return found;
|
|
236
|
+
}
|
|
237
|
+
const uri = stringField(value, "uri") ?? stringField(value, "url");
|
|
238
|
+
if (uri !== null) {
|
|
239
|
+
found.push({
|
|
240
|
+
uri,
|
|
241
|
+
name: stringField(value, "name") ?? stringField(value, "filename"),
|
|
242
|
+
contentType: stringField(value, "content_type") ?? stringField(value, "type")
|
|
243
|
+
});
|
|
244
|
+
return found;
|
|
245
|
+
}
|
|
246
|
+
for (const nested of Object.values(value)) {
|
|
247
|
+
collectAssetRefs(nested, found);
|
|
248
|
+
}
|
|
249
|
+
return found;
|
|
250
|
+
}
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Final message text
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
/**
|
|
255
|
+
* Whether this `message` frame is the turn's answer, and so ends the render.
|
|
256
|
+
*
|
|
257
|
+
* The wire carries several `message` frames per turn that are not the answer,
|
|
258
|
+
* and folding any of them as final hands the user the wrong text and drops
|
|
259
|
+
* everything after it (the fold ignores frames once `ended`):
|
|
260
|
+
*
|
|
261
|
+
* - the compaction echo, `role: "user"` with `execution_event_type:
|
|
262
|
+
* "compaction"`, sent *before* the turn streams — its content is a summary
|
|
263
|
+
* of the earlier conversation;
|
|
264
|
+
* - the mid-turn assistant echo and the synthetic tool-call card, both
|
|
265
|
+
* `role: "assistant"` carrying `tool_calls` and often no text at all;
|
|
266
|
+
* - tool results, `role: "tool"`.
|
|
267
|
+
*
|
|
268
|
+
* So: an assistant message, with no execution event on it, that is not calling
|
|
269
|
+
* a tool. The text of the answer also arrives as chunks, so a frame this
|
|
270
|
+
* refuses costs the render nothing.
|
|
271
|
+
*/
|
|
272
|
+
function isFinalMessage(frame) {
|
|
273
|
+
if (frame.role !== "assistant") {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
if (typeof frame.execution_event_type === "string" && frame.execution_event_type.length > 0) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
return !Array.isArray(frame.tool_calls) || frame.tool_calls.length === 0;
|
|
280
|
+
}
|
|
281
|
+
function textOfMessage(frame) {
|
|
282
|
+
const content = frame.content;
|
|
283
|
+
if (typeof content === "string") {
|
|
284
|
+
return content;
|
|
285
|
+
}
|
|
286
|
+
if (!Array.isArray(content)) {
|
|
287
|
+
return "";
|
|
288
|
+
}
|
|
289
|
+
return content
|
|
290
|
+
.filter((part) => isRecord(part) && part.type === "text" && typeof part.text === "string")
|
|
291
|
+
.map((part) => part.text)
|
|
292
|
+
.join("");
|
|
293
|
+
}
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
// Fold
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
/**
|
|
298
|
+
* Apply one frame to the renderer state.
|
|
299
|
+
*
|
|
300
|
+
* @param state Renderer state from `createRendererState` or a previous fold.
|
|
301
|
+
* @param frame The server frame.
|
|
302
|
+
* @param nowMs Caller's clock, in milliseconds. The only time source.
|
|
303
|
+
*/
|
|
304
|
+
export function foldFrame(state, frame, nowMs) {
|
|
305
|
+
const seq = frame.seq;
|
|
306
|
+
if (typeof seq === "number" && state.lastSeq !== null && seq <= state.lastSeq) {
|
|
307
|
+
return { state, ops: [] };
|
|
308
|
+
}
|
|
309
|
+
const seen = typeof seq === "number" ? { ...state, lastSeq: Math.max(seq, state.lastSeq ?? seq) } : state;
|
|
310
|
+
if (seen.ended) {
|
|
311
|
+
return { state: seen, ops: [] };
|
|
312
|
+
}
|
|
313
|
+
switch (frame.type) {
|
|
314
|
+
case "chunk": {
|
|
315
|
+
const content = frame.content;
|
|
316
|
+
if (typeof content !== "string" || content.length === 0) {
|
|
317
|
+
return { state: seen, ops: [] };
|
|
318
|
+
}
|
|
319
|
+
if (frame.thinking === true) {
|
|
320
|
+
return { state: seen, ops: [] };
|
|
321
|
+
}
|
|
322
|
+
const ops = [];
|
|
323
|
+
let next = seen;
|
|
324
|
+
if (!next.typingSent && !next.streamOpen) {
|
|
325
|
+
ops.push({ kind: "typing" });
|
|
326
|
+
next = { ...next, typingSent: true };
|
|
327
|
+
}
|
|
328
|
+
next = { ...next, carry: next.carry + content };
|
|
329
|
+
const flushed = flushText(next, nowMs, frame.done === true);
|
|
330
|
+
return { state: flushed.state, ops: [...ops, ...flushed.ops] };
|
|
331
|
+
}
|
|
332
|
+
case "tool_call_update":
|
|
333
|
+
return statusOps(seen, toolLine(frame));
|
|
334
|
+
case "task_update":
|
|
335
|
+
return statusOps(seen, taskLine(frame));
|
|
336
|
+
case "planning_update":
|
|
337
|
+
return statusOps(seen, planningLine(frame));
|
|
338
|
+
case "node_update":
|
|
339
|
+
return statusOps(seen, nodeLine(frame));
|
|
340
|
+
case "job_update":
|
|
341
|
+
return statusOps(seen, jobLine(frame));
|
|
342
|
+
case "output_update": {
|
|
343
|
+
const assets = collectAssetRefs(frame.value);
|
|
344
|
+
return {
|
|
345
|
+
state: seen,
|
|
346
|
+
ops: assets.map((asset) => ({ kind: "attach", asset }))
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
case "message": {
|
|
350
|
+
if (!isFinalMessage(frame)) {
|
|
351
|
+
return { state: seen, ops: [] };
|
|
352
|
+
}
|
|
353
|
+
const finalText = textOfMessage(frame);
|
|
354
|
+
const withText = seen.carry.length === 0 && finalText.length > 0
|
|
355
|
+
? { ...seen, carry: finalText }
|
|
356
|
+
: seen;
|
|
357
|
+
const finished = finishText(withText, nowMs);
|
|
358
|
+
const ops = [...finished.ops];
|
|
359
|
+
const closed = closeStatus(finished.state, ops);
|
|
360
|
+
return { state: { ...closed, ended: true }, ops };
|
|
361
|
+
}
|
|
362
|
+
case "error": {
|
|
363
|
+
const ops = [];
|
|
364
|
+
let next = seen;
|
|
365
|
+
if (next.carry.length > 0) {
|
|
366
|
+
const flushed = finishText(next, nowMs);
|
|
367
|
+
ops.push(...flushed.ops);
|
|
368
|
+
next = flushed.state;
|
|
369
|
+
}
|
|
370
|
+
const line = `⚠️ ${frame.message}`;
|
|
371
|
+
const rendered = present(line);
|
|
372
|
+
ops.push({
|
|
373
|
+
kind: "finalize",
|
|
374
|
+
target: "status",
|
|
375
|
+
text: rendered.text,
|
|
376
|
+
parseMode: rendered.parseMode,
|
|
377
|
+
create: !next.statusOpen
|
|
378
|
+
});
|
|
379
|
+
return {
|
|
380
|
+
state: { ...next, ended: true, statusOpen: false, status: line, statusRendered: null },
|
|
381
|
+
ops
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
case "generation_stopped": {
|
|
385
|
+
const finished = finishText(seen, nowMs);
|
|
386
|
+
const ops = [...finished.ops];
|
|
387
|
+
const closed = closeStatus(finished.state, ops);
|
|
388
|
+
ops.push({ kind: "stop-note", text: "⏹ stopped" });
|
|
389
|
+
return { state: { ...closed, ended: true }, ops };
|
|
390
|
+
}
|
|
391
|
+
default:
|
|
392
|
+
return { state: seen, ops: [] };
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
/** Fold a whole sequence of frames, for tests and replay. */
|
|
396
|
+
export function foldFrames(state, frames) {
|
|
397
|
+
const ops = [];
|
|
398
|
+
let next = state;
|
|
399
|
+
for (const entry of frames) {
|
|
400
|
+
const result = foldFrame(next, entry.frame, entry.nowMs);
|
|
401
|
+
next = result.state;
|
|
402
|
+
ops.push(...result.ops);
|
|
403
|
+
}
|
|
404
|
+
return { state: next, ops };
|
|
405
|
+
}
|
|
406
|
+
export { TELEGRAM_MESSAGE_LIMIT };
|
|
407
|
+
//# sourceMappingURL=frame-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-renderer.js","sourceRoot":"","sources":["../src/frame-renderer.ts"],"names":[],"mappings":"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"}
|