@yeaft/webchat-agent 0.1.499 → 0.1.501

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.499",
3
+ "version": "0.1.501",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/unify/engine.js CHANGED
@@ -26,8 +26,17 @@ import { buildMemoryInjection } from './memory/layout.js';
26
26
  import { runStopHooks } from './stop-hooks.js';
27
27
  import { getThreadStore, MAIN_THREAD_ID } from './threads/store.js';
28
28
 
29
- /** Maximum number of turns before the engine stops to prevent infinite loops. */
30
- const MAX_TURNS = 25;
29
+ /**
30
+ * task-324 — Turn cap removed.
31
+ *
32
+ * Previously MAX_TURNS=25 broke the query loop out of long tool-driven
33
+ * conversations (user report: Unify loop errored at the cap). The engine
34
+ * now runs until the LLM itself returns stopReason='end_turn' or a
35
+ * non-retryable error surfaces. Real runaway loops are still bounded by:
36
+ * • provider rate limits / context window (LLMContextError → compact)
37
+ * • user-initiated abort (AbortController / cancel)
38
+ * • MAX_CONTINUE_TURNS for the max_tokens auto-continue path
39
+ */
31
40
 
32
41
  /** Maximum auto-continue turns when stopReason is 'max_tokens'. */
33
42
  const MAX_CONTINUE_TURNS = 3;
@@ -401,15 +410,9 @@ export class Engine {
401
410
  while (true) {
402
411
  turnNumber++;
403
412
 
404
- // Safety: prevent infinite loops
405
- if (turnNumber > MAX_TURNS) {
406
- yield {
407
- type: 'error',
408
- error: new Error(`Max turns (${MAX_TURNS}) reached — stopping to prevent infinite loop`),
409
- retryable: false,
410
- };
411
- break;
412
- }
413
+ // task-324: no hard MAX_TURNS cap. Loop terminates on end_turn,
414
+ // non-retryable error, LLMContextError (after compact retry), or
415
+ // caller abort. Keeping this comment so the removal is traceable.
413
416
 
414
417
  const turnId = this.#trace.startTurn({
415
418
  traceId: this.#traceId,
@@ -921,20 +921,31 @@ export async function handleUnifyLoadHistory(msg) {
921
921
  const bucket = getThreadMessages(tid);
922
922
  bucket.push({ role: m.role, content: m.content });
923
923
  }
924
-
925
- sendUnifyEvent({
926
- type: 'session_ready',
927
- conversationId: unifyConversationId,
928
- model: session.config.model,
929
- availableModels: session.config.availableModels || [],
930
- skills: session.status.skills,
931
- mcpServers: session.status.mcpServers,
932
- tools: session.status.tools,
933
- });
934
- // task-301 Part 2: initial thread snapshot for history-load session.
935
- sendThreadListUpdate();
936
924
  }
937
925
 
926
+ // task-322: replay `session_ready` + `thread_list_updated` UNCONDITIONALLY
927
+ // on every load-history call. The module-level `session` is a process-wide
928
+ // singleton — on page refresh the agent reuses it, so the lazy-init block
929
+ // above is skipped. The frontend's `enterUnify()` resets
930
+ // `unifyModel=null`, `unifyThreads=[]`, `unifySessionReady=false` every
931
+ // time, so without this replay the UI is left with the model selector
932
+ // stuck on the placeholder, sidebar empty, and the local→agent
933
+ // conversationId migration never triggers (leaving the main pane blank).
934
+ //
935
+ // Frontend is idempotent: the `session_ready` handler either migrates
936
+ // local→agent convId (first time) or just updates model/status fields
937
+ // (repeat) — receiving it twice is a no-op on state invariants.
938
+ sendUnifyEvent({
939
+ type: 'session_ready',
940
+ conversationId: unifyConversationId,
941
+ model: session.config.model,
942
+ availableModels: session.config.availableModels || [],
943
+ skills: session.status.skills,
944
+ mcpServers: session.status.mcpServers,
945
+ tools: session.status.tools,
946
+ });
947
+ sendThreadListUpdate();
948
+
938
949
  const limit = msg.limit || 50;
939
950
  const messages = session.conversationStore.loadRecent(limit);
940
951
  const compactSummary = session.conversationStore.readCompactSummary();