patchrelay 0.25.4 → 0.25.6
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/build-info.json
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
function truncate(text, max) {
|
|
4
|
-
const line = text.replace(/\s+/g, " ").trim();
|
|
5
|
-
return line.length > max ? `${line.slice(0, Math.max(0, max - 3))}...` : line;
|
|
6
|
-
}
|
|
7
3
|
function cleanCommand(raw) {
|
|
8
4
|
const bashMatch = raw.match(/^\/bin\/(?:ba)?sh\s+-\w*c\s+['"](.+?)['"]$/s);
|
|
9
5
|
if (bashMatch?.[1])
|
|
@@ -21,7 +17,7 @@ function summarizeToolCall(item) {
|
|
|
21
17
|
return `used ${item.toolName ?? item.type}`;
|
|
22
18
|
}
|
|
23
19
|
function summarizeText(item) {
|
|
24
|
-
return
|
|
20
|
+
return (item.text ?? "").replace(/\s+/g, " ").trim();
|
|
25
21
|
}
|
|
26
22
|
function itemPrefix(item) {
|
|
27
23
|
if (item.type === "commandExecution")
|
|
@@ -35,7 +31,7 @@ function itemText(item) {
|
|
|
35
31
|
case "reasoning":
|
|
36
32
|
return summarizeText(item);
|
|
37
33
|
case "commandExecution":
|
|
38
|
-
return
|
|
34
|
+
return cleanCommand(item.command ?? "?");
|
|
39
35
|
case "fileChange":
|
|
40
36
|
return summarizeFileChange(item);
|
|
41
37
|
case "mcpToolCall":
|
|
@@ -62,5 +58,5 @@ export function ItemLine({ item }) {
|
|
|
62
58
|
return _jsx(_Fragment, {});
|
|
63
59
|
}
|
|
64
60
|
const color = itemColor(item);
|
|
65
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { wrap: "wrap", ...(color ? { color } : {}), children: [itemPrefix(item), text] }), item.output && item.status === "inProgress" && (_jsx(Text, { dimColor: true, wrap: "
|
|
61
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Text, { wrap: "wrap", bold: item.type === "agentMessage", ...(color ? { color } : {}), children: [itemPrefix(item), text] }), item.output && item.status === "inProgress" && (_jsx(Box, { paddingLeft: 2, children: _jsx(Text, { dimColor: true, wrap: "wrap", children: item.output.split("\n").filter(Boolean).at(-1) ?? "" }) }))] }));
|
|
66
62
|
}
|
|
@@ -21,5 +21,5 @@ export function Timeline({ entries, follow, mode }) {
|
|
|
21
21
|
if (displayRows.length === 0) {
|
|
22
22
|
return _jsx(Text, { dimColor: true, children: "No timeline events yet." });
|
|
23
23
|
}
|
|
24
|
-
return (_jsxs(Box, { flexDirection: "column", children: [finalized.length > 0 && (_jsx(Static, { items: finalized, children: (entry) => _jsx(TimelineRow, { entry: entry }, entry.id) })), active.map((entry) => (_jsx(TimelineRow, { entry: entry }, entry.id)))] }));
|
|
24
|
+
return (_jsxs(Box, { flexDirection: "column", children: [finalized.length > 0 && (_jsx(Static, { items: finalized, children: (entry) => _jsx(TimelineRow, { entry: entry, mode: mode }, entry.id) })), active.map((entry) => (_jsx(TimelineRow, { entry: entry, mode: mode }, entry.id)))] }));
|
|
25
25
|
}
|
|
@@ -51,31 +51,53 @@ function detailPrefix(detail) {
|
|
|
51
51
|
return "$ ";
|
|
52
52
|
return "";
|
|
53
53
|
}
|
|
54
|
+
function verboseItemLabel(type) {
|
|
55
|
+
switch (type) {
|
|
56
|
+
case "agentMessage":
|
|
57
|
+
return "message";
|
|
58
|
+
case "commandExecution":
|
|
59
|
+
return "command";
|
|
60
|
+
case "fileChange":
|
|
61
|
+
return "files";
|
|
62
|
+
case "mcpToolCall":
|
|
63
|
+
case "dynamicToolCall":
|
|
64
|
+
return "tool";
|
|
65
|
+
case "userMessage":
|
|
66
|
+
return "you";
|
|
67
|
+
case "plan":
|
|
68
|
+
return "plan";
|
|
69
|
+
case "reasoning":
|
|
70
|
+
return "reasoning";
|
|
71
|
+
default:
|
|
72
|
+
return type;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
54
75
|
function FeedRow({ entry }) {
|
|
55
76
|
const label = entry.feed.status ?? entry.feed.feedKind;
|
|
56
|
-
return (_jsxs(Box, { children: [_jsxs(Text, { dimColor: true, children: [formatTime(entry.at), " "] }), _jsx(Text, { color: "cyan", children: label.padEnd(12) }),
|
|
77
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { dimColor: true, children: [formatTime(entry.at), " "] }), _jsx(Text, { color: "cyan", bold: true, children: label.padEnd(12) })] }), _jsx(Box, { paddingLeft: 6, children: _jsx(Text, { wrap: "wrap", children: entry.feed.summary }) })] }));
|
|
57
78
|
}
|
|
58
|
-
function RunRow({ entry }) {
|
|
79
|
+
function RunRow({ entry, mode, }) {
|
|
59
80
|
const run = entry.run;
|
|
60
81
|
const color = runStatusColor(run.status);
|
|
61
82
|
const duration = run.endedAt ? formatDuration(run.startedAt, run.endedAt) : undefined;
|
|
62
|
-
|
|
83
|
+
const showVerboseItems = mode === "verbose" && entry.items.length > 0;
|
|
84
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { dimColor: true, children: [formatTime(entry.at), " "] }), _jsx(Text, { bold: true, color: "yellow", children: (RUN_LABELS[run.runType] ?? run.runType).padEnd(12) }), _jsxs(Text, { bold: true, color: color, children: [" ", runStatusLabel(run.status)] }), duration ? _jsx(Text, { dimColor: true, children: ` ${duration}` }) : null] }), entry.details.length > 0 && _jsx(Text, { children: " " }), entry.details.map((detail, index) => (_jsx(Box, { paddingLeft: 6, marginBottom: index === entry.details.length - 1 ? 0 : 1, children: _jsxs(Text, { wrap: "wrap", ...(detailColor(detail) ? { color: detailColor(detail) } : {}), bold: detail.tone === "message", children: [detailPrefix(detail), detail.text] }) }, `${entry.id}-detail-${index}`))), showVerboseItems && _jsx(Text, { children: " " }), showVerboseItems && entry.items.map((itemEntry, index) => (_jsxs(Box, { flexDirection: "column", paddingLeft: 6, marginBottom: index === entry.items.length - 1 ? 0 : 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { dimColor: true, children: [formatTime(itemEntry.at), " "] }), _jsx(Text, { dimColor: true, children: verboseItemLabel(itemEntry.item.type) })] }), _jsx(Box, { paddingLeft: 2, children: _jsx(ItemLine, { item: itemEntry.item }) })] }, `${entry.id}-item-${index}`)))] }));
|
|
63
85
|
}
|
|
64
|
-
function ItemRow({ entry }) {
|
|
65
|
-
return (
|
|
86
|
+
function ItemRow({ entry, mode, }) {
|
|
87
|
+
return (_jsxs(Box, { flexDirection: "column", paddingLeft: 6, marginBottom: mode === "verbose" ? 1 : 0, children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { dimColor: true, children: [formatTime(entry.at), " "] }), _jsx(Text, { dimColor: true, children: entry.item.type })] }), _jsx(Box, { paddingLeft: 2, children: _jsx(ItemLine, { item: entry.item }) })] }));
|
|
66
88
|
}
|
|
67
89
|
function CIChecksRow({ entry }) {
|
|
68
90
|
const ci = entry.ciChecks;
|
|
69
|
-
return (_jsxs(Box, { children: [_jsxs(Text, { dimColor: true, children: [formatTime(entry.at), " "] }), _jsx(Text, { color: CHECK_COLORS[ci.overall] ?? "white", children: "checks".padEnd(12) }), _jsx(
|
|
91
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { dimColor: true, children: [formatTime(entry.at), " "] }), _jsx(Text, { color: CHECK_COLORS[ci.overall] ?? "white", bold: true, children: "checks".padEnd(12) })] }), _jsx(Box, { paddingLeft: 6, gap: 2, flexWrap: "wrap", children: ci.checks.map((check, i) => (_jsxs(Text, { children: [_jsx(Text, { color: CHECK_COLORS[check.status] ?? "white", children: CHECK_SYMBOLS[check.status] ?? " " }), _jsx(Text, { dimColor: true, children: check.name })] }, `c-${i}`))) })] }));
|
|
70
92
|
}
|
|
71
|
-
export function TimelineRow({ entry }) {
|
|
93
|
+
export function TimelineRow({ entry, mode }) {
|
|
72
94
|
switch (entry.kind) {
|
|
73
95
|
case "feed":
|
|
74
96
|
return _jsx(FeedRow, { entry: entry });
|
|
75
97
|
case "run":
|
|
76
|
-
return _jsx(RunRow, { entry: entry });
|
|
98
|
+
return _jsx(RunRow, { entry: entry, mode: mode });
|
|
77
99
|
case "item":
|
|
78
|
-
return _jsx(ItemRow, { entry: entry });
|
|
100
|
+
return _jsx(ItemRow, { entry: entry, mode: mode });
|
|
79
101
|
case "ci-checks":
|
|
80
102
|
return _jsx(CIChecksRow, { entry: entry });
|
|
81
103
|
}
|
|
@@ -2,52 +2,98 @@ export function buildTimelineRows(entries, mode) {
|
|
|
2
2
|
return mode === "compact" ? buildCompactTimelineRows(entries) : buildVerboseTimelineRows(entries);
|
|
3
3
|
}
|
|
4
4
|
function buildVerboseTimelineRows(entries) {
|
|
5
|
-
|
|
5
|
+
const rows = [];
|
|
6
|
+
const runs = new Map();
|
|
7
|
+
for (const entry of entries) {
|
|
8
|
+
if (entry.kind === "run-start" && entry.runId !== undefined) {
|
|
9
|
+
const existing = runs.get(entry.runId);
|
|
10
|
+
if (!existing) {
|
|
11
|
+
const run = { ...entry.run };
|
|
12
|
+
runs.set(entry.runId, {
|
|
13
|
+
id: `run-${entry.runId}`,
|
|
14
|
+
at: run.startedAt,
|
|
15
|
+
run,
|
|
16
|
+
items: [],
|
|
17
|
+
endedAt: run.endedAt,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (entry.kind === "run-end" && entry.runId !== undefined) {
|
|
23
|
+
const existing = runs.get(entry.runId);
|
|
24
|
+
if (existing) {
|
|
25
|
+
existing.run = { ...entry.run };
|
|
26
|
+
existing.endedAt = entry.run?.endedAt;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const run = { ...entry.run };
|
|
30
|
+
runs.set(entry.runId, {
|
|
31
|
+
id: `run-${entry.runId}`,
|
|
32
|
+
at: run.startedAt,
|
|
33
|
+
run,
|
|
34
|
+
items: [],
|
|
35
|
+
endedAt: run.endedAt,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (entry.kind === "item" && entry.runId !== undefined && runs.has(entry.runId)) {
|
|
41
|
+
runs.get(entry.runId).items.push(entry.item);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
6
44
|
switch (entry.kind) {
|
|
7
|
-
case "run-start":
|
|
8
|
-
return [{
|
|
9
|
-
id: entry.id,
|
|
10
|
-
kind: "run",
|
|
11
|
-
at: entry.at,
|
|
12
|
-
finalized: false,
|
|
13
|
-
run: entry.run,
|
|
14
|
-
details: [],
|
|
15
|
-
}];
|
|
16
|
-
case "run-end":
|
|
17
|
-
return [{
|
|
18
|
-
id: entry.id,
|
|
19
|
-
kind: "run",
|
|
20
|
-
at: entry.at,
|
|
21
|
-
finalized: true,
|
|
22
|
-
run: entry.run,
|
|
23
|
-
details: [],
|
|
24
|
-
}];
|
|
25
45
|
case "feed":
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
rows.push({
|
|
47
|
+
id: entry.id,
|
|
48
|
+
kind: "feed",
|
|
49
|
+
at: entry.at,
|
|
50
|
+
finalized: true,
|
|
51
|
+
feed: entry.feed,
|
|
52
|
+
});
|
|
53
|
+
break;
|
|
33
54
|
case "ci-checks":
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
rows.push({
|
|
56
|
+
id: entry.id,
|
|
57
|
+
kind: "ci-checks",
|
|
58
|
+
at: entry.at,
|
|
59
|
+
finalized: true,
|
|
60
|
+
ciChecks: entry.ciChecks,
|
|
61
|
+
});
|
|
62
|
+
break;
|
|
41
63
|
case "item":
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
64
|
+
rows.push({
|
|
65
|
+
id: entry.id,
|
|
66
|
+
kind: "item",
|
|
67
|
+
at: entry.at,
|
|
68
|
+
finalized: entry.item?.status !== "inProgress",
|
|
69
|
+
item: entry.item,
|
|
70
|
+
});
|
|
71
|
+
break;
|
|
49
72
|
}
|
|
73
|
+
}
|
|
74
|
+
for (const [runId, run] of runs) {
|
|
75
|
+
rows.push({
|
|
76
|
+
id: run.id,
|
|
77
|
+
kind: "run",
|
|
78
|
+
at: run.at,
|
|
79
|
+
finalized: run.items.every((item) => item.status !== "inProgress") && run.run.status !== "running",
|
|
80
|
+
run: { ...run.run, ...(run.endedAt ? { endedAt: run.endedAt } : {}) },
|
|
81
|
+
details: [],
|
|
82
|
+
items: entries
|
|
83
|
+
.filter((entry) => entry.kind === "item" && entry.runId === runId)
|
|
84
|
+
.map((entry) => ({ at: entry.at, item: entry.item })),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
rows.sort((left, right) => {
|
|
88
|
+
const cmp = left.at.localeCompare(right.at);
|
|
89
|
+
if (cmp !== 0)
|
|
90
|
+
return cmp;
|
|
91
|
+
const kindCmp = rowKindOrder(left.kind) - rowKindOrder(right.kind);
|
|
92
|
+
if (kindCmp !== 0)
|
|
93
|
+
return kindCmp;
|
|
94
|
+
return left.id.localeCompare(right.id);
|
|
50
95
|
});
|
|
96
|
+
return rows;
|
|
51
97
|
}
|
|
52
98
|
function buildCompactTimelineRows(entries) {
|
|
53
99
|
const rows = [];
|
|
@@ -130,7 +176,8 @@ function buildCompactTimelineRows(entries) {
|
|
|
130
176
|
at: run.at,
|
|
131
177
|
finalized: status !== "running",
|
|
132
178
|
run: { ...run.run, status, ...(run.endedAt ? { endedAt: run.endedAt } : {}) },
|
|
133
|
-
details: summarizeRunDetails(run.items
|
|
179
|
+
details: summarizeRunDetails(run.items),
|
|
180
|
+
items: [],
|
|
134
181
|
});
|
|
135
182
|
}
|
|
136
183
|
rows.sort((left, right) => {
|
|
@@ -162,7 +209,7 @@ function resolveCompactRunStatus(run, items) {
|
|
|
162
209
|
}
|
|
163
210
|
return run.status === "queued" ? "queued" : "running";
|
|
164
211
|
}
|
|
165
|
-
function summarizeRunDetails(items
|
|
212
|
+
function summarizeRunDetails(items) {
|
|
166
213
|
const details = [];
|
|
167
214
|
const latestAgentMessage = findLatest(items, (item) => item.type === "agentMessage" && Boolean(item.text?.trim()));
|
|
168
215
|
const latestUserMessage = findLatest(items, (item) => item.type === "userMessage" && Boolean(item.text?.trim()));
|
|
@@ -172,13 +219,13 @@ function summarizeRunDetails(items, status) {
|
|
|
172
219
|
if (latestUserMessage && !latestAgentMessage) {
|
|
173
220
|
details.push({
|
|
174
221
|
tone: "user",
|
|
175
|
-
text: `you: ${summarizeNarrative(latestUserMessage.text ?? ""
|
|
222
|
+
text: `you: ${summarizeNarrative(latestUserMessage.text ?? "")}`,
|
|
176
223
|
});
|
|
177
224
|
}
|
|
178
225
|
if (latestAgentMessage) {
|
|
179
226
|
details.push({
|
|
180
227
|
tone: "message",
|
|
181
|
-
text: summarizeNarrative(latestAgentMessage.text ?? ""
|
|
228
|
+
text: summarizeNarrative(latestAgentMessage.text ?? ""),
|
|
182
229
|
});
|
|
183
230
|
}
|
|
184
231
|
if (latestCommand?.command) {
|
|
@@ -204,7 +251,7 @@ function summarizeRunDetails(items, status) {
|
|
|
204
251
|
}
|
|
205
252
|
return dedupeDetails(details).slice(0, 3);
|
|
206
253
|
}
|
|
207
|
-
function summarizeNarrative(input
|
|
254
|
+
function summarizeNarrative(input) {
|
|
208
255
|
const normalized = input
|
|
209
256
|
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
|
|
210
257
|
.replace(/`([^`]+)`/g, "$1")
|
|
@@ -212,8 +259,7 @@ function summarizeNarrative(input, max) {
|
|
|
212
259
|
.trim();
|
|
213
260
|
if (!normalized)
|
|
214
261
|
return "";
|
|
215
|
-
|
|
216
|
-
return truncate(sentence, max);
|
|
262
|
+
return normalized.match(/^(.+?[.!?])(?:\s|$)/)?.[1] ?? normalized;
|
|
217
263
|
}
|
|
218
264
|
function summarizeFileChanges(changes) {
|
|
219
265
|
const files = Array.from(new Set(changes
|
|
@@ -275,15 +321,12 @@ function rowKindOrder(kind) {
|
|
|
275
321
|
return 3;
|
|
276
322
|
}
|
|
277
323
|
}
|
|
278
|
-
function truncate(text, max) {
|
|
279
|
-
return text.length > max ? `${text.slice(0, Math.max(0, max - 3))}...` : text;
|
|
280
|
-
}
|
|
281
324
|
function cleanCommand(raw) {
|
|
282
325
|
const bashMatch = raw.match(/^\/bin\/(?:ba)?sh\s+-\w*c\s+['"](.+?)['"]$/s);
|
|
283
326
|
if (bashMatch?.[1])
|
|
284
|
-
return
|
|
327
|
+
return bashMatch[1];
|
|
285
328
|
const bashMatch2 = raw.match(/^\/bin\/(?:ba)?sh\s+-\w*c\s+"(.+?)"$/s);
|
|
286
329
|
if (bashMatch2?.[1])
|
|
287
|
-
return
|
|
288
|
-
return
|
|
330
|
+
return bashMatch2[1];
|
|
331
|
+
return raw;
|
|
289
332
|
}
|