Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,25 @@ jobs:
working-directory: ./hindsight-clients/typescript
run: npm run build

build-docs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies
working-directory: ./hindsight-docs
run: npm ci

- name: Build docs
working-directory: ./hindsight-docs
run: npm run build

build-rust-cli:
runs-on: ubuntu-latest

Expand Down Expand Up @@ -129,24 +148,7 @@ jobs:
test-api:
runs-on: ubuntu-latest
needs: [build-python-packages]

services:
postgres:
image: pgvector/pgvector:pg16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: hindsight_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

env:
HINDSIGHT_API_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/hindsight_test
HINDSIGHT_API_LLM_PROVIDER: groq
HINDSIGHT_API_LLM_API_KEY: ${{ secrets.GROQ_API_KEY }}
HINDSIGHT_API_LLM_MODEL: openai/gpt-oss-20b
Expand All @@ -170,4 +172,4 @@ jobs:

- name: Run tests
working-directory: ./hindsight-api
run: uv run pytest tests -v --ignore=tests/test_fact_extraction_quality.py
run: uv run pytest tests -v
10 changes: 7 additions & 3 deletions docker/standalone/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,15 @@ WORKDIR /app
COPY --from=sdk-builder /app/sdk /app/sdk

# Install Control Plane dependencies
COPY hindsight-control-plane/package*.json ./
RUN npm ci
# Only copy package.json (not package-lock.json) to ensure npm installs
# correct platform-specific native bindings for lightningcss/tailwindcss
COPY hindsight-control-plane/package.json ./
RUN npm install

# Copy Control Plane source
# Copy Control Plane source (excluding node_modules via .dockerignore)
COPY hindsight-control-plane/ ./
# Remove package-lock.json to avoid conflicts with installed native bindings
RUN rm -f package-lock.json

# Link SDK (temporary for build)
RUN cd /app/sdk && npm link && cd /app && npm link @vectorize-io/hindsight-client
Expand Down
26 changes: 24 additions & 2 deletions hindsight-api/hindsight_api/engine/retain/fact_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@
from ..llm_wrapper import OutputTooLongError, LLMConfig


def _sanitize_text(text: str) -> str:
"""
Sanitize text by removing invalid Unicode surrogate characters.

Surrogate characters (U+D800 to U+DFFF) are used in UTF-16 encoding
but cannot be encoded in UTF-8. They can appear in Python strings
from improperly decoded data (e.g., from JavaScript or broken files).

This function removes unpaired surrogates to prevent UnicodeEncodeError
when the text is sent to the LLM API.
"""
if not text:
return text
# Remove surrogate characters (U+D800 to U+DFFF) using regex
# These are invalid in UTF-8 and cause encoding errors
return re.sub(r'[\ud800-\udfff]', '', text)


class Entity(BaseModel):
"""An entity extracted from text."""
text: str = Field(
Expand Down Expand Up @@ -470,17 +488,21 @@ async def _extract_facts_from_chunk(
max_retries = 2
last_error = None

# Sanitize input text to prevent Unicode encoding errors (e.g., unpaired surrogates)
sanitized_chunk = _sanitize_text(chunk)
sanitized_context = _sanitize_text(context) if context else 'none'

# Build user message with metadata and chunk content in a clear format
# Format event_date with day of week for better temporal reasoning
event_date_formatted = event_date.strftime('%A, %B %d, %Y') # e.g., "Monday, June 10, 2024"
user_message = f"""Extract facts from the following text chunk.

Chunk: {chunk_index + 1}/{total_chunks}
Event Date: {event_date_formatted} ({event_date.isoformat()})
Context: {context if context else 'none'}
Context: {sanitized_context}

Text:
{chunk}"""
{sanitized_chunk}"""

for attempt in range(max_retries):
try:
Expand Down
2 changes: 1 addition & 1 deletion hindsight-clients/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ response = client.reflect(

## Documentation

For full documentation, visit [hindsight.dev](https://hindsight.dev).
For full documentation, visit [hindsight](https://github.com/vectorize-io/hindsight).
100 changes: 66 additions & 34 deletions hindsight-clients/typescript/README.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,89 @@
# @hindsight/client
# Hindsight TypeScript Client

TypeScript client for Hindsight - Semantic memory system with personality-driven thinking.

**Auto-generated from OpenAPI spec** - provides type-safe access to all Hindsight API endpoints.
TypeScript client library for the Hindsight API.

## Installation

```bash
npm install @hindsight/client
npm install @vectorize-io/hindsight-client
# or
yarn add @hindsight/client
yarn add @vectorize-io/hindsight-client
```

## Quick Start
## Usage

```typescript
import { OpenAPI, MemoryStorageService, ReasoningService } from '@hindsight/client';
import { HindsightClient } from '@vectorize-io/hindsight-client';

// Configure API base URL
OpenAPI.BASE = 'http://localhost:8888';
const client = new HindsightClient({ baseUrl: 'http://localhost:8888' });

// Store memory
await MemoryStorageService.putApiPutPost({
agent_id: 'user123',
content: 'Alice loves machine learning'
});
// Retain information
await client.retain('my-bank', 'Alice works at Google in Mountain View.');

// Recall memories
const results = await client.recall('my-bank', 'Where does Alice work?');

// Reflect and get an opinion
const response = await client.reflect('my-bank', 'What do you think about Alice\'s career?');
```

## API Reference

### `retain(bankId, content, options?)`

// Think (generate answer with personality)
const response = await ReasoningService.thinkApiThinkPost({
agent_id: 'user123',
query: 'What does Alice think about AI?',
thinking_budget: 50
Store a single memory.

```typescript
await client.retain('my-bank', 'User prefers dark mode', {
timestamp: new Date(),
context: 'Settings conversation',
metadata: { source: 'chat' }
});
```

console.log(response.text);
### `retainBatch(bankId, items, options?)`

Store multiple memories in batch.

```typescript
await client.retainBatch('my-bank', [
{ content: 'Alice loves hiking' },
{ content: 'Alice visited Paris last summer' }
], { async: true });
```

## Available Services
### `recall(bankId, query, options?)`

- `MemoryStorageService` - Store and retrieve facts
- `SearchService` - Semantic and temporal search
- `ReasoningService` - Personality-driven thinking
- `VisualizationService` - Memory graphs and statistics
- `ManagementService` - Agent profiles and configuration
- `DocumentsService` - Document tracking
Recall memories matching a query.

All services are fully typed with TypeScript interfaces.
```typescript
const results = await client.recall('my-bank', 'What are Alice\'s hobbies?', {
budget: 'mid'
});
```

### `reflect(bankId, query, options?)`

Generate a contextual answer using the bank's identity and memories.

```typescript
const response = await client.reflect('my-bank', 'What should I do this weekend?', {
budget: 'low'
});
console.log(response.text);
```

### `createBank(bankId, options)`

## Development
Create or update a memory bank with personality.

Auto-generated from `openapi.json`. See [RELEASE.md](../../RELEASE.md) for regeneration instructions.
```typescript
await client.createBank('my-bank', {
name: 'My Assistant',
background: 'A helpful assistant that remembers everything.'
});
```

## Links
## Documentation

- [GitHub Repository](https://github.com/vectorize-io/hindsight)
- [Full Documentation](https://github.com/vectorize-io/hindsight/blob/main/README.md)
For full documentation, visit [hindsight](https://github.com/vectorize-io/hindsight).
4 changes: 2 additions & 2 deletions hindsight-docs/docs/developer/api/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pip install hindsight-client
npm install @hindsight/client
```

**Requires:** A running Hindsight server (see [Server Deployment](/developer/server) for setup).
**Requires:** A running Hindsight server (see [Server Deployment](/developer/installation) for setup).

</TabItem>
<TabItem value="cli" label="CLI">
Expand Down Expand Up @@ -120,4 +120,4 @@ hindsight --version
## Next Steps

- [**Quick Start**](./quickstart) — Get running in 60 seconds
- [**Server Deployment**](/developer/server) — Production setup options
- [**Server Deployment**](/developer/installation) — Production setup options
2 changes: 1 addition & 1 deletion hindsight-docs/docs/developer/api/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,4 @@ hindsight reflect my-bank "Tell me about Alice"
- [**Recall**](./recall) — Search and retrieval strategies
- [**Reflect**](./reflect) — Personality-aware reasoning
- [**Memory Banks**](./memory-banks) — Configure personality and background
- [**Server Options**](/developer/server) — Production deployment
- [**Server Options**](/developer/installation) — Production deployment
2 changes: 1 addition & 1 deletion hindsight-docs/docs/developer/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,4 @@ The `bias_strength` parameter (0-1) controls how much personality influences opi
- [**Operations**](/developer/api/operations) — Monitor async tasks

### Deployment
- [**Server Setup**](/developer/server) — Deploy with Docker Compose, Helm, or pip
- [**Server Setup**](/developer/installation) — Deploy with Docker Compose, Helm, or pip
Loading
Loading