@blogic-cz/agent-tools 1.7.5 → 1.9.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 +2 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/types.d.ts +1 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/credential-guard/index.d.ts.map +1 -1
- package/dist/db-tool/service.d.ts.map +1 -1
- package/dist/gh-tool/branch.d.ts +2 -3
- package/dist/gh-tool/branch.d.ts.map +1 -1
- package/dist/gh-tool/environment.d.ts +1 -1
- package/dist/gh-tool/environment.d.ts.map +1 -1
- package/dist/gh-tool/gist.d.ts +8 -28
- package/dist/gh-tool/gist.d.ts.map +1 -1
- package/dist/gh-tool/issue/commands.d.ts +11 -9
- package/dist/gh-tool/issue/commands.d.ts.map +1 -1
- package/dist/gh-tool/issue/core.d.ts +116 -9
- package/dist/gh-tool/issue/core.d.ts.map +1 -1
- package/dist/gh-tool/issue/triage.d.ts +6 -6
- package/dist/gh-tool/issue/triage.d.ts.map +1 -1
- package/dist/gh-tool/label.d.ts +20 -0
- package/dist/gh-tool/label.d.ts.map +1 -0
- package/dist/gh-tool/pr/commands.d.ts +53 -46
- package/dist/gh-tool/pr/commands.d.ts.map +1 -1
- package/dist/gh-tool/pr/core.d.ts +156 -86
- package/dist/gh-tool/pr/core.d.ts.map +1 -1
- package/dist/gh-tool/pr/review.d.ts +16 -16
- package/dist/gh-tool/pr/review.d.ts.map +1 -1
- package/dist/gh-tool/pr/snapshot.d.ts +9 -0
- package/dist/gh-tool/pr/snapshot.d.ts.map +1 -0
- package/dist/gh-tool/pr/stack-read.d.ts +1 -6
- package/dist/gh-tool/pr/stack-read.d.ts.map +1 -1
- package/dist/gh-tool/pr/stack.d.ts +3 -3
- package/dist/gh-tool/pr/stack.d.ts.map +1 -1
- package/dist/gh-tool/{api.d.ts → read/api.d.ts} +9 -3
- package/dist/gh-tool/read/api.d.ts.map +1 -0
- package/dist/gh-tool/read/cache.d.ts +44 -0
- package/dist/gh-tool/read/cache.d.ts.map +1 -0
- package/dist/gh-tool/read/catalog.d.ts +170 -0
- package/dist/gh-tool/read/catalog.d.ts.map +1 -0
- package/dist/gh-tool/read/classes.d.ts +98 -0
- package/dist/gh-tool/read/classes.d.ts.map +1 -0
- package/dist/gh-tool/read/commands.d.ts +3 -0
- package/dist/gh-tool/read/commands.d.ts.map +1 -0
- package/dist/gh-tool/read/commits.d.ts +10 -0
- package/dist/gh-tool/read/commits.d.ts.map +1 -0
- package/dist/gh-tool/read/gated.d.ts +14 -0
- package/dist/gh-tool/read/gated.d.ts.map +1 -0
- package/dist/gh-tool/read/index.d.ts +5 -0
- package/dist/gh-tool/read/index.d.ts.map +1 -0
- package/dist/gh-tool/read/issues.d.ts +80 -0
- package/dist/gh-tool/read/issues.d.ts.map +1 -0
- package/dist/gh-tool/read/keys.d.ts +64 -0
- package/dist/gh-tool/read/keys.d.ts.map +1 -0
- package/dist/gh-tool/read/porcelain.d.ts +68 -0
- package/dist/gh-tool/read/porcelain.d.ts.map +1 -0
- package/dist/gh-tool/read/pulls.d.ts +137 -0
- package/dist/gh-tool/read/pulls.d.ts.map +1 -0
- package/dist/gh-tool/read/reads.d.ts +220 -0
- package/dist/gh-tool/read/reads.d.ts.map +1 -0
- package/dist/gh-tool/read/rest.d.ts +49 -0
- package/dist/gh-tool/read/rest.d.ts.map +1 -0
- package/dist/gh-tool/read/review-guards.d.ts +20 -0
- package/dist/gh-tool/read/review-guards.d.ts.map +1 -0
- package/dist/gh-tool/read/review-model.d.ts +190 -0
- package/dist/gh-tool/read/review-model.d.ts.map +1 -0
- package/dist/gh-tool/read/reviews.d.ts +9 -0
- package/dist/gh-tool/read/reviews.d.ts.map +1 -0
- package/dist/gh-tool/read/stacks.d.ts +7 -0
- package/dist/gh-tool/read/stacks.d.ts.map +1 -0
- package/dist/gh-tool/read/store.d.ts +70 -0
- package/dist/gh-tool/read/store.d.ts.map +1 -0
- package/dist/gh-tool/{service.d.ts → read/transport.d.ts} +5 -3
- package/dist/gh-tool/read/transport.d.ts.map +1 -0
- package/dist/gh-tool/read/waits.d.ts +22 -0
- package/dist/gh-tool/read/waits.d.ts.map +1 -0
- package/dist/gh-tool/read/writes.d.ts +16 -0
- package/dist/gh-tool/read/writes.d.ts.map +1 -0
- package/dist/gh-tool/release.d.ts +10 -26
- package/dist/gh-tool/release.d.ts.map +1 -1
- package/dist/gh-tool/repo.d.ts +9 -4
- package/dist/gh-tool/repo.d.ts.map +1 -1
- package/dist/gh-tool/types.d.ts +1 -1
- package/dist/gh-tool/types.d.ts.map +1 -1
- package/dist/gh-tool/workflow.d.ts +43 -21
- package/dist/gh-tool/workflow.d.ts.map +1 -1
- package/dist/observability-tool/shared.d.ts.map +1 -1
- package/dist/shared/content-security.d.ts +2 -0
- package/dist/shared/content-security.d.ts.map +1 -1
- package/package.json +7 -6
- package/schemas/agent-tools.schema.json +5 -0
- package/src/api-tool/proxy-entry.ts +3 -1
- package/src/config/loader.ts +1 -0
- package/src/config/types.ts +1 -0
- package/src/credential-guard/index.ts +169 -1
- package/src/db-tool/service.ts +4 -1
- package/src/gh-tool/branch.ts +5 -8
- package/src/gh-tool/environment.ts +2 -1
- package/src/gh-tool/gist.ts +8 -35
- package/src/gh-tool/issue/commands.ts +12 -2
- package/src/gh-tool/issue/core.ts +58 -122
- package/src/gh-tool/issue/triage.ts +4 -26
- package/src/gh-tool/label.ts +57 -0
- package/src/gh-tool/main.ts +24 -4
- package/src/gh-tool/pr/commands.ts +17 -15
- package/src/gh-tool/pr/core.ts +486 -582
- package/src/gh-tool/pr/review.ts +106 -454
- package/src/gh-tool/pr/snapshot.ts +23 -0
- package/src/gh-tool/pr/stack-read.ts +1 -73
- package/src/gh-tool/pr/stack.ts +37 -36
- package/src/gh-tool/{api.ts → read/api.ts} +40 -7
- package/src/gh-tool/read/cache.ts +192 -0
- package/src/gh-tool/read/catalog.ts +310 -0
- package/src/gh-tool/read/classes.ts +31 -0
- package/src/gh-tool/read/commands.ts +25 -0
- package/src/gh-tool/read/commits.ts +28 -0
- package/src/gh-tool/read/gated.ts +56 -0
- package/src/gh-tool/read/index.ts +4 -0
- package/src/gh-tool/read/issues.ts +124 -0
- package/src/gh-tool/read/keys.ts +104 -0
- package/src/gh-tool/read/porcelain.ts +58 -0
- package/src/gh-tool/read/pulls.ts +266 -0
- package/src/gh-tool/read/reads.ts +306 -0
- package/src/gh-tool/read/rest.ts +111 -0
- package/src/gh-tool/read/review-guards.ts +61 -0
- package/src/gh-tool/read/review-model.ts +286 -0
- package/src/gh-tool/read/reviews.ts +114 -0
- package/src/gh-tool/read/stacks.ts +73 -0
- package/src/gh-tool/read/store.ts +504 -0
- package/src/gh-tool/{service.ts → read/transport.ts} +26 -6
- package/src/gh-tool/read/waits.ts +52 -0
- package/src/gh-tool/read/writes.ts +37 -0
- package/src/gh-tool/release.ts +15 -168
- package/src/gh-tool/repo.ts +26 -78
- package/src/gh-tool/types.ts +1 -1
- package/src/gh-tool/workflow.ts +123 -214
- package/src/observability-tool/shared.ts +2 -1
- package/src/shared/content-security.ts +10 -1
- package/src/shared/credential-patterns.ts +1 -1
- package/dist/gh-tool/api.d.ts.map +0 -1
- package/dist/gh-tool/pr/check-status-cache.d.ts +0 -6
- package/dist/gh-tool/pr/check-status-cache.d.ts.map +0 -1
- package/dist/gh-tool/service.d.ts.map +0 -1
- package/src/gh-tool/pr/check-status-cache.ts +0 -142
|
@@ -3,7 +3,11 @@ import { Effect } from "effect";
|
|
|
3
3
|
import type { GitHubIssueCommentUrl, IssueComment, IssueCommentId, IsoTimestamp } from "#gh/types";
|
|
4
4
|
|
|
5
5
|
import { GitHubCommandError } from "#gh/errors";
|
|
6
|
-
import { GitHubService } from "#gh/
|
|
6
|
+
import { GitHubService } from "#gh/read/transport";
|
|
7
|
+
import { reads, resolveRepo } from "#gh/read/reads";
|
|
8
|
+
import { writes } from "#gh/read/writes";
|
|
9
|
+
import { project } from "#gh/read/porcelain";
|
|
10
|
+
import { repoSlug } from "#gh/read/keys";
|
|
7
11
|
|
|
8
12
|
export type IssueInfo = {
|
|
9
13
|
number: number;
|
|
@@ -34,52 +38,6 @@ export type RawIssueComment = {
|
|
|
34
38
|
html_url: string;
|
|
35
39
|
};
|
|
36
40
|
|
|
37
|
-
const REST_PAGE_SIZE = 100;
|
|
38
|
-
|
|
39
|
-
const parseJson = <T>(
|
|
40
|
-
stdout: string,
|
|
41
|
-
command: string,
|
|
42
|
-
parseFailurePrefix: string,
|
|
43
|
-
): Effect.Effect<T, GitHubCommandError> =>
|
|
44
|
-
Effect.try({
|
|
45
|
-
try: () => JSON.parse(stdout) as T,
|
|
46
|
-
catch: (error) =>
|
|
47
|
-
new GitHubCommandError({
|
|
48
|
-
command,
|
|
49
|
-
exitCode: 0,
|
|
50
|
-
stderr: `${parseFailurePrefix}: ${error instanceof Error ? error.message : String(error)}`,
|
|
51
|
-
message: `${parseFailurePrefix}: ${error instanceof Error ? error.message : String(error)}`,
|
|
52
|
-
}),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const fetchAllRestPages = Effect.fn("issue.fetchAllRestPages")(function* <T>(
|
|
56
|
-
endpoint: string,
|
|
57
|
-
command: string,
|
|
58
|
-
parseFailurePrefix: string,
|
|
59
|
-
) {
|
|
60
|
-
const service = yield* GitHubService;
|
|
61
|
-
|
|
62
|
-
const results: T[] = [];
|
|
63
|
-
let page = 1;
|
|
64
|
-
|
|
65
|
-
while (true) {
|
|
66
|
-
const separator = endpoint.includes("?") ? "&" : "?";
|
|
67
|
-
const result = yield* service.runGh([
|
|
68
|
-
"api",
|
|
69
|
-
`${endpoint}${separator}per_page=${REST_PAGE_SIZE}&page=${page}`,
|
|
70
|
-
]);
|
|
71
|
-
|
|
72
|
-
const rawPage = yield* parseJson<T[]>(result.stdout, command, parseFailurePrefix);
|
|
73
|
-
results.push(...rawPage);
|
|
74
|
-
|
|
75
|
-
if (rawPage.length < REST_PAGE_SIZE) {
|
|
76
|
-
return results;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
page += 1;
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
41
|
const mapRawIssueComment = (comment: RawIssueComment): IssueComment => ({
|
|
84
42
|
id: comment.id as IssueCommentId,
|
|
85
43
|
commitSha: null,
|
|
@@ -94,36 +52,25 @@ export const listIssues = Effect.fn("issue.listIssues")(function* (opts: {
|
|
|
94
52
|
state: string;
|
|
95
53
|
labels: string | null;
|
|
96
54
|
limit: number;
|
|
55
|
+
includeBody?: boolean;
|
|
56
|
+
fresh?: boolean;
|
|
97
57
|
}) {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
const args = [
|
|
101
|
-
"issue",
|
|
102
|
-
"list",
|
|
103
|
-
"--state",
|
|
104
|
-
opts.state,
|
|
105
|
-
"--limit",
|
|
106
|
-
String(opts.limit),
|
|
107
|
-
"--json",
|
|
108
|
-
"number,title,state,url,labels,createdAt",
|
|
109
|
-
];
|
|
110
|
-
|
|
111
|
-
if (opts.labels !== null) {
|
|
112
|
-
args.push("--label", opts.labels);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return yield* gh.runGhJson<IssueListItem[]>(args);
|
|
58
|
+
const { fresh, ...filter } = opts;
|
|
59
|
+
return yield* reads.issueList(yield* resolveRepo(null), filter, fresh ? "origin" : "cached");
|
|
116
60
|
});
|
|
117
61
|
|
|
118
62
|
export const viewIssue = Effect.fn("issue.viewIssue")(function* (issueNumber: number) {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
|
|
125
|
-
"
|
|
126
|
-
"
|
|
63
|
+
const value = yield* reads.issueView(yield* resolveRepo(null), issueNumber);
|
|
64
|
+
return project(value, [
|
|
65
|
+
"number",
|
|
66
|
+
"title",
|
|
67
|
+
"state",
|
|
68
|
+
"url",
|
|
69
|
+
"labels",
|
|
70
|
+
"assignees",
|
|
71
|
+
"author",
|
|
72
|
+
"createdAt",
|
|
73
|
+
"closedAt",
|
|
127
74
|
]);
|
|
128
75
|
});
|
|
129
76
|
|
|
@@ -133,14 +80,7 @@ export const fetchIssueComments = Effect.fn("issue.fetchIssueComments")(function
|
|
|
133
80
|
author: string | null,
|
|
134
81
|
bodyContains: string | null,
|
|
135
82
|
) {
|
|
136
|
-
const
|
|
137
|
-
const repoInfo = yield* gh.getRepoInfo();
|
|
138
|
-
|
|
139
|
-
const raw = yield* fetchAllRestPages<RawIssueComment>(
|
|
140
|
-
`repos/${repoInfo.owner}/${repoInfo.name}/issues/${issueNumber}/comments`,
|
|
141
|
-
"gh-tool issue comments",
|
|
142
|
-
"Failed to parse response",
|
|
143
|
-
);
|
|
83
|
+
const raw = yield* reads.issueComments(yield* resolveRepo(null), issueNumber);
|
|
144
84
|
|
|
145
85
|
let comments = raw.map(mapRawIssueComment);
|
|
146
86
|
|
|
@@ -167,46 +107,40 @@ export const closeIssue = Effect.fn("issue.closeIssue")(function* (opts: {
|
|
|
167
107
|
comment: string | null;
|
|
168
108
|
reason: string;
|
|
169
109
|
}) {
|
|
170
|
-
const gh = yield* GitHubService;
|
|
171
|
-
|
|
172
110
|
const args = ["issue", "close", String(opts.issue), "--reason", opts.reason];
|
|
173
111
|
|
|
174
112
|
if (opts.comment !== null) {
|
|
175
113
|
args.push("--comment", opts.comment);
|
|
176
114
|
}
|
|
177
115
|
|
|
178
|
-
yield*
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
String(opts.issue),
|
|
184
|
-
"--json",
|
|
185
|
-
"number,title,state,url,labels,assignees,author,createdAt,closedAt",
|
|
116
|
+
const repo = yield* resolveRepo(null);
|
|
117
|
+
yield* writes.run(args, [
|
|
118
|
+
`issue:${repoSlug(repo)}#${opts.issue}`,
|
|
119
|
+
`issues:${repoSlug(repo)}`,
|
|
120
|
+
`issue-comments:${repoSlug(repo)}#${opts.issue}`,
|
|
186
121
|
]);
|
|
122
|
+
|
|
123
|
+
return yield* viewIssue(opts.issue);
|
|
187
124
|
});
|
|
188
125
|
|
|
189
126
|
export const reopenIssue = Effect.fn("issue.reopenIssue")(function* (opts: {
|
|
190
127
|
issue: number;
|
|
191
128
|
comment: string | null;
|
|
192
129
|
}) {
|
|
193
|
-
const gh = yield* GitHubService;
|
|
194
|
-
|
|
195
130
|
const args = ["issue", "reopen", String(opts.issue)];
|
|
196
131
|
|
|
197
132
|
if (opts.comment !== null) {
|
|
198
133
|
args.push("--comment", opts.comment);
|
|
199
134
|
}
|
|
200
135
|
|
|
201
|
-
yield*
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
String(opts.issue),
|
|
207
|
-
"--json",
|
|
208
|
-
"number,title,state,url,labels,assignees,author,createdAt,closedAt",
|
|
136
|
+
const repo = yield* resolveRepo(null);
|
|
137
|
+
yield* writes.run(args, [
|
|
138
|
+
`issue:${repoSlug(repo)}#${opts.issue}`,
|
|
139
|
+
`issues:${repoSlug(repo)}`,
|
|
140
|
+
`issue-comments:${repoSlug(repo)}#${opts.issue}`,
|
|
209
141
|
]);
|
|
142
|
+
|
|
143
|
+
return yield* viewIssue(opts.issue);
|
|
210
144
|
});
|
|
211
145
|
|
|
212
146
|
export const commentOnIssue = Effect.fn("issue.commentOnIssue")(function* (opts: {
|
|
@@ -227,14 +161,20 @@ export const commentOnIssue = Effect.fn("issue.commentOnIssue")(function* (opts:
|
|
|
227
161
|
);
|
|
228
162
|
}
|
|
229
163
|
|
|
230
|
-
const result = yield*
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
164
|
+
const result = yield* writes.run(
|
|
165
|
+
[
|
|
166
|
+
"api",
|
|
167
|
+
"-X",
|
|
168
|
+
"POST",
|
|
169
|
+
`repos/${repoInfo.owner}/${repoInfo.name}/issues/${opts.issue}/comments`,
|
|
170
|
+
"-f",
|
|
171
|
+
`body=${opts.body}`,
|
|
172
|
+
],
|
|
173
|
+
[
|
|
174
|
+
`issue-comments:${repoInfo.owner.toLowerCase()}/${repoInfo.name.toLowerCase()}#${opts.issue}`,
|
|
175
|
+
`issue:${repoInfo.owner.toLowerCase()}/${repoInfo.name.toLowerCase()}#${opts.issue}`,
|
|
176
|
+
],
|
|
177
|
+
);
|
|
238
178
|
|
|
239
179
|
const rawComment = yield* Effect.try({
|
|
240
180
|
try: () => JSON.parse(result.stdout) as RawIssueComment,
|
|
@@ -262,8 +202,6 @@ export const createIssue = Effect.fn("issue.createIssue")(function* (opts: {
|
|
|
262
202
|
assignee: string | null;
|
|
263
203
|
labels: string | null;
|
|
264
204
|
}) {
|
|
265
|
-
const gh = yield* GitHubService;
|
|
266
|
-
|
|
267
205
|
const args = ["issue", "create", "--title", opts.title, "--body", opts.body];
|
|
268
206
|
|
|
269
207
|
if (opts.assignee !== null) {
|
|
@@ -273,7 +211,8 @@ export const createIssue = Effect.fn("issue.createIssue")(function* (opts: {
|
|
|
273
211
|
args.push("--label", opts.labels);
|
|
274
212
|
}
|
|
275
213
|
|
|
276
|
-
const
|
|
214
|
+
const repo = yield* resolveRepo(null);
|
|
215
|
+
const result = yield* writes.run(args, [`repo:${repoSlug(repo)}`]);
|
|
277
216
|
|
|
278
217
|
const urlMatch = result.stdout.match(/\/issues\/(\d+)/);
|
|
279
218
|
if (!urlMatch?.[1]) {
|
|
@@ -299,8 +238,6 @@ export const editIssue = Effect.fn("issue.editIssue")(function* (opts: {
|
|
|
299
238
|
addAssignee: string | null;
|
|
300
239
|
removeAssignee: string | null;
|
|
301
240
|
}) {
|
|
302
|
-
const gh = yield* GitHubService;
|
|
303
|
-
|
|
304
241
|
const args = ["issue", "edit", String(opts.issue)];
|
|
305
242
|
|
|
306
243
|
if (opts.title !== null) {
|
|
@@ -322,13 +259,12 @@ export const editIssue = Effect.fn("issue.editIssue")(function* (opts: {
|
|
|
322
259
|
args.push("--remove-assignee", opts.removeAssignee);
|
|
323
260
|
}
|
|
324
261
|
|
|
325
|
-
yield*
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
String(opts.issue),
|
|
331
|
-
"--json",
|
|
332
|
-
"number,title,state,url,labels,assignees,author,createdAt,closedAt",
|
|
262
|
+
const repo = yield* resolveRepo(null);
|
|
263
|
+
yield* writes.run(args, [
|
|
264
|
+
`issue:${repoSlug(repo)}#${opts.issue}`,
|
|
265
|
+
`issues:${repoSlug(repo)}`,
|
|
266
|
+
`issue-comments:${repoSlug(repo)}#${opts.issue}`,
|
|
333
267
|
]);
|
|
268
|
+
|
|
269
|
+
return yield* viewIssue(opts.issue);
|
|
334
270
|
});
|
|
@@ -4,10 +4,11 @@ import { Effect, Option, Schema } from "effect";
|
|
|
4
4
|
import type { CheckResult, IssueComment, PRViewInfo, ReviewThread } from "#gh/types";
|
|
5
5
|
|
|
6
6
|
import { formatOption, logFormatted } from "#shared";
|
|
7
|
-
import { GitHubService } from "#gh/
|
|
7
|
+
import { GitHubService } from "#gh/read/transport";
|
|
8
8
|
import { fetchReviewTriage } from "#gh/pr/commands";
|
|
9
9
|
|
|
10
10
|
import { fetchIssueComments } from "./core";
|
|
11
|
+
import { reads, resolveRepo } from "#gh/read/reads";
|
|
11
12
|
|
|
12
13
|
const repoOption = Flag.String("repo").pipe(
|
|
13
14
|
Flag.withDescription("Target repository profile name or owner/name"),
|
|
@@ -23,19 +24,6 @@ const withRepo = <A, E, R>(repo: Option.Option<string>, effect: Effect.Effect<A,
|
|
|
23
24
|
const TriageVerbosity = Schema.Literals(["compact", "full"]);
|
|
24
25
|
type TriageVerbosity = typeof TriageVerbosity.Type;
|
|
25
26
|
|
|
26
|
-
type RawTriageIssue = {
|
|
27
|
-
number: number;
|
|
28
|
-
title: string;
|
|
29
|
-
state: string;
|
|
30
|
-
url: string;
|
|
31
|
-
labels: Array<{ name: string }>;
|
|
32
|
-
assignees: Array<{ login: string }>;
|
|
33
|
-
author: { login: string };
|
|
34
|
-
body: string;
|
|
35
|
-
createdAt: string;
|
|
36
|
-
closedAt: string | null;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
27
|
type TriageIssue = {
|
|
40
28
|
number: number;
|
|
41
29
|
title: string;
|
|
@@ -114,19 +102,9 @@ export const fetchIssueTriage = Effect.fn("issue.fetchIssueTriage")(function* (o
|
|
|
114
102
|
issue: number;
|
|
115
103
|
verbosity: TriageVerbosity;
|
|
116
104
|
}) {
|
|
117
|
-
const
|
|
118
|
-
|
|
105
|
+
const repo = yield* resolveRepo(null);
|
|
119
106
|
const [rawIssue, comments] = yield* Effect.all(
|
|
120
|
-
[
|
|
121
|
-
gh.runGhJson<RawTriageIssue>([
|
|
122
|
-
"issue",
|
|
123
|
-
"view",
|
|
124
|
-
String(opts.issue),
|
|
125
|
-
"--json",
|
|
126
|
-
"number,title,state,url,labels,assignees,author,body,createdAt,closedAt",
|
|
127
|
-
]),
|
|
128
|
-
fetchIssueComments(opts.issue, null, null, null),
|
|
129
|
-
],
|
|
107
|
+
[reads.issueView(repo, opts.issue), fetchIssueComments(opts.issue, null, null, null)],
|
|
130
108
|
{ concurrency: "unbounded" },
|
|
131
109
|
);
|
|
132
110
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Command, Flag } from "effect/cli";
|
|
2
|
+
import { Effect, Option } from "effect";
|
|
3
|
+
|
|
4
|
+
import { formatOption, logFormatted } from "#shared";
|
|
5
|
+
import { GitHubService } from "#gh/read/transport";
|
|
6
|
+
import { resolveRepo } from "#gh/read/reads";
|
|
7
|
+
import { repoSlug } from "#gh/read/keys";
|
|
8
|
+
import { writes } from "#gh/read/writes";
|
|
9
|
+
|
|
10
|
+
export const createLabel = Effect.fn("label.createLabel")(function* (opts: {
|
|
11
|
+
name: string;
|
|
12
|
+
color: string;
|
|
13
|
+
description: string;
|
|
14
|
+
force: boolean;
|
|
15
|
+
}) {
|
|
16
|
+
const repo = yield* resolveRepo(null);
|
|
17
|
+
const args = [
|
|
18
|
+
"label",
|
|
19
|
+
"create",
|
|
20
|
+
opts.name,
|
|
21
|
+
"--color",
|
|
22
|
+
opts.color,
|
|
23
|
+
"--description",
|
|
24
|
+
opts.description,
|
|
25
|
+
];
|
|
26
|
+
if (opts.force) args.push("--force");
|
|
27
|
+
yield* writes.run(args, [`repo:${repoSlug(repo)}`]);
|
|
28
|
+
return { name: opts.name };
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const labelCreateCommand = Command.make(
|
|
32
|
+
"create",
|
|
33
|
+
{
|
|
34
|
+
name: Flag.String("name").pipe(Flag.withDescription("Label name")),
|
|
35
|
+
color: Flag.String("color").pipe(Flag.withDescription("Six-character hexadecimal color")),
|
|
36
|
+
description: Flag.String("description").pipe(Flag.withDefault("")),
|
|
37
|
+
force: Flag.Boolean("force").pipe(
|
|
38
|
+
Flag.withDescription("Update the label if it already exists"),
|
|
39
|
+
Flag.withDefault(false),
|
|
40
|
+
),
|
|
41
|
+
repo: Flag.String("repo").pipe(
|
|
42
|
+
Flag.withDescription("Target repository profile name or owner/name"),
|
|
43
|
+
Flag.optional,
|
|
44
|
+
),
|
|
45
|
+
format: formatOption,
|
|
46
|
+
},
|
|
47
|
+
({ format, repo, ...opts }) =>
|
|
48
|
+
Effect.gen(function* () {
|
|
49
|
+
const gh = yield* GitHubService;
|
|
50
|
+
yield* gh.withRepoTarget(
|
|
51
|
+
Option.getOrNull(repo),
|
|
52
|
+
Effect.gen(function* () {
|
|
53
|
+
yield* logFormatted(yield* createLabel(opts), format);
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
}),
|
|
57
|
+
).pipe(Command.withDescription("Create a repository label"));
|
package/src/gh-tool/main.ts
CHANGED
|
@@ -71,8 +71,16 @@ import {
|
|
|
71
71
|
releaseStatusCommand,
|
|
72
72
|
releaseViewCommand,
|
|
73
73
|
} from "./release";
|
|
74
|
-
import {
|
|
75
|
-
|
|
74
|
+
import {
|
|
75
|
+
repoCommitAuthorCommand,
|
|
76
|
+
repoInfoCommand,
|
|
77
|
+
repoListCommand,
|
|
78
|
+
repoSearchCodeCommand,
|
|
79
|
+
} from "./repo";
|
|
80
|
+
import { labelCreateCommand } from "./label";
|
|
81
|
+
import { GitHubService } from "./read/transport";
|
|
82
|
+
import { withReadCache } from "./read";
|
|
83
|
+
import { cacheCommand } from "./read/commands";
|
|
76
84
|
import {
|
|
77
85
|
workflowAnnotationsCommand,
|
|
78
86
|
workflowCancelCommand,
|
|
@@ -151,7 +159,17 @@ const branchCommand = Command.make("branch", {}).pipe(
|
|
|
151
159
|
|
|
152
160
|
const repoCommand = Command.make("repo", {}).pipe(
|
|
153
161
|
Command.withDescription("Repository operations"),
|
|
154
|
-
Command.withSubcommands([
|
|
162
|
+
Command.withSubcommands([
|
|
163
|
+
repoInfoCommand,
|
|
164
|
+
repoListCommand,
|
|
165
|
+
repoSearchCodeCommand,
|
|
166
|
+
repoCommitAuthorCommand,
|
|
167
|
+
]),
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const labelCommand = Command.make("label", {}).pipe(
|
|
171
|
+
Command.withDescription("Repository label operations"),
|
|
172
|
+
Command.withSubcommands([labelCreateCommand]),
|
|
155
173
|
);
|
|
156
174
|
|
|
157
175
|
const workflowCommand = Command.make("workflow", {}).pipe(
|
|
@@ -235,11 +253,13 @@ WORKFLOW FOR AI AGENTS:
|
|
|
235
253
|
prCommand,
|
|
236
254
|
issueCommand,
|
|
237
255
|
repoCommand,
|
|
256
|
+
labelCommand,
|
|
238
257
|
branchCommand,
|
|
239
258
|
workflowCommand,
|
|
240
259
|
releaseCommand,
|
|
241
260
|
gistCommand,
|
|
242
261
|
commandsCommand,
|
|
262
|
+
cacheCommand,
|
|
243
263
|
]),
|
|
244
264
|
);
|
|
245
265
|
|
|
@@ -254,7 +274,7 @@ const MainLayer = GitHubService.layer.pipe(
|
|
|
254
274
|
Layer.provideMerge(ConfigServiceLayer),
|
|
255
275
|
);
|
|
256
276
|
|
|
257
|
-
const program = withRedactedOutput(withAudit("gh", cli)).pipe(
|
|
277
|
+
const program = withReadCache(withRedactedOutput(withAudit("gh", cli))).pipe(
|
|
258
278
|
Effect.provide(MainLayer),
|
|
259
279
|
Effect.tapCause(renderCauseToStderr),
|
|
260
280
|
);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { reads, writes } from "#gh/read/index";
|
|
2
|
+
import { repoSlug } from "#gh/read/keys";
|
|
1
3
|
import { Command, Flag, Param } from "effect/cli";
|
|
2
4
|
import { Console, Effect, Option } from "effect";
|
|
3
5
|
|
|
4
6
|
import type { CheckResult, PRStatusResult } from "#gh/types";
|
|
5
7
|
|
|
6
8
|
import { formatOption, logFormatted, logText } from "#shared";
|
|
7
|
-
import { GitHubService } from "#gh/
|
|
9
|
+
import { GitHubService } from "#gh/read/transport";
|
|
8
10
|
import { GitHubCommandError } from "#gh/errors";
|
|
9
11
|
|
|
10
12
|
const emptyBatchError = (batch: string) =>
|
|
@@ -152,20 +154,20 @@ export const requestReview = (pr: number, reviewers: string) =>
|
|
|
152
154
|
const repo = yield* gh.getRepoInfo();
|
|
153
155
|
// ponytail: not atomic — a concurrent request between GET and POST misreports newlyRequested.
|
|
154
156
|
const pendingBefore = new Set(
|
|
155
|
-
(yield* confirmedReviewers(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
(yield* confirmedReviewers(yield* reads.reviewGuards.requestedReviewers(repo, pr))).map(
|
|
158
|
+
(login) => login.toLowerCase(),
|
|
159
|
+
),
|
|
160
|
+
);
|
|
161
|
+
const response = yield* writes.json<RequestedReviewersResponse>(
|
|
162
|
+
[
|
|
163
|
+
"api",
|
|
164
|
+
"--method",
|
|
165
|
+
"POST",
|
|
166
|
+
`repos/${repo.owner}/${repo.name}/pulls/${pr}/requested_reviewers`,
|
|
167
|
+
...submittedReviewers.flatMap((reviewer) => ["-f", `reviewers[]=${reviewer}`]),
|
|
168
|
+
],
|
|
169
|
+
[`pr:${repoSlug(repo)}#${pr}`, `reviews:${repoSlug(repo)}#${pr}`, `pulls:${repoSlug(repo)}`],
|
|
161
170
|
);
|
|
162
|
-
const response = yield* gh.runGhJson<RequestedReviewersResponse>([
|
|
163
|
-
"api",
|
|
164
|
-
"--method",
|
|
165
|
-
"POST",
|
|
166
|
-
`repos/${repo.owner}/${repo.name}/pulls/${pr}/requested_reviewers`,
|
|
167
|
-
...submittedReviewers.flatMap((reviewer) => ["-f", `reviewers[]=${reviewer}`]),
|
|
168
|
-
]);
|
|
169
171
|
return {
|
|
170
172
|
pr,
|
|
171
173
|
submittedReviewers,
|
|
@@ -239,7 +241,7 @@ const withStableHead = Effect.fn("pr.withStableHead")(function* <A, E, R>(
|
|
|
239
241
|
initial,
|
|
240
242
|
(info) => collect(info.number, info.headSha),
|
|
241
243
|
(info) =>
|
|
242
|
-
fetchPRView(info.number).pipe(
|
|
244
|
+
fetchPRView(info.number, "origin").pipe(
|
|
243
245
|
Effect.map((refreshed) => ({ ...refreshed, baseSha: initial.baseSha })),
|
|
244
246
|
),
|
|
245
247
|
(before, after) => after.headSha === before.headSha,
|