mirror of
https://github.com/vectorize-io/hindsight.git
synced 2026-09-14 19:31:49 +08:00
394d66e607
* feat(integrations): add Haystack integration for persistent agent memory Add hindsight-haystack package providing Haystack Tool instances backed by Hindsight's retain/recall/reflect APIs. Uses async client methods with event-loop-safe sync wrapper to work correctly inside Haystack's agent runtime. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(haystack): use persistent event loop for async client calls aiohttp binds its session to the creating event loop, so asyncio.run() (which creates/destroys a loop per call) breaks on sequential calls. Switch to a persistent daemon-thread event loop with run_coroutine_threadsafe. Also removes unused per-operation timeout constants and adds _run_sync tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(haystack): add HindsightToolset with auto-recall/retain, fix review issues - Add HindsightToolset(Toolset) with auto_recall and auto_retain flags that automatically inject recalled memories into the system prompt before each turn and retain user/assistant messages after each turn - Fix _ensure_bank to retry on transient errors instead of permanently disabling bank creation - Fix reflect_on_memory to return structured_output JSON when response_schema is set - Truncate error messages to avoid dumping raw HTTP responses to agents - Extract _build_backend_kwargs() and _build_tools() as shared helpers - Add 20 new tests (60 -> 80 total) covering toolset, auto-recall, auto-retain, structured output, and bank creation retry Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(haystack): address review round 2 — max_recall_results, role metadata, _run_sync cleanup - Add max_recall_results param to HindsightToolset (default 10) to cap auto-recall prompt injection size, matching Pydantic AI pattern - Auto-retain now includes role + source metadata on messages, matching LlamaIndex's metadata pattern for distinguishable conversation turns - _recall_for_prompt now calls the API directly with result cap instead of going through the formatted string from recall_memory - Serialize/deserialize max_recall_results in to_dict/from_dict - Add tests for max_recall_results and role metadata (82 total) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(haystack): default to Cloud without configure(); add gated E2E + bucketing - resolve_client() now falls back to DEFAULT_HINDSIGHT_API_URL and the HINDSIGHT_API_KEY env var when configure() was never called (it previously raised "No Hindsight API URL configured"). Updated the unit test to assert the cloud-default + env-key behavior. Satisfies the "default to Cloud" goal. - Add a gated tests/test_e2e.py (retain/recall/reflect tools against a live Hindsight server), marked requires_real_llm; register the marker in pyproject; the test-haystack-integration CI job now runs the deterministic bucket (-m "not requires_real_llm"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(haystack): close owned clients at exit; run E2E client I/O on the bridge loop The tools run async client calls on a persistent background event loop. aiohttp sessions bound to that loop were never closed, surfacing as "Unclosed client session/connector" warnings. Track module-owned Hindsight clients (those created when the caller didn't pass client=) and close them on the loop via an atexit hook, then stop the loop. The live E2E now performs all client I/O through that same loop (acreate_bank/adelete_bank/aclose via _run_sync) and logs cleanup failures instead of swallowing them — zero unclosed-connector warnings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(haystack): sync openapi.json with main Branch carried an older snapshot of hindsight-docs/static/openapi.json that pre-dated main's addition of OperationProgress. Re-checkout main's openapi.json so check-openapi-compatibility passes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(haystack): strip api_key from to_dict() so it doesn't leak to YAML _build_backend_kwargs was emitting the api_key in the serializable dict that to_dict() returns. Haystack pipelines get dumped to YAML for inspection, checkpointing, and sharing — a serialized key leaks into every dump. Reviewer (benfrank241) flagged this on #1256. Drop the api_key from the serialized backend_kwargs. resolve_client() already reads HINDSIGHT_API_KEY from the env var as a final fallback, so a redeployed pipeline picks the key back up from the host's environment rather than from the YAML. The test_tools_round_trip_serialization_with_client test previously asserted the leak — flipped it to assert the key is NOT present and added a json.dumps probe asserting the literal key value also doesn't appear under any other field name. Pre-fix, the test fails: AssertionError: api_key must not appear in serialized backend_kwargs — would leak to YAML pipeline dumps assert 'api_key' not in {'api_key': 'client-key', ...} 86/86 tests pass post-fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: re-trigger CI A previous push to this branch silently did not trigger a pull_request event in GitHub Actions, leaving the PR without a CI run for the latest HEAD. Push an empty commit to force a new event. * ci: empty commit to attach pull_request CI check to the PR head (Previous pushes did not auto-trigger pull_request workflow events for reasons internal to GitHub Actions; manual workflow_dispatch runs passed green but their checks don't roll up onto the PR. Re-poking the head to surface the green state on the PR.) * ci: trailing newline to force CI retrigger * fix(haystack): register in changelog/gallery + docs page + tidy tools Review follow-ups for the Haystack integration: 1. Add haystack to the INTEGRATIONS map in generate_changelog.py so the release script's changelog step resolves the slug (was missing, which would fail the release). 2. Add the integrations.json gallery entry, a doc page at docs-integrations/haystack.md, and an icon — required by check-integrations.mjs (forward: entry needs a doc page; reverse: a released integration must appear in the gallery). 3. Drop the inaccurate 'Raises: HindsightError' clause from create_hindsight_tools — resolution always succeeds (URL defaults to Cloud) so it never raises; the error type stays exported as the conventional public catch type. 4. Replace the _TOOL_DEFS dict-of-3-tuples with a frozen _ToolDef dataclass and drop the redundant method-name field (it equalled the dict key). * fix(haystack): use official Haystack logo for gallery icon Replace the placeholder glyph with the real deepset Haystack mark (teal #0EAF9C rounded square + white symbol), extracted as vector from deepset's own website source (deepset-ai/haystack-home site-logo partial). --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: DK09876 <dk09876@DK09876s-MacBook-Pro.local>
1.2 KiB
1.2 KiB