@siftd/connect-agent 0.2.27 → 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 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');
@@ -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
- const agentIdentity = readHubFile('AGENTS.md') || '';
84
- const landmarks = readHubFile('LANDMARKS.md') || '';
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}`);
@@ -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
- // Build simple prompt - no bloat
959
- let prompt = task;
960
- if (context) {
961
- prompt = `Context: ${context}\n\nTask: ${task}`;
962
- }
963
- // Add brief instruction
964
- prompt += `\n\nBe concise. Output results directly. Do NOT open browsers or start servers - just create files and report paths.`;
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 = Math.round((job.endTime - job.startTime) / 1000);
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siftd/connect-agent",
3
- "version": "0.2.27",
3
+ "version": "0.2.28",
4
4
  "description": "Master orchestrator agent - control Claude Code remotely via web",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",