@vectorize-io/hindsight-openclaw 0.4.14 → 0.4.15

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/dist/index.js CHANGED
@@ -2,6 +2,12 @@ import { HindsightEmbedManager } from './embed-manager.js';
2
2
  import { HindsightClient } from './client.js';
3
3
  import { dirname } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
+ // Debug logging: silent by default, enable with debug: true in plugin config
6
+ let debugEnabled = false;
7
+ const debug = (...args) => {
8
+ if (debugEnabled)
9
+ console.log(...args);
10
+ };
5
11
  // Module-level state
6
12
  let embedManager = null;
7
13
  let client = null;
@@ -13,6 +19,7 @@ let currentPluginConfig = null;
13
19
  // Track which banks have had their mission set (to avoid re-setting on every request)
14
20
  const banksWithMissionSet = new Set();
15
21
  const inflightRecalls = new Map();
22
+ const turnCountBySession = new Map();
16
23
  const RECALL_TIMEOUT_MS = 10_000;
17
24
  // Cooldown + guard to prevent concurrent reinit attempts
18
25
  let lastReinitAttempt = 0;
@@ -40,7 +47,7 @@ async function lazyReinit() {
40
47
  isReinitInProgress = false;
41
48
  return; // Only external API mode supports lazy reinit
42
49
  }
43
- console.log('[Hindsight] Attempting lazy re-initialization...');
50
+ debug('[Hindsight] Attempting lazy re-initialization...');
44
51
  try {
45
52
  await checkExternalApiHealth(externalApi.apiUrl, externalApi.apiToken);
46
53
  // Health check passed — set up env vars and create client
@@ -59,7 +66,7 @@ async function lazyReinit() {
59
66
  isInitialized = true;
60
67
  // Replace the rejected initPromise with a resolved one
61
68
  initPromise = Promise.resolve();
62
- console.log('[Hindsight] ✓ Lazy re-initialization succeeded');
69
+ debug('[Hindsight] ✓ Lazy re-initialization succeeded');
63
70
  }
64
71
  catch (error) {
65
72
  console.warn(`[Hindsight] Lazy re-initialization failed (will retry in ${REINIT_COOLDOWN_MS / 1000}s):`, error instanceof Error ? error.message : error);
@@ -107,7 +114,7 @@ if (typeof global !== 'undefined') {
107
114
  try {
108
115
  await client.setBankMission(config.bankMission);
109
116
  banksWithMissionSet.add(bankId);
110
- console.log(`[Hindsight] Set mission for new bank: ${bankId}`);
117
+ debug(`[Hindsight] Set mission for new bank: ${bankId}`);
111
118
  }
112
119
  catch (error) {
113
120
  // Log but don't fail - bank mission is not critical
@@ -319,7 +326,7 @@ async function checkExternalApiHealth(apiUrl, apiToken) {
319
326
  const retryDelay = 2000;
320
327
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
321
328
  try {
322
- console.log(`[Hindsight] Checking external API health at ${healthUrl}... (attempt ${attempt}/${maxRetries})`);
329
+ debug(`[Hindsight] Checking external API health at ${healthUrl}... (attempt ${attempt}/${maxRetries})`);
323
330
  const headers = {};
324
331
  if (apiToken) {
325
332
  headers['Authorization'] = `Bearer ${apiToken}`;
@@ -329,12 +336,12 @@ async function checkExternalApiHealth(apiUrl, apiToken) {
329
336
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
330
337
  }
331
338
  const data = await response.json();
332
- console.log(`[Hindsight] External API health: ${JSON.stringify(data)}`);
339
+ debug(`[Hindsight] External API health: ${JSON.stringify(data)}`);
333
340
  return;
334
341
  }
335
342
  catch (error) {
336
343
  if (attempt < maxRetries) {
337
- console.log(`[Hindsight] Health check attempt ${attempt} failed, retrying in ${retryDelay}ms...`);
344
+ debug(`[Hindsight] Health check attempt ${attempt} failed, retrying in ${retryDelay}ms...`);
338
345
  await new Promise(resolve => setTimeout(resolve, retryDelay));
339
346
  }
340
347
  else {
@@ -363,37 +370,39 @@ function getPluginConfig(api) {
363
370
  bankIdPrefix: config.bankIdPrefix,
364
371
  excludeProviders: Array.isArray(config.excludeProviders) ? config.excludeProviders : [],
365
372
  autoRecall: config.autoRecall !== false, // Default: true (on) — backward compatible
373
+ retainEveryNTurns: config.retainEveryNTurns,
374
+ debug: config.debug ?? false,
366
375
  };
367
376
  }
368
377
  export default function (api) {
369
378
  try {
370
- console.log('[Hindsight] Plugin loading...');
371
- // Get plugin config first (needed for LLM detection)
372
- console.log('[Hindsight] Getting plugin config...');
379
+ debug('[Hindsight] Plugin loading...');
380
+ // Get plugin config first (needed for LLM detection and debug flag)
373
381
  const pluginConfig = getPluginConfig(api);
382
+ debugEnabled = pluginConfig.debug ?? false;
374
383
  // Store config globally for bank ID derivation in hooks
375
384
  currentPluginConfig = pluginConfig;
376
385
  // Detect LLM configuration (env vars > plugin config > auto-detect)
377
- console.log('[Hindsight] Detecting LLM config...');
386
+ debug('[Hindsight] Detecting LLM config...');
378
387
  const llmConfig = detectLLMConfig(pluginConfig);
379
388
  const baseUrlInfo = llmConfig.baseUrl ? `, base URL: ${llmConfig.baseUrl}` : '';
380
389
  const modelInfo = llmConfig.model || 'default';
381
390
  if (llmConfig.provider === 'ollama') {
382
- console.log(`[Hindsight] ✓ Using provider: ${llmConfig.provider}, model: ${modelInfo} (${llmConfig.source})`);
391
+ debug(`[Hindsight] ✓ Using provider: ${llmConfig.provider}, model: ${modelInfo} (${llmConfig.source})`);
383
392
  }
384
393
  else {
385
- console.log(`[Hindsight] ✓ Using provider: ${llmConfig.provider}, model: ${modelInfo} (${llmConfig.source}${baseUrlInfo})`);
394
+ debug(`[Hindsight] ✓ Using provider: ${llmConfig.provider}, model: ${modelInfo} (${llmConfig.source}${baseUrlInfo})`);
386
395
  }
387
396
  if (pluginConfig.bankMission) {
388
- console.log(`[Hindsight] Custom bank mission configured: "${pluginConfig.bankMission.substring(0, 50)}..."`);
397
+ debug(`[Hindsight] Custom bank mission configured: "${pluginConfig.bankMission.substring(0, 50)}..."`);
389
398
  }
390
399
  // Log dynamic bank ID mode
391
400
  if (pluginConfig.dynamicBankId) {
392
401
  const prefixInfo = pluginConfig.bankIdPrefix ? ` (prefix: ${pluginConfig.bankIdPrefix})` : '';
393
- console.log(`[Hindsight] ✓ Dynamic bank IDs enabled${prefixInfo} - each channel gets isolated memory`);
402
+ debug(`[Hindsight] ✓ Dynamic bank IDs enabled${prefixInfo} - each channel gets isolated memory`);
394
403
  }
395
404
  else {
396
- console.log(`[Hindsight] Dynamic bank IDs disabled - using static bank: ${DEFAULT_BANK_NAME}`);
405
+ debug(`[Hindsight] Dynamic bank IDs disabled - using static bank: ${DEFAULT_BANK_NAME}`);
397
406
  }
398
407
  // Detect external API mode
399
408
  const externalApi = detectExternalApi(pluginConfig);
@@ -402,64 +411,64 @@ export default function (api) {
402
411
  if (externalApi.apiUrl) {
403
412
  // External API mode - skip local daemon
404
413
  usingExternalApi = true;
405
- console.log(`[Hindsight] ✓ Using external API: ${externalApi.apiUrl}`);
414
+ debug(`[Hindsight] ✓ Using external API: ${externalApi.apiUrl}`);
406
415
  // Set env vars so CLI commands (uvx hindsight-embed) use external API
407
416
  process.env.HINDSIGHT_EMBED_API_URL = externalApi.apiUrl;
408
417
  if (externalApi.apiToken) {
409
418
  process.env.HINDSIGHT_EMBED_API_TOKEN = externalApi.apiToken;
410
- console.log('[Hindsight] API token configured');
419
+ debug('[Hindsight] API token configured');
411
420
  }
412
421
  }
413
422
  else {
414
- console.log(`[Hindsight] Daemon idle timeout: ${pluginConfig.daemonIdleTimeout}s (0 = never timeout)`);
415
- console.log(`[Hindsight] API Port: ${apiPort}`);
423
+ debug(`[Hindsight] Daemon idle timeout: ${pluginConfig.daemonIdleTimeout}s (0 = never timeout)`);
424
+ debug(`[Hindsight] API Port: ${apiPort}`);
416
425
  }
417
426
  // Initialize in background (non-blocking)
418
- console.log('[Hindsight] Starting initialization in background...');
427
+ debug('[Hindsight] Starting initialization in background...');
419
428
  initPromise = (async () => {
420
429
  try {
421
430
  if (usingExternalApi && externalApi.apiUrl) {
422
431
  // External API mode - check health, skip daemon startup
423
- console.log('[Hindsight] External API mode - skipping local daemon...');
432
+ debug('[Hindsight] External API mode - skipping local daemon...');
424
433
  await checkExternalApiHealth(externalApi.apiUrl, externalApi.apiToken);
425
434
  // Initialize client with direct HTTP mode
426
- console.log('[Hindsight] Creating HindsightClient (HTTP mode)...');
435
+ debug('[Hindsight] Creating HindsightClient (HTTP mode)...');
427
436
  client = new HindsightClient(buildClientOptions(llmConfig, pluginConfig, externalApi));
428
437
  // Set default bank (will be overridden per-request when dynamic bank IDs are enabled)
429
438
  const defaultBankId = deriveBankId(undefined, pluginConfig);
430
- console.log(`[Hindsight] Default bank: ${defaultBankId}`);
439
+ debug(`[Hindsight] Default bank: ${defaultBankId}`);
431
440
  client.setBankId(defaultBankId);
432
441
  // Note: Bank mission will be set per-bank when dynamic bank IDs are enabled
433
442
  // For now, set it on the default bank
434
443
  if (pluginConfig.bankMission && !pluginConfig.dynamicBankId) {
435
- console.log(`[Hindsight] Setting bank mission...`);
444
+ debug(`[Hindsight] Setting bank mission...`);
436
445
  await client.setBankMission(pluginConfig.bankMission);
437
446
  }
438
447
  isInitialized = true;
439
- console.log('[Hindsight] ✓ Ready (external API mode)');
448
+ debug('[Hindsight] ✓ Ready (external API mode)');
440
449
  }
441
450
  else {
442
451
  // Local daemon mode - start hindsight-embed daemon
443
- console.log('[Hindsight] Creating HindsightEmbedManager...');
452
+ debug('[Hindsight] Creating HindsightEmbedManager...');
444
453
  embedManager = new HindsightEmbedManager(apiPort, llmConfig.provider, llmConfig.apiKey, llmConfig.model, llmConfig.baseUrl, pluginConfig.daemonIdleTimeout, pluginConfig.embedVersion, pluginConfig.embedPackagePath);
445
454
  // Start the embedded server
446
- console.log('[Hindsight] Starting embedded server...');
455
+ debug('[Hindsight] Starting embedded server...');
447
456
  await embedManager.start();
448
457
  // Initialize client (local daemon mode — no apiUrl)
449
- console.log('[Hindsight] Creating HindsightClient (subprocess mode)...');
458
+ debug('[Hindsight] Creating HindsightClient (subprocess mode)...');
450
459
  client = new HindsightClient(buildClientOptions(llmConfig, pluginConfig, { apiUrl: null, apiToken: null }));
451
460
  // Set default bank (will be overridden per-request when dynamic bank IDs are enabled)
452
461
  const defaultBankId = deriveBankId(undefined, pluginConfig);
453
- console.log(`[Hindsight] Default bank: ${defaultBankId}`);
462
+ debug(`[Hindsight] Default bank: ${defaultBankId}`);
454
463
  client.setBankId(defaultBankId);
455
464
  // Note: Bank mission will be set per-bank when dynamic bank IDs are enabled
456
465
  // For now, set it on the default bank
457
466
  if (pluginConfig.bankMission && !pluginConfig.dynamicBankId) {
458
- console.log(`[Hindsight] Setting bank mission...`);
467
+ debug(`[Hindsight] Setting bank mission...`);
459
468
  await client.setBankMission(pluginConfig.bankMission);
460
469
  }
461
470
  isInitialized = true;
462
- console.log('[Hindsight] ✓ Ready');
471
+ debug('[Hindsight] ✓ Ready');
463
472
  }
464
473
  }
465
474
  catch (error) {
@@ -470,11 +479,11 @@ export default function (api) {
470
479
  // Suppress unhandled rejection — service.start() will await and handle errors
471
480
  initPromise.catch(() => { });
472
481
  // Register background service for cleanup
473
- console.log('[Hindsight] Registering service...');
482
+ debug('[Hindsight] Registering service...');
474
483
  api.registerService({
475
484
  id: 'hindsight-memory',
476
485
  async start() {
477
- console.log('[Hindsight] Service start called...');
486
+ debug('[Hindsight] Service start called...');
478
487
  // Wait for background init if still pending
479
488
  if (initPromise) {
480
489
  try {
@@ -491,7 +500,7 @@ export default function (api) {
491
500
  if (externalApi.apiUrl && isInitialized) {
492
501
  try {
493
502
  await checkExternalApiHealth(externalApi.apiUrl, externalApi.apiToken);
494
- console.log('[Hindsight] External API is healthy');
503
+ debug('[Hindsight] External API is healthy');
495
504
  return;
496
505
  }
497
506
  catch (error) {
@@ -507,10 +516,10 @@ export default function (api) {
507
516
  if (embedManager && isInitialized) {
508
517
  const healthy = await embedManager.checkHealth();
509
518
  if (healthy) {
510
- console.log('[Hindsight] Daemon is healthy');
519
+ debug('[Hindsight] Daemon is healthy');
511
520
  return;
512
521
  }
513
- console.log('[Hindsight] Daemon is not responding - reinitializing...');
522
+ debug('[Hindsight] Daemon is not responding - reinitializing...');
514
523
  // Reset state for reinitialization
515
524
  embedManager = null;
516
525
  client = null;
@@ -519,7 +528,7 @@ export default function (api) {
519
528
  }
520
529
  // Reinitialize if needed (fresh start or recovery)
521
530
  if (!isInitialized) {
522
- console.log('[Hindsight] Reinitializing...');
531
+ debug('[Hindsight] Reinitializing...');
523
532
  const reinitPluginConfig = getPluginConfig(api);
524
533
  currentPluginConfig = reinitPluginConfig;
525
534
  const llmConfig = detectLLMConfig(reinitPluginConfig);
@@ -540,7 +549,7 @@ export default function (api) {
540
549
  await client.setBankMission(reinitPluginConfig.bankMission);
541
550
  }
542
551
  isInitialized = true;
543
- console.log('[Hindsight] Reinitialization complete (external API mode)');
552
+ debug('[Hindsight] Reinitialization complete (external API mode)');
544
553
  }
545
554
  else {
546
555
  // Local daemon mode
@@ -553,13 +562,13 @@ export default function (api) {
553
562
  await client.setBankMission(reinitPluginConfig.bankMission);
554
563
  }
555
564
  isInitialized = true;
556
- console.log('[Hindsight] Reinitialization complete');
565
+ debug('[Hindsight] Reinitialization complete');
557
566
  }
558
567
  }
559
568
  },
560
569
  async stop() {
561
570
  try {
562
- console.log('[Hindsight] Service stopping...');
571
+ debug('[Hindsight] Service stopping...');
563
572
  // Only stop daemon if in local mode
564
573
  if (!usingExternalApi && embedManager) {
565
574
  await embedManager.stop();
@@ -567,7 +576,7 @@ export default function (api) {
567
576
  }
568
577
  client = null;
569
578
  isInitialized = false;
570
- console.log('[Hindsight] Service stopped');
579
+ debug('[Hindsight] Service stopped');
571
580
  }
572
581
  catch (error) {
573
582
  console.error('[Hindsight] Service stop error:', error);
@@ -575,9 +584,9 @@ export default function (api) {
575
584
  }
576
585
  },
577
586
  });
578
- console.log('[Hindsight] Plugin loaded successfully');
587
+ debug('[Hindsight] Plugin loaded successfully');
579
588
  // Register agent hooks for auto-recall and auto-retention
580
- console.log('[Hindsight] Registering agent hooks...');
589
+ debug('[Hindsight] Registering agent hooks...');
581
590
  // Store session key and context for retention
582
591
  let currentSessionKey;
583
592
  let currentAgentContext;
@@ -592,17 +601,17 @@ export default function (api) {
592
601
  currentAgentContext = ctx;
593
602
  // Check if this provider is excluded
594
603
  if (ctx?.messageProvider && pluginConfig.excludeProviders?.includes(ctx.messageProvider)) {
595
- console.log(`[Hindsight] Skipping recall for excluded provider: ${ctx.messageProvider}`);
604
+ debug(`[Hindsight] Skipping recall for excluded provider: ${ctx.messageProvider}`);
596
605
  return;
597
606
  }
598
607
  // Skip auto-recall when disabled (agent has its own recall tool)
599
608
  if (!pluginConfig.autoRecall) {
600
- console.log('[Hindsight] Auto-recall disabled via config, skipping');
609
+ debug('[Hindsight] Auto-recall disabled via config, skipping');
601
610
  return;
602
611
  }
603
612
  // Derive bank ID from context
604
613
  const bankId = deriveBankId(ctx, pluginConfig);
605
- console.log(`[Hindsight] before_agent_start - bank: ${bankId}, channel: ${ctx?.messageProvider}/${ctx?.channelId}`);
614
+ debug(`[Hindsight] before_agent_start - bank: ${bankId}, channel: ${ctx?.messageProvider}/${ctx?.channelId}`);
606
615
  // Get the user's latest message for recall — only the raw user text, not the full prompt
607
616
  // rawMessage is clean user text; prompt includes envelope, system events, media notes, etc.
608
617
  const extracted = extractRecallQuery(event.rawMessage, event.prompt);
@@ -618,23 +627,23 @@ export default function (api) {
618
627
  // Wait for client to be ready
619
628
  const clientGlobal = global.__hindsightClient;
620
629
  if (!clientGlobal) {
621
- console.log('[Hindsight] Client global not available, skipping auto-recall');
630
+ debug('[Hindsight] Client global not available, skipping auto-recall');
622
631
  return;
623
632
  }
624
633
  await clientGlobal.waitForReady();
625
634
  // Get client configured for this context's bank (async to handle mission setup)
626
635
  const client = await clientGlobal.getClientForContext(ctx);
627
636
  if (!client) {
628
- console.log('[Hindsight] Client not initialized, skipping auto-recall');
637
+ debug('[Hindsight] Client not initialized, skipping auto-recall');
629
638
  return;
630
639
  }
631
- console.log(`[Hindsight] Auto-recall for bank ${bankId}, prompt: ${prompt.substring(0, 50)}`);
640
+ debug(`[Hindsight] Auto-recall for bank ${bankId}, prompt: ${prompt.substring(0, 50)}`);
632
641
  // Recall with deduplication: reuse in-flight request for same bank
633
642
  const recallKey = bankId;
634
643
  const existing = inflightRecalls.get(recallKey);
635
644
  let recallPromise;
636
645
  if (existing) {
637
- console.log(`[Hindsight] Reusing in-flight recall for bank ${bankId}`);
646
+ debug(`[Hindsight] Reusing in-flight recall for bank ${bankId}`);
638
647
  recallPromise = existing;
639
648
  }
640
649
  else {
@@ -644,7 +653,7 @@ export default function (api) {
644
653
  }
645
654
  const response = await recallPromise;
646
655
  if (!response.results || response.results.length === 0) {
647
- console.log('[Hindsight] No memories found for auto-recall');
656
+ debug('[Hindsight] No memories found for auto-recall');
648
657
  return;
649
658
  }
650
659
  // Format memories as JSON with all fields from recall
@@ -655,7 +664,7 @@ ${memoriesJson}
655
664
 
656
665
  User message: ${prompt}
657
666
  </hindsight_memories>`;
658
- console.log(`[Hindsight] Auto-recall: Injecting ${response.results.length} memories from bank ${bankId}`);
667
+ debug(`[Hindsight] Auto-recall: Injecting ${response.results.length} memories from bank ${bankId}`);
659
668
  // Inject context before the user message
660
669
  return { prependContext: contextMessage };
661
670
  }
@@ -679,15 +688,15 @@ User message: ${prompt}
679
688
  const effectiveCtx = ctx || currentAgentContext;
680
689
  // Check if this provider is excluded
681
690
  if (effectiveCtx?.messageProvider && pluginConfig.excludeProviders?.includes(effectiveCtx.messageProvider)) {
682
- console.log(`[Hindsight] Skipping retain for excluded provider: ${effectiveCtx.messageProvider}`);
691
+ debug(`[Hindsight] Skipping retain for excluded provider: ${effectiveCtx.messageProvider}`);
683
692
  return;
684
693
  }
685
694
  // Derive bank ID from context
686
695
  const bankId = deriveBankId(effectiveCtx, pluginConfig);
687
- console.log(`[Hindsight Hook] agent_end triggered - bank: ${bankId}`);
696
+ debug(`[Hindsight Hook] agent_end triggered - bank: ${bankId}`);
688
697
  // Check event success and messages
689
698
  if (!event.success || !Array.isArray(event.messages) || event.messages.length === 0) {
690
- console.log('[Hindsight Hook] Skipping: success:', event.success, 'messages:', event.messages?.length);
699
+ debug('[Hindsight Hook] Skipping: success:', event.success, 'messages:', event.messages?.length);
691
700
  return;
692
701
  }
693
702
  // Wait for client to be ready
@@ -703,8 +712,25 @@ User message: ${prompt}
703
712
  console.warn('[Hindsight] Client not initialized, skipping retain');
704
713
  return;
705
714
  }
715
+ // --- Chunked retention: only retain every Nth turn ---
716
+ const retainEveryN = pluginConfig.retainEveryNTurns ?? 10;
717
+ let messagesToRetain = event.messages;
718
+ if (retainEveryN > 1) {
719
+ const sessionTrackingKey = `${bankId}:${effectiveCtx?.sessionKey || currentSessionKey || 'session'}`;
720
+ const turnCount = (turnCountBySession.get(sessionTrackingKey) || 0) + 1;
721
+ turnCountBySession.set(sessionTrackingKey, turnCount);
722
+ if (turnCount % retainEveryN !== 0) {
723
+ const nextRetain = Math.ceil(turnCount / retainEveryN) * retainEveryN;
724
+ debug(`[Hindsight Hook] Skipping retain (turn ${turnCount}, next at ${nextRetain})`);
725
+ return;
726
+ }
727
+ // Sliding window: N turns of new content + 2-turn overlap for context continuity
728
+ const windowSize = retainEveryN * 2 + 4;
729
+ messagesToRetain = event.messages.slice(-windowSize);
730
+ debug(`[Hindsight Hook] Chunked retain at turn ${turnCount} \u2014 last ${messagesToRetain.length} msgs`);
731
+ }
706
732
  // Format messages into a transcript
707
- const transcript = event.messages
733
+ const transcript = messagesToRetain
708
734
  .map((msg) => {
709
735
  const role = msg.role || 'unknown';
710
736
  let content = '';
@@ -724,7 +750,7 @@ User message: ${prompt}
724
750
  })
725
751
  .join('\n\n');
726
752
  if (!transcript.trim() || transcript.length < 10) {
727
- console.log('[Hindsight Hook] Transcript too short, skipping');
753
+ debug('[Hindsight Hook] Transcript too short, skipping');
728
754
  return;
729
755
  }
730
756
  // Use unique document ID per conversation (sessionKey + timestamp)
@@ -736,19 +762,19 @@ User message: ${prompt}
736
762
  document_id: documentId,
737
763
  metadata: {
738
764
  retained_at: new Date().toISOString(),
739
- message_count: String(event.messages.length),
765
+ message_count: String(messagesToRetain.length),
740
766
  channel_type: effectiveCtx?.messageProvider,
741
767
  channel_id: effectiveCtx?.channelId,
742
768
  sender_id: effectiveCtx?.senderId,
743
769
  },
744
770
  });
745
- console.log(`[Hindsight] Retained ${event.messages.length} messages to bank ${bankId} for session ${documentId}`);
771
+ debug(`[Hindsight] Retained ${messagesToRetain.length} messages to bank ${bankId} for session ${documentId}`);
746
772
  }
747
773
  catch (error) {
748
774
  console.error('[Hindsight] Error retaining messages:', error);
749
775
  }
750
776
  });
751
- console.log('[Hindsight] Hooks registered');
777
+ debug('[Hindsight] Hooks registered');
752
778
  }
753
779
  catch (error) {
754
780
  console.error('[Hindsight] Plugin loading error:', error);
package/dist/types.d.ts CHANGED
@@ -40,6 +40,8 @@ export interface PluginConfig {
40
40
  bankIdPrefix?: string;
41
41
  excludeProviders?: string[];
42
42
  autoRecall?: boolean;
43
+ retainEveryNTurns?: number;
44
+ debug?: boolean;
43
45
  }
44
46
  export interface ServiceConfig {
45
47
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectorize-io/hindsight-openclaw",
3
- "version": "0.4.14",
3
+ "version": "0.4.15",
4
4
  "description": "Hindsight memory plugin for OpenClaw - biomimetic long-term memory with fact extraction",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",