@yeaft/webchat-agent 1.0.347 → 1.0.349
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/local-runtime/version.json +1 -1
- package/local-runtime/web/app.bundle.js +85 -85
- package/local-runtime/web/app.bundle.js.gz +0 -0
- package/local-runtime/web/index.html +1 -1
- package/package.json +1 -1
- package/yeaft/conversation/persist.js +4 -0
- package/yeaft/debug-trace.js +392 -103
- package/yeaft/engine.js +16 -3
- package/yeaft/router/continuity.js +12 -3
- package/yeaft/session.js +3 -14
- package/yeaft/web-bridge.js +7 -1
- package/yeaft/work-center/bridge.js +1 -0
- package/yeaft/work-center/runner.js +1 -1
package/yeaft/engine.js
CHANGED
|
@@ -1519,7 +1519,7 @@ export class Engine {
|
|
|
1519
1519
|
return Boolean(this.#conversationStore) && !this.#config._readOnly;
|
|
1520
1520
|
}
|
|
1521
1521
|
|
|
1522
|
-
#conversationRecord(message, { sessionId, turnId, model, incomplete = false, stopReason = null } = {}) {
|
|
1522
|
+
#conversationRecord(message, { sessionId, turnId, model, incomplete = false, stopReason = null, executionOrigin = null } = {}) {
|
|
1523
1523
|
const record = {
|
|
1524
1524
|
role: message.role,
|
|
1525
1525
|
content: typeof message.content === 'string'
|
|
@@ -1545,6 +1545,9 @@ export class Engine {
|
|
|
1545
1545
|
record.foldedMessageIds = [...message.foldedMessageIds];
|
|
1546
1546
|
}
|
|
1547
1547
|
if (turnId && (message.role === 'assistant' || message.role === 'tool')) record.turnId = turnId;
|
|
1548
|
+
if (executionOrigin === 'route_forward' && (message.role === 'assistant' || message.role === 'tool')) {
|
|
1549
|
+
record.executionOrigin = executionOrigin;
|
|
1550
|
+
}
|
|
1548
1551
|
if (this.#vpId && (message.role === 'assistant' || message.role === 'tool')) record.speakerVpId = this.#vpId;
|
|
1549
1552
|
if (incomplete) record.incomplete = true;
|
|
1550
1553
|
if (stopReason) record.stopReason = stopReason;
|
|
@@ -2117,6 +2120,9 @@ export class Engine {
|
|
|
2117
2120
|
const runtimeThreadId = (typeof threadId === 'string' && threadId.trim())
|
|
2118
2121
|
? threadId.trim()
|
|
2119
2122
|
: MAIN_THREAD_ID;
|
|
2123
|
+
const executionOrigin = inboundEnvelope?.msg?.meta?.injectedBy === 'route_forward'
|
|
2124
|
+
? 'route_forward'
|
|
2125
|
+
: null;
|
|
2120
2126
|
const queryTurnId = randomUUID();
|
|
2121
2127
|
const queryStartedAt = Date.now();
|
|
2122
2128
|
const userQuestionPreview = String(prompt || '').slice(0, 200);
|
|
@@ -2615,6 +2621,7 @@ export class Engine {
|
|
|
2615
2621
|
model: currentModel,
|
|
2616
2622
|
incomplete: true,
|
|
2617
2623
|
stopReason: reason,
|
|
2624
|
+
executionOrigin,
|
|
2618
2625
|
});
|
|
2619
2626
|
};
|
|
2620
2627
|
const toolCalls = [];
|
|
@@ -3363,6 +3370,7 @@ export class Engine {
|
|
|
3363
3370
|
sessionId: runtimeSessionId,
|
|
3364
3371
|
turnId: vpTurnId || queryTurnId,
|
|
3365
3372
|
model: currentModel,
|
|
3373
|
+
executionOrigin,
|
|
3366
3374
|
});
|
|
3367
3375
|
if (persistedAssistantMessage) {
|
|
3368
3376
|
assistantMsg._persistedMessageId = persistedAssistantMessage.id;
|
|
@@ -3687,6 +3695,7 @@ export class Engine {
|
|
|
3687
3695
|
count: pairs.length,
|
|
3688
3696
|
originalUserMsg: prompt,
|
|
3689
3697
|
originatingTurnId: queryTurnId,
|
|
3698
|
+
executionOrigin,
|
|
3690
3699
|
ready: false,
|
|
3691
3700
|
result: null,
|
|
3692
3701
|
error: null,
|
|
@@ -3973,6 +3982,7 @@ export class Engine {
|
|
|
3973
3982
|
sessionId: runtimeSessionId,
|
|
3974
3983
|
turnId: vpTurnId || queryTurnId,
|
|
3975
3984
|
model: currentModel,
|
|
3985
|
+
executionOrigin,
|
|
3976
3986
|
});
|
|
3977
3987
|
if (persistedToolMessage) {
|
|
3978
3988
|
toolMessage._persistedMessageId = persistedToolMessage.id;
|
|
@@ -4110,7 +4120,7 @@ export class Engine {
|
|
|
4110
4120
|
batchStart,
|
|
4111
4121
|
batchEnd,
|
|
4112
4122
|
reflectionMessage,
|
|
4113
|
-
{ sessionId: runtimeSessionId, model: currentModel },
|
|
4123
|
+
{ sessionId: runtimeSessionId, model: currentModel, executionOrigin },
|
|
4114
4124
|
);
|
|
4115
4125
|
if (durableRowsInRange && !persistedReflection) {
|
|
4116
4126
|
throw new Error('T1 reflection could not publish its durable range replacement');
|
|
@@ -4303,7 +4313,10 @@ export class Engine {
|
|
|
4303
4313
|
startIdx,
|
|
4304
4314
|
endIdx,
|
|
4305
4315
|
reflectionMessage,
|
|
4306
|
-
|
|
4316
|
+
{
|
|
4317
|
+
...context,
|
|
4318
|
+
executionOrigin: info.executionOrigin === 'route_forward' ? 'route_forward' : null,
|
|
4319
|
+
},
|
|
4307
4320
|
);
|
|
4308
4321
|
if (durableRowsInRange && !persistedReflection) continue;
|
|
4309
4322
|
// Mutate in place so caller's reference stays valid.
|
|
@@ -86,7 +86,8 @@ export function extractPriorPlan(messages, vpId) {
|
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* Return a copy of the messages array with engine-private metadata stripped
|
|
89
|
-
* from every message.
|
|
89
|
+
* from every message. This includes durable UI-only execution provenance.
|
|
90
|
+
* The serialisers (anthropic/openai-responses) read this;
|
|
90
91
|
* these fields are NEVER part of the wire payload. Cheap because we only
|
|
91
92
|
* shallow-clone the messages that actually have private fields.
|
|
92
93
|
*
|
|
@@ -99,9 +100,17 @@ export function stripMetaForWire(messages) {
|
|
|
99
100
|
const out = messages.map(m => {
|
|
100
101
|
if (m && typeof m === 'object'
|
|
101
102
|
&& ('_meta' in m || '_runtimeTurnId' in m || '_partialTurn' in m
|
|
102
|
-
|| '_persistedMessageId' in m || 'userAuthored' in m)) {
|
|
103
|
+
|| '_persistedMessageId' in m || 'userAuthored' in m || 'executionOrigin' in m)) {
|
|
103
104
|
mutated = true;
|
|
104
|
-
const {
|
|
105
|
+
const {
|
|
106
|
+
_meta,
|
|
107
|
+
_runtimeTurnId,
|
|
108
|
+
_partialTurn,
|
|
109
|
+
_persistedMessageId,
|
|
110
|
+
userAuthored,
|
|
111
|
+
executionOrigin,
|
|
112
|
+
...rest
|
|
113
|
+
} = m;
|
|
105
114
|
return rest;
|
|
106
115
|
}
|
|
107
116
|
return m;
|
package/yeaft/session.js
CHANGED
|
@@ -250,23 +250,12 @@ export async function loadSession(options = {}) {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
// ─── 3. Create trajectory trace ─────────────────────────
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
// `<yeaftDir>/debug/` (session traces are nested under
|
|
256
|
-
// `<yeaftDir>/sessions/<sessionId>/debug/requests/`). A request file stores one
|
|
257
|
-
// base request snapshot plus per-loop deltas, so 100-200 loop requests do
|
|
258
|
-
// not become hundreds of tiny files or repeated cumulative payloads.
|
|
253
|
+
// Debug traces can contain prompts, tool payloads, and provider envelopes.
|
|
254
|
+
// Keep collection opt-in and avoid scanning trace history during Session boot.
|
|
259
255
|
const trace = createTrace({
|
|
260
|
-
enabled: true,
|
|
256
|
+
enabled: config.debug === true,
|
|
261
257
|
dirPath: yeaftDir,
|
|
262
258
|
});
|
|
263
|
-
// Hard cap debug history to the most recent 10 requests per Session. Trace
|
|
264
|
-
// failures are best-effort and must never stop the agent loop. cleanup() is
|
|
265
|
-
// now async (it hydrates the in-memory index, then prunes); run it
|
|
266
|
-
// fire-and-forget so session load never blocks on the startup disk scan.
|
|
267
|
-
Promise.resolve(trace.cleanup?.(10)).catch((err) => {
|
|
268
|
-
console.warn('[Yeaft] trace.cleanup failed:', err?.message || err);
|
|
269
|
-
});
|
|
270
259
|
|
|
271
260
|
// ─── 4. Create LLM adapter ────────────────────────────
|
|
272
261
|
const adapter = withUsageAccounting(
|
package/yeaft/web-bridge.js
CHANGED
|
@@ -6440,7 +6440,13 @@ export async function handleYeaftFetchDebugHistory(msg = {}) {
|
|
|
6440
6440
|
let dreamEvents = [];
|
|
6441
6441
|
let hasMore = false;
|
|
6442
6442
|
try {
|
|
6443
|
-
if (session?.trace && typeof session.trace.
|
|
6443
|
+
if (session?.trace && detailTurnId && sessionId && typeof session.trace.fetchTurnDebug === 'function') {
|
|
6444
|
+
const out = await session.trace.fetchTurnDebug({ sessionId, turnId: detailTurnId, dreamLimit });
|
|
6445
|
+
loops = Array.isArray(out?.loops) ? out.loops : [];
|
|
6446
|
+
turns = Array.isArray(out?.turns) ? out.turns : [];
|
|
6447
|
+
dreamEvents = Array.isArray(out?.dreamEvents) ? out.dreamEvents : [];
|
|
6448
|
+
hasMore = false;
|
|
6449
|
+
} else if (session?.trace && typeof session.trace.fetchRecentDebugHistory === 'function') {
|
|
6444
6450
|
const out = await session.trace.fetchRecentDebugHistory({ limit, dreamLimit, sessionId, threadId, indexOnly, detailTurnId, search });
|
|
6445
6451
|
loops = Array.isArray(out?.loops) ? out.loops : [];
|
|
6446
6452
|
turns = Array.isArray(out?.turns) ? out.turns : [];
|
|
@@ -121,6 +121,7 @@ async function createDefaultService() {
|
|
|
121
121
|
policyProvider: async () => readWorkCenterSettings(yeaftDir),
|
|
122
122
|
attachmentRoot: join(yeaftDir, 'work-center', 'attachments'),
|
|
123
123
|
yeaftDir,
|
|
124
|
+
debug: ctx.CONFIG?.debug === true,
|
|
124
125
|
actionWorktreeRoot: join(yeaftDir, 'work-center', 'worktrees'),
|
|
125
126
|
registry: defaultRegistry,
|
|
126
127
|
store: null,
|
|
@@ -797,7 +797,7 @@ export class WorkItemRunner {
|
|
|
797
797
|
this.policyProvider = typeof options.policyProvider === 'function' ? options.policyProvider : null;
|
|
798
798
|
this.attachmentRoot = options.attachmentRoot || null;
|
|
799
799
|
this.trace = options.trace || createTrace({
|
|
800
|
-
enabled: Boolean(options.yeaftDir),
|
|
800
|
+
enabled: options.debug === true && Boolean(options.yeaftDir),
|
|
801
801
|
dirPath: options.yeaftDir || null,
|
|
802
802
|
});
|
|
803
803
|
this.actionWorktreeRoot = options.actionWorktreeRoot || null;
|