Compare commits

...
11 Commits
Author SHA1 Message Date
DK09876 e521914f0f Fix example scripts: remove non-existent API attributes
- recall.py: remove .weight, fix entities iteration (dict not list)
- retain.mjs: remove result.async check
2025-12-17 12:14:43 -07:00
DK09876 7cb469ff75 Fix opinions.py: use actual API attributes instead of non-existent ones 2025-12-17 11:40:55 -07:00
DK09876 9118e7b4cb Fix main-methods.py: RecallResult and ReflectFact don't have weight attribute 2025-12-17 11:18:09 -07:00
DK09876 841a66f375 Fix async API client usage in documents.py example 2025-12-17 11:11:46 -07:00
DK09876 eb06adb2be Add documentation code validation CI job
- Use uv sync + uv run pattern (matches existing CI)
- Add requests to test dependencies for cleanup scripts
2025-12-17 10:48:38 -07:00
DK09876 3913788fd8 Fix: run cd in subshell so install runs from repo root 2025-12-17 10:40:10 -07:00
DK09876 6ea02eb023 Fix: use explicit shell expansion for wheel install 2025-12-17 10:35:01 -07:00
DK09876 55154384f6 Fix wheel path - uv build outputs to repo root dist/ 2025-12-17 10:24:52 -07:00
DK09876 19e4e2d635 Fix CI issue 2025-12-17 10:20:15 -07:00
DK09876 8f2396f04a Fix wheel glob expansion in test-doc-examples CI job 2025-12-17 10:15:13 -07:00
DK09876 bffc0ee0d0 Add documentation code validation system
- Create runnable example scripts in examples/api/ (19 files)
- Add CodeSnippet component for extracting marked sections
- Add raw-loader dependency for importing source files
- Create sample retain-new.mdx showing new approach
- Add README documenting coverage and gaps
2025-12-17 10:06:53 -07:00
28 changed files with 1931 additions and 5 deletions
+93 -1
View File
@@ -495,4 +495,96 @@ jobs:
- name: Run tests
working-directory: ./hindsight-integrations/litellm
run: uv run pytest tests -v
run: uv run pytest tests -v
test-doc-examples:
runs-on: ubuntu-latest
env:
HINDSIGHT_API_LLM_PROVIDER: groq
HINDSIGHT_API_LLM_API_KEY: ${{ secrets.GROQ_API_KEY }}
HINDSIGHT_API_LLM_MODEL: openai/gpt-oss-20b
HINDSIGHT_API_URL: http://localhost:8888
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
UV_INDEX: pytorch=https://download.pytorch.org/whl/cpu
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
prune-cache: false
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: ".python-version"
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: package-lock.json
- name: Build and install API
working-directory: ./hindsight-api
run: |
uv build
uv sync --no-install-project --index-strategy unsafe-best-match
- name: Install Python client dependencies
working-directory: ./hindsight-clients/python
run: uv sync --extra test --index-strategy unsafe-best-match
- name: Install TypeScript client
run: |
npm ci --workspace=hindsight-clients/typescript
npm run build --workspace=hindsight-clients/typescript
- name: Create .env file
run: |
cat > .env << EOF
HINDSIGHT_API_LLM_PROVIDER=${{ env.HINDSIGHT_API_LLM_PROVIDER }}
HINDSIGHT_API_LLM_API_KEY=${{ env.HINDSIGHT_API_LLM_API_KEY }}
HINDSIGHT_API_LLM_MODEL=${{ env.HINDSIGHT_API_LLM_MODEL }}
EOF
- name: Start API server
run: |
./scripts/dev/start-api.sh > /tmp/api-server.log 2>&1 &
echo "Waiting for API server to be ready..."
for i in {1..60}; do
if curl -sf http://localhost:8888/health > /dev/null 2>&1; then
echo "API server is ready after ${i}s"
break
fi
if [ $i -eq 60 ]; then
echo "API server failed to start after 60s"
cat /tmp/api-server.log
exit 1
fi
sleep 1
done
- name: Run Python doc examples
working-directory: ./hindsight-clients/python
run: |
for f in ../../hindsight-docs/examples/api/*.py; do
echo "Running $f..."
uv run python "$f"
done
- name: Run Node.js doc examples
run: |
for f in hindsight-docs/examples/api/*.mjs; do
echo "Running $f..."
node "$f"
done
- name: Show API server logs
if: always()
run: |
echo "=== API Server Logs ==="
cat /tmp/api-server.log || echo "No API server log found"
+1
View File
@@ -20,6 +20,7 @@ dependencies = [
test = [
"pytest>=7.0.0",
"pytest-asyncio>=0.21.0",
"requests>=2.28.0",
]
[build-system]
@@ -0,0 +1,71 @@
---
sidebar_position: 2
---
# Ingest Data (New Format)
This is a demo of the new code snippet approach. Code examples are pulled from executable script files.
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeSnippet from '@site/src/components/CodeSnippet';
{/* Import raw source files */}
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';
:::tip How This Works
The code examples below are extracted from actual runnable script files in `examples/api/`.
When CI runs these scripts, it validates the documentation is correct.
:::
## Store a Single Memory
<Tabs>
<TabItem value="python" label="Python">
<CodeSnippet code={retainPy} section="retain-basic" language="python" />
</TabItem>
<TabItem value="node" label="Node.js">
<CodeSnippet code={retainMjs} section="retain-basic" language="javascript" />
</TabItem>
<TabItem value="cli" label="CLI">
<CodeSnippet code={retainSh} section="retain-basic" language="bash" />
</TabItem>
</Tabs>
## Store with Context
<Tabs>
<TabItem value="python" label="Python">
<CodeSnippet code={retainPy} section="retain-with-context" language="python" />
</TabItem>
<TabItem value="node" label="Node.js">
<CodeSnippet code={retainMjs} section="retain-with-context" language="javascript" />
</TabItem>
<TabItem value="cli" label="CLI">
<CodeSnippet code={retainSh} section="retain-with-context" language="bash" />
</TabItem>
</Tabs>
## Batch Ingestion
<Tabs>
<TabItem value="python" label="Python">
<CodeSnippet code={retainPy} section="retain-batch" language="python" />
</TabItem>
<TabItem value="node" label="Node.js">
<CodeSnippet code={retainMjs} section="retain-batch" language="javascript" />
</TabItem>
</Tabs>
## Async Ingestion
<Tabs>
<TabItem value="python" label="Python">
<CodeSnippet code={retainPy} section="retain-async" language="python" />
</TabItem>
<TabItem value="node" label="Node.js">
<CodeSnippet code={retainMjs} section="retain-async" language="javascript" />
</TabItem>
</Tabs>
+82
View File
@@ -0,0 +1,82 @@
# API Documentation Examples
This directory contains runnable example scripts that serve as the source of truth for code samples in the documentation.
## How It Works
1. **Scripts are runnable** - Each file can be executed as a smoke test
2. **Markers define sections** - Code between `# [docs:section-name]` and `# [/docs:section-name]` markers is extracted
3. **Docs import at build time** - MDX files use `raw-loader` to import scripts, then `CodeSnippet` extracts marked sections
## File Structure
| File | Documentation | Description |
|------|---------------|-------------|
| `quickstart.py/mjs/sh` | quickstart.md | Getting started examples |
| `retain.py/mjs/sh` | retain.md | Memory ingestion examples |
| `recall.py/mjs/sh` | recall.md | Memory retrieval examples |
| `reflect.py/mjs/sh` | reflect.md | AI reflection examples |
| `memory-banks.py/mjs` | memory-banks.md | Bank management examples |
| `documents.py/mjs` | documents.md | Document CRUD examples |
| `opinions.py` | opinions.md | Opinion management examples |
| `main-methods.py` | main-methods.md | Core method examples |
| `cli-reference.sh` | cli.md | CLI command examples |
## Running Examples
```bash
# Run all Python examples
for f in *.py; do python "$f"; done
# Run all Node.js examples
for f in *.mjs; do node "$f"; done
# Run all CLI examples
for f in *.sh; do bash "$f"; done
```
Requires a running Hindsight server at `http://localhost:8888` (or set `HINDSIGHT_API_URL`).
## What's NOT Covered
### 1. OpenAPI Auto-Generated Docs (`/api-reference/*`)
These pages are generated directly from the OpenAPI specification. The spec itself is the source of truth, and the generated docs reflect it automatically. No manual code examples to validate.
### 2. Interactive CLI Commands
| Command | Reason |
|---------|--------|
| `hindsight configure` | Requires interactive user input (prompts for API URL, credentials) |
| `hindsight configure --show` | Displays sensitive configuration, not suitable for automated tests |
### 3. Installation/Setup Instructions
Documentation sections covering `pip install`, `npm install`, or system setup are instructions, not executable code samples. These are validated by the CI environment setup itself.
### 4. Error Handling Examples
Some docs show error responses (e.g., "what happens when bank doesn't exist"). These require intentionally broken states that would fail smoke tests. Error behavior is covered by unit tests instead.
## Adding New Examples
1. Create or edit the appropriate script file
2. Add markers around the new code section:
```python
# [docs:my-new-section]
client.some_method(...)
# [/docs:my-new-section]
```
3. Reference in the MDX file:
```mdx
import myScript from '!!raw-loader!@site/examples/api/my-script.py';
<CodeSnippet code={myScript} section="my-new-section" language="python" />
```
4. Run the script locally to verify it works
## Marker Format
- **Python/Bash**: `# [docs:section-name]` / `# [/docs:section-name]`
- **JavaScript**: `// [docs:section-name]` / `// [/docs:section-name]`
Section names should be kebab-case and descriptive (e.g., `retain-with-context`, `recall-basic`).
+209
View File
@@ -0,0 +1,209 @@
#!/bin/bash
# CLI Reference examples for Hindsight
# Tests all documented CLI commands and flags
# Run: bash examples/api/cli-reference.sh
set -e
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
BANK_ID="cli-test-bank"
DOC_ID="test-document-001"
# =============================================================================
# Setup
# =============================================================================
hindsight configure --api-url "$HINDSIGHT_URL"
# Create test data with a known document ID
hindsight memory retain "$BANK_ID" "Alice works at Google as a software engineer" --document-id "$DOC_ID"
hindsight memory retain "$BANK_ID" "Bob is a data scientist who collaborates with Alice" --document-id "$DOC_ID"
hindsight memory retain "$BANK_ID" "Alice and Bob work on machine learning projects"
# Wait a moment for processing
sleep 2
# =============================================================================
# Configuration (cli.md - Configuration section)
# =============================================================================
# [docs:cli-configure]
hindsight configure --api-url http://localhost:8888
# [/docs:cli-configure]
# =============================================================================
# Core Memory Commands (cli.md - Core Commands section)
# =============================================================================
# [docs:cli-retain-basic]
hindsight memory retain $BANK_ID "Alice works at Google as a software engineer"
# [/docs:cli-retain-basic]
# [docs:cli-retain-context]
hindsight memory retain $BANK_ID "Bob loves hiking" --context "hobby discussion"
# [/docs:cli-retain-context]
# [docs:cli-retain-async]
hindsight memory retain $BANK_ID "Meeting notes" --async
# [/docs:cli-retain-async]
# [docs:cli-recall-basic]
hindsight memory recall $BANK_ID "What does Alice do?"
# [/docs:cli-recall-basic]
# [docs:cli-recall-options]
hindsight memory recall $BANK_ID "hiking recommendations" \
--budget high \
--max-tokens 8192
# [/docs:cli-recall-options]
# [docs:cli-recall-fact-type]
hindsight memory recall $BANK_ID "query" --fact-type world,opinion
# [/docs:cli-recall-fact-type]
# [docs:cli-recall-trace]
hindsight memory recall $BANK_ID "query" --trace
# [/docs:cli-recall-trace]
# [docs:cli-reflect-basic]
hindsight memory reflect $BANK_ID "What do you know about Alice?"
# [/docs:cli-reflect-basic]
# [docs:cli-reflect-context]
hindsight memory reflect $BANK_ID "Should I learn Python?" --context "career advice"
# [/docs:cli-reflect-context]
# [docs:cli-reflect-budget]
hindsight memory reflect $BANK_ID "Summarize my week" --budget high
# [/docs:cli-reflect-budget]
# =============================================================================
# Bank Management (cli.md - Bank Management section)
# =============================================================================
# [docs:cli-bank-list]
hindsight bank list
# [/docs:cli-bank-list]
# [docs:cli-bank-profile]
hindsight bank profile $BANK_ID
# [/docs:cli-bank-profile]
# [docs:cli-bank-stats]
hindsight bank stats $BANK_ID
# [/docs:cli-bank-stats]
# [docs:cli-bank-name]
hindsight bank name $BANK_ID "My Assistant"
# [/docs:cli-bank-name]
# [docs:cli-bank-background]
hindsight bank background $BANK_ID "I am a helpful AI assistant interested in technology"
# [/docs:cli-bank-background]
# [docs:cli-bank-background-no-disposition]
hindsight bank background $BANK_ID "Background text" --no-update-disposition
# [/docs:cli-bank-background-no-disposition]
# =============================================================================
# Document Management (cli.md - Document Management section)
# =============================================================================
# [docs:cli-document-list]
hindsight document list $BANK_ID
# [/docs:cli-document-list]
# [docs:cli-document-get]
hindsight document get $BANK_ID $DOC_ID
# [/docs:cli-document-get]
# [docs:cli-document-delete]
# Create a temp document to delete
hindsight memory retain $BANK_ID "Temporary content" --document-id "temp-doc-to-delete"
sleep 1
hindsight document delete $BANK_ID temp-doc-to-delete
# [/docs:cli-document-delete]
# =============================================================================
# Entity Management (cli.md - Entity Management section)
# =============================================================================
# [docs:cli-entity-list]
hindsight entity list $BANK_ID
# [/docs:cli-entity-list]
# Get an entity ID from the list output and use it
ENTITY_ID=$(hindsight entity list $BANK_ID -o json 2>/dev/null | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4 || echo "")
if [ -n "$ENTITY_ID" ]; then
# [docs:cli-entity-get]
hindsight entity get $BANK_ID $ENTITY_ID
# [/docs:cli-entity-get]
# [docs:cli-entity-regenerate]
hindsight entity regenerate $BANK_ID $ENTITY_ID
# [/docs:cli-entity-regenerate]
else
echo "No entities found yet, skipping entity get/regenerate"
fi
# =============================================================================
# Output Formats (cli.md - Output Formats section)
# =============================================================================
# [docs:cli-output-json]
hindsight memory recall $BANK_ID "query" -o json
# [/docs:cli-output-json]
# [docs:cli-output-yaml]
hindsight memory recall $BANK_ID "query" -o yaml
# [/docs:cli-output-yaml]
# =============================================================================
# Global Options (cli.md - Global Options section)
# =============================================================================
# [docs:cli-verbose]
hindsight memory recall $BANK_ID "Alice" -v
# [/docs:cli-verbose]
# [docs:cli-help]
hindsight --help
# [/docs:cli-help]
# [docs:cli-version]
hindsight --version
# [/docs:cli-version]
# =============================================================================
# Cleanup
# =============================================================================
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/${BANK_ID}" > /dev/null
echo "cli-reference.sh: All examples passed"
+68
View File
@@ -0,0 +1,68 @@
#!/usr/bin/env node
/**
* Documents API examples for Hindsight (Node.js)
* Run: node examples/api/documents.mjs
*/
import { HindsightClient, sdk, createClient, createConfig } from '@vectorize-io/hindsight-client';
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
// =============================================================================
// Setup (not shown in docs)
// =============================================================================
const client = new HindsightClient({ baseUrl: HINDSIGHT_URL });
// =============================================================================
// Doc Examples
// =============================================================================
// [docs:document-retain]
// Retain with document ID
await client.retain('my-bank', 'Alice presented the Q4 roadmap...', {
document_id: 'meeting-2024-03-15'
});
// Batch retain
await client.retainBatch('my-bank', [
{ content: 'Item 1: Product launch delayed to Q2' },
{ content: 'Item 2: New hiring targets announced' },
{ content: 'Item 3: Budget approved for ML team' }
], { documentId: 'meeting-2024-03-15' });
// [/docs:document-retain]
// [docs:document-update]
// Original
await client.retain('my-bank', 'Project deadline: March 31', {
document_id: 'project-plan'
});
// Update
await client.retain('my-bank', 'Project deadline: April 15 (extended)', {
document_id: 'project-plan'
});
// [/docs:document-update]
// [docs:document-get]
const apiClient = createClient(createConfig({ baseUrl: 'http://localhost:8888' }));
// Get document to expand context from recall results
const { data: doc } = await sdk.getDocument({
client: apiClient,
path: { bank_id: 'my-bank', document_id: 'meeting-2024-03-15' }
});
console.log(`Document: ${doc.id}`);
console.log(`Original text: ${doc.original_text}`);
console.log(`Memory count: ${doc.memory_unit_count}`);
console.log(`Created: ${doc.created_at}`);
// [/docs:document-get]
// =============================================================================
// Cleanup (not shown in docs)
// =============================================================================
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
console.log('documents.mjs: All examples passed');
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""
Documents API examples for Hindsight.
Run: python examples/api/documents.py
"""
import os
import requests
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
from hindsight_client import Hindsight
client = Hindsight(base_url=HINDSIGHT_URL)
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:document-retain]
# Retain with document ID
client.retain(
bank_id="my-bank",
content="Alice presented the Q4 roadmap...",
document_id="meeting-2024-03-15"
)
# Batch retain for a document
client.retain_batch(
bank_id="my-bank",
items=[
{"content": "Item 1: Product launch delayed to Q2"},
{"content": "Item 2: New hiring targets announced"},
{"content": "Item 3: Budget approved for ML team"}
],
document_id="meeting-2024-03-15"
)
# [/docs:document-retain]
# [docs:document-update]
# Original
client.retain(
bank_id="my-bank",
content="Project deadline: March 31",
document_id="project-plan"
)
# Update (deletes old facts, creates new ones)
client.retain(
bank_id="my-bank",
content="Project deadline: April 15 (extended)",
document_id="project-plan"
)
# [/docs:document-update]
# [docs:document-get]
import asyncio
from hindsight_client_api import ApiClient, Configuration
from hindsight_client_api.api import DefaultApi
async def get_document_example():
config = Configuration(host="http://localhost:8888")
api_client = ApiClient(config)
api = DefaultApi(api_client)
# Get document to expand context from recall results
doc = await api.get_document(
bank_id="my-bank",
document_id="meeting-2024-03-15"
)
print(f"Document: {doc.id}")
print(f"Original text: {doc.original_text}")
print(f"Memory count: {doc.memory_unit_count}")
print(f"Created: {doc.created_at}")
asyncio.run(get_document_example())
# [/docs:document-get]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
print("documents.py: All examples passed")
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/env python3
"""
Main Methods overview examples for Hindsight.
Run: python examples/api/main-methods.py
"""
import os
import requests
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
from hindsight_client import Hindsight
client = Hindsight(base_url=HINDSIGHT_URL)
# =============================================================================
# Doc Examples - Retain Section
# =============================================================================
# [docs:main-retain]
# Store a single fact
client.retain(
bank_id="my-bank",
content="Alice joined Google in March 2024 as a Senior ML Engineer"
)
# Store a conversation
conversation = """
User: What did you work on today?
Assistant: I reviewed the new ML pipeline architecture.
User: How did it look?
Assistant: Promising, but needs better error handling.
"""
client.retain(
bank_id="my-bank",
content=conversation,
context="Daily standup conversation"
)
# Batch retain multiple items
client.retain_batch(
bank_id="my-bank",
items=[
{"content": "Bob prefers Python for data science"},
{"content": "Alice recommends using pytest for testing"},
{"content": "The team uses GitHub for code reviews"}
]
)
# [/docs:main-retain]
# =============================================================================
# Doc Examples - Recall Section
# =============================================================================
# [docs:main-recall]
# Basic search
results = client.recall(
bank_id="my-bank",
query="What does Alice do at Google?"
)
for result in results.results:
print(f"- {result.text}")
# Search with options
results = client.recall(
bank_id="my-bank",
query="What happened last spring?",
budget="high", # More thorough graph traversal
max_tokens=8192, # Return more context
types=["world"] # Only world facts
)
# Include entity information
results = client.recall(
bank_id="my-bank",
query="Tell me about Alice",
include_entities=True,
max_entity_tokens=500
)
# Check entity details
for entity in results.entities or []:
print(f"Entity: {entity.name}")
print(f"Observations: {entity.observations}")
# [/docs:main-recall]
# =============================================================================
# Doc Examples - Reflect Section
# =============================================================================
# [docs:main-reflect]
# Basic reflect
response = client.reflect(
bank_id="my-bank",
query="Should we adopt TypeScript for our backend?"
)
print(response.text)
print("\nBased on:", len(response.based_on or []), "facts")
# Reflect with options
response = client.reflect(
bank_id="my-bank",
query="What are Alice's strengths for the team lead role?",
budget="high" # More thorough reasoning
)
# See which facts influenced the response
for fact in response.based_on or []:
print(f"- {fact.text}")
# [/docs:main-reflect]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
print("main-methods.py: All examples passed")
@@ -0,0 +1,47 @@
#!/usr/bin/env node
/**
* Memory Banks API examples for Hindsight (Node.js)
* Run: node examples/api/memory-banks.mjs
*/
import { HindsightClient } from '@vectorize-io/hindsight-client';
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
// =============================================================================
// Setup (not shown in docs)
// =============================================================================
const client = new HindsightClient({ baseUrl: HINDSIGHT_URL });
// =============================================================================
// Doc Examples
// =============================================================================
// [docs:create-bank]
await client.createBank('my-bank', {
name: 'Research Assistant',
background: 'I am a research assistant specializing in machine learning',
disposition: {
skepticism: 4,
literalism: 3,
empathy: 3
}
});
// [/docs:create-bank]
// [docs:bank-background]
await client.createBank('financial-advisor', {
background: `I am a conservative financial advisor with 20 years of experience.
I prioritize capital preservation over aggressive growth.
I have seen multiple market crashes and believe in diversification.`
});
// [/docs:bank-background]
// =============================================================================
// Cleanup (not shown in docs)
// =============================================================================
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
await fetch(`${HINDSIGHT_URL}/v1/default/banks/financial-advisor`, { method: 'DELETE' });
console.log('memory-banks.mjs: All examples passed');
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""
Memory Banks API examples for Hindsight.
Run: python examples/api/memory-banks.py
"""
import os
import requests
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
from hindsight_client import Hindsight
client = Hindsight(base_url=HINDSIGHT_URL)
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:create-bank]
client.create_bank(
bank_id="my-bank",
name="Research Assistant",
background="I am a research assistant specializing in machine learning",
disposition={
"skepticism": 4,
"literalism": 3,
"empathy": 3
}
)
# [/docs:create-bank]
# [docs:bank-background]
client.create_bank(
bank_id="financial-advisor",
background="""I am a conservative financial advisor with 20 years of experience.
I prioritize capital preservation over aggressive growth.
I have seen multiple market crashes and believe in diversification."""
)
# [/docs:bank-background]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/financial-advisor")
print("memory-banks.py: All examples passed")
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""
Opinions API examples for Hindsight.
Run: python examples/api/opinions.py
"""
import os
import requests
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
from hindsight_client import Hindsight
client = Hindsight(base_url=HINDSIGHT_URL)
# Seed some data about programming languages
client.retain(bank_id="my-bank", content="Python is widely used for data science and machine learning")
client.retain(bank_id="my-bank", content="Functional programming emphasizes immutability and pure functions")
client.retain(bank_id="my-bank", content="Rust has better memory safety than C++")
client.retain(bank_id="my-bank", content="C++ has a larger ecosystem and more libraries")
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:opinion-form]
# Ask a question - the system may form opinions based on stored facts
answer = client.reflect(
bank_id="my-bank",
query="What do you think about functional programming?"
)
print(answer.text)
# [/docs:opinion-form]
# [docs:opinion-search]
# Search for facts about a topic
results = client.recall(
bank_id="my-bank",
query="programming languages"
)
for result in results.results:
print(f"- {result.text}")
# [/docs:opinion-search]
# [docs:opinion-disposition]
# Create two memory banks with different dispositions
client.create_bank(
bank_id="open-minded",
disposition={"skepticism": 2, "literalism": 2, "empathy": 4}
)
client.create_bank(
bank_id="conservative",
disposition={"skepticism": 5, "literalism": 5, "empathy": 2}
)
# Store the same facts to both
facts = [
"Rust has better memory safety than C++",
"C++ has a larger ecosystem and more libraries",
"Rust compile times are longer than C++"
]
for fact in facts:
client.retain(bank_id="open-minded", content=fact)
client.retain(bank_id="conservative", content=fact)
# Ask both the same question - different dispositions lead to different responses
q = "Should we rewrite our C++ codebase in Rust?"
answer1 = client.reflect(bank_id="open-minded", query=q)
print("Open-minded response:", answer1.text[:100], "...")
answer2 = client.reflect(bank_id="conservative", query=q)
print("Conservative response:", answer2.text[:100], "...")
# [/docs:opinion-disposition]
# [docs:opinion-in-reflect]
answer = client.reflect(bank_id="my-bank", query="What language should I learn?")
print("Response:", answer.text)
# See which facts influenced the response
if answer.based_on:
print("\nBased on these facts:")
for fact in answer.based_on:
print(f" - {fact.text}")
# [/docs:opinion-in-reflect]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/open-minded")
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/conservative")
print("opinions.py: All examples passed")
@@ -0,0 +1,34 @@
#!/usr/bin/env node
/**
* Quickstart examples for Hindsight API (Node.js)
* Run: node examples/api/quickstart.mjs
*/
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
// =============================================================================
// Doc Examples
// =============================================================================
// [docs:quickstart-full]
import { HindsightClient } from '@vectorize-io/hindsight-client';
const client = new HindsightClient({ baseUrl: 'http://localhost:8888' });
// Retain: Store information
await client.retain('my-bank', 'Alice works at Google as a software engineer');
// Recall: Search memories
await client.recall('my-bank', 'What does Alice do?');
// Reflect: Generate response
await client.reflect('my-bank', 'Tell me about Alice');
// [/docs:quickstart-full]
// =============================================================================
// Cleanup (not shown in docs)
// =============================================================================
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
console.log('quickstart.mjs: All examples passed');
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
"""
Quickstart examples for Hindsight API.
Run: python examples/api/quickstart.py
"""
import os
import requests
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:quickstart-full]
from hindsight_client import Hindsight
client = Hindsight(base_url="http://localhost:8888")
# Retain: Store information
client.retain(bank_id="my-bank", content="Alice works at Google as a software engineer")
# Recall: Search memories
client.recall(bank_id="my-bank", query="What does Alice do?")
# Reflect: Generate disposition-aware response
client.reflect(bank_id="my-bank", query="Tell me about Alice")
# [/docs:quickstart-full]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
print("quickstart.py: All examples passed")
+30
View File
@@ -0,0 +1,30 @@
#!/bin/bash
# Quickstart examples for Hindsight CLI
# Run: bash examples/api/quickstart.sh
set -e
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:quickstart-full]
# Retain: Store information
hindsight memory retain my-bank "Alice works at Google as a software engineer"
# Recall: Search memories
hindsight memory recall my-bank "What does Alice do?"
# Reflect: Generate response
hindsight memory reflect my-bank "Tell me about Alice"
# [/docs:quickstart-full]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/my-bank" > /dev/null
echo "quickstart.sh: All examples passed"
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env node
/**
* Recall API examples for Hindsight (Node.js)
* Run: node examples/api/recall.mjs
*/
import { HindsightClient } from '@vectorize-io/hindsight-client';
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
// =============================================================================
// Setup (not shown in docs)
// =============================================================================
const client = new HindsightClient({ baseUrl: HINDSIGHT_URL });
// Seed some data for recall examples
await client.retain('my-bank', 'Alice works at Google as a software engineer');
await client.retain('my-bank', 'Alice loves hiking on weekends');
await client.retain('my-bank', 'Bob is a data scientist who works with Alice');
// =============================================================================
// Doc Examples
// =============================================================================
// [docs:recall-basic]
const response = await client.recall('my-bank', 'What does Alice do?');
for (const r of response.results) {
console.log(`${r.text} (score: ${r.weight})`);
}
// [/docs:recall-basic]
// [docs:recall-with-options]
const detailedResponse = await client.recall('my-bank', 'What does Alice do?', {
types: ['world', 'experience'],
budget: 'high',
maxTokens: 8000,
trace: true
});
// Access results
for (const r of detailedResponse.results) {
console.log(`${r.text} (score: ${r.weight})`);
}
// [/docs:recall-with-options]
// [docs:recall-budget-levels]
// Quick lookup
const quickResults = await client.recall('my-bank', "Alice's email", { budget: 'low' });
// Deep exploration
const deepResults = await client.recall('my-bank', 'How are Alice and Bob connected?', { budget: 'high' });
// [/docs:recall-budget-levels]
// =============================================================================
// Cleanup (not shown in docs)
// =============================================================================
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
console.log('recall.mjs: All examples passed');
+124
View File
@@ -0,0 +1,124 @@
#!/usr/bin/env python3
"""
Recall API examples for Hindsight.
Run: python examples/api/recall.py
"""
import os
import requests
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
from hindsight_client import Hindsight
client = Hindsight(base_url=HINDSIGHT_URL)
# Seed some data for recall examples
client.retain(bank_id="my-bank", content="Alice works at Google as a software engineer")
client.retain(bank_id="my-bank", content="Alice loves hiking on weekends")
client.retain(bank_id="my-bank", content="Bob is a data scientist who works with Alice")
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:recall-basic]
response = client.recall(bank_id="my-bank", query="What does Alice do?")
for r in response.results:
print(f"- {r.text}")
# [/docs:recall-basic]
# [docs:recall-with-options]
response = client.recall(
bank_id="my-bank",
query="What does Alice do?",
types=["world", "experience"],
budget="high",
max_tokens=8000,
trace=True,
include_entities=True,
max_entity_tokens=500
)
# Access results
for r in response.results:
print(f"- {r.text}")
# Access entity observations (if include_entities=True)
if response.entities:
for entity_id, entity in response.entities.items():
print(f"Entity: {entity.canonical_name}")
# [/docs:recall-with-options]
# [docs:recall-world-only]
# Only world facts (objective information)
world_facts = client.recall(
bank_id="my-bank",
query="Where does Alice work?",
types=["world"]
)
# [/docs:recall-world-only]
# [docs:recall-experience-only]
# Only experience (conversations and events)
experience = client.recall(
bank_id="my-bank",
query="What have I recommended?",
types=["experience"]
)
# [/docs:recall-experience-only]
# [docs:recall-opinions-only]
# Only opinions (formed beliefs)
opinions = client.recall(
bank_id="my-bank",
query="What do I think about Python?",
types=["opinion"]
)
# [/docs:recall-opinions-only]
# [docs:recall-token-budget]
# Fill up to 4K tokens of context with relevant memories
results = client.recall(bank_id="my-bank", query="What do I know about Alice?", max_tokens=4096)
# Smaller budget for quick lookups
results = client.recall(bank_id="my-bank", query="Alice's email", max_tokens=500)
# [/docs:recall-token-budget]
# [docs:recall-include-entities]
response = client.recall(
bank_id="my-bank",
query="What does Alice do?",
max_tokens=4096, # Budget for memories
include_entities=True,
max_entity_tokens=1000 # Budget for entity observations
)
# Access the additional context
entities = response.entities or []
# [/docs:recall-include-entities]
# [docs:recall-budget-levels]
# Quick lookup
results = client.recall(bank_id="my-bank", query="Alice's email", budget="low")
# Deep exploration
results = client.recall(bank_id="my-bank", query="How are Alice and Bob connected?", budget="high")
# [/docs:recall-budget-levels]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
print("recall.py: All examples passed")
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
# Recall API examples for Hindsight CLI
# Run: bash examples/api/recall.sh
set -e
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
hindsight memory retain my-bank "Alice works at Google as a software engineer"
hindsight memory retain my-bank "Alice loves hiking on weekends"
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:recall-basic]
hindsight memory recall my-bank "What does Alice do?"
# [/docs:recall-basic]
# [docs:recall-with-options]
hindsight memory recall my-bank "hiking recommendations" \
--budget high \
--max-tokens 8192
# [/docs:recall-with-options]
# [docs:recall-fact-type]
hindsight memory recall my-bank "query" --fact-type world,opinion
# [/docs:recall-fact-type]
# [docs:recall-trace]
hindsight memory recall my-bank "query" --trace
# [/docs:recall-trace]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/my-bank" > /dev/null
echo "recall.sh: All examples passed"
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin/env node
/**
* Reflect API examples for Hindsight (Node.js)
* Run: node examples/api/reflect.mjs
*/
import { HindsightClient } from '@vectorize-io/hindsight-client';
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
// =============================================================================
// Setup (not shown in docs)
// =============================================================================
const client = new HindsightClient({ baseUrl: HINDSIGHT_URL });
// Seed some data for reflect examples
await client.retain('my-bank', 'Alice works at Google as a software engineer');
await client.retain('my-bank', 'Alice has been working there for 5 years');
await client.retain('my-bank', 'Alice recently got promoted to senior engineer');
// =============================================================================
// Doc Examples
// =============================================================================
// [docs:reflect-basic]
await client.reflect('my-bank', 'What should I know about Alice?');
// [/docs:reflect-basic]
// [docs:reflect-with-params]
const response = await client.reflect('my-bank', 'What do you think about remote work?', {
budget: 'mid',
context: "We're considering a hybrid work policy"
});
// [/docs:reflect-with-params]
// [docs:reflect-with-context]
// Context helps the LLM understand the current situation
const contextResponse = await client.reflect('my-bank', 'What do you think about the proposal?', {
context: "We're in a budget review meeting discussing Q4 spending"
});
// [/docs:reflect-with-context]
// [docs:reflect-disposition]
// Create a bank with specific disposition
await client.createBank('cautious-advisor', {
background: 'I am a risk-aware financial advisor',
disposition: {
skepticism: 5,
literalism: 4,
empathy: 2
}
});
// Reflect responses will reflect this disposition
const advisorResponse = await client.reflect('cautious-advisor', 'Should I invest in crypto?');
// [/docs:reflect-disposition]
// [docs:reflect-sources]
const sourcesResponse = await client.reflect('my-bank', 'Tell me about Alice');
console.log('Response:', sourcesResponse.text);
console.log('\nBased on:');
for (const fact of sourcesResponse.based_on || []) {
console.log(` - [${fact.type}] ${fact.text}`);
}
// [/docs:reflect-sources]
// =============================================================================
// Cleanup (not shown in docs)
// =============================================================================
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
await fetch(`${HINDSIGHT_URL}/v1/default/banks/cautious-advisor`, { method: 'DELETE' });
console.log('reflect.mjs: All examples passed');
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""
Reflect API examples for Hindsight.
Run: python examples/api/reflect.py
"""
import os
import requests
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
from hindsight_client import Hindsight
client = Hindsight(base_url=HINDSIGHT_URL)
# Seed some data for reflect examples
client.retain(bank_id="my-bank", content="Alice works at Google as a software engineer")
client.retain(bank_id="my-bank", content="Alice has been working there for 5 years")
client.retain(bank_id="my-bank", content="Alice recently got promoted to senior engineer")
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:reflect-basic]
client.reflect(bank_id="my-bank", query="What should I know about Alice?")
# [/docs:reflect-basic]
# [docs:reflect-with-params]
response = client.reflect(
bank_id="my-bank",
query="What do you think about remote work?",
budget="mid",
context="We're considering a hybrid work policy"
)
# [/docs:reflect-with-params]
# [docs:reflect-with-context]
# Context is passed to the LLM to help it understand the situation
response = client.reflect(
bank_id="my-bank",
query="What do you think about the proposal?",
context="We're in a budget review meeting discussing Q4 spending"
)
# [/docs:reflect-with-context]
# [docs:reflect-disposition]
# Create a bank with specific disposition
client.create_bank(
bank_id="cautious-advisor",
background="I am a risk-aware financial advisor",
disposition={
"skepticism": 5, # Very skeptical of claims
"literalism": 4, # Focuses on exact requirements
"empathy": 2 # Prioritizes facts over feelings
}
)
# Reflect responses will reflect this disposition
response = client.reflect(
bank_id="cautious-advisor",
query="Should I invest in crypto?"
)
# Response will likely emphasize risks and caution
# [/docs:reflect-disposition]
# [docs:reflect-sources]
response = client.reflect(bank_id="my-bank", query="Tell me about Alice")
print("Response:", response.text)
print("\nBased on:")
for fact in response.based_on or []:
print(f" - [{fact.type}] {fact.text}")
# [/docs:reflect-sources]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/cautious-advisor")
print("reflect.py: All examples passed")
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
# Reflect API examples for Hindsight CLI
# Run: bash examples/api/reflect.sh
set -e
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
hindsight memory retain my-bank "Alice works at Google as a software engineer"
hindsight memory retain my-bank "Alice has been working there for 5 years"
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:reflect-basic]
hindsight memory reflect my-bank "What do you know about Alice?"
# [/docs:reflect-basic]
# [docs:reflect-with-context]
hindsight memory reflect my-bank "Should I learn Python?" --context "career advice"
# [/docs:reflect-with-context]
# [docs:reflect-high-budget]
hindsight memory reflect my-bank "Summarize my week" --budget high
# [/docs:reflect-high-budget]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/my-bank" > /dev/null
echo "reflect.sh: All examples passed"
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env node
/**
* Retain API examples for Hindsight (Node.js)
* Run: node examples/api/retain.mjs
*/
import { HindsightClient } from '@vectorize-io/hindsight-client';
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
// =============================================================================
// Setup (not shown in docs)
// =============================================================================
const client = new HindsightClient({ baseUrl: HINDSIGHT_URL });
// =============================================================================
// Doc Examples
// =============================================================================
// [docs:retain-basic]
await client.retain('my-bank', 'Alice works at Google as a software engineer');
// [/docs:retain-basic]
// [docs:retain-with-context]
await client.retain('my-bank', 'Alice got promoted to senior engineer', {
context: 'career update',
timestamp: '2024-03-15T10:00:00Z'
});
// [/docs:retain-with-context]
// [docs:retain-batch]
await client.retainBatch('my-bank', [
{ content: 'Alice works at Google', context: 'career' },
{ content: 'Bob is a data scientist at Meta', context: 'career' },
{ content: 'Alice and Bob are friends', context: 'relationship' }
], { documentId: 'conversation_001' });
// [/docs:retain-batch]
// [docs:retain-async]
// Start async ingestion (returns immediately)
await client.retainBatch('my-bank', [
{ content: 'Large batch item 1' },
{ content: 'Large batch item 2' },
], {
documentId: 'large-doc',
async: true
});
// [/docs:retain-async]
// =============================================================================
// Cleanup (not shown in docs)
// =============================================================================
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
console.log('retain.mjs: All examples passed');
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""
Retain API examples for Hindsight.
Run: python examples/api/retain.py
"""
import os
import requests
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
from hindsight_client import Hindsight
client = Hindsight(base_url=HINDSIGHT_URL)
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:retain-basic]
client.retain(
bank_id="my-bank",
content="Alice works at Google as a software engineer"
)
# [/docs:retain-basic]
# [docs:retain-with-context]
client.retain(
bank_id="my-bank",
content="Alice got promoted to senior engineer",
context="career update",
timestamp="2024-03-15T10:00:00Z"
)
# [/docs:retain-with-context]
# [docs:retain-batch]
client.retain_batch(
bank_id="my-bank",
items=[
{"content": "Alice works at Google", "context": "career"},
{"content": "Bob is a data scientist at Meta", "context": "career"},
{"content": "Alice and Bob are friends", "context": "relationship"}
],
document_id="conversation_001"
)
# [/docs:retain-batch]
# [docs:retain-async]
# Start async ingestion (returns immediately)
result = client.retain_batch(
bank_id="my-bank",
items=[
{"content": "Large batch item 1"},
{"content": "Large batch item 2"},
],
document_id="large-doc",
retain_async=True
)
# Check if it was processed asynchronously
print(result.var_async) # True
# [/docs:retain-async]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
print("retain.py: All examples passed")
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
# Retain API examples for Hindsight CLI
# Run: bash examples/api/retain.sh
set -e
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:retain-basic]
hindsight memory retain my-bank "Alice works at Google as a software engineer"
# [/docs:retain-basic]
# [docs:retain-with-context]
hindsight memory retain my-bank "Alice got promoted" \
--context "career update"
# [/docs:retain-with-context]
# [docs:retain-async]
hindsight memory retain my-bank "Meeting notes" --async
# [/docs:retain-async]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/my-bank" > /dev/null
echo "retain.sh: All examples passed"
+129
View File
@@ -0,0 +1,129 @@
#!/bin/bash
# Run all documentation example scripts
# Usage: ./examples/run-examples.sh [python|node|cli|all]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
passed=0
failed=0
skipped=0
run_python_examples() {
echo -e "${YELLOW}Running Python examples...${NC}"
for f in "$SCRIPT_DIR"/api/*.py; do
if [ -f "$f" ]; then
echo -n " $(basename "$f"): "
if python "$f" 2>&1; then
echo -e "${GREEN}PASSED${NC}"
((passed++))
else
echo -e "${RED}FAILED${NC}"
((failed++))
fi
fi
done
}
run_node_examples() {
echo -e "${YELLOW}Running Node.js examples...${NC}"
for f in "$SCRIPT_DIR"/api/*.mjs; do
if [ -f "$f" ]; then
echo -n " $(basename "$f"): "
if node "$f" 2>&1; then
echo -e "${GREEN}PASSED${NC}"
((passed++))
else
echo -e "${RED}FAILED${NC}"
((failed++))
fi
fi
done
}
run_cli_examples() {
echo -e "${YELLOW}Running CLI examples...${NC}"
# Check if hindsight CLI is available
if ! command -v hindsight &> /dev/null; then
echo -e " ${YELLOW}SKIPPED (hindsight CLI not installed)${NC}"
for f in "$SCRIPT_DIR"/api/*.sh; do
if [ -f "$f" ]; then
((skipped++))
fi
done
return
fi
for f in "$SCRIPT_DIR"/api/*.sh; do
if [ -f "$f" ]; then
echo -n " $(basename "$f"): "
if bash "$f" 2>&1; then
echo -e "${GREEN}PASSED${NC}"
((passed++))
else
echo -e "${RED}FAILED${NC}"
((failed++))
fi
fi
done
}
# Wait for server to be ready
wait_for_server() {
echo "Waiting for Hindsight server at $HINDSIGHT_URL..."
for i in {1..30}; do
if curl -s "$HINDSIGHT_URL/health" > /dev/null 2>&1; then
echo "Server is ready!"
return 0
fi
sleep 1
done
echo "Server not available after 30 seconds"
return 1
}
# Main
case "${1:-all}" in
python)
wait_for_server
run_python_examples
;;
node)
wait_for_server
run_node_examples
;;
cli)
wait_for_server
run_cli_examples
;;
all)
wait_for_server
run_python_examples
echo ""
run_node_examples
echo ""
run_cli_examples
;;
*)
echo "Usage: $0 [python|node|cli|all]"
exit 1
;;
esac
echo ""
echo "========================================"
echo -e "Results: ${GREEN}$passed passed${NC}, ${RED}$failed failed${NC}, ${YELLOW}$skipped skipped${NC}"
echo "========================================"
if [ $failed -gt 0 ]; then
exit 1
fi
+1
View File
@@ -22,6 +22,7 @@
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"raw-loader": "^4.0.2",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"redocusaurus": "^2.5.0"
@@ -0,0 +1,110 @@
import React from 'react';
import CodeBlock from '@theme/CodeBlock';
interface CodeSnippetProps {
/** Raw file content (use raw-loader to import) */
code: string;
/** Section marker name (e.g., "retain-basic" for [docs:retain-basic]) */
section: string;
/** Language for syntax highlighting */
language: string;
/** Optional title for the code block */
title?: string;
}
/**
* Extracts a marked section from source code.
*
* Markers are in the format:
* - Start: `# [docs:section-name]` (Python/Bash) or `// [docs:section-name]` (JS/TS)
* - End: `# [/docs:section-name]` (Python/Bash) or `// [/docs:section-name]` (JS/TS)
*/
function extractSection(code: string, section: string): string {
// Match both Python/Bash (#) and JS/TS (//) comment styles
const startPattern = new RegExp(`(?:#|//)\\s*\\[docs:${section}\\]`);
const endPattern = new RegExp(`(?:#|//)\\s*\\[/docs:${section}\\]`);
const lines = code.split('\n');
let inSection = false;
const sectionLines: string[] = [];
for (const line of lines) {
if (startPattern.test(line)) {
inSection = true;
continue;
}
if (endPattern.test(line)) {
inSection = false;
continue;
}
if (inSection) {
sectionLines.push(line);
}
}
if (sectionLines.length === 0) {
console.warn(`CodeSnippet: Section "${section}" not found in code`);
return `// Section "${section}" not found`;
}
// Trim leading/trailing empty lines and normalize indentation
return trimAndNormalize(sectionLines);
}
/**
* Trims leading/trailing empty lines and removes common leading indentation.
*/
function trimAndNormalize(lines: string[]): string {
// Remove leading empty lines
while (lines.length > 0 && lines[0].trim() === '') {
lines.shift();
}
// Remove trailing empty lines
while (lines.length > 0 && lines[lines.length - 1].trim() === '') {
lines.pop();
}
if (lines.length === 0) return '';
// Find minimum indentation (ignoring empty lines)
const nonEmptyLines = lines.filter(l => l.trim() !== '');
if (nonEmptyLines.length === 0) return '';
const minIndent = Math.min(
...nonEmptyLines.map(line => {
const match = line.match(/^(\s*)/);
return match ? match[1].length : 0;
})
);
// Remove common indentation
return lines
.map(line => line.slice(minIndent))
.join('\n');
}
/**
* CodeSnippet component for embedding code from example files.
*
* Usage in MDX:
* ```mdx
* import CodeSnippet from '@site/src/components/CodeSnippet';
* import retainPy from '!!raw-loader!@site/examples/api/retain.py';
*
* <CodeSnippet code={retainPy} section="retain-basic" language="python" />
* ```
*/
export default function CodeSnippet({
code,
section,
language,
title
}: CodeSnippetProps): React.ReactElement {
const extractedCode = extractSection(code, section);
return (
<CodeBlock language={language} title={title}>
{extractedCode}
</CodeBlock>
);
}
+39
View File
@@ -105,6 +105,7 @@
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"raw-loader": "^4.0.2",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"redocusaurus": "^2.5.0"
@@ -24244,6 +24245,44 @@
"node": ">=0.10.0"
}
},
"node_modules/raw-loader": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz",
"integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==",
"license": "MIT",
"dependencies": {
"loader-utils": "^2.0.0",
"schema-utils": "^3.0.0"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^4.0.0 || ^5.0.0"
}
},
"node_modules/raw-loader/node_modules/schema-utils": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
"license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
Generated
+6 -4
View File
@@ -1141,7 +1141,7 @@ wheels = [
[[package]]
name = "hindsight-all"
version = "0.1.7"
version = "0.1.8"
source = { editable = "hindsight" }
dependencies = [
{ name = "hindsight-api" },
@@ -1165,7 +1165,7 @@ provides-extras = ["test"]
[[package]]
name = "hindsight-api"
version = "0.1.7"
version = "0.1.8"
source = { editable = "hindsight-api" }
dependencies = [
{ name = "alembic" },
@@ -1269,7 +1269,7 @@ dev = [
[[package]]
name = "hindsight-client"
version = "0.1.7"
version = "0.1.8"
source = { editable = "hindsight-clients/python" }
dependencies = [
{ name = "aiohttp" },
@@ -1284,6 +1284,7 @@ dependencies = [
test = [
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "requests" },
]
[package.metadata]
@@ -1294,6 +1295,7 @@ requires-dist = [
{ name = "pytest", marker = "extra == 'test'", specifier = ">=7.0.0" },
{ name = "pytest-asyncio", marker = "extra == 'test'", specifier = ">=0.21.0" },
{ name = "python-dateutil", specifier = ">=2.8.2" },
{ name = "requests", marker = "extra == 'test'", specifier = ">=2.28.0" },
{ name = "typing-extensions", specifier = ">=4.7.1" },
{ name = "urllib3", specifier = ">=2.1.0,<3.0.0" },
]
@@ -1301,7 +1303,7 @@ provides-extras = ["test"]
[[package]]
name = "hindsight-dev"
version = "0.1.7"
version = "0.1.8"
source = { editable = "hindsight-dev" }
dependencies = [
{ name = "hindsight-api" },