@alfe.ai/openclaw-memory-cloud 0.0.25 → 0.0.27

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @alfe.ai/openclaw-memory-cloud@0.0.25 build /home/runner/work/alfe/alfe/packages/openclaw-memory-cloud
2
+ > @alfe.ai/openclaw-memory-cloud@0.0.27 build /home/runner/work/alfe/alfe/packages/openclaw-memory-cloud
3
3
  > tsc
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @alfe.ai/openclaw-memory-cloud
2
2
 
3
+ ## 0.0.27
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [3cb626d]
8
+ - @alfe.ai/agent-api-client@0.6.1
9
+
10
+ ## 0.0.26
11
+
12
+ ### Patch Changes
13
+
14
+ - 0f90085: One-time backfill of existing chat history when memory is first installed. On
15
+ startup, if the server-side `sessionsBackfillSyncedAt` flag is unset, the plugin
16
+ reads the openclaw-chat session files (`~/.alfe/sessions/chat/*.json`), takes the
17
+ most recent `backfillMaxSessions` (default 50) sessions, and ingests messages
18
+ through the existing `/agent/memory/ingest` pipeline. Duplicate-safe by
19
+ construction: a timestamp cutoff excludes anything already captured live (agents
20
+ that had memory before this release only backfill pre-install messages), and the
21
+ ingest consumer's per-session `lastProcessedIndex` high-water mark makes retries
22
+ free. New plugin config: `backfillSessions` (default true), `backfillMaxSessions`
23
+ (default 50). agent-api-client: `memoryBootstrapStatus()` now also returns
24
+ `sessionsBackfillSynced`/`sessionsBackfillSyncedAt`, and
25
+ `memoryBootstrapStatusMark()` accepts an optional `scope` ("files" | "sessions").
26
+ - Updated dependencies [0f90085]
27
+ - @alfe.ai/agent-api-client@0.6.0
28
+
3
29
  ## 0.0.25
4
30
 
5
31
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAeH,UAAU,SAAS;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAC5D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAC7D,CAAC;IACF,YAAY,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IACzF,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5I,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvG,2BAA2B,EAAE,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE;QAAE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;KAAE,KAAK,MAAM,EAAE,KAAK,IAAI,CAAC;IACtG,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACnD;AAED,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACpF;;;;;;;kBA2Be,SAAS,GAAG,IAAI;;AAPhC,wBAoRE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgBH,UAAU,SAAS;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAC5D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAC7D,CAAC;IACF,YAAY,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IACzF,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5I,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACvG,2BAA2B,EAAE,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE;QAAE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;KAAE,KAAK,MAAM,EAAE,KAAK,IAAI,CAAC;IACtG,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACnD;AAED,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACpF;;;;;;;kBAkCe,SAAS,GAAG,IAAI;;AAPhC,wBAoRE"}
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ import { AgentApiClient } from "@alfe.ai/agent-api-client";
18
18
  import { AutoCapture } from "./auto-capture.js";
19
19
  import { AutoRecall } from "./auto-recall.js";
20
20
  import { formatSearchResults } from "./formatter.js";
21
+ import { runSessionsBackfill } from "./session-backfill.js";
21
22
  import { createRequire } from 'node:module';
22
23
  const require = createRequire(import.meta.url);
23
24
  const pkg = require('../package.json');
@@ -26,6 +27,8 @@ const DEFAULT_CONFIG = {
26
27
  autoRecall: true,
27
28
  captureMaxChars: 500,
28
29
  idleFlushSeconds: 60,
30
+ backfillSessions: true,
31
+ backfillMaxSessions: 50,
29
32
  };
30
33
  function resolvePluginConfig(pluginConfig) {
31
34
  return {
@@ -33,6 +36,10 @@ function resolvePluginConfig(pluginConfig) {
33
36
  autoRecall: typeof pluginConfig?.autoRecall === "boolean" ? pluginConfig.autoRecall : DEFAULT_CONFIG.autoRecall,
34
37
  captureMaxChars: typeof pluginConfig?.captureMaxChars === "number" ? pluginConfig.captureMaxChars : DEFAULT_CONFIG.captureMaxChars,
35
38
  idleFlushSeconds: typeof pluginConfig?.idleFlushSeconds === "number" ? pluginConfig.idleFlushSeconds : DEFAULT_CONFIG.idleFlushSeconds,
39
+ backfillSessions: typeof pluginConfig?.backfillSessions === "boolean" ? pluginConfig.backfillSessions : DEFAULT_CONFIG.backfillSessions,
40
+ backfillMaxSessions: typeof pluginConfig?.backfillMaxSessions === "number" && Number.isFinite(pluginConfig.backfillMaxSessions) && pluginConfig.backfillMaxSessions > 0
41
+ ? Math.floor(pluginConfig.backfillMaxSessions)
42
+ : DEFAULT_CONFIG.backfillMaxSessions,
36
43
  };
37
44
  }
38
45
  export default {
@@ -280,16 +287,20 @@ export default {
280
287
  await autoCapture.onAgentEnd();
281
288
  }
282
289
  });
283
- // Fire-and-forget first-run sync: if MEMORY.md / memory/*.md exist
284
- // in the workspace, ingest them once into cloud memory. Idempotent
285
- // via PalaceMetadata.bootstrapSyncedAt.
286
- void runBootstrap(client, logger).catch((err) => {
287
- logger.warn("memory bootstrap failed; will retry on next startup", { err: String(err) });
290
+ // Fire-and-forget first-run sync: workspace files (MEMORY.md / memory/*.md)
291
+ // and pre-existing chat sessions, each idempotent via its own
292
+ // PalaceMetadata flag (bootstrapSyncedAt / sessionsBackfillSyncedAt).
293
+ void runStartupSync(client, config, logger).catch((err) => {
294
+ logger.warn("memory startup sync failed; will retry on next startup", { err: String(err) });
288
295
  });
289
296
  logger.info("memory-cloud extension registered", { autoCapture: config.autoCapture, autoRecall: config.autoRecall });
290
297
  },
291
298
  };
292
- async function runBootstrap(client, logger) {
299
+ async function runStartupSync(client, config, logger) {
300
+ // Fetch status ONCE, before the file bootstrap runs: the sessions backfill
301
+ // computes its dedup cutoff from the pre-bootstrap `syncedAt` (an agent
302
+ // that already had memory installed captured everything after that moment
303
+ // live, so backfilling past it would duplicate memories).
293
304
  let status;
294
305
  try {
295
306
  status = await client.memoryBootstrapStatus();
@@ -298,10 +309,29 @@ async function runBootstrap(client, logger) {
298
309
  logger.debug("memory bootstrap status check failed; skipping", { err: String(err) });
299
310
  return;
300
311
  }
312
+ const startupMs = Date.now();
301
313
  if (status.synced) {
302
314
  logger.debug("memory bootstrap: already synced, skipping");
303
- return;
304
315
  }
316
+ else {
317
+ try {
318
+ await runBootstrap(client, logger);
319
+ }
320
+ catch (err) {
321
+ logger.warn("memory bootstrap failed; will retry on next startup", { err: String(err) });
322
+ }
323
+ }
324
+ // Strict `=== false` on purpose: an old server (deployed before the
325
+ // sessions-backfill release) omits the field entirely, and its mark
326
+ // endpoint would clobber `bootstrapSyncedAt` — corrupting the cutoff
327
+ // anchor. Defer until the service is deployed and reports the flag.
328
+ if (config.backfillSessions && status.sessionsBackfillSynced === false) {
329
+ const installedAtMs = status.syncedAt ? Date.parse(status.syncedAt) : Number.POSITIVE_INFINITY;
330
+ const cutoffMs = Math.min(startupMs, Number.isNaN(installedAtMs) ? Number.POSITIVE_INFINITY : installedAtMs);
331
+ await runSessionsBackfill(client, config, logger, { cutoffMs });
332
+ }
333
+ }
334
+ async function runBootstrap(client, logger) {
305
335
  const cwd = process.cwd();
306
336
  const filesToSync = [];
307
337
  try {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Session backfill — one-time ingestion of pre-existing chat history into
3
+ * cloud memory, run fire-and-forget at plugin startup (see index.ts).
4
+ *
5
+ * Reads the openclaw-chat plugin's on-disk session files directly:
6
+ * ~/.alfe/sessions/chat/{sessionId}.json
7
+ * The write side is packages/openclaw-chat/src/session-store.ts — that path
8
+ * and file shape are a read contract; keep the two in sync. The chat plugin
9
+ * is not a package dependency because its session-store functions aren't
10
+ * part of its public entry and the plugin isn't guaranteed to be installed
11
+ * alongside memory. Like the session store itself, this assumes one agent
12
+ * per machine (`alfe remove` deletes ~/.alfe, so files never outlive the
13
+ * agent they belong to).
14
+ *
15
+ * No-re-sync guarantees (in concert with services/memory):
16
+ * 1. Runs only while the server-side `sessionsBackfillSyncedAt` flag is
17
+ * unset; the flag survives integration uninstall/reinstall.
18
+ * 2. Only messages with timestamp < cutoffMs are ingested — for agents that
19
+ * already had memory installed, everything after `bootstrapSyncedAt` was
20
+ * already captured live by AutoCapture.
21
+ * 3. sessionKey = file sessionId and index = file array position, so the
22
+ * ingest consumer's per-session `lastProcessedIndex` high-water mark makes
23
+ * a crash-and-retry replay free (filtered server-side before any cost).
24
+ *
25
+ * Each session is sent as exactly ONE memoryIngest call (one SQS message,
26
+ * windowed to the most recent messages that fit the caps below). Splitting a
27
+ * session across multiple SQS messages would race the shared per-session
28
+ * high-water mark on the standard (non-FIFO) ingest queue: a transiently
29
+ * failed early chunk redelivered after a later chunk succeeds gets filtered
30
+ * out and silently lost.
31
+ */
32
+ import type { MemoryCloudConfig, MemoryMessage, SessionMetadata } from "./types.js";
33
+ interface BackfillApi {
34
+ memoryIngest(sessionKey: string, messages: MemoryMessage[], metadata?: SessionMetadata): Promise<{
35
+ queued: boolean;
36
+ messageCount: number;
37
+ }>;
38
+ memoryBootstrapStatusMark(scope?: "files" | "sessions"): Promise<{
39
+ synced: true;
40
+ syncedAt: string;
41
+ }>;
42
+ }
43
+ interface BackfillLogger {
44
+ info: (msg: string, ctx?: Record<string, unknown>) => void;
45
+ debug: (msg: string, ctx?: Record<string, unknown>) => void;
46
+ warn: (msg: string, ctx?: Record<string, unknown>) => void;
47
+ }
48
+ export interface SessionsBackfillOptions {
49
+ cutoffMs: number;
50
+ sessionsDir?: string;
51
+ }
52
+ export declare function runSessionsBackfill(client: BackfillApi, config: MemoryCloudConfig, logger: BackfillLogger, opts: SessionsBackfillOptions): Promise<void>;
53
+ export {};
54
+ //# sourceMappingURL=session-backfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-backfill.d.ts","sourceRoot":"","sources":["../src/session-backfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAcpF,UAAU,WAAW;IACnB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5I,yBAAyB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtG;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC3D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC5D;AAWD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAmEf"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Session backfill — one-time ingestion of pre-existing chat history into
3
+ * cloud memory, run fire-and-forget at plugin startup (see index.ts).
4
+ *
5
+ * Reads the openclaw-chat plugin's on-disk session files directly:
6
+ * ~/.alfe/sessions/chat/{sessionId}.json
7
+ * The write side is packages/openclaw-chat/src/session-store.ts — that path
8
+ * and file shape are a read contract; keep the two in sync. The chat plugin
9
+ * is not a package dependency because its session-store functions aren't
10
+ * part of its public entry and the plugin isn't guaranteed to be installed
11
+ * alongside memory. Like the session store itself, this assumes one agent
12
+ * per machine (`alfe remove` deletes ~/.alfe, so files never outlive the
13
+ * agent they belong to).
14
+ *
15
+ * No-re-sync guarantees (in concert with services/memory):
16
+ * 1. Runs only while the server-side `sessionsBackfillSyncedAt` flag is
17
+ * unset; the flag survives integration uninstall/reinstall.
18
+ * 2. Only messages with timestamp < cutoffMs are ingested — for agents that
19
+ * already had memory installed, everything after `bootstrapSyncedAt` was
20
+ * already captured live by AutoCapture.
21
+ * 3. sessionKey = file sessionId and index = file array position, so the
22
+ * ingest consumer's per-session `lastProcessedIndex` high-water mark makes
23
+ * a crash-and-retry replay free (filtered server-side before any cost).
24
+ *
25
+ * Each session is sent as exactly ONE memoryIngest call (one SQS message,
26
+ * windowed to the most recent messages that fit the caps below). Splitting a
27
+ * session across multiple SQS messages would race the shared per-session
28
+ * high-water mark on the standard (non-FIFO) ingest queue: a transiently
29
+ * failed early chunk redelivered after a later chunk succeeds gets filtered
30
+ * out and silently lost.
31
+ */
32
+ import { readdir, readFile } from "node:fs/promises";
33
+ import { join } from "node:path";
34
+ import { homedir } from "node:os";
35
+ const DEFAULT_SESSIONS_DIR = join(homedir(), ".alfe", "sessions", "chat");
36
+ // Server-side zod caps on /agent/memory/ingest (services/memory
37
+ // api-agents/ingest/post.ts) — exceeding any of these is a deterministic 400,
38
+ // which would put the startup retry loop into a permanent failure.
39
+ const MAX_MESSAGES_PER_SESSION = 500;
40
+ const MAX_SESSION_KEY_CHARS = 256;
41
+ const MAX_MESSAGE_INDEX = 1_000_000;
42
+ const MAX_CONTENT_CHARS = 100_000;
43
+ /** One ingest call becomes one SQS SendMessage (256KB hard limit). */
44
+ const MAX_BATCH_BYTES = 180_000;
45
+ export async function runSessionsBackfill(client, config, logger, opts) {
46
+ const sessionsDir = opts.sessionsDir ?? DEFAULT_SESSIONS_DIR;
47
+ let fileNames;
48
+ try {
49
+ fileNames = (await readdir(sessionsDir)).filter((name) => name.endsWith(".json"));
50
+ }
51
+ catch (err) {
52
+ if (err.code === "ENOENT") {
53
+ // No sessions directory — nothing to backfill, ever.
54
+ logger.debug("sessions backfill: no sessions directory, marking complete");
55
+ try {
56
+ await client.memoryBootstrapStatusMark("sessions");
57
+ }
58
+ catch { /* retry next start */ }
59
+ }
60
+ else {
61
+ // Transient (EACCES/EMFILE/...) — don't forfeit the backfill.
62
+ logger.warn("sessions backfill: sessions directory unreadable; will retry on next startup", { err: String(err) });
63
+ }
64
+ return;
65
+ }
66
+ const sessions = [];
67
+ for (const name of fileNames) {
68
+ const parsed = await parseSessionFile(join(sessionsDir, name), config.captureMaxChars, opts.cutoffMs);
69
+ if (parsed)
70
+ sessions.push(parsed);
71
+ }
72
+ // Most recent non-empty sessions first, capped. Filter BEFORE capping:
73
+ // on a retrofit agent the newest sessions are often entirely post-install
74
+ // (emptied by the cutoff) and must not occupy the cap slots.
75
+ const eligible = sessions
76
+ .filter((s) => s.messages.length > 0)
77
+ .sort((a, b) => b.lastMessageMs - a.lastMessageMs)
78
+ .slice(0, config.backfillMaxSessions);
79
+ if (eligible.length === 0) {
80
+ logger.debug("sessions backfill: no eligible sessions, marking complete");
81
+ try {
82
+ await client.memoryBootstrapStatusMark("sessions");
83
+ }
84
+ catch { /* retry next start */ }
85
+ return;
86
+ }
87
+ logger.info("sessions backfill: ingesting sessions", {
88
+ sessionCount: eligible.length,
89
+ messageCount: eligible.reduce((n, s) => n + s.messages.length, 0),
90
+ });
91
+ for (const session of eligible) {
92
+ const metadata = {
93
+ ...(session.channel ? { channelId: session.channel } : {}),
94
+ ...(session.userId ? { userId: session.userId } : {}),
95
+ };
96
+ try {
97
+ await client.memoryIngest(session.sessionId, session.messages, metadata);
98
+ }
99
+ catch (err) {
100
+ // Abort without marking — next startup replays, and the server-side
101
+ // lastProcessedIndex filter discards already-processed sessions free.
102
+ logger.warn("sessions backfill: ingest failed; will retry on next startup", {
103
+ sessionId: session.sessionId,
104
+ err: String(err),
105
+ });
106
+ return;
107
+ }
108
+ }
109
+ try {
110
+ await client.memoryBootstrapStatusMark("sessions");
111
+ logger.info("sessions backfill: complete", { sessionCount: eligible.length });
112
+ }
113
+ catch (err) {
114
+ logger.warn("sessions backfill: mark failed; will retry on next startup", { err: String(err) });
115
+ }
116
+ }
117
+ /**
118
+ * Tolerant parse of a single session file. Returns null for corrupt or
119
+ * shape-mismatched files (skipped, never fatal). Message `index` is the
120
+ * original array position in the file — stable because the store is
121
+ * append-only — so retries resume idempotently server-side.
122
+ */
123
+ async function parseSessionFile(filePath, captureMaxChars, cutoffMs) {
124
+ let raw;
125
+ try {
126
+ raw = JSON.parse(await readFile(filePath, "utf8"));
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ if (typeof raw !== "object" || raw === null)
132
+ return null;
133
+ const data = raw;
134
+ if (typeof data.sessionId !== "string" || data.sessionId.length === 0)
135
+ return null;
136
+ if (data.sessionId.length > MAX_SESSION_KEY_CHARS)
137
+ return null;
138
+ if (!Array.isArray(data.messages))
139
+ return null;
140
+ const maxContentChars = Math.min(captureMaxChars, MAX_CONTENT_CHARS);
141
+ let lastMessageMs = 0;
142
+ const filtered = [];
143
+ for (const [index, entry] of data.messages.entries()) {
144
+ if (index > MAX_MESSAGE_INDEX)
145
+ break;
146
+ if (typeof entry !== "object" || entry === null)
147
+ continue;
148
+ const msg = entry;
149
+ if (msg.role !== "user" && msg.role !== "assistant")
150
+ continue;
151
+ if (typeof msg.content !== "string" || msg.content.trim().length === 0)
152
+ continue;
153
+ if (typeof msg.timestamp !== "number")
154
+ continue;
155
+ lastMessageMs = Math.max(lastMessageMs, msg.timestamp);
156
+ if (msg.timestamp >= cutoffMs)
157
+ continue;
158
+ filtered.push({
159
+ role: msg.role,
160
+ content: msg.content.length > maxContentChars ? msg.content.slice(0, maxContentChars) : msg.content,
161
+ index,
162
+ timestamp: new Date(msg.timestamp).toISOString(),
163
+ });
164
+ }
165
+ return {
166
+ sessionId: data.sessionId,
167
+ channel: typeof data.channel === "string" ? data.channel : undefined,
168
+ userId: typeof data.userId === "string" ? data.userId : undefined,
169
+ messages: recentWindow(filtered),
170
+ lastMessageMs,
171
+ };
172
+ }
173
+ /**
174
+ * The most recent contiguous run of messages fitting both ingest caps
175
+ * (message count and serialized bytes). Walks backwards from the newest
176
+ * message and stops at the first one that would overflow the byte budget.
177
+ */
178
+ function recentWindow(messages) {
179
+ const window = [];
180
+ let bytes = 0;
181
+ for (let i = messages.length - 1; i >= 0; i--) {
182
+ if (window.length >= MAX_MESSAGES_PER_SESSION)
183
+ break;
184
+ const msgBytes = Buffer.byteLength(JSON.stringify(messages[i])) + 1;
185
+ if (bytes + msgBytes > MAX_BATCH_BYTES)
186
+ break;
187
+ window.unshift(messages[i]);
188
+ bytes += msgBytes;
189
+ }
190
+ return window;
191
+ }
192
+ //# sourceMappingURL=session-backfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-backfill.js","sourceRoot":"","sources":["../src/session-backfill.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -3,6 +3,8 @@ export interface MemoryCloudConfig {
3
3
  autoRecall: boolean;
4
4
  captureMaxChars: number;
5
5
  idleFlushSeconds: number;
6
+ backfillSessions: boolean;
7
+ backfillMaxSessions: number;
6
8
  }
7
9
  export interface MemoryMessage {
8
10
  role: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CAAC;IACJ,QAAQ,EAAE;QACR,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;CACL;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/E,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QACjC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC5B,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAEhC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAElC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE5I,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;IAE7G,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAC3C,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAC7H,CAAC,CAAC;IAEH,cAAc,IAAI,OAAO,CAAC;QACxB,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,EAAE,CAAA;SAAE,EAAE,CAAC;QACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC,CAAC;IAEH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAE9D,WAAW,IAAI,OAAO,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;CACJ"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -43,6 +43,18 @@
43
43
  "minimum": 10,
44
44
  "maximum": 600,
45
45
  "description": "Flush memories after this many seconds of no messages"
46
+ },
47
+ "backfillSessions": {
48
+ "type": "boolean",
49
+ "default": true,
50
+ "description": "On first install, ingest the agent's existing chat sessions into memory (one-time, duplicate-safe)"
51
+ },
52
+ "backfillMaxSessions": {
53
+ "type": "number",
54
+ "default": 50,
55
+ "minimum": 1,
56
+ "maximum": 1000,
57
+ "description": "Maximum number of most-recent chat sessions to backfill"
46
58
  }
47
59
  }
48
60
  },
@@ -58,6 +70,14 @@
58
70
  "idleFlushSeconds": {
59
71
  "label": "Idle flush interval",
60
72
  "description": "Seconds of inactivity before flushing pending memories"
73
+ },
74
+ "backfillSessions": {
75
+ "label": "Backfill chat history",
76
+ "description": "Ingest existing chat sessions into memory on first install"
77
+ },
78
+ "backfillMaxSessions": {
79
+ "label": "Backfill session cap",
80
+ "description": "Maximum number of most-recent chat sessions to backfill"
61
81
  }
62
82
  }
63
83
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/openclaw-memory-cloud",
3
- "version": "0.0.25",
3
+ "version": "0.0.27",
4
4
  "description": "Cloud memory extension for OpenClaw — Turbopuffer vectors + DynamoDB knowledge graph",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,7 +11,7 @@
11
11
  ]
12
12
  },
13
13
  "dependencies": {
14
- "@alfe.ai/agent-api-client": "0.5.0",
14
+ "@alfe.ai/agent-api-client": "0.6.1",
15
15
  "@alfe.ai/config": "0.3.0"
16
16
  },
17
17
  "license": "UNLICENSED",
@@ -27,6 +27,8 @@
27
27
  ],
28
28
  "scripts": {
29
29
  "build": "tsc",
30
+ "test": "vitest run --passWithNoTests",
31
+ "test:watch": "vitest",
30
32
  "typecheck": "tsc --noEmit",
31
33
  "lint": "eslint ."
32
34
  }
@@ -0,0 +1,289 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { mkdtemp, writeFile, rm, mkdir, chmod } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { runSessionsBackfill } from "../session-backfill.js";
6
+ import type { MemoryCloudConfig, MemoryMessage, SessionMetadata } from "../types.js";
7
+
8
+ const CONFIG: MemoryCloudConfig = {
9
+ autoCapture: true,
10
+ autoRecall: true,
11
+ captureMaxChars: 500,
12
+ idleFlushSeconds: 60,
13
+ backfillSessions: true,
14
+ backfillMaxSessions: 50,
15
+ };
16
+
17
+ const logger = { info: vi.fn(), debug: vi.fn(), warn: vi.fn() };
18
+
19
+ function makeClient() {
20
+ return {
21
+ memoryIngest: vi.fn(async (sessionKey: string, messages: MemoryMessage[], metadata?: SessionMetadata) => {
22
+ void sessionKey;
23
+ void metadata;
24
+ return { queued: true, messageCount: messages.length };
25
+ }),
26
+ memoryBootstrapStatusMark: vi.fn(async (scope?: "files" | "sessions") => {
27
+ void scope;
28
+ return { synced: true as const, syncedAt: new Date().toISOString() };
29
+ }),
30
+ };
31
+ }
32
+
33
+ function sessionFile(sessionId: string, messages: { role: string; content: string; timestamp: number }[], extra?: Record<string, unknown>) {
34
+ return JSON.stringify({
35
+ sessionId,
36
+ agentId: "",
37
+ channel: "alfe",
38
+ createdAt: new Date(0).toISOString(),
39
+ updatedAt: new Date().toISOString(),
40
+ messages,
41
+ ...extra,
42
+ });
43
+ }
44
+
45
+ describe("runSessionsBackfill", () => {
46
+ let dir: string;
47
+
48
+ beforeEach(async () => {
49
+ dir = await mkdtemp(join(tmpdir(), "memory-backfill-"));
50
+ vi.clearAllMocks();
51
+ });
52
+
53
+ afterEach(async () => {
54
+ await rm(dir, { recursive: true, force: true });
55
+ });
56
+
57
+ it("marks complete immediately when the sessions directory is missing", async () => {
58
+ const client = makeClient();
59
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: join(dir, "nope") });
60
+ expect(client.memoryIngest).not.toHaveBeenCalled();
61
+ expect(client.memoryBootstrapStatusMark).toHaveBeenCalledWith("sessions");
62
+ });
63
+
64
+ it("marks complete when no eligible sessions exist", async () => {
65
+ const client = makeClient();
66
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
67
+ expect(client.memoryIngest).not.toHaveBeenCalled();
68
+ expect(client.memoryBootstrapStatusMark).toHaveBeenCalledWith("sessions");
69
+ });
70
+
71
+ it("skips corrupt and shape-mismatched files but ingests valid ones", async () => {
72
+ await writeFile(join(dir, "corrupt.json"), "{not json");
73
+ await writeFile(join(dir, "no-messages.json"), JSON.stringify({ sessionId: "x" }));
74
+ await writeFile(join(dir, "good.json"), sessionFile("alfe:dm:user1", [
75
+ { role: "user", content: "hello", timestamp: 1000 },
76
+ { role: "assistant", content: "hi there", timestamp: 2000 },
77
+ ]));
78
+
79
+ const client = makeClient();
80
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
81
+
82
+ expect(client.memoryIngest).toHaveBeenCalledTimes(1);
83
+ const [sessionKey, messages] = client.memoryIngest.mock.calls[0];
84
+ expect(sessionKey).toBe("alfe:dm:user1");
85
+ expect(messages).toHaveLength(2);
86
+ expect(client.memoryBootstrapStatusMark).toHaveBeenCalledWith("sessions");
87
+ });
88
+
89
+ it("excludes messages at or after the cutoff (retrofit dedup)", async () => {
90
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", [
91
+ { role: "user", content: "before install", timestamp: 1000 },
92
+ { role: "user", content: "after install", timestamp: 5000 },
93
+ ]));
94
+
95
+ const client = makeClient();
96
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: 5000, sessionsDir: dir });
97
+
98
+ const [, messages] = client.memoryIngest.mock.calls[0];
99
+ expect(messages).toHaveLength(1);
100
+ expect((messages as MemoryMessage[])[0].content).toBe("before install");
101
+ });
102
+
103
+ it("preserves file-array positions as indexes and skips invalid entries without renumbering", async () => {
104
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", [
105
+ { role: "user", content: "first", timestamp: 1000 },
106
+ { role: "system", content: "not a chat role", timestamp: 1500 },
107
+ { role: "assistant", content: "second", timestamp: 2000 },
108
+ ]));
109
+
110
+ const client = makeClient();
111
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
112
+
113
+ const [, messages] = client.memoryIngest.mock.calls[0] as [string, MemoryMessage[]];
114
+ expect(messages.map((m) => m.index)).toEqual([0, 2]);
115
+ expect(messages[0].timestamp).toBe(new Date(1000).toISOString());
116
+ });
117
+
118
+ it("truncates message content to captureMaxChars", async () => {
119
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", [
120
+ { role: "user", content: "x".repeat(2000), timestamp: 1000 },
121
+ ]));
122
+
123
+ const client = makeClient();
124
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
125
+
126
+ const [, messages] = client.memoryIngest.mock.calls[0] as [string, MemoryMessage[]];
127
+ expect(messages[0].content).toHaveLength(500);
128
+ });
129
+
130
+ it("sends each session as exactly one ingest call (no cross-chunk race)", async () => {
131
+ const messages = Array.from({ length: 101 }, (_, i) => ({
132
+ role: "user",
133
+ content: `msg ${String(i)}`,
134
+ timestamp: 1000 + i,
135
+ }));
136
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", messages));
137
+
138
+ const client = makeClient();
139
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
140
+
141
+ expect(client.memoryIngest).toHaveBeenCalledTimes(1);
142
+ expect(client.memoryIngest.mock.calls[0][1]).toHaveLength(101);
143
+ });
144
+
145
+ it("keeps only the most recent 500 messages of a session, preserving original indexes", async () => {
146
+ const messages = Array.from({ length: 600 }, (_, i) => ({
147
+ role: "user",
148
+ content: `msg ${String(i)}`,
149
+ timestamp: 1000 + i,
150
+ }));
151
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", messages));
152
+
153
+ const client = makeClient();
154
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
155
+
156
+ expect(client.memoryIngest).toHaveBeenCalledTimes(1);
157
+ const sent = client.memoryIngest.mock.calls[0][1] as MemoryMessage[];
158
+ expect(sent).toHaveLength(500);
159
+ expect(sent[0].index).toBe(100);
160
+ expect(sent[sent.length - 1].index).toBe(599);
161
+ });
162
+
163
+ it("shrinks the window to the most recent messages when the byte budget would overflow", async () => {
164
+ // ~40KB of content per message → only 4 fit in the 180KB budget.
165
+ const messages = Array.from({ length: 10 }, (_, i) => ({
166
+ role: "user",
167
+ content: "x".repeat(40_000),
168
+ timestamp: 1000 + i,
169
+ }));
170
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", messages));
171
+
172
+ const client = makeClient();
173
+ await runSessionsBackfill(client, { ...CONFIG, captureMaxChars: 50_000 }, logger, { cutoffMs: Date.now(), sessionsDir: dir });
174
+
175
+ expect(client.memoryIngest).toHaveBeenCalledTimes(1);
176
+ const sent = client.memoryIngest.mock.calls[0][1] as MemoryMessage[];
177
+ expect(sent).toHaveLength(4);
178
+ expect(sent[sent.length - 1].index).toBe(9);
179
+ });
180
+
181
+ it("skips sessions whose sessionId exceeds the server's 256-char cap", async () => {
182
+ await writeFile(join(dir, "long.json"), sessionFile("x".repeat(300), [
183
+ { role: "user", content: "hello", timestamp: 1000 },
184
+ ]));
185
+
186
+ const client = makeClient();
187
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
188
+
189
+ expect(client.memoryIngest).not.toHaveBeenCalled();
190
+ expect(client.memoryBootstrapStatusMark).toHaveBeenCalledWith("sessions");
191
+ });
192
+
193
+ it("does not let post-cutoff sessions starve pre-cutoff sessions out of the cap (retrofit)", async () => {
194
+ // Newest session is entirely post-install — emptied by the cutoff. It
195
+ // must not occupy the single cap slot.
196
+ await writeFile(join(dir, "post-install.json"), sessionFile("alfe:dm:recent", [
197
+ { role: "user", content: "captured live already", timestamp: 9000 },
198
+ ]));
199
+ await writeFile(join(dir, "pre-install.json"), sessionFile("alfe:dm:old", [
200
+ { role: "user", content: "history worth keeping", timestamp: 1000 },
201
+ ]));
202
+
203
+ const client = makeClient();
204
+ await runSessionsBackfill(client, { ...CONFIG, backfillMaxSessions: 1 }, logger, { cutoffMs: 5000, sessionsDir: dir });
205
+
206
+ expect(client.memoryIngest).toHaveBeenCalledTimes(1);
207
+ expect(client.memoryIngest.mock.calls[0][0]).toBe("alfe:dm:old");
208
+ });
209
+
210
+ it("caps at backfillMaxSessions, keeping the most recent sessions", async () => {
211
+ await writeFile(join(dir, "old.json"), sessionFile("alfe:dm:old", [
212
+ { role: "user", content: "old", timestamp: 1000 },
213
+ ]));
214
+ await writeFile(join(dir, "new.json"), sessionFile("alfe:dm:new", [
215
+ { role: "user", content: "new", timestamp: 9000 },
216
+ ]));
217
+
218
+ const client = makeClient();
219
+ await runSessionsBackfill(client, { ...CONFIG, backfillMaxSessions: 1 }, logger, { cutoffMs: Date.now(), sessionsDir: dir });
220
+
221
+ expect(client.memoryIngest).toHaveBeenCalledTimes(1);
222
+ expect(client.memoryIngest.mock.calls[0][0]).toBe("alfe:dm:new");
223
+ });
224
+
225
+ it("aborts without marking when an ingest call fails", async () => {
226
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", [
227
+ { role: "user", content: "hello", timestamp: 1000 },
228
+ ]));
229
+
230
+ const client = makeClient();
231
+ client.memoryIngest.mockRejectedValueOnce(new Error("boom"));
232
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
233
+
234
+ expect(client.memoryBootstrapStatusMark).not.toHaveBeenCalled();
235
+ expect(logger.warn).toHaveBeenCalled();
236
+ });
237
+
238
+ it("passes session channel and userId as ingest metadata", async () => {
239
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", [
240
+ { role: "user", content: "hello", timestamp: 1000 },
241
+ ], { channel: "alfe", userId: "user_123" }));
242
+
243
+ const client = makeClient();
244
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
245
+
246
+ const metadata = client.memoryIngest.mock.calls[0][2];
247
+ expect(metadata).toEqual({ channelId: "alfe", userId: "user_123" });
248
+ });
249
+
250
+ it("does not warn or fail when the mark call itself fails (retries next startup)", async () => {
251
+ await writeFile(join(dir, "s.json"), sessionFile("alfe:dm:u", [
252
+ { role: "user", content: "hello", timestamp: 1000 },
253
+ ]));
254
+
255
+ const client = makeClient();
256
+ client.memoryBootstrapStatusMark.mockRejectedValueOnce(new Error("mark failed"));
257
+ await expect(
258
+ runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir }),
259
+ ).resolves.toBeUndefined();
260
+ expect(logger.warn).toHaveBeenCalledWith(
261
+ "sessions backfill: mark failed; will retry on next startup",
262
+ expect.anything(),
263
+ );
264
+ });
265
+
266
+ it("does not mark complete when the directory read fails for a non-ENOENT reason", async () => {
267
+ const locked = join(dir, "locked");
268
+ await mkdir(locked);
269
+ await chmod(locked, 0o000);
270
+ try {
271
+ const client = makeClient();
272
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: locked });
273
+ expect(client.memoryIngest).not.toHaveBeenCalled();
274
+ expect(client.memoryBootstrapStatusMark).not.toHaveBeenCalled();
275
+ expect(logger.warn).toHaveBeenCalled();
276
+ } finally {
277
+ await chmod(locked, 0o755);
278
+ }
279
+ });
280
+
281
+ it("ignores non-json files and nested directories", async () => {
282
+ await writeFile(join(dir, "notes.txt"), "not a session");
283
+ await mkdir(join(dir, "sub.json.d"));
284
+ const client = makeClient();
285
+ await runSessionsBackfill(client, CONFIG, logger, { cutoffMs: Date.now(), sessionsDir: dir });
286
+ expect(client.memoryIngest).not.toHaveBeenCalled();
287
+ expect(client.memoryBootstrapStatusMark).toHaveBeenCalledWith("sessions");
288
+ });
289
+ });
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ import { AgentApiClient } from "@alfe.ai/agent-api-client";
19
19
  import { AutoCapture } from "./auto-capture.js";
20
20
  import { AutoRecall } from "./auto-recall.js";
21
21
  import { formatSearchResults } from "./formatter.js";
22
+ import { runSessionsBackfill } from "./session-backfill.js";
22
23
  import type { MemoryCloudConfig } from "./types.js";
23
24
  import { createRequire } from 'node:module';
24
25
  const require = createRequire(import.meta.url);
@@ -63,6 +64,8 @@ const DEFAULT_CONFIG: MemoryCloudConfig = {
63
64
  autoRecall: true,
64
65
  captureMaxChars: 500,
65
66
  idleFlushSeconds: 60,
67
+ backfillSessions: true,
68
+ backfillMaxSessions: 50,
66
69
  };
67
70
 
68
71
  function resolvePluginConfig(pluginConfig?: Record<string, unknown>): MemoryCloudConfig {
@@ -71,6 +74,11 @@ function resolvePluginConfig(pluginConfig?: Record<string, unknown>): MemoryClou
71
74
  autoRecall: typeof pluginConfig?.autoRecall === "boolean" ? pluginConfig.autoRecall : DEFAULT_CONFIG.autoRecall,
72
75
  captureMaxChars: typeof pluginConfig?.captureMaxChars === "number" ? pluginConfig.captureMaxChars : DEFAULT_CONFIG.captureMaxChars,
73
76
  idleFlushSeconds: typeof pluginConfig?.idleFlushSeconds === "number" ? pluginConfig.idleFlushSeconds : DEFAULT_CONFIG.idleFlushSeconds,
77
+ backfillSessions: typeof pluginConfig?.backfillSessions === "boolean" ? pluginConfig.backfillSessions : DEFAULT_CONFIG.backfillSessions,
78
+ backfillMaxSessions:
79
+ typeof pluginConfig?.backfillMaxSessions === "number" && Number.isFinite(pluginConfig.backfillMaxSessions) && pluginConfig.backfillMaxSessions > 0
80
+ ? Math.floor(pluginConfig.backfillMaxSessions)
81
+ : DEFAULT_CONFIG.backfillMaxSessions,
74
82
  };
75
83
  }
76
84
 
@@ -341,33 +349,60 @@ export default {
341
349
  }
342
350
  });
343
351
 
344
- // Fire-and-forget first-run sync: if MEMORY.md / memory/*.md exist
345
- // in the workspace, ingest them once into cloud memory. Idempotent
346
- // via PalaceMetadata.bootstrapSyncedAt.
347
- void runBootstrap(client, logger).catch((err: unknown) => {
348
- logger.warn("memory bootstrap failed; will retry on next startup", { err: String(err) });
352
+ // Fire-and-forget first-run sync: workspace files (MEMORY.md / memory/*.md)
353
+ // and pre-existing chat sessions, each idempotent via its own
354
+ // PalaceMetadata flag (bootstrapSyncedAt / sessionsBackfillSyncedAt).
355
+ void runStartupSync(client, config, logger).catch((err: unknown) => {
356
+ logger.warn("memory startup sync failed; will retry on next startup", { err: String(err) });
349
357
  });
350
358
 
351
359
  logger.info("memory-cloud extension registered", { autoCapture: config.autoCapture, autoRecall: config.autoRecall });
352
360
  },
353
361
  };
354
362
 
355
- async function runBootstrap(
363
+ async function runStartupSync(
356
364
  client: AgentApiClient,
365
+ config: MemoryCloudConfig,
357
366
  logger: PluginApi["logger"],
358
367
  ): Promise<void> {
359
- let status: { synced: boolean };
368
+ // Fetch status ONCE, before the file bootstrap runs: the sessions backfill
369
+ // computes its dedup cutoff from the pre-bootstrap `syncedAt` (an agent
370
+ // that already had memory installed captured everything after that moment
371
+ // live, so backfilling past it would duplicate memories).
372
+ let status: { synced: boolean; syncedAt?: string; sessionsBackfillSynced?: boolean };
360
373
  try {
361
374
  status = await client.memoryBootstrapStatus();
362
375
  } catch (err) {
363
376
  logger.debug("memory bootstrap status check failed; skipping", { err: String(err) });
364
377
  return;
365
378
  }
379
+ const startupMs = Date.now();
380
+
366
381
  if (status.synced) {
367
382
  logger.debug("memory bootstrap: already synced, skipping");
368
- return;
383
+ } else {
384
+ try {
385
+ await runBootstrap(client, logger);
386
+ } catch (err) {
387
+ logger.warn("memory bootstrap failed; will retry on next startup", { err: String(err) });
388
+ }
369
389
  }
370
390
 
391
+ // Strict `=== false` on purpose: an old server (deployed before the
392
+ // sessions-backfill release) omits the field entirely, and its mark
393
+ // endpoint would clobber `bootstrapSyncedAt` — corrupting the cutoff
394
+ // anchor. Defer until the service is deployed and reports the flag.
395
+ if (config.backfillSessions && status.sessionsBackfillSynced === false) {
396
+ const installedAtMs = status.syncedAt ? Date.parse(status.syncedAt) : Number.POSITIVE_INFINITY;
397
+ const cutoffMs = Math.min(startupMs, Number.isNaN(installedAtMs) ? Number.POSITIVE_INFINITY : installedAtMs);
398
+ await runSessionsBackfill(client, config, logger, { cutoffMs });
399
+ }
400
+ }
401
+
402
+ async function runBootstrap(
403
+ client: AgentApiClient,
404
+ logger: PluginApi["logger"],
405
+ ): Promise<void> {
371
406
  const cwd = process.cwd();
372
407
  const filesToSync: string[] = [];
373
408
 
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Session backfill — one-time ingestion of pre-existing chat history into
3
+ * cloud memory, run fire-and-forget at plugin startup (see index.ts).
4
+ *
5
+ * Reads the openclaw-chat plugin's on-disk session files directly:
6
+ * ~/.alfe/sessions/chat/{sessionId}.json
7
+ * The write side is packages/openclaw-chat/src/session-store.ts — that path
8
+ * and file shape are a read contract; keep the two in sync. The chat plugin
9
+ * is not a package dependency because its session-store functions aren't
10
+ * part of its public entry and the plugin isn't guaranteed to be installed
11
+ * alongside memory. Like the session store itself, this assumes one agent
12
+ * per machine (`alfe remove` deletes ~/.alfe, so files never outlive the
13
+ * agent they belong to).
14
+ *
15
+ * No-re-sync guarantees (in concert with services/memory):
16
+ * 1. Runs only while the server-side `sessionsBackfillSyncedAt` flag is
17
+ * unset; the flag survives integration uninstall/reinstall.
18
+ * 2. Only messages with timestamp < cutoffMs are ingested — for agents that
19
+ * already had memory installed, everything after `bootstrapSyncedAt` was
20
+ * already captured live by AutoCapture.
21
+ * 3. sessionKey = file sessionId and index = file array position, so the
22
+ * ingest consumer's per-session `lastProcessedIndex` high-water mark makes
23
+ * a crash-and-retry replay free (filtered server-side before any cost).
24
+ *
25
+ * Each session is sent as exactly ONE memoryIngest call (one SQS message,
26
+ * windowed to the most recent messages that fit the caps below). Splitting a
27
+ * session across multiple SQS messages would race the shared per-session
28
+ * high-water mark on the standard (non-FIFO) ingest queue: a transiently
29
+ * failed early chunk redelivered after a later chunk succeeds gets filtered
30
+ * out and silently lost.
31
+ */
32
+
33
+ import { readdir, readFile } from "node:fs/promises";
34
+ import { join } from "node:path";
35
+ import { homedir } from "node:os";
36
+ import type { MemoryCloudConfig, MemoryMessage, SessionMetadata } from "./types.js";
37
+
38
+ const DEFAULT_SESSIONS_DIR = join(homedir(), ".alfe", "sessions", "chat");
39
+
40
+ // Server-side zod caps on /agent/memory/ingest (services/memory
41
+ // api-agents/ingest/post.ts) — exceeding any of these is a deterministic 400,
42
+ // which would put the startup retry loop into a permanent failure.
43
+ const MAX_MESSAGES_PER_SESSION = 500;
44
+ const MAX_SESSION_KEY_CHARS = 256;
45
+ const MAX_MESSAGE_INDEX = 1_000_000;
46
+ const MAX_CONTENT_CHARS = 100_000;
47
+ /** One ingest call becomes one SQS SendMessage (256KB hard limit). */
48
+ const MAX_BATCH_BYTES = 180_000;
49
+
50
+ interface BackfillApi {
51
+ memoryIngest(sessionKey: string, messages: MemoryMessage[], metadata?: SessionMetadata): Promise<{ queued: boolean; messageCount: number }>;
52
+ memoryBootstrapStatusMark(scope?: "files" | "sessions"): Promise<{ synced: true; syncedAt: string }>;
53
+ }
54
+
55
+ interface BackfillLogger {
56
+ info: (msg: string, ctx?: Record<string, unknown>) => void;
57
+ debug: (msg: string, ctx?: Record<string, unknown>) => void;
58
+ warn: (msg: string, ctx?: Record<string, unknown>) => void;
59
+ }
60
+
61
+ interface ParsedSession {
62
+ sessionId: string;
63
+ channel?: string;
64
+ userId?: string;
65
+ /** Recent-window messages carrying their original file-array position as `index`. */
66
+ messages: MemoryMessage[];
67
+ lastMessageMs: number;
68
+ }
69
+
70
+ export interface SessionsBackfillOptions {
71
+ cutoffMs: number;
72
+ sessionsDir?: string;
73
+ }
74
+
75
+ export async function runSessionsBackfill(
76
+ client: BackfillApi,
77
+ config: MemoryCloudConfig,
78
+ logger: BackfillLogger,
79
+ opts: SessionsBackfillOptions,
80
+ ): Promise<void> {
81
+ const sessionsDir = opts.sessionsDir ?? DEFAULT_SESSIONS_DIR;
82
+
83
+ let fileNames: string[];
84
+ try {
85
+ fileNames = (await readdir(sessionsDir)).filter((name) => name.endsWith(".json"));
86
+ } catch (err) {
87
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") {
88
+ // No sessions directory — nothing to backfill, ever.
89
+ logger.debug("sessions backfill: no sessions directory, marking complete");
90
+ try { await client.memoryBootstrapStatusMark("sessions"); } catch { /* retry next start */ }
91
+ } else {
92
+ // Transient (EACCES/EMFILE/...) — don't forfeit the backfill.
93
+ logger.warn("sessions backfill: sessions directory unreadable; will retry on next startup", { err: String(err) });
94
+ }
95
+ return;
96
+ }
97
+
98
+ const sessions: ParsedSession[] = [];
99
+ for (const name of fileNames) {
100
+ const parsed = await parseSessionFile(join(sessionsDir, name), config.captureMaxChars, opts.cutoffMs);
101
+ if (parsed) sessions.push(parsed);
102
+ }
103
+
104
+ // Most recent non-empty sessions first, capped. Filter BEFORE capping:
105
+ // on a retrofit agent the newest sessions are often entirely post-install
106
+ // (emptied by the cutoff) and must not occupy the cap slots.
107
+ const eligible = sessions
108
+ .filter((s) => s.messages.length > 0)
109
+ .sort((a, b) => b.lastMessageMs - a.lastMessageMs)
110
+ .slice(0, config.backfillMaxSessions);
111
+
112
+ if (eligible.length === 0) {
113
+ logger.debug("sessions backfill: no eligible sessions, marking complete");
114
+ try { await client.memoryBootstrapStatusMark("sessions"); } catch { /* retry next start */ }
115
+ return;
116
+ }
117
+
118
+ logger.info("sessions backfill: ingesting sessions", {
119
+ sessionCount: eligible.length,
120
+ messageCount: eligible.reduce((n, s) => n + s.messages.length, 0),
121
+ });
122
+
123
+ for (const session of eligible) {
124
+ const metadata: SessionMetadata = {
125
+ ...(session.channel ? { channelId: session.channel } : {}),
126
+ ...(session.userId ? { userId: session.userId } : {}),
127
+ };
128
+ try {
129
+ await client.memoryIngest(session.sessionId, session.messages, metadata);
130
+ } catch (err) {
131
+ // Abort without marking — next startup replays, and the server-side
132
+ // lastProcessedIndex filter discards already-processed sessions free.
133
+ logger.warn("sessions backfill: ingest failed; will retry on next startup", {
134
+ sessionId: session.sessionId,
135
+ err: String(err),
136
+ });
137
+ return;
138
+ }
139
+ }
140
+
141
+ try {
142
+ await client.memoryBootstrapStatusMark("sessions");
143
+ logger.info("sessions backfill: complete", { sessionCount: eligible.length });
144
+ } catch (err) {
145
+ logger.warn("sessions backfill: mark failed; will retry on next startup", { err: String(err) });
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Tolerant parse of a single session file. Returns null for corrupt or
151
+ * shape-mismatched files (skipped, never fatal). Message `index` is the
152
+ * original array position in the file — stable because the store is
153
+ * append-only — so retries resume idempotently server-side.
154
+ */
155
+ async function parseSessionFile(
156
+ filePath: string,
157
+ captureMaxChars: number,
158
+ cutoffMs: number,
159
+ ): Promise<ParsedSession | null> {
160
+ let raw: unknown;
161
+ try {
162
+ raw = JSON.parse(await readFile(filePath, "utf8"));
163
+ } catch {
164
+ return null;
165
+ }
166
+ if (typeof raw !== "object" || raw === null) return null;
167
+
168
+ const data = raw as Record<string, unknown>;
169
+ if (typeof data.sessionId !== "string" || data.sessionId.length === 0) return null;
170
+ if (data.sessionId.length > MAX_SESSION_KEY_CHARS) return null;
171
+ if (!Array.isArray(data.messages)) return null;
172
+
173
+ const maxContentChars = Math.min(captureMaxChars, MAX_CONTENT_CHARS);
174
+ let lastMessageMs = 0;
175
+ const filtered: MemoryMessage[] = [];
176
+ for (const [index, entry] of data.messages.entries()) {
177
+ if (index > MAX_MESSAGE_INDEX) break;
178
+ if (typeof entry !== "object" || entry === null) continue;
179
+ const msg = entry as Record<string, unknown>;
180
+ if (msg.role !== "user" && msg.role !== "assistant") continue;
181
+ if (typeof msg.content !== "string" || msg.content.trim().length === 0) continue;
182
+ if (typeof msg.timestamp !== "number") continue;
183
+
184
+ lastMessageMs = Math.max(lastMessageMs, msg.timestamp);
185
+ if (msg.timestamp >= cutoffMs) continue;
186
+
187
+ filtered.push({
188
+ role: msg.role,
189
+ content: msg.content.length > maxContentChars ? msg.content.slice(0, maxContentChars) : msg.content,
190
+ index,
191
+ timestamp: new Date(msg.timestamp).toISOString(),
192
+ });
193
+ }
194
+
195
+ return {
196
+ sessionId: data.sessionId,
197
+ channel: typeof data.channel === "string" ? data.channel : undefined,
198
+ userId: typeof data.userId === "string" ? data.userId : undefined,
199
+ messages: recentWindow(filtered),
200
+ lastMessageMs,
201
+ };
202
+ }
203
+
204
+ /**
205
+ * The most recent contiguous run of messages fitting both ingest caps
206
+ * (message count and serialized bytes). Walks backwards from the newest
207
+ * message and stops at the first one that would overflow the byte budget.
208
+ */
209
+ function recentWindow(messages: MemoryMessage[]): MemoryMessage[] {
210
+ const window: MemoryMessage[] = [];
211
+ let bytes = 0;
212
+ for (let i = messages.length - 1; i >= 0; i--) {
213
+ if (window.length >= MAX_MESSAGES_PER_SESSION) break;
214
+ const msgBytes = Buffer.byteLength(JSON.stringify(messages[i])) + 1;
215
+ if (bytes + msgBytes > MAX_BATCH_BYTES) break;
216
+ window.unshift(messages[i]);
217
+ bytes += msgBytes;
218
+ }
219
+ return window;
220
+ }
package/src/types.ts CHANGED
@@ -3,6 +3,8 @@ export interface MemoryCloudConfig {
3
3
  autoRecall: boolean;
4
4
  captureMaxChars: number;
5
5
  idleFlushSeconds: number;
6
+ backfillSessions: boolean;
7
+ backfillMaxSessions: number;
6
8
  }
7
9
 
8
10
  export interface MemoryMessage {
package/tsconfig.json CHANGED
@@ -16,5 +16,5 @@
16
16
  "sourceMap": true
17
17
  },
18
18
  "include": ["src/**/*"],
19
- "exclude": ["node_modules", "dist"]
19
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
20
20
  }