@blogic-cz/agent-tools 0.1.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/LICENSE +21 -0
- package/README.md +236 -0
- package/package.json +70 -0
- package/schemas/agent-tools.schema.json +319 -0
- package/src/az-tool/build.ts +295 -0
- package/src/az-tool/config.ts +33 -0
- package/src/az-tool/errors.ts +26 -0
- package/src/az-tool/extract-option-value.ts +12 -0
- package/src/az-tool/index.ts +181 -0
- package/src/az-tool/security.ts +130 -0
- package/src/az-tool/service.ts +292 -0
- package/src/az-tool/types.ts +67 -0
- package/src/config/index.ts +12 -0
- package/src/config/loader.ts +170 -0
- package/src/config/types.ts +82 -0
- package/src/credential-guard/claude-hook.ts +28 -0
- package/src/credential-guard/index.ts +435 -0
- package/src/db-tool/config-service.ts +38 -0
- package/src/db-tool/errors.ts +40 -0
- package/src/db-tool/index.ts +91 -0
- package/src/db-tool/schema.ts +69 -0
- package/src/db-tool/security.ts +116 -0
- package/src/db-tool/service.ts +605 -0
- package/src/db-tool/types.ts +33 -0
- package/src/gh-tool/config.ts +7 -0
- package/src/gh-tool/errors.ts +47 -0
- package/src/gh-tool/index.ts +140 -0
- package/src/gh-tool/issue.ts +361 -0
- package/src/gh-tool/pr/commands.ts +432 -0
- package/src/gh-tool/pr/core.ts +497 -0
- package/src/gh-tool/pr/helpers.ts +84 -0
- package/src/gh-tool/pr/index.ts +19 -0
- package/src/gh-tool/pr/review.ts +571 -0
- package/src/gh-tool/repo.ts +147 -0
- package/src/gh-tool/service.ts +192 -0
- package/src/gh-tool/types.ts +97 -0
- package/src/gh-tool/workflow.ts +542 -0
- package/src/index.ts +1 -0
- package/src/k8s-tool/errors.ts +21 -0
- package/src/k8s-tool/index.ts +151 -0
- package/src/k8s-tool/service.ts +227 -0
- package/src/k8s-tool/types.ts +9 -0
- package/src/logs-tool/errors.ts +29 -0
- package/src/logs-tool/index.ts +176 -0
- package/src/logs-tool/service.ts +323 -0
- package/src/logs-tool/types.ts +40 -0
- package/src/session-tool/config.ts +55 -0
- package/src/session-tool/errors.ts +38 -0
- package/src/session-tool/index.ts +270 -0
- package/src/session-tool/service.ts +210 -0
- package/src/session-tool/types.ts +28 -0
- package/src/shared/bun.ts +59 -0
- package/src/shared/cli.ts +38 -0
- package/src/shared/error-renderer.ts +42 -0
- package/src/shared/exec.ts +62 -0
- package/src/shared/format.ts +27 -0
- package/src/shared/index.ts +16 -0
- package/src/shared/throttle.ts +35 -0
- package/src/shared/types.ts +25 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import { Command, Flag } from "effect/unstable/cli";
|
|
2
|
+
import { Effect, Option } from "effect";
|
|
3
|
+
|
|
4
|
+
import type { PRStatusResult } from "../types";
|
|
5
|
+
|
|
6
|
+
import { formatOption, logFormatted } from "../../shared";
|
|
7
|
+
import {
|
|
8
|
+
CI_CHECK_WATCH_TIMEOUT_MS,
|
|
9
|
+
DEFAULT_DELETE_BRANCH,
|
|
10
|
+
DEFAULT_MERGE_STRATEGY,
|
|
11
|
+
MERGE_STRATEGIES,
|
|
12
|
+
} from "../config";
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
createPR,
|
|
16
|
+
detectPRStatus,
|
|
17
|
+
editPR,
|
|
18
|
+
fetchChecks,
|
|
19
|
+
fetchFailedChecks,
|
|
20
|
+
mergePR,
|
|
21
|
+
rerunChecks,
|
|
22
|
+
viewPR,
|
|
23
|
+
} from "./core";
|
|
24
|
+
import {
|
|
25
|
+
fetchComments,
|
|
26
|
+
fetchDiscussionSummary,
|
|
27
|
+
fetchIssueComments,
|
|
28
|
+
fetchLatestIssueComment,
|
|
29
|
+
fetchThreads,
|
|
30
|
+
postIssueComment,
|
|
31
|
+
replyToComment,
|
|
32
|
+
resolveThread,
|
|
33
|
+
submitPendingReview,
|
|
34
|
+
} from "./review";
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// CLI Commands
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
export const prViewCommand = Command.make(
|
|
41
|
+
"view",
|
|
42
|
+
{
|
|
43
|
+
format: formatOption,
|
|
44
|
+
pr: Flag.integer("pr").pipe(
|
|
45
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
46
|
+
Flag.optional,
|
|
47
|
+
),
|
|
48
|
+
},
|
|
49
|
+
({ format, pr }) =>
|
|
50
|
+
Effect.gen(function* () {
|
|
51
|
+
const prNumber = Option.getOrNull(pr);
|
|
52
|
+
const info = yield* viewPR(prNumber);
|
|
53
|
+
yield* logFormatted(info, format);
|
|
54
|
+
}),
|
|
55
|
+
).pipe(Command.withDescription("View PR information"));
|
|
56
|
+
|
|
57
|
+
export const prStatusCommand = Command.make("status", { format: formatOption }, ({ format }) =>
|
|
58
|
+
Effect.gen(function* () {
|
|
59
|
+
const result: PRStatusResult = yield* detectPRStatus();
|
|
60
|
+
yield* logFormatted(result, format);
|
|
61
|
+
}),
|
|
62
|
+
).pipe(
|
|
63
|
+
Command.withDescription("Auto-detect PR for current branch or GitButler workspace branches"),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
export const prCreateCommand = Command.make(
|
|
67
|
+
"create",
|
|
68
|
+
{
|
|
69
|
+
base: Flag.string("base").pipe(
|
|
70
|
+
Flag.withDescription("Base branch for the PR"),
|
|
71
|
+
Flag.withDefault("test"),
|
|
72
|
+
),
|
|
73
|
+
body: Flag.string("body").pipe(
|
|
74
|
+
Flag.withDescription("PR body/description"),
|
|
75
|
+
Flag.withDefault(""),
|
|
76
|
+
),
|
|
77
|
+
draft: Flag.boolean("draft").pipe(
|
|
78
|
+
Flag.withDescription("Create as draft PR"),
|
|
79
|
+
Flag.withDefault(false),
|
|
80
|
+
),
|
|
81
|
+
format: formatOption,
|
|
82
|
+
head: Flag.string("head").pipe(
|
|
83
|
+
Flag.withDescription("Source branch name (required in GitButler workspace mode)"),
|
|
84
|
+
Flag.optional,
|
|
85
|
+
),
|
|
86
|
+
title: Flag.string("title").pipe(Flag.withDescription("PR title")),
|
|
87
|
+
},
|
|
88
|
+
({ base, body, draft, format, head, title }) =>
|
|
89
|
+
Effect.gen(function* () {
|
|
90
|
+
const info = yield* createPR({
|
|
91
|
+
base,
|
|
92
|
+
body,
|
|
93
|
+
draft,
|
|
94
|
+
head: Option.getOrNull(head),
|
|
95
|
+
title,
|
|
96
|
+
});
|
|
97
|
+
yield* logFormatted(info, format);
|
|
98
|
+
}),
|
|
99
|
+
).pipe(Command.withDescription("Create or update a PR for current branch"));
|
|
100
|
+
|
|
101
|
+
export const prEditCommand = Command.make(
|
|
102
|
+
"edit",
|
|
103
|
+
{
|
|
104
|
+
body: Flag.string("body").pipe(Flag.withDescription("New PR body/description"), Flag.optional),
|
|
105
|
+
format: formatOption,
|
|
106
|
+
pr: Flag.integer("pr").pipe(Flag.withDescription("PR number to edit")),
|
|
107
|
+
title: Flag.string("title").pipe(Flag.withDescription("New PR title"), Flag.optional),
|
|
108
|
+
},
|
|
109
|
+
({ body, format, pr, title }) =>
|
|
110
|
+
Effect.gen(function* () {
|
|
111
|
+
const info = yield* editPR({
|
|
112
|
+
pr,
|
|
113
|
+
title: Option.getOrNull(title),
|
|
114
|
+
body: Option.getOrNull(body),
|
|
115
|
+
});
|
|
116
|
+
yield* logFormatted(info, format);
|
|
117
|
+
}),
|
|
118
|
+
).pipe(Command.withDescription("Edit an existing PR's title, body, or other metadata"));
|
|
119
|
+
|
|
120
|
+
export const prMergeCommand = Command.make(
|
|
121
|
+
"merge",
|
|
122
|
+
{
|
|
123
|
+
confirm: Flag.boolean("confirm").pipe(
|
|
124
|
+
Flag.withDescription("Actually merge (without this flag, only shows dry-run)"),
|
|
125
|
+
Flag.withDefault(false),
|
|
126
|
+
),
|
|
127
|
+
deleteBranch: Flag.boolean("delete-branch").pipe(
|
|
128
|
+
Flag.withDescription("Delete branch after merge"),
|
|
129
|
+
Flag.withDefault(DEFAULT_DELETE_BRANCH),
|
|
130
|
+
),
|
|
131
|
+
format: formatOption,
|
|
132
|
+
pr: Flag.integer("pr").pipe(Flag.withDescription("PR number to merge")),
|
|
133
|
+
strategy: Flag.choice("strategy", MERGE_STRATEGIES).pipe(
|
|
134
|
+
Flag.withDescription("Merge strategy: squash, merge, or rebase"),
|
|
135
|
+
Flag.withDefault(DEFAULT_MERGE_STRATEGY),
|
|
136
|
+
),
|
|
137
|
+
},
|
|
138
|
+
({ confirm, deleteBranch, format, pr, strategy }) =>
|
|
139
|
+
Effect.gen(function* () {
|
|
140
|
+
const result = yield* mergePR({
|
|
141
|
+
confirm,
|
|
142
|
+
deleteBranch,
|
|
143
|
+
pr,
|
|
144
|
+
strategy,
|
|
145
|
+
});
|
|
146
|
+
yield* logFormatted(result, format);
|
|
147
|
+
}),
|
|
148
|
+
).pipe(Command.withDescription("Merge a PR (dry-run by default, use --confirm to execute)"));
|
|
149
|
+
|
|
150
|
+
export const prChecksCommand = Command.make(
|
|
151
|
+
"checks",
|
|
152
|
+
{
|
|
153
|
+
failFast: Flag.boolean("fail-fast").pipe(
|
|
154
|
+
Flag.withDefault(true),
|
|
155
|
+
Flag.withDescription("Stop watching on first failure (with --watch)"),
|
|
156
|
+
),
|
|
157
|
+
format: formatOption,
|
|
158
|
+
pr: Flag.integer("pr").pipe(
|
|
159
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
160
|
+
Flag.optional,
|
|
161
|
+
),
|
|
162
|
+
timeout: Flag.integer("timeout").pipe(
|
|
163
|
+
Flag.withDefault(CI_CHECK_WATCH_TIMEOUT_MS / 1000),
|
|
164
|
+
Flag.withDescription("Timeout in seconds for watch mode (default: 600)"),
|
|
165
|
+
),
|
|
166
|
+
watch: Flag.boolean("watch").pipe(
|
|
167
|
+
Flag.withDefault(false),
|
|
168
|
+
Flag.withDescription("Watch until checks complete or timeout"),
|
|
169
|
+
),
|
|
170
|
+
},
|
|
171
|
+
({ failFast, format, pr, timeout, watch }) =>
|
|
172
|
+
Effect.gen(function* () {
|
|
173
|
+
const prNumber = Option.getOrNull(pr);
|
|
174
|
+
const checks = yield* fetchChecks(prNumber, watch, failFast, timeout);
|
|
175
|
+
yield* logFormatted(checks, format);
|
|
176
|
+
}),
|
|
177
|
+
).pipe(Command.withDescription("Fetch CI check status for a PR (optionally watch with timeout)"));
|
|
178
|
+
|
|
179
|
+
export const prChecksFailedCommand = Command.make(
|
|
180
|
+
"checks-failed",
|
|
181
|
+
{
|
|
182
|
+
format: formatOption,
|
|
183
|
+
pr: Flag.integer("pr").pipe(
|
|
184
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
185
|
+
Flag.optional,
|
|
186
|
+
),
|
|
187
|
+
},
|
|
188
|
+
({ format, pr }) =>
|
|
189
|
+
Effect.gen(function* () {
|
|
190
|
+
const prNumber = Option.getOrNull(pr);
|
|
191
|
+
const checks = yield* fetchFailedChecks(prNumber);
|
|
192
|
+
yield* logFormatted(checks, format);
|
|
193
|
+
}),
|
|
194
|
+
).pipe(Command.withDescription("Fetch only failed CI checks for a PR"));
|
|
195
|
+
|
|
196
|
+
export const prRerunChecksCommand = Command.make(
|
|
197
|
+
"rerun-checks",
|
|
198
|
+
{
|
|
199
|
+
format: formatOption,
|
|
200
|
+
pr: Flag.integer("pr").pipe(
|
|
201
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
202
|
+
Flag.optional,
|
|
203
|
+
),
|
|
204
|
+
failedOnly: Flag.boolean("failed-only").pipe(
|
|
205
|
+
Flag.withDefault(true),
|
|
206
|
+
Flag.withDescription("Only rerun failed checks (default: true)"),
|
|
207
|
+
),
|
|
208
|
+
},
|
|
209
|
+
({ failedOnly, format, pr }) =>
|
|
210
|
+
Effect.gen(function* () {
|
|
211
|
+
const prNumber = Option.getOrNull(pr);
|
|
212
|
+
const result = yield* rerunChecks(prNumber, failedOnly);
|
|
213
|
+
yield* logFormatted(result, format);
|
|
214
|
+
}),
|
|
215
|
+
).pipe(
|
|
216
|
+
Command.withDescription("Rerun CI checks for a PR (GitHub Actions only, failed by default)"),
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
export const prThreadsCommand = Command.make(
|
|
220
|
+
"threads",
|
|
221
|
+
{
|
|
222
|
+
format: formatOption,
|
|
223
|
+
pr: Flag.integer("pr").pipe(
|
|
224
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
225
|
+
Flag.optional,
|
|
226
|
+
),
|
|
227
|
+
unresolvedOnly: Flag.boolean("unresolved-only").pipe(
|
|
228
|
+
Flag.withDescription("Only show unresolved threads"),
|
|
229
|
+
Flag.withDefault(true),
|
|
230
|
+
),
|
|
231
|
+
},
|
|
232
|
+
({ format, pr, unresolvedOnly }) =>
|
|
233
|
+
Effect.gen(function* () {
|
|
234
|
+
const prNumber = Option.getOrNull(pr);
|
|
235
|
+
const threads = yield* fetchThreads(prNumber, unresolvedOnly);
|
|
236
|
+
yield* logFormatted(threads, format);
|
|
237
|
+
}),
|
|
238
|
+
).pipe(Command.withDescription("Fetch review threads for a PR (unresolved by default)"));
|
|
239
|
+
|
|
240
|
+
export const prCommentsCommand = Command.make(
|
|
241
|
+
"comments",
|
|
242
|
+
{
|
|
243
|
+
format: formatOption,
|
|
244
|
+
pr: Flag.integer("pr").pipe(
|
|
245
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
246
|
+
Flag.optional,
|
|
247
|
+
),
|
|
248
|
+
since: Flag.string("since").pipe(
|
|
249
|
+
Flag.withDescription("ISO timestamp to filter comments created after"),
|
|
250
|
+
Flag.optional,
|
|
251
|
+
),
|
|
252
|
+
},
|
|
253
|
+
({ format, pr, since }) =>
|
|
254
|
+
Effect.gen(function* () {
|
|
255
|
+
const prNumber = Option.getOrNull(pr);
|
|
256
|
+
const sinceValue = Option.getOrNull(since);
|
|
257
|
+
const comments = yield* fetchComments(prNumber, sinceValue);
|
|
258
|
+
yield* logFormatted(comments, format);
|
|
259
|
+
}),
|
|
260
|
+
).pipe(Command.withDescription("Fetch review comments for a PR (optionally filter by --since)"));
|
|
261
|
+
|
|
262
|
+
export const prIssueCommentsCommand = Command.make(
|
|
263
|
+
"issue-comments",
|
|
264
|
+
{
|
|
265
|
+
author: Flag.string("author").pipe(
|
|
266
|
+
Flag.withDescription("Filter by author login substring"),
|
|
267
|
+
Flag.optional,
|
|
268
|
+
),
|
|
269
|
+
bodyContains: Flag.string("body-contains").pipe(
|
|
270
|
+
Flag.withDescription("Filter comments by body substring"),
|
|
271
|
+
Flag.optional,
|
|
272
|
+
),
|
|
273
|
+
format: formatOption,
|
|
274
|
+
pr: Flag.integer("pr").pipe(
|
|
275
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
276
|
+
Flag.optional,
|
|
277
|
+
),
|
|
278
|
+
since: Flag.string("since").pipe(
|
|
279
|
+
Flag.withDescription("ISO timestamp to filter comments created after"),
|
|
280
|
+
Flag.optional,
|
|
281
|
+
),
|
|
282
|
+
},
|
|
283
|
+
({ author, bodyContains, format, pr, since }) =>
|
|
284
|
+
Effect.gen(function* () {
|
|
285
|
+
const prNumber = Option.getOrNull(pr);
|
|
286
|
+
const sinceValue = Option.getOrNull(since);
|
|
287
|
+
const authorValue = Option.getOrNull(author);
|
|
288
|
+
const bodyContainsValue = Option.getOrNull(bodyContains);
|
|
289
|
+
|
|
290
|
+
const comments = yield* fetchIssueComments(
|
|
291
|
+
prNumber,
|
|
292
|
+
sinceValue,
|
|
293
|
+
authorValue,
|
|
294
|
+
bodyContainsValue,
|
|
295
|
+
);
|
|
296
|
+
yield* logFormatted(comments, format);
|
|
297
|
+
}),
|
|
298
|
+
).pipe(Command.withDescription("Fetch general PR discussion comments (issue comments)"));
|
|
299
|
+
|
|
300
|
+
export const prIssueCommentsLatestCommand = Command.make(
|
|
301
|
+
"issue-comments-latest",
|
|
302
|
+
{
|
|
303
|
+
author: Flag.string("author").pipe(
|
|
304
|
+
Flag.withDescription("Filter by author login substring"),
|
|
305
|
+
Flag.optional,
|
|
306
|
+
),
|
|
307
|
+
bodyContains: Flag.string("body-contains").pipe(
|
|
308
|
+
Flag.withDescription("Filter comments by body substring"),
|
|
309
|
+
Flag.optional,
|
|
310
|
+
),
|
|
311
|
+
format: formatOption,
|
|
312
|
+
pr: Flag.integer("pr").pipe(
|
|
313
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
314
|
+
Flag.optional,
|
|
315
|
+
),
|
|
316
|
+
},
|
|
317
|
+
({ author, bodyContains, format, pr }) =>
|
|
318
|
+
Effect.gen(function* () {
|
|
319
|
+
const prNumber = Option.getOrNull(pr);
|
|
320
|
+
const authorValue = Option.getOrNull(author);
|
|
321
|
+
const bodyContainsValue = Option.getOrNull(bodyContains);
|
|
322
|
+
|
|
323
|
+
const comment = yield* fetchLatestIssueComment(prNumber, authorValue, bodyContainsValue);
|
|
324
|
+
yield* logFormatted(comment, format);
|
|
325
|
+
}),
|
|
326
|
+
).pipe(Command.withDescription("Fetch latest general PR discussion comment"));
|
|
327
|
+
|
|
328
|
+
export const prCommentCommand = Command.make(
|
|
329
|
+
"comment",
|
|
330
|
+
{
|
|
331
|
+
body: Flag.string("body").pipe(Flag.withDescription("General PR comment body text")),
|
|
332
|
+
format: formatOption,
|
|
333
|
+
pr: Flag.integer("pr").pipe(
|
|
334
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
335
|
+
Flag.optional,
|
|
336
|
+
),
|
|
337
|
+
},
|
|
338
|
+
({ body, format, pr }) =>
|
|
339
|
+
Effect.gen(function* () {
|
|
340
|
+
const prNumber = Option.getOrNull(pr);
|
|
341
|
+
const result = yield* postIssueComment(prNumber, body);
|
|
342
|
+
yield* logFormatted(result, format);
|
|
343
|
+
}),
|
|
344
|
+
).pipe(Command.withDescription("Post a general PR discussion comment"));
|
|
345
|
+
|
|
346
|
+
export const prDiscussionSummaryCommand = Command.make(
|
|
347
|
+
"discussion-summary",
|
|
348
|
+
{
|
|
349
|
+
format: formatOption,
|
|
350
|
+
pr: Flag.integer("pr").pipe(
|
|
351
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
352
|
+
Flag.optional,
|
|
353
|
+
),
|
|
354
|
+
},
|
|
355
|
+
({ format, pr }) =>
|
|
356
|
+
Effect.gen(function* () {
|
|
357
|
+
const prNumber = Option.getOrNull(pr);
|
|
358
|
+
const summary = yield* fetchDiscussionSummary(prNumber);
|
|
359
|
+
yield* logFormatted(summary, format);
|
|
360
|
+
}),
|
|
361
|
+
).pipe(
|
|
362
|
+
Command.withDescription("Fetch counts and latest comment across PR discussions and reviews"),
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
export const prReplyCommand = Command.make(
|
|
366
|
+
"reply",
|
|
367
|
+
{
|
|
368
|
+
body: Flag.string("body").pipe(Flag.withDescription("Reply body text")),
|
|
369
|
+
commentId: Flag.integer("comment-id").pipe(
|
|
370
|
+
Flag.withDescription("ID of the comment to reply to"),
|
|
371
|
+
),
|
|
372
|
+
format: formatOption,
|
|
373
|
+
pr: Flag.integer("pr").pipe(
|
|
374
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
375
|
+
Flag.optional,
|
|
376
|
+
),
|
|
377
|
+
},
|
|
378
|
+
({ body, commentId, format, pr }) =>
|
|
379
|
+
Effect.gen(function* () {
|
|
380
|
+
const prNumber = Option.getOrNull(pr);
|
|
381
|
+
const result = yield* replyToComment(prNumber, commentId, body);
|
|
382
|
+
yield* logFormatted(result, format);
|
|
383
|
+
}),
|
|
384
|
+
).pipe(Command.withDescription("Reply to an inline review comment"));
|
|
385
|
+
|
|
386
|
+
export const prResolveCommand = Command.make(
|
|
387
|
+
"resolve",
|
|
388
|
+
{
|
|
389
|
+
format: formatOption,
|
|
390
|
+
threadId: Flag.string("thread-id").pipe(
|
|
391
|
+
Flag.withDescription("GraphQL node ID of the thread to resolve"),
|
|
392
|
+
),
|
|
393
|
+
},
|
|
394
|
+
({ format, threadId }) =>
|
|
395
|
+
Effect.gen(function* () {
|
|
396
|
+
const result = yield* resolveThread(threadId);
|
|
397
|
+
yield* logFormatted(result, format);
|
|
398
|
+
}),
|
|
399
|
+
).pipe(Command.withDescription("Resolve a review thread via GraphQL"));
|
|
400
|
+
|
|
401
|
+
export const prSubmitReviewCommand = Command.make(
|
|
402
|
+
"submit-review",
|
|
403
|
+
{
|
|
404
|
+
body: Flag.string("body").pipe(
|
|
405
|
+
Flag.withDescription("Optional review body text when submitting"),
|
|
406
|
+
Flag.optional,
|
|
407
|
+
),
|
|
408
|
+
format: formatOption,
|
|
409
|
+
pr: Flag.integer("pr").pipe(
|
|
410
|
+
Flag.withDescription("PR number (default: current branch PR)"),
|
|
411
|
+
Flag.optional,
|
|
412
|
+
),
|
|
413
|
+
reviewId: Flag.string("review-id").pipe(
|
|
414
|
+
Flag.withDescription(
|
|
415
|
+
"Pending review GraphQL ID (defaults to current user's pending review on PR)",
|
|
416
|
+
),
|
|
417
|
+
Flag.optional,
|
|
418
|
+
),
|
|
419
|
+
},
|
|
420
|
+
({ body, format, pr, reviewId }) =>
|
|
421
|
+
Effect.gen(function* () {
|
|
422
|
+
const prNumber = Option.getOrNull(pr);
|
|
423
|
+
const reviewIdValue = Option.getOrNull(reviewId);
|
|
424
|
+
const bodyValue = Option.getOrNull(body);
|
|
425
|
+
const result = yield* submitPendingReview(prNumber, reviewIdValue, bodyValue);
|
|
426
|
+
yield* logFormatted(result, format);
|
|
427
|
+
}),
|
|
428
|
+
).pipe(
|
|
429
|
+
Command.withDescription(
|
|
430
|
+
"Submit a pending review as COMMENT (auto-detects your pending review if --review-id is omitted)",
|
|
431
|
+
),
|
|
432
|
+
);
|