@dev.sail.money/sailor 1.1.0-48 → 1.1.0-50

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev.sail.money/sailor",
3
- "version": "1.1.0-48",
3
+ "version": "1.1.0-50",
4
4
  "description": "Operator toolkit for Sail Protocol",
5
5
  "bin": {
6
6
  "sailor": "packages/cli/dist/index.cjs"
@@ -42509,28 +42509,32 @@ function parseRequires(src) {
42509
42509
  }
42510
42510
 
42511
42511
  // src/commands/mandate.ts
42512
- async function fetchOnChainPermissions(account2) {
42512
+ function resolveActiveChain(account2) {
42513
42513
  try {
42514
42514
  const project = new ProjectContext();
42515
- const rpcUrl = getRpcUrl(project.chainId) ?? getChainById(project.chainId).rpcUrls.default.http[0];
42516
- const pc = createPublicClient({
42517
- chain: getChainById(project.chainId),
42518
- transport: http(rpcUrl)
42519
- });
42515
+ return { chainId: project.chainId, kernel: project.contracts.kernel };
42516
+ } catch {
42517
+ return { chainId: account2.chainId, kernel: null };
42518
+ }
42519
+ }
42520
+ async function fetchOnChainPermissions(safe, chainId, kernel) {
42521
+ try {
42522
+ const rpcUrl = getRpcUrl(chainId) ?? getChainById(chainId).rpcUrls.default.http[0];
42523
+ const pc = createPublicClient({ chain: getChainById(chainId), transport: http(rpcUrl) });
42520
42524
  const onChain = await pc.readContract({
42521
- address: project.contracts.kernel,
42525
+ address: kernel,
42522
42526
  abi: SailKernelAbi,
42523
42527
  functionName: "getPermissions",
42524
- args: [account2.safe]
42528
+ args: [safe]
42525
42529
  });
42526
42530
  return new Set(onChain.map((a) => a.toLowerCase()));
42527
42531
  } catch {
42528
42532
  return null;
42529
42533
  }
42530
42534
  }
42531
- async function trackedPermissionsFor(account2) {
42535
+ async function trackedPermissionsFor(account2, chainId, kernel) {
42532
42536
  const store = new MandateStore();
42533
- const local = store.list().filter((m) => m.chainId === account2.chainId).map((m) => {
42537
+ const local = store.list().filter((m) => m.chainId === chainId).map((m) => {
42534
42538
  const attachment = m.attachments?.find(
42535
42539
  (a) => a.sma.toLowerCase() === account2.safe.toLowerCase()
42536
42540
  );
@@ -42541,7 +42545,7 @@ async function trackedPermissionsFor(account2) {
42541
42545
  attachedAt: attachment?.at
42542
42546
  };
42543
42547
  });
42544
- const onChain = await fetchOnChainPermissions(account2);
42548
+ const onChain = kernel ? await fetchOnChainPermissions(account2.safe, chainId, kernel) : null;
42545
42549
  if (onChain !== null) {
42546
42550
  for (const p of local) {
42547
42551
  if (p.registeredOnSma && !onChain.has(p.address.toLowerCase())) {
@@ -42561,7 +42565,8 @@ async function mandatePrepare() {
42561
42565
  if (!account2) {
42562
42566
  throw new Error('No account found at .sail/account.json.\nRun "sailor onboard --new-sma" first.');
42563
42567
  }
42564
- const permissions = await trackedPermissionsFor(account2);
42568
+ const { chainId, kernel } = resolveActiveChain(account2);
42569
+ const permissions = await trackedPermissionsFor(account2, chainId, kernel);
42565
42570
  if (permissions.length === 0) {
42566
42571
  printNoPermissionsGuidance();
42567
42572
  return;
@@ -42578,7 +42583,7 @@ ${permissions.length} permission(s) tracked for SMA ${account2.safe}:
42578
42583
  const store = new MandateStore();
42579
42584
  const draft = {
42580
42585
  account: account2.safe,
42581
- chainId: account2.chainId,
42586
+ chainId,
42582
42587
  permissions: permissions.filter((p) => !p.revokedOnChain).map((p) => {
42583
42588
  const mandate2 = store.find(p.address);
42584
42589
  const explanation = explainPermission(p.label, mandate2?.sourcePath) ?? void 0;
@@ -42594,7 +42599,8 @@ async function mandateSign(opts = {}) {
42594
42599
  if (!account2) {
42595
42600
  throw new Error('No account found at .sail/account.json.\nRun "sailor onboard --new-sma" first.');
42596
42601
  }
42597
- const permissions = await trackedPermissionsFor(account2);
42602
+ const { chainId, kernel } = resolveActiveChain(account2);
42603
+ const permissions = await trackedPermissionsFor(account2, chainId, kernel);
42598
42604
  if (permissions.length === 0) {
42599
42605
  printNoPermissionsGuidance();
42600
42606
  return;
@@ -42634,7 +42640,7 @@ ${unregistered.length} permission(s) are not yet registered on this SMA. Initiat
42634
42640
  }
42635
42641
  const storedMandate = {
42636
42642
  safe: account2.safe,
42637
- chainId: account2.chainId,
42643
+ chainId,
42638
42644
  signedAt: (/* @__PURE__ */ new Date()).toISOString(),
42639
42645
  signature: "",
42640
42646
  registeredOnChain: true,
@@ -42643,7 +42649,10 @@ ${unregistered.length} permission(s) are not yet registered on this SMA. Initiat
42643
42649
  };
42644
42650
  const existingRaw = readJsonFile(sailPath("mandate.json"));
42645
42651
  const existing = existingRaw ? Array.isArray(existingRaw) ? existingRaw : [existingRaw] : [];
42646
- writeJsonFile(sailPath("mandate.json"), [...existing, storedMandate]);
42652
+ const deduped = existing.filter(
42653
+ (m) => !(m.safe?.toLowerCase() === account2.safe.toLowerCase() && m.chainId === chainId)
42654
+ );
42655
+ writeJsonFile(sailPath("mandate.json"), [...deduped, storedMandate]);
42647
42656
  console.log(`
42648
42657
  \u2713 Saved to .sail/mandate.json \u2014 agent is ready to run.`);
42649
42658
  }
@@ -44213,6 +44222,24 @@ function findFreePort(from14) {
44213
44222
  server.listen(from14, "127.0.0.1", () => server.close(() => resolve3(from14)));
44214
44223
  });
44215
44224
  }
44225
+ function waitForPort(port, timeoutMs) {
44226
+ const deadline = Date.now() + timeoutMs;
44227
+ return new Promise((resolve3) => {
44228
+ const attempt = () => {
44229
+ const socket = import_node_net2.default.connect(port, "127.0.0.1");
44230
+ socket.once("connect", () => {
44231
+ socket.destroy();
44232
+ resolve3(true);
44233
+ });
44234
+ socket.once("error", () => {
44235
+ socket.destroy();
44236
+ if (Date.now() > deadline) resolve3(false);
44237
+ else setTimeout(attempt, 150);
44238
+ });
44239
+ };
44240
+ attempt();
44241
+ });
44242
+ }
44216
44243
  async function uiCommand() {
44217
44244
  const distDir = cliDistDir();
44218
44245
  const uiDistDir = import_node_path13.default.join(packageRoot(), "packages", "ui", "dist");
@@ -44231,17 +44258,40 @@ async function uiCommand() {
44231
44258
  console.log(`Sailor UI is already running (pid ${existing.pid}) at http://localhost:${existing.port}`);
44232
44259
  return;
44233
44260
  }
44261
+ const runtimeDir = import_node_path13.default.join(projectRoot, ".sail", "runtime");
44262
+ import_node_fs17.default.mkdirSync(runtimeDir, { recursive: true });
44263
+ const logFile = import_node_path13.default.join(runtimeDir, "ui.log");
44264
+ const logFd = import_node_fs17.default.openSync(logFile, "a");
44234
44265
  const child = (0, import_node_child_process2.spawn)(process.execPath, [serverBundle], {
44235
44266
  detached: true,
44236
- stdio: "ignore",
44267
+ stdio: ["ignore", logFd, logFd],
44237
44268
  env: { ...process.env, SAIL_DIR: sailDir2, SERVE_DIST: "1", PORT: String(port), SAILOR_UI_DIST: uiDistDir }
44238
44269
  });
44239
44270
  child.unref();
44240
- await new Promise((r) => setTimeout(r, 300));
44241
- if (!isAlive(child.pid)) {
44242
- throw new Error(`Sailor UI process exited immediately. Check that the server bundle is intact.`);
44271
+ import_node_fs17.default.closeSync(logFd);
44272
+ const READY_TIMEOUT_MS = 1e4;
44273
+ const deadline = Date.now() + READY_TIMEOUT_MS;
44274
+ let ready = false;
44275
+ while (Date.now() < deadline) {
44276
+ if (!isAlive(child.pid)) break;
44277
+ if (await waitForPort(port, 500)) {
44278
+ ready = true;
44279
+ break;
44280
+ }
44281
+ }
44282
+ if (!ready) {
44283
+ let tail = "";
44284
+ try {
44285
+ tail = import_node_fs17.default.readFileSync(logFile, "utf-8").split("\n").filter(Boolean).slice(-15).join("\n");
44286
+ } catch {
44287
+ }
44288
+ throw new Error(
44289
+ `Sailor UI failed to start within ${READY_TIMEOUT_MS / 1e3}s on port ${port}.` + (tail ? `
44290
+
44291
+ Server output:
44292
+ ${tail}` : ` See ${import_node_path13.default.relative(projectRoot, logFile)}.`)
44293
+ );
44243
44294
  }
44244
- import_node_fs17.default.mkdirSync(import_node_path13.default.join(projectRoot, ".sail", "runtime"), { recursive: true });
44245
44295
  import_node_fs17.default.writeFileSync(
44246
44296
  import_node_path13.default.join(projectRoot, UI_STATE_FILE),
44247
44297
  JSON.stringify({ pid: child.pid, port, startedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
@@ -5,7 +5,7 @@
5
5
  * Do not edit manually — run `pnpm build` to regenerate.
6
6
  *
7
7
  * Spec version : 1.2.0
8
- * Generated at : 2026-06-15T11:50:59.262Z
8
+ * Generated at : 2026-06-15T12:32:25.357Z
9
9
  */
10
10
  export declare const SAIL_INTELLIGENCE_BASE_URL = "https://api.sail.money";
11
11
  export declare const SAIL_INTELLIGENCE_DOCS_URL = "https://api.sail.money/docs";
@@ -5,7 +5,7 @@
5
5
  * Do not edit manually — run `pnpm build` to regenerate.
6
6
  *
7
7
  * Spec version : 1.2.0
8
- * Generated at : 2026-06-15T11:50:59.262Z
8
+ * Generated at : 2026-06-15T12:32:25.357Z
9
9
  */
10
10
  export const SAIL_INTELLIGENCE_BASE_URL = "https://api.sail.money";
11
11
  export const SAIL_INTELLIGENCE_DOCS_URL = "https://api.sail.money/docs";