diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5fbe91b2..9ac5391a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -139,7 +139,7 @@ jobs: path: hindsight-clients/typescript/*.tgz retention-days: 1 - release-moltbot-integration: + release-openclawd-integration: runs-on: ubuntu-latest environment: npm @@ -153,15 +153,15 @@ jobs: registry-url: 'https://registry.npmjs.org' - name: Install dependencies - working-directory: ./hindsight-integrations/moltbot + working-directory: ./hindsight-integrations/openclawd run: npm ci - name: Build - working-directory: ./hindsight-integrations/moltbot + working-directory: ./hindsight-integrations/openclawd run: npm run build - name: Publish to npm - working-directory: ./hindsight-integrations/moltbot + working-directory: ./hindsight-integrations/openclawd run: | set +e OUTPUT=$(npm publish --access public 2>&1) @@ -178,14 +178,14 @@ jobs: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Pack for GitHub release - working-directory: ./hindsight-integrations/moltbot + working-directory: ./hindsight-integrations/openclawd run: npm pack - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: moltbot-integration - path: hindsight-integrations/moltbot/*.tgz + name: openclawd-integration + path: hindsight-integrations/openclawd/*.tgz retention-days: 1 release-control-plane: @@ -415,7 +415,7 @@ jobs: create-github-release: runs-on: ubuntu-latest - needs: [release-python-packages, release-typescript-client, release-moltbot-integration, release-control-plane, release-rust-cli, release-docker-images, release-helm-chart] + needs: [release-python-packages, release-typescript-client, release-openclawd-integration, release-control-plane, release-rust-cli, release-docker-images, release-helm-chart] permissions: contents: write @@ -438,11 +438,11 @@ jobs: name: typescript-client path: ./artifacts/typescript-client - - name: Download Moltbot Integration + - name: Download OpenClawd Integration uses: actions/download-artifact@v4 with: - name: moltbot-integration - path: ./artifacts/moltbot-integration + name: openclawd-integration + path: ./artifacts/openclawd-integration - name: Download Control Plane uses: actions/download-artifact@v4 @@ -485,8 +485,8 @@ jobs: cp artifacts/python-packages/hindsight-embed/dist/* release-assets/ || true # TypeScript client cp artifacts/typescript-client/*.tgz release-assets/ || true - # Moltbot Integration - cp artifacts/moltbot-integration/*.tgz release-assets/ || true + # OpenClawd Integration + cp artifacts/openclawd-integration/*.tgz release-assets/ || true # Control Plane cp artifacts/control-plane/*.tgz release-assets/ || true # Rust CLI binaries diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2c49c761..95835e66 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -82,7 +82,7 @@ jobs: - name: Build TypeScript client run: npm run build --workspace=hindsight-clients/typescript - build-moltbot-integration: + build-openclawd-integration: runs-on: ubuntu-latest steps: @@ -94,15 +94,15 @@ jobs: node-version: '22' - name: Install dependencies - working-directory: ./hindsight-integrations/moltbot + working-directory: ./hindsight-integrations/openclawd run: npm ci - name: Run tests - working-directory: ./hindsight-integrations/moltbot + working-directory: ./hindsight-integrations/openclawd run: npm test - name: Build - working-directory: ./hindsight-integrations/moltbot + working-directory: ./hindsight-integrations/openclawd run: npm run build build-control-plane: diff --git a/hindsight-docs/docs/sdks/integrations/moltbot.md b/hindsight-docs/docs/sdks/integrations/openclawd.md similarity index 63% rename from hindsight-docs/docs/sdks/integrations/moltbot.md rename to hindsight-docs/docs/sdks/integrations/openclawd.md index f031113a..44df6f17 100644 --- a/hindsight-docs/docs/sdks/integrations/moltbot.md +++ b/hindsight-docs/docs/sdks/integrations/openclawd.md @@ -2,24 +2,23 @@ sidebar_position: 4 --- -# Moltbot (Clawdbot) +# OpenClawd -Biomimetic long-term memory for [Moltbot](https://molt.bot) using [Hindsight](https://vectorize.io/hindsight). Automatically captures conversations and intelligently recalls relevant context. +Biomimetic long-term memory for [OpenClawd](https://openclawd.ai) using [Hindsight](https://vectorize.io/hindsight). + +This plugin integrates [hindsight-embed](https://vectorize.io/hindsight/cli), a standalone daemon that bundles Hindsight's memory engine (API + PostgreSQL) into a single command. The plugin automatically manages the daemon lifecycle and provides hooks for seamless memory capture and recall. ## Quick Start ```bash -# 1. Install the plugin -npm install -g @vectorize-io/hindsight-moltbot-plugin - -# 2. Configure your LLM provider +# 1. Configure your LLM provider export OPENAI_API_KEY="sk-your-key" clawdbot config set 'agents.defaults.models."openai/gpt-4o-mini"' '{}' -# 3. Enable the plugin -clawdbot plugins enable hindsight-memory +# 2. Install and enable the plugin +clawdbot plugins install @vectorize-io/hindsight-openclawd -# 4. Start Moltbot +# 3. Start OpenClawd clawdbot gateway ``` @@ -39,10 +38,10 @@ Before each agent response, relevant memories are **automatically injected**: - Injected into context with `` tags - Agent seamlessly uses past context -## Understanding Moltbot Concepts +## Understanding OpenClawd Concepts ### Plugins -Extensions that add functionality to Moltbot. This Hindsight plugin: +Extensions that add functionality to OpenClawd. This Hindsight plugin: - Runs a background service (manages `hindsight-embed` daemon) - Registers hooks (automatic event handlers) @@ -57,7 +56,7 @@ Think of hooks as "forced automation" - they always run. ``` ┌─────────────────────────────────────────┐ -│ Moltbot Gateway │ +│ OpenClawd Gateway │ │ │ │ ┌───────────────────────────────────┐ │ │ │ Hindsight Plugin │ │ @@ -72,33 +71,33 @@ Think of hooks as "forced automation" - they always run. ↓ uvx hindsight-embed • Daemon on port 8889 - • PostgreSQL (pg0) + • PostgreSQL (pg0://hindsight-embed) + • Bank: 'openclawd' (isolated within shared database) • Fact extraction ``` +**Database Architecture:** All banks share a single pg0 database instance (`pg0://hindsight-embed`). Bank isolation happens within the database via separate tables/schemas per bank ID. The 'openclawd' bank is automatically created when the plugin stores its first memory. + ## Installation ### Prerequisites - **Node.js** 22+ -- **Moltbot** (Clawdbot) with plugin support +- **OpenClawd** (Clawdbot) with plugin support - **uv/uvx** for running `hindsight-embed` - **LLM API key** (OpenAI, Anthropic, etc.) ### Setup ```bash -# 1. Install the plugin -npm install -g @vectorize-io/hindsight-moltbot-plugin - -# 2. Configure your LLM provider +# 1. Configure your LLM provider export OPENAI_API_KEY="sk-your-key" clawdbot config set 'agents.defaults.models."openai/gpt-4o-mini"' '{}' -# 3. Enable the plugin -clawdbot plugins enable hindsight-memory +# 2. Install and enable the plugin +clawdbot plugins install @vectorize-io/hindsight-openclawd -# 4. Start Moltbot +# 3. Start OpenClawd clawdbot gateway ``` @@ -113,7 +112,7 @@ Optional settings in `~/.clawdbot/clawdbot.json`: { "plugins": { "entries": { - "hindsight-memory": { + "hindsight-openclawd": { "enabled": true, "config": { "daemonIdleTimeout": 0 @@ -128,6 +127,7 @@ Optional settings in `~/.clawdbot/clawdbot.json`: - `daemonIdleTimeout` (number, default: `0`) - Seconds before daemon shuts down from inactivity (0 = never) - `embedPort` (number, default: auto) - Port for embedded server - `bankMission` (string, default: none) - Custom context for the memory bank +- `embedVersion` (string, default: `"latest"`) - hindsight-embed version to use (e.g., `"latest"`, `"0.4.2"`, or leave empty for latest). Use this to pin a specific version if latest is broken. ## Supported LLM Providers @@ -156,7 +156,7 @@ clawdbot plugins list | grep hindsight ``` **Test auto-recall:** -Send a message on any Moltbot channel (Telegram, Slack, etc.): +Send a message on any OpenClawd channel (Telegram, Slack, etc.): ``` User: My name is John and I love pizza Bot: Got it! I'll remember that. @@ -172,7 +172,55 @@ tail -f ~/.hindsight/daemon.log **Check memories in database:** ```bash -uvx hindsight-embed memory recall moltbot "pizza" --output json +uvx hindsight-embed@latest memory recall openclawd "pizza" --output json +``` + +## Inspecting Memories + +The plugin uses `hindsight-embed` daemon which provides CLI commands for inspection: + +**View daemon logs:** +```bash +uvx hindsight-embed@latest daemon logs +# Or follow logs in real-time: +tail -f ~/.hindsight/daemon.log +``` + +**Open web UI:** +```bash +uvx hindsight-embed@latest ui +# Opens browser to http://localhost:8890 +# Browse memories, facts, entities, and relationships +``` + +**List memory banks:** +```bash +uvx hindsight-embed@latest bank list +# Shows all banks including 'openclawd' +``` + +**Query memories:** +```bash +# Search memories +uvx hindsight-embed@latest memory recall openclawd "user preferences" --output json + +# View recent memories +uvx hindsight-embed@latest memory list openclawd --limit 10 + +# Export all memories +uvx hindsight-embed@latest memory export openclawd --output memories.json +``` + +**Inspect facts and entities:** +```bash +# List extracted facts +uvx hindsight-embed@latest fact list openclawd + +# List entities +uvx hindsight-embed@latest entity list openclawd + +# Show entity relationships +uvx hindsight-embed@latest entity graph openclawd ``` ## Troubleshooting @@ -180,20 +228,19 @@ uvx hindsight-embed memory recall moltbot "pizza" --output json **Plugin not loading?** ```bash # Check plugin installation -npm list -g @vectorize-io/hindsight-moltbot-plugin +clawdbot plugins list | grep -i hindsight # Reinstall if needed -npm install -g @vectorize-io/hindsight-moltbot-plugin -clawdbot plugins enable hindsight-memory +clawdbot plugins install @vectorize-io/hindsight-openclawd ``` **Daemon not starting?** ```bash # Check daemon status -uvx hindsight-embed daemon status +uvx hindsight-embed@latest daemon status # Manually start -uvx hindsight-embed daemon start +uvx hindsight-embed@latest daemon start # View logs tail -f ~/.hindsight/daemon.log @@ -224,7 +271,7 @@ tail -f /tmp/clawdbot/clawdbot-*.log | grep Hindsight ```bash # Clone repo git clone https://github.com/vectorize-io/hindsight.git -cd hindsight/hindsight-integrations/moltbot +cd hindsight/hindsight-integrations/openclawd # Install dependencies npm install @@ -242,7 +289,7 @@ npm run build && ./install.sh ## Requirements - **Node.js** 22+ -- **Moltbot** (Clawdbot) with plugin support +- **OpenClawd** (Clawdbot) with plugin support - **uv/uvx** for running `hindsight-embed` - **LLM API key** (OpenAI, Anthropic, etc.) @@ -253,5 +300,5 @@ MIT ## Links - [Hindsight Documentation](https://vectorize.io/hindsight) -- [Moltbot Documentation](https://docs.molt.bot) +- [OpenClawd Documentation](https://openclawd.ai) - [GitHub Repository](https://github.com/vectorize-io/hindsight) diff --git a/hindsight-embed/README.md b/hindsight-embed/README.md index 5d7aea55..8ed5405a 100644 --- a/hindsight-embed/README.md +++ b/hindsight-embed/README.md @@ -120,7 +120,9 @@ Run `hindsight-embed configure` for a guided setup that saves to `~/.hindsight/e | `HINDSIGHT_EMBED_LLM_API_KEY` | LLM API key (or use `OPENAI_API_KEY`) | Required | | `HINDSIGHT_EMBED_LLM_PROVIDER` | LLM provider (`openai`, `groq`, `google`, `ollama`) | `openai` | | `HINDSIGHT_EMBED_LLM_MODEL` | LLM model | `gpt-4o-mini` | -| `HINDSIGHT_EMBED_BANK_ID` | Memory bank ID | `default` | +| `HINDSIGHT_EMBED_BANK_ID` | Default memory bank ID (optional, used when not specified in CLI) | `default` | + +**Note:** All banks share a single pg0 database (`pg0://hindsight-embed`). Bank isolation happens within the database via the `bank_id` parameter passed to CLI commands. ### Files diff --git a/hindsight-embed/hindsight_embed/daemon_client.py b/hindsight-embed/hindsight_embed/daemon_client.py index 6d6eecf5..96b06a6e 100644 --- a/hindsight-embed/hindsight_embed/daemon_client.py +++ b/hindsight-embed/hindsight_embed/daemon_client.py @@ -71,9 +71,8 @@ def _start_daemon(config: dict) -> bool: if config.get("llm_model"): env["HINDSIGHT_API_LLM_MODEL"] = config["llm_model"] - # Use pg0 database specific to bank - bank_id = config.get("bank_id", "default") - env["HINDSIGHT_API_DATABASE_URL"] = f"pg0://hindsight-embed-{bank_id}" + # Use single shared pg0 database for all banks (banks are isolated within the database) + env["HINDSIGHT_API_DATABASE_URL"] = "pg0://hindsight-embed" env["HINDSIGHT_API_LOG_LEVEL"] = "info" # Get idle timeout from environment or use default diff --git a/hindsight-integrations/moltbot/README.md b/hindsight-integrations/moltbot/README.md deleted file mode 100644 index 88e2cbce..00000000 --- a/hindsight-integrations/moltbot/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Hindsight Memory Plugin for Moltbot - -Biomimetic long-term memory for [Moltbot](https://molt.bot) using [Hindsight](https://vectorize.io/hindsight). Automatically captures conversations and intelligently recalls relevant context. - -## Quick Start - -```bash -# 1. Install the plugin -npm install -g @vectorize-io/hindsight-moltbot-plugin - -# 2. Configure your LLM provider -export OPENAI_API_KEY="sk-your-key" -clawdbot config set 'agents.defaults.models."openai/gpt-4o-mini"' '{}' - -# 3. Enable the plugin -clawdbot plugins enable hindsight-memory - -# 4. Start Moltbot -clawdbot gateway -``` - -That's it! The plugin will automatically start capturing and recalling memories. - -## Documentation - -For full documentation, configuration options, troubleshooting, and development guide, see: - -**[Moltbot Integration Documentation](https://vectorize.io/hindsight/sdks/integrations/moltbot)** - -## Links - -- [Hindsight Documentation](https://vectorize.io/hindsight) -- [Moltbot Documentation](https://docs.molt.bot) -- [GitHub Repository](https://github.com/vectorize-io/hindsight) - -## License - -MIT diff --git a/hindsight-integrations/moltbot/clawdbot.plugin.json b/hindsight-integrations/moltbot/clawdbot.plugin.json deleted file mode 100644 index 8e1f859c..00000000 --- a/hindsight-integrations/moltbot/clawdbot.plugin.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": "hindsight-memory", - "name": "Hindsight Memory", - "kind": "memory", - "moltbot": { - "skills": ["skills"] - }, - "configSchema": { - "type": "object", - "properties": { - "bankMission": { - "type": "string", - "description": "Custom mission/context for the memory bank (overrides default)" - }, - "embedPort": { - "type": "number", - "description": "Port for hindsight-embed server (auto-assigned if not specified)", - "default": 0 - } - }, - "additionalProperties": false - }, - "uiHints": { - "bankMission": { - "label": "Bank Mission", - "placeholder": "Custom context for what this agent does..." - }, - "embedPort": { - "label": "Embed Server Port", - "placeholder": "0 (auto-assign)" - } - } -} diff --git a/hindsight-integrations/moltbot/hooks/retain-messages/HOOK.md b/hindsight-integrations/moltbot/hooks/retain-messages/HOOK.md deleted file mode 100644 index 80010847..00000000 --- a/hindsight-integrations/moltbot/hooks/retain-messages/HOOK.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: hindsight-retain-messages -description: Automatically retains messages to Hindsight long-term memory -events: - - agent_end -metadata: - moltbot: - emoji: 🧠 ---- - -# Hindsight Message Retention - -This hook automatically retains conversation messages to Hindsight's long-term memory. - -## When It Runs - -- On `agent_end`: After each agent turn completes - -## What It Does - -1. Captures the current session messages -2. Formats them into a conversation transcript -3. Calls Hindsight's retain API with the session_id as document_id -4. Queues for background processing (async) -5. Extracts facts, entities, and relationships from the conversation diff --git a/hindsight-integrations/moltbot/hooks/retain-messages/handler.js b/hindsight-integrations/moltbot/hooks/retain-messages/handler.js deleted file mode 100644 index 3c4844ff..00000000 --- a/hindsight-integrations/moltbot/hooks/retain-messages/handler.js +++ /dev/null @@ -1,68 +0,0 @@ -// Handler for auto-retaining messages to Hindsight -const handler = async (event) => { - console.log(`[Hindsight Hook] Received event: ${event.type}`); - - // Only process agent_end events (after each agent turn) - if (event.type !== 'agent_end') { - return; - } - - console.log('[Hindsight Hook] Processing retention after agent turn...'); - - try { - // Get client from global (set by main plugin) - const clientGlobal = global.__hindsightClient; - if (!clientGlobal) { - console.warn('[Hindsight] Client global not found, skipping retain'); - return; - } - - const client = clientGlobal.getClient(); - if (!client) { - console.warn('[Hindsight] Client not initialized, skipping retain'); - return; - } - - // Extract session information - const { sessionId, sessionKey } = event.context || {}; - if (!sessionId) { - return; - } - - // Get messages from the event context - const sessionEntry = event.context?.sessionEntry; - if (!sessionEntry || !sessionEntry.messages || sessionEntry.messages.length === 0) { - return; - } - - // Format messages into a transcript - const transcript = sessionEntry.messages - .map((msg) => { - const role = msg.role || 'unknown'; - const content = msg.content || ''; - return `${role}: ${content}`; - }) - .join('\n\n'); - - if (!transcript.trim()) { - return; - } - - // Retain to Hindsight with session_id as document_id - await client.retain({ - content: transcript, - document_id: sessionId, - metadata: { - session_key: sessionKey, - retained_at: new Date().toISOString(), - message_count: sessionEntry.messages.length, - }, - }); - - console.log(`[Hindsight] Retained ${sessionEntry.messages.length} messages for session ${sessionId}`); - } catch (error) { - console.error('[Hindsight] Error retaining messages:', error); - } -}; - -export default handler; diff --git a/hindsight-integrations/moltbot/hooks/retain-messages/handler.ts b/hindsight-integrations/moltbot/hooks/retain-messages/handler.ts deleted file mode 100644 index 7d9e7888..00000000 --- a/hindsight-integrations/moltbot/hooks/retain-messages/handler.ts +++ /dev/null @@ -1,71 +0,0 @@ -// Handler for auto-retaining messages to Hindsight - -import type { HookHandler } from 'moltbot/plugin-sdk'; - -const handler: HookHandler = async (event) => { - // Only process tool_result_persist and command:new events - if ( - event.type !== 'tool_result_persist' && - !(event.type === 'command' && event.action === 'new') - ) { - return; - } - - try { - // Get client from global (set by main plugin) - const clientGlobal = (global as any).__hindsightClient; - if (!clientGlobal) { - console.warn('[Hindsight] Client global not found, skipping retain'); - return; - } - - const client = clientGlobal.getClient(); - if (!client) { - console.warn('[Hindsight] Client not initialized, skipping retain'); - return; - } - - // Extract session information - const { sessionId, sessionKey } = event.context || {}; - if (!sessionId) { - return; - } - - // Get messages from the event context - // The messages are in event.context.sessionEntry or similar - const sessionEntry = event.context?.sessionEntry; - if (!sessionEntry || !sessionEntry.messages || sessionEntry.messages.length === 0) { - return; - } - - // Format messages into a transcript - const transcript = sessionEntry.messages - .map((msg: any) => { - const role = msg.role || 'unknown'; - const content = msg.content || ''; - return `${role}: ${content}`; - }) - .join('\n\n'); - - if (!transcript.trim()) { - return; - } - - // Retain to Hindsight with session_id as document_id - await client.retain({ - content: transcript, - document_id: sessionId, - metadata: { - session_key: sessionKey, - retained_at: new Date().toISOString(), - message_count: sessionEntry.messages.length, - }, - }); - - console.log(`[Hindsight] Retained ${sessionEntry.messages.length} messages for session ${sessionId}`); - } catch (error) { - console.error('[Hindsight] Error retaining messages:', error); - } -}; - -export default handler; diff --git a/hindsight-integrations/moltbot/skills/hindsight/SKILL.md b/hindsight-integrations/moltbot/skills/hindsight/SKILL.md deleted file mode 100644 index 553da9e5..00000000 --- a/hindsight-integrations/moltbot/skills/hindsight/SKILL.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: memory_search -description: Search your long-term memory for relevant facts, experiences, and context using semantic and graph-based retrieval -user-invocable: false -disable-model-invocation: false ---- - -# memory_search - -Search your long-term memory for relevant information. This tool provides multi-strategy retrieval combining: -- Semantic search across facts and experiences -- BM25 keyword matching -- Entity graph traversal -- Temporal queries -- Cross-encoder reranking - -## Usage - -Call `memory_search` with a natural language query to find relevant memories: - -``` -memory_search "What does the user prefer for breakfast?" -memory_search "When did we discuss the project deadline?" -memory_search "Tell me about Paris" -``` - -## Returns - -Returns a list of relevant memory fragments with: -- Content: The actual memory text -- Score: Relevance score (0-1) -- Metadata: Source document, creation date, entities - -Use the results to inform your responses with context from past conversations. diff --git a/hindsight-integrations/moltbot/skills/hindsight/handler.ts b/hindsight-integrations/moltbot/skills/hindsight/handler.ts deleted file mode 100644 index 518c8461..00000000 --- a/hindsight-integrations/moltbot/skills/hindsight/handler.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Handler for memory_search tool -// This will be called when the agent invokes memory_search - -import { getClient } from '../../src/index.js'; - -export interface ToolContext { - query: string; - args: Record; -} - -export async function handle(ctx: ToolContext): Promise { - try { - const { query } = ctx; - - const client = getClient(); - if (!client) { - throw new Error('Hindsight client not initialized'); - } - - // Call Hindsight recall API - const response = await client.recall({ - query, - limit: 10, - }); - - // Format results for the agent - if (!response.results || response.results.length === 0) { - return 'No relevant memories found for this query.'; - } - - const formatted = response.results - .map((result: any, idx: number) => { - const score = result.score ? ` (relevance: ${result.score.toFixed(2)})` : ''; - const date = result.metadata?.created_at - ? ` [${new Date(result.metadata.created_at).toLocaleDateString()}]` - : ''; - return `${idx + 1}. ${result.content}${score}${date}`; - }) - .join('\n\n'); - - return `Found ${response.results.length} relevant memories:\n\n${formatted}`; - } catch (error) { - console.error('[Hindsight] memory_search error:', error); - return `Error searching memories: ${error instanceof Error ? error.message : String(error)}`; - } -} diff --git a/hindsight-integrations/moltbot/.gitignore b/hindsight-integrations/openclawd/.gitignore similarity index 100% rename from hindsight-integrations/moltbot/.gitignore rename to hindsight-integrations/openclawd/.gitignore diff --git a/hindsight-integrations/openclawd/README.md b/hindsight-integrations/openclawd/README.md new file mode 100644 index 00000000..e1120dd6 --- /dev/null +++ b/hindsight-integrations/openclawd/README.md @@ -0,0 +1,35 @@ +# Hindsight Memory Plugin for OpenClawd + +Biomimetic long-term memory for [OpenClawd](https://openclawd.ai) using [Hindsight](https://vectorize.io/hindsight). Automatically captures conversations and intelligently recalls relevant context. + +## Quick Start + +```bash +# 1. Configure your LLM provider +export OPENAI_API_KEY="sk-your-key" +clawdbot config set 'agents.defaults.models."openai/gpt-4o-mini"' '{}' + +# 2. Install and enable the plugin +clawdbot plugins install @vectorize-io/hindsight-openclawd + +# 3. Start OpenClawd +clawdbot gateway +``` + +That's it! The plugin will automatically start capturing and recalling memories. + +## Documentation + +For full documentation, configuration options, troubleshooting, and development guide, see: + +**[OpenClawd Integration Documentation](https://vectorize.io/hindsight/sdks/integrations/openclawd)** + +## Links + +- [Hindsight Documentation](https://vectorize.io/hindsight) +- [OpenClawd Documentation](https://openclawd.ai) +- [GitHub Repository](https://github.com/vectorize-io/hindsight) + +## License + +MIT diff --git a/hindsight-integrations/openclawd/clawdbot.plugin.json b/hindsight-integrations/openclawd/clawdbot.plugin.json new file mode 100644 index 00000000..3a5f9685 --- /dev/null +++ b/hindsight-integrations/openclawd/clawdbot.plugin.json @@ -0,0 +1,49 @@ +{ + "id": "hindsight-openclawd", + "name": "Hindsight Memory", + "kind": "memory", + "configSchema": { + "type": "object", + "properties": { + "daemonIdleTimeout": { + "type": "number", + "description": "Seconds before daemon shuts down from inactivity (0 = never)", + "default": 0 + }, + "embedPort": { + "type": "number", + "description": "Port for hindsight-embed server (auto-assigned if not specified)", + "default": 0 + }, + "bankMission": { + "type": "string", + "description": "Custom mission/context for the memory bank", + "default": "You are an AI assistant helping users across multiple communication channels (Telegram, Slack, Discord, etc.). Remember user preferences, instructions, and important context from conversations to provide personalized assistance." + }, + "embedVersion": { + "type": "string", + "description": "hindsight-embed version to use (e.g. 'latest', '0.4.2', or empty for latest)", + "default": "latest" + } + }, + "additionalProperties": false + }, + "uiHints": { + "daemonIdleTimeout": { + "label": "Daemon Idle Timeout", + "placeholder": "0 (never timeout)" + }, + "embedPort": { + "label": "Embed Server Port", + "placeholder": "0 (auto-assign)" + }, + "bankMission": { + "label": "Bank Mission", + "placeholder": "Custom context for what this agent does..." + }, + "embedVersion": { + "label": "Hindsight Embed Version", + "placeholder": "latest (or pin to specific version like 0.4.2)" + } + } +} diff --git a/hindsight-integrations/moltbot/install.sh b/hindsight-integrations/openclawd/install.sh similarity index 83% rename from hindsight-integrations/moltbot/install.sh rename to hindsight-integrations/openclawd/install.sh index 438094ce..771427ab 100755 --- a/hindsight-integrations/moltbot/install.sh +++ b/hindsight-integrations/openclawd/install.sh @@ -5,7 +5,7 @@ echo "🚀 Installing Hindsight Memory Plugin for Moltbot..." # Get the directory where this script is located SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -INSTALL_DIR="$HOME/.clawdbot/extensions/hindsight-memory" +INSTALL_DIR="$HOME/.clawdbot/extensions/hindsight-openclawd" # Check Node version if ! command -v node &> /dev/null; then @@ -25,7 +25,7 @@ rm -rf "$INSTALL_DIR" mkdir -p "$INSTALL_DIR" # Copy files -cp -r dist package.json clawdbot.plugin.json hooks README.md "$INSTALL_DIR/" +cp -r dist package.json clawdbot.plugin.json README.md "$INSTALL_DIR/" # Install dependencies in deployed location echo "📥 Installing dependencies..." @@ -41,9 +41,9 @@ echo "1. Make sure you have an OpenAI API key set:" echo " export OPENAI_API_KEY=\"sk-your-key-here\"" echo "" echo "2. Enable the plugin:" -echo " clawdbot plugins enable hindsight-memory" +echo " clawdbot plugins enable hindsight-openclawd" echo "" -echo "3. Start Moltbot:" +echo "3. Start OpenClawd:" echo " clawdbot start" echo "" echo "On first start, uvx will automatically download hindsight-embed (no manual install needed)" diff --git a/hindsight-integrations/moltbot/package-lock.json b/hindsight-integrations/openclawd/package-lock.json similarity index 100% rename from hindsight-integrations/moltbot/package-lock.json rename to hindsight-integrations/openclawd/package-lock.json diff --git a/hindsight-integrations/moltbot/package.json b/hindsight-integrations/openclawd/package.json similarity index 73% rename from hindsight-integrations/moltbot/package.json rename to hindsight-integrations/openclawd/package.json index d856d8fa..165a18dd 100644 --- a/hindsight-integrations/moltbot/package.json +++ b/hindsight-integrations/openclawd/package.json @@ -1,21 +1,17 @@ { - "name": "@vectorize-io/hindsight-moltbot-plugin", - "version": "0.1.0", - "description": "Hindsight memory plugin for Moltbot - biomimetic long-term memory with fact extraction", + "name": "@vectorize-io/hindsight-openclawd", + "version": "0.0.5", + "description": "Hindsight memory plugin for OpenClawd - biomimetic long-term memory with fact extraction", "main": "dist/index.js", "types": "dist/index.d.ts", "type": "module", "clawdbot": { "extensions": [ "./dist/index.js" - ], - "hooks": [ - "hooks/retain-messages" ] }, "keywords": [ - "moltbot", - "clawdbot", + "openclawd", "memory", "ai", "agent", @@ -27,12 +23,11 @@ "repository": { "type": "git", "url": "https://github.com/vectorize-io/hindsight.git", - "directory": "hindsight-integrations/moltbot" + "directory": "hindsight-integrations/openclawd" }, "files": [ "dist", "clawdbot.plugin.json", - "hooks", "README.md" ], "scripts": { diff --git a/hindsight-integrations/moltbot/src/client.test.ts b/hindsight-integrations/openclawd/src/client.test.ts similarity index 100% rename from hindsight-integrations/moltbot/src/client.test.ts rename to hindsight-integrations/openclawd/src/client.test.ts diff --git a/hindsight-integrations/moltbot/src/client.ts b/hindsight-integrations/openclawd/src/client.ts similarity index 66% rename from hindsight-integrations/moltbot/src/client.ts rename to hindsight-integrations/openclawd/src/client.ts index bd5f25a2..9b021ade 100644 --- a/hindsight-integrations/moltbot/src/client.ts +++ b/hindsight-integrations/openclawd/src/client.ts @@ -15,17 +15,37 @@ export class HindsightClient { private llmProvider: string; private llmApiKey: string; private llmModel?: string; + private embedVersion: string; - constructor(llmProvider: string, llmApiKey: string, llmModel?: string) { + constructor(llmProvider: string, llmApiKey: string, llmModel?: string, embedVersion: string = 'latest') { this.llmProvider = llmProvider; this.llmApiKey = llmApiKey; this.llmModel = llmModel; + this.embedVersion = embedVersion || 'latest'; } setBankId(bankId: string): void { this.bankId = bankId; } + async setBankMission(mission: string): Promise { + if (!mission || mission.trim().length === 0) { + return; + } + + const escapedMission = mission.replace(/'/g, "'\\''"); // Escape single quotes + const embedPackage = this.embedVersion ? `hindsight-embed@${this.embedVersion}` : 'hindsight-embed@latest'; + const cmd = `uvx ${embedPackage} bank mission ${this.bankId} '${escapedMission}'`; + + try { + const { stdout } = await execAsync(cmd, { env: this.getEnv() }); + console.log(`[Hindsight] Bank mission set: ${stdout.trim()}`); + } catch (error) { + // Don't fail if mission set fails - bank might not exist yet, will be created on first retain + console.warn(`[Hindsight] Could not set bank mission (bank may not exist yet): ${error}`); + } + } + private getEnv(): Record { const env: Record = { ...process.env, @@ -44,7 +64,8 @@ export class HindsightClient { const content = request.content.replace(/'/g, "'\\''"); // Escape single quotes const docId = request.document_id || 'conversation'; - const cmd = `uvx hindsight-embed memory retain ${this.bankId} '${content}' --doc-id '${docId}' --async`; + const embedPackage = this.embedVersion ? `hindsight-embed@${this.embedVersion}` : 'hindsight-embed@latest'; + const cmd = `uvx ${embedPackage} memory retain ${this.bankId} '${content}' --doc-id '${docId}' --async`; try { const { stdout } = await execAsync(cmd, { env: this.getEnv() }); @@ -65,7 +86,8 @@ export class HindsightClient { const query = request.query.replace(/'/g, "'\\''"); // Escape single quotes const maxTokens = request.max_tokens || 1024; - const cmd = `uvx hindsight-embed memory recall ${this.bankId} '${query}' --output json --max-tokens ${maxTokens}`; + const embedPackage = this.embedVersion ? `hindsight-embed@${this.embedVersion}` : 'hindsight-embed@latest'; + const cmd = `uvx ${embedPackage} memory recall ${this.bankId} '${query}' --output json --max-tokens ${maxTokens}`; try { const { stdout } = await execAsync(cmd, { env: this.getEnv() }); diff --git a/hindsight-integrations/moltbot/src/embed-manager.ts b/hindsight-integrations/openclawd/src/embed-manager.ts similarity index 87% rename from hindsight-integrations/moltbot/src/embed-manager.ts rename to hindsight-integrations/openclawd/src/embed-manager.ts index 651cad55..a49a4a26 100644 --- a/hindsight-integrations/moltbot/src/embed-manager.ts +++ b/hindsight-integrations/openclawd/src/embed-manager.ts @@ -13,13 +13,15 @@ export class HindsightEmbedManager { private llmApiKey: string; private llmModel?: string; private daemonIdleTimeout: number; + private embedVersion: string; constructor( port: number, llmProvider: string, llmApiKey: string, llmModel?: string, - daemonIdleTimeout: number = 0 // Default: never timeout + daemonIdleTimeout: number = 0, // Default: never timeout + embedVersion: string = 'latest' // Default: latest ) { this.port = 8889; // hindsight-embed uses fixed port 8889 this.baseUrl = `http://127.0.0.1:8889`; @@ -28,6 +30,7 @@ export class HindsightEmbedManager { this.llmApiKey = llmApiKey; this.llmModel = llmModel; this.daemonIdleTimeout = daemonIdleTimeout; + this.embedVersion = embedVersion || 'latest'; } async start(): Promise { @@ -46,9 +49,10 @@ export class HindsightEmbedManager { } // Start hindsight-embed daemon (it manages itself) + const embedPackage = this.embedVersion ? `hindsight-embed@${this.embedVersion}` : 'hindsight-embed@latest'; const startDaemon = spawn( 'uvx', - ['hindsight-embed', 'daemon', 'start'], + [embedPackage, 'daemon', 'start'], { env, stdio: 'pipe', @@ -93,7 +97,8 @@ export class HindsightEmbedManager { async stop(): Promise { console.log('[Hindsight] Stopping hindsight-embed daemon...'); - const stopDaemon = spawn('uvx', ['hindsight-embed', 'daemon', 'stop'], { + const embedPackage = this.embedVersion ? `hindsight-embed@${this.embedVersion}` : 'hindsight-embed@latest'; + const stopDaemon = spawn('uvx', [embedPackage, 'daemon', 'stop'], { stdio: 'pipe', }); diff --git a/hindsight-integrations/moltbot/src/index.ts b/hindsight-integrations/openclawd/src/index.ts similarity index 77% rename from hindsight-integrations/moltbot/src/index.ts rename to hindsight-integrations/openclawd/src/index.ts index 7a290d91..76e9b665 100644 --- a/hindsight-integrations/moltbot/src/index.ts +++ b/hindsight-integrations/openclawd/src/index.ts @@ -7,11 +7,17 @@ import { fileURLToPath } from 'url'; // Module-level state let embedManager: HindsightEmbedManager | null = null; let client: HindsightClient | null = null; +let initPromise: Promise | null = null; +let isInitialized = false; // Global access for hooks (Moltbot loads hooks separately) if (typeof global !== 'undefined') { (global as any).__hindsightClient = { getClient: () => client, + waitForReady: async () => { + if (isInitialized) return; + if (initPromise) await initPromise; + }, }; } @@ -20,7 +26,7 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Default bank name -const BANK_NAME = 'moltbot'; +const BANK_NAME = 'openclawd'; // Provider mapping: moltbot provider name -> hindsight provider name const PROVIDER_MAP: Record = { @@ -108,11 +114,14 @@ function detectLLMConfig(api: MoltbotPluginAPI): { } function getPluginConfig(api: MoltbotPluginAPI): PluginConfig { - const config = api.config.plugins?.entries?.['hindsight-memory']?.config || {}; + const config = api.config.plugins?.entries?.['hindsight-openclawd']?.config || {}; + const defaultMission = 'You are an AI assistant helping users across multiple communication channels (Telegram, Slack, Discord, etc.). Remember user preferences, instructions, and important context from conversations to provide personalized assistance.'; + return { - bankMission: config.bankMission, + bankMission: config.bankMission || defaultMission, embedPort: config.embedPort || 0, daemonIdleTimeout: config.daemonIdleTimeout !== undefined ? config.daemonIdleTimeout : 0, + embedVersion: config.embedVersion || 'latest', }; } @@ -141,41 +150,57 @@ export default function (api: MoltbotPluginAPI) { const port = pluginConfig.embedPort || Math.floor(Math.random() * 10000) + 10000; console.log(`[Hindsight] Port: ${port}`); - // Register background service + // Initialize in background (non-blocking) + console.log('[Hindsight] Starting initialization in background...'); + initPromise = (async () => { + try { + // Initialize embed manager + console.log('[Hindsight] Creating HindsightEmbedManager...'); + embedManager = new HindsightEmbedManager( + port, + llmConfig.provider, + llmConfig.apiKey, + llmConfig.model, + pluginConfig.daemonIdleTimeout, + pluginConfig.embedVersion + ); + + // Start the embedded server + console.log('[Hindsight] Starting embedded server...'); + await embedManager.start(); + + // Initialize client + console.log('[Hindsight] Creating HindsightClient...'); + client = new HindsightClient(llmConfig.provider, llmConfig.apiKey, llmConfig.model, pluginConfig.embedVersion); + + // Use openclawd bank + console.log(`[Hindsight] Using bank: ${BANK_NAME}`); + client.setBankId(BANK_NAME); + + // Set bank mission + if (pluginConfig.bankMission) { + console.log(`[Hindsight] Setting bank mission...`); + await client.setBankMission(pluginConfig.bankMission); + } + + isInitialized = true; + console.log('[Hindsight] ✓ Ready'); + } catch (error) { + console.error('[Hindsight] Initialization error:', error); + throw error; + } + })(); + + // Don't await - let it initialize in background + + // Register background service for cleanup console.log('[Hindsight] Registering service...'); api.registerService({ id: 'hindsight-memory', async start() { - try { - console.log('[Hindsight] Service starting...'); - - // Initialize embed manager - console.log('[Hindsight] Creating HindsightEmbedManager...'); - embedManager = new HindsightEmbedManager( - port, - llmConfig.provider, - llmConfig.apiKey, - llmConfig.model, - pluginConfig.daemonIdleTimeout - ); - - // Start the embedded server - console.log('[Hindsight] Starting embedded server...'); - await embedManager.start(); - - // Initialize client - console.log('[Hindsight] Creating HindsightClient...'); - client = new HindsightClient(llmConfig.provider, llmConfig.apiKey, llmConfig.model); - - // Use moltbot bank - console.log(`[Hindsight] Using bank: ${BANK_NAME}`); - client.setBankId(BANK_NAME); - - console.log('[Hindsight] Service ready'); - } catch (error) { - console.error('[Hindsight] Service start error:', error); - throw error; - } + // Wait for background init if still pending + console.log('[Hindsight] Service start called - ensuring initialization complete...'); + if (initPromise) await initPromise; }, async stop() { @@ -188,6 +213,7 @@ export default function (api: MoltbotPluginAPI) { } client = null; + isInitialized = false; console.log('[Hindsight] Service stopped'); } catch (error) { @@ -229,14 +255,18 @@ export default function (api: MoltbotPluginAPI) { return; // Skip very short messages after extraction } - // Get client from global + // Wait for client to be ready const clientGlobal = (global as any).__hindsightClient; if (!clientGlobal) { + console.log('[Hindsight] Client global not available, skipping auto-recall'); return; } + await clientGlobal.waitForReady(); + const client = clientGlobal.getClient(); if (!client) { + console.log('[Hindsight] Client not initialized, skipping auto-recall'); return; } @@ -253,21 +283,12 @@ export default function (api: MoltbotPluginAPI) { return; } - // Format memories for injection - const memories = response.results - .map((result: any, idx: number) => { - const score = result.score ? ` (relevance: ${result.score.toFixed(2)})` : ''; - return `${idx + 1}. ${result.content}${score}`; - }) - .join('\n\n'); + // Format memories as JSON with all fields from recall + const memoriesJson = JSON.stringify(response.results, null, 2); - const contextMessage = ` -You have access to long-term memory from previous conversations. Here are relevant memories: - -${memories} - -Use this context naturally when relevant to the conversation. Don't mention "memory" or "recall" unless specifically asked about past conversations. -`; + const contextMessage = ` +${memoriesJson} +`; console.log(`[Hindsight] Auto-recall: Injecting ${response.results.length} memories`); @@ -289,13 +310,15 @@ Use this context naturally when relevant to the conversation. Don't mention "mem return; } - // Get client from global + // Wait for client to be ready const clientGlobal = (global as any).__hindsightClient; if (!clientGlobal) { console.warn('[Hindsight] Client global not found, skipping retain'); return; } + await clientGlobal.waitForReady(); + const client = clientGlobal.getClient(); if (!client) { console.warn('[Hindsight] Client not initialized, skipping retain'); diff --git a/hindsight-integrations/moltbot/src/moltbot-types.ts b/hindsight-integrations/openclawd/src/moltbot-types.ts similarity index 100% rename from hindsight-integrations/moltbot/src/moltbot-types.ts rename to hindsight-integrations/openclawd/src/moltbot-types.ts diff --git a/hindsight-integrations/moltbot/src/types.ts b/hindsight-integrations/openclawd/src/types.ts similarity index 95% rename from hindsight-integrations/moltbot/src/types.ts rename to hindsight-integrations/openclawd/src/types.ts index 1ee659ff..838d6216 100644 --- a/hindsight-integrations/moltbot/src/types.ts +++ b/hindsight-integrations/openclawd/src/types.ts @@ -31,6 +31,7 @@ export interface PluginConfig { bankMission?: string; embedPort?: number; daemonIdleTimeout?: number; // Seconds before daemon shuts down (0 = never) + embedVersion?: string; // hindsight-embed version (default: "latest") } export interface ServiceConfig { diff --git a/hindsight-integrations/moltbot/tsconfig.json b/hindsight-integrations/openclawd/tsconfig.json similarity index 86% rename from hindsight-integrations/moltbot/tsconfig.json rename to hindsight-integrations/openclawd/tsconfig.json index 69b801e6..d1f4cf02 100644 --- a/hindsight-integrations/moltbot/tsconfig.json +++ b/hindsight-integrations/openclawd/tsconfig.json @@ -14,5 +14,5 @@ "resolveJsonModule": true }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "skills"] + "exclude": ["node_modules", "dist", "src/**/*.test.ts"] } diff --git a/hindsight-integrations/openclawd/vectorize-io-hindsight-moltbot-plugin-0.1.0.tgz b/hindsight-integrations/openclawd/vectorize-io-hindsight-moltbot-plugin-0.1.0.tgz new file mode 100644 index 00000000..b9a5a71a Binary files /dev/null and b/hindsight-integrations/openclawd/vectorize-io-hindsight-moltbot-plugin-0.1.0.tgz differ diff --git a/hindsight-integrations/moltbot/vitest.config.ts b/hindsight-integrations/openclawd/vitest.config.ts similarity index 100% rename from hindsight-integrations/moltbot/vitest.config.ts rename to hindsight-integrations/openclawd/vitest.config.ts diff --git a/scripts/release.sh b/scripts/release.sh index ae00d080..cb9e003d 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -144,6 +144,16 @@ else print_warn "File $TYPESCRIPT_CLIENT_PKG not found, skipping" fi +# Update OpenClawd integration +OPENCLAWD_PKG="hindsight-integrations/openclawd/package.json" +if [ -f "$OPENCLAWD_PKG" ]; then + print_info "Updating $OPENCLAWD_PKG" + sed -i.bak "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" "$OPENCLAWD_PKG" + rm "${OPENCLAWD_PKG}.bak" +else + print_warn "File $OPENCLAWD_PKG not found, skipping" +fi + # Update documentation version (creates new version or syncs to existing) print_info "Updating documentation for version $VERSION..." if [ -f "scripts/update-docs-version.sh" ]; then @@ -188,6 +198,7 @@ COMMIT_MSG="Release v$VERSION - TypeScript client: hindsight-clients/typescript - Rust CLI: hindsight-cli - Control Plane: hindsight-control-plane +- OpenClawd integration: hindsight-integrations/openclawd - Helm chart" # Add docs update note