@blogic-cz/agent-tools 1.2.1 → 1.2.2

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 CHANGED
@@ -309,9 +309,16 @@ bun gh-tool pr trigger-checks --pr 123 --workflow dotnet-pull-request.yml # only
309
309
  bun gh-tool pr watch --prs 123,124 --format jsonl --timeout 600
310
310
  bun gh-tool pr reply-and-resolve --comment-id 456 --body "Done" # infers PR and thread
311
311
  bun gh-tool pr request-review --repo be --pr 123 --reviewers alice,bob
312
+ bun gh-tool pr review --pr 123 --event comment --body "Notes, no verdict"
313
+ bun gh-tool pr review --pr 123 --event request-changes --body-stdin --confirm <<'EOF'
314
+ Rebase breaks two call sites; the Interop spec belongs in the domain module.
315
+ EOF
316
+ bun gh-tool pr review --pr 123 --event approve --confirm
312
317
  # Optional --pr/--thread-id retain legacy flow and are validated before either mutation.
313
318
  ```
314
319
 
320
+ `pr review` creates and submits a review in one call, for a verdict reached from a diff with no pending review to submit. `pr submit-review` takes the same `--event` for a review that is already pending. `--event approve` and `--event request-changes` change whether the PR can merge, so both require `--confirm`, the same gate `pr merge` uses; `--event comment` carries no verdict and needs none. `--event comment` and `--event request-changes` require a non-empty body — GitHub rejects a bodyless one. GitHub also refuses a verdict on your own PR; that failure returns a hint pointing at `--event comment` instead of the raw API error.
321
+
315
322
  Reruns preflight every target before mutation and fail closed with `evidence_unavailable` when attempt jobs or logs cannot be read. Failed jobs use one `gh run rerun RUN --failed` mutation per workflow run. Without `--watch`, output returns current attempt metadata immediately; with `--watch`, discovery and watching share one absolute `--timeout` deadline and report `discovery_timeout` or `watch_timeout` with latest attempt state. Repeated matching pre-test infrastructure failures return `escalation_required` without mutation. See [`skills/gh-tool/SKILL.md`](skills/gh-tool/SKILL.md) for operating guidance; this section is canonical for added output fields.
316
323
 
317
324
  Zero reported checks is a state, not an error: `gh pr checks` exits nonzero on an empty result, and every command that reads checks maps that to `[]`. `pr trigger-checks` covers the case where GitHub dropped the `pull_request` event and no run exists at all — it dispatches the named `workflow_dispatch` workflow **on the PR head branch**, then compares the created run's `headSha` back to the PR head and reports `matchesPrHead`. A run dispatched on the wrong ref goes green for another branch and must never be read as PR evidence, so `workflow run` also returns the discovered `runId`/`headSha` instead of a bare `dispatched: true`.
@@ -4,4 +4,6 @@ export declare const CI_CHECK_WATCH_TIMEOUT_MS: 600000;
4
4
  export declare const GRAPHQL_PAGE_SIZE: 100;
5
5
  export declare const GH_BINARY: "gh";
6
6
  export declare const MERGE_STRATEGIES: readonly ["squash", "merge", "rebase"];
7
+ export declare const REVIEW_EVENTS: readonly ["comment", "approve", "request-changes"];
8
+ export declare const DEFAULT_REVIEW_EVENT: "comment";
7
9
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/gh-tool/config.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,EAAG,QAAiB,CAAC;AACxD,eAAO,MAAM,qBAAqB,EAAG,IAAa,CAAC;AACnD,eAAO,MAAM,yBAAyB,EAAG,MAAgB,CAAC;AAC1D,eAAO,MAAM,iBAAiB,EAAG,GAAY,CAAC;AAC9C,eAAO,MAAM,SAAS,EAAG,IAAa,CAAC;AAEvC,eAAO,MAAM,gBAAgB,wCAAyC,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/gh-tool/config.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,EAAG,QAAiB,CAAC;AACxD,eAAO,MAAM,qBAAqB,EAAG,IAAa,CAAC;AACnD,eAAO,MAAM,yBAAyB,EAAG,MAAgB,CAAC;AAC1D,eAAO,MAAM,iBAAiB,EAAG,GAAY,CAAC;AAC9C,eAAO,MAAM,SAAS,EAAG,IAAa,CAAC;AAEvC,eAAO,MAAM,gBAAgB,wCAAyC,CAAC;AAEvE,eAAO,MAAM,aAAa,oDAAqD,CAAC;AAChF,eAAO,MAAM,oBAAoB,EAAG,SAAkB,CAAC"}
@@ -340,9 +340,21 @@ export declare const prResolveCommand: Command.Command<"resolve", {
340
340
  readonly threadId: string;
341
341
  readonly repo: Option.Option<string>;
342
342
  }, {}, GitHubCommandError | import("#gh/errors").GitHubNotFoundError | import("#gh/errors").GitHubAuthError, GitHubService>;
343
+ export declare const prReviewCommand: Command.Command<"review", {
344
+ readonly body: Option.Option<string>;
345
+ readonly bodyFile: Option.Option<string>;
346
+ readonly bodyStdin: boolean;
347
+ readonly confirm: boolean;
348
+ readonly event: "approve" | "comment" | "request-changes";
349
+ readonly format: "json" | "toon";
350
+ readonly pr: Option.Option<number>;
351
+ readonly repo: Option.Option<string>;
352
+ }, {}, GitHubCommandError | import("#gh/errors").GitHubNotFoundError | import("#gh/errors").GitHubAuthError, GitHubService>;
343
353
  export declare const prSubmitReviewCommand: Command.Command<"submit-review", {
344
354
  readonly body: Option.Option<string>;
345
355
  readonly bodyFile: Option.Option<string>;
356
+ readonly confirm: boolean;
357
+ readonly event: "approve" | "comment" | "request-changes";
346
358
  readonly format: "json" | "toon";
347
359
  readonly pr: Option.Option<number>;
348
360
  readonly repo: Option.Option<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAW,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,WAAW,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA+FhD,eAAO,MAAM,cAAc,GAAI,WAAW,MAAM,4FAM/C,CAAC;AAiCF,eAAO,MAAM,aAAa,GAAI,IAAI,MAAM,EAAE,WAAW,MAAM;;;;;;uHA6BvD,CAAC;AAEL,KAAK,mBAAmB,GAAG;IACzB,QAAQ,CAAC,6BAA6B,EAAE,MAAM,CAAC;IAC/C,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,4BAA4B,EAAE,MAAM,CAAC;CAC/C,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAChC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,qBAAqB,CAAC;IACjD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,SAAS,mBAAmB,EAC5B,QAAQ,SAAS,WAAW,EAAE,KAC7B,0BAQF,CAAC;AAIF,eAAO,MAAM,cAAc,GACzB,OAAO,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,kBAAkB,CAkBrD,CAAC;AA8BF,eAAO,MAAM,mBAAmB,GAC9B,IAAI,MAAM,GAAG,IAAI,EACjB,gBAAgB,OAAO,EACvB,iBAAiB,OAAO,2KAMgB,CAAC;AAE3C,eAAO,MAAM,oBAAoB,GAAI,IAAI,MAAM,GAAG,IAAI,EAAE,OAAO,MAAM,GAAG,IAAI,4KAIjC,CAAC;AAE5C,eAAO,MAAM,mBAAmB,GAC9B,IAAI,MAAM,GAAG,IAAI,EACjB,QAAQ,MAAM,GAAG,IAAI,EACrB,cAAc,MAAM,GAAG,IAAI,EAC3B,OAAO,MAAM,GAAG,IAAI,gLAMoB,CAAC;AAE3C,eAAO,MAAM,oBAAoB,GAAI,IAAI,MAAM,GAAG,IAAI;;;;;uHAIX,CAAC;AAK5C,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,MACgB,CAAC;AAE9D,eAAO,MAAM,gBAAgB,uEAKnB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,KAAK,iBAAiB,GAAG;IACvB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1F,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAC9B,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC,CAAC;IACH,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC;QACrC,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC,CAAC;IACH,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjG,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,iBAAiB,EACxD,UAAU,CAAC,EACX,SAAS;IACP,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,SAAS,EAAE,OAAO,CAAC;CACpB;;;;;;;;;gBAxByC,MAAM;cAAQ,MAAM;wBAAkB,MAAM;;;mBAEzE,MAAM;cACX,MAAM;wBACI,MAAM;uBACP,OAAO;yBACL,OAAO;;;YAGpB,MAAM;qBACG,MAAM,GAAG,IAAI;gBAClB,MAAM;cACR,MAAM;wBACI,MAAM;;;gBAEwB,MAAM;cAAQ,MAAM;wBAAkB,MAAM;;CA8D7F,CAAC;AAQF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uHAsD5B,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;2HAkCzB,CAAC;AAEF,eAAO,MAAM,eAAe;;;sGAa3B,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;2HA2CzB,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;2HA4BlC,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;2HAsD+C,CAAC;AAE5E,eAAO,MAAM,aAAa;;;;;;;;;2HA0C6D,CAAC;AAExF,eAAO,MAAM,cAAc;;;;;;;2HAwC4D,CAAC;AAExF,eAAO,MAAM,cAAc;;;;;;;qKAkCiE,CAAC;AAE7F,eAAO,MAAM,cAAc;;;;2HAsB1B,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;2HAqE3B,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;2HAyBqC,CAAC;AAExE,eAAO,MAAM,cAAc;;;;;;;yIAkC6D,CAAC;AAEzF,eAAO,MAAM,oBAAoB;;;;;;;2HAoChC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;2HA+BlC,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;2HAiC5B,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;2HAwBkE,CAAC;AAEjG,eAAO,MAAM,0BAA0B;;;;2HAsBtC,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;;2HAyC5B,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;;;2HAgD7B,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;2HAwCqD,CAAC;AAEzF,eAAO,MAAM,4BAA4B;;;;;;2HA8BoC,CAAC;AAE9E,eAAO,MAAM,gBAAgB;;;;;;2HAmC0C,CAAC;AAExE,eAAO,MAAM,0BAA0B;;;;2HAqBtC,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;2HAmCyC,CAAC;AAErE,eAAO,MAAM,gBAAgB;;;;2HAiByC,CAAC;AAYvE,eAAO,MAAM,eAAe;;;;;;;;;2HAkD3B,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;2HAsDjC,CAAC;AAEF,eAAO,MAAM,yBAAyB,6DAI5B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhF,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,QAAQ,CAAC,EACT,MAAM,aAAa,CAAC,MAAM,CAAC;;EAW5B,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;2HAgCjC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;2HAiBsD,CAAC;AAE1F,eAAO,MAAM,0BAA0B;;;;2HAuBtC,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;2HAkDpC,CAAC"}
@@ -1,2 +1,2 @@
1
- export { prChecksCommand, prChecksFailedCommand, prCloseCommand, prCommentCommand, prCommentsCommand, prCreateCommand, prDiscussionSummaryCommand, prEditCommand, prFeedbackCommand, prIssueCommentsCommand, prIssueCommentsLatestCommand, prLastHumanReviewerCommand, prListCommand, prMergeCommand, prReadyCommand, prRequestReviewCommand, prReplyCommand, prRerunChecksCommand, prReplyAndResolveCommand, prResolveCommand, prReviewsCommand, prStatusCommand, prSubmitReviewCommand, prThreadsCommand, prTriggerChecksCommand, prWaitMergeableCommand, prReviewTriageCommand, prReviewTriageBatchCommand, prViewCommand, prWatchCommand, } from "./commands";
1
+ export { prChecksCommand, prChecksFailedCommand, prCloseCommand, prCommentCommand, prCommentsCommand, prCreateCommand, prDiscussionSummaryCommand, prEditCommand, prFeedbackCommand, prIssueCommentsCommand, prIssueCommentsLatestCommand, prLastHumanReviewerCommand, prListCommand, prMergeCommand, prReadyCommand, prRequestReviewCommand, prReplyCommand, prRerunChecksCommand, prReplyAndResolveCommand, prResolveCommand, prReviewCommand, prReviewsCommand, prStatusCommand, prSubmitReviewCommand, prThreadsCommand, prTriggerChecksCommand, prWaitMergeableCommand, prReviewTriageCommand, prReviewTriageBatchCommand, prViewCommand, prWatchCommand, } from "./commands";
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,aAAa,EACb,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,aAAa,EACb,cAAc,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,aAAa,EACb,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,aAAa,EACb,cAAc,GACf,MAAM,YAAY,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { Effect } from "effect";
2
2
  import type { IssueComment, PullRequestReview, ReviewComment, ReviewThread } from "#gh/types";
3
+ import type { REVIEW_EVENTS } from "#gh/config";
3
4
  import { GitHubCommandError } from "#gh/errors";
4
5
  import { GitHubService } from "#gh/service";
5
6
  /**
@@ -77,7 +78,24 @@ export declare const resolveThread: (threadId: string) => Effect.Effect<{
77
78
  resolved: boolean;
78
79
  threadId: string;
79
80
  }, GitHubCommandError | import("#gh/errors").GitHubNotFoundError | import("#gh/errors").GitHubAuthError, GitHubService>;
80
- export declare const submitPendingReview: (pr: number | null, reviewId: string | null, body: string | null) => Effect.Effect<{
81
+ export type ReviewEvent = (typeof REVIEW_EVENTS)[number];
82
+ /**
83
+ * Create and submit a review in one call — the path for a verdict an agent reached from a diff
84
+ * it just read, with no pending review to submit.
85
+ */
86
+ export declare const createReview: (opts: {
87
+ pr: number | null;
88
+ event: ReviewEvent;
89
+ body: string;
90
+ confirm: boolean;
91
+ }) => Effect.Effect<{
92
+ submitted: true;
93
+ pr: number;
94
+ reviewId: number;
95
+ state: string;
96
+ url: string;
97
+ }, GitHubCommandError | import("#gh/errors").GitHubNotFoundError | import("#gh/errors").GitHubAuthError, GitHubService>;
98
+ export declare const submitPendingReview: (pr: number | null, reviewId: string | null, body: string | null, event?: "approve" | "comment" | "request-changes" | undefined, confirm?: any) => Effect.Effect<{
81
99
  submitted: true;
82
100
  reviewId: string;
83
101
  state: string;
@@ -1 +1 @@
1
- {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAEV,YAAY,EAGZ,iBAAiB,EACjB,aAAa,EACb,YAAY,EAEb,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAic5C;;;GAGG;AACH,eAAO,MAAM,YAAY,uQAcvB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa,8OAoCxB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,qPAmC7B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,YAAY,sSA+CvB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;uHAaxB,CAAC;AAEH,eAAO,MAAM,uBAAuB,oOAgBlC,CAAC;AAEH,eAAO,MAAM,gBAAgB,uLA0C3B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;uHA4CjC,CAAC;AAeH;;GAEG;AACH,eAAO,MAAM,cAAc;;;uHA4FzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;uHA0FjC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa;;;uHAWxB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;uHAiD9B,CAAC;AAeH,eAAO,MAAM,sBAAsB;;;;uHA8CjC,CAAC"}
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/pr/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAEV,YAAY,EAGZ,iBAAiB,EACjB,aAAa,EACb,YAAY,EAEb,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAic5C;;;GAGG;AACH,eAAO,MAAM,YAAY,uQAcvB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa,8OAoCxB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,qPAmC7B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,YAAY,sSA+CvB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;uHAaxB,CAAC;AAEH,eAAO,MAAM,uBAAuB,oOAgBlC,CAAC;AAEH,eAAO,MAAM,gBAAgB,uLA0C3B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;uHA4CjC,CAAC;AAeH;;GAEG;AACH,eAAO,MAAM,cAAc;;;uHA4FzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;uHA0FjC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa;;;uHAWxB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAgCzD;;;GAGG;AACH,eAAO,MAAM,YAAY;QACnB,MAAM,GAAG,IAAI;WACV,WAAW;UACZ,MAAM;aACH,OAAO;;;;;;;uHAmDhB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;uHAsD9B,CAAC;AAeH,eAAO,MAAM,sBAAsB;;;;uHA8CjC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/gh-tool/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAY,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpF,OAAO,EAAE,aAAa,EAA4C,MAAM,SAAS,CAAC;AAsDlF,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,OAAO,GAAG,kBAAkB,GAAG,eAAe,GAAG,mBAAmB,CAAC;;oBAKtD,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;wBAChD,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC;yBAC/C,CACnB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,KAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;4BACZ,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,GAAG,SAAS,EAAE,KAAK,CAAC;0BAC1D,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;6BACnC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,kBAAkB,EAAE,CAAC,CAAC;;AAdpD,qBAAa,aAAc,SAAQ,kBAgBF;IAC/B,MAAM,CAAC,QAAQ,CAAC,KAAK,6FAsRnB;CACH"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/gh-tool/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAY,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpF,OAAO,EAAE,aAAa,EAA4C,MAAM,SAAS,CAAC;AA2DlF,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,OAAO,GAAG,kBAAkB,GAAG,eAAe,GAAG,mBAAmB,CAAC;;oBAKtD,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;wBAChD,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC;yBAC/C,CACnB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,KAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;4BACZ,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,GAAG,SAAS,EAAE,KAAK,CAAC;0BAC1D,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;6BACnC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,kBAAkB,EAAE,CAAC,CAAC;;AAdpD,qBAAa,aAAc,SAAQ,kBAgBF;IAC/B,MAAM,CAAC,QAAQ,CAAC,KAAK,6FAsRnB;CACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blogic-cz/agent-tools",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "CLI tools for AI coding agent workflows — GitHub, database, Kubernetes, Azure platform, Azure DevOps, logs, sessions, and audit",
5
5
  "keywords": [
6
6
  "agent",
@@ -5,3 +5,6 @@ export const GRAPHQL_PAGE_SIZE = 100 as const;
5
5
  export const GH_BINARY = "gh" as const;
6
6
 
7
7
  export const MERGE_STRATEGIES = ["squash", "merge", "rebase"] as const;
8
+
9
+ export const REVIEW_EVENTS = ["comment", "approve", "request-changes"] as const;
10
+ export const DEFAULT_REVIEW_EVENT = "comment" as const;
@@ -37,6 +37,7 @@ import {
37
37
  prFeedbackCommand,
38
38
  prReplyCommand,
39
39
  prResolveCommand,
40
+ prReviewCommand,
40
41
  prReviewsCommand,
41
42
  prLastHumanReviewerCommand,
42
43
  prSubmitReviewCommand,
@@ -105,6 +106,7 @@ const prCommand = Command.make("pr", {}).pipe(
105
106
  prDiscussionSummaryCommand,
106
107
  prReplyCommand,
107
108
  prResolveCommand,
109
+ prReviewCommand,
108
110
  prSubmitReviewCommand,
109
111
  prChecksCommand,
110
112
  prChecksFailedCommand,
@@ -199,7 +201,8 @@ WORKFLOW FOR AI AGENTS:
199
201
  1. Use 'pr view' to inspect current PR
200
202
  2. Use 'pr discussion-summary' for overview (counts + latest discussion comment)
201
203
  3. Use 'pr threads' and 'pr issue-comments-latest --author <username> --body-contains "Review"' for review context
202
- 4. Use 'pr submit-review', 'pr reply', 'pr comment' and 'pr resolve' to handle feedback
204
+ 4. Use 'pr reply', 'pr comment' and 'pr resolve' to handle feedback
205
+ 4b. Use 'pr review --event request-changes|approve|comment --confirm' to post a verdict, or 'pr submit-review' for a pending one
203
206
  5. Use 'pr checks' to monitor CI status; 'pr trigger-checks --workflow <file.yml>' when zero checks were reported
204
207
  6. Use 'pr merge' to merge (dry-run by default)
205
208
  7. Use 'issue list' to list open/closed issues
@@ -24,7 +24,9 @@ import {
24
24
  CI_CHECK_WATCH_TIMEOUT_MS,
25
25
  DEFAULT_DELETE_BRANCH,
26
26
  DEFAULT_MERGE_STRATEGY,
27
+ DEFAULT_REVIEW_EVENT,
27
28
  MERGE_STRATEGIES,
29
+ REVIEW_EVENTS,
28
30
  } from "#gh/config";
29
31
 
30
32
  import {
@@ -47,6 +49,7 @@ import {
47
49
  waitForMergeable,
48
50
  } from "./core";
49
51
  import {
52
+ createReview,
50
53
  fetchComments,
51
54
  fetchDiscussionSummary,
52
55
  fetchFeedback,
@@ -1336,6 +1339,68 @@ export const prResolveCommand = Command.make(
1336
1339
  ),
1337
1340
  ).pipe(Command.withDescription("Resolve a review thread via GraphQL"));
1338
1341
 
1342
+ const reviewEventOption = Flag.choice("event", REVIEW_EVENTS).pipe(
1343
+ Flag.withDescription("Review verdict: comment, approve, or request-changes"),
1344
+ Flag.withDefault(DEFAULT_REVIEW_EVENT),
1345
+ );
1346
+
1347
+ const reviewConfirmOption = Flag.boolean("confirm").pipe(
1348
+ Flag.withDescription("Required for --event approve and --event request-changes"),
1349
+ Flag.withDefault(false),
1350
+ );
1351
+
1352
+ export const prReviewCommand = Command.make(
1353
+ "review",
1354
+ {
1355
+ body: Flag.string("body").pipe(Flag.withDescription("Review body text"), Flag.optional),
1356
+ bodyFile: Flag.string("body-file").pipe(
1357
+ Flag.withDescription("Read review body from a file path or '-' for stdin"),
1358
+ Flag.optional,
1359
+ ),
1360
+ bodyStdin: Flag.boolean("body-stdin").pipe(
1361
+ Flag.withDescription("Read review body from stdin"),
1362
+ Flag.withDefault(false),
1363
+ ),
1364
+ confirm: reviewConfirmOption,
1365
+ event: reviewEventOption,
1366
+ format: formatOption,
1367
+ pr: Flag.integer("pr").pipe(
1368
+ Flag.withDescription("PR number (default: current branch PR)"),
1369
+ Flag.optional,
1370
+ ),
1371
+ repo: repoOption,
1372
+ },
1373
+ ({ body, bodyFile, bodyStdin, confirm, event, format, pr, repo }) =>
1374
+ withRepo(
1375
+ repo,
1376
+ Effect.gen(function* () {
1377
+ const resolvedBody = yield* resolveDefaultTextInput({
1378
+ command: "gh-tool pr review",
1379
+ value: Option.getOrNull(body),
1380
+ fileValue: Option.getOrNull(bodyFile),
1381
+ stdin: bodyStdin,
1382
+ valueFlag: "--body",
1383
+ fileFlag: "--body-file",
1384
+ stdinFlag: "--body-stdin",
1385
+ label: "body",
1386
+ defaultValue: "",
1387
+ });
1388
+
1389
+ const result = yield* createReview({
1390
+ pr: Option.getOrNull(pr),
1391
+ event,
1392
+ body: resolvedBody,
1393
+ confirm,
1394
+ });
1395
+ yield* logFormatted(result, format);
1396
+ }),
1397
+ ),
1398
+ ).pipe(
1399
+ Command.withDescription(
1400
+ "Create and submit a review (--event comment, approve, or request-changes; verdicts need --confirm)",
1401
+ ),
1402
+ );
1403
+
1339
1404
  export const prSubmitReviewCommand = Command.make(
1340
1405
  "submit-review",
1341
1406
  {
@@ -1347,6 +1412,8 @@ export const prSubmitReviewCommand = Command.make(
1347
1412
  Flag.withDescription("Read review body from a file path or '-' for stdin"),
1348
1413
  Flag.optional,
1349
1414
  ),
1415
+ confirm: reviewConfirmOption,
1416
+ event: reviewEventOption,
1350
1417
  format: formatOption,
1351
1418
  pr: Flag.integer("pr").pipe(
1352
1419
  Flag.withDescription("PR number (default: current branch PR)"),
@@ -1360,7 +1427,7 @@ export const prSubmitReviewCommand = Command.make(
1360
1427
  Flag.optional,
1361
1428
  ),
1362
1429
  },
1363
- ({ body, bodyFile, format, pr, repo, reviewId }) =>
1430
+ ({ body, bodyFile, confirm, event, format, pr, repo, reviewId }) =>
1364
1431
  withRepo(
1365
1432
  repo,
1366
1433
  Effect.gen(function* () {
@@ -1374,13 +1441,19 @@ export const prSubmitReviewCommand = Command.make(
1374
1441
  fileFlag: "--body-file",
1375
1442
  label: "body",
1376
1443
  });
1377
- const result = yield* submitPendingReview(prNumber, reviewIdValue, bodyValue);
1444
+ const result = yield* submitPendingReview(
1445
+ prNumber,
1446
+ reviewIdValue,
1447
+ bodyValue,
1448
+ event,
1449
+ confirm,
1450
+ );
1378
1451
  yield* logFormatted(result, format);
1379
1452
  }),
1380
1453
  ),
1381
1454
  ).pipe(
1382
1455
  Command.withDescription(
1383
- "Submit a pending review as COMMENT (auto-detects your pending review if --review-id is omitted)",
1456
+ "Submit a pending review (--event comment by default; verdicts need --confirm; auto-detects your pending review if --review-id is omitted)",
1384
1457
  ),
1385
1458
  );
1386
1459
 
@@ -19,6 +19,7 @@ export {
19
19
  prRerunChecksCommand,
20
20
  prReplyAndResolveCommand,
21
21
  prResolveCommand,
22
+ prReviewCommand,
22
23
  prReviewsCommand,
23
24
  prStatusCommand,
24
25
  prSubmitReviewCommand,
@@ -11,6 +11,8 @@ import type {
11
11
  FeedbackOrigin,
12
12
  } from "#gh/types";
13
13
 
14
+ import type { REVIEW_EVENTS } from "#gh/config";
15
+
14
16
  import { GitHubCommandError } from "#gh/errors";
15
17
  import { GitHubService } from "#gh/service";
16
18
 
@@ -967,12 +969,110 @@ export const resolveThread = Effect.fn("pr.resolveThread")(function* (threadId:
967
969
  };
968
970
  });
969
971
 
972
+ export type ReviewEvent = (typeof REVIEW_EVENTS)[number];
973
+
974
+ const REVIEW_EVENT_API = {
975
+ approve: "APPROVE",
976
+ comment: "COMMENT",
977
+ "request-changes": "REQUEST_CHANGES",
978
+ } as const satisfies Record<ReviewEvent, string>;
979
+
980
+ // APPROVE and REQUEST_CHANGES change whether the PR can merge, so they need the same explicit
981
+ // opt-in as `pr merge`. COMMENT carries no verdict and stays free.
982
+ const requireVerdictConfirm = Effect.fn("pr.requireVerdictConfirm")(function* (opts: {
983
+ command: string;
984
+ event: ReviewEvent;
985
+ confirm: boolean;
986
+ }) {
987
+ if (opts.event === "comment" || opts.confirm) {
988
+ return;
989
+ }
990
+
991
+ const detail = `--event ${opts.event} posts a verdict review; pass --confirm to submit it`;
992
+
993
+ return yield* Effect.fail(
994
+ new GitHubCommandError({
995
+ command: opts.command,
996
+ exitCode: 1,
997
+ stderr: detail,
998
+ message: detail,
999
+ hint: "APPROVE and REQUEST_CHANGES change the merge state of the PR. Re-run with --confirm once the verdict is intended.",
1000
+ }),
1001
+ );
1002
+ });
1003
+
1004
+ /**
1005
+ * Create and submit a review in one call — the path for a verdict an agent reached from a diff
1006
+ * it just read, with no pending review to submit.
1007
+ */
1008
+ export const createReview = Effect.fn("pr.createReview")(function* (opts: {
1009
+ pr: number | null;
1010
+ event: ReviewEvent;
1011
+ body: string;
1012
+ confirm: boolean;
1013
+ }) {
1014
+ const service = yield* GitHubService;
1015
+ const command = "gh-tool pr review";
1016
+
1017
+ yield* requireVerdictConfirm({ command, event: opts.event, confirm: opts.confirm });
1018
+
1019
+ // GitHub rejects a bodyless COMMENT or REQUEST_CHANGES review; only APPROVE may be silent.
1020
+ if (opts.event !== "approve" && opts.body.trim() === "") {
1021
+ const detail = `--event ${opts.event} requires a non-empty body`;
1022
+
1023
+ return yield* Effect.fail(
1024
+ new GitHubCommandError({
1025
+ command,
1026
+ exitCode: 1,
1027
+ stderr: detail,
1028
+ message: detail,
1029
+ hint: "Pass --body, --body-file, or --body-stdin with what has to change.",
1030
+ }),
1031
+ );
1032
+ }
1033
+
1034
+ const repoInfo = yield* service.getRepoInfo();
1035
+ const resolvedPr = opts.pr ?? (yield* viewPR(null)).number;
1036
+
1037
+ const args = [
1038
+ "api",
1039
+ "--method",
1040
+ "POST",
1041
+ `repos/${repoInfo.owner}/${repoInfo.name}/pulls/${resolvedPr}/reviews`,
1042
+ "-f",
1043
+ `event=${REVIEW_EVENT_API[opts.event]}`,
1044
+ ];
1045
+
1046
+ if (opts.body !== "") {
1047
+ args.push("-f", `body=${opts.body}`);
1048
+ }
1049
+
1050
+ const result = yield* service.runGhJson<{
1051
+ id: number;
1052
+ state: string;
1053
+ html_url: string;
1054
+ }>(args);
1055
+
1056
+ return {
1057
+ submitted: true as const,
1058
+ pr: resolvedPr,
1059
+ reviewId: result.id,
1060
+ state: result.state,
1061
+ url: result.html_url,
1062
+ };
1063
+ });
1064
+
970
1065
  export const submitPendingReview = Effect.fn("pr.submitPendingReview")(function* (
971
1066
  pr: number | null,
972
1067
  reviewId: string | null,
973
1068
  body: string | null,
1069
+ event: ReviewEvent = "comment",
1070
+ confirm = false,
974
1071
  ) {
975
1072
  const service = yield* GitHubService;
1073
+
1074
+ yield* requireVerdictConfirm({ command: "gh-tool pr submit-review", event, confirm });
1075
+
976
1076
  const repoInfo = yield* service.getRepoInfo();
977
1077
 
978
1078
  const resolvedPr = pr ?? (yield* viewPR(null)).number;
@@ -1007,7 +1107,7 @@ export const submitPendingReview = Effect.fn("pr.submitPendingReview")(function*
1007
1107
 
1008
1108
  const result = (yield* service.runGraphQL(SUBMIT_REVIEW_MUTATION, {
1009
1109
  reviewId: targetReviewId,
1010
- event: "COMMENT",
1110
+ event: REVIEW_EVENT_API[event],
1011
1111
  body: body ?? "",
1012
1112
  })) as SubmitReviewResult;
1013
1113
 
@@ -34,6 +34,11 @@ const KNOWN_STDERR_HINTS: ReadonlyArray<{
34
34
  re: /already exists/i,
35
35
  hint: "The resource already exists. Fetch the existing one and update it instead of creating another.",
36
36
  },
37
+ {
38
+ re: /Can not (?:approve|request changes on) your own pull request/i,
39
+ hint: "GitHub refuses a verdict review on your own PR. Post the findings with --event comment, or have the reviewing account submit the verdict.",
40
+ nextCommand: "agent-tools-gh pr review --pr <number> --event comment --body <text>",
41
+ },
37
42
  {
38
43
  re: /pending review/i,
39
44
  hint: "A pending (unsubmitted) review blocks this mutation. Inspect its contents and submit or discard it before retrying.",