@vectorize-io/hindsight-openclaw 0.4.9 → 0.4.11

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
@@ -217,6 +217,7 @@ function getPluginConfig(api) {
217
217
  // Dynamic bank ID options (default: enabled)
218
218
  dynamicBankId: config.dynamicBankId !== false,
219
219
  bankIdPrefix: config.bankIdPrefix,
220
+ excludeProviders: Array.isArray(config.excludeProviders) ? config.excludeProviders : [],
220
221
  };
221
222
  }
222
223
  export default function (api) {
@@ -443,19 +444,37 @@ export default function (api) {
443
444
  currentSessionKey = ctx.sessionKey;
444
445
  }
445
446
  currentAgentContext = ctx;
447
+ // Check if this provider is excluded
448
+ if (ctx?.messageProvider && pluginConfig.excludeProviders?.includes(ctx.messageProvider)) {
449
+ console.log(`[Hindsight] Skipping recall for excluded provider: ${ctx.messageProvider}`);
450
+ return;
451
+ }
446
452
  // Derive bank ID from context
447
453
  const bankId = deriveBankId(ctx, pluginConfig);
448
454
  console.log(`[Hindsight] before_agent_start - bank: ${bankId}, channel: ${ctx?.messageProvider}/${ctx?.channelId}`);
449
455
  // Get the user's latest message for recall
450
- let prompt = event.prompt;
456
+ // Prefer rawMessage (clean user text) over prompt (envelope-formatted)
457
+ let prompt = event.rawMessage ?? event.prompt;
451
458
  if (!prompt || typeof prompt !== 'string' || prompt.length < 5) {
452
459
  return; // Skip very short messages
453
460
  }
454
- // Extract actual message from Telegram format: [Telegram ... GMT+1] actual message
455
- const telegramMatch = prompt.match(/\[Telegram[^\]]+\]\s*(.+)$/);
456
- if (telegramMatch) {
457
- prompt = telegramMatch[1].trim();
461
+ // Strip envelope-formatted prompts from any channel
462
+ // The prompt may contain: System: lines, abort hints, [Channel ...] header, [from: ...] suffix
463
+ let cleaned = prompt;
464
+ // Remove leading "System: ..." lines (from prependSystemEvents)
465
+ cleaned = cleaned.replace(/^(?:System:.*\n)+\n?/, '');
466
+ // Remove session abort hint
467
+ cleaned = cleaned.replace(/^Note: The previous agent run was aborted[^\n]*\n\n/, '');
468
+ // Extract message after [ChannelName ...] envelope header
469
+ // Handles any channel: Telegram, Slack, Discord, WhatsApp, Signal, etc.
470
+ // Uses [\s\S]+ instead of .+ to support multiline messages
471
+ const envelopeMatch = cleaned.match(/\[[A-Z][A-Za-z]*(?:\s[^\]]+)?\]\s*([\s\S]+)$/);
472
+ if (envelopeMatch) {
473
+ cleaned = envelopeMatch[1];
458
474
  }
475
+ // Remove trailing [from: SenderName] metadata (group chats)
476
+ cleaned = cleaned.replace(/\n\[from:[^\]]*\]\s*$/, '');
477
+ prompt = cleaned.trim() || prompt;
459
478
  if (prompt.length < 5) {
460
479
  return; // Skip very short messages after extraction
461
480
  }
@@ -473,10 +492,10 @@ export default function (api) {
473
492
  return;
474
493
  }
475
494
  console.log(`[Hindsight] Auto-recall for bank ${bankId}, prompt: ${prompt.substring(0, 50)}`);
476
- // Recall relevant memories (up to 512 tokens)
495
+ // Recall relevant memories
477
496
  const response = await client.recall({
478
497
  query: prompt,
479
- max_tokens: 512,
498
+ max_tokens: 2048,
480
499
  });
481
500
  if (!response.results || response.results.length === 0) {
482
501
  console.log('[Hindsight] No memories found for auto-recall');
@@ -504,6 +523,11 @@ User message: ${prompt}
504
523
  try {
505
524
  // Use context from this hook, or fall back to context captured in before_agent_start
506
525
  const effectiveCtx = ctx || currentAgentContext;
526
+ // Check if this provider is excluded
527
+ if (effectiveCtx?.messageProvider && pluginConfig.excludeProviders?.includes(effectiveCtx.messageProvider)) {
528
+ console.log(`[Hindsight] Skipping retain for excluded provider: ${effectiveCtx.messageProvider}`);
529
+ return;
530
+ }
507
531
  // Derive bank ID from context
508
532
  const bankId = deriveBankId(effectiveCtx, pluginConfig);
509
533
  console.log(`[Hindsight Hook] agent_end triggered - bank: ${bankId}`);
@@ -540,6 +564,11 @@ User message: ${prompt}
540
564
  .map((block) => block.text)
541
565
  .join('\n');
542
566
  }
567
+ // Strip plugin-injected memory tags to prevent feedback loop
568
+ // Remove <hindsight_memories> blocks injected during before_agent_start
569
+ content = content.replace(/<hindsight_memories>[\s\S]*?<\/hindsight_memories>/g, '');
570
+ // Remove any <relevant_memories> blocks (legacy/alternative format)
571
+ content = content.replace(/<relevant_memories>[\s\S]*?<\/relevant_memories>/g, '');
543
572
  return `[role: ${role}]\n${content}\n[${role}:end]`;
544
573
  })
545
574
  .join('\n\n');
@@ -547,8 +576,9 @@ User message: ${prompt}
547
576
  console.log('[Hindsight Hook] Transcript too short, skipping');
548
577
  return;
549
578
  }
550
- // Use session key as document ID (prefer context over captured value)
551
- const documentId = effectiveCtx?.sessionKey || currentSessionKey || 'default-session';
579
+ // Use unique document ID per conversation (sessionKey + timestamp)
580
+ // Static sessionKey (e.g. "agent:main:main") causes CASCADE delete of old memories
581
+ const documentId = `${effectiveCtx?.sessionKey || currentSessionKey || 'session'}-${Date.now()}`;
552
582
  // Retain to Hindsight
553
583
  await client.retain({
554
584
  content: transcript,
package/dist/types.d.ts CHANGED
@@ -38,6 +38,7 @@ export interface PluginConfig {
38
38
  hindsightApiToken?: string;
39
39
  dynamicBankId?: boolean;
40
40
  bankIdPrefix?: string;
41
+ excludeProviders?: string[];
41
42
  }
42
43
  export interface ServiceConfig {
43
44
  id: string;
@@ -49,8 +49,7 @@
49
49
  },
50
50
  "hindsightApiUrl": {
51
51
  "type": "string",
52
- "description": "External Hindsight API URL (e.g. 'https://mcp.hindsight.devcraft.team'). When set, skips local daemon and connects directly to this API.",
53
- "format": "uri"
52
+ "description": "External Hindsight API URL (e.g. 'https://mcp.hindsight.devcraft.team'). When set, skips local daemon and connects directly to this API."
54
53
  },
55
54
  "hindsightApiToken": {
56
55
  "type": "string",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectorize-io/hindsight-openclaw",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
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",