fix(codex): cleanup dead code, add release lifecycle and docs (#753)
* fix(codex): cleanup dead code and add to release lifecycle - Remove orphaned reflect() method from client.py (leftover from dropped auto-mode) - Remove dead retainToolCalls config default (never wired through) - Add codex to release-integration.sh valid integrations - Add settings.json version fallback to release script - Add codex CI test job in test.yml - Add codex to integrations.json registry * docs(codex): add changelog page and link from integration docs * feat(codex): add hosted installer script (get-codex) Add self-contained installer at hindsight.vectorize.io/get-codex that downloads scripts from GitHub, configures hooks, and supports local/cloud mode selection — no git clone required. Update docs and README to use the one-liner install: curl -fsSL https://hindsight.vectorize.io/get-codex | bash * chore(codex): remove install.sh in favor of hosted get-codex * fix(docs): use /next/ prefix for codex changelog link * fix(docs): use GitHub link for codex changelog back-link
This commit is contained in:
parent
0b17a67c70
commit
ecf16ea1e6
11 changed files with 433 additions and 194 deletions
26
.github/workflows/test.yml
vendored
26
.github/workflows/test.yml
vendored
|
|
@ -32,6 +32,7 @@ jobs:
|
|||
integrations-ai-sdk: ${{ steps.filter.outputs.integrations-ai-sdk }}
|
||||
integrations-chat: ${{ steps.filter.outputs.integrations-chat }}
|
||||
integrations-claude-code: ${{ steps.filter.outputs.integrations-claude-code }}
|
||||
integrations-codex: ${{ steps.filter.outputs.integrations-codex }}
|
||||
integrations-crewai: ${{ steps.filter.outputs.integrations-crewai }}
|
||||
integrations-litellm: ${{ steps.filter.outputs.integrations-litellm }}
|
||||
integrations-pydantic-ai: ${{ steps.filter.outputs.integrations-pydantic-ai }}
|
||||
|
|
@ -89,6 +90,8 @@ jobs:
|
|||
- 'hindsight-integrations/chat/**'
|
||||
integrations-claude-code:
|
||||
- 'hindsight-integrations/claude-code/**'
|
||||
integrations-codex:
|
||||
- 'hindsight-integrations/codex/**'
|
||||
integrations-crewai:
|
||||
- 'hindsight-integrations/crewai/**'
|
||||
integrations-litellm:
|
||||
|
|
@ -207,6 +210,29 @@ jobs:
|
|||
working-directory: ./hindsight-integrations/claude-code
|
||||
run: python -m pytest tests/ -v
|
||||
|
||||
test-codex-integration:
|
||||
needs: [detect-changes]
|
||||
if: >-
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
needs.detect-changes.outputs.integrations-codex == 'true' ||
|
||||
needs.detect-changes.outputs.ci == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install pytest
|
||||
run: pip install pytest
|
||||
|
||||
- name: Run tests
|
||||
working-directory: ./hindsight-integrations/codex
|
||||
run: python -m pytest tests/ -v
|
||||
|
||||
build-ai-sdk-integration:
|
||||
needs: [detect-changes]
|
||||
if: >-
|
||||
|
|
|
|||
|
|
@ -4,30 +4,23 @@ sidebar_position: 6
|
|||
|
||||
# OpenAI Codex CLI
|
||||
|
||||
[View Changelog →](/changelog/integrations/codex)
|
||||
|
||||
Persistent memory for [OpenAI Codex CLI](https://github.com/openai/codex) using [Hindsight](https://vectorize.io/hindsight). Three Python hook scripts automatically recall relevant context before each prompt and retain conversations after each turn — no changes to your Codex workflow required.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# 1. Clone the Hindsight repo and install the plugin
|
||||
git clone https://github.com/vectorize-io/hindsight.git
|
||||
cd hindsight/hindsight-integrations/codex
|
||||
./install.sh
|
||||
|
||||
# 2. Configure your Hindsight connection
|
||||
cat > ~/.hindsight/codex.json << 'EOF'
|
||||
{
|
||||
"hindsightApiUrl": "https://api.hindsight.vectorize.io",
|
||||
"hindsightApiToken": "hsk_your_token_here",
|
||||
"bankId": "codex"
|
||||
}
|
||||
EOF
|
||||
|
||||
# 3. Start Codex — memory is live
|
||||
codex
|
||||
curl -fsSL https://hindsight.vectorize.io/get-codex | bash
|
||||
```
|
||||
|
||||
For a local Hindsight instance, set `hindsightApiUrl` to `http://localhost:9077` and omit `hindsightApiToken`.
|
||||
The installer will guide you through choosing local or cloud mode and configuring your connection. Once installed, start a new Codex session — memory is live.
|
||||
|
||||
To uninstall:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --uninstall
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
|
|
@ -172,7 +165,7 @@ With this config, running Codex in `~/projects/api` and `~/projects/frontend` st
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
**Hooks not firing**: Check that `~/.codex/config.toml` contains `codex_hooks = true` under `[features]`. Re-run `install.sh` to write this automatically.
|
||||
**Hooks not firing**: Check that `~/.codex/config.toml` contains `codex_hooks = true` under `[features]`. Re-run the installer to fix this automatically.
|
||||
|
||||
**No memories recalled**: Recall returns results only after something has been retained. Either complete one Codex session first, or seed your bank manually using the [cookbook example](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/codex-memory).
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,16 @@
|
|||
"link": "/sdks/integrations/claude-code",
|
||||
"icon": "/img/icons/claudecode.svg"
|
||||
},
|
||||
{
|
||||
"id": "codex",
|
||||
"name": "OpenAI Codex CLI",
|
||||
"description": "Automatic long-term memory for OpenAI Codex CLI via Hindsight hooks. Captures every conversation, recalls relevant context on every prompt.",
|
||||
"type": "official",
|
||||
"by": "hindsight",
|
||||
"category": "tool",
|
||||
"link": "/sdks/integrations/codex",
|
||||
"icon": "/img/icons/terminal.svg"
|
||||
},
|
||||
{
|
||||
"id": "openclaw",
|
||||
"name": "OpenClaw",
|
||||
|
|
|
|||
19
hindsight-docs/src/pages/changelog/integrations/codex.md
Normal file
19
hindsight-docs/src/pages/changelog/integrations/codex.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
import PageHero from '@site/src/components/PageHero';
|
||||
|
||||
<PageHero title="OpenAI Codex CLI Changelog" subtitle="Hindsight memory integration for OpenAI Codex CLI." />
|
||||
|
||||
[← Codex CLI integration](https://github.com/vectorize-io/hindsight/tree/main/hindsight-integrations/codex)
|
||||
|
||||
## [0.1.0](https://github.com/vectorize-io/hindsight/tree/integrations/codex/v0.1.0)
|
||||
|
||||
**Features**
|
||||
|
||||
- Added Hindsight memory integration for OpenAI Codex CLI with three hook scripts: SessionStart (daemon warm-up), UserPromptSubmit (auto-recall), and Stop (auto-retain). ([`0b17a67c`](https://github.com/vectorize-io/hindsight/commit/0b17a67c))
|
||||
- Full-session retain with session-level upsert using session ID as document ID. ([`0b17a67c`](https://github.com/vectorize-io/hindsight/commit/0b17a67c))
|
||||
- Dynamic bank IDs for per-project memory isolation. ([`0b17a67c`](https://github.com/vectorize-io/hindsight/commit/0b17a67c))
|
||||
- Automatic daemon lifecycle management with background pre-start. ([`0b17a67c`](https://github.com/vectorize-io/hindsight/commit/0b17a67c))
|
||||
- 57 automated tests covering content processing and end-to-end hook behavior. ([`71125cd9`](https://github.com/vectorize-io/hindsight/commit/71125cd9))
|
||||
356
hindsight-docs/static/get-codex
Executable file
356
hindsight-docs/static/get-codex
Executable file
|
|
@ -0,0 +1,356 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Install Hindsight Memory for OpenAI Codex CLI
|
||||
#
|
||||
# Usage:
|
||||
# curl -fsSL https://hindsight.vectorize.io/get-codex | bash
|
||||
#
|
||||
# Options:
|
||||
# --uninstall Remove Hindsight hooks
|
||||
# --mode <mode> Mode: local (default) or cloud
|
||||
#
|
||||
# Examples:
|
||||
# curl -fsSL https://hindsight.vectorize.io/get-codex | bash
|
||||
# curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --mode cloud
|
||||
# curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --uninstall
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
DIM='\033[2m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}ℹ${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}✗${NC} $1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠${NC} $1"
|
||||
}
|
||||
|
||||
print_step() {
|
||||
echo ""
|
||||
echo -e "${BOLD}${CYAN}▸ $1${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
print_banner() {
|
||||
echo ""
|
||||
# ANSI logo
|
||||
echo -e " \033[38;2;9;127;184m▄\033[0m\033[48;2;8;130;178m\033[38;2;5;133;186m▄\033[0m \033[48;2;10;143;160m\033[38;2;10;143;165m▄\033[0m\033[38;2;7;140;156m▄\033[0m "
|
||||
echo -e " \033[38;2;8;125;192m▄\033[0m \033[38;2;3;132;191m▀\033[0m\033[38;2;2;133;192m▄\033[0m \033[38;2;3;132;180m▄\033[0m\033[38;2;1;137;184m▄\033[0m\033[38;2;3;133;174m▄\033[0m \033[38;2;3;142;176m▄\033[0m\033[38;2;4;142;169m▀\033[0m \033[38;2;10;144;164m▄\033[0m "
|
||||
echo -e "\033[38;2;6;121;195m▀\033[0m\033[38;2;5;128;203m▀\033[0m\033[48;2;5;124;195m\033[38;2;3;125;200m▄\033[0m\033[38;2;2;126;196m▄\033[0m\033[48;2;3;128;188m\033[38;2;1;131;196m▄\033[0m\033[48;2;0;152;219m\033[38;2;2;131;191m▄\033[0m\033[38;2;1;141;196m▀\033[0m\033[38;2;1;135;183m▀\033[0m\033[38;2;1;148;198m▀\033[0m\033[48;2;1;156;202m\033[38;2;2;135;180m▄\033[0m\033[48;2;4;134;169m\033[38;2;1;137;177m▄\033[0m\033[38;2;3;138;173m▄\033[0m\033[48;2;6;137;165m\033[38;2;2;140;170m▄\033[0m\033[38;2;7;144;169m▀\033[0m\033[38;2;7;139;158m▀\033[0m"
|
||||
echo -e " \033[48;2;2;128;202m\033[38;2;2;124;201m▄\033[0m\033[48;2;1;130;201m\033[38;2;0;135;212m▄\033[0m\033[38;2;2;128;196m▄\033[0m \033[48;2;2;142;204m\033[38;2;7;138;199m▄\033[0m \033[38;2;1;135;186m▄\033[0m\033[48;2;1;142;186m\033[38;2;2;144;194m▄\033[0m\033[48;2;3;138;176m\033[38;2;2;134;176m▄\033[0m "
|
||||
echo -e " \033[48;2;8;118;200m\033[38;2;8;121;209m▄\033[0m\033[38;2;3;121;203m▀\033[0m \033[38;2;3;122;192m▀\033[0m\033[38;2;1;138;216m▀\033[0m\033[48;2;0;138;210m\033[38;2;3;128;198m▄\033[0m\033[48;2;0;126;188m\033[38;2;2;131;198m▄\033[0m\033[48;2;0;142;205m\033[38;2;3;132;193m▄\033[0m\033[38;2;1;140;196m▀\033[0m \033[38;2;4;134;175m▀\033[0m\033[48;2;13;135;167m\033[38;2;8;136;174m▄\033[0m "
|
||||
echo ""
|
||||
echo -e " ${BOLD}HINDSIGHT FOR CODEX CLI${NC}"
|
||||
echo -e " ${DIM}Give your Codex agent persistent memory${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
GITHUB_RAW="https://raw.githubusercontent.com/vectorize-io/hindsight/main/hindsight-integrations/codex"
|
||||
INSTALL_DIR="${HOME}/.hindsight/codex"
|
||||
SCRIPTS_DIR="${INSTALL_DIR}/scripts"
|
||||
CODEX_DIR="${HOME}/.codex"
|
||||
HOOKS_FILE="${CODEX_DIR}/hooks.json"
|
||||
CONFIG_FILE="${CODEX_DIR}/config.toml"
|
||||
|
||||
# Script files to download
|
||||
SCRIPT_FILES=(
|
||||
"scripts/session_start.py"
|
||||
"scripts/recall.py"
|
||||
"scripts/retain.py"
|
||||
"scripts/lib/__init__.py"
|
||||
"scripts/lib/bank.py"
|
||||
"scripts/lib/client.py"
|
||||
"scripts/lib/config.py"
|
||||
"scripts/lib/content.py"
|
||||
"scripts/lib/daemon.py"
|
||||
"scripts/lib/llm.py"
|
||||
"scripts/lib/state.py"
|
||||
)
|
||||
|
||||
# Parse arguments
|
||||
MODE=""
|
||||
UNINSTALL=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--uninstall)
|
||||
UNINSTALL=true
|
||||
shift
|
||||
;;
|
||||
--mode)
|
||||
MODE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Usage: curl -fsSL https://hindsight.vectorize.io/get-codex | bash [-s -- OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --mode <mode> Mode: local (default) or cloud"
|
||||
echo " --uninstall Remove Hindsight hooks"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown option: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Uninstall
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
if [ "$UNINSTALL" = true ]; then
|
||||
echo "Uninstalling Hindsight Codex integration..."
|
||||
|
||||
if [ -d "${SCRIPTS_DIR}" ]; then
|
||||
rm -rf "${SCRIPTS_DIR}"
|
||||
echo " Removed ${SCRIPTS_DIR}"
|
||||
fi
|
||||
|
||||
if [ -f "${HOOKS_FILE}" ]; then
|
||||
rm -f "${HOOKS_FILE}"
|
||||
echo " Removed ${HOOKS_FILE}"
|
||||
fi
|
||||
|
||||
if [ -f "${CONFIG_FILE}" ]; then
|
||||
sed -i.bak '/^codex_hooks *= *true/d' "${CONFIG_FILE}" && rm -f "${CONFIG_FILE}.bak"
|
||||
echo " Removed codex_hooks from ${CONFIG_FILE}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
print_success "Uninstall complete."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Install
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
print_banner
|
||||
|
||||
# Step 1: Check prerequisites
|
||||
print_step "Checking prerequisites"
|
||||
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
print_error "Python 3 is required.\nInstall from https://python.org"
|
||||
fi
|
||||
print_success "Python 3 available"
|
||||
|
||||
if ! command -v curl &> /dev/null && ! command -v wget &> /dev/null; then
|
||||
print_error "curl or wget is required to download scripts."
|
||||
fi
|
||||
|
||||
# Step 2: Select mode
|
||||
if [ -z "$MODE" ]; then
|
||||
if [ -t 0 ] || [ -e /dev/tty ]; then
|
||||
echo -e "${DIM}Select deployment mode:${NC}"
|
||||
echo ""
|
||||
echo -e " ${BOLD}1)${NC} Local ${DIM}- Run Hindsight on your machine (default)${NC}"
|
||||
echo -e " ${BOLD}2)${NC} Cloud ${DIM}- Connect to Hindsight Cloud${NC}"
|
||||
echo ""
|
||||
if [ -t 0 ]; then
|
||||
read -p "Enter choice [1]: " mode_choice
|
||||
else
|
||||
read -p "Enter choice [1]: " mode_choice </dev/tty
|
||||
fi
|
||||
mode_choice=${mode_choice:-1}
|
||||
case $mode_choice in
|
||||
1) MODE="local" ;;
|
||||
2) MODE="cloud" ;;
|
||||
*) MODE="local" ;;
|
||||
esac
|
||||
echo ""
|
||||
else
|
||||
MODE="local"
|
||||
fi
|
||||
fi
|
||||
|
||||
print_info "Mode: ${BOLD}$MODE${NC}"
|
||||
|
||||
# Step 3: Download scripts from GitHub
|
||||
print_step "Downloading hook scripts"
|
||||
|
||||
mkdir -p "${SCRIPTS_DIR}/lib"
|
||||
|
||||
download_file() {
|
||||
local url="$1"
|
||||
local dest="$2"
|
||||
if command -v curl &> /dev/null; then
|
||||
curl -fsSL "$url" -o "$dest"
|
||||
else
|
||||
wget -q "$url" -O "$dest"
|
||||
fi
|
||||
}
|
||||
|
||||
for file in "${SCRIPT_FILES[@]}"; do
|
||||
download_file "${GITHUB_RAW}/${file}" "${SCRIPTS_DIR}/${file#scripts/}"
|
||||
done
|
||||
|
||||
chmod +x "${SCRIPTS_DIR}/session_start.py"
|
||||
chmod +x "${SCRIPTS_DIR}/recall.py"
|
||||
chmod +x "${SCRIPTS_DIR}/retain.py"
|
||||
|
||||
print_success "Scripts installed to ${SCRIPTS_DIR}"
|
||||
|
||||
# Step 4: Download default settings (don't overwrite existing)
|
||||
SETTINGS_DST="${INSTALL_DIR}/settings.json"
|
||||
if [ ! -f "${SETTINGS_DST}" ]; then
|
||||
download_file "${GITHUB_RAW}/settings.json" "${SETTINGS_DST}"
|
||||
print_success "Default settings written to ${SETTINGS_DST}"
|
||||
else
|
||||
print_info "Keeping existing settings at ${SETTINGS_DST}"
|
||||
fi
|
||||
|
||||
# Step 5: Configure connection
|
||||
if [ "$MODE" = "cloud" ]; then
|
||||
print_step "Configuring Hindsight Cloud connection"
|
||||
|
||||
DEFAULT_CLOUD_URL="https://api.hindsight.vectorize.io"
|
||||
|
||||
echo -e "${DIM}Enter your Hindsight Cloud connection details.${NC}"
|
||||
echo -e "${DIM}Get these from https://ui.hindsight.vectorize.io${NC}"
|
||||
echo ""
|
||||
|
||||
if [ -t 0 ]; then
|
||||
read -p "Cloud API URL [$DEFAULT_CLOUD_URL]: " CLOUD_URL
|
||||
read -p "API Token: " CLOUD_TOKEN
|
||||
else
|
||||
read -p "Cloud API URL [$DEFAULT_CLOUD_URL]: " CLOUD_URL </dev/tty
|
||||
read -p "API Token: " CLOUD_TOKEN </dev/tty
|
||||
fi
|
||||
CLOUD_URL=${CLOUD_URL:-$DEFAULT_CLOUD_URL}
|
||||
|
||||
if [ -z "$CLOUD_TOKEN" ]; then
|
||||
print_error "API Token is required for cloud mode"
|
||||
fi
|
||||
|
||||
# Write user config
|
||||
USER_CONFIG="${HOME}/.hindsight/codex.json"
|
||||
cat > "$USER_CONFIG" <<CFGEOF
|
||||
{
|
||||
"hindsightApiUrl": "${CLOUD_URL}",
|
||||
"hindsightApiToken": "${CLOUD_TOKEN}"
|
||||
}
|
||||
CFGEOF
|
||||
chmod 600 "$USER_CONFIG"
|
||||
print_success "Cloud config saved to ${USER_CONFIG}"
|
||||
|
||||
else
|
||||
# Local mode — check for LLM provider
|
||||
print_step "Checking LLM configuration"
|
||||
|
||||
if [ -n "${OPENAI_API_KEY:-}" ]; then
|
||||
print_success "OpenAI API key detected"
|
||||
elif [ -n "${ANTHROPIC_API_KEY:-}" ]; then
|
||||
print_success "Anthropic API key detected"
|
||||
elif [ -n "${GEMINI_API_KEY:-}" ]; then
|
||||
print_success "Gemini API key detected"
|
||||
elif [ -n "${GROQ_API_KEY:-}" ]; then
|
||||
print_success "Groq API key detected"
|
||||
else
|
||||
print_warning "No LLM API key detected. Set one before using Codex:"
|
||||
echo -e " ${CYAN}export OPENAI_API_KEY=sk-your-key${NC}"
|
||||
echo -e " ${DIM}or${NC}"
|
||||
echo -e " ${CYAN}export ANTHROPIC_API_KEY=your-key${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Step 6: Write hooks.json
|
||||
print_step "Configuring Codex hooks"
|
||||
|
||||
mkdir -p "${CODEX_DIR}"
|
||||
cat > "${HOOKS_FILE}" <<HOOKSEOF
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"${SCRIPTS_DIR}/session_start.py\"",
|
||||
"timeout": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"${SCRIPTS_DIR}/recall.py\"",
|
||||
"timeout": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"${SCRIPTS_DIR}/retain.py\"",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
HOOKSEOF
|
||||
print_success "Hooks written to ${HOOKS_FILE}"
|
||||
|
||||
# Step 7: Enable codex_hooks in config.toml
|
||||
if [ ! -f "${CONFIG_FILE}" ]; then
|
||||
touch "${CONFIG_FILE}"
|
||||
fi
|
||||
|
||||
if grep -q '^\[features\]' "${CONFIG_FILE}" 2>/dev/null; then
|
||||
if ! grep -q '^codex_hooks' "${CONFIG_FILE}"; then
|
||||
sed -i.bak '/^\[features\]/a codex_hooks = true' "${CONFIG_FILE}" && rm -f "${CONFIG_FILE}.bak"
|
||||
print_success "Added codex_hooks = true to ${CONFIG_FILE}"
|
||||
else
|
||||
print_info "codex_hooks already enabled"
|
||||
fi
|
||||
else
|
||||
printf '\n[features]\ncodex_hooks = true\n' >> "${CONFIG_FILE}"
|
||||
print_success "Added codex_hooks = true to ${CONFIG_FILE}"
|
||||
fi
|
||||
|
||||
# Done!
|
||||
echo ""
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${GREEN} ✓ Installation Complete!${NC}"
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
echo -e " Hindsight memory is now active in ${BOLD}Codex CLI${NC}."
|
||||
echo ""
|
||||
echo -e " ${DIM}Configuration:${NC}"
|
||||
echo -e " ${CYAN}~/.hindsight/codex/settings.json${NC} ${DIM}(plugin defaults)${NC}"
|
||||
echo -e " ${CYAN}~/.hindsight/codex.json${NC} ${DIM}(personal overrides)${NC}"
|
||||
echo ""
|
||||
echo -e " ${DIM}Start a new Codex session to activate.${NC}"
|
||||
echo ""
|
||||
echo -e " ${DIM}Uninstall:${NC}"
|
||||
echo -e " ${CYAN}curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --uninstall${NC}"
|
||||
echo ""
|
||||
echo -e " ${DIM}Documentation:${NC} ${BLUE}https://hindsight.vectorize.io/sdks/integrations/codex${NC}"
|
||||
echo ""
|
||||
|
|
@ -21,20 +21,18 @@ Three Codex hooks keep memory in sync automatically:
|
|||
## Installation
|
||||
|
||||
```bash
|
||||
git clone https://github.com/vectorize-io/hindsight
|
||||
cd hindsight/hindsight-integrations/codex
|
||||
./install.sh
|
||||
curl -fsSL https://hindsight.vectorize.io/get-codex | bash
|
||||
```
|
||||
|
||||
The installer:
|
||||
1. Copies scripts to `~/.hindsight/codex/scripts/`
|
||||
1. Downloads scripts to `~/.hindsight/codex/scripts/`
|
||||
2. Writes `~/.codex/hooks.json` with absolute paths to the scripts
|
||||
3. Adds `codex_hooks = true` to `~/.codex/config.toml`
|
||||
|
||||
### Uninstall
|
||||
|
||||
```bash
|
||||
./install.sh --uninstall
|
||||
curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --uninstall
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
|
|
|||
|
|
@ -1,149 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# Hindsight memory integration for OpenAI Codex CLI
|
||||
#
|
||||
# This script installs the Hindsight hooks into ~/.codex/ and copies
|
||||
# the hook scripts to ~/.hindsight/codex/scripts/.
|
||||
#
|
||||
# Usage:
|
||||
# ./install.sh # Install (or update)
|
||||
# ./install.sh --uninstall # Remove Hindsight hooks
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
INTEGRATION_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
INSTALL_DIR="${HOME}/.hindsight/codex"
|
||||
SCRIPTS_DIR="${INSTALL_DIR}/scripts"
|
||||
CODEX_DIR="${HOME}/.codex"
|
||||
HOOKS_FILE="${CODEX_DIR}/hooks.json"
|
||||
CONFIG_FILE="${CODEX_DIR}/config.toml"
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Uninstall
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
if [[ "${1:-}" == "--uninstall" ]]; then
|
||||
echo "Uninstalling Hindsight Codex integration..."
|
||||
|
||||
# Remove scripts directory
|
||||
if [[ -d "${SCRIPTS_DIR}" ]]; then
|
||||
rm -rf "${SCRIPTS_DIR}"
|
||||
echo " Removed ${SCRIPTS_DIR}"
|
||||
fi
|
||||
|
||||
# Remove hooks.json
|
||||
if [[ -f "${HOOKS_FILE}" ]]; then
|
||||
rm -f "${HOOKS_FILE}"
|
||||
echo " Removed ${HOOKS_FILE}"
|
||||
fi
|
||||
|
||||
# Remove codex_hooks feature flag from config.toml (if present)
|
||||
if [[ -f "${CONFIG_FILE}" ]]; then
|
||||
# Remove the [features] block line for codex_hooks
|
||||
sed -i.bak '/^codex_hooks *= *true/d' "${CONFIG_FILE}" && rm -f "${CONFIG_FILE}.bak"
|
||||
echo " Removed codex_hooks from ${CONFIG_FILE}"
|
||||
fi
|
||||
|
||||
echo "Uninstall complete."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Install
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
echo "Installing Hindsight Codex integration..."
|
||||
|
||||
# 1. Copy scripts to ~/.hindsight/codex/scripts/
|
||||
mkdir -p "${SCRIPTS_DIR}"
|
||||
cp -r "${INTEGRATION_DIR}/scripts/." "${SCRIPTS_DIR}/"
|
||||
chmod +x "${SCRIPTS_DIR}/session_start.py"
|
||||
chmod +x "${SCRIPTS_DIR}/recall.py"
|
||||
chmod +x "${SCRIPTS_DIR}/retain.py"
|
||||
echo " Scripts installed to ${SCRIPTS_DIR}"
|
||||
|
||||
# 2. Copy default settings (don't overwrite user's existing settings)
|
||||
SETTINGS_DST="${INSTALL_DIR}/settings.json"
|
||||
if [[ ! -f "${SETTINGS_DST}" ]]; then
|
||||
cp "${INTEGRATION_DIR}/settings.json" "${SETTINGS_DST}"
|
||||
echo " Default settings written to ${SETTINGS_DST}"
|
||||
else
|
||||
echo " Keeping existing settings at ${SETTINGS_DST}"
|
||||
fi
|
||||
|
||||
# 3. Write ~/.codex/hooks.json with absolute paths
|
||||
mkdir -p "${CODEX_DIR}"
|
||||
cat > "${HOOKS_FILE}" <<EOF
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"${SCRIPTS_DIR}/session_start.py\"",
|
||||
"timeout": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"${SCRIPTS_DIR}/recall.py\"",
|
||||
"timeout": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"${SCRIPTS_DIR}/retain.py\"",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
EOF
|
||||
echo " Hooks written to ${HOOKS_FILE}"
|
||||
|
||||
# 4. Enable codex_hooks in ~/.codex/config.toml
|
||||
if [[ ! -f "${CONFIG_FILE}" ]]; then
|
||||
touch "${CONFIG_FILE}"
|
||||
fi
|
||||
|
||||
# Check if [features] section exists
|
||||
if grep -q '^\[features\]' "${CONFIG_FILE}" 2>/dev/null; then
|
||||
# Section exists — add codex_hooks under it if not already present
|
||||
if ! grep -q '^codex_hooks' "${CONFIG_FILE}"; then
|
||||
# Insert codex_hooks after [features]
|
||||
sed -i.bak '/^\[features\]/a codex_hooks = true' "${CONFIG_FILE}" && rm -f "${CONFIG_FILE}.bak"
|
||||
echo " Added codex_hooks = true to [features] in ${CONFIG_FILE}"
|
||||
else
|
||||
echo " codex_hooks already enabled in ${CONFIG_FILE}"
|
||||
fi
|
||||
else
|
||||
# No [features] section — append it
|
||||
printf '\n[features]\ncodex_hooks = true\n' >> "${CONFIG_FILE}"
|
||||
echo " Added [features] codex_hooks = true to ${CONFIG_FILE}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Hindsight is installed for Codex."
|
||||
echo ""
|
||||
echo "Configuration:"
|
||||
echo " Edit ${SETTINGS_DST} to customize settings."
|
||||
echo " Or create ~/.hindsight/codex.json for personal overrides."
|
||||
echo ""
|
||||
echo "For Hindsight Cloud, set:"
|
||||
echo " \"hindsightApiUrl\": \"https://api.hindsight.vectorize.io\""
|
||||
echo " \"hindsightApiToken\": \"your-api-key\""
|
||||
echo ""
|
||||
echo "For local daemon mode, set an LLM API key:"
|
||||
echo " export OPENAI_API_KEY=sk-your-key"
|
||||
echo ""
|
||||
echo "Start a new Codex session to activate."
|
||||
|
|
@ -130,24 +130,6 @@ class HindsightClient:
|
|||
}
|
||||
return self._request("POST", path, body, timeout=timeout)
|
||||
|
||||
def reflect(
|
||||
self,
|
||||
bank_id: str,
|
||||
query: str,
|
||||
budget: str = "mid",
|
||||
max_tokens: int = 1024,
|
||||
timeout: int = 30,
|
||||
) -> dict:
|
||||
"""Reflect on memories and return a synthesized answer.
|
||||
|
||||
Runs an agentic loop that retrieves facts, mental models, and experiences,
|
||||
then uses the LLM to formulate a coherent response. Slower than recall
|
||||
but produces a synthesized prose answer rather than raw facts.
|
||||
"""
|
||||
path = f"/v1/default/banks/{urllib.parse.quote(bank_id, safe='')}/reflect"
|
||||
body = {"query": query, "budget": budget, "max_tokens": max_tokens}
|
||||
return self._request("POST", path, body, timeout=timeout)
|
||||
|
||||
def set_bank_mission(
|
||||
self, bank_id: str, mission: str, retain_mission: Optional[str] = None, timeout: int = 15
|
||||
) -> dict:
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ DEFAULTS = {
|
|||
"retainRoles": ["user", "assistant"],
|
||||
"retainEveryNTurns": 10,
|
||||
"retainOverlapTurns": 2,
|
||||
"retainToolCalls": True,
|
||||
"retainContext": "codex",
|
||||
"retainTags": [],
|
||||
"retainMetadata": {},
|
||||
|
|
@ -118,7 +117,7 @@ def load_config() -> dict:
|
|||
"""
|
||||
config = dict(DEFAULTS)
|
||||
|
||||
# 1. Plugin install settings.json (written by install.sh)
|
||||
# 1. Plugin install settings.json (written by get-codex installer)
|
||||
install_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
_load_settings_file(os.path.join(install_root, "settings.json"), config)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"version": "0.1.0",
|
||||
"hindsightApiUrl": "",
|
||||
"bankId": "codex",
|
||||
"bankMission": "You are a Codex AI coding assistant. Focus on technical decisions, code changes, debugging sessions, and project context relevant to the user's work.",
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ print_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|||
print_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
VALID_INTEGRATIONS=("litellm" "pydantic-ai" "crewai" "ag2" "ai-sdk" "chat" "openclaw" "langgraph" "nemoclaw" "strands" "claude-code")
|
||||
VALID_INTEGRATIONS=("litellm" "pydantic-ai" "crewai" "ag2" "ai-sdk" "chat" "openclaw" "langgraph" "nemoclaw" "strands" "claude-code" "codex")
|
||||
|
||||
usage() {
|
||||
print_error "Usage: $0 <integration> <version>"
|
||||
|
|
@ -116,8 +116,12 @@ elif [ -f "$INTEGRATION_DIR/.claude-plugin/plugin.json" ]; then
|
|||
print_info "Updating version in $INTEGRATION_DIR/.claude-plugin/plugin.json"
|
||||
sed -i.bak "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" "$INTEGRATION_DIR/.claude-plugin/plugin.json"
|
||||
rm "$INTEGRATION_DIR/.claude-plugin/plugin.json.bak"
|
||||
elif [ -f "$INTEGRATION_DIR/settings.json" ] && grep -q '"version"' "$INTEGRATION_DIR/settings.json"; then
|
||||
print_info "Updating version in $INTEGRATION_DIR/settings.json"
|
||||
sed -i.bak "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" "$INTEGRATION_DIR/settings.json"
|
||||
rm "$INTEGRATION_DIR/settings.json.bak"
|
||||
else
|
||||
print_error "No pyproject.toml, package.json, or plugin.json found in $INTEGRATION_DIR"
|
||||
print_error "No pyproject.toml, package.json, plugin.json, or versioned settings.json found in $INTEGRATION_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue