@ironbee-ai/cli 0.11.4 → 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/CHANGELOG.md +12 -0
- package/README.md +17 -3
- package/dist/assets/banner.txt +1 -1
- package/dist/clients/claude/hooks/session-start.d.ts.map +1 -1
- package/dist/clients/claude/hooks/session-start.js +7 -0
- package/dist/clients/claude/hooks/session-start.js.map +1 -1
- package/dist/clients/claude/hooks/session-status.d.ts +129 -0
- package/dist/clients/claude/hooks/session-status.d.ts.map +1 -0
- package/dist/clients/claude/hooks/session-status.js +450 -0
- package/dist/clients/claude/hooks/session-status.js.map +1 -0
- package/dist/clients/claude/index.d.ts +26 -0
- package/dist/clients/claude/index.d.ts.map +1 -1
- package/dist/clients/claude/index.js +151 -0
- package/dist/clients/claude/index.js.map +1 -1
- package/dist/clients/cursor/index.d.ts.map +1 -1
- package/dist/clients/cursor/index.js +6 -0
- package/dist/clients/cursor/index.js.map +1 -1
- package/dist/clients/registry.d.ts +8 -9
- package/dist/clients/registry.d.ts.map +1 -1
- package/dist/clients/registry.js +13 -11
- package/dist/clients/registry.js.map +1 -1
- package/dist/commands/config.d.ts +5 -4
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +10 -4
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/hook.js +44 -0
- package/dist/commands/hook.js.map +1 -1
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +4 -5
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/register.d.ts +0 -1
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +7 -27
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/statusline-toggle.d.ts +29 -0
- package/dist/commands/statusline-toggle.d.ts.map +1 -0
- package/dist/commands/statusline-toggle.js +114 -0
- package/dist/commands/statusline-toggle.js.map +1 -0
- package/dist/commands/statusline.d.ts +24 -0
- package/dist/commands/statusline.d.ts.map +1 -0
- package/dist/commands/statusline.js +79 -0
- package/dist/commands/statusline.js.map +1 -0
- package/dist/commands/uninstall.d.ts +2 -3
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +3 -4
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/unregister.d.ts +0 -1
- package/dist/commands/unregister.d.ts.map +1 -1
- package/dist/commands/unregister.js +3 -24
- package/dist/commands/unregister.js.map +1 -1
- package/dist/hooks/core/session-state.d.ts +25 -0
- package/dist/hooks/core/session-state.d.ts.map +1 -1
- package/dist/hooks/core/session-state.js +49 -1
- package/dist/hooks/core/session-state.js.map +1 -1
- package/dist/index.js +35 -15
- package/dist/index.js.map +1 -1
- package/dist/lib/config.d.ts +64 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +48 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/event.d.ts +60 -0
- package/dist/lib/event.d.ts.map +1 -1
- package/dist/lib/event.js +1 -0
- package/dist/lib/event.js.map +1 -1
- package/dist/lib/fs-prune.d.ts +20 -0
- package/dist/lib/fs-prune.d.ts.map +1 -0
- package/dist/lib/fs-prune.js +72 -0
- package/dist/lib/fs-prune.js.map +1 -0
- package/dist/lib/gitignore.d.ts.map +1 -1
- package/dist/lib/gitignore.js +11 -0
- package/dist/lib/gitignore.js.map +1 -1
- package/dist/lib/install-snapshots.d.ts +70 -0
- package/dist/lib/install-snapshots.d.ts.map +1 -0
- package/dist/lib/install-snapshots.js +168 -0
- package/dist/lib/install-snapshots.js.map +1 -0
- package/dist/lib/projects-registry.d.ts +6 -13
- package/dist/lib/projects-registry.d.ts.map +1 -1
- package/dist/lib/projects-registry.js +11 -46
- package/dist/lib/projects-registry.js.map +1 -1
- package/dist/tui/command.d.ts +18 -0
- package/dist/tui/command.d.ts.map +1 -0
- package/dist/tui/command.js +87 -0
- package/dist/tui/command.js.map +1 -0
- package/dist/tui/config/area.d.ts +6 -0
- package/dist/tui/config/area.d.ts.map +1 -0
- package/dist/tui/config/area.js +16 -0
- package/dist/tui/config/area.js.map +1 -0
- package/dist/tui/config/docs.d.ts +28 -0
- package/dist/tui/config/docs.d.ts.map +1 -0
- package/dist/tui/config/docs.js +68 -0
- package/dist/tui/config/docs.js.map +1 -0
- package/dist/tui/config/edit.d.ts +36 -0
- package/dist/tui/config/edit.d.ts.map +1 -0
- package/dist/tui/config/edit.js +69 -0
- package/dist/tui/config/edit.js.map +1 -0
- package/dist/tui/config/introspect.d.ts +58 -0
- package/dist/tui/config/introspect.d.ts.map +1 -0
- package/dist/tui/config/introspect.js +93 -0
- package/dist/tui/config/introspect.js.map +1 -0
- package/dist/tui/config/schema.d.ts +81 -0
- package/dist/tui/config/schema.d.ts.map +1 -0
- package/dist/tui/config/schema.js +534 -0
- package/dist/tui/config/schema.js.map +1 -0
- package/dist/tui/config/tree.d.ts +39 -0
- package/dist/tui/config/tree.d.ts.map +1 -0
- package/dist/tui/config/tree.js +59 -0
- package/dist/tui/config/tree.js.map +1 -0
- package/dist/tui/config/value.d.ts +75 -0
- package/dist/tui/config/value.d.ts.map +1 -0
- package/dist/tui/config/value.js +228 -0
- package/dist/tui/config/value.js.map +1 -0
- package/dist/tui/config/view.d.ts +13 -0
- package/dist/tui/config/view.d.ts.map +1 -0
- package/dist/tui/config/view.js +423 -0
- package/dist/tui/config/view.js.map +1 -0
- package/dist/tui/import/area.d.ts +11 -0
- package/dist/tui/import/area.d.ts.map +1 -0
- package/dist/tui/import/area.js +202 -0
- package/dist/tui/import/area.js.map +1 -0
- package/dist/tui/index.d.ts +9 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +14 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/platforms/area.d.ts +12 -0
- package/dist/tui/platforms/area.d.ts.map +1 -0
- package/dist/tui/platforms/area.js +228 -0
- package/dist/tui/platforms/area.js.map +1 -0
- package/dist/tui/projects/area.d.ts +26 -0
- package/dist/tui/projects/area.d.ts.map +1 -0
- package/dist/tui/projects/area.js +588 -0
- package/dist/tui/projects/area.js.map +1 -0
- package/dist/tui/queue/area.d.ts +11 -0
- package/dist/tui/queue/area.d.ts.map +1 -0
- package/dist/tui/queue/area.js +338 -0
- package/dist/tui/queue/area.js.map +1 -0
- package/dist/tui/queue/read.d.ts +49 -0
- package/dist/tui/queue/read.d.ts.map +1 -0
- package/dist/tui/queue/read.js +261 -0
- package/dist/tui/queue/read.js.map +1 -0
- package/dist/tui/sessions/area.d.ts +10 -0
- package/dist/tui/sessions/area.d.ts.map +1 -0
- package/dist/tui/sessions/area.js +266 -0
- package/dist/tui/sessions/area.js.map +1 -0
- package/dist/tui/sessions/read.d.ts +79 -0
- package/dist/tui/sessions/read.d.ts.map +1 -0
- package/dist/tui/sessions/read.js +202 -0
- package/dist/tui/sessions/read.js.map +1 -0
- package/dist/tui/shell/area.d.ts +47 -0
- package/dist/tui/shell/area.d.ts.map +1 -0
- package/dist/tui/shell/area.js +13 -0
- package/dist/tui/shell/area.js.map +1 -0
- package/dist/tui/shell/frame.d.ts +23 -0
- package/dist/tui/shell/frame.d.ts.map +1 -0
- package/dist/tui/shell/frame.js +91 -0
- package/dist/tui/shell/frame.js.map +1 -0
- package/dist/tui/shell/registry.d.ts +11 -0
- package/dist/tui/shell/registry.d.ts.map +1 -0
- package/dist/tui/shell/registry.js +29 -0
- package/dist/tui/shell/registry.js.map +1 -0
- package/dist/tui/shell/rerender.d.ts +16 -0
- package/dist/tui/shell/rerender.d.ts.map +1 -0
- package/dist/tui/shell/rerender.js +34 -0
- package/dist/tui/shell/rerender.js.map +1 -0
- package/dist/tui/shell/session.d.ts +75 -0
- package/dist/tui/shell/session.d.ts.map +1 -0
- package/dist/tui/shell/session.js +333 -0
- package/dist/tui/shell/session.js.map +1 -0
- package/dist/tui/shell/shell.d.ts +16 -0
- package/dist/tui/shell/shell.d.ts.map +1 -0
- package/dist/tui/shell/shell.js +213 -0
- package/dist/tui/shell/shell.js.map +1 -0
- package/dist/tui/shell/util.d.ts +18 -0
- package/dist/tui/shell/util.d.ts.map +1 -0
- package/dist/tui/shell/util.js +31 -0
- package/dist/tui/shell/util.js.map +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* IronBee — Queue area (read-only)
|
|
4
|
+
*
|
|
5
|
+
* Per-session view of the file-backed job queue: pending jobs (live + frozen
|
|
6
|
+
* snapshots) and dead-letter counts. Read-only operator view backed by the pure
|
|
7
|
+
* `listQueues` reader; draining / retrying stays on the `ironbee queue` CLI
|
|
8
|
+
* (those spawn workers / print, which would corrupt the screen).
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.queueArea = void 0;
|
|
45
|
+
const blessed = __importStar(require("blessed"));
|
|
46
|
+
const fs_1 = require("fs");
|
|
47
|
+
const path_1 = require("path");
|
|
48
|
+
const queue_1 = require("../../queue");
|
|
49
|
+
const util_1 = require("../shell/util");
|
|
50
|
+
const import_1 = require("../../import");
|
|
51
|
+
const read_1 = require("./read");
|
|
52
|
+
const STATUS = " {bold}↑/↓{/bold} move {bold}d{/bold} drain {bold}D{/bold} drain-all {bold}l{/bold} dead-letter {bold}s{/bold} stats {bold}c{/bold} clear {bold}p{/bold} purge "
|
|
53
|
+
+ "{bold}r{/bold} refresh {bold}Esc{/bold} back {bold}q{/bold} quit";
|
|
54
|
+
function mountQueueView(ctx) {
|
|
55
|
+
const projectDir = ctx.session.projectDir;
|
|
56
|
+
let queues = (0, read_1.listQueues)(projectDir);
|
|
57
|
+
let index = 0;
|
|
58
|
+
const list = blessed.list({
|
|
59
|
+
parent: ctx.container,
|
|
60
|
+
top: 0,
|
|
61
|
+
left: 0,
|
|
62
|
+
width: "62%",
|
|
63
|
+
height: "100%",
|
|
64
|
+
border: { type: "line" },
|
|
65
|
+
label: " Queue (per session) ",
|
|
66
|
+
tags: true,
|
|
67
|
+
keys: false,
|
|
68
|
+
mouse: false,
|
|
69
|
+
scrollbar: { ch: " " },
|
|
70
|
+
style: { selected: { bg: "blue", fg: "white" }, border: { fg: "cyan" } },
|
|
71
|
+
items: [],
|
|
72
|
+
});
|
|
73
|
+
const detail = blessed.box({
|
|
74
|
+
parent: ctx.container,
|
|
75
|
+
top: 0,
|
|
76
|
+
left: "62%",
|
|
77
|
+
width: "38%",
|
|
78
|
+
height: "100%",
|
|
79
|
+
border: { type: "line" },
|
|
80
|
+
label: " Detail ",
|
|
81
|
+
tags: true,
|
|
82
|
+
scrollable: true,
|
|
83
|
+
alwaysScroll: true,
|
|
84
|
+
scrollbar: { ch: " " },
|
|
85
|
+
style: { border: { fg: "cyan" } },
|
|
86
|
+
content: "",
|
|
87
|
+
});
|
|
88
|
+
function rowLabel(q) {
|
|
89
|
+
const shortId = q.sessionId.length > 16 ? q.sessionId.slice(0, 15) + "…" : q.sessionId.padEnd(16, " ");
|
|
90
|
+
const pend = q.pending > 0 ? `{yellow-fg}${q.pending} pending{/yellow-fg}` : "{gray-fg}0 pending{/gray-fg}";
|
|
91
|
+
const dl = q.deadLetter > 0 ? ` {red-fg}${q.deadLetter} dead{/red-fg}` : "";
|
|
92
|
+
return `${(0, util_1.escapeTags)(shortId)} ${pend}${dl}`;
|
|
93
|
+
}
|
|
94
|
+
function buildDetail(q) {
|
|
95
|
+
if (q === undefined) {
|
|
96
|
+
return "{gray-fg}No queues for this project.{/gray-fg}";
|
|
97
|
+
}
|
|
98
|
+
const lines = [];
|
|
99
|
+
lines.push(`{bold}${(0, util_1.escapeTags)(q.sessionId)}{/bold}`);
|
|
100
|
+
lines.push("{gray-fg}" + "─".repeat(34) + "{/gray-fg}");
|
|
101
|
+
lines.push(`{gray-fg}pending jobs:{/gray-fg} ${q.pending}`);
|
|
102
|
+
lines.push(`{gray-fg}snapshots:{/gray-fg} ${q.snapshots}`);
|
|
103
|
+
lines.push(`{gray-fg}dead-letter:{/gray-fg} ${q.deadLetter > 0 ? `{red-fg}${q.deadLetter}{/red-fg}` : "0"}`);
|
|
104
|
+
lines.push("");
|
|
105
|
+
lines.push("{gray-fg}d drain · l dead-letter (pick one to retry) · c clear dead-letter{/gray-fg}");
|
|
106
|
+
return lines.join("\n");
|
|
107
|
+
}
|
|
108
|
+
function render() {
|
|
109
|
+
if (queues.length === 0) {
|
|
110
|
+
list.setItems(["{gray-fg}(no queues){/gray-fg}"]);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
list.setItems(queues.map((q) => rowLabel(q)));
|
|
114
|
+
list.select((0, util_1.clamp)(index, 0, queues.length - 1));
|
|
115
|
+
}
|
|
116
|
+
const cur = queues.length === 0 ? undefined : queues[(0, util_1.clamp)(index, 0, queues.length - 1)];
|
|
117
|
+
detail.setContent(buildDetail(cur));
|
|
118
|
+
detail.setScroll(0);
|
|
119
|
+
ctx.screen.render();
|
|
120
|
+
}
|
|
121
|
+
function move(delta) {
|
|
122
|
+
if (queues.length === 0) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
index = (0, util_1.clamp)(index + delta, 0, queues.length - 1);
|
|
126
|
+
render();
|
|
127
|
+
}
|
|
128
|
+
function current() {
|
|
129
|
+
return queues.length === 0 ? undefined : queues[(0, util_1.clamp)(index, 0, queues.length - 1)];
|
|
130
|
+
}
|
|
131
|
+
function refresh() {
|
|
132
|
+
queues = (0, read_1.listQueues)(projectDir);
|
|
133
|
+
index = (0, util_1.clamp)(index, 0, Math.max(0, queues.length - 1));
|
|
134
|
+
render();
|
|
135
|
+
}
|
|
136
|
+
async function drainSession() {
|
|
137
|
+
const q = current();
|
|
138
|
+
if (q === undefined) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
await ctx.session.runWithOutput(`Drain ${q.sessionId}`, async () => {
|
|
142
|
+
const result = await (0, queue_1.drain)(projectDir, q.sessionId);
|
|
143
|
+
return `Drain result:\n${JSON.stringify(result, null, 2)}`;
|
|
144
|
+
});
|
|
145
|
+
refresh();
|
|
146
|
+
}
|
|
147
|
+
function entryLabel(e, i) {
|
|
148
|
+
if ("original" in e) {
|
|
149
|
+
return `#${i + 1} ${e.original.id} [${e.category}] ${e.original.type}`;
|
|
150
|
+
}
|
|
151
|
+
return `#${i + 1} (unparseable record)`;
|
|
152
|
+
}
|
|
153
|
+
function retryEntry(sessionId, entry) {
|
|
154
|
+
ctx.session.confirm(`Re-submit job ${entry.original.id} (${entry.original.type}) to the live queue?`, (yes) => {
|
|
155
|
+
if (!yes) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
if ((0, read_1.removeDeadLetterEntry)(projectDir, sessionId, entry.original.id)) {
|
|
160
|
+
(0, queue_1.submit)(projectDir, sessionId, entry.original.type, entry.original.data, { id: entry.original.id });
|
|
161
|
+
refresh();
|
|
162
|
+
ctx.session.message(`Re-submitted ${entry.original.id}. It will ship on the next drain / flush.`);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
ctx.session.message("Entry no longer present — refresh and try again.");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
ctx.session.message(`Retry failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
function deadLetterManage() {
|
|
174
|
+
const q = current();
|
|
175
|
+
if (q === undefined) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const entries = (0, queue_1.readDeadLetterEntries)(projectDir, q.sessionId);
|
|
179
|
+
if (entries.length === 0) {
|
|
180
|
+
ctx.session.message(`No dead-letter entries for ${q.sessionId}.`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
ctx.session.pick(`Dead-letter ${q.sessionId} — Enter to retry · Esc to close`, entries.map((e, i) => entryLabel(e, i)), (idx) => {
|
|
184
|
+
if (idx < 0 || idx >= entries.length) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const entry = entries[idx];
|
|
188
|
+
if (!("original" in entry)) {
|
|
189
|
+
ctx.session.message("That record couldn't be parsed — not retryable.");
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
retryEntry(q.sessionId, entry);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function clearDeadLetter() {
|
|
196
|
+
const q = current();
|
|
197
|
+
if (q === undefined || q.deadLetter === 0) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
ctx.session.confirm(`Clear ${q.deadLetter} dead-letter entr${q.deadLetter === 1 ? "y" : "ies"} for ${q.sessionId}?`, (yes) => {
|
|
201
|
+
if (!yes) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
const main = (0, queue_1.deadLetterFile)(projectDir, q.sessionId);
|
|
206
|
+
if ((0, fs_1.existsSync)(main)) {
|
|
207
|
+
(0, fs_1.writeFileSync)(main, "");
|
|
208
|
+
}
|
|
209
|
+
const dir = (0, queue_1.queueDir)(projectDir, q.sessionId);
|
|
210
|
+
if ((0, fs_1.existsSync)(dir)) {
|
|
211
|
+
for (const name of (0, fs_1.readdirSync)(dir)) {
|
|
212
|
+
if (queue_1.DEAD_LETTER_ROTATED_REGEX.test(name)) {
|
|
213
|
+
(0, fs_1.unlinkSync)((0, path_1.join)(dir, name));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
refresh();
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
ctx.session.message(`Clear failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
list.key(["up", "k"], () => move(-1));
|
|
225
|
+
list.key(["down", "j"], () => move(1));
|
|
226
|
+
function deadLetterStatsView() {
|
|
227
|
+
const q = current();
|
|
228
|
+
if (q === undefined) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const entries = (0, queue_1.readDeadLetterEntries)(projectDir, q.sessionId);
|
|
232
|
+
if (entries.length === 0) {
|
|
233
|
+
ctx.session.message(`No dead-letter entries for ${q.sessionId}.`);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const stats = (0, read_1.deadLetterStats)(entries);
|
|
237
|
+
const lines = [
|
|
238
|
+
`{bold}Dead-letter stats — ${(0, util_1.escapeTags)(q.sessionId)}{/bold}`,
|
|
239
|
+
"{gray-fg}" + "─".repeat(34) + "{/gray-fg}",
|
|
240
|
+
`total: {bold}${stats.total}{/bold}`,
|
|
241
|
+
"",
|
|
242
|
+
];
|
|
243
|
+
for (const cat of Object.keys(stats.byCategory).sort()) {
|
|
244
|
+
lines.push(` ${(0, util_1.escapeTags)(cat)}: {bold}${stats.byCategory[cat]}{/bold}`);
|
|
245
|
+
}
|
|
246
|
+
ctx.session.showPane(`Dead-letter stats — ${q.sessionId}`, lines.join("\n"));
|
|
247
|
+
}
|
|
248
|
+
async function drainAll() {
|
|
249
|
+
await ctx.session.runWithOutput("Drain — all sessions", async () => {
|
|
250
|
+
const all = (0, read_1.listQueues)(projectDir);
|
|
251
|
+
if (all.length === 0) {
|
|
252
|
+
return "No sessions to drain.";
|
|
253
|
+
}
|
|
254
|
+
for (const sq of all) {
|
|
255
|
+
const result = await (0, queue_1.drain)(projectDir, sq.sessionId);
|
|
256
|
+
console.log(`${sq.sessionId}: ${JSON.stringify(result)}`);
|
|
257
|
+
}
|
|
258
|
+
return `\nDrained ${all.length} session(s).`;
|
|
259
|
+
});
|
|
260
|
+
refresh();
|
|
261
|
+
}
|
|
262
|
+
function purgeSnapshotsFlow() {
|
|
263
|
+
ctx.session.confirm("Purge ALL pending queue snapshots for this project, WITHOUT processing them? (destructive)", (yes) => {
|
|
264
|
+
if (!yes) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const n = (0, read_1.purgeSnapshots)(projectDir);
|
|
269
|
+
refresh();
|
|
270
|
+
ctx.session.message(`Purged ${n} snapshot file(s).`);
|
|
271
|
+
}
|
|
272
|
+
catch (e) {
|
|
273
|
+
ctx.session.message(`Purge failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
function purgeOldSessionsFlow() {
|
|
278
|
+
ctx.session.prompt("Remove EMPTY session queues older than (e.g. 14d, 2w, 6m, 12h):", "14d", (raw) => {
|
|
279
|
+
if (raw === null || raw.trim().length === 0) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const ms = (0, import_1.parseSinceDuration)(raw.trim());
|
|
283
|
+
if (ms === null) {
|
|
284
|
+
ctx.session.message(`Invalid duration "${raw.trim()}". Use forms like 14d, 2w, 6m, 12h.`);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
ctx.session.confirm(`Remove empty session queue dirs older than ${raw.trim()}? (destructive)`, (yes) => {
|
|
288
|
+
if (!yes) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
const n = (0, read_1.purgeOldSessions)(projectDir, ms);
|
|
293
|
+
refresh();
|
|
294
|
+
ctx.session.message(`Removed ${n} old empty queue dir(s).`);
|
|
295
|
+
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
ctx.session.message(`Purge failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
function purge() {
|
|
303
|
+
ctx.session.pick("Purge what?", ["Pending snapshots (all sessions, no processing)", "Old empty session queues (older-than…)"], (idx) => {
|
|
304
|
+
if (idx === 0) {
|
|
305
|
+
purgeSnapshotsFlow();
|
|
306
|
+
}
|
|
307
|
+
else if (idx === 1) {
|
|
308
|
+
purgeOldSessionsFlow();
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
list.key(["d"], () => { void drainSession(); });
|
|
313
|
+
list.key(["S-d"], () => { void drainAll(); });
|
|
314
|
+
list.key(["l"], () => deadLetterManage());
|
|
315
|
+
list.key(["s"], () => deadLetterStatsView());
|
|
316
|
+
list.key(["c"], () => clearDeadLetter());
|
|
317
|
+
list.key(["p"], () => purge());
|
|
318
|
+
list.key(["r"], () => refresh());
|
|
319
|
+
ctx.setStatus(STATUS);
|
|
320
|
+
render();
|
|
321
|
+
list.focus();
|
|
322
|
+
ctx.screen.render();
|
|
323
|
+
return {
|
|
324
|
+
unmount() {
|
|
325
|
+
list.destroy();
|
|
326
|
+
detail.destroy();
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
exports.queueArea = {
|
|
331
|
+
id: "queue",
|
|
332
|
+
title: "Queue",
|
|
333
|
+
summary: "Per-session job queue: drain · dead-letter view/retry/clear/stats · purge",
|
|
334
|
+
mount(ctx) {
|
|
335
|
+
return mountQueueView(ctx);
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
//# sourceMappingURL=area.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"area.js","sourceRoot":"","sources":["../../../src/tui/queue/area.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IronBee — Queue area: pure reader
|
|
3
|
+
*
|
|
4
|
+
* Summarizes the file-backed job queue per session by counting lines in the
|
|
5
|
+
* queue artifacts under `<projectDir>/.ironbee/sessions/<id>/queue/`:
|
|
6
|
+
* - pending = live `jobs.jsonl` + frozen `jobs-<uuid>.jsonl` snapshots
|
|
7
|
+
* - deadLetter = `dead-letter.jsonl` + rotated `dead-letter-<uuid>.jsonl`
|
|
8
|
+
* fs-only, no blessed; unit-tested independently.
|
|
9
|
+
*/
|
|
10
|
+
import { DeadLetterEntry } from "../../queue";
|
|
11
|
+
/** One session's queue counts. */
|
|
12
|
+
export interface QueueSummary {
|
|
13
|
+
sessionId: string;
|
|
14
|
+
pending: number;
|
|
15
|
+
snapshots: number;
|
|
16
|
+
deadLetter: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Summarize the queue for every session under a project. Returns `[]` when the
|
|
20
|
+
* project has no `.ironbee/sessions` directory. Sessions without a `queue/`
|
|
21
|
+
* subdir are included with zero counts.
|
|
22
|
+
*/
|
|
23
|
+
export declare function listQueues(projectDir: string): QueueSummary[];
|
|
24
|
+
/**
|
|
25
|
+
* Remove the dead-letter entry whose `original.id === jobId` from the session's
|
|
26
|
+
* `dead-letter.jsonl` (atomic tmp+rename, keeping all other lines). Returns
|
|
27
|
+
* `true` when an entry was removed. Mirrors the `ironbee queue dead-letter
|
|
28
|
+
* retry` rewrite; the caller re-submits the job afterward. fs-only, unit-tested.
|
|
29
|
+
*/
|
|
30
|
+
export declare function removeDeadLetterEntry(projectDir: string, sessionId: string, jobId: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Delete all frozen snapshot files (`jobs-<uuid>.jsonl`) across every session's
|
|
33
|
+
* queue dir WITHOUT processing them. Returns the number deleted. Mirrors
|
|
34
|
+
* `ironbee queue purge --snapshots` (destructive). fs-only, unit-tested.
|
|
35
|
+
*/
|
|
36
|
+
export declare function purgeSnapshots(projectDir: string): number;
|
|
37
|
+
/**
|
|
38
|
+
* Remove queue/ subdirs that are BOTH empty (no pending jobs, no snapshots, no
|
|
39
|
+
* dead-letter) AND older than `olderThanMs`. Returns the number removed. Mirrors
|
|
40
|
+
* `ironbee queue purge --sessions older-than=<dur>` (the safety rule — never
|
|
41
|
+
* remove a dir with undelivered work). fs-only, unit-tested.
|
|
42
|
+
*/
|
|
43
|
+
export declare function purgeOldSessions(projectDir: string, olderThanMs: number): number;
|
|
44
|
+
/** Histogram of dead-letter entries by category (the `dead-letter stats` view). */
|
|
45
|
+
export declare function deadLetterStats(entries: DeadLetterEntry[]): {
|
|
46
|
+
total: number;
|
|
47
|
+
byCategory: Record<string, number>;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/tui/queue/read.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAkB,eAAe,EAA2B,MAAM,aAAa,CAAC;AAEvF,kCAAkC;AAClC,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB;AA+CD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE,CAoB7D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAmDnG;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAqCzD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAyChF;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAOjH"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* IronBee — Queue area: pure reader
|
|
4
|
+
*
|
|
5
|
+
* Summarizes the file-backed job queue per session by counting lines in the
|
|
6
|
+
* queue artifacts under `<projectDir>/.ironbee/sessions/<id>/queue/`:
|
|
7
|
+
* - pending = live `jobs.jsonl` + frozen `jobs-<uuid>.jsonl` snapshots
|
|
8
|
+
* - deadLetter = `dead-letter.jsonl` + rotated `dead-letter-<uuid>.jsonl`
|
|
9
|
+
* fs-only, no blessed; unit-tested independently.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.listQueues = listQueues;
|
|
13
|
+
exports.removeDeadLetterEntry = removeDeadLetterEntry;
|
|
14
|
+
exports.purgeSnapshots = purgeSnapshots;
|
|
15
|
+
exports.purgeOldSessions = purgeOldSessions;
|
|
16
|
+
exports.deadLetterStats = deadLetterStats;
|
|
17
|
+
const fs_1 = require("fs");
|
|
18
|
+
const path_1 = require("path");
|
|
19
|
+
const queue_1 = require("../../queue");
|
|
20
|
+
function countLines(filePath) {
|
|
21
|
+
try {
|
|
22
|
+
const raw = (0, fs_1.readFileSync)(filePath, "utf-8");
|
|
23
|
+
return raw.split("\n").filter((l) => l.trim().length > 0).length;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function isFile(filePath) {
|
|
30
|
+
try {
|
|
31
|
+
return (0, fs_1.statSync)(filePath).isFile();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Summarize one session's queue dir. */
|
|
38
|
+
function readQueueDir(queueDir, sessionId) {
|
|
39
|
+
let pending = 0;
|
|
40
|
+
let snapshots = 0;
|
|
41
|
+
let deadLetter = 0;
|
|
42
|
+
let names = [];
|
|
43
|
+
try {
|
|
44
|
+
names = (0, fs_1.readdirSync)(queueDir);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
names = [];
|
|
48
|
+
}
|
|
49
|
+
for (const name of names) {
|
|
50
|
+
const full = (0, path_1.join)(queueDir, name);
|
|
51
|
+
if (!isFile(full)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (name === "jobs.jsonl") {
|
|
55
|
+
pending += countLines(full);
|
|
56
|
+
}
|
|
57
|
+
else if (/^jobs-.*\.jsonl$/.test(name)) {
|
|
58
|
+
snapshots += 1;
|
|
59
|
+
pending += countLines(full);
|
|
60
|
+
}
|
|
61
|
+
else if (name === "dead-letter.jsonl" || /^dead-letter-.*\.jsonl$/.test(name)) {
|
|
62
|
+
deadLetter += countLines(full);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { sessionId, pending, snapshots, deadLetter };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Summarize the queue for every session under a project. Returns `[]` when the
|
|
69
|
+
* project has no `.ironbee/sessions` directory. Sessions without a `queue/`
|
|
70
|
+
* subdir are included with zero counts.
|
|
71
|
+
*/
|
|
72
|
+
function listQueues(projectDir) {
|
|
73
|
+
const sessionsDir = (0, path_1.join)(projectDir, ".ironbee", "sessions");
|
|
74
|
+
if (!(0, fs_1.existsSync)(sessionsDir)) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
let ids;
|
|
78
|
+
try {
|
|
79
|
+
ids = (0, fs_1.readdirSync)(sessionsDir, { withFileTypes: true })
|
|
80
|
+
.filter((d) => d.isDirectory())
|
|
81
|
+
.map((d) => d.name);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const id of ids) {
|
|
88
|
+
const queueDir = (0, path_1.join)(sessionsDir, id, "queue");
|
|
89
|
+
out.push((0, fs_1.existsSync)(queueDir) ? readQueueDir(queueDir, id) : { sessionId: id, pending: 0, snapshots: 0, deadLetter: 0 });
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Remove the dead-letter entry whose `original.id === jobId` from the session's
|
|
95
|
+
* `dead-letter.jsonl` (atomic tmp+rename, keeping all other lines). Returns
|
|
96
|
+
* `true` when an entry was removed. Mirrors the `ironbee queue dead-letter
|
|
97
|
+
* retry` rewrite; the caller re-submits the job afterward. fs-only, unit-tested.
|
|
98
|
+
*/
|
|
99
|
+
function removeDeadLetterEntry(projectDir, sessionId, jobId) {
|
|
100
|
+
const dlPath = (0, queue_1.deadLetterFile)(projectDir, sessionId);
|
|
101
|
+
if (!(0, fs_1.existsSync)(dlPath)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
let content;
|
|
105
|
+
try {
|
|
106
|
+
content = (0, fs_1.readFileSync)(dlPath, "utf-8");
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const kept = [];
|
|
112
|
+
let removed = false;
|
|
113
|
+
for (const line of content.split("\n")) {
|
|
114
|
+
if (line.length === 0) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (!removed) {
|
|
118
|
+
try {
|
|
119
|
+
const parsed = JSON.parse(line);
|
|
120
|
+
if (parsed !== null && typeof parsed === "object" && "original" in parsed) {
|
|
121
|
+
const original = parsed.original;
|
|
122
|
+
if (original !== null && typeof original === "object" && original.id === jobId) {
|
|
123
|
+
removed = true;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// keep malformed lines — never risk data loss
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
kept.push(line);
|
|
133
|
+
}
|
|
134
|
+
if (!removed) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const tmp = `${dlPath}.tmp-${process.pid}-${Date.now()}`;
|
|
138
|
+
try {
|
|
139
|
+
(0, fs_1.writeFileSync)(tmp, kept.length > 0 ? kept.join("\n") + "\n" : "");
|
|
140
|
+
(0, fs_1.renameSync)(tmp, dlPath);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
try {
|
|
144
|
+
if ((0, fs_1.existsSync)(tmp)) {
|
|
145
|
+
(0, fs_1.unlinkSync)(tmp);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// best-effort cleanup
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Delete all frozen snapshot files (`jobs-<uuid>.jsonl`) across every session's
|
|
157
|
+
* queue dir WITHOUT processing them. Returns the number deleted. Mirrors
|
|
158
|
+
* `ironbee queue purge --snapshots` (destructive). fs-only, unit-tested.
|
|
159
|
+
*/
|
|
160
|
+
function purgeSnapshots(projectDir) {
|
|
161
|
+
const sessionsDir = (0, path_1.join)(projectDir, ".ironbee", "sessions");
|
|
162
|
+
if (!(0, fs_1.existsSync)(sessionsDir)) {
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
let ids;
|
|
166
|
+
try {
|
|
167
|
+
ids = (0, fs_1.readdirSync)(sessionsDir, { withFileTypes: true })
|
|
168
|
+
.filter((d) => d.isDirectory())
|
|
169
|
+
.map((d) => d.name);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
let removed = 0;
|
|
175
|
+
for (const id of ids) {
|
|
176
|
+
const qdir = (0, path_1.join)(sessionsDir, id, "queue");
|
|
177
|
+
if (!(0, fs_1.existsSync)(qdir)) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
let names;
|
|
181
|
+
try {
|
|
182
|
+
names = (0, fs_1.readdirSync)(qdir);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
for (const name of names) {
|
|
188
|
+
if (queue_1.SNAPSHOT_FILENAME_REGEX.test(name)) {
|
|
189
|
+
try {
|
|
190
|
+
(0, fs_1.unlinkSync)((0, path_1.join)(qdir, name));
|
|
191
|
+
removed += 1;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// best-effort
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return removed;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Remove queue/ subdirs that are BOTH empty (no pending jobs, no snapshots, no
|
|
203
|
+
* dead-letter) AND older than `olderThanMs`. Returns the number removed. Mirrors
|
|
204
|
+
* `ironbee queue purge --sessions older-than=<dur>` (the safety rule — never
|
|
205
|
+
* remove a dir with undelivered work). fs-only, unit-tested.
|
|
206
|
+
*/
|
|
207
|
+
function purgeOldSessions(projectDir, olderThanMs) {
|
|
208
|
+
const cutoff = Date.now() - olderThanMs;
|
|
209
|
+
const sessionsDir = (0, path_1.join)(projectDir, ".ironbee", "sessions");
|
|
210
|
+
if (!(0, fs_1.existsSync)(sessionsDir)) {
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
let ids;
|
|
214
|
+
try {
|
|
215
|
+
ids = (0, fs_1.readdirSync)(sessionsDir, { withFileTypes: true })
|
|
216
|
+
.filter((d) => d.isDirectory())
|
|
217
|
+
.map((d) => d.name);
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
222
|
+
let removed = 0;
|
|
223
|
+
for (const id of ids) {
|
|
224
|
+
const qdir = (0, path_1.join)(sessionsDir, id, "queue");
|
|
225
|
+
if (!(0, fs_1.existsSync)(qdir)) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const summary = readQueueDir(qdir, id);
|
|
229
|
+
if (summary.pending > 0 || summary.snapshots > 0 || summary.deadLetter > 0) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
let mtimeMs;
|
|
233
|
+
try {
|
|
234
|
+
mtimeMs = (0, fs_1.statSync)(qdir).mtimeMs;
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (mtimeMs > cutoff) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
(0, fs_1.rmSync)(qdir, { recursive: true, force: true });
|
|
244
|
+
removed += 1;
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// best-effort
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return removed;
|
|
251
|
+
}
|
|
252
|
+
/** Histogram of dead-letter entries by category (the `dead-letter stats` view). */
|
|
253
|
+
function deadLetterStats(entries) {
|
|
254
|
+
const byCategory = {};
|
|
255
|
+
for (const e of entries) {
|
|
256
|
+
const cat = "category" in e && typeof e.category === "string" ? e.category : "(unknown)";
|
|
257
|
+
byCategory[cat] = (byCategory[cat] ?? 0) + 1;
|
|
258
|
+
}
|
|
259
|
+
return { total: entries.length, byCategory };
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=read.js.map
|