agent-tasks 1.9.21 → 1.9.22
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/agent-desk-plugin.json +1 -1
- package/dist/transport/ws.d.ts +2 -6
- package/dist/transport/ws.d.ts.map +1 -1
- package/dist/transport/ws.js +46 -149
- package/dist/transport/ws.js.map +1 -1
- package/package.json +2 -2
package/agent-desk-plugin.json
CHANGED
package/dist/transport/ws.d.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type WsHandle } from 'agent-common';
|
|
2
2
|
import type { Server } from 'http';
|
|
3
3
|
import type { AppContext } from '../context.js';
|
|
4
|
-
export
|
|
5
|
-
wss: WebSocketServer;
|
|
6
|
-
broadcast(message: string): void;
|
|
7
|
-
close(): void;
|
|
8
|
-
}
|
|
4
|
+
export type WebSocketHandle = WsHandle;
|
|
9
5
|
export declare function setupWebSocket(httpServer: Server, ctx: AppContext): WebSocketHandle;
|
|
10
6
|
//# sourceMappingURL=ws.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/transport/ws.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/transport/ws.ts"],"names":[],"mappings":"AAWA,OAAO,EAAuC,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAMhD,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;AAyBvC,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,eAAe,CA8CnF"}
|
package/dist/transport/ws.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
// =============================================================================
|
|
2
2
|
// agent-tasks — WebSocket transport
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Thin wrapper around agent-common's setupWebSocket. Streams full state on
|
|
5
|
+
// any DB change (single scalar fingerprint over tasks + comments + artifacts).
|
|
6
|
+
// Custom `subscribe` message type is handled via the onMessage callback;
|
|
7
|
+
// per-client subscribed-event filters are stored in a side Map keyed by
|
|
8
|
+
// WebSocket. The underlying broadcast() method is re-exposed for the UI
|
|
9
|
+
// file watcher (hot reload).
|
|
7
10
|
// =============================================================================
|
|
8
|
-
import {
|
|
11
|
+
import { setupWebSocket as setupKitWebSocket } from 'agent-common';
|
|
9
12
|
import { readPackageMeta } from '../package-meta.js';
|
|
10
13
|
const packageMeta = readPackageMeta();
|
|
11
|
-
const MAX_WS_MESSAGE_SIZE = 4096;
|
|
12
|
-
const MAX_WS_CONNECTIONS = 50;
|
|
13
|
-
const PING_INTERVAL_MS = 30_000;
|
|
14
|
-
const DB_POLL_INTERVAL_MS = 2_000;
|
|
15
14
|
const VALID_EVENT_TYPES = new Set([
|
|
16
15
|
'*',
|
|
17
16
|
'task:created',
|
|
@@ -35,157 +34,55 @@ const VALID_EVENT_TYPES = new Set([
|
|
|
35
34
|
'approval:rejected',
|
|
36
35
|
]);
|
|
37
36
|
export function setupWebSocket(httpServer, ctx) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
ws.close(1013, 'Too many connections');
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const state = {
|
|
46
|
-
alive: true,
|
|
47
|
-
subscribedEvents: new Set(),
|
|
48
|
-
};
|
|
49
|
-
clients.set(ws, state);
|
|
50
|
-
sendFullState(ws, ctx);
|
|
51
|
-
ws.on('pong', () => {
|
|
52
|
-
state.alive = true;
|
|
53
|
-
});
|
|
54
|
-
ws.on('message', (raw) => {
|
|
55
|
-
let parsed;
|
|
56
|
-
try {
|
|
57
|
-
parsed = JSON.parse(raw.toString());
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
ws.send(JSON.stringify({ type: 'error', message: 'Invalid JSON' }));
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
64
|
-
ws.send(JSON.stringify({ type: 'error', message: 'Message must be a JSON object' }));
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const msg = parsed;
|
|
68
|
-
if (typeof msg.type !== 'string') {
|
|
69
|
-
ws.send(JSON.stringify({ type: 'error', message: 'Missing type field' }));
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
switch (msg.type) {
|
|
73
|
-
case 'refresh':
|
|
74
|
-
sendFullState(ws, ctx);
|
|
75
|
-
break;
|
|
76
|
-
case 'subscribe': {
|
|
77
|
-
const events = msg.events;
|
|
78
|
-
if (!Array.isArray(events)) {
|
|
79
|
-
ws.send(JSON.stringify({
|
|
80
|
-
type: 'error',
|
|
81
|
-
message: '"events" must be an array of event type strings',
|
|
82
|
-
}));
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
state.subscribedEvents.clear();
|
|
86
|
-
for (const e of events) {
|
|
87
|
-
if (typeof e === 'string' && VALID_EVENT_TYPES.has(e)) {
|
|
88
|
-
state.subscribedEvents.add(e);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
ws.send(JSON.stringify({ type: 'subscribed', events: [...state.subscribedEvents] }));
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
default: {
|
|
95
|
-
const safeType = String(msg.type)
|
|
96
|
-
.slice(0, 64)
|
|
97
|
-
.replace(/[<>&"']/g, '');
|
|
98
|
-
ws.send(JSON.stringify({ type: 'error', message: `Unknown message type: ${safeType}` }));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
ws.on('error', () => {
|
|
103
|
-
clients.delete(ws);
|
|
104
|
-
});
|
|
105
|
-
ws.on('close', () => {
|
|
106
|
-
clients.delete(ws);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
const pingInterval = setInterval(() => {
|
|
110
|
-
for (const [ws, state] of clients) {
|
|
111
|
-
if (!state.alive) {
|
|
112
|
-
ws.terminate();
|
|
113
|
-
clients.delete(ws);
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
state.alive = false;
|
|
117
|
-
ws.ping();
|
|
118
|
-
}
|
|
119
|
-
}, PING_INTERVAL_MS);
|
|
120
|
-
pingInterval.unref();
|
|
121
|
-
// Poll DB for changes from other processes (MCP stdio servers write directly).
|
|
122
|
-
// Computes a lightweight fingerprint of tasks and pushes full state on change.
|
|
123
|
-
let lastFingerprint = '';
|
|
124
|
-
const dbPollInterval = setInterval(() => {
|
|
125
|
-
if (clients.size === 0)
|
|
126
|
-
return;
|
|
127
|
-
try {
|
|
37
|
+
const subscribedByClient = new WeakMap();
|
|
38
|
+
return setupKitWebSocket({
|
|
39
|
+
httpServer,
|
|
40
|
+
getFingerprints: () => {
|
|
128
41
|
const row = ctx.db.queryOne(`SELECT
|
|
129
42
|
(SELECT COUNT(*) || ':' || COALESCE(MAX(updated_at),'') || ':' || COALESCE(MAX(id),0) FROM tasks)
|
|
130
43
|
|| '|' ||
|
|
131
44
|
(SELECT COALESCE(MAX(id),0) FROM task_comments)
|
|
132
45
|
|| '|' ||
|
|
133
46
|
(SELECT COALESCE(MAX(id),0) FROM task_artifacts)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
47
|
+
AS fp`);
|
|
48
|
+
return { pipeline: row?.fp ?? '' };
|
|
49
|
+
},
|
|
50
|
+
getCategoryData: () => buildStatePayload(ctx),
|
|
51
|
+
getFullState: () => ({ version: packageMeta.version, ...buildStatePayload(ctx) }),
|
|
52
|
+
onMessage: (ws, msg) => {
|
|
53
|
+
if (msg.type !== 'subscribe')
|
|
54
|
+
return false;
|
|
55
|
+
const events = msg.events;
|
|
56
|
+
if (!Array.isArray(events)) {
|
|
57
|
+
ws.send(JSON.stringify({
|
|
58
|
+
type: 'error',
|
|
59
|
+
message: '"events" must be an array of event type strings',
|
|
60
|
+
}));
|
|
61
|
+
return true;
|
|
143
62
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}, DB_POLL_INTERVAL_MS);
|
|
149
|
-
dbPollInterval.unref();
|
|
150
|
-
return {
|
|
151
|
-
wss,
|
|
152
|
-
broadcast(message) {
|
|
153
|
-
for (const [ws] of clients) {
|
|
154
|
-
if (ws.readyState === WebSocket.OPEN) {
|
|
155
|
-
ws.send(message);
|
|
63
|
+
const subs = new Set();
|
|
64
|
+
for (const e of events) {
|
|
65
|
+
if (typeof e === 'string' && VALID_EVENT_TYPES.has(e)) {
|
|
66
|
+
subs.add(e);
|
|
156
67
|
}
|
|
157
68
|
}
|
|
69
|
+
subscribedByClient.set(ws, subs);
|
|
70
|
+
ws.send(JSON.stringify({ type: 'subscribed', events: [...subs] }));
|
|
71
|
+
return true;
|
|
158
72
|
},
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
clearInterval(dbPollInterval);
|
|
162
|
-
for (const [ws] of clients) {
|
|
163
|
-
ws.close(1001, 'Server shutting down');
|
|
164
|
-
}
|
|
165
|
-
clients.clear();
|
|
166
|
-
wss.close();
|
|
167
|
-
},
|
|
168
|
-
};
|
|
73
|
+
logError: (err) => process.stderr.write('[agent-tasks] WS error: ' + (err instanceof Error ? err.message : String(err)) + '\n'),
|
|
74
|
+
});
|
|
169
75
|
}
|
|
170
|
-
function
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
gateConfigs: ctx.tasks.getAllGateConfigs(),
|
|
182
|
-
collaborators: ctx.collaborators.listAllByTask(),
|
|
183
|
-
}));
|
|
184
|
-
}
|
|
185
|
-
catch (err) {
|
|
186
|
-
process.stderr.write('[agent-tasks] sendFullState error: ' +
|
|
187
|
-
(err instanceof Error ? err.message : String(err)) +
|
|
188
|
-
'\n');
|
|
189
|
-
}
|
|
76
|
+
function buildStatePayload(ctx) {
|
|
77
|
+
return {
|
|
78
|
+
tasks: ctx.tasks.list(),
|
|
79
|
+
dependencies: ctx.tasks.getAllDependencies(),
|
|
80
|
+
artifactCounts: ctx.tasks.getArtifactCounts(),
|
|
81
|
+
commentCounts: ctx.comments.countByTask(),
|
|
82
|
+
subtaskProgress: ctx.tasks.getAllSubtaskProgress(),
|
|
83
|
+
stages: ctx.tasks.getPipelineStages(),
|
|
84
|
+
gateConfigs: ctx.tasks.getAllGateConfigs(),
|
|
85
|
+
collaborators: ctx.collaborators.listAllByTask(),
|
|
86
|
+
};
|
|
190
87
|
}
|
|
191
88
|
//# sourceMappingURL=ws.js.map
|
package/dist/transport/ws.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.js","sourceRoot":"","sources":["../../src/transport/ws.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,oCAAoC;AACpC,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"ws.js","sourceRoot":"","sources":["../../src/transport/ws.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-tasks",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.22",
|
|
4
4
|
"description": "Pipeline-driven task management for AI coding agents — stages, dependencies, artifacts, and multi-agent claiming",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
]
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"agent-common": "^1.0.
|
|
51
|
+
"agent-common": "^1.0.2",
|
|
52
52
|
"better-sqlite3": "^12.8.0",
|
|
53
53
|
"morphdom": "^2.7.8",
|
|
54
54
|
"ws": "^8.20.0"
|