@cortexmem/bridge-openclaw 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # @cortexmem/bridge-openclaw
2
+
3
+ Bridge plugin that connects [OpenClaw](https://github.com/openclaw) agents to [Cortex](https://github.com/rikouu/cortex) memory service.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @cortexmem/bridge-openclaw
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import cortexBridge from '@cortexmem/bridge-openclaw';
15
+
16
+ const agent = new Agent({
17
+ plugins: [cortexBridge],
18
+ });
19
+ ```
20
+
21
+ ## Environment Variables
22
+
23
+ | Variable | Default | Description |
24
+ |----------|---------|-------------|
25
+ | `CORTEX_URL` | `http://localhost:21100` | Cortex server URL |
26
+ | `CORTEX_DEBUG` | — | Enable debug logging |
27
+
28
+ ## Hooks
29
+
30
+ The plugin provides three automatic hooks:
31
+
32
+ - **`onBeforeResponse`** — Recalls relevant memories and injects them as context before the agent responds.
33
+ - **`onAfterResponse`** — Extracts memories from conversations after the agent responds (fire-and-forget).
34
+ - **`onBeforeCompaction`** — Emergency flush of key information before context window compression.
35
+
36
+ ## API
37
+
38
+ ### `healthCheck()`
39
+
40
+ Verify the Cortex server is reachable.
41
+
42
+ ```typescript
43
+ import { healthCheck } from '@cortexmem/bridge-openclaw';
44
+
45
+ const status = await healthCheck();
46
+ // { ok: true, latency_ms: 12 }
47
+ ```
48
+
49
+ ### Individual Hooks
50
+
51
+ You can also import hooks individually:
52
+
53
+ ```typescript
54
+ import { onBeforeResponse, onAfterResponse, onBeforeCompaction } from '@cortexmem/bridge-openclaw';
55
+ ```
56
+
57
+ ## License
58
+
59
+ MIT
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Cortex Bridge Plugin for OpenClaw
3
+ *
4
+ * Thin bridge (~200 lines) that forwards OpenClaw hooks to Cortex Sidecar REST API.
5
+ * Key design: NEVER block the Agent. All calls have hard timeouts + graceful fallback.
6
+ */
7
+ interface AgentContext {
8
+ agentId?: string;
9
+ sessionId?: string;
10
+ lastUserMessage?: string;
11
+ lastAssistantMessage?: string;
12
+ messages?: {
13
+ role: string;
14
+ content: string;
15
+ }[];
16
+ metadata?: Record<string, any>;
17
+ }
18
+ interface PluginResult {
19
+ prependContext?: string;
20
+ }
21
+ /**
22
+ * Called before Agent generates a response.
23
+ * Searches Cortex for relevant memories and injects them as context.
24
+ */
25
+ declare function onBeforeResponse(context: AgentContext): Promise<PluginResult | null>;
26
+ /**
27
+ * Called after Agent generates a response.
28
+ * Sends the conversation exchange to Cortex for memory extraction.
29
+ * Fire-and-forget — does NOT wait for result.
30
+ */
31
+ declare function onAfterResponse(context: AgentContext): Promise<void>;
32
+ /**
33
+ * Called before context window compaction.
34
+ * Emergency flush — extract key info before it's lost.
35
+ */
36
+ declare function onBeforeCompaction(context: AgentContext): Promise<void>;
37
+ /**
38
+ * Health check — verify Cortex Sidecar is reachable.
39
+ */
40
+ declare function healthCheck(): Promise<{
41
+ ok: boolean;
42
+ latency_ms: number;
43
+ error?: string;
44
+ }>;
45
+ declare const pluginInfo: {
46
+ name: string;
47
+ version: string;
48
+ description: string;
49
+ cortexUrl: string;
50
+ };
51
+ declare const _default: {
52
+ name: string;
53
+ onBeforeResponse: typeof onBeforeResponse;
54
+ onAfterResponse: typeof onAfterResponse;
55
+ onBeforeCompaction: typeof onBeforeCompaction;
56
+ healthCheck: typeof healthCheck;
57
+ pluginInfo: {
58
+ name: string;
59
+ version: string;
60
+ description: string;
61
+ cortexUrl: string;
62
+ };
63
+ };
64
+
65
+ export { _default as default, healthCheck, onAfterResponse, onBeforeCompaction, onBeforeResponse, pluginInfo };
package/dist/index.js ADDED
@@ -0,0 +1,103 @@
1
+ // src/index.ts
2
+ var CORTEX_URL = process.env.CORTEX_URL || "http://localhost:21100";
3
+ var RECALL_TIMEOUT = 3e3;
4
+ var INGEST_TIMEOUT = 5e3;
5
+ var FLUSH_TIMEOUT = 5e3;
6
+ async function onBeforeResponse(context) {
7
+ if (!context.lastUserMessage) return null;
8
+ try {
9
+ const res = await fetch(`${CORTEX_URL}/api/v1/recall`, {
10
+ method: "POST",
11
+ headers: { "Content-Type": "application/json" },
12
+ body: JSON.stringify({
13
+ query: context.lastUserMessage,
14
+ agent_id: context.agentId || "openclaw",
15
+ max_tokens: 2e3
16
+ }),
17
+ signal: AbortSignal.timeout(RECALL_TIMEOUT)
18
+ });
19
+ if (res.ok) {
20
+ const data = await res.json();
21
+ if (data.context && data.meta.injected_count > 0) {
22
+ return { prependContext: data.context };
23
+ }
24
+ }
25
+ } catch (e) {
26
+ if (process.env.CORTEX_DEBUG) {
27
+ console.warn("[cortex-bridge] Sidecar unreachable for recall:", e.message);
28
+ }
29
+ }
30
+ return null;
31
+ }
32
+ async function onAfterResponse(context) {
33
+ if (!context.lastUserMessage || !context.lastAssistantMessage) return;
34
+ try {
35
+ fetch(`${CORTEX_URL}/api/v1/ingest`, {
36
+ method: "POST",
37
+ headers: { "Content-Type": "application/json" },
38
+ body: JSON.stringify({
39
+ user_message: context.lastUserMessage,
40
+ assistant_message: context.lastAssistantMessage,
41
+ agent_id: context.agentId || "openclaw",
42
+ session_id: context.sessionId
43
+ }),
44
+ signal: AbortSignal.timeout(INGEST_TIMEOUT)
45
+ }).catch(() => {
46
+ });
47
+ } catch {
48
+ }
49
+ }
50
+ async function onBeforeCompaction(context) {
51
+ if (!context.messages || context.messages.length === 0) return;
52
+ try {
53
+ await fetch(`${CORTEX_URL}/api/v1/flush`, {
54
+ method: "POST",
55
+ headers: { "Content-Type": "application/json" },
56
+ body: JSON.stringify({
57
+ messages: context.messages,
58
+ agent_id: context.agentId || "openclaw",
59
+ session_id: context.sessionId,
60
+ reason: "compaction"
61
+ }),
62
+ signal: AbortSignal.timeout(FLUSH_TIMEOUT)
63
+ });
64
+ } catch (e) {
65
+ if (process.env.CORTEX_DEBUG) {
66
+ console.warn("[cortex-bridge] Flush failed:", e.message);
67
+ }
68
+ }
69
+ }
70
+ async function healthCheck() {
71
+ const start = Date.now();
72
+ try {
73
+ const res = await fetch(`${CORTEX_URL}/api/v1/health`, {
74
+ signal: AbortSignal.timeout(2e3)
75
+ });
76
+ const data = await res.json();
77
+ return { ok: data.status === "ok", latency_ms: Date.now() - start };
78
+ } catch (e) {
79
+ return { ok: false, latency_ms: Date.now() - start, error: e.message };
80
+ }
81
+ }
82
+ var pluginInfo = {
83
+ name: "cortex-bridge",
84
+ version: "0.1.0",
85
+ description: "Bridge plugin for Cortex AI Agent Memory Service",
86
+ cortexUrl: CORTEX_URL
87
+ };
88
+ var index_default = {
89
+ name: "cortex-bridge",
90
+ onBeforeResponse,
91
+ onAfterResponse,
92
+ onBeforeCompaction,
93
+ healthCheck,
94
+ pluginInfo
95
+ };
96
+ export {
97
+ index_default as default,
98
+ healthCheck,
99
+ onAfterResponse,
100
+ onBeforeCompaction,
101
+ onBeforeResponse,
102
+ pluginInfo
103
+ };
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@cortexmem/bridge-openclaw",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "scripts": {
15
+ "build": "tsup src/index.ts --format esm --dts",
16
+ "dev": "tsx src/index.ts"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^22.19.11",
20
+ "tsup": "^8.4.0",
21
+ "tsx": "^4.19.3",
22
+ "typescript": "^5.7.3"
23
+ }
24
+ }