diff --git a/hindsight-docs/docs-integrations/opencode.md b/hindsight-docs/docs-integrations/opencode.md index 93057dc9..1f307ddd 100644 --- a/hindsight-docs/docs-integrations/opencode.md +++ b/hindsight-docs/docs-integrations/opencode.md @@ -76,6 +76,9 @@ This ensures memories survive context window trimming. "autoRecall": true, "autoRetain": true, "recallBudget": "mid", + "recallTags": [], + "recallTagsMatch": "any", + "retainTags": [], "retainEveryNTurns": 10, "debug": false }] @@ -108,6 +111,8 @@ Create `~/.hindsight/opencode.json` for persistent configuration that applies ac | `HINDSIGHT_RETAIN_MODE` | `full-session` or `last-turn` | `full-session` | | `HINDSIGHT_RECALL_BUDGET` | Recall budget: `low`, `mid`, `high` | `mid` | | `HINDSIGHT_RECALL_MAX_TOKENS` | Max tokens for recall results | `1024` | +| `HINDSIGHT_RECALL_TAGS` | Comma-separated tags to filter recall results | | +| `HINDSIGHT_RECALL_TAGS_MATCH` | Tag match mode: `any`, `all`, `any_strict`, `all_strict` | `any` | | `HINDSIGHT_DYNAMIC_BANK_ID` | Enable dynamic bank ID derivation | `false` | | `HINDSIGHT_BANK_MISSION` | Bank mission/context for reflect | | | `HINDSIGHT_DEBUG` | Enable debug logging to stderr | `false` | diff --git a/hindsight-integrations/opencode/src/config.ts b/hindsight-integrations/opencode/src/config.ts index c86c442d..9c0daa96 100644 --- a/hindsight-integrations/opencode/src/config.ts +++ b/hindsight-integrations/opencode/src/config.ts @@ -21,6 +21,8 @@ export interface HindsightConfig { recallContextTurns: number; recallMaxQueryChars: number; recallPromptPreamble: string; + recallTags: string[]; + recallTagsMatch: 'any' | 'all' | 'any_strict' | 'all_strict'; // Retain autoRetain: boolean; @@ -56,6 +58,8 @@ const DEFAULTS: HindsightConfig = { recallTypes: ['world', 'experience'], recallContextTurns: 1, recallMaxQueryChars: 800, + recallTags: [], + recallTagsMatch: 'any', recallPromptPreamble: 'Relevant memories from past conversations (prioritize recent when ' + 'conflicting). Only use memories that are directly useful to continue ' + @@ -156,6 +160,19 @@ export function loadConfig(pluginOptions?: Record): HindsightCo } } + // Array env vars (comma-separated) + const recallTagsEnv = process.env['HINDSIGHT_RECALL_TAGS']; + if (recallTagsEnv !== undefined) { + config['recallTags'] = recallTagsEnv + .split(',') + .map((t) => t.trim()) + .filter(Boolean); + } + const recallTagsMatchEnv = process.env['HINDSIGHT_RECALL_TAGS_MATCH']; + if (recallTagsMatchEnv !== undefined) { + config['recallTagsMatch'] = recallTagsMatchEnv; + } + const result = config as unknown as HindsightConfig; // Validate enum-like fields to catch typos early @@ -168,6 +185,15 @@ export function loadConfig(pluginOptions?: Record): HindsightCo result.retainMode = 'full-session'; } + const VALID_TAGS_MATCH = ['any', 'all', 'any_strict', 'all_strict']; + if (!VALID_TAGS_MATCH.includes(result.recallTagsMatch)) { + console.error( + `[Hindsight] Unknown recallTagsMatch "${result.recallTagsMatch}" — ` + + `valid: ${VALID_TAGS_MATCH.join(', ')}. Falling back to "any".`, + ); + result.recallTagsMatch = 'any'; + } + const VALID_BUDGETS = ['low', 'mid', 'high']; if (!VALID_BUDGETS.includes(result.recallBudget)) { console.error( diff --git a/hindsight-integrations/opencode/src/hooks.ts b/hindsight-integrations/opencode/src/hooks.ts index 3db7d72f..521ee548 100644 --- a/hindsight-integrations/opencode/src/hooks.ts +++ b/hindsight-integrations/opencode/src/hooks.ts @@ -95,6 +95,8 @@ export function createHooks( budget: config.recallBudget as 'low' | 'mid' | 'high', maxTokens: config.recallMaxTokens, types: config.recallTypes, + tags: config.recallTags.length ? config.recallTags : undefined, + tagsMatch: config.recallTags.length ? config.recallTagsMatch : undefined, }); const results = response.results || []; diff --git a/hindsight-integrations/opencode/src/test-helpers.ts b/hindsight-integrations/opencode/src/test-helpers.ts index 0f124143..ef3ac573 100644 --- a/hindsight-integrations/opencode/src/test-helpers.ts +++ b/hindsight-integrations/opencode/src/test-helpers.ts @@ -9,6 +9,8 @@ export function makeConfig(overrides: Partial = {}): HindsightC recallContextTurns: 1, recallMaxQueryChars: 800, recallPromptPreamble: '', + recallTags: [], + recallTagsMatch: 'any', autoRetain: true, retainMode: 'full-session', retainEveryNTurns: 10, diff --git a/hindsight-integrations/opencode/src/tools.ts b/hindsight-integrations/opencode/src/tools.ts index 8ef884e8..637e175e 100644 --- a/hindsight-integrations/opencode/src/tools.ts +++ b/hindsight-integrations/opencode/src/tools.ts @@ -68,6 +68,8 @@ export function createTools( budget: config.recallBudget as 'low' | 'mid' | 'high', maxTokens: config.recallMaxTokens, types: config.recallTypes, + tags: config.recallTags.length ? config.recallTags : undefined, + tagsMatch: config.recallTags.length ? config.recallTagsMatch : undefined, }); const results = response.results || [];