@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 +81 -205
- 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,40 @@
|
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
###
|
|
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
|
-
###
|
|
58
|
+
### Environment Variables
|
|
66
59
|
|
|
67
|
-
|
|
60
|
+
| Variable | Description | Default |
|
|
61
|
+
|----------|-------------|---------|
|
|
62
|
+
| `OPENCLAW_PORT` | Plugin HTTP server port | `9090` |
|
|
63
|
+
| `OPENCLAW_API_KEY` | Default OpenClaw hooks token | - |
|
|
68
64
|
|
|
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
|
-
```
|
|
65
|
+
## How It Works
|
|
82
66
|
|
|
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
|
|
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
|
-
|
|
69
|
+
2. **Event Subscription**: The plugin subscribes to OpenCode's `session.updated`, `message.part.*`, and `session.deleted` events.
|
|
90
70
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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 /
|
|
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,73 @@ 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
|
|
160
118
|
|
|
161
|
-
|
|
119
|
+
The plugin subscribes to the following OpenCode events:
|
|
162
120
|
|
|
163
|
-
|
|
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
|
-
|
|
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:
|
|
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 <
|
|
147
|
+
Authorization: Bearer <apiKey>
|
|
183
148
|
Content-Type: application/json
|
|
184
149
|
```
|
|
185
150
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
OpenClaw's `/hooks/agent` endpoint accepts the following payload structure:
|
|
151
|
+
## Usage with CLI
|
|
189
152
|
|
|
190
|
-
|
|
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
|
-
|
|
155
|
+
**See the [CLI documentation](https://github.com/LaceLetho/openclaw-opencode-cli) for usage instructions.**
|
|
205
156
|
|
|
206
|
-
|
|
157
|
+
## Testing
|
|
207
158
|
|
|
208
|
-
|
|
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
|
-
|
|
231
|
-
export OPENCLAW_API_KEY="my-secure-webhook-token"
|
|
232
|
-
opencode serve
|
|
162
|
+
curl http://localhost:9090/health
|
|
233
163
|
```
|
|
234
164
|
|
|
235
|
-
|
|
165
|
+
Test callback registration:
|
|
236
166
|
|
|
237
167
|
```bash
|
|
238
|
-
curl -X POST http://localhost:9090/
|
|
168
|
+
curl -X POST http://localhost:9090/register \
|
|
239
169
|
-H "Content-Type: application/json" \
|
|
240
170
|
-d '{
|
|
241
|
-
"
|
|
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
|
-
"
|
|
246
|
-
"
|
|
247
|
-
"
|
|
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
|
-
|
|
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": "
|
|
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
|
},
|