@laceletho/plugin-openclaw 0.1.2 → 0.2.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 CHANGED
@@ -1,41 +1,38 @@
1
1
  # @laceletho/plugin-openclaw
2
2
 
3
- OpenCode plugin for asynchronous task execution with OpenClaw callback support.
3
+ OpenCode plugin for session callback support with OpenClaw. Subscribes to OpenCode events and sends webhooks to OpenClaw when registered sessions complete.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Webhook Receiver**: HTTP endpoint to receive tasks from OpenClaw
8
- - **Async Task Queue**: Configurable concurrent task execution
9
- - **Automatic Callback**: Reports task results back to OpenClaw via webhook
10
- - **Session Integration**: Uses OpenCode's session API for task execution
7
+ - **Event-Driven**: Subscribes to OpenCode `session.updated` events
8
+ - **Callback Registration**: HTTP endpoint for CLI/tools to register callback needs
9
+ - **Automatic Callback**: Sends webhooks to OpenClaw when sessions complete
10
+ - **Session Tracking**: Tracks registered sessions and cleans up after callback
11
11
 
12
12
  ## Architecture
13
13
 
14
14
  ```
15
- ┌─────────────┐ POST /tasks ┌─────────────────────┐
16
- OpenClaw ─────────────────────→ │ OpenclawPlugin │
17
- │ (External) │ (Webhook Server)
18
- └─────────────┘ └──────────┬──────────┘
19
-
20
- ┌───────────────────────┘
21
-
22
-
23
- ┌───────────────┐
24
- │ Task Queue │
25
- └───────┬───────┘
26
-
27
-
28
- ┌───────────────┐
29
- OpenCode │
30
- Session │
31
- └───────┬───────┘
32
-
33
-
34
- ┌───────────────┐
35
- │ Callback │
36
- │ to OpenClaw │
37
- │ /hooks/agent │
38
- └───────────────┘
15
+ ┌─────────────────┐ POST /register ┌─────────────────────┐
16
+ CLI/Tool ──────────────────────> │ OpenclawPlugin │
17
+ │ (External) │ {sessionId, callback} │ (HTTP Server 9090)
18
+ └─────────────────┘ └──────────┬──────────┘
19
+
20
+ │ stores in
21
+ callbackRegistry
22
+
23
+
24
+ ┌─────────────────────┐
25
+ │ Subscribe to │
26
+ session.updated │
27
+ │ session.deleted │
28
+ └──────────┬──────────┘
29
+
30
+ session completes
31
+
32
+ ┌─────────────────────┐
33
+ │ Send callback to │
34
+ │ OpenClaw /hooks │
35
+ └─────────────────────┘
39
36
  ```
40
37
 
41
38
  ## Installation
@@ -55,67 +52,44 @@ Add to your `opencode.json`:
55
52
  "plugins": ["@laceletho/plugin-openclaw"],
56
53
  "openclaw": {
57
54
  "port": 9090,
58
- "openclawWebhookUrl": "http://localhost:18789/hooks/agent",
59
- "openclawApiKey": "your-openclaw-hooks-token",
60
- "maxConcurrentTasks": 5
55
+ "openclawApiKey": "your-openclaw-hooks-token"
61
56
  }
62
57
  }
63
58
  ```
64
59
 
65
- ### OpenClaw Configuration (Required)
60
+ ### Environment Variables
66
61
 
67
- To receive webhook callbacks from this plugin, OpenClaw must have its **hooks system enabled**. Add this to your OpenClaw configuration file (`~/.openclaw/openclaw.json` or `openclaw.json`):
62
+ | Variable | Description | Default |
63
+ |----------|-------------|---------|
64
+ | `OPENCLAW_PORT` | Plugin HTTP server port | `9090` |
65
+ | `OPENCLAW_API_KEY` | Default OpenClaw hooks token | - |
68
66
 
69
- ```json
70
- {
71
- "hooks": {
72
- "enabled": true,
73
- "token": "your-openclaw-hooks-token",
74
- "path": "/hooks",
75
- "allowedAgentIds": ["main", "hooks"],
76
- "defaultSessionKey": "hook:opencode",
77
- "allowRequestSessionKey": false,
78
- "allowedSessionKeyPrefixes": ["hook:"]
79
- }
80
- }
81
- ```
67
+ ## How It Works
82
68
 
83
- **Important security settings:**
84
- - `token`: Must match the `openclawApiKey` in the plugin config
85
- - `allowedAgentIds`: Restrict which agents can receive hook messages
86
- - `allowRequestSessionKey: false`: Prevents external callers from specifying session keys (recommended)
87
- - `allowedSessionKeyPrefixes`: When `allowRequestSessionKey` is false, OpenClaw generates session keys with these prefixes
69
+ 1. **Registration**: When a CLI/tool creates an OpenCode session and wants a callback, it sends a POST request to the plugin's `/register` endpoint with the session ID and callback configuration.
88
70
 
89
- ### Environment Variables
71
+ 2. **Event Subscription**: The plugin subscribes to OpenCode's `session.updated` and `session.deleted` events.
90
72
 
91
- | Variable | Description | Default |
92
- |----------|-------------|---------|
93
- | `OPENCLAW_PORT` | Webhook server port | `9090` |
94
- | `OPENCLAW_WEBHOOK_URL` | OpenClaw hooks endpoint | `http://localhost:18789/hooks/agent` |
95
- | `OPENCLAW_API_KEY` | OpenClaw hooks token | - |
96
- | `OPENCLAW_MAX_CONCURRENT` | Max concurrent tasks | `5` |
73
+ 3. **Callback Trigger**: When a registered session's status changes to `completed` or `failed`, the plugin automatically sends a webhook to the configured OpenClaw endpoint.
74
+
75
+ 4. **Cleanup**: After sending the callback (or when a session is deleted), the plugin removes the registration from memory.
97
76
 
98
77
  ## API Endpoints
99
78
 
100
- ### POST /tasks
79
+ ### POST /register
101
80
 
102
- Submit a new task for execution.
81
+ Register a session for callback when it completes.
103
82
 
104
83
  **Request:**
105
84
  ```json
106
85
  {
107
- "taskId": "unique-task-id",
108
- "prompt": "Write a Python function to calculate fibonacci numbers",
109
- "callbackUrl": "http://localhost:18789/hooks/agent",
86
+ "sessionId": "sess_abc123",
110
87
  "callbackConfig": {
111
- "name": "OpenCode Task",
88
+ "url": "http://localhost:18789/hooks/agent",
89
+ "apiKey": "your-openclaw-token",
112
90
  "agentId": "main",
113
- "deliver": true,
114
- "channel": "telegram"
115
- },
116
- "metadata": {
117
- "userId": "user-123",
118
- "priority": "high"
91
+ "channel": "last",
92
+ "deliver": true
119
93
  }
120
94
  }
121
95
  ```
@@ -123,23 +97,8 @@ Submit a new task for execution.
123
97
  **Response:**
124
98
  ```json
125
99
  {
126
- "taskId": "unique-task-id",
127
- "status": "accepted"
128
- }
129
- ```
130
-
131
- ### GET /tasks/:taskId
132
-
133
- Check task status.
134
-
135
- **Response:**
136
- ```json
137
- {
138
- "taskId": "unique-task-id",
139
- "status": "completed",
140
- "result": "Here's the Python function...",
141
- "createdAt": "2024-03-12T10:00:00Z",
142
- "updatedAt": "2024-03-12T10:05:00Z"
100
+ "ok": true,
101
+ "sessionId": "sess_abc123"
143
102
  }
144
103
  ```
145
104
 
@@ -151,156 +110,122 @@ Health check endpoint.
151
110
  ```json
152
111
  {
153
112
  "status": "ok",
154
- "tasks": 3,
155
- "running": 2
113
+ "registeredSessions": 5
156
114
  }
157
115
  ```
158
116
 
159
- ## Callback to OpenClaw
117
+ ## OpenCode Events
118
+
119
+ The plugin subscribes to the following OpenCode events:
120
+
121
+ ### `message.part.updated`
122
+
123
+ Triggered when a message part is created or updated. The plugin accumulates text content and tool outputs from these events to build the complete session result.
124
+
125
+ ### `message.part.delta`
126
+
127
+ Triggered during streaming text generation. The plugin appends streaming deltas to the accumulated content.
128
+
129
+ ### `session.updated`
130
+
131
+ Triggered when session metadata is updated. The plugin monitors the session status and sends the callback when the status becomes `completed` or `failed`.
132
+
133
+ ### `session.error`
134
+
135
+ Triggered when a session encounters an error. The plugin marks the session as failed and includes error information in the callback.
160
136
 
161
- When a task completes, the plugin sends a POST request to OpenClaw's `/hooks/agent` endpoint:
137
+ ### `session.deleted`
162
138
 
163
- ### OpenClaw /hooks/agent Payload Format
139
+ Triggered when a session is deleted. The plugin removes the session from the callback registry.
164
140
 
165
- The plugin sends task results to OpenClaw using its native hooks format:
141
+ ### Important: Event Data Limitations
142
+
143
+ **`session.updated` events do NOT contain message content**. They only include session metadata (id, status, timestamps, etc.). The actual content is delivered through separate `message.part.*` events.
144
+
145
+ The plugin automatically handles this by:
146
+ 1. Listening to `message.part.updated` and `message.part.delta` events
147
+ 2. Accumulating text and tool outputs in memory
148
+ 3. Including the accumulated content when sending the callback on `session.updated`
149
+
150
+ ## Callback to OpenClaw
151
+
152
+ When a registered session completes, the plugin sends a POST request to the configured URL:
153
+
154
+ ### Payload Format
166
155
 
167
156
  ```json
168
157
  {
169
- "message": "Task completed: File processing finished\n\nResults:\nHere's the Python function...",
158
+ "message": "Task completed: sess_abc123\n\nResult:\nHere's the code...",
170
159
  "name": "OpenCode Task",
171
160
  "agentId": "main",
172
161
  "wakeMode": "now",
173
162
  "deliver": true,
174
- "channel": "last",
175
- "model": "anthropic/claude-sonnet-4-5",
176
- "timeoutSeconds": 300
163
+ "channel": "last"
177
164
  }
178
165
  ```
179
166
 
180
167
  **Authentication:**
181
168
  ```
182
- Authorization: Bearer <openclawApiKey>
169
+ Authorization: Bearer <apiKey>
183
170
  Content-Type: application/json
184
171
  ```
185
172
 
186
- ### OpenClaw /hooks/agent Endpoint Reference
173
+ ## Usage with CLI
187
174
 
188
- OpenClaw's `/hooks/agent` endpoint accepts the following payload structure:
175
+ This plugin is designed to work with `openclaw-opencode-cli`:
189
176
 
190
- | Field | Type | Required | Description |
191
- |-------|------|----------|-------------|
192
- | `message` | string | Yes | The message to send to the agent |
193
- | `name` | string | Yes | Display name for this hook invocation |
194
- | `agentId` | string | No | Target agent ID (falls back to default) |
195
- | `wakeMode` | string | No | `"now"` or `"next-heartbeat"` (default: `"now"`) |
196
- | `sessionKey` | string | No | Session identifier (requires `allowRequestSessionKey: true`) |
197
- | `deliver` | boolean | No | Whether to deliver response to messaging channel (default: `true`) |
198
- | `channel` | string | No | Target channel: `"last"`, `"telegram"`, `"slack"`, `"discord"`, etc. |
199
- | `to` | string | No | Recipient identifier for the channel |
200
- | `model` | string | No | Model override (e.g., `"anthropic/claude-sonnet-4-5"`) |
201
- | `thinking` | string | No | Thinking level: `"low"`, `"medium"`, `"high"` |
202
- | `timeoutSeconds` | number | No | Maximum duration for the agent run |
177
+ ```bash
178
+ # 1. Start OpenCode with the plugin
179
+ opencode serve
203
180
 
204
- ## Usage Example
181
+ # 2. From another terminal, dispatch a task with CLI
182
+ export OPENCODE_URL=http://localhost:4096
183
+ export OPENCODE_PASSWORD=your-password
184
+ export OPENCLAW_CALLBACK_URL=http://localhost:18789/hooks/agent
205
185
 
206
- ### 1. Configure OpenClaw
186
+ openclaw-opencode task "Write a Python function"
207
187
 
208
- Edit your `~/.openclaw/openclaw.json`:
188
+ # 3. Plugin automatically sends callback when session completes
189
+ ```
190
+
191
+ ## OpenClaw Configuration
192
+
193
+ To receive webhook callbacks, OpenClaw must have its **hooks system enabled**. Add this to your OpenClaw configuration:
209
194
 
210
195
  ```json
211
196
  {
212
197
  "hooks": {
213
198
  "enabled": true,
214
- "token": "my-secure-webhook-token",
199
+ "token": "your-openclaw-hooks-token",
215
200
  "path": "/hooks",
216
- "allowedAgentIds": ["main"]
217
- },
218
- "channels": {
219
- "telegram": {
220
- "botToken": "${TELEGRAM_BOT_TOKEN}",
221
- "allowFrom": ["*"]
222
- }
201
+ "allowedAgentIds": ["main", "hooks"]
223
202
  }
224
203
  }
225
204
  ```
226
205
 
227
- ### 2. Start OpenCode with the plugin
206
+ ## Testing
207
+
208
+ Test the plugin health:
228
209
 
229
210
  ```bash
230
- export OPENCLAW_WEBHOOK_URL="http://localhost:18789/hooks/agent"
231
- export OPENCLAW_API_KEY="my-secure-webhook-token"
232
- opencode serve
211
+ curl http://localhost:9090/health
233
212
  ```
234
213
 
235
- ### 3. Send a task from OpenClaw
214
+ Test callback registration:
236
215
 
237
216
  ```bash
238
- curl -X POST http://localhost:9090/tasks \
217
+ curl -X POST http://localhost:9090/register \
239
218
  -H "Content-Type: application/json" \
240
219
  -d '{
241
- "taskId": "task-001",
242
- "prompt": "Create a React component for a todo list",
243
- "callbackUrl": "http://localhost:18789/hooks/agent",
220
+ "sessionId": "test-session-123",
244
221
  "callbackConfig": {
245
- "name": "OpenCode Task",
246
- "agentId": "main",
247
- "deliver": true,
248
- "channel": "telegram"
222
+ "url": "http://localhost:18789/hooks/agent",
223
+ "apiKey": "your-token",
224
+ "agentId": "main"
249
225
  }
250
226
  }'
251
227
  ```
252
228
 
253
- ### 4. Receive callback in OpenClaw
254
-
255
- OpenClaw will receive the task completion via its `/hooks/agent` endpoint and can forward it to your configured messaging channel (Telegram, Slack, Discord, etc.).
256
-
257
- ## Testing Webhook Callback
258
-
259
- Test that OpenClaw can receive webhooks:
260
-
261
- ```bash
262
- curl -X POST http://localhost:18789/hooks/agent \
263
- -H "Authorization: Bearer your-openclaw-hooks-token" \
264
- -H "Content-Type: application/json" \
265
- -d '{
266
- "message": "Test message from OpenCode plugin",
267
- "name": "Test Hook",
268
- "deliver": true,
269
- "channel": "last"
270
- }'
271
- ```
272
-
273
- ## Comparison with claude-code-hooks
274
-
275
- | Feature | claude-code-hooks | @laceletho/plugin-openclaw |
276
- |---------|------------------|------------------------------|
277
- | Trigger | Stop/SessionEnd hooks | Webhook HTTP endpoint |
278
- | Integration | Shell scripts | TypeScript plugin |
279
- | Orchestration | Agent Teams | Session API |
280
- | Notification | Telegram + file | OpenClaw /hooks/agent |
281
- | Metadata | task-meta.json | In-memory + HTTP API |
282
- | Callback Format | Shell + CLI | HTTP POST to /hooks/agent |
283
-
284
- ## Troubleshooting
285
-
286
- ### "Unauthorized" errors
287
-
288
- Ensure the `openclawApiKey` in plugin config matches the `hooks.token` in OpenClaw config.
289
-
290
- ### Callbacks not received
291
-
292
- 1. Verify OpenClaw Gateway is running: `curl http://localhost:18789/health`
293
- 2. Check hooks are enabled in OpenClaw config
294
- 3. Ensure network connectivity between OpenCode and OpenClaw
295
- 4. Check OpenClaw logs for incoming requests
296
-
297
- ### Security Considerations
298
-
299
- - Keep `hooks.token` secret and use a strong random value
300
- - Run OpenClaw Gateway behind a firewall or Tailscale for remote access
301
- - Use `allowRequestSessionKey: false` to prevent session key injection
302
- - Restrict `allowedAgentIds` to only necessary agents
303
-
304
229
  ## Development
305
230
 
306
231
  ```bash
package/dist/index.d.ts CHANGED
@@ -1,28 +1,18 @@
1
+ import type { PluginInput } from "@opencode-ai/plugin";
1
2
  export interface OpenclawConfig {
2
3
  port?: number;
3
4
  openclawWebhookUrl?: string;
4
5
  openclawApiKey?: string;
5
- maxConcurrentTasks?: number;
6
6
  }
7
- interface PluginInput {
8
- client: {
9
- session: {
10
- create: () => Promise<any>;
11
- prompt: (pathParams: {
12
- path: {
13
- id: string;
14
- };
15
- }, body: {
16
- content: string;
17
- }) => Promise<any>;
18
- };
19
- };
20
- }
21
- declare const OpenclawPlugin: ({ client }: PluginInput) => Promise<{
7
+ export default function OpenclawPlugin({}: PluginInput): Promise<{
22
8
  config: (cfg: {
23
9
  openclaw?: OpenclawConfig;
24
10
  }) => Promise<void>;
11
+ "message.part.updated": (event: any) => Promise<void>;
12
+ "message.part.delta": (event: any) => Promise<void>;
13
+ "session.updated": (event: any) => Promise<void>;
14
+ "session.error": (event: any) => Promise<void>;
15
+ "session.deleted": (event: any) => Promise<void>;
25
16
  dispose: () => Promise<void>;
26
17
  }>;
27
- export default OpenclawPlugin;
28
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAcD,UAAU,WAAW;IACnB,MAAM,EAAE;QACN,OAAO,EAAE;YACP,MAAM,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;YAC1B,MAAM,EAAE,CAAC,UAAU,EAAE;gBAAE,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,EAAE,IAAI,EAAE;gBAAE,OAAO,EAAE,MAAM,CAAA;aAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;SAC1F,CAAA;KACF,CAAA;CACF;AAgED,QAAA,MAAM,cAAc,GAAU,YAAY,WAAW;kBA8H7B;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE;;EAgBpD,CAAA;AAED,eAAe,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEtD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAwGD,wBAA8B,cAAc,CAAC,EAAE,EAAE,WAAW;kBAoEpC;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE;oCAOX,GAAG;kCAyCL,GAAG;+BAcN,GAAG;6BAiBL,GAAG;+BAWD,GAAG;;GAcvC"}
package/dist/index.js CHANGED
@@ -1,13 +1,9 @@
1
1
  import { createServer } from "http";
2
- import { EventEmitter } from "events";
3
- const tasks = new Map();
4
- let runningTasks = 0;
5
- const events = new EventEmitter();
6
- const config = {
2
+ const sessionRegistry = new Map();
3
+ let pluginConfig = {
7
4
  port: 9090,
8
5
  openclawWebhookUrl: "",
9
6
  openclawApiKey: "",
10
- maxConcurrentTasks: 5
11
7
  };
12
8
  const readBody = (req) => {
13
9
  return new Promise((resolve, reject) => {
@@ -17,164 +13,222 @@ const readBody = (req) => {
17
13
  req.on("error", reject);
18
14
  });
19
15
  };
20
- const waitForSlot = () => {
21
- return new Promise((resolve) => {
22
- const handler = () => {
23
- events.off("slot-freed", handler);
24
- resolve();
25
- };
26
- events.once("slot-freed", handler);
27
- });
16
+ const formatCallbackMessage = (sessionId, state) => {
17
+ const lines = [];
18
+ if (state.hasError) {
19
+ lines.push(`Task failed: ${sessionId}`);
20
+ if (state.errorMessage) {
21
+ lines.push(`\nError:\n${state.errorMessage}`);
22
+ }
23
+ }
24
+ else {
25
+ lines.push(`Task completed: ${sessionId}`);
26
+ }
27
+ if (state.textParts.length > 0) {
28
+ lines.push("\nResult:");
29
+ lines.push(state.textParts.join(""));
30
+ }
31
+ if (state.toolOutputs.length > 0) {
32
+ lines.push("\n\nTools executed:");
33
+ for (const tool of state.toolOutputs) {
34
+ lines.push(`\n[${tool.tool}]:`);
35
+ if (tool.error) {
36
+ lines.push(` Error: ${tool.error}`);
37
+ }
38
+ else {
39
+ lines.push(` ${tool.output}`);
40
+ }
41
+ }
42
+ }
43
+ return lines.join("\n");
28
44
  };
29
- const notifyOpenclaw = async (task) => {
30
- if (!task.callbackUrl)
31
- return;
45
+ const sendCallback = async (sessionId, state) => {
32
46
  const payload = {
33
- taskId: task.id,
34
- status: task.status,
35
- result: task.result,
36
- error: task.error,
37
- sessionId: task.sessionId,
38
- completedAt: task.updatedAt.toISOString()
47
+ message: formatCallbackMessage(sessionId, state),
48
+ name: "OpenCode Task",
49
+ agentId: state.config.agentId || "main",
50
+ wakeMode: "now",
51
+ deliver: state.config.deliver ?? true,
52
+ channel: state.config.channel || "last",
39
53
  };
40
54
  try {
41
- const res = await fetch(task.callbackUrl, {
55
+ const res = await fetch(state.config.url, {
42
56
  method: "POST",
43
57
  headers: {
44
58
  "Content-Type": "application/json",
45
- ...(config.openclawApiKey ? { "Authorization": `Bearer ${config.openclawApiKey}` } : {})
59
+ ...(state.config.apiKey ? { Authorization: `Bearer ${state.config.apiKey}` } : {}),
46
60
  },
47
- body: JSON.stringify(payload)
61
+ body: JSON.stringify(payload),
48
62
  });
49
63
  if (!res.ok) {
50
- console.error(`[openclaw] Callback failed for task ${task.id}: ${res.status} ${res.statusText}`);
64
+ console.error(`[openclaw] Callback failed for session ${sessionId}: ${res.status} ${res.statusText}`);
51
65
  }
52
66
  else {
53
- console.log(`[openclaw] Callback sent for task: ${task.id}`);
67
+ console.log(`[openclaw] Callback sent for session: ${sessionId}`);
54
68
  }
55
69
  }
56
70
  catch (err) {
57
- console.error(`[openclaw] Failed to send callback for task ${task.id}:`, err);
71
+ console.error(`[openclaw] Failed to send callback for session ${sessionId}:`, err);
58
72
  }
59
73
  };
60
- const OpenclawPlugin = async ({ client }) => {
74
+ const handleSessionComplete = async (sessionId, state) => {
75
+ console.log(`[openclaw] Session ${sessionId} ${state.hasError ? "failed" : "completed"}, sending callback...`);
76
+ await sendCallback(sessionId, state);
77
+ sessionRegistry.delete(sessionId);
78
+ };
79
+ export default async function OpenclawPlugin({}) {
61
80
  const server = createServer(async (req, res) => {
62
81
  const url = req.url || "/";
63
82
  const method = req.method || "GET";
64
83
  res.setHeader("Content-Type", "application/json");
65
84
  if (url === "/health" && method === "GET") {
66
85
  res.writeHead(200);
67
- res.end(JSON.stringify({ status: "ok", tasks: tasks.size, running: runningTasks }));
86
+ res.end(JSON.stringify({
87
+ status: "ok",
88
+ registeredSessions: sessionRegistry.size,
89
+ }));
68
90
  return;
69
91
  }
70
- if (url === "/tasks" && method === "POST") {
92
+ if (url === "/register" && method === "POST") {
71
93
  try {
72
94
  const body = await readBody(req);
73
- const payload = JSON.parse(body);
74
- if (!payload.taskId || !payload.prompt) {
95
+ const { sessionId, callbackConfig } = JSON.parse(body);
96
+ if (!sessionId || !callbackConfig?.url) {
75
97
  res.writeHead(400);
76
- res.end(JSON.stringify({ error: "Missing required fields: taskId, prompt" }));
98
+ res.end(JSON.stringify({ error: "Missing required fields: sessionId, callbackConfig.url" }));
77
99
  return;
78
100
  }
79
- const task = {
80
- id: payload.taskId,
81
- prompt: payload.prompt,
82
- callbackUrl: payload.callbackUrl || config.openclawWebhookUrl,
83
- status: "pending",
84
- createdAt: new Date(),
85
- updatedAt: new Date()
86
- };
87
- tasks.set(task.id, task);
88
- console.log(`[openclaw] Task received: ${task.id}`);
89
- res.writeHead(202);
90
- res.end(JSON.stringify({ taskId: task.id, status: "accepted" }));
91
- const executeTask = async () => {
92
- if (runningTasks >= config.maxConcurrentTasks) {
93
- console.log(`[openclaw] Task ${task.id} queued (max concurrent reached)`);
94
- await waitForSlot();
95
- }
96
- runningTasks++;
97
- task.status = "running";
98
- task.updatedAt = new Date();
99
- try {
100
- console.log(`[openclaw] Executing task: ${task.id}`);
101
- const sessionResult = await client.session.create();
102
- const session = sessionResult.data || sessionResult;
103
- task.sessionId = session.id;
104
- const response = await client.session.prompt({ path: { id: session.id } }, { content: task.prompt });
105
- const message = response.data || response;
106
- task.status = "completed";
107
- task.result = message.info?.content || message.content || JSON.stringify(message);
108
- task.updatedAt = new Date();
109
- console.log(`[openclaw] Task completed: ${task.id}`);
110
- await notifyOpenclaw(task);
111
- }
112
- catch (err) {
113
- task.status = "failed";
114
- task.error = err instanceof Error ? err.message : String(err);
115
- task.updatedAt = new Date();
116
- console.error(`[openclaw] Task failed: ${task.id}`, err);
117
- await notifyOpenclaw(task);
118
- }
119
- finally {
120
- runningTasks--;
121
- events.emit("slot-freed");
122
- }
123
- };
124
- executeTask();
101
+ sessionRegistry.set(sessionId, {
102
+ config: {
103
+ url: callbackConfig.url,
104
+ apiKey: callbackConfig.apiKey || pluginConfig.openclawApiKey,
105
+ agentId: callbackConfig.agentId || "main",
106
+ channel: callbackConfig.channel || "last",
107
+ deliver: callbackConfig.deliver ?? true,
108
+ },
109
+ textParts: [],
110
+ toolOutputs: [],
111
+ hasError: false,
112
+ });
113
+ console.log(`[openclaw] Registered callback for session: ${sessionId} -> ${callbackConfig.url}`);
114
+ res.writeHead(200);
115
+ res.end(JSON.stringify({ ok: true, sessionId }));
125
116
  }
126
117
  catch (err) {
127
- console.error("[openclaw] Failed to handle task request:", err);
118
+ console.error("[openclaw] Failed to register callback:", err);
128
119
  res.writeHead(500);
129
120
  res.end(JSON.stringify({ error: "Internal server error" }));
130
121
  }
131
122
  return;
132
123
  }
133
- if (url.startsWith("/tasks/") && method === "GET") {
134
- const taskId = url.split("/")[2];
135
- const task = tasks.get(taskId);
136
- if (!task) {
137
- res.writeHead(404);
138
- res.end(JSON.stringify({ error: "Task not found" }));
139
- return;
140
- }
141
- res.writeHead(200);
142
- res.end(JSON.stringify({
143
- taskId: task.id,
144
- status: task.status,
145
- result: task.result,
146
- error: task.error,
147
- createdAt: task.createdAt,
148
- updatedAt: task.updatedAt
149
- }));
150
- return;
151
- }
152
124
  res.writeHead(404);
153
125
  res.end(JSON.stringify({ error: "Not found" }));
154
126
  });
155
127
  await new Promise((resolve, reject) => {
156
- server.listen(config.port, () => {
157
- console.log(`[openclaw] Webhook server listening on port ${config.port}`);
128
+ server.listen(pluginConfig.port, () => {
129
+ console.log(`[openclaw] Plugin HTTP server listening on port ${pluginConfig.port}`);
158
130
  resolve();
159
131
  });
160
132
  server.on("error", reject);
161
133
  });
162
134
  return {
163
135
  config: async (cfg) => {
164
- const openclawCfg = cfg.openclaw;
165
- if (openclawCfg) {
166
- Object.assign(config, openclawCfg);
136
+ if (cfg.openclaw) {
137
+ Object.assign(pluginConfig, cfg.openclaw);
138
+ console.log("[openclaw] Configuration updated");
139
+ }
140
+ },
141
+ "message.part.updated": async (event) => {
142
+ const part = event.part;
143
+ if (!part?.sessionID)
144
+ return;
145
+ const state = sessionRegistry.get(part.sessionID);
146
+ if (!state)
147
+ return;
148
+ switch (part.type) {
149
+ case "text": {
150
+ if (part.text) {
151
+ state.textParts.push(part.text);
152
+ }
153
+ break;
154
+ }
155
+ case "tool": {
156
+ if (part.state) {
157
+ switch (part.state.status) {
158
+ case "completed":
159
+ state.toolOutputs.push({
160
+ tool: part.tool,
161
+ output: part.state.output || "(no output)",
162
+ });
163
+ break;
164
+ case "error":
165
+ state.hasError = true;
166
+ state.toolOutputs.push({
167
+ tool: part.tool,
168
+ output: "",
169
+ error: part.state.error || "Unknown error",
170
+ });
171
+ break;
172
+ }
173
+ }
174
+ break;
175
+ }
176
+ case "reasoning": {
177
+ break;
178
+ }
179
+ }
180
+ },
181
+ "message.part.delta": async (event) => {
182
+ const { sessionID, field, delta } = event;
183
+ if (!sessionID || field !== "text" || !delta)
184
+ return;
185
+ const state = sessionRegistry.get(sessionID);
186
+ if (!state)
187
+ return;
188
+ if (state.textParts.length > 0) {
189
+ state.textParts[state.textParts.length - 1] += delta;
167
190
  }
168
- if (!config.openclawWebhookUrl) {
169
- console.log("[openclaw] No default callback URL configured");
191
+ else {
192
+ state.textParts.push(delta);
193
+ }
194
+ },
195
+ "session.updated": async (event) => {
196
+ const info = event.info;
197
+ if (!info?.id)
198
+ return;
199
+ const state = sessionRegistry.get(info.id);
200
+ if (!state)
201
+ return;
202
+ state.status = info.status;
203
+ if (info.status === "completed" || info.status === "failed") {
204
+ if (info.status === "failed") {
205
+ state.hasError = true;
206
+ }
207
+ await handleSessionComplete(info.id, state);
208
+ }
209
+ },
210
+ "session.error": async (event) => {
211
+ const { sessionID, error } = event;
212
+ if (!sessionID)
213
+ return;
214
+ const state = sessionRegistry.get(sessionID);
215
+ if (!state)
216
+ return;
217
+ state.hasError = true;
218
+ state.errorMessage = error?.message || String(error);
219
+ },
220
+ "session.deleted": async (event) => {
221
+ const sessionId = event.info?.id || event.sessionId;
222
+ if (sessionId && sessionRegistry.has(sessionId)) {
223
+ console.log(`[openclaw] Session ${sessionId} deleted, removing callback registration`);
224
+ sessionRegistry.delete(sessionId);
170
225
  }
171
226
  },
172
227
  dispose: async () => {
173
228
  server.close();
174
- events.removeAllListeners();
229
+ sessionRegistry.clear();
175
230
  console.log("[openclaw] Plugin disposed");
176
- }
231
+ },
177
232
  };
178
- };
179
- export default OpenclawPlugin;
233
+ }
180
234
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -3,7 +3,13 @@ export interface OpenclawConfig {
3
3
  port?: number;
4
4
  openclawWebhookUrl?: string;
5
5
  openclawApiKey?: string;
6
- maxConcurrentTasks?: number;
6
+ }
7
+ export interface CallbackConfig {
8
+ url: string;
9
+ apiKey?: string;
10
+ agentId?: string;
11
+ channel?: string;
12
+ deliver?: boolean;
7
13
  }
8
14
  declare module "@opencode-ai/plugin" {
9
15
  interface Config {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAE7D,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd,QAAQ,CAAC,EAAE,cAAc,CAAA;KAC1B;CACF;AAED,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAE7D,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd,QAAQ,CAAC,EAAE,cAAc,CAAA;KAC1B;CACF;AAED,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laceletho/plugin-openclaw",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "OpenCode plugin for async task execution with OpenClaw callback",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -19,6 +19,9 @@
19
19
  "openclaw",
20
20
  "webhook"
21
21
  ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
22
25
  "peerDependencies": {
23
26
  "@opencode-ai/plugin": ">=0.1.0"
24
27
  },