@siftd/connect-agent 0.2.57 → 0.2.59
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/orchestrator.d.ts +6 -0
- package/dist/orchestrator.js +159 -0
- package/package.json +1 -1
package/dist/orchestrator.d.ts
CHANGED
|
@@ -76,6 +76,7 @@ export declare class MasterOrchestrator {
|
|
|
76
76
|
private currentFileScope;
|
|
77
77
|
private forceTeamWorkingDir;
|
|
78
78
|
private recentFileWrites;
|
|
79
|
+
private recentWorkerActivity;
|
|
79
80
|
private bashTool;
|
|
80
81
|
private webTools;
|
|
81
82
|
private workerTools;
|
|
@@ -214,6 +215,11 @@ export declare class MasterOrchestrator {
|
|
|
214
215
|
private toFilesVirtualPath;
|
|
215
216
|
private finalizeResponse;
|
|
216
217
|
private getFileScopeSystemNote;
|
|
218
|
+
private recordWorkerActivity;
|
|
219
|
+
private formatRelativeTime;
|
|
220
|
+
private getRecentWorkerSummary;
|
|
221
|
+
private isStatusInquiry;
|
|
222
|
+
private buildStatusReply;
|
|
217
223
|
/**
|
|
218
224
|
* Check if verbose mode is enabled
|
|
219
225
|
*/
|
package/dist/orchestrator.js
CHANGED
|
@@ -161,6 +161,13 @@ YOUR HUB: ~/Lia-Hub/
|
|
|
161
161
|
- **notebook-a/SCRATCHPAD.md** - Your working notes
|
|
162
162
|
- **shared/outputs/** - Where workers save files
|
|
163
163
|
|
|
164
|
+
HUB PRIVACY:
|
|
165
|
+
- These hub files are INTERNAL. Do NOT list or reveal them to users.
|
|
166
|
+
- Never enumerate ~/Lia-Hub, CLAUDE.md, AGENTS.md, LANDMARKS.md, or other internal files.
|
|
167
|
+
- If a user asks to list files, direct them to /files or list channel files only.
|
|
168
|
+
- Home channels are private. Never access or list another user's Home channel.
|
|
169
|
+
- If asked about another user's Home channel, politely decline and offer to search shared channels.
|
|
170
|
+
|
|
164
171
|
ASSET PREVIEWS:
|
|
165
172
|
The Lia interface has a built-in gallery that shows worker outputs automatically.
|
|
166
173
|
⛔ NEVER use start_local_server or open_browser for previews
|
|
@@ -170,6 +177,7 @@ The Lia interface has a built-in gallery that shows worker outputs automatically
|
|
|
170
177
|
|
|
171
178
|
FILES BROWSER:
|
|
172
179
|
Users can type /files to open the Finder UI (cloud mode).
|
|
180
|
+
Treat /files as the canonical file surface (channel files). Do not expose hub internals.
|
|
173
181
|
When asked to browse or locate files, point them to /files.
|
|
174
182
|
Refer to /files instead of internal Lia-Hub paths in responses.
|
|
175
183
|
When users ask you to create or update a file in /files, use files_write.
|
|
@@ -259,6 +267,7 @@ export class MasterOrchestrator {
|
|
|
259
267
|
currentFileScope = 'personal';
|
|
260
268
|
forceTeamWorkingDir = false;
|
|
261
269
|
recentFileWrites = [];
|
|
270
|
+
recentWorkerActivity = [];
|
|
262
271
|
// New tools from whatsapp-claude
|
|
263
272
|
bashTool;
|
|
264
273
|
webTools;
|
|
@@ -992,6 +1001,98 @@ export class MasterOrchestrator {
|
|
|
992
1001
|
return null;
|
|
993
1002
|
return `TEAM FILES DIRECTORY:\n- ${teamDir}\nUse this path for files meant to be shared with the team.`;
|
|
994
1003
|
}
|
|
1004
|
+
recordWorkerActivity(event) {
|
|
1005
|
+
const normalized = {
|
|
1006
|
+
...event,
|
|
1007
|
+
task: event.task.slice(0, 140),
|
|
1008
|
+
note: event.note?.slice(0, 200)
|
|
1009
|
+
};
|
|
1010
|
+
this.recentWorkerActivity = [normalized, ...this.recentWorkerActivity].slice(0, 12);
|
|
1011
|
+
}
|
|
1012
|
+
formatRelativeTime(timestamp) {
|
|
1013
|
+
const deltaMs = Date.now() - timestamp;
|
|
1014
|
+
if (deltaMs < 1000)
|
|
1015
|
+
return 'just now';
|
|
1016
|
+
const seconds = Math.floor(deltaMs / 1000);
|
|
1017
|
+
if (seconds < 60)
|
|
1018
|
+
return `${seconds}s ago`;
|
|
1019
|
+
const minutes = Math.floor(seconds / 60);
|
|
1020
|
+
if (minutes < 60)
|
|
1021
|
+
return `${minutes}m ago`;
|
|
1022
|
+
const hours = Math.floor(minutes / 60);
|
|
1023
|
+
if (hours < 24)
|
|
1024
|
+
return `${hours}h ago`;
|
|
1025
|
+
const days = Math.floor(hours / 24);
|
|
1026
|
+
return `${days}d ago`;
|
|
1027
|
+
}
|
|
1028
|
+
getRecentWorkerSummary(limit = 4) {
|
|
1029
|
+
if (this.recentWorkerActivity.length === 0)
|
|
1030
|
+
return null;
|
|
1031
|
+
const seen = new Set();
|
|
1032
|
+
const lines = [];
|
|
1033
|
+
for (const event of this.recentWorkerActivity) {
|
|
1034
|
+
if (seen.has(event.id))
|
|
1035
|
+
continue;
|
|
1036
|
+
seen.add(event.id);
|
|
1037
|
+
const when = this.formatRelativeTime(event.endedAt ?? event.startedAt);
|
|
1038
|
+
const note = event.note ? ` — ${event.note}` : '';
|
|
1039
|
+
lines.push(`- ${event.task} (${event.status}, ${when})${note}`);
|
|
1040
|
+
if (lines.length >= limit)
|
|
1041
|
+
break;
|
|
1042
|
+
}
|
|
1043
|
+
return lines.length > 0 ? lines.join('\n') : null;
|
|
1044
|
+
}
|
|
1045
|
+
isStatusInquiry(message) {
|
|
1046
|
+
const lower = message.toLowerCase();
|
|
1047
|
+
if (!lower)
|
|
1048
|
+
return false;
|
|
1049
|
+
const patterns = [
|
|
1050
|
+
/\b(status|progress|queue|queued|pending)\b/,
|
|
1051
|
+
/\bwhat (are|were) you (doing|working on)\b/,
|
|
1052
|
+
/\bwhat happened\b/,
|
|
1053
|
+
/\bstuck\b/,
|
|
1054
|
+
/\btaking (so long|forever|too long)\b/,
|
|
1055
|
+
/\bwhy (is|are) (this|it) (taking|hung|stuck)\b/,
|
|
1056
|
+
];
|
|
1057
|
+
return patterns.some((pattern) => pattern.test(lower));
|
|
1058
|
+
}
|
|
1059
|
+
buildStatusReply() {
|
|
1060
|
+
const queueStatus = this.taskQueue.getStatus();
|
|
1061
|
+
const runningWorkers = this.getWorkerStatus().filter((worker) => worker.status === 'running');
|
|
1062
|
+
const recentWorkers = this.getRecentWorkerSummary(4);
|
|
1063
|
+
const recentTasks = this.taskQueue.getRecentTasks(3)
|
|
1064
|
+
.filter((task) => task.status !== 'pending')
|
|
1065
|
+
.map((task) => `- ${task.content.slice(0, 80)} (${task.status})`);
|
|
1066
|
+
const lines = [];
|
|
1067
|
+
if (runningWorkers.length > 0) {
|
|
1068
|
+
lines.push(`Active workers: ${runningWorkers.length}`);
|
|
1069
|
+
for (const worker of runningWorkers.slice(0, 3)) {
|
|
1070
|
+
lines.push(`- ${worker.task} (${worker.progress}% · ${worker.elapsed}s)`);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
else {
|
|
1074
|
+
lines.push('Active workers: none');
|
|
1075
|
+
}
|
|
1076
|
+
if (queueStatus.isProcessing || queueStatus.pendingCount > 0) {
|
|
1077
|
+
const current = queueStatus.currentTask?.content;
|
|
1078
|
+
lines.push(`Task queue: ${queueStatus.pendingCount} pending${queueStatus.isProcessing ? ' · processing' : ''}`);
|
|
1079
|
+
if (current) {
|
|
1080
|
+
lines.push(`- Current: ${current.slice(0, 100)}`);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
else {
|
|
1084
|
+
lines.push('Task queue: empty');
|
|
1085
|
+
}
|
|
1086
|
+
if (recentWorkers) {
|
|
1087
|
+
lines.push('Recent worker activity:');
|
|
1088
|
+
lines.push(recentWorkers);
|
|
1089
|
+
}
|
|
1090
|
+
if (recentTasks.length > 0) {
|
|
1091
|
+
lines.push('Recent task results:');
|
|
1092
|
+
lines.push(recentTasks.join('\n'));
|
|
1093
|
+
}
|
|
1094
|
+
return lines.join('\n');
|
|
1095
|
+
}
|
|
995
1096
|
/**
|
|
996
1097
|
* Check if verbose mode is enabled
|
|
997
1098
|
*/
|
|
@@ -1010,6 +1111,9 @@ export class MasterOrchestrator {
|
|
|
1010
1111
|
return slashResponse;
|
|
1011
1112
|
}
|
|
1012
1113
|
this.updateFileScope(cleanMessage);
|
|
1114
|
+
if (this.isStatusInquiry(cleanMessage)) {
|
|
1115
|
+
return this.buildStatusReply();
|
|
1116
|
+
}
|
|
1013
1117
|
const wantsTodoOrCal = this.hasTodoMutation(cleanMessage) || this.hasCalendarMutation(cleanMessage);
|
|
1014
1118
|
if (wantsTodoOrCal) {
|
|
1015
1119
|
this.attachmentContext = this.extractAttachmentContext(message);
|
|
@@ -1066,6 +1170,10 @@ ${hubContextStr}
|
|
|
1066
1170
|
if (fileScopeNote) {
|
|
1067
1171
|
systemWithContext += `\n\n${fileScopeNote}`;
|
|
1068
1172
|
}
|
|
1173
|
+
const recentWorkerSummary = this.getRecentWorkerSummary();
|
|
1174
|
+
if (recentWorkerSummary) {
|
|
1175
|
+
systemWithContext += `\n\nRECENT WORKER ACTIVITY (for accurate status updates):\n${recentWorkerSummary}`;
|
|
1176
|
+
}
|
|
1069
1177
|
// Add user message
|
|
1070
1178
|
const messages = [
|
|
1071
1179
|
...conversationHistory,
|
|
@@ -2336,6 +2444,17 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
|
|
|
2336
2444
|
priority: input.priority,
|
|
2337
2445
|
workingDirectory: input.working_directory || fileScope.workingDir
|
|
2338
2446
|
});
|
|
2447
|
+
if (result.success && result.output) {
|
|
2448
|
+
const match = result.output.match(/Job ID:\s*(\S+)/i);
|
|
2449
|
+
if (match) {
|
|
2450
|
+
this.recordWorkerActivity({
|
|
2451
|
+
id: match[1],
|
|
2452
|
+
task: normalizedTask.slice(0, 200),
|
|
2453
|
+
status: 'running',
|
|
2454
|
+
startedAt: Date.now(),
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2339
2458
|
break;
|
|
2340
2459
|
}
|
|
2341
2460
|
case 'check_worker':
|
|
@@ -2349,6 +2468,16 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
|
|
|
2349
2468
|
break;
|
|
2350
2469
|
case 'cancel_worker':
|
|
2351
2470
|
result = await this.workerTools.cancelWorker(input.job_id);
|
|
2471
|
+
if (result.success) {
|
|
2472
|
+
this.recordWorkerActivity({
|
|
2473
|
+
id: String(input.job_id || 'unknown'),
|
|
2474
|
+
task: 'Worker cancelled',
|
|
2475
|
+
status: 'cancelled',
|
|
2476
|
+
startedAt: Date.now(),
|
|
2477
|
+
endedAt: Date.now(),
|
|
2478
|
+
note: 'Cancelled by request'
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2352
2481
|
break;
|
|
2353
2482
|
// Legacy delegate tool
|
|
2354
2483
|
case 'delegate_to_worker': {
|
|
@@ -2509,6 +2638,12 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
|
|
|
2509
2638
|
estimatedTime,
|
|
2510
2639
|
workingDir: cwd
|
|
2511
2640
|
};
|
|
2641
|
+
this.recordWorkerActivity({
|
|
2642
|
+
id,
|
|
2643
|
+
task: job.task,
|
|
2644
|
+
status: 'running',
|
|
2645
|
+
startedAt: job.startTime
|
|
2646
|
+
});
|
|
2512
2647
|
// Escape single quotes in prompt for shell safety
|
|
2513
2648
|
const escapedPrompt = prompt.replace(/'/g, "'\\''");
|
|
2514
2649
|
const budget = resolveClaudeBudgetUsd();
|
|
@@ -2549,6 +2684,14 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
|
|
|
2549
2684
|
job.endTime = Date.now();
|
|
2550
2685
|
child.kill('SIGTERM');
|
|
2551
2686
|
console.log(`[ORCHESTRATOR] Worker ${id} timed out`);
|
|
2687
|
+
this.recordWorkerActivity({
|
|
2688
|
+
id,
|
|
2689
|
+
task: job.task,
|
|
2690
|
+
status: 'timeout',
|
|
2691
|
+
startedAt: job.startTime,
|
|
2692
|
+
endedAt: job.endTime,
|
|
2693
|
+
note: 'Timed out after 5 minutes'
|
|
2694
|
+
});
|
|
2552
2695
|
if (this.workerResultCallback) {
|
|
2553
2696
|
this.workerResultCallback(id, `Worker timed out. Partial output: ${job.output.slice(-1000) || 'none'}`);
|
|
2554
2697
|
}
|
|
@@ -2586,6 +2729,14 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
|
|
|
2586
2729
|
const status = code === 0 ? 'completed' : 'failed';
|
|
2587
2730
|
const filesCreated = assets.map(a => a.name);
|
|
2588
2731
|
logWorker(id, job.task, status, duration, filesCreated.length > 0 ? filesCreated : undefined);
|
|
2732
|
+
this.recordWorkerActivity({
|
|
2733
|
+
id,
|
|
2734
|
+
task: job.task,
|
|
2735
|
+
status,
|
|
2736
|
+
startedAt: job.startTime,
|
|
2737
|
+
endedAt: job.endTime,
|
|
2738
|
+
note: code === 0 ? undefined : `Exit code ${code ?? 'unknown'}`
|
|
2739
|
+
});
|
|
2589
2740
|
if (assets.length > 0) {
|
|
2590
2741
|
console.log(`[ORCHESTRATOR] Worker ${id} created ${assets.length} files: ${assets.map(a => a.name).join(', ')}`);
|
|
2591
2742
|
// Store in memory for gallery queries
|
|
@@ -2613,6 +2764,14 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
|
|
|
2613
2764
|
job.status = 'failed';
|
|
2614
2765
|
job.endTime = Date.now();
|
|
2615
2766
|
console.error(`[ORCHESTRATOR] Worker ${id} error:`, err.message);
|
|
2767
|
+
this.recordWorkerActivity({
|
|
2768
|
+
id,
|
|
2769
|
+
task: job.task,
|
|
2770
|
+
status: 'failed',
|
|
2771
|
+
startedAt: job.startTime,
|
|
2772
|
+
endedAt: job.endTime,
|
|
2773
|
+
note: err.message
|
|
2774
|
+
});
|
|
2616
2775
|
if (this.workerResultCallback) {
|
|
2617
2776
|
this.workerResultCallback(id, `Worker error: ${err.message}`);
|
|
2618
2777
|
}
|