@kky42/pievo-server 2.4.13 → 3.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 (89) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{actionUi-D8m1FDHO.js → actionUi-BZrLpgHT.js} +1 -1
  3. package/.output/public/assets/app-DXLuQNb9.css +2 -0
  4. package/.output/public/assets/index-Di_wpAtL.js +10 -0
  5. package/.output/public/assets/loops._loopId-X3ClNPMY.js +67 -0
  6. package/.output/public/assets/loops._loopId_.runs._runId-ByU2BSyF.js +3 -0
  7. package/.output/public/assets/preload-helper-hRTYB_ju.js +3 -0
  8. package/.output/public/assets/{routes-79D939J4.js → routes-BIOJZsig.js} +1 -1
  9. package/.output/public/assets/routes-K8D5uBiV.js +1 -0
  10. package/.output/server/_chunks/ssr-renderer.mjs +1 -1
  11. package/.output/server/_libs/{drizzle-orm+postgres.mjs → drizzle-orm.mjs} +93 -2218
  12. package/.output/server/_ssr/{MachinesModal-DBIP648Z.mjs → MachinesModal-CmVMec6B.mjs} +52 -46
  13. package/.output/server/_ssr/{actionUi-C_WswNb1.mjs → actionUi-DE-Pb2tv.mjs} +4 -5
  14. package/.output/server/_ssr/{artifactFiles-BvVmixrs.mjs → artifactFiles-Di1xDKvX.mjs} +5 -7
  15. package/.output/server/_ssr/{artifactKind-DRCbYHZU.mjs → artifactKind-DqpmtxDU.mjs} +3 -9
  16. package/.output/server/_ssr/{boot-U-CFI65B.mjs → boot-CYRi-wez.mjs} +531 -1976
  17. package/.output/server/_ssr/lifecycleUi-BsbUsi5K.mjs +106 -0
  18. package/.output/server/_ssr/{loopApi-C4nN0msL.mjs → loopApi-Bez1rHV0.mjs} +50 -65
  19. package/.output/server/_ssr/{loopProjection-DMSNHux6.mjs → loopProjection-esCjyZJg.mjs} +4 -20
  20. package/.output/server/_ssr/{loops._loopId-Q4pRYPip.mjs → loops._loopId-KUezNY69.mjs} +133 -24
  21. package/.output/server/_ssr/{loops._loopId_.runs._runId-DNXVmCt5.mjs → loops._loopId_.runs._runId-BFP9oMrp.mjs} +2 -7
  22. package/.output/server/_ssr/{loops._loopId_.runs._runId-ty3AhkOi.mjs → loops._loopId_.runs._runId-DOkUEesG.mjs} +18 -33
  23. package/.output/server/_ssr/{machineFns-CkNms3zA.mjs → machineFns-CniGcY8s.mjs} +13 -49
  24. package/.output/server/_ssr/networkAccess-CIlK3ION.mjs +30 -0
  25. package/.output/server/_ssr/router-BFIH2UAE.mjs +362 -0
  26. package/.output/server/_ssr/routes-BSVBANI3.mjs +12 -0
  27. package/.output/server/_ssr/{routes-BaanDO41.mjs → routes-DnE7XDe_.mjs} +242 -77
  28. package/.output/server/_ssr/{routes-B3fulW5I.mjs → routes-ngpX7h8D.mjs} +2 -4
  29. package/.output/server/_ssr/ssr.mjs +25 -34
  30. package/.output/server/_ssr/start-B5_9Z5W-.mjs +35 -0
  31. package/.output/server/{_tanstack-start-manifest_v-DkmxsHDK.mjs → _tanstack-start-manifest_v-DnwAupbZ.mjs} +8 -13
  32. package/.output/server/drizzle/0000_baseline.sql +6 -97
  33. package/.output/server/drizzle/meta/_journal.json +2 -16
  34. package/.output/server/index.mjs +43 -50
  35. package/drizzle/0000_baseline.sql +6 -97
  36. package/drizzle/meta/_journal.json +2 -16
  37. package/package.json +4 -8
  38. package/scripts/pievo-server.mjs +49 -47
  39. package/scripts/server-cli-lib.mjs +21 -12
  40. package/scripts/server-network.mjs +139 -0
  41. package/.output/public/assets/SignIn-CDCdDD1a.js +0 -1
  42. package/.output/public/assets/app-PPhgN9iN.css +0 -2
  43. package/.output/public/assets/index-c0XPWXuz.js +0 -10
  44. package/.output/public/assets/loops._loopId-D7i_BGiE.js +0 -67
  45. package/.output/public/assets/loops._loopId_.runs._runId-CksSrEY7.js +0 -3
  46. package/.output/public/assets/preload-helper-Zcmr31XG.js +0 -5
  47. package/.output/public/assets/routes-BYgl3Tmv.js +0 -1
  48. package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +0 -419
  49. package/.output/server/_libs/@aws-sdk/checksums+[...].mjs +0 -10732
  50. package/.output/server/_libs/@aws-sdk/client-s3+[...].mjs +0 -9475
  51. package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +0 -137
  52. package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +0 -440
  53. package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +0 -62
  54. package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +0 -818
  55. package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +0 -59
  56. package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +0 -342
  57. package/.output/server/_libs/aws-crypto__crc32c.mjs +0 -314
  58. package/.output/server/_libs/aws-sdk__nested-clients.mjs +0 -2671
  59. package/.output/server/_ssr/SignIn-Bp3uWaCQ.mjs +0 -53
  60. package/.output/server/_ssr/artifacts-CzDJLaa6.mjs +0 -2
  61. package/.output/server/_ssr/auth-BV0MxVdo.mjs +0 -38355
  62. package/.output/server/_ssr/auth-client-RTpMpT4L.mjs +0 -1070
  63. package/.output/server/_ssr/boot-CsLXrLEa.mjs +0 -2
  64. package/.output/server/_ssr/bun-sqlite-dialect-BW9W1_Ps-D9KUBJ-L.mjs +0 -162
  65. package/.output/server/_ssr/core-RrmWoKne.mjs +0 -5
  66. package/.output/server/_ssr/d1-sqlite-dialect-BLC8LXE6-CVHRzH1n.mjs +0 -112
  67. package/.output/server/_ssr/db-BTX-xORB.mjs +0 -2
  68. package/.output/server/_ssr/dist-D7UDVZ5G.mjs +0 -342
  69. package/.output/server/_ssr/factory-DYFx1fg-.mjs +0 -6903
  70. package/.output/server/_ssr/kysely-adapter-CwdB7yBh.mjs +0 -2
  71. package/.output/server/_ssr/kysely-migration-tables-JkVUjPF_-bPAX9LR_.mjs +0 -19
  72. package/.output/server/_ssr/logger-CwiKSMp6.mjs +0 -2
  73. package/.output/server/_ssr/node-sqlite-dialect-B_g92oFK.mjs +0 -162
  74. package/.output/server/_ssr/router-DCNZ2xLm.mjs +0 -543
  75. package/.output/server/_ssr/routes-8JSF7bX_.mjs +0 -27
  76. package/.output/server/_ssr/runDiff-D7CxAgYL.mjs +0 -2
  77. package/.output/server/_ssr/start-4ifArtKx.mjs +0 -4
  78. package/.output/server/_ssr/store-DSNbXxqz.mjs +0 -2
  79. package/.output/server/_ssr/tokens-DzUv7CCp.mjs +0 -2
  80. package/.output/server/drizzle/0001_add_pi_agent.sql +0 -9
  81. package/.output/server/drizzle/0002_remove_teams.sql +0 -15
  82. package/.output/server/node_modules/tslib/modules/index.js +0 -70
  83. package/.output/server/node_modules/tslib/modules/package.json +0 -3
  84. package/.output/server/node_modules/tslib/package.json +0 -47
  85. package/.output/server/node_modules/tslib/tslib.js +0 -484
  86. package/.output/server/package.json +0 -9
  87. package/drizzle/0001_add_pi_agent.sql +0 -9
  88. package/drizzle/0002_remove_teams.sql +0 -15
  89. package/scripts/prestart.mjs +0 -66
@@ -1,10 +1,10 @@
1
1
  import { o as __toESM } from "../_runtime.mjs";
2
2
  import { g as require_react, h as require_jsx_runtime, s as TooltipProvider } from "../_libs/@base-ui/react+[...].mjs";
3
- import { c as createFileRoute, d as useNavigate, f as useRouter, s as lazyRouteComponent } from "../_libs/@tanstack/react-router+[...].mjs";
4
- import { O as useSession, _ as listLoops, a as PievoLogo, f as getAuthState, i as OpenModeWarning, n as GITHUB_URL, p as getConfig, r as GitHubIcon, v as loadOlderRuns, w as signOut, y as mintConnectKey } from "./auth-client-RTpMpT4L.mjs";
5
- import { f as btnSm } from "./actionUi-C_WswNb1.mjs";
6
- import { c as mergeRuns, i as ModalHead, n as MachinesModal, o as daemonConnectCommand, r as Modal, s as listMachines, t as LoopOverview } from "./MachinesModal-DBIP648Z.mjs";
7
- //#region node_modules/.nitro/vite/services/ssr/assets/routes-BaanDO41.js
3
+ import { c as createFileRoute, d as useNavigate, s as lazyRouteComponent } from "../_libs/@tanstack/react-router+[...].mjs";
4
+ import { c as getConfig, f as listLoops, m as mintConnectKey, p as loadOlderRuns } from "./lifecycleUi-BsbUsi5K.mjs";
5
+ import { f as btnSm, y as focusRing } from "./actionUi-DE-Pb2tv.mjs";
6
+ import { c as listMachines, i as ModalHead, l as mergeRuns, n as MachinesModal, o as connectServerUrl, r as Modal, s as daemonConnectCommand, t as LoopOverview } from "./MachinesModal-CmVMec6B.mjs";
7
+ //#region node_modules/.nitro/vite/services/ssr/assets/routes-DnE7XDe_.js
8
8
  var import_react = /* @__PURE__ */ __toESM(require_react());
9
9
  var import_jsx_runtime = require_jsx_runtime();
10
10
  function LoopCard({ loop, onOpen, onPickRun }) {
@@ -37,6 +37,43 @@ function LoopCard({ loop, onOpen, onPickRun }) {
37
37
  })
38
38
  });
39
39
  }
40
+ function LoopFilterBar({ options, selectedKey, onSelect }) {
41
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
42
+ className: "scrollbar-none -mx-1 overflow-x-auto px-1 pb-1",
43
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
44
+ role: "group",
45
+ "aria-label": "Loop filters",
46
+ className: "flex min-w-max items-center gap-1.5",
47
+ children: options.map((option) => {
48
+ const selected = option.key === selectedKey;
49
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
50
+ type: "button",
51
+ "aria-pressed": selected,
52
+ title: option.filter.kind === "tag" ? option.label : void 0,
53
+ onClick: (event) => {
54
+ event.currentTarget.scrollIntoView?.({
55
+ block: "nearest",
56
+ inline: "nearest"
57
+ });
58
+ onSelect(option.filter);
59
+ },
60
+ className: `inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-full border px-3 text-body font-medium transition-colors ${focusRing} ${selected ? "border-display bg-display text-paper" : "border-hairline bg-surface text-secondary hover:border-wire hover:bg-raised hover:text-primary"}`,
61
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
62
+ className: option.filter.kind === "tag" ? "max-w-44 truncate" : "",
63
+ children: option.label
64
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
65
+ className: selected ? "text-paper/70" : "text-disabled",
66
+ children: [
67
+ "(",
68
+ option.count,
69
+ ")"
70
+ ]
71
+ })]
72
+ }, option.key);
73
+ })
74
+ })
75
+ });
76
+ }
40
77
  function ComposeModal({ open, onClose }) {
41
78
  const [token, setToken] = (0, import_react.useState)(null);
42
79
  const [config, setConfig] = (0, import_react.useState)(null);
@@ -44,7 +81,7 @@ function ComposeModal({ open, onClose }) {
44
81
  const [error, setError] = (0, import_react.useState)(null);
45
82
  const [configError, setConfigError] = (0, import_react.useState)(false);
46
83
  const origin = typeof window !== "undefined" ? window.location.origin : "";
47
- const command = token && config ? daemonConnectCommand(origin, token, config.pievoCli, config.customCli) : "";
84
+ const command = token && config ? daemonConnectCommand(connectServerUrl(origin, config.publicUrl), token, config.pievoCli, config.customCli) : "";
48
85
  (0, import_react.useEffect)(() => {
49
86
  if (!open) return;
50
87
  setToken(null);
@@ -62,9 +99,7 @@ function ComposeModal({ open, onClose }) {
62
99
  if (active) setConfigError(true);
63
100
  });
64
101
  mintConnectKey().then((result) => {
65
- if (!active) return;
66
- if ("token" in result) setToken(result.token);
67
- else setError(result.error);
102
+ if (active) setToken(result.token);
68
103
  }).catch(() => {
69
104
  if (active) setError("could not mint a connect key");
70
105
  });
@@ -169,8 +204,139 @@ function Step({ number, title, continued = false, children }) {
169
204
  })]
170
205
  });
171
206
  }
172
- /** Loops and machines change between polls. Authorization is derived server-side
173
- * from the current session; clients do not send tenant identifiers. */
207
+ /**
208
+ * Shared Pievo mark geometry: eight durable steps form a cycle and the
209
+ * interactive-blue runner marks the next scheduled pass.
210
+ *
211
+ * Variants are props on one geometry (styles in app.css):
212
+ * - `plate` - dark tile behind the steps (favicon / app-icon contexts);
213
+ * without it the steps inherit currentColor (inline contexts).
214
+ * - `trail` - two fading steps behind the runner, so a static rendering
215
+ * still reads as motion (print / social cards).
216
+ * - `animated` - the runner advances around the cycle; reduced-motion users
217
+ * see the canonical static first frame.
218
+ */
219
+ var RING = [
220
+ [9, 9],
221
+ [37, 9],
222
+ [65, 9],
223
+ [65, 37],
224
+ [65, 65],
225
+ [37, 65],
226
+ [9, 65],
227
+ [9, 37]
228
+ ];
229
+ function RingLogo({ size = 24, plate = false, trail = false, animated = false }) {
230
+ const cellClass = (i) => {
231
+ const parts = ["ring-cell", `rc${i}`];
232
+ if (i === 0) parts.push("ring-runner");
233
+ else if (trail && i === 7) parts.push("ring-trail-1");
234
+ else if (trail && i === 6) parts.push("ring-trail-2");
235
+ return parts.join(" ");
236
+ };
237
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
238
+ width: size,
239
+ height: size,
240
+ viewBox: "0 0 96 96",
241
+ role: "img",
242
+ "aria-label": "Pievo",
243
+ className: [
244
+ "ring-logo",
245
+ plate && "ring-logo-plate",
246
+ animated && "ring-logo-animated"
247
+ ].filter(Boolean).join(" "),
248
+ children: [plate && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
249
+ width: "96",
250
+ height: "96",
251
+ rx: "15",
252
+ fill: "#0b0b0b"
253
+ }), RING.map(([x, y], i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", {
254
+ x,
255
+ y,
256
+ width: 22,
257
+ height: 22,
258
+ rx: 6,
259
+ className: cellClass(i)
260
+ }, i))]
261
+ });
262
+ }
263
+ /**
264
+ * Pievo's primary product mark: one scheduled pass moving around a durable ring.
265
+ * It reuses the same geometry as the favicon and README asset; animation is a
266
+ * progressive enhancement and parks on the canonical first frame when reduced
267
+ * motion is requested.
268
+ */
269
+ function PievoLogo({ size = 56 }) {
270
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RingLogo, {
271
+ size,
272
+ plate: true,
273
+ animated: true
274
+ });
275
+ }
276
+ var GITHUB_URL = "https://github.com/kky42/pievo";
277
+ function GitHubIcon({ className }) {
278
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
279
+ viewBox: "0 0 24 24",
280
+ fill: "currentColor",
281
+ "aria-hidden": true,
282
+ className,
283
+ 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" })
284
+ });
285
+ }
286
+ function loopFilterKey(filter) {
287
+ return filter.kind === "tag" ? `tag:${filter.tag}` : filter.kind;
288
+ }
289
+ function loopFilterOptions(loops) {
290
+ const active = loops.filter((loop) => loop.enabled && !loop.deleteRequestedAt).length;
291
+ const paused = loops.filter((loop) => !loop.enabled && !loop.deleteRequestedAt).length;
292
+ const blocked = loops.filter((loop) => !loop.enabled && !loop.deleteRequestedAt && loop.pauseCause?.kind === "blocked").length;
293
+ const tagCounts = /* @__PURE__ */ new Map();
294
+ for (const loop of loops) for (const tag of new Set(loop.tags)) tagCounts.set(tag, (tagCounts.get(tag) ?? 0) + 1);
295
+ return [
296
+ {
297
+ key: "all",
298
+ label: "All Loops",
299
+ count: loops.length,
300
+ filter: { kind: "all" }
301
+ },
302
+ {
303
+ key: "active",
304
+ label: "Active",
305
+ count: active,
306
+ filter: { kind: "active" }
307
+ },
308
+ {
309
+ key: "paused",
310
+ label: "Paused",
311
+ count: paused,
312
+ filter: { kind: "paused" }
313
+ },
314
+ {
315
+ key: "blocked",
316
+ label: "Blocked",
317
+ count: blocked,
318
+ filter: { kind: "blocked" }
319
+ },
320
+ ...[...tagCounts].sort(([a], [b]) => a.localeCompare(b, "en-US")).map(([tag, count]) => ({
321
+ key: `tag:${tag}`,
322
+ label: tag,
323
+ count,
324
+ filter: {
325
+ kind: "tag",
326
+ tag
327
+ }
328
+ }))
329
+ ];
330
+ }
331
+ function filterLoops(loops, filter) {
332
+ switch (filter.kind) {
333
+ case "all": return loops;
334
+ case "active": return loops.filter((loop) => loop.enabled && !loop.deleteRequestedAt);
335
+ case "paused": return loops.filter((loop) => !loop.enabled && !loop.deleteRequestedAt);
336
+ case "blocked": return loops.filter((loop) => !loop.enabled && !loop.deleteRequestedAt && loop.pauseCause?.kind === "blocked");
337
+ case "tag": return loops.filter((loop) => loop.tags.includes(filter.tag));
338
+ }
339
+ }
174
340
  async function fetchLiveData() {
175
341
  const [loops, machines] = await Promise.all([listLoops(), listMachines()]);
176
342
  return {
@@ -178,26 +344,14 @@ async function fetchLiveData() {
178
344
  machines
179
345
  };
180
346
  }
181
- function DashboardView({ initial, mode }) {
347
+ function DashboardView({ initial }) {
182
348
  const [live, setLive] = (0, import_react.useState)(null);
183
349
  const { loops, machines } = live ?? initial;
184
350
  const online = machines.filter((m) => m.online).length;
185
351
  const navigate = useNavigate();
186
- const router = useRouter();
187
- const { data: session } = useSession();
188
- const [signingOut, setSigningOut] = (0, import_react.useState)(false);
189
352
  const [composeOpen, setComposeOpen] = (0, import_react.useState)(false);
190
353
  const [machinesOpen, setMachinesOpen] = (0, import_react.useState)(false);
191
- async function logout() {
192
- setSigningOut(true);
193
- try {
194
- await signOut();
195
- await navigate({ to: "/" });
196
- await router.invalidate();
197
- } finally {
198
- setSigningOut(false);
199
- }
200
- }
354
+ const [filter, setFilter] = (0, import_react.useState)({ kind: "all" });
201
355
  const refetch = (0, import_react.useCallback)(async () => {
202
356
  try {
203
357
  setLive(await fetchLiveData());
@@ -212,14 +366,16 @@ function DashboardView({ initial, mode }) {
212
366
  }, anyRunning ? 3e3 : 1e4);
213
367
  return () => clearInterval(t);
214
368
  }, [refetch, anyRunning]);
215
- const activeCount = loops.filter((loop) => loop.enabled && !loop.deleteRequestedAt).length;
216
- const pausedCount = loops.filter((loop) => !loop.enabled && !loop.deleteRequestedAt).length;
217
- const deletingCount = loops.filter((loop) => Boolean(loop.deleteRequestedAt)).length;
218
- const lifecycleCounts = [
219
- `${activeCount} active`,
220
- `${pausedCount} paused`,
221
- ...deletingCount ? [`${deletingCount} deleting`] : []
222
- ].join(" · ");
369
+ const filterOptions = (0, import_react.useMemo)(() => loopFilterOptions(loops), [loops]);
370
+ const selectedFilterKey = loopFilterKey(filter);
371
+ const filteredLoops = (0, import_react.useMemo)(() => filterLoops(loops, filter), [loops, filter]);
372
+ (0, import_react.useEffect)(() => {
373
+ if (filter.kind === "tag" && !filterOptions.some((option) => option.key === selectedFilterKey)) setFilter({ kind: "all" });
374
+ }, [
375
+ filter,
376
+ filterOptions,
377
+ selectedFilterKey
378
+ ]);
223
379
  const cardProps = () => ({
224
380
  onOpen: (id) => void navigate({
225
381
  to: "/loops/$loopId",
@@ -239,11 +395,14 @@ function DashboardView({ initial, mode }) {
239
395
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("header", {
240
396
  className: "glass glass-bar sticky top-0 z-50",
241
397
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
242
- className: "mx-auto flex max-w-[1180px] items-center gap-3 px-8 py-2.5",
398
+ className: "mx-auto flex max-w-[1180px] items-center gap-2 px-4 py-2.5 sm:gap-3 sm:px-8",
243
399
  children: [
244
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PievoLogo, { size: 30 }),
245
400
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
246
- className: "text-[18px] font-semibold tracking-[-0.015em] text-display",
401
+ className: "shrink-0",
402
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PievoLogo, { size: 30 })
403
+ }),
404
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
405
+ className: "shrink-0 text-[18px] font-semibold tracking-[-0.015em] text-display",
247
406
  children: "Pievo"
248
407
  }),
249
408
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex-1" }),
@@ -253,31 +412,28 @@ function DashboardView({ initial, mode }) {
253
412
  rel: "noreferrer",
254
413
  "aria-label": "GitHub repository",
255
414
  title: "GitHub",
256
- className: headerIconBtn,
415
+ className: `${headerIconBtn} hidden sm:inline-flex`,
257
416
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitHubIcon, { className: "size-[17px]" })
258
417
  }),
259
- mode === "auth" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
260
- className: "flex items-center gap-2",
261
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
262
- className: "max-w-48 truncate text-label text-secondary",
263
- title: session?.user.email ?? session?.user.name ?? "Account",
264
- children: session?.user.email ?? session?.user.name ?? "Account"
265
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
266
- onClick: () => void logout(),
267
- disabled: signingOut,
268
- className: headerBtn,
269
- children: signingOut ? "Signing out…" : "Sign out"
270
- })]
271
- }),
272
418
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
273
419
  onClick: () => setMachinesOpen(true),
274
- className: `${headerBtn} gap-1.5`,
420
+ "aria-label": `${online} ${online === 1 ? "machine" : "machines"} online`,
421
+ className: `${headerBtn} gap-1.5 px-2 sm:px-3`,
275
422
  children: [
276
423
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `inline-block size-1.5 rounded-full ${online ? "bg-rubik-green" : "bg-disabled"}` }),
277
- online,
278
- " ",
279
- online === 1 ? "machine" : "machines",
280
- " online"
424
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
425
+ className: "sm:hidden",
426
+ children: online
427
+ }),
428
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
429
+ className: "hidden sm:inline",
430
+ children: [
431
+ online,
432
+ " ",
433
+ online === 1 ? "machine" : "machines",
434
+ " online"
435
+ ]
436
+ })
281
437
  ]
282
438
  }),
283
439
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
@@ -291,7 +447,6 @@ function DashboardView({ initial, mode }) {
291
447
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", {
292
448
  className: "mx-auto max-w-[1180px] px-8 pb-24",
293
449
  children: [
294
- mode === "open" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OpenModeWarning, { className: "mt-6" }),
295
450
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
296
451
  className: "pb-2 pt-14 text-center",
297
452
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
@@ -310,25 +465,42 @@ function DashboardView({ initial, mode }) {
310
465
  })]
311
466
  }),
312
467
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
313
- className: "mb-5 mt-12 flex items-baseline gap-2.5",
314
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", {
315
- className: "text-body font-semibold text-display",
316
- children: "Loops"
317
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
318
- className: "text-label text-secondary",
319
- children: loops.length ? lifecycleCounts : ""
468
+ className: "mb-5 mt-12",
469
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoopFilterBar, {
470
+ options: filterOptions,
471
+ selectedKey: selectedFilterKey,
472
+ onSelect: setFilter
473
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
474
+ className: "sr-only",
475
+ "aria-live": "polite",
476
+ children: [
477
+ "Showing ",
478
+ filteredLoops.length,
479
+ " loops"
480
+ ]
320
481
  })]
321
482
  }),
322
- loops.length ? loops.map((j) => /* @__PURE__ */ (0, import_react.createElement)(LoopCard, {
483
+ filteredLoops.length ? filteredLoops.map((j) => /* @__PURE__ */ (0, import_react.createElement)(LoopCard, {
323
484
  loop: j,
324
485
  ...cardProps(),
325
486
  key: j.id
326
- })) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
487
+ })) : loops.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
488
+ className: "py-16 text-center",
489
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
490
+ className: "text-[15px] text-secondary",
491
+ children: "No loops match this filter"
492
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
493
+ type: "button",
494
+ onClick: () => setFilter({ kind: "all" }),
495
+ className: "mt-2 text-body font-medium text-interactive hover:underline",
496
+ children: "Show all loops"
497
+ })]
498
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
327
499
  className: "py-16 text-center",
328
500
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
329
501
  className: "text-[15px] text-secondary",
330
502
  children: "No loops yet"
331
- }), !loops.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
503
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
332
504
  className: "mt-1.5 text-body text-disabled",
333
505
  children: "Create a scheduled prompt for a connected machine."
334
506
  })]
@@ -347,19 +519,12 @@ function DashboardView({ initial, mode }) {
347
519
  });
348
520
  }
349
521
  var headerBtn = "inline-flex shrink-0 cursor-pointer items-center rounded-full px-3 py-1.5 text-meta font-medium text-secondary transition-colors hover:bg-raised hover:text-display";
350
- var headerIconBtn = "inline-flex shrink-0 cursor-pointer items-center rounded-full p-1.5 text-secondary transition-colors hover:bg-raised hover:text-display";
351
- var $$splitErrorComponentImporter = () => import("./routes-B3fulW5I.mjs");
352
- var $$splitComponentImporter = () => import("./routes-8JSF7bX_.mjs");
353
- /** The dashboard route. Auth mode shows sign-in before loading owner-scoped data;
354
- * open mode renders the server's shared administrative workspace. */
522
+ var headerIconBtn = "shrink-0 cursor-pointer items-center rounded-full p-1.5 text-secondary transition-colors hover:bg-raised hover:text-display";
523
+ var $$splitErrorComponentImporter = () => import("./routes-ngpX7h8D.mjs");
524
+ var $$splitComponentImporter = () => import("./routes-BSVBANI3.mjs");
355
525
  var Route = createFileRoute("/")({
356
526
  ssr: false,
357
- loader: async () => {
358
- return {
359
- auth: await getAuthState(),
360
- initial: await fetchLiveData()
361
- };
362
- },
527
+ loader: () => fetchLiveData(),
363
528
  component: lazyRouteComponent($$splitComponentImporter, "component"),
364
529
  errorComponent: lazyRouteComponent($$splitErrorComponentImporter, "errorComponent")
365
530
  });
@@ -1,10 +1,8 @@
1
1
  import { h as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
2
2
  import { f as useRouter } from "../_libs/@tanstack/react-router+[...].mjs";
3
- import { i as LoadErrorCard } from "./actionUi-C_WswNb1.mjs";
4
- //#region node_modules/.nitro/vite/services/ssr/assets/routes-B3fulW5I.js
3
+ import { i as LoadErrorCard } from "./actionUi-DE-Pb2tv.mjs";
4
+ //#region node_modules/.nitro/vite/services/ssr/assets/routes-ngpX7h8D.js
5
5
  var import_jsx_runtime = require_jsx_runtime();
6
- /** The dashboard route. Auth mode shows sign-in before loading owner-scoped data;
7
- * open mode renders the server's shared administrative workspace. */
8
6
  /** First-load failure screen — a calm retry instead of the router's default
9
7
  * error dump. Only the initial loader can land here; the in-page poll is
10
8
  * fetch-then-set and keeps stale data on a transient blip. */
@@ -1,5 +1,4 @@
1
1
  import { r as __exportAll } from "../_runtime.mjs";
2
- import { i as __exportAll$1 } from "./factory-DYFx1fg-.mjs";
3
2
  import { g as require_react, h as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
4
3
  import { a as RouterProvider, n as defineHandlerCallback, t as renderRouterToStream } from "../_libs/@tanstack/react-router+[...].mjs";
5
4
  import { PassThrough, Readable } from "node:stream";
@@ -11,7 +10,7 @@ var ssr_exports = /* @__PURE__ */ __exportAll({
11
10
  i: () => getServerFnById,
12
11
  n: () => createServerFn,
13
12
  r: () => TSS_SERVER_FUNCTION,
14
- t: () => server_exports
13
+ t: () => createMiddleware
15
14
  });
16
15
  require_react();
17
16
  var import_jsx_runtime = require_jsx_runtime();
@@ -597,9 +596,6 @@ function getH3Event() {
597
596
  if (!event) throw new Error(`No StartEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`);
598
597
  return event.h3Event;
599
598
  }
600
- function getRequest() {
601
- return getH3Event().req;
602
- }
603
599
  function getResponse() {
604
600
  return getH3Event().res;
605
601
  }
@@ -3418,7 +3414,7 @@ var defaultSerovalPlugins = [
3418
3414
  * the dev styles URL for route-scoped CSS collection.
3419
3415
  */
3420
3416
  async function getStartManifest(matchedRoutes) {
3421
- const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-DkmxsHDK.mjs");
3417
+ const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-DnwAupbZ.mjs");
3422
3418
  const startManifest = tsrStartManifest();
3423
3419
  let routes = startManifest.routes;
3424
3420
  routes[rootRouteId];
@@ -3440,87 +3436,83 @@ async function getStartManifest(matchedRoutes) {
3440
3436
  var manifest = {
3441
3437
  "08565e35f6a3dd06ef25401de0343976c47f7ae319d3baed6320b56dd3718311": {
3442
3438
  functionName: "runLoop_createServerFn_handler",
3443
- importer: () => import("./loopApi-C4nN0msL.mjs")
3439
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3444
3440
  },
3445
3441
  "08c28b892712a1b491b120b74c7dcb81761988d31ccea60216d1807b73c1182c": {
3446
3442
  functionName: "getRunDiff_createServerFn_handler",
3447
- importer: () => import("./loopApi-C4nN0msL.mjs")
3443
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3448
3444
  },
3449
3445
  "169566e7637a22599b4eb32ee3775574e99677406922bbef7482a102036c33dd": {
3450
3446
  functionName: "machineStatus_createServerFn_handler",
3451
- importer: () => import("./machineFns-CkNms3zA.mjs")
3447
+ importer: () => import("./machineFns-CniGcY8s.mjs")
3452
3448
  },
3453
3449
  "23e290b2b7483ceea6fe669024c35b12c2c4ddd76649f6fab21c958ceda02940": {
3454
3450
  functionName: "listLoops_createServerFn_handler",
3455
- importer: () => import("./loopApi-C4nN0msL.mjs")
3451
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3456
3452
  },
3457
3453
  "27d7eba0b6a2257949392fdd56057275a5c5366484ae01faf3b5897a225ecd83": {
3458
3454
  functionName: "finalizeMachine_createServerFn_handler",
3459
- importer: () => import("./machineFns-CkNms3zA.mjs")
3455
+ importer: () => import("./machineFns-CniGcY8s.mjs")
3460
3456
  },
3461
3457
  "5660ea82ea5ff2549e0ce2f8f070c54f3e9e24fee84d547601ef5d6ef49a4016": {
3462
3458
  functionName: "startLoop_createServerFn_handler",
3463
- importer: () => import("./loopApi-C4nN0msL.mjs")
3459
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3464
3460
  },
3465
3461
  "5e0d6b55f5629faac2f55a68661eeb82668b2be752192b16264ffb5cd1e6fabe": {
3466
3462
  functionName: "deleteLoop_createServerFn_handler",
3467
- importer: () => import("./loopApi-C4nN0msL.mjs")
3463
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3468
3464
  },
3469
3465
  "6850ba403da9dec5aff45794eb52636ca540ddec2d9e59f5c75ccbb852bfeacb": {
3470
3466
  functionName: "stopRun_createServerFn_handler",
3471
- importer: () => import("./loopApi-C4nN0msL.mjs")
3467
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3472
3468
  },
3473
3469
  "85fdf73d4fee43aed762f93c5d47d33200fbff39e2d082647dc921f610d32698": {
3474
3470
  functionName: "loadOlderRuns_createServerFn_handler",
3475
- importer: () => import("./loopApi-C4nN0msL.mjs")
3471
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3476
3472
  },
3477
3473
  "95b7483b333d7649e70c848319417e83c2af6a0327bbcda2d0e331f626dffe05": {
3478
3474
  functionName: "pauseLoop_createServerFn_handler",
3479
- importer: () => import("./loopApi-C4nN0msL.mjs")
3475
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3480
3476
  },
3481
3477
  "9befe6b8d67ccbbd7aa9b538bde2a161a9894761c8936761a9503fda1a88c0fc": {
3482
3478
  functionName: "patchLoop_createServerFn_handler",
3483
- importer: () => import("./loopApi-C4nN0msL.mjs")
3479
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3484
3480
  },
3485
3481
  "a6384dc7154d9930422d29396f5de64b3ac69c62ad3824bc4a22d745fc07b293": {
3486
3482
  functionName: "deleteMachine_createServerFn_handler",
3487
- importer: () => import("./machineFns-CkNms3zA.mjs")
3483
+ importer: () => import("./machineFns-CniGcY8s.mjs")
3488
3484
  },
3489
3485
  "aa46310016bb8a58b273a648ffd498c87f1f450d12827e30110a3b83ba6a27d9": {
3490
3486
  functionName: "listMachines_createServerFn_handler",
3491
- importer: () => import("./machineFns-CkNms3zA.mjs")
3487
+ importer: () => import("./machineFns-CniGcY8s.mjs")
3492
3488
  },
3493
3489
  "b050455aacc84dd2a2c9a45517826ad10f91d8f1545e87cc7015784cc7116a97": {
3494
3490
  functionName: "getLoopDetail_createServerFn_handler",
3495
- importer: () => import("./loopApi-C4nN0msL.mjs")
3491
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3496
3492
  },
3497
3493
  "b18bbec3d06dfc77714e1e527dfb9172fd7575a64a6c0d6e73ba6dc658dccf0d": {
3498
3494
  functionName: "getArtifacts_createServerFn_handler",
3499
- importer: () => import("./loopApi-C4nN0msL.mjs")
3500
- },
3501
- "b8119d5fe6ca1ed9f609702aa2133b5ac5337030c0bdcf92dc7eba889d6bd2e6": {
3502
- functionName: "getAuthState_createServerFn_handler",
3503
- importer: () => import("./loopApi-C4nN0msL.mjs")
3495
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3504
3496
  },
3505
3497
  "cbb6a1b09b309459bbba3dc3851ae85fc468658b3cda77e22b6c6f3e28b65af4": {
3506
3498
  functionName: "getConfig_createServerFn_handler",
3507
- importer: () => import("./loopApi-C4nN0msL.mjs")
3499
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3508
3500
  },
3509
3501
  "ce43dcb9366e7c8f7338a6ad28e4290b75a5ee3b13d0d2c9cb585020008f12c6": {
3510
3502
  functionName: "mintConnectKey_createServerFn_handler",
3511
- importer: () => import("./loopApi-C4nN0msL.mjs")
3503
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3512
3504
  },
3513
3505
  "e233a461e4526dec3cc4cbaa891a7c3621d5967ce7f32b4fb17e9fb645857b9a": {
3514
3506
  functionName: "stopLoop_createServerFn_handler",
3515
- importer: () => import("./loopApi-C4nN0msL.mjs")
3507
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3516
3508
  },
3517
3509
  "ed10d5fe79208e5e0e4e18e4a17b18d7f7db4dd16204c00c3ac90c4644668841": {
3518
3510
  functionName: "getArtifact_createServerFn_handler",
3519
- importer: () => import("./loopApi-C4nN0msL.mjs")
3511
+ importer: () => import("./loopApi-Bez1rHV0.mjs")
3520
3512
  },
3521
3513
  "ed679b4e1e05e903a5d4ba4a70d9b9d883991ab22ed59b4d2d69078941818415": {
3522
3514
  functionName: "createMachine_createServerFn_handler",
3523
- importer: () => import("./machineFns-CkNms3zA.mjs")
3515
+ importer: () => import("./machineFns-CniGcY8s.mjs")
3524
3516
  }
3525
3517
  };
3526
3518
  async function getServerFnById(id, access) {
@@ -5352,8 +5344,8 @@ var getBaseManifest = getProdBaseManifest;
5352
5344
  var createEarlyHintsForRequest = createEarlyHintsCollector;
5353
5345
  async function loadEntries() {
5354
5346
  const [routerEntry, startEntry, pluginAdapters] = await Promise.all([
5355
- import("./router-DCNZ2xLm.mjs"),
5356
- import("./start-4ifArtKx.mjs"),
5347
+ import("./router-BFIH2UAE.mjs"),
5348
+ import("./start-B5_9Z5W-.mjs"),
5357
5349
  import("./empty-plugin-adapters-DKUlnwwl.mjs")
5358
5350
  ]);
5359
5351
  return {
@@ -5729,7 +5721,6 @@ async function handleServerRoutes({ getRouter, request, url, executeRouter, cont
5729
5721
  }
5730
5722
  return normalizeSsrResponse(response);
5731
5723
  }
5732
- var server_exports = /* @__PURE__ */ __exportAll$1({ getRequest: () => getRequest });
5733
5724
  var fetch$1 = createStartHandler(defaultStreamHandler);
5734
5725
  function createServerEntry(entry) {
5735
5726
  return { async fetch(...args) {
@@ -5738,4 +5729,4 @@ function createServerEntry(entry) {
5738
5729
  }
5739
5730
  var server_default = createServerEntry({ fetch: fetch$1 });
5740
5731
  //#endregion
5741
- export { ssr_exports as i, createServerFn as n, getServerFnById as r, TSS_SERVER_FUNCTION as t };
5732
+ export { ssr_exports as a, getServerFnById as i, createMiddleware as n, createServerFn as r, TSS_SERVER_FUNCTION as t };
@@ -0,0 +1,35 @@
1
+ import { n as createMiddleware } from "./ssr.mjs";
2
+ //#region node_modules/.nitro/vite/services/ssr/assets/start-B5_9Z5W-.js
3
+ function dedupeSerializationAdapters(deduped, serializationAdapters) {
4
+ for (let i = 0, len = serializationAdapters.length; i < len; i++) {
5
+ const current = serializationAdapters[i];
6
+ if (!deduped.has(current)) {
7
+ deduped.add(current);
8
+ if (current.extends) dedupeSerializationAdapters(deduped, current.extends);
9
+ }
10
+ }
11
+ }
12
+ var createStart = (getOptions) => {
13
+ return {
14
+ getOptions: async () => {
15
+ const options = await getOptions();
16
+ if (options.serializationAdapters) {
17
+ const deduped = /* @__PURE__ */ new Set();
18
+ dedupeSerializationAdapters(deduped, options.serializationAdapters);
19
+ options.serializationAdapters = Array.from(deduped);
20
+ }
21
+ return options;
22
+ },
23
+ createMiddleware
24
+ };
25
+ };
26
+ /** Rejects requests from outside this machine, the LAN, and the tailnet. */
27
+ var networkAccess = createMiddleware().server(async ({ request, next }) => {
28
+ const { isTrustedPeer } = await import("./networkAccess-CIlK3ION.mjs");
29
+ const peer = request.ip;
30
+ if (!isTrustedPeer(peer)) return new Response("Pievo only accepts connections from this machine, the local network, or Tailscale.", { status: 403 });
31
+ return next();
32
+ });
33
+ var startInstance = createStart(() => ({ requestMiddleware: [networkAccess] }));
34
+ //#endregion
35
+ export { startInstance };