@delorenj/pjangler 1.5.39 → 1.5.41
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/crank/tui.js +63 -6
- package/dist/index.js +1027 -62
- package/package.json +1 -1
package/dist/crank/tui.js
CHANGED
|
@@ -213,6 +213,59 @@ var PJANGLER_VERSION = (() => {
|
|
|
213
213
|
return "0.0.0";
|
|
214
214
|
})();
|
|
215
215
|
|
|
216
|
+
// src/crank/engine.ts
|
|
217
|
+
var WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
218
|
+
var TICK_MS = 5 * 60 * 1e3;
|
|
219
|
+
var STALL_MS = 3 * TICK_MS;
|
|
220
|
+
var ENGINE_AUDIT_TAIL_BYTES = 1024 * 1024;
|
|
221
|
+
var FUTURE_SKEW_MS = 5 * 6e4;
|
|
222
|
+
function clockTime(ms) {
|
|
223
|
+
const d = new Date(ms);
|
|
224
|
+
return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
225
|
+
}
|
|
226
|
+
function ago(thenMs, nowMs) {
|
|
227
|
+
const s = Math.max(0, Math.round((nowMs - thenMs) / 1e3));
|
|
228
|
+
if (s < 60) return `${s}s ago`;
|
|
229
|
+
if (s < 3600) return `${Math.floor(s / 60)}m ago`;
|
|
230
|
+
if (s < 86400) return `${Math.floor(s / 3600)}h ${String(Math.floor(s % 3600 / 60)).padStart(2, "0")}m ago`;
|
|
231
|
+
return `${Math.floor(s / 86400)}d ${Math.floor(s % 86400 / 3600)}h ago`;
|
|
232
|
+
}
|
|
233
|
+
function compactTokens(n) {
|
|
234
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
235
|
+
if (n >= 1e3) return `${Math.round(n / 1e3)}k`;
|
|
236
|
+
return String(n);
|
|
237
|
+
}
|
|
238
|
+
function nextTickAtOrAfter(ms) {
|
|
239
|
+
return Math.ceil(ms / TICK_MS) * TICK_MS;
|
|
240
|
+
}
|
|
241
|
+
function engineStalled(status) {
|
|
242
|
+
return status.known && status.lastTickMs !== void 0 && status.readAtMs - status.lastTickMs > STALL_MS;
|
|
243
|
+
}
|
|
244
|
+
function engineBlockedLabel(status) {
|
|
245
|
+
if (!status.known) return void 0;
|
|
246
|
+
if (engineStalled(status) && status.lastTickMs !== void 0) return `blocked: engine not ticking (last tick ${ago(status.lastTickMs, status.readAtMs)})`;
|
|
247
|
+
if (status.outcome !== "refused") return void 0;
|
|
248
|
+
if (status.tokenBlocked) {
|
|
249
|
+
const resume = status.resumeMs !== void 0 ? ` \u2014 resumes \u2248 ${clockTime(nextTickAtOrAfter(status.resumeMs))}` : "";
|
|
250
|
+
return `blocked: daily token cap${resume}`;
|
|
251
|
+
}
|
|
252
|
+
return `blocked: ${status.reason ?? "engine refused the last tick"}`;
|
|
253
|
+
}
|
|
254
|
+
function engineSummary(status) {
|
|
255
|
+
if (!status.known || status.lastTickMs === void 0) return { text: "engine status unknown", tone: "unknown" };
|
|
256
|
+
const now = status.readAtMs;
|
|
257
|
+
const usage = `${status.beats24h} beat${status.beats24h === 1 ? "" : "s"} / ${compactTokens(status.tokens24h)} tokens in 24h${status.cap ? ` of ${compactTokens(status.cap)}` : ""}`;
|
|
258
|
+
const tick = `last tick ${ago(status.lastTickMs, now)}`;
|
|
259
|
+
const stalled = engineStalled(status) ? " - not ticking" : "";
|
|
260
|
+
if (status.outcome === "cranked") return { text: `${tick} (cranked)${stalled} \xB7 ${usage}`, tone: stalled ? "warn" : "ok" };
|
|
261
|
+
if (status.outcome === "refused") {
|
|
262
|
+
const since = status.refusedSinceMs !== void 0 && status.refusedSinceMs < status.lastTickMs ? ` since ${ago(status.refusedSinceMs, now)}` : "";
|
|
263
|
+
const resume = status.tokenBlocked && status.resumeMs !== void 0 ? ` \xB7 resumes \u2248 ${clockTime(nextTickAtOrAfter(status.resumeMs))}` : "";
|
|
264
|
+
return { text: `REFUSING${since}: ${status.reason ?? "refused"} \xB7 ${tick}${stalled} \xB7 ${usage}${resume}`, tone: "warn" };
|
|
265
|
+
}
|
|
266
|
+
return { text: `${tick} (${status.lastStatus ?? "other"}${status.reason ? `: ${status.reason}` : ""})${stalled} \xB7 ${usage}`, tone: "warn" };
|
|
267
|
+
}
|
|
268
|
+
|
|
216
269
|
// src/crank/index.ts
|
|
217
270
|
var ZCRANK_INTERVALS = ["5m", "1h", "6h", "1d"];
|
|
218
271
|
var INTERVAL_SECONDS = { "5m": 300, "1h": 3600, "6h": 21600, "1d": 86400 };
|
|
@@ -239,6 +292,7 @@ function formatAge(thenMs, nowMs) {
|
|
|
239
292
|
if (s < 60) return `${s}s ago`;
|
|
240
293
|
return `${formatDuration(s)} ago`;
|
|
241
294
|
}
|
|
295
|
+
var PANE_CWD_TTL_SECONDS = 6 * 3600;
|
|
242
296
|
function renderLogRow(raw) {
|
|
243
297
|
try {
|
|
244
298
|
const parsed = JSON.parse(raw);
|
|
@@ -294,10 +348,6 @@ async function pickInterval(props, run = {}) {
|
|
|
294
348
|
const choice = await runInk((finish) => /* @__PURE__ */ jsx3(IntervalPicker, { ...props, onDone: finish }), run);
|
|
295
349
|
return choice ?? null;
|
|
296
350
|
}
|
|
297
|
-
function clockTime(ms) {
|
|
298
|
-
const d = new Date(ms);
|
|
299
|
-
return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
300
|
-
}
|
|
301
351
|
function describeMatch(view) {
|
|
302
352
|
const { resolution } = view;
|
|
303
353
|
if (resolution.storedAsIs) return `no live tab or key matches "${view.name}" - stored under the project name`;
|
|
@@ -346,6 +396,9 @@ function CrankDashboard({ controller, refreshMs = 5e3, clock = Date.now, onQuit
|
|
|
346
396
|
});
|
|
347
397
|
const onInterval = (interval) => act(`interval ${interval}`, () => controller.setInterval(interval));
|
|
348
398
|
const next = nextRunMs({ enabled: isOn, interval: snap.interval, lastRun: snap.lastRunMs, nowMs: now });
|
|
399
|
+
const engineLine = engineSummary(view.engine);
|
|
400
|
+
const blocked = isOn ? engineBlockedLabel(view.engine) : void 0;
|
|
401
|
+
const engineColor = engineLine.tone === "ok" ? themeColor("ok") : engineLine.tone === "warn" ? themeColor("warn") : themeColor("muted");
|
|
349
402
|
const logRows = Math.max(3, (rows || 24) - 19);
|
|
350
403
|
const tail = snap.log.slice(-logRows);
|
|
351
404
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 1, children: [
|
|
@@ -390,7 +443,7 @@ function CrankDashboard({ controller, refreshMs = 5e3, clock = Date.now, onQuit
|
|
|
390
443
|
] }),
|
|
391
444
|
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
392
445
|
/* @__PURE__ */ jsx3(Text3, { color: themeColor("muted"), children: "Next run " }),
|
|
393
|
-
next === void 0 ? /* @__PURE__ */ jsx3(Text3, { color: themeColor("muted"), children: "off" }) : /* @__PURE__ */ jsxs3(Text3, { children: [
|
|
446
|
+
next === void 0 ? /* @__PURE__ */ jsx3(Text3, { color: themeColor("muted"), children: "off" }) : blocked ? /* @__PURE__ */ jsx3(Text3, { color: themeColor("warn"), children: blocked }) : /* @__PURE__ */ jsxs3(Text3, { children: [
|
|
394
447
|
next <= now ? "now" : `in ${formatDuration((next - now) / 1e3)}`,
|
|
395
448
|
" ",
|
|
396
449
|
/* @__PURE__ */ jsxs3(Text3, { color: themeColor("muted"), children: [
|
|
@@ -400,8 +453,12 @@ function CrankDashboard({ controller, refreshMs = 5e3, clock = Date.now, onQuit
|
|
|
400
453
|
] })
|
|
401
454
|
] })
|
|
402
455
|
] }),
|
|
456
|
+
/* @__PURE__ */ jsxs3(Text3, { wrap: "truncate-end", children: [
|
|
457
|
+
/* @__PURE__ */ jsx3(Text3, { color: themeColor("muted"), children: "Engine " }),
|
|
458
|
+
/* @__PURE__ */ jsx3(Text3, { color: engineColor, children: engineLine.text })
|
|
459
|
+
] }),
|
|
403
460
|
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
|
|
404
|
-
/* @__PURE__ */ jsx3(Text3, { color: themeColor("muted"), children: "Last runs" }),
|
|
461
|
+
/* @__PURE__ */ jsx3(Text3, { color: themeColor("muted"), children: "Last runs of this tab (beats that touched it, not engine ticks)" }),
|
|
405
462
|
snap.beats.length === 0 ? /* @__PURE__ */ jsx3(Text3, { color: themeColor("muted"), children: " none yet" }) : snap.beats.map((beat, i) => /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate-end", children: [
|
|
406
463
|
" ",
|
|
407
464
|
formatAge(beat.tsMs, now).padEnd(10),
|