fleet-memory/hindsight-docs/examples/api/recall.mjs
Nicolò Boschi a56cd044e5
feat: 4-tab code parity across all documentation examples (#613)
* feat: independent versioning for integrations

- Add per-integration changelog pages at /changelog/integrations/<name>
- Move main changelog to changelog/index.md (URL unchanged)
- Add --integration flag to generate-changelog for LLM-based per-integration changelog generation
- Add scripts/release-integration.sh <name> <version> for cutting integration releases
- Add .github/workflows/release-integration.yml to publish on integrations/** tags
- Remove integrations from main release.sh and release.yml cycle

* fix: add agno and hermes integration docs to version-0.4 for production build

* chore: apply ruff formatting to generate_changelog.py

* feat: add 4-tab code parity across all documentation examples

Every code snippet Tabs block now has Python, Node.js, CLI, and Go variants.
Raw HTTP/curl tabs replaced with proper SDK calls.

New example files:
- Go: retain.go, recall.go, reflect.go, memory-banks.go, directives.go,
  mental-models.go, documents.go, main-methods.go
- Shell: memory-banks.sh, directives.sh, mental-models.sh
- Node.js: mental-models.mjs

Extended example files with missing sections:
- recall.mjs/sh: world/experience/observation types, token-budget, all tag modes
- reflect.sh: reflect-with-params, reflect-disposition, reflect-sources, reflect-with-tags
- reflect.mjs: reflect-with-tags, fixed reflect-sources API usage
- retain.mjs/sh: retain-conversation, retain-batch, retain-files-batch

SDK/CLI additions:
- TypeScript: getMentalModelHistory method
- CLI recall: --tags, --tags-match flags
- CLI reflect: --tags, --tags-match, --include-facts flags
- CLI directive update: --is-active flag
- CLI bank set-config: --retain-mission, --retain-extraction-mode,
  --observations-mission, --reflect-mission, --disposition-* flags

Build validation:
- scripts/check-code-parity.mjs validates 4-tab parity across all MDX files
- Integrated into npm run build — fails if any Tabs block is missing a variant

* fix: fix doc examples for Go, Node.js, CLI + add mental model with-id examples

- Fix Go Budget constants: BUDGET_HIGH/LOW/MID → HIGH/LOW/MID
- Fix Go documents.go: ListDocuments returns []map[string]interface{}, use map access
- Fix Go retain.go: use correct relative path for sample.pdf
- Fix Node.js createMentalModel: use positional args (name, sourceQuery) not object
- Add CLI 'history' subcommand for mental models (api.rs, main.rs, mental_model.rs)
- Rebuild TypeScript/Python clients to support id param in createMentalModel
- Add create-mental-model-with-id examples across all 4 languages and docs

* fix: move id param to end of create_mental_model signature for backwards compat
2026-03-19 11:31:51 +01:00

181 lines
5.7 KiB
JavaScript

#!/usr/bin/env node
/**
* Recall API examples for Hindsight (Node.js)
* Run: node examples/api/recall.mjs
*/
import { HindsightClient } from '@vectorize-io/hindsight-client';
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
// =============================================================================
// Setup (not shown in docs)
// =============================================================================
const client = new HindsightClient({ baseUrl: HINDSIGHT_URL });
// Seed some data for recall examples
await client.retain('my-bank', 'Alice works at Google as a software engineer');
await client.retain('my-bank', 'Alice loves hiking on weekends');
await client.retain('my-bank', 'Bob is a data scientist who works with Alice');
// =============================================================================
// Doc Examples
// =============================================================================
// [docs:recall-basic]
const response = await client.recall('my-bank', 'What does Alice do?');
// response.results is an array of result objects, each with:
// - id: fact ID
// - text: the extracted fact
// - type: "world", "experience", or "observation"
// - context: context label set during retain
// - metadata: Record<string, string> set during retain
// - tags: string[] of tags
// - entities: string[] of entity names linked to this fact
// - occurredStart: ISO datetime of when the event started
// - occurredEnd: ISO datetime of when the event ended
// - mentionedAt: ISO datetime of when the fact was retained
// - documentId: document this fact belongs to
// - chunkId: chunk this fact was extracted from
// Example response.results:
// [
// { id: "a1b2...", text: "Alice works at Google as a software engineer", type: "world", context: "career", ... },
// { id: "c3d4...", text: "Alice got promoted to senior engineer", type: "experience", occurredStart: "2024-03-15T00:00:00Z", ... },
// ]
// [/docs:recall-basic]
// [docs:recall-with-options]
const detailedResponse = await client.recall('my-bank', 'What does Alice do?', {
types: ['world', 'experience'],
budget: 'high',
maxTokens: 8000,
trace: true
});
// Access results
for (const r of detailedResponse.results) {
console.log(`${r.text} (score: ${r.weight})`);
}
// [/docs:recall-with-options]
// [docs:recall-world-only]
await client.recall('my-bank', 'query', { types: ['world'] });
// [/docs:recall-world-only]
// [docs:recall-experience-only]
await client.recall('my-bank', 'query', { types: ['experience'] });
// [/docs:recall-experience-only]
// [docs:recall-observations-only]
await client.recall('my-bank', 'query', { types: ['observation'] });
// [/docs:recall-observations-only]
// [docs:recall-token-budget]
// Fill up to 4K tokens of context with relevant memories
await client.recall('my-bank', 'What do I know about Alice?', { maxTokens: 4096 });
// Smaller budget for quick lookups
await client.recall('my-bank', "Alice's email", { maxTokens: 500 });
// [/docs:recall-token-budget]
// [docs:recall-with-tags]
// Filter recall to only memories tagged for a specific user
await client.recall('my-bank', 'What feedback did the user give?', {
tags: ['user:alice']
});
// [/docs:recall-with-tags]
// [docs:recall-tags-strict]
// Strict: only memories that have matching tags (excludes untagged)
await client.recall('my-bank', 'What did the user say?', {
tags: ['user:alice'],
tagsMatch: 'any_strict'
});
// [/docs:recall-tags-strict]
// [docs:recall-tags-all]
// AND matching: require ALL specified tags to be present
await client.recall('my-bank', 'What bugs were reported?', {
tags: ['user:alice', 'bug-report'],
tagsMatch: 'all_strict'
});
// [/docs:recall-tags-all]
// [docs:recall-tags-any]
await client.recall('my-bank', 'communication preferences', {
tags: ['user:alice'],
tagsMatch: 'any'
});
// [/docs:recall-tags-any]
// [docs:recall-tags-any-strict]
await client.recall('my-bank', 'communication preferences', {
tags: ['user:alice'],
tagsMatch: 'any_strict'
});
// [/docs:recall-tags-any-strict]
// [docs:recall-tags-all-mode]
await client.recall('my-bank', 'communication tools', {
tags: ['user:alice', 'team'],
tagsMatch: 'all'
});
// [/docs:recall-tags-all-mode]
// [docs:recall-tags-all-strict]
await client.recall('my-bank', 'communication tools', {
tags: ['user:alice', 'team'],
tagsMatch: 'all_strict'
});
// [/docs:recall-tags-all-strict]
// [docs:recall-source-facts]
// Recall observations and include their source facts
const obsResponse = await client.recall('my-bank', 'What patterns have I learned about Alice?', {
types: ['observation'],
includeSourceFacts: true,
maxSourceFactsTokens: 4096,
});
for (const obs of obsResponse.results) {
console.log(`Observation: ${obs.text}`);
if (obs.source_fact_ids && obsResponse.source_facts) {
console.log(' Derived from:');
for (const factId of obs.source_fact_ids) {
const fact = obsResponse.source_facts[factId];
if (fact) console.log(` - [${fact.type}] ${fact.text}`);
}
}
}
// [/docs:recall-source-facts]
// [docs:recall-budget-levels]
// Quick lookup
const quickResults = await client.recall('my-bank', "Alice's email", { budget: 'low' });
// Deep exploration
const deepResults = await client.recall('my-bank', 'How are Alice and Bob connected?', { budget: 'high' });
// [/docs:recall-budget-levels]
// =============================================================================
// Cleanup (not shown in docs)
// =============================================================================
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
console.log('recall.mjs: All examples passed');