@cabane/companion 0.6.203 → 0.6.205
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/README.md +25 -1
- package/dist/cli.js +2010 -2125
- package/dist/launch.js +5 -23
- package/dist/pairing-config.js +29 -45
- package/dist/runtime.js +161 -120
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -133,6 +133,16 @@ var ApiError = class extends CompanionError {
|
|
|
133
133
|
status;
|
|
134
134
|
body;
|
|
135
135
|
};
|
|
136
|
+
var EdgeBlockError = class extends ApiError {
|
|
137
|
+
constructor(status, ray, requestId) {
|
|
138
|
+
super(status, `${status} blocked by a proxy in front of Cabane`);
|
|
139
|
+
this.ray = ray;
|
|
140
|
+
this.requestId = requestId;
|
|
141
|
+
this.name = "EdgeBlockError";
|
|
142
|
+
}
|
|
143
|
+
ray;
|
|
144
|
+
requestId;
|
|
145
|
+
};
|
|
136
146
|
var ConfigError = class extends CompanionError {
|
|
137
147
|
constructor(message) {
|
|
138
148
|
super(message);
|
|
@@ -167,25 +177,7 @@ var prepareHookSchema = z.object({
|
|
|
167
177
|
// Wall-clock cap for the hook. Provisioning is slow (minutes), so the
|
|
168
178
|
// default is generous; a hook that hangs past this is killed and the turn
|
|
169
179
|
// fails with a clear timeout message rather than pinning the companion.
|
|
170
|
-
timeoutMs: z.number().int().positive().optional()
|
|
171
|
-
// Re-invoke the hook when a prepared result already exists, in VALIDATE
|
|
172
|
-
// mode: the cached result is handed back as `prepared` and stdout is
|
|
173
|
-
// ignored, so the cwd cannot move. Its only power is to exit non-zero and
|
|
174
|
-
// fail the turn. The hook resolves once per (conversation, agent), so a
|
|
175
|
-
// later message asking for a different environment is otherwise silently
|
|
176
|
-
// ignored; this lets a hook refuse it out loud.
|
|
177
|
-
//
|
|
178
|
-
// Default OFF: a hook that provisions unconditionally must not start
|
|
179
|
-
// running on every turn because the companion upgraded.
|
|
180
|
-
validateCached: z.boolean().optional(),
|
|
181
|
-
// Independent operator-owned reporter. Receives sanitized failure metadata
|
|
182
|
-
// on stdin; never re-enters this hook and cannot change the turn outcome.
|
|
183
|
-
failureReporter: z.object({
|
|
184
|
-
command: z.string().min(1),
|
|
185
|
-
args: z.array(z.string()).optional(),
|
|
186
|
-
env: z.record(z.string(), z.string()).optional(),
|
|
187
|
-
timeoutMs: z.number().int().positive().max(3e4).optional()
|
|
188
|
-
}).strict().optional()
|
|
180
|
+
timeoutMs: z.number().int().positive().optional()
|
|
189
181
|
}).strict();
|
|
190
182
|
var DEFAULT_TIMEOUT_MS = 10 * 6e4;
|
|
191
183
|
var prepareResultSchema = z.object({
|
|
@@ -260,8 +252,7 @@ var companionConfigSchema = z2.object({
|
|
|
260
252
|
// The DEVICE-LEVEL prepare hook, for every agent assigned here unless its own
|
|
261
253
|
// `agents` row names one. Per-agent hooks alone make the config a second
|
|
262
254
|
// silent roster: an agent nobody listed gets no hook and no error, and starts
|
|
263
|
-
// in the operator's `$HOME
|
|
264
|
-
// 2026-08-17).
|
|
255
|
+
// in the operator's `$HOME`.
|
|
265
256
|
prepareHook: prepareHookSchema.optional(),
|
|
266
257
|
// `dashboardPort` and `autoOpen` are IGNORED by the CLI (no port, no browser)
|
|
267
258
|
// but stay in the schema so an existing file still parses; the Electron shell
|
|
@@ -298,9 +289,10 @@ var companionConfigSchema = z2.object({
|
|
|
298
289
|
root: z2.string().min(1).refine(isRootPath, { message: "must be an absolute path, or start with ~/" }).optional(),
|
|
299
290
|
// An argv prefix the operator puts in front of every turn's runner: the companion starts
|
|
300
291
|
// `<prefix…> <its own run-turn command…>` instead of the runner bare. What the prefix does
|
|
301
|
-
// is the operator's (a
|
|
292
|
+
// is the operator's (a container or VM per turn, say); the companion knows nothing of it
|
|
302
293
|
// beyond handing the runner over, with the turn's inputs in its environment and the
|
|
303
|
-
// credential and secrets on its stdin (`runner/launch.ts`, `
|
|
294
|
+
// credential and secrets on its stdin (`runner/launch.ts`, `wrapped`). The README lists
|
|
295
|
+
// what a wrapper can rely on.
|
|
304
296
|
runner: z2.object({
|
|
305
297
|
command: z2.array(z2.string().min(1)).min(1)
|
|
306
298
|
}).strict().optional()
|
|
@@ -312,33 +304,38 @@ function workRoot(cfg) {
|
|
|
312
304
|
if (root.startsWith("~/")) return join4(homedir5(), root.slice(2));
|
|
313
305
|
return root;
|
|
314
306
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
307
|
+
var RETIRED_ROW_KEYS = ["sandbox"];
|
|
308
|
+
var RETIRED_HOOK_KEYS = ["validateCached", "failureReporter"];
|
|
309
|
+
function isObject(value) {
|
|
310
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
311
|
+
}
|
|
312
|
+
function splitRetired(raw) {
|
|
318
313
|
const keys = [];
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
314
|
+
const without = (obj, names, path) => {
|
|
315
|
+
const out = {};
|
|
316
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
317
|
+
if (names.includes(k)) keys.push(`${path}${k}`);
|
|
318
|
+
else out[k] = v;
|
|
324
319
|
}
|
|
320
|
+
return out;
|
|
321
|
+
};
|
|
322
|
+
const hook = (row, path) => isObject(row.prepareHook) ? { ...row, prepareHook: without(row.prepareHook, RETIRED_HOOK_KEYS, `${path}prepareHook.`) } : row;
|
|
323
|
+
const kept = hook(without(raw, ["runners"], ""), "");
|
|
324
|
+
if (isObject(kept.agents)) {
|
|
325
|
+
const agents = {};
|
|
326
|
+
for (const [key, row] of Object.entries(kept.agents)) {
|
|
327
|
+
const path = `agents.${key}.`;
|
|
328
|
+
agents[key] = isObject(row) ? hook(without(row, RETIRED_ROW_KEYS, path), path) : row;
|
|
329
|
+
}
|
|
330
|
+
kept.agents = agents;
|
|
325
331
|
}
|
|
326
|
-
return keys;
|
|
332
|
+
return { keys, kept };
|
|
333
|
+
}
|
|
334
|
+
function retiredConfigKeys(raw) {
|
|
335
|
+
return isObject(raw) ? splitRetired(raw).keys : [];
|
|
327
336
|
}
|
|
328
337
|
function withoutRetiredKeys(raw) {
|
|
329
|
-
|
|
330
|
-
const { runners: _runners, ...rest } = raw;
|
|
331
|
-
if (!rest.agents || typeof rest.agents !== "object") return rest;
|
|
332
|
-
const agents = {};
|
|
333
|
-
for (const [key, row] of Object.entries(rest.agents)) {
|
|
334
|
-
if (row && typeof row === "object" && "sandbox" in row) {
|
|
335
|
-
const { sandbox: _sandbox, ...kept } = row;
|
|
336
|
-
agents[key] = kept;
|
|
337
|
-
} else {
|
|
338
|
-
agents[key] = row;
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
return { ...rest, agents };
|
|
338
|
+
return isObject(raw) ? splitRetired(raw).kept : raw;
|
|
342
339
|
}
|
|
343
340
|
function retiredConfigKeysOnDisk() {
|
|
344
341
|
try {
|
|
@@ -1598,7 +1595,7 @@ var emptyHeartbeatStatus = () => ({
|
|
|
1598
1595
|
});
|
|
1599
1596
|
|
|
1600
1597
|
// src/supervisor.ts
|
|
1601
|
-
import { hostname
|
|
1598
|
+
import { hostname } from "os";
|
|
1602
1599
|
|
|
1603
1600
|
// packages/agent-runtime/src/failure.ts
|
|
1604
1601
|
import { z as z4 } from "zod";
|
|
@@ -1841,11 +1838,20 @@ function describeCause(err) {
|
|
|
1841
1838
|
if (text === void 0 || text.length === 0) return void 0;
|
|
1842
1839
|
return text.length > CAUSE_TEXT_CAP ? `${text.slice(0, CAUSE_TEXT_CAP)}\u2026` : text;
|
|
1843
1840
|
}
|
|
1841
|
+
function edgeBlock(status, headers, raw) {
|
|
1842
|
+
if (status !== 403 || !(headers.get("content-type") ?? "").includes("text/html")) return null;
|
|
1843
|
+
const requestId = /Request ID:\s*(?:<[^>]*>\s*)*([A-Za-z0-9-]+)/i.exec(raw)?.[1];
|
|
1844
|
+
return new EdgeBlockError(status, headers.get("cf-ray") ?? void 0, requestId);
|
|
1845
|
+
}
|
|
1844
1846
|
function apiErrorLogFields(err) {
|
|
1845
1847
|
const fields = {
|
|
1846
1848
|
err: describeError(err)
|
|
1847
1849
|
};
|
|
1848
|
-
if (err instanceof
|
|
1850
|
+
if (err instanceof EdgeBlockError) {
|
|
1851
|
+
fields.status = err.status;
|
|
1852
|
+
if (err.ray) fields.edgeRay = err.ray;
|
|
1853
|
+
if (err.requestId) fields.edgeRequestId = err.requestId;
|
|
1854
|
+
} else if (err instanceof ApiError) {
|
|
1849
1855
|
fields.status = err.status;
|
|
1850
1856
|
const body = describeErrorBody(err.body);
|
|
1851
1857
|
if (body !== void 0) fields.responseBody = body;
|
|
@@ -1861,11 +1867,14 @@ var bootId = randomUUID();
|
|
|
1861
1867
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
1862
1868
|
|
|
1863
1869
|
// src/api.ts
|
|
1870
|
+
import { promisify } from "util";
|
|
1871
|
+
import { gzip } from "zlib";
|
|
1864
1872
|
var DEVICE_HEADER = "x-cabane-device";
|
|
1865
1873
|
var RETRY_BACKOFF_MS = [250, 750];
|
|
1866
1874
|
var TURN_CONTEXT_BACKOFF_MS = [250, 750, 2e3, 5e3];
|
|
1867
1875
|
var ACTIVE_RUN_OUTBOX_SEQ = 0;
|
|
1868
1876
|
var LEASE_CHECK_TIMEOUT_MS = 1e4;
|
|
1877
|
+
var gzipAsync = promisify(gzip);
|
|
1869
1878
|
function activeRunOutboxKey(conversationId, agentId) {
|
|
1870
1879
|
return `activerun:${conversationId}:${agentId}`;
|
|
1871
1880
|
}
|
|
@@ -1885,19 +1894,24 @@ var CabaneApi = class {
|
|
|
1885
1894
|
// rethrows transport errors (fetch reject) unchanged so the caller's retry
|
|
1886
1895
|
// logic can classify them.
|
|
1887
1896
|
async attempt(method, path, body, signal) {
|
|
1897
|
+
const json = body !== void 0 ? JSON.stringify(body) : void 0;
|
|
1898
|
+
const gzipped = json !== void 0 && this.opts.gzipBodies?.() === true;
|
|
1888
1899
|
const res = await fetch(`${this.base}${path}`, {
|
|
1889
1900
|
method,
|
|
1890
1901
|
headers: {
|
|
1891
1902
|
Authorization: `Bearer ${this.opts.token}`,
|
|
1892
1903
|
...this.opts.deviceToken ? { [DEVICE_HEADER]: this.opts.deviceToken } : {},
|
|
1893
|
-
...
|
|
1904
|
+
...json !== void 0 ? { "content-type": "application/json" } : {},
|
|
1905
|
+
...gzipped ? { "content-encoding": "gzip" } : {},
|
|
1894
1906
|
accept: "application/json"
|
|
1895
1907
|
},
|
|
1896
|
-
...
|
|
1908
|
+
...json !== void 0 ? { body: gzipped ? await gzipAsync(json) : json } : {},
|
|
1897
1909
|
...signal ? { signal } : {}
|
|
1898
1910
|
});
|
|
1899
1911
|
if (res.status === 204) return void 0;
|
|
1900
1912
|
const raw = await res.text();
|
|
1913
|
+
const blocked = edgeBlock(res.status, res.headers, raw);
|
|
1914
|
+
if (blocked) throw blocked;
|
|
1901
1915
|
let parsed = void 0;
|
|
1902
1916
|
if (raw.length > 0) {
|
|
1903
1917
|
try {
|
|
@@ -6378,7 +6392,7 @@ function createCodexAdapter(deps = {}) {
|
|
|
6378
6392
|
if (signal.aborted) return;
|
|
6379
6393
|
if (compactions === null) {
|
|
6380
6394
|
deps.onWarn?.(
|
|
6381
|
-
"codex adapter: the thread's compaction count could not be read \u2014 re-sending the standing instructions
|
|
6395
|
+
"codex adapter: the thread's compaction count could not be read \u2014 re-sending the standing instructions",
|
|
6382
6396
|
{ threadId: decision.resume }
|
|
6383
6397
|
);
|
|
6384
6398
|
} else if (decision.compactions === compactions) {
|
|
@@ -6388,7 +6402,7 @@ function createCodexAdapter(deps = {}) {
|
|
|
6388
6402
|
};
|
|
6389
6403
|
} else if (decision.compactions !== null && compactions > decision.compactions) {
|
|
6390
6404
|
deps.onWarn?.(
|
|
6391
|
-
"codex adapter: the thread compacted since the last turn \u2014 re-sending the standing instructions
|
|
6405
|
+
"codex adapter: the thread compacted since the last turn \u2014 re-sending the standing instructions",
|
|
6392
6406
|
{
|
|
6393
6407
|
threadId: decision.resume,
|
|
6394
6408
|
compactions,
|
|
@@ -7539,8 +7553,6 @@ var ConnectorHealthStore = class {
|
|
|
7539
7553
|
|
|
7540
7554
|
// src/dispatcher.ts
|
|
7541
7555
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
7542
|
-
import { existsSync as existsSync12, readdirSync as readdirSync2, statSync as statSync4 } from "fs";
|
|
7543
|
-
import { join as join21 } from "path";
|
|
7544
7556
|
|
|
7545
7557
|
// src/runner/launch.ts
|
|
7546
7558
|
import { createInterface } from "readline";
|
|
@@ -7579,8 +7591,8 @@ async function stopRemoteOpencodeSession(serverUrl, sessionId, opts = {}) {
|
|
|
7579
7591
|
// src/turn-containment.ts
|
|
7580
7592
|
import { execFile, execFileSync, spawn as spawn2 } from "child_process";
|
|
7581
7593
|
import { readFileSync as readFileSync6 } from "fs";
|
|
7582
|
-
import { promisify } from "util";
|
|
7583
|
-
var execFileAsync =
|
|
7594
|
+
import { promisify as promisify2 } from "util";
|
|
7595
|
+
var execFileAsync = promisify2(execFile);
|
|
7584
7596
|
var CONTAINMENT_STOP_GRACE_SEC = 5;
|
|
7585
7597
|
var FALLBACK_GRACE_MS = CONTAINMENT_STOP_GRACE_SEC * 1e3;
|
|
7586
7598
|
var OOM_READ_TIMEOUT_MS = 1500;
|
|
@@ -7733,7 +7745,10 @@ var runnerSpecSchema = z14.object({
|
|
|
7733
7745
|
sessionWriteNoticeClaimed: z14.boolean(),
|
|
7734
7746
|
// The runner's identity, minted with its credential. The start
|
|
7735
7747
|
// PATCH carries it so the lease knows which runner holds the span.
|
|
7736
|
-
runnerId: z14.string()
|
|
7748
|
+
runnerId: z14.string(),
|
|
7749
|
+
// Whether the server took gzip request bodies at the latest heartbeat, as of
|
|
7750
|
+
// the start. The launcher writes `gzip_bodies` when that changes mid-turn.
|
|
7751
|
+
gzipBodies: z14.boolean().optional()
|
|
7737
7752
|
});
|
|
7738
7753
|
var dispatchSchema = z14.object({
|
|
7739
7754
|
type: z14.literal("device:dispatch_requested"),
|
|
@@ -7782,6 +7797,22 @@ function decodeRunnerEvent(line) {
|
|
|
7782
7797
|
}
|
|
7783
7798
|
|
|
7784
7799
|
// src/runner/launch.ts
|
|
7800
|
+
function gzipBodiesSignal() {
|
|
7801
|
+
let on = false;
|
|
7802
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
7803
|
+
return {
|
|
7804
|
+
current: () => on,
|
|
7805
|
+
subscribe(listener) {
|
|
7806
|
+
listeners.add(listener);
|
|
7807
|
+
return () => listeners.delete(listener);
|
|
7808
|
+
},
|
|
7809
|
+
set(next) {
|
|
7810
|
+
if (next === on) return;
|
|
7811
|
+
on = next;
|
|
7812
|
+
for (const listener of listeners) listener(on);
|
|
7813
|
+
}
|
|
7814
|
+
};
|
|
7815
|
+
}
|
|
7785
7816
|
function selfRunnerCommand() {
|
|
7786
7817
|
const script = process.argv[1];
|
|
7787
7818
|
if (!script) throw new Error("runner: cannot tell which script started this companion");
|
|
@@ -7790,7 +7821,7 @@ function selfRunnerCommand() {
|
|
|
7790
7821
|
function wrappedRunnerCommand(prefix, own) {
|
|
7791
7822
|
return [...prefix ?? [], ...own];
|
|
7792
7823
|
}
|
|
7793
|
-
var
|
|
7824
|
+
var WRAPPED_ENV_DROPPED = [
|
|
7794
7825
|
"ANTHROPIC_API_KEY",
|
|
7795
7826
|
"CLAUDE_CODE_OAUTH_TOKEN",
|
|
7796
7827
|
"CODEX_API_KEY",
|
|
@@ -7799,11 +7830,11 @@ var BOXED_ENV_DROPPED = [
|
|
|
7799
7830
|
"DBUS_SESSION_BUS_ADDRESS",
|
|
7800
7831
|
"XDG_RUNTIME_DIR"
|
|
7801
7832
|
];
|
|
7802
|
-
function runnerExecEnv(base,
|
|
7833
|
+
function runnerExecEnv(base, wrapped) {
|
|
7803
7834
|
const env = {};
|
|
7804
7835
|
for (const [k, v] of Object.entries(base)) {
|
|
7805
7836
|
if (v === void 0) continue;
|
|
7806
|
-
if (
|
|
7837
|
+
if (wrapped && WRAPPED_ENV_DROPPED.includes(k)) continue;
|
|
7807
7838
|
env[k] = v;
|
|
7808
7839
|
}
|
|
7809
7840
|
return env;
|
|
@@ -7843,7 +7874,8 @@ function runnerSpec(opts, launch, duties, runnerId) {
|
|
|
7843
7874
|
transcripts: opts.transcriptDir !== void 0,
|
|
7844
7875
|
logLevel: opts.log.level,
|
|
7845
7876
|
connectorHealth: healthSnapshot(launch.connectorHealth),
|
|
7846
|
-
sessionWriteNoticeClaimed: duties.sessionWriteNoticeClaimed()
|
|
7877
|
+
sessionWriteNoticeClaimed: duties.sessionWriteNoticeClaimed(),
|
|
7878
|
+
...launch.gzipBodies?.current() ? { gzipBodies: true } : {}
|
|
7847
7879
|
};
|
|
7848
7880
|
}
|
|
7849
7881
|
var PINO_LEVELS = {
|
|
@@ -7967,6 +7999,7 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
7967
7999
|
const stopRunner = new AbortController();
|
|
7968
8000
|
let ready = false;
|
|
7969
8001
|
let child;
|
|
8002
|
+
let unsubscribeGzip;
|
|
7970
8003
|
let stopAnnounced = false;
|
|
7971
8004
|
const announceStop = () => {
|
|
7972
8005
|
if (stopAnnounced || !child?.stdin.writable) return;
|
|
@@ -8025,13 +8058,13 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
8025
8058
|
return { ok: false, durationMs: durationMs2, reason: reason2 };
|
|
8026
8059
|
}
|
|
8027
8060
|
try {
|
|
8028
|
-
const
|
|
8029
|
-
const env = runnerExecEnv(launch.env ?? process.env,
|
|
8061
|
+
const wrapped = launch.wrapped === true;
|
|
8062
|
+
const env = runnerExecEnv(launch.env ?? process.env, wrapped);
|
|
8030
8063
|
const grants = minted.deviceGrants.length > 0 ? launch.grants?.(minted.deviceGrants) ?? {} : {};
|
|
8031
8064
|
const input = {
|
|
8032
8065
|
baseUrl: opts.baseUrl,
|
|
8033
8066
|
credential: minted.credential,
|
|
8034
|
-
...
|
|
8067
|
+
...wrapped ? { secrets: launch.secrets?.() ?? {} } : {},
|
|
8035
8068
|
...Object.keys(grants).length > 0 ? { grants } : {},
|
|
8036
8069
|
dispatch: payload,
|
|
8037
8070
|
turnId,
|
|
@@ -8044,6 +8077,10 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
8044
8077
|
stdin: runnerStdin(input)
|
|
8045
8078
|
});
|
|
8046
8079
|
child = running;
|
|
8080
|
+
unsubscribeGzip = launch.gzipBodies?.subscribe((on) => {
|
|
8081
|
+
if (running.stdin.writable)
|
|
8082
|
+
running.stdin.write(encodeLauncherMessage({ cabaneLauncher: "gzip_bodies", on }));
|
|
8083
|
+
});
|
|
8047
8084
|
if (controller.signal.aborted) announceStop();
|
|
8048
8085
|
log.debug(
|
|
8049
8086
|
{ turnId, runnerPid: running.pid, provider: launch.provider.name },
|
|
@@ -8105,7 +8142,7 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
8105
8142
|
locks?.release(lockOwner(event.id));
|
|
8106
8143
|
return;
|
|
8107
8144
|
case "process_group":
|
|
8108
|
-
if (!
|
|
8145
|
+
if (!wrapped) groups.push(event.pgid);
|
|
8109
8146
|
return;
|
|
8110
8147
|
case "remote_session":
|
|
8111
8148
|
remote.push({ serverUrl: event.serverUrl, sessionId: event.sessionId });
|
|
@@ -8129,6 +8166,7 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
8129
8166
|
await Promise.all([stdoutDone, stderrDone]);
|
|
8130
8167
|
} finally {
|
|
8131
8168
|
if (locks) giveBackLocks(locks, `${turnId}#`, remote, launch, log);
|
|
8169
|
+
unsubscribeGzip?.();
|
|
8132
8170
|
child?.stdin.end();
|
|
8133
8171
|
controller.signal.removeEventListener("abort", forwardStop);
|
|
8134
8172
|
duties.releaseAbort(turnId, controller);
|
|
@@ -8180,7 +8218,7 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
8180
8218
|
|
|
8181
8219
|
// src/turn-execution.ts
|
|
8182
8220
|
import { createHash as createHash2, randomUUID as randomUUID3 } from "crypto";
|
|
8183
|
-
import { mkdirSync as mkdirSync9 } from "fs";
|
|
8221
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync9 } from "fs";
|
|
8184
8222
|
|
|
8185
8223
|
// src/grants.ts
|
|
8186
8224
|
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
@@ -8234,7 +8272,7 @@ function loadGrantsFile(report) {
|
|
|
8234
8272
|
const result = grantsFileSchema.safeParse(parsed);
|
|
8235
8273
|
if (!result.success) {
|
|
8236
8274
|
report.unreadable(
|
|
8237
|
-
`${path} must map a secret's variable name to an object of "VARIABLE": "value" pairs (e.g. { "
|
|
8275
|
+
`${path} must map a secret's variable name to an object of "VARIABLE": "value" pairs (e.g. { "HAS_STAGING_DB": { "DATABASE_URL": "postgres://\u2026" } }).`
|
|
8238
8276
|
);
|
|
8239
8277
|
return {};
|
|
8240
8278
|
}
|
|
@@ -8277,10 +8315,6 @@ import { homedir as homedir7 } from "os";
|
|
|
8277
8315
|
import { join as join17 } from "path";
|
|
8278
8316
|
import { createInterface as createInterface2 } from "readline";
|
|
8279
8317
|
|
|
8280
|
-
// src/prepare-failure.ts
|
|
8281
|
-
import { spawn as spawn3 } from "child_process";
|
|
8282
|
-
import { hostname } from "os";
|
|
8283
|
-
|
|
8284
8318
|
// src/prepared.ts
|
|
8285
8319
|
import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, rmSync as rmSync5, writeFileSync as writeFileSync5, existsSync as existsSync10 } from "fs";
|
|
8286
8320
|
import { join as join18 } from "path";
|
|
@@ -8356,7 +8390,7 @@ function requiredSecretNames(mcpServers) {
|
|
|
8356
8390
|
}
|
|
8357
8391
|
|
|
8358
8392
|
// src/harness-usable.ts
|
|
8359
|
-
import { spawn as
|
|
8393
|
+
import { spawn as spawn3 } from "child_process";
|
|
8360
8394
|
|
|
8361
8395
|
// src/harness-versions.ts
|
|
8362
8396
|
var EMPTY = { claudeCode: null, opencode: null, codex: null };
|
|
@@ -8459,7 +8493,7 @@ function runBounded(path, args, env) {
|
|
|
8459
8493
|
};
|
|
8460
8494
|
let child;
|
|
8461
8495
|
try {
|
|
8462
|
-
child =
|
|
8496
|
+
child = spawn3(path, args, { stdio: ["ignore", "pipe", "pipe"], env });
|
|
8463
8497
|
} catch {
|
|
8464
8498
|
resolve({ code: null, output: "", error: "spawn" });
|
|
8465
8499
|
return;
|
|
@@ -8626,7 +8660,7 @@ function hostReport() {
|
|
|
8626
8660
|
}
|
|
8627
8661
|
|
|
8628
8662
|
// src/providers/local-process.ts
|
|
8629
|
-
import { spawn as
|
|
8663
|
+
import { spawn as spawn4 } from "child_process";
|
|
8630
8664
|
import { constants as constants2 } from "os";
|
|
8631
8665
|
var DEFAULT_KILL_GRACE_MS = 3e4;
|
|
8632
8666
|
var DEFAULT_REAP_GRACE_MS = 3e3;
|
|
@@ -8637,7 +8671,7 @@ function exitCode(code, signal) {
|
|
|
8637
8671
|
}
|
|
8638
8672
|
function createLocalProcessProvider(opts = {}) {
|
|
8639
8673
|
const killGraceMs = opts.killGraceMs ?? DEFAULT_KILL_GRACE_MS;
|
|
8640
|
-
const spawnFn = opts.spawnFn ??
|
|
8674
|
+
const spawnFn = opts.spawnFn ?? spawn4;
|
|
8641
8675
|
const reapGraceMs = opts.reapGraceMs ?? DEFAULT_REAP_GRACE_MS;
|
|
8642
8676
|
const killFn = opts.killFn ?? ((pid, signal) => process.kill(pid, signal));
|
|
8643
8677
|
const groupAlive = (pgid) => {
|
|
@@ -8841,7 +8875,7 @@ function checkReason(check) {
|
|
|
8841
8875
|
|
|
8842
8876
|
// src/harness-copy.ts
|
|
8843
8877
|
import { homedir as homedir8 } from "os";
|
|
8844
|
-
import { join as
|
|
8878
|
+
import { join as join21 } from "path";
|
|
8845
8879
|
var HARNESS_LABELS = {
|
|
8846
8880
|
"claude-code": "Claude Code",
|
|
8847
8881
|
codex: "Codex",
|
|
@@ -8855,7 +8889,7 @@ function failureText(runtime, reason) {
|
|
|
8855
8889
|
case "spawn":
|
|
8856
8890
|
return `Couldn't check whether ${label} is signed in: Cabane's bundled ${label} wouldn't start. Repair it with ${repairSteps()} and try again.${spaced(repairCost())}`;
|
|
8857
8891
|
case "config":
|
|
8858
|
-
return `Couldn't check whether ${label} is signed in: its configuration file didn't load${runtime === "codex" ? ` (${tildePath(
|
|
8892
|
+
return `Couldn't check whether ${label} is signed in: its configuration file didn't load${runtime === "codex" ? ` (${tildePath(join21(homedir8(), ".codex", "config.toml"))})` : ""}. Fix it, then try again.`;
|
|
8859
8893
|
case "unreadable":
|
|
8860
8894
|
return `Couldn't check whether ${label} is signed in: it answered in a way Cabane couldn't read. Try again, and if it keeps happening, update Cabane.`;
|
|
8861
8895
|
}
|
|
@@ -9114,13 +9148,13 @@ var DispatchClaims = class {
|
|
|
9114
9148
|
import {
|
|
9115
9149
|
existsSync as existsSync14,
|
|
9116
9150
|
mkdirSync as mkdirSync10,
|
|
9117
|
-
readdirSync as
|
|
9151
|
+
readdirSync as readdirSync2,
|
|
9118
9152
|
readFileSync as readFileSync11,
|
|
9119
9153
|
renameSync as renameSync5,
|
|
9120
9154
|
rmSync as rmSync7,
|
|
9121
9155
|
writeFileSync as writeFileSync6
|
|
9122
9156
|
} from "fs";
|
|
9123
|
-
import { join as
|
|
9157
|
+
import { join as join22 } from "path";
|
|
9124
9158
|
var MAX_ENTRIES = 2e3;
|
|
9125
9159
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
9126
9160
|
var Outbox = class {
|
|
@@ -9133,10 +9167,10 @@ var Outbox = class {
|
|
|
9133
9167
|
// Resolved lazily (per call) so tests that swap HOME between
|
|
9134
9168
|
// cases route writes at the right tmpdir.
|
|
9135
9169
|
dir() {
|
|
9136
|
-
return
|
|
9170
|
+
return join22(cabaneDir(), "outbox", encodeURIComponent(this.workspaceId));
|
|
9137
9171
|
}
|
|
9138
9172
|
fileFor(turnId, seq) {
|
|
9139
|
-
return
|
|
9173
|
+
return join22(this.dir(), `${encodeURIComponent(turnId)}__${seq}.json`);
|
|
9140
9174
|
}
|
|
9141
9175
|
// Persist a commit for later draining. Atomic (temp file + rename) so a
|
|
9142
9176
|
// concurrent `list()` never reads a half-written entry, then enforces the
|
|
@@ -9171,14 +9205,14 @@ var Outbox = class {
|
|
|
9171
9205
|
if (!existsSync14(dir2)) return [];
|
|
9172
9206
|
let names;
|
|
9173
9207
|
try {
|
|
9174
|
-
names =
|
|
9208
|
+
names = readdirSync2(dir2);
|
|
9175
9209
|
} catch {
|
|
9176
9210
|
return [];
|
|
9177
9211
|
}
|
|
9178
9212
|
const entries = [];
|
|
9179
9213
|
for (const name of names) {
|
|
9180
9214
|
if (!name.endsWith(".json")) continue;
|
|
9181
|
-
const full =
|
|
9215
|
+
const full = join22(dir2, name);
|
|
9182
9216
|
try {
|
|
9183
9217
|
const parsed = JSON.parse(readFileSync11(full, "utf8"));
|
|
9184
9218
|
if (parsed && typeof parsed.turnId === "string" && typeof parsed.seq === "number" && typeof parsed.path === "string") {
|
|
@@ -9215,7 +9249,7 @@ var Outbox = class {
|
|
|
9215
9249
|
maxSeqForTurn(turnId) {
|
|
9216
9250
|
const dir2 = this.dir();
|
|
9217
9251
|
if (!existsSync14(dir2)) return 0;
|
|
9218
|
-
const names =
|
|
9252
|
+
const names = readdirSync2(dir2);
|
|
9219
9253
|
const prefix = `${encodeURIComponent(turnId)}__`;
|
|
9220
9254
|
let max = 0;
|
|
9221
9255
|
for (const name of names) {
|
|
@@ -9236,7 +9270,7 @@ var Outbox = class {
|
|
|
9236
9270
|
const dir2 = this.dir();
|
|
9237
9271
|
if (!existsSync14(dir2)) return 0;
|
|
9238
9272
|
try {
|
|
9239
|
-
return
|
|
9273
|
+
return readdirSync2(dir2).filter((n) => n.endsWith(".json")).length;
|
|
9240
9274
|
} catch {
|
|
9241
9275
|
return 0;
|
|
9242
9276
|
}
|
|
@@ -9400,9 +9434,9 @@ var SseSubscriber = class {
|
|
|
9400
9434
|
};
|
|
9401
9435
|
|
|
9402
9436
|
// src/updater.ts
|
|
9403
|
-
import { spawn as
|
|
9437
|
+
import { spawn as spawn5 } from "child_process";
|
|
9404
9438
|
import { copyFileSync as copyFileSync2, existsSync as existsSync16, mkdirSync as mkdirSync14, renameSync as renameSync9, rmSync as rmSync10 } from "fs";
|
|
9405
|
-
import { dirname as dirname11, join as
|
|
9439
|
+
import { dirname as dirname11, join as join26 } from "path";
|
|
9406
9440
|
|
|
9407
9441
|
// src/boot-rule.ts
|
|
9408
9442
|
import {
|
|
@@ -9414,7 +9448,7 @@ import {
|
|
|
9414
9448
|
symlinkSync,
|
|
9415
9449
|
writeFileSync as writeFileSync7
|
|
9416
9450
|
} from "fs";
|
|
9417
|
-
import { dirname as dirname8, join as
|
|
9451
|
+
import { dirname as dirname8, join as join23 } from "path";
|
|
9418
9452
|
var UNCONFIRMED_WINDOW_MS = 10 * 6e4;
|
|
9419
9453
|
var MAX_STAGE_ATTEMPTS = 3;
|
|
9420
9454
|
function superseded(pending, ...running) {
|
|
@@ -9441,32 +9475,32 @@ import {
|
|
|
9441
9475
|
lstatSync,
|
|
9442
9476
|
mkdirSync as mkdirSync12,
|
|
9443
9477
|
readFileSync as readFileSync13,
|
|
9444
|
-
readdirSync as
|
|
9478
|
+
readdirSync as readdirSync3,
|
|
9445
9479
|
realpathSync as realpathSync5,
|
|
9446
9480
|
renameSync as renameSync7,
|
|
9447
9481
|
rmSync as rmSync9,
|
|
9448
9482
|
symlinkSync as symlinkSync2
|
|
9449
9483
|
} from "fs";
|
|
9450
|
-
import { dirname as dirname9, join as
|
|
9484
|
+
import { dirname as dirname9, join as join24 } from "path";
|
|
9451
9485
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
9452
9486
|
function versionsDir() {
|
|
9453
|
-
return
|
|
9487
|
+
return join24(cabaneDir(), "versions");
|
|
9454
9488
|
}
|
|
9455
9489
|
function currentLink() {
|
|
9456
|
-
return
|
|
9490
|
+
return join24(cabaneDir(), "current");
|
|
9457
9491
|
}
|
|
9458
9492
|
function bootGuardPath() {
|
|
9459
|
-
return
|
|
9493
|
+
return join24(cabaneDir(), "boot-guard.mjs");
|
|
9460
9494
|
}
|
|
9461
9495
|
function versionPackageRoot(version) {
|
|
9462
|
-
return
|
|
9496
|
+
return join24(versionsDir(), version, "node_modules", "@cabane", "companion");
|
|
9463
9497
|
}
|
|
9464
9498
|
function ownPackageRoot(moduleUrl = import.meta.url) {
|
|
9465
9499
|
return dirname9(dirname9(fileURLToPath5(moduleUrl)));
|
|
9466
9500
|
}
|
|
9467
9501
|
function packageVersion(root) {
|
|
9468
9502
|
try {
|
|
9469
|
-
const pkg2 = JSON.parse(readFileSync13(
|
|
9503
|
+
const pkg2 = JSON.parse(readFileSync13(join24(root, "package.json"), "utf8"));
|
|
9470
9504
|
return typeof pkg2.version === "string" ? pkg2.version : null;
|
|
9471
9505
|
} catch {
|
|
9472
9506
|
return null;
|
|
@@ -9475,7 +9509,7 @@ function packageVersion(root) {
|
|
|
9475
9509
|
function currentRoot() {
|
|
9476
9510
|
try {
|
|
9477
9511
|
const root = realpathSync5(currentLink());
|
|
9478
|
-
return existsSync15(
|
|
9512
|
+
return existsSync15(join24(root, "dist", "cli.js")) ? root : null;
|
|
9479
9513
|
} catch {
|
|
9480
9514
|
return null;
|
|
9481
9515
|
}
|
|
@@ -9496,9 +9530,9 @@ function pruneVersions(keep) {
|
|
|
9496
9530
|
const dir2 = versionsDir();
|
|
9497
9531
|
if (!existsSync15(dir2)) return [];
|
|
9498
9532
|
const removed = [];
|
|
9499
|
-
for (const name of
|
|
9533
|
+
for (const name of readdirSync3(dir2)) {
|
|
9500
9534
|
if (keep.includes(name)) continue;
|
|
9501
|
-
rmSync9(
|
|
9535
|
+
rmSync9(join24(dir2, name), { recursive: true, force: true });
|
|
9502
9536
|
removed.push(name);
|
|
9503
9537
|
}
|
|
9504
9538
|
return removed;
|
|
@@ -9517,7 +9551,7 @@ function compareVersions(a, b) {
|
|
|
9517
9551
|
|
|
9518
9552
|
// src/update-state.ts
|
|
9519
9553
|
import { mkdirSync as mkdirSync13, readFileSync as readFileSync14, renameSync as renameSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
9520
|
-
import { dirname as dirname10, join as
|
|
9554
|
+
import { dirname as dirname10, join as join25 } from "path";
|
|
9521
9555
|
import { z as z18 } from "zod";
|
|
9522
9556
|
var resultSchema = z18.object({
|
|
9523
9557
|
kind: z18.enum(["updated", "rolled_back", "failed"]),
|
|
@@ -9541,7 +9575,7 @@ var stateSchema = z18.object({
|
|
|
9541
9575
|
failed: z18.object({ version: z18.string(), attempts: z18.number().int(), at: z18.string() }).optional()
|
|
9542
9576
|
});
|
|
9543
9577
|
function updateStatePath(dir2 = cabaneDir()) {
|
|
9544
|
-
return
|
|
9578
|
+
return join25(dir2, "update.json");
|
|
9545
9579
|
}
|
|
9546
9580
|
function readUpdateState(path = updateStatePath()) {
|
|
9547
9581
|
try {
|
|
@@ -9590,7 +9624,7 @@ function rollBack(pending, reason, now = /* @__PURE__ */ new Date()) {
|
|
|
9590
9624
|
return updateUpdateState((state) => rolledBackState(state, pending, reason, now));
|
|
9591
9625
|
}
|
|
9592
9626
|
function writeBootGuard(root = ownPackageRoot()) {
|
|
9593
|
-
const built =
|
|
9627
|
+
const built = join26(root, "dist", "boot-guard.js");
|
|
9594
9628
|
if (!existsSync16(built)) return false;
|
|
9595
9629
|
const target = bootGuardPath();
|
|
9596
9630
|
mkdirSync14(dirname11(target), { recursive: true });
|
|
@@ -9607,7 +9641,7 @@ var runProcess = (command, args, opts = {}) => new Promise((resolve) => {
|
|
|
9607
9641
|
let stderr = "";
|
|
9608
9642
|
let child;
|
|
9609
9643
|
try {
|
|
9610
|
-
child =
|
|
9644
|
+
child = spawn5(command, [...args], {
|
|
9611
9645
|
stdio: ["ignore", "pipe", "pipe"],
|
|
9612
9646
|
env: opts.env ?? process.env
|
|
9613
9647
|
});
|
|
@@ -9630,17 +9664,17 @@ var runProcess = (command, args, opts = {}) => new Promise((resolve) => {
|
|
|
9630
9664
|
async function stageVersion(version, harnesses, deps = {}) {
|
|
9631
9665
|
const run = deps.run ?? runProcess;
|
|
9632
9666
|
const node = deps.execPath ?? process.execPath;
|
|
9633
|
-
const target =
|
|
9667
|
+
const target = join26(versionsDir(), version);
|
|
9634
9668
|
const placed = versionPackageRoot(version);
|
|
9635
9669
|
if (existsSync16(placed)) {
|
|
9636
9670
|
if (!await verifyInstall(placed, version, harnesses, { run, execPath: node }))
|
|
9637
9671
|
return { ok: true, root: placed };
|
|
9638
9672
|
}
|
|
9639
|
-
const npm =
|
|
9673
|
+
const npm = join26(dirname11(node), "npm");
|
|
9640
9674
|
if (!existsSync16(npm))
|
|
9641
9675
|
return { ok: false, reason: `there is no npm beside Node at ${dirname11(node)}` };
|
|
9642
9676
|
mkdirSync14(versionsDir(), { recursive: true });
|
|
9643
|
-
const staging =
|
|
9677
|
+
const staging = join26(versionsDir(), `.${version}.staging-${process.pid}`);
|
|
9644
9678
|
rmSync10(staging, { recursive: true, force: true });
|
|
9645
9679
|
const installed = await run(
|
|
9646
9680
|
npm,
|
|
@@ -9669,7 +9703,7 @@ async function stageVersion(version, harnesses, deps = {}) {
|
|
|
9669
9703
|
return { ok: false, reason: `version ${version} isn't published yet`, unpublished: true };
|
|
9670
9704
|
return { ok: false, reason: `npm couldn't install it: ${lastLine(installed.stderr)}` };
|
|
9671
9705
|
}
|
|
9672
|
-
const root =
|
|
9706
|
+
const root = join26(staging, "node_modules", "@cabane", "companion");
|
|
9673
9707
|
const verdict = await verifyInstall(root, version, harnesses, { run, execPath: node });
|
|
9674
9708
|
if (verdict) {
|
|
9675
9709
|
rmSync10(staging, { recursive: true, force: true });
|
|
@@ -9681,7 +9715,7 @@ async function stageVersion(version, harnesses, deps = {}) {
|
|
|
9681
9715
|
}
|
|
9682
9716
|
async function verifyInstall(root, version, harnesses, deps) {
|
|
9683
9717
|
if (packageVersion(root) !== version) return `the installed package isn't version ${version}`;
|
|
9684
|
-
const answered = await deps.run(deps.execPath, [
|
|
9718
|
+
const answered = await deps.run(deps.execPath, [join26(root, "dist", "bin.js"), "--version"], {
|
|
9685
9719
|
timeoutMs: 6e4,
|
|
9686
9720
|
env: { ...process.env, CABANE_LAUNCH_SELF: "1" }
|
|
9687
9721
|
});
|
|
@@ -9689,7 +9723,7 @@ async function verifyInstall(root, version, harnesses, deps) {
|
|
|
9689
9723
|
return `it doesn't start: ${lastLine(answered.stderr) || "no version printed"}`;
|
|
9690
9724
|
}
|
|
9691
9725
|
if (harnesses.length === 0) return null;
|
|
9692
|
-
const probed = await deps.run(deps.execPath, [
|
|
9726
|
+
const probed = await deps.run(deps.execPath, [join26(root, "dist", "postinstall.js"), "--json"], {
|
|
9693
9727
|
timeoutMs: 6e4
|
|
9694
9728
|
});
|
|
9695
9729
|
let resolutions = {};
|
|
@@ -10060,6 +10094,10 @@ var CompanionSupervisor = class {
|
|
|
10060
10094
|
reconciliationAbort = new AbortController();
|
|
10061
10095
|
// The version-skew warning is logged once, not every heartbeat.
|
|
10062
10096
|
versionSkewWarned = false;
|
|
10097
|
+
// Whether the server takes gzip request bodies, as the latest accepted
|
|
10098
|
+
// heartbeat said; false until one has. Read per request by every agent's API
|
|
10099
|
+
// client and pushed to the runners in flight when it changes.
|
|
10100
|
+
gzipBodies = gzipBodiesSignal();
|
|
10063
10101
|
// This device's id, captured from the heartbeat / assignments response. The SSE
|
|
10064
10102
|
// router uses it to tell a dispatch addressed to THIS device (a freshly-assigned
|
|
10065
10103
|
// agent the last poll hasn't caught yet — the assignment-change race) from one
|
|
@@ -10106,13 +10144,13 @@ var CompanionSupervisor = class {
|
|
|
10106
10144
|
if (this.stopped) return;
|
|
10107
10145
|
this.log.info(
|
|
10108
10146
|
{ protocolVersion: TURN_PROTOCOL_VERSION, version: COMPANION_VERSION },
|
|
10109
|
-
`Companion ${COMPANION_VERSION} starting on ${this.config.deviceLabel ??
|
|
10147
|
+
`Companion ${COMPANION_VERSION} starting on ${this.config.deviceLabel ?? hostname()}`
|
|
10110
10148
|
);
|
|
10111
10149
|
const retired = retiredConfigKeysOnDisk();
|
|
10112
10150
|
if (retired.length > 0) {
|
|
10113
10151
|
this.log.warn(
|
|
10114
10152
|
{ keys: retired },
|
|
10115
|
-
`config.json: ${retired.join(", ")} ${retired.length === 1 ? "is" : "are"} no longer read and can be removed
|
|
10153
|
+
`config.json: ${retired.join(", ")} ${retired.length === 1 ? "is" : "are"} no longer read and can be removed.`
|
|
10116
10154
|
);
|
|
10117
10155
|
}
|
|
10118
10156
|
if (this.config.deviceToken) {
|
|
@@ -10152,7 +10190,7 @@ var CompanionSupervisor = class {
|
|
|
10152
10190
|
log: this.log,
|
|
10153
10191
|
lastEventId: null,
|
|
10154
10192
|
onOpen: () => {
|
|
10155
|
-
this.log.info(`Connected to Cabane as ${this.hub.statusJson().device_label ??
|
|
10193
|
+
this.log.info(`Connected to Cabane as ${this.hub.statusJson().device_label ?? hostname()}`);
|
|
10156
10194
|
this.deviceConnected = true;
|
|
10157
10195
|
for (const wr of this.workspaces.values()) {
|
|
10158
10196
|
this.hub.setConnected(wr.workspaceId, true);
|
|
@@ -10262,6 +10300,7 @@ var CompanionSupervisor = class {
|
|
|
10262
10300
|
this.hub.setDevice({ deviceId: res.deviceId });
|
|
10263
10301
|
this.deviceId = res.deviceId;
|
|
10264
10302
|
this.checkVersionSkew(res.serverVersion);
|
|
10303
|
+
this.gzipBodies.set(res.acceptsGzipBodies === true);
|
|
10265
10304
|
this.heartbeated = true;
|
|
10266
10305
|
const view = acknowledgedDeviceSchema.safeParse(res.device);
|
|
10267
10306
|
this.heartbeatStatus = {
|
|
@@ -10503,7 +10542,8 @@ var CompanionSupervisor = class {
|
|
|
10503
10542
|
token: credential,
|
|
10504
10543
|
...this.config.deviceToken ? { deviceToken: this.config.deviceToken } : {},
|
|
10505
10544
|
outbox,
|
|
10506
|
-
log: agentLog
|
|
10545
|
+
log: agentLog,
|
|
10546
|
+
gzipBodies: () => this.gzipBodies.current()
|
|
10507
10547
|
});
|
|
10508
10548
|
const aborts = /* @__PURE__ */ new Map();
|
|
10509
10549
|
const dispatcher = this.buildDispatcher({
|
|
@@ -10698,9 +10738,9 @@ var CompanionSupervisor = class {
|
|
|
10698
10738
|
this.runnerCommand ?? selfRunnerCommand()
|
|
10699
10739
|
),
|
|
10700
10740
|
...this.config.runner?.command ? {
|
|
10701
|
-
|
|
10741
|
+
wrapped: true,
|
|
10702
10742
|
secrets: () => loadSecretValuesTolerant(
|
|
10703
|
-
(m) => this.log.warn({ err: m }, "Could not read the secrets file for a
|
|
10743
|
+
(m) => this.log.warn({ err: m }, "Could not read the secrets file for a wrapped turn.")
|
|
10704
10744
|
)
|
|
10705
10745
|
} : {},
|
|
10706
10746
|
// Read per dispatch, for the secret variables its mint named and no others.
|
|
@@ -10714,7 +10754,8 @@ var CompanionSupervisor = class {
|
|
|
10714
10754
|
...this.runnerEnv ? { env: this.runnerEnv } : {},
|
|
10715
10755
|
reportRunnerGone: (report) => this.reportRunnerGone(report),
|
|
10716
10756
|
connectorHealth: this.connectorHealth,
|
|
10717
|
-
locks: this.runnerLocks
|
|
10757
|
+
locks: this.runnerLocks,
|
|
10758
|
+
gzipBodies: this.gzipBodies
|
|
10718
10759
|
},
|
|
10719
10760
|
observer: this.hub.observerFor(ctx.workspaceId, ctx.agentId, ctx.workspaceSlug),
|
|
10720
10761
|
aborts: ctx.aborts
|
|
@@ -11379,9 +11420,9 @@ async function waitForBoundedHeartbeat(heartbeat) {
|
|
|
11379
11420
|
}
|
|
11380
11421
|
function defaultReexec() {
|
|
11381
11422
|
clearRuntimeState();
|
|
11382
|
-
void import("child_process").then(({ spawn:
|
|
11423
|
+
void import("child_process").then(({ spawn: spawn6 }) => {
|
|
11383
11424
|
try {
|
|
11384
|
-
const child =
|
|
11425
|
+
const child = spawn6(process.execPath, process.argv.slice(1), {
|
|
11385
11426
|
stdio: "inherit",
|
|
11386
11427
|
detached: false
|
|
11387
11428
|
});
|
|
@@ -11452,9 +11493,9 @@ function handleUncaught(log, err, origin) {
|
|
|
11452
11493
|
|
|
11453
11494
|
// src/crash-marker.ts
|
|
11454
11495
|
import { existsSync as existsSync17, mkdirSync as mkdirSync15, readFileSync as readFileSync15, rmSync as rmSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
11455
|
-
import { join as
|
|
11496
|
+
import { join as join27 } from "path";
|
|
11456
11497
|
function crashMarkerPath() {
|
|
11457
|
-
return
|
|
11498
|
+
return join27(cabaneDir(), "last-error.json");
|
|
11458
11499
|
}
|
|
11459
11500
|
function recordCrash(rec) {
|
|
11460
11501
|
try {
|
|
@@ -11474,7 +11515,7 @@ function clearCrash() {
|
|
|
11474
11515
|
// src/stray-companion.ts
|
|
11475
11516
|
import { spawnSync } from "child_process";
|
|
11476
11517
|
import { readFileSync as readFileSync16 } from "fs";
|
|
11477
|
-
import { join as
|
|
11518
|
+
import { join as join28 } from "path";
|
|
11478
11519
|
var COMPANION_ENTRY = /@cabane\/companion\/|cabane-companion|(^|[\s/])cabane\s|\.cabane\/(versions|current|boot-guard)/;
|
|
11479
11520
|
var START = /\sstart(\s|$)/;
|
|
11480
11521
|
function companionStarts(psOutput) {
|
|
@@ -11491,7 +11532,7 @@ function companionStarts(psOutput) {
|
|
|
11491
11532
|
}
|
|
11492
11533
|
function stateDirOf(env) {
|
|
11493
11534
|
const home = env.CABANE_COMPANION_HOME || env.HOME;
|
|
11494
|
-
return home ?
|
|
11535
|
+
return home ? join28(home, ".cabane") : null;
|
|
11495
11536
|
}
|
|
11496
11537
|
function envFromPsE(output, command) {
|
|
11497
11538
|
const line = output.replace(/\n$/, "");
|