@openviking/openclaw-plugin 2026.9.11 → 2026.9.13

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/README.md CHANGED
@@ -227,6 +227,14 @@ After that, the plugin checks `pending_tokens`. Once it reaches `commitTokenThre
227
227
 
228
228
  Memory extraction on this automatic path is commit-dependent. Short but important facts can stay only in the live session until a threshold commit, `/compact`, or an explicit store happens.
229
229
 
230
+ Auto-commit keeps the most recent 10 messages by default (`commitKeepRecentCount`). This count-based window can start mid-turn. With a server that supports turn-aware retention, set `"commitRetentionMode": "turn_budget"` in the plugin config to opt in:
231
+
232
+ - `commitKeepRecentCount` is ignored. The server defaults apply: up to 3 recent user turns, a 12,000-token retention budget, and at least the final assistant/tool step.
233
+ - For an oversized newest turn, the server retains its user question and recent steps and checkpoints the archived prefix. The mandatory tail can exceed the retention budget.
234
+ - `pending_tokens` counts only messages that will leave the live window, not a user question shared with the archive.
235
+
236
+ Manual commit and `/compact` still archive everything. Leave the option unset (or use `"message_count"`) to preserve existing behavior.
237
+
230
238
  ### Explicit long-term memory writes
231
239
 
232
240
  When the user explicitly asks the agent to remember, save, or store an important long-term fact, preference, project, or decision, prefer `memory_store` over waiting for normal auto-capture. `memory_store` writes the text to an OpenViking session and calls `commit(wait=true)`, so it is the reliable integration-side path for facts that should be available as long-term memory as soon as possible.
package/client.ts CHANGED
@@ -848,6 +848,8 @@ export class OpenVikingClient {
848
848
  keepRecentCount?: number;
849
849
  /** Start empty context in the same session after archiving. */
850
850
  resetContext?: boolean;
851
+ /** Opt in to the server's turn-aware defaults instead of message-count retention. */
852
+ retentionMode?: "turn_budget";
851
853
  agentId?: string;
852
854
  },
853
855
  ): Promise<CommitSessionResult> {
@@ -862,11 +864,14 @@ export class OpenVikingClient {
862
864
  sessionId,
863
865
  wait: options?.wait ?? false,
864
866
  keepRecentCount,
867
+ retentionMode: options?.retentionMode,
865
868
  },
866
869
  options?.agentId,
867
870
  );
868
871
  const body: Record<string, unknown> = {};
869
- if (keepRecentCount > 0) {
872
+ if (options?.retentionMode === "turn_budget") {
873
+ body.retention_mode = "turn_budget";
874
+ } else if (keepRecentCount > 0) {
870
875
  body.keep_recent_count = keepRecentCount;
871
876
  }
872
877
  if (options?.resetContext) {
package/commands/setup.ts CHANGED
@@ -82,6 +82,7 @@ const CONFIG_KEYS_TO_PRESERVE = [
82
82
  "recallPreferAbstract",
83
83
  "recallTokenBudget",
84
84
  "commitTokenThresholdRatio",
85
+ "commitRetentionMode",
85
86
  "commitKeepRecentCount",
86
87
  "bypassSessionPatterns",
87
88
  "emitStandardDiagnostics",
package/config.ts CHANGED
@@ -68,11 +68,13 @@ export type MemoryOpenVikingConfig = {
68
68
  * compatibility). Set to 0 to commit every turn.
69
69
  */
70
70
  commitTokenThresholdRatio?: number;
71
+ /** Auto-commit retention: legacy message count (default) or the server's turn-budget policy. */
72
+ commitRetentionMode?: "message_count" | "turn_budget";
71
73
  /**
72
74
  * WM v2: number of most-recent messages to keep live after an afterTurn
73
75
  * commit so the next turn still has immediate context. Forwarded to the
74
- * server as `keep_recent_count`. Default 10. The compact path ignores this
75
- * value and always passes 0.
76
+ * server as `keep_recent_count`. Default 10. Ignored in turn_budget mode.
77
+ * The compact path ignores this value and always passes 0.
76
78
  */
77
79
  commitKeepRecentCount?: number;
78
80
  bypassSessionPatterns?: string[];
@@ -538,6 +540,7 @@ export const memoryOpenVikingConfigSchema = {
538
540
  "recallTokenBudget",
539
541
  "commitTokenThreshold",
540
542
  "commitTokenThresholdRatio",
543
+ "commitRetentionMode",
541
544
  "commitKeepRecentCount",
542
545
  "bypassSessionPatterns",
543
546
  "ingestReplyAssist",
@@ -588,6 +591,14 @@ export const memoryOpenVikingConfigSchema = {
588
591
  ? (cfg.apiKey as string | OpenVikingSecretRef)
589
592
  : getEnv("OPENVIKING_API_KEY") || undefined;
590
593
  const captureMode = cfg.captureMode;
594
+ const commitRetentionMode = cfg.commitRetentionMode;
595
+ if (
596
+ commitRetentionMode !== undefined &&
597
+ commitRetentionMode !== "message_count" &&
598
+ commitRetentionMode !== "turn_budget"
599
+ ) {
600
+ throw new Error('openviking commitRetentionMode must be "message_count" or "turn_budget"');
601
+ }
591
602
  if (
592
603
  typeof captureMode !== "undefined" &&
593
604
  captureMode !== "semantic" &&
@@ -666,6 +677,7 @@ export const memoryOpenVikingConfigSchema = {
666
677
  0,
667
678
  Math.min(1, toNumber(cfg.commitTokenThresholdRatio, DEFAULT_COMMIT_TOKEN_THRESHOLD_RATIO)),
668
679
  ),
680
+ commitRetentionMode: commitRetentionMode ?? "message_count",
669
681
  commitKeepRecentCount: Math.max(
670
682
  0,
671
683
  Math.min(
@@ -916,13 +928,18 @@ export const memoryOpenVikingConfigSchema = {
916
928
  advanced: true,
917
929
  help: "Auto-commit triggers once estimated pending tokens reach this fraction (0-1) of the model context window (e.g. 0.5 = 50%). Set to 0 to commit every turn.",
918
930
  },
931
+ commitRetentionMode: {
932
+ label: "Commit Retention Mode",
933
+ advanced: true,
934
+ help: "Auto-commit only: message_count (default) keeps recent messages; turn_budget uses the server's turn-aware defaults. Manual commit and compact still archive everything.",
935
+ },
919
936
  commitKeepRecentCount: {
920
937
  label: "Commit Keep Recent Count",
921
938
  placeholder: String(DEFAULT_COMMIT_KEEP_RECENT_COUNT),
922
939
  advanced: true,
923
940
  help:
924
941
  "Number of most-recent messages to keep live after an afterTurn commit. " +
925
- "Forwarded as keep_recent_count to the server. Compact path always uses 0.",
942
+ "Forwarded as keep_recent_count to the server in message_count mode; ignored in turn_budget mode. Compact path always uses 0.",
926
943
  },
927
944
  emitStandardDiagnostics: {
928
945
  label: "Standard diagnostics (diag JSON lines)",
package/dist/client.js CHANGED
@@ -410,9 +410,13 @@ export class OpenVikingClient {
410
410
  sessionId,
411
411
  wait: options?.wait ?? false,
412
412
  keepRecentCount,
413
+ retentionMode: options?.retentionMode,
413
414
  }, options?.agentId);
414
415
  const body = {};
415
- if (keepRecentCount > 0) {
416
+ if (options?.retentionMode === "turn_budget") {
417
+ body.retention_mode = "turn_budget";
418
+ }
419
+ else if (keepRecentCount > 0) {
416
420
  body.keep_recent_count = keepRecentCount;
417
421
  }
418
422
  if (options?.resetContext) {
@@ -72,6 +72,7 @@ const CONFIG_KEYS_TO_PRESERVE = [
72
72
  "recallPreferAbstract",
73
73
  "recallTokenBudget",
74
74
  "commitTokenThresholdRatio",
75
+ "commitRetentionMode",
75
76
  "commitKeepRecentCount",
76
77
  "bypassSessionPatterns",
77
78
  "emitStandardDiagnostics",
package/dist/config.js CHANGED
@@ -354,6 +354,7 @@ export const memoryOpenVikingConfigSchema = {
354
354
  "recallTokenBudget",
355
355
  "commitTokenThreshold",
356
356
  "commitTokenThresholdRatio",
357
+ "commitRetentionMode",
357
358
  "commitKeepRecentCount",
358
359
  "bypassSessionPatterns",
359
360
  "ingestReplyAssist",
@@ -396,6 +397,12 @@ export const memoryOpenVikingConfigSchema = {
396
397
  ? cfg.apiKey
397
398
  : getEnv("OPENVIKING_API_KEY") || undefined;
398
399
  const captureMode = cfg.captureMode;
400
+ const commitRetentionMode = cfg.commitRetentionMode;
401
+ if (commitRetentionMode !== undefined &&
402
+ commitRetentionMode !== "message_count" &&
403
+ commitRetentionMode !== "turn_budget") {
404
+ throw new Error('openviking commitRetentionMode must be "message_count" or "turn_budget"');
405
+ }
399
406
  if (typeof captureMode !== "undefined" &&
400
407
  captureMode !== "semantic" &&
401
408
  captureMode !== "keyword") {
@@ -437,6 +444,7 @@ export const memoryOpenVikingConfigSchema = {
437
444
  recallMaxInjectedChars,
438
445
  recallTokenBudget: recallMaxInjectedChars,
439
446
  commitTokenThresholdRatio: Math.max(0, Math.min(1, toNumber(cfg.commitTokenThresholdRatio, DEFAULT_COMMIT_TOKEN_THRESHOLD_RATIO))),
447
+ commitRetentionMode: commitRetentionMode ?? "message_count",
440
448
  commitKeepRecentCount: Math.max(0, Math.min(1_000, Math.floor(toNumber(cfg.commitKeepRecentCount, DEFAULT_COMMIT_KEEP_RECENT_COUNT)))),
441
449
  bypassSessionPatterns: toStringArray(cfg.bypassSessionPatterns, toStringArray(cfg.ingestReplyAssistIgnoreSessionPatterns, DEFAULT_BYPASS_SESSION_PATTERNS)),
442
450
  emitStandardDiagnostics: typeof cfg.emitStandardDiagnostics === "boolean"
@@ -612,12 +620,17 @@ export const memoryOpenVikingConfigSchema = {
612
620
  advanced: true,
613
621
  help: "Auto-commit triggers once estimated pending tokens reach this fraction (0-1) of the model context window (e.g. 0.5 = 50%). Set to 0 to commit every turn.",
614
622
  },
623
+ commitRetentionMode: {
624
+ label: "Commit Retention Mode",
625
+ advanced: true,
626
+ help: "Auto-commit only: message_count (default) keeps recent messages; turn_budget uses the server's turn-aware defaults. Manual commit and compact still archive everything.",
627
+ },
615
628
  commitKeepRecentCount: {
616
629
  label: "Commit Keep Recent Count",
617
630
  placeholder: String(DEFAULT_COMMIT_KEEP_RECENT_COUNT),
618
631
  advanced: true,
619
632
  help: "Number of most-recent messages to keep live after an afterTurn commit. " +
620
- "Forwarded as keep_recent_count to the server. Compact path always uses 0.",
633
+ "Forwarded as keep_recent_count to the server in message_count mode; ignored in turn_budget mode. Compact path always uses 0.",
621
634
  },
622
635
  emitStandardDiagnostics: {
623
636
  label: "Standard diagnostics (diag JSON lines)",
@@ -657,7 +657,9 @@ export async function afterTurnOpenVikingSession({ throwOnError = false, session
657
657
  }
658
658
  const commitResult = await client.commitSession(ovSessionId, {
659
659
  wait: false,
660
- keepRecentCount: cfg.commitKeepRecentCount,
660
+ ...(cfg.commitRetentionMode === "turn_budget"
661
+ ? { retentionMode: "turn_budget" }
662
+ : { keepRecentCount: cfg.commitKeepRecentCount }),
661
663
  });
662
664
  logger.info(`openviking: committed session=${ovSessionId}, ` +
663
665
  `status=${commitResult.status}, archived=${commitResult.archived ?? false}, ` +
@@ -204,11 +204,16 @@
204
204
  "advanced": true,
205
205
  "help": "Auto-commit triggers once estimated pending tokens reach this fraction (0-1) of the model context window (e.g. 0.5 = 50%). Set to 0 to commit every turn."
206
206
  },
207
+ "commitRetentionMode": {
208
+ "label": "Commit Retention Mode",
209
+ "advanced": true,
210
+ "help": "Auto-commit only: message_count (default) keeps recent messages; turn_budget uses the server's turn-aware defaults. Manual commit and compact still archive everything."
211
+ },
207
212
  "commitKeepRecentCount": {
208
213
  "label": "Commit Keep Recent Count",
209
214
  "placeholder": "10",
210
215
  "advanced": true,
211
- "help": "WM v2: number of most-recent messages kept live after an afterTurn commit. Compact path always uses 0."
216
+ "help": "Number of most-recent messages kept live after an afterTurn commit in message_count mode; ignored in turn_budget mode. Compact path always uses 0."
212
217
  },
213
218
  "emitStandardDiagnostics": {
214
219
  "label": "Standard diagnostics (diag JSON lines)",
@@ -405,6 +410,10 @@
405
410
  "minimum": 0,
406
411
  "maximum": 1
407
412
  },
413
+ "commitRetentionMode": {
414
+ "type": "string",
415
+ "enum": ["message_count", "turn_budget"]
416
+ },
408
417
  "commitKeepRecentCount": {
409
418
  "type": "number",
410
419
  "minimum": 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openviking/openclaw-plugin",
3
- "version": "2026.9.11",
3
+ "version": "2026.9.13",
4
4
  "displayName": "OpenViking",
5
5
  "description": "OpenClaw context-engine plugin — OpenViking AI memory, long-term memory, knowledge base, semantic search, RAG, context engine. 长期记忆 · 知识库 · 语义检索 · 上下文引擎",
6
6
  "type": "module",
@@ -140,6 +140,7 @@ export type AfterTurnOpenVikingSessionParams = {
140
140
  autoCapture: boolean;
141
141
  commitTokenThresholdRatio: number;
142
142
  commitKeepRecentCount: number;
143
+ commitRetentionMode?: "message_count" | "turn_budget";
143
144
  logFindRequests: boolean;
144
145
  peer_role?: OpenVikingPeerRole;
145
146
  };
@@ -987,7 +988,9 @@ export async function afterTurnOpenVikingSession({
987
988
 
988
989
  const commitResult = await client.commitSession(ovSessionId, {
989
990
  wait: false,
990
- keepRecentCount: cfg.commitKeepRecentCount,
991
+ ...(cfg.commitRetentionMode === "turn_budget"
992
+ ? { retentionMode: "turn_budget" as const }
993
+ : { keepRecentCount: cfg.commitKeepRecentCount }),
991
994
  });
992
995
  logger.info(
993
996
  `openviking: committed session=${ovSessionId}, ` +