@sailorbridge/client 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -7
- package/dist/src/cli.js +604 -136
- package/dist/src/cli.js.map +10 -9
- package/package.json +1 -1
package/dist/src/cli.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
4
4
|
|
|
5
|
-
// .dist-releases/
|
|
5
|
+
// .dist-releases/1784862378006-1249051/src/cli.js
|
|
6
6
|
import { hostname as hostname3 } from "node:os";
|
|
7
7
|
import { writeSync } from "node:fs";
|
|
8
|
-
// .dist-releases/
|
|
8
|
+
// .dist-releases/1784862378006-1249051/src/auth/host-pairing.js
|
|
9
9
|
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
10
10
|
import { homedir, hostname, platform } from "node:os";
|
|
11
11
|
import path from "node:path";
|
|
@@ -220,7 +220,7 @@ function _assertObject(value) {
|
|
|
220
220
|
throw new Error("host pairing response must be an object");
|
|
221
221
|
return value;
|
|
222
222
|
}
|
|
223
|
-
// .dist-releases/
|
|
223
|
+
// .dist-releases/1784862378006-1249051/src/host/repo-tip-reporter.js
|
|
224
224
|
import { createHash } from "node:crypto";
|
|
225
225
|
import { existsSync, mkdirSync } from "node:fs";
|
|
226
226
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -402,10 +402,10 @@ ${error.message}`));
|
|
|
402
402
|
proc.on("close", (code) => finish(code ?? 1));
|
|
403
403
|
});
|
|
404
404
|
}
|
|
405
|
-
// .dist-releases/
|
|
405
|
+
// .dist-releases/1784862378006-1249051/src/host/request-consumer.js
|
|
406
406
|
import { hostname as hostname2 } from "node:os";
|
|
407
407
|
|
|
408
|
-
// .dist-releases/
|
|
408
|
+
// .dist-releases/1784862378006-1249051/src/driver/secrets.js
|
|
409
409
|
function redactSensitiveText(text, env = {}, explicitSecrets = []) {
|
|
410
410
|
let redacted = text;
|
|
411
411
|
for (const [key, value] of Object.entries(env)) {
|
|
@@ -424,16 +424,16 @@ function isSensitiveEnvKey(key) {
|
|
|
424
424
|
return /(TOKEN|KEY|SECRET|AUTHORIZATION|PASSWORD)/i.test(key);
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
-
// .dist-releases/
|
|
428
|
-
var CLIENT_VERSION = "0.2.
|
|
429
|
-
var CLIENT_GIT_SHA = "
|
|
427
|
+
// .dist-releases/1784862378006-1249051/src/version.js
|
|
428
|
+
var CLIENT_VERSION = "0.2.2";
|
|
429
|
+
var CLIENT_GIT_SHA = "f943ffe8e731-dirty";
|
|
430
430
|
var CLIENT_BUILD_DIRTY = true;
|
|
431
431
|
var CLIENT_VERSION_LABEL = formatClientVersion(CLIENT_VERSION, CLIENT_GIT_SHA);
|
|
432
432
|
function formatClientVersion(version, gitSha) {
|
|
433
433
|
return `${version}+git.${gitSha}`;
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
-
// .dist-releases/
|
|
436
|
+
// .dist-releases/1784862378006-1249051/src/host/request-consumer.js
|
|
437
437
|
var MAX_ERROR_LENGTH = 500;
|
|
438
438
|
function defaultHostIdentity(config) {
|
|
439
439
|
const captainId = config.captainId?.trim();
|
|
@@ -488,7 +488,7 @@ function limitErrorMessage(error, explicitSecrets) {
|
|
|
488
488
|
const trimmed = redactSensitiveText(message, process.env, explicitSecrets).trim() || "host request starter failed";
|
|
489
489
|
return trimmed.length <= MAX_ERROR_LENGTH ? trimmed : `${trimmed.slice(0, MAX_ERROR_LENGTH - 3)}...`;
|
|
490
490
|
}
|
|
491
|
-
// .dist-releases/
|
|
491
|
+
// .dist-releases/1784862378006-1249051/src/product/start-request.js
|
|
492
492
|
async function createAgentStartRequest(options) {
|
|
493
493
|
const apiUrl = _required(options.apiUrl, "product API URL").replace(/\/+$/u, "");
|
|
494
494
|
const accessToken = _required(options.accessToken, "product API bearer token");
|
|
@@ -548,7 +548,7 @@ function _string(value, label) {
|
|
|
548
548
|
throw new Error(`${label} must be a non-empty string`);
|
|
549
549
|
return value;
|
|
550
550
|
}
|
|
551
|
-
// .dist-releases/
|
|
551
|
+
// .dist-releases/1784862378006-1249051/src/product/pair.js
|
|
552
552
|
async function createPair(options) {
|
|
553
553
|
const apiUrl = _required2(options.apiUrl, "product API URL").replace(/\/+$/u, "");
|
|
554
554
|
const accessToken = _required2(options.accessToken, "product API bearer token");
|
|
@@ -625,7 +625,7 @@ function _string2(value, label) {
|
|
|
625
625
|
throw new Error(`${label} must be a non-empty string`);
|
|
626
626
|
return value;
|
|
627
627
|
}
|
|
628
|
-
// .dist-releases/
|
|
628
|
+
// .dist-releases/1784862378006-1249051/src/product/worker.js
|
|
629
629
|
async function createWorker(options) {
|
|
630
630
|
const apiUrl = _required3(options.apiUrl, "product API URL").replace(/\/+$/u, "");
|
|
631
631
|
const accessToken = _required3(options.accessToken, "product API bearer token");
|
|
@@ -689,7 +689,7 @@ function _string3(value, label) {
|
|
|
689
689
|
throw new Error(`${label} must be a non-empty string`);
|
|
690
690
|
return value;
|
|
691
691
|
}
|
|
692
|
-
// .dist-releases/
|
|
692
|
+
// .dist-releases/1784862378006-1249051/src/driver/events.js
|
|
693
693
|
class DriverEventEmitter {
|
|
694
694
|
callbacks = new Map;
|
|
695
695
|
on(type, callback) {
|
|
@@ -704,7 +704,7 @@ class DriverEventEmitter {
|
|
|
704
704
|
}
|
|
705
705
|
}
|
|
706
706
|
}
|
|
707
|
-
// .dist-releases/
|
|
707
|
+
// .dist-releases/1784862378006-1249051/src/driver/async-queue.js
|
|
708
708
|
class AsyncQueue {
|
|
709
709
|
values = [];
|
|
710
710
|
waiters = [];
|
|
@@ -743,7 +743,7 @@ class AsyncQueue {
|
|
|
743
743
|
}
|
|
744
744
|
}
|
|
745
745
|
|
|
746
|
-
// .dist-releases/
|
|
746
|
+
// .dist-releases/1784862378006-1249051/src/driver/types.js
|
|
747
747
|
class DriverUnsupportedError extends Error {
|
|
748
748
|
constructor(message) {
|
|
749
749
|
super(message);
|
|
@@ -758,7 +758,7 @@ class DriverTargetNotReadyError extends Error {
|
|
|
758
758
|
}
|
|
759
759
|
}
|
|
760
760
|
|
|
761
|
-
// .dist-releases/
|
|
761
|
+
// .dist-releases/1784862378006-1249051/src/driver/sdk-loader.js
|
|
762
762
|
async function loadSdk(loader, packageName, env = {}, installHint = `Install the optional SDK dependency ${packageName} and its peers for this transport.`) {
|
|
763
763
|
try {
|
|
764
764
|
return await loader();
|
|
@@ -768,7 +768,7 @@ async function loadSdk(loader, packageName, env = {}, installHint = `Install the
|
|
|
768
768
|
}
|
|
769
769
|
}
|
|
770
770
|
|
|
771
|
-
// .dist-releases/
|
|
771
|
+
// .dist-releases/1784862378006-1249051/src/driver/claude/driver.js
|
|
772
772
|
class ClaudeAgentSdkDriver {
|
|
773
773
|
options;
|
|
774
774
|
capabilities = { structured: true, resume: true, attach: false };
|
|
@@ -944,7 +944,7 @@ function asRecord(value) {
|
|
|
944
944
|
function stringValue(value) {
|
|
945
945
|
return typeof value === "string" ? value : undefined;
|
|
946
946
|
}
|
|
947
|
-
// .dist-releases/
|
|
947
|
+
// .dist-releases/1784862378006-1249051/src/driver/codex/driver.js
|
|
948
948
|
class CodexSdkDriver {
|
|
949
949
|
options;
|
|
950
950
|
capabilities = { structured: true, resume: true, attach: false };
|
|
@@ -1125,7 +1125,7 @@ function asRecord2(value) {
|
|
|
1125
1125
|
function stringValue2(value) {
|
|
1126
1126
|
return typeof value === "string" ? value : undefined;
|
|
1127
1127
|
}
|
|
1128
|
-
// .dist-releases/
|
|
1128
|
+
// .dist-releases/1784862378006-1249051/src/driver/liveness-heuristics.js
|
|
1129
1129
|
var BUSY_MARKERS = ["Working (", "Waiting for background", "Pasted Content", "tab to queue"];
|
|
1130
1130
|
var ANSI_PATTERN = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\)|[PX^_][\s\S]*?\x1B\\)/g;
|
|
1131
1131
|
function stripAnsi(text) {
|
|
@@ -1152,7 +1152,7 @@ function classifyInteractiveOutput(input) {
|
|
|
1152
1152
|
function isOutputStable(now, lastOutputAt, idleStableMs) {
|
|
1153
1153
|
return Boolean(lastOutputAt && now.getTime() - lastOutputAt.getTime() >= idleStableMs);
|
|
1154
1154
|
}
|
|
1155
|
-
// .dist-releases/
|
|
1155
|
+
// .dist-releases/1784862378006-1249051/src/driver/pty/loader.js
|
|
1156
1156
|
async function loadNodePty(loader = defaultNodePtyLoader) {
|
|
1157
1157
|
try {
|
|
1158
1158
|
return await loader();
|
|
@@ -1178,7 +1178,7 @@ async function defaultNodePtyLoader() {
|
|
|
1178
1178
|
return loaded;
|
|
1179
1179
|
}
|
|
1180
1180
|
|
|
1181
|
-
// .dist-releases/
|
|
1181
|
+
// .dist-releases/1784862378006-1249051/src/driver/pty/driver.js
|
|
1182
1182
|
class PtyDriver {
|
|
1183
1183
|
options;
|
|
1184
1184
|
capabilities = { structured: false, resume: false, attach: false };
|
|
@@ -1330,12 +1330,12 @@ function tail(text, lines) {
|
|
|
1330
1330
|
function sleep(ms) {
|
|
1331
1331
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1332
1332
|
}
|
|
1333
|
-
// .dist-releases/
|
|
1333
|
+
// .dist-releases/1784862378006-1249051/src/driver/tmux/driver.js
|
|
1334
1334
|
import { mkdtemp, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
1335
1335
|
import { tmpdir } from "node:os";
|
|
1336
1336
|
import { join } from "node:path";
|
|
1337
1337
|
|
|
1338
|
-
// .dist-releases/
|
|
1338
|
+
// .dist-releases/1784862378006-1249051/src/driver/tmux/launch.js
|
|
1339
1339
|
var ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
1340
1340
|
var PANE_BOOTSTRAP_COMMAND = 'tmux set-option -t "$TMUX_PANE" remain-on-exit on >/dev/null 2>&1 || true; tmux wait-for -S "$1"; shift; exec "$@"';
|
|
1341
1341
|
function buildTmuxNewSessionArgs(input) {
|
|
@@ -1358,7 +1358,7 @@ function validateEnv(env) {
|
|
|
1358
1358
|
}
|
|
1359
1359
|
}
|
|
1360
1360
|
|
|
1361
|
-
// .dist-releases/
|
|
1361
|
+
// .dist-releases/1784862378006-1249051/src/driver/tmux/paste.js
|
|
1362
1362
|
function buildDispatchPlan(text, useTyping) {
|
|
1363
1363
|
return {
|
|
1364
1364
|
mode: useTyping ? "type-literal" : "paste-buffer",
|
|
@@ -1382,7 +1382,7 @@ function arraysEqual(left, right) {
|
|
|
1382
1382
|
return left.length === right.length && left.every((item, index) => item === right[index]);
|
|
1383
1383
|
}
|
|
1384
1384
|
|
|
1385
|
-
// .dist-releases/
|
|
1385
|
+
// .dist-releases/1784862378006-1249051/src/driver/tmux/liveness.js
|
|
1386
1386
|
var SHELL_COMMANDS = new Set(["", "bash", "zsh", "sh", "fish", "pwsh", "powershell"]);
|
|
1387
1387
|
function classifyTmuxLiveness(input) {
|
|
1388
1388
|
if (!input.hasSession) {
|
|
@@ -1402,7 +1402,7 @@ function isTmuxProcessAlive(command, runningCommands) {
|
|
|
1402
1402
|
return !SHELL_COMMANDS.has(command);
|
|
1403
1403
|
}
|
|
1404
1404
|
|
|
1405
|
-
// .dist-releases/
|
|
1405
|
+
// .dist-releases/1784862378006-1249051/src/driver/tmux/runner.js
|
|
1406
1406
|
import { spawn as spawn2 } from "node:child_process";
|
|
1407
1407
|
var DEFAULT_TIMEOUT_MS = 15000;
|
|
1408
1408
|
|
|
@@ -1527,7 +1527,7 @@ class TmuxClient {
|
|
|
1527
1527
|
}
|
|
1528
1528
|
}
|
|
1529
1529
|
|
|
1530
|
-
// .dist-releases/
|
|
1530
|
+
// .dist-releases/1784862378006-1249051/src/driver/tmux/driver.js
|
|
1531
1531
|
var ATTACHED_STOP_GRACE_MS = 1e4;
|
|
1532
1532
|
var DEFAULT_STOP_TIMEOUT_MS = 15000;
|
|
1533
1533
|
var DEFAULT_READY_TIMEOUT_MS = 90000;
|
|
@@ -1922,12 +1922,12 @@ function isMissingTmuxSessionError(error) {
|
|
|
1922
1922
|
${error.result.stderr}`.toLowerCase();
|
|
1923
1923
|
return text.includes("can't find session") || text.includes("cannot find session") || text.includes("no such session") || text.includes("session not found");
|
|
1924
1924
|
}
|
|
1925
|
-
// .dist-releases/
|
|
1925
|
+
// .dist-releases/1784862378006-1249051/src/relay/client.js
|
|
1926
1926
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
1927
1927
|
import http from "node:http";
|
|
1928
1928
|
import https from "node:https";
|
|
1929
1929
|
|
|
1930
|
-
// .dist-releases/
|
|
1930
|
+
// .dist-releases/1784862378006-1249051/src/relay/errors.js
|
|
1931
1931
|
class RelayError extends Error {
|
|
1932
1932
|
method;
|
|
1933
1933
|
path;
|
|
@@ -1964,7 +1964,37 @@ class RelayProtocolError extends RelayError {
|
|
|
1964
1964
|
}
|
|
1965
1965
|
}
|
|
1966
1966
|
|
|
1967
|
-
// .dist-releases/
|
|
1967
|
+
// .dist-releases/1784862378006-1249051/src/worker/protocol.js
|
|
1968
|
+
var DEFAULT_RELAY_URL = DEFAULT_PRODUCT_API_URL;
|
|
1969
|
+
var DEFAULT_WORKER = "host";
|
|
1970
|
+
var DEFAULT_WORKDIR = "~/sailorbridge-workdir";
|
|
1971
|
+
var DEFAULT_JOB_TIMEOUT_SECONDS = 300;
|
|
1972
|
+
var MAX_JOB_TIMEOUT_SECONDS = 24 * 60 * 60;
|
|
1973
|
+
var MIN_JOB_TIMEOUT_SECONDS = 1;
|
|
1974
|
+
var WORKER_JOB_RESULT_GRACE_SECONDS = 30;
|
|
1975
|
+
var ACTIVE_JOB_KINDS = new Set(["apply_diff", "bash", "read_file", "write_file", "compose", "stream", "status"]);
|
|
1976
|
+
var READONLY_ALLOWED_KINDS = new Set(["read_file", "status"]);
|
|
1977
|
+
var WORKER_SOCK_CONNECT_MS = 1e4;
|
|
1978
|
+
var WORKER_PULL_READ_IDLE_MS = 45000;
|
|
1979
|
+
var WORKER_QUICK_READ_IDLE_MS = 15000;
|
|
1980
|
+
var WORKER_UPLOAD_READ_IDLE_MS = (MAX_JOB_TIMEOUT_SECONDS + 300) * 1000;
|
|
1981
|
+
var DRAIN_AFTER_KILL_MS = 5000;
|
|
1982
|
+
var WORKER_RETRY_INITIAL_MS = 1000;
|
|
1983
|
+
var WORKER_RETRY_MAX_MS = 30000;
|
|
1984
|
+
var WORKER_SESSION_REBUILD_FAILURES = 10;
|
|
1985
|
+
var MAX_WORKER_RESULT_OUTPUT_BYTES = 256 * 1024;
|
|
1986
|
+
function coerceJobTimeoutSeconds(spec) {
|
|
1987
|
+
const value = spec.timeout_sec === undefined ? DEFAULT_JOB_TIMEOUT_SECONDS : spec.timeout_sec;
|
|
1988
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
1989
|
+
throw new Error("spec.timeout_sec must be a finite positive number");
|
|
1990
|
+
}
|
|
1991
|
+
return Math.max(MIN_JOB_TIMEOUT_SECONDS, Math.min(value, MAX_JOB_TIMEOUT_SECONDS));
|
|
1992
|
+
}
|
|
1993
|
+
function effectiveJobKind(kind, spec) {
|
|
1994
|
+
return kind === "stream" || spec.stream === true ? "stream" : kind;
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
// .dist-releases/1784862378006-1249051/src/relay/client.js
|
|
1968
1998
|
var JSON_CONTENT_TYPE = "application/json";
|
|
1969
1999
|
var MAX_MAILBOX_LIMIT = 16;
|
|
1970
2000
|
var MAX_WAIT_TIMEOUT_SEC = 120;
|
|
@@ -1999,6 +2029,44 @@ class RelayClient {
|
|
|
1999
2029
|
close() {
|
|
2000
2030
|
this.httpClient?.close();
|
|
2001
2031
|
}
|
|
2032
|
+
async listWorkers(captainId, session) {
|
|
2033
|
+
requireCaptainId(captainId);
|
|
2034
|
+
if (session !== undefined)
|
|
2035
|
+
requireSegment(session, "session");
|
|
2036
|
+
const suffix = session === undefined ? "" : `?session=${segment(session)}`;
|
|
2037
|
+
const path3 = `/api/v1/captains/${segment(captainId)}/workers${suffix}`;
|
|
2038
|
+
const response = await this.requestJson("GET", path3);
|
|
2039
|
+
if (!Array.isArray(response.workers)) {
|
|
2040
|
+
throw new RelayProtocolError("GET", path3, "workers must be an array");
|
|
2041
|
+
}
|
|
2042
|
+
return { workers: response.workers.map((worker) => _parseWorkerRecord(worker, path3)) };
|
|
2043
|
+
}
|
|
2044
|
+
async submitJob(captainId, body) {
|
|
2045
|
+
requireCaptainId(captainId);
|
|
2046
|
+
_validateWorkerJobSubmit(body);
|
|
2047
|
+
const path3 = `/api/v1/captains/${segment(captainId)}/task`;
|
|
2048
|
+
const spec = {
|
|
2049
|
+
argv: [...body.argv],
|
|
2050
|
+
...body.timeoutSec === undefined ? {} : { timeout_sec: body.timeoutSec }
|
|
2051
|
+
};
|
|
2052
|
+
const response = await this.requestJson("POST", path3, { kind: "bash", worker: body.worker, spec });
|
|
2053
|
+
return _parseWorkerJobSubmitResponse(response, path3);
|
|
2054
|
+
}
|
|
2055
|
+
async getJobStatus(captainId, jobId) {
|
|
2056
|
+
return this._getJob(captainId, jobId);
|
|
2057
|
+
}
|
|
2058
|
+
async getJobResult(captainId, jobId, timeoutSec) {
|
|
2059
|
+
_validateWorkerJobWaitTimeout(timeoutSec);
|
|
2060
|
+
return this._getJob(captainId, jobId, timeoutSec);
|
|
2061
|
+
}
|
|
2062
|
+
async _getJob(captainId, jobId, timeoutSec) {
|
|
2063
|
+
requireCaptainId(captainId);
|
|
2064
|
+
requireSegment(jobId, "jobId");
|
|
2065
|
+
const base = `/api/v1/captains/${segment(captainId)}/task/${segment(jobId)}`;
|
|
2066
|
+
const path3 = timeoutSec === undefined ? base : `${base}?wait=true&timeout_sec=${timeoutSec}`;
|
|
2067
|
+
const timeoutMs = timeoutSec === undefined ? this.defaultTimeoutMs : (timeoutSec + 5) * 1000;
|
|
2068
|
+
return _parseWorkerJobResultResponse(await this.requestJson("GET", path3, undefined, timeoutMs), path3);
|
|
2069
|
+
}
|
|
2002
2070
|
async claimMailbox(agentName, options = {}) {
|
|
2003
2071
|
requireSegment(agentName, "agentName");
|
|
2004
2072
|
if (options.messageId)
|
|
@@ -2917,14 +2985,139 @@ function parseAgentMonitor(value) {
|
|
|
2917
2985
|
if (typeof value.context_checkpoint_percent !== "number" || !Number.isFinite(value.context_checkpoint_percent)) {
|
|
2918
2986
|
throw new RelayProtocolError("GET", "/api/v1/agents/{name}/monitor", "context_checkpoint_percent must be a finite number");
|
|
2919
2987
|
}
|
|
2988
|
+
if (value.idle_presave_min !== null && (typeof value.idle_presave_min !== "number" || !Number.isFinite(value.idle_presave_min))) {
|
|
2989
|
+
throw new RelayProtocolError("GET", "/api/v1/agents/{name}/monitor", "idle_presave_min must be a finite number or null");
|
|
2990
|
+
}
|
|
2991
|
+
const latestInbound = value.latest_message_inbound_at;
|
|
2992
|
+
const latestOutbound = value.latest_message_outbound_at;
|
|
2993
|
+
if (latestInbound !== null && typeof latestInbound !== "string") {
|
|
2994
|
+
throw new RelayProtocolError("GET", "/api/v1/agents/{name}/monitor", "latest_message_inbound_at must be string or null");
|
|
2995
|
+
}
|
|
2996
|
+
if (latestOutbound !== null && typeof latestOutbound !== "string") {
|
|
2997
|
+
throw new RelayProtocolError("GET", "/api/v1/agents/{name}/monitor", "latest_message_outbound_at must be string or null");
|
|
2998
|
+
}
|
|
2920
2999
|
return {
|
|
2921
3000
|
name: value.name,
|
|
2922
3001
|
engine: value.engine,
|
|
2923
3002
|
should_resume: value.should_resume,
|
|
2924
3003
|
session_handle: value.session_handle,
|
|
2925
|
-
context_checkpoint_percent: value.context_checkpoint_percent
|
|
3004
|
+
context_checkpoint_percent: value.context_checkpoint_percent,
|
|
3005
|
+
idle_presave_min: value.idle_presave_min,
|
|
3006
|
+
latest_message_inbound_at: latestInbound,
|
|
3007
|
+
latest_message_outbound_at: latestOutbound
|
|
2926
3008
|
};
|
|
2927
3009
|
}
|
|
3010
|
+
function _parseWorkerRecord(value, path3) {
|
|
3011
|
+
const worker = _requireObject(value, "GET", path3, "worker");
|
|
3012
|
+
for (const field of ["id", "session", "name", "host", "consumer_status", "last_seen"]) {
|
|
3013
|
+
_requireStringField(worker, field, "GET", path3, "worker");
|
|
3014
|
+
}
|
|
3015
|
+
if (!isStringArray(worker.capabilities) || !isStringArray(worker.caps)) {
|
|
3016
|
+
throw new RelayProtocolError("GET", path3, "worker capabilities and caps must be string arrays");
|
|
3017
|
+
}
|
|
3018
|
+
if (!Number.isSafeInteger(worker.max_concurrency) || worker.max_concurrency < 1) {
|
|
3019
|
+
throw new RelayProtocolError("GET", path3, "worker.max_concurrency must be a positive integer");
|
|
3020
|
+
}
|
|
3021
|
+
if (typeof worker.online !== "boolean") {
|
|
3022
|
+
throw new RelayProtocolError("GET", path3, "worker.online must be boolean");
|
|
3023
|
+
}
|
|
3024
|
+
return worker;
|
|
3025
|
+
}
|
|
3026
|
+
function _validateWorkerJobSubmit(body) {
|
|
3027
|
+
requireSegment(body.worker, "worker");
|
|
3028
|
+
if (body.argv.length === 0 || !body.argv[0]?.trim())
|
|
3029
|
+
throw new Error("job argv requires a command");
|
|
3030
|
+
if (body.argv.some((arg) => typeof arg !== "string"))
|
|
3031
|
+
throw new Error("job argv must contain strings");
|
|
3032
|
+
if (body.timeoutSec !== undefined)
|
|
3033
|
+
_validateWorkerJobTimeout(body.timeoutSec);
|
|
3034
|
+
}
|
|
3035
|
+
function _validateWorkerJobTimeout(value) {
|
|
3036
|
+
if (!Number.isFinite(value) || value < 1 || value > MAX_JOB_TIMEOUT_SECONDS) {
|
|
3037
|
+
throw new Error(`timeoutSec must be a number from 1 to ${MAX_JOB_TIMEOUT_SECONDS}`);
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
function _validateWorkerJobWaitTimeout(value) {
|
|
3041
|
+
const maximum = MAX_JOB_TIMEOUT_SECONDS + WORKER_JOB_RESULT_GRACE_SECONDS;
|
|
3042
|
+
if (!Number.isFinite(value) || value < 1 || value > maximum) {
|
|
3043
|
+
throw new Error(`result wait timeoutSec must be a number from 1 to ${maximum}`);
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
function _parseWorkerJobSubmitResponse(value, path3) {
|
|
3047
|
+
if (typeof value.id !== "string" || !value.id || value.status !== "queued") {
|
|
3048
|
+
throw new RelayProtocolError("POST", path3, "job submit response requires id and queued status");
|
|
3049
|
+
}
|
|
3050
|
+
if (value.warning !== undefined && typeof value.warning !== "string") {
|
|
3051
|
+
throw new RelayProtocolError("POST", path3, "job submit warning must be a string");
|
|
3052
|
+
}
|
|
3053
|
+
return {
|
|
3054
|
+
id: value.id,
|
|
3055
|
+
status: "queued",
|
|
3056
|
+
...value.warning === undefined ? {} : { warning: value.warning }
|
|
3057
|
+
};
|
|
3058
|
+
}
|
|
3059
|
+
function _parseWorkerJobResultResponse(value, path3) {
|
|
3060
|
+
const status = value.status;
|
|
3061
|
+
if (!_isWorkerJobStatus(status))
|
|
3062
|
+
throw new RelayProtocolError("GET", path3, "job status is invalid");
|
|
3063
|
+
for (const field of ["id", "created_at"])
|
|
3064
|
+
_requireStringField(value, field, "GET", path3, "job");
|
|
3065
|
+
_requireNullableStringFields(value, ["started_at", "finished_at", "submitter_agent_name"], path3);
|
|
3066
|
+
_requireNullableNumberFields(value, ["duration_sec"], path3);
|
|
3067
|
+
if (value.exit_code !== null && !Number.isSafeInteger(value.exit_code)) {
|
|
3068
|
+
throw new RelayProtocolError("GET", path3, "job.exit_code must be an integer or null");
|
|
3069
|
+
}
|
|
3070
|
+
const result = value.result === undefined ? undefined : _parseWorkerJobResult(value.result, path3);
|
|
3071
|
+
if (_isTerminalJobStatus(status) && (result === undefined || value.exit_code !== result.exit_code)) {
|
|
3072
|
+
throw new RelayProtocolError("GET", path3, "terminal job response requires a matching result");
|
|
3073
|
+
}
|
|
3074
|
+
return { ...value, status, ...result ? { result } : {} };
|
|
3075
|
+
}
|
|
3076
|
+
function _parseWorkerJobResult(value, path3) {
|
|
3077
|
+
const result = _requireObject(value, "GET", path3, "job result");
|
|
3078
|
+
for (const field of ["stdout", "stderr"])
|
|
3079
|
+
_requireStringField(result, field, "GET", path3, "job result", true);
|
|
3080
|
+
_requireNullableStringFields(result, ["started_at", "ended_at"], path3, "job result");
|
|
3081
|
+
if (!Number.isSafeInteger(result.exit_code)) {
|
|
3082
|
+
throw new RelayProtocolError("GET", path3, "job result.exit_code must be an integer");
|
|
3083
|
+
}
|
|
3084
|
+
_requireNullableNumberFields(result, ["duration_sec"], path3, "job result");
|
|
3085
|
+
if (!isStringArray(result.attached_file_paths)) {
|
|
3086
|
+
throw new RelayProtocolError("GET", path3, "job result.attached_file_paths must be a string array");
|
|
3087
|
+
}
|
|
3088
|
+
return result;
|
|
3089
|
+
}
|
|
3090
|
+
function _isWorkerJobStatus(value) {
|
|
3091
|
+
return value === "queued" || value === "running" || value === "done" || value === "failed" || value === "cancelled";
|
|
3092
|
+
}
|
|
3093
|
+
function _isTerminalJobStatus(value) {
|
|
3094
|
+
return value === "done" || value === "failed" || value === "cancelled";
|
|
3095
|
+
}
|
|
3096
|
+
function _requireObject(value, method, path3, label) {
|
|
3097
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3098
|
+
throw new RelayProtocolError(method, path3, `${label} must be an object`);
|
|
3099
|
+
}
|
|
3100
|
+
return value;
|
|
3101
|
+
}
|
|
3102
|
+
function _requireStringField(value, field, method, path3, label, allowEmpty = false) {
|
|
3103
|
+
if (typeof value[field] !== "string" || !allowEmpty && !value[field]) {
|
|
3104
|
+
throw new RelayProtocolError(method, path3, `${label}.${field} must be a string`);
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
function _requireNullableStringFields(value, fields, path3, label = "job") {
|
|
3108
|
+
for (const field of fields) {
|
|
3109
|
+
if (value[field] !== null && typeof value[field] !== "string") {
|
|
3110
|
+
throw new RelayProtocolError("GET", path3, `${label}.${field} must be a string or null`);
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
function _requireNullableNumberFields(value, fields, path3, label = "job") {
|
|
3115
|
+
for (const field of fields) {
|
|
3116
|
+
if (value[field] !== null && (typeof value[field] !== "number" || !Number.isFinite(value[field]))) {
|
|
3117
|
+
throw new RelayProtocolError("GET", path3, `${label}.${field} must be a finite number or null`);
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
2928
3121
|
function parseScheduledEventResponse(value, method, path3) {
|
|
2929
3122
|
return { event: parseScheduledEvent(value.event, method, path3) };
|
|
2930
3123
|
}
|
|
@@ -3854,41 +4047,10 @@ function redact(value, token) {
|
|
|
3854
4047
|
function bytesToBase64(bytes) {
|
|
3855
4048
|
return Buffer2.from(bytes).toString("base64");
|
|
3856
4049
|
}
|
|
3857
|
-
// .dist-releases/
|
|
4050
|
+
// .dist-releases/1784862378006-1249051/src/relay/config.js
|
|
3858
4051
|
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
3859
4052
|
import { homedir as homedir3 } from "node:os";
|
|
3860
4053
|
import path3 from "node:path";
|
|
3861
|
-
|
|
3862
|
-
// .dist-releases/1784809313131-4113078/src/worker/protocol.js
|
|
3863
|
-
var DEFAULT_RELAY_URL = DEFAULT_PRODUCT_API_URL;
|
|
3864
|
-
var DEFAULT_WORKER = "host";
|
|
3865
|
-
var DEFAULT_WORKDIR = "~/sailorbridge-workdir";
|
|
3866
|
-
var DEFAULT_JOB_TIMEOUT_SECONDS = 300;
|
|
3867
|
-
var MAX_JOB_TIMEOUT_SECONDS = 24 * 60 * 60;
|
|
3868
|
-
var MIN_JOB_TIMEOUT_SECONDS = 1;
|
|
3869
|
-
var ACTIVE_JOB_KINDS = new Set(["apply_diff", "bash", "read_file", "write_file", "compose", "stream", "status"]);
|
|
3870
|
-
var READONLY_ALLOWED_KINDS = new Set(["read_file", "status"]);
|
|
3871
|
-
var WORKER_SOCK_CONNECT_MS = 1e4;
|
|
3872
|
-
var WORKER_PULL_READ_IDLE_MS = 45000;
|
|
3873
|
-
var WORKER_QUICK_READ_IDLE_MS = 15000;
|
|
3874
|
-
var WORKER_UPLOAD_READ_IDLE_MS = (MAX_JOB_TIMEOUT_SECONDS + 300) * 1000;
|
|
3875
|
-
var DRAIN_AFTER_KILL_MS = 5000;
|
|
3876
|
-
var WORKER_RETRY_INITIAL_MS = 1000;
|
|
3877
|
-
var WORKER_RETRY_MAX_MS = 30000;
|
|
3878
|
-
var WORKER_SESSION_REBUILD_FAILURES = 10;
|
|
3879
|
-
var MAX_WORKER_RESULT_OUTPUT_BYTES = 256 * 1024;
|
|
3880
|
-
function coerceJobTimeoutSeconds(spec) {
|
|
3881
|
-
const value = spec.timeout_sec === undefined ? DEFAULT_JOB_TIMEOUT_SECONDS : spec.timeout_sec;
|
|
3882
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
3883
|
-
throw new Error("spec.timeout_sec must be a finite positive number");
|
|
3884
|
-
}
|
|
3885
|
-
return Math.max(MIN_JOB_TIMEOUT_SECONDS, Math.min(value, MAX_JOB_TIMEOUT_SECONDS));
|
|
3886
|
-
}
|
|
3887
|
-
function effectiveJobKind(kind, spec) {
|
|
3888
|
-
return kind === "stream" || spec.stream === true ? "stream" : kind;
|
|
3889
|
-
}
|
|
3890
|
-
|
|
3891
|
-
// .dist-releases/1784809313131-4113078/src/relay/config.js
|
|
3892
4054
|
function loadRelayConfig(env = process.env) {
|
|
3893
4055
|
const envRelayUrl = nonEmpty(env.SAILORBRIDGE_RELAY_URL);
|
|
3894
4056
|
const envBearerToken = nonEmpty(env.SAILORBRIDGE_TOKEN);
|
|
@@ -3960,7 +4122,7 @@ function storedCaptainId(value) {
|
|
|
3960
4122
|
}
|
|
3961
4123
|
return;
|
|
3962
4124
|
}
|
|
3963
|
-
// .dist-releases/
|
|
4125
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/retirement.js
|
|
3964
4126
|
var DEFAULT_THRESHOLD = 3;
|
|
3965
4127
|
var DEFAULT_WINDOW_MS = 30000;
|
|
3966
4128
|
var DEFAULT_COOLDOWN_MS = 1000;
|
|
@@ -4035,7 +4197,7 @@ function isAuthoritativeRetirementReason(reason) {
|
|
|
4035
4197
|
return reason === "monitor_fetch" || reason === "agent_session_patch";
|
|
4036
4198
|
}
|
|
4037
4199
|
|
|
4038
|
-
// .dist-releases/
|
|
4200
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/wait.js
|
|
4039
4201
|
async function waitForWakeableTimeout(ms, setWake, sleep3) {
|
|
4040
4202
|
if (sleep3) {
|
|
4041
4203
|
await Promise.race([
|
|
@@ -4066,7 +4228,7 @@ async function waitForWakeableTimeout(ms, setWake, sleep3) {
|
|
|
4066
4228
|
setWake(null);
|
|
4067
4229
|
}
|
|
4068
4230
|
|
|
4069
|
-
// .dist-releases/
|
|
4231
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/mailbox.js
|
|
4070
4232
|
var CLEAR_TAG = "CLEAR";
|
|
4071
4233
|
var REFRESH_TAG = "WORKFLOW-REFRESH";
|
|
4072
4234
|
var SYNC_TAG = "SYNC";
|
|
@@ -4602,19 +4764,19 @@ function ordinaryDeliveryAttempt(error) {
|
|
|
4602
4764
|
function _isMissingModerator(error) {
|
|
4603
4765
|
return error instanceof RelayHttpError && error.status === 400 && error.body.includes("no agents match");
|
|
4604
4766
|
}
|
|
4605
|
-
// .dist-releases/
|
|
4767
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/runtime.js
|
|
4606
4768
|
import path9 from "node:path";
|
|
4607
4769
|
import { execFile } from "node:child_process";
|
|
4608
4770
|
import { promisify } from "node:util";
|
|
4609
4771
|
|
|
4610
|
-
// .dist-releases/
|
|
4772
|
+
// .dist-releases/1784862378006-1249051/src/host/managed-materialization.js
|
|
4611
4773
|
import { createHash as createHash2, randomBytes } from "node:crypto";
|
|
4612
4774
|
import { constants as fsConstants } from "node:fs";
|
|
4613
4775
|
import { lstat, mkdir as mkdir3, open, readdir, rename, rm as rm2 } from "node:fs/promises";
|
|
4614
4776
|
import { homedir as homedir5 } from "node:os";
|
|
4615
4777
|
import path5 from "node:path";
|
|
4616
4778
|
|
|
4617
|
-
// .dist-releases/
|
|
4779
|
+
// .dist-releases/1784862378006-1249051/src/host/memory-stub.js
|
|
4618
4780
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile3 } from "node:fs/promises";
|
|
4619
4781
|
import { homedir as homedir4 } from "node:os";
|
|
4620
4782
|
import path4 from "node:path";
|
|
@@ -4761,7 +4923,7 @@ function _safePathLabel(value, field) {
|
|
|
4761
4923
|
return trimmed;
|
|
4762
4924
|
}
|
|
4763
4925
|
|
|
4764
|
-
// .dist-releases/
|
|
4926
|
+
// .dist-releases/1784862378006-1249051/src/host/managed-materialization.js
|
|
4765
4927
|
var MANIFEST_FILE = ".sailorbridge-managed-manifest.json";
|
|
4766
4928
|
var BANNER_PREFIX = "# SailorBridge managed file";
|
|
4767
4929
|
var HASH_RE = /^sha256:[a-f0-9]{64}$/u;
|
|
@@ -5287,7 +5449,7 @@ function _expandHome2(value) {
|
|
|
5287
5449
|
return value;
|
|
5288
5450
|
}
|
|
5289
5451
|
|
|
5290
|
-
// .dist-releases/
|
|
5452
|
+
// .dist-releases/1784862378006-1249051/src/host/credential-guardian.js
|
|
5291
5453
|
import { lstat as lstat2, readFile as readFile3, rename as rename2, symlink, unlink, writeFile as writeFile4 } from "node:fs/promises";
|
|
5292
5454
|
import path6 from "node:path";
|
|
5293
5455
|
var DEFAULT_CREDENTIAL_SWEEP_INTERVAL_MS = 60000;
|
|
@@ -5433,7 +5595,7 @@ function _tmpSibling(filePath) {
|
|
|
5433
5595
|
return path6.join(path6.dirname(filePath), `.${path6.basename(filePath)}.sb-guardian.${process.pid}.${tmpSequence}.tmp`);
|
|
5434
5596
|
}
|
|
5435
5597
|
|
|
5436
|
-
// .dist-releases/
|
|
5598
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/resolve.js
|
|
5437
5599
|
var DEFAULT_CAPTURE_LINES = 200;
|
|
5438
5600
|
var MAX_CAPTURE_LINES = 1000;
|
|
5439
5601
|
|
|
@@ -5639,7 +5801,7 @@ function defaultSleep(ms) {
|
|
|
5639
5801
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5640
5802
|
}
|
|
5641
5803
|
|
|
5642
|
-
// .dist-releases/
|
|
5804
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/transcript-backfill.js
|
|
5643
5805
|
import { createHash as createHash3 } from "node:crypto";
|
|
5644
5806
|
import {
|
|
5645
5807
|
closeSync,
|
|
@@ -6296,7 +6458,7 @@ function errorMessage4(error) {
|
|
|
6296
6458
|
return error instanceof Error ? error.message : String(error);
|
|
6297
6459
|
}
|
|
6298
6460
|
|
|
6299
|
-
// .dist-releases/
|
|
6461
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/usage-collector.js
|
|
6300
6462
|
import { statSync as statSync2 } from "node:fs";
|
|
6301
6463
|
import path8 from "node:path";
|
|
6302
6464
|
var SUPPORTED_USAGE_ENGINES = new Set(["claude", "codex"]);
|
|
@@ -6705,7 +6867,7 @@ function sourceUnreadableReason(source) {
|
|
|
6705
6867
|
}
|
|
6706
6868
|
}
|
|
6707
6869
|
|
|
6708
|
-
// .dist-releases/
|
|
6870
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/runtime.js
|
|
6709
6871
|
var RESOLVE_CAPTURE_LINES = 200;
|
|
6710
6872
|
var SHORT_LIVED_EXIT_MS = 5000;
|
|
6711
6873
|
var STARTUP_OBSERVATION_MS = 1e4;
|
|
@@ -7375,7 +7537,7 @@ function errorMessage5(error) {
|
|
|
7375
7537
|
function formatRestartCommand(command) {
|
|
7376
7538
|
return command.map((part) => /^[A-Za-z0-9_./:=@%+-]+$/.test(part) ? part : `'${part.replaceAll("'", "'\\''")}'`).join(" ");
|
|
7377
7539
|
}
|
|
7378
|
-
// .dist-releases/
|
|
7540
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/transport.js
|
|
7379
7541
|
var SUPPORTED_PHASE1_CLI_KINDS = ["claude", "codex"];
|
|
7380
7542
|
var PHASE1_ENGINE_GATE_MESSAGE = "Only claude and codex engines are available in this release; opencode and custom CLI engines will open in the next release.";
|
|
7381
7543
|
var PHASE1_TRANSPORT_GATE_MESSAGE = "Only tmux transport is available in this release; sdk, headless, and pty transports will open in the next release.";
|
|
@@ -7583,7 +7745,7 @@ function hasCodexSafetyDriverOptions(options) {
|
|
|
7583
7745
|
return options?.codex?.sandboxMode !== undefined || options?.codex?.approvalPolicy !== undefined || options?.codex?.yolo !== undefined;
|
|
7584
7746
|
}
|
|
7585
7747
|
|
|
7586
|
-
// .dist-releases/
|
|
7748
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/cli-options.js
|
|
7587
7749
|
function parseSuperviseArgs(argv) {
|
|
7588
7750
|
const split = argv.indexOf("--");
|
|
7589
7751
|
const flagArgs = split >= 0 ? argv.slice(0, split) : argv;
|
|
@@ -7735,7 +7897,7 @@ function optionalBoolean(value, label) {
|
|
|
7735
7897
|
return false;
|
|
7736
7898
|
throw new Error(`${label} must be true or false`);
|
|
7737
7899
|
}
|
|
7738
|
-
// .dist-releases/
|
|
7900
|
+
// .dist-releases/1784862378006-1249051/src/supervisor/tmux-availability.js
|
|
7739
7901
|
import { spawn as spawn3 } from "node:child_process";
|
|
7740
7902
|
import { createInterface } from "node:readline";
|
|
7741
7903
|
function isTmuxAvailable(spawnFn = spawn3) {
|
|
@@ -7852,26 +8014,29 @@ function _tmuxMissingMessage(platform2) {
|
|
|
7852
8014
|
const how = platform2 === "darwin" ? "brew install tmux" : platform2 === "linux" ? "install tmux via your package manager (e.g. sudo apt-get install -y tmux)" : "install tmux";
|
|
7853
8015
|
return `tmux is required in this release but was not found. Install tmux (${how}) and re-run.`;
|
|
7854
8016
|
}
|
|
7855
|
-
// .dist-releases/
|
|
8017
|
+
// .dist-releases/1784862378006-1249051/src/output-format.js
|
|
7856
8018
|
function parseOutputArgs(argv) {
|
|
8019
|
+
const separator = argv.indexOf("--");
|
|
8020
|
+
const localArgv = separator < 0 ? argv : argv.slice(0, separator);
|
|
8021
|
+
const remoteArgv = separator < 0 ? [] : argv.slice(separator);
|
|
7857
8022
|
const cleaned = [];
|
|
7858
8023
|
let format = "plain";
|
|
7859
8024
|
let seen = false;
|
|
7860
|
-
for (let index = 0;index <
|
|
7861
|
-
const token =
|
|
8025
|
+
for (let index = 0;index < localArgv.length; index += 1) {
|
|
8026
|
+
const token = localArgv[index];
|
|
7862
8027
|
if (token !== "--format" && !token.startsWith("--format=")) {
|
|
7863
8028
|
cleaned.push(token);
|
|
7864
8029
|
continue;
|
|
7865
8030
|
}
|
|
7866
8031
|
if (seen)
|
|
7867
8032
|
throw new Error("--format may only be provided once");
|
|
7868
|
-
const value = token === "--format" ?
|
|
8033
|
+
const value = token === "--format" ? localArgv[++index] : token.slice("--format=".length);
|
|
7869
8034
|
if (value !== "plain" && value !== "json")
|
|
7870
8035
|
throw new Error("--format must be plain or json");
|
|
7871
8036
|
format = value;
|
|
7872
8037
|
seen = true;
|
|
7873
8038
|
}
|
|
7874
|
-
return { argv: cleaned, format, provided: seen };
|
|
8039
|
+
return { argv: [...cleaned, ...remoteArgv], format, provided: seen };
|
|
7875
8040
|
}
|
|
7876
8041
|
function _renderOutput(value, format, plain) {
|
|
7877
8042
|
if (format === "json") {
|
|
@@ -7942,7 +8107,7 @@ ${normalized.split(`
|
|
|
7942
8107
|
`)}`;
|
|
7943
8108
|
}
|
|
7944
8109
|
|
|
7945
|
-
// .dist-releases/
|
|
8110
|
+
// .dist-releases/1784862378006-1249051/src/plain-output-fields.js
|
|
7946
8111
|
var PREVIEW_LIMIT = 20;
|
|
7947
8112
|
var UNSAFE_DISPLAY_CODE_POINT = /[\u007f-\u009f\u2028-\u202e\u2066-\u2069]/gu;
|
|
7948
8113
|
function renderTaskPlain(command, value) {
|
|
@@ -8350,7 +8515,7 @@ function _omissionLine(total) {
|
|
|
8350
8515
|
return total > PREVIEW_LIMIT ? `Omitted ${total - PREVIEW_LIMIT}; rerun with --format json for the complete response.` : undefined;
|
|
8351
8516
|
}
|
|
8352
8517
|
|
|
8353
|
-
// .dist-releases/
|
|
8518
|
+
// .dist-releases/1784862378006-1249051/src/host/cli.js
|
|
8354
8519
|
var HOST_RELAY_SUBCOMMANDS = new Set(["consume", "heartbeat", "list", "register"]);
|
|
8355
8520
|
async function runHostCommandFromCli(client, argv, config, io) {
|
|
8356
8521
|
const sub = argv[0] ?? "list";
|
|
@@ -8588,7 +8753,7 @@ function optionalDisplayName(value) {
|
|
|
8588
8753
|
const trimmed = value?.trim();
|
|
8589
8754
|
return trimmed || undefined;
|
|
8590
8755
|
}
|
|
8591
|
-
// .dist-releases/
|
|
8756
|
+
// .dist-releases/1784862378006-1249051/src/host/service.js
|
|
8592
8757
|
import { execFile as execFileCb } from "node:child_process";
|
|
8593
8758
|
import { createHash as createHash4 } from "node:crypto";
|
|
8594
8759
|
import { constants as fsConstants2 } from "node:fs";
|
|
@@ -9071,7 +9236,7 @@ function writeServiceLog(io, event, fields) {
|
|
|
9071
9236
|
io.stderr.write(`${JSON.stringify({ ts: new Date().toISOString(), event, ...fields ?? {} })}
|
|
9072
9237
|
`);
|
|
9073
9238
|
}
|
|
9074
|
-
// .dist-releases/
|
|
9239
|
+
// .dist-releases/1784862378006-1249051/src/host/git-remote.js
|
|
9075
9240
|
var GIT_SECRET_PATH_MARKERS = [
|
|
9076
9241
|
"token",
|
|
9077
9242
|
"credential",
|
|
@@ -9163,7 +9328,7 @@ function looksLikeCredential(segment2) {
|
|
|
9163
9328
|
return value.length >= 32 && /^[A-Za-z0-9_-]+$/u.test(value);
|
|
9164
9329
|
}
|
|
9165
9330
|
|
|
9166
|
-
// .dist-releases/
|
|
9331
|
+
// .dist-releases/1784862378006-1249051/src/host/start-spec.js
|
|
9167
9332
|
var TRANSPORTS = ["auto", "sdk", "pty", "tmux", "headless"];
|
|
9168
9333
|
var SUPPORTED_PHASE1_ENGINES = ["claude", "codex"];
|
|
9169
9334
|
var ENGINE_PATTERN = /^[a-z][a-z0-9._-]{0,63}$/u;
|
|
@@ -9413,7 +9578,7 @@ function _trimmed(value, label) {
|
|
|
9413
9578
|
throw new Error(`${label} must not be empty`);
|
|
9414
9579
|
return trimmed;
|
|
9415
9580
|
}
|
|
9416
|
-
// .dist-releases/
|
|
9581
|
+
// .dist-releases/1784862378006-1249051/src/host/workspace.js
|
|
9417
9582
|
import { spawn as spawn4 } from "node:child_process";
|
|
9418
9583
|
import { existsSync as existsSync4 } from "node:fs";
|
|
9419
9584
|
import { mkdir as mkdir5, readdir as readdir2, rename as rename4, stat } from "node:fs/promises";
|
|
@@ -9644,7 +9809,7 @@ function _safeSegment(value) {
|
|
|
9644
9809
|
throw new Error("workspace path segment is empty after sanitizing");
|
|
9645
9810
|
return segment2;
|
|
9646
9811
|
}
|
|
9647
|
-
// .dist-releases/
|
|
9812
|
+
// .dist-releases/1784862378006-1249051/src/host/workspace-inventory.js
|
|
9648
9813
|
import { access as access2 } from "node:fs/promises";
|
|
9649
9814
|
import { constants } from "node:fs";
|
|
9650
9815
|
import { execFile as execFile2 } from "node:child_process";
|
|
@@ -9736,7 +9901,7 @@ async function canAccess(path12, mode, deps) {
|
|
|
9736
9901
|
return false;
|
|
9737
9902
|
}
|
|
9738
9903
|
}
|
|
9739
|
-
// .dist-releases/
|
|
9904
|
+
// .dist-releases/1784862378006-1249051/src/host/host-config.js
|
|
9740
9905
|
import { chmod as chmod3, mkdir as mkdir6, readFile as readFile5, writeFile as writeFile6 } from "node:fs/promises";
|
|
9741
9906
|
import { homedir as homedir10 } from "node:os";
|
|
9742
9907
|
import path12 from "node:path";
|
|
@@ -9821,7 +9986,7 @@ function _parseHostConfig(text, configPath) {
|
|
|
9821
9986
|
});
|
|
9822
9987
|
return { kind: HOST_CONFIG_KIND, workspaces };
|
|
9823
9988
|
}
|
|
9824
|
-
// .dist-releases/
|
|
9989
|
+
// .dist-releases/1784862378006-1249051/src/host/host-workspace-cli.js
|
|
9825
9990
|
async function runHostWorkspaceCommandFromCli(argv, io, deps = {}) {
|
|
9826
9991
|
const configPath = deps.configPath ?? defaultHostConfigPath();
|
|
9827
9992
|
const sub = argv[0] ?? "list";
|
|
@@ -9865,7 +10030,7 @@ function _renderAddPlain(result) {
|
|
|
9865
10030
|
return result.note ? `${status} ${result.path}
|
|
9866
10031
|
${result.note}` : `${status} ${result.path}`;
|
|
9867
10032
|
}
|
|
9868
|
-
// .dist-releases/
|
|
10033
|
+
// .dist-releases/1784862378006-1249051/src/host/agent-env.js
|
|
9869
10034
|
var RUNTIME_NATIVE_HOME_ENV = new Set(["CLAUDE_CONFIG_DIR", "CODEX_HOME"]);
|
|
9870
10035
|
function buildAgentEnv(options) {
|
|
9871
10036
|
const env = {};
|
|
@@ -9894,15 +10059,15 @@ function buildAgentEnv(options) {
|
|
|
9894
10059
|
}
|
|
9895
10060
|
return env;
|
|
9896
10061
|
}
|
|
9897
|
-
// .dist-releases/
|
|
10062
|
+
// .dist-releases/1784862378006-1249051/src/host/runtime-env.js
|
|
9898
10063
|
import path16 from "node:path";
|
|
9899
10064
|
|
|
9900
|
-
// .dist-releases/
|
|
10065
|
+
// .dist-releases/1784862378006-1249051/src/host/agent-defaults.js
|
|
9901
10066
|
import { chmod as chmod4, mkdir as mkdir7, readFile as readFile7, stat as stat2, writeFile as writeFile7 } from "node:fs/promises";
|
|
9902
10067
|
import { homedir as homedir11 } from "node:os";
|
|
9903
10068
|
import path14 from "node:path";
|
|
9904
10069
|
|
|
9905
|
-
// .dist-releases/
|
|
10070
|
+
// .dist-releases/1784862378006-1249051/src/host/claude-settings.js
|
|
9906
10071
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
9907
10072
|
import path13 from "node:path";
|
|
9908
10073
|
async function readHostClaudeSettings(claudeConfigDir) {
|
|
@@ -9943,7 +10108,7 @@ function _nonEmptyString(value) {
|
|
|
9943
10108
|
return typeof value === "string" && value.trim() ? value : null;
|
|
9944
10109
|
}
|
|
9945
10110
|
|
|
9946
|
-
// .dist-releases/
|
|
10111
|
+
// .dist-releases/1784862378006-1249051/src/host/agent-defaults.js
|
|
9947
10112
|
var CODEX_BLOCK_BEGIN = "# sailorbridge-terse-defaults:begin";
|
|
9948
10113
|
var CODEX_BLOCK_END = "# sailorbridge-terse-defaults:end";
|
|
9949
10114
|
var CODEX_MODEL_BLOCK_BEGIN = "# sailorbridge-host-model-settings:begin";
|
|
@@ -11073,7 +11238,7 @@ function _escapeRegExp(value) {
|
|
|
11073
11238
|
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
11074
11239
|
}
|
|
11075
11240
|
|
|
11076
|
-
// .dist-releases/
|
|
11241
|
+
// .dist-releases/1784862378006-1249051/src/host/engine-auth.js
|
|
11077
11242
|
import { lstat as lstat4, mkdir as mkdir8, readlink, realpath, stat as stat3, symlink as symlink2, unlink as unlink2 } from "node:fs/promises";
|
|
11078
11243
|
import { homedir as homedir12 } from "node:os";
|
|
11079
11244
|
import path15 from "node:path";
|
|
@@ -11163,7 +11328,7 @@ async function _ensureSymlink(linkPath, targetPath, sharedTargetPath) {
|
|
|
11163
11328
|
await symlink2(targetPath, linkPath);
|
|
11164
11329
|
}
|
|
11165
11330
|
|
|
11166
|
-
// .dist-releases/
|
|
11331
|
+
// .dist-releases/1784862378006-1249051/src/host/runtime-env.js
|
|
11167
11332
|
async function materializeAgentRuntimeEnv(options) {
|
|
11168
11333
|
const env = buildAgentEnv({
|
|
11169
11334
|
hostEnv: options.hostEnv,
|
|
@@ -11203,7 +11368,7 @@ function _ensureRootSandboxEscape(env, engine, uid) {
|
|
|
11203
11368
|
function _currentUid() {
|
|
11204
11369
|
return typeof process.getuid === "function" ? process.getuid() : null;
|
|
11205
11370
|
}
|
|
11206
|
-
// .dist-releases/
|
|
11371
|
+
// .dist-releases/1784862378006-1249051/src/host/context-statusline.js
|
|
11207
11372
|
function renderClaudeContextStatusLine(payload) {
|
|
11208
11373
|
const percent = _usedPercentage(payload);
|
|
11209
11374
|
if (percent === null)
|
|
@@ -11241,7 +11406,7 @@ function _bar(percent) {
|
|
|
11241
11406
|
const filled = Math.min(10, Math.max(0, Math.trunc(percent / 10)));
|
|
11242
11407
|
return "█".repeat(filled) + "░".repeat(10 - filled);
|
|
11243
11408
|
}
|
|
11244
|
-
// .dist-releases/
|
|
11409
|
+
// .dist-releases/1784862378006-1249051/src/host/scratch-sweeper.js
|
|
11245
11410
|
import { execFile as execFile3 } from "node:child_process";
|
|
11246
11411
|
import { lstat as lstat5, readdir as readdir3, realpath as realpath2, unlink as unlink3 } from "node:fs/promises";
|
|
11247
11412
|
import path17 from "node:path";
|
|
@@ -11384,7 +11549,7 @@ function _errno(error) {
|
|
|
11384
11549
|
return String(error.code);
|
|
11385
11550
|
return error instanceof Error ? error.message : String(error);
|
|
11386
11551
|
}
|
|
11387
|
-
// .dist-releases/
|
|
11552
|
+
// .dist-releases/1784862378006-1249051/src/host/launcher.js
|
|
11388
11553
|
var MAX_TMUX_SESSION_SUFFIX = 100;
|
|
11389
11554
|
async function launchSupervisedAgent(input, deps = {}) {
|
|
11390
11555
|
const spec = parseAgentStartSpec(input.spec);
|
|
@@ -11535,7 +11700,7 @@ async function _tmuxSessionExists(session) {
|
|
|
11535
11700
|
throw error;
|
|
11536
11701
|
}
|
|
11537
11702
|
}
|
|
11538
|
-
// .dist-releases/
|
|
11703
|
+
// .dist-releases/1784862378006-1249051/src/worker/capability.js
|
|
11539
11704
|
import { accessSync, constants as constants2, mkdirSync as mkdirSync3, mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
11540
11705
|
import os from "node:os";
|
|
11541
11706
|
import path18 from "node:path";
|
|
@@ -11678,7 +11843,7 @@ function commandPath(command) {
|
|
|
11678
11843
|
return null;
|
|
11679
11844
|
}
|
|
11680
11845
|
|
|
11681
|
-
// .dist-releases/
|
|
11846
|
+
// .dist-releases/1784862378006-1249051/src/host/worker-start-spec.js
|
|
11682
11847
|
var MAX_TAGS = 32;
|
|
11683
11848
|
var TAG_PATTERN = /^[a-z0-9][a-z0-9=._:/-]{0,63}$/iu;
|
|
11684
11849
|
var RESERVED_TAG_KEYS = new Set(["os", "kernel", "arch", "gpu", "mode", "role", "tool"]);
|
|
@@ -11738,16 +11903,16 @@ function _trimmed2(value, label) {
|
|
|
11738
11903
|
return trimmed;
|
|
11739
11904
|
}
|
|
11740
11905
|
|
|
11741
|
-
// .dist-releases/
|
|
11906
|
+
// .dist-releases/1784862378006-1249051/src/host/worker-launcher.js
|
|
11742
11907
|
import { statSync as statSync3 } from "node:fs";
|
|
11743
11908
|
import os4 from "node:os";
|
|
11744
11909
|
import path21 from "node:path";
|
|
11745
|
-
// .dist-releases/
|
|
11910
|
+
// .dist-releases/1784862378006-1249051/src/worker/client.js
|
|
11746
11911
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
11747
11912
|
import os3 from "node:os";
|
|
11748
11913
|
import path20 from "node:path";
|
|
11749
11914
|
|
|
11750
|
-
// .dist-releases/
|
|
11915
|
+
// .dist-releases/1784862378006-1249051/src/worker/errors.js
|
|
11751
11916
|
class LeaseFencingRejected extends Error {
|
|
11752
11917
|
status;
|
|
11753
11918
|
constructor(status, message) {
|
|
@@ -11811,7 +11976,7 @@ function countsTowardWorkerSessionRebuild(path19) {
|
|
|
11811
11976
|
return true;
|
|
11812
11977
|
}
|
|
11813
11978
|
|
|
11814
|
-
// .dist-releases/
|
|
11979
|
+
// .dist-releases/1784862378006-1249051/src/worker/executor.js
|
|
11815
11980
|
import { spawn as spawn5 } from "node:child_process";
|
|
11816
11981
|
import { mkdirSync as mkdirSync4, mkdtempSync as mkdtempSync2, readFileSync as readFileSync4, realpathSync, rmSync as rmSync2, statfsSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
11817
11982
|
import { tmpdir as tmpdir2, loadavg } from "node:os";
|
|
@@ -11819,7 +11984,7 @@ import os2 from "node:os";
|
|
|
11819
11984
|
import path19 from "node:path";
|
|
11820
11985
|
import { TextDecoder } from "node:util";
|
|
11821
11986
|
|
|
11822
|
-
// .dist-releases/
|
|
11987
|
+
// .dist-releases/1784862378006-1249051/src/worker/async-queue.js
|
|
11823
11988
|
class AsyncByteQueue {
|
|
11824
11989
|
maxSize;
|
|
11825
11990
|
values = [];
|
|
@@ -11879,7 +12044,7 @@ class AsyncByteQueue {
|
|
|
11879
12044
|
}
|
|
11880
12045
|
}
|
|
11881
12046
|
|
|
11882
|
-
// .dist-releases/
|
|
12047
|
+
// .dist-releases/1784862378006-1249051/src/worker/http.js
|
|
11883
12048
|
import { request as httpRequest } from "node:http";
|
|
11884
12049
|
import { request as httpsRequest } from "node:https";
|
|
11885
12050
|
import { URLSearchParams as URLSearchParams2 } from "node:url";
|
|
@@ -12073,7 +12238,7 @@ function pathOnly(path19) {
|
|
|
12073
12238
|
return path19.split("?", 1)[0] || path19;
|
|
12074
12239
|
}
|
|
12075
12240
|
|
|
12076
|
-
// .dist-releases/
|
|
12241
|
+
// .dist-releases/1784862378006-1249051/src/worker/stream-upload.js
|
|
12077
12242
|
async function uploadStream(session, jobId, stream, leaseToken, chunks, workerId) {
|
|
12078
12243
|
if (!leaseToken.trim())
|
|
12079
12244
|
throw new Error("lease_token is required");
|
|
@@ -12083,7 +12248,7 @@ async function uploadStream(session, jobId, stream, leaseToken, chunks, workerId
|
|
|
12083
12248
|
await session.http.postBytes(`/api/v1/jobs/${encodeURIComponent(jobId)}/stream-upload?${query.toString()}`, chunks, { "X-Lease-Token": leaseToken }, UPLOAD_TIMEOUTS);
|
|
12084
12249
|
}
|
|
12085
12250
|
|
|
12086
|
-
// .dist-releases/
|
|
12251
|
+
// .dist-releases/1784862378006-1249051/src/worker/executor.js
|
|
12087
12252
|
class StreamingProcessFailure extends Error {
|
|
12088
12253
|
exitCode;
|
|
12089
12254
|
stdout;
|
|
@@ -12615,7 +12780,7 @@ function errorMessage6(error) {
|
|
|
12615
12780
|
return error instanceof Error ? error.message : String(error);
|
|
12616
12781
|
}
|
|
12617
12782
|
|
|
12618
|
-
// .dist-releases/
|
|
12783
|
+
// .dist-releases/1784862378006-1249051/src/worker/client.js
|
|
12619
12784
|
var TOKEN_FILES = [
|
|
12620
12785
|
"~/.config/sailorbridge/token",
|
|
12621
12786
|
"/etc/sailorbridge/token"
|
|
@@ -13012,7 +13177,7 @@ function errorName2(error) {
|
|
|
13012
13177
|
function errorMessage7(error) {
|
|
13013
13178
|
return error instanceof Error ? error.message : String(error);
|
|
13014
13179
|
}
|
|
13015
|
-
// .dist-releases/
|
|
13180
|
+
// .dist-releases/1784862378006-1249051/src/host/worker-launcher.js
|
|
13016
13181
|
var DEFAULT_WORKER_READY_TIMEOUT_MS = 60000;
|
|
13017
13182
|
async function launchSupervisedWorker(input, deps = {}) {
|
|
13018
13183
|
const logger = input.logger ?? (() => {});
|
|
@@ -13109,7 +13274,7 @@ function _assertWorkdir(workdir) {
|
|
|
13109
13274
|
return workdir;
|
|
13110
13275
|
}
|
|
13111
13276
|
|
|
13112
|
-
// .dist-releases/
|
|
13277
|
+
// .dist-releases/1784862378006-1249051/src/host/daemon.js
|
|
13113
13278
|
async function runHostDaemon(options) {
|
|
13114
13279
|
const logger = options.logger ?? (() => {});
|
|
13115
13280
|
const sleep3 = options.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
@@ -13458,7 +13623,7 @@ async function _drainOnce(options, identity, starter, logger, redactSecrets) {
|
|
|
13458
13623
|
return false;
|
|
13459
13624
|
}
|
|
13460
13625
|
}
|
|
13461
|
-
// .dist-releases/
|
|
13626
|
+
// .dist-releases/1784862378006-1249051/src/host/enrollment-redeem.js
|
|
13462
13627
|
var DEFAULT_NOT_FOUND_RETRIES = 3;
|
|
13463
13628
|
var NOT_FOUND_RETRY_DELAY_MS = 500;
|
|
13464
13629
|
function createEnrollmentRedeemer(options) {
|
|
@@ -13595,7 +13760,7 @@ function _role2(enrollment) {
|
|
|
13595
13760
|
}
|
|
13596
13761
|
return _string4(enrollment.roles[0], "roles[0]").trim();
|
|
13597
13762
|
}
|
|
13598
|
-
// .dist-releases/
|
|
13763
|
+
// .dist-releases/1784862378006-1249051/src/host/tutorial.js
|
|
13599
13764
|
function buildTutorialSteps(state) {
|
|
13600
13765
|
const paired = state.hasCredential;
|
|
13601
13766
|
return [
|
|
@@ -13666,7 +13831,7 @@ async function runTutorial(options) {
|
|
|
13666
13831
|
}
|
|
13667
13832
|
return steps;
|
|
13668
13833
|
}
|
|
13669
|
-
// .dist-releases/
|
|
13834
|
+
// .dist-releases/1784862378006-1249051/src/events.js
|
|
13670
13835
|
var EVENT_COMMANDS = new Set(["add", "list", "enable", "disable", "rm"]);
|
|
13671
13836
|
var EVENT_FLAGS = new Set(["at", "days", "message", "run-date", "session", "tag", "tz"]);
|
|
13672
13837
|
var PRODUCT_DAYS_MODES = new Set(["once", "daily", "weekday"]);
|
|
@@ -13756,7 +13921,7 @@ function _assertListArgs(args) {
|
|
|
13756
13921
|
}
|
|
13757
13922
|
}
|
|
13758
13923
|
|
|
13759
|
-
// .dist-releases/
|
|
13924
|
+
// .dist-releases/1784862378006-1249051/src/text-input.js
|
|
13760
13925
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
13761
13926
|
var _readUtf8File = async (file) => await readFile8(file, "utf8");
|
|
13762
13927
|
async function readTextInput(input) {
|
|
@@ -13800,7 +13965,7 @@ async function readTextFileOrStdin(path22, input, unusedInputMessage, readUtf8Fi
|
|
|
13800
13965
|
return await readTextFile(path22, readUtf8File2);
|
|
13801
13966
|
}
|
|
13802
13967
|
|
|
13803
|
-
// .dist-releases/
|
|
13968
|
+
// .dist-releases/1784862378006-1249051/src/ask.js
|
|
13804
13969
|
var ASK_FLAGS = new Set(["body-file", "option", "reason", "recommend", "session", "title"]);
|
|
13805
13970
|
async function runAskFromCli(client2, argv, config, input) {
|
|
13806
13971
|
const args = _parseAskArgs(argv);
|
|
@@ -13915,7 +14080,7 @@ function _singleAskValue(values, name) {
|
|
|
13915
14080
|
return entries[0];
|
|
13916
14081
|
}
|
|
13917
14082
|
|
|
13918
|
-
// .dist-releases/
|
|
14083
|
+
// .dist-releases/1784862378006-1249051/src/task.js
|
|
13919
14084
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
13920
14085
|
import { basename } from "node:path";
|
|
13921
14086
|
var TASK_FLAGS = new Set(["after", "all", "artifact-id", "before", "body-file", "commit", "depends", "description", "description-file", "draft", "findings", "image", "level", "limit", "owner-of-resume", "pair", "priority", "query", "reason", "resume-condition", "resume-dependency", "session", "status", "type", "version"]);
|
|
@@ -14405,7 +14570,7 @@ function _taskListFooter(shown, returned, total, hasMore, cursor) {
|
|
|
14405
14570
|
return `Shown ${shown} of ${total}${local}${next}`;
|
|
14406
14571
|
}
|
|
14407
14572
|
|
|
14408
|
-
// .dist-releases/
|
|
14573
|
+
// .dist-releases/1784862378006-1249051/src/team.js
|
|
14409
14574
|
var TEAM_BOOTSTRAP_ENGINES = new Set(["claude", "codex"]);
|
|
14410
14575
|
var SLOT_SPEC_RE = /^([^=\s]+)=([^:@\s]+):([^:@\s]+)$/;
|
|
14411
14576
|
var TEAM_PLAIN_LIMIT = 20;
|
|
@@ -14560,7 +14725,7 @@ function _slotTable(slots) {
|
|
|
14560
14725
|
Shown ${shown.length} of ${slots.length}${omitted ? `; ${omitted} omitted (use --format json)` : ""}`;
|
|
14561
14726
|
}
|
|
14562
14727
|
|
|
14563
|
-
// .dist-releases/
|
|
14728
|
+
// .dist-releases/1784862378006-1249051/src/memory.js
|
|
14564
14729
|
var VALUE_FLAGS = new Set(["file", "source"]);
|
|
14565
14730
|
var MEMORY_SEARCH_PLAIN_LIMIT = 20;
|
|
14566
14731
|
async function runMemoryFromCli(client2, argv, config, input, format) {
|
|
@@ -14695,7 +14860,7 @@ function _summary(value) {
|
|
|
14695
14860
|
return value.replace(/\s+/gu, " ").trim().slice(0, 180);
|
|
14696
14861
|
}
|
|
14697
14862
|
|
|
14698
|
-
// .dist-releases/
|
|
14863
|
+
// .dist-releases/1784862378006-1249051/src/mailbox-send.js
|
|
14699
14864
|
var SEND_FLAGS = new Set(["body-file", "commit", "session", "tag", "task-id", "task-version", "to-agents", "to-roles", "to-host"]);
|
|
14700
14865
|
function parseMailboxSendArgs(argv) {
|
|
14701
14866
|
const parsed = argsFromValues(parseFlagValues(argv));
|
|
@@ -14794,7 +14959,7 @@ function splitList(value) {
|
|
|
14794
14959
|
return list?.length ? list : undefined;
|
|
14795
14960
|
}
|
|
14796
14961
|
|
|
14797
|
-
// .dist-releases/
|
|
14962
|
+
// .dist-releases/1784862378006-1249051/src/reply.js
|
|
14798
14963
|
var REPLY_FLAGS = new Set(["agent", "body-file", "in-reply-to", "session"]);
|
|
14799
14964
|
async function sendReplyFromCli(client2, argv, config, io) {
|
|
14800
14965
|
const args = _parseReplyArgs(argv);
|
|
@@ -14851,11 +15016,192 @@ function _requiredReplyValue(values, name) {
|
|
|
14851
15016
|
return value;
|
|
14852
15017
|
}
|
|
14853
15018
|
|
|
14854
|
-
// .dist-releases/
|
|
15019
|
+
// .dist-releases/1784862378006-1249051/src/worker-command.js
|
|
15020
|
+
async function runWorkerCommandFromCli(client2, argv, config, io, format = "plain") {
|
|
15021
|
+
const captainId = config.captainId;
|
|
15022
|
+
if (!captainId)
|
|
15023
|
+
throw new Error("SAILORBRIDGE_CAPTAIN_ID is required for worker commands");
|
|
15024
|
+
const command = argv[0];
|
|
15025
|
+
switch (command) {
|
|
15026
|
+
case "list":
|
|
15027
|
+
return _listWorkers(client2, captainId, _requireSession(config.session), argv.slice(1), io, format);
|
|
15028
|
+
case "run":
|
|
15029
|
+
return _runWorker(client2, captainId, _requireSession(config.session), argv.slice(1), io, format);
|
|
15030
|
+
case "job":
|
|
15031
|
+
return _showJob(client2, captainId, argv.slice(1), io, format);
|
|
15032
|
+
default:
|
|
15033
|
+
throw new Error("worker command must be job, list, run, or serve");
|
|
15034
|
+
}
|
|
15035
|
+
}
|
|
15036
|
+
function _requireSession(session) {
|
|
15037
|
+
if (!session)
|
|
15038
|
+
throw new Error("SAILORBRIDGE_SESSION is required for worker list and run");
|
|
15039
|
+
return session;
|
|
15040
|
+
}
|
|
15041
|
+
async function _listWorkers(client2, captainId, session, argv, io, format) {
|
|
15042
|
+
if (argv.length > 0)
|
|
15043
|
+
throw new Error(`unexpected argument: ${argv[0]}`);
|
|
15044
|
+
const response = await client2.listWorkers(captainId, session);
|
|
15045
|
+
if (format === "json") {
|
|
15046
|
+
writeOutput(io.stdout, response, format);
|
|
15047
|
+
return;
|
|
15048
|
+
}
|
|
15049
|
+
const { workers } = response;
|
|
15050
|
+
if (workers.length === 0) {
|
|
15051
|
+
io.stdout.write(`No workers registered.
|
|
15052
|
+
`);
|
|
15053
|
+
return;
|
|
15054
|
+
}
|
|
15055
|
+
for (const worker of workers.slice(0, 20)) {
|
|
15056
|
+
io.stdout.write(`${worker.name} ${worker.online ? "online" : "offline"} ${worker.host}
|
|
15057
|
+
`);
|
|
15058
|
+
}
|
|
15059
|
+
const omitted = workers.length - 20;
|
|
15060
|
+
if (omitted > 0)
|
|
15061
|
+
io.stdout.write(`${omitted} omitted; run sail worker list --format json for all.
|
|
15062
|
+
`);
|
|
15063
|
+
}
|
|
15064
|
+
async function _runWorker(client2, captainId, session, argv, io, format) {
|
|
15065
|
+
const input = _parseRunArgs(argv);
|
|
15066
|
+
const workers = (await client2.listWorkers(captainId, session)).workers;
|
|
15067
|
+
const worker = _requireRunnableWorker(workers, input.worker);
|
|
15068
|
+
const submitted = await _submitWorkerJob(client2, captainId, input);
|
|
15069
|
+
if (!input.detach || format === "plain" || !submitted.warning) {
|
|
15070
|
+
_writeWarning(submitted.warning, worker, io);
|
|
15071
|
+
}
|
|
15072
|
+
if (input.detach) {
|
|
15073
|
+
if (format === "json")
|
|
15074
|
+
writeOutput(io.stdout, submitted, format);
|
|
15075
|
+
else
|
|
15076
|
+
io.stdout.write(`${submitted.id}
|
|
15077
|
+
`);
|
|
15078
|
+
return;
|
|
15079
|
+
}
|
|
15080
|
+
const remoteBudget = input.timeoutSec ?? DEFAULT_JOB_TIMEOUT_SECONDS;
|
|
15081
|
+
const result = await client2.getJobResult(captainId, submitted.id, remoteBudget + WORKER_JOB_RESULT_GRACE_SECONDS);
|
|
15082
|
+
_writeResult(result, io, format);
|
|
15083
|
+
}
|
|
15084
|
+
function _requireRunnableWorker(workers, name) {
|
|
15085
|
+
const worker = workers.find((item) => item.name === name);
|
|
15086
|
+
if (!worker)
|
|
15087
|
+
throw new Error(`worker '${name}' is not registered in this team`);
|
|
15088
|
+
if (worker.capabilities.includes("mode=readonly")) {
|
|
15089
|
+
throw new Error(`worker '${name}' does not support bash jobs in readonly mode`);
|
|
15090
|
+
}
|
|
15091
|
+
return worker;
|
|
15092
|
+
}
|
|
15093
|
+
function _submitWorkerJob(client2, captainId, input) {
|
|
15094
|
+
return client2.submitJob(captainId, {
|
|
15095
|
+
worker: input.worker,
|
|
15096
|
+
argv: input.argv,
|
|
15097
|
+
...input.timeoutSec === undefined ? {} : { timeoutSec: input.timeoutSec }
|
|
15098
|
+
});
|
|
15099
|
+
}
|
|
15100
|
+
async function _showJob(client2, captainId, argv, io, format) {
|
|
15101
|
+
if (argv.length !== 1 || !argv[0])
|
|
15102
|
+
throw new Error("worker job requires exactly one job id");
|
|
15103
|
+
const result = await client2.getJobStatus(captainId, argv[0]);
|
|
15104
|
+
if (format === "json") {
|
|
15105
|
+
writeOutput(io.stdout, result, format);
|
|
15106
|
+
if (result.exit_code !== null)
|
|
15107
|
+
io.setExitCode(_localExitStatus(result.exit_code));
|
|
15108
|
+
return;
|
|
15109
|
+
}
|
|
15110
|
+
if (result.status === "queued" || result.status === "running") {
|
|
15111
|
+
io.stdout.write(`${result.id} ${result.status}
|
|
15112
|
+
`);
|
|
15113
|
+
return;
|
|
15114
|
+
}
|
|
15115
|
+
_writeResult(result, io, format);
|
|
15116
|
+
}
|
|
15117
|
+
function _parseRunArgs(argv) {
|
|
15118
|
+
const separator = argv.indexOf("--");
|
|
15119
|
+
if (separator < 0)
|
|
15120
|
+
throw new Error("worker run requires '--' before argv");
|
|
15121
|
+
const remoteArgv = argv.slice(separator + 1);
|
|
15122
|
+
if (remoteArgv.length === 0 || !remoteArgv[0]?.trim())
|
|
15123
|
+
throw new Error("worker run requires a command after '--'");
|
|
15124
|
+
const { worker, timeoutSec, detach } = _parseRunFlags(argv.slice(0, separator));
|
|
15125
|
+
if (!worker)
|
|
15126
|
+
throw new Error("--worker is required");
|
|
15127
|
+
return { worker, argv: remoteArgv, detach, ...timeoutSec === undefined ? {} : { timeoutSec } };
|
|
15128
|
+
}
|
|
15129
|
+
function _parseRunFlags(flags) {
|
|
15130
|
+
let worker = "";
|
|
15131
|
+
let timeoutSec;
|
|
15132
|
+
let detach = false;
|
|
15133
|
+
for (let index = 0;index < flags.length; index += 1) {
|
|
15134
|
+
const flag = flags[index];
|
|
15135
|
+
if (flag === "--detach") {
|
|
15136
|
+
detach = true;
|
|
15137
|
+
continue;
|
|
15138
|
+
}
|
|
15139
|
+
const value = flags[index + 1];
|
|
15140
|
+
if (!value)
|
|
15141
|
+
throw new Error(`${flag} requires a value`);
|
|
15142
|
+
if (flag === "--worker")
|
|
15143
|
+
worker = value.trim();
|
|
15144
|
+
else if (flag === "--timeout")
|
|
15145
|
+
timeoutSec = _parseTimeout(value);
|
|
15146
|
+
else
|
|
15147
|
+
throw new Error(`unexpected argument: ${flag}`);
|
|
15148
|
+
index += 1;
|
|
15149
|
+
}
|
|
15150
|
+
return { worker, detach, ...timeoutSec === undefined ? {} : { timeoutSec } };
|
|
15151
|
+
}
|
|
15152
|
+
function _parseTimeout(value) {
|
|
15153
|
+
if (!/^(?:0|[1-9]\d*)(?:\.\d+)?$/u.test(value)) {
|
|
15154
|
+
throw new Error(`timeout must be a number from 1 to ${MAX_JOB_TIMEOUT_SECONDS} seconds`);
|
|
15155
|
+
}
|
|
15156
|
+
const timeout = Number(value);
|
|
15157
|
+
if (!Number.isFinite(timeout) || timeout < 1 || timeout > MAX_JOB_TIMEOUT_SECONDS) {
|
|
15158
|
+
throw new Error(`timeout must be a number from 1 to ${MAX_JOB_TIMEOUT_SECONDS} seconds`);
|
|
15159
|
+
}
|
|
15160
|
+
return timeout;
|
|
15161
|
+
}
|
|
15162
|
+
function _writeWarning(warning, worker, io) {
|
|
15163
|
+
if (warning) {
|
|
15164
|
+
io.stderr.write(`Warning: ${warning}
|
|
15165
|
+
`);
|
|
15166
|
+
return;
|
|
15167
|
+
}
|
|
15168
|
+
if (!worker.online)
|
|
15169
|
+
io.stderr.write(`Warning: worker '${worker.name}' is registered but offline.
|
|
15170
|
+
`);
|
|
15171
|
+
}
|
|
15172
|
+
function _writeResult(response, io, format) {
|
|
15173
|
+
if (!response.result || response.exit_code === null) {
|
|
15174
|
+
throw new Error(`job ${response.id} did not finish before the timeout (status=${response.status})`);
|
|
15175
|
+
}
|
|
15176
|
+
const localStatus = _localExitStatus(response.exit_code);
|
|
15177
|
+
if (format === "json") {
|
|
15178
|
+
writeOutput(io.stdout, response, format);
|
|
15179
|
+
io.setExitCode(localStatus);
|
|
15180
|
+
return;
|
|
15181
|
+
}
|
|
15182
|
+
io.stdout.write(response.result.stdout);
|
|
15183
|
+
io.stderr.write(response.result.stderr);
|
|
15184
|
+
if (response.exit_code < 0)
|
|
15185
|
+
_writeSignalStatus(response.exit_code, localStatus, response.result.stderr, io);
|
|
15186
|
+
io.setExitCode(localStatus);
|
|
15187
|
+
}
|
|
15188
|
+
function _localExitStatus(remoteCode) {
|
|
15189
|
+
return remoteCode < 0 ? 128 + Math.abs(remoteCode) : remoteCode;
|
|
15190
|
+
}
|
|
15191
|
+
function _writeSignalStatus(remoteCode, localStatus, remoteStderr, io) {
|
|
15192
|
+
if (remoteStderr && !remoteStderr.endsWith(`
|
|
15193
|
+
`))
|
|
15194
|
+
io.stderr.write(`
|
|
15195
|
+
`);
|
|
15196
|
+
io.stderr.write(`Remote exit code ${remoteCode}; local exit status ${localStatus}.
|
|
15197
|
+
`);
|
|
15198
|
+
}
|
|
15199
|
+
|
|
15200
|
+
// .dist-releases/1784862378006-1249051/src/create.js
|
|
14855
15201
|
var CREATE_ENGINES = new Set(["claude", "codex"]);
|
|
14856
15202
|
var DEFAULT_ENGINE = "claude";
|
|
14857
15203
|
var WORKSPACE_PLAIN_LIMIT = 20;
|
|
14858
|
-
var CREATE_SUBCOMMANDS = new Set(["team", "pair", "worker"]);
|
|
15204
|
+
var CREATE_SUBCOMMANDS = new Set(["team", "pair", "planner", "tester", "worker"]);
|
|
14859
15205
|
async function runCreateFromCli(argv, io, deps = {}) {
|
|
14860
15206
|
const sub = argv[0];
|
|
14861
15207
|
if (!sub || sub.startsWith("--"))
|
|
@@ -14867,6 +15213,8 @@ async function runCreateFromCli(argv, io, deps = {}) {
|
|
|
14867
15213
|
return await _createTeam(flags, io, deps);
|
|
14868
15214
|
if (sub === "pair")
|
|
14869
15215
|
return await _createPair(flags, io, deps);
|
|
15216
|
+
if (sub === "planner" || sub === "tester")
|
|
15217
|
+
return await _createMember(sub, flags, io, deps);
|
|
14870
15218
|
return await _createWorker(flags, io, deps);
|
|
14871
15219
|
}
|
|
14872
15220
|
async function _createTeam(flags, io, deps) {
|
|
@@ -14875,7 +15223,7 @@ async function _createTeam(flags, io, deps) {
|
|
|
14875
15223
|
const displayName = _required4(flags.name, "--name");
|
|
14876
15224
|
const template = _required4(flags.template, "--template");
|
|
14877
15225
|
const engine = _engine3(flags.engine);
|
|
14878
|
-
const ctx = await _teamConsoleContext(flags, deps);
|
|
15226
|
+
const ctx = await _teamConsoleContext("team", flags, deps);
|
|
14879
15227
|
const host = await _resolveOnlineHost(ctx.relay, ctx.captainId, flags.host);
|
|
14880
15228
|
const workspace = await _resolveHostWorkspace(ctx.relay, ctx.captainId, host.host_id, flags.workspace);
|
|
14881
15229
|
const { team, slots } = await _createAndApplyTeam(deps, ctx, displayName, template);
|
|
@@ -14918,6 +15266,19 @@ async function _postConsoleJson(deps, ctx, path22, body) {
|
|
|
14918
15266
|
throw new Error("SailorBridge API returned a malformed object");
|
|
14919
15267
|
return parsed;
|
|
14920
15268
|
}
|
|
15269
|
+
async function _getConsoleJson(deps, ctx, path22) {
|
|
15270
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
15271
|
+
const response = await fetchImpl(`${ctx.apiUrl.replace(/\/$/, "")}${path22}`, {
|
|
15272
|
+
headers: { Authorization: `Bearer ${ctx.token}` }
|
|
15273
|
+
});
|
|
15274
|
+
const text = await response.text();
|
|
15275
|
+
if (!response.ok)
|
|
15276
|
+
throw new Error(`SailorBridge API ${response.status}: ${text}`);
|
|
15277
|
+
const parsed = JSON.parse(text);
|
|
15278
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
15279
|
+
throw new Error("SailorBridge API returned a malformed object");
|
|
15280
|
+
return parsed;
|
|
15281
|
+
}
|
|
14921
15282
|
function _responseString(body, field) {
|
|
14922
15283
|
const value = body[field];
|
|
14923
15284
|
if (typeof value !== "string" || !value)
|
|
@@ -14959,6 +15320,77 @@ async function _createPair(flags, io, deps) {
|
|
|
14959
15320
|
});
|
|
14960
15321
|
writeOutput(io.stdout, result, io.format, () => _pairPlain(host.host_id, workspace, engine, result));
|
|
14961
15322
|
}
|
|
15323
|
+
async function _createMember(role, flags, io, deps) {
|
|
15324
|
+
_rejectMemberFlags(role, flags);
|
|
15325
|
+
const engine = _engine3(flags.engine);
|
|
15326
|
+
const session = _requiredSession(flags.session, _envSession(deps));
|
|
15327
|
+
const ctx = await _teamConsoleContext(role, flags, deps);
|
|
15328
|
+
const host = await _resolveOnlineHost(ctx.relay, ctx.captainId, flags.host);
|
|
15329
|
+
const workspace = await _resolveHostWorkspace(ctx.relay, ctx.captainId, host.host_id, flags.workspace);
|
|
15330
|
+
const slot = await _memberSlotForCreate(deps, ctx, session, role);
|
|
15331
|
+
const request = await _startMember(deps, ctx, session, host.host_id, workspace.path, engine, role, slot);
|
|
15332
|
+
const result = { role, host: host.host_id, workspace: workspace.path, engine, slot, request };
|
|
15333
|
+
writeOutput(io.stdout, result, io.format, () => _memberPlain(result));
|
|
15334
|
+
}
|
|
15335
|
+
function _rejectMemberFlags(role, flags) {
|
|
15336
|
+
const unsupported = [
|
|
15337
|
+
["--name", flags.name],
|
|
15338
|
+
["--template", flags.template],
|
|
15339
|
+
["--concurrency", flags.concurrency]
|
|
15340
|
+
];
|
|
15341
|
+
const found = unsupported.find(([, value]) => value !== undefined);
|
|
15342
|
+
if (found)
|
|
15343
|
+
throw new Error(`create ${role} does not accept ${found[0]}`);
|
|
15344
|
+
}
|
|
15345
|
+
async function _memberSlotForCreate(deps, ctx, session, role) {
|
|
15346
|
+
const path22 = `/api/console/teams/${encodeURIComponent(session)}/agent-slots`;
|
|
15347
|
+
const slots = _responseMemberSlots(await _getConsoleJson(deps, ctx, path22));
|
|
15348
|
+
const retryable = slots.find((slot) => _isRetryableMemberSlot(slot, role));
|
|
15349
|
+
if (retryable)
|
|
15350
|
+
return retryable;
|
|
15351
|
+
if (role === "planner" && slots.some((slot) => slot.role === role)) {
|
|
15352
|
+
throw new Error("duplicate-singleton-role: team already has a planner slot");
|
|
15353
|
+
}
|
|
15354
|
+
const created = _responseMemberSlot(await _postConsoleJson(deps, ctx, path22, { role }));
|
|
15355
|
+
if (created.role !== role)
|
|
15356
|
+
throw new Error("SailorBridge API returned a member slot with the wrong role");
|
|
15357
|
+
return created;
|
|
15358
|
+
}
|
|
15359
|
+
function _isRetryableMemberSlot(slot, role) {
|
|
15360
|
+
return slot.role === role && slot.status === "planned" && slot.template_origin === "single-add";
|
|
15361
|
+
}
|
|
15362
|
+
async function _startMember(deps, ctx, session, hostId, workspaceRoot, engine, role, slot) {
|
|
15363
|
+
const response = await _postConsoleJson(deps, ctx, `/api/console/teams/${encodeURIComponent(session)}/agent-start-requests`, { host_id: hostId, slot_id: slot.slot_id, spec: { engine, role, workspace: { mode: "worktree", root: workspaceRoot } } });
|
|
15364
|
+
const request = _responseStartRequest(response);
|
|
15365
|
+
if (request.host_id !== hostId || request.agent_name !== slot.agent_name) {
|
|
15366
|
+
throw new Error("SailorBridge API returned a start request with mismatched identity");
|
|
15367
|
+
}
|
|
15368
|
+
return request;
|
|
15369
|
+
}
|
|
15370
|
+
function _responseMemberSlots(body) {
|
|
15371
|
+
if (!Array.isArray(body.agent_slots))
|
|
15372
|
+
throw new Error("SailorBridge API response is missing agent_slots");
|
|
15373
|
+
return body.agent_slots.map(_responseMemberSlotValue);
|
|
15374
|
+
}
|
|
15375
|
+
function _responseMemberSlot(body) {
|
|
15376
|
+
if (!body.agent_slot || typeof body.agent_slot !== "object" || Array.isArray(body.agent_slot)) {
|
|
15377
|
+
throw new Error("SailorBridge API response is missing agent_slot");
|
|
15378
|
+
}
|
|
15379
|
+
return _responseMemberSlotValue(body.agent_slot);
|
|
15380
|
+
}
|
|
15381
|
+
function _responseMemberSlotValue(raw) {
|
|
15382
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
15383
|
+
throw new Error("SailorBridge API returned a malformed agent slot");
|
|
15384
|
+
}
|
|
15385
|
+
const slot = raw;
|
|
15386
|
+
return {
|
|
15387
|
+
slot_id: _responseString(slot, "slot_id"),
|
|
15388
|
+
agent_name: _responseString(slot, "agent_name"),
|
|
15389
|
+
role: _responseString(slot, "role"),
|
|
15390
|
+
status: _responseString(slot, "status"),
|
|
15391
|
+
template_origin: _responseString(slot, "template_origin")
|
|
15392
|
+
};
|
|
15393
|
+
}
|
|
14962
15394
|
async function _createWorker(flags, io, deps) {
|
|
14963
15395
|
const workerName = _required4(flags.name, "--name");
|
|
14964
15396
|
const maxConcurrency = _concurrency(flags.concurrency);
|
|
@@ -14995,11 +15427,11 @@ async function _consoleContext(flags, deps) {
|
|
|
14995
15427
|
token: credential.token
|
|
14996
15428
|
};
|
|
14997
15429
|
}
|
|
14998
|
-
async function _teamConsoleContext(flags, deps) {
|
|
15430
|
+
async function _teamConsoleContext(command, flags, deps) {
|
|
14999
15431
|
const env = deps.env ?? process.env;
|
|
15000
15432
|
const accessToken = env.SAILORBRIDGE_CAPTAIN_ACCESS_TOKEN?.trim();
|
|
15001
15433
|
if (!accessToken) {
|
|
15002
|
-
throw new Error(
|
|
15434
|
+
throw new Error(`create ${command} requires SAILORBRIDGE_CAPTAIN_ACCESS_TOKEN for captain-authorized console operations`);
|
|
15003
15435
|
}
|
|
15004
15436
|
return { ...await _consoleContext(flags, deps), token: accessToken };
|
|
15005
15437
|
}
|
|
@@ -15132,6 +15564,18 @@ function _pairPlain(hostId, workspace, engine, result) {
|
|
|
15132
15564
|
].join(`
|
|
15133
15565
|
`);
|
|
15134
15566
|
}
|
|
15567
|
+
function _memberPlain(result) {
|
|
15568
|
+
return [
|
|
15569
|
+
`${result.role}: ${result.slot.agent_name}`,
|
|
15570
|
+
`slot: ${result.slot.slot_id}`,
|
|
15571
|
+
`host: ${result.host}`,
|
|
15572
|
+
`workspace: ${result.workspace}`,
|
|
15573
|
+
`engine: ${result.engine}`,
|
|
15574
|
+
`request: ${result.request.id}`,
|
|
15575
|
+
`status: ${result.request.status}`
|
|
15576
|
+
].join(`
|
|
15577
|
+
`);
|
|
15578
|
+
}
|
|
15135
15579
|
function _workerPlain(hostId, workdir, result) {
|
|
15136
15580
|
return [
|
|
15137
15581
|
`worker: ${result.worker.name}`,
|
|
@@ -15143,7 +15587,7 @@ function _workerPlain(hostId, workdir, result) {
|
|
|
15143
15587
|
`);
|
|
15144
15588
|
}
|
|
15145
15589
|
|
|
15146
|
-
// .dist-releases/
|
|
15590
|
+
// .dist-releases/1784862378006-1249051/src/cli.js
|
|
15147
15591
|
var FORMATTED_COMMANDS = new Set([
|
|
15148
15592
|
"ask",
|
|
15149
15593
|
"create",
|
|
@@ -15156,7 +15600,8 @@ var FORMATTED_COMMANDS = new Set([
|
|
|
15156
15600
|
"reply",
|
|
15157
15601
|
"task",
|
|
15158
15602
|
"team",
|
|
15159
|
-
"tutorial"
|
|
15603
|
+
"tutorial",
|
|
15604
|
+
"worker"
|
|
15160
15605
|
]);
|
|
15161
15606
|
var SERVICE_INSTALL_COMMAND = "sailorbridge host service install";
|
|
15162
15607
|
var SERVICE_UNINSTALL_COMMAND = "sailorbridge host service uninstall";
|
|
@@ -15183,6 +15628,9 @@ async function main(argv) {
|
|
|
15183
15628
|
if (command === "host" && argv[1] === "run" && output2.provided) {
|
|
15184
15629
|
throw new Error("host run does not produce a finite result; remove --format");
|
|
15185
15630
|
}
|
|
15631
|
+
if (command === "worker" && argv[1] === "serve" && output2.provided) {
|
|
15632
|
+
throw new Error("worker serve does not produce a finite result; remove --format");
|
|
15633
|
+
}
|
|
15186
15634
|
await _rejectUnsupportedCliInput(command, argv.slice(1), process.stdin);
|
|
15187
15635
|
if (command === "login") {
|
|
15188
15636
|
await _hostLogin(argv.slice(1), output2.format);
|
|
@@ -15219,7 +15667,7 @@ async function main(argv) {
|
|
|
15219
15667
|
await runHostWorkspaceCommandFromCli(argv.slice(2), { stdout: process.stdout, format: output2.format });
|
|
15220
15668
|
return;
|
|
15221
15669
|
}
|
|
15222
|
-
if (command === "worker") {
|
|
15670
|
+
if (command === "worker" && argv[1] === "serve") {
|
|
15223
15671
|
await runWorkerFromCli(argv.slice(2));
|
|
15224
15672
|
return;
|
|
15225
15673
|
}
|
|
@@ -15266,6 +15714,16 @@ async function main(argv) {
|
|
|
15266
15714
|
writeOutput(process.stdout, await runMemoryFromCli(client2, argv.slice(1), config, process.stdin, output2.format), output2.format);
|
|
15267
15715
|
return;
|
|
15268
15716
|
}
|
|
15717
|
+
if (command === "worker") {
|
|
15718
|
+
await runWorkerCommandFromCli(client2, argv.slice(1), config, {
|
|
15719
|
+
stdout: process.stdout,
|
|
15720
|
+
stderr: process.stderr,
|
|
15721
|
+
setExitCode: (code) => {
|
|
15722
|
+
process.exitCode = code;
|
|
15723
|
+
}
|
|
15724
|
+
}, output2.format);
|
|
15725
|
+
return;
|
|
15726
|
+
}
|
|
15269
15727
|
if (command === "enrollment") {
|
|
15270
15728
|
await _enrollment(client2, argv.slice(1), config.captainId, output2.format);
|
|
15271
15729
|
return;
|
|
@@ -15322,7 +15780,7 @@ var SUBCOMMANDS = {
|
|
|
15322
15780
|
"unpark"
|
|
15323
15781
|
]),
|
|
15324
15782
|
team: new Set(["bootstrap"]),
|
|
15325
|
-
worker: new Set(["serve"])
|
|
15783
|
+
worker: new Set(["job", "list", "run", "serve"])
|
|
15326
15784
|
};
|
|
15327
15785
|
function _assertKnownCommand(command, subcommand) {
|
|
15328
15786
|
if (!KNOWN_COMMANDS.has(command))
|
|
@@ -15807,6 +16265,10 @@ function _usageText() {
|
|
|
15807
16265
|
creates an auto-numbered team and starts every template slot on one paired online host.
|
|
15808
16266
|
sailorbridge create pair [--host H] [--workspace PATH|GIT_URL] [--engine claude|codex] [--name N] [--session S]
|
|
15809
16267
|
builds a writer+reviewer dev pair on a paired online host; workspace defaults to the host's reported one.
|
|
16268
|
+
sailorbridge create planner [--host H] [--workspace PATH] [--engine claude|codex] [--session S]
|
|
16269
|
+
adds the team's single planner through the console slot + start flow.
|
|
16270
|
+
sailorbridge create tester [--host H] [--workspace PATH] [--engine claude|codex] [--session S]
|
|
16271
|
+
adds one tester through the console slot + start flow.
|
|
15810
16272
|
sailorbridge create worker --name N --concurrency N [--host H] [--workspace PATH] [--session S]
|
|
15811
16273
|
starts a worker on a paired online host. All create commands: [--api-url URL] [--credentials-path PATH] [--format plain|json]
|
|
15812
16274
|
sailorbridge team bootstrap --template classic3 --slot SLOT=HOST:claude|codex [--slot ...] [--session S]
|
|
@@ -15822,13 +16284,19 @@ function _usageText() {
|
|
|
15822
16284
|
sailorbridge host service install|uninstall|status [--binary PATH] [--credentials-path PATH] [--workspace-root DIR] [--service-dir DIR] [--service-name NAME]
|
|
15823
16285
|
sailorbridge host start-request [--credentials-path PATH] [--api-url URL] [--access-token TOKEN] --team T [--host-id H] --agent A --engine codex --roles operator --workspace-mode fresh|git [--git-url URL]
|
|
15824
16286
|
sailorbridge host run [--credentials-path PATH] [--api-url URL] [--host-id H] [--display-name N] [--workspace-root DIR]
|
|
16287
|
+
sailorbridge worker list [--format plain|json]
|
|
16288
|
+
sailorbridge worker run [--detach] --worker NAME [--timeout SEC] [--format plain|json] -- ARGV...
|
|
16289
|
+
sailorbridge worker job ID [--format plain|json]
|
|
16290
|
+
list/run/job require SAILORBRIDGE_CAPTAIN_ID; list/run also require SAILORBRIDGE_SESSION.
|
|
15825
16291
|
sailorbridge worker serve [--relay-url URL] [--worker NAME] [--workdir DIR] [--max-concurrency N]
|
|
15826
16292
|
sailorbridge supervise --agent A --cli claude|codex --cwd DIR --i-own-this-agent [--transport tmux] [--tmux-session S] [-- COMMAND...]
|
|
15827
16293
|
|
|
15828
16294
|
Environment:
|
|
15829
16295
|
SAILORBRIDGE_RELAY_URL / SAILORBRIDGE_TOKEN
|
|
15830
16296
|
SAILORBRIDGE_API_URL overrides the default product API for login/tutorial (${DEFAULT_PRODUCT_API_URL}); --api-url wins
|
|
15831
|
-
SAILORBRIDGE_AGENT_NAME
|
|
16297
|
+
SAILORBRIDGE_AGENT_NAME
|
|
16298
|
+
SAILORBRIDGE_CAPTAIN_ID is required for worker list/run/job.
|
|
16299
|
+
SAILORBRIDGE_SESSION is also required for worker list/run.
|
|
15832
16300
|
SAILORBRIDGE_HOST_ID / SAILORBRIDGE_HOST_DISPLAY_NAME
|
|
15833
16301
|
SAILORBRIDGE_NO_SERVICE=1 makes login skip the host service install
|
|
15834
16302
|
SAILORBRIDGE_DEBUG=1 prints the internal pairing id during login (diagnostics only)
|
|
@@ -15869,5 +16337,5 @@ function _looksLikeNetworkFailure(message) {
|
|
|
15869
16337
|
return /fetch failed|network|ECONN(?:REFUSED|RESET)|ENOTFOUND|ETIMEDOUT/iu.test(message);
|
|
15870
16338
|
}
|
|
15871
16339
|
|
|
15872
|
-
//# debugId=
|
|
16340
|
+
//# debugId=3B810968682A4A6F64756E2164756E21
|
|
15873
16341
|
//# sourceMappingURL=cli.js.map
|