@blogic-cz/agent-tools 1.5.3 → 1.5.5

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.
Files changed (51) hide show
  1. package/README.md +7 -6
  2. package/dist/audit-tool/main.d.ts +3 -0
  3. package/dist/audit-tool/main.d.ts.map +1 -0
  4. package/dist/az-tool/main.d.ts +3 -0
  5. package/dist/az-tool/main.d.ts.map +1 -0
  6. package/dist/azdo-tool/main.d.ts +3 -0
  7. package/dist/azdo-tool/main.d.ts.map +1 -0
  8. package/dist/credential-guard/index.d.ts.map +1 -1
  9. package/dist/db-tool/main.d.ts +3 -0
  10. package/dist/db-tool/main.d.ts.map +1 -0
  11. package/dist/gh-tool/main.d.ts +3 -0
  12. package/dist/gh-tool/main.d.ts.map +1 -0
  13. package/dist/gh-tool/pr/core.d.ts.map +1 -1
  14. package/dist/gh-tool/workflow.d.ts.map +1 -1
  15. package/dist/k8s-tool/main.d.ts +3 -0
  16. package/dist/k8s-tool/main.d.ts.map +1 -0
  17. package/dist/logs-tool/index.d.ts +1 -19
  18. package/dist/logs-tool/index.d.ts.map +1 -1
  19. package/dist/logs-tool/main.d.ts +21 -0
  20. package/dist/logs-tool/main.d.ts.map +1 -0
  21. package/dist/observability-tool/main.d.ts +3 -0
  22. package/dist/observability-tool/main.d.ts.map +1 -0
  23. package/dist/session-tool/index.d.ts +1 -11
  24. package/dist/session-tool/index.d.ts.map +1 -1
  25. package/dist/session-tool/main.d.ts +13 -0
  26. package/dist/session-tool/main.d.ts.map +1 -0
  27. package/dist/shared/effect-version.d.ts +4 -0
  28. package/dist/shared/effect-version.d.ts.map +1 -0
  29. package/package.json +2 -2
  30. package/src/audit-tool/index.ts +3 -109
  31. package/src/audit-tool/main.ts +111 -0
  32. package/src/az-tool/index.ts +3 -151
  33. package/src/az-tool/main.ts +153 -0
  34. package/src/azdo-tool/index.ts +3 -220
  35. package/src/azdo-tool/main.ts +222 -0
  36. package/src/credential-guard/index.ts +570 -96
  37. package/src/db-tool/index.ts +3 -260
  38. package/src/db-tool/main.ts +262 -0
  39. package/src/gh-tool/index.ts +3 -256
  40. package/src/gh-tool/main.ts +258 -0
  41. package/src/gh-tool/pr/core.ts +52 -2
  42. package/src/gh-tool/workflow.ts +1 -0
  43. package/src/k8s-tool/index.ts +3 -487
  44. package/src/k8s-tool/main.ts +489 -0
  45. package/src/logs-tool/index.ts +3 -247
  46. package/src/logs-tool/main.ts +249 -0
  47. package/src/observability-tool/index.ts +3 -34
  48. package/src/observability-tool/main.ts +36 -0
  49. package/src/session-tool/index.ts +3 -337
  50. package/src/session-tool/main.ts +339 -0
  51. package/src/shared/effect-version.ts +32 -0
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env bun
2
+ import { Command, Flag } from "effect/unstable/cli";
3
+ import { BunRuntime, BunServices } from "@effect/platform-bun";
4
+ import { Effect, Layer, Option } from "effect";
5
+
6
+ import {
7
+ makeSchemaCommand,
8
+ formatAny,
9
+ formatOption,
10
+ logText,
11
+ renderCauseToStderr,
12
+ VERSION,
13
+ } from "#shared";
14
+ import { AuditServiceLayer, withAudit } from "#shared/audit";
15
+ import { AzService, AzServiceLayer } from "./service";
16
+ import { ConfigServiceLayer } from "#config";
17
+
18
+ const profileFlag = Flag.optional(Flag.String("profile")).pipe(
19
+ Flag.withDescription("Azure platform profile name (from agent-tools config)"),
20
+ );
21
+
22
+ const commonFlags = {
23
+ format: formatOption,
24
+ profile: profileFlag,
25
+ };
26
+
27
+ /** Run a fixed read-only command through the same security gate as `cmd`. */
28
+ const runFixed = (cmd: string, profile: Option.Option<string>, format: "toon" | "json") =>
29
+ Effect.gen(function* () {
30
+ const az = yield* AzService;
31
+ const result = yield* az.runCommand(cmd, Option.getOrUndefined(profile));
32
+ yield* logText(formatAny(result.data, format));
33
+ });
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Typed subcommands
37
+ // ---------------------------------------------------------------------------
38
+
39
+ const subscriptionCommand = Command.make("subscription", commonFlags, ({ format, profile }) =>
40
+ runFixed("account show", profile, format),
41
+ ).pipe(Command.withDescription("Show the subscription every command in this profile is pinned to"));
42
+
43
+ const groupsCommand = Command.make("groups", commonFlags, ({ format, profile }) =>
44
+ runFixed("group list", profile, format),
45
+ ).pipe(Command.withDescription("List resource groups in the pinned subscription"));
46
+
47
+ const resourcesCommand = Command.make(
48
+ "resources",
49
+ {
50
+ ...commonFlags,
51
+ group: Flag.optional(Flag.String("group")).pipe(
52
+ Flag.withDescription("Limit the listing to one resource group"),
53
+ ),
54
+ },
55
+ ({ format, group, profile }) =>
56
+ Effect.gen(function* () {
57
+ const groupName = Option.getOrUndefined(group);
58
+ const cmd = groupName ? `resource list --resource-group ${groupName}` : "resource list";
59
+ yield* runFixed(cmd, profile, format);
60
+ }),
61
+ ).pipe(Command.withDescription("List resources, optionally scoped to one resource group"));
62
+
63
+ // ---------------------------------------------------------------------------
64
+ // Raw command passthrough
65
+ // ---------------------------------------------------------------------------
66
+
67
+ const cmdCommand = Command.make(
68
+ "cmd",
69
+ {
70
+ ...commonFlags,
71
+ cmd: Flag.String("cmd").pipe(Flag.withDescription("az command (without the 'az' prefix)")),
72
+ dryRun: Flag.Boolean("dry-run").pipe(
73
+ Flag.withDescription("Show the command that would run, after security checks"),
74
+ Flag.withDefault(false),
75
+ ),
76
+ },
77
+ ({ cmd, dryRun, format, profile }) =>
78
+ Effect.gen(function* () {
79
+ const az = yield* AzService;
80
+ const profileName = Option.getOrUndefined(profile);
81
+
82
+ if (dryRun) {
83
+ const rendered = yield* az.renderCommand(cmd, profileName);
84
+ yield* logText(`[DRY-RUN] Would execute: ${rendered}`);
85
+ return;
86
+ }
87
+
88
+ const result = yield* az.runCommand(cmd, profileName);
89
+ yield* logText(formatAny(result.data, format));
90
+ }),
91
+ ).pipe(
92
+ Command.withDescription(
93
+ `Execute a read-only Azure platform command.
94
+
95
+ The subscription is pinned by the selected profile — passing --subscription is rejected.
96
+ Mutating verbs, unknown verbs, credential reads, and shell syntax are all blocked.
97
+
98
+ EXAMPLES:
99
+ az-tool cmd --cmd "vm list"
100
+ az-tool cmd --cmd "webapp show --name my-app --resource-group my-rg"
101
+ az-tool cmd --cmd "aks list --query \\"[].{name:name,version:kubernetesVersion}\\""
102
+ az-tool cmd --cmd "storage account list" --profile prod --dry-run`,
103
+ ),
104
+ );
105
+
106
+ // ---------------------------------------------------------------------------
107
+ // Main command
108
+ // ---------------------------------------------------------------------------
109
+
110
+ const commandsCommand = makeSchemaCommand(() => mainCommand);
111
+
112
+ const mainCommand = Command.make("az-tool", {}).pipe(
113
+ Command.withDescription(
114
+ `Azure Platform Tool for Coding Agents (READ-ONLY)
115
+
116
+ Inspects Azure PaaS resources — vm, webapp, storage, aks, acr, monitor, and the rest.
117
+ For Azure DevOps pipelines, builds, and repos use azdo-tool instead.
118
+
119
+ Typed subcommands:
120
+ az-tool subscription
121
+ az-tool groups
122
+ az-tool resources --group my-rg
123
+
124
+ Raw az wrapper:
125
+ az-tool cmd --cmd "webapp list"`,
126
+ ),
127
+ Command.withSubcommands([
128
+ subscriptionCommand,
129
+ groupsCommand,
130
+ resourcesCommand,
131
+ cmdCommand,
132
+ commandsCommand,
133
+ ]),
134
+ );
135
+
136
+ const cli = Command.run(mainCommand, {
137
+ version: VERSION,
138
+ });
139
+
140
+ const MainLayer = AzServiceLayer.pipe(
141
+ Layer.provideMerge(ConfigServiceLayer),
142
+ Layer.provideMerge(BunServices.layer),
143
+ Layer.provideMerge(AuditServiceLayer),
144
+ );
145
+
146
+ const program = withAudit("az", cli).pipe(
147
+ Effect.provide(MainLayer),
148
+ Effect.tapCause(renderCauseToStderr),
149
+ );
150
+
151
+ BunRuntime.runMain(program, {
152
+ disableErrorReporting: true,
153
+ });
@@ -1,222 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { Command, Flag } from "effect/unstable/cli";
3
- import { BunRuntime, BunServices } from "@effect/platform-bun";
4
- import { Effect, Layer, Option } from "effect";
2
+ import { checkEffectVersion } from "#shared/effect-version";
5
3
 
6
- import {
7
- makeSchemaCommand,
8
- formatAny,
9
- formatOption,
10
- formatOutput,
11
- logText,
12
- renderCauseToStderr,
13
- VERSION,
14
- } from "#shared";
15
- import { AuditServiceLayer, withAudit } from "#shared/audit";
16
- import {
17
- findFailedJobs,
18
- getBuildJobSummary,
19
- getBuildLogContent,
20
- getBuildLogs,
21
- getBuildTimeline,
22
- } from "./build";
23
- import { AzdoService, AzdoServiceLayer } from "./service";
24
- import { ConfigServiceLayer } from "#config";
25
-
26
- // ---------------------------------------------------------------------------
27
- // Common flags shared across build subcommands
28
- // ---------------------------------------------------------------------------
29
-
30
- const commonBuildFlags = {
31
- format: formatOption,
32
- profile: Flag.optional(Flag.String("profile")).pipe(
33
- Flag.withDescription("Azure DevOps profile name (from agent-tools config)"),
34
- ),
35
- };
36
-
37
- // ---------------------------------------------------------------------------
38
- // Build subcommands
39
- // ---------------------------------------------------------------------------
40
-
41
- const buildTimelineCommand = Command.make(
42
- "timeline",
43
- {
44
- ...commonBuildFlags,
45
- buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
46
- },
47
- ({ buildId, format, profile: _profile }) =>
48
- Effect.gen(function* () {
49
- const result = yield* getBuildTimeline(buildId);
50
- yield* logText(formatAny(result, format));
51
- }),
52
- ).pipe(Command.withDescription("Get build timeline with all records (jobs, stages, tasks)"));
53
-
54
- const buildFailedJobsCommand = Command.make(
55
- "failed-jobs",
56
- {
57
- ...commonBuildFlags,
58
- buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
59
- },
60
- ({ buildId, format, profile: _profile }) =>
61
- Effect.gen(function* () {
62
- const failedJobs = yield* findFailedJobs(buildId);
63
- yield* logText(formatAny({ buildId, failedJobs }, format));
64
- }),
65
- ).pipe(Command.withDescription("Find failed or canceled jobs in a build"));
66
-
67
- const buildLogsCommand = Command.make(
68
- "logs",
69
- {
70
- ...commonBuildFlags,
71
- buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
72
- },
73
- ({ buildId, format, profile: _profile }) =>
74
- Effect.gen(function* () {
75
- const result = yield* getBuildLogs(buildId);
76
- yield* logText(formatAny(result, format));
77
- }),
78
- ).pipe(Command.withDescription("Get list of build logs"));
79
-
80
- const buildLogContentCommand = Command.make(
81
- "log-content",
82
- {
83
- ...commonBuildFlags,
84
- buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
85
- logId: Flag.Int("log-id").pipe(Flag.withDescription("Log ID")),
86
- },
87
- ({ buildId, format, logId, profile: _profile }) =>
88
- Effect.gen(function* () {
89
- const content = yield* getBuildLogContent(buildId, logId);
90
- yield* logText(formatAny({ buildId, logId, content }, format));
91
- }),
92
- ).pipe(Command.withDescription("Get specific log content by log ID"));
93
-
94
- const buildSummaryCommand = Command.make(
95
- "summary",
96
- {
97
- ...commonBuildFlags,
98
- buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
99
- },
100
- ({ buildId, format, profile: _profile }) =>
101
- Effect.gen(function* () {
102
- const summary = yield* getBuildJobSummary(buildId);
103
- yield* logText(formatAny({ buildId, summary }, format));
104
- }),
105
- ).pipe(Command.withDescription("Get job summaries with duration and status information"));
106
-
107
- // ---------------------------------------------------------------------------
108
- // Build parent command
109
- // ---------------------------------------------------------------------------
110
-
111
- const buildCommand = Command.make("build", {}).pipe(
112
- Command.withDescription("Build helpers for Azure DevOps pipelines"),
113
- Command.withSubcommands([
114
- buildTimelineCommand,
115
- buildFailedJobsCommand,
116
- buildLogsCommand,
117
- buildLogContentCommand,
118
- buildSummaryCommand,
119
- ]),
120
- );
121
-
122
- // ---------------------------------------------------------------------------
123
- // Raw command subcommand (preserves existing --cmd behavior)
124
- // ---------------------------------------------------------------------------
125
-
126
- const cmdCommand = Command.make(
127
- "cmd",
128
- {
129
- profile: Flag.optional(Flag.String("profile")).pipe(
130
- Flag.withDescription("Azure DevOps profile name (from agent-tools config)"),
131
- ),
132
- project: Flag.optional(Flag.String("project")).pipe(
133
- Flag.withDescription("Azure DevOps project name (overrides config default)"),
134
- ),
135
- cmd: Flag.String("cmd").pipe(Flag.withDescription("az command (without 'az' prefix)")),
136
- dryRun: Flag.Boolean("dry-run").pipe(
137
- Flag.withDescription("Show command without executing"),
138
- Flag.withDefault(false),
139
- ),
140
- format: formatOption,
141
- },
142
- ({ profile: _profile, project, cmd, dryRun, format }) =>
143
- Effect.gen(function* () {
144
- const projectName = project ? Option.getOrUndefined(project) : undefined;
145
-
146
- if (dryRun) {
147
- const fullCommand = `az ${cmd}`;
148
- yield* logText(`[DRY-RUN] Would execute: ${fullCommand}`);
149
- return;
150
- }
151
-
152
- const az = yield* AzdoService;
153
-
154
- const startTime = Date.now();
155
- const output = yield* az.runCommand(cmd, projectName);
156
- const executionTimeMs = Date.now() - startTime;
157
-
158
- yield* logText(
159
- formatOutput(
160
- {
161
- success: true,
162
- data: output,
163
- executionTimeMs,
164
- },
165
- format,
166
- ),
167
- );
168
- }),
169
- ).pipe(
170
- Command.withDescription(
171
- `Execute raw az CLI commands directly.
172
-
173
- EXAMPLES:
174
- agent-tools-azdo cmd --cmd "pipelines list"
175
- agent-tools-azdo cmd --cmd "repos list" --project my-project
176
- agent-tools-azdo cmd --cmd "pipelines runs list --output json"`,
177
- ),
178
- );
179
-
180
- // ---------------------------------------------------------------------------
181
- // Main command with subcommands
182
- // ---------------------------------------------------------------------------
183
-
184
- const commandsCommand = makeSchemaCommand(() => mainCommand);
185
-
186
- const mainCommand = Command.make("azdo-tool", {}).pipe(
187
- Command.withDescription(
188
- `Azure DevOps Tool for Coding Agents (READ-ONLY)
189
-
190
- For Azure platform (PaaS) resources — vm, webapp, storage, aks, keyvault — use az-tool instead.
191
-
192
- Typed build subcommands:
193
- azdo-tool build timeline --build-id 123
194
- azdo-tool build failed-jobs --build-id 123
195
- azdo-tool build logs --build-id 123
196
- azdo-tool build log-content --build-id 123 --log-id 45
197
- azdo-tool build summary --build-id 123
198
-
199
- Raw az wrapper:
200
- azdo-tool cmd --cmd "pipelines list"`,
201
- ),
202
- Command.withSubcommands([buildCommand, cmdCommand, commandsCommand]),
203
- );
204
-
205
- const cli = Command.run(mainCommand, {
206
- version: VERSION,
207
- });
208
-
209
- const MainLayer = AzdoServiceLayer.pipe(
210
- Layer.provideMerge(ConfigServiceLayer),
211
- Layer.provideMerge(BunServices.layer),
212
- Layer.provideMerge(AuditServiceLayer),
213
- );
214
-
215
- const program = withAudit("azdo", cli).pipe(
216
- Effect.provide(MainLayer),
217
- Effect.tapCause(renderCauseToStderr),
218
- );
219
-
220
- BunRuntime.runMain(program, {
221
- disableErrorReporting: true,
222
- });
4
+ if (await checkEffectVersion()) await import("./main");
5
+ else process.exitCode = 1;
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env bun
2
+ import { Command, Flag } from "effect/unstable/cli";
3
+ import { BunRuntime, BunServices } from "@effect/platform-bun";
4
+ import { Effect, Layer, Option } from "effect";
5
+
6
+ import {
7
+ makeSchemaCommand,
8
+ formatAny,
9
+ formatOption,
10
+ formatOutput,
11
+ logText,
12
+ renderCauseToStderr,
13
+ VERSION,
14
+ } from "#shared";
15
+ import { AuditServiceLayer, withAudit } from "#shared/audit";
16
+ import {
17
+ findFailedJobs,
18
+ getBuildJobSummary,
19
+ getBuildLogContent,
20
+ getBuildLogs,
21
+ getBuildTimeline,
22
+ } from "./build";
23
+ import { AzdoService, AzdoServiceLayer } from "./service";
24
+ import { ConfigServiceLayer } from "#config";
25
+
26
+ // ---------------------------------------------------------------------------
27
+ // Common flags shared across build subcommands
28
+ // ---------------------------------------------------------------------------
29
+
30
+ const commonBuildFlags = {
31
+ format: formatOption,
32
+ profile: Flag.optional(Flag.String("profile")).pipe(
33
+ Flag.withDescription("Azure DevOps profile name (from agent-tools config)"),
34
+ ),
35
+ };
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // Build subcommands
39
+ // ---------------------------------------------------------------------------
40
+
41
+ const buildTimelineCommand = Command.make(
42
+ "timeline",
43
+ {
44
+ ...commonBuildFlags,
45
+ buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
46
+ },
47
+ ({ buildId, format, profile: _profile }) =>
48
+ Effect.gen(function* () {
49
+ const result = yield* getBuildTimeline(buildId);
50
+ yield* logText(formatAny(result, format));
51
+ }),
52
+ ).pipe(Command.withDescription("Get build timeline with all records (jobs, stages, tasks)"));
53
+
54
+ const buildFailedJobsCommand = Command.make(
55
+ "failed-jobs",
56
+ {
57
+ ...commonBuildFlags,
58
+ buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
59
+ },
60
+ ({ buildId, format, profile: _profile }) =>
61
+ Effect.gen(function* () {
62
+ const failedJobs = yield* findFailedJobs(buildId);
63
+ yield* logText(formatAny({ buildId, failedJobs }, format));
64
+ }),
65
+ ).pipe(Command.withDescription("Find failed or canceled jobs in a build"));
66
+
67
+ const buildLogsCommand = Command.make(
68
+ "logs",
69
+ {
70
+ ...commonBuildFlags,
71
+ buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
72
+ },
73
+ ({ buildId, format, profile: _profile }) =>
74
+ Effect.gen(function* () {
75
+ const result = yield* getBuildLogs(buildId);
76
+ yield* logText(formatAny(result, format));
77
+ }),
78
+ ).pipe(Command.withDescription("Get list of build logs"));
79
+
80
+ const buildLogContentCommand = Command.make(
81
+ "log-content",
82
+ {
83
+ ...commonBuildFlags,
84
+ buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
85
+ logId: Flag.Int("log-id").pipe(Flag.withDescription("Log ID")),
86
+ },
87
+ ({ buildId, format, logId, profile: _profile }) =>
88
+ Effect.gen(function* () {
89
+ const content = yield* getBuildLogContent(buildId, logId);
90
+ yield* logText(formatAny({ buildId, logId, content }, format));
91
+ }),
92
+ ).pipe(Command.withDescription("Get specific log content by log ID"));
93
+
94
+ const buildSummaryCommand = Command.make(
95
+ "summary",
96
+ {
97
+ ...commonBuildFlags,
98
+ buildId: Flag.Int("build-id").pipe(Flag.withDescription("Build ID")),
99
+ },
100
+ ({ buildId, format, profile: _profile }) =>
101
+ Effect.gen(function* () {
102
+ const summary = yield* getBuildJobSummary(buildId);
103
+ yield* logText(formatAny({ buildId, summary }, format));
104
+ }),
105
+ ).pipe(Command.withDescription("Get job summaries with duration and status information"));
106
+
107
+ // ---------------------------------------------------------------------------
108
+ // Build parent command
109
+ // ---------------------------------------------------------------------------
110
+
111
+ const buildCommand = Command.make("build", {}).pipe(
112
+ Command.withDescription("Build helpers for Azure DevOps pipelines"),
113
+ Command.withSubcommands([
114
+ buildTimelineCommand,
115
+ buildFailedJobsCommand,
116
+ buildLogsCommand,
117
+ buildLogContentCommand,
118
+ buildSummaryCommand,
119
+ ]),
120
+ );
121
+
122
+ // ---------------------------------------------------------------------------
123
+ // Raw command subcommand (preserves existing --cmd behavior)
124
+ // ---------------------------------------------------------------------------
125
+
126
+ const cmdCommand = Command.make(
127
+ "cmd",
128
+ {
129
+ profile: Flag.optional(Flag.String("profile")).pipe(
130
+ Flag.withDescription("Azure DevOps profile name (from agent-tools config)"),
131
+ ),
132
+ project: Flag.optional(Flag.String("project")).pipe(
133
+ Flag.withDescription("Azure DevOps project name (overrides config default)"),
134
+ ),
135
+ cmd: Flag.String("cmd").pipe(Flag.withDescription("az command (without 'az' prefix)")),
136
+ dryRun: Flag.Boolean("dry-run").pipe(
137
+ Flag.withDescription("Show command without executing"),
138
+ Flag.withDefault(false),
139
+ ),
140
+ format: formatOption,
141
+ },
142
+ ({ profile: _profile, project, cmd, dryRun, format }) =>
143
+ Effect.gen(function* () {
144
+ const projectName = project ? Option.getOrUndefined(project) : undefined;
145
+
146
+ if (dryRun) {
147
+ const fullCommand = `az ${cmd}`;
148
+ yield* logText(`[DRY-RUN] Would execute: ${fullCommand}`);
149
+ return;
150
+ }
151
+
152
+ const az = yield* AzdoService;
153
+
154
+ const startTime = Date.now();
155
+ const output = yield* az.runCommand(cmd, projectName);
156
+ const executionTimeMs = Date.now() - startTime;
157
+
158
+ yield* logText(
159
+ formatOutput(
160
+ {
161
+ success: true,
162
+ data: output,
163
+ executionTimeMs,
164
+ },
165
+ format,
166
+ ),
167
+ );
168
+ }),
169
+ ).pipe(
170
+ Command.withDescription(
171
+ `Execute raw az CLI commands directly.
172
+
173
+ EXAMPLES:
174
+ agent-tools-azdo cmd --cmd "pipelines list"
175
+ agent-tools-azdo cmd --cmd "repos list" --project my-project
176
+ agent-tools-azdo cmd --cmd "pipelines runs list --output json"`,
177
+ ),
178
+ );
179
+
180
+ // ---------------------------------------------------------------------------
181
+ // Main command with subcommands
182
+ // ---------------------------------------------------------------------------
183
+
184
+ const commandsCommand = makeSchemaCommand(() => mainCommand);
185
+
186
+ const mainCommand = Command.make("azdo-tool", {}).pipe(
187
+ Command.withDescription(
188
+ `Azure DevOps Tool for Coding Agents (READ-ONLY)
189
+
190
+ For Azure platform (PaaS) resources — vm, webapp, storage, aks, keyvault — use az-tool instead.
191
+
192
+ Typed build subcommands:
193
+ azdo-tool build timeline --build-id 123
194
+ azdo-tool build failed-jobs --build-id 123
195
+ azdo-tool build logs --build-id 123
196
+ azdo-tool build log-content --build-id 123 --log-id 45
197
+ azdo-tool build summary --build-id 123
198
+
199
+ Raw az wrapper:
200
+ azdo-tool cmd --cmd "pipelines list"`,
201
+ ),
202
+ Command.withSubcommands([buildCommand, cmdCommand, commandsCommand]),
203
+ );
204
+
205
+ const cli = Command.run(mainCommand, {
206
+ version: VERSION,
207
+ });
208
+
209
+ const MainLayer = AzdoServiceLayer.pipe(
210
+ Layer.provideMerge(ConfigServiceLayer),
211
+ Layer.provideMerge(BunServices.layer),
212
+ Layer.provideMerge(AuditServiceLayer),
213
+ );
214
+
215
+ const program = withAudit("azdo", cli).pipe(
216
+ Effect.provide(MainLayer),
217
+ Effect.tapCause(renderCauseToStderr),
218
+ );
219
+
220
+ BunRuntime.runMain(program, {
221
+ disableErrorReporting: true,
222
+ });