@kky42/pievo-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +17 -0
- package/.output/public/assets/CodeField-dOzyFQNH.js +34 -0
- package/.output/public/assets/LoopView-B4H9QibC.js +55 -0
- package/.output/public/assets/Modal-D33gNSgx.js +1 -0
- package/.output/public/assets/SignIn-SHuRRyOv.js +1 -0
- package/.output/public/assets/actionUi-ChGGALzg.js +1 -0
- package/.output/public/assets/app-DElSo_jy.css +2 -0
- package/.output/public/assets/artifactView-DFuubXLJ.js +66 -0
- package/.output/public/assets/index-DfpTWRSz.js +12 -0
- package/.output/public/assets/invite._token-DJtd-XE2.js +1 -0
- package/.output/public/assets/invite._token-T8oo4Qtw.js +1 -0
- package/.output/public/assets/jsx-runtime-BseJUIpC.js +1 -0
- package/.output/public/assets/lifecycleUi-DKkChdnU.js +1 -0
- package/.output/public/assets/loopApi-BM2nj71x.js +3 -0
- package/.output/public/assets/loops._loopId-B19Jw7jC.js +5 -0
- package/.output/public/assets/loops._loopId_.runs._runId-_CflHV38.js +3 -0
- package/.output/public/assets/notifyFns-DCubjpRy.js +1 -0
- package/.output/public/assets/preload-helper-CKUiEq3b.js +3 -0
- package/.output/public/assets/routes-B9tgli5f.js +1 -0
- package/.output/public/assets/routes-CTtlM_qt.js +1 -0
- package/.output/public/assets/t._teamId-Bm21mngW.js +1 -0
- package/.output/public/assets/t._teamId-gR7BVKkR.js +1 -0
- package/.output/public/assets/ui-Dp88qUWh.js +1 -0
- package/.output/public/assets/useRouter-DsjH8G0p.js +1 -0
- package/.output/public/favicon.svg +12 -0
- package/.output/public/fonts/GeistPixel-Square.woff2 +0 -0
- package/.output/server/_chunks/ssr-renderer.mjs +26 -0
- package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +419 -0
- package/.output/server/_libs/@aws-sdk/checksums+[...].mjs +10732 -0
- package/.output/server/_libs/@aws-sdk/client-s3+[...].mjs +9475 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +137 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +440 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +62 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +818 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +59 -0
- package/.output/server/_libs/@base-ui/react+[...].mjs +11125 -0
- package/.output/server/_libs/@codemirror/autocomplete+[...].mjs +19713 -0
- package/.output/server/_libs/@codemirror/lang-css+[...].mjs +2636 -0
- package/.output/server/_libs/@codemirror/lang-html+[...].mjs +2247 -0
- package/.output/server/_libs/@codemirror/lang-json+[...].mjs +79 -0
- package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1736 -0
- package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +342 -0
- package/.output/server/_libs/@tanstack/react-router+[...].mjs +14300 -0
- package/.output/server/_libs/@uiw/codemirror-extensions-basic-setup+[...].mjs +76 -0
- package/.output/server/_libs/atomic-sleep.mjs +27 -0
- package/.output/server/_libs/aws-crypto__crc32c.mjs +314 -0
- package/.output/server/_libs/aws-sdk__nested-clients.mjs +2671 -0
- package/.output/server/_libs/babel__runtime.mjs +30 -0
- package/.output/server/_libs/clsx.mjs +16 -0
- package/.output/server/_libs/codemirror__commands.mjs +1725 -0
- package/.output/server/_libs/codemirror__lint.mjs +565 -0
- package/.output/server/_libs/codemirror__search.mjs +1138 -0
- package/.output/server/_libs/codemirror__theme-one-dark.mjs +161 -0
- package/.output/server/_libs/colorette.mjs +129 -0
- package/.output/server/_libs/croner.mjs +735 -0
- package/.output/server/_libs/d3-array.mjs +231 -0
- package/.output/server/_libs/d3-color.mjs +330 -0
- package/.output/server/_libs/d3-format.mjs +252 -0
- package/.output/server/_libs/d3-interpolate.mjs +163 -0
- package/.output/server/_libs/d3-path.mjs +77 -0
- package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
- package/.output/server/_libs/d3-shape.mjs +689 -0
- package/.output/server/_libs/dateformat.mjs +341 -0
- package/.output/server/_libs/decimal.js-light.mjs +884 -0
- package/.output/server/_libs/diff.mjs +732 -0
- package/.output/server/_libs/dom-serializer+[...].mjs +708 -0
- package/.output/server/_libs/domhandler.mjs +461 -0
- package/.output/server/_libs/dompurify.mjs +2111 -0
- package/.output/server/_libs/domutils.mjs +868 -0
- package/.output/server/_libs/drizzle-orm+postgres.mjs +7689 -0
- package/.output/server/_libs/electric-sql__pglite.mjs +14674 -0
- package/.output/server/_libs/end-of-stream+once+wrappy.mjs +145 -0
- package/.output/server/_libs/es-toolkit.mjs +1737 -0
- package/.output/server/_libs/eventemitter3.mjs +236 -0
- package/.output/server/_libs/fast-copy.mjs +285 -0
- package/.output/server/_libs/fast-safe-stringify.mjs +172 -0
- package/.output/server/_libs/h3+rou3+srvx.mjs +1201 -0
- package/.output/server/_libs/html-dom-parser+htmlparser2.mjs +1560 -0
- package/.output/server/_libs/html-react-parser+[...].mjs +1360 -0
- package/.output/server/_libs/initdb.wasm +0 -0
- package/.output/server/_libs/marked.mjs +1548 -0
- package/.output/server/_libs/on-exit-leak-free.mjs +80 -0
- package/.output/server/_libs/pglite.data +37667 -8
- package/.output/server/_libs/pglite.wasm +0 -0
- package/.output/server/_libs/pino+[...].mjs +3196 -0
- package/.output/server/_libs/pino-abstract-transport+split2.mjs +194 -0
- package/.output/server/_libs/pino-pretty+[...].mjs +1623 -0
- package/.output/server/_libs/pinojs__redact.mjs +280 -0
- package/.output/server/_libs/react-redux+[...].mjs +205 -0
- package/.output/server/_libs/recharts+victory-vendor.mjs +15875 -0
- package/.output/server/_libs/tanstack__history.mjs +342 -0
- package/.output/server/_libs/ufo.mjs +64 -0
- package/.output/server/_libs/uiw__codemirror-themes.mjs +32 -0
- package/.output/server/_libs/uiw__react-codemirror.mjs +354 -0
- package/.output/server/_runtime.mjs +37 -0
- package/.output/server/_ssr/CodeField-tm4rr6G3.mjs +143 -0
- package/.output/server/_ssr/DashboardView-CC7htv28.mjs +2795 -0
- package/.output/server/_ssr/LoopPlaybook-BXH8mhiX.mjs +2105 -0
- package/.output/server/_ssr/LoopView-DCugEbHx.mjs +1106 -0
- package/.output/server/_ssr/Modal-DpKZHLZK.mjs +49 -0
- package/.output/server/_ssr/SignIn-dTndU6Hw.mjs +67 -0
- package/.output/server/_ssr/actionUi-CZbEixbf.mjs +119 -0
- package/.output/server/_ssr/adapters-BS8XosjF.mjs +130 -0
- package/.output/server/_ssr/artifactFiles-Cagtj7J0.mjs +61 -0
- package/.output/server/_ssr/artifactKind-BW0isV8L.mjs +37 -0
- package/.output/server/_ssr/artifactView-DS4O22wl.mjs +304 -0
- package/.output/server/_ssr/artifacts-DngKyW2u.mjs +2 -0
- package/.output/server/_ssr/auth-DY1DuYZd.mjs +38429 -0
- package/.output/server/_ssr/boot-BbtG0ImW.mjs +9010 -0
- package/.output/server/_ssr/boot-CMHTxQpJ.mjs +2 -0
- package/.output/server/_ssr/bun-sqlite-dialect-BW9W1_Ps-CU1Spd6z.mjs +162 -0
- package/.output/server/_ssr/core-RrmWoKne.mjs +5 -0
- package/.output/server/_ssr/createServerRpc-BD8Xn_0_.mjs +12 -0
- package/.output/server/_ssr/d1-sqlite-dialect-BLC8LXE6-DfG7tB8s.mjs +112 -0
- package/.output/server/_ssr/db-DWAuZq1o.mjs +2 -0
- package/.output/server/_ssr/dist-BIxFFVZg.mjs +342 -0
- package/.output/server/_ssr/empty-plugin-adapters-DKUlnwwl.mjs +5 -0
- package/.output/server/_ssr/factory-Blq0DYfT.mjs +6903 -0
- package/.output/server/_ssr/invite._token-BRCo9LGB.mjs +36 -0
- package/.output/server/_ssr/invite._token-DJxGLILJ.mjs +28 -0
- package/.output/server/_ssr/invite._token-NewFt27g.mjs +92 -0
- package/.output/server/_ssr/kysely-adapter-D3XTe64J.mjs +2 -0
- package/.output/server/_ssr/kysely-migration-tables-JkVUjPF_-bPAX9LR_.mjs +19 -0
- package/.output/server/_ssr/lifecycleUi-C9lg1r3r.mjs +38 -0
- package/.output/server/_ssr/logger-Dw82jNjH.mjs +2 -0
- package/.output/server/_ssr/loopApi-BtfkZQYK.mjs +532 -0
- package/.output/server/_ssr/loopApi-Cxe8WyOB.mjs +105 -0
- package/.output/server/_ssr/loops._loopId-7NQJPB9W.mjs +30 -0
- package/.output/server/_ssr/loops._loopId-DhnArGdL.mjs +1635 -0
- package/.output/server/_ssr/loops._loopId_.runs._runId-Bvuo2nki.mjs +29 -0
- package/.output/server/_ssr/loops._loopId_.runs._runId-Dip5Xk-q.mjs +674 -0
- package/.output/server/_ssr/machineFns-Dvr5ICUy.mjs +266 -0
- package/.output/server/_ssr/node-sqlite-dialect-DhyOpJTX.mjs +162 -0
- package/.output/server/_ssr/notifyFns-BcMRY5kP.mjs +118 -0
- package/.output/server/_ssr/notifyFns-Q458pZmE.mjs +580 -0
- package/.output/server/_ssr/router-J8KZ30xw.mjs +678 -0
- package/.output/server/_ssr/routes-Bcs4T1ox.mjs +28 -0
- package/.output/server/_ssr/routes-BoGrcf-b.mjs +43 -0
- package/.output/server/_ssr/routes-D4am3Zff.mjs +28 -0
- package/.output/server/_ssr/runDiff-CpEFqo7G.mjs +113 -0
- package/.output/server/_ssr/ssr.mjs +5837 -0
- package/.output/server/_ssr/start-4ifArtKx.mjs +4 -0
- package/.output/server/_ssr/store-b3JcQ08F.mjs +2 -0
- package/.output/server/_ssr/t._teamId-CeUhzgzT.mjs +32 -0
- package/.output/server/_ssr/t._teamId-DR-hQK7o.mjs +47 -0
- package/.output/server/_ssr/t._teamId-Dy_McbRt.mjs +31 -0
- package/.output/server/_ssr/teamCookie-B7hLOIie.mjs +10 -0
- package/.output/server/_ssr/teamFns-BIDnsg2A.mjs +473 -0
- package/.output/server/_ssr/teamFns-DA4ovI5g.mjs +33 -0
- package/.output/server/_ssr/tokens-ytd60FUt.mjs +2 -0
- package/.output/server/_ssr/ui-Dej2qjuS.mjs +267 -0
- package/.output/server/_tanstack-start-manifest_v-CVS6c7re.mjs +95 -0
- package/.output/server/drizzle/0000_round_marauders.sql +193 -0
- package/.output/server/drizzle/0001_naive_silver_fox.sql +25 -0
- package/.output/server/drizzle/0002_funny_sage.sql +12 -0
- package/.output/server/drizzle/0003_optimal_slapstick.sql +102 -0
- package/.output/server/drizzle/0004_remove_grok_agent.sql +5 -0
- package/.output/server/drizzle/0005_heavy_gauntlet.sql +8 -0
- package/.output/server/drizzle/0006_tranquil_sharon_carter.sql +1 -0
- package/.output/server/drizzle/0007_faulty_starbolt.sql +30 -0
- package/.output/server/drizzle/0008_durable_lifecycle_evidence.sql +15 -0
- package/.output/server/drizzle/meta/0000_snapshot.json +1333 -0
- package/.output/server/drizzle/meta/0001_snapshot.json +1498 -0
- package/.output/server/drizzle/meta/0002_snapshot.json +1576 -0
- package/.output/server/drizzle/meta/0003_snapshot.json +1666 -0
- package/.output/server/drizzle/meta/0005_snapshot.json +1666 -0
- package/.output/server/drizzle/meta/0006_snapshot.json +1672 -0
- package/.output/server/drizzle/meta/0007_snapshot.json +1787 -0
- package/.output/server/drizzle/meta/_journal.json +69 -0
- package/.output/server/index.mjs +464 -0
- package/.output/server/node_modules/tslib/modules/index.js +70 -0
- package/.output/server/node_modules/tslib/modules/package.json +3 -0
- package/.output/server/node_modules/tslib/package.json +47 -0
- package/.output/server/node_modules/tslib/tslib.js +484 -0
- package/.output/server/package.json +9 -0
- package/LICENSE +21 -0
- package/drizzle/0000_round_marauders.sql +193 -0
- package/drizzle/0001_naive_silver_fox.sql +25 -0
- package/drizzle/0002_funny_sage.sql +12 -0
- package/drizzle/0003_optimal_slapstick.sql +102 -0
- package/drizzle/0004_remove_grok_agent.sql +5 -0
- package/drizzle/0005_heavy_gauntlet.sql +8 -0
- package/drizzle/0006_tranquil_sharon_carter.sql +1 -0
- package/drizzle/0007_faulty_starbolt.sql +30 -0
- package/drizzle/0008_durable_lifecycle_evidence.sql +15 -0
- package/drizzle/meta/0000_snapshot.json +1333 -0
- package/drizzle/meta/0001_snapshot.json +1498 -0
- package/drizzle/meta/0002_snapshot.json +1576 -0
- package/drizzle/meta/0003_snapshot.json +1666 -0
- package/drizzle/meta/0005_snapshot.json +1666 -0
- package/drizzle/meta/0006_snapshot.json +1672 -0
- package/drizzle/meta/0007_snapshot.json +1787 -0
- package/drizzle/meta/_journal.json +69 -0
- package/package.json +84 -0
- package/scripts/pievo-server.mjs +390 -0
- package/scripts/prestart.mjs +66 -0
- package/scripts/server-cli-lib.mjs +451 -0
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
import { o as __toESM } from "../_runtime.mjs";
|
|
2
|
+
import { C as require_jsx_runtime, S as require_react } from "../_libs/@base-ui/react+[...].mjs";
|
|
3
|
+
import { O as runPulseStyle, _ as fmt, a as StatusPill, c as btnDanger, g as dur, k as sectionHeadCls, n as Loading, o as btn, r as Pill, v as fnum, y as humanBytes } from "./ui-Dej2qjuS.mjs";
|
|
4
|
+
import { u as Link } from "../_libs/@tanstack/react-router+[...].mjs";
|
|
5
|
+
import { T as stopRun, _ as loadOlderRuns, f as getJobDetail, p as getRunDiff } from "./loopApi-Cxe8WyOB.mjs";
|
|
6
|
+
import { r as LoadErrorCard } from "./actionUi-CZbEixbf.mjs";
|
|
7
|
+
import { s as useSession } from "./LoopPlaybook-BXH8mhiX.mjs";
|
|
8
|
+
import { t as SignIn } from "./SignIn-dTndU6Hw.mjs";
|
|
9
|
+
import { t as Route } from "./loops._loopId_.runs._runId-Bvuo2nki.mjs";
|
|
10
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loops._loopId_.runs._runId-Dip5Xk-q.js
|
|
11
|
+
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
12
|
+
var import_jsx_runtime = require_jsx_runtime();
|
|
13
|
+
/**
|
|
14
|
+
* Classify one physical diff line, given whether we are already inside a hunk.
|
|
15
|
+
* Classification is STATEFUL over hunk position: only the preamble (before the
|
|
16
|
+
* first `@@`) may hold `---`/`+++`/`diff `/`index `/`Index:`/`===` headers, so
|
|
17
|
+
* once inside a hunk a content line whose text merely begins with `--`/`++`
|
|
18
|
+
* (a markdown `---` HR/frontmatter, a `-- comment`, a `++x`) is read by its
|
|
19
|
+
* single leading marker char and keeps its del/add tint + stat.
|
|
20
|
+
*/
|
|
21
|
+
function classify(line, inHunk) {
|
|
22
|
+
if (line.startsWith("@@")) return {
|
|
23
|
+
kind: "hunk",
|
|
24
|
+
text: line,
|
|
25
|
+
gutter: ""
|
|
26
|
+
};
|
|
27
|
+
if (!inHunk) {
|
|
28
|
+
if (line.startsWith("---") || line.startsWith("+++") || line.startsWith("diff ") || line.startsWith("index ") || line.startsWith("Index:") || line.startsWith("===")) return {
|
|
29
|
+
kind: "meta",
|
|
30
|
+
text: line,
|
|
31
|
+
gutter: ""
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
kind: "context",
|
|
35
|
+
text: line,
|
|
36
|
+
gutter: ""
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (line.startsWith("+")) return {
|
|
40
|
+
kind: "add",
|
|
41
|
+
text: line.slice(1),
|
|
42
|
+
gutter: "+"
|
|
43
|
+
};
|
|
44
|
+
if (line.startsWith("-")) return {
|
|
45
|
+
kind: "del",
|
|
46
|
+
text: line.slice(1),
|
|
47
|
+
gutter: "-"
|
|
48
|
+
};
|
|
49
|
+
if (line.startsWith(" ")) return {
|
|
50
|
+
kind: "context",
|
|
51
|
+
text: line.slice(1),
|
|
52
|
+
gutter: ""
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
kind: "context",
|
|
56
|
+
text: line,
|
|
57
|
+
gutter: ""
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Split a unified-diff string into classified lines. A trailing newline does not
|
|
62
|
+
* emit a spurious empty final line (common in generated diffs).
|
|
63
|
+
*/
|
|
64
|
+
function parseUnifiedDiff(diff) {
|
|
65
|
+
if (!diff) return [];
|
|
66
|
+
const body = diff.endsWith("\n") ? diff.slice(0, -1) : diff;
|
|
67
|
+
let inHunk = false;
|
|
68
|
+
return body.split("\n").map((line) => {
|
|
69
|
+
const classified = classify(line, inHunk);
|
|
70
|
+
if (classified.kind === "hunk") inHunk = true;
|
|
71
|
+
return classified;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** Counts of added/removed content lines — for a compact per-file "+N −M" tally. */
|
|
75
|
+
function diffStat(lines) {
|
|
76
|
+
let added = 0;
|
|
77
|
+
let removed = 0;
|
|
78
|
+
for (const l of lines) if (l.kind === "add") added++;
|
|
79
|
+
else if (l.kind === "del") removed++;
|
|
80
|
+
return {
|
|
81
|
+
added,
|
|
82
|
+
removed
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** Per-file status word + its ink (reused from the old Changes list). */
|
|
86
|
+
var STATUS_LABEL = {
|
|
87
|
+
added: "Added",
|
|
88
|
+
modified: "Changed",
|
|
89
|
+
removed: "Removed"
|
|
90
|
+
};
|
|
91
|
+
var STATUS_CLS = {
|
|
92
|
+
added: "text-success",
|
|
93
|
+
modified: "text-secondary",
|
|
94
|
+
removed: "text-accent"
|
|
95
|
+
};
|
|
96
|
+
/** Signed byte delta — "+1.8 KB", "−240 B", "" when unknown/zero. */
|
|
97
|
+
function fmtDelta(n) {
|
|
98
|
+
if (n == null || n === 0) return "";
|
|
99
|
+
return `${n > 0 ? "+" : "−"}${humanBytes(n)}`;
|
|
100
|
+
}
|
|
101
|
+
/** A diff line's row classes — line-level tint + gutter ink per kind. */
|
|
102
|
+
var LINE_CLS = {
|
|
103
|
+
add: "bg-[color:var(--color-diff-add-bg)] text-primary",
|
|
104
|
+
del: "bg-[color:var(--color-diff-del-bg)] text-primary",
|
|
105
|
+
hunk: "bg-[color:var(--color-diff-hunk-bg)] text-disabled",
|
|
106
|
+
meta: "text-disabled",
|
|
107
|
+
context: "text-secondary"
|
|
108
|
+
};
|
|
109
|
+
var GUTTER_CLS = {
|
|
110
|
+
add: "text-success",
|
|
111
|
+
del: "text-accent",
|
|
112
|
+
hunk: "text-disabled",
|
|
113
|
+
meta: "text-disabled",
|
|
114
|
+
context: "text-disabled"
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* The colored diff body for one file. Each physical line becomes a row with a
|
|
118
|
+
* `+`/`-`/` ` gutter and a line-level background tint (add=green, del=red, hunk
|
|
119
|
+
* de-emphasized). Long lines DON'T wrap — the pane scrolls them horizontally
|
|
120
|
+
* (`overflow-x-auto min-w-0`) so a wide line never widens the page. Height is
|
|
121
|
+
* capped so a long diff scrolls inside its own box.
|
|
122
|
+
*/
|
|
123
|
+
function DiffBody({ lines }) {
|
|
124
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
125
|
+
className: "min-w-0 max-h-[420px] overflow-auto border-t border-hairline bg-raised font-mono text-label leading-[1.55]",
|
|
126
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
127
|
+
className: "min-w-max",
|
|
128
|
+
children: lines.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
129
|
+
className: `flex ${LINE_CLS[l.kind]}`,
|
|
130
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
131
|
+
"aria-hidden": true,
|
|
132
|
+
className: `w-6 shrink-0 select-none pl-2.5 text-center ${GUTTER_CLS[l.kind]}`,
|
|
133
|
+
children: l.gutter
|
|
134
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
135
|
+
className: "whitespace-pre pr-4",
|
|
136
|
+
children: l.text || "\xA0"
|
|
137
|
+
})]
|
|
138
|
+
}, i))
|
|
139
|
+
})
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/** One file row header — status word, path, size delta, and binary/too-large markers. */
|
|
143
|
+
function FileHead({ f, lines }) {
|
|
144
|
+
const delta = fmtDelta(f.sizeDelta);
|
|
145
|
+
const stat = lines ? diffStat(lines) : null;
|
|
146
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
147
|
+
className: "flex min-w-0 flex-wrap items-baseline gap-x-2.5 gap-y-1 text-meta",
|
|
148
|
+
children: [
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
150
|
+
className: `shrink-0 text-caption font-medium ${STATUS_CLS[f.status]}`,
|
|
151
|
+
children: STATUS_LABEL[f.status]
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
154
|
+
className: "min-w-0 break-all font-mono text-primary",
|
|
155
|
+
children: f.path
|
|
156
|
+
}),
|
|
157
|
+
stat && (stat.added > 0 || stat.removed > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
158
|
+
className: "shrink-0 font-mono text-caption",
|
|
159
|
+
children: [
|
|
160
|
+
stat.added > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
161
|
+
className: "text-success",
|
|
162
|
+
children: ["+", stat.added]
|
|
163
|
+
}),
|
|
164
|
+
stat.added > 0 && stat.removed > 0 && " ",
|
|
165
|
+
stat.removed > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
166
|
+
className: "text-accent",
|
|
167
|
+
children: ["−", stat.removed]
|
|
168
|
+
})
|
|
169
|
+
]
|
|
170
|
+
}),
|
|
171
|
+
delta && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
172
|
+
className: "shrink-0 font-mono text-caption text-disabled",
|
|
173
|
+
children: delta
|
|
174
|
+
}),
|
|
175
|
+
f.binary && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
176
|
+
className: "shrink-0 text-caption text-secondary",
|
|
177
|
+
children: "Binary"
|
|
178
|
+
}),
|
|
179
|
+
f.tooLarge && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
180
|
+
className: "shrink-0 text-caption text-secondary",
|
|
181
|
+
children: "Too large to diff"
|
|
182
|
+
})
|
|
183
|
+
]
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/** Small enough to auto-open; larger diffs start collapsed. */
|
|
187
|
+
var AUTO_OPEN_LINES = 40;
|
|
188
|
+
/**
|
|
189
|
+
* The Changes diff view — a list of changed files, each collapsible, its unified
|
|
190
|
+
* diff rendered as colored add/remove/context lines. Files with no inline diff
|
|
191
|
+
* (binary / oversize / too-large) render just the header row. Small diffs default
|
|
192
|
+
* open, large ones collapsed. Built entirely from theme tokens — no external diff
|
|
193
|
+
* library.
|
|
194
|
+
*/
|
|
195
|
+
function DiffView({ files }) {
|
|
196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
197
|
+
className: "space-y-1.5",
|
|
198
|
+
children: files.map((f) => {
|
|
199
|
+
if (!f.diff) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
200
|
+
className: "rounded-control border border-hairline bg-surface px-3.5 py-2",
|
|
201
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileHead, {
|
|
202
|
+
f,
|
|
203
|
+
lines: null
|
|
204
|
+
})
|
|
205
|
+
}, f.path);
|
|
206
|
+
const lines = parseUnifiedDiff(f.diff);
|
|
207
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", {
|
|
208
|
+
open: lines.length <= AUTO_OPEN_LINES,
|
|
209
|
+
className: "group min-w-0 overflow-hidden rounded-control border border-hairline bg-surface",
|
|
210
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("summary", {
|
|
211
|
+
className: "flex cursor-pointer select-none items-center gap-2 px-3.5 py-2 marker:content-['']",
|
|
212
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
213
|
+
"aria-hidden": true,
|
|
214
|
+
className: "shrink-0 text-micro text-disabled transition-transform group-open:rotate-90",
|
|
215
|
+
children: "▸"
|
|
216
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileHead, {
|
|
217
|
+
f,
|
|
218
|
+
lines
|
|
219
|
+
})]
|
|
220
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiffBody, { lines })]
|
|
221
|
+
}, f.path);
|
|
222
|
+
})
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
/** A section card - mirrors the loop page's surface panels with a sentence-case
|
|
226
|
+
* section heading. `min-w-0` so wide inner content (a wide diff line)
|
|
227
|
+
* scrolls inside the card, never widens the page. */
|
|
228
|
+
function Card({ label, count, children }) {
|
|
229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
230
|
+
className: "min-w-0 rounded-card border border-hairline bg-surface px-6 py-5 shadow-card",
|
|
231
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
232
|
+
className: `mb-3.5 border-b border-hairline pb-1.5 ${sectionHeadCls}`,
|
|
233
|
+
children: [label, count != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
234
|
+
className: "text-disabled",
|
|
235
|
+
children: [
|
|
236
|
+
" (",
|
|
237
|
+
count,
|
|
238
|
+
")"
|
|
239
|
+
]
|
|
240
|
+
})]
|
|
241
|
+
}), children]
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
/** A stacked key/value field for the metadata rail - a small label over its value. */
|
|
245
|
+
function Field({ k, children }) {
|
|
246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
247
|
+
className: "min-w-0",
|
|
248
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
249
|
+
className: "mb-0.5 text-label font-medium text-secondary",
|
|
250
|
+
children: k
|
|
251
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
252
|
+
className: "min-w-0 text-body text-primary",
|
|
253
|
+
children
|
|
254
|
+
})]
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/** Per-run artifact diff vs the previous run (Phase 3), rendered as a colored diff
|
|
258
|
+
* view. Lazy by runId; degrades to a calm fallback for runs with no snapshot. */
|
|
259
|
+
function Changes({ run }) {
|
|
260
|
+
const [data, setData] = (0, import_react.useState)(null);
|
|
261
|
+
(0, import_react.useEffect)(() => {
|
|
262
|
+
if (run.queued || run.running) return;
|
|
263
|
+
let alive = true;
|
|
264
|
+
getRunDiff({ data: { runId: run.id } }).then((d) => alive && setData(d)).catch(() => alive && setData({
|
|
265
|
+
hasSnapshot: false,
|
|
266
|
+
files: []
|
|
267
|
+
}));
|
|
268
|
+
return () => {
|
|
269
|
+
alive = false;
|
|
270
|
+
};
|
|
271
|
+
}, [
|
|
272
|
+
run.id,
|
|
273
|
+
run.queued,
|
|
274
|
+
run.running
|
|
275
|
+
]);
|
|
276
|
+
if (run.queued || run.running) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
277
|
+
label: "Changes",
|
|
278
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
279
|
+
className: "text-body text-disabled",
|
|
280
|
+
children: "File changes appear once the run finishes."
|
|
281
|
+
})
|
|
282
|
+
});
|
|
283
|
+
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
284
|
+
label: "Changes",
|
|
285
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Loading, {})
|
|
286
|
+
});
|
|
287
|
+
if (!data.hasSnapshot) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
288
|
+
label: "Changes",
|
|
289
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
290
|
+
className: "text-body text-disabled",
|
|
291
|
+
children: "No file snapshot was recorded for this run."
|
|
292
|
+
})
|
|
293
|
+
});
|
|
294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
295
|
+
label: "Changes",
|
|
296
|
+
count: data.files.length,
|
|
297
|
+
children: data.files.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
298
|
+
className: "text-body text-disabled",
|
|
299
|
+
children: "No files changed since the previous run."
|
|
300
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiffView, { files: data.files })
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function RunningState({ run }) {
|
|
304
|
+
const elapsed = dur(Math.max(0, Date.now() - Date.parse(run.ts)));
|
|
305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
306
|
+
label: "Activity",
|
|
307
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
308
|
+
className: "flex items-center gap-2.5 text-body text-secondary",
|
|
309
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
310
|
+
"aria-hidden": true,
|
|
311
|
+
className: "size-2 shrink-0 rounded-full",
|
|
312
|
+
style: runPulseStyle
|
|
313
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
314
|
+
"Run in progress",
|
|
315
|
+
elapsed ? ` for ${elapsed}` : "",
|
|
316
|
+
"."
|
|
317
|
+
] })]
|
|
318
|
+
})
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
function SessionId({ id }) {
|
|
322
|
+
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
324
|
+
type: "button",
|
|
325
|
+
onClick: () => {
|
|
326
|
+
navigator.clipboard?.writeText(id);
|
|
327
|
+
setCopied(true);
|
|
328
|
+
setTimeout(() => setCopied(false), 1200);
|
|
329
|
+
},
|
|
330
|
+
title: "Copy session id",
|
|
331
|
+
className: "inline-flex max-w-full cursor-pointer items-center gap-1.5 border-none bg-transparent p-0 text-left font-mono text-label text-secondary transition-colors hover:text-display",
|
|
332
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
333
|
+
className: "truncate",
|
|
334
|
+
children: id
|
|
335
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
336
|
+
"aria-hidden": true,
|
|
337
|
+
className: "shrink-0 text-micro text-disabled",
|
|
338
|
+
children: copied ? "✓ copied" : "copy"
|
|
339
|
+
})]
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
/** How many older pages to walk back looking for a run not in the latest set
|
|
343
|
+
* (cursor paging via loadOlderRuns) before giving up — a safety bound so a bad
|
|
344
|
+
* runId can't page the whole history. 64 × 100/page covers very deep histories. */
|
|
345
|
+
var MAX_OLDER_PAGES = 64;
|
|
346
|
+
/**
|
|
347
|
+
* Run detail PAGE body — its own route (`/loops/$loopId/runs/$runId`). Resolves
|
|
348
|
+
* the run by id from the loop's detail payload (reusing getJobDetail, no new
|
|
349
|
+
* backend); a run older than that latest window is located by paging backward
|
|
350
|
+
* with the existing `loadOlderRuns` cursor fn. Self-polls while it's in flight.
|
|
351
|
+
*
|
|
352
|
+
* Layout mirrors the loop detail page: a header card (name / status pill / chips
|
|
353
|
+
* + action toolbar), then a two-column main — the meaty content (Changes diff +
|
|
354
|
+
* Execution trace + Report) in a wide `minmax(0,1fr)` column, the run metadata in
|
|
355
|
+
* a capped right rail. `min-w-0` everywhere + panes that scroll their own wide
|
|
356
|
+
* content keep the page free of horizontal scroll at any width.
|
|
357
|
+
*/
|
|
358
|
+
function RunDetailView({ loopId, runId }) {
|
|
359
|
+
const [detail, setDetail] = (0, import_react.useState)(null);
|
|
360
|
+
const [olderRun, setOlderRun] = (0, import_react.useState)(null);
|
|
361
|
+
const [searchDone, setSearchDone] = (0, import_react.useState)(false);
|
|
362
|
+
const [err, setErr] = (0, import_react.useState)(null);
|
|
363
|
+
const load = (0, import_react.useCallback)(async () => {
|
|
364
|
+
try {
|
|
365
|
+
setDetail(await getJobDetail({ data: loopId }));
|
|
366
|
+
setErr(null);
|
|
367
|
+
} catch (e) {
|
|
368
|
+
setErr(String(e));
|
|
369
|
+
}
|
|
370
|
+
}, [loopId]);
|
|
371
|
+
const poll = (0, import_react.useCallback)(async () => {
|
|
372
|
+
try {
|
|
373
|
+
setDetail(await getJobDetail({ data: loopId }));
|
|
374
|
+
} catch {}
|
|
375
|
+
}, [loopId]);
|
|
376
|
+
(0, import_react.useEffect)(() => {
|
|
377
|
+
setDetail(null);
|
|
378
|
+
setOlderRun(null);
|
|
379
|
+
setSearchDone(false);
|
|
380
|
+
setErr(null);
|
|
381
|
+
load();
|
|
382
|
+
}, [
|
|
383
|
+
loopId,
|
|
384
|
+
runId,
|
|
385
|
+
load
|
|
386
|
+
]);
|
|
387
|
+
const run = detail?.runs.find((r) => r.id === runId) ?? olderRun;
|
|
388
|
+
(0, import_react.useEffect)(() => {
|
|
389
|
+
if (!detail || run || searchDone) return;
|
|
390
|
+
let alive = true;
|
|
391
|
+
(async () => {
|
|
392
|
+
try {
|
|
393
|
+
let cursor = detail.runs.length ? detail.runs[detail.runs.length - 1].ts : (/* @__PURE__ */ new Date()).toISOString();
|
|
394
|
+
for (let i = 0; i < MAX_OLDER_PAGES && alive; i++) {
|
|
395
|
+
const page = await loadOlderRuns({ data: {
|
|
396
|
+
loopId,
|
|
397
|
+
beforeTs: cursor,
|
|
398
|
+
limit: 100
|
|
399
|
+
} });
|
|
400
|
+
if (!page.length) break;
|
|
401
|
+
const hit = page.find((r) => r.id === runId);
|
|
402
|
+
if (hit) {
|
|
403
|
+
if (alive) setOlderRun(hit);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
cursor = page[0].ts;
|
|
407
|
+
}
|
|
408
|
+
} finally {
|
|
409
|
+
if (alive) setSearchDone(true);
|
|
410
|
+
}
|
|
411
|
+
})();
|
|
412
|
+
return () => {
|
|
413
|
+
alive = false;
|
|
414
|
+
};
|
|
415
|
+
}, [
|
|
416
|
+
detail,
|
|
417
|
+
run,
|
|
418
|
+
searchDone,
|
|
419
|
+
loopId,
|
|
420
|
+
runId
|
|
421
|
+
]);
|
|
422
|
+
const running = !!(run?.queued || run?.running);
|
|
423
|
+
(0, import_react.useEffect)(() => {
|
|
424
|
+
if (!running) return;
|
|
425
|
+
const t = setInterval(() => void poll(), 3e3);
|
|
426
|
+
return () => clearInterval(t);
|
|
427
|
+
}, [running, poll]);
|
|
428
|
+
async function onStop() {
|
|
429
|
+
if (!run) return;
|
|
430
|
+
if (!confirm("Stop this run? If it is running, Pievo will ask the daemon to terminate it.")) return;
|
|
431
|
+
const r = await stopRun({ data: run.id });
|
|
432
|
+
if (r?.error) {
|
|
433
|
+
alert(`Stop failed: ${r.error}`);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
await load();
|
|
437
|
+
}
|
|
438
|
+
if (err) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadErrorCard, {
|
|
439
|
+
title: "Couldn't load this run.",
|
|
440
|
+
detail: err,
|
|
441
|
+
onRetry: () => void load()
|
|
442
|
+
});
|
|
443
|
+
if (!detail || !run && !searchDone) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Loading, {});
|
|
444
|
+
if (!run) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
445
|
+
className: "rounded-card border border-hairline bg-surface px-6 py-10 text-center shadow-card",
|
|
446
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
447
|
+
className: "text-[14px] text-secondary",
|
|
448
|
+
children: "This run is no longer available."
|
|
449
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
|
|
450
|
+
to: "/loops/$loopId",
|
|
451
|
+
params: { loopId },
|
|
452
|
+
className: "mt-3 inline-block text-label font-medium text-interactive underline underline-offset-2 hover:text-display",
|
|
453
|
+
children: "← Back to the loop"
|
|
454
|
+
})]
|
|
455
|
+
});
|
|
456
|
+
const jobName = detail.summary.name;
|
|
457
|
+
const roleChip = run.role || null;
|
|
458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
|
|
459
|
+
className: "rounded-card border border-hairline bg-surface px-6 pb-5 pt-[22px] shadow-card",
|
|
460
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
461
|
+
className: "flex flex-wrap items-start justify-between gap-x-6 gap-y-4",
|
|
462
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
463
|
+
className: "min-w-0",
|
|
464
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
465
|
+
className: "flex flex-wrap items-center gap-3",
|
|
466
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h1", {
|
|
467
|
+
className: "text-[26px] font-medium leading-tight tracking-tight text-display",
|
|
468
|
+
children: ["Run · ", jobName]
|
|
469
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusPill, {
|
|
470
|
+
run,
|
|
471
|
+
colorText: true
|
|
472
|
+
})]
|
|
473
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
474
|
+
className: "mt-2.5 flex flex-wrap items-center gap-x-2.5 gap-y-1.5 text-meta text-secondary",
|
|
475
|
+
children: [
|
|
476
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
477
|
+
className: "text-primary",
|
|
478
|
+
children: fmt(run.ts)
|
|
479
|
+
}),
|
|
480
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
481
|
+
className: "text-wire",
|
|
482
|
+
children: "·"
|
|
483
|
+
}),
|
|
484
|
+
roleChip && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pill, { children: roleChip }),
|
|
485
|
+
run.durationMs != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pill, {
|
|
486
|
+
tone: "ink",
|
|
487
|
+
children: dur(run.durationMs)
|
|
488
|
+
}),
|
|
489
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
490
|
+
className: "font-mono text-disabled",
|
|
491
|
+
children: run.id
|
|
492
|
+
})
|
|
493
|
+
]
|
|
494
|
+
})]
|
|
495
|
+
})
|
|
496
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
497
|
+
className: "mt-5 flex flex-wrap gap-2.5 border-t border-hairline pt-4",
|
|
498
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
|
|
499
|
+
to: "/loops/$loopId",
|
|
500
|
+
params: { loopId },
|
|
501
|
+
className: btn,
|
|
502
|
+
children: "View the whole loop →"
|
|
503
|
+
}), (run.queued || run.running) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
504
|
+
type: "button",
|
|
505
|
+
onClick: onStop,
|
|
506
|
+
className: btnDanger,
|
|
507
|
+
disabled: !!run.running && detail.machine.daemonProtocol !== 2,
|
|
508
|
+
title: run.running && detail.machine.daemonProtocol !== 2 ? "Daemon upgrade required to stop a running process. Run `npm install -g @kky42/pievo@latest`, then `pievo daemon restart`." : void 0,
|
|
509
|
+
children: "Stop run"
|
|
510
|
+
})]
|
|
511
|
+
})]
|
|
512
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
513
|
+
className: "mt-6 grid grid-cols-1 gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(300px,360px)]",
|
|
514
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
515
|
+
className: "flex min-w-0 flex-col gap-6",
|
|
516
|
+
children: [
|
|
517
|
+
run.queued ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
518
|
+
label: "Activity",
|
|
519
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
520
|
+
className: "text-body text-secondary",
|
|
521
|
+
children: "Queued; it starts when this loop is free and the machine polls."
|
|
522
|
+
})
|
|
523
|
+
}) : run.running ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunningState, { run }) : null,
|
|
524
|
+
run.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
525
|
+
label: "Report",
|
|
526
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
527
|
+
className: "whitespace-pre-wrap break-words rounded-control border border-hairline bg-raised px-4 py-3.5 text-body leading-relaxed text-primary",
|
|
528
|
+
children: run.message
|
|
529
|
+
})
|
|
530
|
+
}),
|
|
531
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Changes, { run }),
|
|
532
|
+
run.control && run.control.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
533
|
+
label: "Control actions",
|
|
534
|
+
count: run.control.length,
|
|
535
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
536
|
+
className: "space-y-1.5",
|
|
537
|
+
children: run.control.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", {
|
|
538
|
+
className: "flex flex-wrap items-baseline gap-x-2 gap-y-0.5 font-mono text-label",
|
|
539
|
+
children: [
|
|
540
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
541
|
+
className: "text-display",
|
|
542
|
+
children: c.command
|
|
543
|
+
}),
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
545
|
+
className: "min-w-0 break-all text-secondary",
|
|
546
|
+
children: JSON.stringify(c.args)
|
|
547
|
+
}),
|
|
548
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
549
|
+
"aria-hidden": true,
|
|
550
|
+
className: "text-wire",
|
|
551
|
+
children: "→"
|
|
552
|
+
}),
|
|
553
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
554
|
+
className: "text-primary",
|
|
555
|
+
children: c.result
|
|
556
|
+
}),
|
|
557
|
+
c.detail && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
558
|
+
className: "text-disabled",
|
|
559
|
+
children: [
|
|
560
|
+
"(",
|
|
561
|
+
c.detail,
|
|
562
|
+
")"
|
|
563
|
+
]
|
|
564
|
+
})
|
|
565
|
+
]
|
|
566
|
+
}, i))
|
|
567
|
+
})
|
|
568
|
+
}),
|
|
569
|
+
run.finalText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
570
|
+
label: "Final output",
|
|
571
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
572
|
+
className: "whitespace-pre-wrap break-words text-body text-primary",
|
|
573
|
+
children: run.finalText
|
|
574
|
+
})
|
|
575
|
+
})
|
|
576
|
+
]
|
|
577
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
578
|
+
className: "flex min-w-0 flex-col gap-6",
|
|
579
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, {
|
|
580
|
+
label: "Details",
|
|
581
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
582
|
+
className: "space-y-3.5",
|
|
583
|
+
children: [
|
|
584
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
585
|
+
k: "State",
|
|
586
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusPill, {
|
|
587
|
+
run,
|
|
588
|
+
colorText: true
|
|
589
|
+
})
|
|
590
|
+
}),
|
|
591
|
+
run.status && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
592
|
+
k: "Status",
|
|
593
|
+
children: run.status
|
|
594
|
+
}),
|
|
595
|
+
run.durationMs != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
596
|
+
k: "Duration",
|
|
597
|
+
children: dur(run.durationMs)
|
|
598
|
+
}),
|
|
599
|
+
run.exitCode != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
600
|
+
k: "Exit code",
|
|
601
|
+
children: run.exitCode
|
|
602
|
+
}),
|
|
603
|
+
run.usage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
604
|
+
k: "Token usage",
|
|
605
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
606
|
+
className: "text-disabled",
|
|
607
|
+
children: [
|
|
608
|
+
fnum((run.usage.inputTokens ?? 0) + (run.usage.cacheReadTokens ?? 0) + (run.usage.cacheCreationTokens ?? 0)),
|
|
609
|
+
" in · ",
|
|
610
|
+
fnum(run.usage.outputTokens ?? 0),
|
|
611
|
+
" out"
|
|
612
|
+
]
|
|
613
|
+
})
|
|
614
|
+
}),
|
|
615
|
+
run.state != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
616
|
+
k: "Run state",
|
|
617
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
618
|
+
className: "block break-all font-mono text-label text-secondary",
|
|
619
|
+
children: JSON.stringify(run.state)
|
|
620
|
+
})
|
|
621
|
+
}),
|
|
622
|
+
run.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
623
|
+
k: "Error",
|
|
624
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
625
|
+
className: "break-words",
|
|
626
|
+
style: { color: "var(--color-run-error)" },
|
|
627
|
+
children: run.error
|
|
628
|
+
})
|
|
629
|
+
}),
|
|
630
|
+
run.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
631
|
+
k: "Session",
|
|
632
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionId, { id: run.sessionId })
|
|
633
|
+
})
|
|
634
|
+
]
|
|
635
|
+
})
|
|
636
|
+
})
|
|
637
|
+
})]
|
|
638
|
+
})] });
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Run detail PAGE — `/loops/$loopId/runs/$runId`. A standalone page (the trailing
|
|
642
|
+
* `_` on the `$loopId` segment opts it out of the loop page's component so the run
|
|
643
|
+
* gets its own full surface, deep-linkable + browser-back friendly) rather than a
|
|
644
|
+
* modal or an inline panel. It resolves the run from the loop's detail payload
|
|
645
|
+
* (reusing getJobDetail — no new backend) and reuses the Phase 3 artifact diff.
|
|
646
|
+
*
|
|
647
|
+
* Auth-gated like the dashboard (`/`) so a logged-out/expired DEEP LINK shows the
|
|
648
|
+
* sign-in CTA instead of a raw `loop not found` error from the blocked fetch.
|
|
649
|
+
*/
|
|
650
|
+
function RunDetailPage() {
|
|
651
|
+
const { loopId, runId } = Route.useParams();
|
|
652
|
+
const { auth } = Route.useLoaderData() ?? { auth: { enabled: false } };
|
|
653
|
+
const { data: session, isPending } = useSession();
|
|
654
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", {
|
|
655
|
+
className: "mx-auto max-w-[1360px] px-8 pb-24 pt-10",
|
|
656
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
657
|
+
className: "mb-5",
|
|
658
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
|
|
659
|
+
to: "/loops/$loopId",
|
|
660
|
+
params: { loopId },
|
|
661
|
+
className: "inline-flex items-center gap-1.5 text-label font-medium text-secondary transition-colors hover:text-display",
|
|
662
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
663
|
+
"aria-hidden": true,
|
|
664
|
+
children: "←"
|
|
665
|
+
}), " Back to loop"]
|
|
666
|
+
})
|
|
667
|
+
}), auth?.enabled && !isPending && !session ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SignIn, { callbackURL: `/loops/${loopId}/runs/${runId}` }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunDetailView, {
|
|
668
|
+
loopId,
|
|
669
|
+
runId
|
|
670
|
+
})]
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
//#endregion
|
|
674
|
+
export { RunDetailPage as component };
|