@siftd/connect-agent 0.2.14 → 0.2.15
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/dist/agent.js +8 -0
- package/dist/heartbeat.js +1 -1
- package/dist/orchestrator.d.ts +27 -0
- package/dist/orchestrator.js +109 -1
- package/dist/websocket.d.ts +5 -0
- package/dist/websocket.js +9 -0
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -213,6 +213,14 @@ export async function runAgent(pollInterval = 2000) {
|
|
|
213
213
|
const wsConnected = await wsClient.connect();
|
|
214
214
|
if (wsConnected) {
|
|
215
215
|
console.log('[AGENT] Using WebSocket for real-time communication\n');
|
|
216
|
+
// Set up worker status callback for progress bars
|
|
217
|
+
if (orchestrator) {
|
|
218
|
+
orchestrator.setWorkerStatusCallback((workers) => {
|
|
219
|
+
if (wsClient?.connected()) {
|
|
220
|
+
wsClient.sendWorkersUpdate(workers);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
216
224
|
// Handle messages via WebSocket
|
|
217
225
|
wsClient.onMessage(async (wsMsg) => {
|
|
218
226
|
if (wsMsg.type === 'message' && wsMsg.content && wsMsg.id) {
|
package/dist/heartbeat.js
CHANGED
|
@@ -10,7 +10,7 @@ import { hostname } from 'os';
|
|
|
10
10
|
import { createHash } from 'crypto';
|
|
11
11
|
import { getServerUrl, getAgentToken, getUserId, isCloudMode } from './config.js';
|
|
12
12
|
const HEARTBEAT_INTERVAL = 10000; // 10 seconds
|
|
13
|
-
const VERSION = '0.2.
|
|
13
|
+
const VERSION = '0.2.15'; // Should match package.json
|
|
14
14
|
const state = {
|
|
15
15
|
intervalId: null,
|
|
16
16
|
runnerId: null,
|
package/dist/orchestrator.d.ts
CHANGED
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { MessageParam } from '@anthropic-ai/sdk/resources/messages';
|
|
8
8
|
export type MessageSender = (message: string) => Promise<void>;
|
|
9
|
+
export interface WorkerStatus {
|
|
10
|
+
id: string;
|
|
11
|
+
task: string;
|
|
12
|
+
status: 'running' | 'completed' | 'failed' | 'timeout';
|
|
13
|
+
progress: number;
|
|
14
|
+
elapsed: number;
|
|
15
|
+
estimated: number;
|
|
16
|
+
}
|
|
17
|
+
export type WorkerStatusCallback = (workers: WorkerStatus[]) => void;
|
|
9
18
|
export declare class MasterOrchestrator {
|
|
10
19
|
private client;
|
|
11
20
|
private model;
|
|
@@ -15,6 +24,8 @@ export declare class MasterOrchestrator {
|
|
|
15
24
|
private indexer;
|
|
16
25
|
private jobs;
|
|
17
26
|
private jobCounter;
|
|
27
|
+
private workerStatusCallback;
|
|
28
|
+
private workerStatusInterval;
|
|
18
29
|
private userId;
|
|
19
30
|
private workspaceDir;
|
|
20
31
|
private claudePath;
|
|
@@ -36,6 +47,22 @@ export declare class MasterOrchestrator {
|
|
|
36
47
|
* Initialize the orchestrator - indexes filesystem on first call
|
|
37
48
|
*/
|
|
38
49
|
initialize(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Set callback for worker status updates (for UI progress bars)
|
|
52
|
+
*/
|
|
53
|
+
setWorkerStatusCallback(callback: WorkerStatusCallback | null): void;
|
|
54
|
+
/**
|
|
55
|
+
* Get current status of all workers
|
|
56
|
+
*/
|
|
57
|
+
getWorkerStatus(): WorkerStatus[];
|
|
58
|
+
/**
|
|
59
|
+
* Broadcast worker status to callback
|
|
60
|
+
*/
|
|
61
|
+
private broadcastWorkerStatus;
|
|
62
|
+
/**
|
|
63
|
+
* Estimate task duration based on content
|
|
64
|
+
*/
|
|
65
|
+
private estimateTaskDuration;
|
|
39
66
|
/**
|
|
40
67
|
* Find the claude binary path
|
|
41
68
|
*/
|
package/dist/orchestrator.js
CHANGED
|
@@ -79,6 +79,8 @@ export class MasterOrchestrator {
|
|
|
79
79
|
indexer;
|
|
80
80
|
jobs = new Map();
|
|
81
81
|
jobCounter = 0;
|
|
82
|
+
workerStatusCallback = null;
|
|
83
|
+
workerStatusInterval = null;
|
|
82
84
|
userId;
|
|
83
85
|
workspaceDir;
|
|
84
86
|
claudePath;
|
|
@@ -140,6 +142,104 @@ export class MasterOrchestrator {
|
|
|
140
142
|
}
|
|
141
143
|
this.initialized = true;
|
|
142
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Set callback for worker status updates (for UI progress bars)
|
|
147
|
+
*/
|
|
148
|
+
setWorkerStatusCallback(callback) {
|
|
149
|
+
this.workerStatusCallback = callback;
|
|
150
|
+
if (callback) {
|
|
151
|
+
// Start broadcasting status every 500ms when workers are running
|
|
152
|
+
if (!this.workerStatusInterval) {
|
|
153
|
+
this.workerStatusInterval = setInterval(() => {
|
|
154
|
+
this.broadcastWorkerStatus();
|
|
155
|
+
}, 500);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// Stop broadcasting
|
|
160
|
+
if (this.workerStatusInterval) {
|
|
161
|
+
clearInterval(this.workerStatusInterval);
|
|
162
|
+
this.workerStatusInterval = null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get current status of all workers
|
|
168
|
+
*/
|
|
169
|
+
getWorkerStatus() {
|
|
170
|
+
const now = Date.now();
|
|
171
|
+
const workers = [];
|
|
172
|
+
for (const [id, job] of this.jobs) {
|
|
173
|
+
const elapsed = (now - job.startTime) / 1000;
|
|
174
|
+
const estimated = job.estimatedTime;
|
|
175
|
+
// Calculate progress: cap at 90% while running, 100% when done
|
|
176
|
+
let progress;
|
|
177
|
+
if (job.status === 'completed') {
|
|
178
|
+
progress = 100;
|
|
179
|
+
}
|
|
180
|
+
else if (job.status === 'failed' || job.status === 'timeout') {
|
|
181
|
+
progress = 100; // Show as complete even on failure
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
progress = Math.min(90, (elapsed / estimated) * 100);
|
|
185
|
+
}
|
|
186
|
+
workers.push({
|
|
187
|
+
id,
|
|
188
|
+
task: job.task.slice(0, 60),
|
|
189
|
+
status: job.status,
|
|
190
|
+
progress: Math.round(progress),
|
|
191
|
+
elapsed: Math.round(elapsed),
|
|
192
|
+
estimated: Math.round(estimated)
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return workers;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Broadcast worker status to callback
|
|
199
|
+
*/
|
|
200
|
+
broadcastWorkerStatus() {
|
|
201
|
+
if (!this.workerStatusCallback)
|
|
202
|
+
return;
|
|
203
|
+
const workers = this.getWorkerStatus();
|
|
204
|
+
// Only broadcast if there are running workers
|
|
205
|
+
const hasRunning = workers.some(w => w.status === 'running');
|
|
206
|
+
if (hasRunning || workers.length > 0) {
|
|
207
|
+
this.workerStatusCallback(workers);
|
|
208
|
+
}
|
|
209
|
+
// Clean up completed jobs after 3 seconds
|
|
210
|
+
const now = Date.now();
|
|
211
|
+
for (const [id, job] of this.jobs) {
|
|
212
|
+
if (job.status !== 'running' && job.endTime && (now - job.endTime) > 3000) {
|
|
213
|
+
this.jobs.delete(id);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Estimate task duration based on content
|
|
219
|
+
*/
|
|
220
|
+
estimateTaskDuration(task) {
|
|
221
|
+
const lower = task.toLowerCase();
|
|
222
|
+
// Complex tasks: 3 minutes
|
|
223
|
+
if (lower.includes('refactor') || lower.includes('implement') ||
|
|
224
|
+
lower.includes('create') || lower.includes('build') ||
|
|
225
|
+
lower.includes('write tests') || lower.includes('add tests')) {
|
|
226
|
+
return 180;
|
|
227
|
+
}
|
|
228
|
+
// Medium tasks: 90 seconds
|
|
229
|
+
if (lower.includes('fix') || lower.includes('update') ||
|
|
230
|
+
lower.includes('modify') || lower.includes('change') ||
|
|
231
|
+
lower.includes('add') || lower.includes('install')) {
|
|
232
|
+
return 90;
|
|
233
|
+
}
|
|
234
|
+
// Simple tasks: 45 seconds
|
|
235
|
+
if (lower.includes('find') || lower.includes('search') ||
|
|
236
|
+
lower.includes('read') || lower.includes('list') ||
|
|
237
|
+
lower.includes('check') || lower.includes('show')) {
|
|
238
|
+
return 45;
|
|
239
|
+
}
|
|
240
|
+
// Default: 60 seconds
|
|
241
|
+
return 60;
|
|
242
|
+
}
|
|
143
243
|
/**
|
|
144
244
|
* Find the claude binary path
|
|
145
245
|
*/
|
|
@@ -757,13 +857,16 @@ If you need to share data with other workers or signal completion:
|
|
|
757
857
|
[MESSAGE] to=worker_xyz | content=Please review the changes I made
|
|
758
858
|
This enables parallel workers to coordinate.`;
|
|
759
859
|
console.log(`[ORCHESTRATOR] Delegating to worker ${id}: ${task.slice(0, 80)}...`);
|
|
860
|
+
// Estimate task duration based on content
|
|
861
|
+
const estimatedTime = this.estimateTaskDuration(task);
|
|
760
862
|
return new Promise((resolve) => {
|
|
761
863
|
const job = {
|
|
762
864
|
id,
|
|
763
865
|
task: task.slice(0, 200),
|
|
764
866
|
status: 'running',
|
|
765
867
|
startTime: Date.now(),
|
|
766
|
-
output: ''
|
|
868
|
+
output: '',
|
|
869
|
+
estimatedTime
|
|
767
870
|
};
|
|
768
871
|
// Escape single quotes in prompt for shell safety
|
|
769
872
|
// Replace ' with '\'' (end quote, escaped quote, start quote)
|
|
@@ -1141,6 +1244,11 @@ This enables parallel workers to coordinate.`;
|
|
|
1141
1244
|
* Shutdown cleanly
|
|
1142
1245
|
*/
|
|
1143
1246
|
async shutdown() {
|
|
1247
|
+
// Stop worker status broadcasting
|
|
1248
|
+
if (this.workerStatusInterval) {
|
|
1249
|
+
clearInterval(this.workerStatusInterval);
|
|
1250
|
+
this.workerStatusInterval = null;
|
|
1251
|
+
}
|
|
1144
1252
|
this.scheduler.shutdown();
|
|
1145
1253
|
if (this.memory instanceof PostgresMemoryStore) {
|
|
1146
1254
|
await this.memory.close();
|
package/dist/websocket.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* - Streams responses as they're generated
|
|
7
7
|
* - Supports interruption and progress updates
|
|
8
8
|
*/
|
|
9
|
+
import type { WorkerStatus } from './orchestrator.js';
|
|
9
10
|
export type MessageHandler = (message: WebSocketMessage) => Promise<void>;
|
|
10
11
|
export type StreamHandler = (chunk: string) => void;
|
|
11
12
|
export interface WebSocketMessage {
|
|
@@ -57,6 +58,10 @@ export declare class AgentWebSocket {
|
|
|
57
58
|
* Send typing indicator
|
|
58
59
|
*/
|
|
59
60
|
sendTyping(isTyping: boolean): void;
|
|
61
|
+
/**
|
|
62
|
+
* Send workers status update for progress bars
|
|
63
|
+
*/
|
|
64
|
+
sendWorkersUpdate(workers: WorkerStatus[]): void;
|
|
60
65
|
/**
|
|
61
66
|
* Check if connected
|
|
62
67
|
*/
|
package/dist/websocket.js
CHANGED
|
@@ -159,6 +159,15 @@ export class AgentWebSocket {
|
|
|
159
159
|
isTyping
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Send workers status update for progress bars
|
|
164
|
+
*/
|
|
165
|
+
sendWorkersUpdate(workers) {
|
|
166
|
+
this.sendToServer({
|
|
167
|
+
type: 'workers_update',
|
|
168
|
+
workers
|
|
169
|
+
});
|
|
170
|
+
}
|
|
162
171
|
/**
|
|
163
172
|
* Check if connected
|
|
164
173
|
*/
|