@bretwardjames/ghp-core 0.6.0 → 0.7.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/README.md +59 -0
- package/dist/index.cjs +369 -2
- package/dist/index.d.cts +72 -3
- package/dist/index.d.ts +72 -3
- package/dist/index.js +367 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,64 @@ if (result.success) {
|
|
|
64
64
|
}
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
### Error Handling
|
|
68
|
+
|
|
69
|
+
The `GitError` class provides detailed context for git operation failures:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { GitError } from '@bretwardjames/ghp-core';
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
await checkoutBranch('nonexistent-branch');
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof GitError) {
|
|
78
|
+
console.log(error.command); // 'git checkout nonexistent-branch'
|
|
79
|
+
console.log(error.stderr); // 'error: pathspec ... did not match'
|
|
80
|
+
console.log(error.exitCode); // 1
|
|
81
|
+
console.log(error.cwd); // '/path/to/repo'
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Retry Utilities
|
|
87
|
+
|
|
88
|
+
Handle transient GitHub API failures with exponential backoff:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { withRetry, isTransientError, DEFAULT_RETRY_CONFIG } from '@bretwardjames/ghp-core';
|
|
92
|
+
|
|
93
|
+
// Wrap any async function with retry logic
|
|
94
|
+
const result = await withRetry(
|
|
95
|
+
() => api.getIssue(repo, 123),
|
|
96
|
+
{
|
|
97
|
+
maxRetries: 3,
|
|
98
|
+
baseDelayMs: 1000,
|
|
99
|
+
maxDelayMs: 30000,
|
|
100
|
+
shouldRetry: isTransientError, // Retries 429, 5xx, network errors
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// Or use default config
|
|
105
|
+
const result = await withRetry(() => api.getIssue(repo, 123), DEFAULT_RETRY_CONFIG);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Shell Utilities
|
|
109
|
+
|
|
110
|
+
Safe shell command construction to prevent injection:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { shellEscape, validateNumericInput, validateUrl } from '@bretwardjames/ghp-core';
|
|
114
|
+
|
|
115
|
+
// Escape strings for shell
|
|
116
|
+
const safe = shellEscape("user's input"); // 'user'\''s input'
|
|
117
|
+
|
|
118
|
+
// Validate numeric input
|
|
119
|
+
const num = validateNumericInput("123", "issue number"); // 123 or throws
|
|
120
|
+
|
|
121
|
+
// Validate URLs
|
|
122
|
+
validateUrl("https://github.com/...", "issue URL"); // throws if invalid
|
|
123
|
+
```
|
|
124
|
+
|
|
67
125
|
### Event Hooks
|
|
68
126
|
|
|
69
127
|
Register and execute lifecycle event hooks:
|
|
@@ -92,6 +150,7 @@ const payload: IssueStartedPayload = {
|
|
|
92
150
|
// Hooks can execute in a specific directory (e.g., inside a worktree)
|
|
93
151
|
const results = await executeHooksForEvent('issue-started', payload, {
|
|
94
152
|
cwd: '/path/to/worktree',
|
|
153
|
+
onFailure: 'continue', // 'fail-fast' (default) or 'continue'
|
|
95
154
|
});
|
|
96
155
|
```
|
|
97
156
|
|
package/dist/index.cjs
CHANGED
|
@@ -78,6 +78,7 @@ __export(index_exports, {
|
|
|
78
78
|
findSessionFile: () => findSessionFile,
|
|
79
79
|
formatAction: () => formatAction,
|
|
80
80
|
formatConflict: () => formatConflict,
|
|
81
|
+
formatStandupText: () => formatStandupText,
|
|
81
82
|
gatherDashboardData: () => gatherDashboardData,
|
|
82
83
|
generateBranchName: () => generateBranchName,
|
|
83
84
|
generateWorktreePath: () => generateWorktreePath,
|
|
@@ -135,6 +136,7 @@ __export(index_exports, {
|
|
|
135
136
|
parseIssueUrl: () => parseIssueUrl,
|
|
136
137
|
parseRateLimitDelay: () => parseRateLimitDelay,
|
|
137
138
|
parseSessionLine: () => parseSessionLine,
|
|
139
|
+
parseSince: () => parseSince,
|
|
138
140
|
pullLatest: () => pullLatest,
|
|
139
141
|
queries: () => queries_exports,
|
|
140
142
|
registerAgent: () => registerAgent,
|
|
@@ -190,6 +192,7 @@ __export(queries_exports, {
|
|
|
190
192
|
ISSUE_FOR_UPDATE_QUERY: () => ISSUE_FOR_UPDATE_QUERY,
|
|
191
193
|
ISSUE_NODE_ID_QUERY: () => ISSUE_NODE_ID_QUERY,
|
|
192
194
|
ISSUE_RELATIONSHIPS_QUERY: () => ISSUE_RELATIONSHIPS_QUERY,
|
|
195
|
+
ISSUE_TIMELINE_QUERY: () => ISSUE_TIMELINE_QUERY,
|
|
193
196
|
ISSUE_TYPES_QUERY: () => ISSUE_TYPES_QUERY,
|
|
194
197
|
ISSUE_WITH_PROJECT_ITEMS_QUERY: () => ISSUE_WITH_PROJECT_ITEMS_QUERY,
|
|
195
198
|
LABEL_EXISTS_QUERY: () => LABEL_EXISTS_QUERY,
|
|
@@ -280,6 +283,7 @@ var PROJECT_ITEMS_QUERY = `
|
|
|
280
283
|
number
|
|
281
284
|
url
|
|
282
285
|
state
|
|
286
|
+
updatedAt
|
|
283
287
|
issueType { name }
|
|
284
288
|
assignees(first: 5) { nodes { login } }
|
|
285
289
|
labels(first: 10) { nodes { name color } }
|
|
@@ -294,6 +298,7 @@ var PROJECT_ITEMS_QUERY = `
|
|
|
294
298
|
number
|
|
295
299
|
url
|
|
296
300
|
state
|
|
301
|
+
updatedAt
|
|
297
302
|
merged
|
|
298
303
|
assignees(first: 5) { nodes { login } }
|
|
299
304
|
labels(first: 10) { nodes { name color } }
|
|
@@ -657,6 +662,112 @@ var ISSUE_WITH_PROJECT_ITEMS_QUERY = `
|
|
|
657
662
|
}
|
|
658
663
|
}
|
|
659
664
|
`;
|
|
665
|
+
var ISSUE_TIMELINE_QUERY = `
|
|
666
|
+
query($owner: String!, $name: String!, $number: Int!, $since: DateTime!) {
|
|
667
|
+
repository(owner: $owner, name: $name) {
|
|
668
|
+
issueOrPullRequest(number: $number) {
|
|
669
|
+
... on Issue {
|
|
670
|
+
timelineItems(first: 100, since: $since) {
|
|
671
|
+
nodes {
|
|
672
|
+
__typename
|
|
673
|
+
... on IssueComment {
|
|
674
|
+
author { login }
|
|
675
|
+
createdAt
|
|
676
|
+
body
|
|
677
|
+
}
|
|
678
|
+
... on LabeledEvent {
|
|
679
|
+
actor { login }
|
|
680
|
+
createdAt
|
|
681
|
+
label { name }
|
|
682
|
+
}
|
|
683
|
+
... on UnlabeledEvent {
|
|
684
|
+
actor { login }
|
|
685
|
+
createdAt
|
|
686
|
+
label { name }
|
|
687
|
+
}
|
|
688
|
+
... on AssignedEvent {
|
|
689
|
+
actor { login }
|
|
690
|
+
createdAt
|
|
691
|
+
assignee { ... on User { login } }
|
|
692
|
+
}
|
|
693
|
+
... on UnassignedEvent {
|
|
694
|
+
actor { login }
|
|
695
|
+
createdAt
|
|
696
|
+
assignee { ... on User { login } }
|
|
697
|
+
}
|
|
698
|
+
... on ClosedEvent {
|
|
699
|
+
actor { login }
|
|
700
|
+
createdAt
|
|
701
|
+
}
|
|
702
|
+
... on ReopenedEvent {
|
|
703
|
+
actor { login }
|
|
704
|
+
createdAt
|
|
705
|
+
}
|
|
706
|
+
... on CrossReferencedEvent {
|
|
707
|
+
actor { login }
|
|
708
|
+
createdAt
|
|
709
|
+
source {
|
|
710
|
+
__typename
|
|
711
|
+
... on PullRequest { number title url }
|
|
712
|
+
... on Issue { number title }
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
... on PullRequest {
|
|
719
|
+
timelineItems(first: 100, since: $since) {
|
|
720
|
+
nodes {
|
|
721
|
+
__typename
|
|
722
|
+
... on IssueComment {
|
|
723
|
+
author { login }
|
|
724
|
+
createdAt
|
|
725
|
+
body
|
|
726
|
+
}
|
|
727
|
+
... on LabeledEvent {
|
|
728
|
+
actor { login }
|
|
729
|
+
createdAt
|
|
730
|
+
label { name }
|
|
731
|
+
}
|
|
732
|
+
... on UnlabeledEvent {
|
|
733
|
+
actor { login }
|
|
734
|
+
createdAt
|
|
735
|
+
label { name }
|
|
736
|
+
}
|
|
737
|
+
... on AssignedEvent {
|
|
738
|
+
actor { login }
|
|
739
|
+
createdAt
|
|
740
|
+
assignee { ... on User { login } }
|
|
741
|
+
}
|
|
742
|
+
... on UnassignedEvent {
|
|
743
|
+
actor { login }
|
|
744
|
+
createdAt
|
|
745
|
+
assignee { ... on User { login } }
|
|
746
|
+
}
|
|
747
|
+
... on ClosedEvent {
|
|
748
|
+
actor { login }
|
|
749
|
+
createdAt
|
|
750
|
+
}
|
|
751
|
+
... on ReopenedEvent {
|
|
752
|
+
actor { login }
|
|
753
|
+
createdAt
|
|
754
|
+
}
|
|
755
|
+
... on CrossReferencedEvent {
|
|
756
|
+
actor { login }
|
|
757
|
+
createdAt
|
|
758
|
+
source {
|
|
759
|
+
__typename
|
|
760
|
+
... on PullRequest { number title url }
|
|
761
|
+
... on Issue { number title }
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
`;
|
|
660
771
|
var ISSUE_RELATIONSHIPS_QUERY = `
|
|
661
772
|
query($owner: String!, $name: String!, $number: Int!) {
|
|
662
773
|
repository(owner: $owner, name: $name) {
|
|
@@ -1062,7 +1173,8 @@ var GitHubAPI = class {
|
|
|
1062
1173
|
parent,
|
|
1063
1174
|
subIssues,
|
|
1064
1175
|
blockedBy,
|
|
1065
|
-
blocking
|
|
1176
|
+
blocking,
|
|
1177
|
+
updatedAt: content.updatedAt || null
|
|
1066
1178
|
};
|
|
1067
1179
|
});
|
|
1068
1180
|
}
|
|
@@ -1171,7 +1283,8 @@ var GitHubAPI = class {
|
|
|
1171
1283
|
parent: issue.parent,
|
|
1172
1284
|
subIssues: issue.subIssues.nodes,
|
|
1173
1285
|
blockedBy: issue.blockedBy.nodes,
|
|
1174
|
-
blocking: issue.blocking.nodes
|
|
1286
|
+
blocking: issue.blocking.nodes,
|
|
1287
|
+
updatedAt: null
|
|
1175
1288
|
};
|
|
1176
1289
|
} catch (error) {
|
|
1177
1290
|
return null;
|
|
@@ -1733,6 +1846,158 @@ var GitHubAPI = class {
|
|
|
1733
1846
|
return null;
|
|
1734
1847
|
}
|
|
1735
1848
|
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Get recent activity across all project items since a given time.
|
|
1851
|
+
* Uses a two-pass approach for efficiency:
|
|
1852
|
+
* Pass 1: Fetch all project items, filter by updatedAt client-side
|
|
1853
|
+
* Pass 2: Fetch timeline events only for items that changed
|
|
1854
|
+
*/
|
|
1855
|
+
async getRecentActivity(repo, since, options) {
|
|
1856
|
+
if (!this.graphqlWithAuth) throw new Error("Not authenticated");
|
|
1857
|
+
const projects = await this.getProjects(repo);
|
|
1858
|
+
if (projects.length === 0) return [];
|
|
1859
|
+
const allItems = [];
|
|
1860
|
+
for (const project of projects) {
|
|
1861
|
+
const items = await this.getProjectItems(project.id, project.title);
|
|
1862
|
+
allItems.push(...items);
|
|
1863
|
+
}
|
|
1864
|
+
const sinceMs = since.getTime();
|
|
1865
|
+
const sinceISO = since.toISOString();
|
|
1866
|
+
let recentItems = allItems.filter(
|
|
1867
|
+
(item) => item.updatedAt && new Date(item.updatedAt).getTime() >= sinceMs
|
|
1868
|
+
);
|
|
1869
|
+
if (options?.mine && this.username) {
|
|
1870
|
+
recentItems = recentItems.filter(
|
|
1871
|
+
(item) => item.assignees.includes(this.username)
|
|
1872
|
+
);
|
|
1873
|
+
}
|
|
1874
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1875
|
+
recentItems = recentItems.filter((item) => {
|
|
1876
|
+
const key = `${item.repository || ""}#${item.number}`;
|
|
1877
|
+
if (!item.number || seen.has(key)) return false;
|
|
1878
|
+
seen.add(key);
|
|
1879
|
+
return true;
|
|
1880
|
+
});
|
|
1881
|
+
const activities = [];
|
|
1882
|
+
const BATCH_SIZE = 5;
|
|
1883
|
+
for (let i = 0; i < recentItems.length; i += BATCH_SIZE) {
|
|
1884
|
+
const batch = recentItems.slice(i, i + BATCH_SIZE);
|
|
1885
|
+
const results = await Promise.allSettled(
|
|
1886
|
+
batch.map(async (item) => {
|
|
1887
|
+
if (!item.number || !item.repository) return null;
|
|
1888
|
+
const [owner, name] = item.repository.split("/");
|
|
1889
|
+
if (!owner || !name) return null;
|
|
1890
|
+
const events = await this.fetchTimelineEvents(
|
|
1891
|
+
owner,
|
|
1892
|
+
name,
|
|
1893
|
+
item.number,
|
|
1894
|
+
sinceISO
|
|
1895
|
+
);
|
|
1896
|
+
if (events.length === 0) return null;
|
|
1897
|
+
return {
|
|
1898
|
+
issue: {
|
|
1899
|
+
number: item.number,
|
|
1900
|
+
title: item.title,
|
|
1901
|
+
url: item.url || ""
|
|
1902
|
+
},
|
|
1903
|
+
status: item.status,
|
|
1904
|
+
assignees: item.assignees,
|
|
1905
|
+
changes: events
|
|
1906
|
+
};
|
|
1907
|
+
})
|
|
1908
|
+
);
|
|
1909
|
+
for (const result of results) {
|
|
1910
|
+
if (result.status === "fulfilled" && result.value) {
|
|
1911
|
+
activities.push(result.value);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
activities.sort((a, b) => {
|
|
1916
|
+
const aLatest = a.changes[a.changes.length - 1]?.timestamp || "";
|
|
1917
|
+
const bLatest = b.changes[b.changes.length - 1]?.timestamp || "";
|
|
1918
|
+
return bLatest.localeCompare(aLatest);
|
|
1919
|
+
});
|
|
1920
|
+
return activities;
|
|
1921
|
+
}
|
|
1922
|
+
/**
|
|
1923
|
+
* Fetch and normalize timeline events for a single issue/PR
|
|
1924
|
+
*/
|
|
1925
|
+
async fetchTimelineEvents(owner, name, number, since) {
|
|
1926
|
+
if (!this.graphqlWithAuth) throw new Error("Not authenticated");
|
|
1927
|
+
const response = await this.graphqlWithRetry(
|
|
1928
|
+
ISSUE_TIMELINE_QUERY,
|
|
1929
|
+
{ owner, name, number, since }
|
|
1930
|
+
);
|
|
1931
|
+
const item = response.repository.issueOrPullRequest;
|
|
1932
|
+
if (!item) return [];
|
|
1933
|
+
const events = [];
|
|
1934
|
+
for (const node of item.timelineItems.nodes) {
|
|
1935
|
+
const actor = node.actor?.login || node.author?.login || "unknown";
|
|
1936
|
+
const timestamp = node.createdAt || "";
|
|
1937
|
+
switch (node.__typename) {
|
|
1938
|
+
case "IssueComment":
|
|
1939
|
+
events.push({
|
|
1940
|
+
type: "comment",
|
|
1941
|
+
actor,
|
|
1942
|
+
timestamp,
|
|
1943
|
+
details: node.body ? node.body.substring(0, 80) + (node.body.length > 80 ? "..." : "") : void 0
|
|
1944
|
+
});
|
|
1945
|
+
break;
|
|
1946
|
+
case "LabeledEvent":
|
|
1947
|
+
events.push({
|
|
1948
|
+
type: "labeled",
|
|
1949
|
+
actor,
|
|
1950
|
+
timestamp,
|
|
1951
|
+
details: node.label?.name
|
|
1952
|
+
});
|
|
1953
|
+
break;
|
|
1954
|
+
case "UnlabeledEvent":
|
|
1955
|
+
events.push({
|
|
1956
|
+
type: "unlabeled",
|
|
1957
|
+
actor,
|
|
1958
|
+
timestamp,
|
|
1959
|
+
details: node.label?.name
|
|
1960
|
+
});
|
|
1961
|
+
break;
|
|
1962
|
+
case "AssignedEvent":
|
|
1963
|
+
events.push({
|
|
1964
|
+
type: "assigned",
|
|
1965
|
+
actor,
|
|
1966
|
+
timestamp,
|
|
1967
|
+
details: node.assignee?.login
|
|
1968
|
+
});
|
|
1969
|
+
break;
|
|
1970
|
+
case "UnassignedEvent":
|
|
1971
|
+
events.push({
|
|
1972
|
+
type: "unassigned",
|
|
1973
|
+
actor,
|
|
1974
|
+
timestamp,
|
|
1975
|
+
details: node.assignee?.login
|
|
1976
|
+
});
|
|
1977
|
+
break;
|
|
1978
|
+
case "ClosedEvent":
|
|
1979
|
+
events.push({ type: "closed", actor, timestamp });
|
|
1980
|
+
break;
|
|
1981
|
+
case "ReopenedEvent":
|
|
1982
|
+
events.push({ type: "reopened", actor, timestamp });
|
|
1983
|
+
break;
|
|
1984
|
+
case "CrossReferencedEvent": {
|
|
1985
|
+
const source = node.source;
|
|
1986
|
+
if (source) {
|
|
1987
|
+
const ref = source.__typename === "PullRequest" ? `PR #${source.number}: ${source.title}` : `#${source.number}: ${source.title}`;
|
|
1988
|
+
events.push({
|
|
1989
|
+
type: "referenced",
|
|
1990
|
+
actor,
|
|
1991
|
+
timestamp,
|
|
1992
|
+
details: ref
|
|
1993
|
+
});
|
|
1994
|
+
}
|
|
1995
|
+
break;
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
return events;
|
|
2000
|
+
}
|
|
1736
2001
|
};
|
|
1737
2002
|
|
|
1738
2003
|
// src/branch-linker.ts
|
|
@@ -3804,6 +4069,106 @@ function validateUrl(url) {
|
|
|
3804
4069
|
return url;
|
|
3805
4070
|
}
|
|
3806
4071
|
|
|
4072
|
+
// src/standup.ts
|
|
4073
|
+
function formatStandupText(activities, options) {
|
|
4074
|
+
const { since } = options;
|
|
4075
|
+
const lines = [];
|
|
4076
|
+
const sinceStr = formatRelativeDate(since);
|
|
4077
|
+
const issueCount = activities.length;
|
|
4078
|
+
lines.push(`Since ${sinceStr} \u2014 ${issueCount} issue${issueCount !== 1 ? "s" : ""} changed`);
|
|
4079
|
+
lines.push("");
|
|
4080
|
+
if (activities.length === 0) {
|
|
4081
|
+
lines.push("No activity found in this time window.");
|
|
4082
|
+
return lines.join("\n");
|
|
4083
|
+
}
|
|
4084
|
+
for (const activity of activities) {
|
|
4085
|
+
const statusTag = activity.status ? ` [${activity.status}]` : "";
|
|
4086
|
+
lines.push(`#${activity.issue.number} ${activity.issue.title}${statusTag}`);
|
|
4087
|
+
for (const event of activity.changes) {
|
|
4088
|
+
lines.push(` ${formatEventLine(event)}`);
|
|
4089
|
+
}
|
|
4090
|
+
lines.push("");
|
|
4091
|
+
}
|
|
4092
|
+
return lines.join("\n").trimEnd();
|
|
4093
|
+
}
|
|
4094
|
+
function parseSince(input) {
|
|
4095
|
+
const isoDate = new Date(input);
|
|
4096
|
+
if (!isNaN(isoDate.getTime()) && input.includes("-")) {
|
|
4097
|
+
return isoDate;
|
|
4098
|
+
}
|
|
4099
|
+
const match = input.match(/^(\d+)\s*(h|d|w)$/i);
|
|
4100
|
+
if (!match) {
|
|
4101
|
+
throw new Error(`Invalid duration format: "${input}". Use formats like "24h", "2d", "1w", or an ISO date.`);
|
|
4102
|
+
}
|
|
4103
|
+
const amount = parseInt(match[1], 10);
|
|
4104
|
+
const unit = match[2].toLowerCase();
|
|
4105
|
+
const now = /* @__PURE__ */ new Date();
|
|
4106
|
+
switch (unit) {
|
|
4107
|
+
case "h":
|
|
4108
|
+
return new Date(now.getTime() - amount * 60 * 60 * 1e3);
|
|
4109
|
+
case "d":
|
|
4110
|
+
return new Date(now.getTime() - amount * 24 * 60 * 60 * 1e3);
|
|
4111
|
+
case "w":
|
|
4112
|
+
return new Date(now.getTime() - amount * 7 * 24 * 60 * 60 * 1e3);
|
|
4113
|
+
default:
|
|
4114
|
+
throw new Error(`Unknown duration unit: "${unit}"`);
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
function formatEventLine(event) {
|
|
4118
|
+
const arrow = "\u2197";
|
|
4119
|
+
const timestamp = formatShortTimestamp(event.timestamp);
|
|
4120
|
+
const actor = event.actor;
|
|
4121
|
+
switch (event.type) {
|
|
4122
|
+
case "comment":
|
|
4123
|
+
return `${arrow} Comment by ${actor} (${timestamp})${event.details ? ": " + event.details : ""}`;
|
|
4124
|
+
case "labeled":
|
|
4125
|
+
return `${arrow} Labeled "${event.details}" by ${actor} (${timestamp})`;
|
|
4126
|
+
case "unlabeled":
|
|
4127
|
+
return `${arrow} Unlabeled "${event.details}" by ${actor} (${timestamp})`;
|
|
4128
|
+
case "assigned":
|
|
4129
|
+
return `${arrow} Assigned to ${event.details || actor} (${timestamp})`;
|
|
4130
|
+
case "unassigned":
|
|
4131
|
+
return `${arrow} Unassigned ${event.details || ""} by ${actor} (${timestamp})`;
|
|
4132
|
+
case "closed":
|
|
4133
|
+
return `${arrow} Closed by ${actor} (${timestamp})`;
|
|
4134
|
+
case "reopened":
|
|
4135
|
+
return `${arrow} Reopened by ${actor} (${timestamp})`;
|
|
4136
|
+
case "referenced":
|
|
4137
|
+
return `${arrow} ${event.details} linked by ${actor} (${timestamp})`;
|
|
4138
|
+
default:
|
|
4139
|
+
return `${arrow} ${event.type} by ${actor} (${timestamp})`;
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
function formatRelativeDate(date) {
|
|
4143
|
+
const now = /* @__PURE__ */ new Date();
|
|
4144
|
+
const diffMs = now.getTime() - date.getTime();
|
|
4145
|
+
const diffHours = Math.round(diffMs / (1e3 * 60 * 60));
|
|
4146
|
+
const dateStr = date.toLocaleDateString("en-US", {
|
|
4147
|
+
month: "short",
|
|
4148
|
+
day: "numeric",
|
|
4149
|
+
hour: "2-digit",
|
|
4150
|
+
minute: "2-digit"
|
|
4151
|
+
});
|
|
4152
|
+
if (diffHours < 24) {
|
|
4153
|
+
return `${diffHours}h ago (${dateStr})`;
|
|
4154
|
+
} else if (diffHours < 48) {
|
|
4155
|
+
return `yesterday (${dateStr})`;
|
|
4156
|
+
} else {
|
|
4157
|
+
const diffDays = Math.round(diffHours / 24);
|
|
4158
|
+
return `${diffDays} days ago (${dateStr})`;
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
function formatShortTimestamp(isoTimestamp) {
|
|
4162
|
+
if (!isoTimestamp) return "";
|
|
4163
|
+
const date = new Date(isoTimestamp);
|
|
4164
|
+
return date.toLocaleDateString("en-US", {
|
|
4165
|
+
month: "short",
|
|
4166
|
+
day: "numeric",
|
|
4167
|
+
hour: "2-digit",
|
|
4168
|
+
minute: "2-digit"
|
|
4169
|
+
});
|
|
4170
|
+
}
|
|
4171
|
+
|
|
3807
4172
|
// src/dashboard/index.ts
|
|
3808
4173
|
var import_child_process3 = require("child_process");
|
|
3809
4174
|
var import_util3 = require("util");
|
|
@@ -5261,6 +5626,7 @@ EOF
|
|
|
5261
5626
|
findSessionFile,
|
|
5262
5627
|
formatAction,
|
|
5263
5628
|
formatConflict,
|
|
5629
|
+
formatStandupText,
|
|
5264
5630
|
gatherDashboardData,
|
|
5265
5631
|
generateBranchName,
|
|
5266
5632
|
generateWorktreePath,
|
|
@@ -5318,6 +5684,7 @@ EOF
|
|
|
5318
5684
|
parseIssueUrl,
|
|
5319
5685
|
parseRateLimitDelay,
|
|
5320
5686
|
parseSessionLine,
|
|
5687
|
+
parseSince,
|
|
5321
5688
|
pullLatest,
|
|
5322
5689
|
queries,
|
|
5323
5690
|
registerAgent,
|
package/dist/index.d.cts
CHANGED
|
@@ -121,6 +121,7 @@ interface ProjectItem {
|
|
|
121
121
|
subIssues: RelatedIssue[];
|
|
122
122
|
blockedBy: BlockingIssue[];
|
|
123
123
|
blocking: BlockingIssue[];
|
|
124
|
+
updatedAt: string | null;
|
|
124
125
|
}
|
|
125
126
|
/**
|
|
126
127
|
* Status field information for a project
|
|
@@ -424,6 +425,28 @@ interface BlockingRelationships {
|
|
|
424
425
|
/** Issues that this issue is blocking (these are blocked by this issue) */
|
|
425
426
|
blocking: BlockingIssue[];
|
|
426
427
|
}
|
|
428
|
+
/**
|
|
429
|
+
* Activity summary for a single issue/PR
|
|
430
|
+
*/
|
|
431
|
+
interface IssueActivity {
|
|
432
|
+
issue: {
|
|
433
|
+
number: number;
|
|
434
|
+
title: string;
|
|
435
|
+
url: string;
|
|
436
|
+
};
|
|
437
|
+
status: string | null;
|
|
438
|
+
assignees: string[];
|
|
439
|
+
changes: ActivityEvent[];
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* A single activity event on an issue
|
|
443
|
+
*/
|
|
444
|
+
interface ActivityEvent {
|
|
445
|
+
type: 'comment' | 'assigned' | 'unassigned' | 'labeled' | 'unlabeled' | 'closed' | 'reopened' | 'referenced';
|
|
446
|
+
actor: string;
|
|
447
|
+
timestamp: string;
|
|
448
|
+
details?: string;
|
|
449
|
+
}
|
|
427
450
|
|
|
428
451
|
/**
|
|
429
452
|
* GitHub API client for Projects V2.
|
|
@@ -658,6 +681,19 @@ declare class GitHubAPI {
|
|
|
658
681
|
* Get issue relationships (parent, sub-issues, and blocking relationships)
|
|
659
682
|
*/
|
|
660
683
|
getIssueRelationships(repo: RepoInfo, issueNumber: number): Promise<IssueRelationships | null>;
|
|
684
|
+
/**
|
|
685
|
+
* Get recent activity across all project items since a given time.
|
|
686
|
+
* Uses a two-pass approach for efficiency:
|
|
687
|
+
* Pass 1: Fetch all project items, filter by updatedAt client-side
|
|
688
|
+
* Pass 2: Fetch timeline events only for items that changed
|
|
689
|
+
*/
|
|
690
|
+
getRecentActivity(repo: RepoInfo, since: Date, options?: {
|
|
691
|
+
mine?: boolean;
|
|
692
|
+
}): Promise<IssueActivity[]>;
|
|
693
|
+
/**
|
|
694
|
+
* Fetch and normalize timeline events for a single issue/PR
|
|
695
|
+
*/
|
|
696
|
+
private fetchTimelineEvents;
|
|
661
697
|
}
|
|
662
698
|
|
|
663
699
|
/**
|
|
@@ -1110,7 +1146,7 @@ declare const REPOSITORY_ID_QUERY = "\n query($owner: String!, $name: String!
|
|
|
1110
1146
|
/**
|
|
1111
1147
|
* Query to get project items with all field values (paginated)
|
|
1112
1148
|
*/
|
|
1113
|
-
declare const PROJECT_ITEMS_QUERY = "\n query($projectId: ID!, $cursor: String) {\n node(id: $projectId) {\n ... on ProjectV2 {\n items(first: 100, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n id\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldSingleSelectValue {\n name\n field { ... on ProjectV2SingleSelectField { name } }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldDateValue {\n date\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n field { ... on ProjectV2IterationField { name } }\n }\n }\n }\n content {\n __typename\n ... on Issue {\n title\n number\n url\n state\n issueType { name }\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n repository { name owner { login } }\n parent { id number title state }\n subIssues(first: 50) { nodes { id number title state } }\n blockedBy(first: 20) { nodes { id number title state } }\n blocking(first: 20) { nodes { id number title state } }\n }\n ... on PullRequest {\n title\n number\n url\n state\n merged\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n repository { name owner { login } }\n }\n ... on DraftIssue {\n title\n }\n }\n }\n }\n }\n }\n }\n";
|
|
1149
|
+
declare const PROJECT_ITEMS_QUERY = "\n query($projectId: ID!, $cursor: String) {\n node(id: $projectId) {\n ... on ProjectV2 {\n items(first: 100, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n id\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldSingleSelectValue {\n name\n field { ... on ProjectV2SingleSelectField { name } }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldDateValue {\n date\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n field { ... on ProjectV2IterationField { name } }\n }\n }\n }\n content {\n __typename\n ... on Issue {\n title\n number\n url\n state\n updatedAt\n issueType { name }\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n repository { name owner { login } }\n parent { id number title state }\n subIssues(first: 50) { nodes { id number title state } }\n blockedBy(first: 20) { nodes { id number title state } }\n blocking(first: 20) { nodes { id number title state } }\n }\n ... on PullRequest {\n title\n number\n url\n state\n updatedAt\n merged\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n repository { name owner { login } }\n }\n ... on DraftIssue {\n title\n }\n }\n }\n }\n }\n }\n }\n";
|
|
1114
1150
|
/**
|
|
1115
1151
|
* Query to get project fields (including status options)
|
|
1116
1152
|
*/
|
|
@@ -1215,6 +1251,11 @@ declare const REMOVE_BLOCKED_BY_MUTATION = "\n mutation($issueId: ID!, $block
|
|
|
1215
1251
|
* Query to get issue with its project items (direct lookup, no pagination needed)
|
|
1216
1252
|
*/
|
|
1217
1253
|
declare const ISSUE_WITH_PROJECT_ITEMS_QUERY = "\n query($owner: String!, $name: String!, $number: Int!) {\n repository(owner: $owner, name: $name) {\n issue(number: $number) {\n id\n title\n number\n url\n state\n issueType { name }\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n parent { id number title state }\n subIssues(first: 50) { nodes { id number title state } }\n blockedBy(first: 20) { nodes { id number title state } }\n blocking(first: 20) { nodes { id number title state } }\n projectItems(first: 10) {\n nodes {\n id\n project { id title number }\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldSingleSelectValue {\n name\n field { ... on ProjectV2SingleSelectField { name } }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldDateValue {\n date\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n field { ... on ProjectV2IterationField { name } }\n }\n }\n }\n }\n }\n }\n }\n }\n";
|
|
1254
|
+
/**
|
|
1255
|
+
* Query to get timeline events for an issue since a given time.
|
|
1256
|
+
* Used by the standup command to fetch specific activity details.
|
|
1257
|
+
*/
|
|
1258
|
+
declare const ISSUE_TIMELINE_QUERY = "\n query($owner: String!, $name: String!, $number: Int!, $since: DateTime!) {\n repository(owner: $owner, name: $name) {\n issueOrPullRequest(number: $number) {\n ... on Issue {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n ... on PullRequest {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n }\n }\n }\n";
|
|
1218
1259
|
/**
|
|
1219
1260
|
* Query to get issue relationships (parent and sub-issues)
|
|
1220
1261
|
*/
|
|
@@ -1233,6 +1274,7 @@ declare const queries_ISSUE_DETAILS_QUERY: typeof ISSUE_DETAILS_QUERY;
|
|
|
1233
1274
|
declare const queries_ISSUE_FOR_UPDATE_QUERY: typeof ISSUE_FOR_UPDATE_QUERY;
|
|
1234
1275
|
declare const queries_ISSUE_NODE_ID_QUERY: typeof ISSUE_NODE_ID_QUERY;
|
|
1235
1276
|
declare const queries_ISSUE_RELATIONSHIPS_QUERY: typeof ISSUE_RELATIONSHIPS_QUERY;
|
|
1277
|
+
declare const queries_ISSUE_TIMELINE_QUERY: typeof ISSUE_TIMELINE_QUERY;
|
|
1236
1278
|
declare const queries_ISSUE_TYPES_QUERY: typeof ISSUE_TYPES_QUERY;
|
|
1237
1279
|
declare const queries_ISSUE_WITH_PROJECT_ITEMS_QUERY: typeof ISSUE_WITH_PROJECT_ITEMS_QUERY;
|
|
1238
1280
|
declare const queries_LABEL_EXISTS_QUERY: typeof LABEL_EXISTS_QUERY;
|
|
@@ -1252,7 +1294,7 @@ declare const queries_UPDATE_ITEM_FIELD_MUTATION: typeof UPDATE_ITEM_FIELD_MUTAT
|
|
|
1252
1294
|
declare const queries_UPDATE_ITEM_STATUS_MUTATION: typeof UPDATE_ITEM_STATUS_MUTATION;
|
|
1253
1295
|
declare const queries_VIEWER_QUERY: typeof VIEWER_QUERY;
|
|
1254
1296
|
declare namespace queries {
|
|
1255
|
-
export { queries_ADD_BLOCKED_BY_MUTATION as ADD_BLOCKED_BY_MUTATION, queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_SUB_ISSUE_MUTATION as ADD_SUB_ISSUE_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_RELATIONSHIPS_QUERY as ISSUE_RELATIONSHIPS_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_ISSUE_WITH_PROJECT_ITEMS_QUERY as ISSUE_WITH_PROJECT_ITEMS_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_BLOCKED_BY_MUTATION as REMOVE_BLOCKED_BY_MUTATION, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REMOVE_SUB_ISSUE_MUTATION as REMOVE_SUB_ISSUE_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
|
|
1297
|
+
export { queries_ADD_BLOCKED_BY_MUTATION as ADD_BLOCKED_BY_MUTATION, queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_SUB_ISSUE_MUTATION as ADD_SUB_ISSUE_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_RELATIONSHIPS_QUERY as ISSUE_RELATIONSHIPS_QUERY, queries_ISSUE_TIMELINE_QUERY as ISSUE_TIMELINE_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_ISSUE_WITH_PROJECT_ITEMS_QUERY as ISSUE_WITH_PROJECT_ITEMS_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_BLOCKED_BY_MUTATION as REMOVE_BLOCKED_BY_MUTATION, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REMOVE_SUB_ISSUE_MUTATION as REMOVE_SUB_ISSUE_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
|
|
1256
1298
|
}
|
|
1257
1299
|
|
|
1258
1300
|
/**
|
|
@@ -2207,6 +2249,33 @@ declare function validateSafeString(value: string, fieldName?: string, pattern?:
|
|
|
2207
2249
|
*/
|
|
2208
2250
|
declare function validateUrl(url: string): string;
|
|
2209
2251
|
|
|
2252
|
+
/**
|
|
2253
|
+
* Standup formatting utilities.
|
|
2254
|
+
*
|
|
2255
|
+
* Provides shared formatting for standup activity summaries,
|
|
2256
|
+
* used by CLI, VS Code extension, and MCP tool.
|
|
2257
|
+
*/
|
|
2258
|
+
|
|
2259
|
+
/**
|
|
2260
|
+
* Options for formatting standup output
|
|
2261
|
+
*/
|
|
2262
|
+
interface FormatStandupOptions {
|
|
2263
|
+
since: Date;
|
|
2264
|
+
colorize?: boolean;
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Format a standup summary as human-readable text.
|
|
2268
|
+
*
|
|
2269
|
+
* @param activities - Activity data from GitHubAPI.getRecentActivity()
|
|
2270
|
+
* @param options - Formatting options
|
|
2271
|
+
* @returns Formatted text string
|
|
2272
|
+
*/
|
|
2273
|
+
declare function formatStandupText(activities: IssueActivity[], options: FormatStandupOptions): string;
|
|
2274
|
+
/**
|
|
2275
|
+
* Parse a duration string like "24h", "8h", "2d" or an ISO date into a Date.
|
|
2276
|
+
*/
|
|
2277
|
+
declare function parseSince(input: string): Date;
|
|
2278
|
+
|
|
2210
2279
|
/**
|
|
2211
2280
|
* Dashboard Hooks - Registration and management for external content providers
|
|
2212
2281
|
*
|
|
@@ -3241,4 +3310,4 @@ declare function shouldAbort(results: HookResult[]): boolean;
|
|
|
3241
3310
|
*/
|
|
3242
3311
|
declare function hasHooksForEvent(event: EventType): boolean;
|
|
3243
3312
|
|
|
3244
|
-
export { type AgentInstance, type AgentRegistry, type AgentSessionStatus, type AgentStatus, type AgentSummary, type ApiKeyProvider, type AssigneeInfo, type AuthError, type BaseEventPayload, type BlockingIssue, type BlockingRelationships, type BranchDashboardData, BranchLinker, CLI_TO_VSCODE_MAP, ClaudeClient, type ClaudeClientOptions, type ClaudeResult, type ClaudeTool, type Collaborator, type Commit, type ConflictChoices, type ConflictResolution, type ContentBlock, type CreateIssueOptions, type CreateIssueResult, type CreatePROptions, type CreatePRResult, type CreateWorktreeOptions, type CreateWorktreeResult, DEFAULT_RETRY_CONFIG, DEFAULT_VALUES, type DashboardHook, type DashboardOptions, type DateFieldValue, type DiffStats, type EventHook, type EventHookSettings, type EventHooksConfig, type EventPayload, type EventType, type ExpandIssueOptions, type ExpandedIssue, type FieldInfo, type FieldValue, type FieldValueConnection, type FileChange, GHP_TOOLS, type GeneratePRDescriptionOptions, GitError, GitHubAPI, type GitHubAPIOptions, type GitOptions, type HookExecutionOptions, type HookExecutionResult, type HookExitCodes, type HookItem, type HookMode, type HookOutcome, type HookResponse, type HookResult, type HooksConfig, type IssueCreatedPayload, type IssueDetails, type IssueReference, type IssueRelationships, type IssueStartedPayload, type IterationFieldValue, type LabelInfo, type Message, type NumberFieldValue, type OnFailureBehavior, type PRInfo, type PermissionPrompt, type PlanEpicOptions, type PlanEpicResult, type PrCreatedPayload, type PrCreatingPayload, type PrMergedPayload, type PrePrPayload, type Project, type ProjectConfig, type ProjectConventions, type ProjectItem, type ProjectItemContent, type ProjectItemsQueryResponse, type ProjectV2, type ProjectV2Field, type ProjectV2Item, type ProjectV2View, type ProjectWithViews, type ProjectsQueryResponse, type RegisterAgentOptions, type RelatedIssue, type RemoveWorktreeOptions, type RemoveWorktreeResult, type RepoInfo, type ResolvedClaudeConfig, type ResolvedSettings, type RetryConfig, SETTING_DISPLAY_NAMES, SYNCABLE_KEYS, type SessionEvent, SessionWatcher, type SettingConflict, type SettingsDiff, type SettingsSource, type SingleSelectFieldValue, type StartIssueOptions, type StartIssueResult, type StatusField, type StreamCallbacks, type StreamErrorEvent, type StreamEvent, type StreamEventBase, type StreamMessageCompleteEvent, type StreamOptions, type StreamTextEvent, type StreamToolInputDeltaEvent, type StreamToolUseCompleteEvent, type StreamToolUseStartEvent, type SyncableSettingKey, type SyncableSettings, TOOL_NAMES, type TextFieldValue, type TokenProvider, type TokenUsage, type ToolContext, type ToolHandler, type ToolHandlers, type UpdateAgentOptions, VSCODE_TO_CLI_MAP, type IssueInfo as WorkflowIssueInfo, type WorkflowResult, type WorktreeInfo as WorkflowWorktreeInfo, type WorktreeCreatedPayload, type WorktreeInfo$1 as WorktreeInfo, type WorktreeRemovedPayload, addEventHook, addHook, branchExists, buildConventionsContext, buildIssueUrl, buildOrgProjectUrl, buildProjectUrl, buildPullRequestUrl, buildRepoUrl, calculateBackoffDelay, checkTmuxForPermission, checkoutBranch, index as claudePrompts, cleanupStaleAgents, computeSettingsDiff, createBranch, createIssueWorkflow, createPRWorkflow, createSessionWatcher, createWorktree, createWorktreeWorkflow, detectRepository, disableEventHook, disableHook, enableEventHook, enableHook, executeAllHooks, executeEventHook, executeHook, executeHooksForEvent, extractIssueNumberFromBranch, fetchOrigin, findSessionFile, formatAction, formatConflict, gatherDashboardData, generateBranchName, generateWorktreePath, getAgent, getAgentByIssue, getAgentSummaries, getAllBranches, getChangedFiles, getCommitHistory, getCommitsAhead, getCommitsBehind, getCurrentBranch$1 as getCurrentBranch, getCurrentBranch as getDashboardCurrentBranch, getDefaultBaseBranch, getDefaultBranch, getDiffStats, getDiffSummary, getEnabledEventHooks, getEnabledHooks, getEventHook, getEventHooks, getEventHooksConfigPath, getEventSettings, getFullDiff, getGitHubRepo, getHook, getHooks, getHooksByCategory, getHooksConfigPath, getHooksForEvent, getIssueReferenceText, getLocalBranches, getRegistryPath, getRemoteBranches, getRepositoryRoot, getTools, getValidEventTypes, getValidModes, getValidOnFailureBehaviors, getWorktreeForBranch, hasDifferences, hasHooksForEvent, hasUncommittedChanges, isGitRepository, isTransientError, listAgents, listWorktrees, loadEventHooksConfig, loadHooksConfig, loadProjectConventions, loadRegistry, normalizeVSCodeSettings, parseBranchLink, parseGitHubUrl, parseIssueUrl, parseRateLimitDelay, parseSessionLine, pullLatest, queries, registerAgent, removeBranchLinkFromBody, removeEventHook, removeHook, removeWorktree, removeWorktreeWorkflow, resolveConflicts, sanitizeForBranchName, saveEventHooksConfig, saveHooksConfig, saveRegistry, setBranchLinkInBody, shellEscape, shouldAbort, skip, startIssueWorkflow, substituteTemplateVariables, toVSCodeSettings, unregisterAgent, updateAgent, updateEventHook, updateHook, useCli, useCustom, useVSCode, validateNumericInput, validateSafeString, validateUrl, withRetry, worktreeExists, wrapWithRetry };
|
|
3313
|
+
export { type ActivityEvent, type AgentInstance, type AgentRegistry, type AgentSessionStatus, type AgentStatus, type AgentSummary, type ApiKeyProvider, type AssigneeInfo, type AuthError, type BaseEventPayload, type BlockingIssue, type BlockingRelationships, type BranchDashboardData, BranchLinker, CLI_TO_VSCODE_MAP, ClaudeClient, type ClaudeClientOptions, type ClaudeResult, type ClaudeTool, type Collaborator, type Commit, type ConflictChoices, type ConflictResolution, type ContentBlock, type CreateIssueOptions, type CreateIssueResult, type CreatePROptions, type CreatePRResult, type CreateWorktreeOptions, type CreateWorktreeResult, DEFAULT_RETRY_CONFIG, DEFAULT_VALUES, type DashboardHook, type DashboardOptions, type DateFieldValue, type DiffStats, type EventHook, type EventHookSettings, type EventHooksConfig, type EventPayload, type EventType, type ExpandIssueOptions, type ExpandedIssue, type FieldInfo, type FieldValue, type FieldValueConnection, type FileChange, type FormatStandupOptions, GHP_TOOLS, type GeneratePRDescriptionOptions, GitError, GitHubAPI, type GitHubAPIOptions, type GitOptions, type HookExecutionOptions, type HookExecutionResult, type HookExitCodes, type HookItem, type HookMode, type HookOutcome, type HookResponse, type HookResult, type HooksConfig, type IssueActivity, type IssueCreatedPayload, type IssueDetails, type IssueReference, type IssueRelationships, type IssueStartedPayload, type IterationFieldValue, type LabelInfo, type Message, type NumberFieldValue, type OnFailureBehavior, type PRInfo, type PermissionPrompt, type PlanEpicOptions, type PlanEpicResult, type PrCreatedPayload, type PrCreatingPayload, type PrMergedPayload, type PrePrPayload, type Project, type ProjectConfig, type ProjectConventions, type ProjectItem, type ProjectItemContent, type ProjectItemsQueryResponse, type ProjectV2, type ProjectV2Field, type ProjectV2Item, type ProjectV2View, type ProjectWithViews, type ProjectsQueryResponse, type RegisterAgentOptions, type RelatedIssue, type RemoveWorktreeOptions, type RemoveWorktreeResult, type RepoInfo, type ResolvedClaudeConfig, type ResolvedSettings, type RetryConfig, SETTING_DISPLAY_NAMES, SYNCABLE_KEYS, type SessionEvent, SessionWatcher, type SettingConflict, type SettingsDiff, type SettingsSource, type SingleSelectFieldValue, type StartIssueOptions, type StartIssueResult, type StatusField, type StreamCallbacks, type StreamErrorEvent, type StreamEvent, type StreamEventBase, type StreamMessageCompleteEvent, type StreamOptions, type StreamTextEvent, type StreamToolInputDeltaEvent, type StreamToolUseCompleteEvent, type StreamToolUseStartEvent, type SyncableSettingKey, type SyncableSettings, TOOL_NAMES, type TextFieldValue, type TokenProvider, type TokenUsage, type ToolContext, type ToolHandler, type ToolHandlers, type UpdateAgentOptions, VSCODE_TO_CLI_MAP, type IssueInfo as WorkflowIssueInfo, type WorkflowResult, type WorktreeInfo as WorkflowWorktreeInfo, type WorktreeCreatedPayload, type WorktreeInfo$1 as WorktreeInfo, type WorktreeRemovedPayload, addEventHook, addHook, branchExists, buildConventionsContext, buildIssueUrl, buildOrgProjectUrl, buildProjectUrl, buildPullRequestUrl, buildRepoUrl, calculateBackoffDelay, checkTmuxForPermission, checkoutBranch, index as claudePrompts, cleanupStaleAgents, computeSettingsDiff, createBranch, createIssueWorkflow, createPRWorkflow, createSessionWatcher, createWorktree, createWorktreeWorkflow, detectRepository, disableEventHook, disableHook, enableEventHook, enableHook, executeAllHooks, executeEventHook, executeHook, executeHooksForEvent, extractIssueNumberFromBranch, fetchOrigin, findSessionFile, formatAction, formatConflict, formatStandupText, gatherDashboardData, generateBranchName, generateWorktreePath, getAgent, getAgentByIssue, getAgentSummaries, getAllBranches, getChangedFiles, getCommitHistory, getCommitsAhead, getCommitsBehind, getCurrentBranch$1 as getCurrentBranch, getCurrentBranch as getDashboardCurrentBranch, getDefaultBaseBranch, getDefaultBranch, getDiffStats, getDiffSummary, getEnabledEventHooks, getEnabledHooks, getEventHook, getEventHooks, getEventHooksConfigPath, getEventSettings, getFullDiff, getGitHubRepo, getHook, getHooks, getHooksByCategory, getHooksConfigPath, getHooksForEvent, getIssueReferenceText, getLocalBranches, getRegistryPath, getRemoteBranches, getRepositoryRoot, getTools, getValidEventTypes, getValidModes, getValidOnFailureBehaviors, getWorktreeForBranch, hasDifferences, hasHooksForEvent, hasUncommittedChanges, isGitRepository, isTransientError, listAgents, listWorktrees, loadEventHooksConfig, loadHooksConfig, loadProjectConventions, loadRegistry, normalizeVSCodeSettings, parseBranchLink, parseGitHubUrl, parseIssueUrl, parseRateLimitDelay, parseSessionLine, parseSince, pullLatest, queries, registerAgent, removeBranchLinkFromBody, removeEventHook, removeHook, removeWorktree, removeWorktreeWorkflow, resolveConflicts, sanitizeForBranchName, saveEventHooksConfig, saveHooksConfig, saveRegistry, setBranchLinkInBody, shellEscape, shouldAbort, skip, startIssueWorkflow, substituteTemplateVariables, toVSCodeSettings, unregisterAgent, updateAgent, updateEventHook, updateHook, useCli, useCustom, useVSCode, validateNumericInput, validateSafeString, validateUrl, withRetry, worktreeExists, wrapWithRetry };
|
package/dist/index.d.ts
CHANGED
|
@@ -121,6 +121,7 @@ interface ProjectItem {
|
|
|
121
121
|
subIssues: RelatedIssue[];
|
|
122
122
|
blockedBy: BlockingIssue[];
|
|
123
123
|
blocking: BlockingIssue[];
|
|
124
|
+
updatedAt: string | null;
|
|
124
125
|
}
|
|
125
126
|
/**
|
|
126
127
|
* Status field information for a project
|
|
@@ -424,6 +425,28 @@ interface BlockingRelationships {
|
|
|
424
425
|
/** Issues that this issue is blocking (these are blocked by this issue) */
|
|
425
426
|
blocking: BlockingIssue[];
|
|
426
427
|
}
|
|
428
|
+
/**
|
|
429
|
+
* Activity summary for a single issue/PR
|
|
430
|
+
*/
|
|
431
|
+
interface IssueActivity {
|
|
432
|
+
issue: {
|
|
433
|
+
number: number;
|
|
434
|
+
title: string;
|
|
435
|
+
url: string;
|
|
436
|
+
};
|
|
437
|
+
status: string | null;
|
|
438
|
+
assignees: string[];
|
|
439
|
+
changes: ActivityEvent[];
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* A single activity event on an issue
|
|
443
|
+
*/
|
|
444
|
+
interface ActivityEvent {
|
|
445
|
+
type: 'comment' | 'assigned' | 'unassigned' | 'labeled' | 'unlabeled' | 'closed' | 'reopened' | 'referenced';
|
|
446
|
+
actor: string;
|
|
447
|
+
timestamp: string;
|
|
448
|
+
details?: string;
|
|
449
|
+
}
|
|
427
450
|
|
|
428
451
|
/**
|
|
429
452
|
* GitHub API client for Projects V2.
|
|
@@ -658,6 +681,19 @@ declare class GitHubAPI {
|
|
|
658
681
|
* Get issue relationships (parent, sub-issues, and blocking relationships)
|
|
659
682
|
*/
|
|
660
683
|
getIssueRelationships(repo: RepoInfo, issueNumber: number): Promise<IssueRelationships | null>;
|
|
684
|
+
/**
|
|
685
|
+
* Get recent activity across all project items since a given time.
|
|
686
|
+
* Uses a two-pass approach for efficiency:
|
|
687
|
+
* Pass 1: Fetch all project items, filter by updatedAt client-side
|
|
688
|
+
* Pass 2: Fetch timeline events only for items that changed
|
|
689
|
+
*/
|
|
690
|
+
getRecentActivity(repo: RepoInfo, since: Date, options?: {
|
|
691
|
+
mine?: boolean;
|
|
692
|
+
}): Promise<IssueActivity[]>;
|
|
693
|
+
/**
|
|
694
|
+
* Fetch and normalize timeline events for a single issue/PR
|
|
695
|
+
*/
|
|
696
|
+
private fetchTimelineEvents;
|
|
661
697
|
}
|
|
662
698
|
|
|
663
699
|
/**
|
|
@@ -1110,7 +1146,7 @@ declare const REPOSITORY_ID_QUERY = "\n query($owner: String!, $name: String!
|
|
|
1110
1146
|
/**
|
|
1111
1147
|
* Query to get project items with all field values (paginated)
|
|
1112
1148
|
*/
|
|
1113
|
-
declare const PROJECT_ITEMS_QUERY = "\n query($projectId: ID!, $cursor: String) {\n node(id: $projectId) {\n ... on ProjectV2 {\n items(first: 100, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n id\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldSingleSelectValue {\n name\n field { ... on ProjectV2SingleSelectField { name } }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldDateValue {\n date\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n field { ... on ProjectV2IterationField { name } }\n }\n }\n }\n content {\n __typename\n ... on Issue {\n title\n number\n url\n state\n issueType { name }\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n repository { name owner { login } }\n parent { id number title state }\n subIssues(first: 50) { nodes { id number title state } }\n blockedBy(first: 20) { nodes { id number title state } }\n blocking(first: 20) { nodes { id number title state } }\n }\n ... on PullRequest {\n title\n number\n url\n state\n merged\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n repository { name owner { login } }\n }\n ... on DraftIssue {\n title\n }\n }\n }\n }\n }\n }\n }\n";
|
|
1149
|
+
declare const PROJECT_ITEMS_QUERY = "\n query($projectId: ID!, $cursor: String) {\n node(id: $projectId) {\n ... on ProjectV2 {\n items(first: 100, after: $cursor) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n id\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldSingleSelectValue {\n name\n field { ... on ProjectV2SingleSelectField { name } }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldDateValue {\n date\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n field { ... on ProjectV2IterationField { name } }\n }\n }\n }\n content {\n __typename\n ... on Issue {\n title\n number\n url\n state\n updatedAt\n issueType { name }\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n repository { name owner { login } }\n parent { id number title state }\n subIssues(first: 50) { nodes { id number title state } }\n blockedBy(first: 20) { nodes { id number title state } }\n blocking(first: 20) { nodes { id number title state } }\n }\n ... on PullRequest {\n title\n number\n url\n state\n updatedAt\n merged\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n repository { name owner { login } }\n }\n ... on DraftIssue {\n title\n }\n }\n }\n }\n }\n }\n }\n";
|
|
1114
1150
|
/**
|
|
1115
1151
|
* Query to get project fields (including status options)
|
|
1116
1152
|
*/
|
|
@@ -1215,6 +1251,11 @@ declare const REMOVE_BLOCKED_BY_MUTATION = "\n mutation($issueId: ID!, $block
|
|
|
1215
1251
|
* Query to get issue with its project items (direct lookup, no pagination needed)
|
|
1216
1252
|
*/
|
|
1217
1253
|
declare const ISSUE_WITH_PROJECT_ITEMS_QUERY = "\n query($owner: String!, $name: String!, $number: Int!) {\n repository(owner: $owner, name: $name) {\n issue(number: $number) {\n id\n title\n number\n url\n state\n issueType { name }\n assignees(first: 5) { nodes { login } }\n labels(first: 10) { nodes { name color } }\n parent { id number title state }\n subIssues(first: 50) { nodes { id number title state } }\n blockedBy(first: 20) { nodes { id number title state } }\n blocking(first: 20) { nodes { id number title state } }\n projectItems(first: 10) {\n nodes {\n id\n project { id title number }\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldSingleSelectValue {\n name\n field { ... on ProjectV2SingleSelectField { name } }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldDateValue {\n date\n field { ... on ProjectV2Field { name } }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n field { ... on ProjectV2IterationField { name } }\n }\n }\n }\n }\n }\n }\n }\n }\n";
|
|
1254
|
+
/**
|
|
1255
|
+
* Query to get timeline events for an issue since a given time.
|
|
1256
|
+
* Used by the standup command to fetch specific activity details.
|
|
1257
|
+
*/
|
|
1258
|
+
declare const ISSUE_TIMELINE_QUERY = "\n query($owner: String!, $name: String!, $number: Int!, $since: DateTime!) {\n repository(owner: $owner, name: $name) {\n issueOrPullRequest(number: $number) {\n ... on Issue {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n ... on PullRequest {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n }\n }\n }\n";
|
|
1218
1259
|
/**
|
|
1219
1260
|
* Query to get issue relationships (parent and sub-issues)
|
|
1220
1261
|
*/
|
|
@@ -1233,6 +1274,7 @@ declare const queries_ISSUE_DETAILS_QUERY: typeof ISSUE_DETAILS_QUERY;
|
|
|
1233
1274
|
declare const queries_ISSUE_FOR_UPDATE_QUERY: typeof ISSUE_FOR_UPDATE_QUERY;
|
|
1234
1275
|
declare const queries_ISSUE_NODE_ID_QUERY: typeof ISSUE_NODE_ID_QUERY;
|
|
1235
1276
|
declare const queries_ISSUE_RELATIONSHIPS_QUERY: typeof ISSUE_RELATIONSHIPS_QUERY;
|
|
1277
|
+
declare const queries_ISSUE_TIMELINE_QUERY: typeof ISSUE_TIMELINE_QUERY;
|
|
1236
1278
|
declare const queries_ISSUE_TYPES_QUERY: typeof ISSUE_TYPES_QUERY;
|
|
1237
1279
|
declare const queries_ISSUE_WITH_PROJECT_ITEMS_QUERY: typeof ISSUE_WITH_PROJECT_ITEMS_QUERY;
|
|
1238
1280
|
declare const queries_LABEL_EXISTS_QUERY: typeof LABEL_EXISTS_QUERY;
|
|
@@ -1252,7 +1294,7 @@ declare const queries_UPDATE_ITEM_FIELD_MUTATION: typeof UPDATE_ITEM_FIELD_MUTAT
|
|
|
1252
1294
|
declare const queries_UPDATE_ITEM_STATUS_MUTATION: typeof UPDATE_ITEM_STATUS_MUTATION;
|
|
1253
1295
|
declare const queries_VIEWER_QUERY: typeof VIEWER_QUERY;
|
|
1254
1296
|
declare namespace queries {
|
|
1255
|
-
export { queries_ADD_BLOCKED_BY_MUTATION as ADD_BLOCKED_BY_MUTATION, queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_SUB_ISSUE_MUTATION as ADD_SUB_ISSUE_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_RELATIONSHIPS_QUERY as ISSUE_RELATIONSHIPS_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_ISSUE_WITH_PROJECT_ITEMS_QUERY as ISSUE_WITH_PROJECT_ITEMS_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_BLOCKED_BY_MUTATION as REMOVE_BLOCKED_BY_MUTATION, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REMOVE_SUB_ISSUE_MUTATION as REMOVE_SUB_ISSUE_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
|
|
1297
|
+
export { queries_ADD_BLOCKED_BY_MUTATION as ADD_BLOCKED_BY_MUTATION, queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_SUB_ISSUE_MUTATION as ADD_SUB_ISSUE_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_RELATIONSHIPS_QUERY as ISSUE_RELATIONSHIPS_QUERY, queries_ISSUE_TIMELINE_QUERY as ISSUE_TIMELINE_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_ISSUE_WITH_PROJECT_ITEMS_QUERY as ISSUE_WITH_PROJECT_ITEMS_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_BLOCKED_BY_MUTATION as REMOVE_BLOCKED_BY_MUTATION, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REMOVE_SUB_ISSUE_MUTATION as REMOVE_SUB_ISSUE_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
|
|
1256
1298
|
}
|
|
1257
1299
|
|
|
1258
1300
|
/**
|
|
@@ -2207,6 +2249,33 @@ declare function validateSafeString(value: string, fieldName?: string, pattern?:
|
|
|
2207
2249
|
*/
|
|
2208
2250
|
declare function validateUrl(url: string): string;
|
|
2209
2251
|
|
|
2252
|
+
/**
|
|
2253
|
+
* Standup formatting utilities.
|
|
2254
|
+
*
|
|
2255
|
+
* Provides shared formatting for standup activity summaries,
|
|
2256
|
+
* used by CLI, VS Code extension, and MCP tool.
|
|
2257
|
+
*/
|
|
2258
|
+
|
|
2259
|
+
/**
|
|
2260
|
+
* Options for formatting standup output
|
|
2261
|
+
*/
|
|
2262
|
+
interface FormatStandupOptions {
|
|
2263
|
+
since: Date;
|
|
2264
|
+
colorize?: boolean;
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Format a standup summary as human-readable text.
|
|
2268
|
+
*
|
|
2269
|
+
* @param activities - Activity data from GitHubAPI.getRecentActivity()
|
|
2270
|
+
* @param options - Formatting options
|
|
2271
|
+
* @returns Formatted text string
|
|
2272
|
+
*/
|
|
2273
|
+
declare function formatStandupText(activities: IssueActivity[], options: FormatStandupOptions): string;
|
|
2274
|
+
/**
|
|
2275
|
+
* Parse a duration string like "24h", "8h", "2d" or an ISO date into a Date.
|
|
2276
|
+
*/
|
|
2277
|
+
declare function parseSince(input: string): Date;
|
|
2278
|
+
|
|
2210
2279
|
/**
|
|
2211
2280
|
* Dashboard Hooks - Registration and management for external content providers
|
|
2212
2281
|
*
|
|
@@ -3241,4 +3310,4 @@ declare function shouldAbort(results: HookResult[]): boolean;
|
|
|
3241
3310
|
*/
|
|
3242
3311
|
declare function hasHooksForEvent(event: EventType): boolean;
|
|
3243
3312
|
|
|
3244
|
-
export { type AgentInstance, type AgentRegistry, type AgentSessionStatus, type AgentStatus, type AgentSummary, type ApiKeyProvider, type AssigneeInfo, type AuthError, type BaseEventPayload, type BlockingIssue, type BlockingRelationships, type BranchDashboardData, BranchLinker, CLI_TO_VSCODE_MAP, ClaudeClient, type ClaudeClientOptions, type ClaudeResult, type ClaudeTool, type Collaborator, type Commit, type ConflictChoices, type ConflictResolution, type ContentBlock, type CreateIssueOptions, type CreateIssueResult, type CreatePROptions, type CreatePRResult, type CreateWorktreeOptions, type CreateWorktreeResult, DEFAULT_RETRY_CONFIG, DEFAULT_VALUES, type DashboardHook, type DashboardOptions, type DateFieldValue, type DiffStats, type EventHook, type EventHookSettings, type EventHooksConfig, type EventPayload, type EventType, type ExpandIssueOptions, type ExpandedIssue, type FieldInfo, type FieldValue, type FieldValueConnection, type FileChange, GHP_TOOLS, type GeneratePRDescriptionOptions, GitError, GitHubAPI, type GitHubAPIOptions, type GitOptions, type HookExecutionOptions, type HookExecutionResult, type HookExitCodes, type HookItem, type HookMode, type HookOutcome, type HookResponse, type HookResult, type HooksConfig, type IssueCreatedPayload, type IssueDetails, type IssueReference, type IssueRelationships, type IssueStartedPayload, type IterationFieldValue, type LabelInfo, type Message, type NumberFieldValue, type OnFailureBehavior, type PRInfo, type PermissionPrompt, type PlanEpicOptions, type PlanEpicResult, type PrCreatedPayload, type PrCreatingPayload, type PrMergedPayload, type PrePrPayload, type Project, type ProjectConfig, type ProjectConventions, type ProjectItem, type ProjectItemContent, type ProjectItemsQueryResponse, type ProjectV2, type ProjectV2Field, type ProjectV2Item, type ProjectV2View, type ProjectWithViews, type ProjectsQueryResponse, type RegisterAgentOptions, type RelatedIssue, type RemoveWorktreeOptions, type RemoveWorktreeResult, type RepoInfo, type ResolvedClaudeConfig, type ResolvedSettings, type RetryConfig, SETTING_DISPLAY_NAMES, SYNCABLE_KEYS, type SessionEvent, SessionWatcher, type SettingConflict, type SettingsDiff, type SettingsSource, type SingleSelectFieldValue, type StartIssueOptions, type StartIssueResult, type StatusField, type StreamCallbacks, type StreamErrorEvent, type StreamEvent, type StreamEventBase, type StreamMessageCompleteEvent, type StreamOptions, type StreamTextEvent, type StreamToolInputDeltaEvent, type StreamToolUseCompleteEvent, type StreamToolUseStartEvent, type SyncableSettingKey, type SyncableSettings, TOOL_NAMES, type TextFieldValue, type TokenProvider, type TokenUsage, type ToolContext, type ToolHandler, type ToolHandlers, type UpdateAgentOptions, VSCODE_TO_CLI_MAP, type IssueInfo as WorkflowIssueInfo, type WorkflowResult, type WorktreeInfo as WorkflowWorktreeInfo, type WorktreeCreatedPayload, type WorktreeInfo$1 as WorktreeInfo, type WorktreeRemovedPayload, addEventHook, addHook, branchExists, buildConventionsContext, buildIssueUrl, buildOrgProjectUrl, buildProjectUrl, buildPullRequestUrl, buildRepoUrl, calculateBackoffDelay, checkTmuxForPermission, checkoutBranch, index as claudePrompts, cleanupStaleAgents, computeSettingsDiff, createBranch, createIssueWorkflow, createPRWorkflow, createSessionWatcher, createWorktree, createWorktreeWorkflow, detectRepository, disableEventHook, disableHook, enableEventHook, enableHook, executeAllHooks, executeEventHook, executeHook, executeHooksForEvent, extractIssueNumberFromBranch, fetchOrigin, findSessionFile, formatAction, formatConflict, gatherDashboardData, generateBranchName, generateWorktreePath, getAgent, getAgentByIssue, getAgentSummaries, getAllBranches, getChangedFiles, getCommitHistory, getCommitsAhead, getCommitsBehind, getCurrentBranch$1 as getCurrentBranch, getCurrentBranch as getDashboardCurrentBranch, getDefaultBaseBranch, getDefaultBranch, getDiffStats, getDiffSummary, getEnabledEventHooks, getEnabledHooks, getEventHook, getEventHooks, getEventHooksConfigPath, getEventSettings, getFullDiff, getGitHubRepo, getHook, getHooks, getHooksByCategory, getHooksConfigPath, getHooksForEvent, getIssueReferenceText, getLocalBranches, getRegistryPath, getRemoteBranches, getRepositoryRoot, getTools, getValidEventTypes, getValidModes, getValidOnFailureBehaviors, getWorktreeForBranch, hasDifferences, hasHooksForEvent, hasUncommittedChanges, isGitRepository, isTransientError, listAgents, listWorktrees, loadEventHooksConfig, loadHooksConfig, loadProjectConventions, loadRegistry, normalizeVSCodeSettings, parseBranchLink, parseGitHubUrl, parseIssueUrl, parseRateLimitDelay, parseSessionLine, pullLatest, queries, registerAgent, removeBranchLinkFromBody, removeEventHook, removeHook, removeWorktree, removeWorktreeWorkflow, resolveConflicts, sanitizeForBranchName, saveEventHooksConfig, saveHooksConfig, saveRegistry, setBranchLinkInBody, shellEscape, shouldAbort, skip, startIssueWorkflow, substituteTemplateVariables, toVSCodeSettings, unregisterAgent, updateAgent, updateEventHook, updateHook, useCli, useCustom, useVSCode, validateNumericInput, validateSafeString, validateUrl, withRetry, worktreeExists, wrapWithRetry };
|
|
3313
|
+
export { type ActivityEvent, type AgentInstance, type AgentRegistry, type AgentSessionStatus, type AgentStatus, type AgentSummary, type ApiKeyProvider, type AssigneeInfo, type AuthError, type BaseEventPayload, type BlockingIssue, type BlockingRelationships, type BranchDashboardData, BranchLinker, CLI_TO_VSCODE_MAP, ClaudeClient, type ClaudeClientOptions, type ClaudeResult, type ClaudeTool, type Collaborator, type Commit, type ConflictChoices, type ConflictResolution, type ContentBlock, type CreateIssueOptions, type CreateIssueResult, type CreatePROptions, type CreatePRResult, type CreateWorktreeOptions, type CreateWorktreeResult, DEFAULT_RETRY_CONFIG, DEFAULT_VALUES, type DashboardHook, type DashboardOptions, type DateFieldValue, type DiffStats, type EventHook, type EventHookSettings, type EventHooksConfig, type EventPayload, type EventType, type ExpandIssueOptions, type ExpandedIssue, type FieldInfo, type FieldValue, type FieldValueConnection, type FileChange, type FormatStandupOptions, GHP_TOOLS, type GeneratePRDescriptionOptions, GitError, GitHubAPI, type GitHubAPIOptions, type GitOptions, type HookExecutionOptions, type HookExecutionResult, type HookExitCodes, type HookItem, type HookMode, type HookOutcome, type HookResponse, type HookResult, type HooksConfig, type IssueActivity, type IssueCreatedPayload, type IssueDetails, type IssueReference, type IssueRelationships, type IssueStartedPayload, type IterationFieldValue, type LabelInfo, type Message, type NumberFieldValue, type OnFailureBehavior, type PRInfo, type PermissionPrompt, type PlanEpicOptions, type PlanEpicResult, type PrCreatedPayload, type PrCreatingPayload, type PrMergedPayload, type PrePrPayload, type Project, type ProjectConfig, type ProjectConventions, type ProjectItem, type ProjectItemContent, type ProjectItemsQueryResponse, type ProjectV2, type ProjectV2Field, type ProjectV2Item, type ProjectV2View, type ProjectWithViews, type ProjectsQueryResponse, type RegisterAgentOptions, type RelatedIssue, type RemoveWorktreeOptions, type RemoveWorktreeResult, type RepoInfo, type ResolvedClaudeConfig, type ResolvedSettings, type RetryConfig, SETTING_DISPLAY_NAMES, SYNCABLE_KEYS, type SessionEvent, SessionWatcher, type SettingConflict, type SettingsDiff, type SettingsSource, type SingleSelectFieldValue, type StartIssueOptions, type StartIssueResult, type StatusField, type StreamCallbacks, type StreamErrorEvent, type StreamEvent, type StreamEventBase, type StreamMessageCompleteEvent, type StreamOptions, type StreamTextEvent, type StreamToolInputDeltaEvent, type StreamToolUseCompleteEvent, type StreamToolUseStartEvent, type SyncableSettingKey, type SyncableSettings, TOOL_NAMES, type TextFieldValue, type TokenProvider, type TokenUsage, type ToolContext, type ToolHandler, type ToolHandlers, type UpdateAgentOptions, VSCODE_TO_CLI_MAP, type IssueInfo as WorkflowIssueInfo, type WorkflowResult, type WorktreeInfo as WorkflowWorktreeInfo, type WorktreeCreatedPayload, type WorktreeInfo$1 as WorktreeInfo, type WorktreeRemovedPayload, addEventHook, addHook, branchExists, buildConventionsContext, buildIssueUrl, buildOrgProjectUrl, buildProjectUrl, buildPullRequestUrl, buildRepoUrl, calculateBackoffDelay, checkTmuxForPermission, checkoutBranch, index as claudePrompts, cleanupStaleAgents, computeSettingsDiff, createBranch, createIssueWorkflow, createPRWorkflow, createSessionWatcher, createWorktree, createWorktreeWorkflow, detectRepository, disableEventHook, disableHook, enableEventHook, enableHook, executeAllHooks, executeEventHook, executeHook, executeHooksForEvent, extractIssueNumberFromBranch, fetchOrigin, findSessionFile, formatAction, formatConflict, formatStandupText, gatherDashboardData, generateBranchName, generateWorktreePath, getAgent, getAgentByIssue, getAgentSummaries, getAllBranches, getChangedFiles, getCommitHistory, getCommitsAhead, getCommitsBehind, getCurrentBranch$1 as getCurrentBranch, getCurrentBranch as getDashboardCurrentBranch, getDefaultBaseBranch, getDefaultBranch, getDiffStats, getDiffSummary, getEnabledEventHooks, getEnabledHooks, getEventHook, getEventHooks, getEventHooksConfigPath, getEventSettings, getFullDiff, getGitHubRepo, getHook, getHooks, getHooksByCategory, getHooksConfigPath, getHooksForEvent, getIssueReferenceText, getLocalBranches, getRegistryPath, getRemoteBranches, getRepositoryRoot, getTools, getValidEventTypes, getValidModes, getValidOnFailureBehaviors, getWorktreeForBranch, hasDifferences, hasHooksForEvent, hasUncommittedChanges, isGitRepository, isTransientError, listAgents, listWorktrees, loadEventHooksConfig, loadHooksConfig, loadProjectConventions, loadRegistry, normalizeVSCodeSettings, parseBranchLink, parseGitHubUrl, parseIssueUrl, parseRateLimitDelay, parseSessionLine, parseSince, pullLatest, queries, registerAgent, removeBranchLinkFromBody, removeEventHook, removeHook, removeWorktree, removeWorktreeWorkflow, resolveConflicts, sanitizeForBranchName, saveEventHooksConfig, saveHooksConfig, saveRegistry, setBranchLinkInBody, shellEscape, shouldAbort, skip, startIssueWorkflow, substituteTemplateVariables, toVSCodeSettings, unregisterAgent, updateAgent, updateEventHook, updateHook, useCli, useCustom, useVSCode, validateNumericInput, validateSafeString, validateUrl, withRetry, worktreeExists, wrapWithRetry };
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ __export(queries_exports, {
|
|
|
23
23
|
ISSUE_FOR_UPDATE_QUERY: () => ISSUE_FOR_UPDATE_QUERY,
|
|
24
24
|
ISSUE_NODE_ID_QUERY: () => ISSUE_NODE_ID_QUERY,
|
|
25
25
|
ISSUE_RELATIONSHIPS_QUERY: () => ISSUE_RELATIONSHIPS_QUERY,
|
|
26
|
+
ISSUE_TIMELINE_QUERY: () => ISSUE_TIMELINE_QUERY,
|
|
26
27
|
ISSUE_TYPES_QUERY: () => ISSUE_TYPES_QUERY,
|
|
27
28
|
ISSUE_WITH_PROJECT_ITEMS_QUERY: () => ISSUE_WITH_PROJECT_ITEMS_QUERY,
|
|
28
29
|
LABEL_EXISTS_QUERY: () => LABEL_EXISTS_QUERY,
|
|
@@ -113,6 +114,7 @@ var PROJECT_ITEMS_QUERY = `
|
|
|
113
114
|
number
|
|
114
115
|
url
|
|
115
116
|
state
|
|
117
|
+
updatedAt
|
|
116
118
|
issueType { name }
|
|
117
119
|
assignees(first: 5) { nodes { login } }
|
|
118
120
|
labels(first: 10) { nodes { name color } }
|
|
@@ -127,6 +129,7 @@ var PROJECT_ITEMS_QUERY = `
|
|
|
127
129
|
number
|
|
128
130
|
url
|
|
129
131
|
state
|
|
132
|
+
updatedAt
|
|
130
133
|
merged
|
|
131
134
|
assignees(first: 5) { nodes { login } }
|
|
132
135
|
labels(first: 10) { nodes { name color } }
|
|
@@ -490,6 +493,112 @@ var ISSUE_WITH_PROJECT_ITEMS_QUERY = `
|
|
|
490
493
|
}
|
|
491
494
|
}
|
|
492
495
|
`;
|
|
496
|
+
var ISSUE_TIMELINE_QUERY = `
|
|
497
|
+
query($owner: String!, $name: String!, $number: Int!, $since: DateTime!) {
|
|
498
|
+
repository(owner: $owner, name: $name) {
|
|
499
|
+
issueOrPullRequest(number: $number) {
|
|
500
|
+
... on Issue {
|
|
501
|
+
timelineItems(first: 100, since: $since) {
|
|
502
|
+
nodes {
|
|
503
|
+
__typename
|
|
504
|
+
... on IssueComment {
|
|
505
|
+
author { login }
|
|
506
|
+
createdAt
|
|
507
|
+
body
|
|
508
|
+
}
|
|
509
|
+
... on LabeledEvent {
|
|
510
|
+
actor { login }
|
|
511
|
+
createdAt
|
|
512
|
+
label { name }
|
|
513
|
+
}
|
|
514
|
+
... on UnlabeledEvent {
|
|
515
|
+
actor { login }
|
|
516
|
+
createdAt
|
|
517
|
+
label { name }
|
|
518
|
+
}
|
|
519
|
+
... on AssignedEvent {
|
|
520
|
+
actor { login }
|
|
521
|
+
createdAt
|
|
522
|
+
assignee { ... on User { login } }
|
|
523
|
+
}
|
|
524
|
+
... on UnassignedEvent {
|
|
525
|
+
actor { login }
|
|
526
|
+
createdAt
|
|
527
|
+
assignee { ... on User { login } }
|
|
528
|
+
}
|
|
529
|
+
... on ClosedEvent {
|
|
530
|
+
actor { login }
|
|
531
|
+
createdAt
|
|
532
|
+
}
|
|
533
|
+
... on ReopenedEvent {
|
|
534
|
+
actor { login }
|
|
535
|
+
createdAt
|
|
536
|
+
}
|
|
537
|
+
... on CrossReferencedEvent {
|
|
538
|
+
actor { login }
|
|
539
|
+
createdAt
|
|
540
|
+
source {
|
|
541
|
+
__typename
|
|
542
|
+
... on PullRequest { number title url }
|
|
543
|
+
... on Issue { number title }
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
... on PullRequest {
|
|
550
|
+
timelineItems(first: 100, since: $since) {
|
|
551
|
+
nodes {
|
|
552
|
+
__typename
|
|
553
|
+
... on IssueComment {
|
|
554
|
+
author { login }
|
|
555
|
+
createdAt
|
|
556
|
+
body
|
|
557
|
+
}
|
|
558
|
+
... on LabeledEvent {
|
|
559
|
+
actor { login }
|
|
560
|
+
createdAt
|
|
561
|
+
label { name }
|
|
562
|
+
}
|
|
563
|
+
... on UnlabeledEvent {
|
|
564
|
+
actor { login }
|
|
565
|
+
createdAt
|
|
566
|
+
label { name }
|
|
567
|
+
}
|
|
568
|
+
... on AssignedEvent {
|
|
569
|
+
actor { login }
|
|
570
|
+
createdAt
|
|
571
|
+
assignee { ... on User { login } }
|
|
572
|
+
}
|
|
573
|
+
... on UnassignedEvent {
|
|
574
|
+
actor { login }
|
|
575
|
+
createdAt
|
|
576
|
+
assignee { ... on User { login } }
|
|
577
|
+
}
|
|
578
|
+
... on ClosedEvent {
|
|
579
|
+
actor { login }
|
|
580
|
+
createdAt
|
|
581
|
+
}
|
|
582
|
+
... on ReopenedEvent {
|
|
583
|
+
actor { login }
|
|
584
|
+
createdAt
|
|
585
|
+
}
|
|
586
|
+
... on CrossReferencedEvent {
|
|
587
|
+
actor { login }
|
|
588
|
+
createdAt
|
|
589
|
+
source {
|
|
590
|
+
__typename
|
|
591
|
+
... on PullRequest { number title url }
|
|
592
|
+
... on Issue { number title }
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
`;
|
|
493
602
|
var ISSUE_RELATIONSHIPS_QUERY = `
|
|
494
603
|
query($owner: String!, $name: String!, $number: Int!) {
|
|
495
604
|
repository(owner: $owner, name: $name) {
|
|
@@ -895,7 +1004,8 @@ var GitHubAPI = class {
|
|
|
895
1004
|
parent,
|
|
896
1005
|
subIssues,
|
|
897
1006
|
blockedBy,
|
|
898
|
-
blocking
|
|
1007
|
+
blocking,
|
|
1008
|
+
updatedAt: content.updatedAt || null
|
|
899
1009
|
};
|
|
900
1010
|
});
|
|
901
1011
|
}
|
|
@@ -1004,7 +1114,8 @@ var GitHubAPI = class {
|
|
|
1004
1114
|
parent: issue.parent,
|
|
1005
1115
|
subIssues: issue.subIssues.nodes,
|
|
1006
1116
|
blockedBy: issue.blockedBy.nodes,
|
|
1007
|
-
blocking: issue.blocking.nodes
|
|
1117
|
+
blocking: issue.blocking.nodes,
|
|
1118
|
+
updatedAt: null
|
|
1008
1119
|
};
|
|
1009
1120
|
} catch (error) {
|
|
1010
1121
|
return null;
|
|
@@ -1566,6 +1677,158 @@ var GitHubAPI = class {
|
|
|
1566
1677
|
return null;
|
|
1567
1678
|
}
|
|
1568
1679
|
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Get recent activity across all project items since a given time.
|
|
1682
|
+
* Uses a two-pass approach for efficiency:
|
|
1683
|
+
* Pass 1: Fetch all project items, filter by updatedAt client-side
|
|
1684
|
+
* Pass 2: Fetch timeline events only for items that changed
|
|
1685
|
+
*/
|
|
1686
|
+
async getRecentActivity(repo, since, options) {
|
|
1687
|
+
if (!this.graphqlWithAuth) throw new Error("Not authenticated");
|
|
1688
|
+
const projects = await this.getProjects(repo);
|
|
1689
|
+
if (projects.length === 0) return [];
|
|
1690
|
+
const allItems = [];
|
|
1691
|
+
for (const project of projects) {
|
|
1692
|
+
const items = await this.getProjectItems(project.id, project.title);
|
|
1693
|
+
allItems.push(...items);
|
|
1694
|
+
}
|
|
1695
|
+
const sinceMs = since.getTime();
|
|
1696
|
+
const sinceISO = since.toISOString();
|
|
1697
|
+
let recentItems = allItems.filter(
|
|
1698
|
+
(item) => item.updatedAt && new Date(item.updatedAt).getTime() >= sinceMs
|
|
1699
|
+
);
|
|
1700
|
+
if (options?.mine && this.username) {
|
|
1701
|
+
recentItems = recentItems.filter(
|
|
1702
|
+
(item) => item.assignees.includes(this.username)
|
|
1703
|
+
);
|
|
1704
|
+
}
|
|
1705
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1706
|
+
recentItems = recentItems.filter((item) => {
|
|
1707
|
+
const key = `${item.repository || ""}#${item.number}`;
|
|
1708
|
+
if (!item.number || seen.has(key)) return false;
|
|
1709
|
+
seen.add(key);
|
|
1710
|
+
return true;
|
|
1711
|
+
});
|
|
1712
|
+
const activities = [];
|
|
1713
|
+
const BATCH_SIZE = 5;
|
|
1714
|
+
for (let i = 0; i < recentItems.length; i += BATCH_SIZE) {
|
|
1715
|
+
const batch = recentItems.slice(i, i + BATCH_SIZE);
|
|
1716
|
+
const results = await Promise.allSettled(
|
|
1717
|
+
batch.map(async (item) => {
|
|
1718
|
+
if (!item.number || !item.repository) return null;
|
|
1719
|
+
const [owner, name] = item.repository.split("/");
|
|
1720
|
+
if (!owner || !name) return null;
|
|
1721
|
+
const events = await this.fetchTimelineEvents(
|
|
1722
|
+
owner,
|
|
1723
|
+
name,
|
|
1724
|
+
item.number,
|
|
1725
|
+
sinceISO
|
|
1726
|
+
);
|
|
1727
|
+
if (events.length === 0) return null;
|
|
1728
|
+
return {
|
|
1729
|
+
issue: {
|
|
1730
|
+
number: item.number,
|
|
1731
|
+
title: item.title,
|
|
1732
|
+
url: item.url || ""
|
|
1733
|
+
},
|
|
1734
|
+
status: item.status,
|
|
1735
|
+
assignees: item.assignees,
|
|
1736
|
+
changes: events
|
|
1737
|
+
};
|
|
1738
|
+
})
|
|
1739
|
+
);
|
|
1740
|
+
for (const result of results) {
|
|
1741
|
+
if (result.status === "fulfilled" && result.value) {
|
|
1742
|
+
activities.push(result.value);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
activities.sort((a, b) => {
|
|
1747
|
+
const aLatest = a.changes[a.changes.length - 1]?.timestamp || "";
|
|
1748
|
+
const bLatest = b.changes[b.changes.length - 1]?.timestamp || "";
|
|
1749
|
+
return bLatest.localeCompare(aLatest);
|
|
1750
|
+
});
|
|
1751
|
+
return activities;
|
|
1752
|
+
}
|
|
1753
|
+
/**
|
|
1754
|
+
* Fetch and normalize timeline events for a single issue/PR
|
|
1755
|
+
*/
|
|
1756
|
+
async fetchTimelineEvents(owner, name, number, since) {
|
|
1757
|
+
if (!this.graphqlWithAuth) throw new Error("Not authenticated");
|
|
1758
|
+
const response = await this.graphqlWithRetry(
|
|
1759
|
+
ISSUE_TIMELINE_QUERY,
|
|
1760
|
+
{ owner, name, number, since }
|
|
1761
|
+
);
|
|
1762
|
+
const item = response.repository.issueOrPullRequest;
|
|
1763
|
+
if (!item) return [];
|
|
1764
|
+
const events = [];
|
|
1765
|
+
for (const node of item.timelineItems.nodes) {
|
|
1766
|
+
const actor = node.actor?.login || node.author?.login || "unknown";
|
|
1767
|
+
const timestamp = node.createdAt || "";
|
|
1768
|
+
switch (node.__typename) {
|
|
1769
|
+
case "IssueComment":
|
|
1770
|
+
events.push({
|
|
1771
|
+
type: "comment",
|
|
1772
|
+
actor,
|
|
1773
|
+
timestamp,
|
|
1774
|
+
details: node.body ? node.body.substring(0, 80) + (node.body.length > 80 ? "..." : "") : void 0
|
|
1775
|
+
});
|
|
1776
|
+
break;
|
|
1777
|
+
case "LabeledEvent":
|
|
1778
|
+
events.push({
|
|
1779
|
+
type: "labeled",
|
|
1780
|
+
actor,
|
|
1781
|
+
timestamp,
|
|
1782
|
+
details: node.label?.name
|
|
1783
|
+
});
|
|
1784
|
+
break;
|
|
1785
|
+
case "UnlabeledEvent":
|
|
1786
|
+
events.push({
|
|
1787
|
+
type: "unlabeled",
|
|
1788
|
+
actor,
|
|
1789
|
+
timestamp,
|
|
1790
|
+
details: node.label?.name
|
|
1791
|
+
});
|
|
1792
|
+
break;
|
|
1793
|
+
case "AssignedEvent":
|
|
1794
|
+
events.push({
|
|
1795
|
+
type: "assigned",
|
|
1796
|
+
actor,
|
|
1797
|
+
timestamp,
|
|
1798
|
+
details: node.assignee?.login
|
|
1799
|
+
});
|
|
1800
|
+
break;
|
|
1801
|
+
case "UnassignedEvent":
|
|
1802
|
+
events.push({
|
|
1803
|
+
type: "unassigned",
|
|
1804
|
+
actor,
|
|
1805
|
+
timestamp,
|
|
1806
|
+
details: node.assignee?.login
|
|
1807
|
+
});
|
|
1808
|
+
break;
|
|
1809
|
+
case "ClosedEvent":
|
|
1810
|
+
events.push({ type: "closed", actor, timestamp });
|
|
1811
|
+
break;
|
|
1812
|
+
case "ReopenedEvent":
|
|
1813
|
+
events.push({ type: "reopened", actor, timestamp });
|
|
1814
|
+
break;
|
|
1815
|
+
case "CrossReferencedEvent": {
|
|
1816
|
+
const source = node.source;
|
|
1817
|
+
if (source) {
|
|
1818
|
+
const ref = source.__typename === "PullRequest" ? `PR #${source.number}: ${source.title}` : `#${source.number}: ${source.title}`;
|
|
1819
|
+
events.push({
|
|
1820
|
+
type: "referenced",
|
|
1821
|
+
actor,
|
|
1822
|
+
timestamp,
|
|
1823
|
+
details: ref
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
break;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
return events;
|
|
1831
|
+
}
|
|
1569
1832
|
};
|
|
1570
1833
|
|
|
1571
1834
|
// src/branch-linker.ts
|
|
@@ -3637,6 +3900,106 @@ function validateUrl(url) {
|
|
|
3637
3900
|
return url;
|
|
3638
3901
|
}
|
|
3639
3902
|
|
|
3903
|
+
// src/standup.ts
|
|
3904
|
+
function formatStandupText(activities, options) {
|
|
3905
|
+
const { since } = options;
|
|
3906
|
+
const lines = [];
|
|
3907
|
+
const sinceStr = formatRelativeDate(since);
|
|
3908
|
+
const issueCount = activities.length;
|
|
3909
|
+
lines.push(`Since ${sinceStr} \u2014 ${issueCount} issue${issueCount !== 1 ? "s" : ""} changed`);
|
|
3910
|
+
lines.push("");
|
|
3911
|
+
if (activities.length === 0) {
|
|
3912
|
+
lines.push("No activity found in this time window.");
|
|
3913
|
+
return lines.join("\n");
|
|
3914
|
+
}
|
|
3915
|
+
for (const activity of activities) {
|
|
3916
|
+
const statusTag = activity.status ? ` [${activity.status}]` : "";
|
|
3917
|
+
lines.push(`#${activity.issue.number} ${activity.issue.title}${statusTag}`);
|
|
3918
|
+
for (const event of activity.changes) {
|
|
3919
|
+
lines.push(` ${formatEventLine(event)}`);
|
|
3920
|
+
}
|
|
3921
|
+
lines.push("");
|
|
3922
|
+
}
|
|
3923
|
+
return lines.join("\n").trimEnd();
|
|
3924
|
+
}
|
|
3925
|
+
function parseSince(input) {
|
|
3926
|
+
const isoDate = new Date(input);
|
|
3927
|
+
if (!isNaN(isoDate.getTime()) && input.includes("-")) {
|
|
3928
|
+
return isoDate;
|
|
3929
|
+
}
|
|
3930
|
+
const match = input.match(/^(\d+)\s*(h|d|w)$/i);
|
|
3931
|
+
if (!match) {
|
|
3932
|
+
throw new Error(`Invalid duration format: "${input}". Use formats like "24h", "2d", "1w", or an ISO date.`);
|
|
3933
|
+
}
|
|
3934
|
+
const amount = parseInt(match[1], 10);
|
|
3935
|
+
const unit = match[2].toLowerCase();
|
|
3936
|
+
const now = /* @__PURE__ */ new Date();
|
|
3937
|
+
switch (unit) {
|
|
3938
|
+
case "h":
|
|
3939
|
+
return new Date(now.getTime() - amount * 60 * 60 * 1e3);
|
|
3940
|
+
case "d":
|
|
3941
|
+
return new Date(now.getTime() - amount * 24 * 60 * 60 * 1e3);
|
|
3942
|
+
case "w":
|
|
3943
|
+
return new Date(now.getTime() - amount * 7 * 24 * 60 * 60 * 1e3);
|
|
3944
|
+
default:
|
|
3945
|
+
throw new Error(`Unknown duration unit: "${unit}"`);
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
function formatEventLine(event) {
|
|
3949
|
+
const arrow = "\u2197";
|
|
3950
|
+
const timestamp = formatShortTimestamp(event.timestamp);
|
|
3951
|
+
const actor = event.actor;
|
|
3952
|
+
switch (event.type) {
|
|
3953
|
+
case "comment":
|
|
3954
|
+
return `${arrow} Comment by ${actor} (${timestamp})${event.details ? ": " + event.details : ""}`;
|
|
3955
|
+
case "labeled":
|
|
3956
|
+
return `${arrow} Labeled "${event.details}" by ${actor} (${timestamp})`;
|
|
3957
|
+
case "unlabeled":
|
|
3958
|
+
return `${arrow} Unlabeled "${event.details}" by ${actor} (${timestamp})`;
|
|
3959
|
+
case "assigned":
|
|
3960
|
+
return `${arrow} Assigned to ${event.details || actor} (${timestamp})`;
|
|
3961
|
+
case "unassigned":
|
|
3962
|
+
return `${arrow} Unassigned ${event.details || ""} by ${actor} (${timestamp})`;
|
|
3963
|
+
case "closed":
|
|
3964
|
+
return `${arrow} Closed by ${actor} (${timestamp})`;
|
|
3965
|
+
case "reopened":
|
|
3966
|
+
return `${arrow} Reopened by ${actor} (${timestamp})`;
|
|
3967
|
+
case "referenced":
|
|
3968
|
+
return `${arrow} ${event.details} linked by ${actor} (${timestamp})`;
|
|
3969
|
+
default:
|
|
3970
|
+
return `${arrow} ${event.type} by ${actor} (${timestamp})`;
|
|
3971
|
+
}
|
|
3972
|
+
}
|
|
3973
|
+
function formatRelativeDate(date) {
|
|
3974
|
+
const now = /* @__PURE__ */ new Date();
|
|
3975
|
+
const diffMs = now.getTime() - date.getTime();
|
|
3976
|
+
const diffHours = Math.round(diffMs / (1e3 * 60 * 60));
|
|
3977
|
+
const dateStr = date.toLocaleDateString("en-US", {
|
|
3978
|
+
month: "short",
|
|
3979
|
+
day: "numeric",
|
|
3980
|
+
hour: "2-digit",
|
|
3981
|
+
minute: "2-digit"
|
|
3982
|
+
});
|
|
3983
|
+
if (diffHours < 24) {
|
|
3984
|
+
return `${diffHours}h ago (${dateStr})`;
|
|
3985
|
+
} else if (diffHours < 48) {
|
|
3986
|
+
return `yesterday (${dateStr})`;
|
|
3987
|
+
} else {
|
|
3988
|
+
const diffDays = Math.round(diffHours / 24);
|
|
3989
|
+
return `${diffDays} days ago (${dateStr})`;
|
|
3990
|
+
}
|
|
3991
|
+
}
|
|
3992
|
+
function formatShortTimestamp(isoTimestamp) {
|
|
3993
|
+
if (!isoTimestamp) return "";
|
|
3994
|
+
const date = new Date(isoTimestamp);
|
|
3995
|
+
return date.toLocaleDateString("en-US", {
|
|
3996
|
+
month: "short",
|
|
3997
|
+
day: "numeric",
|
|
3998
|
+
hour: "2-digit",
|
|
3999
|
+
minute: "2-digit"
|
|
4000
|
+
});
|
|
4001
|
+
}
|
|
4002
|
+
|
|
3640
4003
|
// src/dashboard/index.ts
|
|
3641
4004
|
import { exec as exec3 } from "child_process";
|
|
3642
4005
|
import { promisify as promisify3 } from "util";
|
|
@@ -5093,6 +5456,7 @@ export {
|
|
|
5093
5456
|
findSessionFile,
|
|
5094
5457
|
formatAction,
|
|
5095
5458
|
formatConflict,
|
|
5459
|
+
formatStandupText,
|
|
5096
5460
|
gatherDashboardData,
|
|
5097
5461
|
generateBranchName,
|
|
5098
5462
|
generateWorktreePath,
|
|
@@ -5150,6 +5514,7 @@ export {
|
|
|
5150
5514
|
parseIssueUrl,
|
|
5151
5515
|
parseRateLimitDelay,
|
|
5152
5516
|
parseSessionLine,
|
|
5517
|
+
parseSince,
|
|
5153
5518
|
pullLatest,
|
|
5154
5519
|
queries_exports as queries,
|
|
5155
5520
|
registerAgent,
|