@kky42/pievo-server 3.0.0 → 4.2.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-C9-AzIkl.js +66 -0
- package/.output/public/assets/{actionUi-BZrLpgHT.js → actionUi-D47jwMfh.js} +1 -1
- package/.output/public/assets/app-C5xfpeJe.css +2 -0
- package/.output/public/assets/index-BgNjFXWE.js +10 -0
- package/.output/public/assets/loops._loopId-Bo63FXPQ.js +2 -0
- package/.output/public/assets/loops._loopId_.runs._runId-DW2HPjtj.js +3 -0
- package/.output/public/assets/{preload-helper-hRTYB_ju.js → preload-helper-CbYqBpY9.js} +2 -2
- package/.output/public/assets/routes-C88oSApK.js +1 -0
- package/.output/public/assets/routes-CTCh8xYm.js +1 -0
- package/.output/server/_ssr/{MachinesModal-CmVMec6B.mjs → MachinesModal-DwHy2cis.mjs} +44 -25
- package/.output/server/_ssr/MarkdownView-BOe75tli.mjs +67 -0
- package/.output/server/_ssr/{actionUi-DE-Pb2tv.mjs → actionUi-CszQXDSN.mjs} +20 -2
- package/.output/server/_ssr/artifactFiles-DJiK99sF.mjs +67 -0
- package/.output/server/_ssr/{artifactKind-DqpmtxDU.mjs → artifactKind-DYMU0q3N.mjs} +2 -7
- package/.output/server/_ssr/{boot-CYRi-wez.mjs → boot-CecCDRoH.mjs} +950 -968
- package/.output/server/_ssr/{lifecycleUi-BsbUsi5K.mjs → lifecycleUi-Bd7_sthp.mjs} +12 -19
- package/.output/server/_ssr/{loopApi-Bez1rHV0.mjs → loopApi-uEiBQ5YX.mjs} +17 -23
- package/.output/server/_ssr/{loopProjection-esCjyZJg.mjs → loopProjection-Bo54jjGd.mjs} +5 -3
- package/.output/server/_ssr/{loops._loopId-KUezNY69.mjs → loops._loopId-c1oRP7cr.mjs} +37 -117
- package/.output/server/_ssr/{loops._loopId_.runs._runId-DOkUEesG.mjs → loops._loopId_.runs._runId-Dl0SwOlC.mjs} +43 -23
- package/.output/server/_ssr/loops._loopId_.runs._runId-czMVvNsk.mjs +11 -0
- package/.output/server/_ssr/{machineFns-CniGcY8s.mjs → machineFns-aw9xe5oz.mjs} +6 -20
- package/.output/server/_ssr/{router-BFIH2UAE.mjs → router-3OQ849sN.mjs} +96 -112
- package/.output/server/_ssr/{routes-BSVBANI3.mjs → routes-CL4y6AEv.mjs} +2 -2
- package/.output/server/_ssr/{routes-DnE7XDe_.mjs → routes-CT5IdoiP.mjs} +6 -6
- package/.output/server/_ssr/{routes-ngpX7h8D.mjs → routes-nU2PDK3W.mjs} +2 -2
- package/.output/server/_ssr/ssr.mjs +22 -22
- package/.output/server/{_tanstack-start-manifest_v-DnwAupbZ.mjs → _tanstack-start-manifest_v-_nMS2ozp.mjs} +9 -10
- package/.output/server/drizzle/0001_loop_files.sql +9 -0
- package/.output/server/drizzle/0002_run_attention.sql +1 -0
- package/.output/server/drizzle/meta/_journal.json +15 -1
- package/.output/server/index.mjs +52 -45
- package/drizzle/0001_loop_files.sql +9 -0
- package/drizzle/0002_run_attention.sql +1 -0
- package/drizzle/meta/_journal.json +15 -1
- package/package.json +1 -1
- package/.output/public/assets/app-DXLuQNb9.css +0 -2
- package/.output/public/assets/index-Di_wpAtL.js +0 -10
- package/.output/public/assets/loops._loopId-X3ClNPMY.js +0 -67
- package/.output/public/assets/loops._loopId_.runs._runId-ByU2BSyF.js +0 -3
- package/.output/public/assets/routes-BIOJZsig.js +0 -1
- package/.output/public/assets/routes-K8D5uBiV.js +0 -1
- package/.output/server/_ssr/artifactFiles-Di1xDKvX.mjs +0 -57
- package/.output/server/_ssr/loops._loopId_.runs._runId-BFP9oMrp.mjs +0 -16
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as getServerFnById, r as createServerFn, t as TSS_SERVER_FUNCTION } from "./ssr.mjs";
|
|
2
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/lifecycleUi-
|
|
2
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/lifecycleUi-Bd7_sthp.js
|
|
3
3
|
var createSsrRpc = (functionId) => {
|
|
4
4
|
const url = "/_serverFn/" + functionId;
|
|
5
5
|
const serverFnMeta = { id: functionId };
|
|
@@ -16,27 +16,20 @@ var createSsrRpc = (functionId) => {
|
|
|
16
16
|
* Server functions backing the dashboard. They run server-side (createServerFn
|
|
17
17
|
* → RPC) and call the IN-PROCESS scheduler + store directly — the scheduler
|
|
18
18
|
* lives in this same TanStack process (booted on first call via ensureServer).
|
|
19
|
-
* The machine-facing poll, CLI, report, and
|
|
20
|
-
*
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Client config. `pievoCli` is the CLI invocation prefix the skill + connect
|
|
24
|
-
* dialog use for every verb (`daemon start`, `new`, …) — defaults to the globally
|
|
25
|
-
* installed `pievo`. Set PIEVO_CLI locally to a runnable command that points at the in-repo
|
|
26
|
-
* daemon, e.g. `tsx /abs/packages/daemon/src/cli.ts` or
|
|
27
|
-
* `node /abs/packages/daemon/dist/cli.js`, so loops created from THIS server tell
|
|
28
|
-
* Claude Code to run your local code instead of the registry build.
|
|
19
|
+
* The machine-facing poll, CLI, report, and run-file endpoints are sibling server
|
|
20
|
+
* routes in this same process, so one process owns the single scheduler.
|
|
29
21
|
*/
|
|
22
|
+
/** `pievoCli` prefixes every command the dashboard shows. PIEVO_CLI points it at an
|
|
23
|
+
* in-repo daemon (e.g. `node /abs/packages/daemon/dist/cli.js`) so loops created
|
|
24
|
+
* from this server run local code instead of the registry build. */
|
|
30
25
|
var getConfig = createServerFn({ method: "GET" }).handler(createSsrRpc("cbb6a1b09b309459bbba3dc3851ae85fc468658b3cda77e22b6c6f3e28b65af4"));
|
|
31
|
-
/** GET — visible loops as compact summaries, most recently run first. */
|
|
32
26
|
var listLoops = createServerFn({ method: "GET" }).handler(createSsrRpc("23e290b2b7483ceea6fe669024c35b12c2c4ddd76649f6fab21c958ceda02940"));
|
|
33
27
|
var getLoopDetail = createServerFn({ method: "GET" }).validator((id) => id).handler(createSsrRpc("b050455aacc84dd2a2c9a45517826ad10f91d8f1545e87cc7015784cc7116a97"));
|
|
34
28
|
var loadOlderRuns = createServerFn({ method: "GET" }).validator((d) => d).handler(createSsrRpc("85fdf73d4fee43aed762f93c5d47d33200fbff39e2d082647dc921f610d32698"));
|
|
35
29
|
var getArtifacts = createServerFn({ method: "GET" }).validator((d) => d).handler(createSsrRpc("b18bbec3d06dfc77714e1e527dfb9172fd7575a64a6c0d6e73ba6dc658dccf0d"));
|
|
36
30
|
var getArtifact = createServerFn({ method: "GET" }).validator((d) => d).handler(createSsrRpc("ed10d5fe79208e5e0e4e18e4a17b18d7f7db4dd16204c00c3ac90c4644668841"));
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
* with no snapshot return `hasSnapshot: false` for the degrade copy. */
|
|
31
|
+
/** A run's per-file diff against the previous run, computed at read time. Runs
|
|
32
|
+
* without a snapshot return `hasSnapshot: false`. */
|
|
40
33
|
var getRunDiff = createServerFn({ method: "GET" }).validator((d) => d).handler(createSsrRpc("08c28b892712a1b491b120b74c7dcb81761988d31ccea60216d1807b73c1182c"));
|
|
41
34
|
var patchLoop = createServerFn({ method: "POST" }).validator((d) => d).handler(createSsrRpc("9befe6b8d67ccbbd7aa9b538bde2a161a9894761c8936761a9503fda1a88c0fc"));
|
|
42
35
|
/** Dedicated lifecycle operations. Dashboard callers never synthesize these
|
|
@@ -78,11 +71,11 @@ function lifecyclePresentation(loop) {
|
|
|
78
71
|
};
|
|
79
72
|
if (loop.pauseCause?.kind === "blocked") return {
|
|
80
73
|
label: "Paused · blocked",
|
|
81
|
-
tone: "
|
|
74
|
+
tone: "accent"
|
|
82
75
|
};
|
|
83
76
|
if (loop.pauseCause?.kind === "failure-streak") return {
|
|
84
77
|
label: "Paused · failure streak",
|
|
85
|
-
tone: "
|
|
78
|
+
tone: "accent"
|
|
86
79
|
};
|
|
87
80
|
if (loop.pauseCause?.kind === "owner") return {
|
|
88
81
|
label: "Paused · owner",
|
|
@@ -94,9 +87,9 @@ function lifecyclePresentation(loop) {
|
|
|
94
87
|
};
|
|
95
88
|
}
|
|
96
89
|
function daemonStopSupport(protocol) {
|
|
97
|
-
return protocol ===
|
|
90
|
+
return protocol === 5 ? {
|
|
98
91
|
supported: true,
|
|
99
|
-
label: `Daemon protocol
|
|
92
|
+
label: `Daemon protocol 5 · Stop supported`
|
|
100
93
|
} : {
|
|
101
94
|
supported: false,
|
|
102
95
|
label: `Daemon protocol ${protocol ?? "unknown"} · upgrade required`
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as toRunSummaries, i as toLoopSummaries, r as toLoopDetail, t as sortLoopSummariesByRecentRun } from "./loopProjection-
|
|
1
|
+
import { C as getRun, G as stopLoop$1, H as requestRunCancel, I as machinePresence, K as tryDeleteLoop, O as listLoops$1, R as pauseLoop$1, S as getMachine, T as hasRunningRun, V as requestDeleteLoop, W as startLoop$1, j as listRunsBefore, k as listMachines, m as validateLoopEdit, q as updateLoop, s as ensureServer, v as forceDeleteLoop, x as getLoop } from "./boot-CecCDRoH.mjs";
|
|
2
|
+
import { a as toRunSummaries, i as toLoopSummaries, r as toLoopDetail, t as sortLoopSummariesByRecentRun } from "./loopProjection-Bo54jjGd.mjs";
|
|
3
3
|
import { r as createServerFn } from "./ssr.mjs";
|
|
4
4
|
import { t as createServerRpc } from "./createServerRpc-BD8Xn_0_.mjs";
|
|
5
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/loopApi-
|
|
5
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loopApi-uEiBQ5YX.js
|
|
6
6
|
/**
|
|
7
7
|
* Server functions backing the dashboard. They run server-side (createServerFn
|
|
8
8
|
* → RPC) and call the IN-PROCESS scheduler + store directly — the scheduler
|
|
9
9
|
* lives in this same TanStack process (booted on first call via ensureServer).
|
|
10
|
-
* The machine-facing poll, CLI, report, and
|
|
11
|
-
*
|
|
10
|
+
* The machine-facing poll, CLI, report, and run-file endpoints are sibling server
|
|
11
|
+
* routes in this same process, so one process owns the single scheduler.
|
|
12
12
|
*/
|
|
13
13
|
function backend() {
|
|
14
14
|
return ensureServer();
|
|
@@ -17,14 +17,9 @@ async function findLoop(id) {
|
|
|
17
17
|
const loop = await getLoop(id);
|
|
18
18
|
return loop ? { loop } : void 0;
|
|
19
19
|
}
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* installed `pievo`. Set PIEVO_CLI locally to a runnable command that points at the in-repo
|
|
24
|
-
* daemon, e.g. `tsx /abs/packages/daemon/src/cli.ts` or
|
|
25
|
-
* `node /abs/packages/daemon/dist/cli.js`, so loops created from THIS server tell
|
|
26
|
-
* Claude Code to run your local code instead of the registry build.
|
|
27
|
-
*/
|
|
20
|
+
/** `pievoCli` prefixes every command the dashboard shows. PIEVO_CLI points it at an
|
|
21
|
+
* in-repo daemon (e.g. `node /abs/packages/daemon/dist/cli.js`) so loops created
|
|
22
|
+
* from this server run local code instead of the registry build. */
|
|
28
23
|
var getConfig_createServerFn_handler = createServerRpc({
|
|
29
24
|
id: "cbb6a1b09b309459bbba3dc3851ae85fc468658b3cda77e22b6c6f3e28b65af4",
|
|
30
25
|
name: "getConfig",
|
|
@@ -34,8 +29,7 @@ var getConfig = createServerFn({ method: "GET" }).handler(getConfig_createServer
|
|
|
34
29
|
const custom = process.env.PIEVO_CLI?.trim();
|
|
35
30
|
return {
|
|
36
31
|
pievoCli: custom || "pievo",
|
|
37
|
-
/**
|
|
38
|
-
* carries an explicit `pievo-cli:` line so Claude Code uses it verbatim. */
|
|
32
|
+
/** A custom CLI is shown verbatim, without the global npm install step. */
|
|
39
33
|
customCli: !!custom,
|
|
40
34
|
/** Best URL for other devices, published by the launcher (HTTPS, Tailscale, then LAN). */
|
|
41
35
|
publicUrl: process.env.PIEVO_PUBLIC_URL?.trim() || null
|
|
@@ -81,7 +75,7 @@ var getArtifacts_createServerFn_handler = createServerRpc({
|
|
|
81
75
|
var getArtifacts = createServerFn({ method: "GET" }).validator((d) => d).handler(getArtifacts_createServerFn_handler, async ({ data }) => {
|
|
82
76
|
await backend();
|
|
83
77
|
if (!await findLoop(data.loopId)) return [];
|
|
84
|
-
const { listLoopArtifacts } = await import("./artifactFiles-
|
|
78
|
+
const { listLoopArtifacts } = await import("./artifactFiles-DJiK99sF.mjs");
|
|
85
79
|
return listLoopArtifacts(data.loopId);
|
|
86
80
|
});
|
|
87
81
|
var getArtifact_createServerFn_handler = createServerRpc({
|
|
@@ -92,7 +86,7 @@ var getArtifact_createServerFn_handler = createServerRpc({
|
|
|
92
86
|
var getArtifact = createServerFn({ method: "GET" }).validator((d) => d).handler(getArtifact_createServerFn_handler, async ({ data }) => {
|
|
93
87
|
await backend();
|
|
94
88
|
if (!await findLoop(data.loopId)) return { error: "file not found" };
|
|
95
|
-
const { readLoopArtifact } = await import("./artifactFiles-
|
|
89
|
+
const { readLoopArtifact } = await import("./artifactFiles-DJiK99sF.mjs");
|
|
96
90
|
return readLoopArtifact(data.loopId, data.path);
|
|
97
91
|
});
|
|
98
92
|
var getRunDiff_createServerFn_handler = createServerRpc({
|
|
@@ -111,7 +105,7 @@ var getRunDiff = createServerFn({ method: "GET" }).validator((d) => d).handler(g
|
|
|
111
105
|
hasSnapshot: false,
|
|
112
106
|
files: []
|
|
113
107
|
};
|
|
114
|
-
const { computeRunDiff } = await import("./boot-
|
|
108
|
+
const { computeRunDiff } = await import("./boot-CecCDRoH.mjs").then((n) => n.r).then((n) => n.i);
|
|
115
109
|
return computeRunDiff(data.runId);
|
|
116
110
|
});
|
|
117
111
|
var patchLoop_createServerFn_handler = createServerRpc({
|
|
@@ -171,7 +165,7 @@ var stopLoop = createServerFn({ method: "POST" }).validator((id) => id).handler(
|
|
|
171
165
|
const found = await findLoop(id);
|
|
172
166
|
if (!found) return { error: "not found" };
|
|
173
167
|
if (await hasRunningRun(id)) {
|
|
174
|
-
if ((await getMachine(found.loop.machineId))?.daemonProtocol !==
|
|
168
|
+
if ((await getMachine(found.loop.machineId))?.daemonProtocol !== 5) return { error: "Daemon upgrade required to stop a running process" };
|
|
175
169
|
}
|
|
176
170
|
const stopped = await stopLoop$1(id);
|
|
177
171
|
if (!stopped) return { error: "not found" };
|
|
@@ -192,12 +186,12 @@ var deleteLoop = createServerFn({ method: "POST" }).validator((id) => id).handle
|
|
|
192
186
|
if (!found) return { error: "not found" };
|
|
193
187
|
const machine = await getMachine(found.loop.machineId);
|
|
194
188
|
const unreachable = machinePresence(machine?.online, machine?.lastSeen) !== "online";
|
|
195
|
-
if (!unreachable && await hasRunningRun(id) && machine?.daemonProtocol !==
|
|
189
|
+
if (!unreachable && await hasRunningRun(id) && machine?.daemonProtocol !== 5) return { error: "Daemon upgrade required to stop a running process" };
|
|
196
190
|
scheduler.removeLoop(id);
|
|
197
191
|
if (!await requestDeleteLoop(id)) return { error: "not found" };
|
|
198
192
|
if (unreachable) {
|
|
199
193
|
if (!await forceDeleteLoop(id)) return { error: "delete failed; server data was not deleted" };
|
|
200
|
-
const { logger } = await import("./boot-
|
|
194
|
+
const { logger } = await import("./boot-CecCDRoH.mjs").then((n) => n.N).then((n) => n.$t);
|
|
201
195
|
logger.child({ mod: "loop-lifecycle" }).warn({
|
|
202
196
|
action: "unreachable-delete",
|
|
203
197
|
loopId: id,
|
|
@@ -242,7 +236,7 @@ var stopRun = createServerFn({ method: "POST" }).validator((id) => id).handler(s
|
|
|
242
236
|
const run = await getRun(id);
|
|
243
237
|
const found = run ? await findLoop(run.loopId) : void 0;
|
|
244
238
|
if (!run || !found) return { error: "run not found" };
|
|
245
|
-
if (run.phase === "running" && (await getMachine(found.loop.machineId))?.daemonProtocol !==
|
|
239
|
+
if (run.phase === "running" && (await getMachine(found.loop.machineId))?.daemonProtocol !== 5) return { error: "Daemon upgrade required to stop a running process" };
|
|
246
240
|
const result = await requestRunCancel(run.loopId, id);
|
|
247
241
|
return result ? {
|
|
248
242
|
ok: true,
|
|
@@ -256,7 +250,7 @@ var mintConnectKey_createServerFn_handler = createServerRpc({
|
|
|
256
250
|
}, (opts) => mintConnectKey.__executeServer(opts));
|
|
257
251
|
var mintConnectKey = createServerFn({ method: "POST" }).handler(mintConnectKey_createServerFn_handler, async () => {
|
|
258
252
|
await backend();
|
|
259
|
-
const { mintDeviceToken, rememberConnectKey } = await import("./boot-
|
|
253
|
+
const { mintDeviceToken, rememberConnectKey } = await import("./boot-CecCDRoH.mjs").then((n) => n.N).then((n) => n.g);
|
|
260
254
|
const token = mintDeviceToken();
|
|
261
255
|
await rememberConnectKey(token);
|
|
262
256
|
return { token };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/loopProjection-
|
|
1
|
+
import { A as listRuns, B as reconciliationStatesForRuns, I as machinePresence, S as getMachine, T as hasRunningRun, a as canonicalLoopSummary, g as countRuns, i as canonicalLoopEnvelope, o as daemonNeedsUpdate, t as MIN_DAEMON_VERSION, w as hasPendingRun, z as recentLoopUsage } from "./boot-CecCDRoH.mjs";
|
|
2
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loopProjection-Bo54jjGd.js
|
|
3
3
|
var SUMMARY_RUNS = 18;
|
|
4
4
|
var RECENT_USAGE_WINDOW_MS = 10080 * 60 * 1e3;
|
|
5
5
|
/** Dashboard order: loops with runs first, most recent run first. The incoming
|
|
@@ -28,6 +28,7 @@ function toRunSummary(r, reconciliation) {
|
|
|
28
28
|
agent: r.agent ?? null,
|
|
29
29
|
status: r.status ?? null,
|
|
30
30
|
message: r.message ?? null,
|
|
31
|
+
attention: r.attention ?? null,
|
|
31
32
|
durationMs: r.durationMs ?? null,
|
|
32
33
|
exitCode: r.exitCode ?? null,
|
|
33
34
|
finalText: r.finalText ?? null,
|
|
@@ -39,7 +40,8 @@ function toRunSummary(r, reconciliation) {
|
|
|
39
40
|
} : null,
|
|
40
41
|
error: r.error ?? null,
|
|
41
42
|
sessionId: r.sessionId ?? null,
|
|
42
|
-
reportIncident: r.reportIncident ?? null
|
|
43
|
+
reportIncident: r.reportIncident ?? null,
|
|
44
|
+
fileNotices: r.fileNotices ?? null
|
|
43
45
|
};
|
|
44
46
|
}
|
|
45
47
|
async function toRunSummaries(loopId, rows) {
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { o as __toESM } from "../_runtime.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Y as validateLoopTags, h as CODING_AGENTS } from "./boot-CecCDRoH.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 { _ 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-
|
|
6
|
-
import { A as
|
|
7
|
-
import { a as Timeline, l as mergeRuns, n as MachinesModal, t as LoopOverview } from "./MachinesModal-
|
|
8
|
-
import { n as artifactKind, t as Route } from "./artifactKind-
|
|
9
|
-
import { t as
|
|
10
|
-
|
|
11
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId-KUezNY69.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-Bd7_sthp.mjs";
|
|
6
|
+
import { A as sectionHeadCls, C as labelCls, E as rel, M as tsShort, O as runPulseStyle, P as useFlash, S as inputCls, _ as dur, a as LoadErrorCard, b as focusRing, d as btnPrimary, f as btnQuiet, h as dotLabel, i as FlashLine, j as selectCls, l as btn, m as dotColor, n as ConfirmBar, o as Loading, r as ErrorBanner, u as btnDanger, v as fmt, x as humanBytes } from "./actionUi-CszQXDSN.mjs";
|
|
7
|
+
import { a as Timeline, l as mergeRuns, n as MachinesModal, t as LoopOverview } from "./MachinesModal-DwHy2cis.mjs";
|
|
8
|
+
import { n as artifactKind, t as Route } from "./artifactKind-DYMU0q3N.mjs";
|
|
9
|
+
import { t as MarkdownView } from "./MarkdownView-BOe75tli.mjs";
|
|
10
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId-c1oRP7cr.js
|
|
12
11
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
13
12
|
var import_jsx_runtime = require_jsx_runtime();
|
|
14
|
-
/** Download URL for one
|
|
15
|
-
*
|
|
13
|
+
/** Download URL for one loop file. Each path segment is encoded independently so
|
|
14
|
+
* the name continues to match the catch-all route. */
|
|
16
15
|
function downloadHref(loopId, path) {
|
|
17
16
|
const encodedPath = path.split("/").map(encodeURIComponent).join("/");
|
|
18
17
|
return `/api/artifact/${encodeURIComponent(loopId)}/${encodedPath}`;
|
|
@@ -21,83 +20,9 @@ function inlineHref(loopId, path) {
|
|
|
21
20
|
return `${downloadHref(loopId, path)}?view=inline`;
|
|
22
21
|
}
|
|
23
22
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* Render the output under
|
|
28
|
-
* the `.artifact-markdown` styles.
|
|
29
|
-
*/
|
|
30
|
-
var MD_SANITIZE = {
|
|
31
|
-
ALLOWED_TAGS: [
|
|
32
|
-
"h1",
|
|
33
|
-
"h2",
|
|
34
|
-
"h3",
|
|
35
|
-
"h4",
|
|
36
|
-
"h5",
|
|
37
|
-
"h6",
|
|
38
|
-
"p",
|
|
39
|
-
"br",
|
|
40
|
-
"hr",
|
|
41
|
-
"strong",
|
|
42
|
-
"b",
|
|
43
|
-
"em",
|
|
44
|
-
"i",
|
|
45
|
-
"del",
|
|
46
|
-
"s",
|
|
47
|
-
"code",
|
|
48
|
-
"pre",
|
|
49
|
-
"blockquote",
|
|
50
|
-
"ul",
|
|
51
|
-
"ol",
|
|
52
|
-
"li",
|
|
53
|
-
"a",
|
|
54
|
-
"span",
|
|
55
|
-
"table",
|
|
56
|
-
"thead",
|
|
57
|
-
"tbody",
|
|
58
|
-
"tr",
|
|
59
|
-
"th",
|
|
60
|
-
"td",
|
|
61
|
-
"img"
|
|
62
|
-
],
|
|
63
|
-
ALLOWED_ATTR: [
|
|
64
|
-
"href",
|
|
65
|
-
"title",
|
|
66
|
-
"target",
|
|
67
|
-
"rel",
|
|
68
|
-
"src",
|
|
69
|
-
"alt"
|
|
70
|
-
]
|
|
71
|
-
};
|
|
72
|
-
function renderMarkdown(content) {
|
|
73
|
-
return purify.sanitize(g.parse(content, {
|
|
74
|
-
async: false,
|
|
75
|
-
gfm: true
|
|
76
|
-
}), MD_SANITIZE);
|
|
77
|
-
}
|
|
78
|
-
function MarkdownView({ content }) {
|
|
79
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
80
|
-
className: "artifact-markdown px-5 py-4",
|
|
81
|
-
dangerouslySetInnerHTML: { __html: (0, import_react.useMemo)(() => renderMarkdown(content), [content]) }
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Shared pieces of the artifact content viewer. The Files panel uses this one
|
|
86
|
-
* dispatch so binary/oversize copy and type-appropriate rendering cannot drift.
|
|
87
|
-
*
|
|
88
|
-
* Display types (see `lib/artifactKind`):
|
|
89
|
-
* - HTML → a STRICT sandboxed iframe (`sandbox="allow-scripts"`, deliberately
|
|
90
|
-
* NO `allow-same-origin`): user-machine-synced markup renders richly
|
|
91
|
-
* but in an opaque origin, so its scripts can't read the app's
|
|
92
|
-
* cookies/session or reach `parent` - stored-XSS is contained by
|
|
93
|
-
* design. A Preview/Source toggle exposes the raw markup too.
|
|
94
|
-
* - image → an <img> pointed at the hardened inline route (`inlineHref`); the
|
|
95
|
-
* bytes are NEVER inlined into the app DOM (SVG is scriptable, so it
|
|
96
|
-
* rides as an image, which does not execute embedded scripts).
|
|
97
|
-
* - markdown → the shared markdown pipeline (Preview) with a raw Source toggle.
|
|
98
|
-
* - text → monospace source.
|
|
99
|
-
* Everything keeps a Download fallback; an oversize (metadata-only) artifact has
|
|
100
|
-
* no synced bytes to render, so it says so rather than showing an empty pane.
|
|
23
|
+
* One viewer dispatch for every loop file, so binary/oversize copy and rendering
|
|
24
|
+
* cannot drift between surfaces. Images, including scriptable SVG, always load
|
|
25
|
+
* through the hardened inline route and are never inlined into the app DOM.
|
|
101
26
|
*/
|
|
102
27
|
function ViewerHead({ path, meta, action }) {
|
|
103
28
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -276,7 +201,6 @@ function ArtifactBody({ loopId, file }) {
|
|
|
276
201
|
kind
|
|
277
202
|
}, file.path);
|
|
278
203
|
}
|
|
279
|
-
var basename = (path) => path.split("/").pop() || path;
|
|
280
204
|
function LoopFilesPanel({ loopId, configuredPaths, running }) {
|
|
281
205
|
const [artifacts, setArtifacts] = (0, import_react.useState)(null);
|
|
282
206
|
const [selected, setSelected] = (0, import_react.useState)(null);
|
|
@@ -309,14 +233,19 @@ function LoopFilesPanel({ loopId, configuredPaths, running }) {
|
|
|
309
233
|
className: "mb-2.5 flex items-end justify-between gap-3 border-b border-hairline pb-1.5",
|
|
310
234
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h2", {
|
|
311
235
|
className: "text-label font-semibold text-secondary",
|
|
312
|
-
children: ["
|
|
236
|
+
children: ["Files", artifacts ? ` (${files.length})` : ""]
|
|
313
237
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
314
238
|
className: "text-caption font-medium text-disabled",
|
|
315
|
-
children: [
|
|
239
|
+
children: [
|
|
240
|
+
"MEMORY.md + ",
|
|
241
|
+
configuredPaths.length,
|
|
242
|
+
" artifact",
|
|
243
|
+
configuredPaths.length === 1 ? "" : "s"
|
|
244
|
+
]
|
|
316
245
|
})]
|
|
317
246
|
}), files.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
318
247
|
className: "rounded-card border border-hairline bg-surface px-5 py-10 text-center text-body text-disabled shadow-card",
|
|
319
|
-
children: artifacts == null ? "Loading…" :
|
|
248
|
+
children: artifacts == null ? "Loading…" : "No files are available for this loop."
|
|
320
249
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
321
250
|
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]",
|
|
322
251
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", {
|
|
@@ -329,17 +258,10 @@ function LoopFilesPanel({ loopId, configuredPaths, running }) {
|
|
|
329
258
|
type: "button",
|
|
330
259
|
onClick: () => setSelected(file.path),
|
|
331
260
|
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"}`,
|
|
332
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
333
|
-
className:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
title: file.path,
|
|
337
|
-
children: basename(file.path)
|
|
338
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
339
|
-
className: "block truncate font-mono text-micro text-disabled",
|
|
340
|
-
title: file.path,
|
|
341
|
-
children: file.path
|
|
342
|
-
})]
|
|
261
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
262
|
+
className: `block min-w-0 flex-1 truncate font-mono text-label ${activeRow ? "text-display" : "text-primary"}`,
|
|
263
|
+
title: file.path,
|
|
264
|
+
children: file.path
|
|
343
265
|
})
|
|
344
266
|
}) }, file.path);
|
|
345
267
|
})
|
|
@@ -348,7 +270,7 @@ function LoopFilesPanel({ loopId, configuredPaths, running }) {
|
|
|
348
270
|
className: "min-w-0 overflow-y-auto",
|
|
349
271
|
children: active && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ViewerHead, {
|
|
350
272
|
path: active.path,
|
|
351
|
-
meta: [active.size != null ? humanBytes(active.size) : "", `
|
|
273
|
+
meta: [active.size != null ? humanBytes(active.size) : "", `updated ${fmt(active.updatedAt)}`].filter(Boolean).join(" · ")
|
|
352
274
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactBody, {
|
|
353
275
|
loopId,
|
|
354
276
|
file: active
|
|
@@ -528,7 +450,7 @@ var LoopForm = (0, import_react.forwardRef)(function LoopForm({ initial }, ref)
|
|
|
528
450
|
noChange: form.noChange,
|
|
529
451
|
block: form.block
|
|
530
452
|
},
|
|
531
|
-
artifacts: form.artifacts.split(/\r?\n/).filter((
|
|
453
|
+
artifacts: form.artifacts.split(/\r?\n/).filter((name) => name.length > 0)
|
|
532
454
|
};
|
|
533
455
|
} }));
|
|
534
456
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -756,10 +678,10 @@ var LoopForm = (0, import_react.forwardRef)(function LoopForm({ initial }, ref)
|
|
|
756
678
|
}),
|
|
757
679
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, {
|
|
758
680
|
title: "Artifacts",
|
|
759
|
-
hint: "Optional
|
|
681
|
+
hint: "Optional text/code file names such as .md, .html, .sh, .py, .json, or .csv (up to 4, 256 KB each) that runs update and the dashboard renders. One name per line. Every loop also has MEMORY.md."
|
|
760
682
|
}),
|
|
761
683
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextArea, {
|
|
762
|
-
label: "Artifact
|
|
684
|
+
label: "Artifact files",
|
|
763
685
|
value: form.artifacts,
|
|
764
686
|
onChange: (value) => set("artifacts", value),
|
|
765
687
|
rows: 6,
|
|
@@ -1033,7 +955,7 @@ function LoopDetailView({ id }) {
|
|
|
1033
955
|
className: "mt-3",
|
|
1034
956
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConfirmBar, {
|
|
1035
957
|
prompt: "Stop this loop and delete its server data?",
|
|
1036
|
-
note: "This stops the loop and deletes server history and
|
|
958
|
+
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.",
|
|
1037
959
|
cta: "Delete",
|
|
1038
960
|
danger: true,
|
|
1039
961
|
busy,
|
|
@@ -1144,13 +1066,13 @@ function LoopDetailView({ id }) {
|
|
|
1144
1066
|
})
|
|
1145
1067
|
}),
|
|
1146
1068
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Config, {
|
|
1147
|
-
label: "
|
|
1069
|
+
label: "Artifacts",
|
|
1148
1070
|
children: loop.artifacts.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
1149
1071
|
className: "space-y-1",
|
|
1150
|
-
children: loop.artifacts.map((
|
|
1072
|
+
children: loop.artifacts.map((name) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
1151
1073
|
className: "break-all font-mono",
|
|
1152
|
-
children:
|
|
1153
|
-
}) },
|
|
1074
|
+
children: name
|
|
1075
|
+
}) }, name))
|
|
1154
1076
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
1155
1077
|
className: "text-disabled",
|
|
1156
1078
|
children: "None"
|
|
@@ -1205,7 +1127,7 @@ function EditHead({ name, onBack }) {
|
|
|
1205
1127
|
}),
|
|
1206
1128
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
1207
1129
|
className: "mt-1.5 text-meta text-secondary",
|
|
1208
|
-
children: "Edit tags, schedule, execution settings, prompt, status definitions, and
|
|
1130
|
+
children: "Edit tags, schedule, execution settings, prompt, status definitions, and artifact files."
|
|
1209
1131
|
})
|
|
1210
1132
|
] });
|
|
1211
1133
|
}
|
|
@@ -1275,6 +1197,9 @@ function RunsSection({ loopId, summary, runs, older, onMore, onPickRun }) {
|
|
|
1275
1197
|
className: "size-1.5 rounded-full",
|
|
1276
1198
|
style: runPulseStyle
|
|
1277
1199
|
}), "Running"]
|
|
1200
|
+
}) : run.attention ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
1201
|
+
className: "font-medium text-running",
|
|
1202
|
+
children: ["! ", run.attention]
|
|
1278
1203
|
}) : run.error || run.message || dotLabel(run)
|
|
1279
1204
|
})]
|
|
1280
1205
|
})]
|
|
@@ -1283,11 +1208,6 @@ function RunsSection({ loopId, summary, runs, older, onMore, onPickRun }) {
|
|
|
1283
1208
|
})]
|
|
1284
1209
|
});
|
|
1285
1210
|
}
|
|
1286
|
-
/**
|
|
1287
|
-
* Loop detail page — `/loops/$loopId`: a loop header and action toolbar, the
|
|
1288
|
-
* exact artifact Files panel, and the runs timeline. The view owns its own
|
|
1289
|
-
* data + self-poll. Run rows link on to `/loops/$loopId/runs/$runId`.
|
|
1290
|
-
*/
|
|
1291
1211
|
function LoopDetailPage() {
|
|
1292
1212
|
const { loopId } = Route.useParams();
|
|
1293
1213
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoopDetailView, { id: loopId });
|
|
@@ -1,10 +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 { b as stopRun, l as getLoopDetail, p as loadOlderRuns, u as getRunDiff } from "./lifecycleUi-
|
|
5
|
-
import {
|
|
6
|
-
import { t as
|
|
7
|
-
|
|
4
|
+
import { b as stopRun, l as getLoopDetail, p as loadOlderRuns, u as getRunDiff } from "./lifecycleUi-Bd7_sthp.mjs";
|
|
5
|
+
import { A as sectionHeadCls, O as runPulseStyle, _ as dur, a as LoadErrorCard, c as StatusPill, l as btn, o as Loading, s as Pill, u as btnDanger, v as fmt, x as humanBytes, y as fnum } from "./actionUi-CszQXDSN.mjs";
|
|
6
|
+
import { t as MarkdownView } from "./MarkdownView-BOe75tli.mjs";
|
|
7
|
+
import { t as Route } from "./loops._loopId_.runs._runId-czMVvNsk.mjs";
|
|
8
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId_.runs._runId-Dl0SwOlC.js
|
|
8
9
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
9
10
|
var import_jsx_runtime = require_jsx_runtime();
|
|
10
11
|
/**
|
|
@@ -422,13 +423,20 @@ function RunDetailView({ loopId, runId }) {
|
|
|
422
423
|
className: "min-w-0",
|
|
423
424
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
424
425
|
className: "flex flex-wrap items-center gap-3",
|
|
425
|
-
children: [
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
426
|
+
children: [
|
|
427
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h1", {
|
|
428
|
+
className: "text-[26px] font-medium leading-tight tracking-tight text-display",
|
|
429
|
+
children: ["Run · ", loopName]
|
|
430
|
+
}),
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusPill, {
|
|
432
|
+
run,
|
|
433
|
+
colorText: true
|
|
434
|
+
}),
|
|
435
|
+
run.attention && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pill, {
|
|
436
|
+
tone: "attention",
|
|
437
|
+
children: "Needs attention"
|
|
438
|
+
})
|
|
439
|
+
]
|
|
432
440
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
433
441
|
className: "mt-2.5 flex flex-wrap items-center gap-x-2.5 gap-y-1.5 text-meta text-secondary",
|
|
434
442
|
children: [
|
|
@@ -462,8 +470,8 @@ function RunDetailView({ loopId, runId }) {
|
|
|
462
470
|
type: "button",
|
|
463
471
|
onClick: onStop,
|
|
464
472
|
className: btnDanger,
|
|
465
|
-
disabled: run.phase === "running" && detail.machine.daemonProtocol !==
|
|
466
|
-
title: run.phase === "running" && detail.machine.daemonProtocol !==
|
|
473
|
+
disabled: run.phase === "running" && detail.machine.daemonProtocol !== 5,
|
|
474
|
+
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,
|
|
467
475
|
children: "Stop run"
|
|
468
476
|
})]
|
|
469
477
|
})]
|
|
@@ -485,6 +493,13 @@ function RunDetailView({ loopId, runId }) {
|
|
|
485
493
|
children: run.reconciliation === "blocking" ? detail.machine.presence === "online" ? "The machine is online and checking an interrupted run. Queued work starts automatically after recovery." : "Waiting for the machine to reconnect and check an interrupted run. Queued work starts automatically; no action is required." : "This interrupted run no longer blocks queued work. Pievo will still accept its saved report if it arrives."
|
|
486
494
|
})
|
|
487
495
|
}) : null,
|
|
496
|
+
run.attention && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
497
|
+
label: "Needs attention",
|
|
498
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
499
|
+
className: "break-words text-body font-medium text-running",
|
|
500
|
+
children: run.attention
|
|
501
|
+
})
|
|
502
|
+
}),
|
|
488
503
|
run.reportIncident && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
489
504
|
label: "Terminal report rejected",
|
|
490
505
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -527,15 +542,25 @@ function RunDetailView({ loopId, runId }) {
|
|
|
527
542
|
]
|
|
528
543
|
})
|
|
529
544
|
}),
|
|
545
|
+
run.fileNotices && run.fileNotices.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
546
|
+
label: "Loop files not kept",
|
|
547
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
548
|
+
className: "list-disc space-y-1.5 pl-5 text-body text-primary",
|
|
549
|
+
children: run.fileNotices.map((notice) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
|
|
550
|
+
className: "break-words",
|
|
551
|
+
children: notice
|
|
552
|
+
}, notice))
|
|
553
|
+
})
|
|
554
|
+
}),
|
|
530
555
|
run.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
531
556
|
label: "Report",
|
|
532
557
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
533
|
-
className: "
|
|
534
|
-
children: run.message
|
|
558
|
+
className: "break-words rounded-control border border-hairline bg-raised text-body leading-relaxed text-primary",
|
|
559
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownView, { content: run.message })
|
|
535
560
|
})
|
|
536
561
|
}),
|
|
537
562
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Changes, { run }),
|
|
538
|
-
run.finalText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
563
|
+
run.finalText && !run.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
539
564
|
label: "Final output",
|
|
540
565
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
541
566
|
className: "whitespace-pre-wrap break-words text-body text-primary",
|
|
@@ -587,13 +612,8 @@ function RunDetailView({ loopId, runId }) {
|
|
|
587
612
|
})]
|
|
588
613
|
})] });
|
|
589
614
|
}
|
|
590
|
-
/**
|
|
591
|
-
*
|
|
592
|
-
* `_` on the `$loopId` segment opts it out of the loop page's component so the run
|
|
593
|
-
* gets its own full surface, deep-linkable + browser-back friendly) rather than a
|
|
594
|
-
* modal or an inline panel. It resolves the run from the loop's detail payload
|
|
595
|
-
* (reusing getLoopDetail) and the existing artifact diff.
|
|
596
|
-
*/
|
|
615
|
+
/** The trailing `_` on `$loopId` opts the run page out of the loop page's component,
|
|
616
|
+
* so a run gets its own deep-linkable, back-button-friendly page. */
|
|
597
617
|
function RunDetailPage() {
|
|
598
618
|
const { loopId, runId } = Route.useParams();
|
|
599
619
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { c as createFileRoute, s as lazyRouteComponent } from "../_libs/@tanstack/react-router+[...].mjs";
|
|
2
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId_.runs._runId-czMVvNsk.js
|
|
3
|
+
var $$splitComponentImporter = () => import("./loops._loopId_.runs._runId-Dl0SwOlC.mjs");
|
|
4
|
+
/** The trailing `_` on `$loopId` opts the run page out of the loop page's component,
|
|
5
|
+
* so a run gets its own deep-linkable, back-button-friendly page. */
|
|
6
|
+
var Route = createFileRoute("/loops/$loopId_/runs/$runId")({
|
|
7
|
+
ssr: false,
|
|
8
|
+
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { Route as t };
|
|
@@ -1,30 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { F as machineIdFromToken, J as updateMachine, L as mintDeviceToken, P as loopsForMachine, S as getMachine, U as sha256, _ as createMachine$1, k as listMachines$1, o as daemonNeedsUpdate, s as ensureServer, t as MIN_DAEMON_VERSION, y as forceDeleteMachine } from "./boot-CecCDRoH.mjs";
|
|
2
2
|
import { r as createServerFn } from "./ssr.mjs";
|
|
3
3
|
import { t as createServerRpc } from "./createServerRpc-BD8Xn_0_.mjs";
|
|
4
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/machineFns-
|
|
4
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/machineFns-aw9xe5oz.js
|
|
5
5
|
/**
|
|
6
|
-
* Latest published @kky42/pievo version
|
|
7
|
-
* npm dist-tag
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* Zero-exec invariant: this is a plain HTTP GET against the public npm registry —
|
|
11
|
-
* the server runs no LLM and executes no user code. It NEVER surfaces an error:
|
|
12
|
-
* if npm is unreachable/slow/garbage, the cache simply stays as-is (undefined at
|
|
13
|
-
* first) and the web shows no update hint. Bounded timeout + ~1h in-memory cache
|
|
14
|
-
* so the machine-list hot path never blocks on the network.
|
|
15
|
-
*
|
|
16
|
-
* The fetch is injectable (mirroring the gateway's injectable notifier/blobStore)
|
|
17
|
-
* so tests need no network: construct a `LatestDaemonVersion` with a fake fetch
|
|
18
|
-
* and `now`, or call the pure `fetchNpmLatest` directly.
|
|
6
|
+
* Latest published @kky42/pievo version for the dashboard's update hint: a plain
|
|
7
|
+
* GET of the npm `latest` dist-tag. Fail-silent with a bounded timeout and a ~1h
|
|
8
|
+
* in-memory cache, so the machine list never blocks on or surfaces npm errors.
|
|
19
9
|
*/
|
|
20
10
|
var NPM_URL = "https://registry.npmjs.org/@kky42/pievo";
|
|
21
11
|
var DEFAULT_TTL_MS = 3600 * 1e3;
|
|
22
12
|
var FETCH_TIMEOUT_MS = 4e3;
|
|
23
|
-
/**
|
|
24
|
-
* One npm `latest` read — bounded + fail-silent. Returns the version string or
|
|
25
|
-
* null (unreachable/timeout/malformed). Pure w.r.t. the injected fetch, so it's
|
|
26
|
-
* directly unit-testable with no network.
|
|
27
|
-
*/
|
|
13
|
+
/** One bounded npm `latest` read; null when unreachable, slow, or malformed. */
|
|
28
14
|
async function fetchNpmLatest(fetchImpl, timeoutMs = FETCH_TIMEOUT_MS) {
|
|
29
15
|
const ctrl = new AbortController();
|
|
30
16
|
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|