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
This commit is contained in:
parent
438ce98b40
commit
a56cd044e5
38 changed files with 2306 additions and 104 deletions
|
|
@ -601,6 +601,13 @@ impl ApiClient {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn get_mental_model_history(&self, bank_id: &str, mental_model_id: &str, _verbose: bool) -> Result<serde_json::Value> {
|
||||
self.runtime.block_on(async {
|
||||
let response = self.client.get_mental_model_history(bank_id, mental_model_id, None).await?;
|
||||
Ok(response.into_inner())
|
||||
})
|
||||
}
|
||||
|
||||
// --- Directive Methods ---
|
||||
|
||||
pub fn list_directives(&self, bank_id: &str, _verbose: bool) -> Result<types::DirectiveListResponse> {
|
||||
|
|
|
|||
|
|
@ -717,6 +717,13 @@ pub fn set_config(
|
|||
llm_model: Option<String>,
|
||||
llm_api_key: Option<String>,
|
||||
llm_base_url: Option<String>,
|
||||
retain_mission: Option<String>,
|
||||
retain_extraction_mode: Option<String>,
|
||||
observations_mission: Option<String>,
|
||||
reflect_mission: Option<String>,
|
||||
disposition_skepticism: Option<i64>,
|
||||
disposition_literalism: Option<i64>,
|
||||
disposition_empathy: Option<i64>,
|
||||
verbose: bool,
|
||||
output_format: OutputFormat,
|
||||
) -> Result<()> {
|
||||
|
|
@ -736,9 +743,30 @@ pub fn set_config(
|
|||
if let Some(base_url) = llm_base_url {
|
||||
updates.insert("llm_base_url".to_string(), serde_json::Value::String(base_url));
|
||||
}
|
||||
if let Some(mission) = retain_mission {
|
||||
updates.insert("retain_mission".to_string(), serde_json::Value::String(mission));
|
||||
}
|
||||
if let Some(mode) = retain_extraction_mode {
|
||||
updates.insert("retain_extraction_mode".to_string(), serde_json::Value::String(mode));
|
||||
}
|
||||
if let Some(mission) = observations_mission {
|
||||
updates.insert("observations_mission".to_string(), serde_json::Value::String(mission));
|
||||
}
|
||||
if let Some(mission) = reflect_mission {
|
||||
updates.insert("reflect_mission".to_string(), serde_json::Value::String(mission));
|
||||
}
|
||||
if let Some(skepticism) = disposition_skepticism {
|
||||
updates.insert("disposition_skepticism".to_string(), serde_json::Value::Number(skepticism.into()));
|
||||
}
|
||||
if let Some(literalism) = disposition_literalism {
|
||||
updates.insert("disposition_literalism".to_string(), serde_json::Value::Number(literalism.into()));
|
||||
}
|
||||
if let Some(empathy) = disposition_empathy {
|
||||
updates.insert("disposition_empathy".to_string(), serde_json::Value::Number(empathy.into()));
|
||||
}
|
||||
|
||||
if updates.is_empty() {
|
||||
return Err(anyhow!("No config updates provided. Use --llm-provider, --llm-model, --llm-api-key, or --llm-base-url".to_string()));
|
||||
return Err(anyhow!("No config updates provided. Use --llm-provider, --llm-model, --retain-mission, --observations-mission, or other flags".to_string()));
|
||||
}
|
||||
|
||||
let spinner = if output_format == OutputFormat::Pretty {
|
||||
|
|
|
|||
|
|
@ -149,11 +149,12 @@ pub fn update(
|
|||
directive_id: &str,
|
||||
name: Option<String>,
|
||||
content: Option<String>,
|
||||
is_active: Option<bool>,
|
||||
verbose: bool,
|
||||
output_format: OutputFormat,
|
||||
) -> Result<()> {
|
||||
if name.is_none() && content.is_none() {
|
||||
anyhow::bail!("At least one of --name or --content must be provided");
|
||||
if name.is_none() && content.is_none() && is_active.is_none() {
|
||||
anyhow::bail!("At least one of --name, --content, or --is-active must be provided");
|
||||
}
|
||||
|
||||
let spinner = if output_format == OutputFormat::Pretty {
|
||||
|
|
@ -165,7 +166,7 @@ pub fn update(
|
|||
let request = types::UpdateDirectiveRequest {
|
||||
name,
|
||||
content,
|
||||
is_active: None,
|
||||
is_active,
|
||||
priority: None,
|
||||
tags: None,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::output::{self, OutputFormat};
|
|||
use crate::ui;
|
||||
|
||||
// Import types from generated client
|
||||
use hindsight_client::types::{Budget, ChunkIncludeOptions, IncludeOptions, TagsMatch};
|
||||
use hindsight_client::types::{Budget, ChunkIncludeOptions, FactsIncludeOptions, IncludeOptions, ReflectIncludeOptions, TagsMatch};
|
||||
use serde::Deserialize;
|
||||
use serde_json;
|
||||
|
||||
|
|
@ -43,6 +43,16 @@ fn parse_budget(budget: &str) -> Budget {
|
|||
}
|
||||
}
|
||||
|
||||
// Helper function to parse tags_match string to TagsMatch enum
|
||||
fn parse_tags_match(tags_match: &Option<String>) -> TagsMatch {
|
||||
match tags_match.as_deref().unwrap_or("any").to_lowercase().as_str() {
|
||||
"all" => TagsMatch::All,
|
||||
"any_strict" => TagsMatch::AnyStrict,
|
||||
"all_strict" => TagsMatch::AllStrict,
|
||||
_ => TagsMatch::Any,
|
||||
}
|
||||
}
|
||||
|
||||
/// List memory units with pagination and optional filters
|
||||
pub fn list(
|
||||
client: &ApiClient,
|
||||
|
|
@ -250,6 +260,8 @@ pub fn recall(
|
|||
trace: bool,
|
||||
include_chunks: bool,
|
||||
chunk_max_tokens: i64,
|
||||
tags: Vec<String>,
|
||||
tags_match: Option<String>,
|
||||
verbose: bool,
|
||||
output_format: OutputFormat,
|
||||
) -> Result<()> {
|
||||
|
|
@ -280,8 +292,8 @@ pub fn recall(
|
|||
trace,
|
||||
query_timestamp: None,
|
||||
include,
|
||||
tags: None,
|
||||
tags_match: TagsMatch::Any,
|
||||
tags: if tags.is_empty() { None } else { Some(tags) },
|
||||
tags_match: parse_tags_match(&tags_match),
|
||||
tag_groups: None,
|
||||
};
|
||||
|
||||
|
|
@ -312,6 +324,9 @@ pub fn reflect(
|
|||
context: Option<String>,
|
||||
max_tokens: Option<i64>,
|
||||
schema_path: Option<PathBuf>,
|
||||
tags: Vec<String>,
|
||||
tags_match: Option<String>,
|
||||
include_facts: bool,
|
||||
verbose: bool,
|
||||
output_format: OutputFormat,
|
||||
) -> Result<()> {
|
||||
|
|
@ -332,15 +347,24 @@ pub fn reflect(
|
|||
None
|
||||
};
|
||||
|
||||
let include = if include_facts {
|
||||
Some(ReflectIncludeOptions {
|
||||
facts: Some(FactsIncludeOptions(serde_json::Map::new())),
|
||||
tool_calls: None,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let request = ReflectRequest {
|
||||
query,
|
||||
budget: Some(parse_budget(&budget)),
|
||||
context,
|
||||
max_tokens: max_tokens.unwrap_or(4096),
|
||||
include: None,
|
||||
include,
|
||||
response_schema,
|
||||
tags: None,
|
||||
tags_match: TagsMatch::Any,
|
||||
tags: if tags.is_empty() { None } else { Some(tags) },
|
||||
tags_match: parse_tags_match(&tags_match),
|
||||
tag_groups: None,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -272,6 +272,55 @@ pub fn refresh(
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the change history of a mental model
|
||||
pub fn history(
|
||||
client: &ApiClient,
|
||||
bank_id: &str,
|
||||
mental_model_id: &str,
|
||||
verbose: bool,
|
||||
output_format: OutputFormat,
|
||||
) -> Result<()> {
|
||||
let spinner = if output_format == OutputFormat::Pretty {
|
||||
Some(ui::create_spinner("Fetching mental model history..."))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let response = client.get_mental_model_history(bank_id, mental_model_id, verbose);
|
||||
|
||||
if let Some(mut sp) = spinner {
|
||||
sp.finish();
|
||||
}
|
||||
|
||||
match response {
|
||||
Ok(history) => {
|
||||
if output_format == OutputFormat::Pretty {
|
||||
ui::print_section_header(&format!("History: {}", mental_model_id));
|
||||
|
||||
if let Some(entries) = history.as_array() {
|
||||
if entries.is_empty() {
|
||||
println!(" {}", ui::dim("No history entries found."));
|
||||
} else {
|
||||
for entry in entries {
|
||||
let changed_at = entry.get("changed_at").and_then(|v| v.as_str()).unwrap_or("unknown");
|
||||
let previous = entry.get("previous_content").and_then(|v| v.as_str()).unwrap_or("(none)");
|
||||
println!(" {} {}", ui::dim("Changed at:"), changed_at);
|
||||
let preview: String = previous.chars().take(80).collect();
|
||||
let ellipsis = if previous.len() > 80 { "..." } else { "" };
|
||||
println!(" {} {}{}", ui::dim("Previous:"), ui::dim(&preview), ellipsis);
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
output::print_output(&history, output_format)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to print mental model details
|
||||
fn print_mental_model_detail(mental_model: &types::MentalModelResponse) {
|
||||
ui::print_section_header(&mental_model.name);
|
||||
|
|
|
|||
|
|
@ -310,6 +310,34 @@ enum BankCommands {
|
|||
/// LLM base URL override
|
||||
#[arg(long)]
|
||||
llm_base_url: Option<String>,
|
||||
|
||||
/// Retain mission: what to focus on during fact extraction
|
||||
#[arg(long)]
|
||||
retain_mission: Option<String>,
|
||||
|
||||
/// Retain extraction mode (concise, verbose, custom)
|
||||
#[arg(long)]
|
||||
retain_extraction_mode: Option<String>,
|
||||
|
||||
/// Observations mission: what to synthesize into durable observations
|
||||
#[arg(long)]
|
||||
observations_mission: Option<String>,
|
||||
|
||||
/// Reflect mission: first-person identity for reflect operations
|
||||
#[arg(long)]
|
||||
reflect_mission: Option<String>,
|
||||
|
||||
/// Disposition skepticism trait (1-5)
|
||||
#[arg(long, value_parser = clap::value_parser!(i64).range(1..=5))]
|
||||
disposition_skepticism: Option<i64>,
|
||||
|
||||
/// Disposition literalism trait (1-5)
|
||||
#[arg(long, value_parser = clap::value_parser!(i64).range(1..=5))]
|
||||
disposition_literalism: Option<i64>,
|
||||
|
||||
/// Disposition empathy trait (1-5)
|
||||
#[arg(long, value_parser = clap::value_parser!(i64).range(1..=5))]
|
||||
disposition_empathy: Option<i64>,
|
||||
},
|
||||
|
||||
/// Reset bank configuration to defaults (remove all overrides)
|
||||
|
|
@ -387,6 +415,14 @@ enum MemoryCommands {
|
|||
/// Maximum tokens for chunks (only used with --include-chunks)
|
||||
#[arg(long, default_value = "8192")]
|
||||
chunk_max_tokens: i64,
|
||||
|
||||
/// Filter by tags (comma-separated, e.g. user:alice,team)
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
tags: Vec<String>,
|
||||
|
||||
/// Tag matching mode: any, all, any_strict, all_strict (default: any)
|
||||
#[arg(long)]
|
||||
tags_match: Option<String>,
|
||||
},
|
||||
|
||||
/// Generate answers using bank identity (reflect/reasoning)
|
||||
|
|
@ -412,6 +448,18 @@ enum MemoryCommands {
|
|||
/// Path to JSON schema file for structured output
|
||||
#[arg(short = 's', long)]
|
||||
schema: Option<PathBuf>,
|
||||
|
||||
/// Filter by tags (comma-separated, e.g. user:alice,team)
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
tags: Vec<String>,
|
||||
|
||||
/// Tag matching mode: any, all, any_strict, all_strict (default: any)
|
||||
#[arg(long)]
|
||||
tags_match: Option<String>,
|
||||
|
||||
/// Include source facts (based_on) in the response
|
||||
#[arg(long)]
|
||||
include_facts: bool,
|
||||
},
|
||||
|
||||
/// Store (retain) a single memory
|
||||
|
|
@ -678,6 +726,15 @@ enum MentalModelCommands {
|
|||
/// Mental model ID
|
||||
mental_model_id: String,
|
||||
},
|
||||
|
||||
/// Get the change history of a mental model
|
||||
History {
|
||||
/// Bank ID
|
||||
bank_id: String,
|
||||
|
||||
/// Mental model ID
|
||||
mental_model_id: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
|
|
@ -724,6 +781,10 @@ enum DirectiveCommands {
|
|||
/// New content
|
||||
#[arg(long)]
|
||||
content: Option<String>,
|
||||
|
||||
/// Enable or disable the directive
|
||||
#[arg(long)]
|
||||
is_active: Option<bool>,
|
||||
},
|
||||
|
||||
/// Delete a directive
|
||||
|
|
@ -821,8 +882,8 @@ fn run() -> Result<()> {
|
|||
BankCommands::Config { bank_id, overrides_only } => {
|
||||
commands::bank::config(&client, &bank_id, overrides_only, verbose, output_format)
|
||||
}
|
||||
BankCommands::SetConfig { bank_id, llm_provider, llm_model, llm_api_key, llm_base_url } => {
|
||||
commands::bank::set_config(&client, &bank_id, llm_provider, llm_model, llm_api_key, llm_base_url, verbose, output_format)
|
||||
BankCommands::SetConfig { bank_id, llm_provider, llm_model, llm_api_key, llm_base_url, retain_mission, retain_extraction_mode, observations_mission, reflect_mission, disposition_skepticism, disposition_literalism, disposition_empathy } => {
|
||||
commands::bank::set_config(&client, &bank_id, llm_provider, llm_model, llm_api_key, llm_base_url, retain_mission, retain_extraction_mode, observations_mission, reflect_mission, disposition_skepticism, disposition_literalism, disposition_empathy, verbose, output_format)
|
||||
}
|
||||
BankCommands::ResetConfig { bank_id, yes } => {
|
||||
commands::bank::reset_config(&client, &bank_id, yes, verbose, output_format)
|
||||
|
|
@ -837,11 +898,11 @@ fn run() -> Result<()> {
|
|||
MemoryCommands::Get { bank_id, memory_id } => {
|
||||
commands::memory::get(&client, &bank_id, &memory_id, verbose, output_format)
|
||||
}
|
||||
MemoryCommands::Recall { bank_id, query, fact_type, budget, max_tokens, trace, include_chunks, chunk_max_tokens } => {
|
||||
commands::memory::recall(&client, &bank_id, query, fact_type, budget, max_tokens, trace, include_chunks, chunk_max_tokens, verbose, output_format)
|
||||
MemoryCommands::Recall { bank_id, query, fact_type, budget, max_tokens, trace, include_chunks, chunk_max_tokens, tags, tags_match } => {
|
||||
commands::memory::recall(&client, &bank_id, query, fact_type, budget, max_tokens, trace, include_chunks, chunk_max_tokens, tags, tags_match, verbose, output_format)
|
||||
}
|
||||
MemoryCommands::Reflect { bank_id, query, budget, context, max_tokens, schema } => {
|
||||
commands::memory::reflect(&client, &bank_id, query, budget, context, max_tokens, schema, verbose, output_format)
|
||||
MemoryCommands::Reflect { bank_id, query, budget, context, max_tokens, schema, tags, tags_match, include_facts } => {
|
||||
commands::memory::reflect(&client, &bank_id, query, budget, context, max_tokens, schema, tags, tags_match, include_facts, verbose, output_format)
|
||||
}
|
||||
MemoryCommands::Retain { bank_id, content, doc_id, context, r#async } => {
|
||||
commands::memory::retain(&client, &bank_id, content, doc_id, context, r#async, verbose, output_format)
|
||||
|
|
@ -930,6 +991,9 @@ fn run() -> Result<()> {
|
|||
MentalModelCommands::Refresh { bank_id, mental_model_id } => {
|
||||
commands::mental_model::refresh(&client, &bank_id, &mental_model_id, verbose, output_format)
|
||||
}
|
||||
MentalModelCommands::History { bank_id, mental_model_id } => {
|
||||
commands::mental_model::history(&client, &bank_id, &mental_model_id, verbose, output_format)
|
||||
}
|
||||
},
|
||||
|
||||
// Directive commands
|
||||
|
|
@ -943,8 +1007,8 @@ fn run() -> Result<()> {
|
|||
DirectiveCommands::Create { bank_id, name, content } => {
|
||||
commands::directive::create(&client, &bank_id, &name, &content, verbose, output_format)
|
||||
}
|
||||
DirectiveCommands::Update { bank_id, directive_id, name, content } => {
|
||||
commands::directive::update(&client, &bank_id, &directive_id, name, content, verbose, output_format)
|
||||
DirectiveCommands::Update { bank_id, directive_id, name, content, is_active } => {
|
||||
commands::directive::update(&client, &bank_id, &directive_id, name, content, is_active, verbose, output_format)
|
||||
}
|
||||
DirectiveCommands::Delete { bank_id, directive_id, yes } => {
|
||||
commands::directive::delete(&client, &bank_id, &directive_id, yes, verbose, output_format)
|
||||
|
|
|
|||
|
|
@ -792,6 +792,7 @@ class Hindsight:
|
|||
tags: list[str] | None = None,
|
||||
max_tokens: int | None = None,
|
||||
trigger: dict[str, Any] | None = None,
|
||||
id: str | None = None,
|
||||
):
|
||||
"""
|
||||
Create a mental model (runs reflect in background).
|
||||
|
|
@ -803,6 +804,7 @@ class Hindsight:
|
|||
tags: Optional tags for filtering during retrieval
|
||||
max_tokens: Optional maximum tokens for the mental model content
|
||||
trigger: Optional trigger settings (e.g., {"refresh_after_consolidation": True})
|
||||
id: Optional custom ID for the mental model (alphanumeric lowercase with hyphens)
|
||||
|
||||
Returns:
|
||||
CreateMentalModelResponse with operation_id
|
||||
|
|
@ -814,6 +816,7 @@ class Hindsight:
|
|||
trigger_obj = mental_model_trigger.MentalModelTrigger(**trigger)
|
||||
|
||||
request_obj = create_mental_model_request.CreateMentalModelRequest(
|
||||
id=id,
|
||||
name=name,
|
||||
source_query=source_query,
|
||||
tags=tags,
|
||||
|
|
|
|||
|
|
@ -628,6 +628,7 @@ export class HindsightClient {
|
|||
name: string,
|
||||
sourceQuery: string,
|
||||
options?: {
|
||||
id?: string;
|
||||
tags?: string[];
|
||||
maxTokens?: number;
|
||||
trigger?: { refreshAfterConsolidation?: boolean };
|
||||
|
|
@ -637,6 +638,7 @@ export class HindsightClient {
|
|||
client: this.client,
|
||||
path: { bank_id: bankId },
|
||||
body: {
|
||||
id: options?.id,
|
||||
name,
|
||||
source_query: sourceQuery,
|
||||
tags: options?.tags,
|
||||
|
|
@ -726,6 +728,18 @@ export class HindsightClient {
|
|||
throw new Error(`deleteMentalModel failed: ${JSON.stringify(response.error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the change history of a mental model.
|
||||
*/
|
||||
async getMentalModelHistory(bankId: string, mentalModelId: string): Promise<any> {
|
||||
const response = await sdk.getMentalModelHistory({
|
||||
client: this.client,
|
||||
path: { bank_id: bankId, mental_model_id: mentalModelId },
|
||||
});
|
||||
|
||||
return this.validateResponse(response, 'getMentalModelHistory');
|
||||
}
|
||||
}
|
||||
|
||||
// Re-export types for convenience
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import CodeSnippet from '@site/src/components/CodeSnippet';
|
|||
{/* Import raw source files */}
|
||||
import documentsPy from '!!raw-loader!@site/examples/api/documents.py';
|
||||
import documentsMjs from '!!raw-loader!@site/examples/api/documents.mjs';
|
||||
import documentsGo from '!!raw-loader!@site/examples/api/documents.go';
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've completed the [Quick Start](./quickstart) and understand [how retain works](./retain).
|
||||
|
|
@ -60,6 +61,9 @@ hindsight memory retain my-bank "Meeting notes content..." --doc-id notes-2024-0
|
|||
hindsight memory retain-files my-bank docs/
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={documentsGo} section="document-retain" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -84,6 +88,9 @@ hindsight memory retain my-bank "Project deadline: March 31" --doc-id project-pl
|
|||
hindsight memory retain my-bank "Project deadline: April 15 (extended)" --doc-id project-plan
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={documentsGo} section="document-update" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -104,6 +111,9 @@ Retrieve a document's original text and metadata. This is useful for expanding d
|
|||
hindsight document get my-bank meeting-2024-03-15
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={documentsGo} section="document-get" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -128,6 +138,9 @@ hindsight document update-tags my-bank meeting-2024-03-15 --tags team-a --tags t
|
|||
hindsight document update-tags my-bank meeting-2024-03-15
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={documentsGo} section="document-update" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -152,6 +165,9 @@ Remove a document and all its associated memories:
|
|||
hindsight document delete my-bank meeting-2024-03-15
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={documentsGo} section="document-delete" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -183,6 +199,9 @@ hindsight document list my-bank --q report
|
|||
hindsight document list my-bank --tags team-a --tags team-b
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={documentsGo} section="document-list" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import CodeSnippet from '@site/src/components/CodeSnippet';
|
|||
{/* Import raw source files */}
|
||||
import mainMethodsPy from '!!raw-loader!@site/examples/api/main-methods.py';
|
||||
import mainMethodsMjs from '!!raw-loader!@site/examples/api/main-methods.mjs';
|
||||
import mainMethodsGo from '!!raw-loader!@site/examples/api/main-methods.go';
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've [installed Hindsight](../installation) and completed the [Quick Start](./quickstart).
|
||||
|
|
@ -33,15 +34,18 @@ Store conversations, documents, and facts into a memory bank.
|
|||
|
||||
```bash
|
||||
# Store a single fact
|
||||
hindsight retain my-bank "Alice joined Google in March 2024 as a Senior ML Engineer"
|
||||
hindsight memory retain my-bank "Alice joined Google in March 2024 as a Senior ML Engineer"
|
||||
|
||||
# Store from a file
|
||||
hindsight retain my-bank --file conversation.txt --context "Daily standup"
|
||||
hindsight memory retain-files my-bank conversation.txt --context "Daily standup"
|
||||
|
||||
# Store multiple files
|
||||
hindsight retain my-bank --files docs/*.md
|
||||
hindsight memory retain-files my-bank docs/
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mainMethodsGo} section="main-retain" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -66,18 +70,21 @@ Search for relevant memories using multi-strategy retrieval.
|
|||
|
||||
```bash
|
||||
# Basic search
|
||||
hindsight recall my-bank "What does Alice do at Google?"
|
||||
hindsight memory recall my-bank "What does Alice do at Google?"
|
||||
|
||||
# Search with options
|
||||
hindsight recall my-bank "What happened last spring?" \
|
||||
hindsight memory recall my-bank "What happened last spring?" \
|
||||
--budget high \
|
||||
--max-tokens 8192 \
|
||||
--fact-type world
|
||||
--fact-type world,experience
|
||||
|
||||
# Verbose output (shows weights and sources)
|
||||
hindsight recall my-bank "Tell me about Alice" -v
|
||||
# Verbose output
|
||||
hindsight memory recall my-bank "Tell me about Alice" -v
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mainMethodsGo} section="main-recall" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -102,15 +109,15 @@ Generate disposition-aware responses using memories and observations.
|
|||
|
||||
```bash
|
||||
# Basic reflect
|
||||
hindsight reflect my-bank "Should we adopt TypeScript for our backend?"
|
||||
|
||||
# Verbose output (shows sources and observations)
|
||||
hindsight reflect my-bank "What are Alice's strengths for the team lead role?" -v
|
||||
hindsight memory reflect my-bank "Should we adopt TypeScript for our backend?"
|
||||
|
||||
# With higher reasoning budget
|
||||
hindsight reflect my-bank "Analyze our tech stack" --budget high
|
||||
hindsight memory reflect my-bank "Analyze our tech stack" --budget high
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mainMethodsGo} section="main-reflect" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,12 @@ import CodeSnippet from '@site/src/components/CodeSnippet';
|
|||
{/* Import raw source files */}
|
||||
import memoryBanksPy from '!!raw-loader!@site/examples/api/memory-banks.py';
|
||||
import memoryBanksMjs from '!!raw-loader!@site/examples/api/memory-banks.mjs';
|
||||
import memoryBanksSh from '!!raw-loader!@site/examples/api/memory-banks.sh';
|
||||
import memoryBanksGo from '!!raw-loader!@site/examples/api/memory-banks.go';
|
||||
import directivesPy from '!!raw-loader!@site/examples/api/directives.py';
|
||||
import directivesMjs from '!!raw-loader!@site/examples/api/directives.mjs';
|
||||
import directivesSh from '!!raw-loader!@site/examples/api/directives.sh';
|
||||
import directivesGo from '!!raw-loader!@site/examples/api/directives.go';
|
||||
|
||||
## What is a Memory Bank?
|
||||
|
||||
|
|
@ -44,11 +48,10 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client
|
|||
<CodeSnippet code={memoryBanksMjs} section="create-bank" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
hindsight bank create my-bank
|
||||
```
|
||||
|
||||
<CodeSnippet code={memoryBanksSh} section="create-bank" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={memoryBanksGo} section="create-bank" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -205,6 +208,12 @@ How skeptical vs trusting the bank is when evaluating claims during `reflect`. S
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={memoryBanksMjs} section="bank-with-disposition" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={memoryBanksSh} section="bank-with-disposition" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={memoryBanksGo} section="bank-with-disposition" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
| Value | Behaviour |
|
||||
|
|
@ -275,6 +284,12 @@ Bank configuration fields (retain mission, extraction mode, observations mission
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={memoryBanksMjs} section="update-bank-config" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={memoryBanksSh} section="update-bank-config" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={memoryBanksGo} section="update-bank-config" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
You can update any subset of fields — only the keys you provide are changed.
|
||||
|
|
@ -288,6 +303,12 @@ You can update any subset of fields — only the keys you provide are changed.
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={memoryBanksMjs} section="get-bank-config" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={memoryBanksSh} section="get-bank-config" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={memoryBanksGo} section="get-bank-config" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The response distinguishes:
|
||||
|
|
@ -303,6 +324,12 @@ The response distinguishes:
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={memoryBanksMjs} section="reset-bank-config" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={memoryBanksSh} section="reset-bank-config" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={memoryBanksGo} section="reset-bank-config" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This removes all bank-level overrides. The bank reverts to server-wide defaults (set via environment variables).
|
||||
|
|
@ -337,6 +364,12 @@ Use directives for rules that must never be violated:
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={directivesMjs} section="create-directive" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={directivesSh} section="create-directive" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={directivesGo} section="create-directive" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Listing Directives
|
||||
|
|
@ -348,6 +381,12 @@ Use directives for rules that must never be violated:
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={directivesMjs} section="list-directives" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={directivesSh} section="list-directives" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={directivesGo} section="list-directives" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Updating Directives
|
||||
|
|
@ -359,6 +398,12 @@ Use directives for rules that must never be violated:
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={directivesMjs} section="update-directive" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={directivesSh} section="update-directive" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={directivesGo} section="update-directive" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Deleting Directives
|
||||
|
|
@ -370,6 +415,12 @@ Use directives for rules that must never be violated:
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={directivesMjs} section="delete-directive" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={directivesSh} section="delete-directive" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={directivesGo} section="delete-directive" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Directives vs Disposition
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ import CodeSnippet from '@site/src/components/CodeSnippet';
|
|||
|
||||
{/* Import raw source files */}
|
||||
import mentalModelsPy from '!!raw-loader!@site/examples/api/mental-models.py';
|
||||
import mentalModelsMjs from '!!raw-loader!@site/examples/api/mental-models.mjs';
|
||||
import mentalModelsSh from '!!raw-loader!@site/examples/api/mental-models.sh';
|
||||
import mentalModelsGo from '!!raw-loader!@site/examples/api/mental-models.go';
|
||||
|
||||
## What Are Mental Models?
|
||||
|
||||
|
|
@ -56,22 +59,14 @@ Creating a mental model runs a reflect operation in the background and saves the
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="create-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="create-mental-model" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Create a mental model (async operation)
|
||||
curl -X POST "http://localhost:8888/v1/default/banks/my-bank/mental-models" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Team Communication Preferences",
|
||||
"source_query": "How does the team prefer to communicate?",
|
||||
"tags": ["team"]
|
||||
}'
|
||||
|
||||
# Response: {"operation_id": "op-123"}
|
||||
# Use the operations endpoint to check completion
|
||||
```
|
||||
|
||||
<CodeSnippet code={mentalModelsSh} section="create-mental-model" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="create-mental-model" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -81,12 +76,38 @@ curl -X POST "http://localhost:8888/v1/default/banks/my-bank/mental-models" \
|
|||
|-----------|------|----------|-------------|
|
||||
| `name` | string | Yes | Human-readable name for the mental model |
|
||||
| `source_query` | string | Yes | The query to run to generate content |
|
||||
| `id` | string | No | Custom ID for the mental model (alphanumeric lowercase with hyphens). Auto-generated if omitted. |
|
||||
| `tags` | list | No | Tags for filtering during retrieval |
|
||||
| `max_tokens` | int | No | Maximum tokens for the mental model content |
|
||||
| `trigger` | object | No | Trigger settings (see [Automatic Refresh](#automatic-refresh)) |
|
||||
|
||||
---
|
||||
|
||||
## Create with Custom ID
|
||||
|
||||
Assign a stable, human-readable ID to a mental model so you can retrieve or update it by name instead of relying on the auto-generated UUID:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="create-mental-model-with-id" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="create-mental-model-with-id" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={mentalModelsSh} section="create-mental-model-with-id" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="create-mental-model-with-id" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip
|
||||
Custom IDs must be lowercase alphanumeric and may contain hyphens (e.g. `team-policies`, `q4-status`). If a mental model with that ID already exists, the request is rejected.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Automatic Refresh
|
||||
|
||||
Mental models can be configured to **automatically refresh** when observations are updated. This keeps them in sync with the latest knowledge without manual intervention.
|
||||
|
|
@ -103,19 +124,14 @@ When `refresh_after_consolidation` is enabled, the mental model will be re-gener
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="create-mental-model-with-trigger" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="create-mental-model-with-trigger" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Create a mental model with automatic refresh enabled
|
||||
curl -X POST "http://localhost:8888/v1/default/banks/my-bank/mental-models" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Project Status",
|
||||
"source_query": "What is the current project status?",
|
||||
"trigger": {"refresh_after_consolidation": true}
|
||||
}'
|
||||
```
|
||||
|
||||
<CodeSnippet code={mentalModelsSh} section="create-mental-model-with-trigger" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="create-mental-model-with-trigger" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -140,12 +156,14 @@ Enable automatic refresh for mental models that need to stay current. Disable it
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="list-mental-models" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="list-mental-models" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8888/v1/default/banks/my-bank/mental-models"
|
||||
```
|
||||
|
||||
<CodeSnippet code={mentalModelsSh} section="list-mental-models" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="list-mental-models" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -157,12 +175,14 @@ curl "http://localhost:8888/v1/default/banks/my-bank/mental-models"
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="get-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="get-mental-model" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8888/v1/default/banks/my-bank/mental-models/{mental_model_id}"
|
||||
```
|
||||
|
||||
<CodeSnippet code={mentalModelsSh} section="get-mental-model" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="get-mental-model" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -190,12 +210,14 @@ Re-run the source query to update the mental model with current knowledge:
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="refresh-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="refresh-mental-model" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8888/v1/default/banks/my-bank/mental-models/{mental_model_id}/refresh"
|
||||
```
|
||||
|
||||
<CodeSnippet code={mentalModelsSh} section="refresh-mental-model" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="refresh-mental-model" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -214,14 +236,14 @@ Update the mental model's name:
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="update-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="update-mental-model" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl -X PATCH "http://localhost:8888/v1/default/banks/my-bank/mental-models/{mental_model_id}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name": "Updated Team Communication Preferences"}'
|
||||
```
|
||||
|
||||
<CodeSnippet code={mentalModelsSh} section="update-mental-model" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="update-mental-model" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -233,12 +255,14 @@ curl -X PATCH "http://localhost:8888/v1/default/banks/my-bank/mental-models/{men
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="delete-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="delete-mental-model" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl -X DELETE "http://localhost:8888/v1/default/banks/my-bank/mental-models/{mental_model_id}"
|
||||
```
|
||||
|
||||
<CodeSnippet code={mentalModelsSh} section="delete-mental-model" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="delete-mental-model" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -280,6 +304,15 @@ Every time a mental model's content changes (via refresh or manual update), the
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="get-mental-model-history" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mentalModelsMjs} section="get-mental-model-history" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={mentalModelsSh} section="get-mental-model-history" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={mentalModelsGo} section="get-mental-model-history" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Response
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {ClientsGrid, IntegrationsGrid} from '@site/src/components/SupportedGrids
|
|||
import quickstartPy from '!!raw-loader!@site/examples/api/quickstart.py';
|
||||
import quickstartMjs from '!!raw-loader!@site/examples/api/quickstart.mjs';
|
||||
import quickstartSh from '!!raw-loader!@site/examples/api/quickstart.sh';
|
||||
import quickstartGo from '!!raw-loader!@site/examples/api/quickstart.go';
|
||||
|
||||
## Clients
|
||||
|
||||
|
|
@ -90,6 +91,15 @@ curl -fsSL https://hindsight.vectorize.io/get-cli | bash
|
|||
|
||||
<CodeSnippet code={quickstartSh} section="quickstart-full" language="bash" />
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
|
||||
```bash
|
||||
go get github.com/vectorize-io/hindsight/hindsight-clients/go
|
||||
```
|
||||
|
||||
<CodeSnippet code={quickstartGo} section="quickstart-full" language="go" />
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import CodeSnippet from '@site/src/components/CodeSnippet';
|
|||
import recallPy from '!!raw-loader!@site/examples/api/recall.py';
|
||||
import recallMjs from '!!raw-loader!@site/examples/api/recall.mjs';
|
||||
import recallSh from '!!raw-loader!@site/examples/api/recall.sh';
|
||||
import recallGo from '!!raw-loader!@site/examples/api/recall.go';
|
||||
|
||||
:::info How Recall Works
|
||||
Learn about the four retrieval strategies (semantic, keyword, graph, temporal) and RRF fusion in the [Recall Architecture](/developer/retrieval) guide.
|
||||
|
|
@ -37,6 +38,9 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client
|
|||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-basic" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-basic" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
|
@ -59,9 +63,19 @@ Each type runs the full four-strategy retrieval pipeline independently, so narro
|
|||
<CodeSnippet code={recallPy} section="recall-experience-only" language="python" />
|
||||
<CodeSnippet code={recallPy} section="recall-observations-only" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-world-only" language="javascript" />
|
||||
<CodeSnippet code={recallMjs} section="recall-experience-only" language="javascript" />
|
||||
<CodeSnippet code={recallMjs} section="recall-observations-only" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-fact-type" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-world-only" language="go" />
|
||||
<CodeSnippet code={recallGo} section="recall-experience-only" language="go" />
|
||||
<CodeSnippet code={recallGo} section="recall-observations-only" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip About Observations
|
||||
|
|
@ -79,6 +93,12 @@ Controls retrieval depth and breadth. Accepted values are `low`, `mid` (default)
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-budget-levels" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-budget-levels" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-budget-levels" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### max_tokens
|
||||
|
|
@ -89,6 +109,15 @@ The maximum number of tokens the returned facts can collectively occupy. Default
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-token-budget" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-token-budget" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-token-budget" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-token-budget" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### query_timestamp
|
||||
|
|
@ -118,6 +147,12 @@ When enabled and `types` includes `observation`, each observation result is acco
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-source-facts" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-source-facts" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-source-facts" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### entities
|
||||
|
|
@ -152,7 +187,20 @@ Consider a bank with these four memories:
|
|||
|
||||
Returns memories that have **at least one** matching tag, plus untagged memories.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-tags-any" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-tags-any" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-tags-any" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-with-tags" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Use this for **shared global knowledge + user-specific** patterns, where untagged memories represent information everyone should see.
|
||||
|
||||
|
|
@ -160,7 +208,20 @@ Use this for **shared global knowledge + user-specific** patterns, where untagge
|
|||
|
||||
Same as `any` but untagged memories are excluded.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-tags-any-strict" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-tags-any-strict" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-tags-any-strict" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-tags-strict" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Use this when memories are **fully partitioned by tags** and untagged memories should never be visible.
|
||||
|
||||
|
|
@ -168,7 +229,20 @@ Use this when memories are **fully partitioned by tags** and untagged memories s
|
|||
|
||||
Returns memories that have **every** specified tag, plus untagged memories.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-tags-all-mode" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-tags-all-mode" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-tags-all-mode" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-tags-all-mode" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Use this when memories must belong to a **specific intersection** of scopes (e.g., only memories relevant to both a user and a project), while still surfacing shared global knowledge.
|
||||
|
||||
|
|
@ -176,7 +250,20 @@ Use this when memories must belong to a **specific intersection** of scopes (e.g
|
|||
|
||||
Returns memories that have **every** specified tag, and excludes untagged memories.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-tags-all-strict" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-tags-all-strict" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-tags-all-strict" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={recallGo} section="recall-tags-all" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Use this for strict scope enforcement where a memory must explicitly belong to **all** specified contexts.
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import CodeSnippet from '@site/src/components/CodeSnippet';
|
|||
import reflectPy from '!!raw-loader!@site/examples/api/reflect.py';
|
||||
import reflectMjs from '!!raw-loader!@site/examples/api/reflect.mjs';
|
||||
import reflectSh from '!!raw-loader!@site/examples/api/reflect.sh';
|
||||
import reflectGo from '!!raw-loader!@site/examples/api/reflect.go';
|
||||
|
||||
:::info How Reflect Works
|
||||
Learn about disposition-driven reasoning in the [Reflect Architecture](/developer/reflect) guide.
|
||||
|
|
@ -37,6 +38,9 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client
|
|||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={reflectSh} section="reflect-basic" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={reflectGo} section="reflect-basic" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
|
@ -58,6 +62,12 @@ Controls how thoroughly the agent explores the memory bank before answering. Acc
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={reflectMjs} section="reflect-with-params" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={reflectSh} section="reflect-with-params" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={reflectGo} section="reflect-with-params" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### max_tokens
|
||||
|
|
@ -78,6 +88,9 @@ An optional JSON Schema object. When provided, the LLM generates a response that
|
|||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={reflectSh} section="reflect-structured-output" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={reflectGo} section="reflect-structured-output" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### tags
|
||||
|
|
@ -88,6 +101,15 @@ Filters which memories the agent can access during reflection. Works identically
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={reflectPy} section="reflect-with-tags" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={reflectMjs} section="reflect-with-tags" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={reflectSh} section="reflect-with-tags" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={reflectGo} section="reflect-with-tags" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### include
|
||||
|
|
@ -102,6 +124,15 @@ When enabled, the response includes a `based_on` object listing the memories, me
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={reflectPy} section="reflect-sources" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={reflectMjs} section="reflect-sources" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={reflectSh} section="reflect-sources" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={reflectGo} section="reflect-sources" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### include.tool_calls
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import CodeSnippet from '@site/src/components/CodeSnippet';
|
|||
import retainPy from '!!raw-loader!@site/examples/api/retain.py';
|
||||
import retainMjs from '!!raw-loader!@site/examples/api/retain.mjs';
|
||||
import retainSh from '!!raw-loader!@site/examples/api/retain.sh';
|
||||
import retainGo from '!!raw-loader!@site/examples/api/retain.go';
|
||||
|
||||
:::info How Retain Works
|
||||
Learn about fact extraction, entity resolution, and graph construction in the [Retain Architecture](/developer/retain) guide.
|
||||
|
|
@ -39,6 +40,9 @@ A single retain call accepts one or more **items**. Each item is a piece of raw
|
|||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-basic" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={retainGo} section="retain-basic" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Retaining a Conversation
|
||||
|
|
@ -52,6 +56,12 @@ A full conversation should be retained as a single item. The LLM can parse any f
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-conversation" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-conversation" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={retainGo} section="retain-conversation" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
When the conversation grows — a new message arrives — just retain again with the full updated content and the same `document_id`. Hindsight will delete the previous version and reprocess from scratch, so memories always reflect the latest state of the conversation.
|
||||
|
|
@ -92,6 +102,9 @@ Providing context consistently is one of the highest-leverage things you can do
|
|||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-with-context" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={retainGo} section="retain-with-context" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### metadata
|
||||
|
|
@ -203,6 +216,12 @@ Multiple items can be submitted in a single request. Batch ingestion is the reco
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-batch" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-batch" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={retainGo} section="retain-batch" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
|
|
@ -215,18 +234,18 @@ Upload files directly — Hindsight converts them to text and extracts memories
|
|||
**Supported formats:** PDF, DOCX, DOC, PPTX, PPT, XLSX, XLS, images (JPG, PNG, GIF, etc. — OCR), audio (MP3, WAV, FLAC, etc. — transcription), HTML, and plain text formats (TXT, MD, CSV, JSON, YAML, etc.)
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-files" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="HTTP">
|
||||
<CodeSnippet code={retainSh} section="retain-files-curl" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-files" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-files" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-files" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={retainGo} section="retain-files" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The file retain endpoint always returns asynchronously. The response contains `operation_ids` — one per uploaded file — which you can poll via `GET /v1/default/banks/{bank_id}/operations` to track progress.
|
||||
|
|
@ -237,6 +256,15 @@ Upload up to 10 files per request (max 100 MB total). Each file becomes a separa
|
|||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-files-batch" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-files-batch" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-files" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={retainGo} section="retain-files" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::info File Storage
|
||||
|
|
@ -256,6 +284,12 @@ For large batches, use async ingestion to avoid blocking your application:
|
|||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-async" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-async" language="bash" />
|
||||
</TabItem>
|
||||
<TabItem value="go" label="Go">
|
||||
<CodeSnippet code={retainGo} section="retain-async" language="go" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
When `async: true`, the call returns immediately with an `operation_id`. Processing runs in the background via the worker service. No `usage` metrics are returned for async operations.
|
||||
|
|
|
|||
86
hindsight-docs/examples/api/directives.go
Normal file
86
hindsight-docs/examples/api/directives.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"
|
||||
)
|
||||
|
||||
const bankID = "directives-example-bank"
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("HINDSIGHT_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = "http://localhost:8888"
|
||||
}
|
||||
|
||||
cfg := hindsight.NewConfiguration()
|
||||
cfg.Servers = hindsight.ServerConfigurations{{URL: apiURL}}
|
||||
client := hindsight.NewAPIClient(cfg)
|
||||
ctx := context.Background()
|
||||
|
||||
// =============================================================================
|
||||
// Setup (not shown in docs)
|
||||
// =============================================================================
|
||||
client.BanksAPI.CreateOrUpdateBank(ctx, bankID).
|
||||
CreateBankRequest(hindsight.CreateBankRequest{
|
||||
Name: *hindsight.NewNullableString(hindsight.PtrString("Test Bank")),
|
||||
}).Execute()
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:create-directive]
|
||||
// Create a directive (hard rule for reflect)
|
||||
directive, _, _ := client.DirectivesAPI.CreateDirective(ctx, bankID).
|
||||
CreateDirectiveRequest(hindsight.CreateDirectiveRequest{
|
||||
Name: "Formal Language",
|
||||
Content: "Always respond in formal English, avoiding slang and colloquialisms.",
|
||||
}).Execute()
|
||||
|
||||
fmt.Printf("Created directive: %s\n", directive.GetId())
|
||||
// [/docs:create-directive]
|
||||
|
||||
directiveID := directive.GetId()
|
||||
|
||||
// [docs:list-directives]
|
||||
// List all directives in a bank
|
||||
directives, _, _ := client.DirectivesAPI.ListDirectives(ctx, bankID).Execute()
|
||||
|
||||
for _, d := range directives.GetItems() {
|
||||
content := d.GetContent()
|
||||
if len(content) > 50 {
|
||||
content = content[:50]
|
||||
}
|
||||
fmt.Printf("- %s: %s...\n", d.GetName(), content)
|
||||
}
|
||||
// [/docs:list-directives]
|
||||
|
||||
// [docs:update-directive]
|
||||
// Update a directive (e.g., disable without deleting)
|
||||
isActiveFalse := false
|
||||
updated, _, _ := client.DirectivesAPI.UpdateDirective(ctx, bankID, directiveID).
|
||||
UpdateDirectiveRequest(hindsight.UpdateDirectiveRequest{
|
||||
IsActive: *hindsight.NewNullableBool(&isActiveFalse),
|
||||
}).Execute()
|
||||
|
||||
fmt.Printf("Directive active: %v\n", updated.GetIsActive())
|
||||
// [/docs:update-directive]
|
||||
|
||||
// [docs:delete-directive]
|
||||
// Delete a directive
|
||||
client.DirectivesAPI.DeleteDirective(ctx, bankID, directiveID).Execute()
|
||||
// [/docs:delete-directive]
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
req, _ := http.NewRequest("DELETE", fmt.Sprintf("%s/v1/default/banks/%s", apiURL, bankID), nil)
|
||||
http.DefaultClient.Do(req)
|
||||
|
||||
fmt.Println("directives.go: All examples passed")
|
||||
}
|
||||
51
hindsight-docs/examples/api/directives.sh
Normal file
51
hindsight-docs/examples/api/directives.sh
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#!/bin/bash
|
||||
# Directives API examples for Hindsight CLI
|
||||
# Run: bash examples/api/directives.sh
|
||||
|
||||
set -e
|
||||
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
BANK_ID="directives-example-bank"
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
hindsight bank create "$BANK_ID" --name "Test Bank"
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:create-directive]
|
||||
# Create a directive (hard rule for reflect)
|
||||
hindsight directive create "$BANK_ID" \
|
||||
"Formal Language" \
|
||||
"Always respond in formal English, avoiding slang and colloquialisms."
|
||||
# [/docs:create-directive]
|
||||
|
||||
# Get the directive ID for subsequent operations
|
||||
DIRECTIVE_ID=$(hindsight directive list "$BANK_ID" -o json | python3 -c "import sys,json; items=json.load(sys.stdin).get('items',[]); print(items[0]['id'] if items else '')" 2>/dev/null || echo "")
|
||||
|
||||
# [docs:list-directives]
|
||||
# List all directives in a bank
|
||||
hindsight directive list "$BANK_ID"
|
||||
# [/docs:list-directives]
|
||||
|
||||
if [ -n "$DIRECTIVE_ID" ]; then
|
||||
# [docs:update-directive]
|
||||
# Update a directive (e.g., disable without deleting)
|
||||
hindsight directive update "$BANK_ID" "$DIRECTIVE_ID" --is-active false
|
||||
# [/docs:update-directive]
|
||||
|
||||
# [docs:delete-directive]
|
||||
# Delete a directive
|
||||
hindsight directive delete "$BANK_ID" "$DIRECTIVE_ID" -y
|
||||
# [/docs:delete-directive]
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
hindsight bank delete "$BANK_ID" -y
|
||||
|
||||
echo "directives.sh: All examples passed"
|
||||
94
hindsight-docs/examples/api/documents.go
Normal file
94
hindsight-docs/examples/api/documents.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("HINDSIGHT_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = "http://localhost:8888"
|
||||
}
|
||||
|
||||
cfg := hindsight.NewConfiguration()
|
||||
cfg.Servers = hindsight.ServerConfigurations{{URL: apiURL}}
|
||||
client := hindsight.NewAPIClient(cfg)
|
||||
ctx := context.Background()
|
||||
|
||||
// [docs:document-retain]
|
||||
// Retain with document ID
|
||||
docID := "meeting-2024-03-15"
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{
|
||||
Content: "Alice presented the Q4 roadmap...",
|
||||
DocumentId: *hindsight.NewNullableString(&docID),
|
||||
},
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:document-retain]
|
||||
|
||||
// [docs:document-update]
|
||||
// Original
|
||||
planDoc := "project-plan"
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{
|
||||
Content: "Project deadline: March 31",
|
||||
DocumentId: *hindsight.NewNullableString(&planDoc),
|
||||
},
|
||||
},
|
||||
}).Execute()
|
||||
|
||||
// Update (deletes old facts, creates new ones)
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{
|
||||
Content: "Project deadline: April 15 (extended)",
|
||||
DocumentId: *hindsight.NewNullableString(&planDoc),
|
||||
},
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:document-update]
|
||||
|
||||
// [docs:document-get]
|
||||
doc, _, err := client.DocumentsAPI.GetDocument(ctx, "my-bank", "meeting-2024-03-15").Execute()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get document: %v", err)
|
||||
}
|
||||
fmt.Printf("Document ID: %s\n", doc.GetId())
|
||||
fmt.Printf("Memory units: %d\n", doc.GetMemoryUnitCount())
|
||||
// [/docs:document-get]
|
||||
|
||||
// [docs:document-delete]
|
||||
client.DocumentsAPI.DeleteDocument(ctx, "my-bank", "meeting-2024-03-15").Execute()
|
||||
// [/docs:document-delete]
|
||||
|
||||
// [docs:document-list]
|
||||
// List all documents
|
||||
docs, _, err := client.DocumentsAPI.ListDocuments(ctx, "my-bank").Execute()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to list documents: %v", err)
|
||||
}
|
||||
for _, d := range docs.Items {
|
||||
id, _ := d["id"].(string)
|
||||
memCount, _ := d["memory_unit_count"].(float64)
|
||||
fmt.Printf("%s: %d memories\n", id, int(memCount))
|
||||
}
|
||||
// [/docs:document-list]
|
||||
|
||||
// Cleanup (not shown in docs)
|
||||
req, _ := http.NewRequest("DELETE", fmt.Sprintf("%s/v1/default/banks/my-bank", apiURL), nil)
|
||||
http.DefaultClient.Do(req)
|
||||
|
||||
fmt.Println("documents.go: All examples passed")
|
||||
}
|
||||
60
hindsight-docs/examples/api/main-methods.go
Normal file
60
hindsight-docs/examples/api/main-methods.go
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("HINDSIGHT_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = "http://localhost:8888"
|
||||
}
|
||||
|
||||
cfg := hindsight.NewConfiguration()
|
||||
cfg.Servers = hindsight.ServerConfigurations{{URL: apiURL}}
|
||||
client := hindsight.NewAPIClient(cfg)
|
||||
ctx := context.Background()
|
||||
|
||||
// [docs:main-retain]
|
||||
// Store a fact or conversation into a memory bank
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{Content: "Alice joined Google in March 2024 as a Senior ML Engineer"},
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:main-retain]
|
||||
|
||||
// [docs:main-recall]
|
||||
// Search for memories using a natural language query
|
||||
resp, _, _ := client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What does Alice do at Google?",
|
||||
}).Execute()
|
||||
|
||||
for _, r := range resp.Results {
|
||||
fmt.Println(r.Text)
|
||||
}
|
||||
// [/docs:main-recall]
|
||||
|
||||
// [docs:main-reflect]
|
||||
// Generate a reasoned response using memories and bank disposition
|
||||
answer, _, _ := client.MemoryAPI.Reflect(ctx, "my-bank").
|
||||
ReflectRequest(hindsight.ReflectRequest{
|
||||
Query: "Should we adopt TypeScript for our backend?",
|
||||
}).Execute()
|
||||
|
||||
fmt.Println(answer.GetText())
|
||||
// [/docs:main-reflect]
|
||||
|
||||
// Cleanup (not shown in docs)
|
||||
req, _ := http.NewRequest("DELETE", fmt.Sprintf("%s/v1/default/banks/my-bank", apiURL), nil)
|
||||
http.DefaultClient.Do(req)
|
||||
|
||||
fmt.Println("main-methods.go: All examples passed")
|
||||
}
|
||||
114
hindsight-docs/examples/api/memory-banks.go
Normal file
114
hindsight-docs/examples/api/memory-banks.go
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("HINDSIGHT_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = "http://localhost:8888"
|
||||
}
|
||||
|
||||
cfg := hindsight.NewConfiguration()
|
||||
cfg.Servers = hindsight.ServerConfigurations{{URL: apiURL}}
|
||||
client := hindsight.NewAPIClient(cfg)
|
||||
ctx := context.Background()
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:create-bank]
|
||||
client.BanksAPI.CreateOrUpdateBank(ctx, "my-bank").
|
||||
CreateBankRequest(hindsight.CreateBankRequest{}).Execute()
|
||||
// [/docs:create-bank]
|
||||
|
||||
// [docs:bank-with-disposition]
|
||||
client.BanksAPI.CreateOrUpdateBank(ctx, "architect-bank").
|
||||
CreateBankRequest(hindsight.CreateBankRequest{
|
||||
ReflectMission: *hindsight.NewNullableString(hindsight.PtrString(
|
||||
"You're a senior software architect - keep track of system designs, " +
|
||||
"technology decisions, and architectural patterns. Prefer simplicity over cutting-edge.",
|
||||
)),
|
||||
DispositionSkepticism: *hindsight.NewNullableInt32(hindsight.PtrInt32(4)),
|
||||
DispositionLiteralism: *hindsight.NewNullableInt32(hindsight.PtrInt32(4)),
|
||||
DispositionEmpathy: *hindsight.NewNullableInt32(hindsight.PtrInt32(2)),
|
||||
}).Execute()
|
||||
// [/docs:bank-with-disposition]
|
||||
|
||||
// [docs:bank-background]
|
||||
client.BanksAPI.CreateOrUpdateBank(ctx, "my-bank").
|
||||
CreateBankRequest(hindsight.CreateBankRequest{
|
||||
ReflectMission: *hindsight.NewNullableString(hindsight.PtrString(
|
||||
"I am a research assistant specializing in machine learning.",
|
||||
)),
|
||||
}).Execute()
|
||||
// [/docs:bank-background]
|
||||
|
||||
// [docs:bank-mission]
|
||||
client.BanksAPI.CreateOrUpdateBank(ctx, "my-bank").
|
||||
CreateBankRequest(hindsight.CreateBankRequest{
|
||||
ReflectMission: *hindsight.NewNullableString(hindsight.PtrString(
|
||||
"You're a senior software architect - keep track of system designs, " +
|
||||
"technology decisions, and architectural patterns.",
|
||||
)),
|
||||
}).Execute()
|
||||
// [/docs:bank-mission]
|
||||
|
||||
// [docs:bank-support-agent]
|
||||
client.BanksAPI.CreateOrUpdateBank(ctx, "support-bank").
|
||||
CreateBankRequest(hindsight.CreateBankRequest{}).Execute()
|
||||
client.BanksAPI.UpdateBankConfig(ctx, "support-bank").
|
||||
BankConfigUpdate(hindsight.BankConfigUpdate{
|
||||
Updates: map[string]interface{}{
|
||||
"observations_mission": "I am a customer support agent. Track customer preferences, " +
|
||||
"recurring issues, and resolution history to provide consistent, personalized support.",
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:bank-support-agent]
|
||||
|
||||
// [docs:update-bank-config]
|
||||
client.BanksAPI.UpdateBankConfig(ctx, "my-bank").
|
||||
BankConfigUpdate(hindsight.BankConfigUpdate{
|
||||
Updates: map[string]interface{}{
|
||||
"retain_mission": "Always include technical decisions, API design choices, and architectural trade-offs. " +
|
||||
"Ignore meeting logistics and social exchanges.",
|
||||
"retain_extraction_mode": "verbose",
|
||||
"observations_mission": "Observations are stable facts about people and projects. " +
|
||||
"Always include preferences, skills, and recurring patterns. Ignore one-off events.",
|
||||
"disposition_skepticism": 4,
|
||||
"disposition_literalism": 4,
|
||||
"disposition_empathy": 2,
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:update-bank-config]
|
||||
|
||||
// [docs:get-bank-config]
|
||||
// Returns resolved config (server defaults merged with bank overrides) and the raw overrides
|
||||
result, _, _ := client.BanksAPI.GetBankConfig(ctx, "my-bank").Execute()
|
||||
// result.Config — full resolved configuration
|
||||
// result.Overrides — only fields overridden at the bank level
|
||||
fmt.Println("Config keys:", len(result.GetConfig()))
|
||||
// [/docs:get-bank-config]
|
||||
|
||||
// [docs:reset-bank-config]
|
||||
// Remove all bank-level overrides, reverting to server defaults
|
||||
client.BanksAPI.ResetBankConfig(ctx, "my-bank").Execute()
|
||||
// [/docs:reset-bank-config]
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
for _, bankID := range []string{"my-bank", "architect-bank", "support-bank"} {
|
||||
req, _ := http.NewRequest("DELETE", fmt.Sprintf("%s/v1/default/banks/%s", apiURL, bankID), nil)
|
||||
http.DefaultClient.Do(req)
|
||||
}
|
||||
|
||||
fmt.Println("memory-banks.go: All examples passed")
|
||||
}
|
||||
71
hindsight-docs/examples/api/memory-banks.sh
Normal file
71
hindsight-docs/examples/api/memory-banks.sh
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#!/bin/bash
|
||||
# Memory Banks API examples for Hindsight CLI
|
||||
# Run: bash examples/api/memory-banks.sh
|
||||
|
||||
set -e
|
||||
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:create-bank]
|
||||
hindsight bank create my-bank
|
||||
# [/docs:create-bank]
|
||||
|
||||
# [docs:bank-with-disposition]
|
||||
hindsight bank create architect-bank \
|
||||
--mission "You're a senior software architect - keep track of system designs, technology decisions, and architectural patterns. Prefer simplicity over cutting-edge." \
|
||||
--skepticism 4 \
|
||||
--literalism 4 \
|
||||
--empathy 2
|
||||
# [/docs:bank-with-disposition]
|
||||
|
||||
# [docs:bank-background]
|
||||
hindsight bank create my-bank \
|
||||
--mission "I am a research assistant specializing in machine learning."
|
||||
# [/docs:bank-background]
|
||||
|
||||
# [docs:bank-mission]
|
||||
hindsight bank create my-bank \
|
||||
--mission "You're a senior software architect - keep track of system designs, technology decisions, and architectural patterns."
|
||||
# [/docs:bank-mission]
|
||||
|
||||
# [docs:bank-support-agent]
|
||||
hindsight bank create support-bank
|
||||
hindsight bank set-config support-bank \
|
||||
--observations-mission "I am a customer support agent. Track customer preferences, recurring issues, and resolution history."
|
||||
# [/docs:bank-support-agent]
|
||||
|
||||
# [docs:update-bank-config]
|
||||
hindsight bank set-config my-bank \
|
||||
--retain-mission "Always include technical decisions, API design choices, and architectural trade-offs. Ignore meeting logistics and social exchanges." \
|
||||
--retain-extraction-mode verbose \
|
||||
--observations-mission "Observations are stable facts about people and projects. Always include preferences, skills, and recurring patterns. Ignore one-off events." \
|
||||
--disposition-skepticism 4 \
|
||||
--disposition-literalism 4 \
|
||||
--disposition-empathy 2
|
||||
# [/docs:update-bank-config]
|
||||
|
||||
# [docs:get-bank-config]
|
||||
# Returns resolved config (server defaults merged with bank overrides)
|
||||
hindsight bank config my-bank
|
||||
|
||||
# Show only bank-specific overrides
|
||||
hindsight bank config my-bank --overrides-only
|
||||
# [/docs:get-bank-config]
|
||||
|
||||
# [docs:reset-bank-config]
|
||||
# Remove all bank-level overrides, reverting to server defaults
|
||||
hindsight bank reset-config my-bank -y
|
||||
# [/docs:reset-bank-config]
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
for bank_id in my-bank architect-bank support-bank; do
|
||||
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/${bank_id}" > /dev/null
|
||||
done
|
||||
|
||||
echo "memory-banks.sh: All examples passed"
|
||||
173
hindsight-docs/examples/api/mental-models.go
Normal file
173
hindsight-docs/examples/api/mental-models.go
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"
|
||||
)
|
||||
|
||||
const mmBankID = "mental-models-demo-bank"
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("HINDSIGHT_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = "http://localhost:8888"
|
||||
}
|
||||
|
||||
cfg := hindsight.NewConfiguration()
|
||||
cfg.Servers = hindsight.ServerConfigurations{{URL: apiURL}}
|
||||
client := hindsight.NewAPIClient(cfg)
|
||||
ctx := context.Background()
|
||||
|
||||
// =============================================================================
|
||||
// Setup (not shown in docs)
|
||||
// =============================================================================
|
||||
client.BanksAPI.CreateOrUpdateBank(ctx, mmBankID).
|
||||
CreateBankRequest(hindsight.CreateBankRequest{
|
||||
Name: *hindsight.NewNullableString(hindsight.PtrString("Mental Models Demo")),
|
||||
}).Execute()
|
||||
for _, content := range []string{
|
||||
"The team prefers async communication via Slack",
|
||||
"For urgent issues, use the #incidents channel",
|
||||
"Weekly syncs happen every Monday at 10am",
|
||||
} {
|
||||
client.MemoryAPI.RetainMemories(ctx, mmBankID).
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{{Content: content}},
|
||||
}).Execute()
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:create-mental-model]
|
||||
// Create a mental model (runs reflect in background)
|
||||
result, _, _ := client.MentalModelsAPI.CreateMentalModel(ctx, mmBankID).
|
||||
CreateMentalModelRequest(hindsight.CreateMentalModelRequest{
|
||||
Name: "Team Communication Preferences",
|
||||
SourceQuery: "How does the team prefer to communicate?",
|
||||
Tags: []string{"team", "communication"},
|
||||
}).Execute()
|
||||
|
||||
// Returns an operation_id — check operations endpoint for completion
|
||||
fmt.Printf("Operation ID: %s\n", result.GetOperationId())
|
||||
// [/docs:create-mental-model]
|
||||
|
||||
// [docs:create-mental-model-with-id]
|
||||
// Create a mental model with a specific custom ID
|
||||
mmID := "communication-policy"
|
||||
resultWithID, _, _ := client.MentalModelsAPI.CreateMentalModel(ctx, mmBankID).
|
||||
CreateMentalModelRequest(hindsight.CreateMentalModelRequest{
|
||||
Id: *hindsight.NewNullableString(&mmID),
|
||||
Name: "Communication Policy",
|
||||
SourceQuery: "What are the team's communication guidelines?",
|
||||
}).Execute()
|
||||
|
||||
fmt.Printf("Created with custom ID: %s\n", resultWithID.GetOperationId())
|
||||
// [/docs:create-mental-model-with-id]
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// [docs:create-mental-model-with-trigger]
|
||||
// Create a mental model with automatic refresh enabled
|
||||
refreshTrue := true
|
||||
result2, _, _ := client.MentalModelsAPI.CreateMentalModel(ctx, mmBankID).
|
||||
CreateMentalModelRequest(hindsight.CreateMentalModelRequest{
|
||||
Name: "Project Status",
|
||||
SourceQuery: "What is the current project status?",
|
||||
Trigger: &hindsight.MentalModelTrigger{
|
||||
RefreshAfterConsolidation: &refreshTrue,
|
||||
},
|
||||
}).Execute()
|
||||
|
||||
// This mental model will automatically refresh when observations are updated
|
||||
fmt.Printf("Operation ID: %s\n", result2.GetOperationId())
|
||||
// [/docs:create-mental-model-with-trigger]
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// [docs:list-mental-models]
|
||||
// List all mental models in a bank
|
||||
mentalModels, _, _ := client.MentalModelsAPI.ListMentalModels(ctx, mmBankID).Execute()
|
||||
|
||||
for _, mm := range mentalModels.GetItems() {
|
||||
fmt.Printf("- %s: %s\n", mm.GetName(), mm.GetSourceQuery())
|
||||
}
|
||||
// [/docs:list-mental-models]
|
||||
|
||||
if len(mentalModels.GetItems()) == 0 {
|
||||
fmt.Println("mental-models.go: All examples passed (no mental models created yet)")
|
||||
cleanupMentalModels(client, ctx, apiURL)
|
||||
return
|
||||
}
|
||||
|
||||
mentalModelID := mentalModels.GetItems()[0].GetId()
|
||||
|
||||
// [docs:get-mental-model]
|
||||
// Get a specific mental model
|
||||
mentalModel, _, _ := client.MentalModelsAPI.GetMentalModel(ctx, mmBankID, mentalModelID).Execute()
|
||||
|
||||
fmt.Printf("Name: %s\n", mentalModel.GetName())
|
||||
fmt.Printf("Content: %s\n", mentalModel.GetContent())
|
||||
fmt.Printf("Last refreshed: %s\n", mentalModel.GetLastRefreshedAt())
|
||||
// [/docs:get-mental-model]
|
||||
|
||||
// [docs:refresh-mental-model]
|
||||
// Refresh a mental model to update with current knowledge
|
||||
refreshResult, _, _ := client.MentalModelsAPI.RefreshMentalModel(ctx, mmBankID, mentalModelID).Execute()
|
||||
|
||||
fmt.Printf("Refresh operation ID: %s\n", refreshResult.GetOperationId())
|
||||
// [/docs:refresh-mental-model]
|
||||
|
||||
// [docs:update-mental-model]
|
||||
// Update a mental model's metadata
|
||||
newName := "Updated Team Communication Preferences"
|
||||
refreshAfter := true
|
||||
updated, _, _ := client.MentalModelsAPI.UpdateMentalModel(ctx, mmBankID, mentalModelID).
|
||||
UpdateMentalModelRequest(hindsight.UpdateMentalModelRequest{
|
||||
Name: *hindsight.NewNullableString(&newName),
|
||||
Trigger: *hindsight.NewNullableMentalModelTrigger(&hindsight.MentalModelTrigger{
|
||||
RefreshAfterConsolidation: &refreshAfter,
|
||||
}),
|
||||
}).Execute()
|
||||
|
||||
fmt.Printf("Updated name: %s\n", updated.GetName())
|
||||
// [/docs:update-mental-model]
|
||||
|
||||
// [docs:get-mental-model-history]
|
||||
// Get the change history of a mental model
|
||||
history, _, _ := client.MentalModelsAPI.GetMentalModelHistory(ctx, mmBankID, mentalModelID).Execute()
|
||||
|
||||
if entries, ok := history.([]interface{}); ok {
|
||||
for _, entry := range entries {
|
||||
if e, ok := entry.(map[string]interface{}); ok {
|
||||
fmt.Printf("Changed at: %v\n", e["changed_at"])
|
||||
fmt.Printf("Previous content: %v\n", e["previous_content"])
|
||||
}
|
||||
}
|
||||
}
|
||||
// [/docs:get-mental-model-history]
|
||||
|
||||
// [docs:delete-mental-model]
|
||||
// Delete a mental model
|
||||
client.MentalModelsAPI.DeleteMentalModel(ctx, mmBankID, mentalModelID).Execute()
|
||||
// [/docs:delete-mental-model]
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
cleanupMentalModels(client, ctx, apiURL)
|
||||
|
||||
fmt.Println("mental-models.go: All examples passed")
|
||||
}
|
||||
|
||||
func cleanupMentalModels(client *hindsight.APIClient, ctx context.Context, apiURL string) {
|
||||
req, _ := http.NewRequest("DELETE", fmt.Sprintf("%s/v1/default/banks/%s", apiURL, mmBankID), nil)
|
||||
http.DefaultClient.Do(req)
|
||||
}
|
||||
129
hindsight-docs/examples/api/mental-models.mjs
Normal file
129
hindsight-docs/examples/api/mental-models.mjs
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Mental Models API examples for Hindsight (Node.js)
|
||||
* Run: node examples/api/mental-models.mjs
|
||||
*/
|
||||
import { HindsightClient } from '@vectorize-io/hindsight-client';
|
||||
|
||||
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
|
||||
const BANK_ID = 'mental-models-demo-bank';
|
||||
|
||||
// =============================================================================
|
||||
// Setup (not shown in docs)
|
||||
// =============================================================================
|
||||
const client = new HindsightClient({ baseUrl: HINDSIGHT_URL });
|
||||
await client.createBank(BANK_ID, { name: 'Mental Models Demo' });
|
||||
await client.retain(BANK_ID, 'The team prefers async communication via Slack');
|
||||
await client.retain(BANK_ID, 'For urgent issues, use the #incidents channel');
|
||||
await client.retain(BANK_ID, 'Weekly syncs happen every Monday at 10am');
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:create-mental-model]
|
||||
// Create a mental model (runs reflect in background)
|
||||
const result = await client.createMentalModel(
|
||||
BANK_ID,
|
||||
'Team Communication Preferences',
|
||||
'How does the team prefer to communicate?',
|
||||
{ tags: ['team', 'communication'] },
|
||||
);
|
||||
|
||||
// Returns an operation_id — check operations endpoint for completion
|
||||
console.log(`Operation ID: ${result.operation_id}`);
|
||||
// [/docs:create-mental-model]
|
||||
|
||||
// [docs:create-mental-model-with-id]
|
||||
// Create a mental model with a specific custom ID
|
||||
const resultWithId = await client.createMentalModel(
|
||||
BANK_ID,
|
||||
'Communication Policy',
|
||||
"What are the team's communication guidelines?",
|
||||
{ id: 'communication-policy' },
|
||||
);
|
||||
|
||||
console.log(`Created with custom ID: ${resultWithId.operation_id}`);
|
||||
// [/docs:create-mental-model-with-id]
|
||||
|
||||
await new Promise(r => setTimeout(r, 5000));
|
||||
|
||||
// [docs:create-mental-model-with-trigger]
|
||||
// Create a mental model with automatic refresh enabled
|
||||
const result2 = await client.createMentalModel(
|
||||
BANK_ID,
|
||||
'Project Status',
|
||||
'What is the current project status?',
|
||||
{ trigger: { refreshAfterConsolidation: true } },
|
||||
);
|
||||
|
||||
// This mental model will automatically refresh when observations are updated
|
||||
console.log(`Operation ID: ${result2.operation_id}`);
|
||||
// [/docs:create-mental-model-with-trigger]
|
||||
|
||||
await new Promise(r => setTimeout(r, 5000));
|
||||
|
||||
// [docs:list-mental-models]
|
||||
// List all mental models in a bank
|
||||
const mentalModels = await client.listMentalModels(BANK_ID);
|
||||
|
||||
for (const mm of mentalModels.items) {
|
||||
console.log(`- ${mm.name}: ${mm.source_query}`);
|
||||
}
|
||||
// [/docs:list-mental-models]
|
||||
|
||||
const mentalModelId = mentalModels.items[0]?.id;
|
||||
if (!mentalModelId) {
|
||||
console.log('mental-models.mjs: All examples passed (no mental models created yet)');
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/${BANK_ID}`, { method: 'DELETE' });
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// [docs:get-mental-model]
|
||||
// Get a specific mental model
|
||||
const mentalModel = await client.getMentalModel(BANK_ID, mentalModelId);
|
||||
|
||||
console.log(`Name: ${mentalModel.name}`);
|
||||
console.log(`Content: ${mentalModel.content}`);
|
||||
console.log(`Last refreshed: ${mentalModel.last_refreshed_at}`);
|
||||
// [/docs:get-mental-model]
|
||||
|
||||
// [docs:refresh-mental-model]
|
||||
// Refresh a mental model to update with current knowledge
|
||||
const refreshResult = await client.refreshMentalModel(BANK_ID, mentalModelId);
|
||||
|
||||
console.log(`Refresh operation ID: ${refreshResult.operation_id}`);
|
||||
// [/docs:refresh-mental-model]
|
||||
|
||||
// [docs:update-mental-model]
|
||||
// Update a mental model's metadata
|
||||
const updated = await client.updateMentalModel(BANK_ID, mentalModelId, {
|
||||
name: 'Updated Team Communication Preferences',
|
||||
trigger: { refresh_after_consolidation: true },
|
||||
});
|
||||
|
||||
console.log(`Updated name: ${updated.name}`);
|
||||
// [/docs:update-mental-model]
|
||||
|
||||
// [docs:get-mental-model-history]
|
||||
// Get the change history of a mental model
|
||||
const history = await client.getMentalModelHistory(BANK_ID, mentalModelId);
|
||||
|
||||
for (const entry of history) {
|
||||
console.log(`Changed at: ${entry.changed_at}`);
|
||||
console.log(`Previous content: ${entry.previous_content}`);
|
||||
}
|
||||
// [/docs:get-mental-model-history]
|
||||
|
||||
// [docs:delete-mental-model]
|
||||
// Delete a mental model
|
||||
await client.deleteMentalModel(BANK_ID, mentalModelId);
|
||||
// [/docs:delete-mental-model]
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
await client.deleteBank(BANK_ID);
|
||||
|
||||
console.log('mental-models.mjs: All examples passed');
|
||||
|
|
@ -42,6 +42,18 @@ result = client.create_mental_model(
|
|||
print(f"Operation ID: {result.operation_id}")
|
||||
# [/docs:create-mental-model]
|
||||
|
||||
# [docs:create-mental-model-with-id]
|
||||
# Create a mental model with a specific custom ID
|
||||
result_with_id = client.create_mental_model(
|
||||
bank_id=BANK_ID,
|
||||
name="Communication Policy",
|
||||
source_query="What are the team's communication guidelines?",
|
||||
id="communication-policy"
|
||||
)
|
||||
|
||||
print(f"Created with custom ID: {result_with_id.operation_id}")
|
||||
# [/docs:create-mental-model-with-id]
|
||||
|
||||
# Wait for the mental model to be created
|
||||
time.sleep(5)
|
||||
|
||||
|
|
|
|||
90
hindsight-docs/examples/api/mental-models.sh
Normal file
90
hindsight-docs/examples/api/mental-models.sh
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#!/bin/bash
|
||||
# Mental Models API examples for Hindsight CLI
|
||||
# Run: bash examples/api/mental-models.sh
|
||||
|
||||
set -e
|
||||
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
BANK_ID="mental-models-demo-bank"
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
hindsight bank create "$BANK_ID" --name "Mental Models Demo"
|
||||
hindsight memory retain "$BANK_ID" "The team prefers async communication via Slack"
|
||||
hindsight memory retain "$BANK_ID" "For urgent issues, use the #incidents channel"
|
||||
hindsight memory retain "$BANK_ID" "Weekly syncs happen every Monday at 10am"
|
||||
sleep 2
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:create-mental-model]
|
||||
# Create a mental model (runs reflect in background)
|
||||
hindsight mental-model create "$BANK_ID" \
|
||||
"Team Communication Preferences" \
|
||||
"How does the team prefer to communicate?"
|
||||
# [/docs:create-mental-model]
|
||||
|
||||
# [docs:create-mental-model-with-id]
|
||||
# Create a mental model with a specific custom ID
|
||||
hindsight mental-model create "$BANK_ID" \
|
||||
"Communication Policy" \
|
||||
"What are the team's communication guidelines?" \
|
||||
--id communication-policy
|
||||
# [/docs:create-mental-model-with-id]
|
||||
|
||||
sleep 5
|
||||
|
||||
# [docs:create-mental-model-with-trigger]
|
||||
# Create a mental model and get its ID for subsequent operations
|
||||
hindsight mental-model create "$BANK_ID" \
|
||||
"Project Status" \
|
||||
"What is the current project status?"
|
||||
# [/docs:create-mental-model-with-trigger]
|
||||
|
||||
sleep 5
|
||||
|
||||
# [docs:list-mental-models]
|
||||
# List all mental models in a bank
|
||||
hindsight mental-model list "$BANK_ID"
|
||||
# [/docs:list-mental-models]
|
||||
|
||||
# Get the first mental model ID for subsequent examples
|
||||
MENTAL_MODEL_ID=$(hindsight mental-model list "$BANK_ID" -o json | python3 -c "import sys,json; items=json.load(sys.stdin).get('items',[]); print(items[0]['id'] if items else '')" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$MENTAL_MODEL_ID" ]; then
|
||||
# [docs:get-mental-model]
|
||||
# Get a specific mental model
|
||||
hindsight mental-model get "$BANK_ID" "$MENTAL_MODEL_ID"
|
||||
# [/docs:get-mental-model]
|
||||
|
||||
# [docs:refresh-mental-model]
|
||||
# Refresh a mental model to update with current knowledge
|
||||
hindsight mental-model refresh "$BANK_ID" "$MENTAL_MODEL_ID"
|
||||
# [/docs:refresh-mental-model]
|
||||
|
||||
# [docs:update-mental-model]
|
||||
# Update a mental model's metadata
|
||||
hindsight mental-model update "$BANK_ID" "$MENTAL_MODEL_ID" \
|
||||
--name "Updated Team Communication Preferences"
|
||||
# [/docs:update-mental-model]
|
||||
|
||||
# [docs:get-mental-model-history]
|
||||
# Get the change history of a mental model
|
||||
hindsight mental-model history "$BANK_ID" "$MENTAL_MODEL_ID"
|
||||
# [/docs:get-mental-model-history]
|
||||
|
||||
# [docs:delete-mental-model]
|
||||
# Delete a mental model
|
||||
hindsight mental-model delete "$BANK_ID" "$MENTAL_MODEL_ID" -y
|
||||
# [/docs:delete-mental-model]
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/${BANK_ID}" > /dev/null
|
||||
|
||||
echo "mental-models.sh: All examples passed"
|
||||
217
hindsight-docs/examples/api/recall.go
Normal file
217
hindsight-docs/examples/api/recall.go
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("HINDSIGHT_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = "http://localhost:8888"
|
||||
}
|
||||
|
||||
cfg := hindsight.NewConfiguration()
|
||||
cfg.Servers = hindsight.ServerConfigurations{{URL: apiURL}}
|
||||
client := hindsight.NewAPIClient(cfg)
|
||||
ctx := context.Background()
|
||||
|
||||
// =============================================================================
|
||||
// Setup (not shown in docs)
|
||||
// =============================================================================
|
||||
for _, content := range []string{
|
||||
"Alice works at Google as a software engineer",
|
||||
"Alice loves hiking on weekends",
|
||||
"Bob is a data scientist who works with Alice",
|
||||
} {
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{{Content: content}},
|
||||
}).Execute()
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:recall-basic]
|
||||
response, _, _ := client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What does Alice do?",
|
||||
}).Execute()
|
||||
|
||||
// response.Results is a slice of RecallResult, each with:
|
||||
// - Id: fact ID
|
||||
// - Text: the extracted fact
|
||||
// - Type: "world", "experience", or "observation"
|
||||
// - Context: context label 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
|
||||
for _, r := range response.GetResults() {
|
||||
fmt.Println(r.GetText())
|
||||
}
|
||||
// [/docs:recall-basic]
|
||||
|
||||
// [docs:recall-with-options]
|
||||
budgetHigh := hindsight.HIGH
|
||||
maxTokens := int32(8000)
|
||||
traceTrue := true
|
||||
detailedResponse, _, _ := client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What does Alice do?",
|
||||
Types: []string{"world", "experience"},
|
||||
Budget: &budgetHigh,
|
||||
MaxTokens: &maxTokens,
|
||||
Trace: &traceTrue,
|
||||
}).Execute()
|
||||
|
||||
for _, r := range detailedResponse.GetResults() {
|
||||
fmt.Println("-", r.GetText())
|
||||
}
|
||||
// [/docs:recall-with-options]
|
||||
|
||||
// [docs:recall-world-only]
|
||||
// Only world facts (objective information)
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "Where does Alice work?",
|
||||
Types: []string{"world"},
|
||||
}).Execute()
|
||||
// [/docs:recall-world-only]
|
||||
|
||||
// [docs:recall-experience-only]
|
||||
// Only experience (conversations and events)
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What have I recommended?",
|
||||
Types: []string{"experience"},
|
||||
}).Execute()
|
||||
// [/docs:recall-experience-only]
|
||||
|
||||
// [docs:recall-observations-only]
|
||||
// Only observations (consolidated knowledge)
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What patterns have I learned?",
|
||||
Types: []string{"observation"},
|
||||
}).Execute()
|
||||
// [/docs:recall-observations-only]
|
||||
|
||||
// [docs:recall-source-facts]
|
||||
// Recall observations and include their source facts
|
||||
maxSFTokens := int32(4096)
|
||||
sfOpts := hindsight.SourceFactsIncludeOptions{MaxTokens: &maxSFTokens}
|
||||
obsResponse, _, _ := client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What patterns have I learned about Alice?",
|
||||
Types: []string{"observation"},
|
||||
Include: &hindsight.IncludeOptions{
|
||||
SourceFacts: *hindsight.NewNullableSourceFactsIncludeOptions(&sfOpts),
|
||||
},
|
||||
}).Execute()
|
||||
|
||||
for _, obs := range obsResponse.GetResults() {
|
||||
fmt.Printf("Observation: %s\n", obs.GetText())
|
||||
for _, factID := range obs.GetSourceFactIds() {
|
||||
if fact, ok := obsResponse.GetSourceFacts()[factID]; ok {
|
||||
fmt.Printf(" - [%s] %s\n", fact.GetType(), fact.GetText())
|
||||
}
|
||||
}
|
||||
}
|
||||
// [/docs:recall-source-facts]
|
||||
|
||||
// [docs:recall-budget-levels]
|
||||
budgetLow := hindsight.LOW
|
||||
// Quick lookup
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "Alice's email",
|
||||
Budget: &budgetLow,
|
||||
}).Execute()
|
||||
|
||||
// Deep exploration
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "How are Alice and Bob connected?",
|
||||
Budget: &budgetHigh,
|
||||
}).Execute()
|
||||
// [/docs:recall-budget-levels]
|
||||
|
||||
// [docs:recall-token-budget]
|
||||
// Fill up to 4K tokens of context with relevant memories
|
||||
mt4k := int32(4096)
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What do I know about Alice?",
|
||||
MaxTokens: &mt4k,
|
||||
}).Execute()
|
||||
|
||||
// Smaller budget for quick lookups
|
||||
mt500 := int32(500)
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "Alice's email",
|
||||
MaxTokens: &mt500,
|
||||
}).Execute()
|
||||
// [/docs:recall-token-budget]
|
||||
|
||||
// [docs:recall-with-tags]
|
||||
// Filter recall to only memories tagged for a specific user
|
||||
tagsMatch := "any"
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What feedback did the user give?",
|
||||
Tags: []string{"user:alice"},
|
||||
TagsMatch: &tagsMatch,
|
||||
}).Execute()
|
||||
// [/docs:recall-with-tags]
|
||||
|
||||
// [docs:recall-tags-strict]
|
||||
// Strict mode: only return memories that have matching tags (exclude untagged)
|
||||
tagsMatchStrict := "any_strict"
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What did the user say?",
|
||||
Tags: []string{"user:alice"},
|
||||
TagsMatch: &tagsMatchStrict,
|
||||
}).Execute()
|
||||
// [/docs:recall-tags-strict]
|
||||
|
||||
// [docs:recall-tags-all]
|
||||
// AND matching: require ALL specified tags to be present
|
||||
tagsMatchAll := "all_strict"
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "What bugs were reported?",
|
||||
Tags: []string{"user:alice", "bug-report"},
|
||||
TagsMatch: &tagsMatchAll,
|
||||
}).Execute()
|
||||
// [/docs:recall-tags-all]
|
||||
|
||||
// [docs:recall-tags-all-mode]
|
||||
// AND matching, includes untagged memories
|
||||
tagsMatchAllMode := "all"
|
||||
client.MemoryAPI.RecallMemories(ctx, "my-bank").
|
||||
RecallRequest(hindsight.RecallRequest{
|
||||
Query: "communication tools",
|
||||
Tags: []string{"user:alice", "team"},
|
||||
TagsMatch: &tagsMatchAllMode,
|
||||
}).Execute()
|
||||
// [/docs:recall-tags-all-mode]
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
req, _ := http.NewRequest("DELETE", fmt.Sprintf("%s/v1/default/banks/my-bank", apiURL), nil)
|
||||
http.DefaultClient.Do(req)
|
||||
|
||||
fmt.Println("recall.go: All examples passed")
|
||||
}
|
||||
|
|
@ -61,6 +61,88 @@ for (const r of detailedResponse.results) {
|
|||
// [/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?', {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,76 @@ hindsight memory recall my-bank "query" --trace
|
|||
# [/docs:recall-trace]
|
||||
|
||||
|
||||
# [docs:recall-budget-levels]
|
||||
# Quick lookup
|
||||
hindsight memory recall my-bank "Alice's email" --budget low
|
||||
|
||||
# Deep exploration
|
||||
hindsight memory recall my-bank "How are Alice and Bob connected?" --budget high
|
||||
# [/docs:recall-budget-levels]
|
||||
|
||||
|
||||
# [docs:recall-token-budget]
|
||||
# Fill up to 4K tokens of context with relevant memories
|
||||
hindsight memory recall my-bank "What do I know about Alice?" --max-tokens 4096
|
||||
|
||||
# Smaller budget for quick lookups
|
||||
hindsight memory recall my-bank "Alice's email" --max-tokens 500
|
||||
# [/docs:recall-token-budget]
|
||||
|
||||
|
||||
# [docs:recall-source-facts]
|
||||
# Recall observations with source facts
|
||||
hindsight memory recall my-bank "What patterns have I learned about Alice?" \
|
||||
--fact-type observation
|
||||
# [/docs:recall-source-facts]
|
||||
|
||||
|
||||
# [docs:recall-with-tags]
|
||||
# Filter recall to only memories tagged for a specific user
|
||||
hindsight memory 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)
|
||||
hindsight memory recall my-bank "What did the user say?" \
|
||||
--tags "user:alice" --tags-match any_strict
|
||||
# [/docs:recall-tags-strict]
|
||||
|
||||
|
||||
# [docs:recall-tags-all]
|
||||
# AND matching: require ALL specified tags to be present
|
||||
hindsight memory recall my-bank "What bugs were reported?" \
|
||||
--tags "user:alice,bug-report" --tags-match all_strict
|
||||
# [/docs:recall-tags-all]
|
||||
|
||||
|
||||
# [docs:recall-tags-any]
|
||||
hindsight memory recall my-bank "communication preferences" \
|
||||
--tags "user:alice" --tags-match any
|
||||
# [/docs:recall-tags-any]
|
||||
|
||||
|
||||
# [docs:recall-tags-any-strict]
|
||||
hindsight memory recall my-bank "communication preferences" \
|
||||
--tags "user:alice" --tags-match any_strict
|
||||
# [/docs:recall-tags-any-strict]
|
||||
|
||||
|
||||
# [docs:recall-tags-all-mode]
|
||||
hindsight memory recall my-bank "communication tools" \
|
||||
--tags "user:alice,team" --tags-match all
|
||||
# [/docs:recall-tags-all-mode]
|
||||
|
||||
|
||||
# [docs:recall-tags-all-strict]
|
||||
hindsight memory recall my-bank "communication tools" \
|
||||
--tags "user:alice,team" --tags-match all_strict
|
||||
# [/docs:recall-tags-all-strict]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
|
|
|
|||
155
hindsight-docs/examples/api/reflect.go
Normal file
155
hindsight-docs/examples/api/reflect.go
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("HINDSIGHT_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = "http://localhost:8888"
|
||||
}
|
||||
|
||||
cfg := hindsight.NewConfiguration()
|
||||
cfg.Servers = hindsight.ServerConfigurations{{URL: apiURL}}
|
||||
client := hindsight.NewAPIClient(cfg)
|
||||
ctx := context.Background()
|
||||
|
||||
// =============================================================================
|
||||
// Setup (not shown in docs)
|
||||
// =============================================================================
|
||||
for _, content := range []string{
|
||||
"Alice works at Google as a software engineer",
|
||||
"Alice has been working there for 5 years",
|
||||
"Alice recently got promoted to senior engineer",
|
||||
} {
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{{Content: content}},
|
||||
}).Execute()
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:reflect-basic]
|
||||
client.MemoryAPI.Reflect(ctx, "my-bank").
|
||||
ReflectRequest(hindsight.ReflectRequest{
|
||||
Query: "What should I know about Alice?",
|
||||
}).Execute()
|
||||
// [/docs:reflect-basic]
|
||||
|
||||
// [docs:reflect-with-params]
|
||||
budgetMid := hindsight.MID
|
||||
client.MemoryAPI.Reflect(ctx, "my-bank").
|
||||
ReflectRequest(hindsight.ReflectRequest{
|
||||
Query: "We're considering a hybrid work policy. What do you think about remote work?",
|
||||
Budget: &budgetMid,
|
||||
}).Execute()
|
||||
// [/docs:reflect-with-params]
|
||||
|
||||
// [docs:reflect-with-context]
|
||||
// Context is passed to the LLM to help it understand the situation
|
||||
ctxText := "We're in a budget review meeting discussing Q4 spending"
|
||||
client.MemoryAPI.Reflect(ctx, "my-bank").
|
||||
ReflectRequest(hindsight.ReflectRequest{
|
||||
Query: "What do you think about the proposal?",
|
||||
Context: *hindsight.NewNullableString(&ctxText),
|
||||
}).Execute()
|
||||
// [/docs:reflect-with-context]
|
||||
|
||||
// [docs:reflect-disposition]
|
||||
// Create a bank with specific disposition
|
||||
skepticism := int32(5)
|
||||
literalism := int32(4)
|
||||
empathy := int32(2)
|
||||
mission := "I am a risk-aware financial advisor"
|
||||
client.BanksAPI.CreateOrUpdateBank(ctx, "cautious-advisor").
|
||||
CreateBankRequest(hindsight.CreateBankRequest{
|
||||
Name: *hindsight.NewNullableString(hindsight.PtrString("Cautious Advisor")),
|
||||
ReflectMission: *hindsight.NewNullableString(&mission),
|
||||
DispositionSkepticism: *hindsight.NewNullableInt32(&skepticism),
|
||||
DispositionLiteralism: *hindsight.NewNullableInt32(&literalism),
|
||||
DispositionEmpathy: *hindsight.NewNullableInt32(&empathy),
|
||||
}).Execute()
|
||||
|
||||
// Reflect responses will reflect this disposition
|
||||
client.MemoryAPI.Reflect(ctx, "cautious-advisor").
|
||||
ReflectRequest(hindsight.ReflectRequest{
|
||||
Query: "Should I invest in crypto?",
|
||||
}).Execute()
|
||||
// Response will likely emphasize risks and caution
|
||||
// [/docs:reflect-disposition]
|
||||
|
||||
// [docs:reflect-sources]
|
||||
// include.facts enables the based_on field in the response
|
||||
sourcesResponse, _, _ := client.MemoryAPI.Reflect(ctx, "my-bank").
|
||||
ReflectRequest(hindsight.ReflectRequest{
|
||||
Query: "Tell me about Alice",
|
||||
Include: &hindsight.ReflectIncludeOptions{
|
||||
Facts: map[string]interface{}{}, // empty map enables fact inclusion
|
||||
},
|
||||
}).Execute()
|
||||
|
||||
fmt.Println("Response:", sourcesResponse.GetText())
|
||||
fmt.Println("\nBased on:")
|
||||
if basedOn := sourcesResponse.GetBasedOn(); basedOn.Memories != nil {
|
||||
for _, fact := range basedOn.GetMemories() {
|
||||
fmt.Printf(" - [%s] %s\n", fact.GetType(), fact.GetText())
|
||||
}
|
||||
}
|
||||
// [/docs:reflect-sources]
|
||||
|
||||
// [docs:reflect-with-tags]
|
||||
// Filter reflection to only consider memories for a specific user
|
||||
tagsMatch := "any_strict"
|
||||
client.MemoryAPI.Reflect(ctx, "my-bank").
|
||||
ReflectRequest(hindsight.ReflectRequest{
|
||||
Query: "What does this user think about our product?",
|
||||
Tags: []string{"user:alice"},
|
||||
TagsMatch: &tagsMatch,
|
||||
}).Execute()
|
||||
// [/docs:reflect-with-tags]
|
||||
|
||||
// [docs:reflect-structured-output]
|
||||
// Define JSON schema for structured output
|
||||
responseSchema := map[string]interface{}{
|
||||
"type": "object",
|
||||
"properties": map[string]interface{}{
|
||||
"recommendation": map[string]interface{}{"type": "string"},
|
||||
"confidence": map[string]interface{}{"type": "string", "enum": []string{"low", "medium", "high"}},
|
||||
"key_factors": map[string]interface{}{"type": "array", "items": map[string]interface{}{"type": "string"}},
|
||||
"risks": map[string]interface{}{"type": "array", "items": map[string]interface{}{"type": "string"}},
|
||||
},
|
||||
"required": []string{"recommendation", "confidence", "key_factors"},
|
||||
}
|
||||
|
||||
structuredResponse, _, _ := client.MemoryAPI.Reflect(ctx, "my-bank").
|
||||
ReflectRequest(hindsight.ReflectRequest{
|
||||
Query: "Should we hire Alice for the ML team lead position?",
|
||||
ResponseSchema: responseSchema,
|
||||
}).Execute()
|
||||
|
||||
// Access structured output
|
||||
if out := structuredResponse.GetStructuredOutput(); out != nil {
|
||||
fmt.Println("Recommendation:", out["recommendation"])
|
||||
fmt.Println("Key factors:", out["key_factors"])
|
||||
}
|
||||
// [/docs:reflect-structured-output]
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
for _, bankID := range []string{"my-bank", "cautious-advisor"} {
|
||||
req, _ := http.NewRequest("DELETE", fmt.Sprintf("%s/v1/default/banks/%s", apiURL, bankID), nil)
|
||||
http.DefaultClient.Do(req)
|
||||
}
|
||||
|
||||
fmt.Println("reflect.go: All examples passed")
|
||||
}
|
||||
|
|
@ -60,16 +60,27 @@ const advisorResponse = await client.reflect('cautious-advisor', 'Should I inves
|
|||
|
||||
|
||||
// [docs:reflect-sources]
|
||||
const sourcesResponse = await client.reflect('my-bank', 'Tell me about Alice');
|
||||
const sourcesResponse = await client.reflect('my-bank', 'Tell me about Alice', {
|
||||
includeFacts: true
|
||||
});
|
||||
|
||||
console.log('Response:', sourcesResponse.text);
|
||||
console.log('\nBased on:');
|
||||
for (const fact of sourcesResponse.based_on || []) {
|
||||
for (const fact of (sourcesResponse.based_on?.memories || [])) {
|
||||
console.log(` - [${fact.type}] ${fact.text}`);
|
||||
}
|
||||
// [/docs:reflect-sources]
|
||||
|
||||
|
||||
// [docs:reflect-with-tags]
|
||||
// Filter reflect to only use memories tagged for a specific user
|
||||
await client.reflect('my-bank', 'What feedback did the user give?', {
|
||||
tags: ['user:alice'],
|
||||
tagsMatch: 'any_strict'
|
||||
});
|
||||
// [/docs:reflect-with-tags]
|
||||
|
||||
|
||||
// [docs:reflect-structured-output]
|
||||
// Define JSON schema directly
|
||||
const responseSchema = {
|
||||
|
|
|
|||
|
|
@ -26,9 +26,29 @@ hindsight memory reflect my-bank "Should I learn Python?" --context "career advi
|
|||
# [/docs:reflect-with-context]
|
||||
|
||||
|
||||
# [docs:reflect-high-budget]
|
||||
hindsight memory reflect my-bank "Summarize my week" --budget high
|
||||
# [/docs:reflect-high-budget]
|
||||
# [docs:reflect-with-params]
|
||||
hindsight memory reflect my-bank "Summarize my week" --budget high --max-tokens 8192
|
||||
# [/docs:reflect-with-params]
|
||||
|
||||
|
||||
# [docs:reflect-disposition]
|
||||
hindsight bank set-config my-bank \
|
||||
--disposition-skepticism 5 \
|
||||
--disposition-literalism 4 \
|
||||
--disposition-empathy 2
|
||||
hindsight memory reflect my-bank "Should I invest in crypto?"
|
||||
# [/docs:reflect-disposition]
|
||||
|
||||
|
||||
# [docs:reflect-sources]
|
||||
hindsight memory reflect my-bank "Tell me about Alice" --include-facts
|
||||
# [/docs:reflect-sources]
|
||||
|
||||
|
||||
# [docs:reflect-with-tags]
|
||||
hindsight memory reflect my-bank "What feedback did the user give?" \
|
||||
--tags "user:alice" --tags-match any_strict
|
||||
# [/docs:reflect-with-tags]
|
||||
|
||||
|
||||
# [docs:reflect-structured-output]
|
||||
|
|
|
|||
137
hindsight-docs/examples/api/retain.go
Normal file
137
hindsight-docs/examples/api/retain.go
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
hindsight "github.com/vectorize-io/hindsight/hindsight-clients/go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("HINDSIGHT_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = "http://localhost:8888"
|
||||
}
|
||||
|
||||
cfg := hindsight.NewConfiguration()
|
||||
cfg.Servers = hindsight.ServerConfigurations{{URL: apiURL}}
|
||||
client := hindsight.NewAPIClient(cfg)
|
||||
ctx := context.Background()
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:retain-basic]
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{Content: "Alice works at Google as a software engineer"},
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:retain-basic]
|
||||
|
||||
// [docs:retain-conversation]
|
||||
// Retain an entire conversation as a single document.
|
||||
conversation := "Alice (2024-03-15T09:00:00Z): Hi Bob! Did you end up going to the doctor last week?\n" +
|
||||
"Bob (2024-03-15T09:01:00Z): Yes, finally. Turns out I have a mild peanut allergy.\n" +
|
||||
"Alice (2024-03-15T09:02:00Z): Oh no! Are you okay?\n" +
|
||||
"Bob (2024-03-15T09:03:00Z): Yeah, nothing serious. Just need to carry an antihistamine.\n" +
|
||||
"Alice (2024-03-15T09:04:00Z): Good to know. We'll avoid peanuts at the team lunch."
|
||||
|
||||
docID := "chat-2024-03-15-alice-bob"
|
||||
context_ := "team chat"
|
||||
ts := "2024-03-15T09:04:00Z"
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{
|
||||
Content: conversation,
|
||||
Context: *hindsight.NewNullableString(&context_),
|
||||
DocumentId: *hindsight.NewNullableString(&docID),
|
||||
Timestamp: *hindsight.NewNullableTimestamp(&hindsight.Timestamp{
|
||||
String: &ts,
|
||||
}),
|
||||
},
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:retain-conversation]
|
||||
|
||||
// [docs:retain-with-context]
|
||||
ctxLabel := "career update"
|
||||
ts2 := "2024-03-15T10:00:00Z"
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{
|
||||
Content: "Alice got promoted to senior engineer",
|
||||
Context: *hindsight.NewNullableString(&ctxLabel),
|
||||
Timestamp: *hindsight.NewNullableTimestamp(&hindsight.Timestamp{
|
||||
String: &ts2,
|
||||
}),
|
||||
},
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:retain-with-context]
|
||||
|
||||
// [docs:retain-batch]
|
||||
doc1 := "conversation_001_msg_1"
|
||||
doc2 := "conversation_001_msg_2"
|
||||
doc3 := "conversation_001_msg_3"
|
||||
ctx1 := "career"
|
||||
ctx2 := "relationship"
|
||||
client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{Content: "Alice works at Google", Context: *hindsight.NewNullableString(&ctx1), DocumentId: *hindsight.NewNullableString(&doc1)},
|
||||
{Content: "Bob is a data scientist at Meta", Context: *hindsight.NewNullableString(&ctx1), DocumentId: *hindsight.NewNullableString(&doc2)},
|
||||
{Content: "Alice and Bob are friends", Context: *hindsight.NewNullableString(&ctx2), DocumentId: *hindsight.NewNullableString(&doc3)},
|
||||
},
|
||||
}).Execute()
|
||||
// [/docs:retain-batch]
|
||||
|
||||
// [docs:retain-async]
|
||||
// Start async ingestion (returns immediately)
|
||||
asyncTrue := true
|
||||
largeDoc1 := "large-doc-1"
|
||||
largeDoc2 := "large-doc-2"
|
||||
retainResp, _, _ := client.MemoryAPI.RetainMemories(ctx, "my-bank").
|
||||
RetainRequest(hindsight.RetainRequest{
|
||||
Items: []hindsight.MemoryItem{
|
||||
{Content: "Large batch item 1", DocumentId: *hindsight.NewNullableString(&largeDoc1)},
|
||||
{Content: "Large batch item 2", DocumentId: *hindsight.NewNullableString(&largeDoc2)},
|
||||
},
|
||||
Async: &asyncTrue,
|
||||
}).Execute()
|
||||
|
||||
// Check if it was processed asynchronously
|
||||
fmt.Println("Async:", retainResp.GetAsync())
|
||||
// [/docs:retain-async]
|
||||
|
||||
// [docs:retain-files]
|
||||
// Open a file and upload it — Hindsight converts it to text and extracts memories.
|
||||
// Supports: PDF, DOCX, PPTX, XLSX, images (OCR), audio (transcription), and text formats.
|
||||
f, err := os.Open("../../hindsight-docs/examples/api/sample.pdf")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fileResp, _, _ := client.FilesAPI.FileRetain(ctx, "my-bank").
|
||||
Files([]*os.File{f}).
|
||||
Request(`{"files_metadata": [{"context": "quarterly report"}]}`).
|
||||
Execute()
|
||||
fmt.Println("Operation IDs:", fileResp.GetOperationIds()) // Track processing via the operations endpoint
|
||||
// [/docs:retain-files]
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
req, _ := http.NewRequest("DELETE", fmt.Sprintf("%s/v1/default/banks/my-bank", apiURL), nil)
|
||||
http.DefaultClient.Do(req)
|
||||
|
||||
fmt.Println("retain.go: All examples passed")
|
||||
}
|
||||
|
|
@ -85,6 +85,21 @@ console.log(result.operation_ids); // Track processing via the operations endpo
|
|||
// [/docs:retain-files]
|
||||
|
||||
|
||||
// [docs:retain-files-batch]
|
||||
// Upload multiple files with per-file metadata (up to 10 files per request)
|
||||
const batchResult = await client.retainFiles('my-bank', [
|
||||
new File([pdfBytes], 'report.pdf'),
|
||||
new File([pdfBytes], 'notes.pdf'),
|
||||
], {
|
||||
filesMetadata: [
|
||||
{ context: 'quarterly report', document_id: 'q1-report', tags: ['project:alpha'] },
|
||||
{ context: 'meeting notes', document_id: 'q1-notes', tags: ['project:alpha'] },
|
||||
]
|
||||
});
|
||||
console.log(batchResult.operation_ids); // One operation ID per file
|
||||
// [/docs:retain-files-batch]
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
|
|
|
|||
|
|
@ -25,12 +25,37 @@ hindsight memory retain my-bank "Alice works at Google as a software engineer"
|
|||
# [/docs:retain-basic]
|
||||
|
||||
|
||||
# [docs:retain-conversation]
|
||||
# Retain an entire conversation as a single document.
|
||||
CONVERSATION="Alice (2024-03-15T09:00:00Z): Hi Bob! Did you end up going to the doctor last week?
|
||||
Bob (2024-03-15T09:01:00Z): Yes, finally. Turns out I have a mild peanut allergy.
|
||||
Alice (2024-03-15T09:02:00Z): Oh no! Are you okay?
|
||||
Bob (2024-03-15T09:03:00Z): Yeah, nothing serious. Just need to carry an antihistamine.
|
||||
Alice (2024-03-15T09:04:00Z): Good to know. We'll avoid peanuts at the team lunch."
|
||||
|
||||
hindsight memory retain my-bank "$CONVERSATION" \
|
||||
--context "team chat" \
|
||||
--doc-id "chat-2024-03-15-alice-bob"
|
||||
# [/docs:retain-conversation]
|
||||
|
||||
|
||||
# [docs:retain-with-context]
|
||||
hindsight memory retain my-bank "Alice got promoted" \
|
||||
--context "career update"
|
||||
# [/docs:retain-with-context]
|
||||
|
||||
|
||||
# [docs:retain-batch]
|
||||
# Batch ingestion via individual retain calls (CLI processes items one at a time)
|
||||
hindsight memory retain my-bank "Alice works at Google" \
|
||||
--context "career" --doc-id "conversation_001_msg_1"
|
||||
hindsight memory retain my-bank "Bob is a data scientist at Meta" \
|
||||
--context "career" --doc-id "conversation_001_msg_2"
|
||||
hindsight memory retain my-bank "Alice and Bob are friends" \
|
||||
--context "relationship" --doc-id "conversation_001_msg_3"
|
||||
# [/docs:retain-batch]
|
||||
|
||||
|
||||
# [docs:retain-async]
|
||||
hindsight memory retain my-bank "Meeting notes" --async
|
||||
# [/docs:retain-async]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"build": "node scripts/check-code-parity.mjs && docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
|
|
|
|||
128
hindsight-docs/scripts/check-code-parity.mjs
Normal file
128
hindsight-docs/scripts/check-code-parity.mjs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Validates that every "language" Tabs block in MDX docs has all 4 required variants:
|
||||
* Python, Node.js, CLI, Go.
|
||||
*
|
||||
* A Tabs block is considered a "language" block if it contains at least one TabItem
|
||||
* with value "python", "node", "cli", or "go".
|
||||
*
|
||||
* Run: node scripts/check-code-parity.mjs
|
||||
*/
|
||||
|
||||
import { readFileSync, readdirSync, statSync } from 'node:fs';
|
||||
import { join, relative } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const docsRoot = join(__dirname, '..');
|
||||
const REQUIRED_TABS = new Set(['python', 'node', 'cli', 'go']);
|
||||
|
||||
const IGNORED_PATHS = [
|
||||
'node_modules',
|
||||
'build',
|
||||
'.docusaurus',
|
||||
'versioned_docs', // skip versioned docs
|
||||
];
|
||||
|
||||
/**
|
||||
* Recursively find all .mdx files under a directory.
|
||||
*/
|
||||
function findMdxFiles(dir) {
|
||||
const results = [];
|
||||
for (const entry of readdirSync(dir)) {
|
||||
if (IGNORED_PATHS.includes(entry)) continue;
|
||||
const full = join(dir, entry);
|
||||
const stat = statSync(full);
|
||||
if (stat.isDirectory()) {
|
||||
results.push(...findMdxFiles(full));
|
||||
} else if (entry.endsWith('.mdx') || entry.endsWith('.md')) {
|
||||
results.push(full);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a single MDX file and return all violations.
|
||||
* A violation is a Tabs block that has at least one language tab but is missing
|
||||
* one or more of the 4 required language variants.
|
||||
*/
|
||||
function checkFile(filePath) {
|
||||
const content = readFileSync(filePath, 'utf8');
|
||||
const violations = [];
|
||||
|
||||
// Split content into Tabs blocks.
|
||||
// Strategy: find <Tabs> ... </Tabs> sections and scan for TabItem values.
|
||||
// We use a simple line-by-line state machine.
|
||||
const lines = content.split('\n');
|
||||
let inTabs = false;
|
||||
let tabsStartLine = -1;
|
||||
let currentTabValues = new Set();
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
|
||||
if (!inTabs) {
|
||||
// Look for opening <Tabs> tag (not <TabItem>)
|
||||
if (/^\s*<Tabs[\s>]/.test(line) && !/<\/Tabs/.test(line)) {
|
||||
inTabs = true;
|
||||
tabsStartLine = i + 1; // 1-indexed
|
||||
currentTabValues = new Set();
|
||||
}
|
||||
} else {
|
||||
// Inside a Tabs block — look for </Tabs> or nested TabItem values
|
||||
if (/^\s*<\/Tabs\s*>/.test(line)) {
|
||||
// End of Tabs block — check if it's a language block
|
||||
const hasLanguageTab = [...currentTabValues].some(v => REQUIRED_TABS.has(v));
|
||||
if (hasLanguageTab) {
|
||||
const missing = [...REQUIRED_TABS].filter(t => !currentTabValues.has(t));
|
||||
if (missing.length > 0) {
|
||||
violations.push({
|
||||
line: tabsStartLine,
|
||||
found: [...currentTabValues].filter(v => REQUIRED_TABS.has(v)),
|
||||
missing,
|
||||
});
|
||||
}
|
||||
}
|
||||
inTabs = false;
|
||||
currentTabValues = new Set();
|
||||
} else {
|
||||
// Look for TabItem value attributes
|
||||
// Matches: <TabItem value="python" or <TabItem value='cli'
|
||||
const match = line.match(/TabItem[^>]*value=["']([^"']+)["']/);
|
||||
if (match) {
|
||||
currentTabValues.add(match[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return violations;
|
||||
}
|
||||
|
||||
// ─── Main ────────────────────────────────────────────────────────────────────
|
||||
|
||||
const mdxFiles = findMdxFiles(docsRoot);
|
||||
let totalViolations = 0;
|
||||
|
||||
for (const filePath of mdxFiles) {
|
||||
const violations = checkFile(filePath);
|
||||
if (violations.length > 0) {
|
||||
const rel = relative(docsRoot, filePath);
|
||||
for (const v of violations) {
|
||||
console.error(
|
||||
`[code-parity] ${rel}:${v.line} — Tabs block missing language tabs: ${v.missing.join(', ')} (found: ${v.found.join(', ')})`
|
||||
);
|
||||
}
|
||||
totalViolations += violations.length;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalViolations > 0) {
|
||||
console.error(`\n[code-parity] ❌ Found ${totalViolations} Tabs block(s) missing required language variants.`);
|
||||
console.error('[code-parity] Every Tabs block with language tabs must include: python, node, cli, go');
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(`[code-parity] ✅ All ${mdxFiles.length} docs files pass 4-tab parity check.`);
|
||||
}
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"hindsight-clients/typescript": {
|
||||
"name": "@vectorize-io/hindsight-client",
|
||||
"version": "0.4.18",
|
||||
"version": "0.4.19",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "0.88.0",
|
||||
|
|
@ -293,7 +293,7 @@
|
|||
},
|
||||
"hindsight-control-plane": {
|
||||
"name": "@vectorize-io/hindsight-control-plane",
|
||||
"version": "0.4.18",
|
||||
"version": "0.4.19",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-alert-dialog": "^1.1.15",
|
||||
|
|
|
|||
Loading…
Reference in a new issue