Commit graph

232 commits

Author SHA1 Message Date
Nicolò Boschi
c2607d7699
fix(helm): improve appVersion usage (#326) 2026-02-09 11:35:08 +01:00
Jerry Henley
e99ee0f243
Add Supabase tenant extension as built-in (#267)
Move the Supabase tenant extension into the hindsight-api package so users
can enable it with just an environment variable — no file copying or Docker
image modifications needed.

Key improvements over the original submission:
- JWKS-based local JWT verification (no network call per request) with
  automatic fallback to /auth/v1/user for legacy HS256 projects
- Service key is now optional (only needed for HS256 or health checks)
- UUID validation on user IDs before schema name construction
- Schema prefix validation against Postgres identifier rules
- Key rotation handling with automatic JWKS cache refresh
- Proper logging via Python logging module
- Tenant extension lifecycle hooks (on_startup/on_shutdown) wired into
  the server lifespan
- Public tenant_extension property on MemoryEngine
- 54 unit tests covering both verification modes, cache behavior, error
  paths, and the extension loader
- README updated to reflect JWKS-first architecture

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-09 10:16:47 +01:00
Van Vuong Ngo
c568094b8c
fix: do not log db user/password (#312)
* fix: security vulnerability - exposed sensitve database credentials in logs

* add comment

* fix: mask credentials of the postgeSQL connection string
2026-02-09 10:15:03 +01:00
Nicolò Boschi
d90588b3e1
feat: improve mcp tools based on endpoint (#318)
* feat: improve mcp tools based on endpoint

* feat: improve mcp tools based on endpoint

* test: add integration test for MCP endpoint routing

- Add test_mcp_endpoint_routing.py to verify single-bank vs multi-bank tool exposure
- Verifies /mcp/ exposes all tools with bank_id parameters
- Verifies /mcp/{bank_id}/ only exposes scoped tools without bank_id parameters
- Regression test for issue #317

Related: #317, #318

* test: use StreamableHTTP client for MCP endpoint routing test

Replace httpx AsyncClient SSE parsing with proper MCP StreamableHTTP
client. This correctly tests the MCP server using the actual protocol
that clients will use.

Fixes #317
2026-02-08 09:28:59 +01:00
DK09876
fedfb494ee
feat: add TenantExtension auth to MCP endpoint (#286)
* feat: add TenantExtension auth to MCP endpoint

Replace static MCP_AUTH_TOKEN check with TenantExtension authentication,
making MCP use the same auth path as REST API.

- MCPMiddleware now calls tenant_extension.authenticate()
- Sets _current_schema from TenantContext for multi-tenant isolation
- Returns 401 on AuthenticationError (same as REST API)
- DefaultTenantExtension: no auth (local dev)
- ApiKeyTenantExtension: validates against env var
- CloudTenantExtension: HMAC + DB lookup (production)

Adds tests for middleware auth rejection, acceptance, and schema routing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Address PR review: backwards compatibility for MCP auth

- Keep MCP_AUTH_TOKEN env var for legacy MCP servers
- Add authenticate_mcp() method to TenantExtension base class
  - Default implementation calls authenticate()
  - Extensions can override to opt-out of MCP auth
- Add mcp_auth_disabled config option to ApiKeyTenantExtension
  - Set HINDSIGHT_API_TENANT_MCP_AUTH_DISABLED=true to skip MCP auth
- Remove CloudTenantExtension from public docstring
- Add tests for legacy auth token and mcp_auth_disabled flag
- Update MCP docs with new auth configuration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add search_docs MCP tool for documentation search

Implements a new MCP tool that searches Hindsight documentation using
Vectorize RAG pipelines. The tool supports:
- Searching core (OSS) docs, cloud docs, or both
- Configurable number of results (1-10)
- Returns ranked results with URLs, similarity scores, and text snippets

New environment variables:
- HINDSIGHT_API_VECTORIZE_ORG_ID
- HINDSIGHT_API_VECTORIZE_API_TOKEN
- HINDSIGHT_API_VECTORIZE_CORE_PIPELINE_ID
- HINDSIGHT_API_VECTORIZE_CLOUD_PIPELINE_ID
- HINDSIGHT_API_VECTORIZE_API_BASE_URL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add documentation for search_docs MCP tool

- Add Vectorize environment variables to configuration.md
- Add search_docs tool to MCP server available tools
- Add reflect tool documentation (was missing)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add tests for search_docs MCP tool

Tests cover:
- DocsSource enum values and parsing
- _clean_text HTML stripping helper
- _search_vectorize_pipeline with mocked httpx
- Tool registration and function execution
- Source filtering (core/cloud/all)
- Result sorting by similarity
- Error handling for pipeline failures
- HTML cleaning in results
- Invalid source defaulting to 'all'

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Move search_docs to hindsight-cloud, add MCPExtension pattern

- Add MCPExtension base class for registering additional MCP tools
- Load MCPExtension in create_mcp_server when configured
- Remove search_docs tool (moved to hindsight-cloud CloudMCPExtension)
- Remove Vectorize config from hindsight-core
- Add tests for MCPExtension pattern
- Update docs to remove search_docs references

The MCPExtension pattern allows cloud (or any extension package) to
register additional MCP tools via:
  HINDSIGHT_API_MCP_EXTENSION=package.module:ExtensionClass

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Address PR review feedback

- Remove CloudTenantExtension mention from MCPMiddleware docstring
- Fix docs: clarify that ApiKeyTenantExtension must be explicitly enabled
- Revert changes to versioned docs (0.3 and 0.4) - synced automatically on release

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Format mcp.py line length

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 12:28:05 -07:00
Nicolò Boschi
0430588e32
fix: hindsight-embed profiles are not loaded correctly (#316)
* fix: hindsight-embed profiles are not loaded correctly

* fix: hindsight-embed profiles are not loaded correctly
2026-02-06 17:13:54 +01:00
Nicolò Boschi
2af0e08dba
doc: update claude-code usage terms (#315)
* doc: update claude-code usage terms

* doc: update claude-code usage terms

* doc: update claude-code usage terms
2026-02-06 16:53:12 +01:00
Nicolò Boschi
fa4cbf7ef2
fix(ci): resolve flaky test failures in api tests (#311)
* fix: resolve flaky test failures in api tests

Fixed 4 critical test failures that revealed real production issues:

1. test_sensory_dimension_preservation: Updated fact extraction prompt to
   clarify that sensory/emotional details ARE important to remember even if
   they seem small. The "6 months" filter was too aggressive and causing LLM
   to skip valid observations.

2. test_llm_provider_api_methods[openai-gpt-5]: Increased max_completion_tokens
   from 200 to 500 for tool calling tests. Non-nano models like gpt-5 were
   hitting token limits before completing tool calls.

3. test_reflect_chinese_content: Added prominent anti-hallucination warnings
   to reflect agent prompts. LLM was making up names (张飞, 张三, 赵信) instead
   of using the actual names from retrieved facts (张伟, 李明). Added explicit
   instructions at the very top of system prompts to NEVER fabricate names and
   to use EXACT names from retrieved data.

4. test_llm_provider_api_methods[groq-openai/gpt-oss-120b]: Skipped this model
   in tests as it consistently times out (>120s) due to slow Groq API responses.

All changes address real production code issues, not test flakiness.

* refactor: simplify anti-hallucination prompts and document groq issue

- Removed verbose anti-hallucination section with emojis/borders
- Moved core anti-hallucination rules to top of system prompts in clean format
- Kept essential rules: NEVER make up names/entities, ONLY use tool results
- Removed language override rule (directives can control language)
- Removed specific example (too prescriptive)

Groq gpt-oss-120b:
- Documented that API hangs on receive_response_body (Groq API bug)
- Skip is justified: headers received successfully but body never arrives
- This is gpt-oss-120b specific, not a general Groq provider issue

* fix: remove groq skip as requested

- Groq gpt-oss-120b may be slow but should not be skipped
- test_extensions.py::test_reflect_pre_hook_receives_all_parameters passes locally (50s)
- CI timeout appears to be from LLM producing malformed tool names (done<|channel|>commentary)
  which triggers retries and slows down the test

* fix: ensure unique timestamps for facts across different documents

The time offset logic was resetting to 0 for each new content_index, causing
all facts from different documents/conversations to have the same base timestamp
even when they should be distinguishable.

Changed to use absolute position (i) instead of relative position (i - content_fact_start)
so that:
- Content 0, Fact 0: offset = 0s
- Content 0, Fact 1: offset = 10s
- Content 1, Fact 0: offset = 20s (now unique!)
- Content 1, Fact 1: offset = 30s

This ensures facts from different batch-retained documents have unique timestamps
for proper temporal ordering in retrieval.

Fixes test_fact_ordering.py::test_multiple_documents_ordering

* fix: increase timeout for test_llm_provider_api_methods to 300s

The groq gpt-oss-120b model can be very slow (API hangs on response body),
taking >120s to complete. Increased timeout to 300s to prevent CI flakiness
while still catching real hangs.

This affects all provider/model combinations in the test, not just Groq,
but most complete in <30s so the increased timeout won't affect them.

* fix: skip structured output for groq gpt-oss-120b, reinforce date extraction

1. Groq gpt-oss-120b doesn't support response_format (structured output)
   - Returns 400 'json_validate_failed' error
   - Retries with exponential backoff caused 300s timeout
   - Skip test #3 (structured output) for this model

2. Reinforce date extraction prompt
   - Add CRITICAL instruction to extract absolute dates like 'March 15, 2024'
   - Helps prevent flaky test_extract_facts_with_absolute_dates failures
2026-02-06 13:56:59 +01:00
Nicolò Boschi
c4ef090a20
feat: support markdown in reflect and mental models (#307)
* feat: support markdown in reflect and mental models

* chore: regenerate clients and OpenAPI spec with markdown field descriptions
2026-02-06 10:49:13 +01:00
Nicolò Boschi
0d8d805832
ci: ensure backwards/forward compatibility of the API (#306) 2026-02-05 18:43:05 +01:00
Nicolò Boschi
278718dd84
fix: tagged directives should be applied to tagged mental models (#303)
* fix: tagged directives should be applied to tagged mental models

* test: add unit test for based_on structure

Verify that reflect returns the correct based_on structure with:
- directives as dicts (id, name, content) in based_on.directives
- mental models as MemoryFact objects in based_on.mental-models
- memories separated properly

This ensures directives and mental models are not mixed together
in the API response.
2026-02-05 13:22:56 +01:00
Hayden Rear
093ecff48d
fixed cast error (#300)
Signed-off-by: hayden.rear <hayden.rear@gmail.com>
2026-02-05 09:05:26 +01:00
Nicolò Boschi
85b9074f43 Release v0.4.9
- Update version to 0.4.9 in all components
- Regenerate OpenAPI spec and client SDKs
- Python packages: hindsight-api, hindsight-dev, hindsight-all, hindsight-litellm, hindsight-embed
- Python client: hindsight-clients/python
- TypeScript client: hindsight-clients/typescript
- Rust CLI: hindsight-cli
- Control Plane: hindsight-control-plane
- OpenClaw integration: hindsight-integrations/openclaw
- AI SDK integration: hindsight-integrations/ai-sdk
- Helm chart
- Sync documentation to version-0.4
2026-02-04 20:27:05 +01:00
Nicolò Boschi
7e339e1677
feat: ai sdk integration (#299)
* feat: ai sdk integration

* more fixes

* fix(security): mental model refresh tag-based security

- Mental model refresh now passes tags with all_strict matching
- Consolidation only triggers refresh for mental models with matching tags
- Consolidation filters related observations by tags (all_strict)
- Added tests to verify tag-based security boundaries
- Updated OpenAPI spec to include tags and text_preview in list_documents
- Added tags column to documents UI table

* chore: regenerate OpenAPI spec after rebase

* fix: improve consolidation prompt for contradiction handling and mental model refresh security

- Enhanced consolidation prompt to be more explicit about capturing temporal changes in contradictions
- Fixed mental model refresh security: tagged memories now only trigger refresh of mental models with matching tags
- Added stricter tag filtering to prevent cross-scope mental model refreshes

Fixes test_consolidation_merges_contradictions by improving LLM instructions to use temporal markers like "used to X, now Y" when merging contradictory facts.

Note: test_refresh_with_tags_only_accesses_same_tagged_models still needs investigation - REFLECT operation may need additional tag filtering.

* fix: mental model refresh security - proper tag filtering in search

Fixed tool_search_mental_models to properly handle all_strict tag matching mode by using the centralized build_tags_where_clause function. Previously, the function only handled "all" vs "any" modes and always included untagged mental models when using non-"all" modes.

This ensures that when a tagged mental model is refreshed with all_strict matching, it cannot access untagged mental models, preventing cross-scope information leakage.

Fixes test_refresh_with_tags_only_accesses_same_tagged_models.

Note: test_sensory_dimension_preservation is failing but this is a pre-existing issue on main branch - the LLM model (gpt-oss-20b) is not extracting facts from sensory text. Not related to security changes.

* chore: apply formatting from pre-commit hook

* fix: allow untagged mental models to be refreshed by any consolidation

Untagged mental models are considered "global" and should be refreshed
by any consolidation, regardless of whether tagged or untagged memories
were consolidated. This maintains security boundaries while allowing
global mental models to stay fresh.

When tagged memories are consolidated:
- Refresh mental models with matching tags (security boundary)
- Also refresh untagged mental models (they're global)
- DO NOT refresh mental models with different tags

When untagged memories are consolidated:
- Only refresh untagged mental models
- DO NOT refresh tagged mental models (security boundary)

Fixes test_consolidation_only_refreshes_matching_tagged_models.
2026-02-04 20:25:59 +01:00
Chris Bartholomew
dd621a69d0
Fix recall endpoint timeout handling and add query length validation (#298)
- Add MAX_QUERY_TOKENS (500) limit to prevent expensive operations on oversized queries
- Return 400 error with clear message when query exceeds token limit
- Add specific handling for TimeoutError to return 504 Gateway Timeout instead of 500
- Improves error messages for timeout scenarios
2026-02-04 17:26:25 +01:00
Nicolò Boschi
7097716204
feat: improve mental models ux on control plane (#297)
* feat: improve mental models ux on control plane

* feat: improve mental models ux on control plane

* gen

* feat(cli): add --id flag to mental model create command

* fix(cli): revert unused variable underscore prefix that breaks compilation

The underscore prefix on stdout/stderr variables was added to suppress
warnings, but these variables are actually used in assert messages,
causing compilation errors. Reverting to original names.
2026-02-04 15:49:03 +01:00
Nicolò Boschi
a43d208e93
fix: improve claude code and codex for /reflect (#285)
* fix: improve mental models response

* fix: improve mental models response

* fix

* improvemnts

* fix test
2026-02-04 13:34:45 +01:00
Nicolò Boschi
34d9188e13
fix: hide hf logging (#295) 2026-02-04 13:12:30 +01:00
Nicolò Boschi
21b25fe8fe Release v0.4.8
- Update version to 0.4.8 in all components
- Regenerate OpenAPI spec and client SDKs
- Python packages: hindsight-api, hindsight-dev, hindsight-all, hindsight-litellm, hindsight-embed
- Python client: hindsight-clients/python
- TypeScript client: hindsight-clients/typescript
- Rust CLI: hindsight-cli
- Control Plane: hindsight-control-plane
- OpenClaw integration: hindsight-integrations/openclaw
- Helm chart
- Sync documentation to version-0.4
2026-02-03 13:51:30 +01:00
Nicolò Boschi
749478d9f9
feat: improve openclaw and hindisght-embed params (#279)
* feat(openclaw): use hindsight-embed profiles for configuration

- Replace manual config file writing with hindsight-embed configure command
- Create and use 'openclaw' profile for all hindsight-embed operations
- Add support for openai-codex and claude-code providers
- Map special providers (openai-codex -> openai, claude-code -> anthropic)
- Simplify client by removing getEnv() method
- All CLI commands now use --profile openclaw flag
- Add get_cli_profile_override() function to cli.py for profile_manager

* feat: improve openclaw and hindisght-embed params

* feat: improve openclaw and hindisght-embed params

* feat(embed): remove daemon.lock, add profile-specific logs and --merge flag

* fix(embed): restore metadata.json functionality for profile tests

- Restore ProfileMetadata class and metadata tracking
- Fix profile manager create_profile to support both (name, config) and (name, port, config) signatures
- Auto-allocate ports when not provided in configure command
- Fix --profile flag parsing (was consumed by parent parser)
- All 47 hindsight-embed tests now pass

* fix(embed): support HINDSIGHT_EMBED_LLM_* env vars for backward compatibility

- configure command now accepts both HINDSIGHT_API_LLM_* and HINDSIGHT_EMBED_LLM_* prefixes
- Fixes test_configure_without_profile_flag test
- All 47 hindsight-embed tests pass

* style(embed): apply ruff formatting to cli.py

* fix(embed): simplify test.sh to verify hindsight-embed availability via uv

Removed CLI installation code from smoke test. The test now simply verifies
that hindsight-embed command is available via `uv run`, which is all that's
needed for CI to pass. This fixes the test-embed check that was failing with
"ERROR: hindsight CLI not found".

* fix(embed): remove hindsight-embed availability check from test.sh

The verification step was failing in CI because hindsight-embed --version
doesn't work without configuration. Since pytest tests already verify the
package is installed (47 tests passed), we don't need this check. The smoke
test itself will verify functionality by running retain/recall commands.

* chore(embed): add comment to test.sh to trigger CI

* fix(embed): use HINDSIGHT_API_LLM_* env vars consistently

Remove support for HINDSIGHT_EMBED_LLM_* variables to align with
the standard HINDSIGHT_API_LLM_* naming convention used across the codebase.

Changes:
- Update get_config() to only check HINDSIGHT_API_LLM_* variables
- Update _do_configure_from_env() to remove HINDSIGHT_EMBED_LLM_* fallbacks
- Update test.sh to check for HINDSIGHT_API_LLM_API_KEY
- Update CI workflow (test-embed job) to set HINDSIGHT_API_LLM_* env vars
2026-02-03 09:39:04 +01:00
Chris Bartholomew
96f0e54efa
Fix: load operation validator extension in worker process (#280)
The worker was not loading the OperationValidatorExtension, so
operation validation was silently skipped for all async operations
(e.g. refresh_mental_model triggered after consolidation). The API
server already loaded this extension but the worker entry point was
missing it.
2026-02-02 14:45:40 -05:00
Nicolò Boschi
382550690a
fix: custom pg schema is not reliable (#278)
* fix: custom pg schema is not reliable

* fix

* fix

* fix: WorkerPoller now always has tenant extension

Ensures WorkerPoller follows same pattern as MemoryEngine - always
creates a DefaultTenantExtension if none is provided, preventing
NoneType errors when calling list_tenants().

Fixes test failures in test_worker.py

* fix: DefaultTenantExtension honors explicit schema parameter

Allows WorkerPoller's schema parameter to be passed through to
DefaultTenantExtension via config dict, maintaining backward
compatibility for tests that use schema parameter without
providing a tenant extension.

Fixes test_poller_with_custom_schema test failure.
2026-02-02 15:33:50 +01:00
Nicolò Boschi
6c7f057e9d
feat(embed): add hindisght-embed profiles (#277)
* feat(embed): add hindisght-embed profiles

* ci: run pytest tests for hindsight-embed in CI

- Add pytest test run step to test-embed job
- This ensures profile tests (37 tests) are run in CI
- Smoke test still runs after pytest tests

* feat(embed): use 'default' profile name consistently

- Configure command now shows "Profile 'default' configured successfully!"
- Profile list shows "default" instead of empty string
- Profile show displays "default" consistently
- All output now uses "default" label for backward-compatible config
- Added port display for default profile in all commands

* fix(embed): replace requests with httpx in profile_manager

- Use httpx.Client() instead of requests.get() for daemon health check
- Update test mock to use httpx.Client instead of requests.get
- Fixes ModuleNotFoundError in CI (requests not in dependencies)
2026-02-02 14:38:06 +01:00
Nicolò Boschi
539190b69e
feat: support for codex and claude-code as llm (#276)
* feat: support for codex and claude-code as llm

* Remove refactoring plan file

* Consolidate Anthropic tests into main LLM provider test suite

- Add Anthropic models (Sonnet, Opus, Haiku) to MODEL_MATRIX
- Remove separate test_anthropic_provider.py file
- All Anthropic models now tested with standard memory operations

* Add provider-specific default models

Each LLM provider now has a sensible default model that's used when
HINDSIGHT_API_LLM_MODEL is not explicitly set. This simplifies
configuration - users can specify just the provider and API key.

Changes:
- Add PROVIDER_DEFAULT_MODELS mapping in config.py
- Update config logic to use provider defaults for both global and
  per-operation LLM configs
- Add comprehensive tests for provider default model selection
- Document provider defaults in models.md

Example usage:
  export HINDSIGHT_API_LLM_PROVIDER=anthropic
  export HINDSIGHT_API_LLM_API_KEY=sk-ant-xxx
  # Automatically uses claude-sonnet-4-20250514

Provider defaults:
  - openai: gpt-5-mini
  - anthropic: claude-sonnet-4-20250514
  - gemini: gemini-2.5-flash
  - groq: openai/gpt-oss-120b
  - ollama: gemma3:12b
  - lmstudio: local-model
  - vertexai: gemini-2.0-flash-001
  - openai-codex: o3-mini
  - claude-code: claude-sonnet-4-20250514
  - mock: mock-model

* Update provider default models

- openai: gpt-5-mini -> o3-mini
- anthropic: claude-sonnet-4-20250514 -> claude-haiku-4-5-20251001
- openai-codex: o3-mini -> gpt-5.2-codex
- claude-code: claude-sonnet-4-20250514 -> claude-sonnet-4-5-20250929

Updated tests and documentation to reflect new defaults.

* Move OpenAI Codex and Claude Code setup to models.md

Moved detailed setup instructions for OpenAI Codex and Claude Code from
configuration.md to models.md where they better fit with model-specific
documentation.

Changes:
- Move "OpenAI Codex Setup" section from configuration.md to models.md
- Move "Claude Code Setup" section from configuration.md to models.md
- Add cross-reference tip in configuration.md pointing to models.md
- Update default model in Claude Code example to claude-sonnet-4-5-20250929
- Keep basic provider examples in configuration.md for quick reference

This makes the configuration.md page more focused on environment
variables while models.md contains provider-specific setup details.
2026-02-02 12:54:44 +01:00
Nicolò Boschi
1499ce5549
feat: print version during startup (#275)
* feat: print version during startup

* feat: print version during startup
2026-02-02 12:40:45 +01:00
Chris Bartholomew
44d912533c
Propagate request context through async task payloads (#273)
The batch_retain and consolidation task handlers created internal
RequestContext objects without tenant_id or api_key_id. This meant
downstream operations (consolidation, mental model refreshes) triggered
by async workers lost the original caller's request context.

Fix by passing tenant_id and api_key_id through the task payload dict
in submit_async_retain and submit_async_consolidation, then restoring
them in the corresponding handlers (_handle_batch_retain,
_handle_consolidation).
2026-02-02 12:39:46 +01:00
Chris Bartholomew
35127d5f8b
Add MentalModelRefreshContext and pre-operation validation for mental model create/refresh (#271)
Wire up validate_mental_model_refresh hook in the HTTP routes for both
create and refresh mental model endpoints, allowing extensions to reject
operations (e.g. insufficient credits) before queuing async LLM work.
2026-02-01 16:16:20 -05:00
Nicolò Boschi
86c733c10e Release v0.4.7
- Update version to 0.4.7 in all components
- Regenerate OpenAPI spec and client SDKs
- Python packages: hindsight-api, hindsight-dev, hindsight-all, hindsight-litellm, hindsight-embed
- Python client: hindsight-clients/python
- TypeScript client: hindsight-clients/typescript
- Rust CLI: hindsight-cli
- Control Plane: hindsight-control-plane
- OpenClaw integration: hindsight-integrations/openclaw
- Helm chart
- Sync documentation to version-0.4
2026-01-31 18:40:32 +01:00
Nicolò Boschi
615509011e Revert "fix release script"
This reverts commit af6bd1b5e1.
2026-01-31 18:39:36 +01:00
Nicolò Boschi
af6bd1b5e1 fix release script 2026-01-31 18:04:21 +01:00
Nicolò Boschi
4b57b82301
feat(hindsight-embed): external API support + OpenClaw fixes (#263, #264) (#265)
* feat(hindsight-embed): external API support + OpenClaw fixes

Adds comprehensive external API support and fixes critical OpenClaw plugin issues.

**External API Support:**
- Add HINDSIGHT_EMBED_API_URL to connect to external Hindsight API servers
- Add HINDSIGHT_EMBED_API_TOKEN for Bearer token authentication
- Add HINDSIGHT_EMBED_API_DATABASE_URL for custom PostgreSQL databases
- Skip daemon startup when external API URL is configured
- Add 10 comprehensive unit tests for external API scenarios

**OpenClaw Plugin Fixes:**
- Fix #263: Port mismatch (DEFAULT_PORT 8888 → 8889)
- Fix #264: Add daemon recovery after OpenClaw SIGUSR1 restarts
- Fix OpenRouter support: Pass HINDSIGHT_API_LLM_BASE_URL to daemon
- Fix macOS crashes: Auto-set FORCE_CPU flags for MPS/Metal issues

**LLM Configuration Refactor:**
- Auto-detect provider from standard env vars (OPENAI_API_KEY, etc.)
- Support explicit override via HINDSIGHT_API_LLM_* env vars
- Update model defaults (gemini-2.5-flash, openai/gpt-oss-20b)
- Remove provider-specific base URL support (only HINDSIGHT_API_LLM_BASE_URL)

**Documentation Updates:**
- Rewrite OpenClaw integration docs with crystal clear examples
- Add external API usage examples
- Add OpenRouter free model examples
- Update Quick Start with simplified provider setup

Closes #263, Closes #264

* docs(openclaw): streamline docs and add config inspection

- Remove duplicate/verbose sections (468 → 216 lines)
- Add section showing how to check ~/.hindsight/embed config file
- Add daemon status checking commands
- Keep only essential configuration examples
- Consolidate troubleshooting sections

* fix(test): update daemon health check port from 8889 to 8888

The test was checking port 8889 but we changed the daemon to use port 8888.
2026-01-31 17:02:13 +01:00
Chris Bartholomew
9c3fda74e2
Add extension hooks for mental model operations (#260)
Add dataclasses and hook methods to OperationValidatorExtension for
tracking mental model operations:

- MentalModelGetContext/Result: context and result for GET operations
- MentalModelRefreshResult: result for refresh operations with token counts
- validate_mental_model_get: pre-operation validation hook
- on_mental_model_get_complete: post-GET completion hook
- on_mental_model_refresh_complete: post-refresh completion hook

Invoke hooks in http.py (GET endpoint) and memory_engine.py (refresh).
Add tests verifying hooks are called with correct parameters.
2026-01-31 09:30:53 -05:00
Anton Evseev
ef9d3a15cb
fix: sanitize null bytes from text fields before PostgreSQL insertion (#238)
* fix: sanitize null bytes from text fields before PostgreSQL insertion

Fixes 'invalid byte sequence for encoding UTF8: 0x00' error during batch retain

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: consolidate _sanitize_text into fact_extraction module

Address review feedback: reuse existing _sanitize_text from fact_extraction
instead of duplicating in fact_storage.

The consolidated function now handles both:
- Null bytes (\x00) for PostgreSQL compatibility
- Unicode surrogates (U+D800-U+DFFF) for UTF-8/LLM API compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 09:16:23 +01:00
Nicolò Boschi
d788a55e28
fix: worker doesn't pick up correct default schema (#259) 2026-01-31 09:15:59 +01:00
Nicolò Boschi
c8ae82d62f Release v0.4.6
- Update version to 0.4.6 in all components
- Regenerate OpenAPI spec and client SDKs
- Python packages: hindsight-api, hindsight-dev, hindsight-all, hindsight-litellm, hindsight-embed
- Python client: hindsight-clients/python
- TypeScript client: hindsight-clients/typescript
- Rust CLI: hindsight-cli
- Control Plane: hindsight-control-plane
- OpenClaw integration: hindsight-integrations/openclaw
- Helm chart
- Sync documentation to version-0.4
2026-01-30 17:37:50 +01:00
Nicolò Boschi
fe88bdf704 Release v0.4.5
- Update version to 0.4.5 in all components
- Python packages: hindsight-api, hindsight-dev, hindsight-all, hindsight-litellm, hindsight-embed
- Python client: hindsight-clients/python
- TypeScript client: hindsight-clients/typescript
- Rust CLI: hindsight-cli
- Control Plane: hindsight-control-plane
- OpenClaw integration: hindsight-integrations/openclaw
- Helm chart
- Sync documentation to version-0.4
2026-01-30 14:55:50 +01:00
Nicolò Boschi
cbb8fc6723
fix: retain async with timestamp might fails (#253) 2026-01-30 14:54:32 +01:00
Nicolò Boschi
c33b9b8bb2 Release v0.4.4
- Update version to 0.4.4 in all components
- Python packages: hindsight-api, hindsight-dev, hindsight-all, hindsight-litellm, hindsight-embed
- Python client: hindsight-clients/python
- TypeScript client: hindsight-clients/typescript
- Rust CLI: hindsight-cli
- Control Plane: hindsight-control-plane
- OpenClaw integration: hindsight-integrations/openclaw
- Helm chart
- Sync documentation to version-0.4
2026-01-30 13:05:07 +01:00
Nicolò Boschi
35f0984b72
fix: retain async fails if timestamp is set (#251)
* fix: retain async fails if timestamp is set

* fix: rename openclawd to openclaw
2026-01-30 13:04:33 +01:00
Nicolò Boschi
7d3ac5ddb9 Release v0.4.3
- Update version to 0.4.3 in all components
- Python packages: hindsight-api, hindsight-dev, hindsight-all, hindsight-litellm, hindsight-embed
- Python client: hindsight-clients/python
- TypeScript client: hindsight-clients/typescript
- Rust CLI: hindsight-cli
- Control Plane: hindsight-control-plane
- OpenClawd integration: hindsight-integrations/openclawd
- Helm chart
- Sync documentation to version-0.4
2026-01-30 11:09:43 +01:00
Nicolò Boschi
f4f86e3842
fix: deadlock in worker polling (#250)
* fix: deadlock in worker polling

* fix: deadlock in worker polling

* fixes
2026-01-30 11:09:29 +01:00
Nicolò Boschi
ab5e31f203
chore: remove dead code (#245)
* chore: remove dead code

* chore: remove extract_opinions from test and regenerate openapi

- Remove extract_opinions parameter from test_fact_extraction_analysis
- Regenerate OpenAPI spec after removing entity observations code

* chore: update generated files and apply formatting

- Regenerate Python and TypeScript client SDKs after main merge
- Apply ruff formatting to llm_wrapper.py

* fix: accept and filter deprecated 'opinion' fact type in recall

The dead code removal eliminated support for the 'opinion' fact type,
but existing clients may still pass it. Instead of rejecting it with
a ValueError, silently filter it out before validation to maintain
backward compatibility.
2026-01-30 09:16:32 +01:00
Anton Evseev
0da77ce2c9
feat(mcp): add Bearer token authentication and tenant auth propagation (#241)
* feat(mcp): add Bearer token authentication support

Add HINDSIGHT_API_MCP_AUTH_TOKEN environment variable to enable
authentication for MCP endpoint. When set, all requests must include
a valid Authorization header (Bearer token or direct token).

If not set, MCP endpoint remains open for backwards compatibility
with local development environments.

* fix: propagate Bearer token from MCP middleware to tools for tenant auth

MCP tools were creating RequestContext() without api_key, causing
"Invalid API key" errors when tenant extension validates requests.
Now the Bearer token is extracted in middleware, stored in a context
variable, and passed through to all MCP tool RequestContext instances.
2026-01-30 09:08:18 +01:00
Anton Evseev
d57e8639c5
fix(auth): skip tenant auth for all internal background tasks (#240)
Previously, _authenticate_tenant only skipped extension auth for
internal requests when _current_schema was set to a non-public schema.
This caused async HTTP retain (document upload with async_processing=True)
to fail with AuthenticationError because the worker had no API key and
the schema was "public".

Remove the public-schema guard since internal tasks were already
authenticated at submission time. The worker sets _current_schema from
the task's _schema field for tenant schemas, and it defaults to "public"
for public schema tasks — both are valid.
2026-01-30 09:07:23 +01:00
Chris Bartholomew
49ae55af03
Switch Vertex AI provider to native genai SDK (#242)
Replace the OpenAI-compatible endpoint approach with the native
google-genai SDK for Vertex AI. This eliminates the custom token
refresher, TokenInjectingTransport, and async lifecycle complexity
while also removing the 8192 output token cap that the OpenAI
endpoint enforced.

Changes:
- vertexai provider now uses genai.Client(vertexai=True) instead of
  AsyncOpenAI with token-injecting transport
- Routes through existing _call_gemini/_call_with_tools_gemini paths
- Strips google/ prefix from model names (native SDK uses bare names)
- Preserves service account key auth via credentials parameter
- Delete vertexai_token_refresher.py (no longer needed)
- Strip markdown code fences in consolidator JSON parsing
- Rewrite vertexai tests for native SDK integration
2026-01-30 08:35:59 +01:00
Nicolò Boschi
c2ac7d0440
feat: support vertex as llm provider (#233)
* feat: support vertex as llm provider

* fix

* fix: add uv index-strategy to resolve dependency conflicts with pytorch index

When using pytorch index for faster torch downloads in CI,
filelock dependency resolution was failing because pytorch index
only has older versions. Adding unsafe-best-match strategy allows
uv to search all configured indexes.

Also fix type checking warnings from ty.

* fix: add index-strategy to root pyproject.toml for workspace-level uv resolution

* chore: regenerate client SDKs after Vertex AI support
2026-01-29 16:13:57 -05:00
Chris Bartholomew
657fe023b2
fix: run migrations on tenant schemas at startup and harden worker poller (#237)
Tenant schemas were never migrated when new migrations were deployed.
Only the public schema was migrated at startup, and tenant schemas only
got migrations when first provisioned. This meant existing tenants
missed any new columns (e.g. task_payload, worker_id, claimed_at on
async_operations), causing the worker poller to crash silently.

Changes:
- Run migrations on all existing tenant schemas at startup when a
  tenant_extension is configured. Each schema migration is wrapped in
  try/except so one failure doesn't block others.
- Add try/except in WorkerPoller.recover_own_tasks() so a broken
  schema doesn't prevent the polling loop from starting.
- Add try/except in WorkerPoller._claim_batch_for_schema() so a
  broken schema doesn't prevent claiming tasks from other schemas.
2026-01-29 15:03:20 -05:00
Chris Bartholomew
9c95a1ac1d
fix: pass tenant extension to worker MemoryEngine for correct schema context (#236)
The worker loaded the tenant extension for the poller (schema discovery)
but did not pass it to MemoryEngine. When execute_task set _current_schema
via the _schema field, _authenticate_tenant would immediately reset it to
"public" because self._tenant_extension was None, causing all worker writes
to land in the public schema instead of the tenant schema.

Move load_extension() before MemoryEngine creation and pass
tenant_extension to the constructor.
2026-01-29 18:35:38 +01:00
Nicolò Boschi
15540075b2 Release v0.4.2
- Update version to 0.4.2 in all components
- Python packages: hindsight-api, hindsight-dev, hindsight-all, hindsight-litellm, hindsight-embed
- Python client: hindsight-clients/python
- TypeScript client: hindsight-clients/typescript
- Rust CLI: hindsight-cli
- Control Plane: hindsight-control-plane
- Helm chart
- Sync documentation to version-0.4
2026-01-29 17:54:19 +01:00
Nicolò Boschi
3f211f0729
feat: add more config options for llm retries (#234) 2026-01-29 17:50:43 +01:00