@workermill/agent 0.7.6 → 0.7.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/ai-sdk-generate.d.ts +33 -0
- package/dist/ai-sdk-generate.js +160 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/planner.js +71 -12
- package/dist/spawner.js +3 -3
- package/package.json +7 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI SDK Text Generation with Tool Support
|
|
3
|
+
*
|
|
4
|
+
* Wraps the Vercel AI SDK to provide tool-enabled text generation for
|
|
5
|
+
* non-Anthropic providers (OpenAI, Google, Ollama). Anthropic planning
|
|
6
|
+
* still uses Claude CLI for tool access (battle-tested, OAuth auth).
|
|
7
|
+
*
|
|
8
|
+
* Tools: glob (file search), read_file (file reading), grep (content search).
|
|
9
|
+
* These match the tools Claude CLI exposes to analysts.
|
|
10
|
+
*/
|
|
11
|
+
import type { AIProvider } from "./providers.js";
|
|
12
|
+
export interface GenerateWithToolsOptions {
|
|
13
|
+
provider: AIProvider;
|
|
14
|
+
model: string;
|
|
15
|
+
apiKey: string;
|
|
16
|
+
prompt: string;
|
|
17
|
+
systemPrompt?: string;
|
|
18
|
+
workingDir?: string;
|
|
19
|
+
maxTokens?: number;
|
|
20
|
+
temperature?: number;
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
maxSteps?: number;
|
|
23
|
+
/** Enable tool use (glob, read_file, grep). Default: true */
|
|
24
|
+
enableTools?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Generate text using the Vercel AI SDK with optional tool support.
|
|
28
|
+
*
|
|
29
|
+
* For providers that support tool calling (OpenAI, Google, Anthropic),
|
|
30
|
+
* the model can use glob/read_file/grep to explore a cloned repo.
|
|
31
|
+
* maxSteps controls how many tool call rounds are allowed.
|
|
32
|
+
*/
|
|
33
|
+
export declare function generateTextWithTools(options: GenerateWithToolsOptions): Promise<string>;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI SDK Text Generation with Tool Support
|
|
3
|
+
*
|
|
4
|
+
* Wraps the Vercel AI SDK to provide tool-enabled text generation for
|
|
5
|
+
* non-Anthropic providers (OpenAI, Google, Ollama). Anthropic planning
|
|
6
|
+
* still uses Claude CLI for tool access (battle-tested, OAuth auth).
|
|
7
|
+
*
|
|
8
|
+
* Tools: glob (file search), read_file (file reading), grep (content search).
|
|
9
|
+
* These match the tools Claude CLI exposes to analysts.
|
|
10
|
+
*/
|
|
11
|
+
import { generateText as aiGenerateText, tool, stepCountIs } from "ai";
|
|
12
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
13
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
14
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
import { execSync } from "child_process";
|
|
17
|
+
import { readFileSync, existsSync } from "fs";
|
|
18
|
+
/**
|
|
19
|
+
* Create the AI SDK model instance for a given provider.
|
|
20
|
+
*/
|
|
21
|
+
function createModel(provider, model, apiKey) {
|
|
22
|
+
switch (provider) {
|
|
23
|
+
case "anthropic": {
|
|
24
|
+
const anthropic = createAnthropic({ apiKey });
|
|
25
|
+
return anthropic(model);
|
|
26
|
+
}
|
|
27
|
+
case "openai": {
|
|
28
|
+
const openai = createOpenAI({ apiKey });
|
|
29
|
+
return openai(model);
|
|
30
|
+
}
|
|
31
|
+
case "google": {
|
|
32
|
+
const google = createGoogleGenerativeAI({ apiKey });
|
|
33
|
+
return google(model);
|
|
34
|
+
}
|
|
35
|
+
case "ollama": {
|
|
36
|
+
// Ollama uses OpenAI-compatible API
|
|
37
|
+
const ollama = createOpenAI({
|
|
38
|
+
baseURL: apiKey || "http://localhost:11434/v1",
|
|
39
|
+
apiKey: "ollama", // Ollama doesn't need a real key
|
|
40
|
+
});
|
|
41
|
+
return ollama(model);
|
|
42
|
+
}
|
|
43
|
+
default:
|
|
44
|
+
throw new Error(`Unsupported AI provider: ${provider}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Zod schemas for tool inputs
|
|
48
|
+
const globSchema = z.object({
|
|
49
|
+
pattern: z
|
|
50
|
+
.string()
|
|
51
|
+
.describe("Glob pattern like '**/*.ts', 'src/**/*.js', 'package.json'"),
|
|
52
|
+
});
|
|
53
|
+
const readFileSchema = z.object({
|
|
54
|
+
path: z.string().describe("File path relative to the working directory"),
|
|
55
|
+
limit: z
|
|
56
|
+
.number()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("Max number of lines to read (default: 500)"),
|
|
59
|
+
});
|
|
60
|
+
const grepSchema = z.object({
|
|
61
|
+
pattern: z.string().describe("Search pattern (regex supported)"),
|
|
62
|
+
glob: z
|
|
63
|
+
.string()
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("File glob to filter (e.g. '*.ts', '*.py')"),
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* Build filesystem tools scoped to a working directory.
|
|
69
|
+
* These are the same tools Claude CLI exposes (Glob, Read, Grep).
|
|
70
|
+
*/
|
|
71
|
+
function buildTools(workingDir) {
|
|
72
|
+
return {
|
|
73
|
+
glob: tool({
|
|
74
|
+
description: "Find files matching a glob pattern. Returns file paths relative to the working directory.",
|
|
75
|
+
inputSchema: globSchema,
|
|
76
|
+
execute: async (input) => {
|
|
77
|
+
try {
|
|
78
|
+
// Use find as a cross-platform glob (fast-glob not available)
|
|
79
|
+
const result = execSync(`find . -path './.git' -prune -o -path './node_modules' -prune -o -name '${input.pattern.replace(/\*\*/g, "*")}' -print 2>/dev/null | head -200`, { cwd: workingDir, encoding: "utf-8", timeout: 15000 }).trim();
|
|
80
|
+
if (!result) {
|
|
81
|
+
// Try with a broader approach for ** patterns
|
|
82
|
+
const broader = execSync(`find . -path './.git' -prune -o -path './node_modules' -prune -o -type f -print 2>/dev/null | head -500`, { cwd: workingDir, encoding: "utf-8", timeout: 15000 }).trim();
|
|
83
|
+
return broader || "No files found";
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return "Error running glob search";
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
read_file: tool({
|
|
93
|
+
description: "Read the contents of a file. Returns the file text.",
|
|
94
|
+
inputSchema: readFileSchema,
|
|
95
|
+
execute: async (input) => {
|
|
96
|
+
try {
|
|
97
|
+
const fullPath = `${workingDir}/${input.path}`.replace(/\/\//g, "/");
|
|
98
|
+
if (!existsSync(fullPath)) {
|
|
99
|
+
return `File not found: ${input.path}`;
|
|
100
|
+
}
|
|
101
|
+
const content = readFileSync(fullPath, "utf-8");
|
|
102
|
+
const lines = content.split("\n");
|
|
103
|
+
const maxLines = input.limit || 500;
|
|
104
|
+
if (lines.length > maxLines) {
|
|
105
|
+
return (lines.slice(0, maxLines).join("\n") +
|
|
106
|
+
`\n... (truncated, ${lines.length - maxLines} more lines)`);
|
|
107
|
+
}
|
|
108
|
+
return content;
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
return `Error reading file: ${err instanceof Error ? err.message : String(err)}`;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
}),
|
|
115
|
+
grep: tool({
|
|
116
|
+
description: "Search for a pattern in files. Returns matching lines with file paths and line numbers.",
|
|
117
|
+
inputSchema: grepSchema,
|
|
118
|
+
execute: async (input) => {
|
|
119
|
+
try {
|
|
120
|
+
const includeFlag = input.glob ? `--include='${input.glob}'` : "";
|
|
121
|
+
const result = execSync(`grep -rn ${includeFlag} --exclude-dir=node_modules --exclude-dir=.git '${input.pattern.replace(/'/g, "'\\''")}' . 2>/dev/null | head -100`, { cwd: workingDir, encoding: "utf-8", timeout: 15000 }).trim();
|
|
122
|
+
return result || "No matches found";
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return "No matches found";
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
}),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Generate text using the Vercel AI SDK with optional tool support.
|
|
133
|
+
*
|
|
134
|
+
* For providers that support tool calling (OpenAI, Google, Anthropic),
|
|
135
|
+
* the model can use glob/read_file/grep to explore a cloned repo.
|
|
136
|
+
* maxSteps controls how many tool call rounds are allowed.
|
|
137
|
+
*/
|
|
138
|
+
export async function generateTextWithTools(options) {
|
|
139
|
+
const { provider, model: modelName, apiKey, prompt, systemPrompt, workingDir, maxTokens = 16384, temperature = 0.7, timeoutMs = 600_000, maxSteps = 15, enableTools = true, } = options;
|
|
140
|
+
const sdkModel = createModel(provider, modelName, apiKey);
|
|
141
|
+
const tools = enableTools && workingDir ? buildTools(workingDir) : undefined;
|
|
142
|
+
const abortController = new AbortController();
|
|
143
|
+
const timeout = setTimeout(() => abortController.abort(), timeoutMs);
|
|
144
|
+
try {
|
|
145
|
+
const result = await aiGenerateText({
|
|
146
|
+
model: sdkModel,
|
|
147
|
+
prompt,
|
|
148
|
+
system: systemPrompt,
|
|
149
|
+
maxOutputTokens: maxTokens,
|
|
150
|
+
temperature,
|
|
151
|
+
tools,
|
|
152
|
+
stopWhen: tools ? stepCountIs(maxSteps) : undefined,
|
|
153
|
+
abortSignal: abortController.signal,
|
|
154
|
+
});
|
|
155
|
+
return result.text;
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
clearTimeout(timeout);
|
|
159
|
+
}
|
|
160
|
+
}
|
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -76,7 +76,7 @@ export function loadConfigFromFile() {
|
|
|
76
76
|
gitlabToken: fc.tokens?.gitlab || "",
|
|
77
77
|
workerImage,
|
|
78
78
|
teamPlanningEnabled: fc.teamPlanningEnabled ?? true,
|
|
79
|
-
analystModel: fc.analystModel
|
|
79
|
+
analystModel: fc.analystModel,
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
@@ -122,7 +122,7 @@ export function loadConfig() {
|
|
|
122
122
|
gitlabToken: process.env.GITLAB_TOKEN || "",
|
|
123
123
|
workerImage: process.env.WORKER_IMAGE || "workermill-worker:local",
|
|
124
124
|
teamPlanningEnabled: process.env.TEAM_PLANNING_ENABLED !== "false",
|
|
125
|
-
analystModel: process.env.ANALYST_MODEL
|
|
125
|
+
analystModel: process.env.ANALYST_MODEL,
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
128
|
/**
|
package/dist/planner.js
CHANGED
|
@@ -19,7 +19,7 @@ import { spawn, execSync } from "child_process";
|
|
|
19
19
|
import { findClaudePath } from "./config.js";
|
|
20
20
|
import { api } from "./api.js";
|
|
21
21
|
import { parseExecutionPlan, applyFileCap, applyStoryCap, serializePlan, runCriticValidation, formatCriticFeedback, AUTO_APPROVAL_THRESHOLD, } from "./plan-validator.js";
|
|
22
|
-
import {
|
|
22
|
+
import { generateTextWithTools } from "./ai-sdk-generate.js";
|
|
23
23
|
/** Max Planner-Critic iterations before giving up */
|
|
24
24
|
const MAX_ITERATIONS = 3;
|
|
25
25
|
/** Timestamp prefix */
|
|
@@ -471,6 +471,43 @@ function runAnalyst(name, claudePath, model, prompt, repoPath, env, timeoutMs =
|
|
|
471
471
|
});
|
|
472
472
|
});
|
|
473
473
|
}
|
|
474
|
+
/**
|
|
475
|
+
* Run an analyst agent via Vercel AI SDK with tool access to the cloned repo.
|
|
476
|
+
* Used for non-Anthropic providers (OpenAI, Google, Ollama) that can't use Claude CLI.
|
|
477
|
+
* Returns the analyst's report text, or an empty string on failure.
|
|
478
|
+
*/
|
|
479
|
+
async function runAnalystWithSdk(name, provider, model, apiKey, prompt, repoPath, timeoutMs = 900_000) {
|
|
480
|
+
const label = chalk.blue(`[${name}]`);
|
|
481
|
+
const startMs = Date.now();
|
|
482
|
+
console.log(`${ts()} ${label} Starting via AI SDK (${chalk.dim(`${provider}/${model}`)})...`);
|
|
483
|
+
try {
|
|
484
|
+
const result = await generateTextWithTools({
|
|
485
|
+
provider,
|
|
486
|
+
model,
|
|
487
|
+
apiKey,
|
|
488
|
+
prompt,
|
|
489
|
+
workingDir: repoPath,
|
|
490
|
+
maxTokens: 16384,
|
|
491
|
+
temperature: 0.3,
|
|
492
|
+
timeoutMs,
|
|
493
|
+
maxSteps: 20, // Allow thorough exploration
|
|
494
|
+
enableTools: true,
|
|
495
|
+
});
|
|
496
|
+
const elapsed = Math.round((Date.now() - startMs) / 1000);
|
|
497
|
+
if (result && result.length > 0) {
|
|
498
|
+
console.log(`${ts()} ${label} ${chalk.green("✓ Done")} in ${elapsed}s (${result.length} chars)`);
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
console.log(`${ts()} ${label} ${chalk.yellow("⚠ Empty output")} after ${elapsed}s`);
|
|
502
|
+
return "";
|
|
503
|
+
}
|
|
504
|
+
catch (error) {
|
|
505
|
+
const elapsed = Math.round((Date.now() - startMs) / 1000);
|
|
506
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
507
|
+
console.log(`${ts()} ${label} ${chalk.red(`✗ Failed`)} after ${elapsed}s: ${errMsg.substring(0, 150)}`);
|
|
508
|
+
return "";
|
|
509
|
+
}
|
|
510
|
+
}
|
|
474
511
|
/** Analyst prompt templates */
|
|
475
512
|
const CODEBASE_ANALYST_PROMPT = `You are a codebase analyst. Your job is to explore this repository using tools and report what you find.
|
|
476
513
|
|
|
@@ -546,13 +583,25 @@ Keep your report under 1500 words. Only report facts you verified with tools.`;
|
|
|
546
583
|
* This runs ONCE before the planner-critic loop — analyst prompts don't
|
|
547
584
|
* include critic feedback, so re-running them on iteration 2+ is waste.
|
|
548
585
|
*/
|
|
549
|
-
async function runTeamAnalysis(task, basePrompt, claudePath, model, env, repoPath, taskId, startTime) {
|
|
586
|
+
async function runTeamAnalysis(task, basePrompt, claudePath, model, env, repoPath, taskId, startTime, provider = "anthropic", providerApiKey) {
|
|
550
587
|
const taskLabel = chalk.cyan(taskId.slice(0, 8));
|
|
551
588
|
console.log(`${ts()} ${taskLabel} ${chalk.magenta("◆ Team planning")} — running 3 analysts in parallel...`);
|
|
552
589
|
await postLog(taskId, `${PREFIX} Team planning: running codebase, requirements, and risk analysts in parallel...`);
|
|
553
590
|
await postProgress(taskId, "reading_repo", Math.round((Date.now() - startTime) / 1000), "Running parallel analysis agents...", 0, 0);
|
|
554
591
|
const analysisModel = model;
|
|
555
592
|
const MAX_TEAM_RETRIES = 3;
|
|
593
|
+
const useCliAnalysts = provider === "anthropic";
|
|
594
|
+
// Helper: dispatch analyst to Claude CLI or AI SDK based on provider
|
|
595
|
+
const dispatchAnalyst = (name, prompt) => {
|
|
596
|
+
if (useCliAnalysts) {
|
|
597
|
+
return runAnalyst(name, claudePath, analysisModel, prompt, repoPath, env);
|
|
598
|
+
}
|
|
599
|
+
if (!providerApiKey) {
|
|
600
|
+
console.log(`${ts()} ${taskLabel} ${chalk.yellow("⚠")} No API key for ${provider} analysts, skipping ${name}`);
|
|
601
|
+
return Promise.resolve("");
|
|
602
|
+
}
|
|
603
|
+
return runAnalystWithSdk(name, provider, analysisModel, providerApiKey, prompt, repoPath);
|
|
604
|
+
};
|
|
556
605
|
let codebaseReport = "";
|
|
557
606
|
let requirementsReport = "";
|
|
558
607
|
let riskReport = "";
|
|
@@ -562,9 +611,9 @@ async function runTeamAnalysis(task, basePrompt, claudePath, model, env, repoPat
|
|
|
562
611
|
await postLog(taskId, `${PREFIX} Team analysis retry ${attempt}/${MAX_TEAM_RETRIES}...`);
|
|
563
612
|
}
|
|
564
613
|
const [codebaseResult, requirementsResult, riskResult] = await Promise.allSettled([
|
|
565
|
-
codebaseReport ? Promise.resolve(codebaseReport) :
|
|
566
|
-
requirementsReport ? Promise.resolve(requirementsReport) :
|
|
567
|
-
riskReport ? Promise.resolve(riskReport) :
|
|
614
|
+
codebaseReport ? Promise.resolve(codebaseReport) : dispatchAnalyst("Codebase", CODEBASE_ANALYST_PROMPT),
|
|
615
|
+
requirementsReport ? Promise.resolve(requirementsReport) : dispatchAnalyst("Requirements", makeRequirementsAnalystPrompt(task)),
|
|
616
|
+
riskReport ? Promise.resolve(riskReport) : dispatchAnalyst("Risk", makeRiskAssessorPrompt(task)),
|
|
568
617
|
]);
|
|
569
618
|
if (!codebaseReport && codebaseResult.status === "fulfilled") {
|
|
570
619
|
codebaseReport = codebaseResult.value;
|
|
@@ -630,7 +679,7 @@ export async function planTask(task, config, credentials) {
|
|
|
630
679
|
});
|
|
631
680
|
const { prompt: basePrompt, model, provider: planningProvider, maxStories: apiMaxStories } = promptResponse.data;
|
|
632
681
|
const maxStories = typeof apiMaxStories === "number" ? apiMaxStories : 8;
|
|
633
|
-
const cliModel = model
|
|
682
|
+
const cliModel = model;
|
|
634
683
|
const provider = (planningProvider || "anthropic");
|
|
635
684
|
const isAnthropicPlanning = provider === "anthropic";
|
|
636
685
|
const claudePath = process.env.CLAUDE_CLI_PATH || findClaudePath() || "claude";
|
|
@@ -646,7 +695,7 @@ export async function planTask(task, config, credentials) {
|
|
|
646
695
|
// on iteration 2+ wastes compute (they'd produce the same reports).
|
|
647
696
|
let repoPath = null;
|
|
648
697
|
let enhancedBasePrompt = basePrompt;
|
|
649
|
-
if (
|
|
698
|
+
if (config.teamPlanningEnabled && task.githubRepo) {
|
|
650
699
|
const scmProvider = task.scmProvider || "github";
|
|
651
700
|
const scmToken = scmProvider === "bitbucket"
|
|
652
701
|
? config.bitbucketToken
|
|
@@ -660,9 +709,10 @@ export async function planTask(task, config, credentials) {
|
|
|
660
709
|
console.log(`${ts()} ${taskLabel} ${chalk.yellow("⚠")} No SCM token for ${scmProvider}, skipping team planning`);
|
|
661
710
|
}
|
|
662
711
|
if (repoPath) {
|
|
663
|
-
const analystModel = config.analystModel ||
|
|
664
|
-
|
|
665
|
-
|
|
712
|
+
const analystModel = config.analystModel || cliModel;
|
|
713
|
+
const analystBackend = isAnthropicPlanning ? "Claude CLI" : `${provider} AI SDK`;
|
|
714
|
+
console.log(`${ts()} ${taskLabel} Analysts using model: ${chalk.yellow(analystModel)} via ${chalk.dim(analystBackend)} (planner: ${chalk.yellow(cliModel)})`);
|
|
715
|
+
const analysisResult = await runTeamAnalysis(task, basePrompt, claudePath, analystModel, cleanEnv, repoPath, task.id, startTime, provider, providerApiKey);
|
|
666
716
|
if (analysisResult) {
|
|
667
717
|
enhancedBasePrompt = analysisResult;
|
|
668
718
|
}
|
|
@@ -701,8 +751,17 @@ export async function planTask(task, config, credentials) {
|
|
|
701
751
|
throw new Error(`No API key available for provider "${provider}". Configure it in Settings > Integrations.`);
|
|
702
752
|
}
|
|
703
753
|
const genStart = Math.round((Date.now() - startTime) / 1000);
|
|
704
|
-
await postProgress(task.id, "generating_plan", genStart, "Generating plan via
|
|
705
|
-
|
|
754
|
+
await postProgress(task.id, "generating_plan", genStart, "Generating plan via AI SDK...", 0, 0);
|
|
755
|
+
// Use AI SDK with tool access to cloned repo (if available)
|
|
756
|
+
rawOutput = await generateTextWithTools({
|
|
757
|
+
provider,
|
|
758
|
+
model: cliModel,
|
|
759
|
+
apiKey: providerApiKey,
|
|
760
|
+
prompt: currentPrompt,
|
|
761
|
+
workingDir: repoPath || undefined,
|
|
762
|
+
enableTools: !!repoPath, // Only enable tools if we have a cloned repo
|
|
763
|
+
maxSteps: 10,
|
|
764
|
+
});
|
|
706
765
|
// Post "validating" phase so the dashboard progress bar transitions correctly
|
|
707
766
|
const genEnd = Math.round((Date.now() - startTime) / 1000);
|
|
708
767
|
await postProgress(task.id, "validating", genEnd, "Validating plan...", rawOutput.length, 0);
|
package/dist/spawner.js
CHANGED
|
@@ -182,9 +182,9 @@ export async function spawnWorker(task, config, orgConfig, credentials) {
|
|
|
182
182
|
// Target repository
|
|
183
183
|
TARGET_REPO: task.githubRepo || "",
|
|
184
184
|
GITHUB_REPO: task.githubRepo || "",
|
|
185
|
-
// Worker model
|
|
186
|
-
WORKER_MODEL: task.workerModel || String(orgConfig.defaultWorkerModel || "
|
|
187
|
-
CLAUDE_MODEL: task.
|
|
185
|
+
// Worker model — comes from task or org settings, no hardcoded fallbacks
|
|
186
|
+
WORKER_MODEL: task.workerModel || String(orgConfig.defaultWorkerModel || ""),
|
|
187
|
+
CLAUDE_MODEL: task.workerModel || String(orgConfig.defaultWorkerModel || ""),
|
|
188
188
|
// Jira credentials (from org Secrets Manager via /api/agent/claim)
|
|
189
189
|
JIRA_BASE_URL: credentials?.jiraBaseUrl || "",
|
|
190
190
|
JIRA_EMAIL: credentials?.jiraEmail || "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workermill/agent",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "WorkerMill Remote Agent - Run AI workers locally with your Claude Max subscription",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,11 +20,16 @@
|
|
|
20
20
|
"node": ">=20.0.0"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
+
"@ai-sdk/anthropic": "^3.0.0",
|
|
24
|
+
"@ai-sdk/google": "^3.0.0",
|
|
25
|
+
"@ai-sdk/openai": "^3.0.0",
|
|
26
|
+
"ai": "^6.0.0",
|
|
23
27
|
"axios": "^1.7.0",
|
|
24
28
|
"chalk": "^5.3.0",
|
|
25
29
|
"commander": "^12.0.0",
|
|
26
30
|
"inquirer": "^9.2.0",
|
|
27
|
-
"ora": "^8.0.0"
|
|
31
|
+
"ora": "^8.0.0",
|
|
32
|
+
"zod": "^3.23.0"
|
|
28
33
|
},
|
|
29
34
|
"devDependencies": {
|
|
30
35
|
"@types/inquirer": "^9.0.9",
|