@hybridaione/hybridclaw 0.1.21 → 0.1.24
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 +59 -0
- package/README.md +50 -8
- package/config.example.json +3 -0
- package/container/package-lock.json +2 -2
- package/container/package.json +1 -1
- package/container/src/browser-tools.ts +53 -3
- package/container/src/hybridai-client.ts +270 -8
- package/container/src/index.ts +66 -3
- package/container/src/token-usage.ts +89 -0
- package/container/src/tools.ts +9 -2
- package/container/src/types.ts +19 -0
- package/container/src/web-fetch.ts +98 -7
- package/dist/agent.d.ts +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +2 -2
- package/dist/agent.js.map +1 -1
- package/dist/chunk.d.ts +6 -0
- package/dist/chunk.d.ts.map +1 -0
- package/dist/chunk.js +129 -0
- package/dist/chunk.js.map +1 -0
- package/dist/container-runner.d.ts +1 -1
- package/dist/container-runner.d.ts.map +1 -1
- package/dist/container-runner.js +25 -1
- package/dist/container-runner.js.map +1 -1
- package/dist/conversation.d.ts +4 -0
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +13 -3
- package/dist/conversation.js.map +1 -1
- package/dist/discord-stream.d.ts +32 -0
- package/dist/discord-stream.d.ts.map +1 -0
- package/dist/discord-stream.js +196 -0
- package/dist/discord-stream.js.map +1 -0
- package/dist/discord.d.ts +9 -2
- package/dist/discord.d.ts.map +1 -1
- package/dist/discord.js +452 -23
- package/dist/discord.js.map +1 -1
- package/dist/gateway-client.d.ts.map +1 -1
- package/dist/gateway-client.js +5 -0
- package/dist/gateway-client.js.map +1 -1
- package/dist/gateway-service.d.ts +1 -0
- package/dist/gateway-service.d.ts.map +1 -1
- package/dist/gateway-service.js +60 -2
- package/dist/gateway-service.js.map +1 -1
- package/dist/gateway-types.d.ts +7 -1
- package/dist/gateway-types.d.ts.map +1 -1
- package/dist/gateway-types.js.map +1 -1
- package/dist/gateway.js +55 -4
- package/dist/gateway.js.map +1 -1
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +7 -0
- package/dist/health.js.map +1 -1
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +20 -0
- package/dist/heartbeat.js.map +1 -1
- package/dist/observability-ingest.d.ts.map +1 -1
- package/dist/observability-ingest.js +26 -0
- package/dist/observability-ingest.js.map +1 -1
- package/dist/prompt-hooks.d.ts +2 -0
- package/dist/prompt-hooks.d.ts.map +1 -1
- package/dist/prompt-hooks.js +29 -0
- package/dist/prompt-hooks.js.map +1 -1
- package/dist/runtime-config.d.ts +3 -0
- package/dist/runtime-config.d.ts.map +1 -1
- package/dist/runtime-config.js +17 -1
- package/dist/runtime-config.js.map +1 -1
- package/dist/scheduled-task-runner.d.ts.map +1 -1
- package/dist/scheduled-task-runner.js +20 -0
- package/dist/scheduled-task-runner.js.map +1 -1
- package/dist/session-maintenance.d.ts.map +1 -1
- package/dist/session-maintenance.js +1 -0
- package/dist/session-maintenance.js.map +1 -1
- package/dist/skills-guard.d.ts +36 -0
- package/dist/skills-guard.d.ts.map +1 -0
- package/dist/skills-guard.js +607 -0
- package/dist/skills-guard.js.map +1 -0
- package/dist/skills.d.ts +13 -2
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +494 -59
- package/dist/skills.js.map +1 -1
- package/dist/token-efficiency.d.ts +41 -0
- package/dist/token-efficiency.d.ts.map +1 -0
- package/dist/token-efficiency.js +164 -0
- package/dist/token-efficiency.js.map +1 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +2 -1
- package/dist/workspace.js.map +1 -1
- package/docs/index.html +33 -7
- package/package.json +1 -1
- package/src/agent.ts +15 -1
- package/src/chunk.ts +153 -0
- package/src/container-runner.ts +24 -0
- package/src/conversation.ts +28 -4
- package/src/discord-stream.ts +240 -0
- package/src/discord.ts +517 -23
- package/src/gateway-client.ts +7 -0
- package/src/gateway-service.ts +72 -1
- package/src/gateway-types.ts +12 -1
- package/src/gateway.ts +65 -4
- package/src/health.ts +8 -0
- package/src/heartbeat.ts +20 -0
- package/src/observability-ingest.ts +24 -0
- package/src/prompt-hooks.ts +29 -0
- package/src/runtime-config.ts +18 -1
- package/src/scheduled-task-runner.ts +20 -0
- package/src/session-maintenance.ts +1 -0
- package/src/skills-guard.ts +736 -0
- package/src/skills.ts +570 -61
- package/src/token-efficiency.ts +228 -0
- package/src/types.ts +12 -0
- package/src/workspace.ts +2 -2
- package/.hybridclaw/container-image-state.json +0 -5
package/container/src/index.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
|
|
3
3
|
import { emitRuntimeEvent, runAfterToolHooks, runBeforeToolHooks } from './extensions.js';
|
|
4
|
-
import { callHybridAI, HybridAIRequestError } from './hybridai-client.js';
|
|
4
|
+
import { callHybridAI, callHybridAIStream, HybridAIRequestError } from './hybridai-client.js';
|
|
5
5
|
import { waitForInput, writeOutput } from './ipc.js';
|
|
6
|
+
import {
|
|
7
|
+
accumulateApiUsage,
|
|
8
|
+
createTokenUsageStats,
|
|
9
|
+
estimateMessageTokens,
|
|
10
|
+
estimateTextTokens,
|
|
11
|
+
finalizeTokenUsage,
|
|
12
|
+
} from './token-usage.js';
|
|
6
13
|
import { executeTool, getPendingSideEffects, resetSideEffects, setModelContext, setScheduledTasks, setSessionContext, TOOL_DEFINITIONS } from './tools.js';
|
|
7
14
|
import type { ArtifactMetadata, ChatMessage, ContainerInput, ContainerOutput, ToolDefinition, ToolExecution } from './types.js';
|
|
8
15
|
|
|
@@ -58,6 +65,12 @@ function sleep(ms: number): Promise<void> {
|
|
|
58
65
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
59
66
|
}
|
|
60
67
|
|
|
68
|
+
function emitStreamDelta(delta: string): void {
|
|
69
|
+
if (!delta) return;
|
|
70
|
+
const payload = Buffer.from(delta, 'utf-8').toString('base64');
|
|
71
|
+
console.error(`[stream] ${payload}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
function isRetryableError(err: unknown): boolean {
|
|
62
75
|
if (err instanceof HybridAIRequestError) {
|
|
63
76
|
return err.status === 429 || (err.status >= 500 && err.status <= 504);
|
|
@@ -144,8 +157,18 @@ async function callHybridAIWithRetry(params: {
|
|
|
144
157
|
enableRag: boolean;
|
|
145
158
|
history: ChatMessage[];
|
|
146
159
|
tools: ToolDefinition[];
|
|
160
|
+
onTextDelta?: (delta: string) => void;
|
|
147
161
|
}): Promise<Awaited<ReturnType<typeof callHybridAI>>> {
|
|
148
|
-
const {
|
|
162
|
+
const {
|
|
163
|
+
baseUrl,
|
|
164
|
+
apiKey,
|
|
165
|
+
model,
|
|
166
|
+
chatbotId,
|
|
167
|
+
enableRag,
|
|
168
|
+
history,
|
|
169
|
+
tools,
|
|
170
|
+
onTextDelta,
|
|
171
|
+
} = params;
|
|
149
172
|
let attempt = 0;
|
|
150
173
|
let delayMs = RETRY_BASE_DELAY_MS;
|
|
151
174
|
|
|
@@ -153,7 +176,31 @@ async function callHybridAIWithRetry(params: {
|
|
|
153
176
|
attempt += 1;
|
|
154
177
|
await emitRuntimeEvent({ event: 'before_model_call', attempt });
|
|
155
178
|
try {
|
|
156
|
-
|
|
179
|
+
let response;
|
|
180
|
+
if (onTextDelta) {
|
|
181
|
+
try {
|
|
182
|
+
response = await callHybridAIStream(
|
|
183
|
+
baseUrl,
|
|
184
|
+
apiKey,
|
|
185
|
+
model,
|
|
186
|
+
chatbotId,
|
|
187
|
+
enableRag,
|
|
188
|
+
history,
|
|
189
|
+
tools,
|
|
190
|
+
onTextDelta,
|
|
191
|
+
);
|
|
192
|
+
} catch (streamErr) {
|
|
193
|
+
const fallbackEligible =
|
|
194
|
+
streamErr instanceof HybridAIRequestError
|
|
195
|
+
&& streamErr.status >= 400
|
|
196
|
+
&& streamErr.status < 500
|
|
197
|
+
&& streamErr.status !== 429;
|
|
198
|
+
if (!fallbackEligible) throw streamErr;
|
|
199
|
+
response = await callHybridAI(baseUrl, apiKey, model, chatbotId, enableRag, history, tools);
|
|
200
|
+
}
|
|
201
|
+
} else {
|
|
202
|
+
response = await callHybridAI(baseUrl, apiKey, model, chatbotId, enableRag, history, tools);
|
|
203
|
+
}
|
|
157
204
|
await emitRuntimeEvent({ event: 'after_model_call', attempt, toolCallCount: response.choices[0]?.message?.tool_calls?.length || 0 });
|
|
158
205
|
return response;
|
|
159
206
|
} catch (err) {
|
|
@@ -189,10 +236,13 @@ async function processRequest(
|
|
|
189
236
|
const toolExecutions: ToolExecution[] = [];
|
|
190
237
|
const artifacts: ArtifactMetadata[] = [];
|
|
191
238
|
const artifactPaths = new Set<string>();
|
|
239
|
+
const tokenUsage = createTokenUsageStats();
|
|
192
240
|
let iterations = 0;
|
|
193
241
|
|
|
194
242
|
while (iterations < MAX_ITERATIONS) {
|
|
195
243
|
iterations++;
|
|
244
|
+
tokenUsage.modelCalls += 1;
|
|
245
|
+
tokenUsage.estimatedPromptTokens += estimateMessageTokens(history);
|
|
196
246
|
|
|
197
247
|
let response;
|
|
198
248
|
try {
|
|
@@ -204,6 +254,7 @@ async function processRequest(
|
|
|
204
254
|
enableRag,
|
|
205
255
|
history,
|
|
206
256
|
tools,
|
|
257
|
+
onTextDelta: emitStreamDelta,
|
|
207
258
|
});
|
|
208
259
|
} catch (err) {
|
|
209
260
|
const failed: ContainerOutput = {
|
|
@@ -212,12 +263,15 @@ async function processRequest(
|
|
|
212
263
|
toolsUsed,
|
|
213
264
|
...(artifacts.length > 0 ? { artifacts } : {}),
|
|
214
265
|
toolExecutions,
|
|
266
|
+
tokenUsage: finalizeTokenUsage(tokenUsage),
|
|
215
267
|
error: `API error: ${err instanceof Error ? err.message : String(err)}`,
|
|
216
268
|
};
|
|
217
269
|
await emitRuntimeEvent({ event: 'turn_end', status: failed.status, toolsUsed });
|
|
218
270
|
return failed;
|
|
219
271
|
}
|
|
220
272
|
|
|
273
|
+
accumulateApiUsage(tokenUsage, response);
|
|
274
|
+
|
|
221
275
|
const choice = response.choices[0];
|
|
222
276
|
if (!choice) {
|
|
223
277
|
const failed: ContainerOutput = {
|
|
@@ -226,12 +280,18 @@ async function processRequest(
|
|
|
226
280
|
toolsUsed,
|
|
227
281
|
...(artifacts.length > 0 ? { artifacts } : {}),
|
|
228
282
|
toolExecutions,
|
|
283
|
+
tokenUsage: finalizeTokenUsage(tokenUsage),
|
|
229
284
|
error: 'No response from API',
|
|
230
285
|
};
|
|
231
286
|
await emitRuntimeEvent({ event: 'turn_end', status: failed.status, toolsUsed });
|
|
232
287
|
return failed;
|
|
233
288
|
}
|
|
234
289
|
|
|
290
|
+
tokenUsage.estimatedCompletionTokens += estimateTextTokens(choice.message.content);
|
|
291
|
+
if (choice.message.tool_calls?.length) {
|
|
292
|
+
tokenUsage.estimatedCompletionTokens += estimateTextTokens(JSON.stringify(choice.message.tool_calls));
|
|
293
|
+
}
|
|
294
|
+
|
|
235
295
|
const assistantMessage: ChatMessage = {
|
|
236
296
|
role: 'assistant',
|
|
237
297
|
content: choice.message.content,
|
|
@@ -251,6 +311,7 @@ async function processRequest(
|
|
|
251
311
|
toolsUsed: [...new Set(toolsUsed)],
|
|
252
312
|
...(artifacts.length > 0 ? { artifacts } : {}),
|
|
253
313
|
toolExecutions,
|
|
314
|
+
tokenUsage: finalizeTokenUsage(tokenUsage),
|
|
254
315
|
};
|
|
255
316
|
await emitRuntimeEvent({ event: 'turn_end', status: completed.status, toolsUsed: completed.toolsUsed });
|
|
256
317
|
return completed;
|
|
@@ -293,6 +354,7 @@ async function processRequest(
|
|
|
293
354
|
toolsUsed,
|
|
294
355
|
...(artifacts.length > 0 ? { artifacts } : {}),
|
|
295
356
|
toolExecutions,
|
|
357
|
+
tokenUsage: finalizeTokenUsage(tokenUsage),
|
|
296
358
|
error: result,
|
|
297
359
|
};
|
|
298
360
|
await emitRuntimeEvent({ event: 'turn_end', status: failed.status, toolsUsed });
|
|
@@ -308,6 +370,7 @@ async function processRequest(
|
|
|
308
370
|
toolsUsed: [...new Set(toolsUsed)],
|
|
309
371
|
...(artifacts.length > 0 ? { artifacts } : {}),
|
|
310
372
|
toolExecutions,
|
|
373
|
+
tokenUsage: finalizeTokenUsage(tokenUsage),
|
|
311
374
|
};
|
|
312
375
|
await emitRuntimeEvent({ event: 'turn_end', status: completed.status, toolsUsed: completed.toolsUsed });
|
|
313
376
|
return completed;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ChatCompletionResponse, ChatMessage, TokenUsageStats } from './types.js';
|
|
2
|
+
|
|
3
|
+
const CHARS_PER_TOKEN = 4;
|
|
4
|
+
|
|
5
|
+
function parseUsageNumber(value: unknown): number {
|
|
6
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
7
|
+
return Math.max(0, Math.floor(value));
|
|
8
|
+
}
|
|
9
|
+
if (typeof value === 'string' && value.trim()) {
|
|
10
|
+
const parsed = Number.parseInt(value, 10);
|
|
11
|
+
if (Number.isFinite(parsed)) return Math.max(0, parsed);
|
|
12
|
+
}
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function createTokenUsageStats(): TokenUsageStats {
|
|
17
|
+
return {
|
|
18
|
+
modelCalls: 0,
|
|
19
|
+
apiUsageAvailable: false,
|
|
20
|
+
apiPromptTokens: 0,
|
|
21
|
+
apiCompletionTokens: 0,
|
|
22
|
+
apiTotalTokens: 0,
|
|
23
|
+
estimatedPromptTokens: 0,
|
|
24
|
+
estimatedCompletionTokens: 0,
|
|
25
|
+
estimatedTotalTokens: 0,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function estimateTextTokens(text: string | null | undefined): number {
|
|
30
|
+
const normalized = typeof text === 'string' ? text : '';
|
|
31
|
+
if (!normalized) return 0;
|
|
32
|
+
return Math.max(1, Math.ceil(normalized.length / CHARS_PER_TOKEN));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function estimateMessageTokens(messages: ChatMessage[]): number {
|
|
36
|
+
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
37
|
+
|
|
38
|
+
let total = 2;
|
|
39
|
+
for (const message of messages) {
|
|
40
|
+
total += 4;
|
|
41
|
+
total += estimateTextTokens(message.role);
|
|
42
|
+
total += estimateTextTokens(message.content);
|
|
43
|
+
if (message.tool_calls) total += estimateTextTokens(JSON.stringify(message.tool_calls));
|
|
44
|
+
if (message.tool_call_id) total += estimateTextTokens(message.tool_call_id);
|
|
45
|
+
}
|
|
46
|
+
return total;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function accumulateApiUsage(
|
|
50
|
+
stats: TokenUsageStats,
|
|
51
|
+
response: ChatCompletionResponse,
|
|
52
|
+
): void {
|
|
53
|
+
const usage = response.usage;
|
|
54
|
+
if (!usage) return;
|
|
55
|
+
|
|
56
|
+
const hasUsageFields =
|
|
57
|
+
usage.prompt_tokens != null
|
|
58
|
+
|| usage.completion_tokens != null
|
|
59
|
+
|| usage.total_tokens != null
|
|
60
|
+
|| usage.input_tokens != null
|
|
61
|
+
|| usage.output_tokens != null;
|
|
62
|
+
if (!hasUsageFields) return;
|
|
63
|
+
|
|
64
|
+
const promptTokens = parseUsageNumber(usage.prompt_tokens ?? usage.input_tokens);
|
|
65
|
+
const completionTokens = parseUsageNumber(usage.completion_tokens ?? usage.output_tokens);
|
|
66
|
+
let totalTokens = parseUsageNumber(usage.total_tokens);
|
|
67
|
+
if (totalTokens === 0 && (promptTokens > 0 || completionTokens > 0)) {
|
|
68
|
+
totalTokens = promptTokens + completionTokens;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
stats.apiUsageAvailable = true;
|
|
72
|
+
stats.apiPromptTokens += promptTokens;
|
|
73
|
+
stats.apiCompletionTokens += completionTokens;
|
|
74
|
+
stats.apiTotalTokens += totalTokens;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function finalizeTokenUsage(stats: TokenUsageStats): TokenUsageStats {
|
|
78
|
+
const estimatedTotalTokens = stats.estimatedPromptTokens + stats.estimatedCompletionTokens;
|
|
79
|
+
let apiTotalTokens = stats.apiTotalTokens;
|
|
80
|
+
if (stats.apiUsageAvailable && apiTotalTokens === 0) {
|
|
81
|
+
apiTotalTokens = stats.apiPromptTokens + stats.apiCompletionTokens;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
...stats,
|
|
86
|
+
apiTotalTokens,
|
|
87
|
+
estimatedTotalTokens,
|
|
88
|
+
};
|
|
89
|
+
}
|
package/container/src/tools.ts
CHANGED
|
@@ -879,7 +879,14 @@ export async function executeTool(name: string, argsJson: string): Promise<strin
|
|
|
879
879
|
});
|
|
880
880
|
const header = result.title ? `# ${result.title}\n\n` : '';
|
|
881
881
|
const meta = `[${result.extractor}] ${result.finalUrl} (${result.status}, ${result.tookMs}ms)`;
|
|
882
|
-
|
|
882
|
+
const lines = [meta];
|
|
883
|
+
if (result.escalationHint) {
|
|
884
|
+
lines.push(`Escalation hint: ${result.escalationHint} (retry with browser_navigate for this URL).`);
|
|
885
|
+
}
|
|
886
|
+
if (result.warning) {
|
|
887
|
+
lines.push(`Warning: ${result.warning}`);
|
|
888
|
+
}
|
|
889
|
+
return `${lines.join('\n')}\n\n${header}${result.text}`;
|
|
883
890
|
}
|
|
884
891
|
|
|
885
892
|
case 'browser_navigate':
|
|
@@ -1207,7 +1214,7 @@ export const TOOL_DEFINITIONS: ToolDefinition[] = [
|
|
|
1207
1214
|
function: {
|
|
1208
1215
|
name: 'web_fetch',
|
|
1209
1216
|
description:
|
|
1210
|
-
'Fetch a URL and extract
|
|
1217
|
+
'Fetch a URL via plain HTTP GET and extract readable content (HTML to markdown/text). No JavaScript execution, no clicks, no form interaction. Use for static read-only retrieval: articles, docs, wikis, READMEs, API JSON/text endpoints, and direct files/PDFs. Avoid for SPAs (React/Vue/Angular/Next client routes), auth/login-gated pages, dashboards/web apps, bot/challenge flows, or content loaded after render via XHR/fetch. Cost: typically ~10-100x cheaper/faster than browser tools. Default to web_fetch for read-only retrieval, then escalate to browser_navigate when output is empty/boilerplate, JavaScript-required, SPA shell-only, or bot-blocked.',
|
|
1211
1218
|
parameters: {
|
|
1212
1219
|
type: 'object',
|
|
1213
1220
|
properties: {
|
package/container/src/types.ts
CHANGED
|
@@ -25,6 +25,13 @@ export interface ChatCompletionResponse {
|
|
|
25
25
|
finish_reason: string;
|
|
26
26
|
}>;
|
|
27
27
|
model: string;
|
|
28
|
+
usage?: {
|
|
29
|
+
prompt_tokens?: number;
|
|
30
|
+
completion_tokens?: number;
|
|
31
|
+
total_tokens?: number;
|
|
32
|
+
input_tokens?: number;
|
|
33
|
+
output_tokens?: number;
|
|
34
|
+
};
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
export interface ToolDefinition {
|
|
@@ -76,6 +83,17 @@ export interface ToolExecution {
|
|
|
76
83
|
blockedReason?: string;
|
|
77
84
|
}
|
|
78
85
|
|
|
86
|
+
export interface TokenUsageStats {
|
|
87
|
+
modelCalls: number;
|
|
88
|
+
apiUsageAvailable: boolean;
|
|
89
|
+
apiPromptTokens: number;
|
|
90
|
+
apiCompletionTokens: number;
|
|
91
|
+
apiTotalTokens: number;
|
|
92
|
+
estimatedPromptTokens: number;
|
|
93
|
+
estimatedCompletionTokens: number;
|
|
94
|
+
estimatedTotalTokens: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
79
97
|
export interface ArtifactMetadata {
|
|
80
98
|
path: string;
|
|
81
99
|
filename: string;
|
|
@@ -88,6 +106,7 @@ export interface ContainerOutput {
|
|
|
88
106
|
toolsUsed: string[];
|
|
89
107
|
artifacts?: ArtifactMetadata[];
|
|
90
108
|
toolExecutions?: ToolExecution[];
|
|
109
|
+
tokenUsage?: TokenUsageStats;
|
|
91
110
|
error?: string;
|
|
92
111
|
sideEffects?: {
|
|
93
112
|
schedules?: ScheduleSideEffect[];
|
|
@@ -19,6 +19,25 @@ const TIMEOUT_MS = 30_000;
|
|
|
19
19
|
const CACHE_TTL_MS = 15 * 60_000; // 15 min
|
|
20
20
|
const CACHE_MAX_ENTRIES = 100;
|
|
21
21
|
const READABILITY_MAX_HTML_CHARS = 1_000_000;
|
|
22
|
+
const ESCALATION_MIN_TEXT_CHARS = 200;
|
|
23
|
+
const ESCALATION_MIN_HTML_CHARS = 5_000;
|
|
24
|
+
const BOT_BLOCKED_PATTERNS = [
|
|
25
|
+
'access denied',
|
|
26
|
+
'bot detected',
|
|
27
|
+
'captcha',
|
|
28
|
+
'cf-chl-',
|
|
29
|
+
'checking your browser',
|
|
30
|
+
'cloudflare',
|
|
31
|
+
'just a moment',
|
|
32
|
+
'attention required',
|
|
33
|
+
'verification required',
|
|
34
|
+
];
|
|
35
|
+
const JAVASCRIPT_REQUIRED_PATTERNS = [
|
|
36
|
+
'enable javascript',
|
|
37
|
+
'javascript required',
|
|
38
|
+
'requires javascript',
|
|
39
|
+
'turn on javascript',
|
|
40
|
+
];
|
|
22
41
|
const USER_AGENT =
|
|
23
42
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_7_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36';
|
|
24
43
|
|
|
@@ -271,10 +290,71 @@ async function fetchWithRedirects(
|
|
|
271
290
|
throw new Error(`Too many redirects (max ${maxRedirects})`);
|
|
272
291
|
}
|
|
273
292
|
|
|
293
|
+
function normalizeForDetection(value: string): string {
|
|
294
|
+
return String(value || '').toLowerCase().replace(/\s+/g, ' ').trim();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function includesAny(haystack: string, needles: readonly string[]): boolean {
|
|
298
|
+
for (const needle of needles) {
|
|
299
|
+
if (haystack.includes(needle)) return true;
|
|
300
|
+
}
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function detectEscalationHint(params: {
|
|
305
|
+
status: number;
|
|
306
|
+
contentType: string;
|
|
307
|
+
body: string;
|
|
308
|
+
extractedText: string;
|
|
309
|
+
}): WebFetchEscalationHint | undefined {
|
|
310
|
+
const normalizedBody = normalizeForDetection(params.body);
|
|
311
|
+
if (params.status === 403 || params.status === 429 || includesAny(normalizedBody, BOT_BLOCKED_PATTERNS)) {
|
|
312
|
+
return 'bot_blocked';
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const isHtml = params.contentType.toLowerCase().includes('text/html');
|
|
316
|
+
if (!isHtml) return undefined;
|
|
317
|
+
|
|
318
|
+
if (
|
|
319
|
+
/<noscript[\s\S]{0,2000}javascript[\s\S]{0,2000}<\/noscript>/i.test(params.body) ||
|
|
320
|
+
includesAny(normalizedBody, JAVASCRIPT_REQUIRED_PATTERNS)
|
|
321
|
+
) {
|
|
322
|
+
return 'javascript_required';
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (
|
|
326
|
+
/<div[^>]+id=["'](?:root|app|__next)["'][^>]*>\s*<\/div>/i.test(params.body) &&
|
|
327
|
+
normalizeForDetection(params.extractedText).length < ESCALATION_MIN_TEXT_CHARS
|
|
328
|
+
) {
|
|
329
|
+
return 'spa_shell_only';
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const normalizedExtracted = normalizeForDetection(params.extractedText);
|
|
333
|
+
if (normalizedExtracted.length === 0) {
|
|
334
|
+
return 'empty_extraction';
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (
|
|
338
|
+
normalizedExtracted.length < ESCALATION_MIN_TEXT_CHARS &&
|
|
339
|
+
params.body.length > ESCALATION_MIN_HTML_CHARS
|
|
340
|
+
) {
|
|
341
|
+
return 'boilerplate_only';
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return undefined;
|
|
345
|
+
}
|
|
346
|
+
|
|
274
347
|
// ---------------------------------------------------------------------------
|
|
275
348
|
// Public API
|
|
276
349
|
// ---------------------------------------------------------------------------
|
|
277
350
|
|
|
351
|
+
export type WebFetchEscalationHint =
|
|
352
|
+
| 'javascript_required'
|
|
353
|
+
| 'empty_extraction'
|
|
354
|
+
| 'spa_shell_only'
|
|
355
|
+
| 'bot_blocked'
|
|
356
|
+
| 'boilerplate_only';
|
|
357
|
+
|
|
278
358
|
export interface WebFetchResult {
|
|
279
359
|
url: string;
|
|
280
360
|
finalUrl: string;
|
|
@@ -290,6 +370,7 @@ export interface WebFetchResult {
|
|
|
290
370
|
text: string;
|
|
291
371
|
cached?: boolean;
|
|
292
372
|
warning?: string;
|
|
373
|
+
escalationHint?: WebFetchEscalationHint;
|
|
293
374
|
}
|
|
294
375
|
|
|
295
376
|
export async function webFetch(params: {
|
|
@@ -327,10 +408,6 @@ export async function webFetch(params: {
|
|
|
327
408
|
controller.signal,
|
|
328
409
|
);
|
|
329
410
|
|
|
330
|
-
if (!res.ok) {
|
|
331
|
-
throw new Error(`Web fetch failed (${res.status}): ${res.statusText}`);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
411
|
const contentType = res.headers.get('content-type') ?? 'application/octet-stream';
|
|
335
412
|
const normalizedContentType = contentType.split(';')[0]?.trim() || 'application/octet-stream';
|
|
336
413
|
const bodyResult = await readResponseText(res, MAX_RESPONSE_BYTES);
|
|
@@ -357,13 +434,26 @@ export async function webFetch(params: {
|
|
|
357
434
|
}
|
|
358
435
|
}
|
|
359
436
|
|
|
437
|
+
const extractedText = extractMode === 'text' ? text : markdownToText(text);
|
|
438
|
+
const escalationHint = detectEscalationHint({
|
|
439
|
+
status: res.status,
|
|
440
|
+
contentType: normalizedContentType,
|
|
441
|
+
body,
|
|
442
|
+
extractedText,
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
if (!res.ok && !escalationHint) {
|
|
446
|
+
throw new Error(`Web fetch failed (${res.status}): ${res.statusText}`);
|
|
447
|
+
}
|
|
448
|
+
|
|
360
449
|
// Truncate
|
|
361
450
|
const truncated = text.length > maxChars;
|
|
362
451
|
if (truncated) text = text.slice(0, maxChars);
|
|
363
452
|
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
453
|
+
const warnings: string[] = [];
|
|
454
|
+
if (!res.ok) warnings.push(`HTTP ${res.status} ${res.statusText}.`);
|
|
455
|
+
if (bodyResult.truncated) warnings.push(`Response body truncated after ${MAX_RESPONSE_BYTES} bytes.`);
|
|
456
|
+
const warning = warnings.length > 0 ? warnings.join(' ') : undefined;
|
|
367
457
|
|
|
368
458
|
const result: WebFetchResult = {
|
|
369
459
|
url: params.url,
|
|
@@ -379,6 +469,7 @@ export async function webFetch(params: {
|
|
|
379
469
|
tookMs: Date.now() - start,
|
|
380
470
|
text,
|
|
381
471
|
warning,
|
|
472
|
+
escalationHint,
|
|
382
473
|
};
|
|
383
474
|
|
|
384
475
|
writeCache(cacheKey, result);
|
package/dist/agent.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ChatMessage, ContainerOutput, ScheduledTask, ToolProgressEvent } from './types.js';
|
|
2
|
-
export declare function runAgent(sessionId: string, messages: ChatMessage[], chatbotId: string, enableRag: boolean, model: string, agentId: string, channelId: string, scheduledTasks?: ScheduledTask[], allowedTools?: string[], onToolProgress?: (event: ToolProgressEvent) => void, abortSignal?: AbortSignal): Promise<ContainerOutput>;
|
|
2
|
+
export declare function runAgent(sessionId: string, messages: ChatMessage[], chatbotId: string, enableRag: boolean, model: string, agentId: string, channelId: string, scheduledTasks?: ScheduledTask[], allowedTools?: string[], onTextDelta?: (delta: string) => void, onToolProgress?: (event: ToolProgressEvent) => void, abortSignal?: AbortSignal): Promise<ContainerOutput>;
|
|
3
3
|
//# sourceMappingURL=agent.d.ts.map
|
package/dist/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAWjG,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,aAAa,EAAE,EAChC,YAAY,CAAC,EAAE,MAAM,EAAE,EACvB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,EACnD,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAWjG,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,aAAa,EAAE,EAChC,YAAY,CAAC,EAAE,MAAM,EAAE,EACvB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACrC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,EACnD,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAgB1B"}
|
package/dist/agent.js
CHANGED
|
@@ -14,8 +14,8 @@ function dumpPrompt(sessionId, messages, model, chatbotId) {
|
|
|
14
14
|
}
|
|
15
15
|
catch { /* best-effort */ }
|
|
16
16
|
}
|
|
17
|
-
export async function runAgent(sessionId, messages, chatbotId, enableRag, model, agentId, channelId, scheduledTasks, allowedTools, onToolProgress, abortSignal) {
|
|
17
|
+
export async function runAgent(sessionId, messages, chatbotId, enableRag, model, agentId, channelId, scheduledTasks, allowedTools, onTextDelta, onToolProgress, abortSignal) {
|
|
18
18
|
dumpPrompt(sessionId, messages, model, chatbotId);
|
|
19
|
-
return runContainer(sessionId, messages, chatbotId, enableRag, model, agentId, channelId, scheduledTasks, allowedTools, onToolProgress, abortSignal);
|
|
19
|
+
return runContainer(sessionId, messages, chatbotId, enableRag, model, agentId, channelId, scheduledTasks, allowedTools, onTextDelta, onToolProgress, abortSignal);
|
|
20
20
|
}
|
|
21
21
|
//# sourceMappingURL=agent.js.map
|
package/dist/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,yFAAyF;AACzF,SAAS,UAAU,CAAC,SAAiB,EAAE,QAAuB,EAAE,KAAa,EAAE,SAAiB;IAC9F,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;QACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QAC1D,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,SAAiB,EACjB,QAAuB,EACvB,SAAiB,EACjB,SAAkB,EAClB,KAAa,EACb,OAAe,EACf,SAAiB,EACjB,cAAgC,EAChC,YAAuB,EACvB,cAAmD,EACnD,WAAyB;IAEzB,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAClD,OAAO,YAAY,
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,yFAAyF;AACzF,SAAS,UAAU,CAAC,SAAiB,EAAE,QAAuB,EAAE,KAAa,EAAE,SAAiB;IAC9F,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;QACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QAC1D,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,SAAiB,EACjB,QAAuB,EACvB,SAAiB,EACjB,SAAkB,EAClB,KAAa,EACb,OAAe,EACf,SAAiB,EACjB,cAAgC,EAChC,YAAuB,EACvB,WAAqC,EACrC,cAAmD,EACnD,WAAyB;IAEzB,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAClD,OAAO,YAAY,CACjB,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,SAAS,EACT,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,WAAW,CACZ,CAAC;AACJ,CAAC"}
|
package/dist/chunk.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk.d.ts","sourceRoot":"","sources":["../src/chunk.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiFD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,MAAM,EAAE,CAoE/E"}
|
package/dist/chunk.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const DEFAULT_MAX_CHARS = 1_900;
|
|
2
|
+
const DEFAULT_MAX_LINES = 20;
|
|
3
|
+
function isFenceLine(line) {
|
|
4
|
+
return line.trim().startsWith('```');
|
|
5
|
+
}
|
|
6
|
+
function parseFenceLanguage(line) {
|
|
7
|
+
const trimmed = line.trim();
|
|
8
|
+
if (!trimmed.startsWith('```'))
|
|
9
|
+
return '';
|
|
10
|
+
return trimmed.slice(3).trim();
|
|
11
|
+
}
|
|
12
|
+
function findSentenceBoundary(input) {
|
|
13
|
+
let best = -1;
|
|
14
|
+
const re = /[.!?]\s+/g;
|
|
15
|
+
for (let match = re.exec(input); match; match = re.exec(input)) {
|
|
16
|
+
best = match.index + match[0].length;
|
|
17
|
+
}
|
|
18
|
+
return best;
|
|
19
|
+
}
|
|
20
|
+
function findPreferredSplit(input, hardLimit) {
|
|
21
|
+
const limit = Math.max(1, Math.min(hardLimit, input.length));
|
|
22
|
+
const window = input.slice(0, limit);
|
|
23
|
+
const paragraph = window.lastIndexOf('\n\n');
|
|
24
|
+
if (paragraph >= Math.floor(limit * 0.45)) {
|
|
25
|
+
return paragraph + 2;
|
|
26
|
+
}
|
|
27
|
+
const line = window.lastIndexOf('\n');
|
|
28
|
+
if (line >= Math.floor(limit * 0.45)) {
|
|
29
|
+
return line + 1;
|
|
30
|
+
}
|
|
31
|
+
const sentence = findSentenceBoundary(window);
|
|
32
|
+
if (sentence >= Math.floor(limit * 0.45)) {
|
|
33
|
+
return sentence;
|
|
34
|
+
}
|
|
35
|
+
const word = window.lastIndexOf(' ');
|
|
36
|
+
if (word >= Math.floor(limit * 0.35)) {
|
|
37
|
+
return word + 1;
|
|
38
|
+
}
|
|
39
|
+
return limit;
|
|
40
|
+
}
|
|
41
|
+
function splitLongLine(line, maxChars) {
|
|
42
|
+
if (line.length <= maxChars)
|
|
43
|
+
return [line];
|
|
44
|
+
const pieces = [];
|
|
45
|
+
let remaining = line;
|
|
46
|
+
while (remaining.length > maxChars) {
|
|
47
|
+
let splitAt = findPreferredSplit(remaining, maxChars);
|
|
48
|
+
if (splitAt <= 0 || splitAt > remaining.length) {
|
|
49
|
+
splitAt = Math.min(maxChars, remaining.length);
|
|
50
|
+
}
|
|
51
|
+
const head = remaining.slice(0, splitAt).trimEnd();
|
|
52
|
+
if (!head) {
|
|
53
|
+
const fallback = remaining.slice(0, maxChars);
|
|
54
|
+
pieces.push(fallback);
|
|
55
|
+
remaining = remaining.slice(maxChars);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
pieces.push(head);
|
|
59
|
+
remaining = remaining.slice(splitAt).trimStart();
|
|
60
|
+
}
|
|
61
|
+
if (remaining.length > 0) {
|
|
62
|
+
pieces.push(remaining);
|
|
63
|
+
}
|
|
64
|
+
return pieces;
|
|
65
|
+
}
|
|
66
|
+
export function chunkMessage(text, opts) {
|
|
67
|
+
const maxChars = Math.max(200, opts?.maxChars ?? DEFAULT_MAX_CHARS);
|
|
68
|
+
const maxLines = Math.max(4, opts?.maxLines ?? DEFAULT_MAX_LINES);
|
|
69
|
+
const normalized = (text || '').replace(/\r\n?/g, '\n');
|
|
70
|
+
if (!normalized.trim())
|
|
71
|
+
return [];
|
|
72
|
+
const inputLines = normalized.split('\n');
|
|
73
|
+
const chunks = [];
|
|
74
|
+
let currentLines = [];
|
|
75
|
+
let currentChars = 0;
|
|
76
|
+
let openFence = false;
|
|
77
|
+
let fenceLanguage = '';
|
|
78
|
+
const flush = (isFinal) => {
|
|
79
|
+
if (currentLines.length === 0)
|
|
80
|
+
return;
|
|
81
|
+
let chunk = currentLines.join('\n');
|
|
82
|
+
if (openFence) {
|
|
83
|
+
chunk += '\n```';
|
|
84
|
+
}
|
|
85
|
+
chunks.push(chunk);
|
|
86
|
+
if (!isFinal && openFence) {
|
|
87
|
+
const reopenedFence = fenceLanguage ? `\`\`\`${fenceLanguage}` : '```';
|
|
88
|
+
currentLines = [reopenedFence];
|
|
89
|
+
currentChars = reopenedFence.length;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
currentLines = [];
|
|
93
|
+
currentChars = 0;
|
|
94
|
+
if (isFinal && openFence) {
|
|
95
|
+
openFence = false;
|
|
96
|
+
fenceLanguage = '';
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const appendLine = (line) => {
|
|
101
|
+
const addedChars = currentLines.length === 0 ? line.length : line.length + 1;
|
|
102
|
+
const nextChars = currentChars + addedChars;
|
|
103
|
+
const nextLines = currentLines.length + 1;
|
|
104
|
+
if (currentLines.length > 0 && (nextChars > maxChars || nextLines > maxLines)) {
|
|
105
|
+
flush(false);
|
|
106
|
+
}
|
|
107
|
+
currentLines.push(line);
|
|
108
|
+
currentChars = currentLines.length === 1 ? line.length : currentChars + line.length + 1;
|
|
109
|
+
if (isFenceLine(line)) {
|
|
110
|
+
if (!openFence) {
|
|
111
|
+
openFence = true;
|
|
112
|
+
fenceLanguage = parseFenceLanguage(line);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
openFence = false;
|
|
116
|
+
fenceLanguage = '';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
for (const rawLine of inputLines) {
|
|
121
|
+
const splitLines = splitLongLine(rawLine, maxChars);
|
|
122
|
+
for (const part of splitLines) {
|
|
123
|
+
appendLine(part);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
flush(true);
|
|
127
|
+
return chunks;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=chunk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk.js","sourceRoot":"","sources":["../src/chunk.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ export declare function getActiveContainerCount(): number;
|
|
|
3
3
|
/**
|
|
4
4
|
* Send a request to a persistent container and wait for the response.
|
|
5
5
|
*/
|
|
6
|
-
export declare function runContainer(sessionId: string, messages: ChatMessage[], chatbotId: string, enableRag: boolean, model?: string, agentId?: string, channelId?: string, scheduledTasks?: ScheduledTask[], allowedTools?: string[], onToolProgress?: (event: ToolProgressEvent) => void, abortSignal?: AbortSignal): Promise<ContainerOutput>;
|
|
6
|
+
export declare function runContainer(sessionId: string, messages: ChatMessage[], chatbotId: string, enableRag: boolean, model?: string, agentId?: string, channelId?: string, scheduledTasks?: ScheduledTask[], allowedTools?: string[], onTextDelta?: (delta: string) => void, onToolProgress?: (event: ToolProgressEvent) => void, abortSignal?: AbortSignal): Promise<ContainerOutput>;
|
|
7
7
|
/**
|
|
8
8
|
* Stop all containers (for graceful shutdown).
|
|
9
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container-runner.d.ts","sourceRoot":"","sources":["../src/container-runner.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAqC,WAAW,EAAkB,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"container-runner.d.ts","sourceRoot":"","sources":["../src/container-runner.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAqC,WAAW,EAAkB,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAsEpJ,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAuKD;;GAEG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,KAAK,GAAE,MAAuB,EAC9B,OAAO,GAAE,MAAkB,EAC3B,SAAS,GAAE,MAAW,EACtB,cAAc,CAAC,EAAE,aAAa,EAAE,EAChC,YAAY,CAAC,EAAE,MAAM,EAAE,EACvB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EACrC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,EACnD,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,eAAe,CAAC,CAgG1B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAMxC"}
|