@yeaft/webchat-agent 0.1.635 → 0.1.636

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.635",
3
+ "version": "0.1.636",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -28,7 +28,7 @@
28
28
  */
29
29
 
30
30
  import { groupTurns, pickCoolingGroups, indicesFromGroups } from './turn-group.js';
31
- import { writeSummary } from '../memory/scope-tree.js';
31
+ import { writeSummary } from '../memory/store-v2.js';
32
32
 
33
33
  /**
34
34
  * @typedef {{
package/unify/engine.js CHANGED
@@ -30,7 +30,7 @@ import { archiveTurn } from './archive/turn-archive.js';
30
30
  import { archiveToolResults } from './archive/tool-results.js';
31
31
  import { buildMemoryInjection } from './memory/layout.js';
32
32
  import { buildUserProfile } from './memory/user-memory-store.js';
33
- import { readSummary as readScopeSummary } from './memory/scope-tree.js';
33
+ import { readSummary as readScopeSummary } from './memory/store-v2.js';
34
34
  import { runStopHooks } from './stop-hooks.js';
35
35
  import { getThreadStore, MAIN_THREAD_ID } from './threads/store.js';
36
36
  import { pickEffort, parseEffortPrefix } from './effort.js';
@@ -36,7 +36,7 @@
36
36
  * }
37
37
  */
38
38
 
39
- import { isVpForeign } from '../memory/scope-tree.js';
39
+ import { isVpForeign } from '../memory/store-v2.js';
40
40
 
41
41
  /** @typedef {{ userOriginal: string, intent: string }} ForwardQuery */
42
42
  /** @typedef {{ memoryPaths: string[], taskIds: string[] }} Preselect */
package/unify/session.js CHANGED
@@ -37,8 +37,9 @@ import { seedDefaultVps } from './vp/seed-defaults.js';
37
37
  import { createDreamScheduler } from './memory/dream-scheduler.js';
38
38
  import { createV2DreamScheduler } from './dream-v2/session-wiring.js';
39
39
  import { getUserMemoryStore } from './memory/user-memory-store.js';
40
+ import { migrateR6toV2 } from './memory/migrate-r6-to-v2.js';
40
41
  import { join } from 'path';
41
- import { existsSync as existsSyncSafe, readFileSync as readFileSyncSafe } from 'fs';
42
+ import { existsSync as existsSyncSafe, readFileSync as readFileSyncSafe, writeFileSync as writeFileSyncSafe } from 'fs';
42
43
 
43
44
  /**
44
45
  * @typedef {Object} SessionOptions
@@ -135,6 +136,54 @@ export async function loadSession(options = {}) {
135
136
  }
136
137
  } catch { /* never let this warn path block session load */ }
137
138
 
139
+ // ─── 2.2 Auto-migrate R6 → v2 on first boot with memoryV2=on ──
140
+ // If `memoryV2` is on AND a R6-shaped tree is on disk AND we
141
+ // haven't already migrated, run the one-shot migration. The
142
+ // migration is idempotent and concatenate-don't-synthesise, so
143
+ // the worst case on re-run is "no R6 dirs found, exit clean".
144
+ // Failure here MUST NOT block session boot — we log + continue;
145
+ // dream will gradually backfill v2 from group diffs.
146
+ try {
147
+ if (config?.memoryV2 === true && !config?._readOnly) {
148
+ const memoryRoot = join(yeaftDir, 'memory');
149
+ const stateFile = join(yeaftDir, '.memory-v2-migration.json');
150
+ let alreadyMigrated = false;
151
+ if (existsSyncSafe(stateFile)) {
152
+ try {
153
+ const state = JSON.parse(readFileSyncSafe(stateFile, 'utf8') || '{}');
154
+ alreadyMigrated = Boolean(state && state.completedAt);
155
+ } catch { /* malformed state → re-run; migration is idempotent */ }
156
+ }
157
+ const hasR6 = existsSyncSafe(join(memoryRoot, 'groups'))
158
+ || existsSyncSafe(join(memoryRoot, 'features'));
159
+ if (!alreadyMigrated && hasR6) {
160
+ console.log('[Yeaft] memoryV2 on + R6 layout detected — running one-shot migration…');
161
+ const result = await migrateR6toV2({ root: memoryRoot, apply: true });
162
+ try {
163
+ writeFileSyncSafe(stateFile, JSON.stringify({
164
+ completedAt: new Date().toISOString(),
165
+ migratedScopes: result.migratedScopes,
166
+ skippedScopes: result.skippedScopes,
167
+ errors: result.errors,
168
+ backedUpTo: result.backedUpTo,
169
+ }, null, 2));
170
+ } catch { /* state file write is best-effort */ }
171
+ console.log(`[Yeaft] memory v2 migration done — ${result.migratedScopes} scopes migrated, backup at ${result.backedUpTo}`);
172
+ } else if (!alreadyMigrated && !hasR6) {
173
+ // Fresh user, no R6 to migrate. Mark as done so we don't keep checking.
174
+ try {
175
+ writeFileSyncSafe(stateFile, JSON.stringify({
176
+ completedAt: new Date().toISOString(),
177
+ migratedScopes: 0,
178
+ note: 'no R6 layout present — fresh v2',
179
+ }, null, 2));
180
+ } catch { /* best-effort */ }
181
+ }
182
+ }
183
+ } catch (err) {
184
+ console.warn(`[Yeaft] memory v2 migration skipped due to error: ${err?.message || err}`);
185
+ }
186
+
138
187
  // ─── 2a. Permission pre-check ─────────────────────────
139
188
  // If the data dir is not writable, mark session as read-only.
140
189
  // Persistence (conversation, memory, dream) is skipped in this mode.