@yeaft/webchat-agent 0.1.817 → 0.1.820

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.817",
3
+ "version": "0.1.820",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -110,14 +110,43 @@ function makeLlm(session) {
110
110
  if (!adapter || typeof adapter.call !== 'function') {
111
111
  throw new Error(`dream-v2: no adapter.call available (pass=${pass})`);
112
112
  }
113
+
114
+ // Bug 2: emit loop event so the debug panel shows dream LLM API calls.
115
+ const startedMs = Date.now();
116
+ session._dreamLoopCounter = (session._dreamLoopCounter || 0) + 1;
117
+ const loopNumber = session._dreamLoopCounter;
118
+ const turnId = session._dreamTurnId || 'dream';
119
+ const effectiveSystem = system || (String(session.config?.language || '').toLowerCase().startsWith('zh')
120
+ ? `你是梦境流水线 — pass: ${pass}。请用中文生成自然语言内容;JSON key 保持英文。`
121
+ : `You are the dream pipeline — pass: ${pass}.`);
122
+
113
123
  const r = await adapter.call({
114
124
  model,
115
- system: system || (String(session.config?.language || '').toLowerCase().startsWith('zh')
116
- ? `你是梦境流水线 — pass: ${pass}。请用中文生成自然语言内容;JSON key 保持英文。`
117
- : `You are the dream pipeline — pass: ${pass}.`),
125
+ system: effectiveSystem,
118
126
  messages: [{ role: 'user', content: prompt }],
119
127
  maxTokens: 2048,
120
128
  });
129
+
130
+ // Emit complete loop event (request + response) to the debug panel.
131
+ if (typeof session._dreamProgressSink === 'function') {
132
+ session._dreamProgressSink({
133
+ type: 'loop',
134
+ turnId,
135
+ loopNumber,
136
+ model: model || 'unknown',
137
+ systemPrompt: effectiveSystem,
138
+ messages: [{ role: 'user', content: prompt }],
139
+ response: typeof r?.text === 'string' ? r.text : '',
140
+ toolCalls: [],
141
+ usage: r?.usage || { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
142
+ latencyMs: Date.now() - startedMs,
143
+ ttfbMs: null,
144
+ stopReason: 'end_turn',
145
+ rawRequest: null,
146
+ rawResponse: null,
147
+ });
148
+ }
149
+
121
150
  return (r && r.text) ? r.text : '';
122
151
  };
123
152
  }
@@ -151,11 +180,46 @@ export function createV2DreamScheduler(session) {
151
180
  } catch { /* never let progress reporting kill the run */ }
152
181
  };
153
182
 
154
- const run = (opts = {}) => runDream({
155
- ...buildRunDreamOpts(session, onProgress),
156
- manual: !!opts.manual,
157
- scopeFilter: Array.isArray(opts.scopeFilter) ? opts.scopeFilter : undefined,
158
- });
183
+ let dreamTurnCounter = 0;
184
+
185
+ const run = (opts = {}) => {
186
+ // Bug 2: emit turn_open before the dream pass so the debug panel
187
+ // can group all LLM loop events under a single dream "turn".
188
+ dreamTurnCounter += 1;
189
+ const turnId = `dream-${dreamTurnCounter}-${Date.now()}`;
190
+ const startedAt = Date.now();
191
+ session._dreamTurnId = turnId;
192
+ session._dreamLoopCounter = 0;
193
+
194
+ if (typeof session._dreamProgressSink === 'function') {
195
+ session._dreamProgressSink({
196
+ type: 'turn_open',
197
+ turnId,
198
+ userPrompt: '[dream] automatic memory consolidation',
199
+ vpId: null,
200
+ groupId: null,
201
+ at: startedAt,
202
+ });
203
+ }
204
+
205
+ return runDream({
206
+ ...buildRunDreamOpts(session, onProgress),
207
+ manual: !!opts.manual,
208
+ scopeFilter: Array.isArray(opts.scopeFilter) ? opts.scopeFilter : undefined,
209
+ }).then((result) => {
210
+ // Bug 2: emit turn_close when the dream pass completes.
211
+ if (typeof session._dreamProgressSink === 'function') {
212
+ session._dreamProgressSink({
213
+ type: 'turn_close',
214
+ turnId,
215
+ totalMs: Date.now() - startedAt,
216
+ totalTokens: 0,
217
+ loopCount: session._dreamLoopCounter || 0,
218
+ });
219
+ }
220
+ return result;
221
+ });
222
+ };
159
223
 
160
224
  const v2 = createDreamScheduler({
161
225
  run,
@@ -1597,11 +1597,19 @@ export function installUnifyRuntimeBridge(s) {
1597
1597
  // `handleUnifyDreamTrigger` wraps THIS sink for the lifetime of the
1598
1598
  // trigger to inject `groupId` per-call (see that function below). The
1599
1599
  // base sink is intentionally a pure passthrough.
1600
+ //
1601
+ // Bug 2: also forward turn_open / turn_close / loop events emitted by
1602
+ // the dream pipeline so the debug panel shows dream LLM API calls.
1600
1603
  s._dreamProgressSink = (evt) => {
1601
1604
  try {
1602
- const out = { type: 'dream_progress', ...evt };
1603
- const tag = evt && evt.groupId ? { groupId: evt.groupId } : {};
1604
- sendUnifyEvent(out, tag);
1605
+ if (evt.type === 'turn_open' || evt.type === 'turn_close' || evt.type === 'loop') {
1606
+ const tag = evt && evt.groupId ? { groupId: evt.groupId } : {};
1607
+ sendUnifyEvent(evt, tag);
1608
+ } else {
1609
+ const out = { type: 'dream_progress', ...evt };
1610
+ const tag = evt && evt.groupId ? { groupId: evt.groupId } : {};
1611
+ sendUnifyEvent(out, tag);
1612
+ }
1605
1613
  } catch { /* never let event delivery throw */ }
1606
1614
  };
1607
1615
 
@@ -2440,6 +2448,7 @@ async function ensureSessionLoaded() {
2440
2448
  skills: session.status.skills,
2441
2449
  mcpServers: session.status.mcpServers,
2442
2450
  tools: session.status.tools,
2451
+ yeaftDir: ctx.CONFIG?.yeaftDir || null,
2443
2452
  });
2444
2453
  sendGroupSnapshotBroadcast();
2445
2454
  // vp-status: rebuild frontend status table from authoritative agent
@@ -3454,6 +3463,7 @@ export async function handleUnifyLoadHistory(msg) {
3454
3463
  skills: session.status.skills,
3455
3464
  mcpServers: session.status.mcpServers,
3456
3465
  tools: session.status.tools,
3466
+ yeaftDir: ctx.CONFIG?.yeaftDir || null,
3457
3467
  });
3458
3468
  sendGroupSnapshotBroadcast();
3459
3469
  // vp-status: replay the authoritative table on reconnect so a refreshed
@@ -3483,7 +3493,7 @@ export async function handleUnifyLoadHistory(msg) {
3483
3493
 
3484
3494
  for (const entry of replayEntries) {
3485
3495
  if (entry.role === 'user') {
3486
- sendUnifyOutput({ type: 'user', message: { content: entry.content, id: entry.id || null } }, { groupId: entry.groupId || null });
3496
+ sendUnifyOutput({ type: 'user', message: { content: entry.content, id: entry.id || null }, ts: entry.ts || null }, { groupId: entry.groupId || null });
3487
3497
  } else if (entry.role === 'assistant') {
3488
3498
  // speakerVpId rides on the envelope so the frontend can route this
3489
3499
  // replayed assistant text to the correct VP track. Without it, the
@@ -3496,6 +3506,7 @@ export async function handleUnifyLoadHistory(msg) {
3496
3506
  sendUnifyOutput({
3497
3507
  type: 'assistant',
3498
3508
  message: { id: entry.id || null, content: [{ type: 'text', text: entry.content }] },
3509
+ ts: entry.ts || null,
3499
3510
  }, envelopeOpts);
3500
3511
  sendUnifyOutput({ type: 'result', result_text: '' }, envelopeOpts);
3501
3512
  }
@@ -3661,6 +3672,7 @@ export async function resetUnifySession() {
3661
3672
  skills: session.status.skills,
3662
3673
  mcpServers: session.status.mcpServers,
3663
3674
  tools: session.status.tools,
3675
+ yeaftDir: ctx.CONFIG?.yeaftDir || null,
3664
3676
  });
3665
3677
  // vp-status: after a forced reset the broker table is still live in
3666
3678
  // memory; broadcast so the frontend can rebuild its mirror without