@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 +114 -189
- package/dist/index.d.ts +7 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +166 -112
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +7 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,41 +1,38 @@
|
|
|
1
1
|
# @laceletho/plugin-openclaw
|
|
2
2
|
|
|
3
|
-
OpenCode plugin for
|
|
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
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **Automatic Callback**:
|
|
10
|
-
- **Session
|
|
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
|
-
|
|
16
|
-
│
|
|
17
|
-
│ (External) │
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
"
|
|
59
|
-
"openclawApiKey": "your-openclaw-hooks-token",
|
|
60
|
-
"maxConcurrentTasks": 5
|
|
55
|
+
"openclawApiKey": "your-openclaw-hooks-token"
|
|
61
56
|
}
|
|
62
57
|
}
|
|
63
58
|
```
|
|
64
59
|
|
|
65
|
-
###
|
|
60
|
+
### Environment Variables
|
|
66
61
|
|
|
67
|
-
|
|
62
|
+
| Variable | Description | Default |
|
|
63
|
+
|----------|-------------|---------|
|
|
64
|
+
| `OPENCLAW_PORT` | Plugin HTTP server port | `9090` |
|
|
65
|
+
| `OPENCLAW_API_KEY` | Default OpenClaw hooks token | - |
|
|
68
66
|
|
|
69
|
-
|
|
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
|
-
**
|
|
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
|
-
|
|
71
|
+
2. **Event Subscription**: The plugin subscribes to OpenCode's `session.updated` and `session.deleted` events.
|
|
90
72
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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 /
|
|
79
|
+
### POST /register
|
|
101
80
|
|
|
102
|
-
|
|
81
|
+
Register a session for callback when it completes.
|
|
103
82
|
|
|
104
83
|
**Request:**
|
|
105
84
|
```json
|
|
106
85
|
{
|
|
107
|
-
"
|
|
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
|
-
"
|
|
88
|
+
"url": "http://localhost:18789/hooks/agent",
|
|
89
|
+
"apiKey": "your-openclaw-token",
|
|
112
90
|
"agentId": "main",
|
|
113
|
-
"
|
|
114
|
-
"
|
|
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
|
-
"
|
|
127
|
-
"
|
|
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
|
-
"
|
|
155
|
-
"running": 2
|
|
113
|
+
"registeredSessions": 5
|
|
156
114
|
}
|
|
157
115
|
```
|
|
158
116
|
|
|
159
|
-
##
|
|
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
|
-
|
|
137
|
+
### `session.deleted`
|
|
162
138
|
|
|
163
|
-
|
|
139
|
+
Triggered when a session is deleted. The plugin removes the session from the callback registry.
|
|
164
140
|
|
|
165
|
-
|
|
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:
|
|
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 <
|
|
169
|
+
Authorization: Bearer <apiKey>
|
|
183
170
|
Content-Type: application/json
|
|
184
171
|
```
|
|
185
172
|
|
|
186
|
-
|
|
173
|
+
## Usage with CLI
|
|
187
174
|
|
|
188
|
-
|
|
175
|
+
This plugin is designed to work with `openclaw-opencode-cli`:
|
|
189
176
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
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
|
-
|
|
186
|
+
openclaw-opencode task "Write a Python function"
|
|
207
187
|
|
|
208
|
-
|
|
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": "
|
|
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
|
-
|
|
206
|
+
## Testing
|
|
207
|
+
|
|
208
|
+
Test the plugin health:
|
|
228
209
|
|
|
229
210
|
```bash
|
|
230
|
-
|
|
231
|
-
export OPENCLAW_API_KEY="my-secure-webhook-token"
|
|
232
|
-
opencode serve
|
|
211
|
+
curl http://localhost:9090/health
|
|
233
212
|
```
|
|
234
213
|
|
|
235
|
-
|
|
214
|
+
Test callback registration:
|
|
236
215
|
|
|
237
216
|
```bash
|
|
238
|
-
curl -X POST http://localhost:9090/
|
|
217
|
+
curl -X POST http://localhost:9090/register \
|
|
239
218
|
-H "Content-Type: application/json" \
|
|
240
219
|
-d '{
|
|
241
|
-
"
|
|
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
|
-
"
|
|
246
|
-
"
|
|
247
|
-
"
|
|
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
|
-
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
3
|
-
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
30
|
-
if (!task.callbackUrl)
|
|
31
|
-
return;
|
|
45
|
+
const sendCallback = async (sessionId, state) => {
|
|
32
46
|
const payload = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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(
|
|
55
|
+
const res = await fetch(state.config.url, {
|
|
42
56
|
method: "POST",
|
|
43
57
|
headers: {
|
|
44
58
|
"Content-Type": "application/json",
|
|
45
|
-
...(config.
|
|
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
|
|
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
|
|
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
|
|
71
|
+
console.error(`[openclaw] Failed to send callback for session ${sessionId}:`, err);
|
|
58
72
|
}
|
|
59
73
|
};
|
|
60
|
-
const
|
|
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({
|
|
86
|
+
res.end(JSON.stringify({
|
|
87
|
+
status: "ok",
|
|
88
|
+
registeredSessions: sessionRegistry.size,
|
|
89
|
+
}));
|
|
68
90
|
return;
|
|
69
91
|
}
|
|
70
|
-
if (url === "/
|
|
92
|
+
if (url === "/register" && method === "POST") {
|
|
71
93
|
try {
|
|
72
94
|
const body = await readBody(req);
|
|
73
|
-
const
|
|
74
|
-
if (!
|
|
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:
|
|
98
|
+
res.end(JSON.stringify({ error: "Missing required fields: sessionId, callbackConfig.url" }));
|
|
77
99
|
return;
|
|
78
100
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
|
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(
|
|
157
|
-
console.log(`[openclaw]
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
169
|
-
|
|
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
|
-
|
|
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":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;
|
|
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
|
-
|
|
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 {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -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;
|
|
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.
|
|
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
|
},
|