@yeaft/webchat-agent 0.1.315 → 0.1.316

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/crew/control.js CHANGED
@@ -187,6 +187,8 @@ async function resumeSession(session) {
187
187
  message: { role: 'assistant', content: [{ type: 'text', text: 'Session 已恢复' }] }
188
188
  });
189
189
  sendStatusUpdate(session);
190
+ // Status changed to running — persist
191
+ saveSessionMeta(session).catch(e => console.warn('[Crew] Failed to save after resume:', e.message));
190
192
 
191
193
  if (session.pendingRoutes.length > 0) {
192
194
  const pending = session.pendingRoutes.slice();
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { dispatchToRole } from './routing.js';
6
6
  import { sendStatusUpdate } from './ui-messages.js';
7
+ import { debouncedSaveSessionMeta } from './persistence.js';
7
8
 
8
9
  /**
9
10
  * 处理人的输入
@@ -50,6 +51,8 @@ export async function handleCrewHumanInput(msg) {
50
51
  session.status = 'running';
51
52
  session.waitingHumanContext = null;
52
53
  sendStatusUpdate(session);
54
+ // Status changed + new human message — persist (debounced, dispatch will follow)
55
+ debouncedSaveSessionMeta(session);
53
56
 
54
57
  const target = targetRole || waitingContext?.fromRole || session.decisionMaker;
55
58
  await dispatchToRole(session, target, buildHumanContent('人工回复:', content), 'human');
@@ -119,6 +119,24 @@ export async function unhideCrewSession(sessionId) {
119
119
  // =====================================================================
120
120
 
121
121
  const MESSAGE_SHARD_SIZE = 256 * 1024; // 256KB per shard
122
+ const SAVE_DEBOUNCE_MS = 10_000; // 10 seconds
123
+
124
+ /**
125
+ * Debounced version of saveSessionMeta.
126
+ * Coalesces rapid-fire calls (e.g. multiple role turn-ends) into a single
127
+ * disk write per session, at most once every SAVE_DEBOUNCE_MS.
128
+ */
129
+ export function debouncedSaveSessionMeta(session) {
130
+ if (session._saveDebounceTimer) {
131
+ clearTimeout(session._saveDebounceTimer);
132
+ }
133
+ session._saveDebounceTimer = setTimeout(() => {
134
+ session._saveDebounceTimer = null;
135
+ saveSessionMeta(session).catch(e =>
136
+ console.warn('[Crew] Debounced save failed:', e.message)
137
+ );
138
+ }, SAVE_DEBOUNCE_MS);
139
+ }
122
140
 
123
141
  export async function saveSessionMeta(session) {
124
142
  const meta = {
@@ -5,6 +5,7 @@
5
5
  import { initRoleDir, updateSharedClaudeMd } from './shared-dir.js';
6
6
  import { saveRoleSessionId } from './role-query.js';
7
7
  import { sendCrewMessage, sendCrewOutput, sendStatusUpdate } from './ui-messages.js';
8
+ import { saveSessionMeta, upsertCrewIndex } from './persistence.js';
8
9
 
9
10
  /** Format role label */
10
11
  function roleLabel(r) {
@@ -94,6 +95,9 @@ export async function addRoleToSession(msg) {
94
95
  }
95
96
 
96
97
  sendStatusUpdate(session);
98
+ // Roles changed — persist
99
+ saveSessionMeta(session).catch(e => console.warn('[Crew] Failed to save after addRole:', e.message));
100
+ upsertCrewIndex(session).catch(e => console.warn('[Crew] Failed to update index after addRole:', e.message));
97
101
  }
98
102
 
99
103
  /**
@@ -152,4 +156,7 @@ export async function removeRoleFromSession(msg) {
152
156
  });
153
157
 
154
158
  sendStatusUpdate(session);
159
+ // Roles changed — persist
160
+ saveSessionMeta(session).catch(e => console.warn('[Crew] Failed to save after removeRole:', e.message));
161
+ upsertCrewIndex(session).catch(e => console.warn('[Crew] Failed to update index after removeRole:', e.message));
155
162
  }
@@ -6,6 +6,7 @@ import { sendCrewMessage, sendCrewOutput, sendStatusUpdate, endRoleStreaming } f
6
6
  import { saveRoleSessionId, clearRoleSessionId, classifyRoleError, createRoleQuery } from './role-query.js';
7
7
  import { parseRoutes, executeRoute, dispatchToRole } from './routing.js';
8
8
  import { parseCompletedTasks, updateFeatureIndex, appendChangelog, saveRoleWorkSummary, updateKanban } from './task-files.js';
9
+ import { debouncedSaveSessionMeta, saveSessionMeta } from './persistence.js';
9
10
  import ctx from '../context.js';
10
11
 
11
12
  // Context 使用率常量(运行时从 ctx.CONFIG 读取)
@@ -170,6 +171,8 @@ export async function processRoleOutput(session, roleName, roleQuery, roleState)
170
171
  });
171
172
 
172
173
  sendStatusUpdate(session);
174
+ // Cost/tokens/messages updated — debounced persist (coalesces rapid turn-ends)
175
+ debouncedSaveSessionMeta(session);
173
176
 
174
177
  // 执行路由
175
178
  if (routes.length > 0) {
@@ -267,6 +270,8 @@ export async function processRoleOutput(session, roleName, roleQuery, roleState)
267
270
  message: errDetail
268
271
  });
269
272
  sendStatusUpdate(session);
273
+ // Status changed to waiting_human — persist
274
+ saveSessionMeta(session).catch(e => console.warn('[Crew] Failed to save after error→human:', e.message));
270
275
  }
271
276
  return;
272
277
  }
package/crew/routing.js CHANGED
@@ -6,6 +6,7 @@ import { join } from 'path';
6
6
  import { sendCrewMessage, sendCrewOutput, sendStatusUpdate } from './ui-messages.js';
7
7
  import { ensureTaskFile, appendTaskRecord, readTaskFile, updateKanban, readKanban, saveRoleWorkSummary } from './task-files.js';
8
8
  import { createRoleQuery, clearRoleSessionId } from './role-query.js';
9
+ import { saveSessionMeta } from './persistence.js';
9
10
  import ctx from '../context.js';
10
11
 
11
12
  /** Format role label */
@@ -169,6 +170,8 @@ export async function executeRoute(session, fromRole, route) {
169
170
  message: summary
170
171
  });
171
172
  sendStatusUpdate(session);
173
+ // Status changed to waiting_human — persist
174
+ saveSessionMeta(session).catch(e => console.warn('[Crew] Failed to save after →human:', e.message));
172
175
  return;
173
176
  }
174
177
 
@@ -3,7 +3,6 @@
3
3
  * sendCrewMessage, sendCrewOutput, sendStatusUpdate, endRoleStreaming, findActiveRole
4
4
  */
5
5
  import ctx from '../context.js';
6
- import { upsertCrewIndex, saveSessionMeta } from './persistence.js';
7
6
 
8
7
  /**
9
8
  * 发送 crew 消息到 server(透传到 Web)
@@ -257,8 +256,6 @@ export function sendStatusUpdate(session) {
257
256
  features: getActiveFeatures(session),
258
257
  initProgress: session.initProgress || null
259
258
  });
260
-
261
- // 异步更新持久化
262
- upsertCrewIndex(session).catch(e => console.warn('[Crew] Failed to update index:', e.message));
263
- saveSessionMeta(session).catch(e => console.warn('[Crew] Failed to save session meta:', e.message));
259
+ // Persist is NOT called here — callers that change persistent state
260
+ // (status, roles, cost, messages) must call saveSessionMeta explicitly.
264
261
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.315",
3
+ "version": "0.1.316",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",