@rallycry/conveyor-agent 8.5.0 → 8.5.1
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/{chunk-63FTZOL5.js → chunk-6B545CHM.js} +126 -9
- package/dist/chunk-6B545CHM.js.map +1 -0
- package/dist/{chunk-3T4SJEH6.js → chunk-WZCO64YR.js} +167 -52
- package/dist/chunk-WZCO64YR.js.map +1 -0
- package/dist/cli.js +23 -14
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -3
- package/dist/index.js +2 -2
- package/dist/{tag-audit-handler-PKYLDJHH.js → tag-audit-handler-3IFB7YDV.js} +2 -2
- package/dist/{task-audit-handler-WINYLZMU.js → task-audit-handler-U5Q52YT2.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-3T4SJEH6.js.map +0 -1
- package/dist/chunk-63FTZOL5.js.map +0 -1
- /package/dist/{tag-audit-handler-PKYLDJHH.js.map → tag-audit-handler-3IFB7YDV.js.map} +0 -0
- /package/dist/{task-audit-handler-WINYLZMU.js.map → task-audit-handler-U5Q52YT2.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ensureClaudeCredentials,
|
|
13
13
|
removeConveyorCredentials,
|
|
14
14
|
sessionTranscriptPath
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-6B545CHM.js";
|
|
16
16
|
|
|
17
17
|
// src/setup/bootstrap.ts
|
|
18
18
|
var BOOTSTRAP_TIMEOUT_MS = 3e4;
|
|
@@ -134,11 +134,13 @@ function applyBootstrapToEnv(config) {
|
|
|
134
134
|
import { io } from "socket.io-client";
|
|
135
135
|
var EVENT_BATCH_MS = 500;
|
|
136
136
|
var MAX_EVENT_BUFFER = 5e3;
|
|
137
|
+
var TOKEN_REFRESH_INTERVAL_MS = 6 * 60 * 60 * 1e3;
|
|
137
138
|
var AgentConnection = class _AgentConnection {
|
|
138
139
|
socket = null;
|
|
139
140
|
config;
|
|
140
141
|
eventBuffer = [];
|
|
141
142
|
flushTimer = null;
|
|
143
|
+
tokenRefreshTimer = null;
|
|
142
144
|
lastEmittedStatus = null;
|
|
143
145
|
lastReportedStatus = null;
|
|
144
146
|
droppedEventCount = 0;
|
|
@@ -202,6 +204,7 @@ var AgentConnection = class _AgentConnection {
|
|
|
202
204
|
if (!this.config.apiUrl) {
|
|
203
205
|
return Promise.reject(new Error("Cannot connect: apiUrl is empty"));
|
|
204
206
|
}
|
|
207
|
+
this.startProactiveTokenRefresh();
|
|
205
208
|
return new Promise((resolve2, reject) => {
|
|
206
209
|
let settled = false;
|
|
207
210
|
let attempts = 0;
|
|
@@ -316,6 +319,7 @@ var AgentConnection = class _AgentConnection {
|
|
|
316
319
|
});
|
|
317
320
|
}
|
|
318
321
|
disconnect() {
|
|
322
|
+
this.stopProactiveTokenRefresh();
|
|
319
323
|
void this.flushEvents();
|
|
320
324
|
if (this.socket) {
|
|
321
325
|
this.socket.io.reconnection(false);
|
|
@@ -399,7 +403,32 @@ var AgentConnection = class _AgentConnection {
|
|
|
399
403
|
}
|
|
400
404
|
}
|
|
401
405
|
looksLikeAuthError(message) {
|
|
402
|
-
return /unauthor|forbid|auth|token/i.test(
|
|
406
|
+
return /unauthor|forbid|auth|token|session (?:not found|expired|invalid)|invalid session/i.test(
|
|
407
|
+
message
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
// ── Proactive task-token refresh ────────────────────────────────────────
|
|
411
|
+
//
|
|
412
|
+
// Socket.IO only re-presents the taskToken on a (re)connect handshake, and
|
|
413
|
+
// the server only re-validates the JWT then. So a token that expires while
|
|
414
|
+
// the socket stays connected goes unnoticed until the next RPC fails. Re-mint
|
|
415
|
+
// periodically from the bootstrap endpoint — refreshFromBootstrap() updates
|
|
416
|
+
// both this.config.taskToken and socket.auth.taskToken, so any later
|
|
417
|
+
// reconnect carries a fresh token. No-ops for project mode / missing
|
|
418
|
+
// codespace env, and is rate-limited to once/60s inside refreshFromBootstrap.
|
|
419
|
+
startProactiveTokenRefresh() {
|
|
420
|
+
if (this.tokenRefreshTimer) return;
|
|
421
|
+
this.tokenRefreshTimer = setInterval(() => {
|
|
422
|
+
void this.refreshTaskTokenFromBootstrap().catch(() => {
|
|
423
|
+
});
|
|
424
|
+
}, TOKEN_REFRESH_INTERVAL_MS);
|
|
425
|
+
this.tokenRefreshTimer.unref?.();
|
|
426
|
+
}
|
|
427
|
+
stopProactiveTokenRefresh() {
|
|
428
|
+
if (this.tokenRefreshTimer) {
|
|
429
|
+
clearInterval(this.tokenRefreshTimer);
|
|
430
|
+
this.tokenRefreshTimer = null;
|
|
431
|
+
}
|
|
403
432
|
}
|
|
404
433
|
drainPendingMessages(messages) {
|
|
405
434
|
for (const msg of messages) {
|
|
@@ -1936,6 +1965,11 @@ var StopProjectBuildRequestSchema = z2.object({
|
|
|
1936
1965
|
taskId: z2.string(),
|
|
1937
1966
|
requestingUserId: z2.string().optional()
|
|
1938
1967
|
});
|
|
1968
|
+
var CreateProjectReleaseRequestSchema = z2.object({
|
|
1969
|
+
projectId: z2.string(),
|
|
1970
|
+
taskIds: z2.array(z2.string()).optional(),
|
|
1971
|
+
requestingUserId: z2.string().optional()
|
|
1972
|
+
});
|
|
1939
1973
|
var ApproveProjectMergePRRequestSchema = z2.object({
|
|
1940
1974
|
projectId: z2.string(),
|
|
1941
1975
|
childTaskId: z2.string(),
|
|
@@ -2011,6 +2045,22 @@ var GetProjectAttachmentRequestSchema = z2.object({
|
|
|
2011
2045
|
/** Max bytes of text content to return from `offset`. Server default applies. */
|
|
2012
2046
|
maxBytes: z2.number().int().positive().optional()
|
|
2013
2047
|
});
|
|
2048
|
+
var RequestProjectFileUploadRequestSchema = z2.object({
|
|
2049
|
+
projectId: z2.string(),
|
|
2050
|
+
taskId: z2.string(),
|
|
2051
|
+
fileName: z2.string().min(1).max(255),
|
|
2052
|
+
mimeType: z2.string().min(1).max(128),
|
|
2053
|
+
fileSize: z2.number().int().positive().max(MAX_FILE_SIZE_BYTES),
|
|
2054
|
+
requestingUserId: z2.string().optional()
|
|
2055
|
+
});
|
|
2056
|
+
var ConfirmProjectFileUploadRequestSchema = z2.object({
|
|
2057
|
+
projectId: z2.string(),
|
|
2058
|
+
taskId: z2.string(),
|
|
2059
|
+
fileId: z2.string(),
|
|
2060
|
+
/** When set, the attachment is also posted to the task chat with this text. */
|
|
2061
|
+
comment: z2.string().max(2e3).optional(),
|
|
2062
|
+
requestingUserId: z2.string().optional()
|
|
2063
|
+
});
|
|
2014
2064
|
var CreateProjectPullRequestRequestSchema = z2.object({
|
|
2015
2065
|
projectId: z2.string(),
|
|
2016
2066
|
taskId: z2.string(),
|
|
@@ -2035,6 +2085,16 @@ var RemoveProjectTaskReviewerRequestSchema = z2.object({
|
|
|
2035
2085
|
userId: z2.string(),
|
|
2036
2086
|
requestingUserId: z2.string().optional()
|
|
2037
2087
|
});
|
|
2088
|
+
var ListProjectManualTestsRequestSchema = z2.object({
|
|
2089
|
+
projectId: z2.string(),
|
|
2090
|
+
taskId: z2.string()
|
|
2091
|
+
});
|
|
2092
|
+
var SetProjectManualTestsRequestSchema = z2.object({
|
|
2093
|
+
projectId: z2.string(),
|
|
2094
|
+
taskId: z2.string(),
|
|
2095
|
+
items: z2.array(z2.object({ title: z2.string().min(1) })).min(1),
|
|
2096
|
+
requestingUserId: z2.string().optional()
|
|
2097
|
+
});
|
|
2038
2098
|
var StartTaskAuditRequestSchema = z3.object({
|
|
2039
2099
|
projectId: z3.string(),
|
|
2040
2100
|
taskIds: z3.array(z3.string()).min(1)
|
|
@@ -8200,7 +8260,10 @@ var SessionRunner = class _SessionRunner {
|
|
|
8200
8260
|
`);
|
|
8201
8261
|
this.connection.sendEvent({ type: "shutdown", reason: finalState });
|
|
8202
8262
|
this.lifecycle.destroy();
|
|
8203
|
-
|
|
8263
|
+
try {
|
|
8264
|
+
await this.setState(finalState);
|
|
8265
|
+
} catch {
|
|
8266
|
+
}
|
|
8204
8267
|
this.connection.disconnect();
|
|
8205
8268
|
this._finalState = finalState;
|
|
8206
8269
|
}
|
|
@@ -8259,20 +8322,31 @@ var ProjectConnection = class {
|
|
|
8259
8322
|
return this.socket?.connected ?? false;
|
|
8260
8323
|
}
|
|
8261
8324
|
// ── Typed service method call ──────────────────────────────────────────
|
|
8262
|
-
call(method, payload) {
|
|
8325
|
+
call(method, payload, opts) {
|
|
8263
8326
|
const socket = this.requireSocket();
|
|
8264
8327
|
return new Promise((resolve2, reject) => {
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
resolve2(response.data);
|
|
8271
|
-
} else {
|
|
8272
|
-
reject(new Error(response.error ?? `Service call failed: ${String(method)}`));
|
|
8273
|
-
}
|
|
8328
|
+
const handleResponse = (response) => {
|
|
8329
|
+
if (response.success && response.data !== void 0) {
|
|
8330
|
+
resolve2(response.data);
|
|
8331
|
+
} else {
|
|
8332
|
+
reject(new Error(response.error ?? `Service call failed: ${String(method)}`));
|
|
8274
8333
|
}
|
|
8275
|
-
|
|
8334
|
+
};
|
|
8335
|
+
if (opts?.timeoutMs) {
|
|
8336
|
+
socket.timeout(opts.timeoutMs).emit(
|
|
8337
|
+
`agentSessionService:${String(method)}`,
|
|
8338
|
+
payload,
|
|
8339
|
+
(err, response) => {
|
|
8340
|
+
if (err) {
|
|
8341
|
+
reject(new Error(`Service call timed out: ${String(method)}`));
|
|
8342
|
+
} else {
|
|
8343
|
+
handleResponse(response);
|
|
8344
|
+
}
|
|
8345
|
+
}
|
|
8346
|
+
);
|
|
8347
|
+
return;
|
|
8348
|
+
}
|
|
8349
|
+
socket.emit(`agentSessionService:${String(method)}`, payload, handleResponse);
|
|
8276
8350
|
});
|
|
8277
8351
|
}
|
|
8278
8352
|
// ── Connection lifecycle ───────────────────────────────────────────────
|
|
@@ -8330,8 +8404,13 @@ var ProjectConnection = class {
|
|
|
8330
8404
|
this.flushTimer = null;
|
|
8331
8405
|
}
|
|
8332
8406
|
this.flushEvents();
|
|
8333
|
-
this.socket
|
|
8334
|
-
|
|
8407
|
+
if (this.socket) {
|
|
8408
|
+
this.socket.io.reconnection(false);
|
|
8409
|
+
this.socket.removeAllListeners();
|
|
8410
|
+
this.socket.disconnect();
|
|
8411
|
+
this.socket = null;
|
|
8412
|
+
}
|
|
8413
|
+
this.reconnectCallbacks = [];
|
|
8335
8414
|
}
|
|
8336
8415
|
onReconnect(callback) {
|
|
8337
8416
|
this.reconnectCallbacks.push(callback);
|
|
@@ -9928,6 +10007,10 @@ function spawnChildAgent(assignment, workDir) {
|
|
|
9928
10007
|
CONVEYOR_MODE: mode,
|
|
9929
10008
|
CONVEYOR_WORKSPACE: workDir,
|
|
9930
10009
|
CONVEYOR_USE_WORKTREE: "false",
|
|
10010
|
+
// The project runner flushes git for every child working tree after the
|
|
10011
|
+
// kill (see ProjectRunner.stop), so the child skips its own shutdown
|
|
10012
|
+
// flush — keeps SIGTERM teardown well inside the SIGKILL window.
|
|
10013
|
+
CONVEYOR_SKIP_SHUTDOWN_GIT_FLUSH: "true",
|
|
9931
10014
|
CONVEYOR_AGENT_MODE: effectiveAgentMode,
|
|
9932
10015
|
CONVEYOR_IS_AUTO: isAuto ? "true" : "false",
|
|
9933
10016
|
CONVEYOR_USE_SANDBOX: useSandbox === true ? "true" : "false",
|
|
@@ -10052,6 +10135,8 @@ function handleStopTask(taskId, activeAgents, projectDir) {
|
|
|
10052
10135
|
// src/runner/project-runner.ts
|
|
10053
10136
|
var logger10 = createServiceLogger("ProjectRunner");
|
|
10054
10137
|
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
10138
|
+
var DISCONNECT_ACK_TIMEOUT_MS = 5e3;
|
|
10139
|
+
var SHUTDOWN_WATCHDOG_MS = 9e4;
|
|
10055
10140
|
var ProjectRunner = class {
|
|
10056
10141
|
connection;
|
|
10057
10142
|
projectDir;
|
|
@@ -10135,11 +10220,17 @@ var ProjectRunner = class {
|
|
|
10135
10220
|
}
|
|
10136
10221
|
/** Best-effort WIP commit + push of every tracked working tree on shutdown.
|
|
10137
10222
|
* Iterates the main project dir plus any active agent worktrees so nothing
|
|
10138
|
-
* pending is lost when the pod is killed. Never throws.
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10223
|
+
* pending is lost when the pod is killed. Never throws.
|
|
10224
|
+
*
|
|
10225
|
+
* Callers that kill child agents first must snapshot the worktree dirs
|
|
10226
|
+
* BEFORE the kill — the child exit handler removes entries from
|
|
10227
|
+
* `activeAgents`, so reading it after the kill misses the worktrees. */
|
|
10228
|
+
async flushGitOnShutdown(dirs) {
|
|
10229
|
+
if (!dirs) {
|
|
10230
|
+
dirs = /* @__PURE__ */ new Set([this.projectDir]);
|
|
10231
|
+
for (const agent of this.activeAgents.values()) {
|
|
10232
|
+
if (agent.worktreePath) dirs.add(agent.worktreePath);
|
|
10233
|
+
}
|
|
10143
10234
|
}
|
|
10144
10235
|
for (const dir of dirs) {
|
|
10145
10236
|
try {
|
|
@@ -10163,38 +10254,62 @@ var ProjectRunner = class {
|
|
|
10163
10254
|
if (this.stopping) return;
|
|
10164
10255
|
this.stopping = true;
|
|
10165
10256
|
logger10.info("Shutting down");
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10257
|
+
const watchdog = setTimeout(() => {
|
|
10258
|
+
logger10.warn("Shutdown watchdog fired, forcing lifecycle resolution");
|
|
10259
|
+
this.finishShutdown();
|
|
10260
|
+
}, SHUTDOWN_WATCHDOG_MS);
|
|
10261
|
+
watchdog.unref();
|
|
10262
|
+
const flushDirs = /* @__PURE__ */ new Set([this.projectDir]);
|
|
10263
|
+
for (const agent of this.activeAgents.values()) {
|
|
10264
|
+
if (agent.worktreePath) flushDirs.add(agent.worktreePath);
|
|
10171
10265
|
}
|
|
10172
|
-
const stopPromises = [...this.activeAgents.keys()].map(
|
|
10173
|
-
(key) => new Promise((resolve2) => {
|
|
10174
|
-
const agent = this.activeAgents.get(key);
|
|
10175
|
-
if (!agent) {
|
|
10176
|
-
resolve2();
|
|
10177
|
-
return;
|
|
10178
|
-
}
|
|
10179
|
-
agent.process.on("exit", () => resolve2());
|
|
10180
|
-
handleStopTask(key, this.activeAgents, this.projectDir);
|
|
10181
|
-
})
|
|
10182
|
-
);
|
|
10183
|
-
await Promise.race([
|
|
10184
|
-
Promise.all(stopPromises),
|
|
10185
|
-
new Promise((resolve2) => {
|
|
10186
|
-
setTimeout(resolve2, STOP_TIMEOUT_MS + 5e3);
|
|
10187
|
-
})
|
|
10188
|
-
]);
|
|
10189
|
-
await this.flushGitOnShutdown();
|
|
10190
10266
|
try {
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10267
|
+
this.commitWatcher.stop();
|
|
10268
|
+
await killStartCommand(this.startCmd);
|
|
10269
|
+
if (this.heartbeatTimer) {
|
|
10270
|
+
clearInterval(this.heartbeatTimer);
|
|
10271
|
+
this.heartbeatTimer = null;
|
|
10272
|
+
}
|
|
10273
|
+
const stopPromises = [...this.activeAgents.keys()].map(
|
|
10274
|
+
(key) => new Promise((resolve2) => {
|
|
10275
|
+
const agent = this.activeAgents.get(key);
|
|
10276
|
+
if (!agent) {
|
|
10277
|
+
resolve2();
|
|
10278
|
+
return;
|
|
10279
|
+
}
|
|
10280
|
+
agent.process.on("exit", () => resolve2());
|
|
10281
|
+
handleStopTask(key, this.activeAgents, this.projectDir);
|
|
10282
|
+
})
|
|
10283
|
+
);
|
|
10284
|
+
await Promise.race([
|
|
10285
|
+
Promise.all(stopPromises),
|
|
10286
|
+
new Promise((resolve2) => {
|
|
10287
|
+
setTimeout(resolve2, STOP_TIMEOUT_MS + 5e3);
|
|
10288
|
+
})
|
|
10289
|
+
]);
|
|
10290
|
+
await this.flushGitOnShutdown(flushDirs);
|
|
10291
|
+
try {
|
|
10292
|
+
await this.connection.call(
|
|
10293
|
+
"disconnectProjectRunner",
|
|
10294
|
+
{ projectId: this.connection.projectId },
|
|
10295
|
+
{ timeoutMs: DISCONNECT_ACK_TIMEOUT_MS }
|
|
10296
|
+
);
|
|
10297
|
+
} catch {
|
|
10298
|
+
}
|
|
10299
|
+
logger10.info("Shutdown complete");
|
|
10300
|
+
} finally {
|
|
10301
|
+
clearTimeout(watchdog);
|
|
10302
|
+
this.finishShutdown();
|
|
10303
|
+
}
|
|
10304
|
+
}
|
|
10305
|
+
/** Idempotent final step: tear down the socket and resolve the lifecycle
|
|
10306
|
+
* promise so start() returns. Called from stop()'s finally and from the
|
|
10307
|
+
* shutdown watchdog. */
|
|
10308
|
+
finishShutdown() {
|
|
10309
|
+
try {
|
|
10310
|
+
this.connection.disconnect();
|
|
10194
10311
|
} catch {
|
|
10195
10312
|
}
|
|
10196
|
-
this.connection.disconnect();
|
|
10197
|
-
logger10.info("Shutdown complete");
|
|
10198
10313
|
if (this.resolveLifecycle) {
|
|
10199
10314
|
this.resolveLifecycle();
|
|
10200
10315
|
this.resolveLifecycle = null;
|
|
@@ -10268,7 +10383,7 @@ var ProjectRunner = class {
|
|
|
10268
10383
|
async handleAuditTags(request) {
|
|
10269
10384
|
this.connection.emitStatus("busy");
|
|
10270
10385
|
try {
|
|
10271
|
-
const { handleTagAudit } = await import("./tag-audit-handler-
|
|
10386
|
+
const { handleTagAudit } = await import("./tag-audit-handler-3IFB7YDV.js");
|
|
10272
10387
|
await handleTagAudit(request, this.connection, this.projectDir);
|
|
10273
10388
|
} catch (error) {
|
|
10274
10389
|
const msg = parseErrorMessage(error);
|
|
@@ -10291,7 +10406,7 @@ var ProjectRunner = class {
|
|
|
10291
10406
|
async handleAuditTasks(request) {
|
|
10292
10407
|
this.connection.emitStatus("busy");
|
|
10293
10408
|
try {
|
|
10294
|
-
const { handleTaskAudit } = await import("./task-audit-handler-
|
|
10409
|
+
const { handleTaskAudit } = await import("./task-audit-handler-U5Q52YT2.js");
|
|
10295
10410
|
await handleTaskAudit(request, this.connection, this.projectDir);
|
|
10296
10411
|
} catch (error) {
|
|
10297
10412
|
const msg = parseErrorMessage(error);
|
|
@@ -10432,4 +10547,4 @@ export {
|
|
|
10432
10547
|
loadConveyorConfig,
|
|
10433
10548
|
unshallowRepo
|
|
10434
10549
|
};
|
|
10435
|
-
//# sourceMappingURL=chunk-
|
|
10550
|
+
//# sourceMappingURL=chunk-WZCO64YR.js.map
|