@sailorbridge/client 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli.js +394 -797
- package/dist/src/cli.js.map +14 -16
- 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/1784809313131-4113078/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/1784809313131-4113078/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,37 +220,82 @@ 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/1784809313131-4113078/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";
|
|
227
227
|
import path2 from "node:path";
|
|
228
228
|
import { spawn } from "node:child_process";
|
|
229
229
|
var COMMAND_TIMEOUT_MS = 120000;
|
|
230
|
+
var REPO_BACKOFF_INITIAL_MS = 60000;
|
|
231
|
+
var REPO_BACKOFF_MAX_MS = 60 * 60000;
|
|
230
232
|
var SHA_RE = /^[0-9a-f]{40}(?:[0-9a-f]{24})?$/;
|
|
231
233
|
function defaultRepoMirrorRoot() {
|
|
232
234
|
return path2.join(homedir2(), ".sailorbridge", "repo-mirrors");
|
|
233
235
|
}
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
+
function createRepoTipReporter(deps = {}) {
|
|
237
|
+
const backoffs = new Map;
|
|
238
|
+
return async (options) => _reportRepoTipsOnce(options, deps, backoffs);
|
|
239
|
+
}
|
|
240
|
+
async function _reportRepoTipsOnce(options, deps, backoffs) {
|
|
236
241
|
const wanted = await options.relay.getTaskRepoTipWanted(options.captainId);
|
|
237
242
|
const mirrorRoot = options.mirrorRoot ?? defaultRepoMirrorRoot();
|
|
238
243
|
let reported = 0;
|
|
239
244
|
for (const entry of wanted.wanted) {
|
|
240
|
-
|
|
241
|
-
const report = await observeRepoTips(entry, mirrorRoot, deps);
|
|
242
|
-
await options.relay.putTaskRepoTips(options.captainId, entry.session, report);
|
|
245
|
+
if (await _reportRepoTip(entry, mirrorRoot, options, deps, backoffs))
|
|
243
246
|
reported += 1;
|
|
244
|
-
} catch (error) {
|
|
245
|
-
logger("host_repo_tip_report_failed", {
|
|
246
|
-
session: entry.session,
|
|
247
|
-
repo: entry.repo_path,
|
|
248
|
-
error: error instanceof Error ? error.message : String(error)
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
247
|
}
|
|
248
|
+
_forgetUnwantedBackoffs(backoffs, wanted.wanted);
|
|
252
249
|
return { observed: wanted.wanted.length, reported };
|
|
253
250
|
}
|
|
251
|
+
async function _reportRepoTip(entry, mirrorRoot, options, deps, backoffs) {
|
|
252
|
+
const backoff = backoffs.get(entry.repo_path);
|
|
253
|
+
if (backoff && _now(deps) < backoff.retryAt)
|
|
254
|
+
return false;
|
|
255
|
+
try {
|
|
256
|
+
const report = await observeRepoTips(entry, mirrorRoot, deps);
|
|
257
|
+
await options.relay.putTaskRepoTips(options.captainId, entry.session, report);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
_backOffRepo(entry, error, options.logger, deps, backoffs);
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
if (backoff)
|
|
263
|
+
_recoverRepo(entry, backoff, options.logger, backoffs);
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
function _backOffRepo(entry, error, logger, deps, backoffs) {
|
|
267
|
+
const previous = backoffs.get(entry.repo_path);
|
|
268
|
+
const retryMs = previous ? Math.min(previous.retryMs * 2, REPO_BACKOFF_MAX_MS) : REPO_BACKOFF_INITIAL_MS;
|
|
269
|
+
const failures = (previous?.failures ?? 0) + 1;
|
|
270
|
+
backoffs.set(entry.repo_path, { failures, retryAt: _now(deps) + retryMs, retryMs });
|
|
271
|
+
if (previous)
|
|
272
|
+
return;
|
|
273
|
+
logger?.("host_repo_tip_backoff_started", {
|
|
274
|
+
session: entry.session,
|
|
275
|
+
repo: entry.repo_path,
|
|
276
|
+
error: error instanceof Error ? error.message : String(error),
|
|
277
|
+
failures,
|
|
278
|
+
retry_ms: retryMs
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
function _recoverRepo(entry, backoff, logger, backoffs) {
|
|
282
|
+
backoffs.delete(entry.repo_path);
|
|
283
|
+
logger?.("host_repo_tip_backoff_recovered", {
|
|
284
|
+
session: entry.session,
|
|
285
|
+
repo: entry.repo_path,
|
|
286
|
+
failures: backoff.failures
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
function _forgetUnwantedBackoffs(backoffs, wanted) {
|
|
290
|
+
const activeRepos = new Set(wanted.map((entry) => entry.repo_path));
|
|
291
|
+
for (const repo of backoffs.keys()) {
|
|
292
|
+
if (!activeRepos.has(repo))
|
|
293
|
+
backoffs.delete(repo);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function _now(deps) {
|
|
297
|
+
return deps.now?.() ?? Date.now();
|
|
298
|
+
}
|
|
254
299
|
async function observeRepoTips(entry, mirrorRoot, deps) {
|
|
255
300
|
const exec = deps.execCommand ?? execArgv;
|
|
256
301
|
const mirror = mirrorPathFor(mirrorRoot, entry.repo_path);
|
|
@@ -357,10 +402,10 @@ ${error.message}`));
|
|
|
357
402
|
proc.on("close", (code) => finish(code ?? 1));
|
|
358
403
|
});
|
|
359
404
|
}
|
|
360
|
-
// .dist-releases/
|
|
405
|
+
// .dist-releases/1784809313131-4113078/src/host/request-consumer.js
|
|
361
406
|
import { hostname as hostname2 } from "node:os";
|
|
362
407
|
|
|
363
|
-
// .dist-releases/
|
|
408
|
+
// .dist-releases/1784809313131-4113078/src/driver/secrets.js
|
|
364
409
|
function redactSensitiveText(text, env = {}, explicitSecrets = []) {
|
|
365
410
|
let redacted = text;
|
|
366
411
|
for (const [key, value] of Object.entries(env)) {
|
|
@@ -379,16 +424,16 @@ function isSensitiveEnvKey(key) {
|
|
|
379
424
|
return /(TOKEN|KEY|SECRET|AUTHORIZATION|PASSWORD)/i.test(key);
|
|
380
425
|
}
|
|
381
426
|
|
|
382
|
-
// .dist-releases/
|
|
383
|
-
var CLIENT_VERSION = "0.
|
|
384
|
-
var CLIENT_GIT_SHA = "
|
|
385
|
-
var CLIENT_BUILD_DIRTY =
|
|
427
|
+
// .dist-releases/1784809313131-4113078/src/version.js
|
|
428
|
+
var CLIENT_VERSION = "0.2.0";
|
|
429
|
+
var CLIENT_GIT_SHA = "d1e5ed371492-dirty";
|
|
430
|
+
var CLIENT_BUILD_DIRTY = true;
|
|
386
431
|
var CLIENT_VERSION_LABEL = formatClientVersion(CLIENT_VERSION, CLIENT_GIT_SHA);
|
|
387
432
|
function formatClientVersion(version, gitSha) {
|
|
388
433
|
return `${version}+git.${gitSha}`;
|
|
389
434
|
}
|
|
390
435
|
|
|
391
|
-
// .dist-releases/
|
|
436
|
+
// .dist-releases/1784809313131-4113078/src/host/request-consumer.js
|
|
392
437
|
var MAX_ERROR_LENGTH = 500;
|
|
393
438
|
function defaultHostIdentity(config) {
|
|
394
439
|
const captainId = config.captainId?.trim();
|
|
@@ -443,7 +488,7 @@ function limitErrorMessage(error, explicitSecrets) {
|
|
|
443
488
|
const trimmed = redactSensitiveText(message, process.env, explicitSecrets).trim() || "host request starter failed";
|
|
444
489
|
return trimmed.length <= MAX_ERROR_LENGTH ? trimmed : `${trimmed.slice(0, MAX_ERROR_LENGTH - 3)}...`;
|
|
445
490
|
}
|
|
446
|
-
// .dist-releases/
|
|
491
|
+
// .dist-releases/1784809313131-4113078/src/product/start-request.js
|
|
447
492
|
async function createAgentStartRequest(options) {
|
|
448
493
|
const apiUrl = _required(options.apiUrl, "product API URL").replace(/\/+$/u, "");
|
|
449
494
|
const accessToken = _required(options.accessToken, "product API bearer token");
|
|
@@ -503,7 +548,7 @@ function _string(value, label) {
|
|
|
503
548
|
throw new Error(`${label} must be a non-empty string`);
|
|
504
549
|
return value;
|
|
505
550
|
}
|
|
506
|
-
// .dist-releases/
|
|
551
|
+
// .dist-releases/1784809313131-4113078/src/product/pair.js
|
|
507
552
|
async function createPair(options) {
|
|
508
553
|
const apiUrl = _required2(options.apiUrl, "product API URL").replace(/\/+$/u, "");
|
|
509
554
|
const accessToken = _required2(options.accessToken, "product API bearer token");
|
|
@@ -580,7 +625,7 @@ function _string2(value, label) {
|
|
|
580
625
|
throw new Error(`${label} must be a non-empty string`);
|
|
581
626
|
return value;
|
|
582
627
|
}
|
|
583
|
-
// .dist-releases/
|
|
628
|
+
// .dist-releases/1784809313131-4113078/src/product/worker.js
|
|
584
629
|
async function createWorker(options) {
|
|
585
630
|
const apiUrl = _required3(options.apiUrl, "product API URL").replace(/\/+$/u, "");
|
|
586
631
|
const accessToken = _required3(options.accessToken, "product API bearer token");
|
|
@@ -644,7 +689,7 @@ function _string3(value, label) {
|
|
|
644
689
|
throw new Error(`${label} must be a non-empty string`);
|
|
645
690
|
return value;
|
|
646
691
|
}
|
|
647
|
-
// .dist-releases/
|
|
692
|
+
// .dist-releases/1784809313131-4113078/src/driver/events.js
|
|
648
693
|
class DriverEventEmitter {
|
|
649
694
|
callbacks = new Map;
|
|
650
695
|
on(type, callback) {
|
|
@@ -659,7 +704,7 @@ class DriverEventEmitter {
|
|
|
659
704
|
}
|
|
660
705
|
}
|
|
661
706
|
}
|
|
662
|
-
// .dist-releases/
|
|
707
|
+
// .dist-releases/1784809313131-4113078/src/driver/async-queue.js
|
|
663
708
|
class AsyncQueue {
|
|
664
709
|
values = [];
|
|
665
710
|
waiters = [];
|
|
@@ -698,7 +743,7 @@ class AsyncQueue {
|
|
|
698
743
|
}
|
|
699
744
|
}
|
|
700
745
|
|
|
701
|
-
// .dist-releases/
|
|
746
|
+
// .dist-releases/1784809313131-4113078/src/driver/types.js
|
|
702
747
|
class DriverUnsupportedError extends Error {
|
|
703
748
|
constructor(message) {
|
|
704
749
|
super(message);
|
|
@@ -713,7 +758,7 @@ class DriverTargetNotReadyError extends Error {
|
|
|
713
758
|
}
|
|
714
759
|
}
|
|
715
760
|
|
|
716
|
-
// .dist-releases/
|
|
761
|
+
// .dist-releases/1784809313131-4113078/src/driver/sdk-loader.js
|
|
717
762
|
async function loadSdk(loader, packageName, env = {}, installHint = `Install the optional SDK dependency ${packageName} and its peers for this transport.`) {
|
|
718
763
|
try {
|
|
719
764
|
return await loader();
|
|
@@ -723,7 +768,7 @@ async function loadSdk(loader, packageName, env = {}, installHint = `Install the
|
|
|
723
768
|
}
|
|
724
769
|
}
|
|
725
770
|
|
|
726
|
-
// .dist-releases/
|
|
771
|
+
// .dist-releases/1784809313131-4113078/src/driver/claude/driver.js
|
|
727
772
|
class ClaudeAgentSdkDriver {
|
|
728
773
|
options;
|
|
729
774
|
capabilities = { structured: true, resume: true, attach: false };
|
|
@@ -899,7 +944,7 @@ function asRecord(value) {
|
|
|
899
944
|
function stringValue(value) {
|
|
900
945
|
return typeof value === "string" ? value : undefined;
|
|
901
946
|
}
|
|
902
|
-
// .dist-releases/
|
|
947
|
+
// .dist-releases/1784809313131-4113078/src/driver/codex/driver.js
|
|
903
948
|
class CodexSdkDriver {
|
|
904
949
|
options;
|
|
905
950
|
capabilities = { structured: true, resume: true, attach: false };
|
|
@@ -1080,7 +1125,7 @@ function asRecord2(value) {
|
|
|
1080
1125
|
function stringValue2(value) {
|
|
1081
1126
|
return typeof value === "string" ? value : undefined;
|
|
1082
1127
|
}
|
|
1083
|
-
// .dist-releases/
|
|
1128
|
+
// .dist-releases/1784809313131-4113078/src/driver/liveness-heuristics.js
|
|
1084
1129
|
var BUSY_MARKERS = ["Working (", "Waiting for background", "Pasted Content", "tab to queue"];
|
|
1085
1130
|
var ANSI_PATTERN = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\)|[PX^_][\s\S]*?\x1B\\)/g;
|
|
1086
1131
|
function stripAnsi(text) {
|
|
@@ -1107,7 +1152,7 @@ function classifyInteractiveOutput(input) {
|
|
|
1107
1152
|
function isOutputStable(now, lastOutputAt, idleStableMs) {
|
|
1108
1153
|
return Boolean(lastOutputAt && now.getTime() - lastOutputAt.getTime() >= idleStableMs);
|
|
1109
1154
|
}
|
|
1110
|
-
// .dist-releases/
|
|
1155
|
+
// .dist-releases/1784809313131-4113078/src/driver/pty/loader.js
|
|
1111
1156
|
async function loadNodePty(loader = defaultNodePtyLoader) {
|
|
1112
1157
|
try {
|
|
1113
1158
|
return await loader();
|
|
@@ -1133,7 +1178,7 @@ async function defaultNodePtyLoader() {
|
|
|
1133
1178
|
return loaded;
|
|
1134
1179
|
}
|
|
1135
1180
|
|
|
1136
|
-
// .dist-releases/
|
|
1181
|
+
// .dist-releases/1784809313131-4113078/src/driver/pty/driver.js
|
|
1137
1182
|
class PtyDriver {
|
|
1138
1183
|
options;
|
|
1139
1184
|
capabilities = { structured: false, resume: false, attach: false };
|
|
@@ -1285,12 +1330,12 @@ function tail(text, lines) {
|
|
|
1285
1330
|
function sleep(ms) {
|
|
1286
1331
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1287
1332
|
}
|
|
1288
|
-
// .dist-releases/
|
|
1333
|
+
// .dist-releases/1784809313131-4113078/src/driver/tmux/driver.js
|
|
1289
1334
|
import { mkdtemp, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
1290
1335
|
import { tmpdir } from "node:os";
|
|
1291
1336
|
import { join } from "node:path";
|
|
1292
1337
|
|
|
1293
|
-
// .dist-releases/
|
|
1338
|
+
// .dist-releases/1784809313131-4113078/src/driver/tmux/launch.js
|
|
1294
1339
|
var ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
1295
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 "$@"';
|
|
1296
1341
|
function buildTmuxNewSessionArgs(input) {
|
|
@@ -1313,7 +1358,7 @@ function validateEnv(env) {
|
|
|
1313
1358
|
}
|
|
1314
1359
|
}
|
|
1315
1360
|
|
|
1316
|
-
// .dist-releases/
|
|
1361
|
+
// .dist-releases/1784809313131-4113078/src/driver/tmux/paste.js
|
|
1317
1362
|
function buildDispatchPlan(text, useTyping) {
|
|
1318
1363
|
return {
|
|
1319
1364
|
mode: useTyping ? "type-literal" : "paste-buffer",
|
|
@@ -1337,7 +1382,7 @@ function arraysEqual(left, right) {
|
|
|
1337
1382
|
return left.length === right.length && left.every((item, index) => item === right[index]);
|
|
1338
1383
|
}
|
|
1339
1384
|
|
|
1340
|
-
// .dist-releases/
|
|
1385
|
+
// .dist-releases/1784809313131-4113078/src/driver/tmux/liveness.js
|
|
1341
1386
|
var SHELL_COMMANDS = new Set(["", "bash", "zsh", "sh", "fish", "pwsh", "powershell"]);
|
|
1342
1387
|
function classifyTmuxLiveness(input) {
|
|
1343
1388
|
if (!input.hasSession) {
|
|
@@ -1357,7 +1402,7 @@ function isTmuxProcessAlive(command, runningCommands) {
|
|
|
1357
1402
|
return !SHELL_COMMANDS.has(command);
|
|
1358
1403
|
}
|
|
1359
1404
|
|
|
1360
|
-
// .dist-releases/
|
|
1405
|
+
// .dist-releases/1784809313131-4113078/src/driver/tmux/runner.js
|
|
1361
1406
|
import { spawn as spawn2 } from "node:child_process";
|
|
1362
1407
|
var DEFAULT_TIMEOUT_MS = 15000;
|
|
1363
1408
|
|
|
@@ -1482,7 +1527,7 @@ class TmuxClient {
|
|
|
1482
1527
|
}
|
|
1483
1528
|
}
|
|
1484
1529
|
|
|
1485
|
-
// .dist-releases/
|
|
1530
|
+
// .dist-releases/1784809313131-4113078/src/driver/tmux/driver.js
|
|
1486
1531
|
var ATTACHED_STOP_GRACE_MS = 1e4;
|
|
1487
1532
|
var DEFAULT_STOP_TIMEOUT_MS = 15000;
|
|
1488
1533
|
var DEFAULT_READY_TIMEOUT_MS = 90000;
|
|
@@ -1877,12 +1922,12 @@ function isMissingTmuxSessionError(error) {
|
|
|
1877
1922
|
${error.result.stderr}`.toLowerCase();
|
|
1878
1923
|
return text.includes("can't find session") || text.includes("cannot find session") || text.includes("no such session") || text.includes("session not found");
|
|
1879
1924
|
}
|
|
1880
|
-
// .dist-releases/
|
|
1925
|
+
// .dist-releases/1784809313131-4113078/src/relay/client.js
|
|
1881
1926
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
1882
1927
|
import http from "node:http";
|
|
1883
1928
|
import https from "node:https";
|
|
1884
1929
|
|
|
1885
|
-
// .dist-releases/
|
|
1930
|
+
// .dist-releases/1784809313131-4113078/src/relay/errors.js
|
|
1886
1931
|
class RelayError extends Error {
|
|
1887
1932
|
method;
|
|
1888
1933
|
path;
|
|
@@ -1919,7 +1964,7 @@ class RelayProtocolError extends RelayError {
|
|
|
1919
1964
|
}
|
|
1920
1965
|
}
|
|
1921
1966
|
|
|
1922
|
-
// .dist-releases/
|
|
1967
|
+
// .dist-releases/1784809313131-4113078/src/relay/client.js
|
|
1923
1968
|
var JSON_CONTENT_TYPE = "application/json";
|
|
1924
1969
|
var MAX_MAILBOX_LIMIT = 16;
|
|
1925
1970
|
var MAX_WAIT_TIMEOUT_SEC = 120;
|
|
@@ -2206,29 +2251,6 @@ class RelayClient {
|
|
|
2206
2251
|
const response = await this.requestJson("POST", path3, body);
|
|
2207
2252
|
return _parseTeamAgentSlot(response.agent_slot, "POST", path3);
|
|
2208
2253
|
}
|
|
2209
|
-
async getTeamRepository(captainId, session) {
|
|
2210
|
-
const path3 = `/api/v1/captains/${segment(captainId)}/sessions`;
|
|
2211
|
-
const response = await this.requestJson("GET", path3);
|
|
2212
|
-
if (!Array.isArray(response.sessions))
|
|
2213
|
-
throw new RelayProtocolError("GET", path3, "sessions must be an array");
|
|
2214
|
-
const rows = response.sessions.map((row) => _parseTeamRepository(row, "GET", path3));
|
|
2215
|
-
const repository = rows.find((row) => row.team_id === session);
|
|
2216
|
-
if (!repository)
|
|
2217
|
-
throw new RelayProtocolError("GET", path3, `team ${session} is missing`);
|
|
2218
|
-
return repository;
|
|
2219
|
-
}
|
|
2220
|
-
async setTeamRepositoryState(captainId, session, body) {
|
|
2221
|
-
const path3 = `${_captainSessionPath(captainId, session)}/repo-verification-state`;
|
|
2222
|
-
const response = await this.requestJson("PATCH", path3, body);
|
|
2223
|
-
return _parseTeamRepository(response.session, "PATCH", path3);
|
|
2224
|
-
}
|
|
2225
|
-
async createRepoVerificationRequest(captainId, session, hostId, gitRepoUrl) {
|
|
2226
|
-
const path3 = `${_captainSessionPath(captainId, session)}/repo-verification-requests`;
|
|
2227
|
-
const response = await this.requestJson("POST", path3, { host_id: hostId, git_repo_url: gitRepoUrl });
|
|
2228
|
-
const request = parseAgentStartRequest(response.request, "POST", path3);
|
|
2229
|
-
_requireRepoVerificationRequest(request, "POST", path3, session, hostId);
|
|
2230
|
-
return request;
|
|
2231
|
-
}
|
|
2232
2254
|
async getAgentStartRequest(captainId, session, requestId, timeoutMs) {
|
|
2233
2255
|
const path3 = `${_captainSessionPath(captainId, session)}/agent-start-requests/${segment(requestId)}`;
|
|
2234
2256
|
const response = await this.requestJson("GET", path3, undefined, timeoutMs);
|
|
@@ -2403,6 +2425,12 @@ class RelayClient {
|
|
|
2403
2425
|
const path3 = `/api/v1/rag/captains/${segment(captainId)}/teams/${segment(teamId)}/index`;
|
|
2404
2426
|
return parseRagMemoryIndex(await this.requestJson("GET", path3), "GET", path3);
|
|
2405
2427
|
}
|
|
2428
|
+
async getRagEntitlement(captainId, teamId) {
|
|
2429
|
+
requireCaptainId(captainId);
|
|
2430
|
+
requireSegment(teamId, "teamId");
|
|
2431
|
+
const path3 = `/api/v1/rag/captains/${segment(captainId)}/teams/${segment(teamId)}/entitlement`;
|
|
2432
|
+
return parseRagEntitlement(await this.requestJson("GET", path3), "GET", path3);
|
|
2433
|
+
}
|
|
2406
2434
|
async setRagCardPin(captainId, teamId, key, pinned) {
|
|
2407
2435
|
requireCaptainId(captainId);
|
|
2408
2436
|
requireSegment(teamId, "teamId");
|
|
@@ -2966,34 +2994,6 @@ function _parseTeamAgentSlot(value, method, path3) {
|
|
|
2966
2994
|
template_id: slot.template_id ?? null
|
|
2967
2995
|
};
|
|
2968
2996
|
}
|
|
2969
|
-
function _parseTeamRepository(value, method, path3) {
|
|
2970
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
2971
|
-
throw new RelayProtocolError(method, path3, "session must be an object");
|
|
2972
|
-
const session = value;
|
|
2973
|
-
if (typeof session.id !== "string" || !session.id)
|
|
2974
|
-
throw new RelayProtocolError(method, path3, "session.id must be a non-empty string");
|
|
2975
|
-
if (session.git_repo_url !== null && typeof session.git_repo_url !== "string")
|
|
2976
|
-
throw new RelayProtocolError(method, path3, "session.git_repo_url must be a string or null");
|
|
2977
|
-
if (!_isTeamRepositoryStatus(session.git_repo_verification_status))
|
|
2978
|
-
throw new RelayProtocolError(method, path3, "session.git_repo_verification_status is invalid");
|
|
2979
|
-
if (session.git_repo_verification_reason !== null && typeof session.git_repo_verification_reason !== "string")
|
|
2980
|
-
throw new RelayProtocolError(method, path3, "session.git_repo_verification_reason must be a string or null");
|
|
2981
|
-
return {
|
|
2982
|
-
team_id: session.id,
|
|
2983
|
-
git_repo_url: session.git_repo_url,
|
|
2984
|
-
git_repo_verification_status: session.git_repo_verification_status,
|
|
2985
|
-
git_repo_verification_reason: session.git_repo_verification_reason
|
|
2986
|
-
};
|
|
2987
|
-
}
|
|
2988
|
-
function _isTeamRepositoryStatus(value) {
|
|
2989
|
-
return value === "unverified" || value === "pending" || value === "verified" || value === "failed";
|
|
2990
|
-
}
|
|
2991
|
-
function _requireRepoVerificationRequest(request, method, path3, session, hostId) {
|
|
2992
|
-
if (request.request_kind !== "repo_verification")
|
|
2993
|
-
throw new RelayProtocolError(method, path3, "request_kind must be repo_verification");
|
|
2994
|
-
if (request.session !== session || request.host_id !== hostId)
|
|
2995
|
-
throw new RelayProtocolError(method, path3, "request identity does not match repository verification target");
|
|
2996
|
-
}
|
|
2997
2997
|
function _parseSessionArtifact(value, method, path3) {
|
|
2998
2998
|
for (const field of ["id", "name", "sha256", "content_url"]) {
|
|
2999
2999
|
if (typeof value[field] !== "string" || !value[field])
|
|
@@ -3357,7 +3357,7 @@ function parseAgentStartRequest(value, method, path3) {
|
|
|
3357
3357
|
}
|
|
3358
3358
|
if (request.request_kind === undefined)
|
|
3359
3359
|
request.request_kind = "agent_start";
|
|
3360
|
-
if (request.request_kind !== "agent_start" && request.request_kind !== "
|
|
3360
|
+
if (request.request_kind !== "agent_start" && request.request_kind !== "worker_start") {
|
|
3361
3361
|
throw new RelayProtocolError(method, path3, "request.request_kind is invalid");
|
|
3362
3362
|
}
|
|
3363
3363
|
if (request.result !== undefined && (!request.result || typeof request.result !== "object" || Array.isArray(request.result))) {
|
|
@@ -3520,6 +3520,11 @@ function parseRagMemoryIndex(value, method, path3) {
|
|
|
3520
3520
|
}));
|
|
3521
3521
|
return { enabled: value.enabled, degraded: value.degraded, text: value.text, budget_tokens: value.budget_tokens, total_cards: value.total_cards, omitted_cards: value.omitted_cards, sections };
|
|
3522
3522
|
}
|
|
3523
|
+
function parseRagEntitlement(value, method, path3) {
|
|
3524
|
+
if (typeof value.enabled !== "boolean")
|
|
3525
|
+
throw new RelayProtocolError(method, path3, "entitlement.enabled must be a boolean");
|
|
3526
|
+
return { enabled: value.enabled };
|
|
3527
|
+
}
|
|
3523
3528
|
function parseManagedMaterializationResponse(value, method, path3, cursor) {
|
|
3524
3529
|
if (value === "not_modified_304") {
|
|
3525
3530
|
if (!cursor?.trim())
|
|
@@ -3849,12 +3854,12 @@ function redact(value, token) {
|
|
|
3849
3854
|
function bytesToBase64(bytes) {
|
|
3850
3855
|
return Buffer2.from(bytes).toString("base64");
|
|
3851
3856
|
}
|
|
3852
|
-
// .dist-releases/
|
|
3857
|
+
// .dist-releases/1784809313131-4113078/src/relay/config.js
|
|
3853
3858
|
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
3854
3859
|
import { homedir as homedir3 } from "node:os";
|
|
3855
3860
|
import path3 from "node:path";
|
|
3856
3861
|
|
|
3857
|
-
// .dist-releases/
|
|
3862
|
+
// .dist-releases/1784809313131-4113078/src/worker/protocol.js
|
|
3858
3863
|
var DEFAULT_RELAY_URL = DEFAULT_PRODUCT_API_URL;
|
|
3859
3864
|
var DEFAULT_WORKER = "host";
|
|
3860
3865
|
var DEFAULT_WORKDIR = "~/sailorbridge-workdir";
|
|
@@ -3883,7 +3888,7 @@ function effectiveJobKind(kind, spec) {
|
|
|
3883
3888
|
return kind === "stream" || spec.stream === true ? "stream" : kind;
|
|
3884
3889
|
}
|
|
3885
3890
|
|
|
3886
|
-
// .dist-releases/
|
|
3891
|
+
// .dist-releases/1784809313131-4113078/src/relay/config.js
|
|
3887
3892
|
function loadRelayConfig(env = process.env) {
|
|
3888
3893
|
const envRelayUrl = nonEmpty(env.SAILORBRIDGE_RELAY_URL);
|
|
3889
3894
|
const envBearerToken = nonEmpty(env.SAILORBRIDGE_TOKEN);
|
|
@@ -3955,7 +3960,7 @@ function storedCaptainId(value) {
|
|
|
3955
3960
|
}
|
|
3956
3961
|
return;
|
|
3957
3962
|
}
|
|
3958
|
-
// .dist-releases/
|
|
3963
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/retirement.js
|
|
3959
3964
|
var DEFAULT_THRESHOLD = 3;
|
|
3960
3965
|
var DEFAULT_WINDOW_MS = 30000;
|
|
3961
3966
|
var DEFAULT_COOLDOWN_MS = 1000;
|
|
@@ -4030,7 +4035,7 @@ function isAuthoritativeRetirementReason(reason) {
|
|
|
4030
4035
|
return reason === "monitor_fetch" || reason === "agent_session_patch";
|
|
4031
4036
|
}
|
|
4032
4037
|
|
|
4033
|
-
// .dist-releases/
|
|
4038
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/wait.js
|
|
4034
4039
|
async function waitForWakeableTimeout(ms, setWake, sleep3) {
|
|
4035
4040
|
if (sleep3) {
|
|
4036
4041
|
await Promise.race([
|
|
@@ -4061,7 +4066,7 @@ async function waitForWakeableTimeout(ms, setWake, sleep3) {
|
|
|
4061
4066
|
setWake(null);
|
|
4062
4067
|
}
|
|
4063
4068
|
|
|
4064
|
-
// .dist-releases/
|
|
4069
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/mailbox.js
|
|
4065
4070
|
var CLEAR_TAG = "CLEAR";
|
|
4066
4071
|
var REFRESH_TAG = "WORKFLOW-REFRESH";
|
|
4067
4072
|
var SYNC_TAG = "SYNC";
|
|
@@ -4597,38 +4602,79 @@ function ordinaryDeliveryAttempt(error) {
|
|
|
4597
4602
|
function _isMissingModerator(error) {
|
|
4598
4603
|
return error instanceof RelayHttpError && error.status === 400 && error.body.includes("no agents match");
|
|
4599
4604
|
}
|
|
4600
|
-
// .dist-releases/
|
|
4605
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/runtime.js
|
|
4601
4606
|
import path9 from "node:path";
|
|
4602
4607
|
import { execFile } from "node:child_process";
|
|
4603
4608
|
import { promisify } from "node:util";
|
|
4604
4609
|
|
|
4605
|
-
// .dist-releases/
|
|
4610
|
+
// .dist-releases/1784809313131-4113078/src/host/managed-materialization.js
|
|
4606
4611
|
import { createHash as createHash2, randomBytes } from "node:crypto";
|
|
4607
4612
|
import { constants as fsConstants } from "node:fs";
|
|
4608
4613
|
import { lstat, mkdir as mkdir3, open, readdir, rename, rm as rm2 } from "node:fs/promises";
|
|
4609
4614
|
import { homedir as homedir5 } from "node:os";
|
|
4610
4615
|
import path5 from "node:path";
|
|
4611
4616
|
|
|
4612
|
-
// .dist-releases/
|
|
4613
|
-
import { mkdir as mkdir2, writeFile as writeFile3 } from "node:fs/promises";
|
|
4617
|
+
// .dist-releases/1784809313131-4113078/src/host/memory-stub.js
|
|
4618
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile3 } from "node:fs/promises";
|
|
4614
4619
|
import { homedir as homedir4 } from "node:os";
|
|
4615
4620
|
import path4 from "node:path";
|
|
4616
|
-
var
|
|
4617
|
-
var
|
|
4618
|
-
var
|
|
4619
|
-
|
|
4621
|
+
var TEAM_MEMORY_STUB_BEGIN = "<!-- sailorbridge-team-memory-stub:begin -->";
|
|
4622
|
+
var TEAM_MEMORY_STUB_END = "<!-- sailorbridge-team-memory-stub:end -->";
|
|
4623
|
+
var LEGACY_STUB_BEGIN = "<!-- sailorbridge-rag-memory-stub:begin -->";
|
|
4624
|
+
var LEGACY_STUB_END = "<!-- sailorbridge-rag-memory-stub:end -->";
|
|
4625
|
+
var STUB_LOCAL_MEMORY = [
|
|
4626
|
+
"- Your local memory files are yours: the product never collects, rewrites, or deletes them.",
|
|
4627
|
+
" Keep working notes and everything tied to your own role in local memory.",
|
|
4628
|
+
"- Role-bound and personal content must stay local. Never publish it to shared team stores:",
|
|
4629
|
+
" another member recalling your role's private memory is an identity mix-up."
|
|
4630
|
+
];
|
|
4631
|
+
var TEAM_MEMORY_STUB_ENTITLED = [
|
|
4632
|
+
"# SailorBridge Team Memory Protocol",
|
|
4620
4633
|
"",
|
|
4621
|
-
|
|
4622
|
-
"-
|
|
4623
|
-
"
|
|
4624
|
-
"-
|
|
4625
|
-
"
|
|
4626
|
-
"-
|
|
4627
|
-
"
|
|
4634
|
+
...STUB_LOCAL_MEMORY,
|
|
4635
|
+
"- Team memory is the team's shared knowledge and experience. Before a non-trivial",
|
|
4636
|
+
" question, run `sail memory search <query>` — someone may already know.",
|
|
4637
|
+
"- When you learn something the whole team benefits from, save it with",
|
|
4638
|
+
" `sail memory set <key> --stdin --source <source>` (or `--file <path>`).",
|
|
4639
|
+
"- Prefer team memory over rules when saving: rules are behavior norms; knowledge",
|
|
4640
|
+
" and experience belong in team memory.",
|
|
4641
|
+
"- If the memory service is unavailable, fail fast and say so; never present stale",
|
|
4642
|
+
" local content as the team's shared truth.",
|
|
4628
4643
|
""
|
|
4629
4644
|
].join(`
|
|
4630
4645
|
`);
|
|
4631
|
-
var
|
|
4646
|
+
var TEAM_MEMORY_STUB_UNENTITLED = [
|
|
4647
|
+
"# SailorBridge Team Memory Protocol",
|
|
4648
|
+
"",
|
|
4649
|
+
...STUB_LOCAL_MEMORY,
|
|
4650
|
+
"- Share lessons and working norms through team rules: propose a rule to your",
|
|
4651
|
+
" captain or moderator so the whole team inherits it.",
|
|
4652
|
+
"- The Team Memory add-on adds shared cross-member memory with corrections",
|
|
4653
|
+
" (`sail memory` commands); the captain can enable it from the console.",
|
|
4654
|
+
""
|
|
4655
|
+
].join(`
|
|
4656
|
+
`);
|
|
4657
|
+
function teamMemoryStub(entitled) {
|
|
4658
|
+
return entitled ? TEAM_MEMORY_STUB_ENTITLED : TEAM_MEMORY_STUB_UNENTITLED;
|
|
4659
|
+
}
|
|
4660
|
+
function teamMemoryStubMarked(entitled) {
|
|
4661
|
+
return `${TEAM_MEMORY_STUB_BEGIN}
|
|
4662
|
+
${teamMemoryStub(entitled)}${TEAM_MEMORY_STUB_END}
|
|
4663
|
+
`;
|
|
4664
|
+
}
|
|
4665
|
+
async function resolveTeamMemoryEntitlement(relay, captainId, teamId) {
|
|
4666
|
+
const captain = captainId?.trim();
|
|
4667
|
+
const team = teamId?.trim();
|
|
4668
|
+
if (!captain || !team)
|
|
4669
|
+
throw new Error("team memory entitlement requires captain_id and session");
|
|
4670
|
+
try {
|
|
4671
|
+
return (await relay.getRagEntitlement(captain, team)).enabled;
|
|
4672
|
+
} catch (error) {
|
|
4673
|
+
if (error instanceof RelayHttpError && error.status === 402)
|
|
4674
|
+
return false;
|
|
4675
|
+
throw error;
|
|
4676
|
+
}
|
|
4677
|
+
}
|
|
4632
4678
|
async function materializeAgentMemoryStub(options) {
|
|
4633
4679
|
const engine = _memoryStubEngine(options.engine);
|
|
4634
4680
|
const homeDir = options.homeDir ? path4.resolve(_expandHome(options.homeDir)) : agentSandboxHome(options.agentName, engine, options.env ?? process.env);
|
|
@@ -4637,7 +4683,10 @@ async function materializeAgentMemoryStub(options) {
|
|
|
4637
4683
|
const mkdirFn = options.mkdir ?? mkdir2;
|
|
4638
4684
|
const writeFileFn = options.writeFile ?? writeFile3;
|
|
4639
4685
|
await mkdirFn(homeDir, { recursive: true });
|
|
4640
|
-
await
|
|
4686
|
+
const existing = await _readIfPresent(filePath, options.readFile ?? readFile2);
|
|
4687
|
+
const next = _spliceStubBlock(existing, teamMemoryStubMarked(options.teamMemoryEntitled));
|
|
4688
|
+
if (next !== existing)
|
|
4689
|
+
await writeFileFn(filePath, next, { mode: 384 });
|
|
4641
4690
|
return {
|
|
4642
4691
|
engine,
|
|
4643
4692
|
homeDir,
|
|
@@ -4652,6 +4701,38 @@ function agentSandboxHome(agentName, engine, env = process.env) {
|
|
|
4652
4701
|
function memoryStubFileName(engine) {
|
|
4653
4702
|
return engine === "claude" ? "CLAUDE.md" : "AGENTS.md";
|
|
4654
4703
|
}
|
|
4704
|
+
function _spliceStubBlock(existing, block) {
|
|
4705
|
+
if (existing === null || !existing.trim())
|
|
4706
|
+
return block;
|
|
4707
|
+
const current = _replaceMarkedBlock(existing, TEAM_MEMORY_STUB_BEGIN, TEAM_MEMORY_STUB_END, block) ?? _replaceMarkedBlock(existing, LEGACY_STUB_BEGIN, LEGACY_STUB_END, block);
|
|
4708
|
+
if (current !== undefined)
|
|
4709
|
+
return current;
|
|
4710
|
+
const cleaned = _dropStrayMarkers(existing);
|
|
4711
|
+
if (!cleaned.trim())
|
|
4712
|
+
return block;
|
|
4713
|
+
return `${block}
|
|
4714
|
+
${cleaned.replace(/^\n+/u, "")}`;
|
|
4715
|
+
}
|
|
4716
|
+
function _replaceMarkedBlock(content, begin, end, block) {
|
|
4717
|
+
const start = content.indexOf(begin);
|
|
4718
|
+
const stop = content.indexOf(end);
|
|
4719
|
+
if (start < 0 || stop < start)
|
|
4720
|
+
return;
|
|
4721
|
+
const after = content.slice(stop + end.length).replace(/^\n/u, "");
|
|
4722
|
+
return `${content.slice(0, start)}${block}${after}`;
|
|
4723
|
+
}
|
|
4724
|
+
function _dropStrayMarkers(content) {
|
|
4725
|
+
return [TEAM_MEMORY_STUB_BEGIN, TEAM_MEMORY_STUB_END, LEGACY_STUB_BEGIN, LEGACY_STUB_END].reduce((text, marker) => text.split(marker).join(""), content);
|
|
4726
|
+
}
|
|
4727
|
+
async function _readIfPresent(filePath, readFileFn) {
|
|
4728
|
+
try {
|
|
4729
|
+
return await readFileFn(filePath, "utf8");
|
|
4730
|
+
} catch (error) {
|
|
4731
|
+
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
|
|
4732
|
+
return null;
|
|
4733
|
+
throw error;
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4655
4736
|
function _memoryStubEngine(value) {
|
|
4656
4737
|
if (value !== "claude" && value !== "codex") {
|
|
4657
4738
|
throw new Error("memory stub engine must be claude or codex");
|
|
@@ -4679,13 +4760,8 @@ function _safePathLabel(value, field) {
|
|
|
4679
4760
|
}
|
|
4680
4761
|
return trimmed;
|
|
4681
4762
|
}
|
|
4682
|
-
function _markedStub(body) {
|
|
4683
|
-
return `${RAG_MEMORY_STUB_BEGIN}
|
|
4684
|
-
${body}${RAG_MEMORY_STUB_END}
|
|
4685
|
-
`;
|
|
4686
|
-
}
|
|
4687
4763
|
|
|
4688
|
-
// .dist-releases/
|
|
4764
|
+
// .dist-releases/1784809313131-4113078/src/host/managed-materialization.js
|
|
4689
4765
|
var MANIFEST_FILE = ".sailorbridge-managed-manifest.json";
|
|
4690
4766
|
var BANNER_PREFIX = "# SailorBridge managed file";
|
|
4691
4767
|
var HASH_RE = /^sha256:[a-f0-9]{64}$/u;
|
|
@@ -5211,14 +5287,14 @@ function _expandHome2(value) {
|
|
|
5211
5287
|
return value;
|
|
5212
5288
|
}
|
|
5213
5289
|
|
|
5214
|
-
// .dist-releases/
|
|
5215
|
-
import { lstat as lstat2, readFile as
|
|
5290
|
+
// .dist-releases/1784809313131-4113078/src/host/credential-guardian.js
|
|
5291
|
+
import { lstat as lstat2, readFile as readFile3, rename as rename2, symlink, unlink, writeFile as writeFile4 } from "node:fs/promises";
|
|
5216
5292
|
import path6 from "node:path";
|
|
5217
5293
|
var DEFAULT_CREDENTIAL_SWEEP_INTERVAL_MS = 60000;
|
|
5218
5294
|
var DEFAULT_FAILURE_ALERT_THRESHOLD = 3;
|
|
5219
5295
|
var defaultFs = {
|
|
5220
5296
|
lstat: lstat2,
|
|
5221
|
-
readFile: (filePath) =>
|
|
5297
|
+
readFile: (filePath) => readFile3(filePath),
|
|
5222
5298
|
writeFile: (filePath, data, options) => writeFile4(filePath, data, options),
|
|
5223
5299
|
rename: rename2,
|
|
5224
5300
|
symlink: (target, linkPath) => symlink(target, linkPath),
|
|
@@ -5357,7 +5433,7 @@ function _tmpSibling(filePath) {
|
|
|
5357
5433
|
return path6.join(path6.dirname(filePath), `.${path6.basename(filePath)}.sb-guardian.${process.pid}.${tmpSequence}.tmp`);
|
|
5358
5434
|
}
|
|
5359
5435
|
|
|
5360
|
-
// .dist-releases/
|
|
5436
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/resolve.js
|
|
5361
5437
|
var DEFAULT_CAPTURE_LINES = 200;
|
|
5362
5438
|
var MAX_CAPTURE_LINES = 1000;
|
|
5363
5439
|
|
|
@@ -5563,7 +5639,7 @@ function defaultSleep(ms) {
|
|
|
5563
5639
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5564
5640
|
}
|
|
5565
5641
|
|
|
5566
|
-
// .dist-releases/
|
|
5642
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/transcript-backfill.js
|
|
5567
5643
|
import { createHash as createHash3 } from "node:crypto";
|
|
5568
5644
|
import {
|
|
5569
5645
|
closeSync,
|
|
@@ -6220,7 +6296,7 @@ function errorMessage4(error) {
|
|
|
6220
6296
|
return error instanceof Error ? error.message : String(error);
|
|
6221
6297
|
}
|
|
6222
6298
|
|
|
6223
|
-
// .dist-releases/
|
|
6299
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/usage-collector.js
|
|
6224
6300
|
import { statSync as statSync2 } from "node:fs";
|
|
6225
6301
|
import path8 from "node:path";
|
|
6226
6302
|
var SUPPORTED_USAGE_ENGINES = new Set(["claude", "codex"]);
|
|
@@ -6629,7 +6705,7 @@ function sourceUnreadableReason(source) {
|
|
|
6629
6705
|
}
|
|
6630
6706
|
}
|
|
6631
6707
|
|
|
6632
|
-
// .dist-releases/
|
|
6708
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/runtime.js
|
|
6633
6709
|
var RESOLVE_CAPTURE_LINES = 200;
|
|
6634
6710
|
var SHORT_LIVED_EXIT_MS = 5000;
|
|
6635
6711
|
var STARTUP_OBSERVATION_MS = 1e4;
|
|
@@ -7299,7 +7375,7 @@ function errorMessage5(error) {
|
|
|
7299
7375
|
function formatRestartCommand(command) {
|
|
7300
7376
|
return command.map((part) => /^[A-Za-z0-9_./:=@%+-]+$/.test(part) ? part : `'${part.replaceAll("'", "'\\''")}'`).join(" ");
|
|
7301
7377
|
}
|
|
7302
|
-
// .dist-releases/
|
|
7378
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/transport.js
|
|
7303
7379
|
var SUPPORTED_PHASE1_CLI_KINDS = ["claude", "codex"];
|
|
7304
7380
|
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.";
|
|
7305
7381
|
var PHASE1_TRANSPORT_GATE_MESSAGE = "Only tmux transport is available in this release; sdk, headless, and pty transports will open in the next release.";
|
|
@@ -7507,7 +7583,7 @@ function hasCodexSafetyDriverOptions(options) {
|
|
|
7507
7583
|
return options?.codex?.sandboxMode !== undefined || options?.codex?.approvalPolicy !== undefined || options?.codex?.yolo !== undefined;
|
|
7508
7584
|
}
|
|
7509
7585
|
|
|
7510
|
-
// .dist-releases/
|
|
7586
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/cli-options.js
|
|
7511
7587
|
function parseSuperviseArgs(argv) {
|
|
7512
7588
|
const split = argv.indexOf("--");
|
|
7513
7589
|
const flagArgs = split >= 0 ? argv.slice(0, split) : argv;
|
|
@@ -7659,7 +7735,7 @@ function optionalBoolean(value, label) {
|
|
|
7659
7735
|
return false;
|
|
7660
7736
|
throw new Error(`${label} must be true or false`);
|
|
7661
7737
|
}
|
|
7662
|
-
// .dist-releases/
|
|
7738
|
+
// .dist-releases/1784809313131-4113078/src/supervisor/tmux-availability.js
|
|
7663
7739
|
import { spawn as spawn3 } from "node:child_process";
|
|
7664
7740
|
import { createInterface } from "node:readline";
|
|
7665
7741
|
function isTmuxAvailable(spawnFn = spawn3) {
|
|
@@ -7776,7 +7852,7 @@ function _tmuxMissingMessage(platform2) {
|
|
|
7776
7852
|
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";
|
|
7777
7853
|
return `tmux is required in this release but was not found. Install tmux (${how}) and re-run.`;
|
|
7778
7854
|
}
|
|
7779
|
-
// .dist-releases/
|
|
7855
|
+
// .dist-releases/1784809313131-4113078/src/output-format.js
|
|
7780
7856
|
function parseOutputArgs(argv) {
|
|
7781
7857
|
const cleaned = [];
|
|
7782
7858
|
let format = "plain";
|
|
@@ -7866,7 +7942,7 @@ ${normalized.split(`
|
|
|
7866
7942
|
`)}`;
|
|
7867
7943
|
}
|
|
7868
7944
|
|
|
7869
|
-
// .dist-releases/
|
|
7945
|
+
// .dist-releases/1784809313131-4113078/src/plain-output-fields.js
|
|
7870
7946
|
var PREVIEW_LIMIT = 20;
|
|
7871
7947
|
var UNSAFE_DISPLAY_CODE_POINT = /[\u007f-\u009f\u2028-\u202e\u2066-\u2069]/gu;
|
|
7872
7948
|
function renderTaskPlain(command, value) {
|
|
@@ -8274,7 +8350,7 @@ function _omissionLine(total) {
|
|
|
8274
8350
|
return total > PREVIEW_LIMIT ? `Omitted ${total - PREVIEW_LIMIT}; rerun with --format json for the complete response.` : undefined;
|
|
8275
8351
|
}
|
|
8276
8352
|
|
|
8277
|
-
// .dist-releases/
|
|
8353
|
+
// .dist-releases/1784809313131-4113078/src/host/cli.js
|
|
8278
8354
|
var HOST_RELAY_SUBCOMMANDS = new Set(["consume", "heartbeat", "list", "register"]);
|
|
8279
8355
|
async function runHostCommandFromCli(client, argv, config, io) {
|
|
8280
8356
|
const sub = argv[0] ?? "list";
|
|
@@ -8512,11 +8588,11 @@ function optionalDisplayName(value) {
|
|
|
8512
8588
|
const trimmed = value?.trim();
|
|
8513
8589
|
return trimmed || undefined;
|
|
8514
8590
|
}
|
|
8515
|
-
// .dist-releases/
|
|
8591
|
+
// .dist-releases/1784809313131-4113078/src/host/service.js
|
|
8516
8592
|
import { execFile as execFileCb } from "node:child_process";
|
|
8517
8593
|
import { createHash as createHash4 } from "node:crypto";
|
|
8518
8594
|
import { constants as fsConstants2 } from "node:fs";
|
|
8519
|
-
import { access, chmod as chmod2, lstat as lstat3, mkdir as mkdir4, readFile as
|
|
8595
|
+
import { access, chmod as chmod2, lstat as lstat3, mkdir as mkdir4, readFile as readFile4, rename as rename3, rm as rm3, writeFile as writeFile5 } from "node:fs/promises";
|
|
8520
8596
|
import { homedir as homedir7, platform as platform2, userInfo } from "node:os";
|
|
8521
8597
|
import path10 from "node:path";
|
|
8522
8598
|
import { promisify as promisify2 } from "node:util";
|
|
@@ -8736,7 +8812,7 @@ function serviceRuntime(deps) {
|
|
|
8736
8812
|
username: deps.username ?? info.username,
|
|
8737
8813
|
execFile: deps.execFile ?? execFileDefault,
|
|
8738
8814
|
writeFile: deps.writeFile ?? writeFile5,
|
|
8739
|
-
readFile: deps.readFile ??
|
|
8815
|
+
readFile: deps.readFile ?? readFile4,
|
|
8740
8816
|
mkdir: deps.mkdir ?? mkdir4,
|
|
8741
8817
|
rm: deps.rm ?? rm3,
|
|
8742
8818
|
access: deps.access ?? access,
|
|
@@ -8995,7 +9071,7 @@ function writeServiceLog(io, event, fields) {
|
|
|
8995
9071
|
io.stderr.write(`${JSON.stringify({ ts: new Date().toISOString(), event, ...fields ?? {} })}
|
|
8996
9072
|
`);
|
|
8997
9073
|
}
|
|
8998
|
-
// .dist-releases/
|
|
9074
|
+
// .dist-releases/1784809313131-4113078/src/host/git-remote.js
|
|
8999
9075
|
var GIT_SECRET_PATH_MARKERS = [
|
|
9000
9076
|
"token",
|
|
9001
9077
|
"credential",
|
|
@@ -9047,16 +9123,6 @@ function sanitizeGitOrigin(value) {
|
|
|
9047
9123
|
}
|
|
9048
9124
|
return hasCredentialPath(origin) ? null : origin;
|
|
9049
9125
|
}
|
|
9050
|
-
function gitRemoteRequiresGitHubAuth(value) {
|
|
9051
|
-
const remote = value.trim();
|
|
9052
|
-
if (remote.startsWith("git@"))
|
|
9053
|
-
return /^git@github\.com:/iu.test(remote);
|
|
9054
|
-
try {
|
|
9055
|
-
return new URL(remote).hostname.toLowerCase() === "github.com";
|
|
9056
|
-
} catch {
|
|
9057
|
-
return false;
|
|
9058
|
-
}
|
|
9059
|
-
}
|
|
9060
9126
|
function isAcceptedRemote(value, allowLocalPath) {
|
|
9061
9127
|
const remote = value.trim();
|
|
9062
9128
|
if (!remote || remote.length > 2048 || GIT_REMOTE_UNSAFE_RE.test(remote))
|
|
@@ -9097,7 +9163,7 @@ function looksLikeCredential(segment2) {
|
|
|
9097
9163
|
return value.length >= 32 && /^[A-Za-z0-9_-]+$/u.test(value);
|
|
9098
9164
|
}
|
|
9099
9165
|
|
|
9100
|
-
// .dist-releases/
|
|
9166
|
+
// .dist-releases/1784809313131-4113078/src/host/start-spec.js
|
|
9101
9167
|
var TRANSPORTS = ["auto", "sdk", "pty", "tmux", "headless"];
|
|
9102
9168
|
var SUPPORTED_PHASE1_ENGINES = ["claude", "codex"];
|
|
9103
9169
|
var ENGINE_PATTERN = /^[a-z][a-z0-9._-]{0,63}$/u;
|
|
@@ -9347,7 +9413,7 @@ function _trimmed(value, label) {
|
|
|
9347
9413
|
throw new Error(`${label} must not be empty`);
|
|
9348
9414
|
return trimmed;
|
|
9349
9415
|
}
|
|
9350
|
-
// .dist-releases/
|
|
9416
|
+
// .dist-releases/1784809313131-4113078/src/host/workspace.js
|
|
9351
9417
|
import { spawn as spawn4 } from "node:child_process";
|
|
9352
9418
|
import { existsSync as existsSync4 } from "node:fs";
|
|
9353
9419
|
import { mkdir as mkdir5, readdir as readdir2, rename as rename4, stat } from "node:fs/promises";
|
|
@@ -9578,7 +9644,7 @@ function _safeSegment(value) {
|
|
|
9578
9644
|
throw new Error("workspace path segment is empty after sanitizing");
|
|
9579
9645
|
return segment2;
|
|
9580
9646
|
}
|
|
9581
|
-
// .dist-releases/
|
|
9647
|
+
// .dist-releases/1784809313131-4113078/src/host/workspace-inventory.js
|
|
9582
9648
|
import { access as access2 } from "node:fs/promises";
|
|
9583
9649
|
import { constants } from "node:fs";
|
|
9584
9650
|
import { execFile as execFile2 } from "node:child_process";
|
|
@@ -9670,8 +9736,8 @@ async function canAccess(path12, mode, deps) {
|
|
|
9670
9736
|
return false;
|
|
9671
9737
|
}
|
|
9672
9738
|
}
|
|
9673
|
-
// .dist-releases/
|
|
9674
|
-
import { chmod as chmod3, mkdir as mkdir6, readFile as
|
|
9739
|
+
// .dist-releases/1784809313131-4113078/src/host/host-config.js
|
|
9740
|
+
import { chmod as chmod3, mkdir as mkdir6, readFile as readFile5, writeFile as writeFile6 } from "node:fs/promises";
|
|
9675
9741
|
import { homedir as homedir10 } from "node:os";
|
|
9676
9742
|
import path12 from "node:path";
|
|
9677
9743
|
var HOST_CONFIG_KIND = "sailorbridge-host-config";
|
|
@@ -9688,7 +9754,7 @@ function normalizeWorkspacePath(entry) {
|
|
|
9688
9754
|
async function loadHostConfig(configPath = defaultHostConfigPath()) {
|
|
9689
9755
|
let text;
|
|
9690
9756
|
try {
|
|
9691
|
-
text = await
|
|
9757
|
+
text = await readFile5(configPath, "utf8");
|
|
9692
9758
|
} catch (error) {
|
|
9693
9759
|
if (error.code === "ENOENT")
|
|
9694
9760
|
return { kind: HOST_CONFIG_KIND, workspaces: [] };
|
|
@@ -9755,7 +9821,7 @@ function _parseHostConfig(text, configPath) {
|
|
|
9755
9821
|
});
|
|
9756
9822
|
return { kind: HOST_CONFIG_KIND, workspaces };
|
|
9757
9823
|
}
|
|
9758
|
-
// .dist-releases/
|
|
9824
|
+
// .dist-releases/1784809313131-4113078/src/host/host-workspace-cli.js
|
|
9759
9825
|
async function runHostWorkspaceCommandFromCli(argv, io, deps = {}) {
|
|
9760
9826
|
const configPath = deps.configPath ?? defaultHostConfigPath();
|
|
9761
9827
|
const sub = argv[0] ?? "list";
|
|
@@ -9799,7 +9865,7 @@ function _renderAddPlain(result) {
|
|
|
9799
9865
|
return result.note ? `${status} ${result.path}
|
|
9800
9866
|
${result.note}` : `${status} ${result.path}`;
|
|
9801
9867
|
}
|
|
9802
|
-
// .dist-releases/
|
|
9868
|
+
// .dist-releases/1784809313131-4113078/src/host/agent-env.js
|
|
9803
9869
|
var RUNTIME_NATIVE_HOME_ENV = new Set(["CLAUDE_CONFIG_DIR", "CODEX_HOME"]);
|
|
9804
9870
|
function buildAgentEnv(options) {
|
|
9805
9871
|
const env = {};
|
|
@@ -9828,16 +9894,16 @@ function buildAgentEnv(options) {
|
|
|
9828
9894
|
}
|
|
9829
9895
|
return env;
|
|
9830
9896
|
}
|
|
9831
|
-
// .dist-releases/
|
|
9897
|
+
// .dist-releases/1784809313131-4113078/src/host/runtime-env.js
|
|
9832
9898
|
import path16 from "node:path";
|
|
9833
9899
|
|
|
9834
|
-
// .dist-releases/
|
|
9835
|
-
import { chmod as chmod4, mkdir as mkdir7, readFile as
|
|
9900
|
+
// .dist-releases/1784809313131-4113078/src/host/agent-defaults.js
|
|
9901
|
+
import { chmod as chmod4, mkdir as mkdir7, readFile as readFile7, stat as stat2, writeFile as writeFile7 } from "node:fs/promises";
|
|
9836
9902
|
import { homedir as homedir11 } from "node:os";
|
|
9837
9903
|
import path14 from "node:path";
|
|
9838
9904
|
|
|
9839
|
-
// .dist-releases/
|
|
9840
|
-
import { readFile as
|
|
9905
|
+
// .dist-releases/1784809313131-4113078/src/host/claude-settings.js
|
|
9906
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
9841
9907
|
import path13 from "node:path";
|
|
9842
9908
|
async function readHostClaudeSettings(claudeConfigDir) {
|
|
9843
9909
|
const settings = await _readSettingsObject(path13.join(claudeConfigDir, "settings.json"));
|
|
@@ -9846,7 +9912,7 @@ async function readHostClaudeSettings(claudeConfigDir) {
|
|
|
9846
9912
|
async function _readSettingsObject(filePath) {
|
|
9847
9913
|
let text;
|
|
9848
9914
|
try {
|
|
9849
|
-
text = await
|
|
9915
|
+
text = await readFile6(filePath, "utf8");
|
|
9850
9916
|
} catch (error) {
|
|
9851
9917
|
if (error.code === "ENOENT")
|
|
9852
9918
|
return {};
|
|
@@ -9877,7 +9943,7 @@ function _nonEmptyString(value) {
|
|
|
9877
9943
|
return typeof value === "string" && value.trim() ? value : null;
|
|
9878
9944
|
}
|
|
9879
9945
|
|
|
9880
|
-
// .dist-releases/
|
|
9946
|
+
// .dist-releases/1784809313131-4113078/src/host/agent-defaults.js
|
|
9881
9947
|
var CODEX_BLOCK_BEGIN = "# sailorbridge-terse-defaults:begin";
|
|
9882
9948
|
var CODEX_BLOCK_END = "# sailorbridge-terse-defaults:end";
|
|
9883
9949
|
var CODEX_MODEL_BLOCK_BEGIN = "# sailorbridge-host-model-settings:begin";
|
|
@@ -10600,7 +10666,7 @@ async function _claudeTrustRoots(projectPath) {
|
|
|
10600
10666
|
}
|
|
10601
10667
|
if (!stats.isFile())
|
|
10602
10668
|
return [projectPath];
|
|
10603
|
-
const gitdir = /^gitdir:\s*(.+)\s*$/m.exec(await
|
|
10669
|
+
const gitdir = /^gitdir:\s*(.+)\s*$/m.exec(await readFile7(pointer, "utf8"))?.[1];
|
|
10604
10670
|
if (!gitdir) {
|
|
10605
10671
|
throw new Error(`workspace ${projectPath} has an unreadable .git pointer — cannot pre-trust its main repository for claude`);
|
|
10606
10672
|
}
|
|
@@ -10986,7 +11052,7 @@ async function _readTextIfExists2(filePath) {
|
|
|
10986
11052
|
return "";
|
|
10987
11053
|
throw error;
|
|
10988
11054
|
}
|
|
10989
|
-
return
|
|
11055
|
+
return readFile7(filePath, "utf8");
|
|
10990
11056
|
}
|
|
10991
11057
|
function _expandHome3(value) {
|
|
10992
11058
|
if (value === "~")
|
|
@@ -11007,7 +11073,7 @@ function _escapeRegExp(value) {
|
|
|
11007
11073
|
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
11008
11074
|
}
|
|
11009
11075
|
|
|
11010
|
-
// .dist-releases/
|
|
11076
|
+
// .dist-releases/1784809313131-4113078/src/host/engine-auth.js
|
|
11011
11077
|
import { lstat as lstat4, mkdir as mkdir8, readlink, realpath, stat as stat3, symlink as symlink2, unlink as unlink2 } from "node:fs/promises";
|
|
11012
11078
|
import { homedir as homedir12 } from "node:os";
|
|
11013
11079
|
import path15 from "node:path";
|
|
@@ -11097,7 +11163,7 @@ async function _ensureSymlink(linkPath, targetPath, sharedTargetPath) {
|
|
|
11097
11163
|
await symlink2(targetPath, linkPath);
|
|
11098
11164
|
}
|
|
11099
11165
|
|
|
11100
|
-
// .dist-releases/
|
|
11166
|
+
// .dist-releases/1784809313131-4113078/src/host/runtime-env.js
|
|
11101
11167
|
async function materializeAgentRuntimeEnv(options) {
|
|
11102
11168
|
const env = buildAgentEnv({
|
|
11103
11169
|
hostEnv: options.hostEnv,
|
|
@@ -11108,6 +11174,7 @@ async function materializeAgentRuntimeEnv(options) {
|
|
|
11108
11174
|
const memoryStub = await materializeAgentMemoryStub({
|
|
11109
11175
|
agentName: options.agentName,
|
|
11110
11176
|
engine: options.engine,
|
|
11177
|
+
teamMemoryEntitled: options.teamMemoryEntitled,
|
|
11111
11178
|
env: options.hostEnv,
|
|
11112
11179
|
homeDir
|
|
11113
11180
|
});
|
|
@@ -11136,7 +11203,7 @@ function _ensureRootSandboxEscape(env, engine, uid) {
|
|
|
11136
11203
|
function _currentUid() {
|
|
11137
11204
|
return typeof process.getuid === "function" ? process.getuid() : null;
|
|
11138
11205
|
}
|
|
11139
|
-
// .dist-releases/
|
|
11206
|
+
// .dist-releases/1784809313131-4113078/src/host/context-statusline.js
|
|
11140
11207
|
function renderClaudeContextStatusLine(payload) {
|
|
11141
11208
|
const percent = _usedPercentage(payload);
|
|
11142
11209
|
if (percent === null)
|
|
@@ -11174,179 +11241,10 @@ function _bar(percent) {
|
|
|
11174
11241
|
const filled = Math.min(10, Math.max(0, Math.trunc(percent / 10)));
|
|
11175
11242
|
return "█".repeat(filled) + "░".repeat(10 - filled);
|
|
11176
11243
|
}
|
|
11177
|
-
// .dist-releases/
|
|
11178
|
-
import { createHash as createHash5 } from "node:crypto";
|
|
11179
|
-
import { readdir as readdir3, readFile as readFile7, stat as stat4, writeFile as writeFile8 } from "node:fs/promises";
|
|
11180
|
-
import path17 from "node:path";
|
|
11181
|
-
function createMemorySweepState() {
|
|
11182
|
-
return { completedFingerprints: new Map };
|
|
11183
|
-
}
|
|
11184
|
-
async function sweepAgentMemory(options) {
|
|
11185
|
-
const captainId = _captainId2(options.captainId);
|
|
11186
|
-
const engine = _memoryEngine(options.engine);
|
|
11187
|
-
const sandbox = agentSandboxHome(options.agentName, engine, options.env ?? process.env);
|
|
11188
|
-
const candidates = await _memoryCandidates(sandbox, engine, options);
|
|
11189
|
-
let ingested = 0;
|
|
11190
|
-
let skipped = 0;
|
|
11191
|
-
for (const candidate of candidates) {
|
|
11192
|
-
const changed = await _sweepCandidate(candidate, { ...options, captainId, engine });
|
|
11193
|
-
if (changed)
|
|
11194
|
-
ingested += 1;
|
|
11195
|
-
else
|
|
11196
|
-
skipped += 1;
|
|
11197
|
-
}
|
|
11198
|
-
return { scanned: candidates.length, ingested, skipped };
|
|
11199
|
-
}
|
|
11200
|
-
async function _sweepCandidate(candidate, options) {
|
|
11201
|
-
const content = await (options.readFile ?? readFile7)(candidate.filePath, "utf8");
|
|
11202
|
-
const spill = _spillContent(content);
|
|
11203
|
-
if (spill.malformedStub) {
|
|
11204
|
-
options.logger?.("host_memory_spill_malformed_marker", {
|
|
11205
|
-
agent_name: options.agentName,
|
|
11206
|
-
engine: options.engine,
|
|
11207
|
-
mode: options.mode ?? "runtime",
|
|
11208
|
-
path: candidate.relativePath
|
|
11209
|
-
});
|
|
11210
|
-
return false;
|
|
11211
|
-
}
|
|
11212
|
-
if (!spill.text.trim())
|
|
11213
|
-
return false;
|
|
11214
|
-
const fingerprint = _fingerprint(candidate.filePath, spill.text, await (options.stat ?? stat4)(candidate.filePath));
|
|
11215
|
-
if (options.state?.completedFingerprints.get(candidate.filePath) === fingerprint)
|
|
11216
|
-
return false;
|
|
11217
|
-
const response = await options.relay.ingestRagDocument(options.captainId, options.teamId, _ingestBody(candidate, options, spill.text));
|
|
11218
|
-
await _verifyCards(options.relay, options.captainId, options.teamId, response);
|
|
11219
|
-
const latestContent = await (options.readFile ?? readFile7)(candidate.filePath, "utf8");
|
|
11220
|
-
if (latestContent !== content) {
|
|
11221
|
-
options.logger?.("host_memory_spill_changed_before_slim", {
|
|
11222
|
-
agent_name: options.agentName,
|
|
11223
|
-
engine: options.engine,
|
|
11224
|
-
mode: options.mode ?? "runtime",
|
|
11225
|
-
path: candidate.relativePath,
|
|
11226
|
-
cards: response.cards
|
|
11227
|
-
});
|
|
11228
|
-
return true;
|
|
11229
|
-
}
|
|
11230
|
-
await (options.writeFile ?? writeFile8)(candidate.filePath, RAG_MEMORY_STUB_MARKED, { mode: 384 });
|
|
11231
|
-
options.state?.completedFingerprints.set(candidate.filePath, fingerprint);
|
|
11232
|
-
options.logger?.("host_memory_spill_ingested", {
|
|
11233
|
-
agent_name: options.agentName,
|
|
11234
|
-
engine: options.engine,
|
|
11235
|
-
mode: options.mode ?? "runtime",
|
|
11236
|
-
path: candidate.relativePath,
|
|
11237
|
-
cards: response.cards
|
|
11238
|
-
});
|
|
11239
|
-
return true;
|
|
11240
|
-
}
|
|
11241
|
-
async function _memoryCandidates(sandbox, engine, deps) {
|
|
11242
|
-
const canonical = path17.join(sandbox, memoryStubFileName(engine));
|
|
11243
|
-
const candidates = await _fileExists(canonical, deps) ? [_candidate(sandbox, canonical)] : [];
|
|
11244
|
-
const projectRoot = path17.join(sandbox, "projects");
|
|
11245
|
-
for (const filePath of await _walkMemoryFiles(projectRoot, deps)) {
|
|
11246
|
-
if (filePath !== canonical)
|
|
11247
|
-
candidates.push(_candidate(sandbox, filePath));
|
|
11248
|
-
}
|
|
11249
|
-
return candidates;
|
|
11250
|
-
}
|
|
11251
|
-
async function _walkMemoryFiles(root, deps) {
|
|
11252
|
-
if (!await _dirExists(root, deps))
|
|
11253
|
-
return [];
|
|
11254
|
-
const out = [];
|
|
11255
|
-
for (const entry of await (deps.readdir ?? readdir3)(root, { withFileTypes: true })) {
|
|
11256
|
-
const filePath = path17.join(root, entry.name);
|
|
11257
|
-
if (entry.isDirectory())
|
|
11258
|
-
out.push(...await _walkMemoryFiles(filePath, deps));
|
|
11259
|
-
if (entry.isFile() && path17.basename(filePath) === "MEMORY.md" && path17.basename(path17.dirname(filePath)) === "memory") {
|
|
11260
|
-
out.push(filePath);
|
|
11261
|
-
}
|
|
11262
|
-
}
|
|
11263
|
-
return out;
|
|
11264
|
-
}
|
|
11265
|
-
function _spillContent(content) {
|
|
11266
|
-
const start = content.indexOf(RAG_MEMORY_STUB_BEGIN);
|
|
11267
|
-
const stop = content.indexOf(RAG_MEMORY_STUB_END);
|
|
11268
|
-
if (start < 0 && stop < 0)
|
|
11269
|
-
return { text: content, malformedStub: false };
|
|
11270
|
-
if (start < 0 || stop < start)
|
|
11271
|
-
return { text: "", malformedStub: true };
|
|
11272
|
-
return {
|
|
11273
|
-
text: _joinSpillParts(content.slice(0, start), content.slice(stop + RAG_MEMORY_STUB_END.length)),
|
|
11274
|
-
malformedStub: false
|
|
11275
|
-
};
|
|
11276
|
-
}
|
|
11277
|
-
function _joinSpillParts(beforeStub, afterStub) {
|
|
11278
|
-
const before = beforeStub.trim();
|
|
11279
|
-
const after = afterStub.trim();
|
|
11280
|
-
if (!before)
|
|
11281
|
-
return after ? `${after}
|
|
11282
|
-
` : "";
|
|
11283
|
-
if (!after)
|
|
11284
|
-
return `${before}
|
|
11285
|
-
`;
|
|
11286
|
-
return `${before}
|
|
11287
|
-
${after}
|
|
11288
|
-
`;
|
|
11289
|
-
}
|
|
11290
|
-
function _ingestBody(candidate, options, text) {
|
|
11291
|
-
return {
|
|
11292
|
-
name: `agent-memory/${options.agentName}/${options.engine}/${candidate.relativePath}`,
|
|
11293
|
-
text,
|
|
11294
|
-
type: "memory",
|
|
11295
|
-
max_chars: 800,
|
|
11296
|
-
citation: { agent: options.agentName, engine: options.engine, file: candidate.relativePath }
|
|
11297
|
-
};
|
|
11298
|
-
}
|
|
11299
|
-
async function _verifyCards(relay, captainId, teamId, response) {
|
|
11300
|
-
if (response.cards < 1)
|
|
11301
|
-
throw new Error("RAG ingest returned no cards for non-empty memory spill");
|
|
11302
|
-
const cards = [];
|
|
11303
|
-
for (let index = 0;index < response.cards; index += 1) {
|
|
11304
|
-
cards.push(await relay.getRagCurrentCard(captainId, teamId, `${response.doc_id}#${String(index).padStart(2, "0")}`));
|
|
11305
|
-
}
|
|
11306
|
-
return cards;
|
|
11307
|
-
}
|
|
11308
|
-
function _candidate(sandbox, filePath) {
|
|
11309
|
-
return { filePath, relativePath: path17.relative(sandbox, filePath).split(path17.sep).join("/") };
|
|
11310
|
-
}
|
|
11311
|
-
function _fingerprint(filePath, content, stats) {
|
|
11312
|
-
const digest = createHash5("sha256").update(content).digest("hex");
|
|
11313
|
-
return `${filePath}:${stats.size}:${stats.mtimeMs}:${digest}`;
|
|
11314
|
-
}
|
|
11315
|
-
async function _fileExists(filePath, deps) {
|
|
11316
|
-
try {
|
|
11317
|
-
return (await (deps.stat ?? stat4)(filePath)).isFile();
|
|
11318
|
-
} catch (error) {
|
|
11319
|
-
if (_notFound(error))
|
|
11320
|
-
return false;
|
|
11321
|
-
throw error;
|
|
11322
|
-
}
|
|
11323
|
-
}
|
|
11324
|
-
async function _dirExists(filePath, deps) {
|
|
11325
|
-
try {
|
|
11326
|
-
return (await (deps.stat ?? stat4)(filePath)).isDirectory();
|
|
11327
|
-
} catch (error) {
|
|
11328
|
-
if (_notFound(error))
|
|
11329
|
-
return false;
|
|
11330
|
-
throw error;
|
|
11331
|
-
}
|
|
11332
|
-
}
|
|
11333
|
-
function _captainId2(value) {
|
|
11334
|
-
if (value?.trim())
|
|
11335
|
-
return value.trim();
|
|
11336
|
-
throw new Error("memory sweep requires descriptor captain_id");
|
|
11337
|
-
}
|
|
11338
|
-
function _memoryEngine(value) {
|
|
11339
|
-
if (value === "claude" || value === "codex")
|
|
11340
|
-
return value;
|
|
11341
|
-
throw new Error("memory sweep engine must be claude or codex");
|
|
11342
|
-
}
|
|
11343
|
-
function _notFound(error) {
|
|
11344
|
-
return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
|
|
11345
|
-
}
|
|
11346
|
-
// .dist-releases/1784772051951-3107696/src/host/scratch-sweeper.js
|
|
11244
|
+
// .dist-releases/1784809313131-4113078/src/host/scratch-sweeper.js
|
|
11347
11245
|
import { execFile as execFile3 } from "node:child_process";
|
|
11348
|
-
import { lstat as lstat5, readdir as
|
|
11349
|
-
import
|
|
11246
|
+
import { lstat as lstat5, readdir as readdir3, realpath as realpath2, unlink as unlink3 } from "node:fs/promises";
|
|
11247
|
+
import path17 from "node:path";
|
|
11350
11248
|
import { promisify as promisify4 } from "node:util";
|
|
11351
11249
|
var execFileAsync3 = promisify4(execFile3);
|
|
11352
11250
|
var SCRATCH_SUBDIR = ".agent/tmp";
|
|
@@ -11360,8 +11258,8 @@ function scratchSweepEnabled(env) {
|
|
|
11360
11258
|
return raw !== "0" && raw !== "false" && raw !== "no" && raw !== "off";
|
|
11361
11259
|
}
|
|
11362
11260
|
async function sweepWorkspaceScratch(options) {
|
|
11363
|
-
const root =
|
|
11364
|
-
const tmpDir =
|
|
11261
|
+
const root = path17.resolve(options.workspaceRoot);
|
|
11262
|
+
const tmpDir = path17.join(root, SCRATCH_SUBDIR);
|
|
11365
11263
|
const state = await _tmpDirState(root, tmpDir);
|
|
11366
11264
|
if (state === "missing")
|
|
11367
11265
|
return EMPTY;
|
|
@@ -11399,7 +11297,7 @@ async function _trackedScratchFiles(root, options) {
|
|
|
11399
11297
|
const tracked = new Set;
|
|
11400
11298
|
for (const rel of stdout.split("\x00"))
|
|
11401
11299
|
if (rel)
|
|
11402
|
-
tracked.add(
|
|
11300
|
+
tracked.add(path17.join(root, rel));
|
|
11403
11301
|
return tracked;
|
|
11404
11302
|
} catch (error) {
|
|
11405
11303
|
options.logger?.("host_scratch_sweep_git_failed", { workspace: root, error: _errno(error) });
|
|
@@ -11408,8 +11306,8 @@ async function _trackedScratchFiles(root, options) {
|
|
|
11408
11306
|
}
|
|
11409
11307
|
async function _collectScratchFiles(dir, root, logger) {
|
|
11410
11308
|
const out = [];
|
|
11411
|
-
for (const entry of await
|
|
11412
|
-
const abs =
|
|
11309
|
+
for (const entry of await readdir3(dir, { withFileTypes: true })) {
|
|
11310
|
+
const abs = path17.join(dir, entry.name);
|
|
11413
11311
|
if (!_within(root, abs)) {
|
|
11414
11312
|
logger?.("host_scratch_sweep_out_of_bounds", { workspace: root, path: abs });
|
|
11415
11313
|
continue;
|
|
@@ -11475,8 +11373,8 @@ async function _runGit2(root, args) {
|
|
|
11475
11373
|
return String(stdout);
|
|
11476
11374
|
}
|
|
11477
11375
|
function _within(root, target) {
|
|
11478
|
-
const rel =
|
|
11479
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
11376
|
+
const rel = path17.relative(root, target);
|
|
11377
|
+
return rel === "" || !rel.startsWith("..") && !path17.isAbsolute(rel);
|
|
11480
11378
|
}
|
|
11481
11379
|
function _isEnoent(error) {
|
|
11482
11380
|
return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
|
|
@@ -11486,16 +11384,22 @@ function _errno(error) {
|
|
|
11486
11384
|
return String(error.code);
|
|
11487
11385
|
return error instanceof Error ? error.message : String(error);
|
|
11488
11386
|
}
|
|
11489
|
-
// .dist-releases/
|
|
11387
|
+
// .dist-releases/1784809313131-4113078/src/host/launcher.js
|
|
11490
11388
|
var MAX_TMUX_SESSION_SUFFIX = 100;
|
|
11491
11389
|
async function launchSupervisedAgent(input, deps = {}) {
|
|
11492
11390
|
const spec = parseAgentStartSpec(input.spec);
|
|
11493
11391
|
const logger = input.logger ?? (() => {});
|
|
11392
|
+
const relay = new RelayClient({
|
|
11393
|
+
relayUrl: input.descriptor.relay_url,
|
|
11394
|
+
bearerToken: input.descriptor.token,
|
|
11395
|
+
...deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}
|
|
11396
|
+
});
|
|
11494
11397
|
const { env, credentialGuard } = await materializeAgentRuntimeEnv({
|
|
11495
11398
|
agentName: input.descriptor.agent_name,
|
|
11496
11399
|
engine: spec.engine,
|
|
11497
11400
|
hostEnv: input.hostEnv ?? process.env,
|
|
11498
11401
|
descriptor: input.descriptor,
|
|
11402
|
+
teamMemoryEntitled: await (deps.resolveTeamMemoryEntitlementFn ?? resolveTeamMemoryEntitlement)(relay, input.captainId, input.descriptor.session),
|
|
11499
11403
|
specEnv: spec.env
|
|
11500
11404
|
});
|
|
11501
11405
|
const cwd = await (deps.prepareWorkspaceFn ?? prepareWorkspace)({
|
|
@@ -11508,11 +11412,6 @@ async function launchSupervisedAgent(input, deps = {}) {
|
|
|
11508
11412
|
});
|
|
11509
11413
|
await _trustPreparedWorkspace(input.descriptor.agent_name, spec.engine, env, cwd);
|
|
11510
11414
|
const resolved = await _resolveTransport(spec, input.descriptor, cwd, logger, deps.ensureTmuxTransportFn, deps.tmuxSessionExistsFn, input.recoveryTmuxSession);
|
|
11511
|
-
const relay = new RelayClient({
|
|
11512
|
-
relayUrl: input.descriptor.relay_url,
|
|
11513
|
-
bearerToken: input.descriptor.token,
|
|
11514
|
-
...deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}
|
|
11515
|
-
});
|
|
11516
11415
|
const runtime = (deps.createRuntime ?? ((options) => new AgentSupervisorRuntime(options)))({
|
|
11517
11416
|
agentName: input.descriptor.agent_name,
|
|
11518
11417
|
displayName: input.descriptor.agent_name,
|
|
@@ -11636,90 +11535,10 @@ async function _tmuxSessionExists(session) {
|
|
|
11636
11535
|
throw error;
|
|
11637
11536
|
}
|
|
11638
11537
|
}
|
|
11639
|
-
// .dist-releases/
|
|
11640
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
11641
|
-
import { tmpdir as tmpdir2 } from "node:os";
|
|
11642
|
-
import path19 from "node:path";
|
|
11643
|
-
import { spawn as spawn5 } from "node:child_process";
|
|
11644
|
-
var COMMAND_TIMEOUT_MS2 = 30000;
|
|
11645
|
-
async function verifyTeamRepository(gitRepoUrl, hostId, deps = {}) {
|
|
11646
|
-
const command = deps.runCommand ?? runCommand;
|
|
11647
|
-
const commandOutput = deps.runCommandOutput ?? runCommandOutput;
|
|
11648
|
-
const trimmed = gitRepoUrl.trim();
|
|
11649
|
-
if (!isAcceptedTeamGitRemote(trimmed))
|
|
11650
|
-
throw new Error("git repository URL is not accepted by SailorBridge hardening rules");
|
|
11651
|
-
if (gitRemoteRequiresGitHubAuth(trimmed)) {
|
|
11652
|
-
await command(["gh", "auth", "status"], process.cwd(), "gh auth status failed; install and authenticate GitHub CLI on the Moderator host");
|
|
11653
|
-
}
|
|
11654
|
-
const readProbe = await commandOutput(["git", "ls-remote", "--symref", trimmed, "HEAD"], process.cwd(), "git read probe failed");
|
|
11655
|
-
const mainRef = _defaultBranchFromSymrefProbe(readProbe);
|
|
11656
|
-
const temp = mkdtempSync(path19.join(tmpdir2(), "sailorbridge-repo-verify-"));
|
|
11657
|
-
try {
|
|
11658
|
-
await command(["git", "init"], temp, "git init failed for write probe");
|
|
11659
|
-
await command(["git", "config", "user.email", "sailorbridge-verify@example.invalid"], temp, "git config failed for write probe");
|
|
11660
|
-
await command(["git", "config", "user.name", "SailorBridge Verify"], temp, "git config failed for write probe");
|
|
11661
|
-
await command(["git", "commit", "--allow-empty", "-m", "sailorbridge verify"], temp, "git commit failed for write probe");
|
|
11662
|
-
await command(["git", "push", "--dry-run", trimmed, "HEAD:refs/heads/sailorbridge-verify"], temp, "git write probe failed");
|
|
11663
|
-
} finally {
|
|
11664
|
-
rmSync(temp, { recursive: true, force: true });
|
|
11665
|
-
}
|
|
11666
|
-
return {
|
|
11667
|
-
verified: true,
|
|
11668
|
-
reason: "git read and dry-run write probes succeeded",
|
|
11669
|
-
verified_at: (deps.now ?? (() => new Date))().toISOString(),
|
|
11670
|
-
verification_host_id: hostId,
|
|
11671
|
-
...mainRef ? { main_ref: mainRef } : {}
|
|
11672
|
-
};
|
|
11673
|
-
}
|
|
11674
|
-
function _defaultBranchFromSymrefProbe(output) {
|
|
11675
|
-
const match = /^ref:\s+refs\/heads\/(\S+)\s+HEAD$/mu.exec(output);
|
|
11676
|
-
return match ? match[1] : null;
|
|
11677
|
-
}
|
|
11678
|
-
async function runCommand(argv, cwd, failurePrefix) {
|
|
11679
|
-
await runCommandOutput(argv, cwd, failurePrefix);
|
|
11680
|
-
}
|
|
11681
|
-
async function runCommandOutput(argv, cwd, failurePrefix) {
|
|
11682
|
-
const result = await execArgv2(argv, cwd);
|
|
11683
|
-
if (result.exitCode === 0)
|
|
11684
|
-
return result.stdout;
|
|
11685
|
-
const detail = [result.stderr.trim(), result.stdout.trim()].filter(Boolean).join(`
|
|
11686
|
-
`).slice(0, 500);
|
|
11687
|
-
throw new Error(detail ? `${failurePrefix}: ${detail}` : failurePrefix);
|
|
11688
|
-
}
|
|
11689
|
-
function execArgv2(argv, cwd) {
|
|
11690
|
-
return new Promise((resolve2) => {
|
|
11691
|
-
const proc = spawn5(argv[0], argv.slice(1), { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
11692
|
-
const stdout = [];
|
|
11693
|
-
const stderr = [];
|
|
11694
|
-
let settled = false;
|
|
11695
|
-
const finish = (exitCode, extraStderr = "") => {
|
|
11696
|
-
if (settled)
|
|
11697
|
-
return;
|
|
11698
|
-
settled = true;
|
|
11699
|
-
clearTimeout(timer);
|
|
11700
|
-
resolve2({
|
|
11701
|
-
exitCode,
|
|
11702
|
-
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
11703
|
-
stderr: `${Buffer.concat(stderr).toString("utf8")}${extraStderr}`
|
|
11704
|
-
});
|
|
11705
|
-
};
|
|
11706
|
-
const timer = setTimeout(() => {
|
|
11707
|
-
proc.kill("SIGTERM");
|
|
11708
|
-
finish(124, `
|
|
11709
|
-
timeout expired`);
|
|
11710
|
-
}, COMMAND_TIMEOUT_MS2);
|
|
11711
|
-
proc.stdout.on("data", (chunk) => stdout.push(chunk));
|
|
11712
|
-
proc.stderr.on("data", (chunk) => stderr.push(chunk));
|
|
11713
|
-
proc.on("error", (error) => finish(127, `
|
|
11714
|
-
${error.message}`));
|
|
11715
|
-
proc.on("close", (code) => finish(code ?? 1));
|
|
11716
|
-
});
|
|
11717
|
-
}
|
|
11718
|
-
|
|
11719
|
-
// .dist-releases/1784772051951-3107696/src/worker/capability.js
|
|
11720
|
-
import { accessSync, constants as constants2, mkdirSync as mkdirSync3, mkdtempSync as mkdtempSync2, readFileSync as readFileSync3, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
11538
|
+
// .dist-releases/1784809313131-4113078/src/worker/capability.js
|
|
11539
|
+
import { accessSync, constants as constants2, mkdirSync as mkdirSync3, mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
11721
11540
|
import os from "node:os";
|
|
11722
|
-
import
|
|
11541
|
+
import path18 from "node:path";
|
|
11723
11542
|
import { spawnSync } from "node:child_process";
|
|
11724
11543
|
var TOOLS = ["podman", "git", "kubectl", "perf", "bpftrace"];
|
|
11725
11544
|
var GPU_TAGS = new Set(["intel-b60", "nvidia-h100", "none"]);
|
|
@@ -11819,11 +11638,11 @@ function parseOsReleaseLine(line) {
|
|
|
11819
11638
|
}
|
|
11820
11639
|
function isReadonly(dir) {
|
|
11821
11640
|
try {
|
|
11822
|
-
const root =
|
|
11641
|
+
const root = path18.resolve(dir);
|
|
11823
11642
|
mkdirSync3(root, { recursive: true });
|
|
11824
|
-
const temp =
|
|
11825
|
-
writeFileSync2(
|
|
11826
|
-
|
|
11643
|
+
const temp = mkdtempSync(path18.join(root, ".sailorbridge-write-test-"));
|
|
11644
|
+
writeFileSync2(path18.join(temp, "probe"), "");
|
|
11645
|
+
rmSync(temp, { recursive: true, force: true });
|
|
11827
11646
|
return false;
|
|
11828
11647
|
} catch {
|
|
11829
11648
|
return true;
|
|
@@ -11847,10 +11666,10 @@ function commandExists(command) {
|
|
|
11847
11666
|
return commandPath(command) !== null;
|
|
11848
11667
|
}
|
|
11849
11668
|
function commandPath(command) {
|
|
11850
|
-
if (command.includes(
|
|
11669
|
+
if (command.includes(path18.sep))
|
|
11851
11670
|
return command;
|
|
11852
|
-
for (const entry of (process.env.PATH ?? "").split(
|
|
11853
|
-
const candidate =
|
|
11671
|
+
for (const entry of (process.env.PATH ?? "").split(path18.delimiter)) {
|
|
11672
|
+
const candidate = path18.join(entry, command);
|
|
11854
11673
|
try {
|
|
11855
11674
|
accessSync(candidate, constants2.X_OK);
|
|
11856
11675
|
return candidate;
|
|
@@ -11859,7 +11678,7 @@ function commandPath(command) {
|
|
|
11859
11678
|
return null;
|
|
11860
11679
|
}
|
|
11861
11680
|
|
|
11862
|
-
// .dist-releases/
|
|
11681
|
+
// .dist-releases/1784809313131-4113078/src/host/worker-start-spec.js
|
|
11863
11682
|
var MAX_TAGS = 32;
|
|
11864
11683
|
var TAG_PATTERN = /^[a-z0-9][a-z0-9=._:/-]{0,63}$/iu;
|
|
11865
11684
|
var RESERVED_TAG_KEYS = new Set(["os", "kernel", "arch", "gpu", "mode", "role", "tool"]);
|
|
@@ -11919,16 +11738,16 @@ function _trimmed2(value, label) {
|
|
|
11919
11738
|
return trimmed;
|
|
11920
11739
|
}
|
|
11921
11740
|
|
|
11922
|
-
// .dist-releases/
|
|
11741
|
+
// .dist-releases/1784809313131-4113078/src/host/worker-launcher.js
|
|
11923
11742
|
import { statSync as statSync3 } from "node:fs";
|
|
11924
11743
|
import os4 from "node:os";
|
|
11925
|
-
import
|
|
11926
|
-
// .dist-releases/
|
|
11744
|
+
import path21 from "node:path";
|
|
11745
|
+
// .dist-releases/1784809313131-4113078/src/worker/client.js
|
|
11927
11746
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
11928
11747
|
import os3 from "node:os";
|
|
11929
|
-
import
|
|
11748
|
+
import path20 from "node:path";
|
|
11930
11749
|
|
|
11931
|
-
// .dist-releases/
|
|
11750
|
+
// .dist-releases/1784809313131-4113078/src/worker/errors.js
|
|
11932
11751
|
class LeaseFencingRejected extends Error {
|
|
11933
11752
|
status;
|
|
11934
11753
|
constructor(status, message) {
|
|
@@ -11942,10 +11761,10 @@ class WorkerHttpError extends Error {
|
|
|
11942
11761
|
method;
|
|
11943
11762
|
path;
|
|
11944
11763
|
status;
|
|
11945
|
-
constructor(method,
|
|
11764
|
+
constructor(method, path19, status, message) {
|
|
11946
11765
|
super(message || `HTTP ${status}`);
|
|
11947
11766
|
this.method = method;
|
|
11948
|
-
this.path =
|
|
11767
|
+
this.path = path19;
|
|
11949
11768
|
this.status = status;
|
|
11950
11769
|
this.name = "WorkerHttpError";
|
|
11951
11770
|
}
|
|
@@ -11954,10 +11773,10 @@ class WorkerHttpError extends Error {
|
|
|
11954
11773
|
class WorkerNetworkError extends Error {
|
|
11955
11774
|
method;
|
|
11956
11775
|
path;
|
|
11957
|
-
constructor(method,
|
|
11776
|
+
constructor(method, path19, message) {
|
|
11958
11777
|
super(message);
|
|
11959
11778
|
this.method = method;
|
|
11960
|
-
this.path =
|
|
11779
|
+
this.path = path19;
|
|
11961
11780
|
this.name = "WorkerNetworkError";
|
|
11962
11781
|
}
|
|
11963
11782
|
}
|
|
@@ -11965,14 +11784,14 @@ var LEASE_FENCING_BAD_REQUEST_MESSAGES = [
|
|
|
11965
11784
|
"lease_token is required",
|
|
11966
11785
|
"lease_token must be a non-empty string"
|
|
11967
11786
|
];
|
|
11968
|
-
function raiseForLeaseFencingOrStatus(method,
|
|
11787
|
+
function raiseForLeaseFencingOrStatus(method, path19, status, body) {
|
|
11969
11788
|
if (status === 409)
|
|
11970
11789
|
throw new LeaseFencingRejected(status, body);
|
|
11971
11790
|
if (status === 400 && LEASE_FENCING_BAD_REQUEST_MESSAGES.some((message) => body.includes(message))) {
|
|
11972
11791
|
throw new LeaseFencingRejected(status, body);
|
|
11973
11792
|
}
|
|
11974
11793
|
if (status >= 300)
|
|
11975
|
-
throw new WorkerHttpError(method,
|
|
11794
|
+
throw new WorkerHttpError(method, path19, status, body);
|
|
11976
11795
|
}
|
|
11977
11796
|
function isNetworkError(error) {
|
|
11978
11797
|
if (error instanceof WorkerNetworkError)
|
|
@@ -11984,23 +11803,23 @@ function isNetworkError(error) {
|
|
|
11984
11803
|
const code = error.code;
|
|
11985
11804
|
return code === "ECONNRESET" || code === "ECONNREFUSED" || code === "ETIMEDOUT" || code === "EPIPE" || error.name === "AbortError";
|
|
11986
11805
|
}
|
|
11987
|
-
function countsTowardWorkerSessionRebuild(
|
|
11988
|
-
if (
|
|
11806
|
+
function countsTowardWorkerSessionRebuild(path19) {
|
|
11807
|
+
if (path19 === "/api/v1/workers/register")
|
|
11989
11808
|
return false;
|
|
11990
|
-
if (/^\/api\/v1\/workers\/[^/]+\/heartbeat$/u.test(
|
|
11809
|
+
if (/^\/api\/v1\/workers\/[^/]+\/heartbeat$/u.test(path19))
|
|
11991
11810
|
return false;
|
|
11992
11811
|
return true;
|
|
11993
11812
|
}
|
|
11994
11813
|
|
|
11995
|
-
// .dist-releases/
|
|
11996
|
-
import { spawn as
|
|
11997
|
-
import { mkdirSync as mkdirSync4, mkdtempSync as
|
|
11998
|
-
import { tmpdir as
|
|
11814
|
+
// .dist-releases/1784809313131-4113078/src/worker/executor.js
|
|
11815
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
11816
|
+
import { mkdirSync as mkdirSync4, mkdtempSync as mkdtempSync2, readFileSync as readFileSync4, realpathSync, rmSync as rmSync2, statfsSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
11817
|
+
import { tmpdir as tmpdir2, loadavg } from "node:os";
|
|
11999
11818
|
import os2 from "node:os";
|
|
12000
|
-
import
|
|
11819
|
+
import path19 from "node:path";
|
|
12001
11820
|
import { TextDecoder } from "node:util";
|
|
12002
11821
|
|
|
12003
|
-
// .dist-releases/
|
|
11822
|
+
// .dist-releases/1784809313131-4113078/src/worker/async-queue.js
|
|
12004
11823
|
class AsyncByteQueue {
|
|
12005
11824
|
maxSize;
|
|
12006
11825
|
values = [];
|
|
@@ -12060,7 +11879,7 @@ class AsyncByteQueue {
|
|
|
12060
11879
|
}
|
|
12061
11880
|
}
|
|
12062
11881
|
|
|
12063
|
-
// .dist-releases/
|
|
11882
|
+
// .dist-releases/1784809313131-4113078/src/worker/http.js
|
|
12064
11883
|
import { request as httpRequest } from "node:http";
|
|
12065
11884
|
import { request as httpsRequest } from "node:https";
|
|
12066
11885
|
import { URLSearchParams as URLSearchParams2 } from "node:url";
|
|
@@ -12090,27 +11909,27 @@ class WorkerHttpClient {
|
|
|
12090
11909
|
throw new Error("token is required");
|
|
12091
11910
|
this.relayUrl = relayUrl.replace(/\/+$/u, "");
|
|
12092
11911
|
}
|
|
12093
|
-
async getJson(
|
|
11912
|
+
async getJson(path19, query, timeouts, options = {}) {
|
|
12094
11913
|
const suffix = new URLSearchParams2(query).toString();
|
|
12095
|
-
return this.requestJson("GET", suffix ? `${
|
|
11914
|
+
return this.requestJson("GET", suffix ? `${path19}?${suffix}` : path19, undefined, timeouts, options);
|
|
12096
11915
|
}
|
|
12097
|
-
async postJson(
|
|
12098
|
-
return this.requestJson("POST",
|
|
11916
|
+
async postJson(path19, value, timeouts) {
|
|
11917
|
+
return this.requestJson("POST", path19, { type: "json", value }, timeouts, {});
|
|
12099
11918
|
}
|
|
12100
|
-
async postBytes(
|
|
12101
|
-
const response = await this.request("POST",
|
|
12102
|
-
raiseForLeaseFencingOrStatus("POST",
|
|
11919
|
+
async postBytes(path19, body, headers, timeouts) {
|
|
11920
|
+
const response = await this.request("POST", path19, { type: "bytes", value: body }, timeouts, headers);
|
|
11921
|
+
raiseForLeaseFencingOrStatus("POST", path19, response.status, response.text);
|
|
12103
11922
|
}
|
|
12104
|
-
async requestJson(method,
|
|
12105
|
-
const response = await this.request(method,
|
|
12106
|
-
const errorPath = pathOnly(
|
|
11923
|
+
async requestJson(method, path19, body, timeouts, options) {
|
|
11924
|
+
const response = await this.request(method, path19, body, timeouts, {});
|
|
11925
|
+
const errorPath = pathOnly(path19);
|
|
12107
11926
|
if (options.leaseFencing === false && response.status >= 300)
|
|
12108
11927
|
throw new WorkerHttpError(method, errorPath, response.status, response.text);
|
|
12109
11928
|
raiseForLeaseFencingOrStatus(method, errorPath, response.status, response.text);
|
|
12110
11929
|
return parseJson(method, errorPath, response.text);
|
|
12111
11930
|
}
|
|
12112
|
-
async request(method,
|
|
12113
|
-
const url = new URL(`${this.relayUrl}${
|
|
11931
|
+
async request(method, path19, body, timeouts, extraHeaders) {
|
|
11932
|
+
const url = new URL(`${this.relayUrl}${path19}`);
|
|
12114
11933
|
const headers = this.headers(body, extraHeaders);
|
|
12115
11934
|
return sendRequest(method, url, body, headers, timeouts, this.signal);
|
|
12116
11935
|
}
|
|
@@ -12237,7 +12056,7 @@ function waitForRequestDrain(req) {
|
|
|
12237
12056
|
req.once("close", onClose);
|
|
12238
12057
|
});
|
|
12239
12058
|
}
|
|
12240
|
-
function parseJson(method,
|
|
12059
|
+
function parseJson(method, path19, text) {
|
|
12241
12060
|
try {
|
|
12242
12061
|
const parsed = JSON.parse(text);
|
|
12243
12062
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -12246,15 +12065,15 @@ function parseJson(method, path21, text) {
|
|
|
12246
12065
|
return parsed;
|
|
12247
12066
|
} catch (error) {
|
|
12248
12067
|
if (error instanceof SyntaxError)
|
|
12249
|
-
throw new WorkerNetworkError(method,
|
|
12068
|
+
throw new WorkerNetworkError(method, path19, "response JSON is invalid");
|
|
12250
12069
|
throw error;
|
|
12251
12070
|
}
|
|
12252
12071
|
}
|
|
12253
|
-
function pathOnly(
|
|
12254
|
-
return
|
|
12072
|
+
function pathOnly(path19) {
|
|
12073
|
+
return path19.split("?", 1)[0] || path19;
|
|
12255
12074
|
}
|
|
12256
12075
|
|
|
12257
|
-
// .dist-releases/
|
|
12076
|
+
// .dist-releases/1784809313131-4113078/src/worker/stream-upload.js
|
|
12258
12077
|
async function uploadStream(session, jobId, stream, leaseToken, chunks, workerId) {
|
|
12259
12078
|
if (!leaseToken.trim())
|
|
12260
12079
|
throw new Error("lease_token is required");
|
|
@@ -12264,7 +12083,7 @@ async function uploadStream(session, jobId, stream, leaseToken, chunks, workerId
|
|
|
12264
12083
|
await session.http.postBytes(`/api/v1/jobs/${encodeURIComponent(jobId)}/stream-upload?${query.toString()}`, chunks, { "X-Lease-Token": leaseToken }, UPLOAD_TIMEOUTS);
|
|
12265
12084
|
}
|
|
12266
12085
|
|
|
12267
|
-
// .dist-releases/
|
|
12086
|
+
// .dist-releases/1784809313131-4113078/src/worker/executor.js
|
|
12268
12087
|
class StreamingProcessFailure extends Error {
|
|
12269
12088
|
exitCode;
|
|
12270
12089
|
stdout;
|
|
@@ -12336,8 +12155,8 @@ function sandboxPath(workdir, requested) {
|
|
|
12336
12155
|
if (requested.startsWith("/") || parts.length === 0 || parts.includes("..")) {
|
|
12337
12156
|
throw new Error("path must be a relative path inside the worker sandbox");
|
|
12338
12157
|
}
|
|
12339
|
-
const root = realpathSync(
|
|
12340
|
-
const target =
|
|
12158
|
+
const root = realpathSync(path19.resolve(workdir));
|
|
12159
|
+
const target = path19.resolve(root, ...parts);
|
|
12341
12160
|
if (!isPathInside(root, target)) {
|
|
12342
12161
|
throw new Error("path escapes worker sandbox");
|
|
12343
12162
|
}
|
|
@@ -12477,7 +12296,7 @@ async function collectAndUpload(session, jobId, stream, pipe, leaseToken, worker
|
|
|
12477
12296
|
return collected.join("");
|
|
12478
12297
|
}
|
|
12479
12298
|
function spawnProcess(argv, cwd) {
|
|
12480
|
-
return
|
|
12299
|
+
return spawn5(argv[0], argv.slice(1), { cwd, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"] });
|
|
12481
12300
|
}
|
|
12482
12301
|
async function terminateProcess(proc) {
|
|
12483
12302
|
if (proc.pid === undefined)
|
|
@@ -12513,9 +12332,9 @@ function writeFileJob(workdir, spec, startedAt, started) {
|
|
|
12513
12332
|
if (typeof spec.content !== "string")
|
|
12514
12333
|
throw new Error("write_file spec.content must be a string");
|
|
12515
12334
|
const target = sandboxPath(workdir, String(spec.path ?? ""));
|
|
12516
|
-
mkdirSync4(
|
|
12335
|
+
mkdirSync4(path19.dirname(target), { recursive: true });
|
|
12517
12336
|
writeFileSync3(target, spec.content, "utf8");
|
|
12518
|
-
return output(0,
|
|
12337
|
+
return output(0, path19.relative(realpathSync(path19.resolve(workdir)), target), "", startedAt, started);
|
|
12519
12338
|
}
|
|
12520
12339
|
function readUtf8File(target) {
|
|
12521
12340
|
return decodeUtf8(readFileSync4(target));
|
|
@@ -12523,13 +12342,13 @@ function readUtf8File(target) {
|
|
|
12523
12342
|
async function applyDiff(workdir, spec, signal) {
|
|
12524
12343
|
if (typeof spec.diff_unified_text !== "string")
|
|
12525
12344
|
throw new Error("apply_diff spec.diff_unified_text must be a string");
|
|
12526
|
-
const dir =
|
|
12527
|
-
const patch =
|
|
12345
|
+
const dir = mkdtempSync2(path19.join(tmpdir2(), "sailorbridge-patch-"));
|
|
12346
|
+
const patch = path19.join(dir, "change.patch");
|
|
12528
12347
|
writeFileSync3(patch, spec.diff_unified_text, "utf8");
|
|
12529
12348
|
try {
|
|
12530
12349
|
return await runArgv(["patch", "-p1", "-i", patch], workdir, coerceJobTimeoutSeconds(spec) * 1000, signal);
|
|
12531
12350
|
} finally {
|
|
12532
|
-
|
|
12351
|
+
rmSync2(dir, { recursive: true, force: true });
|
|
12533
12352
|
}
|
|
12534
12353
|
}
|
|
12535
12354
|
async function executeCompose(spec, workdir, startedAt, started, signal) {
|
|
@@ -12764,24 +12583,24 @@ function resolveExistingTarget(target) {
|
|
|
12764
12583
|
let current = target;
|
|
12765
12584
|
while (true) {
|
|
12766
12585
|
try {
|
|
12767
|
-
return
|
|
12586
|
+
return path19.resolve(realpathSync(current), ...missingParts.reverse());
|
|
12768
12587
|
} catch (error) {
|
|
12769
12588
|
if (error.code !== "ENOENT")
|
|
12770
12589
|
throw error;
|
|
12771
|
-
const parent =
|
|
12590
|
+
const parent = path19.dirname(current);
|
|
12772
12591
|
if (parent === current)
|
|
12773
12592
|
throw error;
|
|
12774
|
-
missingParts.push(
|
|
12593
|
+
missingParts.push(path19.basename(current));
|
|
12775
12594
|
current = parent;
|
|
12776
12595
|
}
|
|
12777
12596
|
}
|
|
12778
12597
|
}
|
|
12779
12598
|
function isPathInside(root, target) {
|
|
12780
|
-
const relative =
|
|
12781
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
12599
|
+
const relative = path19.relative(root, target);
|
|
12600
|
+
return relative === "" || !relative.startsWith("..") && !path19.isAbsolute(relative);
|
|
12782
12601
|
}
|
|
12783
12602
|
function prepareWorkdir(workdir) {
|
|
12784
|
-
const resolved =
|
|
12603
|
+
const resolved = path19.resolve(workdir);
|
|
12785
12604
|
mkdirSync4(resolved, { recursive: true });
|
|
12786
12605
|
return resolved;
|
|
12787
12606
|
}
|
|
@@ -12796,7 +12615,7 @@ function errorMessage6(error) {
|
|
|
12796
12615
|
return error instanceof Error ? error.message : String(error);
|
|
12797
12616
|
}
|
|
12798
12617
|
|
|
12799
|
-
// .dist-releases/
|
|
12618
|
+
// .dist-releases/1784809313131-4113078/src/worker/client.js
|
|
12800
12619
|
var TOKEN_FILES = [
|
|
12801
12620
|
"~/.config/sailorbridge/token",
|
|
12802
12621
|
"/etc/sailorbridge/token"
|
|
@@ -13135,7 +12954,7 @@ ${JSON.stringify(result)}\r
|
|
|
13135
12954
|
`);
|
|
13136
12955
|
for (const file of attachments) {
|
|
13137
12956
|
yield Buffer.from(`--${multipartBoundary}\r
|
|
13138
|
-
Content-Disposition: form-data; name="files"; filename="${
|
|
12957
|
+
Content-Disposition: form-data; name="files"; filename="${path20.basename(file)}"\r
|
|
13139
12958
|
\r
|
|
13140
12959
|
`);
|
|
13141
12960
|
yield readFileSync5(file);
|
|
@@ -13169,7 +12988,7 @@ function parseFlags2(argv) {
|
|
|
13169
12988
|
return values;
|
|
13170
12989
|
}
|
|
13171
12990
|
function expandHome2(value) {
|
|
13172
|
-
return value === "~" || value.startsWith("~/") ?
|
|
12991
|
+
return value === "~" || value.startsWith("~/") ? path20.join(os3.homedir(), value.slice(2)) : value;
|
|
13173
12992
|
}
|
|
13174
12993
|
function _sleep(ms, signal) {
|
|
13175
12994
|
if (signal?.aborted)
|
|
@@ -13193,7 +13012,7 @@ function errorName2(error) {
|
|
|
13193
13012
|
function errorMessage7(error) {
|
|
13194
13013
|
return error instanceof Error ? error.message : String(error);
|
|
13195
13014
|
}
|
|
13196
|
-
// .dist-releases/
|
|
13015
|
+
// .dist-releases/1784809313131-4113078/src/host/worker-launcher.js
|
|
13197
13016
|
var DEFAULT_WORKER_READY_TIMEOUT_MS = 60000;
|
|
13198
13017
|
async function launchSupervisedWorker(input, deps = {}) {
|
|
13199
13018
|
const logger = input.logger ?? (() => {});
|
|
@@ -13276,21 +13095,21 @@ function _requireWorkerName(descriptor) {
|
|
|
13276
13095
|
return worker;
|
|
13277
13096
|
}
|
|
13278
13097
|
function _resolveWorkdir(workdir, homeDir) {
|
|
13279
|
-
return workdir === "~" || workdir.startsWith("~/") ?
|
|
13098
|
+
return workdir === "~" || workdir.startsWith("~/") ? path21.join(homeDir, workdir.slice(2)) : workdir;
|
|
13280
13099
|
}
|
|
13281
13100
|
function _assertWorkdir(workdir) {
|
|
13282
|
-
let
|
|
13101
|
+
let stat4;
|
|
13283
13102
|
try {
|
|
13284
|
-
|
|
13103
|
+
stat4 = statSync3(workdir);
|
|
13285
13104
|
} catch {
|
|
13286
13105
|
throw new Error(`worker workdir does not exist: ${workdir}`);
|
|
13287
13106
|
}
|
|
13288
|
-
if (!
|
|
13107
|
+
if (!stat4.isDirectory())
|
|
13289
13108
|
throw new Error(`worker workdir is not a directory: ${workdir}`);
|
|
13290
13109
|
return workdir;
|
|
13291
13110
|
}
|
|
13292
13111
|
|
|
13293
|
-
// .dist-releases/
|
|
13112
|
+
// .dist-releases/1784809313131-4113078/src/host/daemon.js
|
|
13294
13113
|
async function runHostDaemon(options) {
|
|
13295
13114
|
const logger = options.logger ?? (() => {});
|
|
13296
13115
|
const sleep3 = options.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
@@ -13299,7 +13118,6 @@ async function runHostDaemon(options) {
|
|
|
13299
13118
|
const workerRuntimes = new Map;
|
|
13300
13119
|
const cleanupLocks = new Map;
|
|
13301
13120
|
const startLocks = new Map;
|
|
13302
|
-
const memorySweepTargets = new Map;
|
|
13303
13121
|
const managedTargets = new Map;
|
|
13304
13122
|
const launch = options.launch ?? launchSupervisedAgent;
|
|
13305
13123
|
const launchWorker = options.launchWorker ?? launchSupervisedWorker;
|
|
@@ -13307,15 +13125,14 @@ async function runHostDaemon(options) {
|
|
|
13307
13125
|
const reclaim = options.reclaimOrphanWorkspaces ?? reclaimOrphanWorkspaces;
|
|
13308
13126
|
const identity = { captainId: options.captainId, hostId: options.hostId, displayName: options.displayName };
|
|
13309
13127
|
const redactSecrets = [...options.redactSecrets ?? []];
|
|
13310
|
-
const sweep = options.sweepAgentMemory ?? sweepAgentMemory;
|
|
13311
13128
|
const materializeManaged = options.materializeManagedFiles ?? materializeManagedFiles;
|
|
13312
13129
|
const now = options.now ?? (() => Date.now());
|
|
13313
|
-
const
|
|
13314
|
-
let
|
|
13130
|
+
const managedSyncIntervalMs = options.managedSyncIntervalMs ?? 6 * 60 * 60 * 1000;
|
|
13131
|
+
let lastManagedSyncAt = now();
|
|
13315
13132
|
const scratchSweep = options.sweepWorkspaceScratch ?? sweepWorkspaceScratch;
|
|
13316
13133
|
const scratchSweepIntervalMs = options.scratchSweepIntervalMs ?? 6 * 60 * 60 * 1000;
|
|
13317
13134
|
let lastScratchSweepAt = now();
|
|
13318
|
-
const reportRepoTips = options.reportRepoTips ??
|
|
13135
|
+
const reportRepoTips = options.reportRepoTips ?? createRepoTipReporter();
|
|
13319
13136
|
const repoTipReportIntervalMs = options.repoTipReportIntervalMs ?? 60 * 1000;
|
|
13320
13137
|
let lastRepoTipReportAt = now() - repoTipReportIntervalMs;
|
|
13321
13138
|
const reconcileIntervalMs = options.reconcileIntervalMs ?? 5 * 60 * 1000;
|
|
@@ -13360,9 +13177,7 @@ async function runHostDaemon(options) {
|
|
|
13360
13177
|
await waitForAgentCleanup(cleanupLocks, request.agent_name);
|
|
13361
13178
|
const spec = parseAgentStartSpec(request.spec);
|
|
13362
13179
|
const agentRelay = agentRelayClient(descriptor, options);
|
|
13363
|
-
const memoryTarget = memorySweepTarget(descriptor, spec.engine, options, agentRelay);
|
|
13364
13180
|
const managedTarget = managedMaterializationTarget(descriptor, spec.engine, options, agentRelay);
|
|
13365
|
-
await runMemorySweep(sweep, memoryTarget, "pre-start", logger, true);
|
|
13366
13181
|
await runManagedMaterialization(materializeManaged, managedTarget, "pre-start", logger, true);
|
|
13367
13182
|
await waitForAgentCleanup(cleanupLocks, request.agent_name);
|
|
13368
13183
|
let runtime = null;
|
|
@@ -13379,10 +13194,8 @@ async function runHostDaemon(options) {
|
|
|
13379
13194
|
return;
|
|
13380
13195
|
}
|
|
13381
13196
|
const cleanupTask = Promise.resolve().then(async () => {
|
|
13382
|
-
await runMemorySweep(sweep, memoryTarget, "runtime", logger, false);
|
|
13383
13197
|
await runManagedMaterialization(materializeManaged, managedTarget, "runtime", logger, false);
|
|
13384
13198
|
runtimes.delete(request.agent_name);
|
|
13385
|
-
memorySweepTargets.delete(request.agent_name);
|
|
13386
13199
|
managedTargets.delete(request.agent_name);
|
|
13387
13200
|
try {
|
|
13388
13201
|
await cleanup({
|
|
@@ -13426,7 +13239,6 @@ async function runHostDaemon(options) {
|
|
|
13426
13239
|
}, options.launchDeps);
|
|
13427
13240
|
previous = runtimes.get(request.agent_name);
|
|
13428
13241
|
runtimes.set(request.agent_name, runtime);
|
|
13429
|
-
memorySweepTargets.set(request.agent_name, memoryTarget);
|
|
13430
13242
|
managedTargets.set(request.agent_name, managedTarget);
|
|
13431
13243
|
} finally {
|
|
13432
13244
|
finishStart();
|
|
@@ -13438,14 +13250,6 @@ async function runHostDaemon(options) {
|
|
|
13438
13250
|
await previous.stop().catch(() => {});
|
|
13439
13251
|
};
|
|
13440
13252
|
const starter = async (request) => {
|
|
13441
|
-
if (request.request_kind === "repo_verification") {
|
|
13442
|
-
const gitRepoUrl = request.spec.git_repo_url;
|
|
13443
|
-
if (typeof gitRepoUrl !== "string" || !gitRepoUrl.trim()) {
|
|
13444
|
-
throw new Error("repo verification request requires spec.git_repo_url");
|
|
13445
|
-
}
|
|
13446
|
-
const verifyRepository = options.verifyRepository ?? verifyTeamRepository;
|
|
13447
|
-
return { ...await verifyRepository(gitRepoUrl, options.hostId) };
|
|
13448
|
-
}
|
|
13449
13253
|
if (request.request_kind === "worker_start")
|
|
13450
13254
|
return _startWorker(request);
|
|
13451
13255
|
await startAgent(request, await options.resolveCredential(request));
|
|
@@ -13462,7 +13266,9 @@ async function runHostDaemon(options) {
|
|
|
13462
13266
|
const _recoverDurableRuntimes = async () => {
|
|
13463
13267
|
if (!options.recoverRuntimes)
|
|
13464
13268
|
return;
|
|
13465
|
-
|
|
13269
|
+
const recoveries = await options.recoverRuntimes();
|
|
13270
|
+
const workers = recoveries.filter(({ request }) => request.request_kind === "worker_start").length;
|
|
13271
|
+
for (const recovery of recoveries) {
|
|
13466
13272
|
if (options.signal?.aborted)
|
|
13467
13273
|
return;
|
|
13468
13274
|
try {
|
|
@@ -13475,6 +13281,7 @@ async function runHostDaemon(options) {
|
|
|
13475
13281
|
});
|
|
13476
13282
|
}
|
|
13477
13283
|
}
|
|
13284
|
+
logger("host_runtime_recovery_completed", { agents: recoveries.length - workers, workers });
|
|
13478
13285
|
};
|
|
13479
13286
|
logger("host_daemon_start", { host_id: options.hostId, captain_id: options.captainId });
|
|
13480
13287
|
try {
|
|
@@ -13500,9 +13307,8 @@ async function runHostDaemon(options) {
|
|
|
13500
13307
|
logger("host_workspace_reconcile_failed", { error: errorMessage8(error) });
|
|
13501
13308
|
}
|
|
13502
13309
|
}
|
|
13503
|
-
if (now() -
|
|
13504
|
-
|
|
13505
|
-
await sweepRuntimeMemory(sweep, memorySweepTargets, logger);
|
|
13310
|
+
if (now() - lastManagedSyncAt >= managedSyncIntervalMs) {
|
|
13311
|
+
lastManagedSyncAt = now();
|
|
13506
13312
|
await syncRuntimeManagedMaterialization(materializeManaged, managedTargets, logger);
|
|
13507
13313
|
}
|
|
13508
13314
|
if (now() - lastScratchSweepAt >= scratchSweepIntervalMs) {
|
|
@@ -13530,7 +13336,6 @@ async function runHostDaemon(options) {
|
|
|
13530
13336
|
} finally {
|
|
13531
13337
|
logger("host_daemon_stopping", { agents: runtimes.size, workers: workerRuntimes.size });
|
|
13532
13338
|
try {
|
|
13533
|
-
await sweepRuntimeMemory(sweep, memorySweepTargets, logger);
|
|
13534
13339
|
await syncRuntimeManagedMaterialization(materializeManaged, managedTargets, logger);
|
|
13535
13340
|
} finally {
|
|
13536
13341
|
await Promise.allSettled([
|
|
@@ -13540,17 +13345,6 @@ async function runHostDaemon(options) {
|
|
|
13540
13345
|
}
|
|
13541
13346
|
}
|
|
13542
13347
|
}
|
|
13543
|
-
function memorySweepTarget(descriptor, engine, options, relay) {
|
|
13544
|
-
return {
|
|
13545
|
-
agentName: descriptor.agent_name,
|
|
13546
|
-
engine,
|
|
13547
|
-
captainId: descriptor.captain_id,
|
|
13548
|
-
teamId: descriptor.session,
|
|
13549
|
-
env: options.hostEnv ?? process.env,
|
|
13550
|
-
relay,
|
|
13551
|
-
state: createMemorySweepState()
|
|
13552
|
-
};
|
|
13553
|
-
}
|
|
13554
13348
|
function managedMaterializationTarget(descriptor, engine, options, relay) {
|
|
13555
13349
|
return {
|
|
13556
13350
|
agentName: descriptor.agent_name,
|
|
@@ -13569,11 +13363,6 @@ function agentRelayClient(descriptor, options) {
|
|
|
13569
13363
|
...options.launchDeps?.fetchImpl ? { fetchImpl: options.launchDeps.fetchImpl } : {}
|
|
13570
13364
|
});
|
|
13571
13365
|
}
|
|
13572
|
-
async function sweepRuntimeMemory(sweep, targets, logger) {
|
|
13573
|
-
for (const target of targets.values()) {
|
|
13574
|
-
await runMemorySweep(sweep, target, "runtime", logger, false);
|
|
13575
|
-
}
|
|
13576
|
-
}
|
|
13577
13366
|
async function sweepWorkspaceScratchRoots(scratchSweep, env, logger) {
|
|
13578
13367
|
if (!scratchSweepEnabled(env))
|
|
13579
13368
|
return;
|
|
@@ -13590,15 +13379,6 @@ async function syncRuntimeManagedMaterialization(materialize, targets, logger) {
|
|
|
13590
13379
|
await runManagedMaterialization(materialize, target, "runtime", logger, false);
|
|
13591
13380
|
}
|
|
13592
13381
|
}
|
|
13593
|
-
async function runMemorySweep(sweep, target, mode, logger, failFast) {
|
|
13594
|
-
try {
|
|
13595
|
-
await sweep({ ...target, mode, logger });
|
|
13596
|
-
} catch (error) {
|
|
13597
|
-
logger("host_memory_sweep_failed", { agent_name: target.agentName, mode, error: errorMessage8(error) });
|
|
13598
|
-
if (failFast)
|
|
13599
|
-
throw error;
|
|
13600
|
-
}
|
|
13601
|
-
}
|
|
13602
13382
|
async function runManagedMaterialization(materialize, target, mode, logger, failFast) {
|
|
13603
13383
|
try {
|
|
13604
13384
|
await materialize({ ...target, logger });
|
|
@@ -13678,7 +13458,7 @@ async function _drainOnce(options, identity, starter, logger, redactSecrets) {
|
|
|
13678
13458
|
return false;
|
|
13679
13459
|
}
|
|
13680
13460
|
}
|
|
13681
|
-
// .dist-releases/
|
|
13461
|
+
// .dist-releases/1784809313131-4113078/src/host/enrollment-redeem.js
|
|
13682
13462
|
var DEFAULT_NOT_FOUND_RETRIES = 3;
|
|
13683
13463
|
var NOT_FOUND_RETRY_DELAY_MS = 500;
|
|
13684
13464
|
function createEnrollmentRedeemer(options) {
|
|
@@ -13815,7 +13595,7 @@ function _role2(enrollment) {
|
|
|
13815
13595
|
}
|
|
13816
13596
|
return _string4(enrollment.roles[0], "roles[0]").trim();
|
|
13817
13597
|
}
|
|
13818
|
-
// .dist-releases/
|
|
13598
|
+
// .dist-releases/1784809313131-4113078/src/host/tutorial.js
|
|
13819
13599
|
function buildTutorialSteps(state) {
|
|
13820
13600
|
const paired = state.hasCredential;
|
|
13821
13601
|
return [
|
|
@@ -13886,7 +13666,7 @@ async function runTutorial(options) {
|
|
|
13886
13666
|
}
|
|
13887
13667
|
return steps;
|
|
13888
13668
|
}
|
|
13889
|
-
// .dist-releases/
|
|
13669
|
+
// .dist-releases/1784809313131-4113078/src/events.js
|
|
13890
13670
|
var EVENT_COMMANDS = new Set(["add", "list", "enable", "disable", "rm"]);
|
|
13891
13671
|
var EVENT_FLAGS = new Set(["at", "days", "message", "run-date", "session", "tag", "tz"]);
|
|
13892
13672
|
var PRODUCT_DAYS_MODES = new Set(["once", "daily", "weekday"]);
|
|
@@ -13976,7 +13756,7 @@ function _assertListArgs(args) {
|
|
|
13976
13756
|
}
|
|
13977
13757
|
}
|
|
13978
13758
|
|
|
13979
|
-
// .dist-releases/
|
|
13759
|
+
// .dist-releases/1784809313131-4113078/src/text-input.js
|
|
13980
13760
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
13981
13761
|
var _readUtf8File = async (file) => await readFile8(file, "utf8");
|
|
13982
13762
|
async function readTextInput(input) {
|
|
@@ -14010,17 +13790,17 @@ async function rejectUnusedTextInput(input, message) {
|
|
|
14010
13790
|
input.unref?.();
|
|
14011
13791
|
}
|
|
14012
13792
|
}
|
|
14013
|
-
async function readTextFile(
|
|
14014
|
-
return await readUtf8File2(
|
|
13793
|
+
async function readTextFile(path22, readUtf8File2 = _readUtf8File) {
|
|
13794
|
+
return await readUtf8File2(path22);
|
|
14015
13795
|
}
|
|
14016
|
-
async function readTextFileOrStdin(
|
|
14017
|
-
if (
|
|
13796
|
+
async function readTextFileOrStdin(path22, input, unusedInputMessage, readUtf8File2 = _readUtf8File) {
|
|
13797
|
+
if (path22 === "-")
|
|
14018
13798
|
return await readTextInput(input);
|
|
14019
13799
|
await rejectUnusedTextInput(input, unusedInputMessage);
|
|
14020
|
-
return await readTextFile(
|
|
13800
|
+
return await readTextFile(path22, readUtf8File2);
|
|
14021
13801
|
}
|
|
14022
13802
|
|
|
14023
|
-
// .dist-releases/
|
|
13803
|
+
// .dist-releases/1784809313131-4113078/src/ask.js
|
|
14024
13804
|
var ASK_FLAGS = new Set(["body-file", "option", "reason", "recommend", "session", "title"]);
|
|
14025
13805
|
async function runAskFromCli(client2, argv, config, input) {
|
|
14026
13806
|
const args = _parseAskArgs(argv);
|
|
@@ -14135,7 +13915,7 @@ function _singleAskValue(values, name) {
|
|
|
14135
13915
|
return entries[0];
|
|
14136
13916
|
}
|
|
14137
13917
|
|
|
14138
|
-
// .dist-releases/
|
|
13918
|
+
// .dist-releases/1784809313131-4113078/src/task.js
|
|
14139
13919
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
14140
13920
|
import { basename } from "node:path";
|
|
14141
13921
|
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"]);
|
|
@@ -14625,13 +14405,9 @@ function _taskListFooter(shown, returned, total, hasMore, cursor) {
|
|
|
14625
14405
|
return `Shown ${shown} of ${total}${local}${next}`;
|
|
14626
14406
|
}
|
|
14627
14407
|
|
|
14628
|
-
// .dist-releases/
|
|
14629
|
-
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
14408
|
+
// .dist-releases/1784809313131-4113078/src/team.js
|
|
14630
14409
|
var TEAM_BOOTSTRAP_ENGINES = new Set(["claude", "codex"]);
|
|
14631
14410
|
var SLOT_SPEC_RE = /^([^=\s]+)=([^:@\s]+):([^:@\s]+)$/;
|
|
14632
|
-
var REPO_WAIT_DEFAULT_SECONDS = 60;
|
|
14633
|
-
var REPO_WAIT_MAX_SECONDS = 300;
|
|
14634
|
-
var REPO_POLL_INTERVAL_MS = 250;
|
|
14635
14411
|
var TEAM_PLAIN_LIMIT = 20;
|
|
14636
14412
|
|
|
14637
14413
|
class TeamBootstrapError extends Error {
|
|
@@ -14642,20 +14418,9 @@ class TeamBootstrapError extends Error {
|
|
|
14642
14418
|
this.kind = kind;
|
|
14643
14419
|
}
|
|
14644
14420
|
}
|
|
14645
|
-
|
|
14646
|
-
class TeamRepoError extends Error {
|
|
14647
|
-
kind;
|
|
14648
|
-
constructor(kind, message) {
|
|
14649
|
-
super(message);
|
|
14650
|
-
this.name = "TeamRepoError";
|
|
14651
|
-
this.kind = kind;
|
|
14652
|
-
}
|
|
14653
|
-
}
|
|
14654
14421
|
async function runTeamFromCli(client2, argv, config, format) {
|
|
14655
|
-
if (argv[0] === "repo")
|
|
14656
|
-
return await _runTeamRepoFromCli(client2, argv.slice(1), config, format);
|
|
14657
14422
|
if (argv[0] !== "bootstrap")
|
|
14658
|
-
throw new TeamBootstrapError("usage", "team command must be bootstrap
|
|
14423
|
+
throw new TeamBootstrapError("usage", "team command must be bootstrap");
|
|
14659
14424
|
const captainId = config.captainId;
|
|
14660
14425
|
if (!captainId)
|
|
14661
14426
|
throw new TeamBootstrapError("usage", "team bootstrap requires SAILORBRIDGE_CAPTAIN_ID");
|
|
@@ -14668,173 +14433,6 @@ async function runTeamFromCli(client2, argv, config, format) {
|
|
|
14668
14433
|
const finalSlots = (await client2.getTeamAgentSlots(captainId, args.session)).agent_slots;
|
|
14669
14434
|
return format === "json" ? { agent_slots: finalSlots } : _auditFinalState(finalSlots);
|
|
14670
14435
|
}
|
|
14671
|
-
async function _runTeamRepoFromCli(client2, argv, config, format) {
|
|
14672
|
-
const captainId = config.captainId;
|
|
14673
|
-
if (!captainId)
|
|
14674
|
-
throw new TeamRepoError("usage", "team repo requires SAILORBRIDGE_CAPTAIN_ID");
|
|
14675
|
-
if (argv[0] === "status") {
|
|
14676
|
-
const repository = await client2.getTeamRepository(captainId, _parseRepoStatusArgs(argv.slice(1), config));
|
|
14677
|
-
return format === "json" ? repository : _formatRepository(repository);
|
|
14678
|
-
}
|
|
14679
|
-
if (argv[0] !== "set")
|
|
14680
|
-
throw new TeamRepoError("usage", "team repo command must be set or status");
|
|
14681
|
-
return await _setTeamRepository(client2, captainId, _parseRepoSetArgs(argv.slice(1), config), format);
|
|
14682
|
-
}
|
|
14683
|
-
function _parseRepoStatusArgs(tokens, config) {
|
|
14684
|
-
if (!tokens.length)
|
|
14685
|
-
return _requiredRepoSession(undefined, config);
|
|
14686
|
-
if (tokens.length !== 2 || tokens[0] !== "--session")
|
|
14687
|
-
throw new TeamRepoError("usage", "team repo status accepts only --session TEAM");
|
|
14688
|
-
return _requiredRepoSession(tokens[1], config);
|
|
14689
|
-
}
|
|
14690
|
-
function _parseRepoSetArgs(tokens, config) {
|
|
14691
|
-
const gitRepoUrl = tokens[0]?.trim();
|
|
14692
|
-
if (!gitRepoUrl || gitRepoUrl.startsWith("--"))
|
|
14693
|
-
throw new TeamRepoError("usage", "team repo set requires GIT_URL");
|
|
14694
|
-
if (!isAcceptedTeamGitRemote(gitRepoUrl))
|
|
14695
|
-
throw new TeamRepoError("usage", "GIT_URL must be an accepted git remote without embedded credentials");
|
|
14696
|
-
const flags = _parseRepoSetFlags(tokens.slice(1));
|
|
14697
|
-
return {
|
|
14698
|
-
gitRepoUrl,
|
|
14699
|
-
session: _requiredRepoSession(flags.session, config),
|
|
14700
|
-
wait: flags.wait,
|
|
14701
|
-
timeoutSeconds: flags.timeoutSeconds
|
|
14702
|
-
};
|
|
14703
|
-
}
|
|
14704
|
-
function _parseRepoSetFlags(tokens) {
|
|
14705
|
-
const flags = { wait: false, timeoutSet: false, timeoutSeconds: REPO_WAIT_DEFAULT_SECONDS };
|
|
14706
|
-
for (let index = 0;index < tokens.length; index += 1) {
|
|
14707
|
-
index += _applyRepoSetFlag(tokens, index, flags);
|
|
14708
|
-
}
|
|
14709
|
-
if (flags.timeoutSet && !flags.wait)
|
|
14710
|
-
throw new TeamRepoError("usage", "--timeout-sec requires --wait");
|
|
14711
|
-
return flags;
|
|
14712
|
-
}
|
|
14713
|
-
function _applyRepoSetFlag(tokens, index, flags) {
|
|
14714
|
-
const token = tokens[index];
|
|
14715
|
-
if (token === "--wait") {
|
|
14716
|
-
if (flags.wait)
|
|
14717
|
-
throw new TeamRepoError("usage", "--wait may only be provided once");
|
|
14718
|
-
flags.wait = true;
|
|
14719
|
-
return 0;
|
|
14720
|
-
}
|
|
14721
|
-
if (token === "--session") {
|
|
14722
|
-
flags.session = _singleRepoFlagValue(tokens, index + 1, token, flags.session);
|
|
14723
|
-
return 1;
|
|
14724
|
-
}
|
|
14725
|
-
if (token !== "--timeout-sec")
|
|
14726
|
-
throw new TeamRepoError("usage", `unknown team repo set flag: ${token}`);
|
|
14727
|
-
if (flags.timeoutSet)
|
|
14728
|
-
throw new TeamRepoError("usage", "--timeout-sec may only be provided once");
|
|
14729
|
-
flags.timeoutSet = true;
|
|
14730
|
-
flags.timeoutSeconds = _repoTimeoutSeconds(_singleRepoFlagValue(tokens, index + 1, token));
|
|
14731
|
-
return 1;
|
|
14732
|
-
}
|
|
14733
|
-
function _singleRepoFlagValue(tokens, index, flag, previous) {
|
|
14734
|
-
if (previous !== undefined)
|
|
14735
|
-
throw new TeamRepoError("usage", `${flag} may only be provided once`);
|
|
14736
|
-
const value = tokens[index]?.trim();
|
|
14737
|
-
if (!value || value.startsWith("--"))
|
|
14738
|
-
throw new TeamRepoError("usage", `${flag} requires a value`);
|
|
14739
|
-
return value;
|
|
14740
|
-
}
|
|
14741
|
-
function _repoTimeoutSeconds(value) {
|
|
14742
|
-
const seconds = Number(value);
|
|
14743
|
-
if (!Number.isInteger(seconds) || seconds < 1 || seconds > REPO_WAIT_MAX_SECONDS) {
|
|
14744
|
-
throw new TeamRepoError("usage", `--timeout-sec must be an integer from 1 to ${REPO_WAIT_MAX_SECONDS}`);
|
|
14745
|
-
}
|
|
14746
|
-
return seconds;
|
|
14747
|
-
}
|
|
14748
|
-
function _requiredRepoSession(value, config) {
|
|
14749
|
-
const session = (value ?? config.session)?.trim();
|
|
14750
|
-
if (!session)
|
|
14751
|
-
throw new TeamRepoError("usage", "team repo requires --session or SAILORBRIDGE_SESSION");
|
|
14752
|
-
return session;
|
|
14753
|
-
}
|
|
14754
|
-
async function _setTeamRepository(client2, captainId, args, format) {
|
|
14755
|
-
const hostId = _moderatorHostId((await client2.getTeamAgentSlots(captainId, args.session)).agent_slots);
|
|
14756
|
-
const pending = await client2.setTeamRepositoryState(captainId, args.session, _repoState(args.gitRepoUrl, "pending", null));
|
|
14757
|
-
const request = await _queueRepoVerification(client2, captainId, args, hostId);
|
|
14758
|
-
if (!args.wait) {
|
|
14759
|
-
if (format === "json")
|
|
14760
|
-
return { repository: pending, verification_request: request };
|
|
14761
|
-
return `${_formatRepository(pending)}
|
|
14762
|
-
Verification request: ${request.id}`;
|
|
14763
|
-
}
|
|
14764
|
-
const terminal = await _waitForRepoVerification(client2, captainId, args, request.id);
|
|
14765
|
-
const repository = await _persistRepoTerminal(client2, captainId, args, terminal);
|
|
14766
|
-
return format === "json" ? { repository, verification_request: terminal } : _formatRepository(repository);
|
|
14767
|
-
}
|
|
14768
|
-
function _moderatorHostId(slots) {
|
|
14769
|
-
const moderator = slots.find((slot) => slot.slot_id === "moderator" && slot.status === "materialized");
|
|
14770
|
-
if (!moderator?.host_id) {
|
|
14771
|
-
throw new TeamRepoError("moderator-unavailable", "team repo verification requires a materialized Moderator slot with a host");
|
|
14772
|
-
}
|
|
14773
|
-
return moderator.host_id;
|
|
14774
|
-
}
|
|
14775
|
-
async function _queueRepoVerification(client2, captainId, args, hostId) {
|
|
14776
|
-
try {
|
|
14777
|
-
return await client2.createRepoVerificationRequest(captainId, args.session, hostId, args.gitRepoUrl);
|
|
14778
|
-
} catch (error) {
|
|
14779
|
-
await client2.setTeamRepositoryState(captainId, args.session, _repoState(args.gitRepoUrl, "failed", "Repository verification could not be queued on the Moderator host"));
|
|
14780
|
-
throw error;
|
|
14781
|
-
}
|
|
14782
|
-
}
|
|
14783
|
-
async function _waitForRepoVerification(client2, captainId, args, requestId) {
|
|
14784
|
-
const deadline = Date.now() + args.timeoutSeconds * 1000;
|
|
14785
|
-
while (Date.now() < deadline) {
|
|
14786
|
-
let request;
|
|
14787
|
-
try {
|
|
14788
|
-
request = await client2.getAgentStartRequest(captainId, args.session, requestId, Math.max(1, deadline - Date.now()));
|
|
14789
|
-
} catch (error) {
|
|
14790
|
-
if (Date.now() < deadline)
|
|
14791
|
-
throw error;
|
|
14792
|
-
break;
|
|
14793
|
-
}
|
|
14794
|
-
if (request.status !== "queued" && request.status !== "claimed")
|
|
14795
|
-
return request;
|
|
14796
|
-
await sleep3(Math.min(REPO_POLL_INTERVAL_MS, Math.max(1, deadline - Date.now())));
|
|
14797
|
-
}
|
|
14798
|
-
throw new TeamRepoError("verification-timeout", `repository verification timed out after ${args.timeoutSeconds} second${args.timeoutSeconds === 1 ? "" : "s"}`);
|
|
14799
|
-
}
|
|
14800
|
-
async function _persistRepoTerminal(client2, captainId, args, request) {
|
|
14801
|
-
if (request.status === "started") {
|
|
14802
|
-
try {
|
|
14803
|
-
const reason2 = _verifiedRepoReason(request);
|
|
14804
|
-
return await client2.setTeamRepositoryState(captainId, args.session, _repoState(args.gitRepoUrl, "verified", reason2));
|
|
14805
|
-
} catch (error) {
|
|
14806
|
-
const reason2 = error instanceof Error ? error.message : "Moderator host returned an invalid repository verification result";
|
|
14807
|
-
await client2.setTeamRepositoryState(captainId, args.session, _repoState(args.gitRepoUrl, "failed", reason2));
|
|
14808
|
-
throw error;
|
|
14809
|
-
}
|
|
14810
|
-
}
|
|
14811
|
-
const reason = request.error?.trim() || `Repository verification request ended as ${request.status}`;
|
|
14812
|
-
await client2.setTeamRepositoryState(captainId, args.session, _repoState(args.gitRepoUrl, "failed", reason));
|
|
14813
|
-
throw new TeamRepoError("verification-failed", reason);
|
|
14814
|
-
}
|
|
14815
|
-
function _verifiedRepoReason(request) {
|
|
14816
|
-
const result = request.result;
|
|
14817
|
-
if (result?.verified !== true || typeof result.reason !== "string" || !result.reason.trim()) {
|
|
14818
|
-
throw new TeamRepoError("verification-failed", "Moderator host returned an invalid repository verification result");
|
|
14819
|
-
}
|
|
14820
|
-
if (typeof result.verified_at !== "string" || !result.verified_at || typeof result.verification_host_id !== "string" || !result.verification_host_id) {
|
|
14821
|
-
throw new TeamRepoError("verification-failed", "Moderator host returned an incomplete repository verification result");
|
|
14822
|
-
}
|
|
14823
|
-
if (!Number.isFinite(Date.parse(result.verified_at)) || result.verification_host_id !== request.host_id) {
|
|
14824
|
-
throw new TeamRepoError("verification-failed", "Moderator host returned an inconsistent repository verification result");
|
|
14825
|
-
}
|
|
14826
|
-
return result.reason.trim();
|
|
14827
|
-
}
|
|
14828
|
-
function _repoState(gitRepoUrl, status, reason) {
|
|
14829
|
-
return { git_repo_url: gitRepoUrl, git_repo_verification_status: status, git_repo_verification_reason: reason };
|
|
14830
|
-
}
|
|
14831
|
-
function _formatRepository(repository) {
|
|
14832
|
-
const url = repository.git_repo_url ?? "not configured";
|
|
14833
|
-
const reason = repository.git_repo_verification_reason ?? "-";
|
|
14834
|
-
return `Repository: ${url}
|
|
14835
|
-
Status: ${repository.git_repo_verification_status}
|
|
14836
|
-
Reason: ${reason}`;
|
|
14837
|
-
}
|
|
14838
14436
|
function _parseBootstrapArgs(tokens, config) {
|
|
14839
14437
|
const values = {};
|
|
14840
14438
|
for (let index = 0;index < tokens.length; index += 1) {
|
|
@@ -14962,11 +14560,11 @@ function _slotTable(slots) {
|
|
|
14962
14560
|
Shown ${shown.length} of ${slots.length}${omitted ? `; ${omitted} omitted (use --format json)` : ""}`;
|
|
14963
14561
|
}
|
|
14964
14562
|
|
|
14965
|
-
// .dist-releases/
|
|
14563
|
+
// .dist-releases/1784809313131-4113078/src/memory.js
|
|
14966
14564
|
var VALUE_FLAGS = new Set(["file", "source"]);
|
|
14967
|
-
var
|
|
14968
|
-
async function
|
|
14969
|
-
const args =
|
|
14565
|
+
var MEMORY_SEARCH_PLAIN_LIMIT = 20;
|
|
14566
|
+
async function runMemoryFromCli(client2, argv, config, input, format) {
|
|
14567
|
+
const args = _parseMemoryCliArgs(argv);
|
|
14970
14568
|
const captainId = _requireConfig(config.captainId, "SAILORBRIDGE_CAPTAIN_ID");
|
|
14971
14569
|
const teamId = _requireConfig(config.session, "SAILORBRIDGE_SESSION");
|
|
14972
14570
|
if (args.command === "set")
|
|
@@ -14977,14 +14575,14 @@ async function runRagFromCli(client2, argv, config, input, format) {
|
|
|
14977
14575
|
return await _currentMemory(client2, captainId, teamId, args, format);
|
|
14978
14576
|
if (args.command === "pin" || args.command === "unpin")
|
|
14979
14577
|
return await _pinMemory(client2, captainId, teamId, args, format);
|
|
14980
|
-
|
|
14578
|
+
_assertMemoryShape(args, "memory index", 0, []);
|
|
14981
14579
|
const result = await client2.getRagMemoryIndex(captainId, teamId);
|
|
14982
14580
|
return format === "json" ? result : result.text;
|
|
14983
14581
|
}
|
|
14984
|
-
function
|
|
14582
|
+
function _parseMemoryCliArgs(argv) {
|
|
14985
14583
|
const command = argv[0];
|
|
14986
14584
|
if (command !== "set" && command !== "search" && command !== "current" && command !== "index" && command !== "pin" && command !== "unpin") {
|
|
14987
|
-
throw new Error("
|
|
14585
|
+
throw new Error("memory command must be set, search, current, index, pin, or unpin");
|
|
14988
14586
|
}
|
|
14989
14587
|
const positionals = [];
|
|
14990
14588
|
const flags = {};
|
|
@@ -14993,14 +14591,14 @@ function _parseRagArgs(argv) {
|
|
|
14993
14591
|
if (!token.startsWith("--"))
|
|
14994
14592
|
positionals.push(token);
|
|
14995
14593
|
else
|
|
14996
|
-
|
|
14594
|
+
_addMemoryFlag(flags, token, VALUE_FLAGS.has(token.slice(2)) ? argv[++index] : undefined);
|
|
14997
14595
|
}
|
|
14998
14596
|
return { command, positionals, flags };
|
|
14999
14597
|
}
|
|
15000
|
-
function
|
|
14598
|
+
function _addMemoryFlag(flags, token, value) {
|
|
15001
14599
|
const name = token.slice(2);
|
|
15002
14600
|
if (name !== "stdin" && !VALUE_FLAGS.has(name))
|
|
15003
|
-
throw new Error(`unknown
|
|
14601
|
+
throw new Error(`unknown memory flag: ${token}`);
|
|
15004
14602
|
if (flags[name] !== undefined)
|
|
15005
14603
|
throw new Error(`${token} may only be provided once`);
|
|
15006
14604
|
if (name === "stdin")
|
|
@@ -15011,7 +14609,7 @@ function _addRagFlag(flags, token, value) {
|
|
|
15011
14609
|
flags[name] = value;
|
|
15012
14610
|
}
|
|
15013
14611
|
async function _setMemory(client2, captainId, teamId, args, input, format) {
|
|
15014
|
-
|
|
14612
|
+
_assertMemoryShape(args, "memory set", 1, ["stdin", "file", "source"]);
|
|
15015
14613
|
const key = args.positionals[0];
|
|
15016
14614
|
const source = _requiredFlag(args, "source");
|
|
15017
14615
|
const value = await _payload(args, input);
|
|
@@ -15024,26 +14622,26 @@ async function _setMemory(client2, captainId, teamId, args, input, format) {
|
|
|
15024
14622
|
return `${result.card.key} v${result.card.version ?? 1} ${result.card.status ?? "active"}${suffix}`;
|
|
15025
14623
|
}
|
|
15026
14624
|
async function _searchMemory(client2, captainId, teamId, args, input, format) {
|
|
15027
|
-
|
|
14625
|
+
_assertMemoryShape(args, "memory search", 1, []);
|
|
15028
14626
|
if (args.positionals[0] !== undefined)
|
|
15029
|
-
await rejectUnusedTextInput(input, "
|
|
14627
|
+
await rejectUnusedTextInput(input, "memory search received stdin that its query argument does not consume; omit the query argument to read stdin");
|
|
15030
14628
|
const text = args.positionals[0] ?? await readTextInput(input);
|
|
15031
14629
|
if (!text.trim())
|
|
15032
|
-
throw new Error("
|
|
14630
|
+
throw new Error("memory search requires a query argument or stdin");
|
|
15033
14631
|
const result = await client2.searchRag(captainId, teamId, text);
|
|
15034
14632
|
if (format === "json")
|
|
15035
14633
|
return result;
|
|
15036
14634
|
const { cards } = result;
|
|
15037
14635
|
if (!cards.length)
|
|
15038
14636
|
return "No matching memory cards.";
|
|
15039
|
-
const shown = cards.slice(0,
|
|
14637
|
+
const shown = cards.slice(0, MEMORY_SEARCH_PLAIN_LIMIT);
|
|
15040
14638
|
const lines = shown.map((card) => `${card.key} ${card.score} ${_summary(card.value)}`);
|
|
15041
14639
|
const omitted = cards.length - shown.length;
|
|
15042
14640
|
return [...lines, `Shown ${shown.length} of ${cards.length}${omitted ? `; ${omitted} omitted (use --format json)` : ""}`].join(`
|
|
15043
14641
|
`);
|
|
15044
14642
|
}
|
|
15045
14643
|
async function _currentMemory(client2, captainId, teamId, args, format) {
|
|
15046
|
-
|
|
14644
|
+
_assertMemoryShape(args, "memory current", 1, []);
|
|
15047
14645
|
const card = await client2.getRagCurrentCard(captainId, teamId, args.positionals[0]);
|
|
15048
14646
|
if (format === "json")
|
|
15049
14647
|
return card;
|
|
@@ -15053,14 +14651,14 @@ ${card.value}`;
|
|
|
15053
14651
|
}
|
|
15054
14652
|
async function _pinMemory(client2, captainId, teamId, args, format) {
|
|
15055
14653
|
const pinned = args.command === "pin";
|
|
15056
|
-
|
|
14654
|
+
_assertMemoryShape(args, `memory ${args.command}`, 1, []);
|
|
15057
14655
|
const card = await client2.setRagCardPin(captainId, teamId, args.positionals[0], pinned);
|
|
15058
14656
|
if (format === "json")
|
|
15059
14657
|
return card;
|
|
15060
14658
|
return `${card.key} v${card.version ?? 1} ${pinned ? "pinned" : "unpinned"}`;
|
|
15061
14659
|
}
|
|
15062
|
-
function
|
|
15063
|
-
const requiresKey = name !== "
|
|
14660
|
+
function _assertMemoryShape(args, name, maxPositionals, allowedFlags) {
|
|
14661
|
+
const requiresKey = name !== "memory search" && name !== "memory index";
|
|
15064
14662
|
if (args.positionals.length > maxPositionals) {
|
|
15065
14663
|
const requirement = maxPositionals ? requiresKey ? "requires one key" : "accepts at most one positional argument" : "requires no positional arguments";
|
|
15066
14664
|
throw new Error(`${name} ${requirement}`);
|
|
@@ -15074,12 +14672,12 @@ async function _payload(args, input) {
|
|
|
15074
14672
|
const fromStdin = args.flags.stdin === true;
|
|
15075
14673
|
const file = args.flags.file;
|
|
15076
14674
|
if (fromStdin === (typeof file === "string"))
|
|
15077
|
-
throw new Error("
|
|
14675
|
+
throw new Error("memory set requires exactly one of --stdin or --file");
|
|
15078
14676
|
if (!fromStdin)
|
|
15079
|
-
await rejectUnusedTextInput(input, "
|
|
14677
|
+
await rejectUnusedTextInput(input, "memory set received stdin that --file does not consume; use --stdin");
|
|
15080
14678
|
const value = fromStdin ? await readTextInput(input) : await readTextFile(file);
|
|
15081
14679
|
if (!value.trim())
|
|
15082
|
-
throw new Error("
|
|
14680
|
+
throw new Error("memory set payload must not be empty");
|
|
15083
14681
|
return value;
|
|
15084
14682
|
}
|
|
15085
14683
|
function _requiredFlag(args, name) {
|
|
@@ -15090,14 +14688,14 @@ function _requiredFlag(args, name) {
|
|
|
15090
14688
|
}
|
|
15091
14689
|
function _requireConfig(value, name) {
|
|
15092
14690
|
if (!value?.trim())
|
|
15093
|
-
throw new Error(`
|
|
14691
|
+
throw new Error(`memory requires ${name}`);
|
|
15094
14692
|
return value;
|
|
15095
14693
|
}
|
|
15096
14694
|
function _summary(value) {
|
|
15097
14695
|
return value.replace(/\s+/gu, " ").trim().slice(0, 180);
|
|
15098
14696
|
}
|
|
15099
14697
|
|
|
15100
|
-
// .dist-releases/
|
|
14698
|
+
// .dist-releases/1784809313131-4113078/src/mailbox-send.js
|
|
15101
14699
|
var SEND_FLAGS = new Set(["body-file", "commit", "session", "tag", "task-id", "task-version", "to-agents", "to-roles", "to-host"]);
|
|
15102
14700
|
function parseMailboxSendArgs(argv) {
|
|
15103
14701
|
const parsed = argsFromValues(parseFlagValues(argv));
|
|
@@ -15196,7 +14794,7 @@ function splitList(value) {
|
|
|
15196
14794
|
return list?.length ? list : undefined;
|
|
15197
14795
|
}
|
|
15198
14796
|
|
|
15199
|
-
// .dist-releases/
|
|
14797
|
+
// .dist-releases/1784809313131-4113078/src/reply.js
|
|
15200
14798
|
var REPLY_FLAGS = new Set(["agent", "body-file", "in-reply-to", "session"]);
|
|
15201
14799
|
async function sendReplyFromCli(client2, argv, config, io) {
|
|
15202
14800
|
const args = _parseReplyArgs(argv);
|
|
@@ -15253,7 +14851,7 @@ function _requiredReplyValue(values, name) {
|
|
|
15253
14851
|
return value;
|
|
15254
14852
|
}
|
|
15255
14853
|
|
|
15256
|
-
// .dist-releases/
|
|
14854
|
+
// .dist-releases/1784809313131-4113078/src/create.js
|
|
15257
14855
|
var CREATE_ENGINES = new Set(["claude", "codex"]);
|
|
15258
14856
|
var DEFAULT_ENGINE = "claude";
|
|
15259
14857
|
var WORKSPACE_PLAIN_LIMIT = 20;
|
|
@@ -15305,9 +14903,9 @@ async function _startTeamSlots(deps, ctx, team, hostId, workspaceRoot, engine, s
|
|
|
15305
14903
|
}
|
|
15306
14904
|
return requests;
|
|
15307
14905
|
}
|
|
15308
|
-
async function _postConsoleJson(deps, ctx,
|
|
14906
|
+
async function _postConsoleJson(deps, ctx, path22, body) {
|
|
15309
14907
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
15310
|
-
const response = await fetchImpl(`${ctx.apiUrl.replace(/\/$/, "")}${
|
|
14908
|
+
const response = await fetchImpl(`${ctx.apiUrl.replace(/\/$/, "")}${path22}`, {
|
|
15311
14909
|
method: "POST",
|
|
15312
14910
|
headers: { Authorization: `Bearer ${ctx.token}`, "Content-Type": "application/json" },
|
|
15313
14911
|
body: JSON.stringify(body)
|
|
@@ -15545,7 +15143,7 @@ function _workerPlain(hostId, workdir, result) {
|
|
|
15545
15143
|
`);
|
|
15546
15144
|
}
|
|
15547
15145
|
|
|
15548
|
-
// .dist-releases/
|
|
15146
|
+
// .dist-releases/1784809313131-4113078/src/cli.js
|
|
15549
15147
|
var FORMATTED_COMMANDS = new Set([
|
|
15550
15148
|
"ask",
|
|
15551
15149
|
"create",
|
|
@@ -15554,7 +15152,7 @@ var FORMATTED_COMMANDS = new Set([
|
|
|
15554
15152
|
"host",
|
|
15555
15153
|
"login",
|
|
15556
15154
|
"mailbox",
|
|
15557
|
-
"
|
|
15155
|
+
"memory",
|
|
15558
15156
|
"reply",
|
|
15559
15157
|
"task",
|
|
15560
15158
|
"team",
|
|
@@ -15664,8 +15262,8 @@ async function main(argv) {
|
|
|
15664
15262
|
writeOutput(process.stdout, await runTeamFromCli(client2, argv.slice(1), config, output2.format), output2.format);
|
|
15665
15263
|
return;
|
|
15666
15264
|
}
|
|
15667
|
-
if (command === "
|
|
15668
|
-
writeOutput(process.stdout, await
|
|
15265
|
+
if (command === "memory") {
|
|
15266
|
+
writeOutput(process.stdout, await runMemoryFromCli(client2, argv.slice(1), config, process.stdin, output2.format), output2.format);
|
|
15669
15267
|
return;
|
|
15670
15268
|
}
|
|
15671
15269
|
if (command === "enrollment") {
|
|
@@ -15690,7 +15288,7 @@ var KNOWN_COMMANDS = new Set([
|
|
|
15690
15288
|
"host",
|
|
15691
15289
|
"login",
|
|
15692
15290
|
"mailbox",
|
|
15693
|
-
"
|
|
15291
|
+
"memory",
|
|
15694
15292
|
"refresh",
|
|
15695
15293
|
"reply",
|
|
15696
15294
|
"supervise",
|
|
@@ -15707,7 +15305,7 @@ var SUBCOMMANDS = {
|
|
|
15707
15305
|
event: new Set(["add", "disable", "enable", "list", "rm"]),
|
|
15708
15306
|
host: new Set([...HOST_RELAY_SUBCOMMANDS, "run", "service", "start-request", "statusline", "workspace"]),
|
|
15709
15307
|
mailbox: new Set(["ack", "claim", "peek", "send"]),
|
|
15710
|
-
|
|
15308
|
+
memory: new Set(["current", "index", "pin", "search", "set", "unpin"]),
|
|
15711
15309
|
supervise: new Set,
|
|
15712
15310
|
task: new Set([
|
|
15713
15311
|
"activate",
|
|
@@ -15723,7 +15321,7 @@ var SUBCOMMANDS = {
|
|
|
15723
15321
|
"ready",
|
|
15724
15322
|
"unpark"
|
|
15725
15323
|
]),
|
|
15726
|
-
team: new Set(["bootstrap"
|
|
15324
|
+
team: new Set(["bootstrap"]),
|
|
15727
15325
|
worker: new Set(["serve"])
|
|
15728
15326
|
};
|
|
15729
15327
|
function _assertKnownCommand(command, subcommand) {
|
|
@@ -15740,7 +15338,7 @@ function _assertKnownCommand(command, subcommand) {
|
|
|
15740
15338
|
}
|
|
15741
15339
|
async function _rejectUnsupportedCliInput(command, args, input) {
|
|
15742
15340
|
const subcommand = args[0];
|
|
15743
|
-
const acceptsInput = command === "reply" || command === "host" && subcommand === "statusline" || command === "mailbox" && subcommand === "send" || command === "task" && subcommand === "create" || command === "ask" && subcommand !== "list" && subcommand !== "get" && subcommand !== "status" || command === "
|
|
15341
|
+
const acceptsInput = command === "reply" || command === "host" && subcommand === "statusline" || command === "mailbox" && subcommand === "send" || command === "task" && subcommand === "create" || command === "ask" && subcommand !== "list" && subcommand !== "get" && subcommand !== "status" || command === "memory" && (subcommand === "set" || subcommand === "search");
|
|
15744
15342
|
if (!acceptsInput)
|
|
15745
15343
|
await rejectUnusedTextInput(input, `${command}${subcommand ? ` ${subcommand}` : ""} does not accept stdin`);
|
|
15746
15344
|
}
|
|
@@ -15986,6 +15584,7 @@ async function supervise(client2, argv, config) {
|
|
|
15986
15584
|
agentName: parsed.agentName,
|
|
15987
15585
|
engine: parsed.cli,
|
|
15988
15586
|
hostEnv: process.env,
|
|
15587
|
+
teamMemoryEntitled: await resolveTeamMemoryEntitlement(client2, config.captainId, config.session),
|
|
15989
15588
|
descriptor: {
|
|
15990
15589
|
key_id: "direct-supervise",
|
|
15991
15590
|
relay_url: config.relayUrl,
|
|
@@ -16211,14 +15810,12 @@ function _usageText() {
|
|
|
16211
15810
|
sailorbridge create worker --name N --concurrency N [--host H] [--workspace PATH] [--session S]
|
|
16212
15811
|
starts a worker on a paired online host. All create commands: [--api-url URL] [--credentials-path PATH] [--format plain|json]
|
|
16213
15812
|
sailorbridge team bootstrap --template classic3 --slot SLOT=HOST:claude|codex [--slot ...] [--session S]
|
|
16214
|
-
|
|
16215
|
-
|
|
16216
|
-
sail
|
|
16217
|
-
sail
|
|
16218
|
-
sail
|
|
16219
|
-
sail
|
|
16220
|
-
sail rag unpin KEY (moderator/captain only)
|
|
16221
|
-
sail rag index
|
|
15813
|
+
sail memory set KEY (--stdin | --file PATH) --source SOURCE
|
|
15814
|
+
sail memory search [QUERY]
|
|
15815
|
+
sail memory current KEY
|
|
15816
|
+
sail memory pin KEY (moderator/captain only)
|
|
15817
|
+
sail memory unpin KEY (moderator/captain only)
|
|
15818
|
+
sail memory index
|
|
16222
15819
|
sailorbridge enrollment --session S --agent A --roles operator [--host H] [--name N]
|
|
16223
15820
|
sailorbridge host list|register|heartbeat [--host-id H] [--display-name N]
|
|
16224
15821
|
sailorbridge host consume --once --dry-run-start [--host-id H] [--display-name N]
|
|
@@ -16272,5 +15869,5 @@ function _looksLikeNetworkFailure(message) {
|
|
|
16272
15869
|
return /fetch failed|network|ECONN(?:REFUSED|RESET)|ENOTFOUND|ETIMEDOUT/iu.test(message);
|
|
16273
15870
|
}
|
|
16274
15871
|
|
|
16275
|
-
//# debugId=
|
|
15872
|
+
//# debugId=D1FAA8446085164F64756E2164756E21
|
|
16276
15873
|
//# sourceMappingURL=cli.js.map
|