@dev.sail.money/sailor 1.3.0-225 → 1.3.0-227

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.
Files changed (128) hide show
  1. package/README.md +16 -0
  2. package/examples/custom-mandate/.sail/contracts/interfaces/IPermission.sol +4 -0
  3. package/examples/custom-mandate/README.md +4 -1
  4. package/examples/permissions/interfaces/IBatchPermission.sol +2 -0
  5. package/examples/permissions/interfaces/IPermission.sol +4 -0
  6. package/package.json +7 -1
  7. package/packages/cli/dist/index.cjs +58 -10
  8. package/packages/cli/dist/server.cjs +105 -23
  9. package/packages/sdk/dist/intelligence.d.ts +1 -1
  10. package/packages/sdk/dist/intelligence.js +1 -1
  11. package/packages/ui/dist/assets/{add-QIu9SGBU.js → add-DoHGZfJI.js} +2 -2
  12. package/packages/ui/dist/assets/{all-wallets-2auxp9E5.js → all-wallets-CUKVFyT3.js} +2 -2
  13. package/packages/ui/dist/assets/{app-store-BVtVvk-F.js → app-store-DyQ4PZOs.js} +1 -1
  14. package/packages/ui/dist/assets/{apple-Dq7Ppvqv.js → apple-Dc-GOiDW.js} +2 -2
  15. package/packages/ui/dist/assets/arrow-bottom-C-dI8Oh_.js +8 -0
  16. package/packages/ui/dist/assets/{arrow-bottom-circle-hkf9bWhW.js → arrow-bottom-circle-BH2LebvP.js} +2 -2
  17. package/packages/ui/dist/assets/arrow-left-CUIn5NsD.js +8 -0
  18. package/packages/ui/dist/assets/arrow-right-B-X57DDF.js +8 -0
  19. package/packages/ui/dist/assets/arrow-top-BNOmzVbg.js +8 -0
  20. package/packages/ui/dist/assets/{bank-CkRSSgJy.js → bank-Dqcy3Map.js} +2 -2
  21. package/packages/ui/dist/assets/{basic-D9puI79I.js → basic-CN95kOlB.js} +177 -177
  22. package/packages/ui/dist/assets/{browser-BC8qo0Bh.js → browser-v-WzD6Au.js} +2 -2
  23. package/packages/ui/dist/assets/{card-BYuGTxNc.js → card-DJmQXuOi.js} +2 -2
  24. package/packages/ui/dist/assets/ccip-8oS512uk.js +1 -0
  25. package/packages/ui/dist/assets/{checkmark-C-MZeapS.js → checkmark-6Rvy6Al7.js} +2 -2
  26. package/packages/ui/dist/assets/{checkmark-bold-Bs3hadsW.js → checkmark-bold-GYXSMFUr.js} +2 -2
  27. package/packages/ui/dist/assets/chevron-bottom-BF1Fa2NO.js +8 -0
  28. package/packages/ui/dist/assets/chevron-left-kj9KjPLp.js +8 -0
  29. package/packages/ui/dist/assets/chevron-right-CHH0lg7_.js +8 -0
  30. package/packages/ui/dist/assets/chevron-top-DjHmnG32.js +8 -0
  31. package/packages/ui/dist/assets/{chrome-store-sDKm_6es.js → chrome-store-KzNe4H9H.js} +2 -2
  32. package/packages/ui/dist/assets/{clock-BwfFymxk.js → clock-xHvMNQNx.js} +2 -2
  33. package/packages/ui/dist/assets/{close-BewD5_E0.js → close-nKtgX0WM.js} +2 -2
  34. package/packages/ui/dist/assets/{coinPlaceholder-DRPvf0NA.js → coinPlaceholder-gnwD3g4G.js} +2 -2
  35. package/packages/ui/dist/assets/{compass-BHPvd2dw.js → compass-wnLBxh3w.js} +2 -2
  36. package/packages/ui/dist/assets/{copy-BMv4Y3KF.js → copy-CmLisiOG.js} +2 -2
  37. package/packages/ui/dist/assets/core-BLOM5s8O.js +907 -0
  38. package/packages/ui/dist/assets/cursor-DgwjrlpZ.js +3 -0
  39. package/packages/ui/dist/assets/{cursor-transparent-DT8YBqHU.js → cursor-transparent-CjVDknUI.js} +2 -2
  40. package/packages/ui/dist/assets/{desktop-BeePUUqi.js → desktop-BSGjR5fT.js} +2 -2
  41. package/packages/ui/dist/assets/{disconnect-C2qT29qY.js → disconnect-DkOQ_j9U.js} +2 -2
  42. package/packages/ui/dist/assets/{discord-I4ToELfU.js → discord-DtvZ281_.js} +2 -2
  43. package/packages/ui/dist/assets/{etherscan-3psXC5Ef.js → etherscan-BB3baLbR.js} +2 -2
  44. package/packages/ui/dist/assets/events-DQ172AOg.js +1 -0
  45. package/packages/ui/dist/assets/{exclamation-triangle-BCaWksGJ.js → exclamation-triangle-BrR8a-pR.js} +2 -2
  46. package/packages/ui/dist/assets/{extension-DfYavvbY.js → extension-BiGAMg97.js} +2 -2
  47. package/packages/ui/dist/assets/external-link-qUc7QuKA.js +8 -0
  48. package/packages/ui/dist/assets/{facebook-BSvrXy3w.js → facebook-BuXatc22.js} +2 -2
  49. package/packages/ui/dist/assets/{farcaster-CcAuzEDi.js → farcaster-USwPlLU8.js} +2 -2
  50. package/packages/ui/dist/assets/{filters-umCx-UFU.js → filters-BWx3pZxN.js} +2 -2
  51. package/packages/ui/dist/assets/{github-CBNoBl67.js → github-CUSWD7ff.js} +2 -2
  52. package/packages/ui/dist/assets/{google-yyR1jNOC.js → google-CxJSLEaz.js} +2 -2
  53. package/packages/ui/dist/assets/{help-circle-C0WjKnIM.js → help-circle-_8isjSO0.js} +1 -1
  54. package/packages/ui/dist/assets/{id-BwIK6e_N.js → id-DJCzMfx_.js} +2 -2
  55. package/packages/ui/dist/assets/{image-D5oAo1Te.js → image-CmG69MZj.js} +2 -2
  56. package/packages/ui/dist/assets/{index-DMNSiu42.js → index-3YqzzyrK.js} +3 -3
  57. package/packages/ui/dist/assets/index-B07bCKJ8.css +1 -0
  58. package/packages/ui/dist/assets/index-BIqjq0q5.js +1 -0
  59. package/packages/ui/dist/assets/index-BV8s6ez1.js +1 -0
  60. package/packages/ui/dist/assets/index-D8zwDy7d.js +1780 -0
  61. package/packages/ui/dist/assets/index-DHVwxjrm.js +47 -0
  62. package/packages/ui/dist/assets/index-DsxB7ORb.js +16 -0
  63. package/packages/ui/dist/assets/index.es-Hqwz_Ukd.js +26 -0
  64. package/packages/ui/dist/assets/{info-CtcvKk8x.js → info-XYctdUoY.js} +2 -2
  65. package/packages/ui/dist/assets/{info-circle-BIm6XYyt.js → info-circle-D_fYZUhv.js} +2 -2
  66. package/packages/ui/dist/assets/{lightbulb-CMj21RIi.js → lightbulb-BqKkDThe.js} +2 -2
  67. package/packages/ui/dist/assets/{mail-C805tcaU.js → mail-CM4laVWT.js} +2 -2
  68. package/packages/ui/dist/assets/metamask-sdk-8TvB8vxr.js +542 -0
  69. package/packages/ui/dist/assets/{mobile-BEii3NyZ.js → mobile-C2cl_MIN.js} +2 -2
  70. package/packages/ui/dist/assets/{more-RSnRt81X.js → more-DOik7ytj.js} +2 -2
  71. package/packages/ui/dist/assets/{network-placeholder-s9JaqzCQ.js → network-placeholder-CC9Cg0q_.js} +2 -2
  72. package/packages/ui/dist/assets/{nftPlaceholder-Ccur2yVc.js → nftPlaceholder-Oe_bTYkM.js} +2 -2
  73. package/packages/ui/dist/assets/{off-DUtG4rlI.js → off-ao0Rdo1E.js} +2 -2
  74. package/packages/ui/dist/assets/{play-store-Bt2HvO3e.js → play-store-BcQlROdR.js} +2 -2
  75. package/packages/ui/dist/assets/{plus-BtEzQu0h.js → plus-DSOprccT.js} +2 -2
  76. package/packages/ui/dist/assets/{qr-code-xbQZ-Nio.js → qr-code-B64-C9CJ.js} +1 -1
  77. package/packages/ui/dist/assets/{recycle-horizontal-d9pzE6vq.js → recycle-horizontal-BJg7qNO9.js} +2 -2
  78. package/packages/ui/dist/assets/{refresh-B3-2Sch0.js → refresh-Dexg1q9p.js} +2 -2
  79. package/packages/ui/dist/assets/{reown-logo-DBkmQAX8.js → reown-logo-D8KP4d24.js} +2 -2
  80. package/packages/ui/dist/assets/{search-dgDA8Ou5.js → search-CBfhIhB0.js} +2 -2
  81. package/packages/ui/dist/assets/{secp256k1-C4g4FCze.js → secp256k1-BOKPNuRR.js} +1 -1
  82. package/packages/ui/dist/assets/{send-CEDXr4l7.js → send-DpJV-P0b.js} +2 -2
  83. package/packages/ui/dist/assets/{swapHorizontal-Co6_f8oH.js → swapHorizontal-DC-Elc2j.js} +2 -2
  84. package/packages/ui/dist/assets/{swapHorizontalBold-k4d22FNy.js → swapHorizontalBold-Unn8xI55.js} +2 -2
  85. package/packages/ui/dist/assets/{swapHorizontalMedium-Des6w_mz.js → swapHorizontalMedium-B58RR8wP.js} +2 -2
  86. package/packages/ui/dist/assets/{swapHorizontalRoundedBold-CVd4538j.js → swapHorizontalRoundedBold-UTrbE6zM.js} +2 -2
  87. package/packages/ui/dist/assets/{swapVertical-Cn_eRfv8.js → swapVertical-CLBtBVG1.js} +2 -2
  88. package/packages/ui/dist/assets/{telegram-BE46RC0s.js → telegram-C_tvCVU8.js} +2 -2
  89. package/packages/ui/dist/assets/{three-dots-CvqWsUWa.js → three-dots-BIn_IFa0.js} +2 -2
  90. package/packages/ui/dist/assets/{twitch-9V7YXB0X.js → twitch-BqiEXRul.js} +2 -2
  91. package/packages/ui/dist/assets/{twitterIcon-DbUxk6yk.js → twitterIcon-CquA5TCG.js} +2 -2
  92. package/packages/ui/dist/assets/{verify-CQSnwVrh.js → verify-DOUX5_SE.js} +2 -2
  93. package/packages/ui/dist/assets/{verify-filled-DG_hDTr8.js → verify-filled-nMk53S_a.js} +2 -2
  94. package/packages/ui/dist/assets/{w3m-modal-BsHGIrg7.js → w3m-modal-B-JVYtbP.js} +1 -1
  95. package/packages/ui/dist/assets/{wallet-lbVIReb_.js → wallet-BjbzMOXA.js} +2 -2
  96. package/packages/ui/dist/assets/{wallet-placeholder-C_ndmKAs.js → wallet-placeholder-DPidGoJt.js} +2 -2
  97. package/packages/ui/dist/assets/{walletconnect-ByDpG-E0.js → walletconnect-Dw14KwDj.js} +3 -3
  98. package/packages/ui/dist/assets/{warning-circle-hrS3II0d.js → warning-circle-Ewxxj9bx.js} +2 -2
  99. package/packages/ui/dist/assets/{x-BPMn3x5J.js → x-B5Li_yME.js} +2 -2
  100. package/packages/ui/dist/index.html +2 -2
  101. package/templates/default/.agents/skills/sail-mandates/references/examples-index.md +2 -2
  102. package/templates/default/.agents/skills/sail-servers/SKILL.md +1 -0
  103. package/templates/default/.env.example +9 -0
  104. package/templates/default/test/BoundedCallPermission.t.sol +2 -1
  105. package/packages/ui/dist/assets/arrow-bottom-DpT3R4Rr.js +0 -8
  106. package/packages/ui/dist/assets/arrow-left-3PhiE4SD.js +0 -8
  107. package/packages/ui/dist/assets/arrow-right-DUIXJHib.js +0 -8
  108. package/packages/ui/dist/assets/arrow-top-Cf--02la.js +0 -8
  109. package/packages/ui/dist/assets/ccip-BS_rjbk9.js +0 -1
  110. package/packages/ui/dist/assets/chevron-bottom-C8mqtkD4.js +0 -8
  111. package/packages/ui/dist/assets/chevron-left-Dxj-vVDJ.js +0 -8
  112. package/packages/ui/dist/assets/chevron-right-BoIrOTtL.js +0 -8
  113. package/packages/ui/dist/assets/chevron-top-BlgziB_P.js +0 -8
  114. package/packages/ui/dist/assets/core-BMNH6XFj.js +0 -907
  115. package/packages/ui/dist/assets/cursor-ir0cjMUl.js +0 -3
  116. package/packages/ui/dist/assets/events-Cdt6abbf.js +0 -1
  117. package/packages/ui/dist/assets/external-link-B8uBskz7.js +0 -8
  118. package/packages/ui/dist/assets/fallback-BSMYROva.js +0 -1
  119. package/packages/ui/dist/assets/index-B_Gc8xPp.js +0 -1
  120. package/packages/ui/dist/assets/index-BaEe036r.js +0 -1
  121. package/packages/ui/dist/assets/index-BuqyrXYX.js +0 -16
  122. package/packages/ui/dist/assets/index-CKoOBsKn.css +0 -1
  123. package/packages/ui/dist/assets/index-CPrhuDfP.js +0 -1782
  124. package/packages/ui/dist/assets/index-DCWU1RuS.js +0 -1
  125. package/packages/ui/dist/assets/index.es-DImsg59a.js +0 -26
  126. package/packages/ui/dist/assets/metamask-sdk-DDk4vkrl.js +0 -542
  127. package/packages/ui/dist/assets/native-CJ5et6AR.js +0 -1
  128. package/packages/ui/dist/assets/parseSignature-BbS8pxpB.js +0 -1
package/README.md CHANGED
@@ -295,6 +295,22 @@ the station), set a comma-separated list — the local origin is always allowed:
295
295
  SAILOR_CORS_ORIGINS=https://hermes.example.ts.net,https://another.host
296
296
  ```
297
297
 
298
+ By default the UI server binds `127.0.0.1` (local only). To reach it from another
299
+ device **without** Tailscale — e.g. behind your own reverse proxy on a domain — bind
300
+ all interfaces and throttle the key-management endpoints:
301
+
302
+ ```bash
303
+ SAILOR_HOST=0.0.0.0 # bind all interfaces (default 127.0.0.1)
304
+ SAILOR_TRUST_PROXY=1 # hops to your proxy (or an IP allowlist), so rate limits key on the real client IP
305
+ SAILOR_RATE_LIMIT_PER_MIN=100 # cap /api/signer + /api/onboard/generate-key (default 100)
306
+ ```
307
+
308
+ Behind a reverse proxy, set `SAILOR_TRUST_PROXY` (usually `1`) — otherwise the rate
309
+ limiter sees only the proxy's IP and applies one shared bucket to all clients.
310
+
311
+ The key-management endpoints are **unauthenticated** — only expose them behind your
312
+ own auth (reverse-proxy basic-auth, or a private tailnet), never the open internet.
313
+
298
314
  ---
299
315
 
300
316
  ## Agent-driven onboarding & custom mandates
@@ -10,6 +10,10 @@ struct Context {
10
10
  uint256 value;
11
11
  uint256 blockTimestamp;
12
12
  uint256 blockNumber;
13
+ /// @dev Kernel registrationEpoch(account, permission) at dispatch. Configurable
14
+ /// permissions fail closed on a mismatch with the epoch stamped at configure()
15
+ /// time; permissions without post-deploy configuration can ignore it.
16
+ uint256 configEpoch;
13
17
  }
14
18
 
15
19
  interface IPermission {
@@ -36,11 +36,14 @@ struct Context {
36
36
  uint256 value; // msg.value (native asset) sent with the call
37
37
  uint256 blockTimestamp; // block.timestamp at evaluation
38
38
  uint256 blockNumber; // block.number at evaluation
39
+ uint256 configEpoch; // kernel registrationEpoch(account, permission) at dispatch;
40
+ // ignore it unless your permission takes post-deploy configuration
39
41
  }
40
42
  ```
41
43
 
42
44
  - `evaluate` — your policy. Return `true` to permit the call, `false` to block it. Runs under a
43
- 100k-gas `staticcall`; a revert or gas overage is treated as `false`.
45
+ 150,000-gas `staticcall` (`SailKernel.PERMISSION_GAS_CAP`); a revert or gas overage is treated
46
+ as `false`.
44
47
  - `discriminator` — a stable `bytes32` name for your permission (e.g. `keccak256("MyMandate")`).
45
48
 
46
49
  Keep all policy parameters constructor-configured so each deployment is a complete, reviewable
@@ -26,6 +26,8 @@ struct BatchContext {
26
26
  bytes32 batchHash; // keccak256(abi.encode(calls)) — stable id for the exact sequence
27
27
  uint256 blockTimestamp; // block.timestamp at dispatch
28
28
  uint256 blockNumber; // block.number at dispatch
29
+ uint256 configEpoch; // kernel registrationEpoch(account, permission) at dispatch —
30
+ // same fail-closed freshness check as Context.configEpoch
29
31
  }
30
32
 
31
33
  interface IBatchPermission {
@@ -10,6 +10,10 @@ struct Context {
10
10
  uint256 value;
11
11
  uint256 blockTimestamp;
12
12
  uint256 blockNumber;
13
+ /// @dev Kernel registrationEpoch(account, permission) at dispatch. Configurable
14
+ /// permissions fail closed on a mismatch with the epoch stamped at configure()
15
+ /// time; permissions without post-deploy configuration can ignore it.
16
+ uint256 configEpoch;
13
17
  }
14
18
 
15
19
  interface IPermission {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev.sail.money/sailor",
3
- "version": "1.3.0-225",
3
+ "version": "1.3.0-227",
4
4
  "description": "Operator toolkit for Sail Protocol",
5
5
  "bin": {
6
6
  "sailor": "packages/cli/dist/index.cjs"
@@ -42,5 +42,11 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "tsx": "^4.22.4"
45
+ },
46
+ "pnpm": {
47
+ "overrides": {
48
+ "form-data@<4.0.6": ">=4.0.6",
49
+ "hono@<4.12.25": ">=4.12.25"
50
+ }
45
51
  }
46
52
  }
@@ -39629,8 +39629,9 @@ var SigningServer = class {
39629
39629
  }
39630
39630
  }
39631
39631
  if (!(0, import_node_fs6.existsSync)(this.runtimeDir)) (0, import_node_fs6.mkdirSync)(this.runtimeDir, { recursive: true });
39632
+ const serverStatePath = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
39632
39633
  (0, import_node_fs6.writeFileSync)(
39633
- (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE),
39634
+ serverStatePath,
39634
39635
  JSON.stringify(
39635
39636
  {
39636
39637
  url: this._url,
@@ -39642,8 +39643,10 @@ var SigningServer = class {
39642
39643
  },
39643
39644
  null,
39644
39645
  2
39645
- )
39646
+ ),
39647
+ { mode: 384 }
39646
39648
  );
39649
+ (0, import_node_fs6.chmodSync)(serverStatePath, 384);
39647
39650
  }
39648
39651
  removeRuntimeState() {
39649
39652
  const path11 = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
@@ -40542,15 +40545,36 @@ var IPERMISSION_ABI = [
40542
40545
  { name: "selector", type: "bytes4" },
40543
40546
  { name: "value", type: "uint256" },
40544
40547
  { name: "blockTimestamp", type: "uint256" },
40545
- { name: "blockNumber", type: "uint256" }
40548
+ { name: "blockNumber", type: "uint256" },
40549
+ { name: "configEpoch", type: "uint256" }
40546
40550
  ]
40547
40551
  }
40548
40552
  ],
40549
40553
  outputs: [{ type: "bool" }]
40550
40554
  }
40551
40555
  ];
40556
+ var REGISTRATION_EPOCH_ABI2 = [
40557
+ {
40558
+ type: "function",
40559
+ name: "registrationEpoch",
40560
+ stateMutability: "view",
40561
+ inputs: [
40562
+ { name: "account", type: "address" },
40563
+ { name: "permission", type: "address" }
40564
+ ],
40565
+ outputs: [{ type: "uint256" }]
40566
+ }
40567
+ ];
40568
+ async function readRegistrationEpoch(publicClient, kernel, account2, permission) {
40569
+ return await publicClient.readContract({
40570
+ address: kernel,
40571
+ abi: REGISTRATION_EPOCH_ABI2,
40572
+ functionName: "registrationEpoch",
40573
+ args: [account2, permission]
40574
+ });
40575
+ }
40552
40576
  function buildPermissionContext(params) {
40553
- const { account: account2, manager, call: call2, blockInfo } = params;
40577
+ const { account: account2, manager, call: call2, blockInfo, configEpoch } = params;
40554
40578
  const selector = call2.data.length >= 10 ? call2.data.slice(0, 10) : "0x00000000";
40555
40579
  return {
40556
40580
  account: account2,
@@ -40561,12 +40585,23 @@ function buildPermissionContext(params) {
40561
40585
  selector,
40562
40586
  value: call2.value,
40563
40587
  blockTimestamp: blockInfo.timestamp,
40564
- blockNumber: blockInfo.number
40588
+ blockNumber: blockInfo.number,
40589
+ configEpoch
40565
40590
  };
40566
40591
  }
40567
40592
  async function probePermissionForCall(params) {
40568
- const { publicClient, permission, account: account2, manager, call: call2, blockInfo } = params;
40569
- const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo });
40593
+ const { publicClient, kernel, permission, account: account2, manager, call: call2, blockInfo } = params;
40594
+ let configEpoch;
40595
+ try {
40596
+ configEpoch = await readRegistrationEpoch(publicClient, kernel, account2, permission);
40597
+ } catch (err) {
40598
+ return {
40599
+ accepted: false,
40600
+ reverted: true,
40601
+ error: `could not read registrationEpoch from kernel ${kernel} (${err.message.split("\n")[0]})`
40602
+ };
40603
+ }
40604
+ const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo, configEpoch });
40570
40605
  try {
40571
40606
  const accepted = await publicClient.readContract({
40572
40607
  address: permission,
@@ -40580,10 +40615,11 @@ async function probePermissionForCall(params) {
40580
40615
  }
40581
40616
  }
40582
40617
  async function resolvePermissionForCall(params) {
40583
- const { publicClient, account: account2, manager, call: call2, registeredPermissions, blockInfo } = params;
40584
- const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo });
40618
+ const { publicClient, kernel, account: account2, manager, call: call2, registeredPermissions, blockInfo } = params;
40585
40619
  for (const permission of registeredPermissions) {
40586
40620
  try {
40621
+ const configEpoch = await readRegistrationEpoch(publicClient, kernel, account2, permission);
40622
+ const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo, configEpoch });
40587
40623
  const accepted = await publicClient.readContract({
40588
40624
  address: permission,
40589
40625
  abi: IPERMISSION_ABI,
@@ -40653,7 +40689,10 @@ async function probePassThrough(pc, permission, account2) {
40653
40689
  selector: PROBE_SELECTOR,
40654
40690
  value: 0n,
40655
40691
  blockTimestamp: 0n,
40656
- blockNumber: 0n
40692
+ blockNumber: 0n,
40693
+ // Pass-through probes only run on conjunctive kernels, which predate
40694
+ // registrationEpoch — there is no live epoch to read, so probe with 0.
40695
+ configEpoch: 0n
40657
40696
  }
40658
40697
  ]
40659
40698
  });
@@ -40949,6 +40988,10 @@ struct Context {
40949
40988
  uint256 value; // native ETH forwarded (wei)
40950
40989
  uint256 blockTimestamp; // block.timestamp at dispatch
40951
40990
  uint256 blockNumber; // block.number at dispatch
40991
+ uint256 configEpoch; // kernel registrationEpoch(account, permission) at dispatch;
40992
+ // configurable permissions fail closed on a mismatch with the
40993
+ // epoch stamped at configure() time. Custom permissions that
40994
+ // take no post-deploy configuration can ignore it.
40952
40995
  }
40953
40996
 
40954
40997
  /// @title IPermission
@@ -40984,6 +41027,8 @@ struct BatchContext {
40984
41027
  bytes32 batchHash; // keccak256(abi.encode(calls)) \u2014 stable id for the exact sequence
40985
41028
  uint256 blockTimestamp; // block.timestamp at dispatch
40986
41029
  uint256 blockNumber; // block.number at dispatch
41030
+ uint256 configEpoch; // kernel registrationEpoch(account, permission) at dispatch \u2014
41031
+ // same fail-closed freshness check as Context.configEpoch
40987
41032
  }
40988
41033
 
40989
41034
  /// @title IBatchPermission
@@ -44361,6 +44406,7 @@ async function mandateSimulate(options) {
44361
44406
  const [probe, codeCheck] = await Promise.all([
44362
44407
  probePermissionForCall({
44363
44408
  publicClient: pc,
44409
+ kernel: project.contracts.kernel,
44364
44410
  permission,
44365
44411
  account: account2,
44366
44412
  manager,
@@ -45320,6 +45366,8 @@ Configure the chain in the SDK chain registry or set KERNEL_ADDRESS in .sail/.en
45320
45366
  } else {
45321
45367
  permission = await resolvePermissionForCall({
45322
45368
  publicClient,
45369
+ kernel,
45370
+ // narrowed: runCommand validates kernel before runTick runs
45323
45371
  account: accountAddr,
45324
45372
  manager: agentManager.address,
45325
45373
  call: firstCall,
@@ -46377,6 +46377,8 @@ var init_esm = __esm({
46377
46377
  // ../ui/server.js
46378
46378
  var server_exports = {};
46379
46379
  __export(server_exports, {
46380
+ isHttpUrl: () => isHttpUrl,
46381
+ isSafeEnvValue: () => isSafeEnvValue,
46380
46382
  startServer: () => startServer
46381
46383
  });
46382
46384
  module.exports = __toCommonJS(server_exports);
@@ -47879,6 +47881,41 @@ function persistPassphrase(envPath, passphrase) {
47879
47881
  import_node_fs2.default.writeFileSync(envPath, content, { mode: 384 });
47880
47882
  import_node_fs2.default.chmodSync(envPath, 384);
47881
47883
  }
47884
+ function isSafeEnvValue(v) {
47885
+ return typeof v === "string" && !/[\n\r]/.test(v);
47886
+ }
47887
+ function isHttpUrl(v) {
47888
+ try {
47889
+ const u = new URL(v);
47890
+ return u.protocol === "http:" || u.protocol === "https:";
47891
+ } catch {
47892
+ return false;
47893
+ }
47894
+ }
47895
+ function serverError(res, err) {
47896
+ console.error(err);
47897
+ res.status(500).json({ error: "internal server error" });
47898
+ }
47899
+ function rateLimit({ windowMs, max }) {
47900
+ const hits = /* @__PURE__ */ new Map();
47901
+ let lastSweep = 0;
47902
+ return (req, res, next) => {
47903
+ const now = Date.now();
47904
+ if (now - lastSweep > windowMs) {
47905
+ for (const [k, v] of hits) if (now > v.resetAt) hits.delete(k);
47906
+ lastSweep = now;
47907
+ }
47908
+ const ip = req.ip || req.socket?.remoteAddress || "local";
47909
+ const rec = hits.get(ip);
47910
+ if (!rec || now > rec.resetAt) {
47911
+ hits.set(ip, { count: 1, resetAt: now + windowMs });
47912
+ return next();
47913
+ }
47914
+ if (rec.count >= max) return res.status(429).json({ error: "too many requests" });
47915
+ rec.count += 1;
47916
+ next();
47917
+ };
47918
+ }
47882
47919
  var CHAIN_NAMES = {
47883
47920
  1: "ethereum",
47884
47921
  8453: "base",
@@ -47983,8 +48020,27 @@ function addManagerToList(existing, current, next) {
47983
48020
  var OVERVIEW_TTL_MS = 1e4;
47984
48021
  function startServer(sailDir, { port = PORT } = {}) {
47985
48022
  const app = (0, import_express.default)();
48023
+ const trustProxy = process.env.SAILOR_TRUST_PROXY;
48024
+ if (trustProxy && trustProxy !== "false" && trustProxy !== "0") {
48025
+ const hops = Number(trustProxy);
48026
+ app.set("trust proxy", Number.isFinite(hops) ? hops : trustProxy === "true" ? true : trustProxy);
48027
+ }
47986
48028
  app.use((0, import_cors.default)({ origin: CORS_ORIGINS }));
47987
48029
  app.use(import_express.default.json());
48030
+ const rateLimitPerMin = (() => {
48031
+ const fromEnv = Number(process.env.SAILOR_RATE_LIMIT_PER_MIN);
48032
+ if (Number.isFinite(fromEnv) && fromEnv > 0) return fromEnv;
48033
+ try {
48034
+ const cfg = JSON.parse(import_node_fs2.default.readFileSync(import_node_path.default.join(sailDir, "config.json"), "utf-8"));
48035
+ const fromCfg = Number(cfg?.rateLimitPerMin);
48036
+ if (Number.isFinite(fromCfg) && fromCfg > 0) return fromCfg;
48037
+ } catch {
48038
+ }
48039
+ return 100;
48040
+ })();
48041
+ const keyEndpointLimiter = rateLimit({ windowMs: 6e4, max: rateLimitPerMin });
48042
+ app.use("/api/signer", keyEndpointLimiter);
48043
+ app.use("/api/onboard/generate-key", keyEndpointLimiter);
47988
48044
  const at = (name) => import_node_path.default.join(sailDir, name);
47989
48045
  const syncConfigChainId = (chainId) => {
47990
48046
  if (chainId == null) return;
@@ -48113,7 +48169,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48113
48169
  overviewCacheByAccount.clear();
48114
48170
  res.json({ ok: true });
48115
48171
  } catch (err) {
48116
- res.status(500).json({ error: String(err) });
48172
+ serverError(res, err);
48117
48173
  }
48118
48174
  });
48119
48175
  app.post("/api/account", async (req, res) => {
@@ -48156,7 +48212,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48156
48212
  syncConfigChainId(chainId);
48157
48213
  res.json({ ok: true });
48158
48214
  } catch (err) {
48159
- res.status(500).json({ error: String(err) });
48215
+ serverError(res, err);
48160
48216
  }
48161
48217
  });
48162
48218
  app.get("/api/accounts", (_req, res) => {
@@ -48195,7 +48251,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48195
48251
  syncConfigChainId(target.chainId);
48196
48252
  res.json({ ok: true, active: target });
48197
48253
  } catch (err) {
48198
- res.status(500).json({ error: String(err) });
48254
+ serverError(res, err);
48199
48255
  }
48200
48256
  });
48201
48257
  app.post("/api/account/rename", (req, res) => {
@@ -48204,6 +48260,11 @@ function startServer(sailDir, { port = PORT } = {}) {
48204
48260
  res.status(400).json({ error: "safe and name are required" });
48205
48261
  return;
48206
48262
  }
48263
+ const cleanName = typeof name === "string" ? name.replace(/\p{Cc}/gu, "").trim() : "";
48264
+ if (!cleanName || cleanName.length > 100) {
48265
+ res.status(400).json({ error: "name must be 1\u2013100 characters" });
48266
+ return;
48267
+ }
48207
48268
  try {
48208
48269
  const accountsPath = at("state/accounts.json");
48209
48270
  const accounts = JSON.parse(import_node_fs2.default.readFileSync(accountsPath, "utf-8"));
@@ -48212,12 +48273,12 @@ function startServer(sailDir, { port = PORT } = {}) {
48212
48273
  res.status(404).json({ error: "SMA not found" });
48213
48274
  return;
48214
48275
  }
48215
- accounts[idx] = { ...accounts[idx], name };
48276
+ accounts[idx] = { ...accounts[idx], name: cleanName };
48216
48277
  import_node_fs2.default.writeFileSync(accountsPath, `${JSON.stringify(accounts, null, 2)}
48217
48278
  `);
48218
48279
  res.json({ ok: true });
48219
48280
  } catch (err) {
48220
- res.status(500).json({ error: String(err) });
48281
+ serverError(res, err);
48221
48282
  }
48222
48283
  });
48223
48284
  const readActiveSafe = () => {
@@ -48286,7 +48347,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48286
48347
  `);
48287
48348
  res.json({ ok: true, event });
48288
48349
  } catch (err) {
48289
- res.status(500).json({ error: String(err) });
48350
+ serverError(res, err);
48290
48351
  }
48291
48352
  });
48292
48353
  const managerKeyPath = (safe) => at(`keys/manager-${safe.toLowerCase()}.json`);
@@ -48345,7 +48406,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48345
48406
  invalidateOverviewCache(safe);
48346
48407
  res.json({ ok: true, address: keyring.address, revealed });
48347
48408
  } catch (err) {
48348
- res.status(500).json({ error: String(err) });
48409
+ serverError(res, err);
48349
48410
  }
48350
48411
  });
48351
48412
  app.post("/api/manager/complete", (req, res) => {
@@ -48392,7 +48453,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48392
48453
  invalidateOverviewCache(safe);
48393
48454
  res.json({ ok: true, manager });
48394
48455
  } catch (err) {
48395
- res.status(500).json({ error: String(err) });
48456
+ serverError(res, err);
48396
48457
  }
48397
48458
  });
48398
48459
  const isManagerKeyFile = (file) => file === "manager.json" || file.startsWith("manager-") && file.endsWith(".json") || file.startsWith("managers/") && file.endsWith(".json");
@@ -48445,7 +48506,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48445
48506
  }
48446
48507
  res.json({ signers: [...byAddress.values()] });
48447
48508
  } catch (err) {
48448
- res.status(500).json({ error: String(err) });
48509
+ serverError(res, err);
48449
48510
  }
48450
48511
  });
48451
48512
  app.post("/api/signer/activate", (req, res) => {
@@ -48476,7 +48537,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48476
48537
  invalidateOverviewCache(safe);
48477
48538
  res.json({ ok: true, address: getAddress(address), file: match });
48478
48539
  } catch (err) {
48479
- res.status(500).json({ error: String(err) });
48540
+ serverError(res, err);
48480
48541
  }
48481
48542
  });
48482
48543
  app.get("/api/mandate", (_req, res) => {
@@ -48575,7 +48636,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48575
48636
  }
48576
48637
  }
48577
48638
  } catch (err) {
48578
- res.status(500).json({ error: `On-chain registration failed: ${err?.message ?? String(err)}` });
48639
+ res.status(500).json({ error: `On-chain registration failed: ${(err?.message ?? String(err)).split("\n")[0]}` });
48579
48640
  return;
48580
48641
  }
48581
48642
  const mandate = {
@@ -48606,7 +48667,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48606
48667
  }
48607
48668
  res.json(mandate);
48608
48669
  } catch (err) {
48609
- res.status(500).json({ error: String(err) });
48670
+ serverError(res, err);
48610
48671
  }
48611
48672
  });
48612
48673
  const readPidFile = (filePath) => {
@@ -48822,6 +48883,19 @@ function startServer(sailDir, { port = PORT } = {}) {
48822
48883
  });
48823
48884
  app.post("/api/onboard/save-config", (req, res) => {
48824
48885
  const { rpcUrl, sailApiKey, chainId } = req.body ?? {};
48886
+ const cid = Number(chainId);
48887
+ if (chainId !== void 0 && !CHAIN_RPC_ENV_KEYS[cid]) {
48888
+ res.status(400).json({ error: "unsupported chainId" });
48889
+ return;
48890
+ }
48891
+ if (rpcUrl !== void 0 && (!isSafeEnvValue(rpcUrl) || !isHttpUrl(rpcUrl))) {
48892
+ res.status(400).json({ error: "invalid rpcUrl" });
48893
+ return;
48894
+ }
48895
+ if (sailApiKey !== void 0 && !isSafeEnvValue(sailApiKey)) {
48896
+ res.status(400).json({ error: "invalid sailApiKey" });
48897
+ return;
48898
+ }
48825
48899
  try {
48826
48900
  const config = (() => {
48827
48901
  try {
@@ -48834,20 +48908,20 @@ function startServer(sailDir, { port = PORT } = {}) {
48834
48908
  const envPath = at(".env.local");
48835
48909
  const existing = parseEnvFile(envPath);
48836
48910
  if (rpcUrl && chainId) {
48837
- existing[`RPC_URL_${chainId}`] = rpcUrl;
48838
- if (Number(chainId) === Number(activeChainId)) existing.RPC_URL = rpcUrl;
48911
+ existing[`RPC_URL_${cid}`] = rpcUrl;
48912
+ if (cid === Number(activeChainId)) existing.RPC_URL = rpcUrl;
48839
48913
  } else if (rpcUrl) {
48840
48914
  existing.RPC_URL = rpcUrl;
48841
48915
  }
48842
48916
  if (sailApiKey) existing.SAIL_API_KEY = sailApiKey;
48843
- if (chainId) existing.CHAIN_ID = String(chainId);
48917
+ if (chainId) existing.CHAIN_ID = String(cid);
48844
48918
  const content = Object.entries(existing).map(([k, v]) => `${k}=${v}`).join("\n") + "\n";
48845
48919
  import_node_fs2.default.mkdirSync(sailDir, { recursive: true });
48846
48920
  import_node_fs2.default.writeFileSync(envPath, content, { mode: 384 });
48847
48921
  import_node_fs2.default.chmodSync(envPath, 384);
48848
48922
  res.json({ ok: true });
48849
48923
  } catch (err) {
48850
- res.status(500).json({ error: String(err) });
48924
+ serverError(res, err);
48851
48925
  }
48852
48926
  });
48853
48927
  app.post("/api/onboard/generate-key", async (req, res) => {
@@ -48876,7 +48950,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48876
48950
  persistPassphrase(at(".env.local"), passphrase);
48877
48951
  res.json({ address: keyring.address, existed: false });
48878
48952
  } catch (err) {
48879
- res.status(500).json({ error: String(err) });
48953
+ serverError(res, err);
48880
48954
  }
48881
48955
  });
48882
48956
  app.post("/api/onboard/build-create-tx", (req, res) => {
@@ -48928,7 +49002,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48928
49002
  });
48929
49003
  res.json({ to: kernel, data, chainId, saltNonce: saltNonce.toString() });
48930
49004
  } catch (err) {
48931
- res.status(500).json({ error: String(err) });
49005
+ serverError(res, err);
48932
49006
  }
48933
49007
  });
48934
49008
  app.post("/api/onboard/build-register-path", (req, res) => {
@@ -48982,7 +49056,7 @@ function startServer(sailDir, { port = PORT } = {}) {
48982
49056
  saltNonce: saltNonce.toString()
48983
49057
  });
48984
49058
  } catch (err) {
48985
- res.status(500).json({ error: String(err) });
49059
+ serverError(res, err);
48986
49060
  }
48987
49061
  });
48988
49062
  app.post("/api/onboard/complete", async (req, res) => {
@@ -49050,7 +49124,7 @@ function startServer(sailDir, { port = PORT } = {}) {
49050
49124
  syncConfigChainId(chainId);
49051
49125
  res.json({ ok: true, account: record });
49052
49126
  } catch (err) {
49053
- res.status(500).json({ error: String(err) });
49127
+ serverError(res, err);
49054
49128
  }
49055
49129
  });
49056
49130
  app.get("/api/wizard-state", (_req, res) => {
@@ -49062,13 +49136,18 @@ function startServer(sailDir, { port = PORT } = {}) {
49062
49136
  }
49063
49137
  });
49064
49138
  app.post("/api/wizard-state", (req, res) => {
49139
+ const body = req.body;
49140
+ if (body === null || typeof body !== "object" || Array.isArray(body)) {
49141
+ res.status(400).json({ error: "wizard state must be an object" });
49142
+ return;
49143
+ }
49065
49144
  try {
49066
49145
  import_node_fs2.default.mkdirSync(sailDir, { recursive: true });
49067
- import_node_fs2.default.writeFileSync(at(".wizard-state.json"), `${JSON.stringify(req.body, null, 2)}
49146
+ import_node_fs2.default.writeFileSync(at(".wizard-state.json"), `${JSON.stringify(body, null, 2)}
49068
49147
  `);
49069
49148
  res.json({ ok: true });
49070
49149
  } catch (err) {
49071
- res.status(500).json({ error: String(err) });
49150
+ serverError(res, err);
49072
49151
  }
49073
49152
  });
49074
49153
  app.get("/api/positions", (_req, res) => {
@@ -49348,7 +49427,8 @@ function startServer(sailDir, { port = PORT } = {}) {
49348
49427
  res.sendFile(import_node_path.default.join(distDir, "index.html"));
49349
49428
  });
49350
49429
  }
49351
- const httpServer = app.listen(port, () => {
49430
+ const bindHost = process.env.SAILOR_HOST ?? "127.0.0.1";
49431
+ const httpServer = app.listen(port, bindHost, () => {
49352
49432
  console.log(`Sailor UI running at http://localhost:${port} (reading ${sailDir})`);
49353
49433
  });
49354
49434
  const wss = new import_websocket_server.default({ noServer: true });
@@ -49427,6 +49507,8 @@ if (isMain) {
49427
49507
  }
49428
49508
  // Annotate the CommonJS export names for ESM import in node:
49429
49509
  0 && (module.exports = {
49510
+ isHttpUrl,
49511
+ isSafeEnvValue,
49430
49512
  startServer
49431
49513
  });
49432
49514
  /*! Bundled license information:
@@ -5,7 +5,7 @@
5
5
  * Do not edit manually — run `pnpm build` to regenerate.
6
6
  *
7
7
  * Spec version : 1.2.1
8
- * Generated at : 2026-07-02T13:00:44.579Z
8
+ * Generated at : 2026-07-02T16:26:37.498Z
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.1
8
- * Generated at : 2026-07-02T13:00:44.579Z
8
+ * Generated at : 2026-07-02T16:26:37.498Z
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";
@@ -1,4 +1,4 @@
1
- import{F as o}from"./core-BMNH6XFj.js";import"./index-CPrhuDfP.js";import"./events-Cdt6abbf.js";import"./index.es-DImsg59a.js";import"./fallback-BSMYROva.js";const d=o`<svg
1
+ import{F as o}from"./core-BLOM5s8O.js";import"./index-D8zwDy7d.js";import"./index.es-Hqwz_Ukd.js";import"./events-DQ172AOg.js";const e=o`<svg
2
2
  width="14"
3
3
  height="14"
4
4
  viewBox="0 0 14 14"
@@ -12,4 +12,4 @@ import{F as o}from"./core-BMNH6XFj.js";import"./index-CPrhuDfP.js";import"./even
12
12
  d="M7.0023 0.875C7.48571 0.875 7.8776 1.26675 7.8776 1.75V6.125H12.2541C12.7375 6.125 13.1294 6.51675 13.1294 7C13.1294 7.48325 12.7375 7.875 12.2541 7.875H7.8776V12.25C7.8776 12.7332 7.48571 13.125 7.0023 13.125C6.51889 13.125 6.12701 12.7332 6.12701 12.25V7.875H1.75054C1.26713 7.875 0.875244 7.48325 0.875244 7C0.875244 6.51675 1.26713 6.125 1.75054 6.125H6.12701V1.75C6.12701 1.26675 6.51889 0.875 7.0023 0.875Z"
13
13
  fill="#667dff"
14
14
  /></svg
15
- >`;export{d as addSvg};
15
+ >`;export{e as addSvg};
@@ -1,6 +1,6 @@
1
- import{F as o}from"./core-BMNH6XFj.js";import"./index-CPrhuDfP.js";import"./events-Cdt6abbf.js";import"./index.es-DImsg59a.js";import"./fallback-BSMYROva.js";const p=o`<svg fill="none" viewBox="0 0 24 24">
1
+ import{F as o}from"./core-BLOM5s8O.js";import"./index-D8zwDy7d.js";import"./index.es-Hqwz_Ukd.js";import"./events-DQ172AOg.js";const r=o`<svg fill="none" viewBox="0 0 24 24">
2
2
  <path
3
3
  style="fill: var(--wui-color-accent-100);"
4
4
  d="M10.2 6.6a3.6 3.6 0 1 1-7.2 0 3.6 3.6 0 0 1 7.2 0ZM21 6.6a3.6 3.6 0 1 1-7.2 0 3.6 3.6 0 0 1 7.2 0ZM10.2 17.4a3.6 3.6 0 1 1-7.2 0 3.6 3.6 0 0 1 7.2 0ZM21 17.4a3.6 3.6 0 1 1-7.2 0 3.6 3.6 0 0 1 7.2 0Z"
5
5
  />
6
- </svg>`;export{p as allWalletsSvg};
6
+ </svg>`;export{r as allWalletsSvg};
@@ -1,4 +1,4 @@
1
- import{F as t}from"./core-BMNH6XFj.js";import"./index-CPrhuDfP.js";import"./events-Cdt6abbf.js";import"./index.es-DImsg59a.js";import"./fallback-BSMYROva.js";const e=t`
1
+ import{F as t}from"./core-BLOM5s8O.js";import"./index-D8zwDy7d.js";import"./index.es-Hqwz_Ukd.js";import"./events-DQ172AOg.js";const e=t`
2
2
  <svg width="36" height="36">
3
3
  <path
4
4
  d="M28.724 0H7.271A7.269 7.269 0 0 0 0 7.272v21.46A7.268 7.268 0 0 0 7.271 36H28.73A7.272 7.272 0 0 0 36 28.728V7.272A7.275 7.275 0 0 0 28.724 0Z"
@@ -1,4 +1,4 @@
1
- import{F as i}from"./core-BMNH6XFj.js";import"./index-CPrhuDfP.js";import"./events-Cdt6abbf.js";import"./index.es-DImsg59a.js";import"./fallback-BSMYROva.js";const h=i`<svg fill="none" viewBox="0 0 40 40">
1
+ import{F as i}from"./core-BLOM5s8O.js";import"./index-D8zwDy7d.js";import"./index.es-Hqwz_Ukd.js";import"./events-DQ172AOg.js";const c=i`<svg fill="none" viewBox="0 0 40 40">
2
2
  <g clip-path="url(#a)">
3
3
  <g clip-path="url(#b)">
4
4
  <circle cx="20" cy="19.89" r="20" fill="#000" />
@@ -15,4 +15,4 @@ import{F as i}from"./core-BMNH6XFj.js";import"./index-CPrhuDfP.js";import"./even
15
15
  <clipPath id="b"><path fill="#fff" d="M0 0h40v40H0z" /></clipPath>
16
16
  <clipPath id="c"><path fill="#fff" d="M8 7.89h24v24H8z" /></clipPath>
17
17
  </defs>
18
- </svg>`;export{h as appleSvg};
18
+ </svg>`;export{c as appleSvg};
@@ -0,0 +1,8 @@
1
+ import{F as o}from"./core-BLOM5s8O.js";import"./index-D8zwDy7d.js";import"./index.es-Hqwz_Ukd.js";import"./events-DQ172AOg.js";const i=o`<svg fill="none" viewBox="0 0 14 15">
2
+ <path
3
+ fill="currentColor"
4
+ fill-rule="evenodd"
5
+ d="M7 1.99a1 1 0 0 1 1 1v7.58l2.46-2.46a1 1 0 0 1 1.41 1.42L7.7 13.69a1 1 0 0 1-1.41 0L2.12 9.53A1 1 0 0 1 3.54 8.1L6 10.57V3a1 1 0 0 1 1-1Z"
6
+ clip-rule="evenodd"
7
+ />
8
+ </svg>`;export{i as arrowBottomSvg};
@@ -1,4 +1,4 @@
1
- import{F as o}from"./core-BMNH6XFj.js";import"./index-CPrhuDfP.js";import"./events-Cdt6abbf.js";import"./index.es-DImsg59a.js";import"./fallback-BSMYROva.js";const t=o`<svg
1
+ import{F as C}from"./core-BLOM5s8O.js";import"./index-D8zwDy7d.js";import"./index.es-Hqwz_Ukd.js";import"./events-DQ172AOg.js";const i=C`<svg
2
2
  fill="none"
3
3
  viewBox="0 0 21 20"
4
4
  >
@@ -8,4 +8,4 @@ import{F as o}from"./core-BMNH6XFj.js";import"./index-CPrhuDfP.js";import"./even
8
8
  d="M10.5 2.42908C6.31875 2.42908 2.92859 5.81989 2.92859 10.0034C2.92859 14.1869 6.31875 17.5777 10.5 17.5777C14.6813 17.5777 18.0714 14.1869 18.0714 10.0034C18.0714 5.81989 14.6813 2.42908 10.5 2.42908ZM0.928589 10.0034C0.928589 4.71596 5.21355 0.429077 10.5 0.429077C15.7865 0.429077 20.0714 4.71596 20.0714 10.0034C20.0714 15.2908 15.7865 19.5777 10.5 19.5777C5.21355 19.5777 0.928589 15.2908 0.928589 10.0034ZM10.5 5.75003C11.0523 5.75003 11.5 6.19774 11.5 6.75003L11.5 10.8343L12.7929 9.54137C13.1834 9.15085 13.8166 9.15085 14.2071 9.54137C14.5976 9.9319 14.5976 10.5651 14.2071 10.9556L11.2071 13.9556C10.8166 14.3461 10.1834 14.3461 9.79291 13.9556L6.79291 10.9556C6.40239 10.5651 6.40239 9.9319 6.79291 9.54137C7.18343 9.15085 7.8166 9.15085 8.20712 9.54137L9.50002 10.8343L9.50002 6.75003C9.50002 6.19774 9.94773 5.75003 10.5 5.75003Z"
9
9
  clip-rule="evenodd"
10
10
  /></svg
11
- >`;export{t as arrowBottomCircleSvg};
11
+ >`;export{i as arrowBottomCircleSvg};
@@ -0,0 +1,8 @@
1
+ import{F as o}from"./core-BLOM5s8O.js";import"./index-D8zwDy7d.js";import"./index.es-Hqwz_Ukd.js";import"./events-DQ172AOg.js";const t=o`<svg fill="none" viewBox="0 0 14 15">
2
+ <path
3
+ fill="currentColor"
4
+ fill-rule="evenodd"
5
+ d="M13 7.99a1 1 0 0 1-1 1H4.4l2.46 2.46a1 1 0 1 1-1.41 1.41L1.29 8.7a1 1 0 0 1 0-1.41L5.46 3.1a1 1 0 0 1 1.41 1.42L4.41 6.99H12a1 1 0 0 1 1 1Z"
6
+ clip-rule="evenodd"
7
+ />
8
+ </svg>`;export{t as arrowLeftSvg};