@dobby.ai/dobby 0.1.1 → 0.1.2
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 +20 -7
- package/dist/src/agent/event-forwarder.js +185 -16
- package/dist/src/cli/commands/cron.js +39 -35
- package/dist/src/cli/program.js +0 -6
- package/dist/src/core/types.js +2 -0
- package/dist/src/cron/config.js +2 -2
- package/dist/src/cron/service.js +87 -23
- package/dist/src/cron/store.js +1 -1
- package/package.json +9 -3
- package/.env.example +0 -8
- package/AGENTS.md +0 -267
- package/ROADMAP.md +0 -34
- package/config/cron.example.json +0 -9
- package/config/gateway.example.json +0 -132
- package/dist/plugins/connector-discord/src/mapper.js +0 -75
- package/dist/src/cli/tests/config-command.test.js +0 -42
- package/dist/src/cli/tests/config-io.test.js +0 -64
- package/dist/src/cli/tests/config-mutators.test.js +0 -47
- package/dist/src/cli/tests/discord-mapper.test.js +0 -90
- package/dist/src/cli/tests/doctor.test.js +0 -252
- package/dist/src/cli/tests/init-catalog.test.js +0 -134
- package/dist/src/cli/tests/program-options.test.js +0 -78
- package/dist/src/cli/tests/routing-config.test.js +0 -254
- package/dist/src/core/tests/control-command.test.js +0 -17
- package/dist/src/core/tests/runtime-registry.test.js +0 -116
- package/dist/src/core/tests/typing-controller.test.js +0 -103
- package/docs/BOXLITE_SANDBOX_FEASIBILITY.md +0 -175
- package/docs/CRON_SCHEDULER_DESIGN.md +0 -374
- package/docs/DOCKER_SANDBOX_vs_BOXLITE.md +0 -77
- package/docs/EXTENSION_SYSTEM_ARCHITECTURE.md +0 -119
- package/docs/MVP.md +0 -135
- package/docs/RUNBOOK.md +0 -243
- package/docs/TEAMWORK_HANDOFF_DESIGN.md +0 -440
- package/plugins/connector-discord/dobby.manifest.json +0 -18
- package/plugins/connector-discord/index.js +0 -1
- package/plugins/connector-discord/package-lock.json +0 -360
- package/plugins/connector-discord/package.json +0 -38
- package/plugins/connector-discord/src/connector.ts +0 -345
- package/plugins/connector-discord/src/contribution.ts +0 -21
- package/plugins/connector-discord/src/mapper.ts +0 -101
- package/plugins/connector-discord/tsconfig.json +0 -19
- package/plugins/connector-feishu/dobby.manifest.json +0 -18
- package/plugins/connector-feishu/index.js +0 -1
- package/plugins/connector-feishu/package-lock.json +0 -618
- package/plugins/connector-feishu/package.json +0 -38
- package/plugins/connector-feishu/src/connector.ts +0 -343
- package/plugins/connector-feishu/src/contribution.ts +0 -26
- package/plugins/connector-feishu/src/mapper.ts +0 -401
- package/plugins/connector-feishu/tsconfig.json +0 -19
- package/plugins/plugin-sdk/index.d.ts +0 -261
- package/plugins/plugin-sdk/index.js +0 -1
- package/plugins/plugin-sdk/package-lock.json +0 -12
- package/plugins/plugin-sdk/package.json +0 -22
- package/plugins/provider-claude/dobby.manifest.json +0 -17
- package/plugins/provider-claude/index.js +0 -1
- package/plugins/provider-claude/package-lock.json +0 -3398
- package/plugins/provider-claude/package.json +0 -39
- package/plugins/provider-claude/src/contribution.ts +0 -1018
- package/plugins/provider-claude/tsconfig.json +0 -19
- package/plugins/provider-claude-cli/dobby.manifest.json +0 -17
- package/plugins/provider-claude-cli/index.js +0 -1
- package/plugins/provider-claude-cli/package-lock.json +0 -2898
- package/plugins/provider-claude-cli/package.json +0 -38
- package/plugins/provider-claude-cli/src/contribution.ts +0 -1673
- package/plugins/provider-claude-cli/tsconfig.json +0 -19
- package/plugins/provider-pi/dobby.manifest.json +0 -17
- package/plugins/provider-pi/index.js +0 -1
- package/plugins/provider-pi/package-lock.json +0 -3877
- package/plugins/provider-pi/package.json +0 -40
- package/plugins/provider-pi/src/contribution.ts +0 -606
- package/plugins/provider-pi/tsconfig.json +0 -19
- package/plugins/sandbox-core/boxlite.js +0 -1
- package/plugins/sandbox-core/dobby.manifest.json +0 -17
- package/plugins/sandbox-core/docker.js +0 -1
- package/plugins/sandbox-core/package-lock.json +0 -136
- package/plugins/sandbox-core/package.json +0 -39
- package/plugins/sandbox-core/src/boxlite-context.ts +0 -2
- package/plugins/sandbox-core/src/boxlite-contribution.ts +0 -53
- package/plugins/sandbox-core/src/boxlite-executor.ts +0 -911
- package/plugins/sandbox-core/src/docker-contribution.ts +0 -43
- package/plugins/sandbox-core/src/docker-executor.ts +0 -217
- package/plugins/sandbox-core/tsconfig.json +0 -19
- package/scripts/local-extensions.mjs +0 -168
- package/src/agent/event-forwarder.ts +0 -414
- package/src/cli/commands/config.ts +0 -328
- package/src/cli/commands/configure.ts +0 -92
- package/src/cli/commands/cron.ts +0 -410
- package/src/cli/commands/doctor.ts +0 -331
- package/src/cli/commands/extension.ts +0 -207
- package/src/cli/commands/init.ts +0 -211
- package/src/cli/commands/start.ts +0 -223
- package/src/cli/commands/topology.ts +0 -415
- package/src/cli/index.ts +0 -9
- package/src/cli/program.ts +0 -314
- package/src/cli/shared/config-io.ts +0 -245
- package/src/cli/shared/config-mutators.ts +0 -470
- package/src/cli/shared/config-schema.ts +0 -228
- package/src/cli/shared/config-types.ts +0 -129
- package/src/cli/shared/configure-sections.ts +0 -595
- package/src/cli/shared/discord-config.ts +0 -14
- package/src/cli/shared/init-catalog.ts +0 -249
- package/src/cli/shared/local-extension-specs.ts +0 -108
- package/src/cli/shared/runtime.ts +0 -33
- package/src/cli/shared/schema-prompts.ts +0 -443
- package/src/cli/tests/config-command.test.ts +0 -56
- package/src/cli/tests/config-io.test.ts +0 -92
- package/src/cli/tests/config-mutators.test.ts +0 -59
- package/src/cli/tests/discord-mapper.test.ts +0 -128
- package/src/cli/tests/doctor.test.ts +0 -269
- package/src/cli/tests/init-catalog.test.ts +0 -144
- package/src/cli/tests/program-options.test.ts +0 -95
- package/src/cli/tests/routing-config.test.ts +0 -281
- package/src/core/control-command.ts +0 -12
- package/src/core/dedup-store.ts +0 -103
- package/src/core/gateway.ts +0 -609
- package/src/core/routing.ts +0 -404
- package/src/core/runtime-registry.ts +0 -141
- package/src/core/tests/control-command.test.ts +0 -20
- package/src/core/tests/runtime-registry.test.ts +0 -140
- package/src/core/tests/typing-controller.test.ts +0 -129
- package/src/core/types.ts +0 -324
- package/src/core/typing-controller.ts +0 -119
- package/src/cron/config.ts +0 -154
- package/src/cron/schedule.ts +0 -61
- package/src/cron/service.ts +0 -249
- package/src/cron/store.ts +0 -155
- package/src/cron/types.ts +0 -60
- package/src/extension/loader.ts +0 -145
- package/src/extension/manager.ts +0 -355
- package/src/extension/manifest.ts +0 -26
- package/src/extension/registry.ts +0 -229
- package/src/main.ts +0 -8
- package/src/sandbox/executor.ts +0 -44
- package/src/sandbox/host-executor.ts +0 -118
- package/src/shared/dobby-repo.ts +0 -48
- package/tsconfig.json +0 -18
|
@@ -1,414 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ConnectorPlugin,
|
|
3
|
-
ConnectorUpdateStrategy,
|
|
4
|
-
GatewayAgentEvent,
|
|
5
|
-
GatewayLogger,
|
|
6
|
-
InboundEnvelope,
|
|
7
|
-
Platform,
|
|
8
|
-
} from "../core/types.js";
|
|
9
|
-
|
|
10
|
-
interface ForwarderOptions {
|
|
11
|
-
updateIntervalMs?: number;
|
|
12
|
-
toolMessageMode?: "none" | "errors" | "all";
|
|
13
|
-
onOutboundActivity?: () => void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function truncate(text: string, max?: number): string {
|
|
17
|
-
if (max === undefined) return text;
|
|
18
|
-
if (max <= 0) return "";
|
|
19
|
-
if (text.length <= max) return text;
|
|
20
|
-
const suffix = "\n...(truncated)";
|
|
21
|
-
if (max <= suffix.length) {
|
|
22
|
-
return text.slice(0, max);
|
|
23
|
-
}
|
|
24
|
-
return `${text.slice(0, max - suffix.length)}${suffix}`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function splitForMaxLength(text: string, max?: number, options: { preserveWhitespace?: boolean } = {}): string[] {
|
|
28
|
-
if (max === undefined) {
|
|
29
|
-
return [text];
|
|
30
|
-
}
|
|
31
|
-
if (max <= 0) {
|
|
32
|
-
return [""];
|
|
33
|
-
}
|
|
34
|
-
if (text.length <= max) {
|
|
35
|
-
return [text];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const preserveWhitespace = options.preserveWhitespace ?? false;
|
|
39
|
-
const chunks: string[] = [];
|
|
40
|
-
let offset = 0;
|
|
41
|
-
|
|
42
|
-
while (offset < text.length) {
|
|
43
|
-
const remainingLength = text.length - offset;
|
|
44
|
-
if (remainingLength <= max) {
|
|
45
|
-
chunks.push(text.slice(offset));
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (preserveWhitespace) {
|
|
50
|
-
chunks.push(text.slice(offset, offset + max));
|
|
51
|
-
offset += max;
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const hardLimit = offset + max;
|
|
56
|
-
let splitAt = text.lastIndexOf("\n", hardLimit);
|
|
57
|
-
if (splitAt < offset + Math.floor(max * 0.6)) {
|
|
58
|
-
splitAt = hardLimit;
|
|
59
|
-
} else {
|
|
60
|
-
splitAt += 1;
|
|
61
|
-
}
|
|
62
|
-
chunks.push(text.slice(offset, splitAt));
|
|
63
|
-
offset = splitAt;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return chunks;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export class EventForwarder {
|
|
70
|
-
private rootMessageId: string | null;
|
|
71
|
-
private responseText = "";
|
|
72
|
-
private appendEmittedText = "";
|
|
73
|
-
private pendingFlush: NodeJS.Timeout | null = null;
|
|
74
|
-
private flushSerial: Promise<void> = Promise.resolve();
|
|
75
|
-
private readonly pendingOps: Array<Promise<unknown>> = [];
|
|
76
|
-
private readonly updateIntervalMs: number;
|
|
77
|
-
private readonly toolMessageMode: "none" | "errors" | "all";
|
|
78
|
-
private readonly maxTextLength: number | undefined;
|
|
79
|
-
private readonly onOutboundActivity: (() => void) | undefined;
|
|
80
|
-
private readonly updateStrategy: ConnectorUpdateStrategy;
|
|
81
|
-
private lastEditPrimaryText: string | null = null;
|
|
82
|
-
|
|
83
|
-
constructor(
|
|
84
|
-
private readonly connector: ConnectorPlugin,
|
|
85
|
-
private readonly inbound: InboundEnvelope,
|
|
86
|
-
rootMessageId: string | null,
|
|
87
|
-
private readonly logger: GatewayLogger,
|
|
88
|
-
options: ForwarderOptions = {},
|
|
89
|
-
) {
|
|
90
|
-
this.rootMessageId = rootMessageId;
|
|
91
|
-
this.updateIntervalMs = options.updateIntervalMs ?? 400;
|
|
92
|
-
this.toolMessageMode = options.toolMessageMode ?? "none";
|
|
93
|
-
this.onOutboundActivity = options.onOutboundActivity;
|
|
94
|
-
this.updateStrategy = this.connector.capabilities.updateStrategy;
|
|
95
|
-
const capabilityMaxTextLength = this.connector.capabilities.maxTextLength;
|
|
96
|
-
this.maxTextLength = typeof capabilityMaxTextLength === "number" && capabilityMaxTextLength > 0
|
|
97
|
-
? capabilityMaxTextLength
|
|
98
|
-
: undefined;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
primaryMessageId(): string | null {
|
|
102
|
-
return this.rootMessageId;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
handleEvent = (event: GatewayAgentEvent): void => {
|
|
106
|
-
if (event.type === "message_delta") {
|
|
107
|
-
this.responseText += event.delta;
|
|
108
|
-
if (this.updateStrategy !== "final_only") {
|
|
109
|
-
this.scheduleFlush();
|
|
110
|
-
}
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (event.type === "message_complete") {
|
|
115
|
-
if (event.text.trim().length > 0) {
|
|
116
|
-
this.responseText = event.text;
|
|
117
|
-
if (this.updateStrategy !== "final_only") {
|
|
118
|
-
void this.flushNow();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (event.type === "tool_start") {
|
|
125
|
-
this.logger.info(
|
|
126
|
-
{
|
|
127
|
-
toolName: event.toolName,
|
|
128
|
-
conversation: `${this.inbound.platform}:${this.inbound.accountId}:${this.inbound.chatId}:${this.inbound.threadId ?? "root"}`,
|
|
129
|
-
},
|
|
130
|
-
"Tool execution started",
|
|
131
|
-
);
|
|
132
|
-
if (this.updateStrategy !== "final_only" && this.toolMessageMode === "all") {
|
|
133
|
-
this.enqueueSend(`_-> Running tool: ${event.toolName}_`);
|
|
134
|
-
}
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (event.type === "tool_end") {
|
|
139
|
-
const summary = event.output;
|
|
140
|
-
this.logger.info(
|
|
141
|
-
{
|
|
142
|
-
toolName: event.toolName,
|
|
143
|
-
isError: event.isError,
|
|
144
|
-
conversation: `${this.inbound.platform}:${this.inbound.accountId}:${this.inbound.chatId}:${this.inbound.threadId ?? "root"}`,
|
|
145
|
-
},
|
|
146
|
-
event.isError ? "Tool execution finished with error" : "Tool execution finished",
|
|
147
|
-
);
|
|
148
|
-
if (
|
|
149
|
-
this.updateStrategy !== "final_only" &&
|
|
150
|
-
(this.toolMessageMode === "all" || (this.toolMessageMode === "errors" && event.isError))
|
|
151
|
-
) {
|
|
152
|
-
const prefix = event.isError ? "ERR" : "OK";
|
|
153
|
-
const header = `*${prefix} ${event.toolName}*\n\`\`\`\n`;
|
|
154
|
-
const footer = "\n```";
|
|
155
|
-
const availableSummaryLength = this.maxTextLength === undefined
|
|
156
|
-
? undefined
|
|
157
|
-
: Math.max(0, this.maxTextLength - header.length - footer.length);
|
|
158
|
-
this.enqueueSend(`${header}${truncate(summary, availableSummaryLength)}${footer}`);
|
|
159
|
-
}
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (event.type === "status") {
|
|
164
|
-
if (this.updateStrategy === "final_only") {
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
this.enqueueSend(`_${event.message}_`);
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
async finalize(): Promise<void> {
|
|
172
|
-
if (this.updateStrategy === "final_only") {
|
|
173
|
-
await this.finalizeFinalOnly();
|
|
174
|
-
await Promise.allSettled(this.pendingOps);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (this.updateStrategy === "append") {
|
|
179
|
-
await this.finalizeAppend();
|
|
180
|
-
await Promise.allSettled(this.pendingOps);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
await this.finalizeEdit();
|
|
185
|
-
await Promise.allSettled(this.pendingOps);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private baseEnvelope(): { platform: Platform; accountId: string; chatId: string; threadId?: string } {
|
|
189
|
-
return {
|
|
190
|
-
platform: this.inbound.platform,
|
|
191
|
-
accountId: this.inbound.accountId,
|
|
192
|
-
chatId: this.inbound.chatId,
|
|
193
|
-
...(this.inbound.threadId ? { threadId: this.inbound.threadId } : {}),
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
private scheduleFlush(): void {
|
|
198
|
-
if (this.pendingFlush) return;
|
|
199
|
-
this.pendingFlush = setTimeout(() => {
|
|
200
|
-
void this.flushNow();
|
|
201
|
-
}, this.updateIntervalMs);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
private async flushNow(): Promise<void> {
|
|
205
|
-
const run = this.flushSerial.then(async () => {
|
|
206
|
-
if (this.pendingFlush) {
|
|
207
|
-
clearTimeout(this.pendingFlush);
|
|
208
|
-
this.pendingFlush = null;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (this.responseText.trim().length === 0) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
try {
|
|
216
|
-
if (this.updateStrategy === "append") {
|
|
217
|
-
await this.flushAppendProgress();
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (this.updateStrategy === "edit") {
|
|
222
|
-
const content = truncate(this.responseText, this.maxTextLength);
|
|
223
|
-
await this.sendEditPrimary(content);
|
|
224
|
-
}
|
|
225
|
-
} catch (error) {
|
|
226
|
-
this.logger.warn(
|
|
227
|
-
{
|
|
228
|
-
err: error,
|
|
229
|
-
connectorId: this.inbound.connectorId,
|
|
230
|
-
chatId: this.inbound.chatId,
|
|
231
|
-
targetMessageId: this.rootMessageId,
|
|
232
|
-
contentLength: this.responseText.length,
|
|
233
|
-
updateStrategy: this.updateStrategy,
|
|
234
|
-
},
|
|
235
|
-
"Failed to flush streaming update",
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
this.flushSerial = run.catch(() => {
|
|
241
|
-
// keep chain alive for future flush calls
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
await run;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
private enqueueSend(text: string): void {
|
|
248
|
-
const promise = this.connector
|
|
249
|
-
.send({
|
|
250
|
-
...this.baseEnvelope(),
|
|
251
|
-
mode: "create",
|
|
252
|
-
...(this.rootMessageId ? { replyToMessageId: this.rootMessageId } : {}),
|
|
253
|
-
text,
|
|
254
|
-
})
|
|
255
|
-
.then(() => {
|
|
256
|
-
this.noteOutboundActivity();
|
|
257
|
-
})
|
|
258
|
-
.catch((error) => {
|
|
259
|
-
this.logger.warn(
|
|
260
|
-
{
|
|
261
|
-
err: error,
|
|
262
|
-
connectorId: this.inbound.connectorId,
|
|
263
|
-
chatId: this.inbound.chatId,
|
|
264
|
-
replyToMessageId: this.rootMessageId,
|
|
265
|
-
},
|
|
266
|
-
"Failed to send connector update message",
|
|
267
|
-
);
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
this.pendingOps.push(promise);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
private async sendEditPrimary(text: string): Promise<void> {
|
|
274
|
-
if (this.rootMessageId && this.lastEditPrimaryText === text) {
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (this.rootMessageId) {
|
|
279
|
-
await this.connector.send({
|
|
280
|
-
...this.baseEnvelope(),
|
|
281
|
-
mode: "update",
|
|
282
|
-
targetMessageId: this.rootMessageId,
|
|
283
|
-
text,
|
|
284
|
-
});
|
|
285
|
-
this.lastEditPrimaryText = text;
|
|
286
|
-
this.noteOutboundActivity();
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const created = await this.connector.send({
|
|
291
|
-
...this.baseEnvelope(),
|
|
292
|
-
mode: "create",
|
|
293
|
-
text,
|
|
294
|
-
});
|
|
295
|
-
this.rootMessageId = created.messageId ?? this.rootMessageId;
|
|
296
|
-
this.lastEditPrimaryText = text;
|
|
297
|
-
this.noteOutboundActivity();
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
private async sendCreate(text: string): Promise<void> {
|
|
301
|
-
const created = await this.connector.send({
|
|
302
|
-
...this.baseEnvelope(),
|
|
303
|
-
mode: "create",
|
|
304
|
-
...(this.rootMessageId ? { replyToMessageId: this.rootMessageId } : {}),
|
|
305
|
-
text,
|
|
306
|
-
});
|
|
307
|
-
this.rootMessageId = this.rootMessageId ?? created.messageId ?? null;
|
|
308
|
-
this.noteOutboundActivity();
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
private async flushAppendProgress(): Promise<void> {
|
|
312
|
-
if (this.responseText.startsWith(this.appendEmittedText)) {
|
|
313
|
-
const unsent = this.responseText.slice(this.appendEmittedText.length);
|
|
314
|
-
if (unsent.length === 0) {
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
const chunks = splitForMaxLength(unsent, this.maxTextLength, { preserveWhitespace: true });
|
|
318
|
-
for (const chunk of chunks) {
|
|
319
|
-
await this.sendCreate(chunk);
|
|
320
|
-
}
|
|
321
|
-
this.appendEmittedText = this.responseText;
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const snapshotChunks = splitForMaxLength(this.responseText, this.maxTextLength);
|
|
326
|
-
for (const chunk of snapshotChunks) {
|
|
327
|
-
await this.sendCreate(chunk);
|
|
328
|
-
}
|
|
329
|
-
this.appendEmittedText = this.responseText;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
private async finalizeEdit(): Promise<void> {
|
|
333
|
-
await this.flushNow();
|
|
334
|
-
|
|
335
|
-
if (this.responseText.trim().length === 0) {
|
|
336
|
-
await this.sendEditPrimary("(completed with no text response)");
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const chunks = splitForMaxLength(this.responseText, this.maxTextLength);
|
|
341
|
-
try {
|
|
342
|
-
await this.sendEditPrimary(chunks[0] ?? "");
|
|
343
|
-
|
|
344
|
-
for (const chunk of chunks.slice(1)) {
|
|
345
|
-
await this.sendCreate(chunk);
|
|
346
|
-
}
|
|
347
|
-
} catch (error) {
|
|
348
|
-
this.logger.warn(
|
|
349
|
-
{
|
|
350
|
-
err: error,
|
|
351
|
-
connectorId: this.inbound.connectorId,
|
|
352
|
-
chatId: this.inbound.chatId,
|
|
353
|
-
targetMessageId: this.rootMessageId,
|
|
354
|
-
},
|
|
355
|
-
"Failed to send split final response",
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
private async finalizeFinalOnly(): Promise<void> {
|
|
361
|
-
if (this.pendingFlush) {
|
|
362
|
-
clearTimeout(this.pendingFlush);
|
|
363
|
-
this.pendingFlush = null;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
try {
|
|
367
|
-
if (this.responseText.trim().length === 0) {
|
|
368
|
-
await this.sendCreate("(completed with no text response)");
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
const chunks = splitForMaxLength(this.responseText, this.maxTextLength);
|
|
373
|
-
for (const chunk of chunks) {
|
|
374
|
-
await this.sendCreate(chunk);
|
|
375
|
-
}
|
|
376
|
-
} catch (error) {
|
|
377
|
-
this.logger.warn(
|
|
378
|
-
{
|
|
379
|
-
err: error,
|
|
380
|
-
connectorId: this.inbound.connectorId,
|
|
381
|
-
chatId: this.inbound.chatId,
|
|
382
|
-
updateStrategy: this.updateStrategy,
|
|
383
|
-
},
|
|
384
|
-
"Failed to send final-only response",
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
private async finalizeAppend(): Promise<void> {
|
|
390
|
-
await this.flushNow();
|
|
391
|
-
|
|
392
|
-
if (this.responseText.trim().length > 0 || this.appendEmittedText.trim().length > 0) {
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
try {
|
|
397
|
-
await this.sendCreate("(completed with no text response)");
|
|
398
|
-
} catch (error) {
|
|
399
|
-
this.logger.warn(
|
|
400
|
-
{
|
|
401
|
-
err: error,
|
|
402
|
-
connectorId: this.inbound.connectorId,
|
|
403
|
-
chatId: this.inbound.chatId,
|
|
404
|
-
updateStrategy: this.updateStrategy,
|
|
405
|
-
},
|
|
406
|
-
"Failed to send append fallback response",
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
private noteOutboundActivity(): void {
|
|
412
|
-
this.onOutboundActivity?.();
|
|
413
|
-
}
|
|
414
|
-
}
|