rename to hindsight - #2
Merged
Merged
Conversation
nicoloboschi
force-pushed
the
renaming-pre-launch
branch
from
November 25, 2025 09:11
b0fa0c3 to
31a53c0
Compare
nicoloboschi
had a problem deploying
to
github-pages
November 25, 2025 10:35 — with
GitHub Actions
Failure
nicoloboschi
temporarily deployed
to
github-pages
November 25, 2025 10:42 — with
GitHub Actions
Inactive
nicoloboschi
temporarily deployed
to
github-pages
November 25, 2025 16:01 — with
GitHub Actions
Inactive
nicoloboschi
temporarily deployed
to
github-pages
November 25, 2025 18:31 — with
GitHub Actions
Inactive
|
@nicoloboschi just noticed you're using Hey API – feedback is always welcome! |
DK09876
added a commit
that referenced
this pull request
Mar 19, 2026
- Fix #2: Add per-bank asyncio.Lock to _ensure_bank for concurrency safety - Fix #3: Clamp search score to max(0.0, ...) to prevent negative values - Fix #4: Implement suffix matching in _handle_list_namespaces - Fix #5: Truncate namespaces to max_depth instead of filtering (per BaseStore contract) - Fix #6: Remove list_namespaces/alist_namespaces overrides — let base class handle prefix=/suffix= kwargs - Fix #7: Document ephemeral namespace tracking and get() limitations in class docstring - Fix #8: Add stable ID to recall node SystemMessage, document ordering behavior - Fix #9: Change budget/max_tokens/recall_tags_match defaults to None so global config fallback works - Fix #10: Conditionally populate __all__ so import * works without langgraph installed - Fix #11: Bump langgraph lower bound from >=0.3.0 to >=0.5.0 - Fix #12: Extract _resolve_client to shared _client.py module Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nicoloboschi
pushed a commit
that referenced
this pull request
Mar 20, 2026
* feat: add LangGraph integration with tools, nodes, and store patterns Add hindsight-langgraph SDK providing three integration patterns: - Tools: retain/recall/reflect as LangChain tools for ReAct agents - Nodes: automatic memory injection and storage as graph steps - Store: LangGraph BaseStore implementation for checkpoint-based memory Fix: remove `from __future__ import annotations` in nodes.py which prevented LangGraph from passing RunnableConfig to node functions (runtime type inspection saw string annotations instead of actual types). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: register langgraph with independent versioning system - Set version to 0.1.0 (integrations are versioned independently) - Add langgraph to VALID_INTEGRATIONS in release-integration.sh - Add changelog page for langgraph integration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove manual cookbook recipe page The sync-cookbook script will auto-generate this from the notebook in hindsight-cookbook once PR #17 is merged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: comprehensive improvements to langgraph integration Code fixes: - Retain node only stores latest messages instead of all history (prevents duplicates) - Handle multimodal msg.content (list type) in nodes - Fix store docstring separator "/" → "." - Apply search filters before pagination in store - Add ttl parameter to store.aput for LangGraph BaseStore compat - Fix _ensure_bank to not cache failed bank creations - Fix falsy value bugs (or → is not None) in tools - Remove from __future__ import annotations from all files - Consistent default budget="mid" across tools/nodes/store - Bump langgraph floor to >=0.3.0, remove duplicate dev deps Docs fixes: - Fix broken Cloud client example (base_url is required) - Complete API reference tables with all parameters - Add Limitations and Notes section (async-only store, etc.) - Add Requirements section - Fix broken cookbook link and Cloud claim in blog post All 61 unit tests pass. E2E tested against Hindsight Cloud: tools, nodes, store, configure(), multimodal content. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove blog post (lives in hindsight-marketing-content) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove Hindsight Cloud section from langgraph docs Keep OSS docs self-hosted-first, consistent with other integration docs (crewai, pydantic-ai, agno). Cloud setup details live in the cookbook notebooks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: explicitly mention LangChain compatibility in langgraph integration The tools pattern (create_hindsight_tools) only depends on langchain-core and works with plain LangChain via bind_tools() — no LangGraph required. Update docs to make this clear with both LangGraph and LangChain quick start examples. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review findings 1. Guard manual test files with if __name__ == "__main__" so pytest doesn't collect and execute them during test runs 2. Remove semantic fallback in HindsightStore.aget() — only return exact document_id matches, not unrelated semantic search hits 3. Make langgraph an optional dependency — tools pattern only needs langchain-core. Install with pip install hindsight-langgraph[langgraph] for nodes and store patterns. Lazy imports with clear error messages. 4. Clean up README to be self-hosted-first, consistent with other integration docs 5. Update docs requirements section to reflect optional langgraph dep Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback for langgraph integration - Fix #2: Add per-bank asyncio.Lock to _ensure_bank for concurrency safety - Fix #3: Clamp search score to max(0.0, ...) to prevent negative values - Fix #4: Implement suffix matching in _handle_list_namespaces - Fix #5: Truncate namespaces to max_depth instead of filtering (per BaseStore contract) - Fix #6: Remove list_namespaces/alist_namespaces overrides — let base class handle prefix=/suffix= kwargs - Fix #7: Document ephemeral namespace tracking and get() limitations in class docstring - Fix #8: Add stable ID to recall node SystemMessage, document ordering behavior - Fix #9: Change budget/max_tokens/recall_tags_match defaults to None so global config fallback works - Fix #10: Conditionally populate __all__ so import * works without langgraph installed - Fix #11: Bump langgraph lower bound from >=0.3.0 to >=0.5.0 - Fix #12: Extract _resolve_client to shared _client.py module Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address remaining review gaps for langgraph integration - Add output_key parameter to create_recall_node for prompt ordering control - Add prefix/suffix/combined filter tests for list_namespaces - Add output_key unit tests (memory text, none on empty, none on error) - Remove unused imports and backward-compat alias in tools.py - Update docs with output_key usage example and API reference Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: relax langgraph version constraint to >=0.3.0 Research confirmed all required APIs (BaseStore, SearchItem, Result, GetOp, PutOp, SearchOp, ListNamespacesOp) are available since langgraph-checkpoint 2.0.7, which maps to langgraph >=0.2.63. Using >=0.3.0 as a clean semver boundary — >=0.5.0 was unnecessarily conservative and excluded many compatible versions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
3 tasks
This was referenced May 25, 2026
nicoloboschi
added a commit
that referenced
this pull request
Jun 3, 2026
… always shown The residual near-duplicate observations were recall misses, not LLM errors: the existing near-identical observation (the merge 'twin') is semantic rank #1 for the new fact, but shares no source-fact graph link and little lexical overlap, so RRF averaged it below the per-fact recall budget (512 tokens, ~8 observations) and the LLM never saw it -> created a duplicate. The cross-encoder demoted it the same way (semantic #1 -> reranked #37). Add round-robin interleave fusion: take each retrieval arm's #1, then each #2, ... (semantic, bm25, graph, temporal), de-duplicating, until the budget fills. This guarantees every arm's top hit a slot, so the semantic-#1 twin is always shown and the LLM UPDATEs instead of creating a duplicate. Replace the recall 'rerank: bool' / ad-hoc passthrough with a single named 'reranking' strategy: 'cross_encoder' (default), 'rrf', 'interleave'. Consolidation dedup recall uses 'interleave'. For interleave the fusion order is authoritative — combined scoring's recency/temporal re-sort is skipped (that re-sort is what buried the twin). Measured on an English translation of the hermes transcript (removes the cross-lingual embedding confound): near-dup observations 4% (@0.97) -> 0% at both 1/10 and 1/4 cuts, coverage 89% -> 94%, no false merges (heavy observations are coherent single themes; distinct facets stay separate).
nicoloboschi
added a commit
that referenced
this pull request
Jun 3, 2026
… always shown The residual near-duplicate observations were recall misses, not LLM errors: the existing near-identical observation (the merge 'twin') is semantic rank #1 for the new fact, but shares no source-fact graph link and little lexical overlap, so RRF averaged it below the per-fact recall budget (512 tokens, ~8 observations) and the LLM never saw it -> created a duplicate. The cross-encoder demoted it the same way (semantic #1 -> reranked #37). Add round-robin interleave fusion: take each retrieval arm's #1, then each #2, ... (semantic, bm25, graph, temporal), de-duplicating, until the budget fills. This guarantees every arm's top hit a slot, so the semantic-#1 twin is always shown and the LLM UPDATEs instead of creating a duplicate. Replace the recall 'rerank: bool' / ad-hoc passthrough with a single named 'reranking' strategy: 'cross_encoder' (default), 'rrf', 'interleave'. Consolidation dedup recall uses 'interleave'. For interleave the fusion order is authoritative — combined scoring's recency/temporal re-sort is skipped (that re-sort is what buried the twin). Measured on an English translation of the hermes transcript (removes the cross-lingual embedding confound): near-dup observations 4% (@0.97) -> 0% at both 1/10 and 1/4 cuts, coverage 89% -> 94%, no false merges (heavy observations are coherent single themes; distinct facets stay separate).
benfrank241
added a commit
that referenced
this pull request
Jun 11, 2026
…(review notes 2 & 4) #2 — Webhook signature verification (was: relying only on Zapier's unguessable URL): - performSubscribe now generates a random 32-byte secret and registers it with the webhook; the secret is stored in subscribeData. - perform verifies the X-Hindsight-Signature: sha256=<hmac> header (HMAC-SHA256 of the raw body) and rejects mismatches. (Corrected the header name — the API sends X-Hindsight-Signature, not X-Webhook-Signature; body is delivered byte-for-byte via content=, so the recomputed HMAC matches.) #4 — Optional 'Process asynchronously' toggle on Retain (default false). Lets users with very large content avoid Zapier's action timeout; pairs with the Retain Completed trigger. 17 unit tests pass (added valid/invalid signature cases); zapier validate clean.
benfrank241
added a commit
that referenced
this pull request
Jun 15, 2026
…#2119) * feat(zapier): add Hindsight Zapier app (actions + REST Hook triggers) A Zapier Platform CLI app that brings Hindsight memory into Zaps. Actions: - Retain Memory (create) -> POST /v1/default/banks/{bank}/memories - Recall Memories (search) -> POST .../memories/recall - Reflect (search) -> POST .../reflect Triggers (instant, via Hindsight's webhook API — subscribe POSTs /webhooks, unsubscribe DELETEs it): - Retain Completed, Consolidation Completed, Memory Defense Triggered Auth: API key as Bearer token, Cloud default with self-hosted override; the Bank field is a dynamic dropdown from GET /v1/default/banks. Built on zapier-platform-core 19; 'private': true so the npm release path can never publish it (Zapier publishing is manual via zapier push/promote, not release-integration.yml — and zapier is intentionally NOT in VALID_INTEGRATIONS). Adds test-zapier-integration CI job (npm install -> zapier validate -> npm test) and a repo README row. 15 mocha/nock unit tests; 'zapier validate' is structurally clean. Docs-site gallery card + doc page + icon are a follow-up (need the official Zapier brand asset; omitted here to keep build-docs green). * fix(zapier): make apiKey optional for no-auth self-hosted + prettier-clean - authentication.js: apiKey now optional (required: false). The middleware only adds the Bearer header when a key is present, so you can connect to a self-hosted instance running without auth by leaving it blank; Cloud still requires a working key (blank -> 401 fails the connection test). - README: document self-hosted / localhost usage, the optional key, and correct the CLI binary name to 'zapier-platform' (v19 renamed it from 'zapier'); show the .env approach so 'zapier invoke' needs no global install. - Run prettier across the integration (fixes pre-existing format drift that was failing verify-generated-files on this branch). zapier validate still structurally sound; 15 tests pass. * fix(zapier): correct reflect answer field + recall output shape (found via live test) Extensive live testing against Hindsight Cloud surfaced two response-shape bugs the mocked unit tests missed (they mocked the wrong shapes): - reflect: the synthesized answer is in the response's `text` field, not `answer`. searches/reflect read `data.answer` (undefined), so a Zap got no answer. Now reads `data.text` and surfaces it as `answer`. Test mock fixed to use the real `text` field so it actually guards this. - recall: results carry no numeric `score`, and the fact-type field is `type` (not `fact_type`). Corrected the sample + outputFields so the Zap editor only advertises fields that actually populate; test mock made realistic. Verified live end-to-end: auth, bank dropdown, retain (full + minimal), recall (real fact extraction), reflect (now returns the grounded answer), and the webhook subscribe/list/delete lifecycle. 15 unit tests pass; zapier validate clean. * docs(zapier): correct .env auth-field prefix to authData_ in README zapier invoke reads .env auth fields with the authData_ prefix (e.g. authData_apiKey, authData_apiUrl), not bare apiKey/apiUrl. Confirmed against a working local .env during live testing. * docs(zapier): add integrations gallery card + doc page - gallery entry in integrations.json (id zapier, official, category framework) - doc page docs-integrations/zapier.md (actions + REST Hook triggers, setup) - official Zapier logo at static/img/icons/zapier.png check-integrations passes (forward: entry → doc page); JSON valid; prettier-clean. * feat(zapier): verify webhook HMAC signatures + optional async retain (review notes 2 & 4) #2 — Webhook signature verification (was: relying only on Zapier's unguessable URL): - performSubscribe now generates a random 32-byte secret and registers it with the webhook; the secret is stored in subscribeData. - perform verifies the X-Hindsight-Signature: sha256=<hmac> header (HMAC-SHA256 of the raw body) and rejects mismatches. (Corrected the header name — the API sends X-Hindsight-Signature, not X-Webhook-Signature; body is delivered byte-for-byte via content=, so the recomputed HMAC matches.) #4 — Optional 'Process asynchronously' toggle on Retain (default false). Lets users with very large content avoid Zapier's action timeout; pairs with the Retain Completed trigger. 17 unit tests pass (added valid/invalid signature cases); zapier validate clean.
This was referenced Jul 13, 2026
nicoloboschi
added a commit
that referenced
this pull request
Jul 24, 2026
…e hang)
Retain hung forever on the Oracle backend: every retain test burned its 120s
client timeout while the server sat idle, so test-python-client-oracle and
test-typescript-client-oracle only ever reached ~5% of the suite before the
30-minute job limit.
The server was not slow — it was deadlocked. flush_pending_stats() acquires
its own connection, but it was being called while the enclosing
acquire_with_retry(...) block still held one:
async with acquire_with_retry(pool) as conn: # conn checked out
async with conn.transaction(): # SAVEPOINT only
...write facts/entities...
await entity_resolver.flush_pending_stats() # takes a 2nd connection
oracledb does not autocommit and OracleConnection.transaction() is only a
SAVEPOINT, so the write is committed by OracleBackend.acquire() when its block
exits. Connection #2's `UPDATE entities ...` therefore waits on row locks held
by the still-open connection #1, which cannot commit until the call returns —
a circular wait. Oracle never reports ORA-00060 because session #1 is blocked
in Python, not on the database, so it hangs indefinitely instead of erroring.
Move the flush after the acquire block in all three call sites (streaming
retain, delta retain, transfer importer), which is what its own docstring
already required ("must be called AFTER the retain transaction commits") and
which PostgreSQL satisfied only by accident via asyncpg autocommit.
Guarded with an AST lint test rather than a behavioural one: the deadlock
cannot be reproduced against PostgreSQL, which is what the suite runs on.
nicoloboschi
added a commit
that referenced
this pull request
Jul 24, 2026
…ain deadlock (#2948) * ci(oracle): free runner disk space before Oracle jobs The three Oracle jobs run the Oracle 23ai `free` service image, which together with the Python ML deps (torch) exhausts the runner's ~14 GB root disk. Two symptoms, one cause: - uv fails to extract a wheel with "No space left on device (os error 28)" (fast ~2 min failure), and - a near-full disk starves I/O badly enough to trip the 30-minute job timeout. test-python-client-oracle and test-typescript-client-oracle have been red on every open PR (#2941, #2942, #2943) from this, independent of the code under test. Reclaim ~20 GB of preinstalled tooling (the same jlumbroso action the Docker build job already uses) before the Oracle setup step. docker-images stays false here: unlike the Docker build job, the Oracle service container is already running by the time steps execute, so pruning images could disrupt it. The savings come from the tool cache, Android SDK, .NET, Haskell, large apt packages and swap. * ci(oracle): trim disk reclaim to the fast, high-yield options The first pass enabled every reclaim, which cost ~4 minutes of job time — counterproductive on jobs that are already fighting a 30-minute limit. android + dotnet + haskell + swap are a few rm -rf's worth ~16-21 GB, which is ample headroom for the Oracle image plus torch. Dropped: - large-packages: apt-get remove, costs minutes for little extra space; - tool-cache: deletes the preinstalled Python that actions/setup-python then re-downloads, making the job slower rather than faster. * fix(retain): flush entity stats after releasing the connection (Oracle hang) Retain hung forever on the Oracle backend: every retain test burned its 120s client timeout while the server sat idle, so test-python-client-oracle and test-typescript-client-oracle only ever reached ~5% of the suite before the 30-minute job limit. The server was not slow — it was deadlocked. flush_pending_stats() acquires its own connection, but it was being called while the enclosing acquire_with_retry(...) block still held one: async with acquire_with_retry(pool) as conn: # conn checked out async with conn.transaction(): # SAVEPOINT only ...write facts/entities... await entity_resolver.flush_pending_stats() # takes a 2nd connection oracledb does not autocommit and OracleConnection.transaction() is only a SAVEPOINT, so the write is committed by OracleBackend.acquire() when its block exits. Connection #2's `UPDATE entities ...` therefore waits on row locks held by the still-open connection #1, which cannot commit until the call returns — a circular wait. Oracle never reports ORA-00060 because session #1 is blocked in Python, not on the database, so it hangs indefinitely instead of erroring. Move the flush after the acquire block in all three call sites (streaming retain, delta retain, transfer importer), which is what its own docstring already required ("must be called AFTER the retain transaction commits") and which PostgreSQL satisfied only by accident via asyncpg autocommit. Guarded with an AST lint test rather than a behavioural one: the deadlock cannot be reproduced against PostgreSQL, which is what the suite runs on. * test(repair): retry the concurrent index drop on deadlock test_dry_run_creates_nothing still flaked in test-api shard 3. CONCURRENTLY avoids ACCESS EXCLUSIVE but still takes ShareUpdateExclusive, which conflicts with the ShareLock a fresh bank's plain CREATE INDEX holds — and that one cannot be made concurrent, since it runs inside the bank-create transaction. So _drop_bank_indexes can still be picked as the deadlock victim while another xdist worker seeds a bank: Process A waits for ShareUpdateExclusiveLock on memory_units; blocked by B. Process B waits for ShareLock on virtual transaction; blocked by A. The bank-create side already retries (#2943); give the drop the same treatment. The drop is idempotent, so retrying is safe.
nepenth
pushed a commit
to nepenth/hindsight
that referenced
this pull request
Aug 7, 2026
- Fix vectorize-io#2: Add per-bank asyncio.Lock to _ensure_bank for concurrency safety - Fix vectorize-io#3: Clamp search score to max(0.0, ...) to prevent negative values - Fix vectorize-io#4: Implement suffix matching in _handle_list_namespaces - Fix vectorize-io#5: Truncate namespaces to max_depth instead of filtering (per BaseStore contract) - Fix vectorize-io#6: Remove list_namespaces/alist_namespaces overrides — let base class handle prefix=/suffix= kwargs - Fix #7: Document ephemeral namespace tracking and get() limitations in class docstring - Fix vectorize-io#8: Add stable ID to recall node SystemMessage, document ordering behavior - Fix vectorize-io#9: Change budget/max_tokens/recall_tags_match defaults to None so global config fallback works - Fix vectorize-io#10: Conditionally populate __all__ so import * works without langgraph installed - Fix vectorize-io#11: Bump langgraph lower bound from >=0.3.0 to >=0.5.0 - Fix vectorize-io#12: Extract _resolve_client to shared _client.py module Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nepenth
pushed a commit
to nepenth/hindsight
that referenced
this pull request
Aug 7, 2026
- Fix vectorize-io#2: Add per-bank asyncio.Lock to _ensure_bank for concurrency safety - Fix vectorize-io#3: Clamp search score to max(0.0, ...) to prevent negative values - Fix vectorize-io#4: Implement suffix matching in _handle_list_namespaces - Fix vectorize-io#5: Truncate namespaces to max_depth instead of filtering (per BaseStore contract) - Fix vectorize-io#6: Remove list_namespaces/alist_namespaces overrides — let base class handle prefix=/suffix= kwargs - Fix #7: Document ephemeral namespace tracking and get() limitations in class docstring - Fix vectorize-io#8: Add stable ID to recall node SystemMessage, document ordering behavior - Fix vectorize-io#9: Change budget/max_tokens/recall_tags_match defaults to None so global config fallback works - Fix vectorize-io#10: Conditionally populate __all__ so import * works without langgraph installed - Fix vectorize-io#11: Bump langgraph lower bound from >=0.3.0 to >=0.5.0 - Fix vectorize-io#12: Extract _resolve_client to shared _client.py module Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced Aug 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.