@yeaft/webchat-agent 0.1.1057 → 0.1.1059
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 +32 -8
- package/yeaft/engine.js +5 -1
package/package.json
CHANGED
package/yeaft/debug-trace.js
CHANGED
|
@@ -474,12 +474,36 @@ export class DebugTrace {
|
|
|
474
474
|
};
|
|
475
475
|
// Group rows by (turnId, threadId, sessionId, vpId) → frontend Turn
|
|
476
476
|
// record. Each row is also surfaced as a Loop.
|
|
477
|
+
const duplicateLoopTraceIds = new Set();
|
|
478
|
+
const seenLoopKeys = new Set();
|
|
479
|
+
for (const r of rows) {
|
|
480
|
+
const traceId = r.trace_id || r.id;
|
|
481
|
+
const key = `${traceId}#${r.turn_number || 0}`;
|
|
482
|
+
if (seenLoopKeys.has(key)) duplicateLoopTraceIds.add(traceId);
|
|
483
|
+
else seenLoopKeys.add(key);
|
|
484
|
+
}
|
|
485
|
+
// Legacy rows used one Engine-instance trace_id for many user requests.
|
|
486
|
+
// That creates duplicate Loop 1/2/... rows under the same trace. Split
|
|
487
|
+
// only those corrupted traces by SQLite row id; healthy rows keep trace_id
|
|
488
|
+
// so multi-loop requests still hydrate as one turn. Keep this as one
|
|
489
|
+
// function so loop hydration and tool attachment use the same identity.
|
|
490
|
+
const turnKeyForRow = (r) => {
|
|
491
|
+
const baseTurnId = r.trace_id || r.id;
|
|
492
|
+
return duplicateLoopTraceIds.has(baseTurnId) ? (r.id || baseTurnId) : baseTurnId;
|
|
493
|
+
};
|
|
494
|
+
const loopInstanceIdForRow = (r) => {
|
|
495
|
+
const baseTurnId = r.trace_id || r.id;
|
|
496
|
+
return duplicateLoopTraceIds.has(baseTurnId) ? (r.id || `${baseTurnId}#${r.turn_number || 0}`) : null;
|
|
497
|
+
};
|
|
477
498
|
const turnsById = new Map();
|
|
478
499
|
const loops = rows.map((r) => {
|
|
479
500
|
const parsedMessages = parseJsonSafe(r.messages_json) || [];
|
|
480
501
|
const parsedUsage = parseJsonSafe(r.usage_json);
|
|
502
|
+
const hydratedTurnId = turnKeyForRow(r);
|
|
503
|
+
const loopInstanceId = loopInstanceIdForRow(r);
|
|
481
504
|
const loop = {
|
|
482
|
-
turnId:
|
|
505
|
+
turnId: hydratedTurnId,
|
|
506
|
+
...(loopInstanceId ? { loopInstanceId } : {}),
|
|
483
507
|
loopNumber: r.turn_number || 0,
|
|
484
508
|
model: r.model || null,
|
|
485
509
|
systemPrompt: r.system_prompt || '',
|
|
@@ -496,9 +520,9 @@ export class DebugTrace {
|
|
|
496
520
|
vpId: r.vp_id || null,
|
|
497
521
|
threadId: r.thread_id || null,
|
|
498
522
|
};
|
|
499
|
-
if (!turnsById.has(
|
|
500
|
-
turnsById.set(
|
|
501
|
-
turnId:
|
|
523
|
+
if (!turnsById.has(hydratedTurnId)) {
|
|
524
|
+
turnsById.set(hydratedTurnId, {
|
|
525
|
+
turnId: hydratedTurnId,
|
|
502
526
|
// C2 fix: read the explicit `user_prompt` column persisted at
|
|
503
527
|
// startTurn time. Deriving from messages_json is unsafe — each
|
|
504
528
|
// tool-loop iteration overwrites messages_json with the
|
|
@@ -518,7 +542,7 @@ export class DebugTrace {
|
|
|
518
542
|
tools: [],
|
|
519
543
|
});
|
|
520
544
|
}
|
|
521
|
-
const t = turnsById.get(
|
|
545
|
+
const t = turnsById.get(hydratedTurnId);
|
|
522
546
|
t.loopCount += 1;
|
|
523
547
|
// Aggregate per-loop latency / tokens so the Turn header shows the
|
|
524
548
|
// same totals the live `turn_close` event would have stamped.
|
|
@@ -530,11 +554,11 @@ export class DebugTrace {
|
|
|
530
554
|
// Attach tools to their parent Turn so the panel can render per-tool
|
|
531
555
|
// timing without scanning the loop bodies.
|
|
532
556
|
for (const tool of tools) {
|
|
533
|
-
// Find which loop row this tool belongs to
|
|
534
|
-
//
|
|
557
|
+
// Find which loop row this tool belongs to; use the same hydrated
|
|
558
|
+
// identity as the loop/turn records so split legacy rows keep tools.
|
|
535
559
|
const owner = rows.find(r => r.id === tool.turn_id);
|
|
536
560
|
if (!owner) continue;
|
|
537
|
-
const t = turnsById.get(owner
|
|
561
|
+
const t = turnsById.get(turnKeyForRow(owner));
|
|
538
562
|
if (!t) continue;
|
|
539
563
|
t.tools.push({
|
|
540
564
|
loopNumber: owner.turn_number || 0,
|
package/yeaft/engine.js
CHANGED
|
@@ -1863,7 +1863,11 @@ export class Engine {
|
|
|
1863
1863
|
}
|
|
1864
1864
|
|
|
1865
1865
|
const turnId = this.#trace.startTurn({
|
|
1866
|
-
|
|
1866
|
+
// Persist the wire-level query turn id, not the Engine-instance trace id.
|
|
1867
|
+
// Debug history groups SQLite loop rows by traceId; using #traceId here
|
|
1868
|
+
// merged separate user requests into one debug turn, so every request's
|
|
1869
|
+
// first LLM call showed up as another stale "Loop 1" under the same row.
|
|
1870
|
+
traceId: queryTurnId,
|
|
1867
1871
|
turnNumber,
|
|
1868
1872
|
// fix-vp-multi-thread (bug 4): stamp routing context so the
|
|
1869
1873
|
// debug-trace SQL row carries enough info to be filtered by
|