@huydao/karrot 0.1.7 → 0.1.8
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.
|
@@ -6,6 +6,7 @@ export type RunAgUiPostMessageOptions = {
|
|
|
6
6
|
processTimeoutMs?: number;
|
|
7
7
|
injectMessage?: boolean;
|
|
8
8
|
injectRunMetadata?: boolean;
|
|
9
|
+
textEvents?: AgUiPostTextEventConfig[];
|
|
9
10
|
run?: {
|
|
10
11
|
url: string;
|
|
11
12
|
headers?: Record<string, string>;
|
|
@@ -52,4 +53,13 @@ export type RunAgUiPostMessageOptions = {
|
|
|
52
53
|
timeoutMs?: number;
|
|
53
54
|
};
|
|
54
55
|
};
|
|
56
|
+
export type AgUiPostTextEventConfig = {
|
|
57
|
+
type: string;
|
|
58
|
+
name?: string;
|
|
59
|
+
role?: string;
|
|
60
|
+
textPath?: string;
|
|
61
|
+
contentPath?: string;
|
|
62
|
+
deltaPath?: string;
|
|
63
|
+
mode?: 'content' | 'delta';
|
|
64
|
+
};
|
|
55
65
|
export declare function runAgUiPostMessage(options: RunAgUiPostMessageOptions): Promise<MessageRunResult>;
|
|
@@ -56,6 +56,13 @@ function getStringAtPath(payload, pathExpression) {
|
|
|
56
56
|
const rawValue = getValueByPath(payload, pathExpression);
|
|
57
57
|
return typeof rawValue === 'string' ? rawValue.trim() : '';
|
|
58
58
|
}
|
|
59
|
+
function getRawStringAtPath(payload, pathExpression) {
|
|
60
|
+
if (!pathExpression) {
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
const rawValue = getValueByPath(payload, pathExpression);
|
|
64
|
+
return typeof rawValue === 'string' ? rawValue : '';
|
|
65
|
+
}
|
|
59
66
|
function getArrayAtPath(payload, pathExpression) {
|
|
60
67
|
const rawValue = getValueByPath(payload, pathExpression);
|
|
61
68
|
return Array.isArray(rawValue) ? rawValue : [];
|
|
@@ -278,15 +285,80 @@ function roundSeconds(startTimeMs, endTimeMs) {
|
|
|
278
285
|
}
|
|
279
286
|
return Number(((endTimeMs - startTimeMs) / 1000).toFixed(1));
|
|
280
287
|
}
|
|
281
|
-
function
|
|
288
|
+
function isStandardAssistantTextEvent(event) {
|
|
282
289
|
return (event.type === 'TEXT_MESSAGE_CONTENT' ||
|
|
283
|
-
event.type === 'TEXT_MESSAGE_CHUNK'
|
|
284
|
-
(event.type === 'CUSTOM' && event.name === 'super-testing-agent.model_stream_chunk'));
|
|
290
|
+
event.type === 'TEXT_MESSAGE_CHUNK');
|
|
285
291
|
}
|
|
286
292
|
function isToolStartEvent(event) {
|
|
287
293
|
return (event.type === 'TOOL_CALL_START' ||
|
|
288
294
|
(event.type === 'CUSTOM' && event.name === 'super-testing-agent.tool_started'));
|
|
289
295
|
}
|
|
296
|
+
function matchesConfiguredTextEvent(event, config) {
|
|
297
|
+
if (event.type !== config.type) {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
if (config.name != null && event.name !== config.name) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
if (config.role != null && event.role !== config.role) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
function getConfiguredTextEventValue(event, textEvents) {
|
|
309
|
+
for (const config of textEvents ?? []) {
|
|
310
|
+
if (!matchesConfiguredTextEvent(event, config)) {
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const content = getRawStringAtPath(event, config.contentPath);
|
|
314
|
+
if (content.trim()) {
|
|
315
|
+
return { content: content.trim() };
|
|
316
|
+
}
|
|
317
|
+
const delta = getRawStringAtPath(event, config.deltaPath);
|
|
318
|
+
if (delta) {
|
|
319
|
+
return { delta };
|
|
320
|
+
}
|
|
321
|
+
const text = getRawStringAtPath(event, config.textPath);
|
|
322
|
+
if (!text) {
|
|
323
|
+
return {};
|
|
324
|
+
}
|
|
325
|
+
return config.mode === 'content' ? { content: text.trim() } : { delta: text };
|
|
326
|
+
}
|
|
327
|
+
return {};
|
|
328
|
+
}
|
|
329
|
+
function isAssistantTextEvent(event, textEvents) {
|
|
330
|
+
return (isStandardAssistantTextEvent(event) ||
|
|
331
|
+
Boolean((textEvents ?? []).find((config) => matchesConfiguredTextEvent(event, config))));
|
|
332
|
+
}
|
|
333
|
+
function getAssistantContent(event, textEvents) {
|
|
334
|
+
const configured = getConfiguredTextEventValue(event, textEvents);
|
|
335
|
+
if (configured.content) {
|
|
336
|
+
return configured.content;
|
|
337
|
+
}
|
|
338
|
+
if (typeof event.content === 'string' && event.content.trim()) {
|
|
339
|
+
return event.content.trim();
|
|
340
|
+
}
|
|
341
|
+
if (typeof event.value?.content === 'string' && event.value.content.trim()) {
|
|
342
|
+
return event.value.content.trim();
|
|
343
|
+
}
|
|
344
|
+
if (typeof event.value?.output === 'string' && event.value.output.trim()) {
|
|
345
|
+
return event.value.output.trim();
|
|
346
|
+
}
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
function getAssistantDelta(event, textEvents) {
|
|
350
|
+
const configured = getConfiguredTextEventValue(event, textEvents);
|
|
351
|
+
if (configured.delta) {
|
|
352
|
+
return configured.delta;
|
|
353
|
+
}
|
|
354
|
+
if (typeof event.delta === 'string' && event.delta) {
|
|
355
|
+
return event.delta;
|
|
356
|
+
}
|
|
357
|
+
if (typeof event.value?.delta === 'string' && event.value.delta) {
|
|
358
|
+
return event.value.delta;
|
|
359
|
+
}
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
290
362
|
function createConnectCollector(options) {
|
|
291
363
|
const assistantFragments = [];
|
|
292
364
|
const toolCalls = [];
|
|
@@ -335,13 +407,15 @@ function createConnectCollector(options) {
|
|
|
335
407
|
});
|
|
336
408
|
}
|
|
337
409
|
const isAssistantMessage = parsed.role === 'assistant' || typeof parsed.role !== 'string';
|
|
338
|
-
if (isAssistantTextEvent(parsed) && isAssistantMessage) {
|
|
410
|
+
if (isAssistantTextEvent(parsed, options.textEvents) && isAssistantMessage) {
|
|
339
411
|
firstTextAt ??= eventTime(parsed);
|
|
340
|
-
|
|
341
|
-
|
|
412
|
+
const content = getAssistantContent(parsed, options.textEvents);
|
|
413
|
+
const delta = getAssistantDelta(parsed, options.textEvents);
|
|
414
|
+
if (content) {
|
|
415
|
+
latestAssistantContent = content;
|
|
342
416
|
}
|
|
343
|
-
else if (
|
|
344
|
-
assistantFragments.push(
|
|
417
|
+
else if (delta) {
|
|
418
|
+
assistantFragments.push(delta);
|
|
345
419
|
}
|
|
346
420
|
}
|
|
347
421
|
if (isToolStartEvent(parsed)) {
|
|
@@ -469,11 +543,12 @@ function startConnectStream(options) {
|
|
|
469
543
|
const collector = createConnectCollector({
|
|
470
544
|
targetRunId: options.targetRunId,
|
|
471
545
|
fallbackThreadId: options.fallbackThreadId,
|
|
546
|
+
textEvents: options.textEvents,
|
|
472
547
|
});
|
|
473
548
|
if (!response.body) {
|
|
474
549
|
const rawContent = await response.text();
|
|
475
550
|
await promises_1.default.writeFile(options.outputPath, rawContent, 'utf8');
|
|
476
|
-
const parsed = extractResultFromSse(rawContent, options.fallbackThreadId);
|
|
551
|
+
const parsed = extractResultFromSse(rawContent, options.fallbackThreadId, {}, options.textEvents);
|
|
477
552
|
return {
|
|
478
553
|
output: parsed.output,
|
|
479
554
|
toolCalls: parsed.toolCalls,
|
|
@@ -546,7 +621,7 @@ function startConnectStream(options) {
|
|
|
546
621
|
result,
|
|
547
622
|
};
|
|
548
623
|
}
|
|
549
|
-
function extractResultFromSse(rawContent, fallbackThreadId, fallbackMetrics = {}) {
|
|
624
|
+
function extractResultFromSse(rawContent, fallbackThreadId, fallbackMetrics = {}, textEvents) {
|
|
550
625
|
const fragments = [];
|
|
551
626
|
let latestContent;
|
|
552
627
|
let resolvedThreadId = fallbackThreadId;
|
|
@@ -573,13 +648,15 @@ function extractResultFromSse(rawContent, fallbackThreadId, fallbackMetrics = {}
|
|
|
573
648
|
if (parsed.type === 'RUN_STARTED' && typeof runStartedAt !== 'number') {
|
|
574
649
|
runStartedAt = normalizeEventTimestamp(parsed.timestamp);
|
|
575
650
|
}
|
|
576
|
-
if (isAssistantTextEvent(parsed)) {
|
|
651
|
+
if (isAssistantTextEvent(parsed, textEvents)) {
|
|
577
652
|
firstTextAt ??= normalizeEventTimestamp(parsed.timestamp);
|
|
578
|
-
|
|
579
|
-
|
|
653
|
+
const content = getAssistantContent(parsed, textEvents);
|
|
654
|
+
const delta = getAssistantDelta(parsed, textEvents);
|
|
655
|
+
if (content) {
|
|
656
|
+
latestContent = content;
|
|
580
657
|
}
|
|
581
|
-
else if (
|
|
582
|
-
fragments.push(
|
|
658
|
+
else if (delta) {
|
|
659
|
+
fragments.push(delta);
|
|
583
660
|
}
|
|
584
661
|
}
|
|
585
662
|
if (isToolStartEvent(parsed)) {
|
|
@@ -663,6 +740,7 @@ async function runAgUiPostMessage(options) {
|
|
|
663
740
|
targetRunId: runId,
|
|
664
741
|
fallbackThreadId: resolvedThreadId,
|
|
665
742
|
processTimeoutMs: options.connect.processTimeoutMs ?? options.processTimeoutMs,
|
|
743
|
+
textEvents: options.textEvents,
|
|
666
744
|
});
|
|
667
745
|
await connectStream.ready;
|
|
668
746
|
const runResponse = await postAndCaptureResponse({
|
|
@@ -717,7 +795,7 @@ async function runAgUiPostMessage(options) {
|
|
|
717
795
|
const parsed = extractResultFromSse(runResponse.rawContent, resolvedThreadId, {
|
|
718
796
|
startTimeMs: runResponse.startedAtMs,
|
|
719
797
|
finishedTimeMs: runResponse.finishedAtMs,
|
|
720
|
-
});
|
|
798
|
+
}, options.textEvents);
|
|
721
799
|
if (options.observe) {
|
|
722
800
|
await promises_1.default.writeFile(observePath, '', 'utf8');
|
|
723
801
|
const observed = await waitForObservedCompletion({
|
|
@@ -48,6 +48,7 @@ function createAgUiPostRunner(config) {
|
|
|
48
48
|
processTimeoutMs: processTimeoutMs ?? transport.processTimeoutMs,
|
|
49
49
|
injectMessage: transport.injectMessage,
|
|
50
50
|
injectRunMetadata: transport.injectRunMetadata,
|
|
51
|
+
textEvents: transport.textEvents,
|
|
51
52
|
run: transport.run ?? transport.request,
|
|
52
53
|
connect: transport.connect,
|
|
53
54
|
observe: transport.observe,
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -22,6 +22,15 @@ export type KarrotConfig = {
|
|
|
22
22
|
type: 'ag-ui-post';
|
|
23
23
|
injectMessage?: boolean;
|
|
24
24
|
injectRunMetadata?: boolean;
|
|
25
|
+
textEvents?: Array<{
|
|
26
|
+
type: string;
|
|
27
|
+
name?: string;
|
|
28
|
+
role?: string;
|
|
29
|
+
textPath?: string;
|
|
30
|
+
contentPath?: string;
|
|
31
|
+
deltaPath?: string;
|
|
32
|
+
mode?: 'content' | 'delta';
|
|
33
|
+
}>;
|
|
25
34
|
run?: {
|
|
26
35
|
url: string;
|
|
27
36
|
headers?: Record<string, string>;
|