@siftd/connect-agent 0.2.51 → 0.2.52
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/orchestrator.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ export declare class MasterOrchestrator {
|
|
|
49
49
|
private client;
|
|
50
50
|
private model;
|
|
51
51
|
private maxTokens;
|
|
52
|
+
private toolMaxTokens;
|
|
52
53
|
private memory;
|
|
53
54
|
private contextGraph;
|
|
54
55
|
private orgMemory?;
|
|
@@ -202,6 +203,7 @@ export declare class MasterOrchestrator {
|
|
|
202
203
|
private getLocalTimeZone;
|
|
203
204
|
private getTodoCalSystemPrompt;
|
|
204
205
|
private getToolChoice;
|
|
206
|
+
private recordUsage;
|
|
205
207
|
private withAttachments;
|
|
206
208
|
private updateFileScope;
|
|
207
209
|
private getTeamFilesDir;
|
package/dist/orchestrator.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import Anthropic from '@anthropic-ai/sdk';
|
|
8
8
|
import { spawn, execSync } from 'child_process';
|
|
9
|
-
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
9
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, appendFileSync } from 'fs';
|
|
10
10
|
import { join, resolve, dirname, sep } from 'path';
|
|
11
11
|
import { AdvancedMemoryStore } from './core/memory-advanced.js';
|
|
12
12
|
import { PostgresMemoryStore, isPostgresConfigured } from './core/memory-postgres.js';
|
|
@@ -22,6 +22,35 @@ import { getKnowledgeForPrompt } from './genesis/index.js';
|
|
|
22
22
|
import { loadHubContext, formatHubContext, logAction, logWorker, getSharedOutputPath } from './core/hub.js';
|
|
23
23
|
import { buildWorkerPrompt } from './prompts/worker-system.js';
|
|
24
24
|
import { LiaTaskQueue } from './core/task-queue.js';
|
|
25
|
+
const DEFAULT_CLAUDE_MODEL = 'claude-opus-4-5-20251101';
|
|
26
|
+
const DEFAULT_TOOL_MAX_TOKENS = 1024;
|
|
27
|
+
function readBooleanEnv(value, fallback) {
|
|
28
|
+
if (value === undefined)
|
|
29
|
+
return fallback;
|
|
30
|
+
return !['0', 'false', 'no', 'off'].includes(value.trim().toLowerCase());
|
|
31
|
+
}
|
|
32
|
+
function resolveClaudeModel() {
|
|
33
|
+
const raw = (process.env.LIA_MODEL || process.env.ANTHROPIC_MODEL || DEFAULT_CLAUDE_MODEL).trim();
|
|
34
|
+
if (!raw)
|
|
35
|
+
return DEFAULT_CLAUDE_MODEL;
|
|
36
|
+
if (readBooleanEnv(process.env.LIA_FORCE_OPUS, true) && raw !== DEFAULT_CLAUDE_MODEL) {
|
|
37
|
+
return DEFAULT_CLAUDE_MODEL;
|
|
38
|
+
}
|
|
39
|
+
return raw;
|
|
40
|
+
}
|
|
41
|
+
function resolveClaudeBudgetUsd() {
|
|
42
|
+
const raw = process.env.LIA_MAX_BUDGET_USD || process.env.CLAUDE_MAX_BUDGET_USD;
|
|
43
|
+
if (!raw)
|
|
44
|
+
return null;
|
|
45
|
+
const trimmed = raw.trim();
|
|
46
|
+
return trimmed ? trimmed : null;
|
|
47
|
+
}
|
|
48
|
+
function resolveToolMaxTokens() {
|
|
49
|
+
const raw = Number(process.env.LIA_TOOL_MAX_TOKENS);
|
|
50
|
+
if (Number.isFinite(raw) && raw >= 256)
|
|
51
|
+
return Math.min(raw, 4096);
|
|
52
|
+
return DEFAULT_TOOL_MAX_TOKENS;
|
|
53
|
+
}
|
|
25
54
|
/**
|
|
26
55
|
* Extract file paths from worker output
|
|
27
56
|
* Workers naturally mention files they create: "Created /tmp/foo.html", "Saved to /path/file"
|
|
@@ -203,6 +232,7 @@ export class MasterOrchestrator {
|
|
|
203
232
|
client;
|
|
204
233
|
model;
|
|
205
234
|
maxTokens;
|
|
235
|
+
toolMaxTokens;
|
|
206
236
|
memory;
|
|
207
237
|
contextGraph;
|
|
208
238
|
orgMemory;
|
|
@@ -244,8 +274,14 @@ export class MasterOrchestrator {
|
|
|
244
274
|
todoUpdateCallback;
|
|
245
275
|
constructor(options) {
|
|
246
276
|
this.client = new Anthropic({ apiKey: options.apiKey });
|
|
247
|
-
|
|
277
|
+
const requestedModel = options.model?.trim();
|
|
278
|
+
this.model = requestedModel
|
|
279
|
+
? (readBooleanEnv(process.env.LIA_FORCE_OPUS, true) && requestedModel !== DEFAULT_CLAUDE_MODEL
|
|
280
|
+
? DEFAULT_CLAUDE_MODEL
|
|
281
|
+
: requestedModel)
|
|
282
|
+
: resolveClaudeModel();
|
|
248
283
|
this.maxTokens = options.maxTokens || 4096;
|
|
284
|
+
this.toolMaxTokens = resolveToolMaxTokens();
|
|
249
285
|
this.userId = options.userId;
|
|
250
286
|
this.orgId = options.orgId;
|
|
251
287
|
this.orgRole = options.orgRole;
|
|
@@ -698,7 +734,7 @@ export class MasterOrchestrator {
|
|
|
698
734
|
}
|
|
699
735
|
hasCalendarMutation(message) {
|
|
700
736
|
const lower = this.stripTodoSnapshot(message).toLowerCase();
|
|
701
|
-
const target = /(^|\s)\/cal\b|\/calendar\b|\bcalendar\b/.test(lower);
|
|
737
|
+
const target = /(^|\s)\/cal\b|\/calendar\b|\bcalendar\b|\bcal\b/.test(lower);
|
|
702
738
|
const action = /\b(add|create|schedule|book|move|reschedule|update|change|cancel|delete|remove)\b/.test(lower);
|
|
703
739
|
const query = /\b(what|show|list|open|view|see)\b/.test(lower);
|
|
704
740
|
return target && action && !query;
|
|
@@ -789,6 +825,32 @@ export class MasterOrchestrator {
|
|
|
789
825
|
}
|
|
790
826
|
return undefined;
|
|
791
827
|
}
|
|
828
|
+
recordUsage(response, meta) {
|
|
829
|
+
const usage = response.usage;
|
|
830
|
+
if (!usage)
|
|
831
|
+
return;
|
|
832
|
+
try {
|
|
833
|
+
const usageDir = join(getSharedOutputPath(), '.lia');
|
|
834
|
+
mkdirSync(usageDir, { recursive: true });
|
|
835
|
+
const entry = {
|
|
836
|
+
ts: new Date().toISOString(),
|
|
837
|
+
model: this.model,
|
|
838
|
+
input_tokens: usage.input_tokens,
|
|
839
|
+
output_tokens: usage.output_tokens,
|
|
840
|
+
cache_creation_input_tokens: usage.cache_creation_input_tokens,
|
|
841
|
+
cache_read_input_tokens: usage.cache_read_input_tokens,
|
|
842
|
+
tool_choice: meta.toolChoice || null,
|
|
843
|
+
iterations: meta.iterations,
|
|
844
|
+
messages: meta.messages,
|
|
845
|
+
stop_reason: response.stop_reason || null,
|
|
846
|
+
response_id: response.id || null,
|
|
847
|
+
};
|
|
848
|
+
appendFileSync(join(usageDir, 'usage.jsonl'), `${JSON.stringify(entry)}\n`, 'utf8');
|
|
849
|
+
}
|
|
850
|
+
catch (error) {
|
|
851
|
+
console.warn('[ORCHESTRATOR] Usage log failed:', error);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
792
854
|
withAttachments(task, context) {
|
|
793
855
|
if (!this.attachmentContext)
|
|
794
856
|
return { task, context };
|
|
@@ -1385,12 +1447,13 @@ ${hubContextStr}
|
|
|
1385
1447
|
while (iterations < maxIterations) {
|
|
1386
1448
|
iterations++;
|
|
1387
1449
|
const toolChoice = forcedToolChoice ?? this.getToolChoice(currentMessages);
|
|
1450
|
+
const requestMaxTokens = wantsTodoOrCal ? this.toolMaxTokens : this.maxTokens;
|
|
1388
1451
|
const requestStart = Date.now();
|
|
1389
1452
|
console.log(`[ORCHESTRATOR] Anthropic request ${iterations}/${maxIterations} (model: ${this.model})`);
|
|
1390
1453
|
const response = await Promise.race([
|
|
1391
1454
|
this.client.messages.create({
|
|
1392
1455
|
model: this.model,
|
|
1393
|
-
max_tokens:
|
|
1456
|
+
max_tokens: requestMaxTokens,
|
|
1394
1457
|
system,
|
|
1395
1458
|
tools,
|
|
1396
1459
|
messages: currentMessages,
|
|
@@ -1403,6 +1466,11 @@ ${hubContextStr}
|
|
|
1403
1466
|
})
|
|
1404
1467
|
]);
|
|
1405
1468
|
console.log(`[ORCHESTRATOR] Anthropic response ${iterations}/${maxIterations} in ${Date.now() - requestStart}ms`);
|
|
1469
|
+
this.recordUsage(response, {
|
|
1470
|
+
iterations,
|
|
1471
|
+
messages: currentMessages.length,
|
|
1472
|
+
toolChoice: toolChoice?.name
|
|
1473
|
+
});
|
|
1406
1474
|
// Check if done
|
|
1407
1475
|
if (response.stop_reason === 'end_turn' || !this.hasToolUse(response.content)) {
|
|
1408
1476
|
if (forcedToolChoice && !retriedForcedTool) {
|
|
@@ -2347,7 +2415,9 @@ Unlike lia_plan (internal only), this creates a VISIBLE todo list that appears i
|
|
|
2347
2415
|
};
|
|
2348
2416
|
// Escape single quotes in prompt for shell safety
|
|
2349
2417
|
const escapedPrompt = prompt.replace(/'/g, "'\\''");
|
|
2350
|
-
const
|
|
2418
|
+
const budget = resolveClaudeBudgetUsd();
|
|
2419
|
+
const budgetArg = budget ? ` --max-budget-usd ${budget}` : '';
|
|
2420
|
+
const claudeCmd = `${this.claudePath} -p '${escapedPrompt}' --output-format text --dangerously-skip-permissions --model ${this.model}${budgetArg}`;
|
|
2351
2421
|
const isRoot = process.getuid?.() === 0;
|
|
2352
2422
|
const shellCmd = isRoot
|
|
2353
2423
|
? `runuser -u lia -m -- /bin/bash -l -c "${claudeCmd.replace(/"/g, '\\"')}"`
|
|
@@ -12,7 +12,7 @@ export declare const WORKER_IDENTITY = "## Worker Identity\nYou are a Claude Cod
|
|
|
12
12
|
/**
|
|
13
13
|
* Output format workers should follow
|
|
14
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:
|
|
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: 1-3 short bullets\n\nBe concise. Do not restate the task.";
|
|
16
16
|
/**
|
|
17
17
|
* Instructions for workers to contribute back to memory
|
|
18
18
|
* Workers can add to orchestrator's memory using these patterns
|
|
@@ -44,9 +44,9 @@ export const WORKER_OUTPUT_FORMAT = `## Output Format
|
|
|
44
44
|
When done, clearly list:
|
|
45
45
|
- Files created: /path/to/file.ext
|
|
46
46
|
- Files modified: /path/to/file.ext
|
|
47
|
-
- Key findings:
|
|
47
|
+
- Key findings: 1-3 short bullets
|
|
48
48
|
|
|
49
|
-
Be concise.
|
|
49
|
+
Be concise. Do not restate the task.`;
|
|
50
50
|
/**
|
|
51
51
|
* Instructions for workers to contribute back to memory
|
|
52
52
|
* Workers can add to orchestrator's memory using these patterns
|
|
@@ -71,6 +71,15 @@ Share data with other workers:
|
|
|
71
71
|
*/
|
|
72
72
|
export function getWorkerLoggingInstructions(jobId) {
|
|
73
73
|
const logFile = `/tmp/worker-${jobId}-log.txt`;
|
|
74
|
+
const verbose = process.env.LIA_WORKER_VERBOSE === '1';
|
|
75
|
+
if (!verbose) {
|
|
76
|
+
return `## Progress & Logging
|
|
77
|
+
- Keep output minimal; report only key steps and final results
|
|
78
|
+
|
|
79
|
+
REQUIRED - Log Export:
|
|
80
|
+
At the END of your work, create a final log file at: ${logFile}
|
|
81
|
+
Include: job_id=${jobId}, timestamp, summary of work done, files modified, key findings.`;
|
|
82
|
+
}
|
|
74
83
|
return `## Progress & Logging
|
|
75
84
|
- Output findings as you go, don't wait until the end
|
|
76
85
|
- Print discoveries and insights immediately as you find them
|
package/dist/workers/manager.js
CHANGED
|
@@ -48,6 +48,28 @@ function getFileType(ext) {
|
|
|
48
48
|
return 'text';
|
|
49
49
|
return 'other';
|
|
50
50
|
}
|
|
51
|
+
const DEFAULT_CLAUDE_MODEL = 'claude-opus-4-5-20251101';
|
|
52
|
+
function readBooleanEnv(value, fallback) {
|
|
53
|
+
if (value === undefined)
|
|
54
|
+
return fallback;
|
|
55
|
+
return !['0', 'false', 'no', 'off'].includes(value.trim().toLowerCase());
|
|
56
|
+
}
|
|
57
|
+
function resolveClaudeModel() {
|
|
58
|
+
const raw = (process.env.LIA_MODEL || process.env.ANTHROPIC_MODEL || DEFAULT_CLAUDE_MODEL).trim();
|
|
59
|
+
if (!raw)
|
|
60
|
+
return DEFAULT_CLAUDE_MODEL;
|
|
61
|
+
if (readBooleanEnv(process.env.LIA_FORCE_OPUS, true) && raw !== DEFAULT_CLAUDE_MODEL) {
|
|
62
|
+
return DEFAULT_CLAUDE_MODEL;
|
|
63
|
+
}
|
|
64
|
+
return raw;
|
|
65
|
+
}
|
|
66
|
+
function resolveClaudeBudgetUsd() {
|
|
67
|
+
const raw = process.env.LIA_MAX_BUDGET_USD || process.env.CLAUDE_MAX_BUDGET_USD;
|
|
68
|
+
if (!raw)
|
|
69
|
+
return null;
|
|
70
|
+
const trimmed = raw.trim();
|
|
71
|
+
return trimmed ? trimmed : null;
|
|
72
|
+
}
|
|
51
73
|
export class WorkerManager {
|
|
52
74
|
config;
|
|
53
75
|
activeWorkers = new Map();
|
|
@@ -166,22 +188,30 @@ export class WorkerManager {
|
|
|
166
188
|
try {
|
|
167
189
|
// Add checkpoint and logging instructions to prevent data loss
|
|
168
190
|
const logFile = `/tmp/worker-${jobId}-log.txt`;
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
IMPORTANT - Progress & Logging:
|
|
191
|
+
const verbose = process.env.LIA_WORKER_VERBOSE === '1';
|
|
192
|
+
const loggingBlock = verbose
|
|
193
|
+
? `IMPORTANT - Progress & Logging:
|
|
172
194
|
- Output findings as you go, don't wait until the end
|
|
173
195
|
- Print discoveries and insights immediately as you find them
|
|
174
196
|
- Report on each file/step before moving to the next
|
|
175
|
-
- Do NOT open browsers or start servers - just create files and report paths
|
|
197
|
+
- Do NOT open browsers or start servers - just create files and report paths`
|
|
198
|
+
: `IMPORTANT - Progress & Logging:
|
|
199
|
+
- Keep output minimal; report only key steps and final results
|
|
200
|
+
- Do NOT open browsers or start servers - just create files and report paths`;
|
|
201
|
+
const enhancedTask = `${task}
|
|
202
|
+
|
|
203
|
+
${loggingBlock}
|
|
176
204
|
|
|
177
205
|
REQUIRED - Log Export:
|
|
178
206
|
At the END of your work, create a final log file at: ${logFile}
|
|
179
|
-
Include: job_id=${jobId}, timestamp, summary of work done, files modified, key findings
|
|
180
|
-
This ensures nothing is lost even if your output gets truncated.`;
|
|
207
|
+
Include: job_id=${jobId}, timestamp, summary of work done, files modified, key findings.`;
|
|
181
208
|
// Escape single quotes in task for shell safety
|
|
182
209
|
const escapedTask = enhancedTask.replace(/'/g, "'\\''");
|
|
183
210
|
// Build the claude command
|
|
184
|
-
const
|
|
211
|
+
const model = resolveClaudeModel();
|
|
212
|
+
const budget = resolveClaudeBudgetUsd();
|
|
213
|
+
const budgetArg = budget ? ` --max-budget-usd ${budget}` : '';
|
|
214
|
+
const claudeCmd = `claude -p '${escapedTask}' --output-format text --dangerously-skip-permissions --model ${model}${budgetArg}`;
|
|
185
215
|
// If running as root, run workers as 'lia' user to avoid --dangerously-skip-permissions being blocked
|
|
186
216
|
// The Claude CLI blocks this flag for root users as a security measure
|
|
187
217
|
const isRoot = process.getuid?.() === 0;
|