@laceletho/plugin-openclaw 0.1.2 → 1.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 CHANGED
@@ -1,41 +1,40 @@
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
- ```
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
- └───────────────┘
14
+ This plugin runs inside **OpenCode** and provides an HTTP server for callback registration:
15
+
16
+ ```
17
+ ┌─────────────────┐ POST /register ┌─────────────────────┐
18
+ │ CLI/Tool │ ──────────────────────> │ OpenclawPlugin │
19
+ (External) │ {sessionId, callback} │ (HTTP Server 9090) │
20
+ └─────────────────┘ └──────────┬──────────┘
21
+
22
+ │ stores in
23
+ │ callbackRegistry
24
+
25
+
26
+ ┌─────────────────────┐
27
+ │ Subscribe to │
28
+ │ session.updated │
29
+ message.part.*
30
+ └──────────┬──────────┘
31
+
32
+ session completes
33
+
34
+ ┌─────────────────────┐
35
+ Send callback to
36
+ OpenClaw /hooks
37
+ └─────────────────────┘
39
38
  ```
40
39
 
41
40
  ## Installation
@@ -46,76 +45,51 @@ npm install @laceletho/plugin-openclaw
46
45
 
47
46
  ## Configuration
48
47
 
49
- ### OpenCode Plugin Configuration
48
+ ### Enable Plugin
50
49
 
51
50
  Add to your `opencode.json`:
52
51
 
53
52
  ```json
54
53
  {
55
54
  "plugins": ["@laceletho/plugin-openclaw"],
56
- "openclaw": {
57
- "port": 9090,
58
- "openclawWebhookUrl": "http://localhost:18789/hooks/agent",
59
- "openclawApiKey": "your-openclaw-hooks-token",
60
- "maxConcurrentTasks": 5
61
- }
62
55
  }
63
56
  ```
64
57
 
65
- ### OpenClaw Configuration (Required)
58
+ ### Environment Variables
66
59
 
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`):
60
+ | Variable | Description | Default |
61
+ |----------|-------------|---------|
62
+ | `OPENCLAW_PORT` | Plugin HTTP server port | `9090` |
63
+ | `OPENCLAW_API_KEY` | Default OpenClaw hooks token | - |
68
64
 
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
- ```
65
+ ## How It Works
82
66
 
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
67
+ 1. **Registration**: A CLI/tool creates an OpenCode session and sends a POST request to the plugin's `/register` endpoint with the session ID and callback configuration.
88
68
 
89
- ### Environment Variables
69
+ 2. **Event Subscription**: The plugin subscribes to OpenCode's `session.updated`, `message.part.*`, and `session.deleted` events.
90
70
 
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` |
71
+ 3. **Content Accumulation**: The plugin accumulates text content and tool outputs from `message.part.updated` and `message.part.delta` events.
72
+
73
+ 4. **Callback Trigger**: When a registered session's status changes to `completed` or `failed`, the plugin sends a webhook to the configured OpenClaw endpoint with the accumulated content.
74
+
75
+ 5. **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,73 @@ 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
160
118
 
161
- When a task completes, the plugin sends a POST request to OpenClaw's `/hooks/agent` endpoint:
119
+ The plugin subscribes to the following OpenCode events:
162
120
 
163
- ### OpenClaw /hooks/agent Payload Format
121
+ | Event | Purpose |
122
+ |-------|---------|
123
+ | `message.part.updated` | Accumulate text content and tool outputs |
124
+ | `message.part.delta` | Append streaming text deltas |
125
+ | `session.updated` | Monitor session status for completion |
126
+ | `session.error` | Track session errors |
127
+ | `session.deleted` | Clean up registry on session deletion |
164
128
 
165
- The plugin sends task results to OpenClaw using its native hooks format:
129
+ ## Callback to OpenClaw
130
+
131
+ When a registered session completes, the plugin sends a POST request to the configured URL:
166
132
 
133
+ **Payload:**
167
134
  ```json
168
135
  {
169
- "message": "Task completed: File processing finished\n\nResults:\nHere's the Python function...",
136
+ "message": "Task completed: sess_abc123\n\nResult:\nHere's the code...",
170
137
  "name": "OpenCode Task",
171
138
  "agentId": "main",
172
139
  "wakeMode": "now",
173
140
  "deliver": true,
174
- "channel": "last",
175
- "model": "anthropic/claude-sonnet-4-5",
176
- "timeoutSeconds": 300
141
+ "channel": "last"
177
142
  }
178
143
  ```
179
144
 
180
145
  **Authentication:**
181
146
  ```
182
- Authorization: Bearer <openclawApiKey>
147
+ Authorization: Bearer <apiKey>
183
148
  Content-Type: application/json
184
149
  ```
185
150
 
186
- ### OpenClaw /hooks/agent Endpoint Reference
187
-
188
- OpenClaw's `/hooks/agent` endpoint accepts the following payload structure:
151
+ ## Usage with CLI
189
152
 
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 |
153
+ This plugin is designed to work with `@laceletho/openclaw-opencode-cli`.
203
154
 
204
- ## Usage Example
155
+ **See the [CLI documentation](https://github.com/LaceLetho/openclaw-opencode-cli) for usage instructions.**
205
156
 
206
- ### 1. Configure OpenClaw
157
+ ## Testing
207
158
 
208
- Edit your `~/.openclaw/openclaw.json`:
209
-
210
- ```json
211
- {
212
- "hooks": {
213
- "enabled": true,
214
- "token": "my-secure-webhook-token",
215
- "path": "/hooks",
216
- "allowedAgentIds": ["main"]
217
- },
218
- "channels": {
219
- "telegram": {
220
- "botToken": "${TELEGRAM_BOT_TOKEN}",
221
- "allowFrom": ["*"]
222
- }
223
- }
224
- }
225
- ```
226
-
227
- ### 2. Start OpenCode with the plugin
159
+ Test the plugin health:
228
160
 
229
161
  ```bash
230
- export OPENCLAW_WEBHOOK_URL="http://localhost:18789/hooks/agent"
231
- export OPENCLAW_API_KEY="my-secure-webhook-token"
232
- opencode serve
162
+ curl http://localhost:9090/health
233
163
  ```
234
164
 
235
- ### 3. Send a task from OpenClaw
165
+ Test callback registration:
236
166
 
237
167
  ```bash
238
- curl -X POST http://localhost:9090/tasks \
168
+ curl -X POST http://localhost:9090/register \
239
169
  -H "Content-Type: application/json" \
240
170
  -d '{
241
- "taskId": "task-001",
242
- "prompt": "Create a React component for a todo list",
243
- "callbackUrl": "http://localhost:18789/hooks/agent",
171
+ "sessionId": "test-session-123",
244
172
  "callbackConfig": {
245
- "name": "OpenCode Task",
246
- "agentId": "main",
247
- "deliver": true,
248
- "channel": "telegram"
173
+ "url": "http://localhost:18789/hooks/agent",
174
+ "apiKey": "your-token",
175
+ "agentId": "main"
249
176
  }
250
177
  }'
251
178
  ```
252
179
 
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
180
  ## Development
305
181
 
306
182
  ```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": "1.1.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
  },