@yeaft/webchat-agent 0.1.871 → 0.1.873

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.871",
3
+ "version": "0.1.873",
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/yeaft/init.js CHANGED
@@ -8,9 +8,10 @@
8
8
  import { existsSync, mkdirSync, writeFileSync, accessSync, constants } from 'fs';
9
9
  import { join } from 'path';
10
10
  import { homedir } from 'os';
11
- // NOTE: migrateSessionsV1 is imported by tests directly from
12
- // './migrate/sessions-v1.js' not wired into initYeaftDir() yet (Phase 2
13
- // will activate it once the runtime reads from sessions/).
11
+ // NOTE: migrateSessionsV1 is called at the end of initYeaftDir() to collapse
12
+ // any legacy groups/ + chats/ + memory/{group,chat}/ data into the unified
13
+ // sessions/ layout. Idempotent via sentinel file.
14
+ import { migrateSessionsV1 } from './migrate/sessions-v1.js';
14
15
 
15
16
  /**
16
17
  * Check if an error is a permission error (EACCES or EPERM).
@@ -221,5 +222,20 @@ export function initYeaftDir(dir) {
221
222
  // from under the live group/chat code paths. Phase 2 flips the runtime
222
223
  // and then hooks `migrateSessionsV1(root)` here.
223
224
 
225
+ // NOTE: sessions-v1 migration runs at end. Fire-and-log: keep
226
+ // initYeaftDir() sync so existing callers don't break. The migration is
227
+ // idempotent (sentinel file) so a partial run on crash is safe.
228
+ Promise.resolve()
229
+ .then(() => migrateSessionsV1(root))
230
+ .then((res) => {
231
+ if (res && res.migrated) {
232
+ console.log(`[yeaft] session migration complete (${res.moved} dirs moved${res.warnings?.length ? `, ${res.warnings.length} warnings` : ''})`);
233
+ if (res.warnings?.length) for (const w of res.warnings) console.warn(`[yeaft] migration: ${w}`);
234
+ }
235
+ })
236
+ .catch((err) => {
237
+ console.warn(`[yeaft] session migration failed (continuing): ${err?.message || err}`);
238
+ });
239
+
224
240
  return { dir: root, created, writable, warnings };
225
241
  }
@@ -43,7 +43,7 @@ const SENTINEL = '.session-migration-v1.done';
43
43
  * @param {string} yeaftDir
44
44
  * @returns {{ migrated: boolean, moved: number, warnings: string[] }}
45
45
  */
46
- export function migrateSessionsV1(yeaftDir) {
46
+ export async function migrateSessionsV1(yeaftDir) {
47
47
  const warnings = [];
48
48
  if (!yeaftDir || !existsSync(yeaftDir)) {
49
49
  return { migrated: false, moved: 0, warnings: ['yeaftDir missing'] };
@@ -172,13 +172,32 @@ export function migrateSessionsV1(yeaftDir) {
172
172
  }
173
173
  }
174
174
 
175
- // 6. sentinel
176
- //
177
- // PHASE 2 TODO: the SQLite FTS index (memory/index-db.js) still has rows
178
- // pointing at group/<id> and chat/<id> scopes after this migration. When
179
- // Phase 2 activates this migration from initYeaftDir(), it MUST also
180
- // delete or rebuild the FTS index so the new session/<id> scopes get
181
- // re-indexed. Preflow recall is broken until then.
175
+ // 6. Rewrite SQLite FTS index scope strings via the shared index-db
176
+ // module (which already handles ABI loading). Idempotent: WHERE clause
177
+ // skips already-rewritten rows.
178
+ try {
179
+ const dbPath = join(memoryRoot, 'index.db');
180
+ if (existsSync(dbPath)) {
181
+ const { openSegmentIndex } = await import('../memory/index-db.js');
182
+ const idx = openSegmentIndex(dbPath);
183
+ try {
184
+ const db = idx._db;
185
+ db.exec("BEGIN");
186
+ db.exec("UPDATE memory_segments SET scope = REPLACE(scope, 'group/', 'session/') WHERE scope LIKE 'group/%'");
187
+ db.exec("UPDATE memory_segments SET scope = REPLACE(scope, 'chat/', 'session/') WHERE scope LIKE 'chat/%'");
188
+ db.exec("COMMIT");
189
+ } catch (err) {
190
+ try { idx._db.exec("ROLLBACK"); } catch { /* ignore */ }
191
+ warnings.push(`FTS scope rewrite failed: ${err.message}`);
192
+ } finally {
193
+ try { idx.close(); } catch { /* ignore */ }
194
+ }
195
+ }
196
+ } catch (err) {
197
+ warnings.push(`FTS rewrite skipped: ${err.message}`);
198
+ }
199
+
200
+ // 7. sentinel
182
201
  writeFileSync(sentinel, JSON.stringify({
183
202
  version: 1,
184
203
  migratedAt: new Date().toISOString(),