* feat(codex): add Hindsight memory integration for OpenAI Codex CLI
Hooks-based integration that gives Codex CLI long-term memory via Hindsight.
Three hooks keep memory in sync: SessionStart (daemon pre-warm), UserPromptSubmit
(recall + context injection), Stop (retain conversation to memory).
Key differences from the Claude Code integration:
- Codex transcript format: JSONL with {msg: {type, message}} (user_message/agent_message)
- No CODEX_PLUGIN_ROOT env var — install.sh writes hooks.json with absolute paths
- State stored in ~/.hindsight/codex/state/ (not CLAUDE_PLUGIN_DATA)
- No async: true in hooks (not supported by Codex)
- No SessionEnd event
- hooks.json written to ~/.codex/hooks.json with codex_hooks = true in config.toml
* fix(codex): fix transcript parser for actual Codex disk format
Codex stores sessions as rollout-*.jsonl with response_item entries:
User: {type:response_item, payload:{type:message, role:user, content:[{type:input_text, text:...}]}}
Assistant: {type:response_item, payload:{type:message, role:assistant, phase:final_answer, content:[{type:output_text, text:...}]}}
Previous parser expected an undocumented {msg:{type:user_message}} format from the Rust protocol spec
that does not match the actual on-disk storage format.
* feat(codex): add reflect mode to UserPromptSubmit hook
Add recallMode config option (default: 'recall') that switches the
UserPromptSubmit hook between:
- 'recall': existing behavior, fast raw facts list
- 'reflect': agentic synthesis loop, returns coherent prose answer
Also adds reflect() method to HindsightClient and HINDSIGHT_RECALL_MODE
env var override. Reflect uses a 25s timeout (vs 10s for recall).
* feat(codex): auto mode for recall/reflect selection
Add recallMode: 'auto' (new default) that picks the operation per-query:
- Synthesis patterns (what do you know, what's my, summarize, etc.) → reflect
- All other prompts → recall (fast, raw facts, better for code tasks)
* feat(codex): add automated test suite and finalize recall-only mode
* docs(codex): add docs page and sidebar entry for Codex CLI integration
53 lines
1.6 KiB
Python
Executable file
53 lines
1.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""SessionStart hook: health check and daemon pre-start.
|
|
|
|
Fires once when a Codex session begins. Verifies the Hindsight server is
|
|
reachable, and kicks off a background daemon pre-start if not — so it's
|
|
ready by the first recall or retain hook.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from lib.client import HindsightClient
|
|
from lib.config import debug_log, load_config
|
|
from lib.daemon import get_api_url, prestart_daemon_background
|
|
|
|
|
|
def main():
|
|
config = load_config()
|
|
|
|
if not config.get("autoRecall") and not config.get("autoRetain"):
|
|
debug_log(config, "Both autoRecall and autoRetain disabled, skipping session start")
|
|
return
|
|
|
|
# Consume stdin
|
|
try:
|
|
hook_input = json.load(sys.stdin)
|
|
except (json.JSONDecodeError, EOFError):
|
|
hook_input = {}
|
|
|
|
debug_log(config, f"SessionStart hook, session: {hook_input.get('session_id', 'unknown')}")
|
|
|
|
def _dbg(*a):
|
|
debug_log(config, *a)
|
|
|
|
try:
|
|
api_url = get_api_url(config, debug_fn=_dbg, allow_daemon_start=False)
|
|
HindsightClient(api_url, config.get("hindsightApiToken"))
|
|
debug_log(config, f"Hindsight server reachable at {api_url}")
|
|
except (RuntimeError, ValueError) as e:
|
|
debug_log(config, f"Hindsight not running, initiating background pre-start: {e}")
|
|
prestart_daemon_background(config, debug_fn=_dbg)
|
|
return
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except Exception as e:
|
|
print(f"[Hindsight] SessionStart error: {e}", file=sys.stderr)
|
|
sys.exit(0)
|