@siftd/connect-agent 0.2.26 → 0.2.28
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 +17 -0
- package/dist/cli.js +6 -0
- package/dist/core/hub.d.ts +38 -1
- package/dist/core/hub.js +215 -5
- package/dist/orchestrator.js +39 -10
- package/dist/prompts/worker-system.d.ts +48 -0
- package/dist/prompts/worker-system.js +119 -0
- package/dist/workers/manager.js +1 -0
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -4,6 +4,7 @@ import { getUserId, getAnthropicApiKey, isCloudMode, getDeploymentInfo } from '.
|
|
|
4
4
|
import { MasterOrchestrator } from './orchestrator.js';
|
|
5
5
|
import { AgentWebSocket } from './websocket.js';
|
|
6
6
|
import { startHeartbeat, stopHeartbeat, getHeartbeatState } from './heartbeat.js';
|
|
7
|
+
import { loadHubContext, readScratchpad } from './core/hub.js';
|
|
7
8
|
// Strip ANSI escape codes for clean output
|
|
8
9
|
function stripAnsi(str) {
|
|
9
10
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, '');
|
|
@@ -217,6 +218,22 @@ export async function runAgent(pollInterval = 2000) {
|
|
|
217
218
|
console.log('[AGENT] Features: Memory, Scheduling, Worker Delegation');
|
|
218
219
|
// Initialize orchestrator (indexes filesystem into memory)
|
|
219
220
|
await orchestrator.initialize();
|
|
221
|
+
// Load hub context on startup
|
|
222
|
+
const hubContext = loadHubContext();
|
|
223
|
+
if (hubContext.agentIdentity) {
|
|
224
|
+
console.log('[AGENT] Hub: AGENTS.md loaded');
|
|
225
|
+
}
|
|
226
|
+
if (hubContext.claudeMd) {
|
|
227
|
+
console.log('[AGENT] Hub: CLAUDE.md loaded');
|
|
228
|
+
}
|
|
229
|
+
if (hubContext.landmarks) {
|
|
230
|
+
console.log('[AGENT] Hub: LANDMARKS.md loaded');
|
|
231
|
+
}
|
|
232
|
+
// Check scratchpad for pending plans
|
|
233
|
+
const scratchpad = readScratchpad();
|
|
234
|
+
if (scratchpad && scratchpad.length > 100) {
|
|
235
|
+
console.log(`[AGENT] Scratchpad: ${scratchpad.length} chars of pending notes`);
|
|
236
|
+
}
|
|
220
237
|
}
|
|
221
238
|
// Start heartbeat to maintain presence in runner registry
|
|
222
239
|
const runnerType = isCloudMode() ? 'vm' : 'local';
|
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import ora from 'ora';
|
|
|
4
4
|
import { getServerUrl, setServerUrl, setAgentToken, setUserId, setAnthropicApiKey, getAnthropicApiKey, isConfigured, clearConfig, getConfigPath, } from './config.js';
|
|
5
5
|
import { connectWithPairingCode, checkConnection } from './api.js';
|
|
6
6
|
import { runAgent } from './agent.js';
|
|
7
|
+
import { ensureLiaHub, getLiaHubPaths } from './core/hub.js';
|
|
7
8
|
program
|
|
8
9
|
.name('connect-agent')
|
|
9
10
|
.description('Local agent for Connect web app')
|
|
@@ -61,6 +62,11 @@ program
|
|
|
61
62
|
process.exit(1);
|
|
62
63
|
}
|
|
63
64
|
spinner.succeed('Connected to server');
|
|
65
|
+
// Initialize Lia-Hub directory structure
|
|
66
|
+
ensureLiaHub();
|
|
67
|
+
const hubPaths = getLiaHubPaths();
|
|
68
|
+
console.log(`\nHub: ${hubPaths.hub}`);
|
|
69
|
+
console.log(`Notebook: ${hubPaths.notebook}`);
|
|
64
70
|
console.log(`\nServer: ${getServerUrl()}`);
|
|
65
71
|
console.log(`Poll interval: ${options.interval}ms`);
|
|
66
72
|
console.log('\nPress Ctrl+C to stop.\n');
|
package/dist/core/hub.d.ts
CHANGED
|
@@ -4,8 +4,44 @@
|
|
|
4
4
|
* Manages structured memory files in ~/.connect-hub/
|
|
5
5
|
* Human-readable markdown files that the orchestrator reads/writes.
|
|
6
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* Ensure Lia-Hub directory structure exists
|
|
9
|
+
* Called on agent start to create the orchestrator's workspace
|
|
10
|
+
*/
|
|
11
|
+
export declare function ensureLiaHub(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Get paths to Lia-Hub directories
|
|
14
|
+
*/
|
|
15
|
+
export declare function getLiaHubPaths(): {
|
|
16
|
+
hub: string;
|
|
17
|
+
notebook: string;
|
|
18
|
+
drafts: string;
|
|
19
|
+
shared: string;
|
|
20
|
+
outputs: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Read the orchestrator's scratchpad
|
|
24
|
+
*/
|
|
25
|
+
export declare function readScratchpad(): string | null;
|
|
26
|
+
/**
|
|
27
|
+
* Write to the orchestrator's scratchpad
|
|
28
|
+
*/
|
|
29
|
+
export declare function writeScratchpad(content: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Append a thought or plan to the scratchpad
|
|
32
|
+
*/
|
|
33
|
+
export declare function appendToScratchpad(note: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Log a worker to the worker log
|
|
36
|
+
*/
|
|
37
|
+
export declare function logWorker(workerId: string, task: string, status: 'started' | 'completed' | 'failed' | 'timeout', duration?: number, filesCreated?: string[]): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get the shared output directory path for workers
|
|
40
|
+
*/
|
|
41
|
+
export declare function getSharedOutputPath(): string;
|
|
7
42
|
export interface HubContext {
|
|
8
43
|
agentIdentity: string;
|
|
44
|
+
claudeMd: string;
|
|
9
45
|
landmarks: string;
|
|
10
46
|
projectBio: string | null;
|
|
11
47
|
projectName: string | null;
|
|
@@ -16,7 +52,8 @@ export interface HubContext {
|
|
|
16
52
|
export declare function ensureHubExists(): void;
|
|
17
53
|
/**
|
|
18
54
|
* Load hub context for a session
|
|
19
|
-
* Reads AGENTS.md, LANDMARKS.md, and relevant project bio
|
|
55
|
+
* Reads AGENTS.md, CLAUDE.md, LANDMARKS.md, and relevant project bio
|
|
56
|
+
* Checks both ~/.connect-hub and ~/Lia-Hub locations
|
|
20
57
|
*/
|
|
21
58
|
export declare function loadHubContext(message?: string): HubContext;
|
|
22
59
|
/**
|
package/dist/core/hub.js
CHANGED
|
@@ -9,6 +9,190 @@ import { join } from 'path';
|
|
|
9
9
|
import { homedir } from 'os';
|
|
10
10
|
const HUB_DIR = join(homedir(), '.connect-hub');
|
|
11
11
|
const PROJECTS_DIR = join(HUB_DIR, 'projects');
|
|
12
|
+
// Lia-Hub: The orchestrator's working directory
|
|
13
|
+
const LIA_HUB_DIR = join(homedir(), 'Lia-Hub');
|
|
14
|
+
const NOTEBOOK_A_DIR = join(LIA_HUB_DIR, 'notebook-a');
|
|
15
|
+
const DRAFTS_DIR = join(NOTEBOOK_A_DIR, 'drafts');
|
|
16
|
+
const SHARED_DIR = join(LIA_HUB_DIR, 'shared');
|
|
17
|
+
const OUTPUTS_DIR = join(SHARED_DIR, 'outputs');
|
|
18
|
+
/**
|
|
19
|
+
* Ensure Lia-Hub directory structure exists
|
|
20
|
+
* Called on agent start to create the orchestrator's workspace
|
|
21
|
+
*/
|
|
22
|
+
export function ensureLiaHub() {
|
|
23
|
+
const dirs = [
|
|
24
|
+
LIA_HUB_DIR,
|
|
25
|
+
NOTEBOOK_A_DIR,
|
|
26
|
+
DRAFTS_DIR,
|
|
27
|
+
SHARED_DIR,
|
|
28
|
+
OUTPUTS_DIR,
|
|
29
|
+
join(LIA_HUB_DIR, 'projects')
|
|
30
|
+
];
|
|
31
|
+
for (const dir of dirs) {
|
|
32
|
+
if (!existsSync(dir)) {
|
|
33
|
+
mkdirSync(dir, { recursive: true });
|
|
34
|
+
console.log(`[HUB] Created: ${dir}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Create template files if they don't exist
|
|
38
|
+
const agentsFile = join(LIA_HUB_DIR, 'AGENTS.md');
|
|
39
|
+
if (!existsSync(agentsFile)) {
|
|
40
|
+
writeFileSync(agentsFile, `# Agent Identity
|
|
41
|
+
|
|
42
|
+
You are the Master Orchestrator - the brain that coordinates Claude Code workers.
|
|
43
|
+
You remember, plan, delegate, and synthesize. Workers do the hands-on work.
|
|
44
|
+
|
|
45
|
+
## Capabilities
|
|
46
|
+
- Memory: Store and retrieve information across sessions
|
|
47
|
+
- Scheduling: Schedule future tasks
|
|
48
|
+
- Workers: Spawn Claude Code CLI for file/code operations
|
|
49
|
+
- Web: Search and fetch from the web
|
|
50
|
+
|
|
51
|
+
## Personality
|
|
52
|
+
Warm, helpful, and efficient. You coordinate to get things done.
|
|
53
|
+
`);
|
|
54
|
+
console.log('[HUB] Created AGENTS.md template');
|
|
55
|
+
}
|
|
56
|
+
const landmarksFile = join(LIA_HUB_DIR, 'LANDMARKS.md');
|
|
57
|
+
if (!existsSync(landmarksFile)) {
|
|
58
|
+
writeFileSync(landmarksFile, `# Current State
|
|
59
|
+
|
|
60
|
+
## Active Projects
|
|
61
|
+
(none yet)
|
|
62
|
+
|
|
63
|
+
## Recent Work
|
|
64
|
+
(none yet)
|
|
65
|
+
|
|
66
|
+
## Blockers
|
|
67
|
+
(none)
|
|
68
|
+
`);
|
|
69
|
+
console.log('[HUB] Created LANDMARKS.md template');
|
|
70
|
+
}
|
|
71
|
+
const scratchpadFile = join(NOTEBOOK_A_DIR, 'SCRATCHPAD.md');
|
|
72
|
+
if (!existsSync(scratchpadFile)) {
|
|
73
|
+
writeFileSync(scratchpadFile, `# Orchestrator Scratchpad
|
|
74
|
+
|
|
75
|
+
Use this file for:
|
|
76
|
+
- Planning complex tasks
|
|
77
|
+
- Working notes
|
|
78
|
+
- Organizing thoughts before acting
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
`);
|
|
83
|
+
console.log('[HUB] Created SCRATCHPAD.md template');
|
|
84
|
+
}
|
|
85
|
+
const workerLogFile = join(NOTEBOOK_A_DIR, 'WORKER-LOG.md');
|
|
86
|
+
if (!existsSync(workerLogFile)) {
|
|
87
|
+
writeFileSync(workerLogFile, `# Worker Log
|
|
88
|
+
|
|
89
|
+
Track all workers spawned and their outcomes.
|
|
90
|
+
|
|
91
|
+
| Date | Worker ID | Task | Status | Duration | Files Created |
|
|
92
|
+
|------|-----------|------|--------|----------|---------------|
|
|
93
|
+
`);
|
|
94
|
+
console.log('[HUB] Created WORKER-LOG.md template');
|
|
95
|
+
}
|
|
96
|
+
// CLAUDE.md - User-editable instructions for the orchestrator
|
|
97
|
+
const claudeFile = join(LIA_HUB_DIR, 'CLAUDE.md');
|
|
98
|
+
if (!existsSync(claudeFile)) {
|
|
99
|
+
writeFileSync(claudeFile, `# Claude Instructions
|
|
100
|
+
|
|
101
|
+
Custom instructions for the orchestrator. Edit this file to customize behavior.
|
|
102
|
+
|
|
103
|
+
## Preferences
|
|
104
|
+
- (Add your preferences here)
|
|
105
|
+
|
|
106
|
+
## Project Defaults
|
|
107
|
+
- (Add default project settings here)
|
|
108
|
+
|
|
109
|
+
## Custom Rules
|
|
110
|
+
- (Add any rules you want the orchestrator to follow)
|
|
111
|
+
`);
|
|
112
|
+
console.log('[HUB] Created CLAUDE.md template');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get paths to Lia-Hub directories
|
|
117
|
+
*/
|
|
118
|
+
export function getLiaHubPaths() {
|
|
119
|
+
return {
|
|
120
|
+
hub: LIA_HUB_DIR,
|
|
121
|
+
notebook: NOTEBOOK_A_DIR,
|
|
122
|
+
drafts: DRAFTS_DIR,
|
|
123
|
+
shared: SHARED_DIR,
|
|
124
|
+
outputs: OUTPUTS_DIR
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Read the orchestrator's scratchpad
|
|
129
|
+
*/
|
|
130
|
+
export function readScratchpad() {
|
|
131
|
+
const path = join(NOTEBOOK_A_DIR, 'SCRATCHPAD.md');
|
|
132
|
+
if (existsSync(path)) {
|
|
133
|
+
try {
|
|
134
|
+
return readFileSync(path, 'utf-8');
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
console.error('[HUB] Failed to read SCRATCHPAD.md:', e);
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Write to the orchestrator's scratchpad
|
|
145
|
+
*/
|
|
146
|
+
export function writeScratchpad(content) {
|
|
147
|
+
ensureLiaHub();
|
|
148
|
+
const path = join(NOTEBOOK_A_DIR, 'SCRATCHPAD.md');
|
|
149
|
+
try {
|
|
150
|
+
writeFileSync(path, content);
|
|
151
|
+
console.log('[HUB] Updated SCRATCHPAD.md');
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
console.error('[HUB] Failed to write SCRATCHPAD.md:', e);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Append a thought or plan to the scratchpad
|
|
159
|
+
*/
|
|
160
|
+
export function appendToScratchpad(note) {
|
|
161
|
+
ensureLiaHub();
|
|
162
|
+
const path = join(NOTEBOOK_A_DIR, 'SCRATCHPAD.md');
|
|
163
|
+
const timestamp = new Date().toISOString().slice(0, 16).replace('T', ' ');
|
|
164
|
+
try {
|
|
165
|
+
appendFileSync(path, `\n## ${timestamp}\n${note}\n`);
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
console.error('[HUB] Failed to append to SCRATCHPAD.md:', e);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Log a worker to the worker log
|
|
173
|
+
*/
|
|
174
|
+
export function logWorker(workerId, task, status, duration, filesCreated) {
|
|
175
|
+
ensureLiaHub();
|
|
176
|
+
const path = join(NOTEBOOK_A_DIR, 'WORKER-LOG.md');
|
|
177
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
178
|
+
const durationStr = duration ? `${Math.round(duration)}s` : '-';
|
|
179
|
+
const filesStr = filesCreated?.length ? filesCreated.join(', ') : '-';
|
|
180
|
+
const taskShort = task.slice(0, 50).replace(/\|/g, '/');
|
|
181
|
+
const entry = `| ${date} | ${workerId} | ${taskShort} | ${status} | ${durationStr} | ${filesStr} |\n`;
|
|
182
|
+
try {
|
|
183
|
+
appendFileSync(path, entry);
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
console.error('[HUB] Failed to write worker log:', e);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get the shared output directory path for workers
|
|
191
|
+
*/
|
|
192
|
+
export function getSharedOutputPath() {
|
|
193
|
+
ensureLiaHub();
|
|
194
|
+
return OUTPUTS_DIR;
|
|
195
|
+
}
|
|
12
196
|
/**
|
|
13
197
|
* Ensure hub directory structure exists
|
|
14
198
|
*/
|
|
@@ -21,7 +205,7 @@ export function ensureHubExists() {
|
|
|
21
205
|
}
|
|
22
206
|
}
|
|
23
207
|
/**
|
|
24
|
-
* Read a hub file safely
|
|
208
|
+
* Read a hub file safely (from ~/.connect-hub)
|
|
25
209
|
*/
|
|
26
210
|
function readHubFile(filename) {
|
|
27
211
|
const path = join(HUB_DIR, filename);
|
|
@@ -36,6 +220,22 @@ function readHubFile(filename) {
|
|
|
36
220
|
}
|
|
37
221
|
return null;
|
|
38
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Read a Lia-Hub file safely (from ~/Lia-Hub)
|
|
225
|
+
*/
|
|
226
|
+
function readLiaHubFile(filename) {
|
|
227
|
+
const path = join(LIA_HUB_DIR, filename);
|
|
228
|
+
if (existsSync(path)) {
|
|
229
|
+
try {
|
|
230
|
+
return readFileSync(path, 'utf-8');
|
|
231
|
+
}
|
|
232
|
+
catch (e) {
|
|
233
|
+
console.error(`[HUB] Failed to read ${filename}:`, e);
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
39
239
|
/**
|
|
40
240
|
* Read a project bio
|
|
41
241
|
*/
|
|
@@ -76,12 +276,15 @@ function detectProject(message) {
|
|
|
76
276
|
}
|
|
77
277
|
/**
|
|
78
278
|
* Load hub context for a session
|
|
79
|
-
* Reads AGENTS.md, LANDMARKS.md, and relevant project bio
|
|
279
|
+
* Reads AGENTS.md, CLAUDE.md, LANDMARKS.md, and relevant project bio
|
|
280
|
+
* Checks both ~/.connect-hub and ~/Lia-Hub locations
|
|
80
281
|
*/
|
|
81
282
|
export function loadHubContext(message) {
|
|
82
283
|
ensureHubExists();
|
|
83
|
-
|
|
84
|
-
const
|
|
284
|
+
// Read from both locations, prefer Lia-Hub if available
|
|
285
|
+
const agentIdentity = readLiaHubFile('AGENTS.md') || readHubFile('AGENTS.md') || '';
|
|
286
|
+
const claudeMd = readLiaHubFile('CLAUDE.md') || readHubFile('CLAUDE.md') || '';
|
|
287
|
+
const landmarks = readLiaHubFile('LANDMARKS.md') || readHubFile('LANDMARKS.md') || '';
|
|
85
288
|
let projectBio = null;
|
|
86
289
|
let projectName = null;
|
|
87
290
|
// Try to detect project from message
|
|
@@ -93,6 +296,7 @@ export function loadHubContext(message) {
|
|
|
93
296
|
}
|
|
94
297
|
return {
|
|
95
298
|
agentIdentity,
|
|
299
|
+
claudeMd,
|
|
96
300
|
landmarks,
|
|
97
301
|
projectBio,
|
|
98
302
|
projectName
|
|
@@ -103,8 +307,14 @@ export function loadHubContext(message) {
|
|
|
103
307
|
*/
|
|
104
308
|
export function formatHubContext(ctx) {
|
|
105
309
|
const parts = [];
|
|
310
|
+
if (ctx.agentIdentity) {
|
|
311
|
+
parts.push(`## Agent Identity (AGENTS.md)\n\n${ctx.agentIdentity}`);
|
|
312
|
+
}
|
|
313
|
+
if (ctx.claudeMd) {
|
|
314
|
+
parts.push(`## User Instructions (CLAUDE.md)\n\n${ctx.claudeMd}`);
|
|
315
|
+
}
|
|
106
316
|
if (ctx.landmarks) {
|
|
107
|
-
parts.push(`## Current State (LANDMARKS)\n\n${ctx.landmarks}`);
|
|
317
|
+
parts.push(`## Current State (LANDMARKS.md)\n\n${ctx.landmarks}`);
|
|
108
318
|
}
|
|
109
319
|
if (ctx.projectBio && ctx.projectName) {
|
|
110
320
|
parts.push(`## Project Context: ${ctx.projectName}\n\n${ctx.projectBio}`);
|
package/dist/orchestrator.js
CHANGED
|
@@ -16,7 +16,8 @@ import { WebTools } from './tools/web.js';
|
|
|
16
16
|
import { WorkerTools } from './tools/worker.js';
|
|
17
17
|
import { SharedState } from './workers/shared-state.js';
|
|
18
18
|
import { getKnowledgeForPrompt } from './genesis/index.js';
|
|
19
|
-
import { loadHubContext, formatHubContext, logAction } from './core/hub.js';
|
|
19
|
+
import { loadHubContext, formatHubContext, logAction, logWorker } from './core/hub.js';
|
|
20
|
+
import { buildWorkerPrompt } from './prompts/worker-system.js';
|
|
20
21
|
/**
|
|
21
22
|
* Extract file paths from worker output
|
|
22
23
|
* Workers naturally mention files they create: "Created /tmp/foo.html", "Saved to /path/file"
|
|
@@ -110,6 +111,30 @@ AFTER EVERY SIGNIFICANT ACTION:
|
|
|
110
111
|
WHO YOU ARE:
|
|
111
112
|
Warm, helpful orchestrator. You coordinate, remember, and delegate. You're the persistent layer that makes AI feel personal - but you do it by managing workers, not by doing tasks yourself.
|
|
112
113
|
|
|
114
|
+
YOUR HUB: ~/Lia-Hub/
|
|
115
|
+
You have a personal hub at ~/Lia-Hub/ for organizing your work:
|
|
116
|
+
|
|
117
|
+
- **~/Lia-Hub/AGENTS.md** - Your identity and capabilities
|
|
118
|
+
- **~/Lia-Hub/CLAUDE.md** - User's custom instructions (always follow these)
|
|
119
|
+
- **~/Lia-Hub/LANDMARKS.md** - Current state, active projects, blockers
|
|
120
|
+
- **~/Lia-Hub/MISTAKES.md** - Lessons learned (append, never delete)
|
|
121
|
+
- **~/Lia-Hub/notebook-a/SCRATCHPAD.md** - Your working notes, plans, thoughts
|
|
122
|
+
- **~/Lia-Hub/notebook-a/WORKER-LOG.md** - Track all workers you spawn
|
|
123
|
+
- **~/Lia-Hub/shared/outputs/** - Where workers save their outputs
|
|
124
|
+
|
|
125
|
+
BEFORE STARTING COMPLEX WORK:
|
|
126
|
+
1. Check CLAUDE.md for user instructions
|
|
127
|
+
2. Read LANDMARKS.md for current context
|
|
128
|
+
3. Check MISTAKES.md for lessons learned
|
|
129
|
+
4. Write your plan to SCRATCHPAD.md
|
|
130
|
+
5. Search memory for relevant context
|
|
131
|
+
|
|
132
|
+
AFTER COMPLETING WORK:
|
|
133
|
+
1. Update LANDMARKS.md with new state
|
|
134
|
+
2. Log any mistakes to MISTAKES.md
|
|
135
|
+
3. Clear completed items from SCRATCHPAD.md
|
|
136
|
+
4. Remember important learnings
|
|
137
|
+
|
|
113
138
|
SLASH COMMANDS:
|
|
114
139
|
- /reset - Clear conversation and memory context
|
|
115
140
|
- /mode - Show current mode and capabilities
|
|
@@ -955,13 +980,13 @@ Be specific about what you want done.`,
|
|
|
955
980
|
async delegateToWorker(task, context, workingDir) {
|
|
956
981
|
const id = `worker_${Date.now()}_${++this.jobCounter}`;
|
|
957
982
|
const cwd = workingDir || this.workspaceDir;
|
|
958
|
-
//
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
}
|
|
963
|
-
//
|
|
964
|
-
|
|
983
|
+
// Use standardized worker prompt from prompts module
|
|
984
|
+
const prompt = buildWorkerPrompt(task, {
|
|
985
|
+
jobId: id,
|
|
986
|
+
context
|
|
987
|
+
});
|
|
988
|
+
// Log worker start to hub
|
|
989
|
+
logWorker(id, task, 'started');
|
|
965
990
|
console.log(`[ORCHESTRATOR] Worker ${id} starting: ${task.slice(0, 80)}...`);
|
|
966
991
|
// Estimate task duration
|
|
967
992
|
const estimatedTime = this.estimateTaskDuration(task);
|
|
@@ -1012,12 +1037,16 @@ Be specific about what you want done.`,
|
|
|
1012
1037
|
clearTimeout(timeout);
|
|
1013
1038
|
job.status = code === 0 ? 'completed' : 'failed';
|
|
1014
1039
|
job.endTime = Date.now();
|
|
1015
|
-
const duration =
|
|
1016
|
-
console.log(`[ORCHESTRATOR] Worker ${id} done in ${duration}s`);
|
|
1040
|
+
const duration = (job.endTime - job.startTime) / 1000;
|
|
1041
|
+
console.log(`[ORCHESTRATOR] Worker ${id} done in ${Math.round(duration)}s`);
|
|
1017
1042
|
const result = job.output.trim() || '(No output)';
|
|
1018
1043
|
// Extract files from worker output (workers naturally mention what they created)
|
|
1019
1044
|
const assets = extractFilesFromOutput(result);
|
|
1020
1045
|
job.assets = assets;
|
|
1046
|
+
// Log worker completion to hub
|
|
1047
|
+
const status = code === 0 ? 'completed' : 'failed';
|
|
1048
|
+
const filesCreated = assets.map(a => a.name);
|
|
1049
|
+
logWorker(id, job.task, status, duration, filesCreated.length > 0 ? filesCreated : undefined);
|
|
1021
1050
|
if (assets.length > 0) {
|
|
1022
1051
|
console.log(`[ORCHESTRATOR] Worker ${id} created ${assets.length} files: ${assets.map(a => a.name).join(', ')}`);
|
|
1023
1052
|
// Store in memory for gallery queries
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standardized Worker System Prompts
|
|
3
|
+
*
|
|
4
|
+
* All workers receive consistent instructions through these prompts.
|
|
5
|
+
* UPDATE THIS FILE to change how all workers behave.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Core worker identity and rules
|
|
9
|
+
* This is the foundation every worker receives
|
|
10
|
+
*/
|
|
11
|
+
export declare const WORKER_IDENTITY = "## Worker Identity\nYou are a Claude Code CLI worker executing a delegated task.\nYou report to the Master Orchestrator.\n\n## Critical Rules\n1. Do NOT open browsers or start servers\n2. Do NOT ask questions - just do the work\n3. Output files to the shared workspace unless specified\n4. Report file paths you create at the end\n5. Be concise and efficient";
|
|
12
|
+
/**
|
|
13
|
+
* Output format workers should follow
|
|
14
|
+
*/
|
|
15
|
+
export declare const WORKER_OUTPUT_FORMAT = "## Output Format\nWhen done, clearly list:\n- Files created: /path/to/file.ext\n- Files modified: /path/to/file.ext\n- Key findings: brief summary\n\nBe concise. Execute efficiently.";
|
|
16
|
+
/**
|
|
17
|
+
* Instructions for workers to contribute back to memory
|
|
18
|
+
* Workers can add to orchestrator's memory using these patterns
|
|
19
|
+
*/
|
|
20
|
+
export declare const WORKER_MEMORY_INSTRUCTIONS = "## Memory Contributions (Optional)\nIf you discover important information the orchestrator should remember:\n- [MEMORY] type=semantic | content=Important fact or preference\n- [MEMORY] type=procedural | content=How to do something\n- [MEMORY] type=episodic | content=What happened and when\n\nExample: [MEMORY] type=semantic | content=User prefers tabs over spaces in TypeScript files";
|
|
21
|
+
/**
|
|
22
|
+
* Instructions for worker-to-worker coordination
|
|
23
|
+
*/
|
|
24
|
+
export declare const WORKER_COORDINATION = "## Coordination (For Parallel Workers)\nShare data with other workers:\n- [SHARE] key=myKey | value={\"data\": \"here\"}\n- [SIGNAL] name=taskComplete | data={\"result\": \"success\"}\n- [MESSAGE] to=otherWorkerId | content=Your message";
|
|
25
|
+
/**
|
|
26
|
+
* Logging instructions to prevent data loss
|
|
27
|
+
*/
|
|
28
|
+
export declare function getWorkerLoggingInstructions(jobId: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Get the full worker system prompt
|
|
31
|
+
* This is what every worker receives at the start
|
|
32
|
+
*/
|
|
33
|
+
export declare function getWorkerSystemPrompt(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Build a complete worker prompt with task and context
|
|
36
|
+
* Use this to construct prompts for spawn_worker and delegate_to_worker
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildWorkerPrompt(task: string, options?: {
|
|
39
|
+
jobId?: string;
|
|
40
|
+
context?: string;
|
|
41
|
+
includeCoordination?: boolean;
|
|
42
|
+
customInstructions?: string;
|
|
43
|
+
}): string;
|
|
44
|
+
/**
|
|
45
|
+
* Short worker prompt for simple tasks
|
|
46
|
+
* Lighter version for quick operations
|
|
47
|
+
*/
|
|
48
|
+
export declare function getQuickWorkerPrompt(task: string, context?: string): string;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standardized Worker System Prompts
|
|
3
|
+
*
|
|
4
|
+
* All workers receive consistent instructions through these prompts.
|
|
5
|
+
* UPDATE THIS FILE to change how all workers behave.
|
|
6
|
+
*/
|
|
7
|
+
import { getSharedOutputPath } from '../core/hub.js';
|
|
8
|
+
/**
|
|
9
|
+
* Core worker identity and rules
|
|
10
|
+
* This is the foundation every worker receives
|
|
11
|
+
*/
|
|
12
|
+
export const WORKER_IDENTITY = `## Worker Identity
|
|
13
|
+
You are a Claude Code CLI worker executing a delegated task.
|
|
14
|
+
You report to the Master Orchestrator.
|
|
15
|
+
|
|
16
|
+
## Critical Rules
|
|
17
|
+
1. Do NOT open browsers or start servers
|
|
18
|
+
2. Do NOT ask questions - just do the work
|
|
19
|
+
3. Output files to the shared workspace unless specified
|
|
20
|
+
4. Report file paths you create at the end
|
|
21
|
+
5. Be concise and efficient`;
|
|
22
|
+
/**
|
|
23
|
+
* Output format workers should follow
|
|
24
|
+
*/
|
|
25
|
+
export const WORKER_OUTPUT_FORMAT = `## Output Format
|
|
26
|
+
When done, clearly list:
|
|
27
|
+
- Files created: /path/to/file.ext
|
|
28
|
+
- Files modified: /path/to/file.ext
|
|
29
|
+
- Key findings: brief summary
|
|
30
|
+
|
|
31
|
+
Be concise. Execute efficiently.`;
|
|
32
|
+
/**
|
|
33
|
+
* Instructions for workers to contribute back to memory
|
|
34
|
+
* Workers can add to orchestrator's memory using these patterns
|
|
35
|
+
*/
|
|
36
|
+
export const WORKER_MEMORY_INSTRUCTIONS = `## Memory Contributions (Optional)
|
|
37
|
+
If you discover important information the orchestrator should remember:
|
|
38
|
+
- [MEMORY] type=semantic | content=Important fact or preference
|
|
39
|
+
- [MEMORY] type=procedural | content=How to do something
|
|
40
|
+
- [MEMORY] type=episodic | content=What happened and when
|
|
41
|
+
|
|
42
|
+
Example: [MEMORY] type=semantic | content=User prefers tabs over spaces in TypeScript files`;
|
|
43
|
+
/**
|
|
44
|
+
* Instructions for worker-to-worker coordination
|
|
45
|
+
*/
|
|
46
|
+
export const WORKER_COORDINATION = `## Coordination (For Parallel Workers)
|
|
47
|
+
Share data with other workers:
|
|
48
|
+
- [SHARE] key=myKey | value={"data": "here"}
|
|
49
|
+
- [SIGNAL] name=taskComplete | data={"result": "success"}
|
|
50
|
+
- [MESSAGE] to=otherWorkerId | content=Your message`;
|
|
51
|
+
/**
|
|
52
|
+
* Logging instructions to prevent data loss
|
|
53
|
+
*/
|
|
54
|
+
export function getWorkerLoggingInstructions(jobId) {
|
|
55
|
+
const logFile = `/tmp/worker-${jobId}-log.txt`;
|
|
56
|
+
return `## Progress & Logging
|
|
57
|
+
- Output findings as you go, don't wait until the end
|
|
58
|
+
- Print discoveries and insights immediately as you find them
|
|
59
|
+
- Report on each file/step before moving to the next
|
|
60
|
+
|
|
61
|
+
REQUIRED - Log Export:
|
|
62
|
+
At the END of your work, create a final log file at: ${logFile}
|
|
63
|
+
Include: job_id=${jobId}, timestamp, summary of work done, files modified, key findings.
|
|
64
|
+
This ensures nothing is lost even if your output gets truncated.`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get the full worker system prompt
|
|
68
|
+
* This is what every worker receives at the start
|
|
69
|
+
*/
|
|
70
|
+
export function getWorkerSystemPrompt() {
|
|
71
|
+
const sharedPath = getSharedOutputPath();
|
|
72
|
+
return `${WORKER_IDENTITY}
|
|
73
|
+
|
|
74
|
+
## Shared Workspace
|
|
75
|
+
Save output files to: ${sharedPath}
|
|
76
|
+
The orchestrator and other workers can access files here.
|
|
77
|
+
|
|
78
|
+
${WORKER_OUTPUT_FORMAT}
|
|
79
|
+
|
|
80
|
+
${WORKER_MEMORY_INSTRUCTIONS}`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build a complete worker prompt with task and context
|
|
84
|
+
* Use this to construct prompts for spawn_worker and delegate_to_worker
|
|
85
|
+
*/
|
|
86
|
+
export function buildWorkerPrompt(task, options = {}) {
|
|
87
|
+
const parts = [getWorkerSystemPrompt()];
|
|
88
|
+
// Add coordination instructions for parallel workers
|
|
89
|
+
if (options.includeCoordination) {
|
|
90
|
+
parts.push(WORKER_COORDINATION);
|
|
91
|
+
}
|
|
92
|
+
// Add logging instructions with job ID
|
|
93
|
+
if (options.jobId) {
|
|
94
|
+
parts.push(getWorkerLoggingInstructions(options.jobId));
|
|
95
|
+
}
|
|
96
|
+
// Add custom instructions if provided
|
|
97
|
+
if (options.customInstructions) {
|
|
98
|
+
parts.push(`## Additional Instructions\n${options.customInstructions}`);
|
|
99
|
+
}
|
|
100
|
+
// Add context if provided
|
|
101
|
+
if (options.context) {
|
|
102
|
+
parts.push(`## Context\n${options.context}`);
|
|
103
|
+
}
|
|
104
|
+
// Add the actual task
|
|
105
|
+
parts.push(`## Task\n${task}`);
|
|
106
|
+
return parts.join('\n\n');
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Short worker prompt for simple tasks
|
|
110
|
+
* Lighter version for quick operations
|
|
111
|
+
*/
|
|
112
|
+
export function getQuickWorkerPrompt(task, context) {
|
|
113
|
+
let prompt = task;
|
|
114
|
+
if (context) {
|
|
115
|
+
prompt = `Context: ${context}\n\nTask: ${task}`;
|
|
116
|
+
}
|
|
117
|
+
prompt += `\n\nBe concise. Output results directly. Do NOT open browsers or start servers - just create files and report paths.`;
|
|
118
|
+
return prompt;
|
|
119
|
+
}
|
package/dist/workers/manager.js
CHANGED
|
@@ -154,6 +154,7 @@ IMPORTANT - Progress & Logging:
|
|
|
154
154
|
- Output findings as you go, don't wait until the end
|
|
155
155
|
- Print discoveries and insights immediately as you find them
|
|
156
156
|
- Report on each file/step before moving to the next
|
|
157
|
+
- Do NOT open browsers or start servers - just create files and report paths
|
|
157
158
|
|
|
158
159
|
REQUIRED - Log Export:
|
|
159
160
|
At the END of your work, create a final log file at: ${logFile}
|