@dev.sail.money/sailor 1.2.0-75 → 1.2.0-76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/package.json +1 -1
- package/packages/cli/dist/index.cjs +296 -206
- package/packages/sdk/dist/intelligence.d.ts +1 -1
- package/packages/sdk/dist/intelligence.js +1 -1
- package/scripts/check-docs.mjs +1 -1
- package/scripts/check-init.mjs +16 -13
- package/scripts/check-update.mjs +177 -0
- package/templates/default/.agents/skills/sail-automation/SKILL.md +50 -0
- package/templates/default/.agents/skills/sail-automation/references/docker-vm.md +113 -0
- package/templates/default/.agents/skills/sail-automation/references/github-actions.md +50 -0
- package/templates/default/.agents/skills/sail-automation/references/local-daemon.md +34 -0
- package/templates/default/.agents/skills/sail-automation/references/self-hosted-runner.md +72 -0
- package/templates/default/.agents/skills/sail-onboarding/SKILL.md +2 -0
- package/templates/default/AGENTS.md +1 -1
- package/templates/default/Dockerfile +18 -0
- package/templates/default/_dockerignore +15 -0
- package/templates/default/.agents/skills/sail-ci/SKILL.md +0 -63
|
@@ -966,8 +966,8 @@ var require_command = __commonJS({
|
|
|
966
966
|
"../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports2) {
|
|
967
967
|
var EventEmitter = require("node:events").EventEmitter;
|
|
968
968
|
var childProcess = require("node:child_process");
|
|
969
|
-
var
|
|
970
|
-
var
|
|
969
|
+
var path11 = require("node:path");
|
|
970
|
+
var fs12 = require("node:fs");
|
|
971
971
|
var process2 = require("node:process");
|
|
972
972
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
973
973
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1899,11 +1899,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1899
1899
|
let launchWithNode = false;
|
|
1900
1900
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1901
1901
|
function findFile(baseDir, baseName) {
|
|
1902
|
-
const localBin =
|
|
1903
|
-
if (
|
|
1904
|
-
if (sourceExt.includes(
|
|
1902
|
+
const localBin = path11.resolve(baseDir, baseName);
|
|
1903
|
+
if (fs12.existsSync(localBin)) return localBin;
|
|
1904
|
+
if (sourceExt.includes(path11.extname(baseName))) return void 0;
|
|
1905
1905
|
const foundExt = sourceExt.find(
|
|
1906
|
-
(ext) =>
|
|
1906
|
+
(ext) => fs12.existsSync(`${localBin}${ext}`)
|
|
1907
1907
|
);
|
|
1908
1908
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1909
1909
|
return void 0;
|
|
@@ -1915,21 +1915,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1915
1915
|
if (this._scriptPath) {
|
|
1916
1916
|
let resolvedScriptPath;
|
|
1917
1917
|
try {
|
|
1918
|
-
resolvedScriptPath =
|
|
1918
|
+
resolvedScriptPath = fs12.realpathSync(this._scriptPath);
|
|
1919
1919
|
} catch (err) {
|
|
1920
1920
|
resolvedScriptPath = this._scriptPath;
|
|
1921
1921
|
}
|
|
1922
|
-
executableDir =
|
|
1923
|
-
|
|
1922
|
+
executableDir = path11.resolve(
|
|
1923
|
+
path11.dirname(resolvedScriptPath),
|
|
1924
1924
|
executableDir
|
|
1925
1925
|
);
|
|
1926
1926
|
}
|
|
1927
1927
|
if (executableDir) {
|
|
1928
1928
|
let localFile = findFile(executableDir, executableFile);
|
|
1929
1929
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1930
|
-
const legacyName =
|
|
1930
|
+
const legacyName = path11.basename(
|
|
1931
1931
|
this._scriptPath,
|
|
1932
|
-
|
|
1932
|
+
path11.extname(this._scriptPath)
|
|
1933
1933
|
);
|
|
1934
1934
|
if (legacyName !== this._name) {
|
|
1935
1935
|
localFile = findFile(
|
|
@@ -1940,7 +1940,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1940
1940
|
}
|
|
1941
1941
|
executableFile = localFile || executableFile;
|
|
1942
1942
|
}
|
|
1943
|
-
launchWithNode = sourceExt.includes(
|
|
1943
|
+
launchWithNode = sourceExt.includes(path11.extname(executableFile));
|
|
1944
1944
|
let proc;
|
|
1945
1945
|
if (process2.platform !== "win32") {
|
|
1946
1946
|
if (launchWithNode) {
|
|
@@ -2780,7 +2780,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2780
2780
|
* @return {Command}
|
|
2781
2781
|
*/
|
|
2782
2782
|
nameFromFilename(filename) {
|
|
2783
|
-
this._name =
|
|
2783
|
+
this._name = path11.basename(filename, path11.extname(filename));
|
|
2784
2784
|
return this;
|
|
2785
2785
|
}
|
|
2786
2786
|
/**
|
|
@@ -2794,9 +2794,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2794
2794
|
* @param {string} [path]
|
|
2795
2795
|
* @return {(string|null|Command)}
|
|
2796
2796
|
*/
|
|
2797
|
-
executableDir(
|
|
2798
|
-
if (
|
|
2799
|
-
this._executableDir =
|
|
2797
|
+
executableDir(path12) {
|
|
2798
|
+
if (path12 === void 0) return this._executableDir;
|
|
2799
|
+
this._executableDir = path12;
|
|
2800
2800
|
return this;
|
|
2801
2801
|
}
|
|
2802
2802
|
/**
|
|
@@ -30772,9 +30772,9 @@ var init_defineKzg = __esm({
|
|
|
30772
30772
|
});
|
|
30773
30773
|
|
|
30774
30774
|
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/utils/kzg/setupKzg.js
|
|
30775
|
-
function setupKzg(parameters,
|
|
30775
|
+
function setupKzg(parameters, path11) {
|
|
30776
30776
|
try {
|
|
30777
|
-
parameters.loadTrustedSetup(
|
|
30777
|
+
parameters.loadTrustedSetup(path11);
|
|
30778
30778
|
} catch (e) {
|
|
30779
30779
|
const error = e;
|
|
30780
30780
|
if (!error.message.includes("trusted setup is already loaded"))
|
|
@@ -35190,8 +35190,8 @@ var require_websocket_server2 = __commonJS({
|
|
|
35190
35190
|
});
|
|
35191
35191
|
|
|
35192
35192
|
// src/index.ts
|
|
35193
|
-
var
|
|
35194
|
-
var
|
|
35193
|
+
var import_node_fs21 = require("node:fs");
|
|
35194
|
+
var import_node_path17 = require("node:path");
|
|
35195
35195
|
|
|
35196
35196
|
// ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
|
|
35197
35197
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -37123,14 +37123,14 @@ var HDKey = class _HDKey {
|
|
|
37123
37123
|
}
|
|
37124
37124
|
this.pubHash = hash160(this.pubKey);
|
|
37125
37125
|
}
|
|
37126
|
-
derive(
|
|
37127
|
-
if (!/^[mM]'?/.test(
|
|
37126
|
+
derive(path11) {
|
|
37127
|
+
if (!/^[mM]'?/.test(path11)) {
|
|
37128
37128
|
throw new Error('Path must start with "m" or "M"');
|
|
37129
37129
|
}
|
|
37130
|
-
if (/^[mM]'?$/.test(
|
|
37130
|
+
if (/^[mM]'?$/.test(path11)) {
|
|
37131
37131
|
return this;
|
|
37132
37132
|
}
|
|
37133
|
-
const parts =
|
|
37133
|
+
const parts = path11.replace(/^[mM]'?\//, "").split("/");
|
|
37134
37134
|
let child = this;
|
|
37135
37135
|
for (const c of parts) {
|
|
37136
37136
|
const m = /^(\d+)('?)$/.exec(c);
|
|
@@ -37462,8 +37462,8 @@ function privateKeyToAccount(privateKey, options = {}) {
|
|
|
37462
37462
|
}
|
|
37463
37463
|
|
|
37464
37464
|
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/accounts/hdKeyToAccount.js
|
|
37465
|
-
function hdKeyToAccount(hdKey_, { accountIndex = 0, addressIndex = 0, changeIndex = 0, path:
|
|
37466
|
-
const hdKey = hdKey_.derive(
|
|
37465
|
+
function hdKeyToAccount(hdKey_, { accountIndex = 0, addressIndex = 0, changeIndex = 0, path: path11, ...options } = {}) {
|
|
37466
|
+
const hdKey = hdKey_.derive(path11 || `m/44'/60'/${accountIndex}'/${changeIndex}/${addressIndex}`);
|
|
37467
37467
|
const account2 = privateKeyToAccount(toHex(hdKey.privateKey), options);
|
|
37468
37468
|
return {
|
|
37469
37469
|
...account2,
|
|
@@ -37564,8 +37564,8 @@ var LocalKeyring = class _LocalKeyring {
|
|
|
37564
37564
|
return _LocalKeyring.fromPrivateKey(`0x${pkBytes.toString("hex")}`);
|
|
37565
37565
|
}
|
|
37566
37566
|
/** Loads a keyring from an encrypted JSON keystore file on disk. */
|
|
37567
|
-
static async fromKeystoreFile(
|
|
37568
|
-
const keystore = JSON.parse((0, import_node_fs.readFileSync)(
|
|
37567
|
+
static async fromKeystoreFile(path11, password) {
|
|
37568
|
+
const keystore = JSON.parse((0, import_node_fs.readFileSync)(path11, "utf-8"));
|
|
37569
37569
|
return _LocalKeyring.fromKeystore(keystore, password);
|
|
37570
37570
|
}
|
|
37571
37571
|
/** Signs a raw 32-byte hash. Returns a 65-byte ECDSA signature. */
|
|
@@ -38845,16 +38845,16 @@ var SigningServer = class {
|
|
|
38845
38845
|
syncConfigChainId(chainId) {
|
|
38846
38846
|
if (chainId == null) return;
|
|
38847
38847
|
try {
|
|
38848
|
-
const
|
|
38848
|
+
const path11 = this.sailFile("config.json");
|
|
38849
38849
|
let config = {};
|
|
38850
38850
|
try {
|
|
38851
|
-
config = JSON.parse((0, import_node_fs5.readFileSync)(
|
|
38851
|
+
config = JSON.parse((0, import_node_fs5.readFileSync)(path11, "utf-8"));
|
|
38852
38852
|
} catch {
|
|
38853
38853
|
}
|
|
38854
38854
|
if (Number(config.chainId) === Number(chainId)) return;
|
|
38855
38855
|
config.chainId = Number(chainId);
|
|
38856
38856
|
(0, import_node_fs5.mkdirSync)(this.sailFile(), { recursive: true });
|
|
38857
|
-
(0, import_node_fs5.writeFileSync)(
|
|
38857
|
+
(0, import_node_fs5.writeFileSync)(path11, `${JSON.stringify(config, null, 2)}
|
|
38858
38858
|
`);
|
|
38859
38859
|
} catch {
|
|
38860
38860
|
}
|
|
@@ -39150,10 +39150,10 @@ var SigningServer = class {
|
|
|
39150
39150
|
}
|
|
39151
39151
|
}
|
|
39152
39152
|
writeRuntimeState() {
|
|
39153
|
-
const
|
|
39154
|
-
if ((0, import_node_fs5.existsSync)(
|
|
39153
|
+
const path11 = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
|
|
39154
|
+
if ((0, import_node_fs5.existsSync)(path11)) {
|
|
39155
39155
|
try {
|
|
39156
|
-
const existing = JSON.parse((0, import_node_fs5.readFileSync)(
|
|
39156
|
+
const existing = JSON.parse((0, import_node_fs5.readFileSync)(path11, "utf8"));
|
|
39157
39157
|
if (existing.pid != null && existing.pid !== process.pid && pidAlive(existing.pid)) return;
|
|
39158
39158
|
} catch {
|
|
39159
39159
|
}
|
|
@@ -39176,12 +39176,12 @@ var SigningServer = class {
|
|
|
39176
39176
|
);
|
|
39177
39177
|
}
|
|
39178
39178
|
removeRuntimeState() {
|
|
39179
|
-
const
|
|
39179
|
+
const path11 = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
|
|
39180
39180
|
try {
|
|
39181
|
-
if (!(0, import_node_fs5.existsSync)(
|
|
39182
|
-
const state = JSON.parse((0, import_node_fs5.readFileSync)(
|
|
39181
|
+
if (!(0, import_node_fs5.existsSync)(path11)) return;
|
|
39182
|
+
const state = JSON.parse((0, import_node_fs5.readFileSync)(path11, "utf8"));
|
|
39183
39183
|
if (state.pid != null && state.pid !== process.pid) return;
|
|
39184
|
-
(0, import_node_fs5.unlinkSync)(
|
|
39184
|
+
(0, import_node_fs5.unlinkSync)(path11);
|
|
39185
39185
|
} catch {
|
|
39186
39186
|
}
|
|
39187
39187
|
}
|
|
@@ -39195,12 +39195,12 @@ function pidAlive(pid) {
|
|
|
39195
39195
|
}
|
|
39196
39196
|
}
|
|
39197
39197
|
function reapStaleRuntimeState(projectRoot = process.cwd()) {
|
|
39198
|
-
const
|
|
39198
|
+
const path11 = (0, import_node_path4.join)(projectRoot, RUNTIME_SUBDIR, SERVER_STATE_FILE);
|
|
39199
39199
|
try {
|
|
39200
|
-
if (!(0, import_node_fs5.existsSync)(
|
|
39201
|
-
const state = JSON.parse((0, import_node_fs5.readFileSync)(
|
|
39200
|
+
if (!(0, import_node_fs5.existsSync)(path11)) return;
|
|
39201
|
+
const state = JSON.parse((0, import_node_fs5.readFileSync)(path11, "utf8"));
|
|
39202
39202
|
if (state.pid != null && state.pid !== process.pid && !pidAlive(state.pid)) {
|
|
39203
|
-
(0, import_node_fs5.unlinkSync)(
|
|
39203
|
+
(0, import_node_fs5.unlinkSync)(path11);
|
|
39204
39204
|
}
|
|
39205
39205
|
} catch {
|
|
39206
39206
|
}
|
|
@@ -40453,8 +40453,8 @@ Probe is heuristic: an unknown selector (${PROBE_SELECTOR}) to a neutral target
|
|
|
40453
40453
|
}
|
|
40454
40454
|
|
|
40455
40455
|
// src/commands/init.ts
|
|
40456
|
-
var
|
|
40457
|
-
var
|
|
40456
|
+
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
40457
|
+
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
40458
40458
|
|
|
40459
40459
|
// src/lib/foundry.ts
|
|
40460
40460
|
var import_node_fs7 = require("node:fs");
|
|
@@ -40620,11 +40620,13 @@ function scaffoldFoundryWorkspace(root) {
|
|
|
40620
40620
|
writeIfMissing((0, import_node_path6.join)(root, "mandates", "BoundedCallPermission.sol"), EXAMPLE_MANDATE_SOL);
|
|
40621
40621
|
writeIfMissing((0, import_node_path6.join)(root, "mandates", "README.md"), MANDATES_README);
|
|
40622
40622
|
}
|
|
40623
|
-
function writeIfMissing(
|
|
40624
|
-
if (!(0, import_node_fs7.existsSync)(
|
|
40623
|
+
function writeIfMissing(path11, content) {
|
|
40624
|
+
if (!(0, import_node_fs7.existsSync)(path11)) (0, import_node_fs7.writeFileSync)(path11, content, "utf8");
|
|
40625
40625
|
}
|
|
40626
40626
|
|
|
40627
|
-
// src/
|
|
40627
|
+
// src/lib/template.ts
|
|
40628
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
40629
|
+
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
40628
40630
|
var TEMPLATE_COPY_EXCLUDES = /* @__PURE__ */ new Set([
|
|
40629
40631
|
"node_modules",
|
|
40630
40632
|
"dist",
|
|
@@ -40647,6 +40649,26 @@ function copyDirSync(src, dest) {
|
|
|
40647
40649
|
}
|
|
40648
40650
|
}
|
|
40649
40651
|
}
|
|
40652
|
+
function writeIfMissing2(file, content) {
|
|
40653
|
+
if (!import_node_fs8.default.existsSync(file)) import_node_fs8.default.writeFileSync(file, content, "utf-8");
|
|
40654
|
+
}
|
|
40655
|
+
function copyDirSyncIfMissing(src, dest, added = [], base2 = dest) {
|
|
40656
|
+
import_node_fs8.default.mkdirSync(dest, { recursive: true });
|
|
40657
|
+
for (const entry of import_node_fs8.default.readdirSync(src, { withFileTypes: true })) {
|
|
40658
|
+
if (TEMPLATE_COPY_EXCLUDES.has(entry.name)) continue;
|
|
40659
|
+
const srcPath = import_node_path7.default.join(src, entry.name);
|
|
40660
|
+
const destName = entry.name.startsWith("_") ? `.${entry.name.slice(1)}` : entry.name;
|
|
40661
|
+
const destPath = import_node_path7.default.join(dest, destName);
|
|
40662
|
+
if (entry.isDirectory()) {
|
|
40663
|
+
copyDirSyncIfMissing(srcPath, destPath, added, base2);
|
|
40664
|
+
} else if (!import_node_fs8.default.existsSync(destPath)) {
|
|
40665
|
+
import_node_fs8.default.copyFileSync(srcPath, destPath);
|
|
40666
|
+
added.push(import_node_path7.default.relative(base2, destPath));
|
|
40667
|
+
}
|
|
40668
|
+
}
|
|
40669
|
+
}
|
|
40670
|
+
|
|
40671
|
+
// src/commands/init.ts
|
|
40650
40672
|
var SAIL_WORKSPACE_README = `# Sailor Project Workspace
|
|
40651
40673
|
|
|
40652
40674
|
This folder is the local workspace for one Sailor agent deployment.
|
|
@@ -40661,15 +40683,12 @@ This folder is the local workspace for one Sailor agent deployment.
|
|
|
40661
40683
|
AI coding agents should read the project's \`AGENTS.md\` and this folder's \`config.json\`
|
|
40662
40684
|
before changing strategy code or running commands that touch funds.
|
|
40663
40685
|
`;
|
|
40664
|
-
function writeIfMissing2(file, content) {
|
|
40665
|
-
if (!import_node_fs8.default.existsSync(file)) import_node_fs8.default.writeFileSync(file, content, "utf-8");
|
|
40666
|
-
}
|
|
40667
40686
|
var CANONICAL_PKG = "@sail.money/sailor";
|
|
40668
40687
|
var DEV_PKG = "@dev.sail.money/sailor";
|
|
40669
40688
|
function cliPackageInfo() {
|
|
40670
40689
|
try {
|
|
40671
40690
|
const pkg = JSON.parse(
|
|
40672
|
-
|
|
40691
|
+
import_node_fs9.default.readFileSync(import_node_path8.default.join(packageRoot(), "package.json"), "utf-8")
|
|
40673
40692
|
);
|
|
40674
40693
|
return {
|
|
40675
40694
|
name: pkg.name ?? CANONICAL_PKG,
|
|
@@ -40685,12 +40704,12 @@ function scaffoldProjectWorkspace(dest, name, options) {
|
|
|
40685
40704
|
if (!Number.isInteger(n) || n <= 0) throw new Error(`Invalid chain id: "${options.chain}"`);
|
|
40686
40705
|
return n;
|
|
40687
40706
|
})() : null;
|
|
40688
|
-
const sailDir2 =
|
|
40689
|
-
|
|
40690
|
-
|
|
40691
|
-
|
|
40692
|
-
|
|
40693
|
-
|
|
40707
|
+
const sailDir2 = import_node_path8.default.join(dest, ".sail");
|
|
40708
|
+
import_node_fs9.default.mkdirSync(import_node_path8.default.join(sailDir2, "keys"), { recursive: true });
|
|
40709
|
+
import_node_fs9.default.mkdirSync(import_node_path8.default.join(sailDir2, "runtime"), { recursive: true });
|
|
40710
|
+
import_node_fs9.default.mkdirSync(import_node_path8.default.join(sailDir2, "state"), { recursive: true });
|
|
40711
|
+
import_node_fs9.default.writeFileSync(
|
|
40712
|
+
import_node_path8.default.join(sailDir2, "config.json"),
|
|
40694
40713
|
`${JSON.stringify(
|
|
40695
40714
|
{
|
|
40696
40715
|
version: 1,
|
|
@@ -40710,12 +40729,12 @@ function scaffoldProjectWorkspace(dest, name, options) {
|
|
|
40710
40729
|
`,
|
|
40711
40730
|
"utf-8"
|
|
40712
40731
|
);
|
|
40713
|
-
writeIfMissing2(
|
|
40732
|
+
writeIfMissing2(import_node_path8.default.join(sailDir2, "README.md"), SAIL_WORKSPACE_README);
|
|
40714
40733
|
const chainEntries = Object.values(chains);
|
|
40715
40734
|
const perChainVarLines = chainEntries.map((c) => `# ${c.rpcEnvVar}=https://your-${c.name.toLowerCase().replace(/\s+/g, "-")}-endpoint`).join("\n");
|
|
40716
40735
|
const chainIdExample = chainId != null ? `CHAIN_ID=${chainId}` : `# CHAIN_ID=8453 # set after choosing your chain in Stage 1`;
|
|
40717
|
-
|
|
40718
|
-
|
|
40736
|
+
import_node_fs9.default.writeFileSync(
|
|
40737
|
+
import_node_path8.default.join(dest, ".env.example"),
|
|
40719
40738
|
`# Sailor agent environment
|
|
40720
40739
|
#
|
|
40721
40740
|
# RPC configuration \u2014 two patterns, pick one:
|
|
@@ -40740,8 +40759,8 @@ ${perChainVarLines}
|
|
|
40740
40759
|
const val = isActive && options.rpcUrl ? options.rpcUrl : `https://your-${c.name.toLowerCase().replace(/\s+/g, "-")}-endpoint`;
|
|
40741
40760
|
return isActive && options.rpcUrl ? `${c.rpcEnvVar}=${val}` : `# ${c.rpcEnvVar}=${val}`;
|
|
40742
40761
|
}).join("\n");
|
|
40743
|
-
|
|
40744
|
-
|
|
40762
|
+
import_node_fs9.default.writeFileSync(
|
|
40763
|
+
import_node_path8.default.join(sailDir2, ".env.local"),
|
|
40745
40764
|
`# Real values \u2014 never commit this file.
|
|
40746
40765
|
#
|
|
40747
40766
|
# Option A: single active chain (simplest)
|
|
@@ -40759,16 +40778,16 @@ ${allChainVarLines}
|
|
|
40759
40778
|
}
|
|
40760
40779
|
async function initCommand(dir, options = {}) {
|
|
40761
40780
|
const inPlace = !dir || dir === ".";
|
|
40762
|
-
const dest = inPlace ? process.cwd() :
|
|
40763
|
-
const name =
|
|
40764
|
-
const templatesDir =
|
|
40781
|
+
const dest = inPlace ? process.cwd() : import_node_path8.default.resolve(process.cwd(), dir);
|
|
40782
|
+
const name = import_node_path8.default.basename(dest);
|
|
40783
|
+
const templatesDir = import_node_path8.default.join(packageRoot(), "templates");
|
|
40765
40784
|
const templateName = options.template ?? "default";
|
|
40766
40785
|
if (/[/\\.]/.test(templateName) || templateName.includes("..")) {
|
|
40767
40786
|
throw new Error(`Invalid template name: "${templateName}"`);
|
|
40768
40787
|
}
|
|
40769
|
-
const templateSrc =
|
|
40770
|
-
const availableTemplates = () =>
|
|
40771
|
-
if (!
|
|
40788
|
+
const templateSrc = import_node_path8.default.join(templatesDir, templateName);
|
|
40789
|
+
const availableTemplates = () => import_node_fs9.default.existsSync(templatesDir) ? import_node_fs9.default.readdirSync(templatesDir).filter((e) => import_node_fs9.default.existsSync(import_node_path8.default.join(templatesDir, e, "package.json"))).join(", ") || "none" : "none";
|
|
40790
|
+
if (!import_node_fs9.default.existsSync(templateSrc) || !import_node_fs9.default.existsSync(import_node_path8.default.join(templateSrc, "package.json"))) {
|
|
40772
40791
|
const available = availableTemplates();
|
|
40773
40792
|
const hint = available === "none" ? `
|
|
40774
40793
|
No templates found under ${templatesDir}.
|
|
@@ -40778,49 +40797,49 @@ run from the repo root.` : ` Available: ${available}`;
|
|
|
40778
40797
|
throw new Error(`Template "${templateName}" not found.${hint}`);
|
|
40779
40798
|
}
|
|
40780
40799
|
const cwd = process.cwd();
|
|
40781
|
-
if (!inPlace && !dest.startsWith(cwd +
|
|
40800
|
+
if (!inPlace && !dest.startsWith(cwd + import_node_path8.default.sep) && dest !== cwd) {
|
|
40782
40801
|
throw new Error(`Directory must be inside the current working directory`);
|
|
40783
40802
|
}
|
|
40784
|
-
if (!inPlace &&
|
|
40803
|
+
if (!inPlace && import_node_fs9.default.existsSync(dest)) {
|
|
40785
40804
|
throw new Error(`Directory already exists: ${dest}`);
|
|
40786
40805
|
}
|
|
40787
|
-
if (inPlace &&
|
|
40788
|
-
throw new Error(
|
|
40806
|
+
if (inPlace && import_node_fs9.default.existsSync(import_node_path8.default.join(dest, ".sail", "config.json"))) {
|
|
40807
|
+
throw new Error("This project is already initialized. Run `sailor update` to re-sync template files.");
|
|
40789
40808
|
}
|
|
40790
40809
|
copyDirSync(templateSrc, dest);
|
|
40791
40810
|
const pkgRoot = packageRoot();
|
|
40792
|
-
const examplesPermSrc =
|
|
40793
|
-
if (
|
|
40794
|
-
copyDirSync(examplesPermSrc,
|
|
40795
|
-
}
|
|
40796
|
-
const customMandateSrc =
|
|
40797
|
-
if (
|
|
40798
|
-
copyDirSync(customMandateSrc,
|
|
40799
|
-
}
|
|
40800
|
-
const permModelSrc =
|
|
40801
|
-
if (
|
|
40802
|
-
|
|
40803
|
-
writeIfMissing2(
|
|
40804
|
-
}
|
|
40805
|
-
const pkgPath =
|
|
40806
|
-
if (
|
|
40807
|
-
const pkg = JSON.parse(
|
|
40811
|
+
const examplesPermSrc = import_node_path8.default.join(pkgRoot, "examples", "permissions");
|
|
40812
|
+
if (import_node_fs9.default.existsSync(examplesPermSrc)) {
|
|
40813
|
+
copyDirSync(examplesPermSrc, import_node_path8.default.join(dest, "examples", "permissions"));
|
|
40814
|
+
}
|
|
40815
|
+
const customMandateSrc = import_node_path8.default.join(pkgRoot, "examples", "custom-mandate");
|
|
40816
|
+
if (import_node_fs9.default.existsSync(customMandateSrc)) {
|
|
40817
|
+
copyDirSync(customMandateSrc, import_node_path8.default.join(dest, "examples", "custom-mandate"));
|
|
40818
|
+
}
|
|
40819
|
+
const permModelSrc = import_node_path8.default.join(pkgRoot, "docs", "PERMISSION_MODEL.md");
|
|
40820
|
+
if (import_node_fs9.default.existsSync(permModelSrc)) {
|
|
40821
|
+
import_node_fs9.default.mkdirSync(import_node_path8.default.join(dest, "docs"), { recursive: true });
|
|
40822
|
+
writeIfMissing2(import_node_path8.default.join(dest, "docs", "PERMISSION_MODEL.md"), import_node_fs9.default.readFileSync(permModelSrc, "utf-8"));
|
|
40823
|
+
}
|
|
40824
|
+
const pkgPath = import_node_path8.default.join(dest, "package.json");
|
|
40825
|
+
if (import_node_fs9.default.existsSync(pkgPath)) {
|
|
40826
|
+
const pkg = JSON.parse(import_node_fs9.default.readFileSync(pkgPath, "utf-8"));
|
|
40808
40827
|
pkg.name = name;
|
|
40809
40828
|
const devDeps = pkg.devDependencies ?? {};
|
|
40810
40829
|
const { name: cliName, version: cliVer } = cliPackageInfo();
|
|
40811
40830
|
devDeps[CANONICAL_PKG] = cliName === DEV_PKG ? `npm:${DEV_PKG}@^${cliVer}` : `^${cliVer}`;
|
|
40812
40831
|
pkg.devDependencies = devDeps;
|
|
40813
|
-
|
|
40832
|
+
import_node_fs9.default.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
40814
40833
|
`);
|
|
40815
40834
|
}
|
|
40816
|
-
const tsconfigPath =
|
|
40817
|
-
if (
|
|
40818
|
-
const tsconfig = JSON.parse(
|
|
40835
|
+
const tsconfigPath = import_node_path8.default.join(dest, "tsconfig.json");
|
|
40836
|
+
if (import_node_fs9.default.existsSync(tsconfigPath)) {
|
|
40837
|
+
const tsconfig = JSON.parse(import_node_fs9.default.readFileSync(tsconfigPath, "utf-8"));
|
|
40819
40838
|
const co = tsconfig.compilerOptions;
|
|
40820
40839
|
if (co && "paths" in co) {
|
|
40821
40840
|
delete co.paths;
|
|
40822
40841
|
delete co.baseUrl;
|
|
40823
|
-
|
|
40842
|
+
import_node_fs9.default.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
|
|
40824
40843
|
`);
|
|
40825
40844
|
}
|
|
40826
40845
|
}
|
|
@@ -40846,21 +40865,21 @@ function chainLabel(chainId) {
|
|
|
40846
40865
|
}
|
|
40847
40866
|
function detectState(dest) {
|
|
40848
40867
|
try {
|
|
40849
|
-
const configRaw =
|
|
40868
|
+
const configRaw = import_node_fs9.default.readFileSync(import_node_path8.default.join(dest, ".sail", "config.json"), "utf-8");
|
|
40850
40869
|
const config = JSON.parse(configRaw);
|
|
40851
|
-
const projectName = config.name ??
|
|
40852
|
-
const accountPath =
|
|
40853
|
-
if (!
|
|
40870
|
+
const projectName = config.name ?? import_node_path8.default.basename(dest);
|
|
40871
|
+
const accountPath = import_node_path8.default.join(dest, ".sail", "account.json");
|
|
40872
|
+
if (!import_node_fs9.default.existsSync(accountPath)) {
|
|
40854
40873
|
return { kind: "B", projectName, chain: chainLabel(config.chainId ?? 0) };
|
|
40855
40874
|
}
|
|
40856
|
-
const accountRaw =
|
|
40875
|
+
const accountRaw = import_node_fs9.default.readFileSync(accountPath, "utf-8");
|
|
40857
40876
|
const account2 = JSON.parse(accountRaw);
|
|
40858
40877
|
const sma = account2.safe ?? "";
|
|
40859
40878
|
const chain2 = chainLabel(account2.chainId ?? config.chainId ?? 0);
|
|
40860
40879
|
let permissionCount = 0;
|
|
40861
40880
|
try {
|
|
40862
|
-
const mandatesRaw =
|
|
40863
|
-
|
|
40881
|
+
const mandatesRaw = import_node_fs9.default.readFileSync(
|
|
40882
|
+
import_node_path8.default.join(dest, ".sail", "state", "mandates.json"),
|
|
40864
40883
|
"utf-8"
|
|
40865
40884
|
);
|
|
40866
40885
|
const mandates = JSON.parse(mandatesRaw);
|
|
@@ -40941,9 +40960,79 @@ Created ${name}/`);
|
|
|
40941
40960
|
].join("\n"));
|
|
40942
40961
|
}
|
|
40943
40962
|
|
|
40963
|
+
// src/commands/update.ts
|
|
40964
|
+
var import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
40965
|
+
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
40966
|
+
var UPDATE_PATHS = [
|
|
40967
|
+
".agents",
|
|
40968
|
+
// all sail-* skills
|
|
40969
|
+
".cursor",
|
|
40970
|
+
// cursor IDE rules
|
|
40971
|
+
".env.example"
|
|
40972
|
+
// documents env vars; not meant to be edited directly
|
|
40973
|
+
];
|
|
40974
|
+
var STALE_PATHS = [
|
|
40975
|
+
".agents/skills/sail-ci"
|
|
40976
|
+
// renamed to sail-automation
|
|
40977
|
+
];
|
|
40978
|
+
async function updateCommand() {
|
|
40979
|
+
const dest = process.cwd();
|
|
40980
|
+
if (!import_node_fs10.default.existsSync(import_node_path9.default.join(dest, ".sail", "config.json"))) {
|
|
40981
|
+
throw new Error("Not a sailor project \u2014 .sail/config.json not found. Run `sailor init` first.");
|
|
40982
|
+
}
|
|
40983
|
+
const templateSrc = import_node_path9.default.join(packageRoot(), "templates", "default");
|
|
40984
|
+
if (!import_node_fs10.default.existsSync(templateSrc)) {
|
|
40985
|
+
throw new Error(`Template directory not found at ${templateSrc}`);
|
|
40986
|
+
}
|
|
40987
|
+
const removed = [];
|
|
40988
|
+
for (const p of STALE_PATHS) {
|
|
40989
|
+
const target = import_node_path9.default.join(dest, p);
|
|
40990
|
+
if (import_node_fs10.default.existsSync(target)) {
|
|
40991
|
+
import_node_fs10.default.rmSync(target, { recursive: true, force: true });
|
|
40992
|
+
removed.push(p);
|
|
40993
|
+
}
|
|
40994
|
+
}
|
|
40995
|
+
const updated = [];
|
|
40996
|
+
for (const p of UPDATE_PATHS) {
|
|
40997
|
+
const src = import_node_path9.default.join(templateSrc, p);
|
|
40998
|
+
const dst = import_node_path9.default.join(dest, p);
|
|
40999
|
+
if (!import_node_fs10.default.existsSync(src)) continue;
|
|
41000
|
+
const stat = import_node_fs10.default.statSync(src);
|
|
41001
|
+
if (stat.isDirectory()) {
|
|
41002
|
+
copyDirSync(src, dst);
|
|
41003
|
+
} else {
|
|
41004
|
+
import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(dst), { recursive: true });
|
|
41005
|
+
import_node_fs10.default.copyFileSync(src, dst);
|
|
41006
|
+
}
|
|
41007
|
+
updated.push(p);
|
|
41008
|
+
}
|
|
41009
|
+
const added = [];
|
|
41010
|
+
copyDirSyncIfMissing(templateSrc, dest, added);
|
|
41011
|
+
if (removed.length === 0 && updated.length === 0 && added.length === 0) {
|
|
41012
|
+
console.log("Nothing to update.");
|
|
41013
|
+
return;
|
|
41014
|
+
}
|
|
41015
|
+
if (removed.length > 0) {
|
|
41016
|
+
console.log(`
|
|
41017
|
+
Removed stale files:`);
|
|
41018
|
+
for (const p of removed) console.log(` ${p}`);
|
|
41019
|
+
}
|
|
41020
|
+
if (updated.length > 0) {
|
|
41021
|
+
console.log(`
|
|
41022
|
+
Updated from template:`);
|
|
41023
|
+
for (const p of updated) console.log(` ${p}`);
|
|
41024
|
+
}
|
|
41025
|
+
if (added.length > 0) {
|
|
41026
|
+
console.log(`
|
|
41027
|
+
Added (new in template):`);
|
|
41028
|
+
for (const p of added) console.log(` ${p}`);
|
|
41029
|
+
}
|
|
41030
|
+
console.log();
|
|
41031
|
+
}
|
|
41032
|
+
|
|
40944
41033
|
// src/commands/keys.ts
|
|
40945
|
-
var
|
|
40946
|
-
var
|
|
41034
|
+
var import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
41035
|
+
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
40947
41036
|
async function keysGenerate() {
|
|
40948
41037
|
const roleInput = await prompt("Which key? (agent wallet / mandate signer)", "agent wallet");
|
|
40949
41038
|
const role = normalizeRole(roleInput);
|
|
@@ -40996,15 +41085,15 @@ async function keysExportCi() {
|
|
|
40996
41085
|
'No agent wallet keystore found.\nComplete Stage 1 (browser UI) to generate your agent wallet, or run\n"sailor keys generate" and choose "agent wallet" to create one manually.'
|
|
40997
41086
|
);
|
|
40998
41087
|
}
|
|
40999
|
-
const dest =
|
|
41000
|
-
|
|
41088
|
+
const dest = import_node_path10.default.resolve(process.cwd(), "ci-keystore.json");
|
|
41089
|
+
import_node_fs11.default.copyFileSync(src, dest);
|
|
41001
41090
|
console.log(`\u2713 Keystore copied to ci-keystore.json`);
|
|
41002
41091
|
console.log(` Source: ${src}`);
|
|
41003
|
-
const gitignorePath =
|
|
41004
|
-
if (
|
|
41005
|
-
const content =
|
|
41092
|
+
const gitignorePath = import_node_path10.default.resolve(process.cwd(), ".gitignore");
|
|
41093
|
+
if (import_node_fs11.default.existsSync(gitignorePath)) {
|
|
41094
|
+
const content = import_node_fs11.default.readFileSync(gitignorePath, "utf-8");
|
|
41006
41095
|
if (!content.includes("ci-keystore.json")) {
|
|
41007
|
-
|
|
41096
|
+
import_node_fs11.default.appendFileSync(
|
|
41008
41097
|
gitignorePath,
|
|
41009
41098
|
"\n# CI keystore \u2014 encrypted agent wallet, safe to commit\n!ci-keystore.json\n"
|
|
41010
41099
|
);
|
|
@@ -41042,8 +41131,8 @@ async function keysShow() {
|
|
|
41042
41131
|
|
|
41043
41132
|
// src/commands/mandate-contracts.ts
|
|
41044
41133
|
var import_node_child_process = require("node:child_process");
|
|
41045
|
-
var
|
|
41046
|
-
var
|
|
41134
|
+
var import_node_fs12 = require("node:fs");
|
|
41135
|
+
var import_node_path11 = require("node:path");
|
|
41047
41136
|
init_esm2();
|
|
41048
41137
|
|
|
41049
41138
|
// src/lib/mandates.ts
|
|
@@ -41739,9 +41828,9 @@ async function runDeploy(project, channel, options) {
|
|
|
41739
41828
|
const { abi: abi2, bytecode, contractName, artifactPath } = resolveArtifact(options);
|
|
41740
41829
|
let argsJson;
|
|
41741
41830
|
if (options.argsFile) {
|
|
41742
|
-
const argsFilePath = (0,
|
|
41831
|
+
const argsFilePath = (0, import_node_path11.resolve)(options.argsFile);
|
|
41743
41832
|
try {
|
|
41744
|
-
argsJson = (0,
|
|
41833
|
+
argsJson = (0, import_node_fs12.readFileSync)(argsFilePath, "utf8").trim();
|
|
41745
41834
|
} catch {
|
|
41746
41835
|
throw new Error(`Cannot read --args-file: ${argsFilePath}`);
|
|
41747
41836
|
}
|
|
@@ -42444,11 +42533,11 @@ function resolveArtifact(options) {
|
|
|
42444
42533
|
let contractName = options.contract ?? options.name ?? "";
|
|
42445
42534
|
if (!artifactPath) {
|
|
42446
42535
|
if (!options.contract) throw new Error("Provide --artifact <path> or --contract <name>");
|
|
42447
|
-
artifactPath = (0,
|
|
42536
|
+
artifactPath = (0, import_node_path11.join)(options.out, `${options.contract}.sol`, `${options.contract}.json`);
|
|
42448
42537
|
}
|
|
42449
|
-
const resolved = (0,
|
|
42450
|
-
const projectRoot = (0,
|
|
42451
|
-
if (!resolved.startsWith(projectRoot +
|
|
42538
|
+
const resolved = (0, import_node_path11.resolve)(artifactPath);
|
|
42539
|
+
const projectRoot = (0, import_node_path11.resolve)(process.cwd());
|
|
42540
|
+
if (!resolved.startsWith(projectRoot + import_node_path11.sep) && resolved !== projectRoot) {
|
|
42452
42541
|
throw new Error(
|
|
42453
42542
|
`Artifact path must be inside the project directory.
|
|
42454
42543
|
Resolved: ${resolved}`
|
|
@@ -42456,14 +42545,14 @@ Resolved: ${resolved}`
|
|
|
42456
42545
|
}
|
|
42457
42546
|
artifactPath = resolved;
|
|
42458
42547
|
if (options.build) runForgeBuild();
|
|
42459
|
-
if (!(0,
|
|
42548
|
+
if (!(0, import_node_fs12.existsSync)(artifactPath)) {
|
|
42460
42549
|
ensureForgeHint();
|
|
42461
42550
|
throw new Error(
|
|
42462
42551
|
`Artifact not found: ${artifactPath}
|
|
42463
42552
|
Compile your mandate first (e.g. \`forge build\`), or pass --build.`
|
|
42464
42553
|
);
|
|
42465
42554
|
}
|
|
42466
|
-
const artifact = JSON.parse((0,
|
|
42555
|
+
const artifact = JSON.parse((0, import_node_fs12.readFileSync)(artifactPath, "utf8"));
|
|
42467
42556
|
const abi2 = artifact.abi;
|
|
42468
42557
|
const bytecodeRaw = artifact.bytecode?.object ?? artifact.bytecode;
|
|
42469
42558
|
if (!bytecodeRaw || typeof bytecodeRaw !== "string") {
|
|
@@ -42546,13 +42635,13 @@ function runForgeBuild() {
|
|
|
42546
42635
|
init_esm2();
|
|
42547
42636
|
|
|
42548
42637
|
// src/lib/permission-explainer.ts
|
|
42549
|
-
var
|
|
42550
|
-
var
|
|
42638
|
+
var import_node_fs13 = require("node:fs");
|
|
42639
|
+
var import_node_path12 = require("node:path");
|
|
42551
42640
|
function explainPermission(name, sourcePath) {
|
|
42552
|
-
const resolved = sourcePath ?? (0,
|
|
42641
|
+
const resolved = sourcePath ?? (0, import_node_path12.join)(process.cwd(), "mandates", `${name}.sol`);
|
|
42553
42642
|
let src;
|
|
42554
42643
|
try {
|
|
42555
|
-
src = (0,
|
|
42644
|
+
src = (0, import_node_fs13.readFileSync)(resolved, "utf8");
|
|
42556
42645
|
} catch {
|
|
42557
42646
|
return null;
|
|
42558
42647
|
}
|
|
@@ -42774,7 +42863,7 @@ ${unregistered.length} permission(s) are not yet registered on this SMA. Initiat
|
|
|
42774
42863
|
}
|
|
42775
42864
|
|
|
42776
42865
|
// src/commands/mandate-simulate.ts
|
|
42777
|
-
var
|
|
42866
|
+
var import_node_fs14 = require("node:fs");
|
|
42778
42867
|
init_esm2();
|
|
42779
42868
|
function parseExpect(raw, where) {
|
|
42780
42869
|
if (raw === void 0) return void 0;
|
|
@@ -42790,7 +42879,7 @@ function resolveSampleCalls(options) {
|
|
|
42790
42879
|
if (options.calls) {
|
|
42791
42880
|
let raw;
|
|
42792
42881
|
try {
|
|
42793
|
-
raw = JSON.parse((0,
|
|
42882
|
+
raw = JSON.parse((0, import_node_fs14.readFileSync)(options.calls, "utf8"));
|
|
42794
42883
|
} catch (err) {
|
|
42795
42884
|
throw new Error(`Could not read --calls file "${options.calls}": ${err.message}`);
|
|
42796
42885
|
}
|
|
@@ -43006,7 +43095,7 @@ async function mandateSimulate(options) {
|
|
|
43006
43095
|
}
|
|
43007
43096
|
|
|
43008
43097
|
// src/commands/rotate-signer.ts
|
|
43009
|
-
var
|
|
43098
|
+
var import_node_fs15 = require("node:fs");
|
|
43010
43099
|
init_esm2();
|
|
43011
43100
|
var PENDING_REATTACH_FILE = ["state", "pending-reattach.json"];
|
|
43012
43101
|
async function rotateSigner(options) {
|
|
@@ -43394,7 +43483,7 @@ ensure the agent that signs dispatches holds this key.`
|
|
|
43394
43483
|
const keystore = await keyring.exportKeystore(password);
|
|
43395
43484
|
writeJsonFile(target, keystore, 384);
|
|
43396
43485
|
const perManagerPath = managerKeystorePath(keyring.address);
|
|
43397
|
-
(0,
|
|
43486
|
+
(0, import_node_fs15.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
|
|
43398
43487
|
writeJsonFile(perManagerPath, keystore, 384);
|
|
43399
43488
|
say(
|
|
43400
43489
|
() => console.log(
|
|
@@ -43406,7 +43495,7 @@ ensure the agent that signs dispatches holds this key.`
|
|
|
43406
43495
|
function promoteManagerKeystore(newManager, say) {
|
|
43407
43496
|
const stored = readJsonFile(managerKeystorePath(newManager));
|
|
43408
43497
|
if (!stored) return;
|
|
43409
|
-
(0,
|
|
43498
|
+
(0, import_node_fs15.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
|
|
43410
43499
|
const activeTarget = keyPath("manager");
|
|
43411
43500
|
const displaced = readJsonFile(activeTarget);
|
|
43412
43501
|
if (displaced?.address) {
|
|
@@ -43458,7 +43547,7 @@ function writePending(pending) {
|
|
|
43458
43547
|
}
|
|
43459
43548
|
function clearPending() {
|
|
43460
43549
|
try {
|
|
43461
|
-
(0,
|
|
43550
|
+
(0, import_node_fs15.rmSync)(sailPath(...PENDING_REATTACH_FILE), { force: true });
|
|
43462
43551
|
} catch {
|
|
43463
43552
|
}
|
|
43464
43553
|
}
|
|
@@ -43557,30 +43646,30 @@ function ownerShow(options) {
|
|
|
43557
43646
|
}
|
|
43558
43647
|
|
|
43559
43648
|
// src/commands/run.ts
|
|
43560
|
-
var
|
|
43561
|
-
var
|
|
43649
|
+
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
43650
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
43562
43651
|
var import_node_url = require("node:url");
|
|
43563
43652
|
init_esm2();
|
|
43564
43653
|
|
|
43565
43654
|
// src/lib/process.ts
|
|
43566
|
-
var
|
|
43655
|
+
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
43567
43656
|
function agentPidPath(chainId) {
|
|
43568
43657
|
return chainId != null ? sailPath(`agent-${chainId}.pid`) : sailPath("agent.pid");
|
|
43569
43658
|
}
|
|
43570
43659
|
function writeAgentPid(chainId) {
|
|
43571
|
-
|
|
43572
|
-
|
|
43660
|
+
import_node_fs16.default.mkdirSync(sailPath(), { recursive: true });
|
|
43661
|
+
import_node_fs16.default.writeFileSync(agentPidPath(chainId), `${process.pid}
|
|
43573
43662
|
`);
|
|
43574
43663
|
}
|
|
43575
43664
|
function clearAgentPid(chainId) {
|
|
43576
43665
|
try {
|
|
43577
|
-
|
|
43666
|
+
import_node_fs16.default.rmSync(agentPidPath(chainId));
|
|
43578
43667
|
} catch {
|
|
43579
43668
|
}
|
|
43580
43669
|
}
|
|
43581
43670
|
function readAgentPid(chainId) {
|
|
43582
43671
|
try {
|
|
43583
|
-
const pid = Number.parseInt(
|
|
43672
|
+
const pid = Number.parseInt(import_node_fs16.default.readFileSync(agentPidPath(chainId), "utf-8").trim(), 10);
|
|
43584
43673
|
return Number.isNaN(pid) ? null : pid;
|
|
43585
43674
|
} catch {
|
|
43586
43675
|
return null;
|
|
@@ -43627,7 +43716,7 @@ var ERC20_READ_ABI = [
|
|
|
43627
43716
|
function loadAgentData(filePath) {
|
|
43628
43717
|
if (!filePath) return {};
|
|
43629
43718
|
try {
|
|
43630
|
-
const parsed = JSON.parse(
|
|
43719
|
+
const parsed = JSON.parse(import_node_fs17.default.readFileSync(filePath, "utf-8"));
|
|
43631
43720
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
43632
43721
|
} catch {
|
|
43633
43722
|
return {};
|
|
@@ -43636,8 +43725,8 @@ function loadAgentData(filePath) {
|
|
|
43636
43725
|
async function loadAgent() {
|
|
43637
43726
|
const candidates = ["src/agent.ts", "src/agent.js", "dist/agent.js", "dist/src/agent.js"];
|
|
43638
43727
|
for (const rel of candidates) {
|
|
43639
|
-
const abs =
|
|
43640
|
-
if (!
|
|
43728
|
+
const abs = import_node_path13.default.join(process.cwd(), rel);
|
|
43729
|
+
if (!import_node_fs17.default.existsSync(abs)) continue;
|
|
43641
43730
|
let mod2;
|
|
43642
43731
|
if (abs.endsWith(".ts")) {
|
|
43643
43732
|
const { tsImport } = await import("tsx/esm/api");
|
|
@@ -44113,9 +44202,9 @@ async function scan(options) {
|
|
|
44113
44202
|
|
|
44114
44203
|
// src/commands/service.ts
|
|
44115
44204
|
var import_node_child_process2 = require("node:child_process");
|
|
44116
|
-
var
|
|
44205
|
+
var import_node_fs18 = __toESM(require("node:fs"), 1);
|
|
44117
44206
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
44118
|
-
var
|
|
44207
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
44119
44208
|
function sanitizeName(raw) {
|
|
44120
44209
|
const s = raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
44121
44210
|
return s || "agent";
|
|
@@ -44234,21 +44323,21 @@ function buildWindowsTaskXml(cfg) {
|
|
|
44234
44323
|
`;
|
|
44235
44324
|
}
|
|
44236
44325
|
function isTccProtected(projectDir, home = import_node_os.default.homedir()) {
|
|
44237
|
-
const rel =
|
|
44238
|
-
if (rel.startsWith("..") ||
|
|
44239
|
-
const top = rel.split(
|
|
44326
|
+
const rel = import_node_path14.default.relative(home, import_node_path14.default.resolve(projectDir));
|
|
44327
|
+
if (rel.startsWith("..") || import_node_path14.default.isAbsolute(rel)) return false;
|
|
44328
|
+
const top = rel.split(import_node_path14.default.sep)[0];
|
|
44240
44329
|
return ["Desktop", "Documents", "Downloads"].includes(top ?? "");
|
|
44241
44330
|
}
|
|
44242
44331
|
function resolveCliEntry() {
|
|
44243
44332
|
try {
|
|
44244
|
-
return
|
|
44333
|
+
return import_node_fs18.default.realpathSync(process.argv[1]);
|
|
44245
44334
|
} catch {
|
|
44246
|
-
return
|
|
44335
|
+
return import_node_path14.default.resolve(process.argv[1]);
|
|
44247
44336
|
}
|
|
44248
44337
|
}
|
|
44249
44338
|
function resolveProjectDir(explicit) {
|
|
44250
|
-
const dir =
|
|
44251
|
-
if (!
|
|
44339
|
+
const dir = import_node_path14.default.resolve(explicit ?? process.cwd());
|
|
44340
|
+
if (!import_node_fs18.default.existsSync(import_node_path14.default.join(dir, ".sail"))) {
|
|
44252
44341
|
throw new Error(
|
|
44253
44342
|
`No .sail/ found in ${dir}.
|
|
44254
44343
|
Run this from your Sailor project root, or pass --project <path>. (The installer does not search parent directories \u2014 that would risk targeting the wrong project.)`
|
|
@@ -44260,7 +44349,7 @@ function passphraseReadiness(projectDir) {
|
|
|
44260
44349
|
const account2 = (() => {
|
|
44261
44350
|
try {
|
|
44262
44351
|
return JSON.parse(
|
|
44263
|
-
|
|
44352
|
+
import_node_fs18.default.readFileSync(import_node_path14.default.join(projectDir, ".sail", "account.json"), "utf-8")
|
|
44264
44353
|
);
|
|
44265
44354
|
} catch {
|
|
44266
44355
|
return null;
|
|
@@ -44276,28 +44365,28 @@ function passphraseReadiness(projectDir) {
|
|
|
44276
44365
|
} finally {
|
|
44277
44366
|
process.chdir(prevCwd);
|
|
44278
44367
|
}
|
|
44279
|
-
const env = parseEnvFile(
|
|
44368
|
+
const env = parseEnvFile(import_node_path14.default.join(projectDir, ".sail", ".env.local"));
|
|
44280
44369
|
const passphraseInEnvFile = Boolean(env.SAIL_PASSPHRASE);
|
|
44281
44370
|
return { keystorePresent, passphraseInEnvFile, ready: keystorePresent && passphraseInEnvFile };
|
|
44282
44371
|
}
|
|
44283
44372
|
function buildConfig(opts) {
|
|
44284
44373
|
const projectDir = resolveProjectDir(opts.project);
|
|
44285
44374
|
return {
|
|
44286
|
-
projectName: sanitizeName(
|
|
44375
|
+
projectName: sanitizeName(import_node_path14.default.basename(projectDir)),
|
|
44287
44376
|
projectDir,
|
|
44288
44377
|
nodePath: process.execPath,
|
|
44289
44378
|
cliEntry: resolveCliEntry(),
|
|
44290
|
-
logPath:
|
|
44379
|
+
logPath: import_node_path14.default.join(projectDir, ".sail", "agent.log"),
|
|
44291
44380
|
interval: opts.interval != null ? Number(opts.interval) : void 0,
|
|
44292
44381
|
chain: opts.chain != null ? Number(opts.chain) : void 0,
|
|
44293
44382
|
restartSec: 30
|
|
44294
44383
|
};
|
|
44295
44384
|
}
|
|
44296
44385
|
function plistPath(projectName) {
|
|
44297
|
-
return
|
|
44386
|
+
return import_node_path14.default.join(import_node_os.default.homedir(), "Library", "LaunchAgents", `${launchdLabel(projectName)}.plist`);
|
|
44298
44387
|
}
|
|
44299
44388
|
function systemdPath(projectName) {
|
|
44300
|
-
return
|
|
44389
|
+
return import_node_path14.default.join(import_node_os.default.homedir(), ".config", "systemd", "user", systemdUnitName(projectName));
|
|
44301
44390
|
}
|
|
44302
44391
|
async function serviceInstall(opts = {}) {
|
|
44303
44392
|
const cfg = buildConfig(opts);
|
|
@@ -44321,12 +44410,12 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
44321
44410
|
console.warn(`\u26A0 ${msg}
|
|
44322
44411
|
Proceeding because --force was given.`);
|
|
44323
44412
|
}
|
|
44324
|
-
|
|
44413
|
+
import_node_fs18.default.mkdirSync(import_node_path14.default.dirname(cfg.logPath), { recursive: true });
|
|
44325
44414
|
if (platform === "darwin") {
|
|
44326
44415
|
const plist = buildLaunchdPlist(cfg);
|
|
44327
44416
|
const dest = plistPath(cfg.projectName);
|
|
44328
|
-
|
|
44329
|
-
|
|
44417
|
+
import_node_fs18.default.mkdirSync(import_node_path14.default.dirname(dest), { recursive: true });
|
|
44418
|
+
import_node_fs18.default.writeFileSync(dest, plist);
|
|
44330
44419
|
const uid2 = process.getuid?.() ?? 0;
|
|
44331
44420
|
try {
|
|
44332
44421
|
try {
|
|
@@ -44345,8 +44434,8 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
44345
44434
|
if (platform === "linux") {
|
|
44346
44435
|
const unit = buildSystemdUnit(cfg);
|
|
44347
44436
|
const dest = systemdPath(cfg.projectName);
|
|
44348
|
-
|
|
44349
|
-
|
|
44437
|
+
import_node_fs18.default.mkdirSync(import_node_path14.default.dirname(dest), { recursive: true });
|
|
44438
|
+
import_node_fs18.default.writeFileSync(dest, unit);
|
|
44350
44439
|
try {
|
|
44351
44440
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
|
|
44352
44441
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "enable", "--now", systemdUnitName(cfg.projectName)], {
|
|
@@ -44360,8 +44449,8 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
44360
44449
|
}
|
|
44361
44450
|
if (platform === "win32") {
|
|
44362
44451
|
const xml = buildWindowsTaskXml(cfg);
|
|
44363
|
-
const dest =
|
|
44364
|
-
|
|
44452
|
+
const dest = import_node_path14.default.join(import_node_os.default.tmpdir(), `${windowsTaskName(cfg.projectName)}.xml`);
|
|
44453
|
+
import_node_fs18.default.writeFileSync(dest, xml, "utf-8");
|
|
44365
44454
|
try {
|
|
44366
44455
|
(0, import_node_child_process2.execFileSync)(
|
|
44367
44456
|
"schtasks",
|
|
@@ -44372,7 +44461,7 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
44372
44461
|
throw new Error(`schtasks /Create failed: ${err.message}`);
|
|
44373
44462
|
} finally {
|
|
44374
44463
|
try {
|
|
44375
|
-
|
|
44464
|
+
import_node_fs18.default.rmSync(dest, { force: true });
|
|
44376
44465
|
} catch {
|
|
44377
44466
|
}
|
|
44378
44467
|
}
|
|
@@ -44398,14 +44487,14 @@ function okInstall(cfg, unit) {
|
|
|
44398
44487
|
);
|
|
44399
44488
|
}
|
|
44400
44489
|
async function serviceStatus(opts = {}) {
|
|
44401
|
-
const projectName = sanitizeName(
|
|
44490
|
+
const projectName = sanitizeName(import_node_path14.default.basename(resolveProjectDir(opts.project)));
|
|
44402
44491
|
const platform = process.platform;
|
|
44403
44492
|
let installed = false;
|
|
44404
44493
|
let running = false;
|
|
44405
44494
|
let detail = "";
|
|
44406
44495
|
try {
|
|
44407
44496
|
if (platform === "darwin") {
|
|
44408
|
-
installed =
|
|
44497
|
+
installed = import_node_fs18.default.existsSync(plistPath(projectName));
|
|
44409
44498
|
const uid2 = process.getuid?.() ?? 0;
|
|
44410
44499
|
try {
|
|
44411
44500
|
detail = (0, import_node_child_process2.execFileSync)("launchctl", ["print", `gui/${uid2}/${launchdLabel(projectName)}`], {
|
|
@@ -44417,7 +44506,7 @@ async function serviceStatus(opts = {}) {
|
|
|
44417
44506
|
} catch {
|
|
44418
44507
|
}
|
|
44419
44508
|
} else if (platform === "linux") {
|
|
44420
|
-
installed =
|
|
44509
|
+
installed = import_node_fs18.default.existsSync(systemdPath(projectName));
|
|
44421
44510
|
try {
|
|
44422
44511
|
detail = (0, import_node_child_process2.execFileSync)("systemctl", ["--user", "is-active", systemdUnitName(projectName)], {
|
|
44423
44512
|
encoding: "utf-8",
|
|
@@ -44453,7 +44542,7 @@ async function serviceStatus(opts = {}) {
|
|
|
44453
44542
|
);
|
|
44454
44543
|
}
|
|
44455
44544
|
async function serviceStop(opts = {}) {
|
|
44456
|
-
const projectName = sanitizeName(
|
|
44545
|
+
const projectName = sanitizeName(import_node_path14.default.basename(resolveProjectDir(opts.project)));
|
|
44457
44546
|
const platform = process.platform;
|
|
44458
44547
|
if (platform === "darwin") {
|
|
44459
44548
|
const uid2 = process.getuid?.() ?? 0;
|
|
@@ -44472,7 +44561,7 @@ async function serviceStop(opts = {}) {
|
|
|
44472
44561
|
});
|
|
44473
44562
|
}
|
|
44474
44563
|
async function serviceUninstall(opts = {}) {
|
|
44475
|
-
const projectName = sanitizeName(
|
|
44564
|
+
const projectName = sanitizeName(import_node_path14.default.basename(resolveProjectDir(opts.project)));
|
|
44476
44565
|
const platform = process.platform;
|
|
44477
44566
|
if (platform === "darwin") {
|
|
44478
44567
|
const uid2 = process.getuid?.() ?? 0;
|
|
@@ -44482,7 +44571,7 @@ async function serviceUninstall(opts = {}) {
|
|
|
44482
44571
|
});
|
|
44483
44572
|
} catch {
|
|
44484
44573
|
}
|
|
44485
|
-
|
|
44574
|
+
import_node_fs18.default.rmSync(plistPath(projectName), { force: true });
|
|
44486
44575
|
} else if (platform === "linux") {
|
|
44487
44576
|
try {
|
|
44488
44577
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "disable", "--now", systemdUnitName(projectName)], {
|
|
@@ -44490,7 +44579,7 @@ async function serviceUninstall(opts = {}) {
|
|
|
44490
44579
|
});
|
|
44491
44580
|
} catch {
|
|
44492
44581
|
}
|
|
44493
|
-
|
|
44582
|
+
import_node_fs18.default.rmSync(systemdPath(projectName), { force: true });
|
|
44494
44583
|
try {
|
|
44495
44584
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "daemon-reload"], { stdio: "ignore" });
|
|
44496
44585
|
} catch {
|
|
@@ -44508,21 +44597,21 @@ async function serviceUninstall(opts = {}) {
|
|
|
44508
44597
|
}
|
|
44509
44598
|
async function serviceLogs(opts = {}) {
|
|
44510
44599
|
const projectDir = resolveProjectDir(opts.project);
|
|
44511
|
-
const logPath =
|
|
44512
|
-
if (!
|
|
44600
|
+
const logPath = import_node_path14.default.join(projectDir, ".sail", "agent.log");
|
|
44601
|
+
if (!import_node_fs18.default.existsSync(logPath)) {
|
|
44513
44602
|
console.log(`No log yet at ${logPath}. The service writes here once it runs.`);
|
|
44514
44603
|
return;
|
|
44515
44604
|
}
|
|
44516
44605
|
if (opts.follow) {
|
|
44517
44606
|
if (process.platform === "win32") {
|
|
44518
|
-
console.log(
|
|
44607
|
+
console.log(import_node_fs18.default.readFileSync(logPath, "utf-8"));
|
|
44519
44608
|
console.log("(follow mode is not supported on Windows here \u2014 re-run to refresh)");
|
|
44520
44609
|
return;
|
|
44521
44610
|
}
|
|
44522
44611
|
(0, import_node_child_process2.execFileSync)("tail", ["-f", logPath], { stdio: "inherit" });
|
|
44523
44612
|
return;
|
|
44524
44613
|
}
|
|
44525
|
-
const lines =
|
|
44614
|
+
const lines = import_node_fs18.default.readFileSync(logPath, "utf-8").split("\n");
|
|
44526
44615
|
console.log(lines.slice(-200).join("\n"));
|
|
44527
44616
|
}
|
|
44528
44617
|
|
|
@@ -44676,14 +44765,14 @@ async function sessionResume() {
|
|
|
44676
44765
|
}
|
|
44677
44766
|
|
|
44678
44767
|
// src/commands/station.ts
|
|
44679
|
-
var
|
|
44680
|
-
var
|
|
44681
|
-
var RUNTIME_SERVER_FILE2 = (0,
|
|
44768
|
+
var import_node_fs19 = require("node:fs");
|
|
44769
|
+
var import_node_path15 = require("node:path");
|
|
44770
|
+
var RUNTIME_SERVER_FILE2 = (0, import_node_path15.join)(".sail", "runtime", "server.json");
|
|
44682
44771
|
function readState(projectRoot) {
|
|
44683
|
-
const file = (0,
|
|
44684
|
-
if (!(0,
|
|
44772
|
+
const file = (0, import_node_path15.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
44773
|
+
if (!(0, import_node_fs19.existsSync)(file)) return null;
|
|
44685
44774
|
try {
|
|
44686
|
-
return JSON.parse((0,
|
|
44775
|
+
return JSON.parse((0, import_node_fs19.readFileSync)(file, "utf8"));
|
|
44687
44776
|
} catch {
|
|
44688
44777
|
return null;
|
|
44689
44778
|
}
|
|
@@ -44755,9 +44844,9 @@ async function stationStop(options) {
|
|
|
44755
44844
|
}
|
|
44756
44845
|
const daemon = await discoverDaemon(projectRoot);
|
|
44757
44846
|
if (!daemon) {
|
|
44758
|
-
const file = (0,
|
|
44847
|
+
const file = (0, import_node_path15.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
44759
44848
|
try {
|
|
44760
|
-
if ((0,
|
|
44849
|
+
if ((0, import_node_fs19.existsSync)(file)) (0, import_node_fs19.rmSync)(file);
|
|
44761
44850
|
} catch {
|
|
44762
44851
|
}
|
|
44763
44852
|
emit(options.json, () => console.log("Station process not found; cleared stale state."), {
|
|
@@ -44773,9 +44862,9 @@ async function stationStop(options) {
|
|
|
44773
44862
|
pid: state.pid
|
|
44774
44863
|
});
|
|
44775
44864
|
} catch {
|
|
44776
|
-
const file = (0,
|
|
44865
|
+
const file = (0, import_node_path15.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
44777
44866
|
try {
|
|
44778
|
-
if ((0,
|
|
44867
|
+
if ((0, import_node_fs19.existsSync)(file)) (0, import_node_fs19.rmSync)(file);
|
|
44779
44868
|
} catch {
|
|
44780
44869
|
}
|
|
44781
44870
|
emit(options.json, () => console.log("Station process not found; cleared stale state."), {
|
|
@@ -44830,15 +44919,15 @@ async function status() {
|
|
|
44830
44919
|
|
|
44831
44920
|
// src/commands/ui.ts
|
|
44832
44921
|
var import_node_child_process4 = require("node:child_process");
|
|
44833
|
-
var
|
|
44922
|
+
var import_node_fs20 = __toESM(require("node:fs"), 1);
|
|
44834
44923
|
var import_node_net2 = __toESM(require("node:net"), 1);
|
|
44835
|
-
var
|
|
44836
|
-
var UI_STATE_FILE =
|
|
44924
|
+
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
44925
|
+
var UI_STATE_FILE = import_node_path16.default.join(".sail", "runtime", "ui.json");
|
|
44837
44926
|
function readState2(projectRoot) {
|
|
44838
|
-
const file =
|
|
44839
|
-
if (!
|
|
44927
|
+
const file = import_node_path16.default.join(projectRoot, UI_STATE_FILE);
|
|
44928
|
+
if (!import_node_fs20.default.existsSync(file)) return null;
|
|
44840
44929
|
try {
|
|
44841
|
-
return JSON.parse(
|
|
44930
|
+
return JSON.parse(import_node_fs20.default.readFileSync(file, "utf-8"));
|
|
44842
44931
|
} catch {
|
|
44843
44932
|
return null;
|
|
44844
44933
|
}
|
|
@@ -44879,15 +44968,15 @@ function waitForPort(port, timeoutMs) {
|
|
|
44879
44968
|
}
|
|
44880
44969
|
async function uiCommand() {
|
|
44881
44970
|
const distDir = cliDistDir();
|
|
44882
|
-
const uiDistDir =
|
|
44883
|
-
const serverBundle =
|
|
44971
|
+
const uiDistDir = import_node_path16.default.join(packageRoot(), "packages", "ui", "dist");
|
|
44972
|
+
const serverBundle = import_node_path16.default.resolve(distDir, "server.cjs");
|
|
44884
44973
|
const projectRoot = process.cwd();
|
|
44885
|
-
const sailDir2 =
|
|
44974
|
+
const sailDir2 = import_node_path16.default.join(projectRoot, ".sail");
|
|
44886
44975
|
const port = await findFreePort(projectPort(projectRoot));
|
|
44887
|
-
if (!
|
|
44976
|
+
if (!import_node_fs20.default.existsSync(serverBundle)) {
|
|
44888
44977
|
throw new Error(`Server bundle not found at ${serverBundle}. Re-run the sailor build.`);
|
|
44889
44978
|
}
|
|
44890
|
-
if (!
|
|
44979
|
+
if (!import_node_fs20.default.existsSync(import_node_path16.default.join(uiDistDir, "index.html"))) {
|
|
44891
44980
|
throw new Error(`UI dist not found at ${uiDistDir}. Re-run the sailor build.`);
|
|
44892
44981
|
}
|
|
44893
44982
|
const existing = readState2(projectRoot);
|
|
@@ -44895,17 +44984,17 @@ async function uiCommand() {
|
|
|
44895
44984
|
console.log(`Sailor UI is already running (pid ${existing.pid}) at http://localhost:${existing.port}`);
|
|
44896
44985
|
return;
|
|
44897
44986
|
}
|
|
44898
|
-
const runtimeDir =
|
|
44899
|
-
|
|
44900
|
-
const logFile =
|
|
44901
|
-
const logFd =
|
|
44987
|
+
const runtimeDir = import_node_path16.default.join(projectRoot, ".sail", "runtime");
|
|
44988
|
+
import_node_fs20.default.mkdirSync(runtimeDir, { recursive: true });
|
|
44989
|
+
const logFile = import_node_path16.default.join(runtimeDir, "ui.log");
|
|
44990
|
+
const logFd = import_node_fs20.default.openSync(logFile, "a");
|
|
44902
44991
|
const child = (0, import_node_child_process4.spawn)(process.execPath, [serverBundle], {
|
|
44903
44992
|
detached: true,
|
|
44904
44993
|
stdio: ["ignore", logFd, logFd],
|
|
44905
44994
|
env: { ...process.env, SAIL_DIR: sailDir2, SERVE_DIST: "1", PORT: String(port), SAILOR_UI_DIST: uiDistDir }
|
|
44906
44995
|
});
|
|
44907
44996
|
child.unref();
|
|
44908
|
-
|
|
44997
|
+
import_node_fs20.default.closeSync(logFd);
|
|
44909
44998
|
const READY_TIMEOUT_MS = 1e4;
|
|
44910
44999
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
44911
45000
|
let ready = false;
|
|
@@ -44919,18 +45008,18 @@ async function uiCommand() {
|
|
|
44919
45008
|
if (!ready) {
|
|
44920
45009
|
let tail = "";
|
|
44921
45010
|
try {
|
|
44922
|
-
tail =
|
|
45011
|
+
tail = import_node_fs20.default.readFileSync(logFile, "utf-8").split("\n").filter(Boolean).slice(-15).join("\n");
|
|
44923
45012
|
} catch {
|
|
44924
45013
|
}
|
|
44925
45014
|
throw new Error(
|
|
44926
45015
|
`Sailor UI failed to start within ${READY_TIMEOUT_MS / 1e3}s on port ${port}.` + (tail ? `
|
|
44927
45016
|
|
|
44928
45017
|
Server output:
|
|
44929
|
-
${tail}` : ` See ${
|
|
45018
|
+
${tail}` : ` See ${import_node_path16.default.relative(projectRoot, logFile)}.`)
|
|
44930
45019
|
);
|
|
44931
45020
|
}
|
|
44932
|
-
|
|
44933
|
-
|
|
45021
|
+
import_node_fs20.default.writeFileSync(
|
|
45022
|
+
import_node_path16.default.join(projectRoot, UI_STATE_FILE),
|
|
44934
45023
|
JSON.stringify({ pid: child.pid, port, startedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
|
|
44935
45024
|
);
|
|
44936
45025
|
console.log(`Sailor UI started at http://localhost:${port} (pid ${child.pid})`);
|
|
@@ -44941,7 +45030,7 @@ function uiStatus() {
|
|
|
44941
45030
|
if (state && isAlive(state.pid)) {
|
|
44942
45031
|
console.log(`\u25CF running http://localhost:${state.port} (pid ${state.pid})`);
|
|
44943
45032
|
} else {
|
|
44944
|
-
if (state)
|
|
45033
|
+
if (state) import_node_fs20.default.rmSync(import_node_path16.default.join(process.cwd(), UI_STATE_FILE), { force: true });
|
|
44945
45034
|
console.log("\u25CB Sailor UI is not running");
|
|
44946
45035
|
}
|
|
44947
45036
|
}
|
|
@@ -44953,19 +45042,19 @@ function uiStop() {
|
|
|
44953
45042
|
return;
|
|
44954
45043
|
}
|
|
44955
45044
|
if (!isAlive(state.pid)) {
|
|
44956
|
-
|
|
45045
|
+
import_node_fs20.default.rmSync(import_node_path16.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
44957
45046
|
console.log("Sailor UI is not running (stale state file removed).");
|
|
44958
45047
|
return;
|
|
44959
45048
|
}
|
|
44960
45049
|
process.kill(state.pid, "SIGTERM");
|
|
44961
|
-
|
|
45050
|
+
import_node_fs20.default.rmSync(import_node_path16.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
44962
45051
|
console.log(`Stopped Sailor UI (pid ${state.pid}).`);
|
|
44963
45052
|
}
|
|
44964
45053
|
|
|
44965
45054
|
// src/index.ts
|
|
44966
45055
|
function cliVersion() {
|
|
44967
45056
|
try {
|
|
44968
|
-
const pkg = JSON.parse((0,
|
|
45057
|
+
const pkg = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path17.join)(packageRoot(), "package.json"), "utf-8"));
|
|
44969
45058
|
return pkg.version ?? "0.0.0";
|
|
44970
45059
|
} catch {
|
|
44971
45060
|
return "0.0.0";
|
|
@@ -45007,6 +45096,7 @@ program2.command("init [dir]").description("Scaffold a new Sail agent into the c
|
|
|
45007
45096
|
}
|
|
45008
45097
|
}
|
|
45009
45098
|
);
|
|
45099
|
+
program2.command("update").description("Re-sync agent tooling files (skills, AGENTS.md, Dockerfile) from the latest template").action(action(updateCommand));
|
|
45010
45100
|
var ui = program2.command("ui").description("Manage the local Sailor dashboard");
|
|
45011
45101
|
ui.command("start").description("Start the dashboard at localhost:3333 (default)").action(action(uiCommand));
|
|
45012
45102
|
ui.command("stop").description("Stop the running dashboard").action(() => uiStop());
|