@siftd/connect-agent 0.2.44 → 0.2.45

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.
@@ -71,6 +71,8 @@ export declare class MasterOrchestrator {
71
71
  private workspaceDir;
72
72
  private claudePath;
73
73
  private initialized;
74
+ private currentFileScope;
75
+ private forceTeamWorkingDir;
74
76
  private bashTool;
75
77
  private webTools;
76
78
  private workerTools;
@@ -194,6 +196,10 @@ export declare class MasterOrchestrator {
194
196
  private hasExplicitDate;
195
197
  private getToolChoice;
196
198
  private withAttachments;
199
+ private updateFileScope;
200
+ private getTeamFilesDir;
201
+ private getFileScopeOverrides;
202
+ private getFileScopeSystemNote;
197
203
  /**
198
204
  * Check if verbose mode is enabled
199
205
  */
@@ -7,6 +7,7 @@
7
7
  import Anthropic from '@anthropic-ai/sdk';
8
8
  import { spawn, execSync } from 'child_process';
9
9
  import { existsSync, readFileSync } from 'fs';
10
+ import { join } from 'path';
10
11
  import { AdvancedMemoryStore } from './core/memory-advanced.js';
11
12
  import { PostgresMemoryStore, isPostgresConfigured } from './core/memory-postgres.js';
12
13
  import { TaskScheduler } from './core/scheduler.js';
@@ -146,6 +147,7 @@ FILES SCOPES:
146
147
  - "My Files" are private to the user (default /files view)
147
148
  - "Team Files" are shared across the org (use /files team or the Team Files location)
148
149
  - If a user asks to share with the team, store outputs in Team Files and mention that it is shared
150
+ - When a TEAM FILES DIRECTORY note is present, save shared outputs there
149
151
 
150
152
  CALENDAR + TODO (Lia-managed data):
151
153
  - /cal reads ~/Lia-Hub/shared/outputs/.lia/calendar.json
@@ -209,6 +211,8 @@ export class MasterOrchestrator {
209
211
  workspaceDir;
210
212
  claudePath;
211
213
  initialized = false;
214
+ currentFileScope = 'personal';
215
+ forceTeamWorkingDir = false;
212
216
  // New tools from whatsapp-claude
213
217
  bashTool;
214
218
  webTools;
@@ -716,6 +720,50 @@ export class MasterOrchestrator {
716
720
  }
717
721
  return { task: `${task}\n\n${attachmentNote}` };
718
722
  }
723
+ updateFileScope(message) {
724
+ const marker = '📎 Attached files:';
725
+ const base = message.split(marker)[0]?.trim() || message;
726
+ const lowered = base.toLowerCase();
727
+ const mentionsTeam = /\b(team files|shared files|share with team|team folder|team drive|org files|company files)\b/i.test(lowered);
728
+ const mentionsPersonal = /\b(my files|personal files|private files)\b/i.test(lowered);
729
+ let scope = this.instanceMode === 'team' ? 'team' : 'personal';
730
+ if (mentionsTeam)
731
+ scope = 'team';
732
+ if (mentionsPersonal)
733
+ scope = 'personal';
734
+ this.currentFileScope = scope;
735
+ this.forceTeamWorkingDir = mentionsTeam;
736
+ }
737
+ getTeamFilesDir() {
738
+ if (!this.orgId)
739
+ return null;
740
+ const envDir = process.env.LIA_TEAM_FILES_DIR || process.env.CONNECT_TEAM_FILES_DIR;
741
+ if (envDir && envDir.trim())
742
+ return envDir.trim();
743
+ const dataDir = process.env.DATA_DIR || '/data';
744
+ if (!existsSync(dataDir))
745
+ return null;
746
+ return join(dataDir, 'orgs', this.orgId, 'shared');
747
+ }
748
+ getFileScopeOverrides() {
749
+ if (this.currentFileScope !== 'team')
750
+ return {};
751
+ const teamDir = this.getTeamFilesDir();
752
+ if (!teamDir)
753
+ return {};
754
+ return {
755
+ workingDir: this.forceTeamWorkingDir ? teamDir : undefined,
756
+ instructions: `TEAM FILES DIRECTORY: ${teamDir}\nSave any requested files under this directory so they appear in /files (Team Files). Create the directory if needed.`,
757
+ };
758
+ }
759
+ getFileScopeSystemNote() {
760
+ if (this.currentFileScope !== 'team')
761
+ return null;
762
+ const teamDir = this.getTeamFilesDir();
763
+ if (!teamDir)
764
+ return null;
765
+ return `TEAM FILES DIRECTORY:\n- ${teamDir}\nUse this path for files meant to be shared with the team.`;
766
+ }
719
767
  /**
720
768
  * Check if verbose mode is enabled
721
769
  */
@@ -731,6 +779,7 @@ export class MasterOrchestrator {
731
779
  if (slashResponse) {
732
780
  return slashResponse;
733
781
  }
782
+ this.updateFileScope(message);
734
783
  // DISABLED: Dumb regex extraction was creating garbage todos
735
784
  // Let the AI use calendar_upsert_events and todo_upsert_items tools properly
736
785
  // const quickWrite = this.tryHandleCalendarTodo(message);
@@ -768,6 +817,10 @@ ${hubContextStr}
768
817
  if (memoryContext) {
769
818
  systemWithContext += `\n\nRELEVANT MEMORIES:\n${memoryContext}`;
770
819
  }
820
+ const fileScopeNote = this.getFileScopeSystemNote();
821
+ if (fileScopeNote) {
822
+ systemWithContext += `\n\n${fileScopeNote}`;
823
+ }
771
824
  // Add user message
772
825
  const messages = [
773
826
  ...conversationHistory,
@@ -1406,6 +1459,10 @@ and preserve explicit due dates and priority from the user.`,
1406
1459
  type: 'string',
1407
1460
  enum: ['low', 'normal', 'high', 'critical'],
1408
1461
  description: 'Task priority'
1462
+ },
1463
+ working_directory: {
1464
+ type: 'string',
1465
+ description: 'Directory to work in (defaults to user home)'
1409
1466
  }
1410
1467
  },
1411
1468
  required: ['task']
@@ -1852,9 +1909,12 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
1852
1909
  // Worker tools
1853
1910
  case 'spawn_worker': {
1854
1911
  const { task } = this.withAttachments(input.task);
1855
- result = await this.workerTools.spawnWorker(task, {
1912
+ const fileScope = this.getFileScopeOverrides();
1913
+ const scopedTask = fileScope.instructions ? `${fileScope.instructions}\n\n${task}` : task;
1914
+ result = await this.workerTools.spawnWorker(scopedTask, {
1856
1915
  timeout: input.timeout,
1857
- priority: input.priority
1916
+ priority: input.priority,
1917
+ workingDirectory: input.working_directory || fileScope.workingDir
1858
1918
  });
1859
1919
  break;
1860
1920
  }
@@ -1873,7 +1933,8 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
1873
1933
  // Legacy delegate tool
1874
1934
  case 'delegate_to_worker': {
1875
1935
  const { task, context } = this.withAttachments(input.task, input.context);
1876
- result = await this.delegateToWorker(task, context, input.working_directory);
1936
+ const fileScope = this.getFileScopeOverrides();
1937
+ result = await this.delegateToWorker(task, context, input.working_directory || fileScope.workingDir, fileScope.instructions);
1877
1938
  break;
1878
1939
  }
1879
1940
  case 'remember':
@@ -2004,13 +2065,14 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
2004
2065
  * Delegate task to Claude Code CLI worker - NON-BLOCKING
2005
2066
  * Returns immediately, sends results via callback when done
2006
2067
  */
2007
- async delegateToWorker(task, context, workingDir) {
2068
+ async delegateToWorker(task, context, workingDir, customInstructions) {
2008
2069
  const id = `worker_${Date.now()}_${++this.jobCounter}`;
2009
2070
  const cwd = workingDir || this.workspaceDir;
2010
2071
  // Use standardized worker prompt from prompts module
2011
2072
  const prompt = buildWorkerPrompt(task, {
2012
2073
  jobId: id,
2013
- context
2074
+ context,
2075
+ customInstructions
2014
2076
  });
2015
2077
  // Log worker start to hub
2016
2078
  logWorker(id, task, 'started');
@@ -27,6 +27,7 @@ export declare class WorkerTools {
27
27
  spawnWorker(task: string, options?: {
28
28
  timeout?: number;
29
29
  priority?: 'low' | 'normal' | 'high' | 'critical';
30
+ workingDirectory?: string;
30
31
  }): Promise<ToolResult>;
31
32
  /**
32
33
  * Check worker status
@@ -33,7 +33,8 @@ export class WorkerTools {
33
33
  try {
34
34
  const jobId = await this.manager.spawn(task, {
35
35
  timeout: options?.timeout,
36
- priority: options?.priority
36
+ priority: options?.priority,
37
+ workspace: options?.workingDirectory
37
38
  });
38
39
  const job = this.manager.get(jobId);
39
40
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siftd/connect-agent",
3
- "version": "0.2.44",
3
+ "version": "0.2.45",
4
4
  "description": "Master orchestrator agent - control Claude Code remotely via web",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",