@blogic-cz/agent-tools 0.8.18 → 0.10.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blogic-cz/agent-tools",
3
- "version": "0.8.18",
3
+ "version": "0.10.0",
4
4
  "description": "CLI tools for AI coding agent workflows — GitHub, database, Kubernetes, Azure DevOps, logs, sessions, and audit",
5
5
  "keywords": [
6
6
  "agent",
@@ -0,0 +1,91 @@
1
+ import { Command, Flag } from "effect/unstable/cli";
2
+ import { Effect, Option } from "effect";
3
+
4
+ import { formatOption, logFormatted } from "#shared";
5
+ import type { BranchRenameResult } from "./types";
6
+ import { GitHubService } from "./service";
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // Internal handlers
10
+ // ---------------------------------------------------------------------------
11
+
12
+ export const renameBranch = Effect.fn("branch.renameBranch")(function* (opts: {
13
+ oldName: string;
14
+ newName: string;
15
+ confirm: boolean;
16
+ repo: string | null;
17
+ }) {
18
+ const gh = yield* GitHubService;
19
+
20
+ if (!opts.confirm) {
21
+ const scope = opts.repo !== null ? ` in ${opts.repo}` : "";
22
+
23
+ const dryRun: BranchRenameResult = {
24
+ renamed: false,
25
+ oldName: opts.oldName,
26
+ newName: opts.newName,
27
+ dryRun: true,
28
+ message: `Dry run: would rename branch '${opts.oldName}' to '${opts.newName}'${scope}. Re-run with --confirm to execute.`,
29
+ };
30
+
31
+ return dryRun;
32
+ }
33
+
34
+ const repoInfo =
35
+ opts.repo !== null
36
+ ? opts.repo
37
+ : yield* gh.getRepoInfo().pipe(Effect.map((r) => `${r.owner}/${r.name}`));
38
+
39
+ const args = [
40
+ "api",
41
+ `repos/${repoInfo}/branches/${encodeURIComponent(opts.oldName)}/rename`,
42
+ "-X",
43
+ "POST",
44
+ "-f",
45
+ `new_name=${opts.newName}`,
46
+ ];
47
+
48
+ yield* gh.runGh(args);
49
+
50
+ const result: BranchRenameResult = {
51
+ renamed: true,
52
+ oldName: opts.oldName,
53
+ newName: opts.newName,
54
+ };
55
+
56
+ return result;
57
+ });
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // CLI Commands
61
+ // ---------------------------------------------------------------------------
62
+
63
+ export const branchRenameCommand = Command.make(
64
+ "rename",
65
+ {
66
+ confirm: Flag.boolean("confirm").pipe(
67
+ Flag.withDescription("Actually rename (without this flag, only shows dry-run)"),
68
+ Flag.withDefault(false),
69
+ ),
70
+ format: formatOption,
71
+ newName: Flag.string("new-name").pipe(Flag.withDescription("New branch name")),
72
+ oldName: Flag.string("old-name").pipe(Flag.withDescription("Current branch name to rename")),
73
+ repo: Flag.string("repo").pipe(
74
+ Flag.withDescription("Target repository (owner/name). Defaults to current repo"),
75
+ Flag.optional,
76
+ ),
77
+ },
78
+ ({ confirm, format, newName, oldName, repo }) =>
79
+ Effect.gen(function* () {
80
+ const result = yield* renameBranch({
81
+ oldName,
82
+ newName,
83
+ confirm,
84
+ repo: Option.getOrNull(repo),
85
+ });
86
+
87
+ yield* logFormatted(result, format);
88
+ }),
89
+ ).pipe(
90
+ Command.withDescription("Rename a GitHub branch (dry-run by default, use --confirm to execute)"),
91
+ );
@@ -20,6 +20,7 @@ import {
20
20
  prViewCommand,
21
21
  prStatusCommand,
22
22
  prCreateCommand,
23
+ prCloseCommand,
23
24
  prEditCommand,
24
25
  prMergeCommand,
25
26
  prThreadsCommand,
@@ -37,6 +38,7 @@ import {
37
38
  prReplyAndResolveCommand,
38
39
  prReviewTriageCommand,
39
40
  } from "./pr/index";
41
+ import { branchRenameCommand } from "./branch";
40
42
  import {
41
43
  releaseCreateCommand,
42
44
  releaseDeleteCommand,
@@ -65,6 +67,7 @@ const prCommand = Command.make("pr", {}).pipe(
65
67
  prViewCommand,
66
68
  prStatusCommand,
67
69
  prCreateCommand,
70
+ prCloseCommand,
68
71
  prEditCommand,
69
72
  prMergeCommand,
70
73
  prThreadsCommand,
@@ -100,6 +103,11 @@ const issueCommand = Command.make("issue", {}).pipe(
100
103
  ]),
101
104
  );
102
105
 
106
+ const branchCommand = Command.make("branch", {}).pipe(
107
+ Command.withDescription("Branch operations (rename)"),
108
+ Command.withSubcommands([branchRenameCommand]),
109
+ );
110
+
103
111
  const repoCommand = Command.make("repo", {}).pipe(
104
112
  Command.withDescription("Repository operations"),
105
113
  Command.withSubcommands([repoInfoCommand, repoListCommand, repoSearchCodeCommand]),
@@ -162,9 +170,17 @@ WORKFLOW FOR AI AGENTS:
162
170
  18. Use 'workflow watch --run N' to watch until completion
163
171
  19. Use 'release status' to inspect latest release + repository context
164
172
  20. Use 'release create --tag vX.Y.Z --generate-notes' to publish a release
165
- 21. Use 'release edit/view/list/delete' to maintain existing releases`,
173
+ 21. Use 'release edit/view/list/delete' to maintain existing releases
174
+ 22. Use 'branch rename --old-name X --new-name Y --confirm' to rename a branch`,
166
175
  ),
167
- Command.withSubcommands([prCommand, issueCommand, repoCommand, workflowCommand, releaseCommand]),
176
+ Command.withSubcommands([
177
+ prCommand,
178
+ issueCommand,
179
+ repoCommand,
180
+ branchCommand,
181
+ workflowCommand,
182
+ releaseCommand,
183
+ ]),
168
184
  );
169
185
 
170
186
  const cli = Command.run(mainCommand, {
@@ -17,6 +17,7 @@ import {
17
17
  } from "#gh/config";
18
18
 
19
19
  import {
20
+ closePR,
20
21
  createPR,
21
22
  detectPRStatus,
22
23
  editPR,
@@ -147,6 +148,44 @@ export const prEditCommand = Command.make(
147
148
  }),
148
149
  ).pipe(Command.withDescription("Edit an existing PR's title, body, or other metadata"));
149
150
 
151
+ export const prCloseCommand = Command.make(
152
+ "close",
153
+ {
154
+ comment: Flag.string("comment").pipe(
155
+ Flag.withDescription("Comment to add when closing"),
156
+ Flag.optional,
157
+ ),
158
+ commentFile: Flag.string("comment-file").pipe(
159
+ Flag.withDescription("Read close comment from a file path or '-' for stdin"),
160
+ Flag.optional,
161
+ ),
162
+ deleteBranch: Flag.boolean("delete-branch").pipe(
163
+ Flag.withDescription("Delete the branch after closing"),
164
+ Flag.withDefault(false),
165
+ ),
166
+ format: formatOption,
167
+ pr: Flag.integer("pr").pipe(Flag.withDescription("PR number to close")),
168
+ },
169
+ ({ comment, commentFile, deleteBranch, format, pr }) =>
170
+ Effect.gen(function* () {
171
+ const resolvedComment = yield* resolveOptionalTextInput(
172
+ "gh-tool pr close",
173
+ Option.getOrNull(comment),
174
+ Option.getOrNull(commentFile),
175
+ "--comment",
176
+ "--comment-file",
177
+ "comment",
178
+ );
179
+
180
+ const result = yield* closePR({
181
+ comment: resolvedComment,
182
+ deleteBranch,
183
+ pr,
184
+ });
185
+ yield* logFormatted(result, format);
186
+ }),
187
+ ).pipe(Command.withDescription("Close a PR with optional comment and branch deletion"));
188
+
150
189
  export const prMergeCommand = Command.make(
151
190
  "merge",
152
191
  {
@@ -606,6 +606,28 @@ export const mergePR = Effect.fn("pr.mergePR")(function* (opts: {
606
606
  return result;
607
607
  });
608
608
 
609
+ export const closePR = Effect.fn("pr.closePR")(function* (opts: {
610
+ pr: number;
611
+ comment: string | null;
612
+ deleteBranch: boolean;
613
+ }) {
614
+ const gh = yield* GitHubService;
615
+
616
+ const args = ["pr", "close", String(opts.pr)];
617
+
618
+ if (opts.comment !== null) {
619
+ args.push("--comment", opts.comment);
620
+ }
621
+
622
+ if (opts.deleteBranch) {
623
+ args.push("--delete-branch");
624
+ }
625
+
626
+ yield* gh.runGh(args);
627
+
628
+ return yield* viewPR(opts.pr);
629
+ });
630
+
609
631
  export const editPR = Effect.fn("pr.editPR")(function* (opts: {
610
632
  pr: number;
611
633
  title: string | null;
@@ -1,6 +1,7 @@
1
1
  export {
2
2
  prChecksCommand,
3
3
  prChecksFailedCommand,
4
+ prCloseCommand,
4
5
  prCommentCommand,
5
6
  prCommentsCommand,
6
7
  prCreateCommand,
@@ -159,6 +159,14 @@ export type PRStatusNone = {
159
159
 
160
160
  export type PRStatusResult = PRStatusSingle | PRStatusMultiple | PRStatusNone;
161
161
 
162
+ export type BranchRenameResult = {
163
+ renamed: boolean;
164
+ oldName: string;
165
+ newName: string;
166
+ dryRun?: true;
167
+ message?: string;
168
+ };
169
+
162
170
  export type CheckRunAnnotation = {
163
171
  path: string;
164
172
  start_line: number;