@siftd/connect-agent 0.2.27 → 0.2.29

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/README.md CHANGED
@@ -9,7 +9,9 @@ Connect Agent runs on your machine and bridges the Connect web app to Claude Cod
9
9
  - **Persistent Memory** - Remembers your preferences, projects, and context across sessions
10
10
  - **Worker Delegation** - Delegates complex tasks to Claude Code CLI workers
11
11
  - **Task Scheduling** - Schedule tasks for future execution
12
- - **Semantic Search** - Finds relevant memories by meaning, not just keywords
12
+ - **Hub System** - Organized workspace at `~/Lia-Hub/` for state management
13
+ - **Gallery View** - See all files your workers create in the UI
14
+ - **Progress Tracking** - Real-time progress bars for running workers
13
15
 
14
16
  ## Quick Start
15
17
 
@@ -23,6 +25,12 @@ npx @siftd/connect-agent pair <CODE> --api-key <YOUR_ANTHROPIC_API_KEY>
23
25
  npx @siftd/connect-agent start
24
26
  ```
25
27
 
28
+ On first start, the agent creates `~/Lia-Hub/` with:
29
+ - `AGENTS.md` - Agent identity
30
+ - `CLAUDE.md` - Your custom instructions
31
+ - `LANDMARKS.md` - Current state
32
+ - `notebook-a/` - Working notes and worker logs
33
+
26
34
  ## Modes
27
35
 
28
36
  ### Orchestrator Mode (Recommended)
@@ -31,6 +39,7 @@ When you provide an Anthropic API key, the agent runs as a **master orchestrator
31
39
  - Maintains persistent memory about you and your projects
32
40
  - Delegates file/code work to Claude Code CLI workers
33
41
  - Schedules future tasks
42
+ - Reads hub files for context on every startup
34
43
 
35
44
  ### Simple Relay Mode
36
45
  Without an API key, the agent acts as a simple relay to `claude -p --continue`.
@@ -59,6 +68,24 @@ connect-agent logout
59
68
  - `/reset` or `/clear` - Clear conversation history
60
69
  - `/mode` - Check current mode (orchestrator vs simple)
61
70
  - `/memory` - Show memory statistics
71
+ - `/verbose` - Toggle verbose tool output
72
+
73
+ ## Hub Structure
74
+
75
+ ```
76
+ ~/Lia-Hub/
77
+ ├── AGENTS.md # Agent identity and capabilities
78
+ ├── CLAUDE.md # Your custom instructions (always followed)
79
+ ├── LANDMARKS.md # Current state, active projects
80
+ ├── MISTAKES.md # Lessons learned (never deleted)
81
+ ├── notebook-a/
82
+ │ ├── SCRATCHPAD.md # Working notes and plans
83
+ │ └── WORKER-LOG.md # All worker history (auto-logged)
84
+ └── shared/
85
+ └── outputs/ # Worker output files
86
+ ```
87
+
88
+ Edit `CLAUDE.md` to customize the orchestrator's behavior!
62
89
 
63
90
  ## How It Works
64
91
 
@@ -72,7 +99,7 @@ connect-agent logout
72
99
  ┌─────────────────┐
73
100
  │ Master │
74
101
  │ Orchestrator │
75
- │ (memory, sched)
102
+ │ (memory, hub)
76
103
  └────────┬────────┘
77
104
  │ delegates
78
105
 
@@ -83,17 +110,32 @@ connect-agent logout
83
110
  ```
84
111
 
85
112
  The orchestrator understands it's the **master**, not a worker. It:
86
- 1. Receives your message from the web
87
- 2. Searches memory for relevant context
88
- 3. Decides what needs to be done
89
- 4. Delegates actual work to Claude Code CLI
90
- 5. Synthesizes results into a clear response
91
- 6. Remembers important things for next time
113
+ 1. Loads hub context (AGENTS.md, CLAUDE.md, LANDMARKS.md)
114
+ 2. Receives your message from the web
115
+ 3. Searches memory for relevant context
116
+ 4. Decides what needs to be done
117
+ 5. Delegates actual work to Claude Code CLI workers
118
+ 6. Shows progress in real-time
119
+ 7. Synthesizes results into a clear response
120
+ 8. Logs workers to WORKER-LOG.md
121
+ 9. Remembers important things for next time
122
+
123
+ ## Customizing Worker Behavior
124
+
125
+ All worker prompts are defined in `src/prompts/worker-system.ts`. Update this file to change how ALL workers behave:
126
+
127
+ ```typescript
128
+ // src/prompts/worker-system.ts
129
+ export const WORKER_IDENTITY = `...`;
130
+ export const WORKER_OUTPUT_FORMAT = `...`;
131
+ export function buildWorkerPrompt(task, options) { ... }
132
+ ```
92
133
 
93
134
  ## Environment Variables
94
135
 
95
136
  - `ANTHROPIC_API_KEY` - Alternative to `--api-key` flag
96
137
  - `VOYAGE_API_KEY` - (Optional) For better semantic search embeddings
138
+ - `DATABASE_URL` - (Optional) PostgreSQL for cloud memory persistence
97
139
 
98
140
  ## Requirements
99
141
 
@@ -101,6 +143,13 @@ The orchestrator understands it's the **master**, not a worker. It:
101
143
  - [Claude Code CLI](https://claude.ai/code) installed and authenticated
102
144
  - Anthropic API key (for orchestrator mode)
103
145
 
146
+ ## Version History
147
+
148
+ - **v0.2.28** - Lia-Hub structure, CLAUDE.md support, standardized worker prompts
149
+ - **v0.2.27** - Fixed workers opening browser tabs
150
+ - **v0.2.26** - Gallery view, worker asset tracking
151
+ - **v0.2.25** - Progress bars, heartbeat system
152
+
104
153
  ## License
105
154
 
106
155
  MIT
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
@@ -438,11 +463,26 @@ export class MasterOrchestrator {
438
463
  const memoryContext = await this.getMemoryContext(message);
439
464
  // Build system prompt with hub context, genesis knowledge, and memory context
440
465
  const genesisKnowledge = getKnowledgeForPrompt();
441
- let systemWithContext = SYSTEM_PROMPT + genesisKnowledge;
442
- // Add hub context (landmarks + project bio)
466
+ let systemWithContext = SYSTEM_PROMPT;
467
+ // CRITICAL: Inject hub context IMMEDIATELY after system prompt
468
+ // This ensures the orchestrator sees AGENTS.md, CLAUDE.md, LANDMARKS.md content
443
469
  if (hubContextStr) {
444
- systemWithContext += `\n\n---\n\nHUB CONTEXT:\n${hubContextStr}`;
470
+ systemWithContext += `
471
+
472
+ ═══════════════════════════════════════════════════════════════════════════════
473
+ YOUR HUB FILES (READ THESE FIRST!)
474
+ ═══════════════════════════════════════════════════════════════════════════════
475
+
476
+ The following are the CURRENT CONTENTS of your hub files at ~/Lia-Hub/.
477
+ ALWAYS check these before responding - especially CLAUDE.md for user instructions.
478
+
479
+ ${hubContextStr}
480
+
481
+ ═══════════════════════════════════════════════════════════════════════════════
482
+ `;
445
483
  }
484
+ // Add genesis knowledge and memory context
485
+ systemWithContext += genesisKnowledge;
446
486
  if (memoryContext) {
447
487
  systemWithContext += `\n\nRELEVANT MEMORIES:\n${memoryContext}`;
448
488
  }
@@ -955,13 +995,13 @@ Be specific about what you want done.`,
955
995
  async delegateToWorker(task, context, workingDir) {
956
996
  const id = `worker_${Date.now()}_${++this.jobCounter}`;
957
997
  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.`;
998
+ // Use standardized worker prompt from prompts module
999
+ const prompt = buildWorkerPrompt(task, {
1000
+ jobId: id,
1001
+ context
1002
+ });
1003
+ // Log worker start to hub
1004
+ logWorker(id, task, 'started');
965
1005
  console.log(`[ORCHESTRATOR] Worker ${id} starting: ${task.slice(0, 80)}...`);
966
1006
  // Estimate task duration
967
1007
  const estimatedTime = this.estimateTaskDuration(task);
@@ -1012,12 +1052,16 @@ Be specific about what you want done.`,
1012
1052
  clearTimeout(timeout);
1013
1053
  job.status = code === 0 ? 'completed' : 'failed';
1014
1054
  job.endTime = Date.now();
1015
- const duration = Math.round((job.endTime - job.startTime) / 1000);
1016
- console.log(`[ORCHESTRATOR] Worker ${id} done in ${duration}s`);
1055
+ const duration = (job.endTime - job.startTime) / 1000;
1056
+ console.log(`[ORCHESTRATOR] Worker ${id} done in ${Math.round(duration)}s`);
1017
1057
  const result = job.output.trim() || '(No output)';
1018
1058
  // Extract files from worker output (workers naturally mention what they created)
1019
1059
  const assets = extractFilesFromOutput(result);
1020
1060
  job.assets = assets;
1061
+ // Log worker completion to hub
1062
+ const status = code === 0 ? 'completed' : 'failed';
1063
+ const filesCreated = assets.map(a => a.name);
1064
+ logWorker(id, job.task, status, duration, filesCreated.length > 0 ? filesCreated : undefined);
1021
1065
  if (assets.length > 0) {
1022
1066
  console.log(`[ORCHESTRATOR] Worker ${id} created ${assets.length} files: ${assets.map(a => a.name).join(', ')}`);
1023
1067
  // 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.29",
4
4
  "description": "Master orchestrator agent - control Claude Code remotely via web",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",