patchrelay 0.35.14 → 0.35.16

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,6 +1,6 @@
1
1
  {
2
2
  "service": "patchrelay",
3
- "version": "0.35.14",
4
- "commit": "a8a92461c05e",
5
- "builtAt": "2026-04-08T08:42:31.210Z"
3
+ "version": "0.35.16",
4
+ "commit": "1915fecc2b8c",
5
+ "builtAt": "2026-04-08T09:31:00.146Z"
6
6
  }
@@ -186,10 +186,10 @@ export function App({ baseUrl, bearerToken, initialIssueKey }) {
186
186
  else if (input === "k" || key.upArrow) {
187
187
  dispatch({ type: "detail-scroll", delta: -1 });
188
188
  }
189
- else if (key.pageDown || (key.ctrl && input === "d")) {
189
+ else if (key.pageDown || (key.ctrl && input === "d") || (key.ctrl && key.downArrow)) {
190
190
  dispatch({ type: "detail-page", direction: "down" });
191
191
  }
192
- else if (key.pageUp || (key.ctrl && input === "u")) {
192
+ else if (key.pageUp || (key.ctrl && input === "u") || (key.ctrl && key.upArrow)) {
193
193
  dispatch({ type: "detail-page", direction: "up" });
194
194
  }
195
195
  else if (key.home) {
@@ -4,7 +4,7 @@ export function HelpBar({ view, follow, detailTab }) {
4
4
  let text;
5
5
  if (view === "detail") {
6
6
  const tabHint = detailTab === "history" ? "t: timeline" : "h: history";
7
- text = [tabHint, "j/k: scroll", "PgUp/PgDn: page", "[ ]: issue", "Home/End: jump", `f: live ${follow ? "on" : "off"}`, "p: prompt", "s: stop", "r: retry"]
7
+ text = [tabHint, "j/k: scroll", "Ctrl-U/Ctrl-D: page", "[ ]: issue", "Home/End: jump", `f: live ${follow ? "on" : "off"}`, "p: prompt", "s: stop", "r: retry"]
8
8
  .filter(Boolean)
9
9
  .join(" ");
10
10
  }
@@ -70,7 +70,7 @@ function buildHeaderLines(input, width) {
70
70
  const issue = input.issue;
71
71
  const session = sessionDisplay(issue);
72
72
  const stage = stageDisplay(issue);
73
- const facts = buildFacts(issue, input.issueContext);
73
+ const facts = buildFactSegments(issue, input.issueContext);
74
74
  const meta = buildMeta(input.tokenUsage, input.diffSummary, input.issueContext);
75
75
  const headerSegments = [
76
76
  { text: issue.issueKey ?? issue.projectId, bold: true },
@@ -81,7 +81,7 @@ function buildHeaderLines(input, width) {
81
81
  ];
82
82
  if (facts.length > 0) {
83
83
  headerSegments.push({ text: " ", dimColor: true });
84
- headerSegments.push({ text: facts.join(" · "), dimColor: true });
84
+ headerSegments.push(...joinFactSegments(facts));
85
85
  }
86
86
  if (input.activeRunStartedAt) {
87
87
  headerSegments.push({ text: " ", dimColor: true });
@@ -121,7 +121,6 @@ function buildHeaderLines(input, width) {
121
121
  lines.push(...renderRichTextLines(issue.statusNote, {
122
122
  key: "detail-note",
123
123
  width,
124
- style: { dimColor: true },
125
124
  }));
126
125
  }
127
126
  if (input.issueContext?.latestFailureSummary) {
@@ -395,28 +394,38 @@ function renderSideTripLines(trip, runOffset, width) {
395
394
  }));
396
395
  return lines;
397
396
  }
398
- function buildFacts(issue, issueContext) {
397
+ function buildFactSegments(issue, issueContext) {
399
398
  const facts = [];
400
399
  const rereviewNeeded = isRereviewNeeded(issue);
401
400
  if (issue.prNumber !== undefined)
402
- facts.push(`PR #${issue.prNumber}`);
401
+ facts.push([{ text: `PR #${issue.prNumber}`, color: "cyan" }]);
403
402
  if (issue.prReviewState === "approved")
404
- facts.push("approved");
403
+ facts.push([{ text: "approved", color: "green" }]);
405
404
  else if (rereviewNeeded)
406
- facts.push("re-review needed");
405
+ facts.push([{ text: "re-review needed", color: "yellow" }]);
407
406
  else if (issue.prReviewState === "changes_requested")
408
- facts.push("changes requested");
407
+ facts.push([{ text: "changes requested", color: "yellow" }]);
409
408
  if (issue.waitingReason && issue.sessionState === "waiting_input")
410
- facts.push(issue.waitingReason);
409
+ facts.push([{ text: issue.waitingReason, color: "yellow" }]);
411
410
  const checks = prChecksFact({
412
411
  ...issue,
413
412
  latestFailureCheckName: issueContext?.latestFailureCheckName ?? issue.latestFailureCheckName,
414
413
  });
415
414
  if (checks) {
416
- facts.push(checks.text);
415
+ facts.push([{ text: checks.text, color: checks.color }]);
417
416
  }
418
417
  return facts;
419
418
  }
419
+ function joinFactSegments(facts) {
420
+ const segments = [];
421
+ for (const [index, fact] of facts.entries()) {
422
+ if (index > 0) {
423
+ segments.push({ text: " · ", dimColor: true });
424
+ }
425
+ segments.push(...fact);
426
+ }
427
+ return segments;
428
+ }
420
429
  function buildMeta(tokenUsage, diffSummary, issueContext) {
421
430
  const meta = [];
422
431
  if (tokenUsage)
@@ -113,10 +113,10 @@ function parseInlineMarkdown(text, style) {
113
113
  segments.push({ text: text.slice(lastIndex, index), ...(style ?? {}) });
114
114
  }
115
115
  if (match[1] && match[2]) {
116
- segments.push({ text: match[1], color: "cyan", bold: true });
116
+ segments.push({ text: match[1], color: "cyan" });
117
117
  }
118
118
  else if (match[3]) {
119
- segments.push({ text: match[3], color: "yellow", bold: true });
119
+ segments.push({ text: match[3], color: "yellow" });
120
120
  }
121
121
  else if (match[4]) {
122
122
  segments.push({ text: match[4], ...(style ?? {}), bold: true });
@@ -127,7 +127,7 @@ function detailStateAfterLayout(state, viewportRows, contentRows) {
127
127
  detailContentRows: Math.max(0, contentRows),
128
128
  };
129
129
  const maxOffset = maxDetailScrollOffset(nextState.detailContentRows, nextState.detailViewportRows);
130
- const shouldFollow = state.follow || isDetailNearBottom(state.detailScrollOffset, state.detailContentRows, state.detailViewportRows);
130
+ const shouldFollow = state.follow;
131
131
  const nextOffset = shouldFollow ? maxOffset : Math.min(state.detailScrollOffset, maxOffset);
132
132
  return {
133
133
  detailViewportRows: nextState.detailViewportRows,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchrelay",
3
- "version": "0.35.14",
3
+ "version": "0.35.16",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {