@yeaft/webchat-agent 0.1.1028 → 0.1.1030
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/package.json +1 -1
- package/yeaft/debug-trace.js +21 -9
- package/yeaft/engine.js +40 -12
- package/yeaft/llm/adapter.js +1 -1
- package/yeaft/llm/anthropic.js +2 -0
- package/yeaft/llm/openai-responses.js +1 -0
- package/yeaft/web-bridge.js +3 -0
package/package.json
CHANGED
package/yeaft/debug-trace.js
CHANGED
|
@@ -449,6 +449,25 @@ export class DebugTrace {
|
|
|
449
449
|
try { return JSON.parse(s); }
|
|
450
450
|
catch { return null; }
|
|
451
451
|
};
|
|
452
|
+
const normalizeUsage = (usage, row) => {
|
|
453
|
+
const inputTokens = Number.isFinite(Number(usage?.inputTokens)) ? Number(usage.inputTokens) : (row.input_tokens || 0);
|
|
454
|
+
const outputTokens = Number.isFinite(Number(usage?.outputTokens)) ? Number(usage.outputTokens) : (row.output_tokens || 0);
|
|
455
|
+
const cacheReadTokens = Number.isFinite(Number(usage?.cacheReadTokens)) ? Number(usage.cacheReadTokens) : (row.cache_read_tokens || 0);
|
|
456
|
+
const cacheWriteTokens = Number.isFinite(Number(usage?.cacheWriteTokens)) ? Number(usage.cacheWriteTokens) : (row.cache_write_tokens || 0);
|
|
457
|
+
const totalInputTokens = Number.isFinite(Number(usage?.totalInputTokens))
|
|
458
|
+
? Number(usage.totalInputTokens)
|
|
459
|
+
: inputTokens + cacheReadTokens + cacheWriteTokens;
|
|
460
|
+
return {
|
|
461
|
+
inputTokens,
|
|
462
|
+
outputTokens,
|
|
463
|
+
cacheReadTokens,
|
|
464
|
+
cacheWriteTokens,
|
|
465
|
+
totalInputTokens,
|
|
466
|
+
totalTokens: Number.isFinite(Number(usage?.totalTokens))
|
|
467
|
+
? Number(usage.totalTokens)
|
|
468
|
+
: totalInputTokens + outputTokens,
|
|
469
|
+
};
|
|
470
|
+
};
|
|
452
471
|
// Group rows by (turnId, threadId, sessionId, vpId) → frontend Turn
|
|
453
472
|
// record. Each row is also surfaced as a Loop.
|
|
454
473
|
const turnsById = new Map();
|
|
@@ -463,11 +482,7 @@ export class DebugTrace {
|
|
|
463
482
|
messages: parsedMessages,
|
|
464
483
|
response: r.response_text || '',
|
|
465
484
|
toolCalls: parseJsonSafe(r.tool_calls_json) || [],
|
|
466
|
-
usage: parsedUsage
|
|
467
|
-
inputTokens: r.input_tokens || 0,
|
|
468
|
-
outputTokens: r.output_tokens || 0,
|
|
469
|
-
totalTokens: (r.input_tokens || 0) + (r.output_tokens || 0),
|
|
470
|
-
},
|
|
485
|
+
usage: normalizeUsage(parsedUsage, r),
|
|
471
486
|
latencyMs: r.latency_ms || 0,
|
|
472
487
|
ttfbMs: r.ttfb_ms || null,
|
|
473
488
|
stopReason: r.stop_reason || null,
|
|
@@ -504,10 +519,7 @@ export class DebugTrace {
|
|
|
504
519
|
// Aggregate per-loop latency / tokens so the Turn header shows the
|
|
505
520
|
// same totals the live `turn_close` event would have stamped.
|
|
506
521
|
t.totalMs += r.latency_ms || 0;
|
|
507
|
-
|
|
508
|
-
? parsedUsage.totalTokens
|
|
509
|
-
: (r.input_tokens || 0) + (r.output_tokens || 0);
|
|
510
|
-
t.totalTokens += usageTokens;
|
|
522
|
+
t.totalTokens += loop.usage.totalTokens || 0;
|
|
511
523
|
if (r.ended_at && (!t.closedAt || r.ended_at > t.closedAt)) t.closedAt = r.ended_at;
|
|
512
524
|
return loop;
|
|
513
525
|
});
|
package/yeaft/engine.js
CHANGED
|
@@ -1885,7 +1885,7 @@ export class Engine {
|
|
|
1885
1885
|
const toolCalls = [];
|
|
1886
1886
|
const thinkingBlocks = []; // task-327d: collected from adapter for round-trip
|
|
1887
1887
|
let stopReason = 'end_turn';
|
|
1888
|
-
const totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
1888
|
+
const totalUsage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, cacheInputDeltaTokens: 0 };
|
|
1889
1889
|
// task-344: capture redacted raw request / raw response for debug panel.
|
|
1890
1890
|
let rawRequest = null;
|
|
1891
1891
|
let rawResponse = null;
|
|
@@ -2080,13 +2080,22 @@ export class Engine {
|
|
|
2080
2080
|
toolCalls.push(event);
|
|
2081
2081
|
yield event;
|
|
2082
2082
|
break;
|
|
2083
|
-
case 'usage':
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2083
|
+
case 'usage': {
|
|
2084
|
+
const inputTokens = event.inputTokens || 0;
|
|
2085
|
+
const outputTokens = event.outputTokens || 0;
|
|
2086
|
+
const cacheReadTokens = event.cacheReadTokens || 0;
|
|
2087
|
+
const cacheWriteTokens = event.cacheWriteTokens || 0;
|
|
2088
|
+
const cacheInputDeltaTokens = event.cacheTokensAreIncludedInInput ? 0 : cacheReadTokens + cacheWriteTokens;
|
|
2089
|
+
totalUsage.inputTokens += inputTokens;
|
|
2090
|
+
totalUsage.outputTokens += outputTokens;
|
|
2091
|
+
totalUsage.cacheReadTokens += cacheReadTokens;
|
|
2092
|
+
totalUsage.cacheWriteTokens += cacheWriteTokens;
|
|
2093
|
+
totalUsage.cacheInputDeltaTokens += cacheInputDeltaTokens;
|
|
2094
|
+
cumulativeInputTokens += inputTokens + cacheInputDeltaTokens;
|
|
2095
|
+
cumulativeOutputTokens += outputTokens;
|
|
2088
2096
|
yield event;
|
|
2089
2097
|
break;
|
|
2098
|
+
}
|
|
2090
2099
|
case 'stop':
|
|
2091
2100
|
stopReason = event.stopReason;
|
|
2092
2101
|
yield event;
|
|
@@ -2107,6 +2116,8 @@ export class Engine {
|
|
|
2107
2116
|
model: currentModel,
|
|
2108
2117
|
inputTokens: totalUsage.inputTokens,
|
|
2109
2118
|
outputTokens: totalUsage.outputTokens,
|
|
2119
|
+
cacheReadTokens: totalUsage.cacheReadTokens,
|
|
2120
|
+
cacheWriteTokens: totalUsage.cacheWriteTokens,
|
|
2110
2121
|
stopReason: 'error',
|
|
2111
2122
|
latencyMs,
|
|
2112
2123
|
responseText,
|
|
@@ -2119,7 +2130,10 @@ export class Engine {
|
|
|
2119
2130
|
usage: {
|
|
2120
2131
|
inputTokens: totalUsage.inputTokens || 0,
|
|
2121
2132
|
outputTokens: totalUsage.outputTokens || 0,
|
|
2122
|
-
|
|
2133
|
+
cacheReadTokens: totalUsage.cacheReadTokens || 0,
|
|
2134
|
+
cacheWriteTokens: totalUsage.cacheWriteTokens || 0,
|
|
2135
|
+
totalInputTokens: (totalUsage.inputTokens || 0) + (totalUsage.cacheInputDeltaTokens || 0),
|
|
2136
|
+
totalTokens: (totalUsage.inputTokens || 0) + (totalUsage.cacheInputDeltaTokens || 0) + (totalUsage.outputTokens || 0),
|
|
2123
2137
|
},
|
|
2124
2138
|
ttfbMs,
|
|
2125
2139
|
rawRequest,
|
|
@@ -2127,7 +2141,7 @@ export class Engine {
|
|
|
2127
2141
|
});
|
|
2128
2142
|
|
|
2129
2143
|
// Emit `loop` event for error path too (was `debug_turn`).
|
|
2130
|
-
const errLoopInputTokens = totalUsage.inputTokens || 0;
|
|
2144
|
+
const errLoopInputTokens = (totalUsage.inputTokens || 0) + (totalUsage.cacheInputDeltaTokens || 0);
|
|
2131
2145
|
const errLoopOutputTokens = totalUsage.outputTokens || 0;
|
|
2132
2146
|
yield {
|
|
2133
2147
|
type: 'loop',
|
|
@@ -2140,8 +2154,11 @@ export class Engine {
|
|
|
2140
2154
|
response: responseText || `Error: ${err.message}`,
|
|
2141
2155
|
toolCalls: toolCalls.map(tc => ({ id: tc.id, name: tc.name, input: tc.input })),
|
|
2142
2156
|
usage: {
|
|
2143
|
-
inputTokens:
|
|
2157
|
+
inputTokens: totalUsage.inputTokens || 0,
|
|
2144
2158
|
outputTokens: errLoopOutputTokens,
|
|
2159
|
+
cacheReadTokens: totalUsage.cacheReadTokens || 0,
|
|
2160
|
+
cacheWriteTokens: totalUsage.cacheWriteTokens || 0,
|
|
2161
|
+
totalInputTokens: errLoopInputTokens,
|
|
2145
2162
|
totalTokens: errLoopInputTokens + errLoopOutputTokens,
|
|
2146
2163
|
},
|
|
2147
2164
|
latencyMs,
|
|
@@ -2250,11 +2267,16 @@ export class Engine {
|
|
|
2250
2267
|
|
|
2251
2268
|
const latencyMs = Date.now() - startTime;
|
|
2252
2269
|
|
|
2270
|
+
const turnInputTokens = (totalUsage.inputTokens || 0) + (totalUsage.cacheInputDeltaTokens || 0);
|
|
2271
|
+
const turnOutputTokens = totalUsage.outputTokens || 0;
|
|
2272
|
+
|
|
2253
2273
|
// Record turn in debug trace
|
|
2254
2274
|
this.#trace.endTurn(turnId, {
|
|
2255
2275
|
model: currentModel,
|
|
2256
2276
|
inputTokens: totalUsage.inputTokens,
|
|
2257
2277
|
outputTokens: totalUsage.outputTokens,
|
|
2278
|
+
cacheReadTokens: totalUsage.cacheReadTokens,
|
|
2279
|
+
cacheWriteTokens: totalUsage.cacheWriteTokens,
|
|
2258
2280
|
stopReason,
|
|
2259
2281
|
latencyMs,
|
|
2260
2282
|
responseText,
|
|
@@ -2268,7 +2290,10 @@ export class Engine {
|
|
|
2268
2290
|
usage: {
|
|
2269
2291
|
inputTokens: totalUsage.inputTokens || 0,
|
|
2270
2292
|
outputTokens: totalUsage.outputTokens || 0,
|
|
2271
|
-
|
|
2293
|
+
cacheReadTokens: totalUsage.cacheReadTokens || 0,
|
|
2294
|
+
cacheWriteTokens: totalUsage.cacheWriteTokens || 0,
|
|
2295
|
+
totalInputTokens: turnInputTokens,
|
|
2296
|
+
totalTokens: turnInputTokens + turnOutputTokens,
|
|
2272
2297
|
},
|
|
2273
2298
|
ttfbMs,
|
|
2274
2299
|
rawRequest,
|
|
@@ -2284,7 +2309,7 @@ export class Engine {
|
|
|
2284
2309
|
// task-331: preserve toolCalls / toolCallId / isError on each message
|
|
2285
2310
|
// so the panel can render function_call requests and their paired
|
|
2286
2311
|
// tool_result responses across loops.
|
|
2287
|
-
const loopInputTokens = totalUsage.inputTokens || 0;
|
|
2312
|
+
const loopInputTokens = (totalUsage.inputTokens || 0) + (totalUsage.cacheInputDeltaTokens || 0);
|
|
2288
2313
|
const loopOutputTokens = totalUsage.outputTokens || 0;
|
|
2289
2314
|
yield {
|
|
2290
2315
|
type: 'loop',
|
|
@@ -2296,8 +2321,11 @@ export class Engine {
|
|
|
2296
2321
|
response: responseText,
|
|
2297
2322
|
toolCalls: toolCalls.map(tc => ({ id: tc.id, name: tc.name, input: tc.input })),
|
|
2298
2323
|
usage: {
|
|
2299
|
-
inputTokens:
|
|
2324
|
+
inputTokens: totalUsage.inputTokens || 0,
|
|
2300
2325
|
outputTokens: loopOutputTokens,
|
|
2326
|
+
cacheReadTokens: totalUsage.cacheReadTokens || 0,
|
|
2327
|
+
cacheWriteTokens: totalUsage.cacheWriteTokens || 0,
|
|
2328
|
+
totalInputTokens: loopInputTokens,
|
|
2301
2329
|
totalTokens: loopInputTokens + loopOutputTokens,
|
|
2302
2330
|
},
|
|
2303
2331
|
latencyMs,
|
package/yeaft/llm/adapter.js
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
* @typedef {{ type: 'thinking_delta', text: string }} ThinkingDeltaEvent
|
|
43
43
|
* @typedef {{ type: 'thinking_block_end', thinking: string, signature: string }} ThinkingBlockEndEvent
|
|
44
44
|
* @typedef {{ type: 'tool_call', id: string, name: string, input: object }} ToolCallEvent
|
|
45
|
-
* @typedef {{ type: 'usage', inputTokens: number, outputTokens: number, cacheReadTokens?: number, cacheWriteTokens?: number }} UsageEvent
|
|
45
|
+
* @typedef {{ type: 'usage', inputTokens: number, outputTokens: number, cacheReadTokens?: number, cacheWriteTokens?: number, cacheTokensAreIncludedInInput?: boolean }} UsageEvent
|
|
46
46
|
* @typedef {{ type: 'stop', stopReason: 'end_turn' | 'tool_use' | 'max_tokens' }} StopEvent
|
|
47
47
|
* @typedef {{ type: 'error', error: Error, retryable: boolean }} ErrorEvent
|
|
48
48
|
*
|
package/yeaft/llm/anthropic.js
CHANGED
|
@@ -508,6 +508,8 @@ export class AnthropicAdapter extends LLMAdapter {
|
|
|
508
508
|
usage: {
|
|
509
509
|
inputTokens: result.usage?.input_tokens || 0,
|
|
510
510
|
outputTokens: result.usage?.output_tokens || 0,
|
|
511
|
+
cacheReadTokens: result.usage?.cache_read_input_tokens || 0,
|
|
512
|
+
cacheWriteTokens: result.usage?.cache_creation_input_tokens || 0,
|
|
511
513
|
},
|
|
512
514
|
};
|
|
513
515
|
}
|
|
@@ -435,6 +435,7 @@ export class OpenAIResponsesAdapter extends LLMAdapter {
|
|
|
435
435
|
outputTokens: usage.output_tokens || 0,
|
|
436
436
|
cacheReadTokens: usage.input_tokens_details?.cached_tokens || 0,
|
|
437
437
|
cacheWriteTokens: 0,
|
|
438
|
+
cacheTokensAreIncludedInInput: true,
|
|
438
439
|
};
|
|
439
440
|
|
|
440
441
|
yield {
|
package/yeaft/web-bridge.js
CHANGED
|
@@ -2233,6 +2233,9 @@ function handleEngineEvent(event, hctx) {
|
|
|
2233
2233
|
type: 'context_usage',
|
|
2234
2234
|
inputTokens: event.inputTokens,
|
|
2235
2235
|
outputTokens: event.outputTokens,
|
|
2236
|
+
cacheReadTokens: event.cacheReadTokens || 0,
|
|
2237
|
+
cacheWriteTokens: event.cacheWriteTokens || 0,
|
|
2238
|
+
totalInputTokens: (event.inputTokens || 0) + (event.cacheReadTokens || 0) + (event.cacheWriteTokens || 0),
|
|
2236
2239
|
}, envelope);
|
|
2237
2240
|
break;
|
|
2238
2241
|
|