@workermill/agent 0.1.0 β 0.1.2
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/planner.js +21 -13
- package/dist/poller.js +3 -1
- package/dist/spawner.d.ts +16 -1
- package/dist/spawner.js +20 -1
- package/package.json +1 -1
package/dist/planner.js
CHANGED
|
@@ -51,14 +51,22 @@ async function postProgress(taskId, phase, elapsedSeconds, detail, charsGenerate
|
|
|
51
51
|
// Fire and forget
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
/** Consistent prefix matching local workermill dashboard format */
|
|
55
|
+
const PREFIX = "[πΊοΈ planning_agent π€]";
|
|
56
|
+
/** Format elapsed seconds as human-readable string (e.g. "28s", "1m 25s") */
|
|
57
|
+
function formatElapsed(seconds) {
|
|
58
|
+
const mins = Math.floor(seconds / 60);
|
|
59
|
+
const secs = seconds % 60;
|
|
60
|
+
return mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
|
|
61
|
+
}
|
|
54
62
|
function phaseLabel(phase, elapsed) {
|
|
55
63
|
switch (phase) {
|
|
56
|
-
case "initializing": return
|
|
57
|
-
case "reading_repo": return
|
|
58
|
-
case "analyzing": return
|
|
59
|
-
case "generating_plan": return
|
|
60
|
-
case "validating": return
|
|
61
|
-
case "complete": return
|
|
64
|
+
case "initializing": return `${PREFIX} Starting planning agent...`;
|
|
65
|
+
case "reading_repo": return `${PREFIX} Reading repository structure...`;
|
|
66
|
+
case "analyzing": return `${PREFIX} Analyzing requirements...`;
|
|
67
|
+
case "generating_plan": return `${PREFIX} Planning in progress β analyzing requirements and decomposing into steps (${formatElapsed(elapsed)} elapsed)`;
|
|
68
|
+
case "validating": return `${PREFIX} Validating plan...`;
|
|
69
|
+
case "complete": return `${PREFIX} Planning complete`;
|
|
62
70
|
}
|
|
63
71
|
}
|
|
64
72
|
/**
|
|
@@ -119,7 +127,7 @@ function runClaudeCli(claudePath, model, prompt, env, taskId, startTime) {
|
|
|
119
127
|
// Periodic progress during generation
|
|
120
128
|
if (currentPhase === "generating_plan" && elapsed - lastProgressLogAt >= 30) {
|
|
121
129
|
lastProgressLogAt = elapsed;
|
|
122
|
-
const msg =
|
|
130
|
+
const msg = `${PREFIX} Planning in progress β analyzing requirements and decomposing into steps (${formatElapsed(elapsed)} elapsed)`;
|
|
123
131
|
postLog(taskId, msg);
|
|
124
132
|
console.log(`${ts()} ${taskLabel} ${chalk.dim(msg)}`);
|
|
125
133
|
}
|
|
@@ -217,7 +225,7 @@ function runClaudeCli(claudePath, model, prompt, env, taskId, startTime) {
|
|
|
217
225
|
export async function planTask(task, config) {
|
|
218
226
|
const taskLabel = chalk.cyan(task.id.slice(0, 8));
|
|
219
227
|
console.log(`${ts()} ${taskLabel} Fetching planning prompt...`);
|
|
220
|
-
await postLog(task.id,
|
|
228
|
+
await postLog(task.id, `${PREFIX} Fetching planning prompt from cloud API...`);
|
|
221
229
|
// 1. Fetch the assembled planning prompt from the cloud API
|
|
222
230
|
const promptResponse = await api.get("/api/agent/planning-prompt", {
|
|
223
231
|
params: { taskId: task.id },
|
|
@@ -225,7 +233,7 @@ export async function planTask(task, config) {
|
|
|
225
233
|
const { prompt, model } = promptResponse.data;
|
|
226
234
|
const cliModel = model || "sonnet";
|
|
227
235
|
console.log(`${ts()} ${taskLabel} Running Claude CLI ${chalk.dim(`(model: ${chalk.yellow(cliModel)})`)}`);
|
|
228
|
-
await postLog(task.id,
|
|
236
|
+
await postLog(task.id, `${PREFIX} Starting planning agent using anthropic/${cliModel}`);
|
|
229
237
|
// 2. Run Claude CLI asynchronously with progress logging
|
|
230
238
|
const claudePath = process.env.CLAUDE_CLI_PATH || findClaudePath() || "claude";
|
|
231
239
|
const cleanEnv = { ...process.env };
|
|
@@ -239,12 +247,12 @@ export async function planTask(task, config) {
|
|
|
239
247
|
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
|
240
248
|
const errMsg = error instanceof Error ? error.message : String(error);
|
|
241
249
|
console.error(`${ts()} ${taskLabel} ${chalk.red("β")} Failed after ${elapsed}s: ${errMsg.substring(0, 100)}`);
|
|
242
|
-
await postLog(task.id,
|
|
250
|
+
await postLog(task.id, `${PREFIX} Planning failed after ${formatElapsed(elapsed)}: ${errMsg.substring(0, 200)}`, "error", "error");
|
|
243
251
|
return false;
|
|
244
252
|
}
|
|
245
253
|
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
|
246
254
|
console.log(`${ts()} ${taskLabel} ${chalk.green("β")} Claude CLI done ${chalk.dim(`(${elapsed}s, ${rawOutput.length} chars)`)}`);
|
|
247
|
-
await postLog(task.id,
|
|
255
|
+
await postLog(task.id, `${PREFIX} Planning complete (${formatElapsed(elapsed)}). Validating plan...`);
|
|
248
256
|
// 3. Post raw output back to cloud API for validation
|
|
249
257
|
try {
|
|
250
258
|
const result = await api.post("/api/agent/plan-result", {
|
|
@@ -254,7 +262,7 @@ export async function planTask(task, config) {
|
|
|
254
262
|
});
|
|
255
263
|
const storyCount = result.data.storyCount;
|
|
256
264
|
console.log(`${ts()} ${taskLabel} ${chalk.green("β")} Plan validated: ${chalk.bold(storyCount)} stories β ${chalk.green("queued")}`);
|
|
257
|
-
await postLog(task.id,
|
|
265
|
+
await postLog(task.id, `${PREFIX} Plan validated: ${storyCount} stories. Task queued for execution.`);
|
|
258
266
|
await postProgress(task.id, "complete", elapsed, "Planning complete", 0, 0);
|
|
259
267
|
return true;
|
|
260
268
|
}
|
|
@@ -262,7 +270,7 @@ export async function planTask(task, config) {
|
|
|
262
270
|
const err = error;
|
|
263
271
|
const detail = err.response?.data?.detail || String(error);
|
|
264
272
|
console.error(`${ts()} ${taskLabel} ${chalk.red("β")} Validation failed: ${detail.substring(0, 100)}`);
|
|
265
|
-
await postLog(task.id,
|
|
273
|
+
await postLog(task.id, `${PREFIX} Plan validation failed: ${detail.substring(0, 200)}`, "error", "error");
|
|
266
274
|
return false;
|
|
267
275
|
}
|
|
268
276
|
}
|
package/dist/poller.js
CHANGED
|
@@ -149,8 +149,10 @@ async function handleQueuedTask(task, config) {
|
|
|
149
149
|
executionPlanV2: task.executionPlanV2,
|
|
150
150
|
jiraFields: task.jiraFields || {},
|
|
151
151
|
};
|
|
152
|
+
// Pass org credentials from the claim response to the container
|
|
153
|
+
const credentials = claimData.credentials;
|
|
152
154
|
// Spawn asynchronously (don't block the poll loop)
|
|
153
|
-
spawnWorker(spawnableTask, config, oc).catch((err) => console.error(`${ts()} ${chalk.red("β")} Spawn failed for ${taskLabel}:`, err.message || err));
|
|
155
|
+
spawnWorker(spawnableTask, config, oc, credentials).catch((err) => console.error(`${ts()} ${chalk.red("β")} Spawn failed for ${taskLabel}:`, err.message || err));
|
|
154
156
|
}
|
|
155
157
|
/**
|
|
156
158
|
* Start the poll loop.
|
package/dist/spawner.d.ts
CHANGED
|
@@ -19,11 +19,26 @@ export interface SpawnableTask {
|
|
|
19
19
|
skipManagerReview?: boolean;
|
|
20
20
|
executionPlanV2: unknown;
|
|
21
21
|
jiraFields: Record<string, unknown>;
|
|
22
|
+
taskNotes?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Org credentials returned by /api/agent/claim */
|
|
25
|
+
export interface ClaimCredentials {
|
|
26
|
+
jiraBaseUrl?: string;
|
|
27
|
+
jiraEmail?: string;
|
|
28
|
+
jiraApiToken?: string;
|
|
29
|
+
linearApiKey?: string;
|
|
30
|
+
managerProvider?: string;
|
|
31
|
+
managerModelId?: string;
|
|
32
|
+
customerAwsAccessKeyId?: string;
|
|
33
|
+
customerAwsSecretAccessKey?: string;
|
|
34
|
+
customerAwsRegion?: string;
|
|
35
|
+
issueTrackerProvider?: string;
|
|
36
|
+
bitbucketEmail?: string;
|
|
22
37
|
}
|
|
23
38
|
/**
|
|
24
39
|
* Spawn a Docker worker container for a task.
|
|
25
40
|
*/
|
|
26
|
-
export declare function spawnWorker(task: SpawnableTask, config: AgentConfig, orgConfig: Record<string, unknown
|
|
41
|
+
export declare function spawnWorker(task: SpawnableTask, config: AgentConfig, orgConfig: Record<string, unknown>, credentials?: ClaimCredentials): Promise<void>;
|
|
27
42
|
/**
|
|
28
43
|
* Get count of actively running containers.
|
|
29
44
|
*/
|
package/dist/spawner.js
CHANGED
|
@@ -104,7 +104,7 @@ function hasSelfReviewLabel(task) {
|
|
|
104
104
|
/**
|
|
105
105
|
* Spawn a Docker worker container for a task.
|
|
106
106
|
*/
|
|
107
|
-
export async function spawnWorker(task, config, orgConfig) {
|
|
107
|
+
export async function spawnWorker(task, config, orgConfig, credentials) {
|
|
108
108
|
const taskLabel = chalk.cyan(task.id.slice(0, 8));
|
|
109
109
|
if (activeContainers.has(task.id)) {
|
|
110
110
|
console.log(`${ts()} ${taskLabel} ${chalk.dim("Already running, skipping")}`);
|
|
@@ -174,6 +174,25 @@ export async function spawnWorker(task, config, orgConfig) {
|
|
|
174
174
|
GITHUB_REPO: task.githubRepo || "",
|
|
175
175
|
// Worker model
|
|
176
176
|
WORKER_MODEL: task.workerModel || String(orgConfig.defaultWorkerModel || "sonnet"),
|
|
177
|
+
// Jira credentials (from org Secrets Manager via /api/agent/claim)
|
|
178
|
+
JIRA_BASE_URL: credentials?.jiraBaseUrl || "",
|
|
179
|
+
JIRA_EMAIL: credentials?.jiraEmail || "",
|
|
180
|
+
JIRA_API_TOKEN: credentials?.jiraApiToken || "",
|
|
181
|
+
// Issue tracker system (jira, linear, github-issues)
|
|
182
|
+
TICKET_SYSTEM: credentials?.issueTrackerProvider || "jira",
|
|
183
|
+
LINEAR_API_KEY: credentials?.linearApiKey || "",
|
|
184
|
+
// AWS credentials (from org Secrets Manager for workers that deploy infrastructure)
|
|
185
|
+
AWS_ACCESS_KEY_ID: credentials?.customerAwsAccessKeyId || "",
|
|
186
|
+
AWS_SECRET_ACCESS_KEY: credentials?.customerAwsSecretAccessKey || "",
|
|
187
|
+
AWS_DEFAULT_REGION: credentials?.customerAwsRegion || "",
|
|
188
|
+
AWS_REGION: credentials?.customerAwsRegion || "",
|
|
189
|
+
// Manager provider and model for tech lead review
|
|
190
|
+
MANAGER_PROVIDER: credentials?.managerProvider || "anthropic",
|
|
191
|
+
MANAGER_MODEL: credentials?.managerModelId || "",
|
|
192
|
+
// Bitbucket email (needed for API calls with API tokens)
|
|
193
|
+
BITBUCKET_EMAIL: credentials?.bitbucketEmail || "",
|
|
194
|
+
// Task notes from dashboard
|
|
195
|
+
TASK_NOTES: task.taskNotes || "",
|
|
177
196
|
// Anthropic API key (if available)
|
|
178
197
|
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || "",
|
|
179
198
|
// Resilience settings from org config
|