@kud/gh-cockpit 0.4.2 → 0.4.4
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,12 +1,13 @@
|
|
|
1
1
|
import { useWindowSize, Box, Text, useInput } from 'ink';
|
|
2
2
|
import { Panel, colors, FooterHints, useListCursor } from '@kud/ink-ui';
|
|
3
3
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
-
import {
|
|
4
|
+
import { inboxConfig, clipboard, buildCheckoutCmd, runHere, openInTab, runInPane, runInPaneHorizontal } from '@kud/gh-ink';
|
|
5
5
|
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, PIN_MARK, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, counts, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, labelPriority, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, railCapacity, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache } from '@kud/gh-ink';
|
|
6
|
+
export { toGHItem } from '@kud/gh-workflow';
|
|
6
7
|
import { mkdirSync } from 'fs';
|
|
7
8
|
import { homedir } from 'os';
|
|
8
9
|
import { join } from 'path';
|
|
9
|
-
import { computeHealth as computeHealth$1
|
|
10
|
+
import { computeHealth as computeHealth$1 } from '@kud/gh';
|
|
10
11
|
export { buildInboxQueries, buildInboxQuery, mergeInboxData } from '@kud/gh';
|
|
11
12
|
import { $ } from 'zx';
|
|
12
13
|
import { useRef, useEffect, useState } from 'react';
|
|
@@ -60,107 +61,6 @@ var computeHealth = (node) => computeHealth$1({
|
|
|
60
61
|
(t) => t && !t.isResolved
|
|
61
62
|
).length
|
|
62
63
|
});
|
|
63
|
-
var viewerReacted = (n, content) => (n?.reactionGroups ?? []).some(
|
|
64
|
-
(g) => g?.content === content && g?.viewerHasReacted
|
|
65
|
-
);
|
|
66
|
-
var conversationOf = (node) => {
|
|
67
|
-
const events = [];
|
|
68
|
-
let count = node.comments?.totalCount ?? 0;
|
|
69
|
-
const isBot = (author) => author?.__typename === "Bot";
|
|
70
|
-
for (const c of node.comments?.nodes ?? [])
|
|
71
|
-
events.push({
|
|
72
|
-
at: c.createdAt,
|
|
73
|
-
login: c.author?.login,
|
|
74
|
-
bot: isBot(c.author),
|
|
75
|
-
acked: viewerReacted(c, "EYES")
|
|
76
|
-
});
|
|
77
|
-
for (const r of node.reviews?.nodes ?? [])
|
|
78
|
-
if (r.state !== "PENDING")
|
|
79
|
-
events.push({
|
|
80
|
-
at: r.submittedAt,
|
|
81
|
-
login: r.author?.login,
|
|
82
|
-
bot: isBot(r.author)
|
|
83
|
-
});
|
|
84
|
-
for (const t of node.reviewThreads?.nodes ?? []) {
|
|
85
|
-
count += t.comments?.totalCount ?? 0;
|
|
86
|
-
for (const c of t.comments?.nodes ?? [])
|
|
87
|
-
events.push({
|
|
88
|
-
at: c.createdAt,
|
|
89
|
-
login: c.author?.login,
|
|
90
|
-
bot: isBot(c.author)
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
const last = events.filter((e) => e.at).sort((a, b) => a.at.localeCompare(b.at)).pop();
|
|
94
|
-
const pushedAt = node.commits?.nodes?.[0]?.commit?.committedDate;
|
|
95
|
-
const answeredByPush = Boolean(last?.bot && pushedAt && pushedAt > last.at);
|
|
96
|
-
if (answeredByPush || last?.acked)
|
|
97
|
-
return {
|
|
98
|
-
count,
|
|
99
|
-
lastActor: node.author?.login,
|
|
100
|
-
lastEventAt: answeredByPush ? pushedAt : last?.at
|
|
101
|
-
};
|
|
102
|
-
return { count, lastActor: last?.login, lastEventAt: last?.at };
|
|
103
|
-
};
|
|
104
|
-
var detailOf = (node, lastEventAt) => {
|
|
105
|
-
const active = latestChecks(node.statusCheckRollup?.contexts?.nodes ?? []);
|
|
106
|
-
return {
|
|
107
|
-
reviewDecision: node.reviewDecision ?? void 0,
|
|
108
|
-
mergeable: node.mergeable ?? void 0,
|
|
109
|
-
checksPass: active.filter(isPassCheck).length,
|
|
110
|
-
checksFail: active.filter(isFailCheck).length,
|
|
111
|
-
checksPending: active.filter(isPendingCheck).length,
|
|
112
|
-
threadsTotal: (node.reviewThreads?.nodes ?? []).length,
|
|
113
|
-
lastCommitAt: node.commits?.nodes?.[0]?.commit?.committedDate,
|
|
114
|
-
lastEventAt
|
|
115
|
-
};
|
|
116
|
-
};
|
|
117
|
-
var toGHItem = (node, opts = {}) => {
|
|
118
|
-
const completedAt = node.mergedAt ?? node.closedAt ?? node.createdAt;
|
|
119
|
-
const convo = conversationOf(node);
|
|
120
|
-
const activityAt = [
|
|
121
|
-
node.createdAt,
|
|
122
|
-
convo.lastEventAt,
|
|
123
|
-
node.commits?.nodes?.[0]?.commit?.committedDate
|
|
124
|
-
].filter(Boolean).sort().pop();
|
|
125
|
-
const isDone = Boolean(node.mergedAt ?? node.closedAt);
|
|
126
|
-
const sortAt = isDone ? completedAt : activityAt ?? completedAt;
|
|
127
|
-
return {
|
|
128
|
-
// Prefer GraphQL's own discriminator; fall back to field-presence only when
|
|
129
|
-
// a fragment omitted __typename. Field-presence alone mislabels PRs as issues
|
|
130
|
-
// whenever a fragment (reviewRequests, assigned, reviewed…) skips isDraft /
|
|
131
|
-
// headRefName — which sent PR drills to the issues endpoint.
|
|
132
|
-
kind: node.__typename === "PullRequest" ? "pr" : node.__typename === "Issue" ? "issue" : "isDraft" in node || "headRefName" in node ? "pr" : "issue",
|
|
133
|
-
number: node.number,
|
|
134
|
-
title: node.title ?? "",
|
|
135
|
-
repo: node.repository?.nameWithOwner ?? "",
|
|
136
|
-
url: node.url ?? "",
|
|
137
|
-
branch: node.headRefName,
|
|
138
|
-
health: computeHealth(node),
|
|
139
|
-
author: node.author?.login,
|
|
140
|
-
age: completedAt ? relativeTime(completedAt) : "",
|
|
141
|
-
activityAge: !isDone && activityAt ? relativeTime(activityAt) : void 0,
|
|
142
|
-
ts: sortAt ? new Date(sortAt).getTime() : 0,
|
|
143
|
-
unresolved: (node.reviewThreads?.nodes ?? []).filter(
|
|
144
|
-
(t) => t && !t.isResolved
|
|
145
|
-
).length,
|
|
146
|
-
conversation: convo.count,
|
|
147
|
-
lastActor: convo.lastActor,
|
|
148
|
-
// 👍 on the PR BODY, and the anchor is load-bearing rather than incidental.
|
|
149
|
-
// Scoped to a comment this would quietly evaporate on the next bot comment,
|
|
150
|
-
// which is exactly backwards for something meant to persist — anchoring it
|
|
151
|
-
// on the PR makes it PR-scoped by construction, with no bookkeeping to get
|
|
152
|
-
// wrong. It also reads distinctly on GitHub itself: an eye down in the
|
|
153
|
-
// thread, a thumb at the top.
|
|
154
|
-
//
|
|
155
|
-
// Precedence over 👀 comes for free: the pin is read by whoseMove, which
|
|
156
|
-
// answers before anything derived from lastActor is consulted. Nobody pins
|
|
157
|
-
// by accident, so the pin wins.
|
|
158
|
-
pinned: viewerReacted(node, "THUMBS_UP"),
|
|
159
|
-
labels: (node.labels?.nodes ?? []).map((l) => l?.name).filter((n) => typeof n === "string"),
|
|
160
|
-
detail: detailOf(node, convo.lastEventAt),
|
|
161
|
-
indent: opts.indent ?? false
|
|
162
|
-
};
|
|
163
|
-
};
|
|
164
64
|
var signalPath = () => {
|
|
165
65
|
const dir = join(
|
|
166
66
|
process.env.XDG_CACHE_HOME || join(homedir(), ".cache"),
|
|
@@ -305,4 +205,4 @@ var AiLauncher = ({
|
|
|
305
205
|
);
|
|
306
206
|
};
|
|
307
207
|
|
|
308
|
-
export { AiLauncher, CopyPromptNotice, DrillView, computeHealth, registerPrompts, seedPromptFor, signalPath,
|
|
208
|
+
export { AiLauncher, CopyPromptNotice, DrillView, computeHealth, registerPrompts, seedPromptFor, signalPath, withRetry };
|
package/dist/extensions/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { RepoFilter, InboxExtension, DetailContext, GHItem } from '@kud/gh-ink';
|
|
3
3
|
export * from '@kud/gh-ink';
|
|
4
4
|
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, PIN_MARK, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, checkoutDirs, clipboard, configureInbox, counts, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, labelPriority, layoutGHItems, matchesFilter, maxViewStart, moveCursor, openInTab, parsePatterns, profileOf, railCapacity, readCache, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signatureOf, sortByRecency, sortItems, toCiStatusState, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withoutItem, writeCache } from '@kud/gh-ink';
|
|
5
5
|
import { Health } from '@kud/gh';
|
|
6
6
|
export { InboxSource, buildInboxQueries, buildInboxQuery, mergeInboxData } from '@kud/gh';
|
|
7
|
+
export { CockpitItem, toGHItem } from '@kud/gh-workflow';
|
|
7
8
|
|
|
8
9
|
declare const withRetry: <T>(fn: () => Promise<T>, attempts?: number, delayMs?: number) => Promise<T>;
|
|
9
10
|
declare const computeHealth: (node: any) => Health;
|
|
10
|
-
type CockpitItem = GHItem;
|
|
11
|
-
declare const toGHItem: (node: any, opts?: {
|
|
12
|
-
indent?: boolean;
|
|
13
|
-
}) => CockpitItem;
|
|
14
11
|
declare const signalPath: () => string;
|
|
15
12
|
|
|
16
13
|
type CheckDrillContext = {
|
|
@@ -166,4 +163,4 @@ declare const IssueView: ({ item, login, onBack, }: {
|
|
|
166
163
|
onBack: () => void;
|
|
167
164
|
}) => React.JSX.Element;
|
|
168
165
|
|
|
169
|
-
export { type CheckDrill, type CheckDrillContext, type CockpitArgs, type CockpitConfig,
|
|
166
|
+
export { type CheckDrill, type CheckDrillContext, type CockpitArgs, type CockpitConfig, DrillView, IssueView, PrView, type PromptContext, type PromptForms, type TabSearch, type TabSpec, checkDrillFor, computeHealth, defineCockpit, detailFor, hasPatterns, parseArgs, registerCheckDrills, registerPrompts, signalPath, withRetry };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useActionMenu, buildActions, AiLauncher, seedPromptFor, CopyPromptNotice, DrillView, ActionMenu, resolveRepoPath, openInTab } from './chunk-
|
|
2
|
-
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, DrillView, HealthPanel, PIN_MARK, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, buildInboxQueries, buildInboxQuery, checkoutDirs, clipboard, computeHealth, configureInbox, counts, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, labelPriority, layoutGHItems, matchesFilter, maxViewStart, mergeInboxData, moveCursor, openInTab, parsePatterns, profileOf, railCapacity, readCache, registerPrompts, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signalPath, signatureOf, sortByRecency, sortItems, toCiStatusState, toGHItem, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withRetry, withoutItem, writeCache } from './chunk-
|
|
1
|
+
import { useActionMenu, buildActions, AiLauncher, seedPromptFor, CopyPromptNotice, DrillView, ActionMenu, resolveRepoPath, openInTab } from './chunk-NMOCZJDK.js';
|
|
2
|
+
export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, DrillView, HealthPanel, PIN_MARK, SIDEBAR_COLS, SidePanel, budgetNotice, buildActions, buildCheckoutCmd, buildInboxQueries, buildInboxQuery, checkoutDirs, clipboard, computeHealth, configureInbox, counts, drillCmd, explainGhAction, explainItem, filterByOrigin, filterByRepos, filterBySearch, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, inboxConfig, insertRepoHeaders, itermRun, jumpToRepo, jumpToRepoPane, labelPriority, layoutGHItems, matchesFilter, maxViewStart, mergeInboxData, moveCursor, openInTab, parsePatterns, profileOf, railCapacity, readCache, registerPrompts, relativeTime, renderMarkdown, repoPriority, reposInSections, resetInboxConfig, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, signalPath, signatureOf, sortByRecency, sortItems, toCiStatusState, toGHItem, topLevelCount, truncate, useActionMenu, whoseMove, windowCount, withHeaders, withRetry, withoutItem, writeCache } from './chunk-NMOCZJDK.js';
|
|
3
3
|
import { parsePatterns, HealthPanel, CommentsPanel, inboxConfig } from '@kud/gh-ink';
|
|
4
4
|
import { $ } from 'zx';
|
|
5
5
|
import { useState, useEffect } from 'react';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-cockpit",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "A configurable GitHub cockpit for the terminal — your PRs, reviews and issues in one Ink TUI, grouped by whose move it is.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -53,10 +53,11 @@
|
|
|
53
53
|
"react": ">=19"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@kud/gh": "0.
|
|
57
|
-
"@kud/gh-ink": "0.44.
|
|
56
|
+
"@kud/gh": "0.11.0",
|
|
57
|
+
"@kud/gh-ink": "0.44.4",
|
|
58
58
|
"@kud/ink-ui": "0.22.0",
|
|
59
|
-
"zx": "8.8.5"
|
|
59
|
+
"zx": "8.8.5",
|
|
60
|
+
"@kud/gh-workflow": "0.2.1"
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
62
63
|
"@types/node": "22.20.1",
|