@kky42/pievo-server 2.4.14 → 4.1.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.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/MarkdownView-BuFKr9Jg.js +66 -0
- package/.output/public/assets/{actionUi-5PtES4q0.js → actionUi-BZrLpgHT.js} +1 -1
- package/.output/public/assets/app-x1CeeY7N.css +2 -0
- package/.output/public/assets/index-D0FIKiiW.js +10 -0
- package/.output/public/assets/loops._loopId-DTkIz4C0.js +2 -0
- package/.output/public/assets/loops._loopId_.runs._runId-CsV2Ih4Z.js +3 -0
- package/.output/public/assets/preload-helper-BSxGu4d0.js +3 -0
- package/.output/public/assets/{routes-Dm_3J2aV.js → routes-BIOJZsig.js} +1 -1
- package/.output/public/assets/routes-m4Z90DTR.js +1 -0
- package/.output/server/_chunks/ssr-renderer.mjs +1 -1
- package/.output/server/_libs/{drizzle-orm+postgres.mjs → drizzle-orm.mjs} +93 -2218
- package/.output/server/_ssr/{MachinesModal-BaEtzycr.mjs → MachinesModal-CLBZxZkq.mjs} +47 -47
- package/.output/server/_ssr/MarkdownView-D1J7ImYF.mjs +70 -0
- package/.output/server/_ssr/{actionUi-5HOCZnom.mjs → actionUi-DE-Pb2tv.mjs} +1 -2
- package/.output/server/_ssr/artifactFiles-B0NPRDOR.mjs +52 -0
- package/.output/server/_ssr/{artifactKind-DwDr8IYc.mjs → artifactKind-a2oxT2wQ.mjs} +4 -10
- package/.output/server/_ssr/{boot-C472kLwY.mjs → boot-DmpKtb0A.mjs} +2659 -890
- package/.output/server/_ssr/lifecycleUi-DEjM8Etm.mjs +106 -0
- package/.output/server/_ssr/{loopApi-DT751TJA.mjs → loopApi-DK1lQPrx.mjs} +53 -69
- package/.output/server/_ssr/{loopProjection-qaD2I48a.mjs → loopProjection-DdFivf7-.mjs} +6 -24
- package/.output/server/_ssr/{loops._loopId-CXgw2Rz1.mjs → loops._loopId-DVCvGSEc.mjs} +36 -116
- package/.output/server/_ssr/{loops._loopId_.runs._runId-SASSqOfy.mjs → loops._loopId_.runs._runId-BXbTfLlC.mjs} +35 -39
- package/.output/server/_ssr/{loops._loopId_.runs._runId-Dk94Z0Jq.mjs → loops._loopId_.runs._runId-Dr6E-FA5.mjs} +3 -8
- package/.output/server/_ssr/{machineFns-BSrIgn3f.mjs → machineFns-DLRHgDdS.mjs} +13 -50
- package/.output/server/_ssr/networkAccess-CIlK3ION.mjs +30 -0
- package/.output/server/_ssr/router-BhHsTGqu.mjs +355 -0
- package/.output/server/_ssr/routes-CCallyCT.mjs +12 -0
- package/.output/server/_ssr/{routes-Cr-9yDEH.mjs → routes-CL2Kef-Q.mjs} +91 -50
- package/.output/server/_ssr/{routes-DRBS4Zi4.mjs → routes-ngpX7h8D.mjs} +2 -4
- package/.output/server/_ssr/ssr.mjs +25 -34
- package/.output/server/_ssr/start-B5_9Z5W-.mjs +35 -0
- package/.output/server/{_tanstack-start-manifest_v-DxLIQ0cc.mjs → _tanstack-start-manifest_v-BPiJ4yWT.mjs} +9 -15
- package/.output/server/drizzle/0000_baseline.sql +6 -97
- package/.output/server/drizzle/0001_loop_files.sql +9 -0
- package/.output/server/drizzle/meta/_journal.json +3 -17
- package/.output/server/index.mjs +50 -50
- package/drizzle/0000_baseline.sql +6 -97
- package/drizzle/0001_loop_files.sql +9 -0
- package/drizzle/meta/_journal.json +3 -17
- package/package.json +4 -8
- package/scripts/pievo-server.mjs +49 -47
- package/scripts/server-cli-lib.mjs +21 -12
- package/scripts/server-network.mjs +139 -0
- package/.output/public/assets/SignIn-CIFwnZtF.js +0 -1
- package/.output/public/assets/app-DvHMhs7S.css +0 -2
- package/.output/public/assets/index-CRX2pu0W.js +0 -10
- package/.output/public/assets/loops._loopId-BsuV-Rmf.js +0 -67
- package/.output/public/assets/loops._loopId_.runs._runId-DpK_fzmZ.js +0 -3
- package/.output/public/assets/preload-helper-sAZOZb3G.js +0 -5
- package/.output/public/assets/routes-DxF_s3cD.js +0 -1
- package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +0 -419
- package/.output/server/_libs/@aws-sdk/checksums+[...].mjs +0 -10732
- package/.output/server/_libs/@aws-sdk/client-s3+[...].mjs +0 -9475
- package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +0 -137
- package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +0 -440
- package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +0 -62
- package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +0 -818
- package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +0 -59
- package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +0 -342
- package/.output/server/_libs/aws-crypto__crc32c.mjs +0 -314
- package/.output/server/_libs/aws-sdk__nested-clients.mjs +0 -2671
- package/.output/server/_ssr/SignIn-sHQaBQJC.mjs +0 -53
- package/.output/server/_ssr/artifactFiles-DO43wwXA.mjs +0 -60
- package/.output/server/_ssr/artifacts-Cd7Qx3Qp.mjs +0 -2
- package/.output/server/_ssr/auth-0AamrwHo.mjs +0 -38355
- package/.output/server/_ssr/auth-client-lSMb_Idt.mjs +0 -1070
- package/.output/server/_ssr/bun-sqlite-dialect-BW9W1_Ps-DLIXocA0.mjs +0 -162
- package/.output/server/_ssr/core-RrmWoKne.mjs +0 -5
- package/.output/server/_ssr/d1-sqlite-dialect-BLC8LXE6-BoFMIPr_.mjs +0 -112
- package/.output/server/_ssr/db-BzvMQ2kx.mjs +0 -2
- package/.output/server/_ssr/dist-ClzqkwxD.mjs +0 -342
- package/.output/server/_ssr/factory-ixUjZqJn.mjs +0 -6903
- package/.output/server/_ssr/kysely-adapter-DkZbmKgV.mjs +0 -2
- package/.output/server/_ssr/kysely-migration-tables-JkVUjPF_-bPAX9LR_.mjs +0 -19
- package/.output/server/_ssr/logger-DDjsYB2X.mjs +0 -2
- package/.output/server/_ssr/loopTags-CXx5UdGf.mjs +0 -3356
- package/.output/server/_ssr/node-sqlite-dialect-BbUqnnYv.mjs +0 -162
- package/.output/server/_ssr/router-BlLlhfJe.mjs +0 -543
- package/.output/server/_ssr/routes-DTBltabU.mjs +0 -27
- package/.output/server/_ssr/start-4ifArtKx.mjs +0 -4
- package/.output/server/_ssr/store-vDZ9INSa.mjs +0 -2
- package/.output/server/_ssr/tokens-BHiCElYD.mjs +0 -2
- package/.output/server/drizzle/0001_add_pi_agent.sql +0 -9
- package/.output/server/drizzle/0002_remove_teams.sql +0 -15
- package/.output/server/drizzle/0003_add_loop_tags.sql +0 -5
- package/.output/server/node_modules/tslib/modules/index.js +0 -70
- package/.output/server/node_modules/tslib/modules/package.json +0 -3
- package/.output/server/node_modules/tslib/package.json +0 -47
- package/.output/server/node_modules/tslib/tslib.js +0 -484
- package/.output/server/package.json +0 -9
- package/drizzle/0001_add_pi_agent.sql +0 -9
- package/drizzle/0002_remove_teams.sql +0 -15
- package/drizzle/0003_add_loop_tags.sql +0 -5
- package/scripts/prestart.mjs +0 -66
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { o as __toESM } from "../_runtime.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { J as validateLoopTags, h as CODING_AGENTS } from "./boot-DmpKtb0A.mjs";
|
|
3
3
|
import { g as require_react, h as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
|
|
4
4
|
import { d as useNavigate, u as Link } from "../_libs/@tanstack/react-router+[...].mjs";
|
|
5
|
-
import {
|
|
6
|
-
import { A as tsShort, E as runPulseStyle, M as useFlash, O as sectionHeadCls, S as labelCls, _ as fmt, a as Loading, b as humanBytes, c as btn, d as btnQuiet, g as dur, i as LoadErrorCard, k as selectCls, l as btnDanger, m as dotLabel, n as ErrorBanner, p as dotColor, r as FlashLine, t as ConfirmBar, u as btnPrimary, w as rel, x as inputCls, y as focusRing } from "./actionUi-
|
|
7
|
-
import { a as Timeline,
|
|
8
|
-
import { n as artifactKind, t as Route } from "./artifactKind-
|
|
9
|
-
import { t as
|
|
10
|
-
|
|
11
|
-
import { t as g } from "../_libs/marked.mjs";
|
|
12
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId-CXgw2Rz1.js
|
|
5
|
+
import { _ as runLoop, a as deriveLoopLifecycle, g as pauseLoop, h as patchLoop, i as deleteLoop, l as getLoopDetail, o as getArtifact, p as loadOlderRuns, r as daemonStopSupport, s as getArtifacts, t as DAEMON_UPGRADE_REQUIRED, v as startLoop, y as stopLoop } from "./lifecycleUi-DEjM8Etm.mjs";
|
|
6
|
+
import { A as tsShort, E as runPulseStyle, M as useFlash, O as sectionHeadCls, S as labelCls, _ as fmt, a as Loading, b as humanBytes, c as btn, d as btnQuiet, g as dur, i as LoadErrorCard, k as selectCls, l as btnDanger, m as dotLabel, n as ErrorBanner, p as dotColor, r as FlashLine, t as ConfirmBar, u as btnPrimary, w as rel, x as inputCls, y as focusRing } from "./actionUi-DE-Pb2tv.mjs";
|
|
7
|
+
import { a as Timeline, l as mergeRuns, n as MachinesModal, t as LoopOverview } from "./MachinesModal-CLBZxZkq.mjs";
|
|
8
|
+
import { n as artifactKind, t as Route } from "./artifactKind-a2oxT2wQ.mjs";
|
|
9
|
+
import { t as MarkdownView } from "./MarkdownView-D1J7ImYF.mjs";
|
|
10
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId-DVCvGSEc.js
|
|
13
11
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
14
12
|
var import_jsx_runtime = require_jsx_runtime();
|
|
15
|
-
/** Download URL for one
|
|
16
|
-
*
|
|
13
|
+
/** Download URL for one loop file. Each path segment is encoded independently so
|
|
14
|
+
* the name continues to match the catch-all route. */
|
|
17
15
|
function downloadHref(loopId, path) {
|
|
18
16
|
const encodedPath = path.split("/").map(encodeURIComponent).join("/");
|
|
19
17
|
return `/api/artifact/${encodeURIComponent(loopId)}/${encodedPath}`;
|
|
@@ -22,67 +20,6 @@ function inlineHref(loopId, path) {
|
|
|
22
20
|
return `${downloadHref(loopId, path)}?view=inline`;
|
|
23
21
|
}
|
|
24
22
|
/**
|
|
25
|
-
* Shared markdown → sanitized HTML pipeline: marked (GFM) → DOMPurify (an
|
|
26
|
-
* allowlisted prose subset, NO script/handlers). ONE sanitizer config for every
|
|
27
|
-
* artifact markdown surface so the allowlist cannot drift between viewers.
|
|
28
|
-
* Render the output under
|
|
29
|
-
* the `.artifact-markdown` styles.
|
|
30
|
-
*/
|
|
31
|
-
var MD_SANITIZE = {
|
|
32
|
-
ALLOWED_TAGS: [
|
|
33
|
-
"h1",
|
|
34
|
-
"h2",
|
|
35
|
-
"h3",
|
|
36
|
-
"h4",
|
|
37
|
-
"h5",
|
|
38
|
-
"h6",
|
|
39
|
-
"p",
|
|
40
|
-
"br",
|
|
41
|
-
"hr",
|
|
42
|
-
"strong",
|
|
43
|
-
"b",
|
|
44
|
-
"em",
|
|
45
|
-
"i",
|
|
46
|
-
"del",
|
|
47
|
-
"s",
|
|
48
|
-
"code",
|
|
49
|
-
"pre",
|
|
50
|
-
"blockquote",
|
|
51
|
-
"ul",
|
|
52
|
-
"ol",
|
|
53
|
-
"li",
|
|
54
|
-
"a",
|
|
55
|
-
"span",
|
|
56
|
-
"table",
|
|
57
|
-
"thead",
|
|
58
|
-
"tbody",
|
|
59
|
-
"tr",
|
|
60
|
-
"th",
|
|
61
|
-
"td",
|
|
62
|
-
"img"
|
|
63
|
-
],
|
|
64
|
-
ALLOWED_ATTR: [
|
|
65
|
-
"href",
|
|
66
|
-
"title",
|
|
67
|
-
"target",
|
|
68
|
-
"rel",
|
|
69
|
-
"src",
|
|
70
|
-
"alt"
|
|
71
|
-
]
|
|
72
|
-
};
|
|
73
|
-
function renderMarkdown(content) {
|
|
74
|
-
return purify.sanitize(g.parse(content, {
|
|
75
|
-
async: false,
|
|
76
|
-
gfm: true
|
|
77
|
-
}), MD_SANITIZE);
|
|
78
|
-
}
|
|
79
|
-
function MarkdownView({ content }) {
|
|
80
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
81
|
-
className: "artifact-markdown px-5 py-4",
|
|
82
|
-
dangerouslySetInnerHTML: { __html: (0, import_react.useMemo)(() => renderMarkdown(content), [content]) }
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
23
|
* Shared pieces of the artifact content viewer. The Files panel uses this one
|
|
87
24
|
* dispatch so binary/oversize copy and type-appropriate rendering cannot drift.
|
|
88
25
|
*
|
|
@@ -97,8 +34,8 @@ function MarkdownView({ content }) {
|
|
|
97
34
|
* rides as an image, which does not execute embedded scripts).
|
|
98
35
|
* - markdown → the shared markdown pipeline (Preview) with a raw Source toggle.
|
|
99
36
|
* - text → monospace source.
|
|
100
|
-
* Everything keeps a Download fallback;
|
|
101
|
-
*
|
|
37
|
+
* Everything keeps a Download fallback; a legacy oversize/binary entry has no
|
|
38
|
+
* renderable bytes, so it says so rather than showing an empty pane.
|
|
102
39
|
*/
|
|
103
40
|
function ViewerHead({ path, meta, action }) {
|
|
104
41
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -277,7 +214,6 @@ function ArtifactBody({ loopId, file }) {
|
|
|
277
214
|
kind
|
|
278
215
|
}, file.path);
|
|
279
216
|
}
|
|
280
|
-
var basename = (path) => path.split("/").pop() || path;
|
|
281
217
|
function LoopFilesPanel({ loopId, configuredPaths, running }) {
|
|
282
218
|
const [artifacts, setArtifacts] = (0, import_react.useState)(null);
|
|
283
219
|
const [selected, setSelected] = (0, import_react.useState)(null);
|
|
@@ -310,14 +246,19 @@ function LoopFilesPanel({ loopId, configuredPaths, running }) {
|
|
|
310
246
|
className: "mb-2.5 flex items-end justify-between gap-3 border-b border-hairline pb-1.5",
|
|
311
247
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h2", {
|
|
312
248
|
className: "text-label font-semibold text-secondary",
|
|
313
|
-
children: ["
|
|
249
|
+
children: ["Files", artifacts ? ` (${files.length})` : ""]
|
|
314
250
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
315
251
|
className: "text-caption font-medium text-disabled",
|
|
316
|
-
children: [
|
|
252
|
+
children: [
|
|
253
|
+
"MEMORY.md + ",
|
|
254
|
+
configuredPaths.length,
|
|
255
|
+
" artifact",
|
|
256
|
+
configuredPaths.length === 1 ? "" : "s"
|
|
257
|
+
]
|
|
317
258
|
})]
|
|
318
259
|
}), files.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
319
260
|
className: "rounded-card border border-hairline bg-surface px-5 py-10 text-center text-body text-disabled shadow-card",
|
|
320
|
-
children: artifacts == null ? "Loading…" :
|
|
261
|
+
children: artifacts == null ? "Loading…" : "No loop file has been written yet. Runs create MEMORY.md and any configured artifacts."
|
|
321
262
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
322
263
|
className: "grid h-[min(600px,68vh)] grid-cols-1 overflow-hidden rounded-card border border-hairline bg-surface shadow-card sm:grid-cols-[210px_1fr]",
|
|
323
264
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", {
|
|
@@ -330,17 +271,10 @@ function LoopFilesPanel({ loopId, configuredPaths, running }) {
|
|
|
330
271
|
type: "button",
|
|
331
272
|
onClick: () => setSelected(file.path),
|
|
332
273
|
className: `flex w-full items-center border-l-2 px-3 py-2 text-left transition-colors ${activeRow ? "border-display bg-raised" : "border-transparent hover:bg-raised/60"}`,
|
|
333
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
334
|
-
className:
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
title: file.path,
|
|
338
|
-
children: basename(file.path)
|
|
339
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
340
|
-
className: "block truncate font-mono text-micro text-disabled",
|
|
341
|
-
title: file.path,
|
|
342
|
-
children: file.path
|
|
343
|
-
})]
|
|
274
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
275
|
+
className: `block min-w-0 flex-1 truncate font-mono text-label ${activeRow ? "text-display" : "text-primary"}`,
|
|
276
|
+
title: file.path,
|
|
277
|
+
children: file.path
|
|
344
278
|
})
|
|
345
279
|
}) }, file.path);
|
|
346
280
|
})
|
|
@@ -349,7 +283,7 @@ function LoopFilesPanel({ loopId, configuredPaths, running }) {
|
|
|
349
283
|
className: "min-w-0 overflow-y-auto",
|
|
350
284
|
children: active && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ViewerHead, {
|
|
351
285
|
path: active.path,
|
|
352
|
-
meta: [active.size != null ? humanBytes(active.size) : "", `
|
|
286
|
+
meta: [active.size != null ? humanBytes(active.size) : "", `updated ${fmt(active.updatedAt)}`].filter(Boolean).join(" · ")
|
|
353
287
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactBody, {
|
|
354
288
|
loopId,
|
|
355
289
|
file: active
|
|
@@ -529,7 +463,7 @@ var LoopForm = (0, import_react.forwardRef)(function LoopForm({ initial }, ref)
|
|
|
529
463
|
noChange: form.noChange,
|
|
530
464
|
block: form.block
|
|
531
465
|
},
|
|
532
|
-
artifacts: form.artifacts.split(/\r?\n/).filter((
|
|
466
|
+
artifacts: form.artifacts.split(/\r?\n/).filter((name) => name.length > 0)
|
|
533
467
|
};
|
|
534
468
|
} }));
|
|
535
469
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -757,10 +691,10 @@ var LoopForm = (0, import_react.forwardRef)(function LoopForm({ initial }, ref)
|
|
|
757
691
|
}),
|
|
758
692
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
|
|
759
693
|
title: "Artifacts",
|
|
760
|
-
hint: "Optional
|
|
694
|
+
hint: "Optional .md or .html file names (up to 4, 2 MB each) that runs update and the dashboard renders. One name per line. Every loop also has MEMORY.md."
|
|
761
695
|
}),
|
|
762
696
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextArea, {
|
|
763
|
-
label: "Artifact
|
|
697
|
+
label: "Artifact files",
|
|
764
698
|
value: form.artifacts,
|
|
765
699
|
onChange: (value) => set("artifacts", value),
|
|
766
700
|
rows: 6,
|
|
@@ -1034,7 +968,7 @@ function LoopDetailView({ id }) {
|
|
|
1034
968
|
className: "mt-3",
|
|
1035
969
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConfirmBar, {
|
|
1036
970
|
prompt: "Stop this loop and delete its server data?",
|
|
1037
|
-
note: "This stops the loop and deletes server history and
|
|
971
|
+
note: "This stops the loop and deletes server history, the loop memory, and artifacts. Files in the working directory are not deleted. If the machine is unreachable, its local process may continue running.",
|
|
1038
972
|
cta: "Delete",
|
|
1039
973
|
danger: true,
|
|
1040
974
|
busy,
|
|
@@ -1145,13 +1079,13 @@ function LoopDetailView({ id }) {
|
|
|
1145
1079
|
})
|
|
1146
1080
|
}),
|
|
1147
1081
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Config, {
|
|
1148
|
-
label: "
|
|
1082
|
+
label: "Artifacts",
|
|
1149
1083
|
children: loop.artifacts.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
1150
1084
|
className: "space-y-1",
|
|
1151
|
-
children: loop.artifacts.map((
|
|
1085
|
+
children: loop.artifacts.map((name) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
1152
1086
|
className: "break-all font-mono",
|
|
1153
|
-
children:
|
|
1154
|
-
}) },
|
|
1087
|
+
children: name
|
|
1088
|
+
}) }, name))
|
|
1155
1089
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
1156
1090
|
className: "text-disabled",
|
|
1157
1091
|
children: "None"
|
|
@@ -1206,7 +1140,7 @@ function EditHead({ name, onBack }) {
|
|
|
1206
1140
|
}),
|
|
1207
1141
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
1208
1142
|
className: "mt-1.5 text-meta text-secondary",
|
|
1209
|
-
children: "Edit tags, schedule, execution settings, prompt, status definitions, and
|
|
1143
|
+
children: "Edit tags, schedule, execution settings, prompt, status definitions, and artifact files."
|
|
1210
1144
|
})
|
|
1211
1145
|
] });
|
|
1212
1146
|
}
|
|
@@ -1286,26 +1220,12 @@ function RunsSection({ loopId, summary, runs, older, onMore, onPickRun }) {
|
|
|
1286
1220
|
}
|
|
1287
1221
|
/**
|
|
1288
1222
|
* Loop detail page — `/loops/$loopId`: a loop header and action toolbar, the
|
|
1289
|
-
*
|
|
1290
|
-
*
|
|
1291
|
-
* like the dashboard loader). Run rows link on to `/loops/$loopId/runs/$runId`.
|
|
1292
|
-
*
|
|
1293
|
-
* Auth-gated exactly like the dashboard (`/`): Better Auth's session hook keeps a
|
|
1294
|
-
* logged-out or expired deep link from mounting the ownership-scoped data view.
|
|
1223
|
+
* loop Files panel, and the runs timeline. The view owns its own data + self-poll.
|
|
1224
|
+
* Run rows link on to `/loops/$loopId/runs/$runId`.
|
|
1295
1225
|
*/
|
|
1296
1226
|
function LoopDetailPage() {
|
|
1297
1227
|
const { loopId } = Route.useParams();
|
|
1298
|
-
|
|
1299
|
-
const { data: session, isPending } = useSession();
|
|
1300
|
-
if (auth.enabled && isPending) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("main", {
|
|
1301
|
-
className: "mx-auto max-w-[1360px] px-8 pt-10",
|
|
1302
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Loading, {})
|
|
1303
|
-
});
|
|
1304
|
-
if (auth.enabled && !session) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SignIn, { callbackURL: `/loops/${loopId}` });
|
|
1305
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [!auth.enabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
1306
|
-
className: "mx-auto max-w-[1360px] px-8 pt-6",
|
|
1307
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OpenModeWarning, {})
|
|
1308
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoopDetailView, { id: loopId })] });
|
|
1228
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoopDetailView, { id: loopId });
|
|
1309
1229
|
}
|
|
1310
1230
|
//#endregion
|
|
1311
1231
|
export { LoopDetailPage as component };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { o as __toESM } from "../_runtime.mjs";
|
|
2
2
|
import { g as require_react, h as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
|
|
3
3
|
import { u as Link } from "../_libs/@tanstack/react-router+[...].mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { E as runPulseStyle, O as sectionHeadCls, _ as fmt, a as Loading, b as humanBytes, c as btn, g as dur, i as LoadErrorCard, l as btnDanger, o as Pill, s as StatusPill, v as fnum } from "./actionUi-
|
|
6
|
-
import { t as
|
|
7
|
-
import { t as Route } from "./loops._loopId_.runs._runId-
|
|
8
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId_.runs._runId-
|
|
4
|
+
import { b as stopRun, l as getLoopDetail, p as loadOlderRuns, u as getRunDiff } from "./lifecycleUi-DEjM8Etm.mjs";
|
|
5
|
+
import { E as runPulseStyle, O as sectionHeadCls, _ as fmt, a as Loading, b as humanBytes, c as btn, g as dur, i as LoadErrorCard, l as btnDanger, o as Pill, s as StatusPill, v as fnum } from "./actionUi-DE-Pb2tv.mjs";
|
|
6
|
+
import { t as MarkdownView } from "./MarkdownView-D1J7ImYF.mjs";
|
|
7
|
+
import { t as Route } from "./loops._loopId_.runs._runId-Dr6E-FA5.mjs";
|
|
8
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId_.runs._runId-BXbTfLlC.js
|
|
9
9
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
10
10
|
var import_jsx_runtime = require_jsx_runtime();
|
|
11
11
|
/**
|
|
@@ -463,8 +463,8 @@ function RunDetailView({ loopId, runId }) {
|
|
|
463
463
|
type: "button",
|
|
464
464
|
onClick: onStop,
|
|
465
465
|
className: btnDanger,
|
|
466
|
-
disabled: run.phase === "running" && detail.machine.daemonProtocol !==
|
|
467
|
-
title: run.phase === "running" && detail.machine.daemonProtocol !==
|
|
466
|
+
disabled: run.phase === "running" && detail.machine.daemonProtocol !== 5,
|
|
467
|
+
title: run.phase === "running" && detail.machine.daemonProtocol !== 5 ? "Daemon upgrade required to stop a running process. Run `npm install -g @kky42/pievo@latest`, then `pievo daemon restart`." : void 0,
|
|
468
468
|
children: "Stop run"
|
|
469
469
|
})]
|
|
470
470
|
})]
|
|
@@ -528,15 +528,25 @@ function RunDetailView({ loopId, runId }) {
|
|
|
528
528
|
]
|
|
529
529
|
})
|
|
530
530
|
}),
|
|
531
|
+
run.fileNotices && run.fileNotices.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
532
|
+
label: "Loop files not kept",
|
|
533
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
534
|
+
className: "list-disc space-y-1.5 pl-5 text-body text-primary",
|
|
535
|
+
children: run.fileNotices.map((notice) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
|
|
536
|
+
className: "break-words",
|
|
537
|
+
children: notice
|
|
538
|
+
}, notice))
|
|
539
|
+
})
|
|
540
|
+
}),
|
|
531
541
|
run.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
532
542
|
label: "Report",
|
|
533
543
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
534
|
-
className: "
|
|
535
|
-
children: run.message
|
|
544
|
+
className: "break-words rounded-control border border-hairline bg-raised text-body leading-relaxed text-primary",
|
|
545
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownView, { content: run.message })
|
|
536
546
|
})
|
|
537
547
|
}),
|
|
538
548
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Changes, { run }),
|
|
539
|
-
run.finalText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
549
|
+
run.finalText && !run.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
540
550
|
label: "Final output",
|
|
541
551
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
542
552
|
className: "whitespace-pre-wrap break-words text-body text-primary",
|
|
@@ -593,41 +603,27 @@ function RunDetailView({ loopId, runId }) {
|
|
|
593
603
|
* `_` on the `$loopId` segment opts it out of the loop page's component so the run
|
|
594
604
|
* gets its own full surface, deep-linkable + browser-back friendly) rather than a
|
|
595
605
|
* modal or an inline panel. It resolves the run from the loop's detail payload
|
|
596
|
-
* (reusing getLoopDetail) and the existing
|
|
597
|
-
*
|
|
598
|
-
* Auth-gated like the dashboard (`/`) so Better Auth's session hook keeps a
|
|
599
|
-
* logged-out or expired deep link from mounting the run view.
|
|
606
|
+
* (reusing getLoopDetail) and the existing loop-file diff.
|
|
600
607
|
*/
|
|
601
608
|
function RunDetailPage() {
|
|
602
609
|
const { loopId, runId } = Route.useParams();
|
|
603
|
-
const { auth } = Route.useLoaderData() ?? { auth: { enabled: false } };
|
|
604
|
-
const { data: session, isPending } = useSession();
|
|
605
|
-
if (auth.enabled && isPending) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("main", {
|
|
606
|
-
className: "mx-auto max-w-[1360px] px-8 pt-10",
|
|
607
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Loading, {})
|
|
608
|
-
});
|
|
609
|
-
if (auth.enabled && !session) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SignIn, { callbackURL: `/loops/${loopId}/runs/${runId}` });
|
|
610
610
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", {
|
|
611
611
|
className: "mx-auto max-w-[1360px] px-8 pb-24 pt-6",
|
|
612
|
-
children: [
|
|
613
|
-
|
|
614
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
children:
|
|
621
|
-
|
|
622
|
-
children: "←"
|
|
623
|
-
}), " Back to loop"]
|
|
624
|
-
})
|
|
625
|
-
}),
|
|
626
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunDetailView, {
|
|
627
|
-
loopId,
|
|
628
|
-
runId
|
|
612
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
613
|
+
className: "mb-5",
|
|
614
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
|
|
615
|
+
to: "/loops/$loopId",
|
|
616
|
+
params: { loopId },
|
|
617
|
+
className: "inline-flex items-center gap-1.5 text-label font-medium text-secondary transition-colors hover:text-display",
|
|
618
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
619
|
+
"aria-hidden": true,
|
|
620
|
+
children: "←"
|
|
621
|
+
}), " Back to loop"]
|
|
629
622
|
})
|
|
630
|
-
|
|
623
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunDetailView, {
|
|
624
|
+
loopId,
|
|
625
|
+
runId
|
|
626
|
+
})]
|
|
631
627
|
});
|
|
632
628
|
}
|
|
633
629
|
//#endregion
|
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
import { c as createFileRoute, s as lazyRouteComponent } from "../_libs/@tanstack/react-router+[...].mjs";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var $$splitComponentImporter = () => import("./loops._loopId_.runs._runId-SASSqOfy.mjs");
|
|
2
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId_.runs._runId-Dr6E-FA5.js
|
|
3
|
+
var $$splitComponentImporter = () => import("./loops._loopId_.runs._runId-BXbTfLlC.mjs");
|
|
5
4
|
/**
|
|
6
5
|
* Run detail PAGE — `/loops/$loopId/runs/$runId`. A standalone page (the trailing
|
|
7
6
|
* `_` on the `$loopId` segment opts it out of the loop page's component so the run
|
|
8
7
|
* gets its own full surface, deep-linkable + browser-back friendly) rather than a
|
|
9
8
|
* modal or an inline panel. It resolves the run from the loop's detail payload
|
|
10
|
-
* (reusing getLoopDetail) and the existing
|
|
11
|
-
*
|
|
12
|
-
* Auth-gated like the dashboard (`/`) so Better Auth's session hook keeps a
|
|
13
|
-
* logged-out or expired deep link from mounting the run view.
|
|
9
|
+
* (reusing getLoopDetail) and the existing loop-file diff.
|
|
14
10
|
*/
|
|
15
11
|
var Route = createFileRoute("/loops/$loopId_/runs/$runId")({
|
|
16
12
|
ssr: false,
|
|
17
|
-
loader: async () => ({ auth: await getAuthState() }),
|
|
18
13
|
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
19
14
|
});
|
|
20
15
|
//#endregion
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { requestScope } from "./auth-0AamrwHo.mjs";
|
|
4
|
-
import { n as createServerFn } from "./ssr.mjs";
|
|
1
|
+
import { H as sha256, I as mintDeviceToken, N as loopsForMachine, P as machineIdFromToken, S as getMachine, _ as createMachine$1, k as listMachines$1, o as daemonNeedsUpdate, q as updateMachine, s as ensureServer, t as MIN_DAEMON_VERSION, y as forceDeleteMachine } from "./boot-DmpKtb0A.mjs";
|
|
2
|
+
import { r as createServerFn } from "./ssr.mjs";
|
|
5
3
|
import { t as createServerRpc } from "./createServerRpc-BD8Xn_0_.mjs";
|
|
6
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/machineFns-
|
|
7
|
-
/** Open mode sees every machine; auth mode sees only the signed-in owner's rows. */
|
|
8
|
-
function machineInScope(machine, scope) {
|
|
9
|
-
return !scope.enforce || !!scope.userId && machine.userId === scope.userId;
|
|
10
|
-
}
|
|
11
|
-
/** A device token fully impersonates its machine, so auth mode keeps it owner-only. */
|
|
12
|
-
function tokenVisibleTo(machine, scope) {
|
|
13
|
-
return machineInScope(machine, scope);
|
|
14
|
-
}
|
|
4
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/machineFns-DLRHgDdS.js
|
|
15
5
|
/**
|
|
16
6
|
* Latest published @kky42/pievo version — a cached, fail-silent lookup of the
|
|
17
7
|
* npm dist-tag `latest`, so the web can tell a user their daemon is outdated and
|
|
@@ -93,21 +83,10 @@ var LatestDaemonVersion = class {
|
|
|
93
83
|
};
|
|
94
84
|
var latestDaemonVersion = new LatestDaemonVersion();
|
|
95
85
|
/**
|
|
96
|
-
* Machine-management server functions.
|
|
97
|
-
*
|
|
98
|
-
* administration, including reconnect tokens.
|
|
86
|
+
* Machine-management server functions. Pievo is single-user: anyone who can
|
|
87
|
+
* reach the dashboard administers every machine, including reconnect tokens.
|
|
99
88
|
*/
|
|
100
|
-
|
|
101
|
-
async function scopedMachine(id) {
|
|
102
|
-
const scope = await requestScope();
|
|
103
|
-
if (scope.enforce && !scope.userId) return { scope };
|
|
104
|
-
const candidate = await getMachine(id);
|
|
105
|
-
return {
|
|
106
|
-
scope,
|
|
107
|
-
machine: candidate && machineInScope(candidate, scope) ? candidate : void 0
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
async function toSummary(machine, scope) {
|
|
89
|
+
async function toSummary(machine) {
|
|
111
90
|
return {
|
|
112
91
|
id: machine.id,
|
|
113
92
|
name: machine.name,
|
|
@@ -121,7 +100,7 @@ async function toSummary(machine, scope) {
|
|
|
121
100
|
latestDaemonVersion: latestDaemonVersion.get(),
|
|
122
101
|
needsUpdate: daemonNeedsUpdate(machine.daemonVersion),
|
|
123
102
|
requiredDaemonVersion: MIN_DAEMON_VERSION,
|
|
124
|
-
token:
|
|
103
|
+
token: machine.token ?? null,
|
|
125
104
|
loopCount: (await loopsForMachine(machine.id)).length
|
|
126
105
|
};
|
|
127
106
|
}
|
|
@@ -132,10 +111,8 @@ var listMachines_createServerFn_handler = createServerRpc({
|
|
|
132
111
|
}, (opts) => listMachines.__executeServer(opts));
|
|
133
112
|
var listMachines = createServerFn({ method: "GET" }).handler(listMachines_createServerFn_handler, async () => {
|
|
134
113
|
await ensureServer();
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
const machines = scope.enforce ? await listMachinesForUser(scope.userId) : await listMachines$1();
|
|
138
|
-
return Promise.all(machines.filter((machine) => machine.name.trim()).map((machine) => toSummary(machine, scope)));
|
|
114
|
+
const machines = await listMachines$1();
|
|
115
|
+
return Promise.all(machines.filter((machine) => machine.name.trim()).map(toSummary));
|
|
139
116
|
});
|
|
140
117
|
var createMachine_createServerFn_handler = createServerRpc({
|
|
141
118
|
id: "ed679b4e1e05e903a5d4ba4a70d9b9d883991ab22ed59b4d2d69078941818415",
|
|
@@ -144,13 +121,10 @@ var createMachine_createServerFn_handler = createServerRpc({
|
|
|
144
121
|
}, (opts) => createMachine.__executeServer(opts));
|
|
145
122
|
var createMachine = createServerFn({ method: "POST" }).handler(createMachine_createServerFn_handler, async () => {
|
|
146
123
|
await ensureServer();
|
|
147
|
-
const scope = await requestScope();
|
|
148
|
-
if (scope.enforce && !scope.userId) return { error: "not signed in" };
|
|
149
124
|
const token = mintDeviceToken();
|
|
150
125
|
const id = machineIdFromToken(token);
|
|
151
126
|
await createMachine$1({
|
|
152
127
|
id,
|
|
153
|
-
userId: scope.userId ?? "shared",
|
|
154
128
|
name: "",
|
|
155
129
|
tokenHash: sha256(token),
|
|
156
130
|
token,
|
|
@@ -168,8 +142,8 @@ var machineStatus_createServerFn_handler = createServerRpc({
|
|
|
168
142
|
}, (opts) => machineStatus.__executeServer(opts));
|
|
169
143
|
var machineStatus = createServerFn({ method: "GET" }).validator((id) => id).handler(machineStatus_createServerFn_handler, async ({ data: id }) => {
|
|
170
144
|
await ensureServer();
|
|
171
|
-
const
|
|
172
|
-
return machine ? toSummary(machine
|
|
145
|
+
const machine = await getMachine(id);
|
|
146
|
+
return machine ? toSummary(machine) : null;
|
|
173
147
|
});
|
|
174
148
|
var finalizeMachine_createServerFn_handler = createServerRpc({
|
|
175
149
|
id: "27d7eba0b6a2257949392fdd56057275a5c5366484ae01faf3b5897a225ecd83",
|
|
@@ -180,8 +154,6 @@ var finalizeMachine = createServerFn({ method: "POST" }).validator((data) => dat
|
|
|
180
154
|
await ensureServer();
|
|
181
155
|
const name = data.name?.trim();
|
|
182
156
|
if (!name) return { ok: false };
|
|
183
|
-
const { machine } = await scopedMachine(data.id);
|
|
184
|
-
if (!machine) return { ok: false };
|
|
185
157
|
return { ok: !!await updateMachine(data.id, { name }) };
|
|
186
158
|
});
|
|
187
159
|
var deleteMachine_createServerFn_handler = createServerRpc({
|
|
@@ -191,17 +163,8 @@ var deleteMachine_createServerFn_handler = createServerRpc({
|
|
|
191
163
|
}, (opts) => deleteMachine.__executeServer(opts));
|
|
192
164
|
var deleteMachine = createServerFn({ method: "POST" }).validator((id) => id).handler(deleteMachine_createServerFn_handler, async ({ data: id }) => {
|
|
193
165
|
const { scheduler } = await ensureServer();
|
|
194
|
-
const
|
|
195
|
-
if (
|
|
196
|
-
ok: false,
|
|
197
|
-
error: "unauthorized"
|
|
198
|
-
};
|
|
199
|
-
if (!machine) return {
|
|
200
|
-
ok: false,
|
|
201
|
-
error: "machine not found"
|
|
202
|
-
};
|
|
203
|
-
const deleted = scope.enforce ? await forceDeleteMachine(id, scope.userId) : await forceDeleteMachine(id);
|
|
204
|
-
if (deleted.state === "forbidden" || deleted.state === "not-found") return {
|
|
166
|
+
const deleted = await forceDeleteMachine(id);
|
|
167
|
+
if (deleted.state === "not-found") return {
|
|
205
168
|
ok: false,
|
|
206
169
|
error: "machine not found"
|
|
207
170
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/networkAccess-CIlK3ION.js
|
|
3
|
+
/**
|
|
4
|
+
* Pievo has no login, so the network is the access boundary: only this
|
|
5
|
+
* machine, private LAN ranges, and Tailscale peers may reach any route.
|
|
6
|
+
* Anyone who passes this check can run prompts on every connected machine.
|
|
7
|
+
* Requests proxied by `tailscale serve` arrive from loopback.
|
|
8
|
+
*
|
|
9
|
+
* IPv4: loopback 127/8, RFC 1918 (10/8, 172.16/12, 192.168/16), link-local
|
|
10
|
+
* 169.254/16, and CGNAT 100.64/10 (Tailscale addresses). IPv6: loopback,
|
|
11
|
+
* link-local fe80::/10, and unique-local fc00::/7 (includes Tailscale's
|
|
12
|
+
* fd7a:115c:a1e0::/48). IPv4-mapped IPv6 is checked as IPv4.
|
|
13
|
+
*/
|
|
14
|
+
function isTrustedPeer(address) {
|
|
15
|
+
if (!address) return false;
|
|
16
|
+
const ip = address.toLowerCase().replace(/^::ffff:(?=\d+\.\d+\.\d+\.\d+$)/, "").split("%")[0];
|
|
17
|
+
const family = isIP(ip);
|
|
18
|
+
if (family === 4) {
|
|
19
|
+
const [a, b] = ip.split(".").map(Number);
|
|
20
|
+
return a === 127 || a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 169 && b === 254 || a === 100 && b >= 64 && b <= 127;
|
|
21
|
+
}
|
|
22
|
+
if (family === 6) {
|
|
23
|
+
if (ip === "::1") return true;
|
|
24
|
+
const first = parseInt(ip.split(":")[0] || "0", 16);
|
|
25
|
+
return (first & 65472) === 65152 || (first & 65024) === 64512;
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { isTrustedPeer };
|