@kky42/pievo-server 1.0.0

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 (197) hide show
  1. package/.output/nitro.json +17 -0
  2. package/.output/public/assets/CodeField-dOzyFQNH.js +34 -0
  3. package/.output/public/assets/LoopView-B4H9QibC.js +55 -0
  4. package/.output/public/assets/Modal-D33gNSgx.js +1 -0
  5. package/.output/public/assets/SignIn-SHuRRyOv.js +1 -0
  6. package/.output/public/assets/actionUi-ChGGALzg.js +1 -0
  7. package/.output/public/assets/app-DElSo_jy.css +2 -0
  8. package/.output/public/assets/artifactView-DFuubXLJ.js +66 -0
  9. package/.output/public/assets/index-DfpTWRSz.js +12 -0
  10. package/.output/public/assets/invite._token-DJtd-XE2.js +1 -0
  11. package/.output/public/assets/invite._token-T8oo4Qtw.js +1 -0
  12. package/.output/public/assets/jsx-runtime-BseJUIpC.js +1 -0
  13. package/.output/public/assets/lifecycleUi-DKkChdnU.js +1 -0
  14. package/.output/public/assets/loopApi-BM2nj71x.js +3 -0
  15. package/.output/public/assets/loops._loopId-B19Jw7jC.js +5 -0
  16. package/.output/public/assets/loops._loopId_.runs._runId-_CflHV38.js +3 -0
  17. package/.output/public/assets/notifyFns-DCubjpRy.js +1 -0
  18. package/.output/public/assets/preload-helper-CKUiEq3b.js +3 -0
  19. package/.output/public/assets/routes-B9tgli5f.js +1 -0
  20. package/.output/public/assets/routes-CTtlM_qt.js +1 -0
  21. package/.output/public/assets/t._teamId-Bm21mngW.js +1 -0
  22. package/.output/public/assets/t._teamId-gR7BVKkR.js +1 -0
  23. package/.output/public/assets/ui-Dp88qUWh.js +1 -0
  24. package/.output/public/assets/useRouter-DsjH8G0p.js +1 -0
  25. package/.output/public/favicon.svg +12 -0
  26. package/.output/public/fonts/GeistPixel-Square.woff2 +0 -0
  27. package/.output/server/_chunks/ssr-renderer.mjs +26 -0
  28. package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +419 -0
  29. package/.output/server/_libs/@aws-sdk/checksums+[...].mjs +10732 -0
  30. package/.output/server/_libs/@aws-sdk/client-s3+[...].mjs +9475 -0
  31. package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +137 -0
  32. package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +440 -0
  33. package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +62 -0
  34. package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +818 -0
  35. package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +59 -0
  36. package/.output/server/_libs/@base-ui/react+[...].mjs +11125 -0
  37. package/.output/server/_libs/@codemirror/autocomplete+[...].mjs +19713 -0
  38. package/.output/server/_libs/@codemirror/lang-css+[...].mjs +2636 -0
  39. package/.output/server/_libs/@codemirror/lang-html+[...].mjs +2247 -0
  40. package/.output/server/_libs/@codemirror/lang-json+[...].mjs +79 -0
  41. package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1736 -0
  42. package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +342 -0
  43. package/.output/server/_libs/@tanstack/react-router+[...].mjs +14300 -0
  44. package/.output/server/_libs/@uiw/codemirror-extensions-basic-setup+[...].mjs +76 -0
  45. package/.output/server/_libs/atomic-sleep.mjs +27 -0
  46. package/.output/server/_libs/aws-crypto__crc32c.mjs +314 -0
  47. package/.output/server/_libs/aws-sdk__nested-clients.mjs +2671 -0
  48. package/.output/server/_libs/babel__runtime.mjs +30 -0
  49. package/.output/server/_libs/clsx.mjs +16 -0
  50. package/.output/server/_libs/codemirror__commands.mjs +1725 -0
  51. package/.output/server/_libs/codemirror__lint.mjs +565 -0
  52. package/.output/server/_libs/codemirror__search.mjs +1138 -0
  53. package/.output/server/_libs/codemirror__theme-one-dark.mjs +161 -0
  54. package/.output/server/_libs/colorette.mjs +129 -0
  55. package/.output/server/_libs/croner.mjs +735 -0
  56. package/.output/server/_libs/d3-array.mjs +231 -0
  57. package/.output/server/_libs/d3-color.mjs +330 -0
  58. package/.output/server/_libs/d3-format.mjs +252 -0
  59. package/.output/server/_libs/d3-interpolate.mjs +163 -0
  60. package/.output/server/_libs/d3-path.mjs +77 -0
  61. package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
  62. package/.output/server/_libs/d3-shape.mjs +689 -0
  63. package/.output/server/_libs/dateformat.mjs +341 -0
  64. package/.output/server/_libs/decimal.js-light.mjs +884 -0
  65. package/.output/server/_libs/diff.mjs +732 -0
  66. package/.output/server/_libs/dom-serializer+[...].mjs +708 -0
  67. package/.output/server/_libs/domhandler.mjs +461 -0
  68. package/.output/server/_libs/dompurify.mjs +2111 -0
  69. package/.output/server/_libs/domutils.mjs +868 -0
  70. package/.output/server/_libs/drizzle-orm+postgres.mjs +7689 -0
  71. package/.output/server/_libs/electric-sql__pglite.mjs +14674 -0
  72. package/.output/server/_libs/end-of-stream+once+wrappy.mjs +145 -0
  73. package/.output/server/_libs/es-toolkit.mjs +1737 -0
  74. package/.output/server/_libs/eventemitter3.mjs +236 -0
  75. package/.output/server/_libs/fast-copy.mjs +285 -0
  76. package/.output/server/_libs/fast-safe-stringify.mjs +172 -0
  77. package/.output/server/_libs/h3+rou3+srvx.mjs +1201 -0
  78. package/.output/server/_libs/html-dom-parser+htmlparser2.mjs +1560 -0
  79. package/.output/server/_libs/html-react-parser+[...].mjs +1360 -0
  80. package/.output/server/_libs/initdb.wasm +0 -0
  81. package/.output/server/_libs/marked.mjs +1548 -0
  82. package/.output/server/_libs/on-exit-leak-free.mjs +80 -0
  83. package/.output/server/_libs/pglite.data +37667 -8
  84. package/.output/server/_libs/pglite.wasm +0 -0
  85. package/.output/server/_libs/pino+[...].mjs +3196 -0
  86. package/.output/server/_libs/pino-abstract-transport+split2.mjs +194 -0
  87. package/.output/server/_libs/pino-pretty+[...].mjs +1623 -0
  88. package/.output/server/_libs/pinojs__redact.mjs +280 -0
  89. package/.output/server/_libs/react-redux+[...].mjs +205 -0
  90. package/.output/server/_libs/recharts+victory-vendor.mjs +15875 -0
  91. package/.output/server/_libs/tanstack__history.mjs +342 -0
  92. package/.output/server/_libs/ufo.mjs +64 -0
  93. package/.output/server/_libs/uiw__codemirror-themes.mjs +32 -0
  94. package/.output/server/_libs/uiw__react-codemirror.mjs +354 -0
  95. package/.output/server/_runtime.mjs +37 -0
  96. package/.output/server/_ssr/CodeField-tm4rr6G3.mjs +143 -0
  97. package/.output/server/_ssr/DashboardView-CC7htv28.mjs +2795 -0
  98. package/.output/server/_ssr/LoopPlaybook-BXH8mhiX.mjs +2105 -0
  99. package/.output/server/_ssr/LoopView-DCugEbHx.mjs +1106 -0
  100. package/.output/server/_ssr/Modal-DpKZHLZK.mjs +49 -0
  101. package/.output/server/_ssr/SignIn-dTndU6Hw.mjs +67 -0
  102. package/.output/server/_ssr/actionUi-CZbEixbf.mjs +119 -0
  103. package/.output/server/_ssr/adapters-BS8XosjF.mjs +130 -0
  104. package/.output/server/_ssr/artifactFiles-Cagtj7J0.mjs +61 -0
  105. package/.output/server/_ssr/artifactKind-BW0isV8L.mjs +37 -0
  106. package/.output/server/_ssr/artifactView-DS4O22wl.mjs +304 -0
  107. package/.output/server/_ssr/artifacts-DngKyW2u.mjs +2 -0
  108. package/.output/server/_ssr/auth-DY1DuYZd.mjs +38429 -0
  109. package/.output/server/_ssr/boot-BbtG0ImW.mjs +9010 -0
  110. package/.output/server/_ssr/boot-CMHTxQpJ.mjs +2 -0
  111. package/.output/server/_ssr/bun-sqlite-dialect-BW9W1_Ps-CU1Spd6z.mjs +162 -0
  112. package/.output/server/_ssr/core-RrmWoKne.mjs +5 -0
  113. package/.output/server/_ssr/createServerRpc-BD8Xn_0_.mjs +12 -0
  114. package/.output/server/_ssr/d1-sqlite-dialect-BLC8LXE6-DfG7tB8s.mjs +112 -0
  115. package/.output/server/_ssr/db-DWAuZq1o.mjs +2 -0
  116. package/.output/server/_ssr/dist-BIxFFVZg.mjs +342 -0
  117. package/.output/server/_ssr/empty-plugin-adapters-DKUlnwwl.mjs +5 -0
  118. package/.output/server/_ssr/factory-Blq0DYfT.mjs +6903 -0
  119. package/.output/server/_ssr/invite._token-BRCo9LGB.mjs +36 -0
  120. package/.output/server/_ssr/invite._token-DJxGLILJ.mjs +28 -0
  121. package/.output/server/_ssr/invite._token-NewFt27g.mjs +92 -0
  122. package/.output/server/_ssr/kysely-adapter-D3XTe64J.mjs +2 -0
  123. package/.output/server/_ssr/kysely-migration-tables-JkVUjPF_-bPAX9LR_.mjs +19 -0
  124. package/.output/server/_ssr/lifecycleUi-C9lg1r3r.mjs +38 -0
  125. package/.output/server/_ssr/logger-Dw82jNjH.mjs +2 -0
  126. package/.output/server/_ssr/loopApi-BtfkZQYK.mjs +532 -0
  127. package/.output/server/_ssr/loopApi-Cxe8WyOB.mjs +105 -0
  128. package/.output/server/_ssr/loops._loopId-7NQJPB9W.mjs +30 -0
  129. package/.output/server/_ssr/loops._loopId-DhnArGdL.mjs +1635 -0
  130. package/.output/server/_ssr/loops._loopId_.runs._runId-Bvuo2nki.mjs +29 -0
  131. package/.output/server/_ssr/loops._loopId_.runs._runId-Dip5Xk-q.mjs +674 -0
  132. package/.output/server/_ssr/machineFns-Dvr5ICUy.mjs +266 -0
  133. package/.output/server/_ssr/node-sqlite-dialect-DhyOpJTX.mjs +162 -0
  134. package/.output/server/_ssr/notifyFns-BcMRY5kP.mjs +118 -0
  135. package/.output/server/_ssr/notifyFns-Q458pZmE.mjs +580 -0
  136. package/.output/server/_ssr/router-J8KZ30xw.mjs +678 -0
  137. package/.output/server/_ssr/routes-Bcs4T1ox.mjs +28 -0
  138. package/.output/server/_ssr/routes-BoGrcf-b.mjs +43 -0
  139. package/.output/server/_ssr/routes-D4am3Zff.mjs +28 -0
  140. package/.output/server/_ssr/runDiff-CpEFqo7G.mjs +113 -0
  141. package/.output/server/_ssr/ssr.mjs +5837 -0
  142. package/.output/server/_ssr/start-4ifArtKx.mjs +4 -0
  143. package/.output/server/_ssr/store-b3JcQ08F.mjs +2 -0
  144. package/.output/server/_ssr/t._teamId-CeUhzgzT.mjs +32 -0
  145. package/.output/server/_ssr/t._teamId-DR-hQK7o.mjs +47 -0
  146. package/.output/server/_ssr/t._teamId-Dy_McbRt.mjs +31 -0
  147. package/.output/server/_ssr/teamCookie-B7hLOIie.mjs +10 -0
  148. package/.output/server/_ssr/teamFns-BIDnsg2A.mjs +473 -0
  149. package/.output/server/_ssr/teamFns-DA4ovI5g.mjs +33 -0
  150. package/.output/server/_ssr/tokens-ytd60FUt.mjs +2 -0
  151. package/.output/server/_ssr/ui-Dej2qjuS.mjs +267 -0
  152. package/.output/server/_tanstack-start-manifest_v-CVS6c7re.mjs +95 -0
  153. package/.output/server/drizzle/0000_round_marauders.sql +193 -0
  154. package/.output/server/drizzle/0001_naive_silver_fox.sql +25 -0
  155. package/.output/server/drizzle/0002_funny_sage.sql +12 -0
  156. package/.output/server/drizzle/0003_optimal_slapstick.sql +102 -0
  157. package/.output/server/drizzle/0004_remove_grok_agent.sql +5 -0
  158. package/.output/server/drizzle/0005_heavy_gauntlet.sql +8 -0
  159. package/.output/server/drizzle/0006_tranquil_sharon_carter.sql +1 -0
  160. package/.output/server/drizzle/0007_faulty_starbolt.sql +30 -0
  161. package/.output/server/drizzle/0008_durable_lifecycle_evidence.sql +15 -0
  162. package/.output/server/drizzle/meta/0000_snapshot.json +1333 -0
  163. package/.output/server/drizzle/meta/0001_snapshot.json +1498 -0
  164. package/.output/server/drizzle/meta/0002_snapshot.json +1576 -0
  165. package/.output/server/drizzle/meta/0003_snapshot.json +1666 -0
  166. package/.output/server/drizzle/meta/0005_snapshot.json +1666 -0
  167. package/.output/server/drizzle/meta/0006_snapshot.json +1672 -0
  168. package/.output/server/drizzle/meta/0007_snapshot.json +1787 -0
  169. package/.output/server/drizzle/meta/_journal.json +69 -0
  170. package/.output/server/index.mjs +464 -0
  171. package/.output/server/node_modules/tslib/modules/index.js +70 -0
  172. package/.output/server/node_modules/tslib/modules/package.json +3 -0
  173. package/.output/server/node_modules/tslib/package.json +47 -0
  174. package/.output/server/node_modules/tslib/tslib.js +484 -0
  175. package/.output/server/package.json +9 -0
  176. package/LICENSE +21 -0
  177. package/drizzle/0000_round_marauders.sql +193 -0
  178. package/drizzle/0001_naive_silver_fox.sql +25 -0
  179. package/drizzle/0002_funny_sage.sql +12 -0
  180. package/drizzle/0003_optimal_slapstick.sql +102 -0
  181. package/drizzle/0004_remove_grok_agent.sql +5 -0
  182. package/drizzle/0005_heavy_gauntlet.sql +8 -0
  183. package/drizzle/0006_tranquil_sharon_carter.sql +1 -0
  184. package/drizzle/0007_faulty_starbolt.sql +30 -0
  185. package/drizzle/0008_durable_lifecycle_evidence.sql +15 -0
  186. package/drizzle/meta/0000_snapshot.json +1333 -0
  187. package/drizzle/meta/0001_snapshot.json +1498 -0
  188. package/drizzle/meta/0002_snapshot.json +1576 -0
  189. package/drizzle/meta/0003_snapshot.json +1666 -0
  190. package/drizzle/meta/0005_snapshot.json +1666 -0
  191. package/drizzle/meta/0006_snapshot.json +1672 -0
  192. package/drizzle/meta/0007_snapshot.json +1787 -0
  193. package/drizzle/meta/_journal.json +69 -0
  194. package/package.json +84 -0
  195. package/scripts/pievo-server.mjs +390 -0
  196. package/scripts/prestart.mjs +66 -0
  197. package/scripts/server-cli-lib.mjs +451 -0
@@ -0,0 +1,580 @@
1
+ import { o as __toESM } from "../_runtime.mjs";
2
+ import { C as require_jsx_runtime, S as require_react, d as TooltipPortal, f as TooltipTrigger, l as TooltipPopup, p as TooltipRoot, u as TooltipPositioner } from "../_libs/@base-ui/react+[...].mjs";
3
+ import { jt as machinePresence } from "./boot-BbtG0ImW.mjs";
4
+ import { C as labelCls, D as runPulseAnim, E as rel, M as until, N as useHydrated, S as isCompleted, _ as fmt, b as inputCls, c as btnDanger, g as dur, h as dotLabel, l as btnPrimary, m as dotColor, o as btn, t as ErrorBanner } from "./ui-Dej2qjuS.mjs";
5
+ import { n as createServerFn } from "./ssr.mjs";
6
+ import { r as createSsrRpc, u as getConfig } from "./loopApi-Cxe8WyOB.mjs";
7
+ import { n as ModalHead, r as ModalSection, t as Modal } from "./Modal-DpKZHLZK.mjs";
8
+ import { n as daemonStopSupport } from "./lifecycleUi-C9lg1r3r.mjs";
9
+ //#region node_modules/.nitro/vite/services/ssr/assets/notifyFns-Q458pZmE.js
10
+ var import_react = /* @__PURE__ */ __toESM(require_react());
11
+ var import_jsx_runtime = require_jsx_runtime();
12
+ /**
13
+ * Machine management server functions. Connect flow (two acts):
14
+ * 1. createMachine() → mint a token, create a PENDING (unnamed) row, return
15
+ * {id, token}. The UI shows the connect command + "waiting…".
16
+ * 2. the daemon connects → poll records online + hostname/platform/arch. The
17
+ * UI polls machineStatus(id); once connected it shows the name field
18
+ * (prefilled with the hostname). finalizeMachine({id,name}) names it →
19
+ * it appears in the list. cancelMachine(id) drops a pending row.
20
+ *
21
+ * Scoping: when the auth gate is on, every fn requires a signed-in user, and a
22
+ * machine is visible/actionable only when the requester owns it, its owner is a
23
+ * member of the active team, or the scope is the admin "All teams" view (the
24
+ * same rule listMachines filters by). The PLAINTEXT device token is serialized
25
+ * ONLY to the machine's owner — it fully impersonates the machine (poll /
26
+ * create-loop / log), so a teammate who can see the row must never exfiltrate
27
+ * it. Open mode (gate off) keeps the shared workspace: everyone sees/manages
28
+ * all machines, tokens included. No workdir jail (fully open) for now.
29
+ */
30
+ /** Ids of the machines membership-visible in the scope's active team (the same
31
+ * set listMachines serves). Empty when the scope needs no team check (open
32
+ * mode or signed-out — machineInScope settles those before ever invoking its
33
+ * team-set thunk). */
34
+ /**
35
+ * Resolve a machine and authorize it against the request scope (the machine-fn
36
+ * twin of loopApi's `ownedLoop`). `machine` is undefined when it's missing OR
37
+ * out of scope — callers treat both as "not found" so existence never leaks.
38
+ * The scope rides along so callers don't re-run requestScope (a second session
39
+ * decrypt); the team-set thunk keeps the owner fast path query-free.
40
+ */
41
+ /** Named machines only (pending/unnamed rows are mid-connect). Scoped to the
42
+ * given/active team when the gate is on; the full shared list in open mode. An
43
+ * explicit `teamId` (the `/t/<id>` route) scopes this request independent of the
44
+ * cookie, so a tab on /t/A and one on /t/B list different machines at once. */
45
+ var listMachines = createServerFn({ method: "GET" }).validator((teamId) => teamId).handler(createSsrRpc("aa46310016bb8a58b273a648ffd498c87f1f450d12827e30110a3b83ba6a27d9"));
46
+ /** Act 1 — create a pending machine + token, owned by the signed-in user's team.
47
+ * An explicit `teamId` (the `/t/<id>` route) binds the machine to that tab's team
48
+ * independent of the last-used cookie, mirroring `mintClaim`/`listMachines`. */
49
+ var createMachine = createServerFn({ method: "POST" }).validator((teamId) => teamId).handler(createSsrRpc("ed679b4e1e05e903a5d4ba4a70d9b9d883991ab22ed59b4d2d69078941818415"));
50
+ /** Poll while the connect dialog is open. Scoped like listMachines; the token
51
+ * rides along only for the machine's owner (the connect dialog's minter). */
52
+ var machineStatus = createServerFn({ method: "GET" }).validator((id) => id).handler(createSsrRpc("169566e7637a22599b4eb32ee3775574e99677406922bbef7482a102036c33dd"));
53
+ /** Act 2 — name the connected machine (it then appears in the list). */
54
+ var finalizeMachine = createServerFn({ method: "POST" }).validator((d) => d).handler(createSsrRpc("27d7eba0b6a2257949392fdd56057275a5c5366484ae01faf3b5897a225ecd83"));
55
+ /**
56
+ * Cancel a pending connect (or delete an existing machine). A machine that still
57
+ * owns loops can't be deleted — the loops execute on it, so they must be removed
58
+ * first (we block rather than cascade, to never silently nuke a loop's history).
59
+ * Pending/unnamed machines have no loops, so the connect-cancel path passes through.
60
+ */
61
+ var deleteMachine = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("a6384dc7154d9930422d29396f5de64b3ac69c62ad3824bc4a22d745fc07b293"));
62
+ /** Merge two chronological (oldest-first) run lists, dedup by id (the first
63
+ * occurrence wins, so pass the fresher list first), re-sorted by ts ascending.
64
+ * Shared by the dashboard cards and the loop detail page, which both seed the
65
+ * timeline with the newest page and grow it leftward with lazily-paged older runs. */
66
+ function mergeRuns(primary, secondary) {
67
+ const seen = /* @__PURE__ */ new Set();
68
+ const out = [];
69
+ for (const r of [...primary, ...secondary]) {
70
+ if (seen.has(r.id)) continue;
71
+ seen.add(r.id);
72
+ out.push(r);
73
+ }
74
+ out.sort((a, b) => a.ts < b.ts ? -1 : a.ts > b.ts ? 1 : 0);
75
+ return out;
76
+ }
77
+ var PAGE = 16;
78
+ var RAD = "rounded-[4px]";
79
+ var SEG = `h-5 w-[18px] shrink-0 ${RAD}`;
80
+ function RunSeg({ run, onClick }) {
81
+ const body = run.error || run.message || "";
82
+ const meta = run.durationMs ? ` · ${dur(run.durationMs)}` : "";
83
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TooltipRoot, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipTrigger, { render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
84
+ type: "button",
85
+ onClick: (e) => {
86
+ e.stopPropagation();
87
+ onClick();
88
+ },
89
+ "aria-label": dotLabel(run),
90
+ className: `${SEG} cursor-pointer transition-opacity hover:opacity-70`,
91
+ style: {
92
+ background: dotColor(run),
93
+ ...run.running ? runPulseAnim : {}
94
+ }
95
+ }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipPositioner, {
96
+ sideOffset: 8,
97
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TooltipPopup, {
98
+ className: "glass-strong pointer-events-none max-w-[340px] rounded-control px-3.5 py-2.5 text-meta leading-snug text-primary",
99
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
100
+ className: "flex items-center gap-1.5 font-medium",
101
+ children: [
102
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
103
+ className: "size-2 shrink-0 rounded-[2px]",
104
+ style: { background: dotColor(run) }
105
+ }),
106
+ dotLabel(run),
107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
108
+ className: "ml-auto whitespace-nowrap pl-3 font-mono text-caption font-normal text-secondary",
109
+ children: [fmt(run.ts), meta]
110
+ })
111
+ ]
112
+ }), body && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
113
+ className: `mt-1.5 max-h-[150px] overflow-hidden whitespace-pre-wrap ${run.error ? "text-accent" : "text-secondary"}`,
114
+ children: body
115
+ })]
116
+ })
117
+ }) })] });
118
+ }
119
+ /** An "N more" pager rendered as the SAME cube block as a run — identical 18px
120
+ * width (bordered, not filled, so it reads as an affordance; the "+" is dropped
121
+ * to keep the count inside the run-block width). Renders nothing when there's no
122
+ * overflow — no left-edge whitespace reserved. */
123
+ function Pager({ count, onClick, loading }) {
124
+ if (!count) return null;
125
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
126
+ type: "button",
127
+ onClick: (e) => {
128
+ e.stopPropagation();
129
+ onClick();
130
+ },
131
+ className: `flex h-5 w-[18px] shrink-0 items-center justify-center overflow-hidden border border-wire px-0 font-mono text-[9px] leading-none text-disabled transition-colors hover:border-display hover:text-primary ${RAD} ${loading ? "animate-pulse" : "cursor-pointer"}`,
132
+ title: `${count} more - click to reveal`,
133
+ children: loading ? "…" : count
134
+ });
135
+ }
136
+ function Timeline({ job, runs, total, onLoadMore, onPickRun }) {
137
+ const all = runs;
138
+ const en = job.enabled;
139
+ const done = isCompleted(job);
140
+ const L = all.length;
141
+ const unloaded = Math.max(0, total - L);
142
+ const hydrated = useHydrated();
143
+ const [winStart, setWinStart] = (0, import_react.useState)(-1);
144
+ const [loading, setLoading] = (0, import_react.useState)(false);
145
+ const maxStart = Math.max(0, L - 16);
146
+ const start = winStart < 0 ? maxStart : Math.min(winStart, maxStart);
147
+ const end = Math.min(start + 16, L);
148
+ const visible = all.slice(start, end);
149
+ const olderHidden = unloaded + start;
150
+ const newerHidden = L - end;
151
+ const atLatest = newerHidden === 0;
152
+ const pageBack = async () => {
153
+ const target = start - PAGE;
154
+ if (target < 0 && unloaded > 0 && !loading) {
155
+ setLoading(true);
156
+ const added = await onLoadMore().catch(() => 0);
157
+ setLoading(false);
158
+ setWinStart(Math.max(0, start + added - PAGE));
159
+ return;
160
+ }
161
+ setWinStart(Math.max(0, target));
162
+ };
163
+ const pageFwd = () => {
164
+ const next = start + PAGE;
165
+ setWinStart(next >= maxStart ? -1 : next);
166
+ };
167
+ const running = !!(job.running || job.queued) && atLatest;
168
+ const showNext = atLatest && en && !done && !!job.nextRun && !running;
169
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
170
+ className: "flex min-w-0 items-center gap-[3px] overflow-x-auto",
171
+ children: [
172
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pager, {
173
+ count: olderHidden,
174
+ onClick: pageBack,
175
+ loading
176
+ }),
177
+ visible.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunSeg, {
178
+ run: r,
179
+ onClick: () => onPickRun(r)
180
+ }, r.id)),
181
+ showNext ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
182
+ className: "ml-1 flex items-center gap-2",
183
+ children: [
184
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "w-12 border-t border-dashed border-wire" }),
185
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
186
+ className: "size-[11px] shrink-0 rounded-full border border-wire",
187
+ title: hydrated ? `Next scheduled run · ${fmt(job.nextRun)}` : void 0
188
+ }),
189
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
190
+ className: "text-caption text-disabled",
191
+ children: hydrated ? until(job.nextRun) : ""
192
+ })
193
+ ]
194
+ }) : !atLatest && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pager, {
195
+ count: newerHidden,
196
+ onClick: pageFwd
197
+ })
198
+ ]
199
+ });
200
+ }
201
+ /**
202
+ * Tiny semver comparison — just enough to decide "is the daemon older than the
203
+ * latest published version?" for the web's update hint. No dependency; we only
204
+ * need numeric-core ordering (major.minor.patch), and a pre-release is treated
205
+ * as older than its release (a "0.9.0-rc.1" daemon is still behind "0.9.0").
206
+ */
207
+ /** Parse the leading numeric core `x.y.z` of a version, ignoring any pre-release
208
+ * / build suffix. Returns null when it isn't a recognizable version. */
209
+ function core(v) {
210
+ const m = /^\s*v?(\d+)\.(\d+)\.(\d+)/.exec(v);
211
+ if (!m) return null;
212
+ return [
213
+ Number(m[1]),
214
+ Number(m[2]),
215
+ Number(m[3])
216
+ ];
217
+ }
218
+ /** Does `v` carry a pre-release suffix (e.g. "1.2.3-rc.1")? */
219
+ function isPre(v) {
220
+ return /^\s*v?\d+\.\d+\.\d+-/.test(v);
221
+ }
222
+ /**
223
+ * `true` when `current` is strictly older than `latest`. Returns `false` on any
224
+ * unparseable/equal/newer input — the hint is opt-in, so we only ever show it
225
+ * when we can be confident the daemon is genuinely behind.
226
+ */
227
+ function isOutdated(current, latest) {
228
+ if (!current || !latest) return false;
229
+ const a = core(current);
230
+ const b = core(latest);
231
+ if (!a || !b) return false;
232
+ for (let i = 0; i < 3; i++) {
233
+ const ai = a[i];
234
+ const bi = b[i];
235
+ if (ai < bi) return true;
236
+ if (ai > bi) return false;
237
+ }
238
+ return isPre(current) && !isPre(latest);
239
+ }
240
+ /** User-facing daemon commands. Public UX installs globally; PIEVO_CLI dev
241
+ * overrides are invoked verbatim and never trigger a global npm install. */
242
+ function daemonConnectCommand(origin, token, cli, customCli) {
243
+ const start = `${cli} daemon start --server-url ${origin} --connect-key ${token}`;
244
+ return customCli ? start : `npm install -g @kky42/pievo@latest && ${start}`;
245
+ }
246
+ function daemonUpgradeCommand(cli, customCli) {
247
+ const restart = `${cli} daemon restart`;
248
+ return customCli ? restart : `npm install -g @kky42/pievo@latest && ${restart}`;
249
+ }
250
+ function connectCmd(token, cli, customCli) {
251
+ return daemonConnectCommand(typeof window !== "undefined" ? window.location.origin : "http://127.0.0.1:3000", token, cli, customCli);
252
+ }
253
+ function CopyButton({ text }) {
254
+ const [done, setDone] = (0, import_react.useState)(false);
255
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
256
+ className: btn,
257
+ onClick: () => {
258
+ navigator.clipboard?.writeText(text);
259
+ setDone(true);
260
+ setTimeout(() => setDone(false), 1400);
261
+ },
262
+ children: done ? "Copied ✓" : "Copy"
263
+ });
264
+ }
265
+ function MachinesModal({ open, onClose, teamId }) {
266
+ const [machines, setMachines] = (0, import_react.useState)([]);
267
+ const [pending, setPending] = (0, import_react.useState)(null);
268
+ const [status, setStatus] = (0, import_react.useState)(null);
269
+ const [name, setName] = (0, import_react.useState)("");
270
+ const [busy, setBusy] = (0, import_react.useState)(false);
271
+ const [delErr, setDelErr] = (0, import_react.useState)(null);
272
+ const [cliConfig, setCliConfig] = (0, import_react.useState)(null);
273
+ const [configErr, setConfigErr] = (0, import_react.useState)(false);
274
+ (0, import_react.useEffect)(() => {
275
+ if (!open) {
276
+ setDelErr(null);
277
+ return;
278
+ }
279
+ let active = true;
280
+ setCliConfig(null);
281
+ setConfigErr(false);
282
+ getConfig().then((config) => {
283
+ if (active) setCliConfig(config);
284
+ }).catch(() => {
285
+ if (active) setConfigErr(true);
286
+ });
287
+ return () => {
288
+ active = false;
289
+ };
290
+ }, [open]);
291
+ const load = (0, import_react.useCallback)(async () => {
292
+ try {
293
+ setMachines(await listMachines({ data: teamId }));
294
+ } catch {}
295
+ }, [teamId]);
296
+ const openRef = (0, import_react.useRef)(open);
297
+ openRef.current = open;
298
+ (0, import_react.useEffect)(() => {
299
+ if (!open || pending) return;
300
+ load();
301
+ const t = setInterval(() => openRef.current && void load(), 3e3);
302
+ return () => clearInterval(t);
303
+ }, [
304
+ open,
305
+ pending,
306
+ load
307
+ ]);
308
+ (0, import_react.useEffect)(() => {
309
+ if (!pending) return;
310
+ let active = true;
311
+ const tick = async () => {
312
+ const s = await machineStatus({ data: pending.id }).catch(() => void 0);
313
+ if (!active || s === void 0) return;
314
+ setStatus(s);
315
+ if (s?.online && s.hostname) setName((n) => n || s.hostname || "");
316
+ };
317
+ tick();
318
+ const t = setInterval(tick, 2e3);
319
+ return () => {
320
+ active = false;
321
+ clearInterval(t);
322
+ };
323
+ }, [pending]);
324
+ async function startConnect() {
325
+ setBusy(true);
326
+ setDelErr(null);
327
+ try {
328
+ const r = await createMachine({ data: teamId });
329
+ if ("error" in r) {
330
+ setDelErr(r.error);
331
+ return;
332
+ }
333
+ setStatus(null);
334
+ setName("");
335
+ setPending(r);
336
+ } finally {
337
+ setBusy(false);
338
+ }
339
+ }
340
+ async function cancel() {
341
+ if (pending) await deleteMachine({ data: pending.id });
342
+ setPending(null);
343
+ setStatus(null);
344
+ await load();
345
+ }
346
+ async function done() {
347
+ if (pending && name.trim()) await finalizeMachine({ data: {
348
+ id: pending.id,
349
+ name: name.trim()
350
+ } });
351
+ setPending(null);
352
+ setStatus(null);
353
+ await load();
354
+ }
355
+ async function remove(id) {
356
+ setDelErr(null);
357
+ const r = await deleteMachine({ data: id });
358
+ if (!r.ok) {
359
+ setDelErr(r.error ?? "Could not delete this machine.");
360
+ await load();
361
+ return;
362
+ }
363
+ await load();
364
+ }
365
+ const connected = !!status?.online;
366
+ if (pending) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Modal, {
367
+ open,
368
+ onClose: cancel,
369
+ children: [
370
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModalHead, { title: connected ? "Computer connected" : "Connect computer" }),
371
+ !connected ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
372
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
373
+ className: "mt-5 text-body font-medium text-display",
374
+ children: "Run this command on your computer to connect:"
375
+ }),
376
+ cliConfig ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
377
+ className: "mt-2 flex items-start gap-2",
378
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
379
+ className: "flex-1 overflow-x-auto whitespace-pre-wrap break-all rounded-control bg-display p-4 font-mono text-label leading-relaxed text-paper",
380
+ children: connectCmd(pending.token, cliConfig.pievoCli, cliConfig.customCli)
381
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, { text: connectCmd(pending.token, cliConfig.pievoCli, cliConfig.customCli) })]
382
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
383
+ className: "mt-2 text-body text-secondary",
384
+ children: configErr ? "Could not load the connection command. Close and try again." : "Loading connection command…"
385
+ }),
386
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
387
+ className: "mt-4 flex items-center gap-2.5 rounded-control border border-hairline bg-warn-soft px-4 py-3",
388
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "inline-block h-2.5 w-2.5 animate-pulse rounded-full bg-rubik-orange" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
389
+ className: "text-[14px] font-medium text-warn",
390
+ children: "Waiting for computer to connect…"
391
+ })]
392
+ })
393
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
394
+ className: "mt-5 flex items-center gap-3 rounded-control border border-hairline bg-success-soft px-4 py-3",
395
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
396
+ className: "text-xl text-success",
397
+ children: "✓"
398
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
399
+ className: "text-[15px] font-medium text-display",
400
+ children: "Computer connected successfully!"
401
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
402
+ className: "text-label text-secondary",
403
+ children: [status?.hostname ?? "unknown", status?.platform ? ` - ${status.platform} ${status.arch ?? ""}` : ""]
404
+ })] })]
405
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
406
+ className: "mt-5",
407
+ children: [
408
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", {
409
+ className: labelCls,
410
+ children: "Computer name"
411
+ }),
412
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", {
413
+ className: inputCls,
414
+ value: name,
415
+ onChange: (e) => setName(e.target.value),
416
+ placeholder: status?.hostname ?? "My computer"
417
+ }),
418
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
419
+ className: "mt-1 text-label text-secondary",
420
+ children: "A friendly name for this computer."
421
+ })
422
+ ]
423
+ })] }),
424
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
425
+ className: "mt-6 flex justify-end gap-2",
426
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
427
+ className: btn,
428
+ onClick: () => void cancel(),
429
+ children: "Cancel"
430
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
431
+ className: btnPrimary,
432
+ disabled: !connected || !name.trim(),
433
+ onClick: () => void done(),
434
+ children: "Done"
435
+ })]
436
+ })
437
+ ]
438
+ });
439
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Modal, {
440
+ open,
441
+ onClose,
442
+ children: [
443
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModalHead, {
444
+ title: "Machines",
445
+ sub: "Each machine runs a pievo daemon that executes your loops via your local coding agent."
446
+ }),
447
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModalSection, { children: "Connected machines" }),
448
+ delErr && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorBanner, {
449
+ message: delErr,
450
+ onDismiss: () => setDelErr(null)
451
+ }),
452
+ machines.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
453
+ className: "py-3 text-body text-secondary",
454
+ children: "No machines yet."
455
+ }),
456
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
457
+ className: "flex flex-col gap-2",
458
+ children: machines.map((m) => {
459
+ const presence = machinePresence(m.online, m.lastSeen);
460
+ const dotCls = presence === "online" ? "bg-rubik-green" : presence === "asleep" ? "bg-rubik-yellow" : "bg-disabled";
461
+ const stateText = presence === "online" ? "online" : presence === "asleep" ? `asleep${m.lastSeen ? ` · seen ${rel(m.lastSeen)}` : ""}` : m.lastSeen ? `offline · seen ${rel(m.lastSeen)}` : "offline";
462
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", {
463
+ className: "flex flex-col gap-2 rounded-control border border-hairline bg-surface px-4 py-3",
464
+ children: [
465
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
466
+ className: "flex items-center justify-between gap-3",
467
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
468
+ className: "flex items-center gap-2.5",
469
+ children: [
470
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
471
+ className: `inline-block h-2 w-2 rounded-full ${dotCls}`,
472
+ title: presence
473
+ }),
474
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
475
+ className: "text-[15px] font-medium text-display",
476
+ children: m.name
477
+ }),
478
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
479
+ className: "text-label text-secondary",
480
+ children: [
481
+ stateText,
482
+ m.platform ? ` · ${m.platform} ${m.arch ?? ""}` : "",
483
+ m.loopCount > 0 ? ` · ${m.loopCount} loop${m.loopCount === 1 ? "" : "s"}` : ""
484
+ ]
485
+ })
486
+ ]
487
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
488
+ className: btnDanger,
489
+ disabled: m.loopCount > 0,
490
+ title: m.loopCount > 0 ? "Delete its loops first" : void 0,
491
+ onClick: () => void remove(m.id),
492
+ children: "Delete"
493
+ })]
494
+ }),
495
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
496
+ className: "text-label text-secondary",
497
+ children: daemonStopSupport(m.daemonProtocol).label
498
+ }),
499
+ m.daemonProtocol !== 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
500
+ className: "text-label text-accent",
501
+ children: "Daemon upgrade required to stop a running process"
502
+ }),
503
+ !m.online && !m.token && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
504
+ className: "text-label text-secondary",
505
+ children: "Reconnect command available from the machine owner's account."
506
+ }),
507
+ !m.online && m.token && !cliConfig && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
508
+ className: "text-label text-secondary",
509
+ children: configErr ? "Could not load the reconnect command. Close and try again." : "Loading reconnect command…"
510
+ }),
511
+ !m.online && m.token && cliConfig && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", {
512
+ className: "cursor-pointer select-none text-label font-medium text-secondary marker:content-[''] hover:text-display",
513
+ children: "Reconnect command"
514
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
515
+ className: "mt-2 flex items-start gap-2",
516
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
517
+ className: "flex-1 overflow-x-auto whitespace-pre-wrap break-all rounded-control bg-display p-3 font-mono text-caption leading-relaxed text-paper",
518
+ children: connectCmd(m.token, cliConfig.pievoCli, cliConfig.customCli)
519
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, { text: connectCmd(m.token, cliConfig.pievoCli, cliConfig.customCli) })]
520
+ })] }),
521
+ isOutdated(m.daemonVersion, m.latestDaemonVersion) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
522
+ className: "flex flex-col gap-1.5",
523
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
524
+ className: "text-label text-secondary",
525
+ children: [
526
+ "daemon v",
527
+ m.daemonVersion,
528
+ " · upgrade available (v",
529
+ m.latestDaemonVersion,
530
+ ")"
531
+ ]
532
+ }), cliConfig ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
533
+ className: "flex items-start gap-2",
534
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
535
+ className: "flex-1 overflow-x-auto whitespace-pre-wrap break-all rounded-control bg-display p-3 font-mono text-caption leading-relaxed text-paper",
536
+ children: daemonUpgradeCommand(cliConfig.pievoCli, cliConfig.customCli)
537
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, { text: daemonUpgradeCommand(cliConfig.pievoCli, cliConfig.customCli) })]
538
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
539
+ className: "text-label text-secondary",
540
+ children: configErr ? "Could not load the upgrade command. Close and try again." : "Loading upgrade command…"
541
+ })]
542
+ })
543
+ ]
544
+ }, m.id);
545
+ })
546
+ }),
547
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
548
+ className: "mt-6",
549
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
550
+ className: btnPrimary,
551
+ disabled: busy,
552
+ onClick: () => void startConnect(),
553
+ children: busy ? "Preparing…" : "+ Connect computer"
554
+ })
555
+ })
556
+ ]
557
+ });
558
+ }
559
+ /**
560
+ * Notification-channel server functions. Channels are per-team push targets a
561
+ * loop can route its run messages to. Secrets (bot token / chat id) live in the
562
+ * channel's `config` and are NEVER returned to the client — list/test surface
563
+ * only a redacted summary. Scoped to the request's team (see requestScope).
564
+ *
565
+ * Per-type behavior (validate / hint / send) lives in `CHANNELS` (gateway/notify);
566
+ * this module just wires it to auth + storage.
567
+ */
568
+ /** Resolve a channel and authorize it against the request's team — undefined when
569
+ * missing OR (gate on) owned by another team, so existence never leaks. Mirrors
570
+ * loopApi's ownedLoop for the channel routes. */
571
+ /** GET — the team's channels (redacted summaries, newest first). */
572
+ var listChannels = createServerFn({ method: "GET" }).handler(createSsrRpc("ced5641f28e3e64d3b8773ea4c875b78ee305bd08caba90a2207e86ef1ab3327"));
573
+ /** POST — create a channel in the team. Validates per-type required fields. */
574
+ var createChannel = createServerFn({ method: "POST" }).validator((d) => d).handler(createSsrRpc("d6cb1ea6f7fdaf940fbbe91d6b0898a0d5ac2308f8bc572dc3b856824a1f4581"));
575
+ /** POST — delete a channel (loops pointing at it fall back to dashboard-only). */
576
+ var deleteChannel = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("9defc1b5d0f4316d61621e2c4614a70dc052ad6b7a3aa2ead00836f7d5cb5b4c"));
577
+ /** POST — send a test message through a saved channel (verifies the secrets). */
578
+ var testChannel = createServerFn({ method: "POST" }).validator((id) => id).handler(createSsrRpc("a4e3ae06af7087a3dc291236cf6d5ad272e2f754884c1f948e75a18a4ebada93"));
579
+ //#endregion
580
+ export { listChannels as a, testChannel as c, deleteChannel as i, Timeline as n, listMachines as o, createChannel as r, mergeRuns as s, MachinesModal as t };