@rallycry/conveyor-agent 10.13.18 → 10.13.50
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/{boot-YZCOIV3Q.js → boot-I353EAK6.js} +156 -125
- package/dist/boot-I353EAK6.js.map +1 -0
- package/dist/{chunk-3GDXX3OX.js → chunk-36VMMHYD.js} +5578 -2111
- package/dist/chunk-36VMMHYD.js.map +1 -0
- package/dist/{chunk-AGGVNADW.js → chunk-3Z4YQNJV.js} +59 -13
- package/dist/chunk-3Z4YQNJV.js.map +1 -0
- package/dist/chunk-5OQQSDVT.js +142 -0
- package/dist/chunk-5OQQSDVT.js.map +1 -0
- package/dist/{chunk-UZTJJD7Y.js → chunk-KCB7CSWJ.js} +43 -2
- package/dist/chunk-KCB7CSWJ.js.map +1 -0
- package/dist/{chunk-UDSRAHKP.js → chunk-QOJTJCYZ.js} +67 -19
- package/dist/chunk-QOJTJCYZ.js.map +1 -0
- package/dist/chunk-ULS4QPRE.js +138 -0
- package/dist/chunk-ULS4QPRE.js.map +1 -0
- package/dist/{chunk-72AEN6LB.js → chunk-XR6H326I.js} +26 -2
- package/dist/chunk-XR6H326I.js.map +1 -0
- package/dist/cli.js +196 -334
- package/dist/cli.js.map +1 -1
- package/dist/{client-BU4XA7CV.js → client-LRVVHTNG.js} +2 -2
- package/dist/heartbeat-worker.js +10 -12
- package/dist/heartbeat-worker.js.map +1 -1
- package/dist/index.d.ts +153 -8
- package/dist/index.js +5 -5
- package/dist/oom-watchdog-U7JERHA2.js +11 -0
- package/dist/server-NIOBJ46G.js +10 -0
- package/dist/server-NIOBJ46G.js.map +1 -0
- package/package.json +3 -3
- package/runtime/entrypoint.sh +5 -4
- package/dist/boot-YZCOIV3Q.js.map +0 -1
- package/dist/chunk-3GDXX3OX.js.map +0 -1
- package/dist/chunk-72AEN6LB.js.map +0 -1
- package/dist/chunk-7TQO4ZF4.js +0 -60
- package/dist/chunk-7TQO4ZF4.js.map +0 -1
- package/dist/chunk-AGGVNADW.js.map +0 -1
- package/dist/chunk-UDSRAHKP.js.map +0 -1
- package/dist/chunk-UZTJJD7Y.js.map +0 -1
- package/dist/server-BXAFMYDM.js +0 -9
- /package/dist/{client-BU4XA7CV.js.map → client-LRVVHTNG.js.map} +0 -0
- /package/dist/{server-BXAFMYDM.js.map → oom-watchdog-U7JERHA2.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
TOMBSTONE_MESSAGE,
|
|
4
|
+
isLegacyEntrypointLaunch
|
|
5
|
+
} from "./chunk-6GS5ADIY.js";
|
|
2
6
|
import {
|
|
3
7
|
AgentConnection,
|
|
4
8
|
ClaudeTuiAdapter,
|
|
9
|
+
CodespacePortVisibility,
|
|
5
10
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
6
11
|
DEFAULT_SONNET_MODEL,
|
|
7
12
|
Lifecycle,
|
|
@@ -12,14 +17,15 @@ import {
|
|
|
12
17
|
TuiUnavailableError,
|
|
13
18
|
applyBootstrapToEnv,
|
|
14
19
|
awaitGitReady,
|
|
20
|
+
buildProjectTools,
|
|
15
21
|
buildSessionPreviewPorts,
|
|
16
22
|
buildSynthesizedCredentials,
|
|
17
23
|
claudeJsonPath,
|
|
18
24
|
cleanTerminalOutput,
|
|
19
25
|
createServiceLogger,
|
|
20
|
-
defineTool,
|
|
21
26
|
fetchBootstrap,
|
|
22
27
|
findOnPath,
|
|
28
|
+
isPermissionDeniedError,
|
|
23
29
|
loadConveyorConfig,
|
|
24
30
|
loadForwardPorts,
|
|
25
31
|
parseUsageGauges,
|
|
@@ -27,32 +33,32 @@ import {
|
|
|
27
33
|
resolveSessionStart,
|
|
28
34
|
runUsageProbe,
|
|
29
35
|
sampleKeyUsage,
|
|
30
|
-
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-7TQO4ZF4.js";
|
|
36
|
+
workspacePathExists
|
|
37
|
+
} from "./chunk-36VMMHYD.js";
|
|
33
38
|
import {
|
|
34
|
-
|
|
35
|
-
} from "./chunk-
|
|
39
|
+
reportBootMilestone
|
|
40
|
+
} from "./chunk-KCB7CSWJ.js";
|
|
41
|
+
import "./chunk-5OQQSDVT.js";
|
|
36
42
|
import {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
} from "./chunk-6GS5ADIY.js";
|
|
40
|
-
import "./chunk-UZTJJD7Y.js";
|
|
43
|
+
getWorkbenchClient
|
|
44
|
+
} from "./chunk-QOJTJCYZ.js";
|
|
41
45
|
import {
|
|
42
46
|
workbenchEnabled
|
|
43
47
|
} from "./chunk-4VUQ2NPF.js";
|
|
44
48
|
import {
|
|
45
49
|
buildPromptBytes,
|
|
46
50
|
inheritedEnv,
|
|
47
|
-
|
|
51
|
+
resolvePtySpawn,
|
|
52
|
+
runSetupCommand,
|
|
48
53
|
runStartCommand,
|
|
54
|
+
sessionTempBase,
|
|
49
55
|
terminateProcessGroup
|
|
50
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-XR6H326I.js";
|
|
51
57
|
import "./chunk-JIGG755T.js";
|
|
52
58
|
|
|
53
59
|
// src/cli.ts
|
|
54
60
|
import { readFileSync } from "fs";
|
|
55
|
-
import { join as
|
|
61
|
+
import { join as join4, dirname as dirname3 } from "path";
|
|
56
62
|
import { fileURLToPath } from "url";
|
|
57
63
|
|
|
58
64
|
// src/setup/sidecars.ts
|
|
@@ -202,31 +208,71 @@ async function waitForSidecars(opts = {}) {
|
|
|
202
208
|
);
|
|
203
209
|
}
|
|
204
210
|
|
|
205
|
-
// src/setup/
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
// src/setup/db-schema-sync.ts
|
|
212
|
+
import { basename, dirname, join } from "path";
|
|
213
|
+
var PRISMA_SCHEMA_CANDIDATES = [
|
|
214
|
+
"packages/db/prisma/schema.prisma",
|
|
215
|
+
"prisma/schema.prisma",
|
|
216
|
+
"apps/api/prisma/schema.prisma",
|
|
217
|
+
"packages/db/schema.prisma"
|
|
218
|
+
];
|
|
219
|
+
var PRISMA_DB_PUSH = "bunx prisma db push";
|
|
220
|
+
var SCHEMA_SYNC_TIMEOUT_MS = 18e4;
|
|
221
|
+
function depsInclude(rawDeps, dep) {
|
|
222
|
+
return (rawDeps ?? "").split(",").map((entry) => entry.trim()).includes(dep);
|
|
223
|
+
}
|
|
224
|
+
function isDisabled(env) {
|
|
225
|
+
const flag = env.CONVEYOR_DB_SCHEMA_SYNC?.trim().toLowerCase();
|
|
226
|
+
return flag === "0" || flag === "false";
|
|
227
|
+
}
|
|
228
|
+
function packageRootForSchema(schemaPath) {
|
|
229
|
+
const dir = dirname(schemaPath);
|
|
230
|
+
return basename(dir) === "prisma" ? dirname(dir) : dir;
|
|
231
|
+
}
|
|
232
|
+
async function resolveSchemaSyncPlan(options) {
|
|
233
|
+
const { workspaceDir, env } = options;
|
|
234
|
+
const pathExists = options.pathExists ?? workspacePathExists;
|
|
235
|
+
if (isDisabled(env)) return null;
|
|
236
|
+
const override = env.CONVEYOR_DB_SCHEMA_SYNC_COMMAND?.trim();
|
|
237
|
+
if (override) return { command: override, cwd: workspaceDir, source: "override" };
|
|
238
|
+
if (!depsInclude(env.CONVEYOR_DEPS, "postgresql")) return null;
|
|
239
|
+
if (!env.DATABASE_URL?.trim()) return null;
|
|
240
|
+
for (const relative of PRISMA_SCHEMA_CANDIDATES) {
|
|
241
|
+
const schemaPath = join(workspaceDir, relative);
|
|
242
|
+
if (await pathExists(schemaPath)) {
|
|
243
|
+
return { command: PRISMA_DB_PUSH, cwd: packageRootForSchema(schemaPath), source: "prisma" };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
async function runDbSchemaSync(options) {
|
|
249
|
+
let plan = null;
|
|
215
250
|
try {
|
|
216
|
-
|
|
217
|
-
method: "POST",
|
|
218
|
-
headers: {
|
|
219
|
-
"content-type": "application/json",
|
|
220
|
-
authorization: `Bearer ${token}`
|
|
221
|
-
},
|
|
222
|
-
body: JSON.stringify({ key: opts.key }),
|
|
223
|
-
signal: controller.signal
|
|
224
|
-
});
|
|
225
|
-
return res.ok;
|
|
251
|
+
plan = await resolveSchemaSyncPlan(options);
|
|
226
252
|
} catch {
|
|
227
|
-
return
|
|
253
|
+
return "skipped";
|
|
254
|
+
}
|
|
255
|
+
if (!plan) return "skipped";
|
|
256
|
+
const { onOutput, runCommand } = options;
|
|
257
|
+
onOutput("stdout", `[db] syncing schema (${plan.source}): ${plan.command}
|
|
258
|
+
`);
|
|
259
|
+
const controller = new AbortController();
|
|
260
|
+
const abort = () => controller.abort();
|
|
261
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
262
|
+
const timer = setTimeout(abort, options.timeoutMs ?? SCHEMA_SYNC_TIMEOUT_MS);
|
|
263
|
+
timer.unref();
|
|
264
|
+
try {
|
|
265
|
+
await runCommand(plan.command, plan.cwd, onOutput, controller.signal);
|
|
266
|
+
onOutput("stdout", "[db] schema in sync\n");
|
|
267
|
+
return "synced";
|
|
268
|
+
} catch (error) {
|
|
269
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
270
|
+
onOutput("stderr", `[db] schema sync failed: ${message}
|
|
271
|
+
`);
|
|
272
|
+
return "failed";
|
|
228
273
|
} finally {
|
|
229
274
|
clearTimeout(timer);
|
|
275
|
+
options.signal?.removeEventListener("abort", abort);
|
|
230
276
|
}
|
|
231
277
|
}
|
|
232
278
|
|
|
@@ -235,10 +281,11 @@ function defaultCommandExecutors() {
|
|
|
235
281
|
if (workbenchEnabled()) {
|
|
236
282
|
const client = getWorkbenchClient();
|
|
237
283
|
return {
|
|
238
|
-
runStartCommand: (cmd, cwd, onOutput) => client.runStartCommand(cmd, cwd, onOutput)
|
|
284
|
+
runStartCommand: (cmd, cwd, onOutput) => client.runStartCommand(cmd, cwd, onOutput),
|
|
285
|
+
runShellCommand: (cmd, cwd, onOutput, signal) => client.runSetupCommand(cmd, cwd, onOutput, signal)
|
|
239
286
|
};
|
|
240
287
|
}
|
|
241
|
-
return { runStartCommand };
|
|
288
|
+
return { runStartCommand, runShellCommand: runSetupCommand };
|
|
242
289
|
}
|
|
243
290
|
var defaultWriteOutput = (stream, data) => {
|
|
244
291
|
(stream === "stderr" ? process.stderr : process.stdout).write(data);
|
|
@@ -263,6 +310,7 @@ var WorkspaceCommandSupervisor = class {
|
|
|
263
310
|
awaitGitReadyFn;
|
|
264
311
|
waitForSidecarsFn;
|
|
265
312
|
runStartCommandFn;
|
|
313
|
+
syncDbSchemaFn;
|
|
266
314
|
loadForwardPortsFn;
|
|
267
315
|
writeOutput;
|
|
268
316
|
terminateStartCommand;
|
|
@@ -301,6 +349,13 @@ var WorkspaceCommandSupervisor = class {
|
|
|
301
349
|
this.waitForSidecarsFn = options.waitForSidecars ?? ((opts) => waitForSidecars({ onLog: opts.onLog, signal: opts.signal }));
|
|
302
350
|
const executors = defaultCommandExecutors();
|
|
303
351
|
this.runStartCommandFn = options.runStartCommand ?? executors.runStartCommand;
|
|
352
|
+
this.syncDbSchemaFn = options.syncDbSchema ?? ((opts) => runDbSchemaSync({
|
|
353
|
+
workspaceDir: this.workspaceDir,
|
|
354
|
+
env: this.env,
|
|
355
|
+
runCommand: executors.runShellCommand,
|
|
356
|
+
onOutput: opts.onOutput,
|
|
357
|
+
signal: opts.signal
|
|
358
|
+
}));
|
|
304
359
|
this.loadForwardPortsFn = options.loadForwardPorts ?? loadForwardPorts;
|
|
305
360
|
this.writeOutput = options.writeOutput ?? defaultWriteOutput;
|
|
306
361
|
this.terminateStartCommand = options.terminateStartCommand ?? terminateProcessGroup;
|
|
@@ -352,7 +407,6 @@ var WorkspaceCommandSupervisor = class {
|
|
|
352
407
|
});
|
|
353
408
|
return;
|
|
354
409
|
}
|
|
355
|
-
if (gitState === "ready") this.reportBootMilestoneFn("git_ready");
|
|
356
410
|
await this.waitForSidecarsFn({
|
|
357
411
|
onLog: (message) => this.forwardSetupOutput("stdout", `[sidecars] ${message}
|
|
358
412
|
`),
|
|
@@ -362,6 +416,8 @@ var WorkspaceCommandSupervisor = class {
|
|
|
362
416
|
this.reportBootMilestoneFn("sidecars_ready");
|
|
363
417
|
await this.loopReady;
|
|
364
418
|
if (this.stopped) return;
|
|
419
|
+
await this.syncDbSchema();
|
|
420
|
+
if (this.stopped) return;
|
|
365
421
|
const startCommandRunning = this.config?.startCommand ? await this.ensureStartCommandLaunched(this.config.startCommand) : false;
|
|
366
422
|
if (this.stopped) return;
|
|
367
423
|
this.reportBootMilestoneFn("start_command_launched");
|
|
@@ -374,6 +430,20 @@ var WorkspaceCommandSupervisor = class {
|
|
|
374
430
|
...previewPorts.length > 0 ? { previewPorts } : {}
|
|
375
431
|
});
|
|
376
432
|
}
|
|
433
|
+
/** Run the schema sync, forwarding its output as setup output so it lands in
|
|
434
|
+
* the card's setup log. A failure is announced rather than thrown: it is the
|
|
435
|
+
* exact condition that used to render as a silent "Displaying 0 results". */
|
|
436
|
+
async syncDbSchema() {
|
|
437
|
+
const outcome = await this.syncDbSchemaFn({
|
|
438
|
+
onOutput: (stream, data) => this.forwardSetupOutput(stream, data),
|
|
439
|
+
signal: this.abortController.signal
|
|
440
|
+
});
|
|
441
|
+
if (outcome !== "failed" || this.stopped) return;
|
|
442
|
+
this.connection.sendEvent({
|
|
443
|
+
type: "setup_error",
|
|
444
|
+
message: "Database schema sync failed \u2014 the app may error on queries touching recently added columns (see pod logs)"
|
|
445
|
+
});
|
|
446
|
+
}
|
|
377
447
|
restartStartCommand() {
|
|
378
448
|
if (this.stopped || !this.config?.startCommand) return;
|
|
379
449
|
this.connection.sendEvent({
|
|
@@ -696,8 +766,7 @@ var ProjectSessionRunner = class {
|
|
|
696
766
|
|
|
697
767
|
// src/usage/multi-key-probe.ts
|
|
698
768
|
import { mkdtemp, writeFile, copyFile, rm } from "fs/promises";
|
|
699
|
-
import {
|
|
700
|
-
import { join } from "path";
|
|
769
|
+
import { join as join2 } from "path";
|
|
701
770
|
var logger = createServiceLogger("multi-key-probe");
|
|
702
771
|
function gaugesToSamples(stdout) {
|
|
703
772
|
const { sessionUsage, weeklyUsage, sessionResetsAt, weeklyResetsAt, gauges } = parseUsageGauges(stdout);
|
|
@@ -725,12 +794,12 @@ function gaugesToSamples(stdout) {
|
|
|
725
794
|
async function isolatedProbe(token, now) {
|
|
726
795
|
let dir = null;
|
|
727
796
|
try {
|
|
728
|
-
dir = await mkdtemp(
|
|
729
|
-
await writeFile(
|
|
797
|
+
dir = await mkdtemp(join2(sessionTempBase(), "conveyor-usage-"));
|
|
798
|
+
await writeFile(join2(dir, ".credentials.json"), buildSynthesizedCredentials(token, now), {
|
|
730
799
|
encoding: "utf8",
|
|
731
800
|
mode: 384
|
|
732
801
|
});
|
|
733
|
-
await copyFile(claudeJsonPath(),
|
|
802
|
+
await copyFile(claudeJsonPath(), join2(dir, ".claude.json")).catch(() => {
|
|
734
803
|
});
|
|
735
804
|
return await runUsageProbe({ env: { ...process.env, CLAUDE_CONFIG_DIR: dir } });
|
|
736
805
|
} catch (error) {
|
|
@@ -767,18 +836,18 @@ async function probeKeysUsage(keys, deps = {}) {
|
|
|
767
836
|
|
|
768
837
|
// src/harness/pty/adapters/opencode-auth.ts
|
|
769
838
|
import { promises as fs } from "fs";
|
|
770
|
-
import { dirname, join as
|
|
839
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
771
840
|
import { homedir } from "os";
|
|
772
841
|
var logger2 = createServiceLogger("opencode-auth");
|
|
773
842
|
var OPENCODE_CODEX_PLUGIN = "opencode-openai-codex-auth@4.4.0";
|
|
774
843
|
var PLUGIN_PACKAGE = "opencode-openai-codex-auth";
|
|
775
844
|
function opencodeAuthPath(env) {
|
|
776
|
-
const dataHome = env.XDG_DATA_HOME ??
|
|
777
|
-
return
|
|
845
|
+
const dataHome = env.XDG_DATA_HOME ?? join3(env.HOME ?? homedir(), ".local", "share");
|
|
846
|
+
return join3(dataHome, "opencode", "auth.json");
|
|
778
847
|
}
|
|
779
848
|
function opencodeConfigPath(env) {
|
|
780
|
-
const configHome = env.XDG_CONFIG_HOME ??
|
|
781
|
-
return
|
|
849
|
+
const configHome = env.XDG_CONFIG_HOME ?? join3(env.HOME ?? homedir(), ".config");
|
|
850
|
+
return join3(configHome, "opencode", "opencode.json");
|
|
782
851
|
}
|
|
783
852
|
function parseOauthSeed(b64) {
|
|
784
853
|
if (!b64) return null;
|
|
@@ -808,7 +877,7 @@ async function readJsonFile(path) {
|
|
|
808
877
|
}
|
|
809
878
|
}
|
|
810
879
|
async function writeJsonFile(path, value) {
|
|
811
|
-
await fs.mkdir(
|
|
880
|
+
await fs.mkdir(dirname2(path), { recursive: true });
|
|
812
881
|
await fs.writeFile(path, `${JSON.stringify(value, null, 2)}
|
|
813
882
|
`, { mode: 384 });
|
|
814
883
|
}
|
|
@@ -926,267 +995,6 @@ function resolveTuiAdapter(kind = "claude-code") {
|
|
|
926
995
|
}
|
|
927
996
|
}
|
|
928
997
|
|
|
929
|
-
// src/tools/project-tools.ts
|
|
930
|
-
import { z } from "zod";
|
|
931
|
-
var CONTEXT_PATH_SHAPE = z.object({
|
|
932
|
-
type: z.enum(["rule", "doc", "file", "folder"]).describe("Link kind"),
|
|
933
|
-
path: z.string().min(1).max(500).describe("Repo-relative path"),
|
|
934
|
-
label: z.string().max(100).optional()
|
|
935
|
-
});
|
|
936
|
-
function errText(prefix, error) {
|
|
937
|
-
return textResult(`${prefix}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
938
|
-
}
|
|
939
|
-
function buildListTagsTool(connection, projectId) {
|
|
940
|
-
return defineTool(
|
|
941
|
-
"list_tags",
|
|
942
|
-
"List this project's tags (id, name, color). Use the ids with update_tag.",
|
|
943
|
-
{},
|
|
944
|
-
async () => {
|
|
945
|
-
try {
|
|
946
|
-
const tags = await connection.call("listProjectTags", { projectId });
|
|
947
|
-
return textResult(JSON.stringify(tags, null, 2));
|
|
948
|
-
} catch (error) {
|
|
949
|
-
return errText("Failed to list tags", error);
|
|
950
|
-
}
|
|
951
|
-
},
|
|
952
|
-
{ annotations: { readOnlyHint: true } }
|
|
953
|
-
);
|
|
954
|
-
}
|
|
955
|
-
function buildCreateTagTool(connection, projectId) {
|
|
956
|
-
return defineTool(
|
|
957
|
-
"create_tag",
|
|
958
|
-
"Create a project tag. Include a crisp description and contextPaths (rule/doc/file/folder links agents auto-load when working on matching tasks). Fails if the name already exists.",
|
|
959
|
-
{
|
|
960
|
-
name: z.string().min(1).max(50),
|
|
961
|
-
color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional().describe("#RRGGBB (default gray)"),
|
|
962
|
-
description: z.string().max(500).optional(),
|
|
963
|
-
contextPaths: z.array(CONTEXT_PATH_SHAPE).max(20).optional()
|
|
964
|
-
},
|
|
965
|
-
async ({ name, color, description, contextPaths }) => {
|
|
966
|
-
try {
|
|
967
|
-
const result = await connection.call("createProjectTag", {
|
|
968
|
-
projectId,
|
|
969
|
-
name,
|
|
970
|
-
color,
|
|
971
|
-
description,
|
|
972
|
-
contextPaths
|
|
973
|
-
});
|
|
974
|
-
return textResult(`Tag created: ${result.id}`);
|
|
975
|
-
} catch (error) {
|
|
976
|
-
return errText("Failed to create tag", error);
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
);
|
|
980
|
-
}
|
|
981
|
-
function buildUpdateTagTool(connection, projectId) {
|
|
982
|
-
return defineTool(
|
|
983
|
-
"update_tag",
|
|
984
|
-
"Update a tag's name, color, description, or contextPaths. contextPaths is a FULL replacement \u2014 include existing links you want to keep. Verify paths exist in the repo first.",
|
|
985
|
-
{
|
|
986
|
-
tagId: z.string().describe("Tag id from list_tags"),
|
|
987
|
-
name: z.string().min(1).max(50).optional(),
|
|
988
|
-
color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
|
|
989
|
-
description: z.string().max(500).optional(),
|
|
990
|
-
contextPaths: z.array(CONTEXT_PATH_SHAPE).max(20).optional()
|
|
991
|
-
},
|
|
992
|
-
async ({ tagId, name, color, description, contextPaths }) => {
|
|
993
|
-
try {
|
|
994
|
-
await connection.call("updateProjectTag", {
|
|
995
|
-
projectId,
|
|
996
|
-
tagId,
|
|
997
|
-
name,
|
|
998
|
-
color,
|
|
999
|
-
description,
|
|
1000
|
-
contextPaths
|
|
1001
|
-
});
|
|
1002
|
-
return textResult(`Tag updated: ${tagId}`);
|
|
1003
|
-
} catch (error) {
|
|
1004
|
-
return errText("Failed to update tag", error);
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
);
|
|
1008
|
-
}
|
|
1009
|
-
function buildCreateSuggestionTool(connection, projectId) {
|
|
1010
|
-
return defineTool(
|
|
1011
|
-
"create_suggestion",
|
|
1012
|
-
"File a project suggestion (idea/improvement for maintainers to review). Duplicates are AI-deduped into an existing suggestion with an upvote. Returns the suggestion id.",
|
|
1013
|
-
{
|
|
1014
|
-
title: z.string().min(1).describe("Short title"),
|
|
1015
|
-
description: z.string().optional().describe("1-3 sentences: what should change and why"),
|
|
1016
|
-
tag_names: z.array(z.string()).optional().describe("Tag names to categorize")
|
|
1017
|
-
},
|
|
1018
|
-
async ({ title, description, tag_names }) => {
|
|
1019
|
-
try {
|
|
1020
|
-
const result = await connection.call("createProjectSuggestion", {
|
|
1021
|
-
projectId,
|
|
1022
|
-
title,
|
|
1023
|
-
description,
|
|
1024
|
-
tagNames: tag_names
|
|
1025
|
-
});
|
|
1026
|
-
return textResult(
|
|
1027
|
-
result.merged ? `Merged into existing suggestion ${result.mergedIntoId ?? result.id} (id: ${result.id})` : `Suggestion created: ${result.id}`
|
|
1028
|
-
);
|
|
1029
|
-
} catch (error) {
|
|
1030
|
-
return errText("Failed to create suggestion", error);
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
);
|
|
1034
|
-
}
|
|
1035
|
-
function buildPostToProjectChatTool(connection, projectId) {
|
|
1036
|
-
return defineTool(
|
|
1037
|
-
"post_to_project_chat",
|
|
1038
|
-
"Post a markdown message to the PROJECT chat \u2014 use once at the end of an audit for the summary the team reads.",
|
|
1039
|
-
{
|
|
1040
|
-
message: z.string().min(1).max(2e4),
|
|
1041
|
-
kind: z.enum(["tag_audit_summary"]).optional().describe(
|
|
1042
|
-
"Set to 'tag_audit_summary' when posting a tag-audit summary so it is also saved to the persistent tag history"
|
|
1043
|
-
)
|
|
1044
|
-
},
|
|
1045
|
-
async ({ message, kind }) => {
|
|
1046
|
-
try {
|
|
1047
|
-
await connection.call("postToProjectChat", { projectId, content: message, kind });
|
|
1048
|
-
return textResult("Posted to project chat");
|
|
1049
|
-
} catch (error) {
|
|
1050
|
-
return errText("Failed to post to project chat", error);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
);
|
|
1054
|
-
}
|
|
1055
|
-
function buildGetProjectTaskTool(connection, projectId) {
|
|
1056
|
-
return defineTool(
|
|
1057
|
-
"get_project_task",
|
|
1058
|
-
"Fetch any task in the project by id or slug: title, description, plan, status, and metadata. The audit evidence trail starts here.",
|
|
1059
|
-
{
|
|
1060
|
-
taskId: z.string().describe("Task id or slug")
|
|
1061
|
-
},
|
|
1062
|
-
async ({ taskId }) => {
|
|
1063
|
-
try {
|
|
1064
|
-
const task = await connection.call("getProjectTask", { projectId, taskId });
|
|
1065
|
-
return textResult(JSON.stringify(task, null, 2));
|
|
1066
|
-
} catch (error) {
|
|
1067
|
-
return errText("Failed to get task", error);
|
|
1068
|
-
}
|
|
1069
|
-
},
|
|
1070
|
-
{ annotations: { readOnlyHint: true } }
|
|
1071
|
-
);
|
|
1072
|
-
}
|
|
1073
|
-
function buildReadProjectTaskChatTool(connection, projectId) {
|
|
1074
|
-
return defineTool(
|
|
1075
|
-
"read_project_task_chat",
|
|
1076
|
-
"Read any project task's chat messages (newest last). role 'user' rows are HUMAN turns; 'assistant'/'system' rows are agent posts and activity-log entries.",
|
|
1077
|
-
{
|
|
1078
|
-
taskId: z.string().describe("Task id or slug"),
|
|
1079
|
-
limit: z.number().int().min(1).max(200).optional().describe("Messages to fetch (default 50)")
|
|
1080
|
-
},
|
|
1081
|
-
async ({ taskId, limit }) => {
|
|
1082
|
-
try {
|
|
1083
|
-
const chat = await connection.call("getProjectTaskChat", {
|
|
1084
|
-
projectId,
|
|
1085
|
-
taskId,
|
|
1086
|
-
limit: limit ?? 50
|
|
1087
|
-
});
|
|
1088
|
-
return textResult(JSON.stringify(chat, null, 2));
|
|
1089
|
-
} catch (error) {
|
|
1090
|
-
return errText("Failed to read task chat", error);
|
|
1091
|
-
}
|
|
1092
|
-
},
|
|
1093
|
-
{ annotations: { readOnlyHint: true } }
|
|
1094
|
-
);
|
|
1095
|
-
}
|
|
1096
|
-
function buildGetProjectTaskLogsTool(connection, projectId) {
|
|
1097
|
-
return defineTool(
|
|
1098
|
-
"get_project_task_logs",
|
|
1099
|
-
"Read any project task's persisted agent event stream (message / tool_use / turn_end / error / completed). Turn boundaries are turn_end events. Entries are truncated to ~2KB each; max 500 per call.",
|
|
1100
|
-
{
|
|
1101
|
-
taskId: z.string().describe("Task id or slug"),
|
|
1102
|
-
limit: z.number().int().min(1).max(500).optional().describe("Entries to fetch (default 50)"),
|
|
1103
|
-
source: z.enum(["agent", "application"]).optional().describe("Filter: 'agent' = model events (default useful for grading)")
|
|
1104
|
-
},
|
|
1105
|
-
async ({ taskId, limit, source }) => {
|
|
1106
|
-
try {
|
|
1107
|
-
const logs = await connection.call("getProjectTaskCli", {
|
|
1108
|
-
projectId,
|
|
1109
|
-
taskId,
|
|
1110
|
-
limit: limit ?? 50,
|
|
1111
|
-
source
|
|
1112
|
-
});
|
|
1113
|
-
return textResult(JSON.stringify(logs, null, 2));
|
|
1114
|
-
} catch (error) {
|
|
1115
|
-
return errText("Failed to get task logs", error);
|
|
1116
|
-
}
|
|
1117
|
-
},
|
|
1118
|
-
{ annotations: { readOnlyHint: true } }
|
|
1119
|
-
);
|
|
1120
|
-
}
|
|
1121
|
-
var TURN_GRADE_SHAPE = z.object({
|
|
1122
|
-
turnIndex: z.number().int().min(0),
|
|
1123
|
-
phase: z.enum(["planning", "building", "human"]),
|
|
1124
|
-
grade: z.enum(["correct", "neutral", "blunder"]),
|
|
1125
|
-
reasoning: z.string(),
|
|
1126
|
-
eventType: z.string().describe('e.g. "message", "tool_use", "human_message"'),
|
|
1127
|
-
eventSummary: z.string().max(200).describe("\u2264120 chars of what happened this turn")
|
|
1128
|
-
});
|
|
1129
|
-
var HUMAN_EVAL_SHAPE = z.object({
|
|
1130
|
-
messageIndex: z.number().int().min(0).describe("Index into the task's human messages, oldest first"),
|
|
1131
|
-
rating: z.number().int().min(-1).max(1),
|
|
1132
|
-
reasoning: z.string()
|
|
1133
|
-
});
|
|
1134
|
-
function buildReportTaskAuditResultTool(connection, projectId) {
|
|
1135
|
-
return defineTool(
|
|
1136
|
-
"report_task_audit_result",
|
|
1137
|
-
"Persist one audited task's grades (call once per task after grading it). Pass error instead to mark the audit failed when the evidence is unusable.",
|
|
1138
|
-
{
|
|
1139
|
-
taskId: z.string().describe("The audited task's id (NOT slug)"),
|
|
1140
|
-
summary: z.string().describe("3-6 sentences: what went well, what was wasted"),
|
|
1141
|
-
turnGrades: z.array(TURN_GRADE_SHAPE),
|
|
1142
|
-
planningAccuracy: z.number().min(0).max(1).nullable(),
|
|
1143
|
-
buildingAccuracy: z.number().min(0).max(1).nullable(),
|
|
1144
|
-
humanAccuracy: z.number().min(0).max(1).nullable(),
|
|
1145
|
-
planningCorrect: z.number().int().min(0),
|
|
1146
|
-
planningNeutral: z.number().int().min(0),
|
|
1147
|
-
planningBlunder: z.number().int().min(0),
|
|
1148
|
-
buildingCorrect: z.number().int().min(0),
|
|
1149
|
-
buildingNeutral: z.number().int().min(0),
|
|
1150
|
-
buildingBlunder: z.number().int().min(0),
|
|
1151
|
-
humanCorrect: z.number().int().min(0),
|
|
1152
|
-
humanNeutral: z.number().int().min(0),
|
|
1153
|
-
humanBlunder: z.number().int().min(0),
|
|
1154
|
-
humanEvaluations: z.array(HUMAN_EVAL_SHAPE).optional(),
|
|
1155
|
-
suggestionIds: z.array(z.string()).describe("Suggestion ids filed for this task, or []"),
|
|
1156
|
-
auditCostUsd: z.number().nullable(),
|
|
1157
|
-
model: z.string().nullable().describe("The model you are running as"),
|
|
1158
|
-
error: z.string().optional().describe("Set ONLY to mark this task's audit failed")
|
|
1159
|
-
},
|
|
1160
|
-
async (input) => {
|
|
1161
|
-
try {
|
|
1162
|
-
await connection.call("reportTaskAuditResult", {
|
|
1163
|
-
projectId,
|
|
1164
|
-
...input,
|
|
1165
|
-
humanEvaluations: input.humanEvaluations ?? []
|
|
1166
|
-
});
|
|
1167
|
-
return textResult(
|
|
1168
|
-
input.error ? `Audit for ${input.taskId} marked failed` : `Audit result saved for ${input.taskId}`
|
|
1169
|
-
);
|
|
1170
|
-
} catch (error) {
|
|
1171
|
-
return errText("Failed to report audit result", error);
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
);
|
|
1175
|
-
}
|
|
1176
|
-
function buildProjectTools(connection, projectId) {
|
|
1177
|
-
return [
|
|
1178
|
-
buildListTagsTool(connection, projectId),
|
|
1179
|
-
buildCreateTagTool(connection, projectId),
|
|
1180
|
-
buildUpdateTagTool(connection, projectId),
|
|
1181
|
-
buildCreateSuggestionTool(connection, projectId),
|
|
1182
|
-
buildPostToProjectChatTool(connection, projectId),
|
|
1183
|
-
buildGetProjectTaskTool(connection, projectId),
|
|
1184
|
-
buildReadProjectTaskChatTool(connection, projectId),
|
|
1185
|
-
buildGetProjectTaskLogsTool(connection, projectId),
|
|
1186
|
-
buildReportTaskAuditResultTool(connection, projectId)
|
|
1187
|
-
];
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
998
|
// src/runner/adhoc-session-runner.ts
|
|
1191
999
|
var ADHOC_SYSTEM_NOTE = "You are running in an ad-hoc Conveyor scratch pod \u2014 an interactive terminal on the project's repository checked out at its default branch. There is no task or plan; help the human with whatever they ask directly.";
|
|
1192
1000
|
var HEADLESS_SYSTEM_NOTE = "You are running a HEADLESS Conveyor session on the project's repository \u2014 your instructions were auto-submitted as the first message. Work them to completion autonomously and never wait for user input; a human may attach to this terminal to watch or interject, but none is required.";
|
|
@@ -1205,11 +1013,14 @@ function resolveAdhocTui(env) {
|
|
|
1205
1013
|
if (TUI_KINDS.includes(raw)) return raw;
|
|
1206
1014
|
throw new Error(`Unknown TUI "${raw}" in CONVEYOR_TUI (expected: ${TUI_KINDS.join(", ")})`);
|
|
1207
1015
|
}
|
|
1208
|
-
function buildAdhocPtyBridge(connection) {
|
|
1016
|
+
function buildAdhocPtyBridge(connection, onInputActivity) {
|
|
1209
1017
|
return {
|
|
1210
1018
|
sendOutput: (data, dims) => connection.sendPtyOutput(data, dims),
|
|
1211
1019
|
sendChatEvent: (event) => connection.sendPtyChatEvent(event),
|
|
1212
|
-
onInput: (handler) => connection.onPtyInput(
|
|
1020
|
+
onInput: (handler) => connection.onPtyInput((data) => {
|
|
1021
|
+
onInputActivity?.();
|
|
1022
|
+
handler(data);
|
|
1023
|
+
}),
|
|
1213
1024
|
onResize: (handler) => connection.onPtyResize(handler)
|
|
1214
1025
|
};
|
|
1215
1026
|
}
|
|
@@ -1258,11 +1069,18 @@ var AdhocSessionRunner = class {
|
|
|
1258
1069
|
this.callbacks = callbacks;
|
|
1259
1070
|
this.connection = deps?.connection ?? new AgentConnection(config.connection);
|
|
1260
1071
|
this.harness = deps?.harness ?? new PtyHarness(
|
|
1261
|
-
|
|
1072
|
+
// A keystroke is real human activity — re-arm the idle backstop so an
|
|
1073
|
+
// actively-typing human (or a >60-min audit run) is never hard-stopped
|
|
1074
|
+
// by the idle timer, mirroring ShellSessionRunner. `this.lifecycle` is
|
|
1075
|
+
// assigned later in this constructor but is always set by the time a
|
|
1076
|
+
// keystroke can arrive at runtime.
|
|
1077
|
+
buildAdhocPtyBridge(this.connection, () => this.lifecycle.startIdleTimer()),
|
|
1262
1078
|
resolveTuiAdapter(resolveAdhocTui(process.env))
|
|
1263
1079
|
);
|
|
1080
|
+
const portVisibility = new CodespacePortVisibility();
|
|
1264
1081
|
this.portDiscovery = deps?.portDiscovery ?? new PortDiscovery({
|
|
1265
|
-
report: (ports) => this.connection.reportDiscoveredPorts(ports)
|
|
1082
|
+
report: (ports) => this.connection.reportDiscoveredPorts(ports),
|
|
1083
|
+
onReported: (ports) => portVisibility.ensureVisible(ports.map(({ port }) => port))
|
|
1266
1084
|
});
|
|
1267
1085
|
this.commandSupervisor = deps?.commandSupervisor ?? new WorkspaceCommandSupervisor({
|
|
1268
1086
|
config: loadConveyorConfig(),
|
|
@@ -1344,7 +1162,11 @@ var AdhocSessionRunner = class {
|
|
|
1344
1162
|
initialPrompt,
|
|
1345
1163
|
conveyorMcpServer: this.harness.createMcpServer({
|
|
1346
1164
|
name: "conveyor",
|
|
1347
|
-
tools: buildProjectTools(
|
|
1165
|
+
tools: buildProjectTools(
|
|
1166
|
+
this.connection,
|
|
1167
|
+
this.config.projectId,
|
|
1168
|
+
this.config.workspaceDir
|
|
1169
|
+
)
|
|
1348
1170
|
})
|
|
1349
1171
|
} : void 0;
|
|
1350
1172
|
const options = buildAdhocQueryOptions(
|
|
@@ -1463,9 +1285,9 @@ function buildReviewChildEnv(baseEnv, data) {
|
|
|
1463
1285
|
env.CONVEYOR_TASK_TOKEN = data.sessionJwt;
|
|
1464
1286
|
env.CONVEYOR_SESSION_ID = data.sessionId;
|
|
1465
1287
|
env.CONVEYOR_MODE = "code-review";
|
|
1288
|
+
env.CONVEYOR_WORKBENCH_TOKEN ??= baseEnv.POD_BOOTSTRAP_TOKEN;
|
|
1466
1289
|
delete env.POD_BOOTSTRAP_TOKEN;
|
|
1467
1290
|
delete env.CONVEYOR_BOOTSTRAP_TOKEN;
|
|
1468
|
-
delete env.CONVEYOR_SETUP_COMMAND;
|
|
1469
1291
|
delete env.CONVEYOR_START_COMMAND;
|
|
1470
1292
|
delete env.CONVEYOR_GIT_READY;
|
|
1471
1293
|
delete env.CONVEYOR_GIT_READY_MARKER;
|
|
@@ -1621,7 +1443,6 @@ function buildSpawnedChildEnv(baseEnv, data) {
|
|
|
1621
1443
|
env.CONVEYOR_PROJECT_ID = data.projectId;
|
|
1622
1444
|
delete env.POD_BOOTSTRAP_TOKEN;
|
|
1623
1445
|
delete env.CONVEYOR_BOOTSTRAP_TOKEN;
|
|
1624
|
-
delete env.CONVEYOR_SETUP_COMMAND;
|
|
1625
1446
|
delete env.CONVEYOR_START_COMMAND;
|
|
1626
1447
|
delete env.CONVEYOR_AGENT_MODE;
|
|
1627
1448
|
delete env.CONVEYOR_IS_AUTO;
|
|
@@ -1759,7 +1580,7 @@ var ShellSessionRunner = class {
|
|
|
1759
1580
|
constructor(config, deps) {
|
|
1760
1581
|
this.config = config;
|
|
1761
1582
|
this.connection = deps?.connection ?? new AgentConnection(config.connection);
|
|
1762
|
-
this.loadSpawn = deps?.loadSpawn ??
|
|
1583
|
+
this.loadSpawn = deps?.loadSpawn ?? resolvePtySpawn;
|
|
1763
1584
|
this.lifecycle = new Lifecycle(
|
|
1764
1585
|
// No git flush — the human commits/pushes explicitly from the shell.
|
|
1765
1586
|
{ ...DEFAULT_LIFECYCLE_CONFIG, gitFlushIntervalMs: 0, ...config.lifecycle },
|
|
@@ -1898,9 +1719,14 @@ function createSpawnedChildRunner(inputs) {
|
|
|
1898
1719
|
);
|
|
1899
1720
|
}
|
|
1900
1721
|
|
|
1722
|
+
// src/runner/host-modes.ts
|
|
1723
|
+
function hostsSpawnedChildren(mode) {
|
|
1724
|
+
return mode === "task" || mode === "pack";
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1901
1727
|
// src/cli.ts
|
|
1902
1728
|
if (process.argv[2] === "boot") {
|
|
1903
|
-
const { runBoot } = await import("./boot-
|
|
1729
|
+
const { runBoot } = await import("./boot-I353EAK6.js");
|
|
1904
1730
|
process.exit(await runBoot(process.argv.slice(3)));
|
|
1905
1731
|
}
|
|
1906
1732
|
if (isLegacyEntrypointLaunch(process.env)) {
|
|
@@ -1909,8 +1735,8 @@ if (isLegacyEntrypointLaunch(process.env)) {
|
|
|
1909
1735
|
process.exit(1);
|
|
1910
1736
|
}
|
|
1911
1737
|
if (process.argv.includes("--version")) {
|
|
1912
|
-
const __dirname =
|
|
1913
|
-
const pkgPath =
|
|
1738
|
+
const __dirname = dirname3(fileURLToPath(import.meta.url));
|
|
1739
|
+
const pkgPath = join4(__dirname, "..", "package.json");
|
|
1914
1740
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
1915
1741
|
process.stdout.write(pkg.version + "\n");
|
|
1916
1742
|
process.exit(0);
|
|
@@ -1918,6 +1744,7 @@ if (process.argv.includes("--version")) {
|
|
|
1918
1744
|
var logger6 = createServiceLogger("CLI");
|
|
1919
1745
|
var exitContext = {};
|
|
1920
1746
|
var exitLogged = false;
|
|
1747
|
+
var shuttingDown = false;
|
|
1921
1748
|
function logAgentExit(reason, opts) {
|
|
1922
1749
|
if (exitLogged) return;
|
|
1923
1750
|
exitLogged = true;
|
|
@@ -1970,28 +1797,39 @@ function isExpectedAbortError(error) {
|
|
|
1970
1797
|
const hasAbortCode = !("code" in error) || error.code === void 0 || error.code === "ABORT_ERR";
|
|
1971
1798
|
return hasAbortMessage && hasAbortCode;
|
|
1972
1799
|
}
|
|
1800
|
+
function exitOnPermissionDenial(err) {
|
|
1801
|
+
if (!isPermissionDeniedError(err)) return false;
|
|
1802
|
+
logger6.error("Not authorized for this project \u2014 parking instead of crash-looping", {
|
|
1803
|
+
error: err.message
|
|
1804
|
+
});
|
|
1805
|
+
logAgentExit("unauthorized", { exitCode: 0 });
|
|
1806
|
+
process.exit(0);
|
|
1807
|
+
}
|
|
1973
1808
|
process.on("uncaughtException", (err) => {
|
|
1974
1809
|
if (err.code === "EPIPE") return;
|
|
1975
|
-
if (isExpectedAbortError(err)) {
|
|
1810
|
+
if (shuttingDown && isExpectedAbortError(err)) {
|
|
1976
1811
|
logger6.info("Ignored expected abort after shutdown", { error: err.message, code: err.code });
|
|
1977
1812
|
return;
|
|
1978
1813
|
}
|
|
1814
|
+
if (exitOnPermissionDenial(err)) return;
|
|
1979
1815
|
logger6.error("Uncaught exception", { error: err.message, code: err.code });
|
|
1980
1816
|
logAgentExit("uncaught_exception", { exitCode: 1 });
|
|
1981
1817
|
process.exit(1);
|
|
1982
1818
|
});
|
|
1983
1819
|
process.on("unhandledRejection", (reason) => {
|
|
1984
1820
|
const err = reason instanceof Error ? reason : new Error(String(reason));
|
|
1985
|
-
if (isExpectedAbortError(err)) {
|
|
1821
|
+
if (shuttingDown && isExpectedAbortError(err)) {
|
|
1986
1822
|
logger6.info("Ignored expected abort rejection after shutdown", { error: err.message });
|
|
1987
1823
|
return;
|
|
1988
1824
|
}
|
|
1825
|
+
if (exitOnPermissionDenial(err)) return;
|
|
1989
1826
|
logger6.error("Unhandled rejection", { error: err.message });
|
|
1990
1827
|
logAgentExit("unhandled_rejection", { exitCode: 1 });
|
|
1991
1828
|
process.exit(1);
|
|
1992
1829
|
});
|
|
1993
1830
|
if (process.env.CONVEYOR_MODE === "workbench") {
|
|
1994
|
-
const { startWorkbenchServer } = await import("./server-
|
|
1831
|
+
const { startWorkbenchServer } = await import("./server-NIOBJ46G.js");
|
|
1832
|
+
const { oomWatchdogOptionsFromEnv } = await import("./oom-watchdog-U7JERHA2.js");
|
|
1995
1833
|
const { DEFAULT_WORKBENCH_PORT } = await import("./protocol-QLVS5W6O.js");
|
|
1996
1834
|
const port = Number(process.env.CONVEYOR_WORKBENCH_PORT) || DEFAULT_WORKBENCH_PORT;
|
|
1997
1835
|
const token = process.env.CONVEYOR_WORKBENCH_TOKEN ?? process.env.POD_BOOTSTRAP_TOKEN ?? "";
|
|
@@ -1999,12 +1837,17 @@ if (process.env.CONVEYOR_MODE === "workbench") {
|
|
|
1999
1837
|
logger6.error("workbench mode requires POD_BOOTSTRAP_TOKEN (or CONVEYOR_WORKBENCH_TOKEN)");
|
|
2000
1838
|
process.exit(1);
|
|
2001
1839
|
}
|
|
2002
|
-
const pkgDir =
|
|
2003
|
-
const pkg = JSON.parse(readFileSync(
|
|
1840
|
+
const pkgDir = dirname3(fileURLToPath(import.meta.url));
|
|
1841
|
+
const pkg = JSON.parse(readFileSync(join4(pkgDir, "..", "package.json"), "utf-8"));
|
|
2004
1842
|
const handle = await startWorkbenchServer({
|
|
2005
1843
|
port,
|
|
2006
1844
|
token,
|
|
2007
|
-
version: pkg.version ?? "unknown"
|
|
1845
|
+
version: pkg.version ?? "unknown",
|
|
1846
|
+
oomWatchdog: oomWatchdogOptionsFromEnv({
|
|
1847
|
+
info: (m) => logger6.info(m),
|
|
1848
|
+
warn: (m) => logger6.warn(m),
|
|
1849
|
+
error: (m) => logger6.error(m)
|
|
1850
|
+
})
|
|
2008
1851
|
});
|
|
2009
1852
|
logger6.info(`Workbench launcher listening on 127.0.0.1:${handle.port}`);
|
|
2010
1853
|
process.on("SIGTERM", () => process.exit(0));
|
|
@@ -2060,8 +1903,14 @@ if (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === "adhoc") {
|
|
|
2060
1903
|
exitContext.sessionId = projectIdentity.sessionId;
|
|
2061
1904
|
exitContext.workspaceId = projectIdentity.workspaceId;
|
|
2062
1905
|
exitContext.runnerMode = "adhoc";
|
|
2063
|
-
process.on("SIGTERM", () =>
|
|
2064
|
-
|
|
1906
|
+
process.on("SIGTERM", () => {
|
|
1907
|
+
shuttingDown = true;
|
|
1908
|
+
adhocRunner.stop();
|
|
1909
|
+
});
|
|
1910
|
+
process.on("SIGINT", () => {
|
|
1911
|
+
shuttingDown = true;
|
|
1912
|
+
adhocRunner.stop();
|
|
1913
|
+
});
|
|
2065
1914
|
await adhocRunner.run();
|
|
2066
1915
|
const adhocError = adhocRunner.finalState === "error";
|
|
2067
1916
|
logAgentExit(adhocError ? "error" : "clean", {
|
|
@@ -2093,8 +1942,14 @@ if (!CONVEYOR_TASK_ID && projectIdentity) {
|
|
|
2093
1942
|
exitContext.sessionId = projectIdentity.sessionId;
|
|
2094
1943
|
exitContext.workspaceId = projectIdentity.workspaceId;
|
|
2095
1944
|
exitContext.runnerMode = "pm";
|
|
2096
|
-
process.on("SIGTERM", () =>
|
|
2097
|
-
|
|
1945
|
+
process.on("SIGTERM", () => {
|
|
1946
|
+
shuttingDown = true;
|
|
1947
|
+
projectRunner.stop();
|
|
1948
|
+
});
|
|
1949
|
+
process.on("SIGINT", () => {
|
|
1950
|
+
shuttingDown = true;
|
|
1951
|
+
projectRunner.stop();
|
|
1952
|
+
});
|
|
2098
1953
|
await projectRunner.run();
|
|
2099
1954
|
const projectError = projectRunner.finalState === "error";
|
|
2100
1955
|
logAgentExit(projectError ? "error" : "clean", {
|
|
@@ -2145,8 +2000,14 @@ if (CONVEYOR_MODE === "shell" || CONVEYOR_MODE === "adhoc") {
|
|
|
2145
2000
|
mode: CONVEYOR_MODE,
|
|
2146
2001
|
sessionId: spawnedSessionId
|
|
2147
2002
|
});
|
|
2148
|
-
process.on("SIGTERM", () =>
|
|
2149
|
-
|
|
2003
|
+
process.on("SIGTERM", () => {
|
|
2004
|
+
shuttingDown = true;
|
|
2005
|
+
childRunner.stop();
|
|
2006
|
+
});
|
|
2007
|
+
process.on("SIGINT", () => {
|
|
2008
|
+
shuttingDown = true;
|
|
2009
|
+
childRunner.stop();
|
|
2010
|
+
});
|
|
2150
2011
|
await childRunner.run();
|
|
2151
2012
|
const childError = childRunner.finalState === "error";
|
|
2152
2013
|
logAgentExit(childError ? "error" : "clean", {
|
|
@@ -2191,6 +2052,7 @@ var shutdownSignal;
|
|
|
2191
2052
|
var workspaceCommandSupervisor = null;
|
|
2192
2053
|
var shutdownCompletion = null;
|
|
2193
2054
|
var shutdownAgent = (signal) => {
|
|
2055
|
+
shuttingDown = true;
|
|
2194
2056
|
logger6.info(`Received ${signal}, flushing git and stopping agent`);
|
|
2195
2057
|
const commandShutdown = stopWorkspaceCommands(workspaceCommandSupervisor);
|
|
2196
2058
|
shutdownSignal = signal;
|
|
@@ -2254,7 +2116,7 @@ void checkSessionTaskIdentity({
|
|
|
2254
2116
|
},
|
|
2255
2117
|
logger: logger6
|
|
2256
2118
|
});
|
|
2257
|
-
if (CONVEYOR_MODE
|
|
2119
|
+
if (hostsSpawnedChildren(CONVEYOR_MODE)) {
|
|
2258
2120
|
runner.connection.onSpawnReview((data) => {
|
|
2259
2121
|
void reviewChildren.spawn(data).catch((err) => {
|
|
2260
2122
|
logger6.error("Review child spawn threw", {
|
|
@@ -2267,7 +2129,7 @@ if (CONVEYOR_MODE === "task") {
|
|
|
2267
2129
|
});
|
|
2268
2130
|
});
|
|
2269
2131
|
}
|
|
2270
|
-
if (CONVEYOR_MODE
|
|
2132
|
+
if (hostsSpawnedChildren(CONVEYOR_MODE)) {
|
|
2271
2133
|
runner.connection.onSpawnTui((data) => {
|
|
2272
2134
|
void sessionChildren.spawn(data).catch((err) => {
|
|
2273
2135
|
logger6.error("Session child spawn threw", {
|