@kky42/pievo-server 2.3.0 → 2.4.2

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 (199) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/MachinesModal-CSbnrUER.js +1 -0
  3. package/.output/public/assets/SignIn-0Tjqs-Ma.js +1 -0
  4. package/.output/public/assets/actionUi-DpwGIGpw.js +1 -0
  5. package/.output/public/assets/app-CaZpuwOS.css +2 -0
  6. package/.output/public/assets/index-CaS_SmDq.js +10 -0
  7. package/.output/public/assets/invite._token-Btg_0aLp.js +1 -0
  8. package/.output/public/assets/invite._token-KMD2JAgE.js +1 -0
  9. package/.output/public/assets/lifecycleUi-C7dwHtbw.js +1 -0
  10. package/.output/public/assets/loops._loopId-D5usF3DO.js +67 -0
  11. package/.output/public/assets/loops._loopId_.runs._runId-DRCgXaCq.js +3 -0
  12. package/.output/public/assets/preload-helper-DsxECZIS.js +5 -0
  13. package/.output/public/assets/routes-CtFgwdgW.js +1 -0
  14. package/.output/public/assets/routes-LDbnnQ3f.js +1 -0
  15. package/.output/public/assets/t._teamId-D41xcbsF.js +1 -0
  16. package/.output/public/assets/t._teamId-DUena1pV.js +1 -0
  17. package/.output/public/assets/ui-Do4gqMyP.js +1 -0
  18. package/.output/server/_libs/@base-ui/react+[...].mjs +4130 -4130
  19. package/.output/server/_libs/@tanstack/react-router+[...].mjs +1 -1
  20. package/.output/server/_libs/drizzle-orm+postgres.mjs +28 -1
  21. package/.output/server/_ssr/DashboardView-C2LdV6J0.mjs +914 -0
  22. package/.output/server/_ssr/{notifyFns-DuPR1zd7.mjs → MachinesModal-BjkcVjjx.mjs} +55 -35
  23. package/.output/server/_ssr/{SignIn-RmpWm9uy.mjs → SignIn-DEGrvJvb.mjs} +10 -24
  24. package/.output/server/_ssr/SocialLinks-Cm4H8pUJ.mjs +1044 -0
  25. package/.output/server/_ssr/{actionUi-BN55TNYE.mjs → actionUi-DJBWuNwr.mjs} +3 -3
  26. package/.output/server/_ssr/{artifactFiles-BCaIIrrT.mjs → artifactFiles-DtpRidFZ.mjs} +7 -8
  27. package/.output/server/_ssr/{artifactKind-BW0isV8L.mjs → artifactKind-FBYbgSuf.mjs} +27 -2
  28. package/.output/server/_ssr/artifacts-BR3jj0NC.mjs +2 -0
  29. package/.output/server/_ssr/{auth-30Z4lV1w.mjs → auth-C0zoZCGe.mjs} +16 -19
  30. package/.output/server/_ssr/boot-CdOO4xOo.mjs +2 -0
  31. package/.output/server/_ssr/{boot-3BNKujyp.mjs → boot-sNlIkoLe.mjs} +1331 -3927
  32. package/.output/server/_ssr/{bun-sqlite-dialect-BW9W1_Ps-_7tfuNRi.mjs → bun-sqlite-dialect-BW9W1_Ps-DmlZWqO7.mjs} +2 -2
  33. package/.output/server/_ssr/{d1-sqlite-dialect-BLC8LXE6-ucDUbeBk.mjs → d1-sqlite-dialect-BLC8LXE6-CCNzqZwZ.mjs} +2 -2
  34. package/.output/server/_ssr/db-CwLD-5w1.mjs +2 -0
  35. package/.output/server/_ssr/{dist-Cd6nlLlO.mjs → dist-B3SxDOpW.mjs} +2 -2
  36. package/.output/server/_ssr/{factory-CWWwV7XZ.mjs → factory-Dv3Zopis.mjs} +2 -2
  37. package/.output/server/_ssr/invite._token-CJ6-H-s3.mjs +20 -0
  38. package/.output/server/_ssr/{invite._token-SdWXemIc.mjs → invite._token-dLKDJKVs.mjs} +9 -17
  39. package/.output/server/_ssr/{invite._token-BKlz0R2f.mjs → invite._token-l1SjouDz.mjs} +6 -15
  40. package/.output/server/_ssr/{kysely-adapter-C8iS51DB.mjs → kysely-adapter-nL7WKSgw.mjs} +1 -1
  41. package/.output/server/_ssr/{lifecycleUi-DgBQAYzp.mjs → lifecycleUi-Dad3hvhm.mjs} +11 -11
  42. package/.output/server/_ssr/logger-B8m8F1Qu.mjs +2 -0
  43. package/.output/server/_ssr/loopApi-BKyFB4KM.mjs +342 -0
  44. package/.output/server/_ssr/{adapters-BoLkOf1T.mjs → loopProjection-B8a829ij.mjs} +25 -55
  45. package/.output/server/_ssr/loops._loopId-DS16Phmq.mjs +1271 -0
  46. package/.output/server/_ssr/{loops._loopId_.runs._runId-PUGBrD5q.mjs → loops._loopId_.runs._runId-BEJI6iK5.mjs} +23 -74
  47. package/.output/server/_ssr/{loops._loopId_.runs._runId-Ymy4lwee.mjs → loops._loopId_.runs._runId-CduETLqH.mjs} +4 -5
  48. package/.output/server/_ssr/{machineFns-BZ9puxDt.mjs → machineFns-ByMsgG12.mjs} +3 -5
  49. package/.output/server/_ssr/{node-sqlite-dialect-D_3JmkMo.mjs → node-sqlite-dialect-CjNineno.mjs} +2 -2
  50. package/.output/server/_ssr/router-CXyrnvx-.mjs +565 -0
  51. package/.output/server/_ssr/{routes-ClZEdsnB.mjs → routes-BulNEUEE.mjs} +6 -10
  52. package/.output/server/_ssr/{routes-ComqHvCL.mjs → routes-DD94baie.mjs} +3 -3
  53. package/.output/server/_ssr/{routes-D5jJJ-30.mjs → routes-Wjexi35W.mjs} +6 -6
  54. package/.output/server/_ssr/runDiff-Ba8Lg1vg.mjs +2 -0
  55. package/.output/server/_ssr/ssr.mjs +60 -100
  56. package/.output/server/_ssr/store-Cujtg2QE.mjs +2 -0
  57. package/.output/server/_ssr/{t._teamId-BgHV_KFP.mjs → t._teamId-1CreIlPV.mjs} +7 -11
  58. package/.output/server/_ssr/{t._teamId-DDERNgfn.mjs → t._teamId-Bd6-zZsy.mjs} +4 -4
  59. package/.output/server/_ssr/{t._teamId-DRJvKHZn.mjs → t._teamId-COuMKQ4r.mjs} +7 -7
  60. package/.output/server/_ssr/{teamFns-Bp81UO-x.mjs → teamFns-H438WnZC.mjs} +12 -30
  61. package/.output/server/_ssr/{teamFns-bm82twd5.mjs → teamFns-j2JKjorZ.mjs} +2 -2
  62. package/.output/server/_ssr/tokens-DgG_Syq3.mjs +2 -0
  63. package/.output/server/_ssr/{ui-Ww2tTM2u.mjs → ui-D5KWstlb.mjs} +26 -48
  64. package/.output/server/{_tanstack-start-manifest_v-DwKENYCN.mjs → _tanstack-start-manifest_v-3H7yBKLz.mjs} +25 -35
  65. package/{drizzle/0000_round_marauders.sql → .output/server/drizzle/0000_baseline.sql} +102 -44
  66. package/.output/server/drizzle/meta/_journal.json +3 -115
  67. package/.output/server/index.mjs +83 -132
  68. package/{.output/server/drizzle/0000_round_marauders.sql → drizzle/0000_baseline.sql} +102 -44
  69. package/drizzle/meta/_journal.json +3 -115
  70. package/package.json +2 -11
  71. package/scripts/pievo-server.mjs +3 -1
  72. package/scripts/server-cli-lib.mjs +23 -16
  73. package/.output/public/assets/CodeField-dOzyFQNH.js +0 -34
  74. package/.output/public/assets/LoopView-DjVHUyrR.js +0 -59
  75. package/.output/public/assets/Modal-CCRvx959.js +0 -1
  76. package/.output/public/assets/SignIn-Qxw5zDFq.js +0 -1
  77. package/.output/public/assets/actionUi-CXxhzYe2.js +0 -1
  78. package/.output/public/assets/app-D1cij_NJ.css +0 -2
  79. package/.output/public/assets/artifactView-Cd5wWPil.js +0 -66
  80. package/.output/public/assets/index-BRN_CQ8U.js +0 -12
  81. package/.output/public/assets/invite._token-BIxr8DlP.js +0 -1
  82. package/.output/public/assets/invite._token-j2BTCeG1.js +0 -1
  83. package/.output/public/assets/jsx-runtime-BseJUIpC.js +0 -1
  84. package/.output/public/assets/lifecycleUi-Qy_8beQK.js +0 -1
  85. package/.output/public/assets/loopApi-CT1mMhlb.js +0 -3
  86. package/.output/public/assets/loops._loopId-BRBQzioy.js +0 -4
  87. package/.output/public/assets/loops._loopId_.runs._runId-CMnOJkem.js +0 -3
  88. package/.output/public/assets/notifyFns-DYD4EKaG.js +0 -1
  89. package/.output/public/assets/preload-helper-DFkkpP6W.js +0 -3
  90. package/.output/public/assets/routes-3nuEJGdo.js +0 -1
  91. package/.output/public/assets/routes-DORLim-C.js +0 -1
  92. package/.output/public/assets/t._teamId-F5f4K8kd.js +0 -1
  93. package/.output/public/assets/t._teamId-XfE_S1Fo.js +0 -1
  94. package/.output/public/assets/ui-Dhsx6SW0.js +0 -1
  95. package/.output/public/assets/useRouter-DsjH8G0p.js +0 -1
  96. package/.output/server/_libs/@codemirror/autocomplete+[...].mjs +0 -19713
  97. package/.output/server/_libs/@codemirror/lang-css+[...].mjs +0 -2636
  98. package/.output/server/_libs/@codemirror/lang-html+[...].mjs +0 -2247
  99. package/.output/server/_libs/@codemirror/lang-json+[...].mjs +0 -79
  100. package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +0 -1736
  101. package/.output/server/_libs/@uiw/codemirror-extensions-basic-setup+[...].mjs +0 -76
  102. package/.output/server/_libs/babel__runtime.mjs +0 -30
  103. package/.output/server/_libs/clsx.mjs +0 -16
  104. package/.output/server/_libs/codemirror__commands.mjs +0 -1725
  105. package/.output/server/_libs/codemirror__lint.mjs +0 -565
  106. package/.output/server/_libs/codemirror__search.mjs +0 -1138
  107. package/.output/server/_libs/codemirror__theme-one-dark.mjs +0 -161
  108. package/.output/server/_libs/d3-array.mjs +0 -231
  109. package/.output/server/_libs/d3-color.mjs +0 -330
  110. package/.output/server/_libs/d3-format.mjs +0 -252
  111. package/.output/server/_libs/d3-interpolate.mjs +0 -163
  112. package/.output/server/_libs/d3-path.mjs +0 -77
  113. package/.output/server/_libs/d3-scale+[...].mjs +0 -1907
  114. package/.output/server/_libs/d3-shape.mjs +0 -818
  115. package/.output/server/_libs/decimal.js-light.mjs +0 -884
  116. package/.output/server/_libs/dom-serializer+[...].mjs +0 -708
  117. package/.output/server/_libs/domhandler.mjs +0 -461
  118. package/.output/server/_libs/domutils.mjs +0 -868
  119. package/.output/server/_libs/es-toolkit.mjs +0 -1737
  120. package/.output/server/_libs/eventemitter3.mjs +0 -236
  121. package/.output/server/_libs/html-dom-parser+htmlparser2.mjs +0 -1560
  122. package/.output/server/_libs/html-react-parser+[...].mjs +0 -1360
  123. package/.output/server/_libs/react-is.mjs +0 -48
  124. package/.output/server/_libs/react-redux+[...].mjs +0 -205
  125. package/.output/server/_libs/recharts+victory-vendor.mjs +0 -17303
  126. package/.output/server/_libs/uiw__codemirror-themes.mjs +0 -32
  127. package/.output/server/_libs/uiw__react-codemirror.mjs +0 -354
  128. package/.output/server/_ssr/CodeField-B7oOmmwH.mjs +0 -143
  129. package/.output/server/_ssr/DashboardView-BF7PciP7.mjs +0 -2736
  130. package/.output/server/_ssr/LoopPlaybook-DC7QVvPY.mjs +0 -2105
  131. package/.output/server/_ssr/LoopView-DwSrm9Ja.mjs +0 -1300
  132. package/.output/server/_ssr/Modal-MaCG52Pv.mjs +0 -49
  133. package/.output/server/_ssr/artifactView-iuPsp5aa.mjs +0 -304
  134. package/.output/server/_ssr/artifacts-jQ-bfdhI.mjs +0 -2
  135. package/.output/server/_ssr/boot-CsEFT53K.mjs +0 -2
  136. package/.output/server/_ssr/db-CXownd1H.mjs +0 -2
  137. package/.output/server/_ssr/invite._token-CWl6kipD.mjs +0 -28
  138. package/.output/server/_ssr/logger-Gy-47z3k.mjs +0 -2
  139. package/.output/server/_ssr/loopApi-8_KgBapr.mjs +0 -109
  140. package/.output/server/_ssr/loopApi-ABi9SgWS.mjs +0 -564
  141. package/.output/server/_ssr/loops._loopId-SON_t43g.mjs +0 -30
  142. package/.output/server/_ssr/loops._loopId-p1KWsvMM.mjs +0 -1477
  143. package/.output/server/_ssr/notifyFns-BUCePuF3.mjs +0 -118
  144. package/.output/server/_ssr/router-Czxvra6l.mjs +0 -685
  145. package/.output/server/_ssr/runDiff--qLtU4FI.mjs +0 -2
  146. package/.output/server/_ssr/store-40eVzW1S.mjs +0 -2
  147. package/.output/server/_ssr/tokens-CbfoRC_s.mjs +0 -2
  148. package/.output/server/drizzle/0001_naive_silver_fox.sql +0 -25
  149. package/.output/server/drizzle/0002_funny_sage.sql +0 -12
  150. package/.output/server/drizzle/0003_optimal_slapstick.sql +0 -102
  151. package/.output/server/drizzle/0004_remove_grok_agent.sql +0 -5
  152. package/.output/server/drizzle/0005_heavy_gauntlet.sql +0 -8
  153. package/.output/server/drizzle/0006_tranquil_sharon_carter.sql +0 -1
  154. package/.output/server/drizzle/0007_faulty_starbolt.sql +0 -30
  155. package/.output/server/drizzle/0008_durable_lifecycle_evidence.sql +0 -15
  156. package/.output/server/drizzle/0009_ordinary_electro.sql +0 -1
  157. package/.output/server/drizzle/0010_workable_rage.sql +0 -14
  158. package/.output/server/drizzle/0011_steep_marvel_zombies.sql +0 -3
  159. package/.output/server/drizzle/0012_blocked_run_status.sql +0 -12
  160. package/.output/server/drizzle/0013_drop_run_outcome.sql +0 -2
  161. package/.output/server/drizzle/0014_luxuriant_scrambler.sql +0 -5
  162. package/.output/server/drizzle/0015_run_history_foundation.sql +0 -43
  163. package/.output/server/drizzle/0016_plural_machine_runs.sql +0 -4
  164. package/.output/server/drizzle/meta/0000_snapshot.json +0 -1333
  165. package/.output/server/drizzle/meta/0001_snapshot.json +0 -1498
  166. package/.output/server/drizzle/meta/0002_snapshot.json +0 -1576
  167. package/.output/server/drizzle/meta/0003_snapshot.json +0 -1666
  168. package/.output/server/drizzle/meta/0005_snapshot.json +0 -1666
  169. package/.output/server/drizzle/meta/0006_snapshot.json +0 -1672
  170. package/.output/server/drizzle/meta/0007_snapshot.json +0 -1787
  171. package/.output/server/drizzle/meta/0009_snapshot.json +0 -1793
  172. package/.output/server/drizzle/meta/0010_snapshot.json +0 -1891
  173. package/.output/server/drizzle/meta/0011_snapshot.json +0 -1872
  174. package/drizzle/0001_naive_silver_fox.sql +0 -25
  175. package/drizzle/0002_funny_sage.sql +0 -12
  176. package/drizzle/0003_optimal_slapstick.sql +0 -102
  177. package/drizzle/0004_remove_grok_agent.sql +0 -5
  178. package/drizzle/0005_heavy_gauntlet.sql +0 -8
  179. package/drizzle/0006_tranquil_sharon_carter.sql +0 -1
  180. package/drizzle/0007_faulty_starbolt.sql +0 -30
  181. package/drizzle/0008_durable_lifecycle_evidence.sql +0 -15
  182. package/drizzle/0009_ordinary_electro.sql +0 -1
  183. package/drizzle/0010_workable_rage.sql +0 -14
  184. package/drizzle/0011_steep_marvel_zombies.sql +0 -3
  185. package/drizzle/0012_blocked_run_status.sql +0 -12
  186. package/drizzle/0013_drop_run_outcome.sql +0 -2
  187. package/drizzle/0014_luxuriant_scrambler.sql +0 -5
  188. package/drizzle/0015_run_history_foundation.sql +0 -43
  189. package/drizzle/0016_plural_machine_runs.sql +0 -4
  190. package/drizzle/meta/0000_snapshot.json +0 -1333
  191. package/drizzle/meta/0001_snapshot.json +0 -1498
  192. package/drizzle/meta/0002_snapshot.json +0 -1576
  193. package/drizzle/meta/0003_snapshot.json +0 -1666
  194. package/drizzle/meta/0005_snapshot.json +0 -1666
  195. package/drizzle/meta/0006_snapshot.json +0 -1672
  196. package/drizzle/meta/0007_snapshot.json +0 -1787
  197. package/drizzle/meta/0009_snapshot.json +0 -1793
  198. package/drizzle/meta/0010_snapshot.json +0 -1891
  199. package/drizzle/meta/0011_snapshot.json +0 -1872
@@ -0,0 +1,1044 @@
1
+ import { o as __toESM } from "../_runtime.mjs";
2
+ import { D as defu, Gt as toKebabCase, L as getBaseURL, at as isSafeUrlScheme, g as capitalizeFirstLetter, x as createFetch } from "./boot-sNlIkoLe.mjs";
3
+ import { g as require_react, h as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
4
+ import { n as createServerFn, r as getServerFnById, t as TSS_SERVER_FUNCTION } from "./ssr.mjs";
5
+ //#region node_modules/.nitro/vite/services/ssr/assets/SocialLinks-Cm4H8pUJ.js
6
+ var import_react = /* @__PURE__ */ __toESM(require_react());
7
+ var import_jsx_runtime = require_jsx_runtime();
8
+ var createSsrRpc = (functionId) => {
9
+ const url = "/_serverFn/" + functionId;
10
+ const serverFnMeta = { id: functionId };
11
+ const fn = async (...args) => {
12
+ return (await getServerFnById(functionId, { origin: "server" }))(...args);
13
+ };
14
+ return Object.assign(fn, {
15
+ url,
16
+ serverFnMeta,
17
+ [TSS_SERVER_FUNCTION]: true
18
+ });
19
+ };
20
+ /**
21
+ * Server functions backing the dashboard. They run server-side (createServerFn
22
+ * → RPC) and call the IN-PROCESS scheduler + store directly — the scheduler
23
+ * lives in this same TanStack process (booted on first call via ensureServer).
24
+ * The machine-facing poll, CLI, report, and artifact-sync endpoints are sibling
25
+ * server routes in this same process, so one process owns the single scheduler.
26
+ *
27
+ * Reads and writes are scoped through requestScope/ownedLoop so users only see
28
+ * teams and loops their current session is authorized to access.
29
+ */
30
+ /**
31
+ * Resolve a loop and authorize the request against its owner. Returns the loop,
32
+ * or undefined when it's missing OR (gate on) owned by a different user — callers
33
+ * treat both as "not found" so existence never leaks across users.
34
+ */
35
+ /** Whether the auth gate is active (a GitHub OAuth app is configured). */
36
+ var getAuthState = createServerFn({ method: "GET" }).handler(createSsrRpc("b8119d5fe6ca1ed9f609702aa2133b5ac5337030c0bdcf92dc7eba889d6bd2e6"));
37
+ /**
38
+ * Client config. `pievoCli` is the CLI invocation prefix the skill + connect
39
+ * dialog use for every verb (`daemon start`, `new`, …) — defaults to the globally
40
+ * installed `pievo`. Set PIEVO_CLI locally to a runnable command that points at the in-repo
41
+ * daemon, e.g. `tsx /abs/packages/daemon/src/cli.ts` or
42
+ * `node /abs/packages/daemon/dist/cli.js`, so loops created from THIS server tell
43
+ * Claude Code to run your local code instead of the registry build.
44
+ */
45
+ var getConfig = createServerFn({ method: "GET" }).handler(createSsrRpc("cbb6a1b09b309459bbba3dc3851ae85fc468658b3cda77e22b6c6f3e28b65af4"));
46
+ /** GET — the teams this user may view (for the header switcher) + the active
47
+ * selection. A user gets only their memberships (usually one ⇒ no dropdown).
48
+ * Open mode ⇒ empty. An explicit `teamId` (the `/t/<id>` route) pins the active
49
+ * selection for THIS request — so the switcher highlights the tab's own team,
50
+ * not the cookie's. */
51
+ var listMyTeams = createServerFn({ method: "GET" }).validator((teamId) => teamId).handler(createSsrRpc("0fe12e769203c42f432a927b9cbf13a967a0f9db567b61843598f734afb4f5c6"));
52
+ /** GET — whether the caller may view the given dashboard team (`/t/<id>` loader
53
+ * gate). Enumeration-safe: a team the caller isn't a member of returns false, so
54
+ * the loader throws the same generic not-found as a missing loop — never
55
+ * confirming the team exists. Open mode ⇒ always true (single shared workspace). */
56
+ var canViewTeam = createServerFn({ method: "GET" }).validator((teamId) => teamId).handler(createSsrRpc("7cc22b3a0f6b1c4c73463c3401e981ad42caf6487b479b738ee5aeacb11710da"));
57
+ /** GET — the caller's default dashboard team as an id: the last-used cookie,
58
+ * validated, else the personal team. Backs the `/` → `/t/<id>` redirect. */
59
+ var getDefaultTeam = createServerFn({ method: "GET" }).handler(createSsrRpc("dc0ec955d0d53a150a3e9a4673f98f3509cfb4bd411c512079ae4e94c561b70c"));
60
+ /** GET — the signed-in user's loops as compact summaries (newest first).
61
+ * Gate on ⇒ only the given/active team's loops; open mode ⇒ the full shared list.
62
+ * An explicit `teamId` (the `/t/<id>` route) scopes this request independent of
63
+ * the cookie, so different tabs on /t/A and /t/B list different teams at once. */
64
+ var listLoops = createServerFn({ method: "GET" }).validator((teamId) => teamId).handler(createSsrRpc("23e290b2b7483ceea6fe669024c35b12c2c4ddd76649f6fab21c958ceda02940"));
65
+ /** GET — full detail (loop + summary + reversed runs). */
66
+ var getLoopDetail = createServerFn({ method: "GET" }).validator((id) => id).handler(createSsrRpc("b050455aacc84dd2a2c9a45517826ad10f91d8f1545e87cc7015784cc7116a97"));
67
+ /** GET — one older page of a loop's runs (cursor = `beforeTs`), for the card
68
+ * timeline's lazy "+N" paging. Chronological (oldest-first), capped. */
69
+ var loadOlderRuns = createServerFn({ method: "GET" }).validator((d) => d).handler(createSsrRpc("85fdf73d4fee43aed762f93c5d47d33200fbff39e2d082647dc921f610d32698"));
70
+ /** GET — the loop's current live-synced files (metadata only; path-sorted). */
71
+ var getArtifacts = createServerFn({ method: "GET" }).validator((d) => d).handler(createSsrRpc("b18bbec3d06dfc77714e1e527dfb9172fd7575a64a6c0d6e73ba6dc658dccf0d"));
72
+ /** GET — one artifact's content: decoded text, or a binary/oversize marker the
73
+ * UI turns into a download link (bytes stream from the /api/artifact route). */
74
+ var getArtifact = createServerFn({ method: "GET" }).validator((d) => d).handler(createSsrRpc("ed10d5fe79208e5e0e4e18e4a17b18d7f7db4dd16204c00c3ac90c4644668841"));
75
+ /** GET — a run's per-file diff vs the previous run. Lazy by runId like
76
+ * computed on the server at read time (no stored diffs). Old runs
77
+ * with no snapshot return `hasSnapshot: false` for the degrade copy. */
78
+ var getRunDiff = createServerFn({ method: "GET" }).validator((d) => d).handler(createSsrRpc("08c28b892712a1b491b120b74c7dcb81761988d31ccea60216d1807b73c1182c"));
79
+ var patchLoop = createServerFn({ method: "POST" }).validator((d) => d).handler(createSsrRpc("9befe6b8d67ccbbd7aa9b538bde2a161a9894761c8936761a9503fda1a88c0fc"));
80
+ /** Dedicated lifecycle operations. Dashboard callers never synthesize these
81
+ * transitions with patchLoop: each delegates to the loop-locked store operation. */
82
+ var pauseLoop = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("95b7483b333d7649e70c848319417e83c2af6a0327bbcda2d0e331f626dffe05"));
83
+ var startLoop = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("5660ea82ea5ff2549e0ce2f8f070c54f3e9e24fee84d547601ef5d6ef49a4016"));
84
+ var stopLoop = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("e233a461e4526dec3cc4cbaa891a7c3621d5967ce7f32b4fb17e9fb645857b9a"));
85
+ /** Delete is one confirmed operation. Reachable machines get the graceful
86
+ * Stop-and-wait path; a machine already offline at click time cannot acknowledge
87
+ * Stop, so retire its execution authority and remove server data immediately.
88
+ * Local files are never touched by either path. */
89
+ var deleteLoop = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("5e0d6b55f5629faac2f55a68661eeb82668b2be752192b16264ffb5cd1e6fabe"));
90
+ var runLoop = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("08565e35f6a3dd06ef25401de0343976c47f7ae319d3baed6320b56dd3718311"));
91
+ /** Dedicated Stop-run operation. Pending work cancels immediately; running work
92
+ * records intent and stays Running until the daemon reports its actual result. */
93
+ var stopRun = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("6850ba403da9dec5aff45794eb52636ca540ddec2d9e59f5c75ccbb852bfeacb"));
94
+ /** Mint the key shown in the New-loop daemon connection command. It may enroll
95
+ * a new machine and remains valid as an optional team-bound create claim. */
96
+ var mintClaim = createServerFn({ method: "POST" }).validator((teamId) => teamId).handler(createSsrRpc("4646f52fb09b83c9c9cef34836f3c9d03416423c879d9e5ceffcafd9a71ecba6"));
97
+ var PROTO_POLLUTION_PATTERNS = {
98
+ proto: /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,
99
+ constructor: /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,
100
+ protoShort: /"__proto__"\s*:/,
101
+ constructorShort: /"constructor"\s*:/
102
+ };
103
+ var JSON_SIGNATURE = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
104
+ var SPECIAL_VALUES = {
105
+ true: true,
106
+ false: false,
107
+ null: null,
108
+ undefined: void 0,
109
+ nan: NaN,
110
+ infinity: Number.POSITIVE_INFINITY,
111
+ "-infinity": Number.NEGATIVE_INFINITY
112
+ };
113
+ var ISO_DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,7}))?(?:Z|([+-])(\d{2}):(\d{2}))$/;
114
+ function isValidDate(date) {
115
+ return date instanceof Date && !isNaN(date.getTime());
116
+ }
117
+ function parseISODate(value) {
118
+ const match = ISO_DATE_REGEX.exec(value);
119
+ if (!match) return null;
120
+ const [, year, month, day, hour, minute, second, ms, offsetSign, offsetHour, offsetMinute] = match;
121
+ const date = new Date(Date.UTC(parseInt(year, 10), parseInt(month, 10) - 1, parseInt(day, 10), parseInt(hour, 10), parseInt(minute, 10), parseInt(second, 10), ms ? parseInt(ms.padEnd(3, "0"), 10) : 0));
122
+ if (offsetSign) {
123
+ const offset = (parseInt(offsetHour, 10) * 60 + parseInt(offsetMinute, 10)) * (offsetSign === "+" ? -1 : 1);
124
+ date.setUTCMinutes(date.getUTCMinutes() + offset);
125
+ }
126
+ return isValidDate(date) ? date : null;
127
+ }
128
+ function betterJSONParse(value, options = {}) {
129
+ const { strict = false, warnings = false, reviver, parseDates = true } = options;
130
+ if (typeof value !== "string") return value;
131
+ const trimmed = value.trim();
132
+ const lowerValue = trimmed.toLowerCase();
133
+ if (lowerValue.length <= 9 && lowerValue in SPECIAL_VALUES) return SPECIAL_VALUES[lowerValue];
134
+ if (!JSON_SIGNATURE.test(trimmed)) {
135
+ if (strict) throw new SyntaxError("[better-json] Invalid JSON");
136
+ return value;
137
+ }
138
+ if (Object.entries(PROTO_POLLUTION_PATTERNS).some(([key, pattern]) => {
139
+ const matches = pattern.test(trimmed);
140
+ if (matches && warnings) console.warn(`[better-json] Detected potential prototype pollution attempt using ${key} pattern`);
141
+ return matches;
142
+ }) && strict) throw new Error("[better-json] Potential prototype pollution attempt detected");
143
+ try {
144
+ const secureReviver = (key, value) => {
145
+ if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) {
146
+ if (warnings) console.warn(`[better-json] Dropping "${key}" key to prevent prototype pollution`);
147
+ return;
148
+ }
149
+ if (parseDates && typeof value === "string") {
150
+ const date = parseISODate(value);
151
+ if (date) return date;
152
+ }
153
+ return reviver ? reviver(key, value) : value;
154
+ };
155
+ return JSON.parse(trimmed, secureReviver);
156
+ } catch (error) {
157
+ if (strict) throw error;
158
+ return value;
159
+ }
160
+ }
161
+ function parseJSON(value, options = { strict: true }) {
162
+ return betterJSONParse(value, options);
163
+ }
164
+ var redirectPlugin = {
165
+ id: "redirect",
166
+ name: "Redirect",
167
+ hooks: { onSuccess(context) {
168
+ if (context.data?.url && context.data?.redirect && isSafeUrlScheme(context.data.url)) {
169
+ if (typeof window !== "undefined" && window.location) {
170
+ if (window.location) try {
171
+ window.location.href = context.data.url;
172
+ } catch {}
173
+ }
174
+ }
175
+ } }
176
+ };
177
+ var listenerQueue = [];
178
+ var lqIndex = 0;
179
+ var QUEUE_ITEMS_PER_LISTENER = 4;
180
+ var nanostoresGlobal = globalThis.nanostoresGlobal ||= { epoch: 0 };
181
+ var atom = /* @__NO_SIDE_EFFECTS__ */ (initialValue) => {
182
+ let listeners = [];
183
+ let $atom = {
184
+ get() {
185
+ if (!$atom.lc) $atom.listen(() => {})();
186
+ return $atom.value;
187
+ },
188
+ init: initialValue,
189
+ lc: 0,
190
+ listen(listener) {
191
+ $atom.lc = listeners.push(listener);
192
+ return () => {
193
+ for (let i = lqIndex + QUEUE_ITEMS_PER_LISTENER; i < listenerQueue.length;) if (listenerQueue[i] === listener) listenerQueue.splice(i, QUEUE_ITEMS_PER_LISTENER);
194
+ else i += QUEUE_ITEMS_PER_LISTENER;
195
+ let index = listeners.indexOf(listener);
196
+ if (~index) {
197
+ listeners.splice(index, 1);
198
+ if (!--$atom.lc) $atom.off();
199
+ }
200
+ };
201
+ },
202
+ notify(oldValue, changedKey) {
203
+ nanostoresGlobal.epoch++;
204
+ let runListenerQueue = !listenerQueue.length;
205
+ for (let listener of listeners) listenerQueue.push(listener, $atom.value, oldValue, changedKey);
206
+ if (runListenerQueue) {
207
+ for (lqIndex = 0; lqIndex < listenerQueue.length; lqIndex += QUEUE_ITEMS_PER_LISTENER) listenerQueue[lqIndex](listenerQueue[lqIndex + 1], listenerQueue[lqIndex + 2], listenerQueue[lqIndex + 3]);
208
+ listenerQueue.length = 0;
209
+ }
210
+ },
211
+ off() {},
212
+ set(newValue) {
213
+ let oldValue = $atom.value;
214
+ if (oldValue !== newValue) {
215
+ $atom.value = newValue;
216
+ $atom.notify(oldValue);
217
+ }
218
+ },
219
+ subscribe(listener) {
220
+ let unbind = $atom.listen(listener);
221
+ listener($atom.value);
222
+ return unbind;
223
+ },
224
+ value: initialValue
225
+ };
226
+ return $atom;
227
+ };
228
+ var SET = 2;
229
+ var MOUNT = 5;
230
+ var UNMOUNT = 6;
231
+ var REVERT_MUTATION = 10;
232
+ var on = (object, listener, eventKey, mutateStore) => {
233
+ object.events = object.events || {};
234
+ if (!object.events[eventKey + REVERT_MUTATION]) object.events[eventKey + REVERT_MUTATION] = mutateStore((eventProps) => {
235
+ object.events[eventKey].reduceRight((event, l) => (l(event), event), {
236
+ shared: {},
237
+ ...eventProps
238
+ });
239
+ });
240
+ object.events[eventKey] = object.events[eventKey] || [];
241
+ object.events[eventKey].push(listener);
242
+ return () => {
243
+ let currentListeners = object.events[eventKey];
244
+ let index = currentListeners.indexOf(listener);
245
+ currentListeners.splice(index, 1);
246
+ if (!currentListeners.length) {
247
+ delete object.events[eventKey];
248
+ object.events[eventKey + REVERT_MUTATION]();
249
+ delete object.events[eventKey + REVERT_MUTATION];
250
+ }
251
+ };
252
+ };
253
+ var onSet = ($store, listener) => on($store, listener, SET, (runListeners) => {
254
+ let originSet = $store.set;
255
+ let originSetKey = $store.setKey;
256
+ if ($store.setKey) $store.setKey = (changed, changedValue) => {
257
+ let isAborted;
258
+ let abort = () => {
259
+ isAborted = true;
260
+ };
261
+ runListeners({
262
+ abort,
263
+ changed,
264
+ newValue: {
265
+ ...$store.value,
266
+ [changed]: changedValue
267
+ }
268
+ });
269
+ if (!isAborted) return originSetKey(changed, changedValue);
270
+ };
271
+ $store.set = (newValue) => {
272
+ let isAborted;
273
+ let abort = () => {
274
+ isAborted = true;
275
+ };
276
+ runListeners({
277
+ abort,
278
+ newValue
279
+ });
280
+ if (!isAborted) return originSet(newValue);
281
+ };
282
+ return () => {
283
+ $store.set = originSet;
284
+ $store.setKey = originSetKey;
285
+ };
286
+ });
287
+ var STORE_UNMOUNT_DELAY = 1e3;
288
+ var onMount = ($store, initialize) => {
289
+ let listener = (payload) => {
290
+ let destroy = initialize(payload);
291
+ if (destroy) $store.events[UNMOUNT].push(destroy);
292
+ };
293
+ return on($store, listener, MOUNT, (runListeners) => {
294
+ let originListen = $store.listen;
295
+ $store.listen = (...args) => {
296
+ if (!$store.lc && !$store.active) {
297
+ $store.active = true;
298
+ runListeners();
299
+ }
300
+ return originListen(...args);
301
+ };
302
+ let originOff = $store.off;
303
+ $store.events[UNMOUNT] = [];
304
+ $store.off = () => {
305
+ originOff();
306
+ setTimeout(() => {
307
+ if ($store.active && !$store.lc) {
308
+ $store.active = false;
309
+ for (let destroy of $store.events[UNMOUNT]) destroy();
310
+ $store.events[UNMOUNT] = [];
311
+ }
312
+ }, STORE_UNMOUNT_DELAY);
313
+ };
314
+ return () => {
315
+ $store.listen = originListen;
316
+ $store.off = originOff;
317
+ };
318
+ });
319
+ };
320
+ function listenKeys($store, keys, listener) {
321
+ let keysSet = new Set(keys).add(void 0);
322
+ return $store.listen((value, oldValue, changed) => {
323
+ if (keysSet.has(changed)) listener(value, oldValue, changed);
324
+ });
325
+ }
326
+ function isPlainObject(value) {
327
+ if (typeof value !== "object" || value === null) return false;
328
+ const prototype = Object.getPrototypeOf(value);
329
+ return prototype === Object.prototype || prototype === null;
330
+ }
331
+ /**
332
+ * Deep structural equality for JSON-serializable values.
333
+ * Handles: primitives, null, arrays, and plain objects.
334
+ * Short-circuits on referential equality at every recursion level.
335
+ */
336
+ function isJsonEqual(a, b) {
337
+ if (a === b) return true;
338
+ if (Array.isArray(a) && Array.isArray(b)) {
339
+ if (a.length !== b.length) return false;
340
+ for (let i = 0; i < a.length; i++) if (!isJsonEqual(a[i], b[i])) return false;
341
+ return true;
342
+ }
343
+ if (isPlainObject(a) && isPlainObject(b)) {
344
+ const keysA = Object.keys(a);
345
+ const keysB = Object.keys(b);
346
+ if (keysA.length !== keysB.length) return false;
347
+ for (const key of keysA) if (!(key in b) || !isJsonEqual(a[key], b[key])) return false;
348
+ return true;
349
+ }
350
+ return false;
351
+ }
352
+ /**
353
+ * Attach an equality gate to a nanostores atom via `onSet`.
354
+ * When `isEqual(currentValue, newValue)` returns true, the `set()` call
355
+ * is aborted: no listeners fire, no framework re-renders occur.
356
+ *
357
+ * Returns the unsubscribe function from `onSet`.
358
+ */
359
+ function withEquality(store, isEqual) {
360
+ return onSet(store, ({ newValue, abort }) => {
361
+ if (isEqual(store.value, newValue)) abort();
362
+ });
363
+ }
364
+ var kBroadcastChannel = Symbol.for("better-auth:broadcast-channel");
365
+ var now$1 = () => Math.floor(Date.now() / 1e3);
366
+ var WindowBroadcastChannel = class {
367
+ listeners = /* @__PURE__ */ new Set();
368
+ name;
369
+ constructor(name = "better-auth.message") {
370
+ this.name = name;
371
+ }
372
+ subscribe(listener) {
373
+ this.listeners.add(listener);
374
+ return () => {
375
+ this.listeners.delete(listener);
376
+ };
377
+ }
378
+ post(message) {
379
+ if (typeof window === "undefined") return;
380
+ try {
381
+ localStorage.setItem(this.name, JSON.stringify({
382
+ ...message,
383
+ timestamp: now$1()
384
+ }));
385
+ } catch {}
386
+ }
387
+ setup() {
388
+ if (typeof window === "undefined" || typeof window.addEventListener === "undefined") return () => {};
389
+ const handler = (event) => {
390
+ if (event.key !== this.name) return;
391
+ const message = JSON.parse(event.newValue ?? "{}");
392
+ if (message?.event !== "session" || !message?.data) return;
393
+ this.listeners.forEach((listener) => listener(message));
394
+ };
395
+ window.addEventListener("storage", handler);
396
+ return () => {
397
+ window.removeEventListener("storage", handler);
398
+ };
399
+ }
400
+ };
401
+ function getGlobalBroadcastChannel(name = "better-auth.message") {
402
+ if (!globalThis[kBroadcastChannel]) globalThis[kBroadcastChannel] = new WindowBroadcastChannel(name);
403
+ return globalThis[kBroadcastChannel];
404
+ }
405
+ var kFocusManager = Symbol.for("better-auth:focus-manager");
406
+ var WindowFocusManager = class {
407
+ listeners = /* @__PURE__ */ new Set();
408
+ subscribe(listener) {
409
+ this.listeners.add(listener);
410
+ return () => {
411
+ this.listeners.delete(listener);
412
+ };
413
+ }
414
+ setFocused(focused) {
415
+ this.listeners.forEach((listener) => listener(focused));
416
+ }
417
+ setup() {
418
+ if (typeof window === "undefined" || typeof document === "undefined" || typeof window.addEventListener === "undefined") return () => {};
419
+ const visibilityHandler = () => {
420
+ if (document.visibilityState === "visible") this.setFocused(true);
421
+ };
422
+ document.addEventListener("visibilitychange", visibilityHandler, false);
423
+ return () => {
424
+ document.removeEventListener("visibilitychange", visibilityHandler, false);
425
+ };
426
+ }
427
+ };
428
+ function getGlobalFocusManager() {
429
+ if (!globalThis[kFocusManager]) globalThis[kFocusManager] = new WindowFocusManager();
430
+ return globalThis[kFocusManager];
431
+ }
432
+ var kOnlineManager = Symbol.for("better-auth:online-manager");
433
+ var WindowOnlineManager = class {
434
+ listeners = /* @__PURE__ */ new Set();
435
+ isOnline = typeof navigator !== "undefined" ? navigator.onLine : true;
436
+ subscribe(listener) {
437
+ this.listeners.add(listener);
438
+ return () => {
439
+ this.listeners.delete(listener);
440
+ };
441
+ }
442
+ setOnline(online) {
443
+ this.isOnline = online;
444
+ this.listeners.forEach((listener) => listener(online));
445
+ }
446
+ setup() {
447
+ if (typeof window === "undefined" || typeof window.addEventListener === "undefined") return () => {};
448
+ const onOnline = () => this.setOnline(true);
449
+ const onOffline = () => this.setOnline(false);
450
+ window.addEventListener("online", onOnline, false);
451
+ window.addEventListener("offline", onOffline, false);
452
+ return () => {
453
+ window.removeEventListener("online", onOnline, false);
454
+ window.removeEventListener("offline", onOffline, false);
455
+ };
456
+ }
457
+ };
458
+ function getGlobalOnlineManager() {
459
+ if (!globalThis[kOnlineManager]) globalThis[kOnlineManager] = new WindowOnlineManager();
460
+ return globalThis[kOnlineManager];
461
+ }
462
+ var now = () => Math.floor(Date.now() / 1e3);
463
+ /**
464
+ * Rate limit: don't refetch on focus if a session request was made within this many seconds
465
+ */
466
+ var FOCUS_REFETCH_RATE_LIMIT_SECONDS = 5;
467
+ function createSessionRefreshManager(opts) {
468
+ const { fetchSession, shouldPollSession = () => true, sessionSignal, options = {} } = opts;
469
+ const refetchInterval = options.sessionOptions?.refetchInterval ?? 0;
470
+ const refetchOnWindowFocus = options.sessionOptions?.refetchOnWindowFocus ?? true;
471
+ const refetchWhenOffline = options.sessionOptions?.refetchWhenOffline ?? false;
472
+ const state = {
473
+ isInitialized: false,
474
+ lastSessionRequest: 0
475
+ };
476
+ const shouldRefetch = () => {
477
+ return refetchWhenOffline || getGlobalOnlineManager().isOnline;
478
+ };
479
+ const triggerRefetch = (event) => {
480
+ if (!shouldRefetch()) return;
481
+ if (event?.event === "storage") {
482
+ fetchSession();
483
+ return;
484
+ }
485
+ if (event?.event === "poll") {
486
+ state.lastSessionRequest = now();
487
+ fetchSession();
488
+ return;
489
+ }
490
+ if (event?.event === "visibilitychange") {
491
+ if (now() - state.lastSessionRequest < FOCUS_REFETCH_RATE_LIMIT_SECONDS) return;
492
+ state.lastSessionRequest = now();
493
+ fetchSession();
494
+ return;
495
+ }
496
+ fetchSession();
497
+ };
498
+ const broadcastSessionUpdate = (trigger) => {
499
+ getGlobalBroadcastChannel().post({
500
+ event: "session",
501
+ data: { trigger },
502
+ clientId: Math.random().toString(36).substring(7)
503
+ });
504
+ };
505
+ const setupPolling = () => {
506
+ if (refetchInterval && refetchInterval > 0) state.pollInterval = setInterval(() => {
507
+ if (shouldPollSession()) triggerRefetch({ event: "poll" });
508
+ }, refetchInterval * 1e3);
509
+ };
510
+ const setupBroadcast = () => {
511
+ state.unsubscribeBroadcast = getGlobalBroadcastChannel().subscribe(() => {
512
+ triggerRefetch({ event: "storage" });
513
+ });
514
+ };
515
+ const setupFocusRefetch = () => {
516
+ if (!refetchOnWindowFocus) return;
517
+ state.unsubscribeFocus = getGlobalFocusManager().subscribe(() => {
518
+ triggerRefetch({ event: "visibilitychange" });
519
+ });
520
+ };
521
+ const setupOnlineRefetch = () => {
522
+ state.unsubscribeOnline = getGlobalOnlineManager().subscribe((online) => {
523
+ if (online) triggerRefetch({ event: "visibilitychange" });
524
+ });
525
+ };
526
+ const setupSignalSubscription = () => {
527
+ state.unsubscribeSignal = sessionSignal.listen(() => {
528
+ fetchSession();
529
+ });
530
+ };
531
+ const init = () => {
532
+ if (state.isInitialized) return;
533
+ state.isInitialized = true;
534
+ setupPolling();
535
+ setupBroadcast();
536
+ setupFocusRefetch();
537
+ setupOnlineRefetch();
538
+ setupSignalSubscription();
539
+ state.cleanupBroadcastSetup = getGlobalBroadcastChannel().setup();
540
+ state.cleanupFocusSetup = getGlobalFocusManager().setup();
541
+ state.cleanupOnlineSetup = getGlobalOnlineManager().setup();
542
+ };
543
+ const cleanup = () => {
544
+ if (!state.isInitialized) return;
545
+ if (state.pollInterval) {
546
+ clearInterval(state.pollInterval);
547
+ state.pollInterval = void 0;
548
+ }
549
+ if (state.unsubscribeBroadcast) {
550
+ state.unsubscribeBroadcast();
551
+ state.unsubscribeBroadcast = void 0;
552
+ }
553
+ if (state.unsubscribeFocus) {
554
+ state.unsubscribeFocus();
555
+ state.unsubscribeFocus = void 0;
556
+ }
557
+ if (state.unsubscribeOnline) {
558
+ state.unsubscribeOnline();
559
+ state.unsubscribeOnline = void 0;
560
+ }
561
+ if (state.unsubscribeSignal) {
562
+ state.unsubscribeSignal();
563
+ state.unsubscribeSignal = void 0;
564
+ }
565
+ if (state.cleanupBroadcastSetup) {
566
+ state.cleanupBroadcastSetup();
567
+ state.cleanupBroadcastSetup = void 0;
568
+ }
569
+ if (state.cleanupFocusSetup) {
570
+ state.cleanupFocusSetup();
571
+ state.cleanupFocusSetup = void 0;
572
+ }
573
+ if (state.cleanupOnlineSetup) {
574
+ state.cleanupOnlineSetup();
575
+ state.cleanupOnlineSetup = void 0;
576
+ }
577
+ state.isInitialized = false;
578
+ state.lastSessionRequest = 0;
579
+ };
580
+ return {
581
+ init,
582
+ cleanup,
583
+ triggerRefetch,
584
+ broadcastSessionUpdate
585
+ };
586
+ }
587
+ var isServer = () => typeof window === "undefined";
588
+ /**
589
+ * Normalize $fetch response: `throw: true` returns data directly,
590
+ * otherwise `{ data, error }`.
591
+ */
592
+ function normalizeSessionResponse(res) {
593
+ if (typeof res === "object" && res !== null && "data" in res && "error" in res) return res;
594
+ return {
595
+ data: res,
596
+ error: null
597
+ };
598
+ }
599
+ function normalizeSessionData(data) {
600
+ if (!data) return null;
601
+ if (data.session === null && data.user === null) return null;
602
+ return data;
603
+ }
604
+ function isSessionAtomEqual(a, b) {
605
+ return isJsonEqual(a.data, b.data) && a.error === b.error && a.isPending === b.isPending && a.isRefetching === b.isRefetching && a.refetch === b.refetch;
606
+ }
607
+ function getSessionAtom($fetch, options) {
608
+ const $signal = /* @__PURE__ */ atom(false);
609
+ let abortController;
610
+ const refetch = (queryParams) => fetchSession(queryParams);
611
+ const session = /* @__PURE__ */ atom({
612
+ data: null,
613
+ error: null,
614
+ isPending: true,
615
+ isRefetching: false,
616
+ refetch
617
+ });
618
+ withEquality(session, isSessionAtomEqual);
619
+ const settleAbortedFetch = (controller) => {
620
+ if (abortController !== controller) return;
621
+ const current = session.get();
622
+ abortController = void 0;
623
+ if (!current.isPending && !current.isRefetching) return;
624
+ session.set({
625
+ ...current,
626
+ isPending: false,
627
+ isRefetching: false,
628
+ refetch
629
+ });
630
+ };
631
+ const fetchSession = async (queryParams) => {
632
+ abortController?.abort();
633
+ const controller = new AbortController();
634
+ abortController = controller;
635
+ const current = session.get();
636
+ session.set({
637
+ ...current,
638
+ isPending: current.data === null,
639
+ isRefetching: true,
640
+ error: null,
641
+ refetch
642
+ });
643
+ try {
644
+ const res = await $fetch("/get-session", {
645
+ method: "GET",
646
+ query: queryParams?.query,
647
+ signal: controller.signal
648
+ });
649
+ if (controller.signal.aborted) {
650
+ settleAbortedFetch(controller);
651
+ return;
652
+ }
653
+ let { data, error } = normalizeSessionResponse(res);
654
+ if (data?.needsRefresh) try {
655
+ const refreshRes = await $fetch("/get-session", {
656
+ method: "POST",
657
+ signal: controller.signal
658
+ });
659
+ if (controller.signal.aborted) {
660
+ settleAbortedFetch(controller);
661
+ return;
662
+ }
663
+ ({data, error} = normalizeSessionResponse(refreshRes));
664
+ } catch {
665
+ if (controller.signal.aborted) {
666
+ settleAbortedFetch(controller);
667
+ return;
668
+ }
669
+ }
670
+ if (error) {
671
+ const latest = session.get();
672
+ const isUnauthorized = error?.status === 401;
673
+ session.set({
674
+ data: isUnauthorized ? null : latest.data,
675
+ error,
676
+ isPending: false,
677
+ isRefetching: false,
678
+ refetch
679
+ });
680
+ return;
681
+ }
682
+ const sessionData = normalizeSessionData(data);
683
+ const current = session.get();
684
+ const stableData = current.data != null && sessionData != null && isJsonEqual(current.data, sessionData) ? current.data : sessionData;
685
+ session.set({
686
+ data: stableData,
687
+ error: null,
688
+ isPending: false,
689
+ isRefetching: false,
690
+ refetch
691
+ });
692
+ } catch (fetchError) {
693
+ if (controller.signal.aborted) {
694
+ settleAbortedFetch(controller);
695
+ return;
696
+ }
697
+ const latest = session.get();
698
+ session.set({
699
+ data: latest.data,
700
+ error: fetchError,
701
+ isPending: false,
702
+ isRefetching: false,
703
+ refetch
704
+ });
705
+ }
706
+ };
707
+ let broadcastSessionUpdate = () => {};
708
+ onMount(session, () => {
709
+ let timeoutId;
710
+ if (!isServer()) timeoutId = setTimeout(() => {
711
+ fetchSession();
712
+ }, 0);
713
+ const refreshManager = createSessionRefreshManager({
714
+ fetchSession,
715
+ shouldPollSession: () => session.get().data != null,
716
+ sessionSignal: $signal,
717
+ options
718
+ });
719
+ refreshManager.init();
720
+ broadcastSessionUpdate = refreshManager.broadcastSessionUpdate;
721
+ return () => {
722
+ if (timeoutId) clearTimeout(timeoutId);
723
+ const controller = abortController;
724
+ controller?.abort();
725
+ if (controller) settleAbortedFetch(controller);
726
+ refreshManager.cleanup();
727
+ };
728
+ });
729
+ return {
730
+ session,
731
+ $sessionSignal: $signal,
732
+ broadcastSessionUpdate: (trigger) => broadcastSessionUpdate(trigger)
733
+ };
734
+ }
735
+ var resolvePublicAuthUrl = (basePath) => {
736
+ if (typeof process === "undefined") return void 0;
737
+ const path = basePath ?? "/api/auth";
738
+ if (process.env.NEXT_PUBLIC_AUTH_URL) return process.env.NEXT_PUBLIC_AUTH_URL;
739
+ if (typeof window === "undefined") {
740
+ if (process.env.NEXTAUTH_URL) try {
741
+ return process.env.NEXTAUTH_URL;
742
+ } catch {}
743
+ if (process.env.VERCEL_URL) try {
744
+ const protocol = process.env.VERCEL_URL.startsWith("http") ? "" : "https://";
745
+ return `${new URL(`${protocol}${process.env.VERCEL_URL}`).origin}${path}`;
746
+ } catch {}
747
+ }
748
+ };
749
+ var getClientConfig = (options, loadEnv) => {
750
+ const isCredentialsSupported = "credentials" in Request.prototype;
751
+ const baseURL = getBaseURL(options?.baseURL, options?.basePath, void 0, loadEnv) ?? resolvePublicAuthUrl(options?.basePath) ?? "/api/auth";
752
+ const pluginsFetchPlugins = options?.plugins?.flatMap((plugin) => plugin.fetchPlugins).filter((pl) => pl !== void 0) || [];
753
+ const lifeCyclePlugin = {
754
+ id: "lifecycle-hooks",
755
+ name: "lifecycle-hooks",
756
+ hooks: {
757
+ onSuccess: options?.fetchOptions?.onSuccess,
758
+ onError: options?.fetchOptions?.onError,
759
+ onRequest: options?.fetchOptions?.onRequest,
760
+ onResponse: options?.fetchOptions?.onResponse
761
+ }
762
+ };
763
+ const { onSuccess: _onSuccess, onError: _onError, onRequest: _onRequest, onResponse: _onResponse, ...restOfFetchOptions } = options?.fetchOptions || {};
764
+ const $fetch = createFetch({
765
+ baseURL,
766
+ ...isCredentialsSupported ? { credentials: "include" } : {},
767
+ method: "GET",
768
+ jsonParser(text) {
769
+ if (!text) return null;
770
+ return parseJSON(text, { strict: false });
771
+ },
772
+ customFetchImpl: fetch,
773
+ ...restOfFetchOptions,
774
+ plugins: [
775
+ lifeCyclePlugin,
776
+ ...restOfFetchOptions.plugins || [],
777
+ ...options?.disableDefaultFetchPlugins ? [] : [redirectPlugin],
778
+ ...pluginsFetchPlugins
779
+ ]
780
+ });
781
+ const { $sessionSignal, session, broadcastSessionUpdate } = getSessionAtom($fetch, options);
782
+ const plugins = options?.plugins || [];
783
+ let pluginsActions = {};
784
+ const pluginsAtoms = {
785
+ $sessionSignal,
786
+ session
787
+ };
788
+ const pluginPathMethods = {
789
+ "/sign-out": "POST",
790
+ "/revoke-sessions": "POST",
791
+ "/revoke-other-sessions": "POST",
792
+ "/delete-user": "POST"
793
+ };
794
+ const atomListeners = [{
795
+ signal: "$sessionSignal",
796
+ matcher(path) {
797
+ return path === "/sign-out" || path === "/update-user" || path === "/update-session" || path === "/sign-up/email" || path === "/sign-in/email" || path === "/delete-user" || path === "/verify-email" || path === "/revoke-sessions" || path === "/revoke-session" || path === "/revoke-other-sessions" || path === "/change-email" || path === "/change-password";
798
+ },
799
+ callback(path) {
800
+ if (path === "/sign-out") broadcastSessionUpdate("signout");
801
+ else if (path === "/update-user" || path === "/update-session") broadcastSessionUpdate("updateUser");
802
+ }
803
+ }];
804
+ for (const plugin of plugins) {
805
+ if (plugin.getAtoms) Object.assign(pluginsAtoms, plugin.getAtoms?.($fetch));
806
+ if (plugin.pathMethods) Object.assign(pluginPathMethods, plugin.pathMethods);
807
+ if (plugin.atomListeners) atomListeners.push(...plugin.atomListeners);
808
+ }
809
+ const $store = {
810
+ notify: (signal) => {
811
+ pluginsAtoms[signal].set(!pluginsAtoms[signal].get());
812
+ },
813
+ listen: (signal, listener) => {
814
+ pluginsAtoms[signal].subscribe(listener);
815
+ },
816
+ atoms: pluginsAtoms
817
+ };
818
+ for (const plugin of plugins) if (plugin.getActions) pluginsActions = defu(plugin.getActions?.($fetch, $store, options) ?? {}, pluginsActions);
819
+ return {
820
+ get baseURL() {
821
+ return baseURL;
822
+ },
823
+ pluginsActions,
824
+ pluginsAtoms,
825
+ pluginPathMethods,
826
+ atomListeners,
827
+ $fetch,
828
+ $store
829
+ };
830
+ };
831
+ function isAtom(value) {
832
+ return typeof value === "object" && value !== null && "get" in value && typeof value.get === "function" && "lc" in value && typeof value.lc === "number";
833
+ }
834
+ function getMethod(path, knownPathMethods, args) {
835
+ const method = knownPathMethods[path];
836
+ const { fetchOptions, query: _query, ...body } = args || {};
837
+ if (method) return method;
838
+ if (fetchOptions?.method) return fetchOptions.method;
839
+ if (body && Object.keys(body).length > 0) return "POST";
840
+ return "GET";
841
+ }
842
+ function createDynamicPathProxy(routes, client, knownPathMethods, atoms, atomListeners) {
843
+ function createProxy(path = []) {
844
+ return new Proxy(function() {}, {
845
+ get(_, prop) {
846
+ if (typeof prop !== "string") return;
847
+ if (prop === "then" || prop === "catch" || prop === "finally") return;
848
+ const fullPath = [...path, prop];
849
+ let current = routes;
850
+ for (const segment of fullPath) if (current && typeof current === "object" && segment in current) current = current[segment];
851
+ else {
852
+ current = void 0;
853
+ break;
854
+ }
855
+ if (typeof current === "function") return current;
856
+ if (isAtom(current)) return current;
857
+ return createProxy(fullPath);
858
+ },
859
+ apply: async (_, __, args) => {
860
+ const routePath = "/" + path.map(toKebabCase).join("/");
861
+ const arg = args[0] || {};
862
+ const fetchOptions = args[1] || {};
863
+ const { query, fetchOptions: argFetchOptions, ...body } = arg;
864
+ const options = {
865
+ ...fetchOptions,
866
+ ...argFetchOptions
867
+ };
868
+ const method = getMethod(routePath, knownPathMethods, arg);
869
+ return await client(routePath, {
870
+ ...options,
871
+ body: method === "GET" ? void 0 : {
872
+ ...body,
873
+ ...options?.body || {}
874
+ },
875
+ query: query || options?.query,
876
+ method,
877
+ async onSuccess(context) {
878
+ await options?.onSuccess?.(context);
879
+ if (!atomListeners || options.disableSignal) return;
880
+ /**
881
+ * We trigger listeners
882
+ */
883
+ const matches = atomListeners.filter((s) => s.matcher(routePath));
884
+ if (!matches.length) return;
885
+ const visited = /* @__PURE__ */ new Set();
886
+ for (const match of matches) {
887
+ const signal = atoms[match.signal];
888
+ if (!signal) return;
889
+ if (visited.has(match.signal)) continue;
890
+ visited.add(match.signal);
891
+ /**
892
+ * To avoid race conditions we set the signal in a setTimeout
893
+ */
894
+ const val = signal.get();
895
+ setTimeout(() => {
896
+ signal.set(!val);
897
+ }, 10);
898
+ match.callback?.(routePath);
899
+ }
900
+ }
901
+ });
902
+ }
903
+ });
904
+ }
905
+ return createProxy();
906
+ }
907
+ /**
908
+ * Subscribe to store changes and get store's value.
909
+ *
910
+ * Can be used with store builder too.
911
+ *
912
+ * ```js
913
+ * import { useStore } from 'nanostores/react'
914
+ *
915
+ * import { router } from '../store/router'
916
+ *
917
+ * export const Layout = () => {
918
+ * let page = useStore(router)
919
+ * if (page.route === 'home') {
920
+ * return <HomePage />
921
+ * } else {
922
+ * return <Error404 />
923
+ * }
924
+ * }
925
+ * ```
926
+ *
927
+ * @param store Store instance.
928
+ * @returns Store value.
929
+ */
930
+ function useStore(store, options = {}) {
931
+ const snapshotRef = (0, import_react.useRef)(store.get());
932
+ const { keys, deps = [store, keys] } = options;
933
+ const subscribe = (0, import_react.useCallback)((onChange) => {
934
+ const emitChange = (value) => {
935
+ if (snapshotRef.current === value) return;
936
+ snapshotRef.current = value;
937
+ onChange();
938
+ };
939
+ emitChange(store.value);
940
+ if (keys?.length) return listenKeys(store, keys, emitChange);
941
+ return store.listen(emitChange);
942
+ }, deps);
943
+ const get = () => snapshotRef.current;
944
+ return (0, import_react.useSyncExternalStore)(subscribe, get, get);
945
+ }
946
+ function getAtomKey(str) {
947
+ return `use${capitalizeFirstLetter(str)}`;
948
+ }
949
+ function createAuthClient(options) {
950
+ const { pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, $store, atomListeners } = getClientConfig(options);
951
+ const resolvedHooks = {};
952
+ for (const [key, value] of Object.entries(pluginsAtoms)) resolvedHooks[getAtomKey(key)] = () => useStore(value);
953
+ return createDynamicPathProxy({
954
+ ...pluginsActions,
955
+ ...resolvedHooks,
956
+ $fetch,
957
+ $store
958
+ }, $fetch, pluginPathMethods, pluginsAtoms, atomListeners);
959
+ }
960
+ /** Browser auth client (same-origin /api/auth). */
961
+ var authClient = createAuthClient();
962
+ var { signIn, useSession } = authClient;
963
+ /**
964
+ * Shared Pievo mark geometry: eight durable steps form a cycle and the
965
+ * interactive-blue runner marks the next scheduled pass.
966
+ *
967
+ * Variants are props on one geometry (styles in app.css):
968
+ * - `plate` - dark tile behind the steps (favicon / app-icon contexts);
969
+ * without it the steps inherit currentColor (inline contexts).
970
+ * - `trail` - two fading steps behind the runner, so a static rendering
971
+ * still reads as motion (print / social cards).
972
+ * - `animated` - the runner advances around the cycle; reduced-motion users
973
+ * see the canonical static first frame.
974
+ */
975
+ var RING = [
976
+ [9, 9],
977
+ [37, 9],
978
+ [65, 9],
979
+ [65, 37],
980
+ [65, 65],
981
+ [37, 65],
982
+ [9, 65],
983
+ [9, 37]
984
+ ];
985
+ function RingLogo({ size = 24, plate = false, trail = false, animated = false }) {
986
+ const cellClass = (i) => {
987
+ const parts = ["ring-cell", `rc${i}`];
988
+ if (i === 0) parts.push("ring-runner");
989
+ else if (trail && i === 7) parts.push("ring-trail-1");
990
+ else if (trail && i === 6) parts.push("ring-trail-2");
991
+ return parts.join(" ");
992
+ };
993
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
994
+ width: size,
995
+ height: size,
996
+ viewBox: "0 0 96 96",
997
+ role: "img",
998
+ "aria-label": "Pievo",
999
+ className: [
1000
+ "ring-logo",
1001
+ plate && "ring-logo-plate",
1002
+ animated && "ring-logo-animated"
1003
+ ].filter(Boolean).join(" "),
1004
+ children: [plate && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
1005
+ width: "96",
1006
+ height: "96",
1007
+ rx: "15",
1008
+ fill: "#0b0b0b"
1009
+ }), RING.map(([x, y], i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
1010
+ x,
1011
+ y,
1012
+ width: 22,
1013
+ height: 22,
1014
+ rx: 6,
1015
+ className: cellClass(i)
1016
+ }, i))]
1017
+ });
1018
+ }
1019
+ /**
1020
+ * Pievo's primary product mark: one scheduled pass moving around a durable ring.
1021
+ * It reuses the same geometry as the favicon and README asset; animation is a
1022
+ * progressive enhancement and parks on the canonical first frame when reduced
1023
+ * motion is requested.
1024
+ */
1025
+ function PievoLogo({ size = 56 }) {
1026
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RingLogo, {
1027
+ size,
1028
+ plate: true,
1029
+ animated: true
1030
+ });
1031
+ }
1032
+ /** The project's source repository, shared by public UI surfaces. */
1033
+ var GITHUB_URL = "https://github.com/kky42/pievo";
1034
+ function GitHubIcon({ className }) {
1035
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
1036
+ viewBox: "0 0 24 24",
1037
+ fill: "currentColor",
1038
+ "aria-hidden": true,
1039
+ className,
1040
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.11.79-.25.79-.55 0-.27-.01-1.17-.02-2.12-3.2.7-3.88-1.36-3.88-1.36-.52-1.33-1.28-1.68-1.28-1.68-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.19 1.76 1.19 1.03 1.75 2.69 1.25 3.34.95.1-.74.4-1.25.72-1.54-2.55-.29-5.24-1.28-5.24-5.68 0-1.26.45-2.28 1.19-3.09-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.18 1.18a11.1 11.1 0 0 1 5.8 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.11 3.05.74.81 1.19 1.83 1.19 3.09 0 4.41-2.69 5.38-5.25 5.67.41.35.77 1.05.77 2.12 0 1.53-.01 2.76-.01 3.14 0 .3.2.66.8.55A11.51 11.51 0 0 0 23.5 12C23.5 5.65 18.35.5 12 .5z" })
1041
+ });
1042
+ }
1043
+ //#endregion
1044
+ export { startLoop as C, useSession as E, signIn as S, stopRun as T, loadOlderRuns as _, canViewTeam as a, pauseLoop as b, getArtifact as c, getConfig as d, getDefaultTeam as f, listMyTeams as g, listLoops as h, authClient as i, getArtifacts as l, getRunDiff as m, GitHubIcon as n, createSsrRpc as o, getLoopDetail as p, PievoLogo as r, deleteLoop as s, GITHUB_URL as t, getAuthState as u, mintClaim as v, stopLoop as w, runLoop as x, patchLoop as y };