ghostrail 0.12.2 → 0.13.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/dist/agent/claude-code.d.ts.map +1 -1
- package/dist/agent/claude-code.js +15 -5
- package/dist/agent/claude-code.js.map +1 -1
- package/dist/agent/failure.d.ts +19 -0
- package/dist/agent/failure.d.ts.map +1 -1
- package/dist/agent/failure.js +45 -0
- package/dist/agent/failure.js.map +1 -1
- package/dist/board/page.d.ts +1 -1
- package/dist/board/page.d.ts.map +1 -1
- package/dist/board/page.js +27 -2
- package/dist/board/page.js.map +1 -1
- package/dist/board/server.d.ts +8 -4
- package/dist/board/server.d.ts.map +1 -1
- package/dist/board/server.js +50 -4
- package/dist/board/server.js.map +1 -1
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +3 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/loop/budget.d.ts +35 -0
- package/dist/loop/budget.d.ts.map +1 -0
- package/dist/loop/budget.js +42 -0
- package/dist/loop/budget.js.map +1 -0
- package/dist/loop/control.d.ts +15 -0
- package/dist/loop/control.d.ts.map +1 -0
- package/dist/loop/control.js +30 -0
- package/dist/loop/control.js.map +1 -0
- package/dist/loop/engine.d.ts.map +1 -1
- package/dist/loop/engine.js +21 -2
- package/dist/loop/engine.js.map +1 -1
- package/dist/loop/index.d.ts +1 -0
- package/dist/loop/index.d.ts.map +1 -1
- package/dist/loop/index.js +1 -0
- package/dist/loop/index.js.map +1 -1
- package/dist/loop/ports.d.ts +12 -2
- package/dist/loop/ports.d.ts.map +1 -1
- package/dist/loop/watch.d.ts +7 -0
- package/dist/loop/watch.d.ts.map +1 -1
- package/dist/loop/watch.js +14 -0
- package/dist/loop/watch.js.map +1 -1
- package/dist/respond/respond.d.ts.map +1 -1
- package/dist/respond/respond.js +24 -4
- package/dist/respond/respond.js.map +1 -1
- package/dist/respond/store.d.ts +12 -0
- package/dist/respond/store.d.ts.map +1 -1
- package/dist/respond/store.js +22 -1
- package/dist/respond/store.js.map +1 -1
- package/dist/store/file-store.d.ts +2 -0
- package/dist/store/file-store.d.ts.map +1 -1
- package/dist/store/file-store.js +3 -0
- package/dist/store/file-store.js.map +1 -1
- package/package.json +1 -1
- package/templates/code-local/ghostrail.toml +4 -0
- package/templates/content-loop/ghostrail.toml +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/agent/claude-code.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/agent/claude-code.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAc,MAAM,kBAAkB,CAAC;AAKtF,+EAA+E;AAC/E,eAAO,MAAM,WAAW,2BAA2B,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IAC/C,sDAAsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAwBpE;AAYD;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,KAAK;IAO/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IANxC;;;;;OAKG;gBAC0B,UAAU,CAAC,EAAE,MAAM,YAAA;IAE1C,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAoExD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import { describeAgentFailure, describeSilentRun, spokenReason } from "./failure.js";
|
|
2
|
+
import { costFromJson, describeAgentFailure, describeSilentRun, spokenReason } from "./failure.js";
|
|
3
3
|
import { renderPrompt } from "./prompt.js";
|
|
4
4
|
import { parseAgentResult } from "./result.js";
|
|
5
5
|
/** Path, relative to the workspace root, where the agent writes its result. */
|
|
@@ -86,8 +86,13 @@ export class ClaudeCodeAgent {
|
|
|
86
86
|
? {}
|
|
87
87
|
: { env: { HOME: profileDir, CLAUDE_CONFIG_DIR: join(profileDir, ".claude") } }),
|
|
88
88
|
});
|
|
89
|
+
// Read once, before any return, and attached to every one of them. A run
|
|
90
|
+
// that timed out or failed still spent money, and the tick's ceiling is
|
|
91
|
+
// only honest if those count too. A partial envelope simply yields no cost,
|
|
92
|
+
// which the caller charges as an assumption rather than as free.
|
|
93
|
+
const spend = withSpend(costFromJson(run.stdout));
|
|
89
94
|
if (run.timedOut) {
|
|
90
|
-
return { status: "failed", error: "agent timed out" };
|
|
95
|
+
return { ...spend, status: "failed", error: "agent timed out" };
|
|
91
96
|
}
|
|
92
97
|
const raw = await readFile(backend, workspace, RESULT_PATH);
|
|
93
98
|
if (raw !== undefined && raw.trim().length > 0) {
|
|
@@ -100,12 +105,13 @@ export class ClaudeCodeAgent {
|
|
|
100
105
|
if (outcome.status === "noop" && outcome.reason === undefined) {
|
|
101
106
|
const spoken = spokenReason(run.stdout);
|
|
102
107
|
if (spoken !== undefined)
|
|
103
|
-
return { status: "noop", reason: spoken };
|
|
108
|
+
return { ...spend, status: "noop", reason: spoken };
|
|
104
109
|
}
|
|
105
|
-
return outcome;
|
|
110
|
+
return { ...spend, ...outcome };
|
|
106
111
|
}
|
|
107
112
|
if (run.exitCode !== 0) {
|
|
108
113
|
return {
|
|
114
|
+
...spend,
|
|
109
115
|
status: "failed",
|
|
110
116
|
error: describeAgentFailure(run.exitCode, run.stdout, run.stderr),
|
|
111
117
|
};
|
|
@@ -114,7 +120,11 @@ export class ClaudeCodeAgent {
|
|
|
114
120
|
// nothing was reported and nothing should be published, but it is not the
|
|
115
121
|
// same event as an agent that deliberately wrote {"status":"noop"}. Carry
|
|
116
122
|
// what the agent said so the two can be told apart after the fact.
|
|
117
|
-
return { status: "noop", reason: describeSilentRun(run.stdout, run.stderr) };
|
|
123
|
+
return { ...spend, status: "noop", reason: describeSilentRun(run.stdout, run.stderr) };
|
|
118
124
|
}
|
|
119
125
|
}
|
|
126
|
+
/** An optional cost as a spreadable object, so absent stays absent. */
|
|
127
|
+
function withSpend(costUsd) {
|
|
128
|
+
return costUsd === undefined ? {} : { costUsd };
|
|
129
|
+
}
|
|
120
130
|
//# sourceMappingURL=claude-code.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/agent/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/agent/claude-code.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/failure.d.ts
CHANGED
|
@@ -26,6 +26,25 @@ export declare function describeSilentRun(stdout: string, stderr: string): strin
|
|
|
26
26
|
* only account of a silent run anyone gets.
|
|
27
27
|
*/
|
|
28
28
|
export declare function resultFromJson(stdout: string): string | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* The `total_cost_usd` of the agent's output envelope, or undefined.
|
|
31
|
+
*
|
|
32
|
+
* Lives next to {@link resultFromJson} and tries the same two shapes, because
|
|
33
|
+
* both read one field out of the same payload: `--output-format json` puts the
|
|
34
|
+
* envelope in the whole text, `stream-json` puts it on the last non-empty line.
|
|
35
|
+
* Two parsers for one envelope would drift.
|
|
36
|
+
*
|
|
37
|
+
* Undefined covers every way of not knowing: absent, not a number, NaN,
|
|
38
|
+
* infinite, or negative. A non-finite cost poisons every sum it enters, and a
|
|
39
|
+
* negative one would let a single run refund the tick's budget. Zero is a
|
|
40
|
+
* value, not a miss: a run that genuinely cost nothing reported a cost, and the
|
|
41
|
+
* caller charges an assumption for a run that reported none.
|
|
42
|
+
*
|
|
43
|
+
* Never throws. Unparseable output means a missing cost, not a failed run: the
|
|
44
|
+
* work happened, and failing it over its accounting would be worse than not
|
|
45
|
+
* knowing what it spent.
|
|
46
|
+
*/
|
|
47
|
+
export declare function costFromJson(stdout: string): number | undefined;
|
|
29
48
|
/**
|
|
30
49
|
* The one-line error recorded for a failed agent run.
|
|
31
50
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failure.d.ts","sourceRoot":"","sources":["../../src/agent/failure.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,iCAAiC,CAAC;AAK/D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKxE;AAYD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASjE;
|
|
1
|
+
{"version":3,"file":"failure.d.ts","sourceRoot":"","sources":["../../src/agent/failure.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,iCAAiC,CAAC;AAK/D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKxE;AAYD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASjE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAS/D;AAiCD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK7F"}
|
package/dist/agent/failure.js
CHANGED
|
@@ -55,6 +55,51 @@ export function resultFromJson(stdout) {
|
|
|
55
55
|
}
|
|
56
56
|
return undefined;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* The `total_cost_usd` of the agent's output envelope, or undefined.
|
|
60
|
+
*
|
|
61
|
+
* Lives next to {@link resultFromJson} and tries the same two shapes, because
|
|
62
|
+
* both read one field out of the same payload: `--output-format json` puts the
|
|
63
|
+
* envelope in the whole text, `stream-json` puts it on the last non-empty line.
|
|
64
|
+
* Two parsers for one envelope would drift.
|
|
65
|
+
*
|
|
66
|
+
* Undefined covers every way of not knowing: absent, not a number, NaN,
|
|
67
|
+
* infinite, or negative. A non-finite cost poisons every sum it enters, and a
|
|
68
|
+
* negative one would let a single run refund the tick's budget. Zero is a
|
|
69
|
+
* value, not a miss: a run that genuinely cost nothing reported a cost, and the
|
|
70
|
+
* caller charges an assumption for a run that reported none.
|
|
71
|
+
*
|
|
72
|
+
* Never throws. Unparseable output means a missing cost, not a failed run: the
|
|
73
|
+
* work happened, and failing it over its accounting would be worse than not
|
|
74
|
+
* knowing what it spent.
|
|
75
|
+
*/
|
|
76
|
+
export function costFromJson(stdout) {
|
|
77
|
+
const lines = stdout.split("\n").filter((line) => line.trim().length > 0);
|
|
78
|
+
const lastLine = lines[lines.length - 1];
|
|
79
|
+
for (const candidate of [stdout, lastLine]) {
|
|
80
|
+
if (candidate === undefined)
|
|
81
|
+
continue;
|
|
82
|
+
const cost = costField(candidate);
|
|
83
|
+
if (cost !== undefined)
|
|
84
|
+
return cost;
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
/** The usable `total_cost_usd` of one JSON object, or undefined. */
|
|
89
|
+
function costField(text) {
|
|
90
|
+
try {
|
|
91
|
+
const parsed = JSON.parse(text);
|
|
92
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
93
|
+
return undefined;
|
|
94
|
+
const cost = parsed.total_cost_usd;
|
|
95
|
+
if (typeof cost !== "number" || !Number.isFinite(cost) || cost < 0)
|
|
96
|
+
return undefined;
|
|
97
|
+
return cost;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
58
103
|
/** The non-empty string `result` of one JSON object, or undefined. */
|
|
59
104
|
function resultField(text) {
|
|
60
105
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failure.js","sourceRoot":"","sources":["../../src/agent/failure.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"failure.js","sourceRoot":"","sources":["../../src/agent/failure.ts"],"names":[],"mappings":"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"}
|
package/dist/board/page.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** The self-contained board page: polls the read API and renders runs + stats. */
|
|
2
|
-
export declare const PAGE_HTML = "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>ghostrail board</title>\n<style>\n :root { color-scheme: light dark; }\n body { font: 14px/1.5 system-ui, sans-serif; margin: 0; padding: 1.5rem; }\n h1 { font-size: 1.1rem; margin: 0 0 1rem; }\n .stats { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }\n .stat { border: 1px solid #8884; border-radius: 8px; padding: .5rem .75rem; }\n .stat b { display: block; font-size: 1.3rem; }\n table { border-collapse: collapse; width: 100%; }\n th, td { text-align: left; padding: .4rem .6rem; border-bottom: 1px solid #8883; }\n .state { font-weight: 600; }\n .done { color: #2a9d3a; } .failed { color: #d33; } .blocked { color: #d90; }\n .noop, .skipped { opacity: .6; } .muted { opacity: .6; }\n a { color: inherit; }\n</style>\n</head>\n<body>\n<h1>ghostrail board</h1>\n<div class=\"stats\" id=\"stats\"></div>\n<table><thead><tr><th>Run</th><th>Item</th><th>State</th><th>Backend</th><th>Gate</th><th>PR</th><th>When</th></tr></thead>\n<tbody id=\"rows\"></tbody></table>\n<script>\nconst esc = (s) => String(s ?? \"\").replace(/[&<>]/g, (c) => ({ \"&\": \"&\", \"<\": \"<\", \">\": \">\" }[c]));\nasync function refresh() {\n const [runs, stats] = await Promise.all([\n fetch(\"api/runs\").then((r) => r.json()),\n fetch(\"api/stats\").then((r) => r.json()),\n ]);\n document.getElementById(\"stats\").innerHTML = [\n [\"runs\", stats.total],\n [\"success\", (stats.successRate * 100).toFixed(0) + \"%\"],\n [\"PRs\", stats.prCount],\n ].map(([k, v]) => '<div class=\"stat\"><b>' + esc(v) + \"</b>\" + esc(k) + \"</div>\").join(\"\");\n document.getElementById(\"rows\").innerHTML = runs.map((r) => {\n const gate = (r.gate || []).map((s) => (s.exitCode === 0 ? \"\u2713\" : \"\u2717\")).join(\"\");\n const pr = r.prUrl ? '<a href=\"' + esc(r.prUrl) + '\">#' + esc(r.prNumber) + \"</a>\" : \"\";\n const when = r.startedAt ? new Date(r.startedAt).toLocaleString() : \"\";\n const state = esc(r.state || \"in-progress\");\n return \"<tr><td class=muted>\" + esc(r.runId.slice(0, 8)) + \"</td><td>\" + esc(r.title || r.itemId || \"\") +\n '</td><td class=\"state ' + state + '\">' + state + \"</td><td>\" + esc(r.backend || \"\") +\n \"</td><td>\" + gate + \"</td><td>\" + pr + \"</td><td class=muted>\" + esc(when) + \"</td></tr>\";\n }).join(\"\");\n}\nrefresh();\nsetInterval(refresh, 5000);\n</script>\n</body>\n</html>";
|
|
2
|
+
export declare const PAGE_HTML = "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>ghostrail board</title>\n<style>\n :root { color-scheme: light dark; }\n body { font: 14px/1.5 system-ui, sans-serif; margin: 0; padding: 1.5rem; }\n h1 { font-size: 1.1rem; margin: 0 0 1rem; }\n .stats { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }\n .stat { border: 1px solid #8884; border-radius: 8px; padding: .5rem .75rem; }\n .stat b { display: block; font-size: 1.3rem; }\n table { border-collapse: collapse; width: 100%; }\n th, td { text-align: left; padding: .4rem .6rem; border-bottom: 1px solid #8883; }\n .state { font-weight: 600; }\n .done { color: #2a9d3a; } .failed { color: #d33; } .blocked { color: #d90; }\n .noop, .skipped { opacity: .6; } .muted { opacity: .6; }\n a { color: inherit; }\n .toggle { font-size: .8rem; font-weight: normal; margin-left: .75rem; }\n</style>\n</head>\n<body>\n<h1>ghostrail board <label class=\"toggle\"><input type=\"checkbox\" id=\"running\" /> running</label></h1>\n<div class=\"stats\" id=\"stats\"></div>\n<table><thead><tr><th>Run</th><th>Item</th><th>State</th><th>Backend</th><th>Gate</th><th>PR</th><th>When</th></tr></thead>\n<tbody id=\"rows\"></tbody></table>\n<script>\nconst esc = (s) => String(s ?? \"\").replace(/[&<>]/g, (c) => ({ \"&\": \"&\", \"<\": \"<\", \">\": \">\" }[c]));\nconst runningBox = document.getElementById(\"running\");\nlet toggling = false;\nrunningBox.addEventListener(\"change\", async () => {\n const wanted = runningBox.checked;\n toggling = true;\n runningBox.disabled = true;\n try {\n const res = await fetch(\"api/control\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ enabled: wanted }),\n });\n if (!res.ok) throw new Error(\"toggle failed\");\n const state = await res.json();\n runningBox.checked = state.enabled;\n } catch {\n runningBox.checked = !wanted;\n } finally {\n runningBox.disabled = false;\n toggling = false;\n }\n});\nasync function refresh() {\n const [runs, stats, control] = await Promise.all([\n fetch(\"api/runs\").then((r) => r.json()),\n fetch(\"api/stats\").then((r) => r.json()),\n fetch(\"api/control\").then((r) => r.json()),\n ]);\n if (!toggling) runningBox.checked = control.enabled;\n document.getElementById(\"stats\").innerHTML = [\n [\"runs\", stats.total],\n [\"success\", (stats.successRate * 100).toFixed(0) + \"%\"],\n [\"PRs\", stats.prCount],\n ].map(([k, v]) => '<div class=\"stat\"><b>' + esc(v) + \"</b>\" + esc(k) + \"</div>\").join(\"\");\n document.getElementById(\"rows\").innerHTML = runs.map((r) => {\n const gate = (r.gate || []).map((s) => (s.exitCode === 0 ? \"\u2713\" : \"\u2717\")).join(\"\");\n const pr = r.prUrl ? '<a href=\"' + esc(r.prUrl) + '\">#' + esc(r.prNumber) + \"</a>\" : \"\";\n const when = r.startedAt ? new Date(r.startedAt).toLocaleString() : \"\";\n const state = esc(r.state || \"in-progress\");\n return \"<tr><td class=muted>\" + esc(r.runId.slice(0, 8)) + \"</td><td>\" + esc(r.title || r.itemId || \"\") +\n '</td><td class=\"state ' + state + '\">' + state + \"</td><td>\" + esc(r.backend || \"\") +\n \"</td><td>\" + gate + \"</td><td>\" + pr + \"</td><td class=muted>\" + esc(when) + \"</td></tr>\";\n }).join(\"\");\n}\nrefresh();\nsetInterval(refresh, 5000);\n</script>\n</body>\n</html>";
|
|
3
3
|
//# sourceMappingURL=page.d.ts.map
|
package/dist/board/page.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/board/page.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/board/page.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,eAAO,MAAM,SAAS,y8GA6Ed,CAAC"}
|
package/dist/board/page.js
CHANGED
|
@@ -18,20 +18,45 @@ export const PAGE_HTML = `<!doctype html>
|
|
|
18
18
|
.done { color: #2a9d3a; } .failed { color: #d33; } .blocked { color: #d90; }
|
|
19
19
|
.noop, .skipped { opacity: .6; } .muted { opacity: .6; }
|
|
20
20
|
a { color: inherit; }
|
|
21
|
+
.toggle { font-size: .8rem; font-weight: normal; margin-left: .75rem; }
|
|
21
22
|
</style>
|
|
22
23
|
</head>
|
|
23
24
|
<body>
|
|
24
|
-
<h1>ghostrail board</h1>
|
|
25
|
+
<h1>ghostrail board <label class="toggle"><input type="checkbox" id="running" /> running</label></h1>
|
|
25
26
|
<div class="stats" id="stats"></div>
|
|
26
27
|
<table><thead><tr><th>Run</th><th>Item</th><th>State</th><th>Backend</th><th>Gate</th><th>PR</th><th>When</th></tr></thead>
|
|
27
28
|
<tbody id="rows"></tbody></table>
|
|
28
29
|
<script>
|
|
29
30
|
const esc = (s) => String(s ?? "").replace(/[&<>]/g, (c) => ({ "&": "&", "<": "<", ">": ">" }[c]));
|
|
31
|
+
const runningBox = document.getElementById("running");
|
|
32
|
+
let toggling = false;
|
|
33
|
+
runningBox.addEventListener("change", async () => {
|
|
34
|
+
const wanted = runningBox.checked;
|
|
35
|
+
toggling = true;
|
|
36
|
+
runningBox.disabled = true;
|
|
37
|
+
try {
|
|
38
|
+
const res = await fetch("api/control", {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "content-type": "application/json" },
|
|
41
|
+
body: JSON.stringify({ enabled: wanted }),
|
|
42
|
+
});
|
|
43
|
+
if (!res.ok) throw new Error("toggle failed");
|
|
44
|
+
const state = await res.json();
|
|
45
|
+
runningBox.checked = state.enabled;
|
|
46
|
+
} catch {
|
|
47
|
+
runningBox.checked = !wanted;
|
|
48
|
+
} finally {
|
|
49
|
+
runningBox.disabled = false;
|
|
50
|
+
toggling = false;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
30
53
|
async function refresh() {
|
|
31
|
-
const [runs, stats] = await Promise.all([
|
|
54
|
+
const [runs, stats, control] = await Promise.all([
|
|
32
55
|
fetch("api/runs").then((r) => r.json()),
|
|
33
56
|
fetch("api/stats").then((r) => r.json()),
|
|
57
|
+
fetch("api/control").then((r) => r.json()),
|
|
34
58
|
]);
|
|
59
|
+
if (!toggling) runningBox.checked = control.enabled;
|
|
35
60
|
document.getElementById("stats").innerHTML = [
|
|
36
61
|
["runs", stats.total],
|
|
37
62
|
["success", (stats.successRate * 100).toFixed(0) + "%"],
|
package/dist/board/page.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/board/page.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,CAAC,MAAM,SAAS,GAAG
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/board/page.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6EjB,CAAC"}
|
package/dist/board/server.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export type Route = {
|
|
|
15
15
|
} | {
|
|
16
16
|
kind: "artifact";
|
|
17
17
|
hash: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "control";
|
|
18
20
|
} | {
|
|
19
21
|
kind: "notfound";
|
|
20
22
|
};
|
|
@@ -36,10 +38,12 @@ export interface BoardOptions {
|
|
|
36
38
|
/** True for an address only this machine can reach, where a token is optional. */
|
|
37
39
|
export declare function isLoopback(bind: string): boolean;
|
|
38
40
|
/**
|
|
39
|
-
* Build the board's HTTP server over the store: a static page plus a small
|
|
40
|
-
* API (`/api/runs`, `/api/runs/:id`, `/api/runs/:id/events`,
|
|
41
|
-
* `/api/artifacts/:hash`)
|
|
42
|
-
*
|
|
41
|
+
* Build the board's HTTP server over the store: a static page plus a small
|
|
42
|
+
* read API (`/api/runs`, `/api/runs/:id`, `/api/runs/:id/events`,
|
|
43
|
+
* `/api/stats`, `/api/artifacts/:hash`) and one read/write route,
|
|
44
|
+
* `/api/control`, that starts/stops the ghostrail this board serves. When a
|
|
45
|
+
* token is configured (required whenever the bind is not loopback), every
|
|
46
|
+
* request must present it.
|
|
43
47
|
*/
|
|
44
48
|
export declare function createBoardServer(store: FileStore, options?: BoardOptions): Server;
|
|
45
49
|
/** A token that is absent, empty, or only whitespace is no token at all. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,MAAM,EAAqC,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,MAAM,EAAqC,MAAM,WAAW,CAAC;AAEjG,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,wBAAwB,CAAC;AAInE,MAAM,MAAM,KAAK,GACb;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAkBlD;AAuBD,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAQD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAqBtF;AAED,4EAA4E;AAC5E;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG5E"}
|
package/dist/board/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createServer } from "node:http";
|
|
2
|
+
import { readControl, writeControl } from "../loop/control.js";
|
|
2
3
|
import { PAGE_HTML } from "./page.js";
|
|
3
4
|
import { computeStats } from "./stats.js";
|
|
4
5
|
/** Map a request pathname to a board route. Pure. */
|
|
@@ -20,11 +21,32 @@ export function parseRoute(pathname) {
|
|
|
20
21
|
}
|
|
21
22
|
if (parts[1] === "stats" && parts.length === 2)
|
|
22
23
|
return { kind: "stats" };
|
|
24
|
+
if (parts[1] === "control" && parts.length === 2)
|
|
25
|
+
return { kind: "control" };
|
|
23
26
|
if (parts[1] === "artifacts" && parts.length === 3) {
|
|
24
27
|
return { kind: "artifact", hash: decodeURIComponent(parts[2] ?? "") };
|
|
25
28
|
}
|
|
26
29
|
return { kind: "notfound" };
|
|
27
30
|
}
|
|
31
|
+
const MAX_CONTROL_BODY_BYTES = 4096;
|
|
32
|
+
/** Read a request body, rejecting once it exceeds a small cap. */
|
|
33
|
+
function readBody(req) {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
let size = 0;
|
|
36
|
+
const chunks = [];
|
|
37
|
+
req.on("data", (chunk) => {
|
|
38
|
+
size += chunk.length;
|
|
39
|
+
if (size > MAX_CONTROL_BODY_BYTES) {
|
|
40
|
+
req.destroy();
|
|
41
|
+
reject(new Error("body too large"));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
chunks.push(chunk);
|
|
45
|
+
});
|
|
46
|
+
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
47
|
+
req.on("error", reject);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
28
50
|
/** True for an address only this machine can reach, where a token is optional. */
|
|
29
51
|
export function isLoopback(bind) {
|
|
30
52
|
return bind === "127.0.0.1" || bind === "::1" || bind === "localhost";
|
|
@@ -35,10 +57,12 @@ function sendJson(res, status, data) {
|
|
|
35
57
|
res.end(body);
|
|
36
58
|
}
|
|
37
59
|
/**
|
|
38
|
-
* Build the board's HTTP server over the store: a static page plus a small
|
|
39
|
-
* API (`/api/runs`, `/api/runs/:id`, `/api/runs/:id/events`,
|
|
40
|
-
* `/api/artifacts/:hash`)
|
|
41
|
-
*
|
|
60
|
+
* Build the board's HTTP server over the store: a static page plus a small
|
|
61
|
+
* read API (`/api/runs`, `/api/runs/:id`, `/api/runs/:id/events`,
|
|
62
|
+
* `/api/stats`, `/api/artifacts/:hash`) and one read/write route,
|
|
63
|
+
* `/api/control`, that starts/stops the ghostrail this board serves. When a
|
|
64
|
+
* token is configured (required whenever the bind is not loopback), every
|
|
65
|
+
* request must present it.
|
|
42
66
|
*/
|
|
43
67
|
export function createBoardServer(store, options = {}) {
|
|
44
68
|
const bind = options.bind ?? "127.0.0.1";
|
|
@@ -113,6 +137,28 @@ async function handle(store, options, req, res) {
|
|
|
113
137
|
case "stats":
|
|
114
138
|
sendJson(res, 200, computeStats(await store.listRuns()));
|
|
115
139
|
return;
|
|
140
|
+
case "control": {
|
|
141
|
+
if (req.method === "POST") {
|
|
142
|
+
let payload;
|
|
143
|
+
try {
|
|
144
|
+
payload = JSON.parse(await readBody(req));
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
sendJson(res, 400, { error: "invalid JSON body" });
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const enabled = typeof payload === "object" && payload !== null && "enabled" in payload
|
|
151
|
+
? payload.enabled
|
|
152
|
+
: undefined;
|
|
153
|
+
if (typeof enabled !== "boolean") {
|
|
154
|
+
sendJson(res, 400, { error: "enabled must be a boolean" });
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
await writeControl(store.dir, { enabled });
|
|
158
|
+
}
|
|
159
|
+
sendJson(res, 200, await readControl(store.dir));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
116
162
|
case "artifact": {
|
|
117
163
|
const blob = await store.getArtifact(route.hash);
|
|
118
164
|
if (blob === undefined) {
|
package/dist/board/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0D,YAAY,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/commands.js
CHANGED
|
@@ -18,6 +18,7 @@ import { DEFAULT_FACTORY_IMAGE, dockerBuildArgs, dockerDir, parseImageFlags, } f
|
|
|
18
18
|
import { extractPlaceholders, isClean, missingSignals, repoPathFor, } from "../init/drift.js";
|
|
19
19
|
import { classify, hashContent, mergeManifest, readManifest, writeManifest, } from "../init/template.js";
|
|
20
20
|
import { FileLock } from "../lock/file-lock.js";
|
|
21
|
+
import { readControl } from "../loop/control.js";
|
|
21
22
|
import { runTick } from "../loop/engine.js";
|
|
22
23
|
import { watchLoop } from "../loop/watch.js";
|
|
23
24
|
import { respondTick } from "../respond/respond.js";
|
|
@@ -186,10 +187,12 @@ export async function cmdWatch(argv, streams, env = process.env, cwd = process.c
|
|
|
186
187
|
process.once("SIGTERM", onSignal);
|
|
187
188
|
streams.err(`watching every ${watch.intervalLabel}; press Ctrl-C to stop\n`);
|
|
188
189
|
try {
|
|
190
|
+
const controlDir = join(flags.repo, STORE_DIR);
|
|
189
191
|
const ticks = await watchLoop({
|
|
190
192
|
intervalMs: watch.intervalMs,
|
|
191
193
|
signal: controller.signal,
|
|
192
194
|
logger: makeLogger(streams, setup.secrets),
|
|
195
|
+
isEnabled: async () => (await readControl(controlDir)).enabled,
|
|
193
196
|
...(watch.maxTicks === undefined ? {} : { maxTicks: watch.maxTicks }),
|
|
194
197
|
tick: async () => {
|
|
195
198
|
const result = await runTick(setup.deps, setup.config);
|