fission-worker 0.4.0 → 0.5.0
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/agent.js +20 -0
- package/dist/agent.js.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/runner/modules/pipeline/data/api-data.service.js +3 -1
- package/runner/modules/pipeline/pipeline-helpers.service.js +1 -1
- package/runner/modules/pipeline/pipeline-worker.service.js +11 -5
- package/runner/modules/worker-api/worker-api.controller.js +7 -1
package/dist/agent.js
CHANGED
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.agentLoop = agentLoop;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
4
6
|
const docker_1 = require("./docker");
|
|
5
7
|
const POLL_INTERVAL_MS = 5_000;
|
|
6
8
|
const HEARTBEAT_INTERVAL_MS = 30_000;
|
|
7
9
|
function sleep(ms) {
|
|
8
10
|
return new Promise((r) => setTimeout(r, ms));
|
|
9
11
|
}
|
|
12
|
+
/** Clean up leftover workspace directories from previous crashed runs. */
|
|
13
|
+
function cleanupStaleWorkspaces(config) {
|
|
14
|
+
const workspacesDir = (0, path_1.join)(config.cacheDir, "..", "workspaces");
|
|
15
|
+
if (!(0, fs_1.existsSync)(workspacesDir))
|
|
16
|
+
return;
|
|
17
|
+
try {
|
|
18
|
+
const dirs = (0, fs_1.readdirSync)(workspacesDir);
|
|
19
|
+
if (dirs.length > 0) {
|
|
20
|
+
console.log(`[agent] Cleaning up ${dirs.length} leftover workspace(s) from previous run`);
|
|
21
|
+
for (const dir of dirs) {
|
|
22
|
+
(0, fs_1.rmSync)((0, path_1.join)(workspacesDir, dir), { recursive: true, force: true });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch { /* best effort */ }
|
|
27
|
+
}
|
|
10
28
|
async function agentLoop(config) {
|
|
11
29
|
const activeSessions = new Map();
|
|
12
30
|
let running = true;
|
|
31
|
+
// Clean up stale workspaces from previous crashes
|
|
32
|
+
cleanupStaleWorkspaces(config);
|
|
13
33
|
// Graceful shutdown
|
|
14
34
|
const shutdown = () => {
|
|
15
35
|
console.log("\n[agent] Shutting down — waiting for active sessions to finish...");
|
package/dist/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
5
7
|
const config_1 = require("./config");
|
|
6
8
|
const agent_1 = require("./agent");
|
|
7
9
|
const setup_1 = require("./setup");
|
|
8
10
|
const health_1 = require("./health");
|
|
11
|
+
// Read version from package.json at runtime
|
|
12
|
+
let PKG_VERSION = "unknown";
|
|
13
|
+
try {
|
|
14
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "..", "package.json"), "utf-8"));
|
|
15
|
+
PKG_VERSION = pkg.version;
|
|
16
|
+
}
|
|
17
|
+
catch { /* fallback */ }
|
|
9
18
|
const program = new commander_1.Command();
|
|
10
19
|
program
|
|
11
20
|
.name("fission-worker")
|
|
12
21
|
.description("Fission Worker Agent — runs pipeline sessions in Docker containers")
|
|
13
|
-
.version(
|
|
22
|
+
.version(PKG_VERSION);
|
|
14
23
|
program
|
|
15
24
|
.command("setup")
|
|
16
25
|
.description("Interactive setup wizard — register this machine as a Fission worker")
|
|
@@ -27,7 +36,7 @@ program
|
|
|
27
36
|
process.exit(1);
|
|
28
37
|
}
|
|
29
38
|
const config = (0, config_1.readConfig)();
|
|
30
|
-
console.log(`[fission-worker]
|
|
39
|
+
console.log(`[fission-worker] v${PKG_VERSION} — starting worker "${config.workerName}" (${config.workerId.slice(0, 8)})`);
|
|
31
40
|
await (0, agent_1.agentLoop)(config);
|
|
32
41
|
});
|
|
33
42
|
program
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,qCAAmE;AACnE,mCAAoC;AACpC,mCAAmC;AACnC,qCAA8C;AAE9C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,gBAAgB,CAAC;KACtB,WAAW,CAAC,oEAAoE,CAAC;KACjF,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -123,7 +123,9 @@ class ApiDataService {
|
|
|
123
123
|
type,
|
|
124
124
|
data,
|
|
125
125
|
sessionId: this.sessionId,
|
|
126
|
-
}).catch(() => {
|
|
126
|
+
}).catch((err) => {
|
|
127
|
+
console.error(`[ApiDataService] Failed to emit ${type}: ${err}`);
|
|
128
|
+
});
|
|
127
129
|
}
|
|
128
130
|
// -- Activity Log ----------------------------------------------------- //
|
|
129
131
|
async log(action, entityType, entityId, userId, details) {
|
|
@@ -54,7 +54,7 @@ let PipelineHelpersService = PipelineHelpersService_1 = class PipelineHelpersSer
|
|
|
54
54
|
// ------------------------------------------------------------------ //
|
|
55
55
|
spawnClaude(prompt, cwd, model, timeoutMs, streamContext, options) {
|
|
56
56
|
return new Promise((resolve, reject) => {
|
|
57
|
-
const args = ["-p", prompt, "--verbose"];
|
|
57
|
+
const args = ["-p", prompt, "--verbose", "--dangerously-skip-permissions"];
|
|
58
58
|
if (model)
|
|
59
59
|
args.push("--model", model);
|
|
60
60
|
if (options?.resumeSessionId)
|
|
@@ -92,7 +92,7 @@ let PipelineWorkerService = PipelineWorkerService_1 = class PipelineWorkerServic
|
|
|
92
92
|
: 15 * 60 * 1000; // 15 minutes (medium default)
|
|
93
93
|
// Use persistent session: resume if this slot already has a session, otherwise start new
|
|
94
94
|
const existingSession = this.slotSessions.get(slot);
|
|
95
|
-
const workerResult = await this.helpers.spawnClaude(workerPrompt, repoPath,
|
|
95
|
+
const workerResult = await this.helpers.spawnClaude(workerPrompt, repoPath, "claude-sonnet-4-6", taskTimeout, { projectId, phase: "BUILD" }, { resumeSessionId: existingSession, jsonOutput: true });
|
|
96
96
|
// Capture session ID for future tasks in this slot
|
|
97
97
|
if (workerResult.sessionId) {
|
|
98
98
|
this.slotSessions.set(slot, workerResult.sessionId);
|
|
@@ -112,18 +112,24 @@ let PipelineWorkerService = PipelineWorkerService_1 = class PipelineWorkerServic
|
|
|
112
112
|
if (!hasDiff) {
|
|
113
113
|
// No diff — check if worker actually failed despite exit code 0
|
|
114
114
|
const summaryText = workerOutput?.summary ?? workerResult.stdout.slice(0, 2000);
|
|
115
|
+
const lowerSummary = summaryText.toLowerCase();
|
|
115
116
|
const failureIndicators = ["unable to", "could not", "blocked", "not applied", "not granted", "were denied", "was denied", "permission"];
|
|
116
|
-
const workerActuallyFailed = failureIndicators.some((indicator) =>
|
|
117
|
+
const workerActuallyFailed = failureIndicators.some((indicator) => lowerSummary.includes(indicator));
|
|
118
|
+
// Permission errors are unrecoverable — fail immediately, don't waste retries
|
|
119
|
+
const permissionDenied = lowerSummary.includes("permission") && (lowerSummary.includes("denied") || lowerSummary.includes("mode"));
|
|
117
120
|
if (workerActuallyFailed) {
|
|
121
|
+
const failImmediately = permissionDenied;
|
|
118
122
|
const updatedTask = await this.data.updateTask(task.id, {
|
|
119
|
-
status: (task.retryCount + 1) >= 3 ? "FAILED" : "READY_TO_START",
|
|
120
|
-
retryCount: { increment: 1 },
|
|
123
|
+
status: failImmediately || (task.retryCount + 1) >= 3 ? "FAILED" : "READY_TO_START",
|
|
124
|
+
retryCount: failImmediately ? 3 : { increment: 1 },
|
|
121
125
|
metadata: (workerOutput ?? { rawOutput: summaryText }),
|
|
122
126
|
});
|
|
123
127
|
await this.data.createTaskComment({
|
|
124
128
|
taskId: task.id,
|
|
125
129
|
author: "worker",
|
|
126
|
-
content:
|
|
130
|
+
content: failImmediately
|
|
131
|
+
? `Failed (permission denied — not retryable): ${summaryText.slice(0, 300)}`
|
|
132
|
+
: `Failed (no code changes made, attempt ${task.retryCount + 1}/3): ${summaryText.slice(0, 300)}`,
|
|
127
133
|
});
|
|
128
134
|
this.data.emit(projectId, "task_updated", { id: task.id, status: updatedTask.status });
|
|
129
135
|
}
|
|
@@ -76,11 +76,16 @@ let WorkerApiController = WorkerApiController_1 = class WorkerApiController {
|
|
|
76
76
|
this.logger.warn(`Failed to generate GitHub token for installation ${repoWithInstallation.githubInstallationId}: ${err}`);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
// Mark as ACTIVE
|
|
79
|
+
// Mark as ACTIVE and notify browser
|
|
80
80
|
await this.prisma.session.update({
|
|
81
81
|
where: { id: session.id },
|
|
82
82
|
data: { status: "ACTIVE" },
|
|
83
83
|
});
|
|
84
|
+
this.eventBus.emit(session.projectId, "phase_changed", {
|
|
85
|
+
sessionId: session.id,
|
|
86
|
+
phase: "BUILD",
|
|
87
|
+
status: "ACTIVE",
|
|
88
|
+
});
|
|
84
89
|
return {
|
|
85
90
|
sessionId: session.id,
|
|
86
91
|
projectId: session.projectId,
|
|
@@ -117,6 +122,7 @@ let WorkerApiController = WorkerApiController_1 = class WorkerApiController {
|
|
|
117
122
|
}
|
|
118
123
|
// ── Event relay (worker → SSE → browser) ──────────────────────── //
|
|
119
124
|
async relayEvent(body) {
|
|
125
|
+
this.logger.debug(`[EventRelay] ${body.type} for project ${body.projectId?.slice(0, 8)}`);
|
|
120
126
|
this.eventBus.emit(body.projectId, body.type, body.data);
|
|
121
127
|
}
|
|
122
128
|
// ── Tasks ──────────────────────────────────────────────────────── //
|