@dev.sail.money/sailor 1.3.0-206 → 1.3.0-208
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/package.json +1 -1
- package/packages/cli/dist/index.cjs +402 -324
- package/packages/cli/dist/server.cjs +7 -8
- package/packages/sdk/dist/intelligence.d.ts +1 -1
- package/packages/sdk/dist/intelligence.js +1 -1
- package/packages/sdk/dist/keyring.d.ts +0 -6
- package/packages/sdk/dist/keyring.d.ts.map +1 -1
- package/packages/sdk/dist/keyring.js +1 -8
- package/packages/sdk/dist/keyring.js.map +1 -1
- package/packages/ui/dist/assets/{add-Dj4_n773.js → add-CfTRVkh-.js} +1 -1
- package/packages/ui/dist/assets/{all-wallets-BaFysN1G.js → all-wallets-VZChJwJf.js} +1 -1
- package/packages/ui/dist/assets/{app-store-DOc31zzY.js → app-store-CuFK1xBJ.js} +1 -1
- package/packages/ui/dist/assets/{apple-BvrvOkPH.js → apple-DETqVk_I.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-E1AfjXOT.js → arrow-bottom-CnNYsZfo.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-circle-sou7Vo1V.js → arrow-bottom-circle-DZwJF3UO.js} +1 -1
- package/packages/ui/dist/assets/{arrow-left-wk3G9Ywf.js → arrow-left-CBnisTAa.js} +1 -1
- package/packages/ui/dist/assets/{arrow-right-_a703_Pw.js → arrow-right-DA3Y1Yzf.js} +1 -1
- package/packages/ui/dist/assets/{arrow-top-txyg3R3e.js → arrow-top-e8-FE_fo.js} +1 -1
- package/packages/ui/dist/assets/{bank-BB1kd0NJ.js → bank-DdwromQn.js} +1 -1
- package/packages/ui/dist/assets/{basic-D0dy7nIZ.js → basic-DLYER2un.js} +1 -1
- package/packages/ui/dist/assets/{browser-BwHLhsTn.js → browser-BJNrv4Zj.js} +1 -1
- package/packages/ui/dist/assets/{card-DRC6HmPF.js → card-DB6j4DSk.js} +1 -1
- package/packages/ui/dist/assets/{ccip-Dq6KeJQl.js → ccip-Dy_s323Y.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-TbAAQGjd.js → checkmark-Db9oicko.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-bold-4723vJ0-.js → checkmark-bold-D9MgGHxv.js} +1 -1
- package/packages/ui/dist/assets/{chevron-bottom-DtLoBRe9.js → chevron-bottom-IGUDJRKN.js} +1 -1
- package/packages/ui/dist/assets/{chevron-left-BtydsF9j.js → chevron-left-CWpfP-rw.js} +1 -1
- package/packages/ui/dist/assets/{chevron-right-BbkU_Kf8.js → chevron-right-BejY0vtE.js} +1 -1
- package/packages/ui/dist/assets/{chevron-top-BWf-sN-F.js → chevron-top-BaUN0LGF.js} +1 -1
- package/packages/ui/dist/assets/{chrome-store-CVFxc5H2.js → chrome-store-fox1tIqs.js} +1 -1
- package/packages/ui/dist/assets/{clock-B4hJww1X.js → clock-DlqB4Ehi.js} +1 -1
- package/packages/ui/dist/assets/{close-Ci93jqGe.js → close-03e52feP.js} +1 -1
- package/packages/ui/dist/assets/{coinPlaceholder-cRv_xDgC.js → coinPlaceholder-BO3nv4hx.js} +1 -1
- package/packages/ui/dist/assets/{compass-_sZZPtm6.js → compass-CIqPRE0k.js} +1 -1
- package/packages/ui/dist/assets/{copy-DLaiLK0n.js → copy-D5cJBwZq.js} +1 -1
- package/packages/ui/dist/assets/{core-YssZmpJa.js → core-COelOg3-.js} +3 -3
- package/packages/ui/dist/assets/cursor-CRb7R3u1.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-CzXQbB2p.js → cursor-transparent-Cvbiq9Br.js} +1 -1
- package/packages/ui/dist/assets/{desktop-BiqQI1Ss.js → desktop-Dp2wtF3n.js} +1 -1
- package/packages/ui/dist/assets/{disconnect-DYu7YCzu.js → disconnect-Dx_IGM73.js} +1 -1
- package/packages/ui/dist/assets/{discord-C-ife-UZ.js → discord-Cxryn14a.js} +1 -1
- package/packages/ui/dist/assets/{etherscan-Dq7ac-p9.js → etherscan-D8aNXWCx.js} +1 -1
- package/packages/ui/dist/assets/{events-BhTGLk8n.js → events-DR6OOHz2.js} +1 -1
- package/packages/ui/dist/assets/{exclamation-triangle-BcOdRdbp.js → exclamation-triangle-BBCaPLj1.js} +1 -1
- package/packages/ui/dist/assets/{extension-DmJLIidM.js → extension-bACRNBl5.js} +1 -1
- package/packages/ui/dist/assets/{external-link-HNjp7-Po.js → external-link-BZRqHo3q.js} +1 -1
- package/packages/ui/dist/assets/{facebook-BrSvHNyw.js → facebook-TAdUitg4.js} +1 -1
- package/packages/ui/dist/assets/{fallback-Ubz80uXP.js → fallback-DGiwrboN.js} +1 -1
- package/packages/ui/dist/assets/{farcaster-BsjltM6k.js → farcaster-YzdobBfR.js} +1 -1
- package/packages/ui/dist/assets/{filters-B4yQbYZP.js → filters-CT-xLEoI.js} +1 -1
- package/packages/ui/dist/assets/{github-CFq82Dds.js → github-DxPBbmEL.js} +1 -1
- package/packages/ui/dist/assets/{google-DwZutf4a.js → google-B0TMgFhK.js} +1 -1
- package/packages/ui/dist/assets/{help-circle-CyA_8KQg.js → help-circle-Be6sRPTw.js} +1 -1
- package/packages/ui/dist/assets/{id-jyZYn4LJ.js → id-Dem_akbE.js} +1 -1
- package/packages/ui/dist/assets/{image-Zv0yoBcH.js → image-CszBzFVG.js} +1 -1
- package/packages/ui/dist/assets/{index-BxRaYDiX.js → index-B0FDHAiK.js} +1 -1
- package/packages/ui/dist/assets/{index-67NncC_u.js → index-C2n9XvGG.js} +3 -3
- package/packages/ui/dist/assets/{index-_DkPx8RN.js → index-Cb5eBfrN.js} +77 -77
- package/packages/ui/dist/assets/{index-BY8A6EK8.js → index-DAawBKd2.js} +1 -1
- package/packages/ui/dist/assets/{index-CeGppB9s.js → index-DXqj6oYp.js} +1 -1
- package/packages/ui/dist/assets/{index-BdG43zCl.js → index-homh6mWC.js} +1 -1
- package/packages/ui/dist/assets/{index.es-C8EklrJY.js → index.es-DJgl78dj.js} +4 -4
- package/packages/ui/dist/assets/{info-BwGEOdmB.js → info-BimGN4NK.js} +1 -1
- package/packages/ui/dist/assets/{info-circle-BPCcX-Iq.js → info-circle-lnKEJu2R.js} +1 -1
- package/packages/ui/dist/assets/{lightbulb-BRwr4IaC.js → lightbulb-DS1vEMce.js} +1 -1
- package/packages/ui/dist/assets/{mail-D-k_Vhe4.js → mail-DoS3Wibk.js} +1 -1
- package/packages/ui/dist/assets/{metamask-sdk-AcOgwGrj.js → metamask-sdk-CMIU3BwW.js} +1 -1
- package/packages/ui/dist/assets/{mobile-B1ok9PfY.js → mobile-B09Cs95_.js} +1 -1
- package/packages/ui/dist/assets/{more-DeMTMLWs.js → more-CLBZT8WI.js} +1 -1
- package/packages/ui/dist/assets/{network-placeholder-J0Rc1I89.js → network-placeholder-C45Cp8rY.js} +1 -1
- package/packages/ui/dist/assets/{nftPlaceholder-dXGrzzoa.js → nftPlaceholder-CAVclL3u.js} +1 -1
- package/packages/ui/dist/assets/{off-CS0f77lw.js → off-CwE8HoZ0.js} +1 -1
- package/packages/ui/dist/assets/{parseSignature-DJ16fHC4.js → parseSignature-kmMNHYjl.js} +1 -1
- package/packages/ui/dist/assets/{play-store-DmK8UaNC.js → play-store-DiFF_6n4.js} +1 -1
- package/packages/ui/dist/assets/{plus-CSGSnoCh.js → plus-aygpl_pZ.js} +1 -1
- package/packages/ui/dist/assets/{qr-code-BJMH0xmM.js → qr-code-DpIS4fFK.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-D5XP5VgJ.js → recycle-horizontal-Qk2N74JE.js} +1 -1
- package/packages/ui/dist/assets/{refresh-MLX3Rdp6.js → refresh-sWRq9Vnt.js} +1 -1
- package/packages/ui/dist/assets/{reown-logo-CVoDFQbM.js → reown-logo-YQxBa9i9.js} +1 -1
- package/packages/ui/dist/assets/{search-BDJDyvjC.js → search-Bt6BSPcC.js} +1 -1
- package/packages/ui/dist/assets/{secp256k1-BWh3B02k.js → secp256k1-BUh3OoFd.js} +1 -1
- package/packages/ui/dist/assets/{send-BOq2svx_.js → send-ym-Fn17O.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontal-ByjLi_-_.js → swapHorizontal-fBE2gnqc.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalBold-fmCp_4AE.js → swapHorizontalBold-CekQ22FJ.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalMedium-D6dFseYw.js → swapHorizontalMedium-B9BI9ovU.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-B2V3m4ha.js → swapHorizontalRoundedBold-DOC75mBH.js} +1 -1
- package/packages/ui/dist/assets/{swapVertical-DVmCsmeT.js → swapVertical-CSQAPH0z.js} +1 -1
- package/packages/ui/dist/assets/{telegram-Bv8JRbMM.js → telegram-BPjzFxKU.js} +1 -1
- package/packages/ui/dist/assets/{three-dots-YYDJ18z6.js → three-dots-DP6hdXH8.js} +1 -1
- package/packages/ui/dist/assets/{twitch-B2_Jy-Ft.js → twitch-CgHMd-f3.js} +1 -1
- package/packages/ui/dist/assets/{twitterIcon-pKQzPQRt.js → twitterIcon-BrR8ynXm.js} +1 -1
- package/packages/ui/dist/assets/{verify-Bty2jIav.js → verify-D35D7Wtv.js} +1 -1
- package/packages/ui/dist/assets/{verify-filled-CKz2fuKl.js → verify-filled-DCP5CT59.js} +1 -1
- package/packages/ui/dist/assets/{w3m-modal-Wg1mtmVM.js → w3m-modal-B-ZptWk0.js} +1 -1
- package/packages/ui/dist/assets/{wallet-DslzC8rD.js → wallet-Cnb4dkr3.js} +1 -1
- package/packages/ui/dist/assets/{wallet-placeholder-Dyw8jJ56.js → wallet-placeholder-CCzk0PqU.js} +1 -1
- package/packages/ui/dist/assets/{walletconnect-DZBfbgp4.js → walletconnect-f6tQZYRi.js} +1 -1
- package/packages/ui/dist/assets/{warning-circle-D7NPDx4k.js → warning-circle-zxMagvfx.js} +1 -1
- package/packages/ui/dist/assets/{x-DRR_9FNs.js → x-D0nEGO1G.js} +1 -1
- package/packages/ui/dist/index.html +1 -1
- package/packages/ui/dist/assets/cursor-B_xyJnjj.js +0 -3
|
@@ -22626,7 +22626,7 @@ var require_websocket = __commonJS({
|
|
|
22626
22626
|
var EventEmitter = require("events");
|
|
22627
22627
|
var https = require("https");
|
|
22628
22628
|
var http2 = require("http");
|
|
22629
|
-
var
|
|
22629
|
+
var net3 = require("net");
|
|
22630
22630
|
var tls = require("tls");
|
|
22631
22631
|
var { randomBytes: randomBytes4, createHash } = require("crypto");
|
|
22632
22632
|
var { Duplex, Readable } = require("stream");
|
|
@@ -23360,12 +23360,12 @@ var require_websocket = __commonJS({
|
|
|
23360
23360
|
}
|
|
23361
23361
|
function netConnect(options) {
|
|
23362
23362
|
options.path = options.socketPath;
|
|
23363
|
-
return
|
|
23363
|
+
return net3.connect(options);
|
|
23364
23364
|
}
|
|
23365
23365
|
function tlsConnect(options) {
|
|
23366
23366
|
options.path = void 0;
|
|
23367
23367
|
if (!options.servername && options.servername !== "") {
|
|
23368
|
-
options.servername =
|
|
23368
|
+
options.servername = net3.isIP(options.host) ? "" : options.host;
|
|
23369
23369
|
}
|
|
23370
23370
|
return tls.connect(options);
|
|
23371
23371
|
}
|
|
@@ -33756,7 +33756,7 @@ var require_websocket2 = __commonJS({
|
|
|
33756
33756
|
var EventEmitter = require("events");
|
|
33757
33757
|
var https = require("https");
|
|
33758
33758
|
var http2 = require("http");
|
|
33759
|
-
var
|
|
33759
|
+
var net3 = require("net");
|
|
33760
33760
|
var tls = require("tls");
|
|
33761
33761
|
var { randomBytes: randomBytes4, createHash } = require("crypto");
|
|
33762
33762
|
var { Duplex, Readable } = require("stream");
|
|
@@ -34500,12 +34500,12 @@ var require_websocket2 = __commonJS({
|
|
|
34500
34500
|
}
|
|
34501
34501
|
function netConnect(options) {
|
|
34502
34502
|
options.path = options.socketPath;
|
|
34503
|
-
return
|
|
34503
|
+
return net3.connect(options);
|
|
34504
34504
|
}
|
|
34505
34505
|
function tlsConnect(options) {
|
|
34506
34506
|
options.path = void 0;
|
|
34507
34507
|
if (!options.servername && options.servername !== "") {
|
|
34508
|
-
options.servername =
|
|
34508
|
+
options.servername = net3.isIP(options.host) ? "" : options.host;
|
|
34509
34509
|
}
|
|
34510
34510
|
return tls.connect(options);
|
|
34511
34511
|
}
|
|
@@ -37445,18 +37445,12 @@ var LocalKeyring = class _LocalKeyring {
|
|
|
37445
37445
|
this.account = account2;
|
|
37446
37446
|
this.address = account2.address;
|
|
37447
37447
|
this.privateKey = options.privateKey;
|
|
37448
|
-
} else
|
|
37448
|
+
} else {
|
|
37449
37449
|
const account2 = mnemonicToAccount(options.mnemonic, options.derivationPath ? { path: options.derivationPath } : void 0);
|
|
37450
37450
|
this.account = account2;
|
|
37451
37451
|
this.address = account2.address;
|
|
37452
|
-
} else {
|
|
37453
|
-
throw new Error("keystore decryption not implemented \u2014 use type: 'privateKey' or type: 'mnemonic' instead");
|
|
37454
37452
|
}
|
|
37455
37453
|
}
|
|
37456
|
-
/** Returns a lightweight signer stub for read-only contexts where the key is not available. */
|
|
37457
|
-
static fromAddress(address) {
|
|
37458
|
-
return { address };
|
|
37459
|
-
}
|
|
37460
37454
|
/** Generates a brand-new keyring backed by a random private key. */
|
|
37461
37455
|
static generate() {
|
|
37462
37456
|
return new _LocalKeyring({ type: "privateKey", privateKey: generatePrivateKey() });
|
|
@@ -38497,15 +38491,58 @@ function upsertAccountInList(account2, name, baseSailDir = sailDir()) {
|
|
|
38497
38491
|
}
|
|
38498
38492
|
|
|
38499
38493
|
// src/signing/client.ts
|
|
38500
|
-
var
|
|
38494
|
+
var import_node_fs7 = require("node:fs");
|
|
38501
38495
|
var import_node_path5 = require("node:path");
|
|
38502
38496
|
|
|
38503
38497
|
// src/signing/server.ts
|
|
38504
38498
|
var import_node_crypto2 = require("node:crypto");
|
|
38505
|
-
var
|
|
38499
|
+
var import_node_fs6 = require("node:fs");
|
|
38506
38500
|
var import_node_http = require("node:http");
|
|
38507
|
-
var import_node_net = require("node:net");
|
|
38508
38501
|
var import_node_path4 = require("node:path");
|
|
38502
|
+
|
|
38503
|
+
// src/lib/process.ts
|
|
38504
|
+
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
38505
|
+
var import_node_net = __toESM(require("node:net"), 1);
|
|
38506
|
+
function agentPidPath(chainId) {
|
|
38507
|
+
return chainId != null ? sailPath(`agent-${chainId}.pid`) : sailPath("agent.pid");
|
|
38508
|
+
}
|
|
38509
|
+
function writeAgentPid(chainId) {
|
|
38510
|
+
import_node_fs5.default.mkdirSync(sailPath(), { recursive: true });
|
|
38511
|
+
import_node_fs5.default.writeFileSync(agentPidPath(chainId), `${process.pid}
|
|
38512
|
+
`);
|
|
38513
|
+
}
|
|
38514
|
+
function clearAgentPid(chainId) {
|
|
38515
|
+
try {
|
|
38516
|
+
import_node_fs5.default.rmSync(agentPidPath(chainId));
|
|
38517
|
+
} catch {
|
|
38518
|
+
}
|
|
38519
|
+
}
|
|
38520
|
+
function readAgentPid(chainId) {
|
|
38521
|
+
try {
|
|
38522
|
+
const pid = Number.parseInt(import_node_fs5.default.readFileSync(agentPidPath(chainId), "utf-8").trim(), 10);
|
|
38523
|
+
return Number.isNaN(pid) ? null : pid;
|
|
38524
|
+
} catch {
|
|
38525
|
+
return null;
|
|
38526
|
+
}
|
|
38527
|
+
}
|
|
38528
|
+
function isProcessAlive(pid) {
|
|
38529
|
+
try {
|
|
38530
|
+
process.kill(pid, 0);
|
|
38531
|
+
return true;
|
|
38532
|
+
} catch (err) {
|
|
38533
|
+
return err.code === "EPERM";
|
|
38534
|
+
}
|
|
38535
|
+
}
|
|
38536
|
+
function findFreePort(from14) {
|
|
38537
|
+
return new Promise((resolve3, reject) => {
|
|
38538
|
+
const server = import_node_net.default.createServer();
|
|
38539
|
+
server.unref();
|
|
38540
|
+
server.on("error", () => findFreePort(from14 + 1).then(resolve3, reject));
|
|
38541
|
+
server.listen(from14, "127.0.0.1", () => server.close(() => resolve3(from14)));
|
|
38542
|
+
});
|
|
38543
|
+
}
|
|
38544
|
+
|
|
38545
|
+
// src/signing/server.ts
|
|
38509
38546
|
init_esm2();
|
|
38510
38547
|
|
|
38511
38548
|
// ../../node_modules/.pnpm/ws@8.21.0_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/wrapper.mjs
|
|
@@ -38545,7 +38582,7 @@ function findUiDist() {
|
|
|
38545
38582
|
(0, import_node_path4.join)(process.cwd(), "..", "ui", "dist")
|
|
38546
38583
|
];
|
|
38547
38584
|
for (const c of candidates) {
|
|
38548
|
-
if ((0,
|
|
38585
|
+
if ((0, import_node_fs6.existsSync)((0, import_node_path4.join)(c, "index.html"))) return c;
|
|
38549
38586
|
}
|
|
38550
38587
|
return null;
|
|
38551
38588
|
}
|
|
@@ -38593,7 +38630,7 @@ var SigningServer = class {
|
|
|
38593
38630
|
return this.httpServer?.listening ?? false;
|
|
38594
38631
|
}
|
|
38595
38632
|
async start() {
|
|
38596
|
-
this.port = await
|
|
38633
|
+
this.port = await findFreePort(this.port);
|
|
38597
38634
|
this._url = `http://localhost:${this.port}`;
|
|
38598
38635
|
this.requestSecret = (0, import_node_crypto2.randomBytes)(16).toString("hex");
|
|
38599
38636
|
const http2 = (0, import_node_http.createServer)((req, res) => this.handleHttp(req, res));
|
|
@@ -38773,13 +38810,13 @@ var SigningServer = class {
|
|
|
38773
38810
|
const path11 = this.sailFile("config.json");
|
|
38774
38811
|
let config = {};
|
|
38775
38812
|
try {
|
|
38776
|
-
config = JSON.parse((0,
|
|
38813
|
+
config = JSON.parse((0, import_node_fs6.readFileSync)(path11, "utf-8"));
|
|
38777
38814
|
} catch {
|
|
38778
38815
|
}
|
|
38779
38816
|
if (Number(config.chainId) === Number(chainId)) return;
|
|
38780
38817
|
config.chainId = Number(chainId);
|
|
38781
|
-
(0,
|
|
38782
|
-
(0,
|
|
38818
|
+
(0, import_node_fs6.mkdirSync)(this.sailFile(), { recursive: true });
|
|
38819
|
+
(0, import_node_fs6.writeFileSync)(path11, `${JSON.stringify(config, null, 2)}
|
|
38783
38820
|
`);
|
|
38784
38821
|
} catch {
|
|
38785
38822
|
}
|
|
@@ -38787,7 +38824,7 @@ var SigningServer = class {
|
|
|
38787
38824
|
/** Stream a JSON file back, or a fallback body when it is missing/invalid. */
|
|
38788
38825
|
sendJsonFile(res, filePath, fallback2) {
|
|
38789
38826
|
try {
|
|
38790
|
-
const raw = (0,
|
|
38827
|
+
const raw = (0, import_node_fs6.readFileSync)(filePath, "utf-8");
|
|
38791
38828
|
JSON.parse(raw);
|
|
38792
38829
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
38793
38830
|
res.end(raw);
|
|
@@ -38854,8 +38891,8 @@ var SigningServer = class {
|
|
|
38854
38891
|
};
|
|
38855
38892
|
const baseSailDir = this.sailFile();
|
|
38856
38893
|
upsertAccountInList(record, void 0, baseSailDir);
|
|
38857
|
-
(0,
|
|
38858
|
-
(0,
|
|
38894
|
+
(0, import_node_fs6.mkdirSync)(baseSailDir, { recursive: true });
|
|
38895
|
+
(0, import_node_fs6.writeFileSync)(this.sailFile("account.json"), `${JSON.stringify(record, null, 2)}
|
|
38859
38896
|
`);
|
|
38860
38897
|
this.syncConfigChainId(chainId);
|
|
38861
38898
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -38870,12 +38907,12 @@ var SigningServer = class {
|
|
|
38870
38907
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
38871
38908
|
let active = null;
|
|
38872
38909
|
try {
|
|
38873
|
-
active = JSON.parse((0,
|
|
38910
|
+
active = JSON.parse((0, import_node_fs6.readFileSync)(this.sailFile("account.json"), "utf-8")).safe;
|
|
38874
38911
|
} catch {
|
|
38875
38912
|
}
|
|
38876
38913
|
try {
|
|
38877
38914
|
const accounts = JSON.parse(
|
|
38878
|
-
(0,
|
|
38915
|
+
(0, import_node_fs6.readFileSync)(this.sailFile("state", "accounts.json"), "utf-8")
|
|
38879
38916
|
);
|
|
38880
38917
|
res.end(
|
|
38881
38918
|
JSON.stringify(
|
|
@@ -38888,7 +38925,7 @@ var SigningServer = class {
|
|
|
38888
38925
|
} catch {
|
|
38889
38926
|
try {
|
|
38890
38927
|
const a = JSON.parse(
|
|
38891
|
-
(0,
|
|
38928
|
+
(0, import_node_fs6.readFileSync)(this.sailFile("account.json"), "utf-8")
|
|
38892
38929
|
);
|
|
38893
38930
|
res.end(JSON.stringify([{ ...a, name: "My SMA", active: true, addedAt: null }]));
|
|
38894
38931
|
} catch {
|
|
@@ -39011,16 +39048,16 @@ var SigningServer = class {
|
|
|
39011
39048
|
res.end();
|
|
39012
39049
|
return;
|
|
39013
39050
|
}
|
|
39014
|
-
if ((0,
|
|
39051
|
+
if ((0, import_node_fs6.existsSync)(filePath)) {
|
|
39015
39052
|
const mime = MIME[(0, import_node_path4.extname)(filePath)] ?? "application/octet-stream";
|
|
39016
39053
|
res.writeHead(200, { "Content-Type": mime });
|
|
39017
|
-
res.end((0,
|
|
39054
|
+
res.end((0, import_node_fs6.readFileSync)(filePath));
|
|
39018
39055
|
return;
|
|
39019
39056
|
}
|
|
39020
39057
|
const indexHtml = (0, import_node_path4.join)(this.uiDist, "index.html");
|
|
39021
|
-
if ((0,
|
|
39058
|
+
if ((0, import_node_fs6.existsSync)(indexHtml)) {
|
|
39022
39059
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
39023
|
-
res.end((0,
|
|
39060
|
+
res.end((0, import_node_fs6.readFileSync)(indexHtml));
|
|
39024
39061
|
return;
|
|
39025
39062
|
}
|
|
39026
39063
|
}
|
|
@@ -39107,15 +39144,15 @@ var SigningServer = class {
|
|
|
39107
39144
|
}
|
|
39108
39145
|
writeRuntimeState() {
|
|
39109
39146
|
const path11 = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
|
|
39110
|
-
if ((0,
|
|
39147
|
+
if ((0, import_node_fs6.existsSync)(path11)) {
|
|
39111
39148
|
try {
|
|
39112
|
-
const existing = JSON.parse((0,
|
|
39113
|
-
if (existing.pid != null && existing.pid !== process.pid &&
|
|
39149
|
+
const existing = JSON.parse((0, import_node_fs6.readFileSync)(path11, "utf8"));
|
|
39150
|
+
if (existing.pid != null && existing.pid !== process.pid && isProcessAlive(existing.pid)) return;
|
|
39114
39151
|
} catch {
|
|
39115
39152
|
}
|
|
39116
39153
|
}
|
|
39117
|
-
if (!(0,
|
|
39118
|
-
(0,
|
|
39154
|
+
if (!(0, import_node_fs6.existsSync)(this.runtimeDir)) (0, import_node_fs6.mkdirSync)(this.runtimeDir, { recursive: true });
|
|
39155
|
+
(0, import_node_fs6.writeFileSync)(
|
|
39119
39156
|
(0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE),
|
|
39120
39157
|
JSON.stringify(
|
|
39121
39158
|
{
|
|
@@ -39134,43 +39171,25 @@ var SigningServer = class {
|
|
|
39134
39171
|
removeRuntimeState() {
|
|
39135
39172
|
const path11 = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
|
|
39136
39173
|
try {
|
|
39137
|
-
if (!(0,
|
|
39138
|
-
const state = JSON.parse((0,
|
|
39174
|
+
if (!(0, import_node_fs6.existsSync)(path11)) return;
|
|
39175
|
+
const state = JSON.parse((0, import_node_fs6.readFileSync)(path11, "utf8"));
|
|
39139
39176
|
if (state.pid != null && state.pid !== process.pid) return;
|
|
39140
|
-
(0,
|
|
39177
|
+
(0, import_node_fs6.unlinkSync)(path11);
|
|
39141
39178
|
} catch {
|
|
39142
39179
|
}
|
|
39143
39180
|
}
|
|
39144
39181
|
};
|
|
39145
|
-
function pidAlive(pid) {
|
|
39146
|
-
try {
|
|
39147
|
-
process.kill(pid, 0);
|
|
39148
|
-
return true;
|
|
39149
|
-
} catch (err) {
|
|
39150
|
-
return err.code === "EPERM";
|
|
39151
|
-
}
|
|
39152
|
-
}
|
|
39153
39182
|
function reapStaleRuntimeState(projectRoot = process.cwd()) {
|
|
39154
39183
|
const path11 = (0, import_node_path4.join)(projectRoot, RUNTIME_SUBDIR, SERVER_STATE_FILE);
|
|
39155
39184
|
try {
|
|
39156
|
-
if (!(0,
|
|
39157
|
-
const state = JSON.parse((0,
|
|
39158
|
-
if (state.pid != null && state.pid !== process.pid && !
|
|
39159
|
-
(0,
|
|
39185
|
+
if (!(0, import_node_fs6.existsSync)(path11)) return;
|
|
39186
|
+
const state = JSON.parse((0, import_node_fs6.readFileSync)(path11, "utf8"));
|
|
39187
|
+
if (state.pid != null && state.pid !== process.pid && !isProcessAlive(state.pid)) {
|
|
39188
|
+
(0, import_node_fs6.unlinkSync)(path11);
|
|
39160
39189
|
}
|
|
39161
39190
|
} catch {
|
|
39162
39191
|
}
|
|
39163
39192
|
}
|
|
39164
|
-
async function findAvailablePort(startPort) {
|
|
39165
|
-
return new Promise((res) => {
|
|
39166
|
-
const probe = (0, import_node_net.createServer)();
|
|
39167
|
-
probe.listen(startPort, "127.0.0.1", () => {
|
|
39168
|
-
const addr = probe.address();
|
|
39169
|
-
probe.close(() => res(addr.port));
|
|
39170
|
-
});
|
|
39171
|
-
probe.on("error", () => res(findAvailablePort(startPort + 1)));
|
|
39172
|
-
});
|
|
39173
|
-
}
|
|
39174
39193
|
|
|
39175
39194
|
// src/signing/client.ts
|
|
39176
39195
|
var RUNTIME_SERVER_FILE = (0, import_node_path5.join)(".sail", "runtime", "server.json");
|
|
@@ -39252,14 +39271,14 @@ function toLoopbackIPv4(url) {
|
|
|
39252
39271
|
}
|
|
39253
39272
|
function readRuntimeServerState(projectRoot) {
|
|
39254
39273
|
const file = (0, import_node_path5.join)(projectRoot, RUNTIME_SERVER_FILE);
|
|
39255
|
-
if (!(0,
|
|
39274
|
+
if (!(0, import_node_fs7.existsSync)(file)) return null;
|
|
39256
39275
|
try {
|
|
39257
|
-
return JSON.parse((0,
|
|
39276
|
+
return JSON.parse((0, import_node_fs7.readFileSync)(file, "utf8"));
|
|
39258
39277
|
} catch {
|
|
39259
39278
|
return null;
|
|
39260
39279
|
}
|
|
39261
39280
|
}
|
|
39262
|
-
function signingPageUrl(
|
|
39281
|
+
function signingPageUrl(dashboardPort) {
|
|
39263
39282
|
return `http://localhost:${dashboardPort}/#/station`;
|
|
39264
39283
|
}
|
|
39265
39284
|
async function discoverDaemon(projectRoot = process.cwd()) {
|
|
@@ -39530,7 +39549,7 @@ Deploying SMA on ${getChainById(targetChainId).name} (chain ${targetChainId})\u2
|
|
|
39530
39549
|
const channel = await createSigningChannel(process.cwd());
|
|
39531
39550
|
try {
|
|
39532
39551
|
await channel.start();
|
|
39533
|
-
const stationUrl = signingPageUrl(
|
|
39552
|
+
const stationUrl = signingPageUrl(projectPort(process.cwd()));
|
|
39534
39553
|
if (json) {
|
|
39535
39554
|
console.log(
|
|
39536
39555
|
JSON.stringify(
|
|
@@ -39667,100 +39686,6 @@ function emit(json, human, payload) {
|
|
|
39667
39686
|
|
|
39668
39687
|
// src/lib/project.ts
|
|
39669
39688
|
init_esm2();
|
|
39670
|
-
|
|
39671
|
-
// src/lib/keys.ts
|
|
39672
|
-
init_esm2();
|
|
39673
|
-
var ROLES = ["manager", "permissionSigner"];
|
|
39674
|
-
function normalizeRole(input) {
|
|
39675
|
-
const n = input.trim().toLowerCase().replace(/[-_\s]/g, "");
|
|
39676
|
-
if (n === "manager" || n === "mgr" || n === "m" || n === "agent" || n === "agentwallet") {
|
|
39677
|
-
return "manager";
|
|
39678
|
-
}
|
|
39679
|
-
if (n === "permissionsigner" || n === "signer" || n === "ps" || n === "permission" || n === "mandatesigner" || n === "mandate") {
|
|
39680
|
-
return "permissionSigner";
|
|
39681
|
-
}
|
|
39682
|
-
return null;
|
|
39683
|
-
}
|
|
39684
|
-
function roleLabel(role) {
|
|
39685
|
-
return role === "manager" ? "agent wallet" : "mandate signer";
|
|
39686
|
-
}
|
|
39687
|
-
function safeHex(safe) {
|
|
39688
|
-
return safe.toLowerCase().replace(/^0x/, "").replace(/[^0-9a-f]/g, "");
|
|
39689
|
-
}
|
|
39690
|
-
function keyPath(role, safe) {
|
|
39691
|
-
if (safe) {
|
|
39692
|
-
return sailPath("keys", `${role}-0x${safeHex(safe)}.json`);
|
|
39693
|
-
}
|
|
39694
|
-
return sailPath("keys", `${role}.json`);
|
|
39695
|
-
}
|
|
39696
|
-
function legacyKeyPath(role, safe) {
|
|
39697
|
-
return sailPath("keys", `${role}-${safeHex(safe)}.json`);
|
|
39698
|
-
}
|
|
39699
|
-
function resolveKeyPath(role, safe) {
|
|
39700
|
-
if (safe) {
|
|
39701
|
-
const perSma = keyPath(role, safe);
|
|
39702
|
-
if (fileExists(perSma)) return perSma;
|
|
39703
|
-
const legacy = legacyKeyPath(role, safe);
|
|
39704
|
-
if (fileExists(legacy)) return legacy;
|
|
39705
|
-
}
|
|
39706
|
-
return keyPath(role);
|
|
39707
|
-
}
|
|
39708
|
-
function keyExists(role, safe) {
|
|
39709
|
-
return fileExists(resolveKeyPath(role, safe));
|
|
39710
|
-
}
|
|
39711
|
-
async function loadKeyring(role, safe) {
|
|
39712
|
-
const keystore = readJsonFile(resolveKeyPath(role, safe));
|
|
39713
|
-
if (!keystore) {
|
|
39714
|
-
throw new Error(
|
|
39715
|
-
`No ${roleLabel(role)} found.
|
|
39716
|
-
Run "sailor keys generate" and choose "${roleLabel(role)}" first.`
|
|
39717
|
-
);
|
|
39718
|
-
}
|
|
39719
|
-
const password = await promptHidden(`Password for ${roleLabel(role)} key`);
|
|
39720
|
-
try {
|
|
39721
|
-
return await LocalKeyring.fromKeystore(keystore, password);
|
|
39722
|
-
} catch {
|
|
39723
|
-
throw new Error("Invalid password.");
|
|
39724
|
-
}
|
|
39725
|
-
}
|
|
39726
|
-
async function loadManagerSigner(safe) {
|
|
39727
|
-
const passphrase = process.env.SAIL_PASSPHRASE;
|
|
39728
|
-
if (passphrase) {
|
|
39729
|
-
const keystore = readJsonFile(resolveKeyPath("manager", safe));
|
|
39730
|
-
if (!keystore) {
|
|
39731
|
-
throw new Error(
|
|
39732
|
-
'No agent wallet found.\nRun "sailor keys generate" and choose "agent wallet".'
|
|
39733
|
-
);
|
|
39734
|
-
}
|
|
39735
|
-
try {
|
|
39736
|
-
return await LocalKeyring.fromKeystore(keystore, passphrase);
|
|
39737
|
-
} catch {
|
|
39738
|
-
throw new Error(
|
|
39739
|
-
"SAIL_PASSPHRASE does not match this keystore.\nCheck the value in .sail/.env.local (or the SAIL_PASSPHRASE CI secret) \u2014 it must be the passphrase the agent wallet was encrypted with."
|
|
39740
|
-
);
|
|
39741
|
-
}
|
|
39742
|
-
}
|
|
39743
|
-
if (process.stdin.isTTY !== true && keyExists("manager", safe)) {
|
|
39744
|
-
throw new Error(
|
|
39745
|
-
'Agent keystore found but SAIL_PASSPHRASE is not set.\nIf you created the key in the dashboard, add SAIL_PASSPHRASE to .sail/.env.local, or run "sailor keys generate".\nFor CI, set the SAIL_PASSPHRASE GitHub Actions secret.'
|
|
39746
|
-
);
|
|
39747
|
-
}
|
|
39748
|
-
return loadKeyring("manager", safe);
|
|
39749
|
-
}
|
|
39750
|
-
function managerKeystorePath(managerAddr) {
|
|
39751
|
-
if (!isAddress(managerAddr, { strict: false })) {
|
|
39752
|
-
throw new Error(`managerKeystorePath: invalid address "${managerAddr}"`);
|
|
39753
|
-
}
|
|
39754
|
-
const hex = managerAddr.toLowerCase().replace(/^0x/, "");
|
|
39755
|
-
return sailPath("keys", "managers", `${hex}.json`);
|
|
39756
|
-
}
|
|
39757
|
-
async function loadAnySigner() {
|
|
39758
|
-
if (keyExists("permissionSigner")) return loadKeyring("permissionSigner");
|
|
39759
|
-
if (keyExists("manager")) return loadKeyring("manager");
|
|
39760
|
-
throw new Error('No signing key found.\nRun "sailor keys generate" first.');
|
|
39761
|
-
}
|
|
39762
|
-
|
|
39763
|
-
// src/lib/project.ts
|
|
39764
39689
|
function nonEmpty(value) {
|
|
39765
39690
|
return typeof value === "string" && value.trim().length > 0;
|
|
39766
39691
|
}
|
|
@@ -39819,24 +39744,6 @@ var ProjectContext = class {
|
|
|
39819
39744
|
});
|
|
39820
39745
|
}
|
|
39821
39746
|
};
|
|
39822
|
-
async function loadManagerSigner2() {
|
|
39823
|
-
if (!process.env.SAIL_PASSPHRASE) {
|
|
39824
|
-
try {
|
|
39825
|
-
const env = parseEnvFile(sailPath(".env.local"));
|
|
39826
|
-
if (env.SAIL_PASSPHRASE) process.env.SAIL_PASSPHRASE = env.SAIL_PASSPHRASE;
|
|
39827
|
-
} catch {
|
|
39828
|
-
}
|
|
39829
|
-
}
|
|
39830
|
-
const passphrase = process.env.SAIL_PASSPHRASE;
|
|
39831
|
-
if (passphrase) {
|
|
39832
|
-
const keystore = readJsonFile(keyPath("manager"));
|
|
39833
|
-
if (!keystore) {
|
|
39834
|
-
throw new Error('No manager key found.\nRun "sailor keys generate" and choose "manager".');
|
|
39835
|
-
}
|
|
39836
|
-
return LocalKeyring.fromKeystore(keystore, passphrase);
|
|
39837
|
-
}
|
|
39838
|
-
return loadKeyring("manager");
|
|
39839
|
-
}
|
|
39840
39747
|
|
|
39841
39748
|
// src/commands/capabilities.ts
|
|
39842
39749
|
function chainName(chainId) {
|
|
@@ -40044,6 +39951,101 @@ function checkSelectorRoutes(calldata, bytecode) {
|
|
|
40044
39951
|
return { selector, routes: body.includes(selector) };
|
|
40045
39952
|
}
|
|
40046
39953
|
|
|
39954
|
+
// src/lib/keys.ts
|
|
39955
|
+
init_esm2();
|
|
39956
|
+
var ROLES = ["manager", "permissionSigner"];
|
|
39957
|
+
function normalizeRole(input) {
|
|
39958
|
+
const n = input.trim().toLowerCase().replace(/[-_\s]/g, "");
|
|
39959
|
+
if (n === "manager" || n === "mgr" || n === "m" || n === "agent" || n === "agentwallet") {
|
|
39960
|
+
return "manager";
|
|
39961
|
+
}
|
|
39962
|
+
if (n === "permissionsigner" || n === "signer" || n === "ps" || n === "permission" || n === "mandatesigner" || n === "mandate") {
|
|
39963
|
+
return "permissionSigner";
|
|
39964
|
+
}
|
|
39965
|
+
return null;
|
|
39966
|
+
}
|
|
39967
|
+
function roleLabel(role) {
|
|
39968
|
+
return role === "manager" ? "agent wallet" : "mandate signer";
|
|
39969
|
+
}
|
|
39970
|
+
function safeHex(safe) {
|
|
39971
|
+
return safe.toLowerCase().replace(/^0x/, "").replace(/[^0-9a-f]/g, "");
|
|
39972
|
+
}
|
|
39973
|
+
function keyPath(role, safe) {
|
|
39974
|
+
if (safe) {
|
|
39975
|
+
return sailPath("keys", `${role}-0x${safeHex(safe)}.json`);
|
|
39976
|
+
}
|
|
39977
|
+
return sailPath("keys", `${role}.json`);
|
|
39978
|
+
}
|
|
39979
|
+
function legacyKeyPath(role, safe) {
|
|
39980
|
+
return sailPath("keys", `${role}-${safeHex(safe)}.json`);
|
|
39981
|
+
}
|
|
39982
|
+
function resolveKeyPath(role, safe) {
|
|
39983
|
+
if (safe) {
|
|
39984
|
+
const perSma = keyPath(role, safe);
|
|
39985
|
+
if (fileExists(perSma)) return perSma;
|
|
39986
|
+
const legacy = legacyKeyPath(role, safe);
|
|
39987
|
+
if (fileExists(legacy)) return legacy;
|
|
39988
|
+
}
|
|
39989
|
+
return keyPath(role);
|
|
39990
|
+
}
|
|
39991
|
+
function keyExists(role, safe) {
|
|
39992
|
+
return fileExists(resolveKeyPath(role, safe));
|
|
39993
|
+
}
|
|
39994
|
+
async function loadKeyring(role, safe) {
|
|
39995
|
+
const keystore = readJsonFile(resolveKeyPath(role, safe));
|
|
39996
|
+
if (!keystore) {
|
|
39997
|
+
throw new Error(
|
|
39998
|
+
`No ${roleLabel(role)} found.
|
|
39999
|
+
Run "sailor keys generate" and choose "${roleLabel(role)}" first.`
|
|
40000
|
+
);
|
|
40001
|
+
}
|
|
40002
|
+
const passphrase = process.env.SAIL_PASSPHRASE;
|
|
40003
|
+
if (passphrase) {
|
|
40004
|
+
try {
|
|
40005
|
+
return await LocalKeyring.fromKeystore(keystore, passphrase);
|
|
40006
|
+
} catch {
|
|
40007
|
+
throw new Error(
|
|
40008
|
+
`SAIL_PASSPHRASE does not match the ${roleLabel(role)} keystore.
|
|
40009
|
+
Check the value in .sail/.env.local (or the SAIL_PASSPHRASE CI secret) \u2014 it must be the passphrase this key was encrypted with.`
|
|
40010
|
+
);
|
|
40011
|
+
}
|
|
40012
|
+
}
|
|
40013
|
+
if (process.stdin.isTTY !== true) {
|
|
40014
|
+
throw new Error(
|
|
40015
|
+
`${roleLabel(role)} keystore found but SAIL_PASSPHRASE is not set.
|
|
40016
|
+
Set SAIL_PASSPHRASE in .sail/.env.local (or as a CI secret) to run non-interactively.`
|
|
40017
|
+
);
|
|
40018
|
+
}
|
|
40019
|
+
const password = await promptHidden(`Password for ${roleLabel(role)} key`);
|
|
40020
|
+
try {
|
|
40021
|
+
return await LocalKeyring.fromKeystore(keystore, password);
|
|
40022
|
+
} catch {
|
|
40023
|
+
throw new Error("Invalid password.");
|
|
40024
|
+
}
|
|
40025
|
+
}
|
|
40026
|
+
async function loadManagerSigner(safe) {
|
|
40027
|
+
if (!process.env.SAIL_PASSPHRASE) {
|
|
40028
|
+
try {
|
|
40029
|
+
const env = parseEnvFile(sailPath(".env.local"));
|
|
40030
|
+
if (env.SAIL_PASSPHRASE) process.env.SAIL_PASSPHRASE = env.SAIL_PASSPHRASE;
|
|
40031
|
+
} catch {
|
|
40032
|
+
}
|
|
40033
|
+
}
|
|
40034
|
+
return loadKeyring("manager", safe);
|
|
40035
|
+
}
|
|
40036
|
+
function managerKeystorePath(managerAddr) {
|
|
40037
|
+
if (!isAddress(managerAddr, { strict: false })) {
|
|
40038
|
+
throw new Error(`managerKeystorePath: invalid address "${managerAddr}"`);
|
|
40039
|
+
}
|
|
40040
|
+
const hex = managerAddr.toLowerCase().replace(/^0x/, "");
|
|
40041
|
+
return sailPath("keys", "managers", `${hex}.json`);
|
|
40042
|
+
}
|
|
40043
|
+
async function loadAnySigner() {
|
|
40044
|
+
if (keyExists("permissionSigner")) return loadKeyring("permissionSigner");
|
|
40045
|
+
if (keyExists("manager")) return loadKeyring("manager");
|
|
40046
|
+
throw new Error('No signing key found.\nRun "sailor keys generate" first.');
|
|
40047
|
+
}
|
|
40048
|
+
|
|
40047
40049
|
// src/lib/permission-resolver.ts
|
|
40048
40050
|
var IPERMISSION_ABI = [
|
|
40049
40051
|
{
|
|
@@ -40439,11 +40441,11 @@ Probe is heuristic: an unknown selector (${PROBE_SELECTOR}) to a neutral target
|
|
|
40439
40441
|
}
|
|
40440
40442
|
|
|
40441
40443
|
// src/commands/init.ts
|
|
40442
|
-
var
|
|
40444
|
+
var import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
40443
40445
|
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
40444
40446
|
|
|
40445
40447
|
// src/lib/foundry.ts
|
|
40446
|
-
var
|
|
40448
|
+
var import_node_fs8 = require("node:fs");
|
|
40447
40449
|
var import_node_path6 = require("node:path");
|
|
40448
40450
|
var FOUNDRY_TOML = `[profile.default]
|
|
40449
40451
|
src = "mandates"
|
|
@@ -40592,7 +40594,7 @@ Compiled artifacts are written to \`out/\` and the deployed address is tracked i
|
|
|
40592
40594
|
function scaffoldFoundryWorkspace(root) {
|
|
40593
40595
|
const dirs = [(0, import_node_path6.join)(root, "mandates"), (0, import_node_path6.join)(root, ".sail", "contracts", "interfaces")];
|
|
40594
40596
|
for (const d of dirs) {
|
|
40595
|
-
if (!(0,
|
|
40597
|
+
if (!(0, import_node_fs8.existsSync)(d)) (0, import_node_fs8.mkdirSync)(d, { recursive: true });
|
|
40596
40598
|
}
|
|
40597
40599
|
writeIfMissing((0, import_node_path6.join)(root, "foundry.toml"), FOUNDRY_TOML);
|
|
40598
40600
|
writeIfMissing(
|
|
@@ -40607,11 +40609,11 @@ function scaffoldFoundryWorkspace(root) {
|
|
|
40607
40609
|
writeIfMissing((0, import_node_path6.join)(root, "mandates", "README.md"), MANDATES_README);
|
|
40608
40610
|
}
|
|
40609
40611
|
function writeIfMissing(path11, content) {
|
|
40610
|
-
if (!(0,
|
|
40612
|
+
if (!(0, import_node_fs8.existsSync)(path11)) (0, import_node_fs8.writeFileSync)(path11, content, "utf8");
|
|
40611
40613
|
}
|
|
40612
40614
|
|
|
40613
40615
|
// src/lib/template.ts
|
|
40614
|
-
var
|
|
40616
|
+
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
40615
40617
|
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
40616
40618
|
var TEMPLATE_COPY_EXCLUDES = /* @__PURE__ */ new Set([
|
|
40617
40619
|
"node_modules",
|
|
@@ -40622,8 +40624,8 @@ var TEMPLATE_COPY_EXCLUDES = /* @__PURE__ */ new Set([
|
|
|
40622
40624
|
".git"
|
|
40623
40625
|
]);
|
|
40624
40626
|
function copyDirSync(src, dest) {
|
|
40625
|
-
|
|
40626
|
-
for (const entry of
|
|
40627
|
+
import_node_fs9.default.mkdirSync(dest, { recursive: true });
|
|
40628
|
+
for (const entry of import_node_fs9.default.readdirSync(src, { withFileTypes: true })) {
|
|
40627
40629
|
if (TEMPLATE_COPY_EXCLUDES.has(entry.name)) continue;
|
|
40628
40630
|
const srcPath = import_node_path7.default.join(src, entry.name);
|
|
40629
40631
|
const destName = entry.name.startsWith("_") ? `.${entry.name.slice(1)}` : entry.name;
|
|
@@ -40631,24 +40633,24 @@ function copyDirSync(src, dest) {
|
|
|
40631
40633
|
if (entry.isDirectory()) {
|
|
40632
40634
|
copyDirSync(srcPath, destPath);
|
|
40633
40635
|
} else {
|
|
40634
|
-
|
|
40636
|
+
import_node_fs9.default.copyFileSync(srcPath, destPath);
|
|
40635
40637
|
}
|
|
40636
40638
|
}
|
|
40637
40639
|
}
|
|
40638
40640
|
function writeIfMissing2(file, content) {
|
|
40639
|
-
if (!
|
|
40641
|
+
if (!import_node_fs9.default.existsSync(file)) import_node_fs9.default.writeFileSync(file, content, "utf-8");
|
|
40640
40642
|
}
|
|
40641
40643
|
function copyDirSyncIfMissing(src, dest, added = [], base2 = dest) {
|
|
40642
|
-
|
|
40643
|
-
for (const entry of
|
|
40644
|
+
import_node_fs9.default.mkdirSync(dest, { recursive: true });
|
|
40645
|
+
for (const entry of import_node_fs9.default.readdirSync(src, { withFileTypes: true })) {
|
|
40644
40646
|
if (TEMPLATE_COPY_EXCLUDES.has(entry.name)) continue;
|
|
40645
40647
|
const srcPath = import_node_path7.default.join(src, entry.name);
|
|
40646
40648
|
const destName = entry.name.startsWith("_") ? `.${entry.name.slice(1)}` : entry.name;
|
|
40647
40649
|
const destPath = import_node_path7.default.join(dest, destName);
|
|
40648
40650
|
if (entry.isDirectory()) {
|
|
40649
40651
|
copyDirSyncIfMissing(srcPath, destPath, added, base2);
|
|
40650
|
-
} else if (!
|
|
40651
|
-
|
|
40652
|
+
} else if (!import_node_fs9.default.existsSync(destPath)) {
|
|
40653
|
+
import_node_fs9.default.copyFileSync(srcPath, destPath);
|
|
40652
40654
|
added.push(import_node_path7.default.relative(base2, destPath));
|
|
40653
40655
|
}
|
|
40654
40656
|
}
|
|
@@ -40674,7 +40676,7 @@ var DEV_PKG = "@dev.sail.money/sailor";
|
|
|
40674
40676
|
function cliPackageInfo() {
|
|
40675
40677
|
try {
|
|
40676
40678
|
const pkg = JSON.parse(
|
|
40677
|
-
|
|
40679
|
+
import_node_fs10.default.readFileSync(import_node_path8.default.join(packageRoot(), "package.json"), "utf-8")
|
|
40678
40680
|
);
|
|
40679
40681
|
return {
|
|
40680
40682
|
name: pkg.name ?? CANONICAL_PKG,
|
|
@@ -40691,13 +40693,13 @@ function scaffoldProjectWorkspace(dest, name, options) {
|
|
|
40691
40693
|
return n;
|
|
40692
40694
|
})() : null;
|
|
40693
40695
|
const sailDir2 = import_node_path8.default.join(dest, ".sail");
|
|
40694
|
-
|
|
40695
|
-
|
|
40696
|
-
|
|
40696
|
+
import_node_fs10.default.mkdirSync(import_node_path8.default.join(sailDir2, "keys"), { recursive: true });
|
|
40697
|
+
import_node_fs10.default.mkdirSync(import_node_path8.default.join(sailDir2, "runtime"), { recursive: true });
|
|
40698
|
+
import_node_fs10.default.mkdirSync(import_node_path8.default.join(sailDir2, "state"), { recursive: true });
|
|
40697
40699
|
const installMode = process.env.SAILOR_INSTALL_MODE === "docker" ? "docker" : "local";
|
|
40698
40700
|
const _rawContainerName = process.env.SAILOR_CONTAINER_NAME ?? "agent";
|
|
40699
40701
|
const containerName = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(_rawContainerName) ? _rawContainerName : "agent";
|
|
40700
|
-
|
|
40702
|
+
import_node_fs10.default.writeFileSync(
|
|
40701
40703
|
import_node_path8.default.join(sailDir2, "config.json"),
|
|
40702
40704
|
`${JSON.stringify(
|
|
40703
40705
|
{
|
|
@@ -40724,7 +40726,7 @@ function scaffoldProjectWorkspace(dest, name, options) {
|
|
|
40724
40726
|
const chainEntries = Object.values(chains);
|
|
40725
40727
|
const perChainVarLines = chainEntries.map((c) => `# ${c.rpcEnvVar}=https://your-${c.name.toLowerCase().replace(/\s+/g, "-")}-endpoint`).join("\n");
|
|
40726
40728
|
const chainIdExample = chainId != null ? `CHAIN_ID=${chainId}` : `# CHAIN_ID=8453 # set after choosing your chain in Stage 1`;
|
|
40727
|
-
|
|
40729
|
+
import_node_fs10.default.writeFileSync(
|
|
40728
40730
|
import_node_path8.default.join(dest, ".env.example"),
|
|
40729
40731
|
`# Sailor agent environment
|
|
40730
40732
|
#
|
|
@@ -40750,7 +40752,7 @@ ${perChainVarLines}
|
|
|
40750
40752
|
const val = isActive && options.rpcUrl ? options.rpcUrl : `https://your-${c.name.toLowerCase().replace(/\s+/g, "-")}-endpoint`;
|
|
40751
40753
|
return isActive && options.rpcUrl ? `${c.rpcEnvVar}=${val}` : `# ${c.rpcEnvVar}=${val}`;
|
|
40752
40754
|
}).join("\n");
|
|
40753
|
-
|
|
40755
|
+
import_node_fs10.default.writeFileSync(
|
|
40754
40756
|
import_node_path8.default.join(sailDir2, ".env.local"),
|
|
40755
40757
|
`# Real values \u2014 never commit this file.
|
|
40756
40758
|
#
|
|
@@ -40777,8 +40779,8 @@ async function initCommand(dir, options = {}) {
|
|
|
40777
40779
|
throw new Error(`Invalid template name: "${templateName}"`);
|
|
40778
40780
|
}
|
|
40779
40781
|
const templateSrc = import_node_path8.default.join(templatesDir, templateName);
|
|
40780
|
-
const availableTemplates = () =>
|
|
40781
|
-
if (!
|
|
40782
|
+
const availableTemplates = () => import_node_fs10.default.existsSync(templatesDir) ? import_node_fs10.default.readdirSync(templatesDir).filter((e) => import_node_fs10.default.existsSync(import_node_path8.default.join(templatesDir, e, "package.json"))).join(", ") || "none" : "none";
|
|
40783
|
+
if (!import_node_fs10.default.existsSync(templateSrc) || !import_node_fs10.default.existsSync(import_node_path8.default.join(templateSrc, "package.json"))) {
|
|
40782
40784
|
const available = availableTemplates();
|
|
40783
40785
|
const hint = available === "none" ? `
|
|
40784
40786
|
No templates found under ${templatesDir}.
|
|
@@ -40791,19 +40793,19 @@ run from the repo root.` : ` Available: ${available}`;
|
|
|
40791
40793
|
if (!inPlace && !dest.startsWith(cwd + import_node_path8.default.sep) && dest !== cwd) {
|
|
40792
40794
|
throw new Error(`Directory must be inside the current working directory`);
|
|
40793
40795
|
}
|
|
40794
|
-
if (!inPlace &&
|
|
40796
|
+
if (!inPlace && import_node_fs10.default.existsSync(dest) && !options.force) {
|
|
40795
40797
|
throw new Error(`Directory already exists: ${dest}
|
|
40796
40798
|
Pass --force to scaffold into it anyway (existing files with the same name are overwritten).`);
|
|
40797
40799
|
}
|
|
40798
|
-
if (inPlace &&
|
|
40800
|
+
if (inPlace && import_node_fs10.default.existsSync(import_node_path8.default.join(dest, ".sail", "config.json")) && !options.force) {
|
|
40799
40801
|
throw new Error(
|
|
40800
40802
|
"This project is already initialized.\nRun `sailor update` to re-sync template files, or `sailor init --force` to re-initialize (overwrites scaffold files; your .sail/keys/ and .sail/state/ are left in place)."
|
|
40801
40803
|
);
|
|
40802
40804
|
}
|
|
40803
40805
|
const existingConfigPath = import_node_path8.default.join(dest, ".sail", "config.json");
|
|
40804
|
-
const previousConfig =
|
|
40806
|
+
const previousConfig = import_node_fs10.default.existsSync(existingConfigPath) ? (() => {
|
|
40805
40807
|
try {
|
|
40806
|
-
return JSON.parse(
|
|
40808
|
+
return JSON.parse(import_node_fs10.default.readFileSync(existingConfigPath, "utf-8"));
|
|
40807
40809
|
} catch {
|
|
40808
40810
|
return null;
|
|
40809
40811
|
}
|
|
@@ -40811,37 +40813,37 @@ Pass --force to scaffold into it anyway (existing files with the same name are o
|
|
|
40811
40813
|
copyDirSync(templateSrc, dest);
|
|
40812
40814
|
const pkgRoot = packageRoot();
|
|
40813
40815
|
const examplesPermSrc = import_node_path8.default.join(pkgRoot, "examples", "permissions");
|
|
40814
|
-
if (
|
|
40816
|
+
if (import_node_fs10.default.existsSync(examplesPermSrc)) {
|
|
40815
40817
|
copyDirSync(examplesPermSrc, import_node_path8.default.join(dest, "examples", "permissions"));
|
|
40816
40818
|
}
|
|
40817
40819
|
const customMandateSrc = import_node_path8.default.join(pkgRoot, "examples", "custom-mandate");
|
|
40818
|
-
if (
|
|
40820
|
+
if (import_node_fs10.default.existsSync(customMandateSrc)) {
|
|
40819
40821
|
copyDirSync(customMandateSrc, import_node_path8.default.join(dest, "examples", "custom-mandate"));
|
|
40820
40822
|
}
|
|
40821
40823
|
const permModelSrc = import_node_path8.default.join(pkgRoot, "docs", "PERMISSION_MODEL.md");
|
|
40822
|
-
if (
|
|
40823
|
-
|
|
40824
|
-
writeIfMissing2(import_node_path8.default.join(dest, "docs", "PERMISSION_MODEL.md"),
|
|
40824
|
+
if (import_node_fs10.default.existsSync(permModelSrc)) {
|
|
40825
|
+
import_node_fs10.default.mkdirSync(import_node_path8.default.join(dest, "docs"), { recursive: true });
|
|
40826
|
+
writeIfMissing2(import_node_path8.default.join(dest, "docs", "PERMISSION_MODEL.md"), import_node_fs10.default.readFileSync(permModelSrc, "utf-8"));
|
|
40825
40827
|
}
|
|
40826
40828
|
const pkgPath = import_node_path8.default.join(dest, "package.json");
|
|
40827
|
-
if (
|
|
40828
|
-
const pkg = JSON.parse(
|
|
40829
|
+
if (import_node_fs10.default.existsSync(pkgPath)) {
|
|
40830
|
+
const pkg = JSON.parse(import_node_fs10.default.readFileSync(pkgPath, "utf-8"));
|
|
40829
40831
|
pkg.name = name;
|
|
40830
40832
|
const devDeps = pkg.devDependencies ?? {};
|
|
40831
40833
|
const { name: cliName, version: cliVer } = cliPackageInfo();
|
|
40832
40834
|
devDeps[CANONICAL_PKG] = cliName === DEV_PKG ? `npm:${DEV_PKG}@^${cliVer}` : `^${cliVer}`;
|
|
40833
40835
|
pkg.devDependencies = devDeps;
|
|
40834
|
-
|
|
40836
|
+
import_node_fs10.default.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
40835
40837
|
`);
|
|
40836
40838
|
}
|
|
40837
40839
|
const tsconfigPath = import_node_path8.default.join(dest, "tsconfig.json");
|
|
40838
|
-
if (
|
|
40839
|
-
const tsconfig = JSON.parse(
|
|
40840
|
+
if (import_node_fs10.default.existsSync(tsconfigPath)) {
|
|
40841
|
+
const tsconfig = JSON.parse(import_node_fs10.default.readFileSync(tsconfigPath, "utf-8"));
|
|
40840
40842
|
const co = tsconfig.compilerOptions;
|
|
40841
40843
|
if (co && "paths" in co) {
|
|
40842
40844
|
delete co.paths;
|
|
40843
40845
|
delete co.baseUrl;
|
|
40844
|
-
|
|
40846
|
+
import_node_fs10.default.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
|
|
40845
40847
|
`);
|
|
40846
40848
|
}
|
|
40847
40849
|
}
|
|
@@ -40879,20 +40881,20 @@ function chainLabel(chainId) {
|
|
|
40879
40881
|
}
|
|
40880
40882
|
function detectState(dest) {
|
|
40881
40883
|
try {
|
|
40882
|
-
const configRaw =
|
|
40884
|
+
const configRaw = import_node_fs10.default.readFileSync(import_node_path8.default.join(dest, ".sail", "config.json"), "utf-8");
|
|
40883
40885
|
const config = JSON.parse(configRaw);
|
|
40884
40886
|
const projectName = config.name ?? import_node_path8.default.basename(dest);
|
|
40885
40887
|
const accountPath = import_node_path8.default.join(dest, ".sail", "account.json");
|
|
40886
|
-
if (!
|
|
40888
|
+
if (!import_node_fs10.default.existsSync(accountPath)) {
|
|
40887
40889
|
return { kind: "B", projectName, chain: chainLabel(config.chainId ?? 0) };
|
|
40888
40890
|
}
|
|
40889
|
-
const accountRaw =
|
|
40891
|
+
const accountRaw = import_node_fs10.default.readFileSync(accountPath, "utf-8");
|
|
40890
40892
|
const account2 = JSON.parse(accountRaw);
|
|
40891
40893
|
const sma = account2.safe ?? "";
|
|
40892
40894
|
const chain2 = chainLabel(account2.chainId ?? config.chainId ?? 0);
|
|
40893
40895
|
let permissionCount = 0;
|
|
40894
40896
|
try {
|
|
40895
|
-
const mandatesRaw =
|
|
40897
|
+
const mandatesRaw = import_node_fs10.default.readFileSync(
|
|
40896
40898
|
import_node_path8.default.join(dest, ".sail", "state", "mandates.json"),
|
|
40897
40899
|
"utf-8"
|
|
40898
40900
|
);
|
|
@@ -40981,7 +40983,7 @@ Created ${name}/`);
|
|
|
40981
40983
|
}
|
|
40982
40984
|
|
|
40983
40985
|
// src/commands/update.ts
|
|
40984
|
-
var
|
|
40986
|
+
var import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
40985
40987
|
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
40986
40988
|
var UPDATE_PATHS = [
|
|
40987
40989
|
".agents",
|
|
@@ -40997,18 +40999,18 @@ var STALE_PATHS = [
|
|
|
40997
40999
|
];
|
|
40998
41000
|
async function updateCommand() {
|
|
40999
41001
|
const dest = process.cwd();
|
|
41000
|
-
if (!
|
|
41002
|
+
if (!import_node_fs11.default.existsSync(import_node_path9.default.join(dest, ".sail", "config.json"))) {
|
|
41001
41003
|
throw new Error("Not a sailor project \u2014 .sail/config.json not found. Run `sailor init` first.");
|
|
41002
41004
|
}
|
|
41003
41005
|
const templateSrc = import_node_path9.default.join(packageRoot(), "templates", "default");
|
|
41004
|
-
if (!
|
|
41006
|
+
if (!import_node_fs11.default.existsSync(templateSrc)) {
|
|
41005
41007
|
throw new Error(`Template directory not found at ${templateSrc}`);
|
|
41006
41008
|
}
|
|
41007
41009
|
const removed = [];
|
|
41008
41010
|
for (const p of STALE_PATHS) {
|
|
41009
41011
|
const target = import_node_path9.default.join(dest, p);
|
|
41010
|
-
if (
|
|
41011
|
-
|
|
41012
|
+
if (import_node_fs11.default.existsSync(target)) {
|
|
41013
|
+
import_node_fs11.default.rmSync(target, { recursive: true, force: true });
|
|
41012
41014
|
removed.push(p);
|
|
41013
41015
|
}
|
|
41014
41016
|
}
|
|
@@ -41016,13 +41018,13 @@ async function updateCommand() {
|
|
|
41016
41018
|
for (const p of UPDATE_PATHS) {
|
|
41017
41019
|
const src = import_node_path9.default.join(templateSrc, p);
|
|
41018
41020
|
const dst = import_node_path9.default.join(dest, p);
|
|
41019
|
-
if (!
|
|
41020
|
-
const stat =
|
|
41021
|
+
if (!import_node_fs11.default.existsSync(src)) continue;
|
|
41022
|
+
const stat = import_node_fs11.default.statSync(src);
|
|
41021
41023
|
if (stat.isDirectory()) {
|
|
41022
41024
|
copyDirSync(src, dst);
|
|
41023
41025
|
} else {
|
|
41024
|
-
|
|
41025
|
-
|
|
41026
|
+
import_node_fs11.default.mkdirSync(import_node_path9.default.dirname(dst), { recursive: true });
|
|
41027
|
+
import_node_fs11.default.copyFileSync(src, dst);
|
|
41026
41028
|
}
|
|
41027
41029
|
updated.push(p);
|
|
41028
41030
|
}
|
|
@@ -41030,7 +41032,7 @@ async function updateCommand() {
|
|
|
41030
41032
|
copyDirSyncIfMissing(templateSrc, dest, added);
|
|
41031
41033
|
const configPath = import_node_path9.default.join(dest, ".sail", "config.json");
|
|
41032
41034
|
try {
|
|
41033
|
-
const config = JSON.parse(
|
|
41035
|
+
const config = JSON.parse(import_node_fs11.default.readFileSync(configPath, "utf-8"));
|
|
41034
41036
|
const newMode = process.env.SAILOR_INSTALL_MODE === "docker" ? "docker" : "local";
|
|
41035
41037
|
const _rawContainerName = process.env.SAILOR_CONTAINER_NAME ?? "agent";
|
|
41036
41038
|
const containerName = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(_rawContainerName) ? _rawContainerName : "agent";
|
|
@@ -41043,7 +41045,7 @@ async function updateCommand() {
|
|
|
41043
41045
|
} else {
|
|
41044
41046
|
delete config.containerName;
|
|
41045
41047
|
}
|
|
41046
|
-
|
|
41048
|
+
import_node_fs11.default.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
41047
41049
|
`, "utf-8");
|
|
41048
41050
|
if (previousMode === "docker" && newMode === "local") {
|
|
41049
41051
|
const prev = previousContainer ?? "agent";
|
|
@@ -41057,7 +41059,7 @@ Switched to Docker install (container: ${containerName}).`);
|
|
|
41057
41059
|
}
|
|
41058
41060
|
} else if (newMode === "docker" && config.containerName !== containerName) {
|
|
41059
41061
|
config.containerName = containerName;
|
|
41060
|
-
|
|
41062
|
+
import_node_fs11.default.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
41061
41063
|
`, "utf-8");
|
|
41062
41064
|
}
|
|
41063
41065
|
} catch {
|
|
@@ -41086,7 +41088,7 @@ Added (new in template):`);
|
|
|
41086
41088
|
}
|
|
41087
41089
|
|
|
41088
41090
|
// src/commands/keys.ts
|
|
41089
|
-
var
|
|
41091
|
+
var import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
41090
41092
|
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
41091
41093
|
function readStdin() {
|
|
41092
41094
|
return new Promise((resolve3, reject) => {
|
|
@@ -41193,14 +41195,14 @@ async function keysExportCi() {
|
|
|
41193
41195
|
);
|
|
41194
41196
|
}
|
|
41195
41197
|
const dest = import_node_path10.default.resolve(process.cwd(), "ci-keystore.json");
|
|
41196
|
-
|
|
41198
|
+
import_node_fs12.default.copyFileSync(src, dest);
|
|
41197
41199
|
console.log(`\u2713 Keystore copied to ci-keystore.json`);
|
|
41198
41200
|
console.log(` Source: ${src}`);
|
|
41199
41201
|
const gitignorePath = import_node_path10.default.resolve(process.cwd(), ".gitignore");
|
|
41200
|
-
if (
|
|
41201
|
-
const content =
|
|
41202
|
+
if (import_node_fs12.default.existsSync(gitignorePath)) {
|
|
41203
|
+
const content = import_node_fs12.default.readFileSync(gitignorePath, "utf-8");
|
|
41202
41204
|
if (!content.includes("ci-keystore.json")) {
|
|
41203
|
-
|
|
41205
|
+
import_node_fs12.default.appendFileSync(
|
|
41204
41206
|
gitignorePath,
|
|
41205
41207
|
"\n# CI keystore \u2014 encrypted agent wallet, safe to commit\n!ci-keystore.json\n"
|
|
41206
41208
|
);
|
|
@@ -41238,7 +41240,7 @@ async function keysShow() {
|
|
|
41238
41240
|
|
|
41239
41241
|
// src/commands/mandate-contracts.ts
|
|
41240
41242
|
var import_node_child_process = require("node:child_process");
|
|
41241
|
-
var
|
|
41243
|
+
var import_node_fs13 = require("node:fs");
|
|
41242
41244
|
var import_node_path11 = require("node:path");
|
|
41243
41245
|
init_esm2();
|
|
41244
41246
|
|
|
@@ -41370,7 +41372,7 @@ Project: ${project.name}`));
|
|
|
41370
41372
|
if (!keyExists("manager")) {
|
|
41371
41373
|
throw new Error('No agent wallet found. Run "sailor keys generate" and choose "agent wallet" first.');
|
|
41372
41374
|
}
|
|
41373
|
-
const agentSigner = await
|
|
41375
|
+
const agentSigner = await loadManagerSigner();
|
|
41374
41376
|
const agentAddress = agentSigner.address;
|
|
41375
41377
|
say(() => console.log("\u2713", `Agent wallet: ${agentAddress}`));
|
|
41376
41378
|
const chain2 = getChainById(project.chainId);
|
|
@@ -41383,7 +41385,7 @@ Project: ${project.name}`));
|
|
|
41383
41385
|
() => console.log(
|
|
41384
41386
|
`
|
|
41385
41387
|
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
41386
|
-
${signingPageUrl(
|
|
41388
|
+
${signingPageUrl(projectPort(process.cwd()))}
|
|
41387
41389
|
`
|
|
41388
41390
|
)
|
|
41389
41391
|
);
|
|
@@ -41884,7 +41886,7 @@ Mandate command failed: ${msg}`), {
|
|
|
41884
41886
|
process.exit(1);
|
|
41885
41887
|
}
|
|
41886
41888
|
function announceSigningUrl(json) {
|
|
41887
|
-
const url = signingPageUrl(
|
|
41889
|
+
const url = signingPageUrl(projectPort(process.cwd()));
|
|
41888
41890
|
if (json) {
|
|
41889
41891
|
process.stdout.write(`${JSON.stringify({ status: "waiting_for_signature", url })}
|
|
41890
41892
|
`);
|
|
@@ -41937,7 +41939,7 @@ async function runDeploy(project, channel, options) {
|
|
|
41937
41939
|
if (options.argsFile) {
|
|
41938
41940
|
const argsFilePath = (0, import_node_path11.resolve)(options.argsFile);
|
|
41939
41941
|
try {
|
|
41940
|
-
argsJson = (0,
|
|
41942
|
+
argsJson = (0, import_node_fs13.readFileSync)(argsFilePath, "utf8").trim();
|
|
41941
41943
|
} catch {
|
|
41942
41944
|
throw new Error(`Cannot read --args-file: ${argsFilePath}`);
|
|
41943
41945
|
}
|
|
@@ -42145,7 +42147,7 @@ async function runDeployClone(project, channel, options) {
|
|
|
42145
42147
|
}
|
|
42146
42148
|
const chain2 = getChainById(project.chainId);
|
|
42147
42149
|
const publicClient = publicClientFor(project);
|
|
42148
|
-
const agentSigner = await
|
|
42150
|
+
const agentSigner = await loadManagerSigner();
|
|
42149
42151
|
const registered = await publicClient.readContract({
|
|
42150
42152
|
address: project.contracts.kernel,
|
|
42151
42153
|
abi: SailKernelAbi,
|
|
@@ -42489,7 +42491,7 @@ Connect the owner wallet (mandate signer) in the browser \u2014 the agent wallet
|
|
|
42489
42491
|
} catch (err) {
|
|
42490
42492
|
if (err.message.startsWith("Security:")) throw err;
|
|
42491
42493
|
}
|
|
42492
|
-
const agentSigner = await
|
|
42494
|
+
const agentSigner = await loadManagerSigner();
|
|
42493
42495
|
const walletClient = createWalletClient({
|
|
42494
42496
|
account: agentSigner.viemAccount,
|
|
42495
42497
|
chain: getChainById(project.chainId),
|
|
@@ -42531,7 +42533,7 @@ async function attachToSma(project, channel, publicClient, sma, mandate2, label,
|
|
|
42531
42533
|
const say = (fn) => {
|
|
42532
42534
|
if (!json) fn();
|
|
42533
42535
|
};
|
|
42534
|
-
const agentSigner = await
|
|
42536
|
+
const agentSigner = await loadManagerSigner();
|
|
42535
42537
|
const registered = await publicClient.readContract({
|
|
42536
42538
|
address: project.contracts.kernel,
|
|
42537
42539
|
abi: SailKernelAbi,
|
|
@@ -42572,7 +42574,7 @@ async function attachBatchToSma(project, channel, publicClient, sma, permissions
|
|
|
42572
42574
|
const say = (fn) => {
|
|
42573
42575
|
if (!json) fn();
|
|
42574
42576
|
};
|
|
42575
|
-
const agentSigner = await
|
|
42577
|
+
const agentSigner = await loadManagerSigner();
|
|
42576
42578
|
const registered = await publicClient.readContract({
|
|
42577
42579
|
address: project.contracts.kernel,
|
|
42578
42580
|
abi: SailKernelAbi,
|
|
@@ -42788,14 +42790,14 @@ Resolved: ${resolved}`
|
|
|
42788
42790
|
}
|
|
42789
42791
|
artifactPath = resolved;
|
|
42790
42792
|
if (options.build) runForgeBuild();
|
|
42791
|
-
if (!(0,
|
|
42793
|
+
if (!(0, import_node_fs13.existsSync)(artifactPath)) {
|
|
42792
42794
|
ensureForgeHint();
|
|
42793
42795
|
throw new Error(
|
|
42794
42796
|
`Artifact not found: ${artifactPath}
|
|
42795
42797
|
Compile your mandate first (e.g. \`forge build\`), or pass --build.`
|
|
42796
42798
|
);
|
|
42797
42799
|
}
|
|
42798
|
-
const artifact = JSON.parse((0,
|
|
42800
|
+
const artifact = JSON.parse((0, import_node_fs13.readFileSync)(artifactPath, "utf8"));
|
|
42799
42801
|
const abi2 = artifact.abi;
|
|
42800
42802
|
const bytecodeRaw = artifact.bytecode?.object ?? artifact.bytecode;
|
|
42801
42803
|
if (!bytecodeRaw || typeof bytecodeRaw !== "string") {
|
|
@@ -42878,13 +42880,13 @@ function runForgeBuild() {
|
|
|
42878
42880
|
init_esm2();
|
|
42879
42881
|
|
|
42880
42882
|
// src/lib/permission-explainer.ts
|
|
42881
|
-
var
|
|
42883
|
+
var import_node_fs14 = require("node:fs");
|
|
42882
42884
|
var import_node_path12 = require("node:path");
|
|
42883
42885
|
function explainPermission(name, sourcePath) {
|
|
42884
42886
|
const resolved = sourcePath ?? (0, import_node_path12.join)(process.cwd(), "mandates", `${name}.sol`);
|
|
42885
42887
|
let src;
|
|
42886
42888
|
try {
|
|
42887
|
-
src = (0,
|
|
42889
|
+
src = (0, import_node_fs14.readFileSync)(resolved, "utf8");
|
|
42888
42890
|
} catch {
|
|
42889
42891
|
return null;
|
|
42890
42892
|
}
|
|
@@ -43106,7 +43108,7 @@ ${unregistered.length} permission(s) are not yet registered on this SMA. Initiat
|
|
|
43106
43108
|
}
|
|
43107
43109
|
|
|
43108
43110
|
// src/commands/mandate-simulate.ts
|
|
43109
|
-
var
|
|
43111
|
+
var import_node_fs15 = require("node:fs");
|
|
43110
43112
|
init_esm2();
|
|
43111
43113
|
function parseExpect(raw, where) {
|
|
43112
43114
|
if (raw === void 0) return void 0;
|
|
@@ -43122,7 +43124,7 @@ function resolveSampleCalls(options) {
|
|
|
43122
43124
|
if (options.calls) {
|
|
43123
43125
|
let raw;
|
|
43124
43126
|
try {
|
|
43125
|
-
raw = JSON.parse((0,
|
|
43127
|
+
raw = JSON.parse((0, import_node_fs15.readFileSync)(options.calls, "utf8"));
|
|
43126
43128
|
} catch (err) {
|
|
43127
43129
|
throw new Error(`Could not read --calls file "${options.calls}": ${err.message}`);
|
|
43128
43130
|
}
|
|
@@ -43338,7 +43340,7 @@ async function mandateSimulate(options) {
|
|
|
43338
43340
|
}
|
|
43339
43341
|
|
|
43340
43342
|
// src/commands/rotate-signer.ts
|
|
43341
|
-
var
|
|
43343
|
+
var import_node_fs16 = require("node:fs");
|
|
43342
43344
|
init_esm2();
|
|
43343
43345
|
var PENDING_REATTACH_FILE = ["state", "pending-reattach.json"];
|
|
43344
43346
|
async function rotateSigner(options) {
|
|
@@ -43468,7 +43470,7 @@ SMA: ${smaAddress}`);
|
|
|
43468
43470
|
console.log(
|
|
43469
43471
|
`
|
|
43470
43472
|
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
43471
|
-
${signingPageUrl(
|
|
43473
|
+
${signingPageUrl(projectPort(process.cwd()))}
|
|
43472
43474
|
`
|
|
43473
43475
|
);
|
|
43474
43476
|
});
|
|
@@ -43726,7 +43728,7 @@ ensure the agent that signs dispatches holds this key.`
|
|
|
43726
43728
|
const keystore = await keyring.exportKeystore(password);
|
|
43727
43729
|
writeJsonFile(target, keystore, 384);
|
|
43728
43730
|
const perManagerPath = managerKeystorePath(keyring.address);
|
|
43729
|
-
(0,
|
|
43731
|
+
(0, import_node_fs16.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
|
|
43730
43732
|
writeJsonFile(perManagerPath, keystore, 384);
|
|
43731
43733
|
say(
|
|
43732
43734
|
() => console.log(
|
|
@@ -43738,7 +43740,7 @@ ensure the agent that signs dispatches holds this key.`
|
|
|
43738
43740
|
function promoteManagerKeystore(newManager, say) {
|
|
43739
43741
|
const stored = readJsonFile(managerKeystorePath(newManager));
|
|
43740
43742
|
if (!stored) return;
|
|
43741
|
-
(0,
|
|
43743
|
+
(0, import_node_fs16.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
|
|
43742
43744
|
const activeTarget = keyPath("manager");
|
|
43743
43745
|
const displaced = readJsonFile(activeTarget);
|
|
43744
43746
|
if (displaced?.address) {
|
|
@@ -43790,7 +43792,7 @@ function writePending(pending) {
|
|
|
43790
43792
|
}
|
|
43791
43793
|
function clearPending() {
|
|
43792
43794
|
try {
|
|
43793
|
-
(0,
|
|
43795
|
+
(0, import_node_fs16.rmSync)(sailPath(...PENDING_REATTACH_FILE), { force: true });
|
|
43794
43796
|
} catch {
|
|
43795
43797
|
}
|
|
43796
43798
|
}
|
|
@@ -43844,7 +43846,7 @@ async function ownerConnect(options) {
|
|
|
43844
43846
|
await channel.start();
|
|
43845
43847
|
if (!options.json) {
|
|
43846
43848
|
console.log("\u2192 Open the Sailor dashboard and connect your wallet:");
|
|
43847
|
-
console.log(` ${signingPageUrl(
|
|
43849
|
+
console.log(` ${signingPageUrl(projectPort(projectRoot))}`);
|
|
43848
43850
|
if (channel.remote) console.log(" (using the running signing station)");
|
|
43849
43851
|
console.log("\nWaiting for a wallet connection\u2026");
|
|
43850
43852
|
}
|
|
@@ -43893,41 +43895,6 @@ var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
|
43893
43895
|
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
43894
43896
|
var import_node_url = require("node:url");
|
|
43895
43897
|
init_esm2();
|
|
43896
|
-
|
|
43897
|
-
// src/lib/process.ts
|
|
43898
|
-
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
43899
|
-
function agentPidPath(chainId) {
|
|
43900
|
-
return chainId != null ? sailPath(`agent-${chainId}.pid`) : sailPath("agent.pid");
|
|
43901
|
-
}
|
|
43902
|
-
function writeAgentPid(chainId) {
|
|
43903
|
-
import_node_fs16.default.mkdirSync(sailPath(), { recursive: true });
|
|
43904
|
-
import_node_fs16.default.writeFileSync(agentPidPath(chainId), `${process.pid}
|
|
43905
|
-
`);
|
|
43906
|
-
}
|
|
43907
|
-
function clearAgentPid(chainId) {
|
|
43908
|
-
try {
|
|
43909
|
-
import_node_fs16.default.rmSync(agentPidPath(chainId));
|
|
43910
|
-
} catch {
|
|
43911
|
-
}
|
|
43912
|
-
}
|
|
43913
|
-
function readAgentPid(chainId) {
|
|
43914
|
-
try {
|
|
43915
|
-
const pid = Number.parseInt(import_node_fs16.default.readFileSync(agentPidPath(chainId), "utf-8").trim(), 10);
|
|
43916
|
-
return Number.isNaN(pid) ? null : pid;
|
|
43917
|
-
} catch {
|
|
43918
|
-
return null;
|
|
43919
|
-
}
|
|
43920
|
-
}
|
|
43921
|
-
function isProcessAlive(pid) {
|
|
43922
|
-
try {
|
|
43923
|
-
process.kill(pid, 0);
|
|
43924
|
-
return true;
|
|
43925
|
-
} catch {
|
|
43926
|
-
return false;
|
|
43927
|
-
}
|
|
43928
|
-
}
|
|
43929
|
-
|
|
43930
|
-
// src/commands/run.ts
|
|
43931
43898
|
var DEFAULT_INTERVAL_SEC = 60;
|
|
43932
43899
|
var sleep2 = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
43933
43900
|
var ERC20_READ_ABI = [
|
|
@@ -44972,7 +44939,7 @@ function requireAccount() {
|
|
|
44972
44939
|
}
|
|
44973
44940
|
return account2;
|
|
44974
44941
|
}
|
|
44975
|
-
async function sessionPause() {
|
|
44942
|
+
async function sessionPause(opts = {}) {
|
|
44976
44943
|
const account2 = requireAccount();
|
|
44977
44944
|
const signer = await loadAnySigner();
|
|
44978
44945
|
const client = makeClient(account2.chainId);
|
|
@@ -44987,9 +44954,10 @@ async function sessionPause() {
|
|
|
44987
44954
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
44988
44955
|
};
|
|
44989
44956
|
writeJsonFile(sailPath("session.json"), session2);
|
|
44990
|
-
console.log(
|
|
44957
|
+
if (opts.json) console.log(JSON.stringify(session2));
|
|
44958
|
+
else console.log("Session paused \u2014 agent dispatch rights revoked.");
|
|
44991
44959
|
}
|
|
44992
|
-
async function sessionResume() {
|
|
44960
|
+
async function sessionResume(opts = {}) {
|
|
44993
44961
|
const account2 = requireAccount();
|
|
44994
44962
|
const signer = await loadAnySigner();
|
|
44995
44963
|
const client = makeClient(account2.chainId);
|
|
@@ -45004,7 +44972,8 @@ async function sessionResume() {
|
|
|
45004
44972
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
45005
44973
|
};
|
|
45006
44974
|
writeJsonFile(sailPath("session.json"), session2);
|
|
45007
|
-
console.log(
|
|
44975
|
+
if (opts.json) console.log(JSON.stringify(session2));
|
|
44976
|
+
else console.log("Session resumed \u2014 agent dispatch rights restored.");
|
|
45008
44977
|
}
|
|
45009
44978
|
|
|
45010
44979
|
// src/commands/station.ts
|
|
@@ -45122,7 +45091,11 @@ async function status() {
|
|
|
45122
45091
|
const hasManager = keyExists("manager");
|
|
45123
45092
|
const hasPermissionSigner = keyExists("permissionSigner");
|
|
45124
45093
|
const account2 = readJsonFile(sailPath("account.json"));
|
|
45125
|
-
const
|
|
45094
|
+
const mandateRaw = readJsonFile(sailPath("mandate.json"));
|
|
45095
|
+
const mandates = (Array.isArray(mandateRaw) ? mandateRaw : mandateRaw ? [mandateRaw] : []).filter(
|
|
45096
|
+
Boolean
|
|
45097
|
+
);
|
|
45098
|
+
const hasMandate = mandates.length > 0;
|
|
45126
45099
|
const session2 = readJsonFile(sailPath("session.json"));
|
|
45127
45100
|
console.log("Sailor status");
|
|
45128
45101
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
@@ -45138,9 +45111,12 @@ async function status() {
|
|
|
45138
45111
|
console.log(' \u2717 not deployed run "sailor onboard --new-sma"');
|
|
45139
45112
|
}
|
|
45140
45113
|
console.log("Mandate:");
|
|
45141
|
-
if (
|
|
45142
|
-
const n =
|
|
45143
|
-
|
|
45114
|
+
if (hasMandate) {
|
|
45115
|
+
const n = mandates.reduce((sum, m) => sum + (m?.permissions?.length ?? 0), 0);
|
|
45116
|
+
const permLabel = `${n} permission${n === 1 ? "" : "s"}`;
|
|
45117
|
+
console.log(
|
|
45118
|
+
mandates.length > 1 ? ` \u2713 signed ${mandates.length} mandates, ${permLabel}` : ` \u2713 signed ${permLabel}`
|
|
45119
|
+
);
|
|
45144
45120
|
} else {
|
|
45145
45121
|
console.log(' \u2717 not signed run "sailor mandate sign"');
|
|
45146
45122
|
}
|
|
@@ -45150,7 +45126,7 @@ async function status() {
|
|
|
45150
45126
|
let agentState;
|
|
45151
45127
|
if (running) {
|
|
45152
45128
|
agentState = `running (PID ${pid})`;
|
|
45153
|
-
} else if (!
|
|
45129
|
+
} else if (!hasMandate) {
|
|
45154
45130
|
agentState = "not configured";
|
|
45155
45131
|
} else if (session2 && session2.active === false) {
|
|
45156
45132
|
agentState = "stopped (session paused)";
|
|
@@ -45161,10 +45137,52 @@ async function status() {
|
|
|
45161
45137
|
}
|
|
45162
45138
|
|
|
45163
45139
|
// src/commands/ui.ts
|
|
45164
|
-
var
|
|
45140
|
+
var import_node_child_process5 = require("node:child_process");
|
|
45165
45141
|
var import_node_fs20 = __toESM(require("node:fs"), 1);
|
|
45166
45142
|
var import_node_net2 = __toESM(require("node:net"), 1);
|
|
45167
45143
|
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
45144
|
+
|
|
45145
|
+
// src/lib/tailscale.ts
|
|
45146
|
+
var import_node_child_process4 = require("node:child_process");
|
|
45147
|
+
function tailscaleAvailable() {
|
|
45148
|
+
try {
|
|
45149
|
+
return (0, import_node_child_process4.spawnSync)("tailscale", ["version"], { stdio: "ignore" }).status === 0;
|
|
45150
|
+
} catch {
|
|
45151
|
+
return false;
|
|
45152
|
+
}
|
|
45153
|
+
}
|
|
45154
|
+
function tailnetDnsName() {
|
|
45155
|
+
const r = (0, import_node_child_process4.spawnSync)("tailscale", ["status", "--json"], { encoding: "utf-8" });
|
|
45156
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
45157
|
+
try {
|
|
45158
|
+
const j = JSON.parse(r.stdout);
|
|
45159
|
+
if (j.BackendState && j.BackendState !== "Running") return null;
|
|
45160
|
+
const dns = j.Self?.DNSName;
|
|
45161
|
+
if (typeof dns !== "string" || dns.length === 0) return null;
|
|
45162
|
+
return dns.replace(/\.$/, "");
|
|
45163
|
+
} catch {
|
|
45164
|
+
return null;
|
|
45165
|
+
}
|
|
45166
|
+
}
|
|
45167
|
+
function tailscaleServeUp(port) {
|
|
45168
|
+
const r = (0, import_node_child_process4.spawnSync)(
|
|
45169
|
+
"tailscale",
|
|
45170
|
+
["serve", "--bg", "--https=443", `http://127.0.0.1:${port}`],
|
|
45171
|
+
{ encoding: "utf-8" }
|
|
45172
|
+
);
|
|
45173
|
+
if (r.status !== 0) {
|
|
45174
|
+
const detail = (r.stderr || r.stdout || "").trim() || `exit ${r.status ?? "?"}`;
|
|
45175
|
+
throw new Error(detail);
|
|
45176
|
+
}
|
|
45177
|
+
}
|
|
45178
|
+
function tailscaleServeDown() {
|
|
45179
|
+
try {
|
|
45180
|
+
(0, import_node_child_process4.spawnSync)("tailscale", ["serve", "--https=443", "off"], { stdio: "ignore" });
|
|
45181
|
+
} catch {
|
|
45182
|
+
}
|
|
45183
|
+
}
|
|
45184
|
+
|
|
45185
|
+
// src/commands/ui.ts
|
|
45168
45186
|
var UI_STATE_FILE = import_node_path16.default.join(".sail", "runtime", "ui.json");
|
|
45169
45187
|
function readState2(projectRoot) {
|
|
45170
45188
|
const file = import_node_path16.default.join(projectRoot, UI_STATE_FILE);
|
|
@@ -45175,21 +45193,33 @@ function readState2(projectRoot) {
|
|
|
45175
45193
|
return null;
|
|
45176
45194
|
}
|
|
45177
45195
|
}
|
|
45178
|
-
function
|
|
45196
|
+
function installedCliVersion() {
|
|
45179
45197
|
try {
|
|
45180
|
-
|
|
45181
|
-
|
|
45198
|
+
const pkg = JSON.parse(
|
|
45199
|
+
import_node_fs20.default.readFileSync(import_node_path16.default.join(packageRoot(), "package.json"), "utf-8")
|
|
45200
|
+
);
|
|
45201
|
+
return pkg.version ?? null;
|
|
45182
45202
|
} catch {
|
|
45183
|
-
return
|
|
45203
|
+
return null;
|
|
45184
45204
|
}
|
|
45185
45205
|
}
|
|
45186
|
-
function
|
|
45187
|
-
|
|
45188
|
-
|
|
45189
|
-
|
|
45190
|
-
|
|
45191
|
-
|
|
45192
|
-
|
|
45206
|
+
async function warnIfVersionSkew(port) {
|
|
45207
|
+
const cli = installedCliVersion();
|
|
45208
|
+
if (!cli) return;
|
|
45209
|
+
try {
|
|
45210
|
+
const res = await fetch(`http://127.0.0.1:${port}/api/version`, {
|
|
45211
|
+
signal: AbortSignal.timeout(500)
|
|
45212
|
+
});
|
|
45213
|
+
if (!res.ok) return;
|
|
45214
|
+
const { running } = await res.json();
|
|
45215
|
+
if (running && running !== cli) {
|
|
45216
|
+
console.warn(
|
|
45217
|
+
`\u26A0 Version skew: the running dashboard is v${running}, but the installed CLI is v${cli}.
|
|
45218
|
+
Restart it to load the new version: sailor ui stop && sailor ui start`
|
|
45219
|
+
);
|
|
45220
|
+
}
|
|
45221
|
+
} catch {
|
|
45222
|
+
}
|
|
45193
45223
|
}
|
|
45194
45224
|
function waitForPort(port, timeoutMs) {
|
|
45195
45225
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -45209,7 +45239,7 @@ function waitForPort(port, timeoutMs) {
|
|
|
45209
45239
|
attempt();
|
|
45210
45240
|
});
|
|
45211
45241
|
}
|
|
45212
|
-
async function uiCommand() {
|
|
45242
|
+
async function uiCommand(opts = {}) {
|
|
45213
45243
|
const distDir = cliDistDir();
|
|
45214
45244
|
const uiDistDir = import_node_path16.default.join(packageRoot(), "packages", "ui", "dist");
|
|
45215
45245
|
const serverBundle = import_node_path16.default.resolve(distDir, "server.cjs");
|
|
@@ -45223,19 +45253,49 @@ async function uiCommand() {
|
|
|
45223
45253
|
if (!import_node_fs20.default.existsSync(import_node_path16.default.join(uiDistDir, "index.html"))) {
|
|
45224
45254
|
throw new Error(`UI dist not found at ${uiDistDir}. Re-run the sailor build.`);
|
|
45225
45255
|
}
|
|
45256
|
+
let tailnetUrl = null;
|
|
45257
|
+
if (opts.expose) {
|
|
45258
|
+
if (opts.expose !== "tailscale") {
|
|
45259
|
+
throw new Error(`Unknown --expose mode "${opts.expose}". Supported: tailscale.`);
|
|
45260
|
+
}
|
|
45261
|
+
if (!tailscaleAvailable()) {
|
|
45262
|
+
throw new Error(
|
|
45263
|
+
"tailscale CLI not found. Install Tailscale and run `tailscale up`, or start the dashboard without --expose to keep it local-only."
|
|
45264
|
+
);
|
|
45265
|
+
}
|
|
45266
|
+
const dns = tailnetDnsName();
|
|
45267
|
+
if (!dns) {
|
|
45268
|
+
throw new Error(
|
|
45269
|
+
"Could not resolve this node's tailnet name. Is tailscale running and logged in? Run `tailscale status` to check."
|
|
45270
|
+
);
|
|
45271
|
+
}
|
|
45272
|
+
tailnetUrl = `https://${dns}`;
|
|
45273
|
+
}
|
|
45226
45274
|
const existing = readState2(projectRoot);
|
|
45227
|
-
if (existing &&
|
|
45275
|
+
if (existing && isProcessAlive(existing.pid)) {
|
|
45228
45276
|
console.log(`Sailor UI is already running (pid ${existing.pid}) at http://localhost:${existing.port}`);
|
|
45277
|
+
if (opts.expose) {
|
|
45278
|
+
console.log("To expose it on the tailnet, stop it first: sailor ui stop && sailor ui start --expose tailscale");
|
|
45279
|
+
}
|
|
45280
|
+
await warnIfVersionSkew(existing.port);
|
|
45229
45281
|
return;
|
|
45230
45282
|
}
|
|
45231
45283
|
const runtimeDir = import_node_path16.default.join(projectRoot, ".sail", "runtime");
|
|
45232
45284
|
import_node_fs20.default.mkdirSync(runtimeDir, { recursive: true });
|
|
45233
45285
|
const logFile = import_node_path16.default.join(runtimeDir, "ui.log");
|
|
45234
45286
|
const logFd = import_node_fs20.default.openSync(logFile, "a");
|
|
45235
|
-
const
|
|
45287
|
+
const corsOrigins = [process.env.SAILOR_CORS_ORIGINS, tailnetUrl].filter(Boolean).join(",");
|
|
45288
|
+
const child = (0, import_node_child_process5.spawn)(process.execPath, [serverBundle], {
|
|
45236
45289
|
detached: true,
|
|
45237
45290
|
stdio: ["ignore", logFd, logFd],
|
|
45238
|
-
env: {
|
|
45291
|
+
env: {
|
|
45292
|
+
...process.env,
|
|
45293
|
+
SAIL_DIR: sailDir2,
|
|
45294
|
+
SERVE_DIST: "1",
|
|
45295
|
+
PORT: String(port),
|
|
45296
|
+
SAILOR_UI_DIST: uiDistDir,
|
|
45297
|
+
...corsOrigins ? { SAILOR_CORS_ORIGINS: corsOrigins } : {}
|
|
45298
|
+
}
|
|
45239
45299
|
});
|
|
45240
45300
|
child.unref();
|
|
45241
45301
|
import_node_fs20.default.closeSync(logFd);
|
|
@@ -45243,7 +45303,7 @@ async function uiCommand() {
|
|
|
45243
45303
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
45244
45304
|
let ready = false;
|
|
45245
45305
|
while (Date.now() < deadline) {
|
|
45246
|
-
if (!
|
|
45306
|
+
if (!isProcessAlive(child.pid)) break;
|
|
45247
45307
|
if (await waitForPort(port, 500)) {
|
|
45248
45308
|
ready = true;
|
|
45249
45309
|
break;
|
|
@@ -45262,17 +45322,31 @@ Server output:
|
|
|
45262
45322
|
${tail}` : ` See ${import_node_path16.default.relative(projectRoot, logFile)}.`)
|
|
45263
45323
|
);
|
|
45264
45324
|
}
|
|
45325
|
+
let exposed = false;
|
|
45326
|
+
if (tailnetUrl) {
|
|
45327
|
+
try {
|
|
45328
|
+
tailscaleServeUp(port);
|
|
45329
|
+
exposed = true;
|
|
45330
|
+
} catch (err) {
|
|
45331
|
+
console.warn(
|
|
45332
|
+
`\u26A0 Could not expose on the tailnet: ${err.message}
|
|
45333
|
+
The dashboard is still running locally.`
|
|
45334
|
+
);
|
|
45335
|
+
}
|
|
45336
|
+
}
|
|
45265
45337
|
import_node_fs20.default.writeFileSync(
|
|
45266
45338
|
import_node_path16.default.join(projectRoot, UI_STATE_FILE),
|
|
45267
|
-
JSON.stringify({ pid: child.pid, port, startedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
|
|
45339
|
+
JSON.stringify({ pid: child.pid, port, startedAt: (/* @__PURE__ */ new Date()).toISOString(), exposed }, null, 2)
|
|
45268
45340
|
);
|
|
45269
45341
|
console.log(`Sailor UI started at http://localhost:${port} (pid ${child.pid})`);
|
|
45342
|
+
if (exposed) console.log(`Exposed on your tailnet at ${tailnetUrl}/`);
|
|
45270
45343
|
console.log(`Stop it with: sailor ui stop`);
|
|
45271
45344
|
}
|
|
45272
|
-
function uiStatus() {
|
|
45345
|
+
async function uiStatus() {
|
|
45273
45346
|
const state = readState2(process.cwd());
|
|
45274
|
-
if (state &&
|
|
45347
|
+
if (state && isProcessAlive(state.pid)) {
|
|
45275
45348
|
console.log(`\u25CF running http://localhost:${state.port} (pid ${state.pid})`);
|
|
45349
|
+
await warnIfVersionSkew(state.port);
|
|
45276
45350
|
} else {
|
|
45277
45351
|
if (state) import_node_fs20.default.rmSync(import_node_path16.default.join(process.cwd(), UI_STATE_FILE), { force: true });
|
|
45278
45352
|
console.log("\u25CB Sailor UI is not running");
|
|
@@ -45285,12 +45359,16 @@ function uiStop() {
|
|
|
45285
45359
|
console.log("Sailor UI is not running.");
|
|
45286
45360
|
return;
|
|
45287
45361
|
}
|
|
45288
|
-
if (!
|
|
45362
|
+
if (!isProcessAlive(state.pid)) {
|
|
45289
45363
|
import_node_fs20.default.rmSync(import_node_path16.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
45290
45364
|
console.log("Sailor UI is not running (stale state file removed).");
|
|
45291
45365
|
return;
|
|
45292
45366
|
}
|
|
45293
45367
|
process.kill(state.pid, "SIGTERM");
|
|
45368
|
+
if (state.exposed) {
|
|
45369
|
+
tailscaleServeDown();
|
|
45370
|
+
console.log("Tailnet exposure removed.");
|
|
45371
|
+
}
|
|
45294
45372
|
import_node_fs20.default.rmSync(import_node_path16.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
45295
45373
|
console.log(`Stopped Sailor UI (pid ${state.pid}).`);
|
|
45296
45374
|
}
|
|
@@ -45342,7 +45420,7 @@ program2.command("init [dir]").description("Scaffold a new Sail agent into the c
|
|
|
45342
45420
|
);
|
|
45343
45421
|
program2.command("update").description("Re-sync agent tooling files (skills, AGENTS.md, Dockerfile) from the latest template").action(action(updateCommand));
|
|
45344
45422
|
var ui = program2.command("ui").description("Manage the local Sailor dashboard");
|
|
45345
|
-
ui.command("start").description("Start the dashboard at localhost:3333 (default)").
|
|
45423
|
+
ui.command("start").description("Start the dashboard at localhost:3333 (default)").option("--expose <mode>", "Expose the dashboard over HTTPS on your tailnet (mode: tailscale)").action(actionWith(uiCommand));
|
|
45346
45424
|
ui.command("stop").description("Stop the running dashboard").action(() => uiStop());
|
|
45347
45425
|
ui.command("status").description("Show whether the dashboard is running").action(() => uiStatus());
|
|
45348
45426
|
ui.action(action(uiCommand));
|
|
@@ -45407,8 +45485,8 @@ program2.command("run").description("Run the agent execution loop (use --once fo
|
|
|
45407
45485
|
var trigger = program2.command("trigger").description("Wake the agent on demand from an external system");
|
|
45408
45486
|
trigger.command("github").description("Fire the agent's GitHub Actions workflow_dispatch (the same job the cron runs)").option("--workflow <file>", "Workflow file to dispatch", "agent-tick.yml").option("--ref <branch>", "Git ref to run the workflow on", "main").option("--reason <text>", "Why this run fired \u2014 recorded as the workflow's reason input").option("--repo <owner/repo>", "Override the repository (default: from the git origin remote)").option("--json", "Emit machine-readable JSON").action(actionWith(triggerGithub));
|
|
45409
45487
|
var session = program2.command("session").description("Control the agent session");
|
|
45410
|
-
session.command("pause").description("Pause the agent session (revoke dispatch rights)").
|
|
45411
|
-
session.command("resume").description("Resume a paused session").
|
|
45488
|
+
session.command("pause").description("Pause the agent session (revoke dispatch rights)").option("--json", "Emit machine-readable JSON").action(actionWith(sessionPause));
|
|
45489
|
+
session.command("resume").description("Resume a paused session").option("--json", "Emit machine-readable JSON").action(actionWith(sessionResume));
|
|
45412
45490
|
program2.command("doctor").description(
|
|
45413
45491
|
"Preflight (read-only): kernel model, permission health, RPC + gas balances, before spending gas"
|
|
45414
45492
|
).option("--json", "Output machine-readable JSON").option("--account <address>", "SMA to check (defaults to .sail/account.json)").action(actionWith(doctor));
|