@siftd/connect-agent 0.2.6 → 0.2.8

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/heartbeat.js CHANGED
@@ -10,7 +10,7 @@ import { hostname } from 'os';
10
10
  import { createHash } from 'crypto';
11
11
  import { getServerUrl, getAgentToken, getUserId, isCloudMode } from './config.js';
12
12
  const HEARTBEAT_INTERVAL = 10000; // 10 seconds
13
- const VERSION = '0.2.6'; // Should match package.json
13
+ const VERSION = '0.2.8'; // Should match package.json
14
14
  const state = {
15
15
  intervalId: null,
16
16
  runnerId: null,
@@ -77,6 +77,11 @@ export declare class MasterOrchestrator {
77
77
  * Delegate task to Claude Code CLI worker with retry logic
78
78
  */
79
79
  private delegateToWorker;
80
+ /**
81
+ * Extract memory contributions from worker output
82
+ * Workers can contribute learnings using: [MEMORY] type=X | content=Y
83
+ */
84
+ private extractWorkerMemories;
80
85
  /**
81
86
  * Execute remember tool
82
87
  */
@@ -362,7 +362,7 @@ export class MasterOrchestrator {
362
362
  },
363
363
  timeout: {
364
364
  type: 'number',
365
- description: 'Timeout in milliseconds (default: 300000 / 5 min)'
365
+ description: 'Timeout in milliseconds (default: 600000 / 10 min, max: 3600000 / 60 min)'
366
366
  },
367
367
  priority: {
368
368
  type: 'string',
@@ -690,11 +690,27 @@ Be specific about what you want done.`,
690
690
  const maxRetries = 2;
691
691
  const id = `worker_${Date.now()}_${++this.jobCounter}`;
692
692
  const cwd = workingDir || this.workspaceDir;
693
- // Build prompt for worker with checkpoint instructions
693
+ // Search for relevant memories to inject into worker prompt
694
+ let memoryContext = '';
695
+ try {
696
+ const relevantMemories = await this.memory.search(task, { limit: 5, minImportance: 0.3 });
697
+ if (relevantMemories.length > 0) {
698
+ memoryContext = '\n\nRELEVANT KNOWLEDGE FROM MEMORY:\n' +
699
+ relevantMemories.map(m => `[${m.type}] ${m.content}`).join('\n');
700
+ }
701
+ }
702
+ catch (error) {
703
+ // Memory search failed, continue without it
704
+ console.log('[ORCHESTRATOR] Memory search failed, continuing without context');
705
+ }
706
+ // Build prompt for worker with memory context and checkpoint instructions
694
707
  let prompt = task;
695
708
  if (context) {
696
709
  prompt = `Context: ${context}\n\nTask: ${task}`;
697
710
  }
711
+ if (memoryContext) {
712
+ prompt += memoryContext;
713
+ }
698
714
  // Add checkpoint and logging instructions to prevent data loss
699
715
  const logFile = `/tmp/worker-${id}-log.txt`;
700
716
  prompt += `
@@ -707,7 +723,14 @@ IMPORTANT - Progress & Logging:
707
723
  REQUIRED - Log Export:
708
724
  At the END of your work, create a final log file at: ${logFile}
709
725
  Include: job_id=${id}, timestamp, summary of work done, files modified, key findings.
710
- This ensures nothing is lost even if your output gets truncated.`;
726
+ This ensures nothing is lost even if your output gets truncated.
727
+
728
+ LEARNING EXPORT (optional but valuable):
729
+ If you discover something important (patterns, user preferences, technical insights),
730
+ end your response with a line like:
731
+ [MEMORY] type=semantic | content=User prefers X over Y for this type of task
732
+ [MEMORY] type=procedural | content=When doing X, always check Y first
733
+ This helps me remember and improve for future tasks.`;
711
734
  console.log(`[ORCHESTRATOR] Delegating to worker ${id}: ${task.slice(0, 80)}...`);
712
735
  return new Promise((resolve) => {
713
736
  const job = {
@@ -729,7 +752,8 @@ This ensures nothing is lost even if your output gets truncated.`;
729
752
  });
730
753
  job.process = child;
731
754
  this.jobs.set(id, job);
732
- // Timeout after 5 minutes
755
+ // Timeout after 10 minutes (increased from 5 for complex tasks)
756
+ const WORKER_TIMEOUT = 10 * 60 * 1000;
733
757
  const timeout = setTimeout(() => {
734
758
  if (job.status === 'running') {
735
759
  job.status = 'timeout';
@@ -746,11 +770,11 @@ This ensures nothing is lost even if your output gets truncated.`;
746
770
  resolve({
747
771
  success: false,
748
772
  output: partialOutput
749
- ? `Worker timed out after 5 minutes. Partial findings:\n${partialOutput.slice(-2000)}`
750
- : 'Worker timed out after 5 minutes with no output. The task may be too complex - try breaking it into smaller steps.'
773
+ ? `Worker timed out after 10 minutes. Partial findings:\n${partialOutput.slice(-2000)}`
774
+ : 'Worker timed out after 10 minutes with no output. The task may be too complex - try breaking it into smaller steps.'
751
775
  });
752
776
  }
753
- }, 5 * 60 * 1000);
777
+ }, WORKER_TIMEOUT);
754
778
  child.stdout?.on('data', (data) => {
755
779
  job.output += data.toString();
756
780
  });
@@ -761,7 +785,7 @@ This ensures nothing is lost even if your output gets truncated.`;
761
785
  job.output += text;
762
786
  }
763
787
  });
764
- child.on('close', (code) => {
788
+ child.on('close', async (code) => {
765
789
  clearTimeout(timeout);
766
790
  job.status = code === 0 ? 'completed' : 'failed';
767
791
  job.endTime = Date.now();
@@ -770,6 +794,8 @@ This ensures nothing is lost even if your output gets truncated.`;
770
794
  if (code !== 0 || job.output.length === 0) {
771
795
  console.log(`[ORCHESTRATOR] Worker ${id} output: ${job.output.slice(0, 200) || '(empty)'}`);
772
796
  }
797
+ // Extract and store memory contributions from worker output
798
+ await this.extractWorkerMemories(job.output, id);
773
799
  resolve({
774
800
  success: code === 0,
775
801
  output: job.output.trim() || '(No output)'
@@ -795,6 +821,40 @@ This ensures nothing is lost even if your output gets truncated.`;
795
821
  });
796
822
  });
797
823
  }
824
+ /**
825
+ * Extract memory contributions from worker output
826
+ * Workers can contribute learnings using: [MEMORY] type=X | content=Y
827
+ */
828
+ async extractWorkerMemories(output, workerId) {
829
+ // Match lines like: [MEMORY] type=semantic | content=User prefers X
830
+ const memoryPattern = /\[MEMORY\]\s*type=(\w+)\s*\|\s*content=(.+?)(?=\n|$)/g;
831
+ let match;
832
+ let count = 0;
833
+ while ((match = memoryPattern.exec(output)) !== null) {
834
+ const type = match[1].toLowerCase();
835
+ const content = match[2].trim();
836
+ if (!content)
837
+ continue;
838
+ // Validate memory type
839
+ const validTypes = ['episodic', 'semantic', 'procedural'];
840
+ const memType = validTypes.includes(type) ? type : 'semantic';
841
+ try {
842
+ await this.memory.remember(content, {
843
+ type: memType,
844
+ source: `worker:${workerId}`,
845
+ importance: 0.7, // Worker-contributed memories are valuable
846
+ tags: ['worker-contributed', 'auto-learned']
847
+ });
848
+ count++;
849
+ }
850
+ catch (error) {
851
+ console.log(`[ORCHESTRATOR] Failed to store worker memory: ${error}`);
852
+ }
853
+ }
854
+ if (count > 0) {
855
+ console.log(`[ORCHESTRATOR] Extracted ${count} memory contributions from worker ${workerId}`);
856
+ }
857
+ }
798
858
  /**
799
859
  * Execute remember tool
800
860
  */
@@ -2,9 +2,9 @@
2
2
  * Worker System Types
3
3
  */
4
4
  export const DEFAULT_WORKER_CONFIG = {
5
- maxParallel: 3,
6
- defaultTimeout: 300000, // 5 minutes
7
- maxTimeout: 1800000, // 30 minutes
8
- jobRetention: 3600000, // 1 hour
5
+ maxParallel: 20, // Increased from 3 for real orchestration
6
+ defaultTimeout: 600000, // 10 minutes (was 5)
7
+ maxTimeout: 3600000, // 60 minutes (was 30)
8
+ jobRetention: 86400000, // 24 hours (was 1 hour)
9
9
  jobsDir: '' // Set at runtime
10
10
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siftd/connect-agent",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Master orchestrator agent - control Claude Code remotely via web",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",