@build-astron-co/nimbus 0.2.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.
Files changed (313) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +628 -0
  3. package/bin/nimbus +38 -0
  4. package/package.json +80 -0
  5. package/src/__tests__/app.test.ts +76 -0
  6. package/src/__tests__/audit.test.ts +877 -0
  7. package/src/__tests__/circuit-breaker.test.ts +116 -0
  8. package/src/__tests__/cli-run.test.ts +115 -0
  9. package/src/__tests__/context-manager.test.ts +502 -0
  10. package/src/__tests__/context.test.ts +242 -0
  11. package/src/__tests__/enterprise.test.ts +401 -0
  12. package/src/__tests__/generator.test.ts +433 -0
  13. package/src/__tests__/hooks.test.ts +582 -0
  14. package/src/__tests__/init.test.ts +436 -0
  15. package/src/__tests__/intent-parser.test.ts +229 -0
  16. package/src/__tests__/llm-router.test.ts +209 -0
  17. package/src/__tests__/lsp.test.ts +293 -0
  18. package/src/__tests__/modes.test.ts +336 -0
  19. package/src/__tests__/permissions.test.ts +338 -0
  20. package/src/__tests__/serve.test.ts +275 -0
  21. package/src/__tests__/sessions.test.ts +227 -0
  22. package/src/__tests__/sharing.test.ts +288 -0
  23. package/src/__tests__/snapshots.test.ts +581 -0
  24. package/src/__tests__/state-db.test.ts +334 -0
  25. package/src/__tests__/stream-with-tools.test.ts +732 -0
  26. package/src/__tests__/subagents.test.ts +176 -0
  27. package/src/__tests__/system-prompt.test.ts +169 -0
  28. package/src/__tests__/tool-converter.test.ts +256 -0
  29. package/src/__tests__/tool-schemas.test.ts +397 -0
  30. package/src/__tests__/tools.test.ts +143 -0
  31. package/src/__tests__/version.test.ts +49 -0
  32. package/src/agent/compaction-agent.ts +227 -0
  33. package/src/agent/context-manager.ts +435 -0
  34. package/src/agent/context.ts +427 -0
  35. package/src/agent/deploy-preview.ts +426 -0
  36. package/src/agent/index.ts +68 -0
  37. package/src/agent/loop.ts +717 -0
  38. package/src/agent/modes.ts +429 -0
  39. package/src/agent/permissions.ts +466 -0
  40. package/src/agent/subagents/base.ts +116 -0
  41. package/src/agent/subagents/cost.ts +51 -0
  42. package/src/agent/subagents/explore.ts +42 -0
  43. package/src/agent/subagents/general.ts +54 -0
  44. package/src/agent/subagents/index.ts +102 -0
  45. package/src/agent/subagents/infra.ts +59 -0
  46. package/src/agent/subagents/security.ts +69 -0
  47. package/src/agent/system-prompt.ts +436 -0
  48. package/src/app.ts +122 -0
  49. package/src/audit/activity-log.ts +290 -0
  50. package/src/audit/compliance-checker.ts +540 -0
  51. package/src/audit/cost-tracker.ts +318 -0
  52. package/src/audit/index.ts +23 -0
  53. package/src/audit/security-scanner.ts +596 -0
  54. package/src/auth/guard.ts +75 -0
  55. package/src/auth/index.ts +56 -0
  56. package/src/auth/oauth.ts +455 -0
  57. package/src/auth/providers.ts +470 -0
  58. package/src/auth/sso.ts +113 -0
  59. package/src/auth/store.ts +505 -0
  60. package/src/auth/types.ts +187 -0
  61. package/src/build.ts +141 -0
  62. package/src/cli/index.ts +16 -0
  63. package/src/cli/init.ts +854 -0
  64. package/src/cli/openapi-spec.ts +356 -0
  65. package/src/cli/run.ts +237 -0
  66. package/src/cli/serve-auth.ts +80 -0
  67. package/src/cli/serve.ts +462 -0
  68. package/src/cli/web.ts +67 -0
  69. package/src/cli.ts +1417 -0
  70. package/src/clients/core-engine-client.ts +227 -0
  71. package/src/clients/enterprise-client.ts +334 -0
  72. package/src/clients/generator-client.ts +351 -0
  73. package/src/clients/git-client.ts +627 -0
  74. package/src/clients/github-client.ts +410 -0
  75. package/src/clients/helm-client.ts +504 -0
  76. package/src/clients/index.ts +80 -0
  77. package/src/clients/k8s-client.ts +497 -0
  78. package/src/clients/llm-client.ts +161 -0
  79. package/src/clients/rest-client.ts +130 -0
  80. package/src/clients/service-discovery.ts +33 -0
  81. package/src/clients/terraform-client.ts +482 -0
  82. package/src/clients/tools-client.ts +1843 -0
  83. package/src/clients/ws-client.ts +115 -0
  84. package/src/commands/analyze/index.ts +352 -0
  85. package/src/commands/apply/helm.ts +473 -0
  86. package/src/commands/apply/index.ts +213 -0
  87. package/src/commands/apply/k8s.ts +454 -0
  88. package/src/commands/apply/terraform.ts +582 -0
  89. package/src/commands/ask.ts +167 -0
  90. package/src/commands/audit/index.ts +238 -0
  91. package/src/commands/auth-cloud.ts +294 -0
  92. package/src/commands/auth-list.ts +134 -0
  93. package/src/commands/auth-profile.ts +121 -0
  94. package/src/commands/auth-status.ts +141 -0
  95. package/src/commands/aws/ec2.ts +501 -0
  96. package/src/commands/aws/iam.ts +397 -0
  97. package/src/commands/aws/index.ts +133 -0
  98. package/src/commands/aws/lambda.ts +396 -0
  99. package/src/commands/aws/rds.ts +439 -0
  100. package/src/commands/aws/s3.ts +439 -0
  101. package/src/commands/aws/vpc.ts +393 -0
  102. package/src/commands/aws-discover.ts +649 -0
  103. package/src/commands/aws-terraform.ts +805 -0
  104. package/src/commands/azure/aks.ts +376 -0
  105. package/src/commands/azure/functions.ts +253 -0
  106. package/src/commands/azure/index.ts +116 -0
  107. package/src/commands/azure/storage.ts +478 -0
  108. package/src/commands/azure/vm.ts +355 -0
  109. package/src/commands/billing/index.ts +256 -0
  110. package/src/commands/chat.ts +314 -0
  111. package/src/commands/config.ts +346 -0
  112. package/src/commands/cost/cloud-cost-estimator.ts +266 -0
  113. package/src/commands/cost/estimator.ts +79 -0
  114. package/src/commands/cost/index.ts +594 -0
  115. package/src/commands/cost/parsers/terraform.ts +273 -0
  116. package/src/commands/cost/parsers/types.ts +25 -0
  117. package/src/commands/cost/pricing/aws.ts +544 -0
  118. package/src/commands/cost/pricing/azure.ts +499 -0
  119. package/src/commands/cost/pricing/gcp.ts +396 -0
  120. package/src/commands/cost/pricing/index.ts +40 -0
  121. package/src/commands/demo.ts +250 -0
  122. package/src/commands/doctor.ts +794 -0
  123. package/src/commands/drift/index.ts +439 -0
  124. package/src/commands/explain.ts +277 -0
  125. package/src/commands/feedback.ts +389 -0
  126. package/src/commands/fix.ts +324 -0
  127. package/src/commands/fs/index.ts +402 -0
  128. package/src/commands/gcp/compute.ts +325 -0
  129. package/src/commands/gcp/functions.ts +271 -0
  130. package/src/commands/gcp/gke.ts +438 -0
  131. package/src/commands/gcp/iam.ts +344 -0
  132. package/src/commands/gcp/index.ts +129 -0
  133. package/src/commands/gcp/storage.ts +284 -0
  134. package/src/commands/generate-helm.ts +1249 -0
  135. package/src/commands/generate-k8s.ts +1560 -0
  136. package/src/commands/generate-terraform.ts +1460 -0
  137. package/src/commands/gh/index.ts +863 -0
  138. package/src/commands/git/index.ts +1343 -0
  139. package/src/commands/helm/index.ts +1126 -0
  140. package/src/commands/help.ts +539 -0
  141. package/src/commands/history.ts +142 -0
  142. package/src/commands/import.ts +868 -0
  143. package/src/commands/index.ts +367 -0
  144. package/src/commands/init.ts +1046 -0
  145. package/src/commands/k8s/index.ts +1137 -0
  146. package/src/commands/login.ts +631 -0
  147. package/src/commands/logout.ts +83 -0
  148. package/src/commands/onboarding.ts +228 -0
  149. package/src/commands/plan/display.ts +279 -0
  150. package/src/commands/plan/index.ts +599 -0
  151. package/src/commands/preview.ts +452 -0
  152. package/src/commands/questionnaire.ts +1270 -0
  153. package/src/commands/resume.ts +55 -0
  154. package/src/commands/team/index.ts +346 -0
  155. package/src/commands/template.ts +232 -0
  156. package/src/commands/tf/index.ts +1034 -0
  157. package/src/commands/upgrade.ts +550 -0
  158. package/src/commands/usage/index.ts +134 -0
  159. package/src/commands/version.ts +170 -0
  160. package/src/compat/index.ts +2 -0
  161. package/src/compat/runtime.ts +12 -0
  162. package/src/compat/sqlite.ts +107 -0
  163. package/src/config/index.ts +17 -0
  164. package/src/config/manager.ts +530 -0
  165. package/src/config/safety-policy.ts +358 -0
  166. package/src/config/schema.ts +125 -0
  167. package/src/config/types.ts +527 -0
  168. package/src/context/context-db.ts +199 -0
  169. package/src/demo/index.ts +349 -0
  170. package/src/demo/scenarios/full-journey.ts +229 -0
  171. package/src/demo/scenarios/getting-started.ts +127 -0
  172. package/src/demo/scenarios/helm-release.ts +341 -0
  173. package/src/demo/scenarios/k8s-deployment.ts +194 -0
  174. package/src/demo/scenarios/terraform-vpc.ts +170 -0
  175. package/src/demo/types.ts +92 -0
  176. package/src/engine/cost-estimator.ts +438 -0
  177. package/src/engine/diagram-generator.ts +256 -0
  178. package/src/engine/drift-detector.ts +902 -0
  179. package/src/engine/executor.ts +1035 -0
  180. package/src/engine/index.ts +76 -0
  181. package/src/engine/orchestrator.ts +636 -0
  182. package/src/engine/planner.ts +720 -0
  183. package/src/engine/safety.ts +743 -0
  184. package/src/engine/verifier.ts +770 -0
  185. package/src/enterprise/audit.ts +348 -0
  186. package/src/enterprise/auth.ts +270 -0
  187. package/src/enterprise/billing.ts +822 -0
  188. package/src/enterprise/index.ts +17 -0
  189. package/src/enterprise/teams.ts +443 -0
  190. package/src/generator/best-practices.ts +1608 -0
  191. package/src/generator/helm.ts +630 -0
  192. package/src/generator/index.ts +37 -0
  193. package/src/generator/intent-parser.ts +514 -0
  194. package/src/generator/kubernetes.ts +976 -0
  195. package/src/generator/terraform.ts +1867 -0
  196. package/src/history/index.ts +8 -0
  197. package/src/history/manager.ts +322 -0
  198. package/src/history/types.ts +34 -0
  199. package/src/hooks/config.ts +432 -0
  200. package/src/hooks/engine.ts +391 -0
  201. package/src/hooks/index.ts +4 -0
  202. package/src/llm/auth-bridge.ts +198 -0
  203. package/src/llm/circuit-breaker.ts +140 -0
  204. package/src/llm/config-loader.ts +201 -0
  205. package/src/llm/cost-calculator.ts +171 -0
  206. package/src/llm/index.ts +8 -0
  207. package/src/llm/model-aliases.ts +115 -0
  208. package/src/llm/provider-registry.ts +63 -0
  209. package/src/llm/providers/anthropic.ts +433 -0
  210. package/src/llm/providers/bedrock.ts +477 -0
  211. package/src/llm/providers/google.ts +405 -0
  212. package/src/llm/providers/ollama.ts +767 -0
  213. package/src/llm/providers/openai-compatible.ts +340 -0
  214. package/src/llm/providers/openai.ts +328 -0
  215. package/src/llm/providers/openrouter.ts +338 -0
  216. package/src/llm/router.ts +1035 -0
  217. package/src/llm/types.ts +232 -0
  218. package/src/lsp/client.ts +298 -0
  219. package/src/lsp/languages.ts +116 -0
  220. package/src/lsp/manager.ts +278 -0
  221. package/src/mcp/client.ts +402 -0
  222. package/src/mcp/index.ts +5 -0
  223. package/src/mcp/manager.ts +133 -0
  224. package/src/nimbus.ts +214 -0
  225. package/src/plugins/index.ts +27 -0
  226. package/src/plugins/loader.ts +334 -0
  227. package/src/plugins/manager.ts +376 -0
  228. package/src/plugins/types.ts +284 -0
  229. package/src/scanners/cicd-scanner.ts +258 -0
  230. package/src/scanners/cloud-scanner.ts +466 -0
  231. package/src/scanners/framework-scanner.ts +469 -0
  232. package/src/scanners/iac-scanner.ts +388 -0
  233. package/src/scanners/index.ts +539 -0
  234. package/src/scanners/language-scanner.ts +276 -0
  235. package/src/scanners/package-manager-scanner.ts +277 -0
  236. package/src/scanners/types.ts +172 -0
  237. package/src/sessions/manager.ts +365 -0
  238. package/src/sessions/types.ts +44 -0
  239. package/src/sharing/sync.ts +296 -0
  240. package/src/sharing/viewer.ts +97 -0
  241. package/src/snapshots/index.ts +2 -0
  242. package/src/snapshots/manager.ts +530 -0
  243. package/src/state/artifacts.ts +147 -0
  244. package/src/state/audit.ts +137 -0
  245. package/src/state/billing.ts +240 -0
  246. package/src/state/checkpoints.ts +117 -0
  247. package/src/state/config.ts +67 -0
  248. package/src/state/conversations.ts +14 -0
  249. package/src/state/credentials.ts +154 -0
  250. package/src/state/db.ts +58 -0
  251. package/src/state/index.ts +26 -0
  252. package/src/state/messages.ts +115 -0
  253. package/src/state/projects.ts +123 -0
  254. package/src/state/schema.ts +236 -0
  255. package/src/state/sessions.ts +147 -0
  256. package/src/state/teams.ts +200 -0
  257. package/src/telemetry.ts +108 -0
  258. package/src/tools/aws-ops.ts +952 -0
  259. package/src/tools/azure-ops.ts +579 -0
  260. package/src/tools/file-ops.ts +593 -0
  261. package/src/tools/gcp-ops.ts +625 -0
  262. package/src/tools/git-ops.ts +773 -0
  263. package/src/tools/github-ops.ts +799 -0
  264. package/src/tools/helm-ops.ts +943 -0
  265. package/src/tools/index.ts +17 -0
  266. package/src/tools/k8s-ops.ts +819 -0
  267. package/src/tools/schemas/converter.ts +184 -0
  268. package/src/tools/schemas/devops.ts +612 -0
  269. package/src/tools/schemas/index.ts +73 -0
  270. package/src/tools/schemas/standard.ts +1144 -0
  271. package/src/tools/schemas/types.ts +705 -0
  272. package/src/tools/terraform-ops.ts +862 -0
  273. package/src/types/ambient.d.ts +193 -0
  274. package/src/types/config.ts +83 -0
  275. package/src/types/drift.ts +116 -0
  276. package/src/types/enterprise.ts +335 -0
  277. package/src/types/index.ts +20 -0
  278. package/src/types/plan.ts +44 -0
  279. package/src/types/request.ts +65 -0
  280. package/src/types/response.ts +54 -0
  281. package/src/types/service.ts +51 -0
  282. package/src/ui/App.tsx +997 -0
  283. package/src/ui/DeployPreview.tsx +169 -0
  284. package/src/ui/Header.tsx +68 -0
  285. package/src/ui/InputBox.tsx +350 -0
  286. package/src/ui/MessageList.tsx +585 -0
  287. package/src/ui/PermissionPrompt.tsx +151 -0
  288. package/src/ui/StatusBar.tsx +158 -0
  289. package/src/ui/ToolCallDisplay.tsx +409 -0
  290. package/src/ui/chat-ui.ts +853 -0
  291. package/src/ui/index.ts +33 -0
  292. package/src/ui/ink/index.ts +711 -0
  293. package/src/ui/streaming.ts +176 -0
  294. package/src/ui/types.ts +57 -0
  295. package/src/utils/analytics.ts +72 -0
  296. package/src/utils/cost-warning.ts +27 -0
  297. package/src/utils/env.ts +46 -0
  298. package/src/utils/errors.ts +69 -0
  299. package/src/utils/event-bus.ts +38 -0
  300. package/src/utils/index.ts +24 -0
  301. package/src/utils/logger.ts +171 -0
  302. package/src/utils/rate-limiter.ts +121 -0
  303. package/src/utils/service-auth.ts +49 -0
  304. package/src/utils/validation.ts +53 -0
  305. package/src/version.ts +4 -0
  306. package/src/watcher/index.ts +163 -0
  307. package/src/wizard/approval.ts +383 -0
  308. package/src/wizard/index.ts +25 -0
  309. package/src/wizard/prompts.ts +338 -0
  310. package/src/wizard/types.ts +171 -0
  311. package/src/wizard/ui.ts +556 -0
  312. package/src/wizard/wizard.ts +304 -0
  313. package/tsconfig.json +24 -0
@@ -0,0 +1,410 @@
1
+ /**
2
+ * GitHub Tools Client
3
+ *
4
+ * REST client for communicating with the GitHub Tools Service
5
+ */
6
+
7
+ import { RestClient, ServiceURLs } from '.';
8
+ import { authStore } from '../auth/store';
9
+
10
+ export interface GitHubUser {
11
+ login: string;
12
+ name: string;
13
+ email?: string;
14
+ avatar_url?: string;
15
+ }
16
+
17
+ export interface GitHubPullRequest {
18
+ number: number;
19
+ title: string;
20
+ body?: string;
21
+ state: 'open' | 'closed';
22
+ user: GitHubUser;
23
+ head: { ref: string; sha: string };
24
+ base: { ref: string; sha: string };
25
+ created_at: string;
26
+ updated_at: string;
27
+ merged_at?: string;
28
+ mergeable?: boolean;
29
+ draft?: boolean;
30
+ labels: Array<{ name: string; color: string }>;
31
+ }
32
+
33
+ export interface GitHubIssue {
34
+ number: number;
35
+ title: string;
36
+ body?: string;
37
+ state: 'open' | 'closed';
38
+ user: GitHubUser;
39
+ labels: Array<{ name: string; color: string }>;
40
+ created_at: string;
41
+ updated_at: string;
42
+ closed_at?: string;
43
+ comments: number;
44
+ }
45
+
46
+ export interface GitHubRepository {
47
+ full_name: string;
48
+ name: string;
49
+ owner: { login: string };
50
+ description?: string;
51
+ private: boolean;
52
+ default_branch: string;
53
+ language?: string;
54
+ stargazers_count: number;
55
+ forks_count: number;
56
+ open_issues_count: number;
57
+ }
58
+
59
+ export interface GitHubBranch {
60
+ name: string;
61
+ commit: { sha: string };
62
+ protected: boolean;
63
+ }
64
+
65
+ export interface CreatePRParams {
66
+ title: string;
67
+ head: string;
68
+ base: string;
69
+ body?: string;
70
+ draft?: boolean;
71
+ }
72
+
73
+ export interface CreateIssueParams {
74
+ title: string;
75
+ body?: string;
76
+ labels?: string[];
77
+ assignees?: string[];
78
+ }
79
+
80
+ /**
81
+ * Client for GitHub Tools Service
82
+ */
83
+ export class GitHubClient {
84
+ private client: RestClient;
85
+ private baseUrl: string;
86
+
87
+ constructor(baseUrl?: string) {
88
+ this.baseUrl = baseUrl || ServiceURLs.GITHUB_TOOLS;
89
+ this.client = new RestClient(this.baseUrl);
90
+ }
91
+
92
+ /**
93
+ * Get authorization header from stored GitHub identity
94
+ */
95
+ private getAuthHeader(): Record<string, string> {
96
+ const identity = authStore.getIdentity();
97
+ if (identity?.accessToken) {
98
+ return { Authorization: `Bearer ${identity.accessToken}` };
99
+ }
100
+ return {};
101
+ }
102
+
103
+ /**
104
+ * Create a REST client with auth headers
105
+ */
106
+ private getAuthClient(): RestClient {
107
+ const authHeaders = this.getAuthHeader();
108
+ return new RestClient(this.baseUrl, {
109
+ headers: authHeaders,
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Get authenticated user info
115
+ */
116
+ async getUser(): Promise<{ success: boolean; data?: GitHubUser; error?: string }> {
117
+ const client = this.getAuthClient();
118
+ const response = await client.get<{ success: boolean; data: GitHubUser }>('/api/github/user');
119
+ if (response.success && response.data) {
120
+ return response.data;
121
+ }
122
+ return { success: false, error: response.error?.message || 'Unknown error' };
123
+ }
124
+
125
+ /**
126
+ * List pull requests
127
+ */
128
+ async listPRs(
129
+ owner: string,
130
+ repo: string,
131
+ options?: { state?: 'open' | 'closed' | 'all'; perPage?: number }
132
+ ): Promise<{ success: boolean; data?: GitHubPullRequest[]; error?: string }> {
133
+ const client = this.getAuthClient();
134
+ const params = new URLSearchParams();
135
+ params.set('owner', owner);
136
+ params.set('repo', repo);
137
+ if (options?.state) {
138
+ params.set('state', options.state);
139
+ }
140
+ if (options?.perPage) {
141
+ params.set('per_page', String(options.perPage));
142
+ }
143
+
144
+ const response = await client.get<{ success: boolean; data: GitHubPullRequest[] }>(
145
+ `/api/github/prs?${params.toString()}`
146
+ );
147
+ if (response.success && response.data) {
148
+ return response.data;
149
+ }
150
+ return { success: false, error: response.error?.message || 'Unknown error' };
151
+ }
152
+
153
+ /**
154
+ * Get a single pull request
155
+ */
156
+ async getPR(
157
+ owner: string,
158
+ repo: string,
159
+ prNumber: number
160
+ ): Promise<{ success: boolean; data?: GitHubPullRequest; error?: string }> {
161
+ const client = this.getAuthClient();
162
+ const params = new URLSearchParams();
163
+ params.set('owner', owner);
164
+ params.set('repo', repo);
165
+
166
+ const response = await client.get<{ success: boolean; data: GitHubPullRequest }>(
167
+ `/api/github/prs/${prNumber}?${params.toString()}`
168
+ );
169
+ if (response.success && response.data) {
170
+ return response.data;
171
+ }
172
+ return { success: false, error: response.error?.message || 'Unknown error' };
173
+ }
174
+
175
+ /**
176
+ * Create a pull request
177
+ */
178
+ async createPR(
179
+ owner: string,
180
+ repo: string,
181
+ params: CreatePRParams
182
+ ): Promise<{ success: boolean; data?: GitHubPullRequest; error?: string }> {
183
+ const client = this.getAuthClient();
184
+ const response = await client.post<{ success: boolean; data: GitHubPullRequest }>(
185
+ '/api/github/prs',
186
+ { owner, repo, ...params }
187
+ );
188
+ if (response.success && response.data) {
189
+ return response.data;
190
+ }
191
+ return { success: false, error: response.error?.message || 'Unknown error' };
192
+ }
193
+
194
+ /**
195
+ * Merge a pull request
196
+ */
197
+ async mergePR(
198
+ owner: string,
199
+ repo: string,
200
+ prNumber: number,
201
+ options?: { mergeMethod?: 'merge' | 'squash' | 'rebase'; commitTitle?: string }
202
+ ): Promise<{
203
+ success: boolean;
204
+ data?: { sha: string; merged: boolean; message: string };
205
+ error?: string;
206
+ }> {
207
+ const client = this.getAuthClient();
208
+ const response = await client.post<{
209
+ success: boolean;
210
+ data: { sha: string; merged: boolean; message: string };
211
+ }>(`/api/github/prs/${prNumber}/merge`, { owner, repo, ...options });
212
+ if (response.success && response.data) {
213
+ return response.data;
214
+ }
215
+ return { success: false, error: response.error?.message || 'Unknown error' };
216
+ }
217
+
218
+ /**
219
+ * Create a review on a pull request
220
+ */
221
+ async createPRReview(
222
+ owner: string,
223
+ repo: string,
224
+ prNumber: number,
225
+ event: 'APPROVE' | 'REQUEST_CHANGES' | 'COMMENT',
226
+ body?: string
227
+ ): Promise<{ success: boolean; data?: { id: number; state: string }; error?: string }> {
228
+ const client = this.getAuthClient();
229
+ const response = await client.post<{
230
+ success: boolean;
231
+ data: { id: number; state: string };
232
+ }>(`/api/github/prs/${prNumber}/reviews`, { owner, repo, event, body });
233
+ if (response.success && response.data) {
234
+ return response.data;
235
+ }
236
+ return { success: false, error: response.error?.message || 'Unknown error' };
237
+ }
238
+
239
+ /**
240
+ * List issues
241
+ */
242
+ async listIssues(
243
+ owner: string,
244
+ repo: string,
245
+ options?: { state?: 'open' | 'closed' | 'all'; perPage?: number }
246
+ ): Promise<{ success: boolean; data?: GitHubIssue[]; error?: string }> {
247
+ const client = this.getAuthClient();
248
+ const params = new URLSearchParams();
249
+ params.set('owner', owner);
250
+ params.set('repo', repo);
251
+ if (options?.state) {
252
+ params.set('state', options.state);
253
+ }
254
+ if (options?.perPage) {
255
+ params.set('per_page', String(options.perPage));
256
+ }
257
+
258
+ const response = await client.get<{ success: boolean; data: GitHubIssue[] }>(
259
+ `/api/github/issues?${params.toString()}`
260
+ );
261
+ if (response.success && response.data) {
262
+ return response.data;
263
+ }
264
+ return { success: false, error: response.error?.message || 'Unknown error' };
265
+ }
266
+
267
+ /**
268
+ * Get a single issue
269
+ */
270
+ async getIssue(
271
+ owner: string,
272
+ repo: string,
273
+ issueNumber: number
274
+ ): Promise<{ success: boolean; data?: GitHubIssue; error?: string }> {
275
+ const client = this.getAuthClient();
276
+ const params = new URLSearchParams();
277
+ params.set('owner', owner);
278
+ params.set('repo', repo);
279
+
280
+ const response = await client.get<{ success: boolean; data: GitHubIssue }>(
281
+ `/api/github/issues/${issueNumber}?${params.toString()}`
282
+ );
283
+ if (response.success && response.data) {
284
+ return response.data;
285
+ }
286
+ return { success: false, error: response.error?.message || 'Unknown error' };
287
+ }
288
+
289
+ /**
290
+ * Create an issue
291
+ */
292
+ async createIssue(
293
+ owner: string,
294
+ repo: string,
295
+ params: CreateIssueParams
296
+ ): Promise<{ success: boolean; data?: GitHubIssue; error?: string }> {
297
+ const client = this.getAuthClient();
298
+ const response = await client.post<{ success: boolean; data: GitHubIssue }>(
299
+ '/api/github/issues',
300
+ { owner, repo, ...params }
301
+ );
302
+ if (response.success && response.data) {
303
+ return response.data;
304
+ }
305
+ return { success: false, error: response.error?.message || 'Unknown error' };
306
+ }
307
+
308
+ /**
309
+ * Close an issue
310
+ */
311
+ async closeIssue(
312
+ owner: string,
313
+ repo: string,
314
+ issueNumber: number
315
+ ): Promise<{ success: boolean; data?: GitHubIssue; error?: string }> {
316
+ const client = this.getAuthClient();
317
+ const params = new URLSearchParams();
318
+ params.set('owner', owner);
319
+ params.set('repo', repo);
320
+
321
+ const response = await client.put<{ success: boolean; data: GitHubIssue }>(
322
+ `/api/github/issues/${issueNumber}/close?${params.toString()}`,
323
+ {}
324
+ );
325
+ if (response.success && response.data) {
326
+ return response.data;
327
+ }
328
+ return { success: false, error: response.error?.message || 'Unknown error' };
329
+ }
330
+
331
+ /**
332
+ * Add a comment to an issue or PR
333
+ */
334
+ async addComment(
335
+ owner: string,
336
+ repo: string,
337
+ issueNumber: number,
338
+ body: string
339
+ ): Promise<{ success: boolean; data?: { id: number; body: string }; error?: string }> {
340
+ const client = this.getAuthClient();
341
+ const response = await client.post<{ success: boolean; data: { id: number; body: string } }>(
342
+ `/api/github/issues/${issueNumber}/comments`,
343
+ { owner, repo, body }
344
+ );
345
+ if (response.success && response.data) {
346
+ return response.data;
347
+ }
348
+ return { success: false, error: response.error?.message || 'Unknown error' };
349
+ }
350
+
351
+ /**
352
+ * Get repository info
353
+ */
354
+ async getRepo(
355
+ owner: string,
356
+ repo: string
357
+ ): Promise<{ success: boolean; data?: GitHubRepository; error?: string }> {
358
+ const client = this.getAuthClient();
359
+ const params = new URLSearchParams();
360
+ params.set('owner', owner);
361
+ params.set('repo', repo);
362
+
363
+ const response = await client.get<{ success: boolean; data: GitHubRepository }>(
364
+ `/api/github/repos?${params.toString()}`
365
+ );
366
+ if (response.success && response.data) {
367
+ return response.data;
368
+ }
369
+ return { success: false, error: response.error?.message || 'Unknown error' };
370
+ }
371
+
372
+ /**
373
+ * List branches
374
+ */
375
+ async listBranches(
376
+ owner: string,
377
+ repo: string,
378
+ options?: { perPage?: number }
379
+ ): Promise<{ success: boolean; data?: GitHubBranch[]; error?: string }> {
380
+ const client = this.getAuthClient();
381
+ const params = new URLSearchParams();
382
+ params.set('owner', owner);
383
+ params.set('repo', repo);
384
+ if (options?.perPage) {
385
+ params.set('per_page', String(options.perPage));
386
+ }
387
+
388
+ const response = await client.get<{ success: boolean; data: GitHubBranch[] }>(
389
+ `/api/github/repos/branches?${params.toString()}`
390
+ );
391
+ if (response.success && response.data) {
392
+ return response.data;
393
+ }
394
+ return { success: false, error: response.error?.message || 'Unknown error' };
395
+ }
396
+
397
+ /**
398
+ * Check if service is available
399
+ */
400
+ async isAvailable(): Promise<boolean> {
401
+ try {
402
+ const response = await this.client.get<{ status: string }>('/health');
403
+ return response.success && response.data?.status === 'healthy';
404
+ } catch {
405
+ return false;
406
+ }
407
+ }
408
+ }
409
+
410
+ export const githubClient = new GitHubClient();