patchrelay 0.45.1 → 0.46.1

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.
@@ -1,35 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text } from "ink";
3
- import { hasOpenPr } from "../../pr-state.js";
4
- import { computeAggregates } from "./watch-state.js";
5
3
  import { FreshnessBadge } from "./FreshnessBadge.js";
6
- const FILTER_LABELS = {
4
+ const FILTER_LABEL = {
7
5
  "all": "all",
8
6
  "active": "active",
9
7
  "non-done": "in progress",
10
8
  };
11
- export function StatusBar({ issues, totalCount, filter, connected, lastServerMessageAt, allIssues, frozen, compact = false, }) {
12
- const showing = filter === "all" ? `${totalCount} issues` : `${issues.length}/${totalCount} issues`;
13
- const aggregateSource = filter === "all" ? allIssues : issues;
14
- const agg = computeAggregates(aggregateSource);
15
- const withPr = aggregateSource.filter((i) => hasOpenPr(i.prNumber, i.prState)).length;
16
- const waitingInput = aggregateSource.filter((i) => i.sessionState === "waiting_input" || i.factoryState === "awaiting_input").length;
17
- const intervention = aggregateSource.filter((i) => i.sessionState === "failed" || i.factoryState === "failed" || i.factoryState === "escalated").length;
18
- const running = aggregateSource.filter((i) => i.sessionState === "running").length;
19
- const idle = aggregateSource.filter((i) => i.sessionState === "idle").length;
20
- if (compact) {
21
- const compactParts = [
22
- withPr > 0 ? `p${withPr}` : null,
23
- running > 0 ? `r${running}` : null,
24
- waitingInput > 0 ? `w${waitingInput}` : null,
25
- intervention > 0 ? `x${intervention}` : null,
26
- agg.blocked > 0 ? `b${agg.blocked}` : null,
27
- agg.ready > 0 ? `q${agg.ready}` : null,
28
- agg.failed > 0 ? `f${agg.failed}` : null,
29
- agg.done > 0 ? `d${agg.done}` : null,
30
- frozen ? "frozen" : null,
31
- ].filter(Boolean);
32
- return (_jsxs(Box, { justifyContent: "space-between", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { bold: true, children: "patchrelay" }), _jsx(Text, { dimColor: true, children: showing }), _jsxs(Text, { dimColor: true, children: ["[", FILTER_LABELS[filter][0], "]"] }), compactParts.length > 0 ? _jsx(Text, { dimColor: true, children: compactParts.join(" ") }) : null] }), _jsx(FreshnessBadge, { connected: connected, lastServerMessageAt: lastServerMessageAt })] }));
33
- }
34
- return (_jsxs(Box, { justifyContent: "space-between", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { bold: true, children: showing }), _jsxs(Text, { dimColor: true, children: ["[", FILTER_LABELS[filter], "]"] }), _jsx(Text, { dimColor: true, children: "|" }), running > 0 && _jsxs(Text, { color: "cyan", children: [running, " running"] }), idle > 0 && _jsxs(Text, { color: "blueBright", children: [idle, " idle"] }), agg.ready > 0 && _jsxs(Text, { color: "blueBright", children: [agg.ready, " ready"] }), agg.blocked > 0 && _jsxs(Text, { color: "yellow", children: [agg.blocked, " blocked"] }), withPr > 0 && _jsxs(Text, { dimColor: true, children: [withPr, " PRs"] }), waitingInput > 0 && _jsxs(Text, { color: "yellow", children: [waitingInput, " needs input"] }), intervention > 0 && _jsxs(Text, { color: "red", children: [intervention, " needs help"] }), agg.done > 0 && _jsxs(Text, { color: "green", children: [agg.done, " done"] }), agg.failed > 0 && _jsxs(Text, { color: "red", children: [agg.failed, " failed"] }), frozen && _jsx(Text, { color: "magenta", children: "frozen" })] }), _jsx(FreshnessBadge, { connected: connected, lastServerMessageAt: lastServerMessageAt })] }));
9
+ export function StatusBar({ filter, connected, lastServerMessageAt, frozen }) {
10
+ return (_jsxs(Box, { justifyContent: "space-between", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { bold: true, children: "patchrelay" }), _jsxs(Text, { dimColor: true, children: ["[", FILTER_LABEL[filter], "]"] }), frozen ? _jsx(Text, { color: "magenta", children: "frozen" }) : null] }), _jsx(FreshnessBadge, { connected: connected, lastServerMessageAt: lastServerMessageAt })] }));
35
11
  }
@@ -0,0 +1,82 @@
1
+ import { renderTextLines } from "./render-rich-text.js";
2
+ const ROLE_WIDTH = 10;
3
+ export function buildCodexLogLines(timeline, width) {
4
+ const lines = [];
5
+ const wrapWidth = Math.max(20, width - ROLE_WIDTH);
6
+ for (const entry of timeline) {
7
+ if (entry.kind !== "item" || !entry.item)
8
+ continue;
9
+ const block = renderItem(entry.id, entry.item, wrapWidth);
10
+ if (block.length === 0)
11
+ continue;
12
+ if (lines.length > 0)
13
+ lines.push(blankLine(`${entry.id}-gap`));
14
+ lines.push(...block);
15
+ }
16
+ return lines;
17
+ }
18
+ function renderItem(key, item, wrapWidth) {
19
+ switch (item.type) {
20
+ case "agentMessage":
21
+ return renderRolePrefixed("assistant", item.text ?? "", key, wrapWidth, { bold: false });
22
+ case "userMessage":
23
+ return renderRolePrefixed("user", item.text ?? "", key, wrapWidth, { bold: false });
24
+ case "reasoning":
25
+ return renderRolePrefixed("reasoning", item.text ?? "", key, wrapWidth, { dimColor: true });
26
+ case "commandExecution":
27
+ return renderCommand(key, item.command ?? "", item.output ?? "", item.exitCode, wrapWidth);
28
+ case "plan":
29
+ return renderRolePrefixed("plan", item.text ?? "", key, wrapWidth, { dimColor: true });
30
+ default:
31
+ return [];
32
+ }
33
+ }
34
+ function renderRolePrefixed(role, text, key, wrapWidth, textStyle) {
35
+ if (!text.trim())
36
+ return [];
37
+ const rolePrefix = [{ text: role.padEnd(ROLE_WIDTH, " "), dimColor: true }];
38
+ const emptyPrefix = [{ text: "".padEnd(ROLE_WIDTH, " ") }];
39
+ return renderTextLines(text, {
40
+ key,
41
+ width: wrapWidth,
42
+ firstPrefix: rolePrefix,
43
+ continuationPrefix: emptyPrefix,
44
+ style: textStyle,
45
+ });
46
+ }
47
+ function renderCommand(key, command, output, exitCode, wrapWidth) {
48
+ const lines = [];
49
+ const commandText = command.trim() ? `$ ${command.trim()}` : "$";
50
+ const rolePrefix = [{ text: "tool".padEnd(ROLE_WIDTH, " "), dimColor: true }];
51
+ const indentPrefix = [{ text: "".padEnd(ROLE_WIDTH, " ") }];
52
+ lines.push(...renderTextLines(commandText, {
53
+ key: `${key}-cmd`,
54
+ width: wrapWidth,
55
+ firstPrefix: rolePrefix,
56
+ continuationPrefix: indentPrefix,
57
+ style: { dimColor: true },
58
+ }));
59
+ const outputTrimmed = output.trim();
60
+ if (outputTrimmed) {
61
+ lines.push(...renderTextLines(outputTrimmed, {
62
+ key: `${key}-out`,
63
+ width: wrapWidth,
64
+ firstPrefix: indentPrefix,
65
+ continuationPrefix: indentPrefix,
66
+ style: { dimColor: true },
67
+ }));
68
+ }
69
+ if (exitCode !== undefined && exitCode !== 0) {
70
+ lines.push(...renderTextLines(`exit ${exitCode}`, {
71
+ key: `${key}-exit`,
72
+ width: wrapWidth,
73
+ firstPrefix: indentPrefix,
74
+ continuationPrefix: indentPrefix,
75
+ style: { color: "red" },
76
+ }));
77
+ }
78
+ return lines;
79
+ }
80
+ function blankLine(key) {
81
+ return { key, segments: [{ text: "" }] };
82
+ }