@kky42/pievo-server 4.1.0 → 5.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 +1 -1
- package/.output/public/assets/{MarkdownView-BuFKr9Jg.js → MarkdownView-T28pBEgh.js} +1 -1
- package/.output/public/assets/{actionUi-BZrLpgHT.js → actionUi-CY207nNM.js} +1 -1
- package/.output/public/assets/app-Cye1TgwS.css +2 -0
- package/.output/public/assets/{index-D0FIKiiW.js → index-BxXrF3gW.js} +3 -3
- package/.output/public/assets/loops._loopId-DuSEcu38.js +2 -0
- package/.output/public/assets/loops._loopId_.runs._runId-vjQaPXEe.js +3 -0
- package/.output/public/assets/{preload-helper-BSxGu4d0.js → preload-helper-B7p1iHUP.js} +2 -2
- package/.output/public/assets/routes-BUMEAWuS.js +1 -0
- package/.output/public/assets/{routes-BIOJZsig.js → routes-BrqOpUEi.js} +1 -1
- package/.output/server/_ssr/{MachinesModal-CLBZxZkq.mjs → MachinesModal-CB8rpDG2.mjs} +60 -29
- package/.output/server/_ssr/{MarkdownView-D1J7ImYF.mjs → MarkdownView-BOe75tli.mjs} +3 -6
- package/.output/server/_ssr/{actionUi-DE-Pb2tv.mjs → actionUi-CPYgZIr7.mjs} +57 -61
- package/.output/server/_ssr/artifactFiles-DLfSRhrV.mjs +67 -0
- package/.output/server/_ssr/{artifactKind-a2oxT2wQ.mjs → artifactKind-C0oXLA23.mjs} +2 -7
- package/.output/server/_ssr/{boot-DmpKtb0A.mjs → boot-jtVCf_pN.mjs} +239 -289
- package/.output/server/_ssr/{lifecycleUi-DEjM8Etm.mjs → lifecycleUi-Bd7_sthp.mjs} +8 -15
- package/.output/server/_ssr/{loopApi-DK1lQPrx.mjs → loopApi-0nR35Kh2.mjs} +12 -18
- package/.output/server/_ssr/{loopProjection-DdFivf7-.mjs → loopProjection-ZNfSmA5e.mjs} +3 -2
- package/.output/server/_ssr/{loops._loopId-DVCvGSEc.mjs → loops._loopId-CcJ3rxCU.mjs} +18 -89
- package/.output/server/_ssr/loops._loopId_.runs._runId-DFlrV3dJ.mjs +11 -0
- package/.output/server/_ssr/{loops._loopId_.runs._runId-BXbTfLlC.mjs → loops._loopId_.runs._runId-XkGF7HKo.mjs} +28 -19
- package/.output/server/_ssr/{machineFns-DLRHgDdS.mjs → machineFns-D-97a_hz.mjs} +6 -20
- package/.output/server/_ssr/{router-BhHsTGqu.mjs → router-CZ9CFWS2.mjs} +22 -31
- package/.output/server/_ssr/{routes-CCallyCT.mjs → routes-BBmuVs6n.mjs} +2 -2
- package/.output/server/_ssr/{routes-ngpX7h8D.mjs → routes-JxTh5mbj.mjs} +2 -2
- package/.output/server/_ssr/{routes-CL2Kef-Q.mjs → routes-fHRtSpkH.mjs} +6 -6
- package/.output/server/_ssr/ssr.mjs +22 -22
- package/.output/server/{_tanstack-start-manifest_v-BPiJ4yWT.mjs → _tanstack-start-manifest_v-C9JsxlwC.mjs} +8 -8
- package/.output/server/drizzle/0002_run_attention.sql +1 -0
- package/.output/server/drizzle/0003_run_status_ok.sql +13 -0
- package/.output/server/drizzle/meta/_journal.json +14 -0
- package/.output/server/index.mjs +49 -49
- package/drizzle/0002_run_attention.sql +1 -0
- package/drizzle/0003_run_status_ok.sql +13 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +1 -1
- package/.output/public/assets/app-x1CeeY7N.css +0 -2
- package/.output/public/assets/loops._loopId-DTkIz4C0.js +0 -2
- package/.output/public/assets/loops._loopId_.runs._runId-CsV2Ih4Z.js +0 -3
- package/.output/public/assets/routes-m4Z90DTR.js +0 -1
- package/.output/server/_ssr/artifactFiles-B0NPRDOR.mjs +0 -52
- package/.output/server/_ssr/loops._loopId_.runs._runId-Dr6E-FA5.mjs +0 -16
|
@@ -11,14 +11,14 @@ import { fileURLToPath } from "node:url";
|
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import os from "node:os";
|
|
13
13
|
import fs$1 from "node:fs/promises";
|
|
14
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/loopTags-
|
|
15
|
-
var
|
|
14
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/loopTags-CI_aMcqh.js
|
|
15
|
+
var loopTags_CI_aMcqh_exports = /* @__PURE__ */ __exportAll$1({
|
|
16
16
|
$: () => loopIdsWithSnapshots,
|
|
17
|
-
$t: () =>
|
|
17
|
+
$t: () => logger_exports,
|
|
18
18
|
A: () => enqueueRun,
|
|
19
19
|
At: () => updateMachine,
|
|
20
20
|
B: () => getRun,
|
|
21
|
-
Bt: () =>
|
|
21
|
+
Bt: () => loopFileIssue,
|
|
22
22
|
C: () => buildLoopManifest,
|
|
23
23
|
Ct: () => setMachineOnline,
|
|
24
24
|
D: () => createLoop,
|
|
@@ -26,47 +26,47 @@ var loopTags_CnVLi70h_exports = /* @__PURE__ */ __exportAll$1({
|
|
|
26
26
|
E: () => countRuns,
|
|
27
27
|
Et: () => stopLoop,
|
|
28
28
|
F: () => getArtifactFile,
|
|
29
|
-
Ft: () =>
|
|
29
|
+
Ft: () => LoopFiles,
|
|
30
30
|
G: () => initializeCronCadence,
|
|
31
|
-
Gt: () =>
|
|
31
|
+
Gt: () => createBlobStore,
|
|
32
32
|
H: () => getTerminalReportIncidents,
|
|
33
|
-
Ht: () =>
|
|
33
|
+
Ht: () => loopFiles_exports,
|
|
34
34
|
I: () => getExactTerminalReportIncident,
|
|
35
|
-
It: () =>
|
|
35
|
+
It: () => MEMORY_CHAR_CAP,
|
|
36
36
|
J: () => listLoops,
|
|
37
|
-
Jt: () =>
|
|
37
|
+
Jt: () => runMigrations,
|
|
38
38
|
K: () => lastRun,
|
|
39
|
-
Kt: () =>
|
|
39
|
+
Kt: () => closeClient,
|
|
40
40
|
L: () => getLoop,
|
|
41
|
-
Lt: () =>
|
|
41
|
+
Lt: () => MEMORY_FILE,
|
|
42
42
|
M: () => finalizeRunningRun,
|
|
43
|
-
Mt: () =>
|
|
43
|
+
Mt: () => ARTIFACT_EXTENSIONS,
|
|
44
44
|
N: () => forceDeleteLoop,
|
|
45
|
-
Nt: () =>
|
|
45
|
+
Nt: () => EMPTY_SHA256,
|
|
46
46
|
O: () => createMachine,
|
|
47
47
|
Ot: () => tryDeleteLoop,
|
|
48
48
|
P: () => forceDeleteMachine,
|
|
49
|
-
Pt: () =>
|
|
49
|
+
Pt: () => LOOP_FILE_BYTE_CAP,
|
|
50
50
|
Q: () => liveBlobRefs,
|
|
51
|
-
Qt: () =>
|
|
51
|
+
Qt: () => logger,
|
|
52
52
|
R: () => getMachine,
|
|
53
|
-
Rt: () =>
|
|
53
|
+
Rt: () => fileLimitLabel,
|
|
54
54
|
S: () => blobSizes,
|
|
55
55
|
St: () => runningRunsForMachine,
|
|
56
56
|
T: () => countRunSnapshots,
|
|
57
57
|
Tt: () => startLoop,
|
|
58
58
|
U: () => hasPendingRun,
|
|
59
|
-
Ut: () =>
|
|
59
|
+
Ut: () => sha256Buf,
|
|
60
60
|
V: () => getRunSnapshot,
|
|
61
|
-
Vt: () =>
|
|
61
|
+
Vt: () => loopFileNames,
|
|
62
62
|
W: () => hasRunningRun,
|
|
63
|
-
Wt: () =>
|
|
63
|
+
Wt: () => validArtifactName,
|
|
64
64
|
X: () => listRuns,
|
|
65
|
-
Xt: () =>
|
|
65
|
+
Xt: () => CODING_AGENTS,
|
|
66
66
|
Y: () => listMachines,
|
|
67
|
-
Yt: () =>
|
|
67
|
+
Yt: () => runs,
|
|
68
68
|
Z: () => listRunsBefore,
|
|
69
|
-
Zt: () =>
|
|
69
|
+
Zt: () => coerceCodingAgent,
|
|
70
70
|
_: () => acknowledgeRetiredReport,
|
|
71
71
|
_t: () => releaseAbsentReconciliations,
|
|
72
72
|
a: () => TERMINAL_GRACE_MS,
|
|
@@ -77,7 +77,7 @@ var loopTags_CnVLi70h_exports = /* @__PURE__ */ __exportAll$1({
|
|
|
77
77
|
ct: () => putRunSnapshot,
|
|
78
78
|
d: () => readNewIdempotency,
|
|
79
79
|
dt: () => reclaimRun,
|
|
80
|
-
en: () =>
|
|
80
|
+
en: () => BLOB_GC_GRACE_MS,
|
|
81
81
|
et: () => loopsForMachine,
|
|
82
82
|
f: () => recordNewIdempotency,
|
|
83
83
|
ft: () => reconcileReclaimedRun,
|
|
@@ -96,19 +96,20 @@ var loopTags_CnVLi70h_exports = /* @__PURE__ */ __exportAll$1({
|
|
|
96
96
|
m: () => retireLease,
|
|
97
97
|
mt: () => recordBlob,
|
|
98
98
|
n: () => isOutdated,
|
|
99
|
+
nn: () => __exportAll,
|
|
99
100
|
nt: () => pauseLoop,
|
|
100
101
|
o: () => connectKeyValid,
|
|
101
102
|
ot: () => pruneRunSnapshots,
|
|
102
103
|
p: () => resolveLease,
|
|
103
104
|
pt: () => reconciliationStatesForRuns,
|
|
104
105
|
q: () => listArtifacts,
|
|
105
|
-
qt: () =>
|
|
106
|
+
qt: () => db,
|
|
106
107
|
r: () => isValidSemver,
|
|
107
108
|
rt: () => pauseLoopState,
|
|
108
109
|
s: () => isDeviceTokenShape,
|
|
109
110
|
st: () => putReportReceiptIfAbsent,
|
|
110
111
|
t: () => validateLoopTags,
|
|
111
|
-
tn: () =>
|
|
112
|
+
tn: () => GC_INTERVAL_MS,
|
|
112
113
|
tt: () => openRuns,
|
|
113
114
|
u: () => pruneExpiredLeases,
|
|
114
115
|
ut: () => recentLoopUsage,
|
|
@@ -121,7 +122,7 @@ var loopTags_CnVLi70h_exports = /* @__PURE__ */ __exportAll$1({
|
|
|
121
122
|
y: () => advanceDueSchedules,
|
|
122
123
|
yt: () => requestDeleteLoop,
|
|
123
124
|
z: () => getReportReceipt,
|
|
124
|
-
zt: () =>
|
|
125
|
+
zt: () => isValidHash
|
|
125
126
|
});
|
|
126
127
|
var import_pino = /* @__PURE__ */ __toESM(require_pino());
|
|
127
128
|
var import_pino_pretty = /* @__PURE__ */ __toESM(require_pino_pretty());
|
|
@@ -153,9 +154,9 @@ var BLOB_GC_GRACE_MS = 3600 * 1e3;
|
|
|
153
154
|
/** Storage-maintenance cadence (prune snapshots, then GC blobs). 15 minutes. */
|
|
154
155
|
var GC_INTERVAL_MS = 900 * 1e3;
|
|
155
156
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
157
|
+
* pino-pretty as a synchronous destination stream (not a worker-thread transport)
|
|
158
|
+
* so logs flush before process.exit() in the one-shot CLIs. Writes to stderr so
|
|
159
|
+
* stdout carries only CLI output.
|
|
159
160
|
*/
|
|
160
161
|
var logger_exports = /* @__PURE__ */ __exportAll({ logger: () => logger });
|
|
161
162
|
var level = (process.env.PIEVO_LOG_LEVEL || "info").toLowerCase();
|
|
@@ -166,17 +167,9 @@ var stream = (0, import_pino_pretty.default)({
|
|
|
166
167
|
ignore: "pid,hostname"
|
|
167
168
|
});
|
|
168
169
|
var logger = (0, import_pino.default)({ level }, stream);
|
|
169
|
-
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* integration lands; execution itself is real for every value.
|
|
173
|
-
*
|
|
174
|
-
* Runtime SINGLE SOURCE (anti-drift): every server consumer DERIVES from this
|
|
175
|
-
* array — the `CodingAgent` type here, the `db/schema.ts` `CodingAgent` type AND
|
|
176
|
-
* the `loops.agent` column enum, the edit validator (`coerceCodingAgent`), and the
|
|
177
|
-
* web agent `<select>` (LoopForm). So widening the set is a one-line edit HERE with
|
|
178
|
-
* no other server change (the daemon's own enum in `packages/daemon/src/create.ts`
|
|
179
|
-
* is a separate package, widened alongside). */
|
|
170
|
+
/** Single source for coding agents: server types, the `loops.agent` column enum,
|
|
171
|
+
* validators, and the dashboard select all derive from this array. The daemon
|
|
172
|
+
* keeps its own copy in `packages/daemon/src/create.ts`; widen both together. */
|
|
180
173
|
var CODING_AGENTS = [
|
|
181
174
|
"claude-code",
|
|
182
175
|
"codex",
|
|
@@ -196,10 +189,6 @@ var RESERVED_LOOP_TAGS = [
|
|
|
196
189
|
* Pievo is single-user: no row carries an owner. Timestamp values are ISO
|
|
197
190
|
* strings; JSON columns use `jsonb().$type<>()`.
|
|
198
191
|
*/
|
|
199
|
-
/** `skipped`: a pending run retired without executing (pause/retention cleanup,
|
|
200
|
-
* queue coalescing, or the offline catch-up window elapsed).
|
|
201
|
-
* Neither success nor failure — excluded from the failure streak (it rides
|
|
202
|
-
* phase `canceled`, and the streak counts only phase `error`). */
|
|
203
192
|
var machines = pgTable("machines", {
|
|
204
193
|
id: text("id").primaryKey(),
|
|
205
194
|
name: text("name").notNull(),
|
|
@@ -228,11 +217,8 @@ var loops = pgTable("loops", {
|
|
|
228
217
|
name: text("name").notNull(),
|
|
229
218
|
tags: text("tags").array().notNull().default(sql`ARRAY[]::text[]`),
|
|
230
219
|
prompt: text("prompt").notNull(),
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
statusBlock: text("status_block").notNull(),
|
|
234
|
-
/** Configured artifact file names (`.md`/`.html`), in addition to the
|
|
235
|
-
* always-present MEMORY.md. See `gateway/loopFiles.ts`. */
|
|
220
|
+
/** Configured artifact names, in addition to the always-present MEMORY.md.
|
|
221
|
+
* See `gateway/loopFiles.ts`. */
|
|
236
222
|
artifacts: jsonb("artifacts").$type().notNull().default([]),
|
|
237
223
|
cron: text("cron").notNull(),
|
|
238
224
|
scheduleMode: text("schedule_mode", { enum: ["cron", "continuous"] }).notNull(),
|
|
@@ -249,11 +235,8 @@ var loops = pgTable("loops", {
|
|
|
249
235
|
pauseCause: jsonb("pause_cause").$type(),
|
|
250
236
|
model: text("model"),
|
|
251
237
|
reasoningEffort: text("reasoning_effort"),
|
|
252
|
-
/**
|
|
253
|
-
*
|
|
254
|
-
* `codex` → `codex exec`, `pi` → Pi print mode). Measured from the creating CLI's env when
|
|
255
|
-
* detectable, else the declared/selected value. The text column carries
|
|
256
|
-
* both a TypeScript enum and a database CHECK constraint. */
|
|
238
|
+
/** The daemon launches this agent for every run (`buildAgentSpawn`). Enforced by
|
|
239
|
+
* both the TypeScript enum and a database CHECK constraint. */
|
|
257
240
|
agent: text("agent", { enum: CODING_AGENTS }).notNull(),
|
|
258
241
|
enabled: boolean("enabled").notNull().default(true),
|
|
259
242
|
nextRunAt: text("next_run_at"),
|
|
@@ -281,6 +264,9 @@ var runs = pgTable("runs", {
|
|
|
281
264
|
model: text("model"),
|
|
282
265
|
reasoningEffort: text("reasoning_effort"),
|
|
283
266
|
runIndex: integer("run_index"),
|
|
267
|
+
/** A pending run retired without executing (pause, retention cleanup, queue
|
|
268
|
+
* coalescing, or an elapsed offline catch-up window) is `canceled`, not `error`,
|
|
269
|
+
* so it never counts toward the failure streak. */
|
|
284
270
|
phase: text("phase", { enum: [
|
|
285
271
|
"pending",
|
|
286
272
|
"running",
|
|
@@ -294,12 +280,11 @@ var runs = pgTable("runs", {
|
|
|
294
280
|
ts: text("ts").notNull(),
|
|
295
281
|
createdAt: text("created_at").notNull().default(sql`CURRENT_TIMESTAMP::text`),
|
|
296
282
|
updatedAt: text("updated_at").notNull().default(sql`CURRENT_TIMESTAMP::text`),
|
|
297
|
-
status: text("status", { enum: [
|
|
298
|
-
"keep",
|
|
299
|
-
"no-change",
|
|
300
|
-
"block"
|
|
301
|
-
] }),
|
|
283
|
+
status: text("status", { enum: ["ok", "block"] }),
|
|
302
284
|
message: text("message"),
|
|
285
|
+
/** Owner-facing reason from the final response's ATTENTION line. Independent
|
|
286
|
+
* of status: it never pauses the loop. */
|
|
287
|
+
attention: text("attention"),
|
|
303
288
|
durationMs: integer("duration_ms"),
|
|
304
289
|
exitCode: integer("exit_code"),
|
|
305
290
|
finalText: text("final_text"),
|
|
@@ -329,7 +314,8 @@ var runs = pgTable("runs", {
|
|
|
329
314
|
check("runs_agent_check", sql`${t.agent} IS NULL OR ${t.agent} IN ('claude-code', 'codex', 'pi')`),
|
|
330
315
|
check("runs_phase_check", sql`${t.phase} IN ('pending', 'running', 'done', 'error', 'canceled')`),
|
|
331
316
|
check("runs_requested_by_check", sql`${t.requestedBy} IN ('owner', 'system')`),
|
|
332
|
-
check("runs_status_check", sql`${t.status} IS NULL OR ${t.status} IN ('
|
|
317
|
+
check("runs_status_check", sql`${t.status} IS NULL OR ${t.status} IN ('ok', 'block')`),
|
|
318
|
+
check("runs_done_status_check", sql`(${t.phase} = 'done') = (${t.status} IS NOT NULL)`)
|
|
333
319
|
]);
|
|
334
320
|
var runLeases = pgTable("run_leases", {
|
|
335
321
|
tokenHash: text("token_hash").primaryKey(),
|
|
@@ -403,7 +389,6 @@ var blobs = pgTable("blobs", {
|
|
|
403
389
|
var artifactFiles = pgTable("artifact_files", {
|
|
404
390
|
id: text("id").primaryKey(),
|
|
405
391
|
loopId: text("loop_id").notNull(),
|
|
406
|
-
/** Loop file name: MEMORY.md or a configured artifact name. */
|
|
407
392
|
path: text("path").notNull(),
|
|
408
393
|
hash: text("hash"),
|
|
409
394
|
size: integer("size"),
|
|
@@ -486,7 +471,6 @@ function migrationsDir() {
|
|
|
486
471
|
if (fs.existsSync(builtDir)) return builtDir;
|
|
487
472
|
return devDir;
|
|
488
473
|
}
|
|
489
|
-
/** Apply generated migrations in-process (idempotent). */
|
|
490
474
|
async function runMigrations() {
|
|
491
475
|
const dir = migrationsDir();
|
|
492
476
|
if (!fs.existsSync(dir)) return;
|
|
@@ -637,7 +621,7 @@ function createBlobStore() {
|
|
|
637
621
|
* Loop files: a loop's server-owned memory and display artifacts.
|
|
638
622
|
*
|
|
639
623
|
* Every loop has the required `MEMORY.md` plus up to MAX_ARTIFACTS configured
|
|
640
|
-
*
|
|
624
|
+
* text/code artifact names. The server is authoritative: bytes live in the
|
|
641
625
|
* content-addressed BlobStore and the current version of each name is an
|
|
642
626
|
* `artifact_files` row. For each run the daemon downloads the current files into
|
|
643
627
|
* a private run directory, and the terminal report carries the changed versions
|
|
@@ -651,6 +635,7 @@ function createBlobStore() {
|
|
|
651
635
|
*/
|
|
652
636
|
var loopFiles_exports = /* @__PURE__ */ __exportAll({
|
|
653
637
|
ARTIFACT_BYTE_CAP: () => ARTIFACT_BYTE_CAP,
|
|
638
|
+
ARTIFACT_EXTENSIONS: () => ARTIFACT_EXTENSIONS,
|
|
654
639
|
EMPTY_SHA256: () => EMPTY_SHA256,
|
|
655
640
|
LOOP_FILE_BYTE_CAP: () => LOOP_FILE_BYTE_CAP,
|
|
656
641
|
LoopFiles: () => LoopFiles,
|
|
@@ -668,26 +653,107 @@ var MEMORY_FILE = "MEMORY.md";
|
|
|
668
653
|
/** Memory is re-read by every run, so it is bounded in characters (Unicode code
|
|
669
654
|
* points), roughly 2k tokens of prompt context per run. */
|
|
670
655
|
var MEMORY_CHAR_CAP = 8e3;
|
|
671
|
-
/**
|
|
672
|
-
var ARTIFACT_BYTE_CAP =
|
|
656
|
+
/** 256 KB bounds a run's upload and keeps dashboard rendering smooth. */
|
|
657
|
+
var ARTIFACT_BYTE_CAP = 256 * 1024;
|
|
658
|
+
var ARTIFACT_LIMIT_LABEL = `${ARTIFACT_BYTE_CAP / 1024} KB`;
|
|
673
659
|
/** sha256 of zero bytes: the version of a loop file that has never been written. */
|
|
674
660
|
var EMPTY_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
|
675
|
-
|
|
661
|
+
/** Text/code formats accepted as artifacts. Loop files are NUL-free text, so
|
|
662
|
+
* binary formats (images, PDFs, archives) are deliberately absent; `.svg` is
|
|
663
|
+
* text and renders through the hardened inline image route. */
|
|
664
|
+
var ARTIFACT_EXTENSIONS = [
|
|
665
|
+
"md",
|
|
666
|
+
"markdown",
|
|
667
|
+
"mdx",
|
|
668
|
+
"html",
|
|
669
|
+
"htm",
|
|
670
|
+
"txt",
|
|
671
|
+
"text",
|
|
672
|
+
"rst",
|
|
673
|
+
"adoc",
|
|
674
|
+
"org",
|
|
675
|
+
"sh",
|
|
676
|
+
"bash",
|
|
677
|
+
"zsh",
|
|
678
|
+
"fish",
|
|
679
|
+
"ps1",
|
|
680
|
+
"bat",
|
|
681
|
+
"cmd",
|
|
682
|
+
"py",
|
|
683
|
+
"rb",
|
|
684
|
+
"pl",
|
|
685
|
+
"lua",
|
|
686
|
+
"r",
|
|
687
|
+
"js",
|
|
688
|
+
"mjs",
|
|
689
|
+
"cjs",
|
|
690
|
+
"ts",
|
|
691
|
+
"tsx",
|
|
692
|
+
"jsx",
|
|
693
|
+
"go",
|
|
694
|
+
"rs",
|
|
695
|
+
"java",
|
|
696
|
+
"kt",
|
|
697
|
+
"kts",
|
|
698
|
+
"scala",
|
|
699
|
+
"c",
|
|
700
|
+
"h",
|
|
701
|
+
"cc",
|
|
702
|
+
"cpp",
|
|
703
|
+
"hpp",
|
|
704
|
+
"cs",
|
|
705
|
+
"php",
|
|
706
|
+
"swift",
|
|
707
|
+
"dart",
|
|
708
|
+
"ex",
|
|
709
|
+
"exs",
|
|
710
|
+
"erl",
|
|
711
|
+
"hs",
|
|
712
|
+
"clj",
|
|
713
|
+
"cljs",
|
|
714
|
+
"json",
|
|
715
|
+
"jsonl",
|
|
716
|
+
"yaml",
|
|
717
|
+
"yml",
|
|
718
|
+
"toml",
|
|
719
|
+
"xml",
|
|
720
|
+
"csv",
|
|
721
|
+
"tsv",
|
|
722
|
+
"svg",
|
|
723
|
+
"css",
|
|
724
|
+
"scss",
|
|
725
|
+
"sass",
|
|
726
|
+
"less",
|
|
727
|
+
"sql",
|
|
728
|
+
"ini",
|
|
729
|
+
"conf",
|
|
730
|
+
"cfg",
|
|
731
|
+
"env",
|
|
732
|
+
"properties",
|
|
733
|
+
"diff",
|
|
734
|
+
"patch",
|
|
735
|
+
"tex",
|
|
736
|
+
"log"
|
|
737
|
+
];
|
|
738
|
+
var ARTIFACT_EXTENSION_SET = new Set(ARTIFACT_EXTENSIONS);
|
|
739
|
+
var ARTIFACT_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}\.([A-Za-z0-9]{1,16})$/;
|
|
676
740
|
function sha256Buf(bytes) {
|
|
677
741
|
return createHash("sha256").update(bytes).digest("hex");
|
|
678
742
|
}
|
|
679
743
|
function isValidHash(hash) {
|
|
680
744
|
return typeof hash === "string" && /^[0-9a-f]{64}$/.test(hash);
|
|
681
745
|
}
|
|
682
|
-
/** A plain file name (no directories)
|
|
746
|
+
/** A plain text/code file name (no directories) other than MEMORY.md. */
|
|
683
747
|
function validArtifactName(name) {
|
|
684
|
-
|
|
748
|
+
if (typeof name !== "string" || name.toLowerCase() === "MEMORY.md".toLowerCase()) return false;
|
|
749
|
+
const match = ARTIFACT_NAME_RE.exec(name);
|
|
750
|
+
return match !== null && ARTIFACT_EXTENSION_SET.has(match[1].toLowerCase());
|
|
685
751
|
}
|
|
686
752
|
function loopFileNames(loop) {
|
|
687
753
|
return [MEMORY_FILE, ...loop.artifacts];
|
|
688
754
|
}
|
|
689
755
|
function fileLimitLabel(name) {
|
|
690
|
-
return name === "MEMORY.md" ? `${MEMORY_CHAR_CAP} characters` :
|
|
756
|
+
return name === "MEMORY.md" ? `${MEMORY_CHAR_CAP} characters` : ARTIFACT_LIMIT_LABEL;
|
|
691
757
|
}
|
|
692
758
|
/** Why `bytes` cannot become the next version of `name`, or undefined if it can. */
|
|
693
759
|
function loopFileIssue(name, bytes) {
|
|
@@ -697,7 +763,7 @@ function loopFileIssue(name, bytes) {
|
|
|
697
763
|
if (chars > 8e3) return `${name}: ${chars} characters exceeds the ${MEMORY_CHAR_CAP}-character limit`;
|
|
698
764
|
return;
|
|
699
765
|
}
|
|
700
|
-
if (bytes.length >
|
|
766
|
+
if (bytes.length > 262144) return `${name}: ${(bytes.length / 1024).toFixed(1)} KB exceeds the ${ARTIFACT_LIMIT_LABEL} limit`;
|
|
701
767
|
}
|
|
702
768
|
/** The largest byte size any loop file can have (a code point is at most 4 bytes). */
|
|
703
769
|
var LOOP_FILE_BYTE_CAP = Math.max(ARTIFACT_BYTE_CAP, MEMORY_CHAR_CAP * 4);
|
|
@@ -721,10 +787,7 @@ var LoopFiles = class {
|
|
|
721
787
|
return hash === "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" || this.blobStore.has(hash);
|
|
722
788
|
}
|
|
723
789
|
};
|
|
724
|
-
/**
|
|
725
|
-
* Data-access layer over Drizzle. Loop-locked state transitions live here; every
|
|
726
|
-
* DB-touching function is async, while the pure helpers stay sync.
|
|
727
|
-
*/
|
|
790
|
+
/** Data-access layer over Drizzle. Loop-locked state transitions live here. */
|
|
728
791
|
var store_exports = /* @__PURE__ */ __exportAll({
|
|
729
792
|
TERMINAL_REPORT_GRACE_MS: () => TERMINAL_REPORT_GRACE_MS,
|
|
730
793
|
acknowledgeRetiredReport: () => acknowledgeRetiredReport,
|
|
@@ -1928,19 +1991,15 @@ async function countRunSnapshots() {
|
|
|
1928
1991
|
return Number(r?.n ?? 0);
|
|
1929
1992
|
}
|
|
1930
1993
|
/**
|
|
1931
|
-
* Machine
|
|
1932
|
-
*
|
|
1933
|
-
*
|
|
1934
|
-
*
|
|
1935
|
-
* against it. Its lifecycle is a small state machine (`active` →
|
|
1936
|
-
* `terminal-grace` → `reconciliation-only`/`retired`), not a mint→revoke pair;
|
|
1937
|
-
* see `RunLease` below.
|
|
1994
|
+
* Machine and run credentials. A device token (`dk_…`) identifies a machine whose
|
|
1995
|
+
* id is derived from it (`m-sha256(token)[:16]`). A run lease (`rk_…`) is minted per
|
|
1996
|
+
* delivery and authorizes only that run's loop-file transfer and terminal report;
|
|
1997
|
+
* its lifecycle is the state machine on `RunLease`.
|
|
1938
1998
|
*
|
|
1939
|
-
* Leases and connect-key bindings are
|
|
1940
|
-
*
|
|
1941
|
-
*
|
|
1942
|
-
*
|
|
1943
|
-
* losing it only degrades retry deduplication, never persisted data.
|
|
1999
|
+
* Leases and connect-key bindings are durable so a restart neither rejects
|
|
2000
|
+
* in-flight reports nor blocks a just-connected machine from enrolling. The
|
|
2001
|
+
* 15-minute `new` idempotency window stays in memory; losing it on restart only
|
|
2002
|
+
* weakens retry deduplication.
|
|
1944
2003
|
*/
|
|
1945
2004
|
var tokens_exports = /* @__PURE__ */ __exportAll({
|
|
1946
2005
|
CONNECT_KEY_TTL_MS: () => CONNECT_KEY_TTL_MS,
|
|
@@ -2203,8 +2262,8 @@ function validateLoopTags(value) {
|
|
|
2203
2262
|
};
|
|
2204
2263
|
}
|
|
2205
2264
|
//#endregion
|
|
2206
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/boot-
|
|
2207
|
-
var
|
|
2265
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/boot-jtVCf_pN.js
|
|
2266
|
+
var boot_jtVCf_pN_exports = /* @__PURE__ */ __exportAll$1({
|
|
2208
2267
|
_: () => validOptionalPollString,
|
|
2209
2268
|
a: () => POLL_HTTP_BODY_FIELDS,
|
|
2210
2269
|
c: () => MIN_DAEMON_VERSION,
|
|
@@ -2296,11 +2355,8 @@ function validOptionalPollString(value, cap) {
|
|
|
2296
2355
|
function nowIso() {
|
|
2297
2356
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2298
2357
|
}
|
|
2299
|
-
/**
|
|
2300
|
-
*
|
|
2301
|
-
* throw mid-finalize on the DB write. The single sanitizing primitive behind
|
|
2302
|
-
* `clipText` - and used directly by `cli.ts`
|
|
2303
|
-
* (parseFlags/validateState, the same one-chokepoint discipline). */
|
|
2358
|
+
/** Postgres text/jsonb columns reject NUL, so a daemon-supplied string carrying
|
|
2359
|
+
* one would fail mid-finalize. The single sanitizer behind `clipText` and `cli.ts`. */
|
|
2304
2360
|
function stripNul(s) {
|
|
2305
2361
|
return s.replace(/\u0000/g, "");
|
|
2306
2362
|
}
|
|
@@ -2310,33 +2366,35 @@ function clipText(s, cap) {
|
|
|
2310
2366
|
/** Literal placeholder the daemon replaces with the run's absolute loop-file
|
|
2311
2367
|
* directory before launch (and exports as an env var of the same name). */
|
|
2312
2368
|
var LOOP_DIR_PLACEHOLDER = "$PIEVO_LOOP_DIR";
|
|
2313
|
-
var STATUS_LINE_RE = /^STATUS:\s*(
|
|
2369
|
+
var STATUS_LINE_RE = /^STATUS:\s*(ok|block)\.?$/i;
|
|
2370
|
+
var ATTENTION_LINE_RE = /^ATTENTION:\s*(.*)$/i;
|
|
2314
2371
|
/**
|
|
2315
|
-
* Deliver the user's prompt unchanged, followed by the
|
|
2316
|
-
*
|
|
2372
|
+
* Deliver the user's prompt unchanged, followed by the loop-file contract and the
|
|
2373
|
+
* final-line status contract. The run index
|
|
2317
2374
|
* intentionally remains an internal history fact.
|
|
2318
2375
|
*/
|
|
2319
2376
|
function buildRunTask(loop, previousNotices = []) {
|
|
2320
|
-
const files = [`- ${MEMORY_FILE}: this loop's
|
|
2377
|
+
const files = [`- ${MEMORY_FILE}: this loop's long-term experience (max ${MEMORY_CHAR_CAP} characters). Read it first and follow it. Before finishing, record only lessons this run learned the hard way that make later runs faster or safer: a pitfall hit, a workaround found, an environment fact discovered. One line each; correct or delete lessons that proved wrong. Never restate the task or these instructions, and never store state, results, baselines, trends, or run logs (those go in an artifact). Most runs add nothing.`, ...loop.artifacts.map((name) => `- ${name}: artifact shown on the Pievo dashboard (max ${fileLimitLabel(name)}). Update it only as the task above asks.`)];
|
|
2321
2378
|
const notices = previousNotices.length ? `\n\nNotices from the previous run:\n${previousNotices.map((notice) => `- ${notice}`).join("\n")}` : "";
|
|
2322
2379
|
return `${loop.prompt}
|
|
2323
2380
|
|
|
2324
|
-
Status definitions:
|
|
2325
|
-
- keep: ${loop.statusKeep}
|
|
2326
|
-
- no-change: ${loop.statusNoChange}
|
|
2327
|
-
- block: ${loop.statusBlock}
|
|
2328
|
-
|
|
2329
2381
|
Loop files in ${LOOP_DIR_PLACEHOLDER}:
|
|
2330
2382
|
${files.join("\n")}
|
|
2331
2383
|
A file over its limit is rejected and its previous version kept. Other files in that directory are discarded.${notices}
|
|
2332
2384
|
|
|
2333
|
-
|
|
2334
|
-
|
|
2385
|
+
Be concise in everything you write: lead with what changed or needs action; prefer tables and short lists; no filler or restated instructions.
|
|
2386
|
+
|
|
2387
|
+
Your final response is only: a summary of at most five short lines (no headings, no repeated tables or file contents); if the owner should look at something, one line \`ATTENTION: <reason>\`; then exactly one last line:
|
|
2388
|
+
STATUS: ok|block
|
|
2389
|
+
- ok: the loop keeps running on schedule. Findings and alerts are ok; flag them with ATTENTION.
|
|
2390
|
+
- block: the loop must stop until the owner acts, because the task says to stop or the next run cannot proceed safely (missing access, broken environment, unsafe next step). Block pauses the loop.`;
|
|
2335
2391
|
}
|
|
2392
|
+
var bareLine = (line) => line.trim().replace(/^[*_`>\s]+|[*_`\s]+$/g, "");
|
|
2336
2393
|
/**
|
|
2337
|
-
* Split a provider's final response into the reported status
|
|
2338
|
-
*
|
|
2339
|
-
*
|
|
2394
|
+
* Split a provider's final response into the reported status, an optional
|
|
2395
|
+
* attention reason from the ATTENTION lines just above it, and the summary. The final
|
|
2396
|
+
* non-empty line must be the status line; markdown emphasis or code ticks around
|
|
2397
|
+
* either line are tolerated because models add them unprompted.
|
|
2340
2398
|
*/
|
|
2341
2399
|
function parseFinalStatus(finalText) {
|
|
2342
2400
|
if (!finalText) return void 0;
|
|
@@ -2344,12 +2402,26 @@ function parseFinalStatus(finalText) {
|
|
|
2344
2402
|
let index = lines.length - 1;
|
|
2345
2403
|
while (index >= 0 && lines[index].trim() === "") index--;
|
|
2346
2404
|
if (index < 0) return void 0;
|
|
2347
|
-
const
|
|
2348
|
-
const match = STATUS_LINE_RE.exec(bare);
|
|
2405
|
+
const match = STATUS_LINE_RE.exec(bareLine(lines[index]));
|
|
2349
2406
|
if (!match) return void 0;
|
|
2407
|
+
const status = match[1].toLowerCase();
|
|
2408
|
+
const reasons = [];
|
|
2409
|
+
let end = index;
|
|
2410
|
+
for (;;) {
|
|
2411
|
+
let previous = end;
|
|
2412
|
+
while (previous > 0 && lines[previous - 1].trim() === "") previous--;
|
|
2413
|
+
const attentionMatch = previous > 0 ? ATTENTION_LINE_RE.exec(bareLine(lines[previous - 1])) : null;
|
|
2414
|
+
if (!attentionMatch) break;
|
|
2415
|
+
end = previous - 1;
|
|
2416
|
+
const reason = attentionMatch[1].trim();
|
|
2417
|
+
if (reason && !/^(none|n\/a|-)$/i.test(reason)) reasons.unshift(reason);
|
|
2418
|
+
}
|
|
2419
|
+
const joined = reasons.join("; ");
|
|
2420
|
+
const attention = joined ? joined.length > 200 ? `${joined.slice(0, 199)}…` : joined : null;
|
|
2350
2421
|
return {
|
|
2351
|
-
status
|
|
2352
|
-
message: lines.slice(0,
|
|
2422
|
+
status,
|
|
2423
|
+
message: lines.slice(0, end).join("\n").trim(),
|
|
2424
|
+
attention
|
|
2353
2425
|
};
|
|
2354
2426
|
}
|
|
2355
2427
|
async function buildDelivery(loop, queuedRun, runToken, roots) {
|
|
@@ -2373,31 +2445,11 @@ async function buildDelivery(loop, queuedRun, runToken, roots) {
|
|
|
2373
2445
|
};
|
|
2374
2446
|
}
|
|
2375
2447
|
/**
|
|
2376
|
-
* Loop-file storage retention
|
|
2377
|
-
*
|
|
2378
|
-
*
|
|
2379
|
-
*
|
|
2380
|
-
*
|
|
2381
|
-
* the OLD blob is no longer pointed at by the current file row — but nothing was
|
|
2382
|
-
* reclaiming it, so the byte store grew forever. This module closes that gap with two pieces:
|
|
2383
|
-
*
|
|
2384
|
-
* 1. pruneSnapshots() — bound the per-loop run-snapshot history to a window, so
|
|
2385
|
-
* old snapshots stop pinning the blobs they referenced for diffs.
|
|
2386
|
-
* 2. gcBlobs() — delete blob bytes no LIVE row needs: a blob is collected
|
|
2387
|
-
* only when NO artifact_files row AND NO retained run_snapshot references its
|
|
2388
|
-
* hash. CORRECTNESS over aggressiveness — a still-referenced blob is never
|
|
2389
|
-
* deleted; a leaked blob is only a cost bug the next pass reclaims.
|
|
2390
|
-
*
|
|
2391
|
-
* Concurrency: gcBlobs is safe alongside owner writes and run uploads. Three guards
|
|
2392
|
-
* combine — a grace window (a blob whose metadata row is younger than the window is
|
|
2393
|
-
* never collected, so a blob a run just uploaded is untouchable), a point re-check
|
|
2394
|
-
* of each candidate immediately before its bytes are deleted (so a blob
|
|
2395
|
-
* re-referenced before we touch it keeps both its bytes and metadata), and a
|
|
2396
|
-
* bytes-before-metadata delete ordering: each candidate's bytes are reclaimed
|
|
2397
|
-
* FIRST, then its metadata row is dropped unconditionally — so blobExists() goes
|
|
2398
|
-
* false and any writer that re-references the hash (even one that raced the byte
|
|
2399
|
-
* delete) re-uploads the bytes (self-healing). We never leave a live blobs row
|
|
2400
|
-
* pointing at deleted bytes.
|
|
2448
|
+
* Loop-file storage retention. Blob bytes are content-addressed and shared, so
|
|
2449
|
+
* replacing a file never frees its old blob by itself. pruneSnapshots() bounds
|
|
2450
|
+
* per-loop snapshot history; gcBlobs() then deletes bytes no file row and no
|
|
2451
|
+
* retained snapshot references. Correctness wins over aggressiveness: a leaked
|
|
2452
|
+
* blob is a storage cost the next pass reclaims, a deleted live blob is data loss.
|
|
2401
2453
|
*/
|
|
2402
2454
|
var log$2 = logger.child({ mod: "retention" });
|
|
2403
2455
|
/**
|
|
@@ -2411,28 +2463,14 @@ async function pruneSnapshots(keep = 20) {
|
|
|
2411
2463
|
return pruned;
|
|
2412
2464
|
}
|
|
2413
2465
|
/**
|
|
2414
|
-
* Reclaim unreferenced blob bytes
|
|
2415
|
-
*
|
|
2416
|
-
*
|
|
2417
|
-
*
|
|
2418
|
-
*
|
|
2419
|
-
*
|
|
2420
|
-
*
|
|
2421
|
-
*
|
|
2422
|
-
* a. Pre-delete guard: if a sync re-referenced it since the keep-set was
|
|
2423
|
-
* computed, skip it — leaving both its bytes AND metadata row intact
|
|
2424
|
-
* (a consistent live blob, nothing to heal). The guard is two O(1) checks:
|
|
2425
|
-
* an indexed artifact_files point query (always fresh) plus membership in a
|
|
2426
|
-
* snapshot-hash Set deserialized ONCE per pass and rebuilt only when the
|
|
2427
|
-
* snapshot row count changes (a report() raced us) — never the old
|
|
2428
|
-
* per-candidate full snapshot scan (which was O(garbage × snapshots), since
|
|
2429
|
-
* genuine garbage always misses the file check and fell through to it).
|
|
2430
|
-
* b. Otherwise delete the BYTES (the await), then drop the metadata row
|
|
2431
|
-
* UNCONDITIONALLY. Bytes-before-metadata is the data-loss fix: if a sync
|
|
2432
|
-
* raced the byte delete (re-referencing the hash + recreating the blobs
|
|
2433
|
-
* row mid-await), dropping the metadata still leaves blobExists()=false,
|
|
2434
|
-
* so that file re-uploads its bytes on the next sync. We never leave a
|
|
2435
|
-
* live blobs row pointing at deleted bytes.
|
|
2466
|
+
* Reclaim unreferenced blob bytes; returns the number collected. Safe alongside
|
|
2467
|
+
* owner writes and run uploads because of three guards:
|
|
2468
|
+
* - grace window: blobs whose metadata row is younger than `graceMs` are skipped;
|
|
2469
|
+
* - per-candidate re-check right before deletion: an indexed file-row lookup plus
|
|
2470
|
+
* a snapshot-hash set rebuilt only when the snapshot count changes (a concurrent
|
|
2471
|
+
* report), instead of an O(garbage x snapshots) scan;
|
|
2472
|
+
* - bytes before metadata: the metadata row is dropped after the bytes even if a
|
|
2473
|
+
* writer raced the delete, so blobExists() is false and that writer re-uploads.
|
|
2436
2474
|
*/
|
|
2437
2475
|
async function gcBlobs(blobStore, graceMs = BLOB_GC_GRACE_MS) {
|
|
2438
2476
|
const refs = await liveBlobRefs();
|
|
@@ -2592,7 +2630,6 @@ var LOOP_CONFIG_FIELDS = [
|
|
|
2592
2630
|
"model",
|
|
2593
2631
|
"reasoningEffort",
|
|
2594
2632
|
"prompt",
|
|
2595
|
-
"statusDefinitions",
|
|
2596
2633
|
"artifacts",
|
|
2597
2634
|
"enabled"
|
|
2598
2635
|
];
|
|
@@ -2768,36 +2805,6 @@ function validateSchedule(value) {
|
|
|
2768
2805
|
detail: "schedule.mode must be cron|continuous"
|
|
2769
2806
|
};
|
|
2770
2807
|
}
|
|
2771
|
-
function validateStatusDefinitions(value) {
|
|
2772
|
-
const raw = object(value);
|
|
2773
|
-
if (!raw) return {
|
|
2774
|
-
ok: false,
|
|
2775
|
-
detail: "statusDefinitions is required"
|
|
2776
|
-
};
|
|
2777
|
-
const unknown = Object.keys(raw).filter((key) => ![
|
|
2778
|
-
"keep",
|
|
2779
|
-
"noChange",
|
|
2780
|
-
"block"
|
|
2781
|
-
].includes(key));
|
|
2782
|
-
if (unknown.length) return {
|
|
2783
|
-
ok: false,
|
|
2784
|
-
detail: `statusDefinitions has unknown field(s): ${unknown.join(", ")}`
|
|
2785
|
-
};
|
|
2786
|
-
const keep = requiredText(raw.keep, "statusDefinitions.keep", true);
|
|
2787
|
-
if (!keep.ok) return keep;
|
|
2788
|
-
const noChange = requiredText(raw.noChange, "statusDefinitions.noChange", true);
|
|
2789
|
-
if (!noChange.ok) return noChange;
|
|
2790
|
-
const block = requiredText(raw.block, "statusDefinitions.block", true);
|
|
2791
|
-
if (!block.ok) return block;
|
|
2792
|
-
return {
|
|
2793
|
-
ok: true,
|
|
2794
|
-
value: {
|
|
2795
|
-
keep: keep.value,
|
|
2796
|
-
noChange: noChange.value,
|
|
2797
|
-
block: block.value
|
|
2798
|
-
}
|
|
2799
|
-
};
|
|
2800
|
-
}
|
|
2801
2808
|
function validateArtifactNames(value) {
|
|
2802
2809
|
if (value === void 0 || value === null) return {
|
|
2803
2810
|
ok: true,
|
|
@@ -2816,7 +2823,7 @@ function validateArtifactNames(value) {
|
|
|
2816
2823
|
for (const entry of value) {
|
|
2817
2824
|
if (!validArtifactName(entry)) return {
|
|
2818
2825
|
ok: false,
|
|
2819
|
-
detail: `artifact must be a plain
|
|
2826
|
+
detail: `artifact must be a plain text/code file name other than ${MEMORY_FILE} (supported extensions: ${ARTIFACT_EXTENSIONS.join(", ")}; letters, digits, . _ -; at most 64 characters before the extension): ${JSON.stringify(entry)}`
|
|
2820
2827
|
};
|
|
2821
2828
|
const key = entry.toLowerCase();
|
|
2822
2829
|
if (seen.has(key)) return {
|
|
@@ -2862,18 +2869,10 @@ function scheduleFromLoop(loop) {
|
|
|
2862
2869
|
}
|
|
2863
2870
|
throw new Error(`invariant: loop ${loop.id} has unknown schedule mode: ${String(loop.scheduleMode)}`);
|
|
2864
2871
|
}
|
|
2865
|
-
function statusDefinitionsFromLoop(loop) {
|
|
2866
|
-
return {
|
|
2867
|
-
keep: loop.statusKeep,
|
|
2868
|
-
noChange: loop.statusNoChange,
|
|
2869
|
-
block: loop.statusBlock
|
|
2870
|
-
};
|
|
2871
|
-
}
|
|
2872
2872
|
function canonicalLoopEnvelope(loop) {
|
|
2873
2873
|
return {
|
|
2874
2874
|
...canonicalLoopSummary(loop),
|
|
2875
2875
|
prompt: loop.prompt,
|
|
2876
|
-
statusDefinitions: statusDefinitionsFromLoop(loop),
|
|
2877
2876
|
artifacts: loop.artifacts,
|
|
2878
2877
|
enabled: loop.enabled
|
|
2879
2878
|
};
|
|
@@ -2911,8 +2910,6 @@ function validateLoopCreate(value) {
|
|
|
2911
2910
|
if (!prompt.ok) return prompt;
|
|
2912
2911
|
const schedule = validateSchedule(raw.schedule);
|
|
2913
2912
|
if (!schedule.ok) return schedule;
|
|
2914
|
-
const statusDefinitions = validateStatusDefinitions(raw.statusDefinitions);
|
|
2915
|
-
if (!statusDefinitions.ok) return statusDefinitions;
|
|
2916
2913
|
const artifacts = validateArtifactNames(raw.artifacts);
|
|
2917
2914
|
if (!artifacts.ok) return artifacts;
|
|
2918
2915
|
const model = optionalProvider(raw.model, "model");
|
|
@@ -2937,7 +2934,6 @@ function validateLoopCreate(value) {
|
|
|
2937
2934
|
model: model.value,
|
|
2938
2935
|
reasoningEffort: reasoningEffort.value,
|
|
2939
2936
|
prompt: prompt.value,
|
|
2940
|
-
statusDefinitions: statusDefinitions.value,
|
|
2941
2937
|
artifacts: artifacts.value,
|
|
2942
2938
|
enabled: raw.enabled !== false
|
|
2943
2939
|
};
|
|
@@ -2954,9 +2950,6 @@ function validateLoopCreate(value) {
|
|
|
2954
2950
|
model: config.model,
|
|
2955
2951
|
reasoningEffort: config.reasoningEffort,
|
|
2956
2952
|
prompt: config.prompt,
|
|
2957
|
-
statusKeep: config.statusDefinitions.keep,
|
|
2958
|
-
statusNoChange: config.statusDefinitions.noChange,
|
|
2959
|
-
statusBlock: config.statusDefinitions.block,
|
|
2960
2953
|
artifacts: config.artifacts,
|
|
2961
2954
|
enabled: config.enabled
|
|
2962
2955
|
}
|
|
@@ -3000,13 +2993,6 @@ function validateLoopEdit(loop, value) {
|
|
|
3000
2993
|
if (!result.ok) return result;
|
|
3001
2994
|
Object.assign(update, rowSchedule(result.value, loop.cron));
|
|
3002
2995
|
}
|
|
3003
|
-
if (raw.statusDefinitions !== void 0) {
|
|
3004
|
-
const result = validateStatusDefinitions(raw.statusDefinitions);
|
|
3005
|
-
if (!result.ok) return result;
|
|
3006
|
-
update.statusKeep = result.value.keep;
|
|
3007
|
-
update.statusNoChange = result.value.noChange;
|
|
3008
|
-
update.statusBlock = result.value.block;
|
|
3009
|
-
}
|
|
3010
2996
|
if (raw.artifacts !== void 0) {
|
|
3011
2997
|
const result = validateArtifactNames(raw.artifacts);
|
|
3012
2998
|
if (!result.ok) return result;
|
|
@@ -3077,22 +3063,16 @@ var validPollWireId = (value) => typeof value === "string" && value.length <= 20
|
|
|
3077
3063
|
var validPollCurrentRun = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 2 && Object.prototype.hasOwnProperty.call(value, "runId") && Object.prototype.hasOwnProperty.call(value, "stage") && validPollWireId(value.runId) && (value.stage === "executing" || value.stage === "reporting");
|
|
3078
3064
|
var validPollInfo = (value) => value === void 0 || value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).every((key) => POLL_INFO_FIELDS.has(key)) && validOptionalPollString(value.host, 524288) && validOptionalPollString(value.platform, 524288) && validOptionalPollString(value.arch, 524288) && validOptionalPollString(value.version, 64);
|
|
3079
3065
|
/**
|
|
3080
|
-
* Machine gateway
|
|
3081
|
-
*
|
|
3082
|
-
* long-poll while idle). Framework-agnostic like the rest of the gateway
|
|
3083
|
-
* (return `{ status, body }` so the methods can be mounted on a plain http
|
|
3084
|
-
* server or TanStack server routes):
|
|
3066
|
+
* Machine gateway: the run-lifecycle core the daemon talks to. Methods return
|
|
3067
|
+
* transport-free `{ status, body }` results for the thin route shells:
|
|
3085
3068
|
*
|
|
3086
|
-
* POST /api/machine/poll
|
|
3087
|
-
* POST /machine/report
|
|
3088
|
-
* GET|PUT /api/machine/run-files/:name
|
|
3069
|
+
* POST /api/machine/poll (device token) claim and deliver runs
|
|
3070
|
+
* POST /machine/report (run token) finalize a run
|
|
3071
|
+
* GET|PUT /api/machine/run-files/:name (run token) loop-file transfer
|
|
3089
3072
|
*
|
|
3090
|
-
*
|
|
3091
|
-
*
|
|
3092
|
-
*
|
|
3093
|
-
* CLI verb dispatch at `/api/machine/cli` lives in `gateway/cli.ts`
|
|
3094
|
-
* (`CliGateway`), which reuses this class's owner methods;
|
|
3095
|
-
* canonical loop configuration validation lives in `gateway/loopConfig.ts`.
|
|
3073
|
+
* Idle polls may be held open (long-poll) until the scheduler's dispatcher wakes
|
|
3074
|
+
* them. `sweep()` marks stale machines offline and reclaims silent runs. CLI verbs
|
|
3075
|
+
* live in `cli.ts`; loop config validation lives in `loopConfig.ts`.
|
|
3096
3076
|
*/
|
|
3097
3077
|
var log$1 = logger.child({ mod: "gateway" });
|
|
3098
3078
|
var ONLINE_TTL_MS = 3e4;
|
|
@@ -3242,7 +3222,7 @@ function incidentDiagnosis(code, issues, reportId, payloadDigest) {
|
|
|
3242
3222
|
recommendedAction
|
|
3243
3223
|
};
|
|
3244
3224
|
}
|
|
3245
|
-
var MISSING_STATUS_ERROR = "run protocol incomplete: the final response has no \"STATUS:
|
|
3225
|
+
var MISSING_STATUS_ERROR = "run protocol incomplete: the final response has no \"STATUS: ok|block\" line";
|
|
3246
3226
|
/** The run outcome a terminal report establishes. Only a successful provider
|
|
3247
3227
|
* exit is read for a status; a successful exit without one is a protocol error. */
|
|
3248
3228
|
function reportOutcome(body) {
|
|
@@ -3269,6 +3249,7 @@ function reportOutcome(body) {
|
|
|
3269
3249
|
patch: {
|
|
3270
3250
|
status: parsed.status,
|
|
3271
3251
|
message: clipText(parsed.message, 2e3) || null,
|
|
3252
|
+
attention: parsed.attention,
|
|
3272
3253
|
error: null
|
|
3273
3254
|
}
|
|
3274
3255
|
};
|
|
@@ -3352,7 +3333,6 @@ var MachineGateway = class {
|
|
|
3352
3333
|
this.blobStore = blobStore;
|
|
3353
3334
|
this.loopFiles = new LoopFiles(blobStore);
|
|
3354
3335
|
}
|
|
3355
|
-
/** Loop-file bytes over the same blob store that maintenance garbage-collects. */
|
|
3356
3336
|
loopFiles;
|
|
3357
3337
|
/** In-flight latch: the maintenance pass is sequential and the first post-deploy
|
|
3358
3338
|
* backlog reclamation can overrun the interval, so a fresh tick skips rather than
|
|
@@ -3430,20 +3410,12 @@ var MachineGateway = class {
|
|
|
3430
3410
|
await pruneExpiredLeases(now);
|
|
3431
3411
|
for (const loop of await listLoops()) if (loop.deleteRequestedAt) await tryDeleteLoop(loop.id);
|
|
3432
3412
|
}
|
|
3433
|
-
/**
|
|
3434
|
-
*
|
|
3435
|
-
*
|
|
3436
|
-
*
|
|
3437
|
-
*
|
|
3438
|
-
*
|
|
3439
|
-
* (often SUCCESSFUL) result. Retiring the lease here would 401 that late report
|
|
3440
|
-
* and strand the run as a permanent false failure with its message lost (the
|
|
3441
|
-
* investigated bug). So the lease survives a bounded grace window
|
|
3442
|
-
* (`TERMINAL_GRACE_MS`) during which exactly ONE late wake-report may reconcile
|
|
3443
|
-
* the run — see `report()`'s terminal-grace branch. The credential is still
|
|
3444
|
-
* bounded: CLI mutations are refused while terminal-grace, and the
|
|
3445
|
-
* reconciliation retires the lease single-shot. Pending rows are durable inbox
|
|
3446
|
-
* entries and are never reclaimed by this path. */
|
|
3413
|
+
/** Reclaim one silent running run as an error, but terminalize its lease instead
|
|
3414
|
+
* of retiring it. The usual cause is a laptop that fell asleep mid-run; on wake
|
|
3415
|
+
* the daemon delivers the real (often successful) result, and a retired lease
|
|
3416
|
+
* would 401 it and leave a false failure. During TERMINAL_GRACE_MS exactly one
|
|
3417
|
+
* late report may reconcile the run (see `report()`); CLI mutations stay refused.
|
|
3418
|
+
* Pending rows are durable queue entries and never reach this path. */
|
|
3447
3419
|
async reclaimRun(run, reason) {
|
|
3448
3420
|
if (run.phase !== "running") return;
|
|
3449
3421
|
const at = nowIso();
|
|
@@ -3629,11 +3601,8 @@ var MachineGateway = class {
|
|
|
3629
3601
|
waiter.cancel();
|
|
3630
3602
|
}
|
|
3631
3603
|
}
|
|
3632
|
-
/**
|
|
3633
|
-
*
|
|
3634
|
-
* Claude Code can avoid starting a duplicate. `online` is fresh-checked against
|
|
3635
|
-
* the poll TTL, not just the stored flag.
|
|
3636
|
-
*/
|
|
3604
|
+
/** Whether this machine has a live daemon. `online` is fresh-checked against the
|
|
3605
|
+
* poll TTL, not just the stored flag. */
|
|
3637
3606
|
async status(deviceToken) {
|
|
3638
3607
|
const auth = await authenticateDeviceToken(deviceToken, { allowUnknown: true });
|
|
3639
3608
|
if (!auth.ok) return auth.response;
|
|
@@ -4325,10 +4294,8 @@ function renderLoopsText(loops, fields) {
|
|
|
4325
4294
|
return doc(countLine(loops.length), listBlock("loops", fields, loops.map((l) => fields.map((f) => loopCell(l, f)))), helpBlock(["Run `pievo show <id>` to see a loop's full config", "Run `pievo log <id>` to see a loop's recent runs"]));
|
|
4326
4295
|
}
|
|
4327
4296
|
function runResultToken(r) {
|
|
4328
|
-
if (r.
|
|
4329
|
-
|
|
4330
|
-
const base = r.phase === "error" ? "failed" : r.phase === "done" ? "ok" : r.phase;
|
|
4331
|
-
return r.status ? `${base}/${r.status}` : `${base}/missing-status`;
|
|
4297
|
+
if (r.phase === "error") return "failed";
|
|
4298
|
+
return r.status ?? r.phase;
|
|
4332
4299
|
}
|
|
4333
4300
|
/** Stable JSON with recursively sorted object keys — so two structurally-equal values
|
|
4334
4301
|
* serialize identically regardless of key ordering (pg `jsonb` normalizes key order). */
|
|
@@ -4558,11 +4525,7 @@ var TERMINAL_PHASES = [
|
|
|
4558
4525
|
"error",
|
|
4559
4526
|
"canceled"
|
|
4560
4527
|
];
|
|
4561
|
-
var STATUSES = [
|
|
4562
|
-
"keep",
|
|
4563
|
-
"no-change",
|
|
4564
|
-
"block"
|
|
4565
|
-
];
|
|
4528
|
+
var STATUSES = ["ok", "block"];
|
|
4566
4529
|
var LOG_FLAGS = new Set([
|
|
4567
4530
|
"_",
|
|
4568
4531
|
"loop",
|
|
@@ -4620,7 +4583,7 @@ function parseHistoryFlags(flags) {
|
|
|
4620
4583
|
const status = flags.status;
|
|
4621
4584
|
if (status !== void 0 && (typeof status !== "string" || !STATUSES.includes(status))) return {
|
|
4622
4585
|
ok: false,
|
|
4623
|
-
error: "--status must be
|
|
4586
|
+
error: "--status must be ok|block"
|
|
4624
4587
|
};
|
|
4625
4588
|
const phase = flags.phase;
|
|
4626
4589
|
if (phase !== void 0 && (typeof phase !== "string" || !TERMINAL_PHASES.includes(phase))) return {
|
|
@@ -4689,15 +4652,19 @@ function boundedText(value, cap = HISTORY_DETAIL_TEXT_CAP) {
|
|
|
4689
4652
|
}
|
|
4690
4653
|
function normalizedListRun(run) {
|
|
4691
4654
|
const message = boundedText(run.message ?? null, 500);
|
|
4655
|
+
const error = boundedText(run.error ?? null, 500);
|
|
4692
4656
|
return {
|
|
4693
4657
|
runIndex: run.runIndex,
|
|
4694
4658
|
terminalAt: run.ts,
|
|
4695
4659
|
phase: run.phase,
|
|
4696
4660
|
status: run.status ?? null,
|
|
4661
|
+
attention: run.attention ?? null,
|
|
4697
4662
|
durationMs: run.durationMs ?? null,
|
|
4698
4663
|
tokenUsage: totalTokenUsage(run.usage ?? null),
|
|
4699
4664
|
message: message.value,
|
|
4700
4665
|
messageTruncated: message.truncated,
|
|
4666
|
+
error: error.value,
|
|
4667
|
+
errorTruncated: error.truncated,
|
|
4701
4668
|
finalTextAvailable: !!run.finalText?.trim()
|
|
4702
4669
|
};
|
|
4703
4670
|
}
|
|
@@ -4748,18 +4715,22 @@ async function listHistory(loop, q) {
|
|
|
4748
4715
|
"terminal",
|
|
4749
4716
|
"phase",
|
|
4750
4717
|
"status",
|
|
4718
|
+
"attention",
|
|
4751
4719
|
"durationMs",
|
|
4752
4720
|
"tokenUsage",
|
|
4753
4721
|
"message",
|
|
4722
|
+
"error",
|
|
4754
4723
|
"finalTextAvailable"
|
|
4755
4724
|
], rows.map((run) => [
|
|
4756
4725
|
run.runIndex,
|
|
4757
4726
|
fmt(run.ts),
|
|
4758
4727
|
run.phase,
|
|
4759
4728
|
run.status ?? null,
|
|
4729
|
+
run.attention ?? null,
|
|
4760
4730
|
run.durationMs ?? null,
|
|
4761
4731
|
totalTokenUsage(run.usage ?? null),
|
|
4762
4732
|
run.message ? truncate(run.message, 500, "use --run for detail").value : null,
|
|
4733
|
+
run.error ? truncate(run.error, 500, "use --run for detail").value : null,
|
|
4763
4734
|
!!run.finalText?.trim()
|
|
4764
4735
|
])) : emptyList("runs");
|
|
4765
4736
|
return response(doc(`loop: ${scalar(loop.name)} (${loop.id})`, `count: ${rows.length} of ${Number(counted[0]?.n ?? 0)} matching`, table, helpBlock(["Use `pievo log --run <index>` for one run"])));
|
|
@@ -4804,6 +4775,7 @@ async function detailHistory(loop, q) {
|
|
|
4804
4775
|
terminalAt: TERMINAL_PHASES.includes(run.phase) ? run.ts : null,
|
|
4805
4776
|
phase: run.phase,
|
|
4806
4777
|
status: run.status ?? null,
|
|
4778
|
+
attention: run.attention ?? null,
|
|
4807
4779
|
durationMs: run.durationMs ?? null,
|
|
4808
4780
|
tokenUsage: totalTokenUsage(run.usage ?? null),
|
|
4809
4781
|
message: message.value,
|
|
@@ -4830,6 +4802,7 @@ async function detailHistory(loop, q) {
|
|
|
4830
4802
|
["terminalAt", detail.terminalAt],
|
|
4831
4803
|
["phase", detail.phase],
|
|
4832
4804
|
["status", detail.status],
|
|
4805
|
+
["attention", detail.attention],
|
|
4833
4806
|
["durationMs", detail.durationMs],
|
|
4834
4807
|
["tokenUsage", detail.tokenUsage],
|
|
4835
4808
|
["message", detail.message],
|
|
@@ -4853,18 +4826,10 @@ async function readLoopHistory(loop, flags) {
|
|
|
4853
4826
|
return parsed.value.mode === "detail" ? detailHistory(loop, parsed.value) : listHistory(loop, parsed.value);
|
|
4854
4827
|
}
|
|
4855
4828
|
/**
|
|
4856
|
-
*
|
|
4857
|
-
*
|
|
4858
|
-
*
|
|
4859
|
-
*
|
|
4860
|
-
*
|
|
4861
|
-
* POST /api/machine/cli (Bearer device OR run credential) → unified dispatch
|
|
4862
|
-
*
|
|
4863
|
-
* The verb router keys authority on credential type first (`dk_` device prefix
|
|
4864
|
-
* vs `rk_` run lease) and reuses the core gateway
|
|
4865
|
-
* methods (`createLoop`/`editLoop`) through the injected `MachineGateway`,
|
|
4866
|
-
* plus the credential-neutral history module. Run credentials authorize no CLI
|
|
4867
|
-
* verb: a run reports through its final response, not a callback.
|
|
4829
|
+
* `/api/machine/cli` verb router. Authority keys on credential type: a device
|
|
4830
|
+
* (`dk_`) token gets owner verbs over loops bound to its machine, reusing
|
|
4831
|
+
* `MachineGateway`'s owner methods; a run (`rk_`) token gets no verb, because a
|
|
4832
|
+
* run reports only through its final response.
|
|
4868
4833
|
*/
|
|
4869
4834
|
var cliLog = logger.child({ mod: "cli" });
|
|
4870
4835
|
var CliGateway = class {
|
|
@@ -4878,14 +4843,6 @@ var CliGateway = class {
|
|
|
4878
4843
|
this.forceDeleteLoop = deps.forceDeleteLoop ?? forceDeleteLoop;
|
|
4879
4844
|
this.destructiveLog = deps.destructiveLog ?? ((event) => cliLog.warn(event, "force-delete: destructive server authority removal"));
|
|
4880
4845
|
}
|
|
4881
|
-
/**
|
|
4882
|
-
* The unified CLI endpoint. It is a ROUTER in front of the gateway logic that
|
|
4883
|
-
* already exists — never a rewrite — that keys authority on the credential type:
|
|
4884
|
-
* · DEVICE credential (`dk_`-prefixed) → owner authority over any loop bound to
|
|
4885
|
-
* the machine: `new`→createLoop, `loops`→listLoops, `edit`→editLoop,
|
|
4886
|
-
* `log`→readLoopHistory, `show`→describe, `file`→loop files.
|
|
4887
|
-
* · RUN credential (`rk_` run lease) → rejected; runs have no CLI.
|
|
4888
|
-
*/
|
|
4889
4846
|
async cli(token, argv) {
|
|
4890
4847
|
return finalizeCli(token.startsWith("dk_") ? await this.deviceCli(token, argv) : await this.runCli(token, argv));
|
|
4891
4848
|
}
|
|
@@ -5266,7 +5223,7 @@ var CliGateway = class {
|
|
|
5266
5223
|
})), scoped.elsewhere, await recentMachineRuns(loops, 3));
|
|
5267
5224
|
}
|
|
5268
5225
|
};
|
|
5269
|
-
var RUN_HAS_NO_CLI = "pievo commands are not available inside a run; end your final response with a summary and a last line `STATUS:
|
|
5226
|
+
var RUN_HAS_NO_CLI = "pievo commands are not available inside a run; end your final response with a summary and a last line `STATUS: ok|block`";
|
|
5270
5227
|
var FILE_USAGE = "pievo file list <loop> | file get <loop> <name> | file set <loop> <name> --from <path>";
|
|
5271
5228
|
var PAUSED_FINISHING = "loop paused; current run is finishing";
|
|
5272
5229
|
var STOP_UPGRADE_REQUIRED = "Daemon upgrade required to stop a running process. Run `npm install -g @kky42/pievo@latest`, then `pievo daemon restart`.";
|
|
@@ -5336,7 +5293,7 @@ var DEVICE_VERB_HELP = {
|
|
|
5336
5293
|
new: {
|
|
5337
5294
|
syntax: "new --json '<config>' [--dry-run]",
|
|
5338
5295
|
summary: `create a loop from the canonical envelope (keys: ${[...EDITABLE_LOOP_FIELDS].join(", ")}; agent required)`,
|
|
5339
|
-
help: ["Run `pievo new --json '{\"name\":\"Daily check\",\"schedule\":{\"mode\":\"cron\",\"cron\":\"0 8 * * *\",\"timezone\":\"UTC\",\"overlap\":\"skip\"},\"workdir\":\"<path>\",\"agent\":\"claude-code\",\"prompt\":\"Check the project.\"
|
|
5296
|
+
help: ["Run `pievo new --json '{\"name\":\"Daily check\",\"schedule\":{\"mode\":\"cron\",\"cron\":\"0 8 * * *\",\"timezone\":\"UTC\",\"overlap\":\"skip\"},\"workdir\":\"<path>\",\"agent\":\"claude-code\",\"prompt\":\"Check the project.\"}'` to create a loop", "Run `pievo new --json '{...}' --dry-run` to validate without creating"]
|
|
5340
5297
|
},
|
|
5341
5298
|
loops: {
|
|
5342
5299
|
syntax: "loops [--fields a,b] [--json]",
|
|
@@ -5384,7 +5341,7 @@ var DEVICE_VERB_HELP = {
|
|
|
5384
5341
|
help: ["Run `pievo file get <id> MEMORY.md` to read the loop's memory", "An edit made while a run is executing wins over that run's version of the file"]
|
|
5385
5342
|
},
|
|
5386
5343
|
log: {
|
|
5387
|
-
syntax: "log [<id>] [--limit 1..20] [--since ISO] [--until ISO] [--status
|
|
5344
|
+
syntax: "log [<id>] [--limit 1..20] [--since ISO] [--until ISO] [--status ok|block] [--phase done|error|canceled] [--run <index|UUID> [--diff]] [--json]",
|
|
5388
5345
|
summary: "bounded terminal history or one detailed run",
|
|
5389
5346
|
help: ["Run `pievo log <id> --json` for structured history", "Run `pievo log <id> --run 12 --diff` for bounded run detail and artifact diff"]
|
|
5390
5347
|
}
|
|
@@ -5421,7 +5378,6 @@ function renderShowText(loop, env, totalRuns, lastRun, opts = {}) {
|
|
|
5421
5378
|
["model", env.model == null ? { raw: "default" } : env.model],
|
|
5422
5379
|
["reasoningEffort", env.reasoningEffort == null ? { raw: "default" } : env.reasoningEffort],
|
|
5423
5380
|
["prompt", contentField(loop.prompt, full)],
|
|
5424
|
-
["statusDefinitions", { raw: JSON.stringify(env.statusDefinitions) }],
|
|
5425
5381
|
["artifacts", { raw: JSON.stringify(env.artifacts) }],
|
|
5426
5382
|
["enabled", env.enabled]
|
|
5427
5383
|
]);
|
|
@@ -5648,14 +5604,8 @@ var Scheduler = class {
|
|
|
5648
5604
|
function msg(err) {
|
|
5649
5605
|
return err instanceof Error ? err.message : String(err);
|
|
5650
5606
|
}
|
|
5651
|
-
/**
|
|
5652
|
-
*
|
|
5653
|
-
* migrations, wire the machine gateway's dispatcher into the Scheduler, start
|
|
5654
|
-
* the Scheduler + an offline-sweep interval. Guarded on `globalThis` so it
|
|
5655
|
-
* survives dev HMR and runs at most once per process. Call `ensureServer()`
|
|
5656
|
-
* from any server-side entry (the standalone machine server / TanStack server
|
|
5657
|
-
* fns); the first call boots, the rest share the same instance.
|
|
5658
|
-
*/
|
|
5607
|
+
/** One-time, idempotent in-process backend boot (migrations, scheduler, sweep and
|
|
5608
|
+
* storage-maintenance intervals). Guarded on `globalThis` to survive dev HMR. */
|
|
5659
5609
|
var boot_exports = /* @__PURE__ */ __exportAll({
|
|
5660
5610
|
ensureServer: () => ensureServer,
|
|
5661
5611
|
getCliGateway: () => getCliGateway,
|
|
@@ -5713,4 +5663,4 @@ async function getCliGateway() {
|
|
|
5713
5663
|
return (await ensureServer()).cliGateway;
|
|
5714
5664
|
}
|
|
5715
5665
|
//#endregion
|
|
5716
|
-
export { listRuns as A,
|
|
5666
|
+
export { listRuns as A, reconciliationStatesForRuns as B, getRun as C, listArtifacts as D, isOutdated as E, machineIdFromToken as F, stopLoop as G, requestRunCancel as H, machinePresence as I, updateMachine as J, tryDeleteLoop as K, mintDeviceToken as L, loopFileNames as M, loopTags_CI_aMcqh_exports as N, listLoops as O, loopsForMachine as P, pauseLoop as R, getMachine as S, hasRunningRun as T, sha256 as U, requestDeleteLoop as V, startLoop as W, validateLoopTags as Y, createMachine as _, canonicalLoopSummary as a, getArtifactFile as b, getLoopFiles as c, validOptionalPollString as d, validPollCurrentRun as f, countRuns as g, CODING_AGENTS as h, canonicalLoopEnvelope as i, listRunsBefore as j, listMachines as k, readByteBody as l, validateLoopEdit as m, POLL_HTTP_BODY_FIELDS as n, daemonNeedsUpdate as o, validPollWireId as p, updateLoop as q, boot_jtVCf_pN_exports as r, ensureServer as s, MIN_DAEMON_VERSION as t, readJsonBody as u, forceDeleteLoop as v, hasPendingRun as w, getLoop as x, forceDeleteMachine as y, recentLoopUsage as z };
|