@ai-setting/roy-plugin-task-show 0.3.0 → 0.5.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 +310 -84
- package/dist/collector.d.ts +19 -3
- package/dist/collector.d.ts.map +1 -1
- package/dist/collector.js +42 -7
- package/dist/collector.js.map +1 -1
- package/dist/event-bus.d.ts +98 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +210 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +69 -28
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +238 -94
- package/dist/plugin.js.map +1 -1
- package/dist/server.d.ts +16 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +104 -53
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +79 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +15 -1
- package/dist/types.js.map +1 -1
- package/dist/url-injector.d.ts +15 -37
- package/dist/url-injector.d.ts.map +1 -1
- package/dist/url-injector.js +15 -47
- package/dist/url-injector.js.map +1 -1
- package/package.json +2 -1
- package/plugin.json +33 -11
- package/public/app.js +409 -57
- package/public/index.html +28 -10
- package/public/style.css +49 -1
package/README.md
CHANGED
|
@@ -1,22 +1,42 @@
|
|
|
1
1
|
# roy-plugin-task-show
|
|
2
2
|
|
|
3
3
|
> A [roy-agent](https://example/roy-agent) plugin that visualizes the tool-call
|
|
4
|
-
> chain of every task on a local web service
|
|
5
|
-
>
|
|
4
|
+
> chain of every task on a local web service with **real-time Server-Sent
|
|
5
|
+
> Events** for live page updates.
|
|
6
6
|
|
|
7
7
|
## What it does
|
|
8
8
|
|
|
9
9
|
When loaded into a `roy-agent` host, this plugin:
|
|
10
10
|
|
|
11
|
-
1. Listens to the `tool:
|
|
11
|
+
1. Listens to the `tool:before.execute`, `tool:after.execute`,
|
|
12
|
+
`task:before.create`, `task:after.create`, `task:after.complete`
|
|
13
|
+
(preferred) and `task:after.update` (legacy fallback) hook points.
|
|
12
14
|
2. Records every tool invocation (tool name, args, result preview, duration,
|
|
13
15
|
success flag, timestamp) into an in-memory collector keyed by task id.
|
|
14
|
-
3.
|
|
16
|
+
3. **Pushes every state change over a Server-Sent Events stream** served by
|
|
17
|
+
the plugin's local HTTP service. The frontend subscribes to
|
|
18
|
+
`GET /api/events` and re-renders the page within milliseconds of:
|
|
19
|
+
- a new task being created (`task.created`)
|
|
20
|
+
- a tool call being recorded (`tool.recorded`)
|
|
21
|
+
- a task status changing (`task.updated`)
|
|
22
|
+
- a task transitioning to a terminal status (`task.completed`)
|
|
15
23
|
4. Serves the visualization on a local HTTP server (default
|
|
16
|
-
`http://127.0.0.1:7788/`)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
`http://127.0.0.1:7788/`) — index page, per-task detail page, and the
|
|
25
|
+
`/api/events` SSE stream.
|
|
26
|
+
|
|
27
|
+
The result: every task gets a clickable link the user can open in a
|
|
28
|
+
browser. Once open, the page **stays in sync** with the running agent
|
|
29
|
+
loop — tool calls appear as they happen, status badges update in
|
|
30
|
+
real-time, and the progress bar grows with each call. No manual refresh
|
|
31
|
+
needed.
|
|
32
|
+
|
|
33
|
+
> **v0.5.0+** — the plugin no longer uses `env.notify`. The previous
|
|
34
|
+
> `env.notify({type:"visualization_ready"})` mechanism has been replaced
|
|
35
|
+
> with an in-process event bus + SSE stream. This makes the plugin work
|
|
36
|
+
> with **any** roy-agent host (no NotificationChannel required) and gives
|
|
37
|
+
> the frontend proper incremental updates instead of just a one-shot URL
|
|
38
|
+
> at the end. See [SSE Migration (v0.5.0+)](#sse-migration-v050) for the
|
|
39
|
+
> migration guide.
|
|
20
40
|
|
|
21
41
|
## Repository layout
|
|
22
42
|
|
|
@@ -32,17 +52,20 @@ roy-plugin-task-show/
|
|
|
32
52
|
│ └── app.js
|
|
33
53
|
├── src/
|
|
34
54
|
│ ├── index.ts ← public API (re-exports)
|
|
35
|
-
│ ├── types.ts ← shared types & default config
|
|
55
|
+
│ ├── types.ts ← shared types & default config + TaskEvent
|
|
36
56
|
│ ├── collector.ts ← in-memory tool-call collector
|
|
37
|
-
│ ├── server.ts ← tiny standalone Node http server
|
|
38
|
-
│ ├──
|
|
57
|
+
│ ├── server.ts ← tiny standalone Node http server + SSE endpoint
|
|
58
|
+
│ ├── event-bus.ts ← SSE event bus (broadcast / subscribe / keep-alive)
|
|
59
|
+
│ ├── url-injector.ts ← URL builders (no more mutation helpers)
|
|
39
60
|
│ ├── plugin.ts ← the TaskShowPlugin class (BasePlugin-compatible)
|
|
40
61
|
│ └── core-stub.d.ts ← type stub for the optional core peer dep
|
|
41
62
|
├── test/
|
|
42
63
|
│ ├── collector.test.ts
|
|
43
64
|
│ ├── url-injector.test.ts
|
|
44
|
-
│ ├── server.test.ts
|
|
45
|
-
│
|
|
65
|
+
│ ├── server.test.ts ← includes SSE endpoint test
|
|
66
|
+
│ ├── plugin.test.ts ← covers all six hooks + broadcast assertions
|
|
67
|
+
│ ├── plugin-sse.test.ts ← dedicated SSE event-bus consumer tests
|
|
68
|
+
│ └── integration.test.ts ← full lifecycle through HTTP + SSE
|
|
46
69
|
└── scripts/
|
|
47
70
|
├── verify-service.ts ← end-to-end check (port 7788 + curl pages)
|
|
48
71
|
└── run-demo.ts ← demo that simulates a real task lifecycle
|
|
@@ -120,77 +143,266 @@ await taskShow.dispose();
|
|
|
120
143
|
|
|
121
144
|
The plugin registers hooks for:
|
|
122
145
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
146
|
+
| Hook point | Priority | Purpose |
|
|
147
|
+
| ---------------------- | -------- | ------------------------------------------------------------------------ |
|
|
148
|
+
| `tool:before.execute` | 40 | Records per-call start timestamp for accurate `durationMs` |
|
|
149
|
+
| `tool:after.execute` | 50 | Records the call into the collector and broadcasts `tool.recorded` |
|
|
150
|
+
| `task:before.create` | 55 | Mints a fresh `TaskSession` and broadcasts `task.created` |
|
|
151
|
+
| `task:after.create` | 55 | Same as above (fallback for hosts that only emit `task:after.create`) |
|
|
152
|
+
| `task:after.complete` | 60 | **PREFERRED** — broadcasts `task.completed` on terminal transition |
|
|
153
|
+
| `task:after.update` | 60 | Legacy fallback; broadcasts `task.updated` or `task.completed` |
|
|
154
|
+
|
|
155
|
+
When both `task:after.complete` AND `task:after.update` fire (newer
|
|
156
|
+
hosts do this on completion), the handler dedupes — at most one
|
|
157
|
+
`task.completed` event per task.
|
|
131
158
|
|
|
132
159
|
## Configuration
|
|
133
160
|
|
|
134
161
|
All config lives in `plugin.json` (and is overridable at construction time):
|
|
135
162
|
|
|
136
|
-
| key
|
|
137
|
-
|
|
|
138
|
-
| `port`
|
|
139
|
-
| `host`
|
|
140
|
-
| `autoStart`
|
|
141
|
-
| `maxStoredTasks`
|
|
142
|
-
| `
|
|
143
|
-
|
|
163
|
+
| key | type | default | description |
|
|
164
|
+
| ---------------- | -------- | ----------- | -------------------------------------------------------- |
|
|
165
|
+
| `port` | number | `7788` | HTTP port for the visualization service. |
|
|
166
|
+
| `host` | string | `127.0.0.1` | HTTP host. Use `0.0.0.0` to allow LAN access. |
|
|
167
|
+
| `autoStart` | boolean | `true` | Start the HTTP server when `init()` is called. |
|
|
168
|
+
| `maxStoredTasks` | number | `50` | Max sessions kept in memory. Older ones are evicted. |
|
|
169
|
+
| `publicDir` | string | `public` | Directory holding the static frontend. |
|
|
170
|
+
|
|
171
|
+
> **v0.5.0**: the previous `urlInjectEnabled` config was removed. The
|
|
172
|
+
> plugin no longer mutates tool result output.
|
|
144
173
|
|
|
145
174
|
Override at construction time:
|
|
146
175
|
|
|
147
176
|
```ts
|
|
148
177
|
createTaskShowPlugin({
|
|
149
178
|
port: 9000,
|
|
150
|
-
|
|
179
|
+
maxStoredTasks: 100,
|
|
151
180
|
});
|
|
152
181
|
```
|
|
153
182
|
|
|
154
183
|
## HTTP API
|
|
155
184
|
|
|
156
|
-
| route | description
|
|
157
|
-
| --------------------------- |
|
|
158
|
-
| `GET /` | Index of recent task sessions.
|
|
159
|
-
| `GET /task/:taskId` | Per-task page with mermaid flow + tool-call table.
|
|
160
|
-
| `GET /api/sessions` | JSON list of all sessions (newest first).
|
|
161
|
-
| `GET /api/sessions/:taskId` | JSON detail of one session (full payload).
|
|
162
|
-
|
|
|
185
|
+
| route | description |
|
|
186
|
+
| --------------------------- | ------------------------------------------------------------ |
|
|
187
|
+
| `GET /` | Index of recent task sessions. |
|
|
188
|
+
| `GET /task/:taskId` | Per-task page with mermaid flow + tool-call table. |
|
|
189
|
+
| `GET /api/sessions` | JSON list of all sessions (newest first). |
|
|
190
|
+
| `GET /api/sessions/:taskId` | JSON detail of one session (full payload). |
|
|
191
|
+
| **`GET /api/events`** | **SSE stream** — see [Server-Sent Events](#server-sent-events). |
|
|
192
|
+
| `GET /static/*` | Static frontend assets (`style.css`, `app.js`). |
|
|
163
193
|
|
|
164
194
|
If the configured `port` is already in use, the service falls back to an OS
|
|
165
195
|
assigned port and logs the actual URL to stderr.
|
|
166
196
|
|
|
167
|
-
##
|
|
197
|
+
## Server-Sent Events
|
|
198
|
+
|
|
199
|
+
The local HTTP service exposes `GET /api/events` as a standard Server-Sent
|
|
200
|
+
Events stream. Every connected client receives:
|
|
201
|
+
|
|
202
|
+
1. An initial `snapshot` frame carrying the full list of currently-known
|
|
203
|
+
sessions — useful for instant render on connect / reconnect.
|
|
204
|
+
2. A `task.created` frame whenever a new task is opened
|
|
205
|
+
(`task:before.create` or `task:after.create`).
|
|
206
|
+
3. A `tool.recorded` frame after each tool call
|
|
207
|
+
(`tool:after.execute`).
|
|
208
|
+
4. A `task.updated` frame on any non-terminal status transition
|
|
209
|
+
(`task:after.update` with `running` / `paused` / etc.).
|
|
210
|
+
5. A `task.completed` frame on terminal transition
|
|
211
|
+
(`task:after.complete` or `task:after.update` with terminal status).
|
|
168
212
|
|
|
169
|
-
|
|
170
|
-
|
|
213
|
+
A 15-second keep-alive comment (`:keep-alive`) prevents reverse proxies /
|
|
214
|
+
load balancers from dropping the connection.
|
|
171
215
|
|
|
172
|
-
|
|
173
|
-
…original tool output…
|
|
216
|
+
### Event shape
|
|
174
217
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
218
|
+
Every event has the same envelope:
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
interface TaskEvent<T> {
|
|
222
|
+
type: "task.created" | "task.updated" | "task.completed" | "tool.recorded";
|
|
223
|
+
taskId: number;
|
|
224
|
+
timestamp: number; // Unix ms
|
|
225
|
+
pluginVersion: string; // "0.5.0"
|
|
226
|
+
data: T;
|
|
227
|
+
}
|
|
178
228
|
```
|
|
179
229
|
|
|
180
|
-
|
|
181
|
-
|
|
230
|
+
The `data` payload differs per `type`:
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
// task.created
|
|
234
|
+
data: { session: TaskSession }
|
|
235
|
+
|
|
236
|
+
// task.updated
|
|
237
|
+
data: { session: TaskSession, newStatus: TaskStatus, previousStatus?: TaskStatus }
|
|
238
|
+
|
|
239
|
+
// task.completed
|
|
240
|
+
data: { session: TaskSession, terminalStatus: TaskStatus }
|
|
241
|
+
|
|
242
|
+
// tool.recorded
|
|
243
|
+
data: { session: TaskSession, toolCall: ToolCallRecord }
|
|
244
|
+
```
|
|
182
245
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
246
|
+
### Subscribing from the browser
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
const source = new EventSource("/api/events");
|
|
250
|
+
source.addEventListener("snapshot", (ev) => {
|
|
251
|
+
const data = JSON.parse(ev.data);
|
|
252
|
+
console.log("initial sessions:", data.data.sessions);
|
|
253
|
+
});
|
|
254
|
+
source.addEventListener("task.created", (ev) => {
|
|
255
|
+
const data = JSON.parse(ev.data);
|
|
256
|
+
console.log("new task:", data.data.session.taskId);
|
|
257
|
+
});
|
|
258
|
+
source.addEventListener("tool.recorded", (ev) => {
|
|
259
|
+
const data = JSON.parse(ev.data);
|
|
260
|
+
console.log("tool call:", data.data.toolCall.toolName);
|
|
261
|
+
});
|
|
262
|
+
source.addEventListener("task.completed", (ev) => {
|
|
263
|
+
const data = JSON.parse(ev.data);
|
|
264
|
+
console.log("task done:", data.data.terminalStatus);
|
|
265
|
+
});
|
|
266
|
+
// EventSource auto-reconnects on connection drop. If SSE is unavailable
|
|
267
|
+
// (e.g. ancient browser), the bundled frontend falls back to a 3-second
|
|
268
|
+
// poll of /api/sessions.
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Subscribing from Node / custom adapter
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
import http from "node:http";
|
|
275
|
+
|
|
276
|
+
http.get("http://127.0.0.1:7788/api/events", (res) => {
|
|
277
|
+
let buf = "";
|
|
278
|
+
res.on("data", (chunk) => {
|
|
279
|
+
buf += chunk.toString("utf-8");
|
|
280
|
+
let idx;
|
|
281
|
+
while ((idx = buf.indexOf("\n\n")) !== -1) {
|
|
282
|
+
const frame = buf.slice(0, idx);
|
|
283
|
+
buf = buf.slice(idx + 2);
|
|
284
|
+
// frame is `event: <type>\ndata: <json>`
|
|
285
|
+
// ...
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Architecture
|
|
292
|
+
|
|
293
|
+
The plugin runs entirely inside its local HTTP server. The hook handlers
|
|
294
|
+
emit events into an in-process `EventBus` (`src/event-bus.ts`), and every
|
|
295
|
+
connected SSE client receives a frame. No host-side NotificationChannel
|
|
296
|
+
plumbing is required.
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
TaskShowPlugin (tool/task hooks)
|
|
300
|
+
│
|
|
301
|
+
│ eventBus.broadcast({type, taskId, timestamp, data})
|
|
302
|
+
▼
|
|
303
|
+
EventBus (in-process subscriber Set + keep-alive loop)
|
|
304
|
+
│
|
|
305
|
+
│ write frame to every connected http.ServerResponse
|
|
306
|
+
▼
|
|
307
|
+
TaskShowServer.handleSSE
|
|
308
|
+
│
|
|
309
|
+
│ Content-Type: text/event-stream
|
|
310
|
+
▼
|
|
311
|
+
Browser EventSource ◄──── 3-second polling fallback if SSE unavailable
|
|
312
|
+
│
|
|
313
|
+
▼
|
|
314
|
+
DOM updates (badge / progress / timeline / mermaid re-render)
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The in-process bus also exposes `addListener(fn)` so custom callers
|
|
318
|
+
(CLI tools, IM adapters, log shippers) can subscribe to the same event
|
|
319
|
+
stream without going through HTTP:
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
const plugin = createTaskShowPlugin();
|
|
323
|
+
plugin.getEventBus().addListener((event) => {
|
|
324
|
+
console.log("event:", event.type, event.taskId);
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Plugin ↔ host version correspondence
|
|
329
|
+
|
|
330
|
+
| Plugin version | Compatible host (`roy-agent`) | Notes |
|
|
331
|
+
| -------------- | ------------------------------------ | ------------------------------------------------------------------ |
|
|
332
|
+
| `0.1.0` | pre-2026-07-10 (`task:after.update`) | Mutates tool result. **Removed** in v0.4.0 plugin. |
|
|
333
|
+
| `0.2.0` | pre-2026-07-10 (`task:after.update`) | Same as 0.1.0; tiny refactors. |
|
|
334
|
+
| `0.3.0` | `>= 2026-07-10` | Adds `tool:before.execute` for self-managed timing. |
|
|
335
|
+
| `0.4.0` | `>= 2026-07-10` (NotificationChannel) | Switches to `env.notify` consumer; no longer mutates output. |
|
|
336
|
+
| **`0.5.0` (this)** | **`>= 2026-07-10`** | **Adds `task:before.create` / `task:after.create`; switches from `env.notify` to in-process EventBus + SSE.** |
|
|
337
|
+
|
|
338
|
+
### Host design reference
|
|
339
|
+
|
|
340
|
+
The full host-side design — including the `NotificationChannel`
|
|
341
|
+
interface and `EventBusNotificationChannel` (default) — is documented
|
|
342
|
+
in the host repository:
|
|
343
|
+
|
|
344
|
+
>
|
|
345
|
+
|
|
346
|
+
## SSE Migration (v0.5.0+)
|
|
347
|
+
|
|
348
|
+
> **TL;DR**: stop depending on `env.notify`. The plugin now pushes events
|
|
349
|
+
> over SSE. Connect with `new EventSource('/api/events')` (browser) or
|
|
350
|
+
> `http.get(...)` (Node).
|
|
351
|
+
|
|
352
|
+
### Before (v0.4.0)
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
// Plugin called env.notify({type:"visualization_ready", ...}).
|
|
356
|
+
// Host's EventBusNotificationChannel re-emitted on env event bus:
|
|
357
|
+
// env.pushEnvEvent({type:"plugin.notification.visualization_ready", ...})
|
|
358
|
+
// Subscribers (CLI / IM) listened on the env event bus.
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### After (v0.5.0+)
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
// Plugin emits via in-process EventBus; HTTP server streams frames
|
|
365
|
+
// over /api/events. Frontend connects with EventSource — no host
|
|
366
|
+
// NotificationChannel required.
|
|
367
|
+
const source = new EventSource("/api/events");
|
|
368
|
+
source.addEventListener("task.completed", (ev) => {
|
|
369
|
+
const { taskId, data } = JSON.parse(ev.data);
|
|
370
|
+
console.log(`Task ${taskId} → ${data.terminalStatus}`);
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Why we changed
|
|
375
|
+
|
|
376
|
+
1. **No host dependency**: the SSE stream is served by the plugin's own
|
|
377
|
+
HTTP server. Works with any roy-agent host — no NotificationChannel
|
|
378
|
+
required.
|
|
379
|
+
2. **Incremental updates**: instead of one-shot "URL injection" on
|
|
380
|
+
terminal status, the frontend receives a frame for *every*
|
|
381
|
+
meaningful change (created / recorded / updated / completed). The
|
|
382
|
+
page updates as the agent works, not after.
|
|
383
|
+
3. **Progress bar + timeline**: with continuous updates, the frontend
|
|
384
|
+
can show a live progress bar (tool call count) and a real-time
|
|
385
|
+
timeline without manual refresh.
|
|
386
|
+
4. **Simpler host contract**: removed `env.notify` plumbing from the
|
|
387
|
+
plugin surface. The plugin's `PluginEnvLike` type no longer mentions
|
|
388
|
+
`notify`.
|
|
389
|
+
|
|
390
|
+
### Backward compatibility
|
|
391
|
+
|
|
392
|
+
The plugin no longer mutates tool result output (that mechanism was
|
|
393
|
+
removed in v0.4.0). Pin to `roy-plugin-task-show@0.4.x` if you depend
|
|
394
|
+
on the legacy `env.notify` consumer path.
|
|
186
395
|
|
|
187
396
|
## Development
|
|
188
397
|
|
|
189
398
|
```bash
|
|
190
|
-
# Type-check
|
|
399
|
+
# Type-check (no emit)
|
|
400
|
+
bun run typecheck
|
|
401
|
+
|
|
402
|
+
# Build (emit dist/)
|
|
191
403
|
bun run build
|
|
192
404
|
|
|
193
|
-
# Run unit tests (
|
|
405
|
+
# Run unit tests (52 tests across 6 files)
|
|
194
406
|
bun test
|
|
195
407
|
|
|
196
408
|
# End-to-end check (boots the service, hits it, asserts response)
|
|
@@ -232,54 +444,68 @@ It also recognizes (in priority order):
|
|
|
232
444
|
If no task id can be recovered, the call lands in a synthetic session so
|
|
233
445
|
the visualization still works.
|
|
234
446
|
|
|
235
|
-
### `task:
|
|
236
|
-
|
|
237
|
-
The plugin accepts the standard `TaskCompleteResultContext`:
|
|
447
|
+
### `task:before.create` (v0.5.0+)
|
|
238
448
|
|
|
239
449
|
```ts
|
|
240
450
|
{
|
|
241
|
-
task: { id: number,
|
|
242
|
-
|
|
243
|
-
changes: Partial<UpdateTaskOptions>,
|
|
244
|
-
sessionId: string,
|
|
245
|
-
tagService: TagService,
|
|
451
|
+
data: { task: { id: number, title?: string } }
|
|
452
|
+
// OR flat: { taskId: number, title?: string }
|
|
246
453
|
}
|
|
247
454
|
```
|
|
248
455
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
below.
|
|
456
|
+
If a session already exists for the task id (re-create / retry), its
|
|
457
|
+
`toolCalls` are preserved.
|
|
252
458
|
|
|
253
|
-
### `task:after.
|
|
459
|
+
### `task:after.create` (v0.5.0+)
|
|
460
|
+
|
|
461
|
+
Same payload as `task:before.create`. Useful for hosts that don't emit
|
|
462
|
+
`task:before.create`; the plugin opens the session here and broadcasts
|
|
463
|
+
`task.created`.
|
|
254
464
|
|
|
255
|
-
|
|
256
|
-
|
|
465
|
+
### `task:after.complete` (preferred, consumed)
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
{
|
|
469
|
+
data: {
|
|
470
|
+
task: { id: number, status: 'completed' | 'failed' | 'cancelled', title?: string },
|
|
471
|
+
terminalStatus: 'completed' | 'failed' | 'cancelled',
|
|
472
|
+
changes: Partial<UpdateTaskOptions>,
|
|
473
|
+
sessionId: string,
|
|
474
|
+
tagService: TagService,
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### `task:after.update` (legacy fallback, consumed)
|
|
257
480
|
|
|
258
481
|
```ts
|
|
259
482
|
{ data: { task: { id: number, status: string, title?: string }, changes, tagService } }
|
|
260
483
|
```
|
|
261
484
|
|
|
262
|
-
The handler filters for terminal status (`completed` / `failed` /
|
|
263
|
-
`
|
|
264
|
-
that supports both hooks),
|
|
485
|
+
The handler filters for terminal status (`completed` / `failed` /
|
|
486
|
+
`cancelled`) and dedupes — if `AFTER_COMPLETE` also fires (it can, on a
|
|
487
|
+
host that supports both hooks), only one `task.completed` event is
|
|
488
|
+
broadcast.
|
|
265
489
|
|
|
266
490
|
## Limitations & follow-ups
|
|
267
491
|
|
|
268
|
-
- **Memory-only**: the collector keeps data in memory only. Restarting
|
|
269
|
-
host process drops everything. Persisting to a file would be a
|
|
270
|
-
follow-up.
|
|
271
|
-
- **Single host**: if you launch multiple `roy-agent` instances on the
|
|
272
|
-
machine, change the `port` to avoid clashes (the service falls
|
|
273
|
-
random port automatically, but the URL won't be
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
- **
|
|
281
|
-
|
|
492
|
+
- **Memory-only**: the collector keeps data in memory only. Restarting
|
|
493
|
+
the host process drops everything. Persisting to a file would be a
|
|
494
|
+
small follow-up.
|
|
495
|
+
- **Single host**: if you launch multiple `roy-agent` instances on the
|
|
496
|
+
same machine, change the `port` to avoid clashes (the service falls
|
|
497
|
+
back to a random port automatically, but the URL won't be
|
|
498
|
+
predictable).
|
|
499
|
+
- **Mermaid CDN**: the frontend loads `mermaid@10` from jsDelivr.
|
|
500
|
+
Air-gapped deployments should vendor a copy locally.
|
|
501
|
+
- **No file persistence**: data lives only in memory. A future
|
|
502
|
+
improvement would be a tiny SQLite sink so a restart still shows
|
|
503
|
+
recent tasks.
|
|
504
|
+
- **SSE-only push**: the bundled frontend uses EventSource as the
|
|
505
|
+
primary update channel. A 3-second polling fallback covers older
|
|
506
|
+
browsers and proxies that strip SSE, but it's a degraded experience.
|
|
507
|
+
WebSocket support is a possible future addition.
|
|
282
508
|
|
|
283
509
|
## License
|
|
284
510
|
|
|
285
|
-
MIT
|
|
511
|
+
MIT
|
package/dist/collector.d.ts
CHANGED
|
@@ -66,9 +66,14 @@ export declare class ToolCallCollector {
|
|
|
66
66
|
* Mark a task as completed/failed and freeze its `endedAt`. Used by the
|
|
67
67
|
* `task:after.update` hook.
|
|
68
68
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
69
|
+
* If no session exists for the task yet (e.g. the task completed without
|
|
70
|
+
* any recorded tool calls — pure response tasks), we create a synthetic
|
|
71
|
+
* session on the fly so the visualization page can still render a
|
|
72
|
+
* meaningful "task finished" card. `startedAt` is set to one second
|
|
73
|
+
* before `endedAt` so the duration widget renders as ~1s rather than 0s.
|
|
74
|
+
*
|
|
75
|
+
* Returns the (possibly newly-created) session, or undefined only if
|
|
76
|
+
* taskId is invalid.
|
|
72
77
|
*/
|
|
73
78
|
finalizeOnTaskUpdate(opts: {
|
|
74
79
|
taskId: number;
|
|
@@ -81,6 +86,17 @@ export declare class ToolCallCollector {
|
|
|
81
86
|
* context that happens to know the title, e.g. task:before.create).
|
|
82
87
|
*/
|
|
83
88
|
setTaskTitle(taskId: number, title: string): void;
|
|
89
|
+
/**
|
|
90
|
+
* Insert or replace a session. Used by `task:before.create` /
|
|
91
|
+
* `task:after.create` to mint a fresh TaskSession before any tool call
|
|
92
|
+
* is recorded — gives the frontend a stable taskId/title even for tasks
|
|
93
|
+
* that complete without firing any tool.
|
|
94
|
+
*
|
|
95
|
+
* If a session already exists for the taskId, it is overwritten with the
|
|
96
|
+
* new value (callers should pass a snapshot built from the existing
|
|
97
|
+
* session if they want to preserve toolCalls).
|
|
98
|
+
*/
|
|
99
|
+
upsertSession(session: TaskSession): void;
|
|
84
100
|
/**
|
|
85
101
|
* Clear all data. Useful in tests and when the plugin is disposed.
|
|
86
102
|
*/
|
package/dist/collector.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EAEX,cAAc,EACf,MAAM,YAAY,CAAC;AA6DpB;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAa;gBAGrC,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAOzD;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAMnD;;OAEG;IACH,YAAY,IAAI,WAAW,EAAE;IAM7B;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;;;;;;OAOG;IACH,cAAc,CAAC,IAAI,EAAE;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,OAAO,EAAE,OAAO,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,GAAG,CAAC,EAAE,GAAG,CAAC;QACV,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,MAAM;IA6CV
|
|
1
|
+
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EAEX,cAAc,EACf,MAAM,YAAY,CAAC;AA6DpB;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAa;gBAGrC,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAOzD;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAMnD;;OAEG;IACH,YAAY,IAAI,WAAW,EAAE;IAM7B;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;;;;;;OAOG;IACH,cAAc,CAAC,IAAI,EAAE;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,OAAO,EAAE,OAAO,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,GAAG,CAAC,EAAE,GAAG,CAAC;QACV,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,MAAM;IA6CV;;;;;;;;;;;;OAYG;IACH,oBAAoB,CAAC,IAAI,EAAE;QACzB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,WAAW,GAAG,SAAS;IAiC3B;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAOjD;;;;;;;;;OASG;IACH,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMzC;;OAEG;IACH,KAAK,IAAI,IAAI;IASb;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAoBrB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;CAGrB"}
|
package/dist/collector.js
CHANGED
|
@@ -153,16 +153,36 @@ export class ToolCallCollector {
|
|
|
153
153
|
* Mark a task as completed/failed and freeze its `endedAt`. Used by the
|
|
154
154
|
* `task:after.update` hook.
|
|
155
155
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
156
|
+
* If no session exists for the task yet (e.g. the task completed without
|
|
157
|
+
* any recorded tool calls — pure response tasks), we create a synthetic
|
|
158
|
+
* session on the fly so the visualization page can still render a
|
|
159
|
+
* meaningful "task finished" card. `startedAt` is set to one second
|
|
160
|
+
* before `endedAt` so the duration widget renders as ~1s rather than 0s.
|
|
161
|
+
*
|
|
162
|
+
* Returns the (possibly newly-created) session, or undefined only if
|
|
163
|
+
* taskId is invalid.
|
|
159
164
|
*/
|
|
160
165
|
finalizeOnTaskUpdate(opts) {
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
const now = opts.timestamp ?? Date.now();
|
|
167
|
+
let session = this.sessions.get(opts.taskId);
|
|
168
|
+
if (!session) {
|
|
169
|
+
// Synthetic session — task completed without any recorded tool call.
|
|
170
|
+
session = {
|
|
171
|
+
taskId: opts.taskId,
|
|
172
|
+
title: opts.title ?? "",
|
|
173
|
+
startedAt: now - 1000,
|
|
174
|
+
endedAt: now,
|
|
175
|
+
status: opts.newStatus,
|
|
176
|
+
toolCalls: [],
|
|
177
|
+
};
|
|
178
|
+
this.sessions.set(opts.taskId, session);
|
|
179
|
+
this.evictIfNeeded();
|
|
180
|
+
this.onChange?.();
|
|
181
|
+
this.logger.info(`Task ${opts.taskId} → ${opts.newStatus} (synthetic, no tool calls recorded)`);
|
|
182
|
+
return this.cloneSession(session);
|
|
183
|
+
}
|
|
164
184
|
session.status = opts.newStatus;
|
|
165
|
-
session.endedAt =
|
|
185
|
+
session.endedAt = now;
|
|
166
186
|
if (opts.title)
|
|
167
187
|
session.title = opts.title;
|
|
168
188
|
this.logger.info(`Task ${opts.taskId} → ${opts.newStatus} (${session.toolCalls.length} tool calls)`);
|
|
@@ -180,6 +200,21 @@ export class ToolCallCollector {
|
|
|
180
200
|
session.title = title;
|
|
181
201
|
this.onChange?.();
|
|
182
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Insert or replace a session. Used by `task:before.create` /
|
|
205
|
+
* `task:after.create` to mint a fresh TaskSession before any tool call
|
|
206
|
+
* is recorded — gives the frontend a stable taskId/title even for tasks
|
|
207
|
+
* that complete without firing any tool.
|
|
208
|
+
*
|
|
209
|
+
* If a session already exists for the taskId, it is overwritten with the
|
|
210
|
+
* new value (callers should pass a snapshot built from the existing
|
|
211
|
+
* session if they want to preserve toolCalls).
|
|
212
|
+
*/
|
|
213
|
+
upsertSession(session) {
|
|
214
|
+
this.sessions.set(session.taskId, session);
|
|
215
|
+
this.evictIfNeeded();
|
|
216
|
+
this.onChange?.();
|
|
217
|
+
}
|
|
183
218
|
/**
|
|
184
219
|
* Clear all data. Useful in tests and when the plugin is disposed.
|
|
185
220
|
*/
|
package/dist/collector.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"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"}
|