@g-abhishek/gitx 0.1.1 → 0.1.4

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 (161) hide show
  1. package/README.md +374 -3
  2. package/dist/ai/claudeAi.d.ts +35 -0
  3. package/dist/ai/claudeAi.d.ts.map +1 -0
  4. package/dist/ai/claudeAi.js +396 -0
  5. package/dist/ai/claudeAi.js.map +1 -0
  6. package/dist/ai/claudeCliAi.d.ts +27 -0
  7. package/dist/ai/claudeCliAi.d.ts.map +1 -0
  8. package/dist/ai/claudeCliAi.js +312 -0
  9. package/dist/ai/claudeCliAi.js.map +1 -0
  10. package/dist/ai/localClaudeAi.d.ts +2 -0
  11. package/dist/ai/localClaudeAi.d.ts.map +1 -0
  12. package/dist/ai/localClaudeAi.js +4 -0
  13. package/dist/ai/localClaudeAi.js.map +1 -0
  14. package/dist/ai/mockAi.d.ts +8 -1
  15. package/dist/ai/mockAi.d.ts.map +1 -1
  16. package/dist/ai/mockAi.js +57 -0
  17. package/dist/ai/mockAi.js.map +1 -1
  18. package/dist/ai/openAiAi.d.ts +33 -0
  19. package/dist/ai/openAiAi.d.ts.map +1 -0
  20. package/dist/ai/openAiAi.js +388 -0
  21. package/dist/ai/openAiAi.js.map +1 -0
  22. package/dist/ai/reviewHelpers.d.ts +66 -0
  23. package/dist/ai/reviewHelpers.d.ts.map +1 -0
  24. package/dist/ai/reviewHelpers.js +559 -0
  25. package/dist/ai/reviewHelpers.js.map +1 -0
  26. package/dist/ai/types.d.ts +247 -0
  27. package/dist/ai/types.d.ts.map +1 -1
  28. package/dist/ai/types.js.map +1 -1
  29. package/dist/cli/commands/ask.d.ts +27 -0
  30. package/dist/cli/commands/ask.d.ts.map +1 -0
  31. package/dist/cli/commands/ask.js +230 -0
  32. package/dist/cli/commands/ask.js.map +1 -0
  33. package/dist/cli/commands/commit.d.ts +16 -0
  34. package/dist/cli/commands/commit.d.ts.map +1 -0
  35. package/dist/cli/commands/commit.js +163 -0
  36. package/dist/cli/commands/commit.js.map +1 -0
  37. package/dist/cli/commands/config.d.ts +4 -0
  38. package/dist/cli/commands/config.d.ts.map +1 -0
  39. package/dist/cli/commands/config.js +666 -0
  40. package/dist/cli/commands/config.js.map +1 -0
  41. package/dist/cli/commands/implement.d.ts.map +1 -1
  42. package/dist/cli/commands/implement.js +149 -28
  43. package/dist/cli/commands/implement.js.map +1 -1
  44. package/dist/cli/commands/init.d.ts +4 -0
  45. package/dist/cli/commands/init.d.ts.map +1 -1
  46. package/dist/cli/commands/init.js +7 -54
  47. package/dist/cli/commands/init.js.map +1 -1
  48. package/dist/cli/commands/port.d.ts +32 -0
  49. package/dist/cli/commands/port.d.ts.map +1 -0
  50. package/dist/cli/commands/port.js +554 -0
  51. package/dist/cli/commands/port.js.map +1 -0
  52. package/dist/cli/commands/pr/close.d.ts +15 -0
  53. package/dist/cli/commands/pr/close.d.ts.map +1 -0
  54. package/dist/cli/commands/pr/close.js +71 -0
  55. package/dist/cli/commands/pr/close.js.map +1 -0
  56. package/dist/cli/commands/pr/create.d.ts +17 -0
  57. package/dist/cli/commands/pr/create.d.ts.map +1 -1
  58. package/dist/cli/commands/pr/create.js +209 -5
  59. package/dist/cli/commands/pr/create.js.map +1 -1
  60. package/dist/cli/commands/pr/fixComments.d.ts.map +1 -1
  61. package/dist/cli/commands/pr/fixComments.js +77 -5
  62. package/dist/cli/commands/pr/fixComments.js.map +1 -1
  63. package/dist/cli/commands/pr/index.d.ts.map +1 -1
  64. package/dist/cli/commands/pr/index.js +4 -0
  65. package/dist/cli/commands/pr/index.js.map +1 -1
  66. package/dist/cli/commands/pr/list.d.ts.map +1 -1
  67. package/dist/cli/commands/pr/list.js +26 -3
  68. package/dist/cli/commands/pr/list.js.map +1 -1
  69. package/dist/cli/commands/pr/merge.d.ts +23 -0
  70. package/dist/cli/commands/pr/merge.d.ts.map +1 -0
  71. package/dist/cli/commands/pr/merge.js +191 -0
  72. package/dist/cli/commands/pr/merge.js.map +1 -0
  73. package/dist/cli/commands/pr/review.d.ts.map +1 -1
  74. package/dist/cli/commands/pr/review.js +123 -5
  75. package/dist/cli/commands/pr/review.js.map +1 -1
  76. package/dist/cli/commands/push.d.ts +16 -0
  77. package/dist/cli/commands/push.d.ts.map +1 -0
  78. package/dist/cli/commands/push.js +166 -0
  79. package/dist/cli/commands/push.js.map +1 -0
  80. package/dist/cli/commands/sync.d.ts +24 -0
  81. package/dist/cli/commands/sync.d.ts.map +1 -0
  82. package/dist/cli/commands/sync.js +414 -0
  83. package/dist/cli/commands/sync.js.map +1 -0
  84. package/dist/cli/index.d.ts.map +1 -1
  85. package/dist/cli/index.js +34 -6
  86. package/dist/cli/index.js.map +1 -1
  87. package/dist/config/config.d.ts +20 -3
  88. package/dist/config/config.d.ts.map +1 -1
  89. package/dist/config/config.js +103 -24
  90. package/dist/config/config.js.map +1 -1
  91. package/dist/config/schema.d.ts.map +1 -1
  92. package/dist/config/schema.js +70 -9
  93. package/dist/config/schema.js.map +1 -1
  94. package/dist/core/context.d.ts +13 -0
  95. package/dist/core/context.d.ts.map +1 -0
  96. package/dist/core/context.js +2 -0
  97. package/dist/core/context.js.map +1 -0
  98. package/dist/core/gitx.d.ts +47 -0
  99. package/dist/core/gitx.d.ts.map +1 -1
  100. package/dist/core/gitx.js +204 -9
  101. package/dist/core/gitx.js.map +1 -1
  102. package/dist/index.d.ts +1 -5
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +4 -1
  105. package/dist/index.js.map +1 -1
  106. package/dist/providers/azure.d.ts +26 -0
  107. package/dist/providers/azure.d.ts.map +1 -0
  108. package/dist/providers/azure.js +256 -0
  109. package/dist/providers/azure.js.map +1 -0
  110. package/dist/providers/base.d.ts +104 -0
  111. package/dist/providers/base.d.ts.map +1 -0
  112. package/dist/providers/base.js +5 -0
  113. package/dist/providers/base.js.map +1 -0
  114. package/dist/providers/factory.d.ts +8 -0
  115. package/dist/providers/factory.d.ts.map +1 -0
  116. package/dist/providers/factory.js +25 -0
  117. package/dist/providers/factory.js.map +1 -0
  118. package/dist/providers/github.d.ts +19 -0
  119. package/dist/providers/github.d.ts.map +1 -0
  120. package/dist/providers/github.js +291 -0
  121. package/dist/providers/github.js.map +1 -0
  122. package/dist/providers/gitlab.d.ts +19 -0
  123. package/dist/providers/gitlab.d.ts.map +1 -0
  124. package/dist/providers/gitlab.js +186 -0
  125. package/dist/providers/gitlab.js.map +1 -0
  126. package/dist/types/config.d.ts +53 -9
  127. package/dist/types/config.d.ts.map +1 -1
  128. package/dist/types/config.js.map +1 -1
  129. package/dist/utils/azureAuth.d.ts +51 -0
  130. package/dist/utils/azureAuth.d.ts.map +1 -0
  131. package/dist/utils/azureAuth.js +172 -0
  132. package/dist/utils/azureAuth.js.map +1 -0
  133. package/dist/utils/git.d.ts +22 -0
  134. package/dist/utils/git.d.ts.map +1 -1
  135. package/dist/utils/git.js +63 -7
  136. package/dist/utils/git.js.map +1 -1
  137. package/dist/utils/gitOps.d.ts +118 -0
  138. package/dist/utils/gitOps.d.ts.map +1 -0
  139. package/dist/utils/gitOps.js +380 -0
  140. package/dist/utils/gitOps.js.map +1 -0
  141. package/dist/utils/lockFile.d.ts +13 -0
  142. package/dist/utils/lockFile.d.ts.map +1 -0
  143. package/dist/utils/lockFile.js +54 -0
  144. package/dist/utils/lockFile.js.map +1 -0
  145. package/dist/utils/retry.d.ts +10 -0
  146. package/dist/utils/retry.d.ts.map +1 -0
  147. package/dist/utils/retry.js +31 -0
  148. package/dist/utils/retry.js.map +1 -0
  149. package/dist/workflows/implement.d.ts +41 -0
  150. package/dist/workflows/implement.d.ts.map +1 -0
  151. package/dist/workflows/implement.js +219 -0
  152. package/dist/workflows/implement.js.map +1 -0
  153. package/dist/workflows/pr.d.ts +41 -0
  154. package/dist/workflows/pr.d.ts.map +1 -0
  155. package/dist/workflows/pr.js +285 -0
  156. package/dist/workflows/pr.js.map +1 -0
  157. package/dist/workflows/prAddress.d.ts +55 -0
  158. package/dist/workflows/prAddress.d.ts.map +1 -0
  159. package/dist/workflows/prAddress.js +349 -0
  160. package/dist/workflows/prAddress.js.map +1 -0
  161. package/package.json +1 -1
@@ -34,11 +34,258 @@ export interface AiSuggestFixesResponse {
34
34
  unifiedDiff: string;
35
35
  }>;
36
36
  }
37
+ export interface AiCommitMessageResponse {
38
+ /** Full conventional commit subject line, e.g. "feat(auth): add OAuth2 login flow" */
39
+ subject: string;
40
+ /** Optional multi-line body explaining WHY the change was made */
41
+ body?: string;
42
+ }
43
+ export interface AiPrContentResponse {
44
+ /** Short, human-readable PR title (not necessarily conventional-commit format) */
45
+ title: string;
46
+ /** Multi-paragraph PR description: what changed, why, how to test */
47
+ body: string;
48
+ }
49
+ export interface AiConflictResolutionResponse {
50
+ /** The full file content with ALL conflict markers removed and conflicts resolved. */
51
+ resolved: string;
52
+ /**
53
+ * "high" → AI is confident both sides are fully reconciled — safe to auto-apply.
54
+ * "low" → Changes are contradictory or ambiguous — show to user for confirmation.
55
+ */
56
+ confidence: "high" | "low";
57
+ /** One-sentence explanation of what the AI did (shown to the user). */
58
+ explanation: string;
59
+ }
60
+ /**
61
+ * AI-generated fix for a single PR review comment.
62
+ * Targets a specific line range in a file with a minimal replacement.
63
+ */
64
+ export interface AiFixResponse {
65
+ /** Relative path to the file that needs to change */
66
+ file: string;
67
+ /** 1-based line number where the replacement starts */
68
+ startLine: number;
69
+ /** 1-based line number where the replacement ends (inclusive) */
70
+ endLine: number;
71
+ /**
72
+ * The new code to replace lines startLine–endLine with.
73
+ * Must preserve surrounding indentation style.
74
+ */
75
+ replacement: string;
76
+ /** One-sentence explanation shown to the user */
77
+ explanation: string;
78
+ /**
79
+ * "high" → safe to auto-apply without confirmation.
80
+ * "low" → show diff and ask user before applying.
81
+ */
82
+ confidence: "high" | "low";
83
+ /** Does this fix fully resolve the comment (vs partially)? */
84
+ resolves: boolean;
85
+ /**
86
+ * true when the comment is a question / discussion with no code change needed.
87
+ * In this case startLine/endLine/replacement are empty and should be ignored.
88
+ */
89
+ isDiscussion: boolean;
90
+ }
91
+ /**
92
+ * Diagnostic snapshot of which AI provider is active and how it was resolved.
93
+ * Keys are never included — only whether they are present.
94
+ */
95
+ export interface AiSetupStatus {
96
+ /**
97
+ * Human-readable provider name, e.g. "claude (Anthropic API)", "openai", "claude-cli (local)", "none".
98
+ * "none" means no provider is configured and MockAi will be used.
99
+ */
100
+ provider: string;
101
+ /** Model in use, if applicable (e.g. "claude-3-5-haiku-20241022", "gpt-4o") */
102
+ model?: string;
103
+ /**
104
+ * Where the key / credential came from:
105
+ * "ANTHROPIC_API_KEY env var" | "OPENAI_API_KEY env var" | "config file" | "local CLI" | "none"
106
+ */
107
+ keySource: string;
108
+ /** true when at least one real AI provider is available */
109
+ isConfigured: boolean;
110
+ }
111
+ /**
112
+ * Status of a single configured git hosting provider.
113
+ * The actual token value is never included.
114
+ */
115
+ export interface GitProviderStatus {
116
+ /** "github" | "gitlab" | "azure" */
117
+ name: string;
118
+ /** true when a non-empty token exists for this provider */
119
+ hasToken: boolean;
120
+ }
121
+ /**
122
+ * Live repo context gathered by `gitx ask` and injected into the AI prompt.
123
+ * All fields are optional so partial context still produces useful answers.
124
+ */
125
+ export interface AiAskContext {
126
+ /** Whether the CWD is inside a git repository */
127
+ isInsideGitRepo: boolean;
128
+ /** Current checked-out branch name (only meaningful when isInsideGitRepo is true) */
129
+ currentBranch: string;
130
+ /** Last 10 commits as one-line summaries (hash + subject) */
131
+ recentCommits: string[];
132
+ /** Output of `git status --short` */
133
+ gitStatus: string;
134
+ /** Open pull requests from the remote provider */
135
+ openPRs?: Array<{
136
+ number: number;
137
+ title: string;
138
+ state: string;
139
+ branch: string;
140
+ }>;
141
+ /** Stash entries (e.g. "stash@{0}: WIP on feat/x: abc1234 msg") */
142
+ stashes?: string[];
143
+ /** Detailed status of the active AI provider */
144
+ aiSetup: AiSetupStatus;
145
+ /** All configured git hosting providers (github / gitlab / azure) */
146
+ gitProviders: GitProviderStatus[];
147
+ /** The configured default base branch, if any */
148
+ defaultBranch?: string;
149
+ }
150
+ /** Response returned by `AiClient.ask()` for the `gitx ask` command. */
151
+ export interface AiAskResponse {
152
+ /** Full answer in plain text or markdown */
153
+ answer: string;
154
+ /**
155
+ * Concrete gitx (or git) commands the user can run to act on the answer.
156
+ * Omit when not applicable.
157
+ */
158
+ suggestedCommands?: string[];
159
+ }
37
160
  export interface AiClient {
38
161
  analyzeTask(input: string): Promise<AiAnalyzeTaskResponse>;
39
162
  generatePlan(context: unknown): Promise<AiGeneratePlanResponse>;
40
163
  generateDiffs(step: unknown): Promise<AiGenerateDiffsResponse>;
41
164
  summarizeChanges(diff: unknown): Promise<AiSummarizeChangesResponse>;
42
165
  suggestFixes(comment: unknown): Promise<AiSuggestFixesResponse>;
166
+ reviewPR(context: unknown): Promise<AiReviewPRResponse>;
167
+ /** Generate a conventional commit message from a unified diff. */
168
+ generateCommitMessage(diff: string): Promise<AiCommitMessageResponse>;
169
+ /**
170
+ * Generate a PR title and description from branch commits + diff.
171
+ * Pass `stat` (output of `git diff --stat`) alongside the diff so the AI
172
+ * sees every changed file even when the detailed patch is truncated.
173
+ */
174
+ generatePrContent(commits: string[], diff: string, stat?: string): Promise<AiPrContentResponse>;
175
+ /**
176
+ * Resolve git merge conflict markers in a file.
177
+ * Returns the fully resolved file content + confidence level.
178
+ */
179
+ resolveConflict(filePath: string, conflictContent: string): Promise<AiConflictResolutionResponse>;
180
+ /**
181
+ * Generate a targeted fix for a single PR review comment.
182
+ * Returns a line-range replacement (startLine–endLine → replacement).
183
+ */
184
+ generateFix(context: {
185
+ /** The review comment text to address */
186
+ comment: string;
187
+ /** Author of the comment */
188
+ commentAuthor: string;
189
+ /** Relative file path the comment is on */
190
+ filePath: string;
191
+ /** 1-based line number the comment targets */
192
+ line: number;
193
+ /** Full current file content (after PR changes) */
194
+ fileContent: string;
195
+ /** The relevant diff section for this file */
196
+ fileDiff: string;
197
+ }): Promise<AiFixResponse>;
198
+ /**
199
+ * Answer a free-form question about the repo using live git context + AI.
200
+ * Used by `gitx ask "<question>"`.
201
+ *
202
+ * @param question The raw question string from the user.
203
+ * @param context Live repo state gathered by the ask command.
204
+ */
205
+ ask(question: string, context: AiAskContext): Promise<AiAskResponse>;
206
+ /**
207
+ * Senior-developer quality PR review with full codebase context.
208
+ * Returns inline comments, checklist, and a formal verdict.
209
+ */
210
+ reviewPRDetailed(context: {
211
+ /** PR title */
212
+ prTitle: string;
213
+ /** PR description */
214
+ prBody: string;
215
+ /** Author of the PR */
216
+ author: string;
217
+ /** Source branch name */
218
+ headBranch: string;
219
+ /** Target branch name */
220
+ baseBranch: string;
221
+ /** Full unified diff of the PR (may be truncated) */
222
+ diff: string;
223
+ /** Files changed — key: relative path, value: FULL file content after changes */
224
+ changedFiles: Record<string, string>;
225
+ /** Supporting context files the changes depend on */
226
+ contextFiles: Record<string, string>;
227
+ /** Flat list of all repo files (for structural awareness) */
228
+ repoFileList: string[];
229
+ /** Existing PR comments */
230
+ existingComments: Array<{
231
+ author: string;
232
+ body: string;
233
+ path?: string;
234
+ line?: number;
235
+ }>;
236
+ }): Promise<AiDetailedReviewResponse>;
237
+ }
238
+ export interface AiReviewPRResponse {
239
+ summary: string;
240
+ issues: Array<{
241
+ severity: "critical" | "warning" | "suggestion";
242
+ description: string;
243
+ file?: string;
244
+ line?: number;
245
+ }>;
246
+ positives: string[];
247
+ verdict: "approve" | "request_changes" | "comment";
248
+ }
249
+ /** Inline comment on a specific file + line produced by the senior-dev review. */
250
+ export interface AiInlineComment {
251
+ /** Relative path to the file being commented on */
252
+ path: string;
253
+ /** The line number in the NEW (right) version of the file */
254
+ line: number;
255
+ /** The comment body (markdown supported) */
256
+ body: string;
257
+ /** Severity for local display */
258
+ severity: "critical" | "warning" | "suggestion";
259
+ /** Optional drop-in code suggestion (replaces the commented line) */
260
+ suggestion?: string;
261
+ }
262
+ /**
263
+ * Rich structured review response from the senior-dev AI reviewer.
264
+ * Supersedes the basic AiReviewPRResponse for the `gitx pr review` command.
265
+ */
266
+ export interface AiDetailedReviewResponse {
267
+ /** 3-5 sentence executive summary of the PR */
268
+ summary: string;
269
+ /** Verdict to submit to the hosting platform */
270
+ verdict: "approve" | "request_changes" | "comment";
271
+ /** High-level issues not tied to a specific line */
272
+ issues: Array<{
273
+ severity: "critical" | "warning" | "suggestion";
274
+ description: string;
275
+ file?: string;
276
+ line?: number;
277
+ }>;
278
+ /** Specific inline comments on changed lines */
279
+ inlineComments: AiInlineComment[];
280
+ /** Things done well in this PR */
281
+ positives: string[];
282
+ /** How to manually test the changes */
283
+ testingNotes: string;
284
+ /** Which review dimensions were checked */
285
+ checklist: Array<{
286
+ area: string;
287
+ status: "pass" | "warn" | "fail";
288
+ note: string;
289
+ }>;
43
290
  }
44
291
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ai/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAA;KAAE,CAAC,CAAC;CAChF;AAED,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjF;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3D,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAChE,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC/D,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACrE,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACjE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ai/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAA;KAAE,CAAC,CAAC;CAChF;AAED,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjF;AAED,MAAM,WAAW,uBAAuB;IACtC,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,4BAA4B;IAC3C,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;IAC3B,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB;AAID;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,eAAe,EAAE,OAAO,CAAC;IACzB,qFAAqF;IACrF,aAAa,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClF,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gDAAgD;IAChD,OAAO,EAAE,aAAa,CAAC;IACvB,qEAAqE;IACrE,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3D,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAChE,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC/D,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACrE,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAChE,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACxD,kEAAkE;IAClE,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACtE;;;;OAIG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAChG;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAElG;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE;QACnB,yCAAyC;QACzC,OAAO,EAAE,MAAM,CAAC;QAChB,4BAA4B;QAC5B,aAAa,EAAE,MAAM,CAAC;QACtB,2CAA2C;QAC3C,QAAQ,EAAE,MAAM,CAAC;QACjB,8CAA8C;QAC9C,IAAI,EAAE,MAAM,CAAC;QACb,mDAAmD;QACnD,WAAW,EAAE,MAAM,CAAC;QACpB,8CAA8C;QAC9C,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE3B;;;;;;OAMG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAErE;;;OAGG;IACH,gBAAgB,CAAC,OAAO,EAAE;QACxB,eAAe;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,qBAAqB;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,uBAAuB;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,yBAAyB;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,yBAAyB;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,qDAAqD;QACrD,IAAI,EAAE,MAAM,CAAC;QACb,iFAAiF;QACjF,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,qDAAqD;QACrD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,6DAA6D;QAC7D,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,2BAA2B;QAC3B,gBAAgB,EAAE,KAAK,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACzF,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;QACZ,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,YAAY,CAAC;QAChD,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAAC;CACpD;AAED,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,YAAY,CAAC;IAChD,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,OAAO,EAAE,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAAC;IACnD,oDAAoD;IACpD,MAAM,EAAE,KAAK,CAAC;QACZ,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,YAAY,CAAC;QAChD,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,gDAAgD;IAChD,cAAc,EAAE,eAAe,EAAE,CAAC;IAClC,kCAAkC;IAClC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,SAAS,EAAE,KAAK,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;QACjC,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ai/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface AiAnalyzeTaskResponse {\n task: string;\n intent: \"refactor\" | \"bugfix\" | \"feature\" | \"chore\" | \"unknown\";\n summary: string;\n assumptions: string[];\n risks: string[];\n}\n\nexport interface AiPlanStep {\n id: string;\n title: string;\n description: string;\n}\n\nexport interface AiGeneratePlanResponse {\n steps: AiPlanStep[];\n}\n\nexport interface AiGenerateDiffsResponse {\n stepId: string;\n diffs: Array<{ path: string; unifiedDiff: string }>;\n}\n\nexport interface AiSummarizeChangesResponse {\n summary: string;\n filesChanged: Array<{ path: string; changeType: \"add\" | \"modify\" | \"delete\" }>;\n}\n\nexport interface AiSuggestFixesResponse {\n suggestedEdits: Array<{ path: string; rationale: string; unifiedDiff: string }>;\n}\n\nexport interface AiClient {\n analyzeTask(input: string): Promise<AiAnalyzeTaskResponse>;\n generatePlan(context: unknown): Promise<AiGeneratePlanResponse>;\n generateDiffs(step: unknown): Promise<AiGenerateDiffsResponse>;\n summarizeChanges(diff: unknown): Promise<AiSummarizeChangesResponse>;\n suggestFixes(comment: unknown): Promise<AiSuggestFixesResponse>;\n}\n\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ai/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface AiAnalyzeTaskResponse {\n task: string;\n intent: \"refactor\" | \"bugfix\" | \"feature\" | \"chore\" | \"unknown\";\n summary: string;\n assumptions: string[];\n risks: string[];\n}\n\nexport interface AiPlanStep {\n id: string;\n title: string;\n description: string;\n}\n\nexport interface AiGeneratePlanResponse {\n steps: AiPlanStep[];\n}\n\nexport interface AiGenerateDiffsResponse {\n stepId: string;\n diffs: Array<{ path: string; unifiedDiff: string }>;\n}\n\nexport interface AiSummarizeChangesResponse {\n summary: string;\n filesChanged: Array<{ path: string; changeType: \"add\" | \"modify\" | \"delete\" }>;\n}\n\nexport interface AiSuggestFixesResponse {\n suggestedEdits: Array<{ path: string; rationale: string; unifiedDiff: string }>;\n}\n\nexport interface AiCommitMessageResponse {\n /** Full conventional commit subject line, e.g. \"feat(auth): add OAuth2 login flow\" */\n subject: string;\n /** Optional multi-line body explaining WHY the change was made */\n body?: string;\n}\n\nexport interface AiPrContentResponse {\n /** Short, human-readable PR title (not necessarily conventional-commit format) */\n title: string;\n /** Multi-paragraph PR description: what changed, why, how to test */\n body: string;\n}\n\nexport interface AiConflictResolutionResponse {\n /** The full file content with ALL conflict markers removed and conflicts resolved. */\n resolved: string;\n /**\n * \"high\" → AI is confident both sides are fully reconciled — safe to auto-apply.\n * \"low\" → Changes are contradictory or ambiguous — show to user for confirmation.\n */\n confidence: \"high\" | \"low\";\n /** One-sentence explanation of what the AI did (shown to the user). */\n explanation: string;\n}\n\n/**\n * AI-generated fix for a single PR review comment.\n * Targets a specific line range in a file with a minimal replacement.\n */\nexport interface AiFixResponse {\n /** Relative path to the file that needs to change */\n file: string;\n /** 1-based line number where the replacement starts */\n startLine: number;\n /** 1-based line number where the replacement ends (inclusive) */\n endLine: number;\n /**\n * The new code to replace lines startLine–endLine with.\n * Must preserve surrounding indentation style.\n */\n replacement: string;\n /** One-sentence explanation shown to the user */\n explanation: string;\n /**\n * \"high\" → safe to auto-apply without confirmation.\n * \"low\" → show diff and ask user before applying.\n */\n confidence: \"high\" | \"low\";\n /** Does this fix fully resolve the comment (vs partially)? */\n resolves: boolean;\n /**\n * true when the comment is a question / discussion with no code change needed.\n * In this case startLine/endLine/replacement are empty and should be ignored.\n */\n isDiscussion: boolean;\n}\n\n// ─── Ask command types ────────────────────────────────────────────────────────\n\n/**\n * Diagnostic snapshot of which AI provider is active and how it was resolved.\n * Keys are never included — only whether they are present.\n */\nexport interface AiSetupStatus {\n /**\n * Human-readable provider name, e.g. \"claude (Anthropic API)\", \"openai\", \"claude-cli (local)\", \"none\".\n * \"none\" means no provider is configured and MockAi will be used.\n */\n provider: string;\n /** Model in use, if applicable (e.g. \"claude-3-5-haiku-20241022\", \"gpt-4o\") */\n model?: string;\n /**\n * Where the key / credential came from:\n * \"ANTHROPIC_API_KEY env var\" | \"OPENAI_API_KEY env var\" | \"config file\" | \"local CLI\" | \"none\"\n */\n keySource: string;\n /** true when at least one real AI provider is available */\n isConfigured: boolean;\n}\n\n/**\n * Status of a single configured git hosting provider.\n * The actual token value is never included.\n */\nexport interface GitProviderStatus {\n /** \"github\" | \"gitlab\" | \"azure\" */\n name: string;\n /** true when a non-empty token exists for this provider */\n hasToken: boolean;\n}\n\n/**\n * Live repo context gathered by `gitx ask` and injected into the AI prompt.\n * All fields are optional so partial context still produces useful answers.\n */\nexport interface AiAskContext {\n /** Whether the CWD is inside a git repository */\n isInsideGitRepo: boolean;\n /** Current checked-out branch name (only meaningful when isInsideGitRepo is true) */\n currentBranch: string;\n /** Last 10 commits as one-line summaries (hash + subject) */\n recentCommits: string[];\n /** Output of `git status --short` */\n gitStatus: string;\n /** Open pull requests from the remote provider */\n openPRs?: Array<{ number: number; title: string; state: string; branch: string }>;\n /** Stash entries (e.g. \"stash@{0}: WIP on feat/x: abc1234 msg\") */\n stashes?: string[];\n /** Detailed status of the active AI provider */\n aiSetup: AiSetupStatus;\n /** All configured git hosting providers (github / gitlab / azure) */\n gitProviders: GitProviderStatus[];\n /** The configured default base branch, if any */\n defaultBranch?: string;\n}\n\n/** Response returned by `AiClient.ask()` for the `gitx ask` command. */\nexport interface AiAskResponse {\n /** Full answer in plain text or markdown */\n answer: string;\n /**\n * Concrete gitx (or git) commands the user can run to act on the answer.\n * Omit when not applicable.\n */\n suggestedCommands?: string[];\n}\n\nexport interface AiClient {\n analyzeTask(input: string): Promise<AiAnalyzeTaskResponse>;\n generatePlan(context: unknown): Promise<AiGeneratePlanResponse>;\n generateDiffs(step: unknown): Promise<AiGenerateDiffsResponse>;\n summarizeChanges(diff: unknown): Promise<AiSummarizeChangesResponse>;\n suggestFixes(comment: unknown): Promise<AiSuggestFixesResponse>;\n reviewPR(context: unknown): Promise<AiReviewPRResponse>;\n /** Generate a conventional commit message from a unified diff. */\n generateCommitMessage(diff: string): Promise<AiCommitMessageResponse>;\n /**\n * Generate a PR title and description from branch commits + diff.\n * Pass `stat` (output of `git diff --stat`) alongside the diff so the AI\n * sees every changed file even when the detailed patch is truncated.\n */\n generatePrContent(commits: string[], diff: string, stat?: string): Promise<AiPrContentResponse>;\n /**\n * Resolve git merge conflict markers in a file.\n * Returns the fully resolved file content + confidence level.\n */\n resolveConflict(filePath: string, conflictContent: string): Promise<AiConflictResolutionResponse>;\n\n /**\n * Generate a targeted fix for a single PR review comment.\n * Returns a line-range replacement (startLine–endLine → replacement).\n */\n generateFix(context: {\n /** The review comment text to address */\n comment: string;\n /** Author of the comment */\n commentAuthor: string;\n /** Relative file path the comment is on */\n filePath: string;\n /** 1-based line number the comment targets */\n line: number;\n /** Full current file content (after PR changes) */\n fileContent: string;\n /** The relevant diff section for this file */\n fileDiff: string;\n }): Promise<AiFixResponse>;\n\n /**\n * Answer a free-form question about the repo using live git context + AI.\n * Used by `gitx ask \"<question>\"`.\n *\n * @param question The raw question string from the user.\n * @param context Live repo state gathered by the ask command.\n */\n ask(question: string, context: AiAskContext): Promise<AiAskResponse>;\n\n /**\n * Senior-developer quality PR review with full codebase context.\n * Returns inline comments, checklist, and a formal verdict.\n */\n reviewPRDetailed(context: {\n /** PR title */\n prTitle: string;\n /** PR description */\n prBody: string;\n /** Author of the PR */\n author: string;\n /** Source branch name */\n headBranch: string;\n /** Target branch name */\n baseBranch: string;\n /** Full unified diff of the PR (may be truncated) */\n diff: string;\n /** Files changed — key: relative path, value: FULL file content after changes */\n changedFiles: Record<string, string>;\n /** Supporting context files the changes depend on */\n contextFiles: Record<string, string>;\n /** Flat list of all repo files (for structural awareness) */\n repoFileList: string[];\n /** Existing PR comments */\n existingComments: Array<{ author: string; body: string; path?: string; line?: number }>;\n }): Promise<AiDetailedReviewResponse>;\n}\n\nexport interface AiReviewPRResponse {\n summary: string;\n issues: Array<{\n severity: \"critical\" | \"warning\" | \"suggestion\";\n description: string;\n file?: string;\n line?: number;\n }>;\n positives: string[];\n verdict: \"approve\" | \"request_changes\" | \"comment\";\n}\n\n/** Inline comment on a specific file + line produced by the senior-dev review. */\nexport interface AiInlineComment {\n /** Relative path to the file being commented on */\n path: string;\n /** The line number in the NEW (right) version of the file */\n line: number;\n /** The comment body (markdown supported) */\n body: string;\n /** Severity for local display */\n severity: \"critical\" | \"warning\" | \"suggestion\";\n /** Optional drop-in code suggestion (replaces the commented line) */\n suggestion?: string;\n}\n\n/**\n * Rich structured review response from the senior-dev AI reviewer.\n * Supersedes the basic AiReviewPRResponse for the `gitx pr review` command.\n */\nexport interface AiDetailedReviewResponse {\n /** 3-5 sentence executive summary of the PR */\n summary: string;\n /** Verdict to submit to the hosting platform */\n verdict: \"approve\" | \"request_changes\" | \"comment\";\n /** High-level issues not tied to a specific line */\n issues: Array<{\n severity: \"critical\" | \"warning\" | \"suggestion\";\n description: string;\n file?: string;\n line?: number;\n }>;\n /** Specific inline comments on changed lines */\n inlineComments: AiInlineComment[];\n /** Things done well in this PR */\n positives: string[];\n /** How to manually test the changes */\n testingNotes: string;\n /** Which review dimensions were checked */\n checklist: Array<{\n area: string; // e.g. \"Security\", \"Performance\", \"Error handling\"\n status: \"pass\" | \"warn\" | \"fail\";\n note: string;\n }>;\n}\n"]}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `gitx ask "<question>"` — Smart support assistant for your repo.
3
+ *
4
+ * Acts as a support agent that can answer three types of questions:
5
+ *
6
+ * 1. SETUP / DIAGNOSTIC — "is my AI provider set up?", "why isn't gitx working?",
7
+ * "do I have a GitHub token configured?"
8
+ * → Reads your live gitx config and reports real status (no fabrication).
9
+ *
10
+ * 2. REPO STATE — "what did I last commit?", "do I have unstaged changes?",
11
+ * "show me all open PRs"
12
+ * → Reads live git state (branch, commits, status, stashes).
13
+ *
14
+ * 3. HOW-TO — "how do I sync with main?", "how do I undo my last commit?",
15
+ * "what command creates a PR?"
16
+ * → Uses built-in gitx command reference embedded in every prompt.
17
+ *
18
+ * Examples:
19
+ * gitx ask "is my AI provider set up?"
20
+ * gitx ask "what did I last commit?"
21
+ * gitx ask "how do I sync my branch with main?"
22
+ * gitx ask "do I have any open PRs?" --pr
23
+ * gitx ask "why is gitx not working?"
24
+ */
25
+ import type { Command } from "commander";
26
+ export declare function registerAskCommand(program: Command): void;
27
+ //# sourceMappingURL=ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ask.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyHzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8GzD"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * `gitx ask "<question>"` — Smart support assistant for your repo.
3
+ *
4
+ * Acts as a support agent that can answer three types of questions:
5
+ *
6
+ * 1. SETUP / DIAGNOSTIC — "is my AI provider set up?", "why isn't gitx working?",
7
+ * "do I have a GitHub token configured?"
8
+ * → Reads your live gitx config and reports real status (no fabrication).
9
+ *
10
+ * 2. REPO STATE — "what did I last commit?", "do I have unstaged changes?",
11
+ * "show me all open PRs"
12
+ * → Reads live git state (branch, commits, status, stashes).
13
+ *
14
+ * 3. HOW-TO — "how do I sync with main?", "how do I undo my last commit?",
15
+ * "what command creates a PR?"
16
+ * → Uses built-in gitx command reference embedded in every prompt.
17
+ *
18
+ * Examples:
19
+ * gitx ask "is my AI provider set up?"
20
+ * gitx ask "what did I last commit?"
21
+ * gitx ask "how do I sync my branch with main?"
22
+ * gitx ask "do I have any open PRs?" --pr
23
+ * gitx ask "why is gitx not working?"
24
+ */
25
+ import ora from "ora";
26
+ import chalk from "chalk";
27
+ import { Gitx } from "../../core/gitx.js";
28
+ import { logger } from "../../logger/logger.js";
29
+ import { getCurrentBranch, getGitStatus, getRecentCommits, getStashList, } from "../../utils/gitOps.js";
30
+ import { isInsideGitRepo } from "../../utils/git.js";
31
+ import { createProvider } from "../../providers/factory.js";
32
+ // ─── Config diagnostic helpers ────────────────────────────────────────────────
33
+ /**
34
+ * Inspect the loaded config + environment variables and return a plain-English
35
+ * snapshot of which AI provider is active — WITHOUT exposing actual key values.
36
+ */
37
+ function buildAiSetupStatus(config) {
38
+ // 1. ANTHROPIC_API_KEY env var (highest priority)
39
+ if (process.env["ANTHROPIC_API_KEY"]) {
40
+ const model = process.env["GITX_AI_MODEL"] ?? config.aiProviders?.claude?.model ?? "claude-3-5-haiku-20241022";
41
+ return {
42
+ provider: "claude (Anthropic API)",
43
+ model,
44
+ keySource: "ANTHROPIC_API_KEY env var",
45
+ isConfigured: true,
46
+ };
47
+ }
48
+ // 2. OPENAI_API_KEY env var
49
+ if (process.env["OPENAI_API_KEY"]) {
50
+ const model = process.env["GITX_AI_MODEL"] ?? config.aiProviders?.openai?.model ?? "gpt-4o";
51
+ return {
52
+ provider: "openai",
53
+ model,
54
+ keySource: "OPENAI_API_KEY env var",
55
+ isConfigured: true,
56
+ };
57
+ }
58
+ // 3. defaultAiProvider in config
59
+ const defaultProv = config.defaultAiProvider;
60
+ if (defaultProv) {
61
+ const entry = config.aiProviders?.[defaultProv];
62
+ if (defaultProv === "claude-cli") {
63
+ return {
64
+ provider: "claude-cli (local)",
65
+ keySource: "local CLI",
66
+ isConfigured: true,
67
+ };
68
+ }
69
+ if (entry?.apiKey) {
70
+ const model = process.env["GITX_AI_MODEL"] ?? entry.model ?? (defaultProv === "claude" ? "claude-3-5-haiku-20241022" : "gpt-4o");
71
+ return {
72
+ provider: defaultProv === "claude" ? "claude (Anthropic API)" : defaultProv,
73
+ model,
74
+ keySource: "config file",
75
+ isConfigured: true,
76
+ };
77
+ }
78
+ // defaultAiProvider set but key is missing
79
+ return {
80
+ provider: `${defaultProv} (key missing)`,
81
+ keySource: "config file (key missing — needs to be set)",
82
+ isConfigured: false,
83
+ };
84
+ }
85
+ // 4. Scan all aiProviders entries
86
+ const entries = Object.entries(config.aiProviders ?? {});
87
+ for (const [kind, entry] of entries) {
88
+ if (kind === "claude-cli") {
89
+ return {
90
+ provider: "claude-cli (local)",
91
+ keySource: "config file",
92
+ isConfigured: true,
93
+ };
94
+ }
95
+ if (entry?.apiKey) {
96
+ const model = process.env["GITX_AI_MODEL"] ?? entry.model;
97
+ return {
98
+ provider: kind === "claude" ? "claude (Anthropic API)" : kind,
99
+ model,
100
+ keySource: "config file",
101
+ isConfigured: true,
102
+ };
103
+ }
104
+ }
105
+ // 5. No provider found
106
+ return {
107
+ provider: "none (not configured)",
108
+ keySource: "none",
109
+ isConfigured: false,
110
+ };
111
+ }
112
+ /**
113
+ * Return the list of configured git hosting providers with a simple
114
+ * "has auth / missing auth" status. Never exposes actual token values.
115
+ * Recognises both PAT tokens and GCM (OAuth) as "configured".
116
+ */
117
+ function buildGitProviderStatus(config) {
118
+ const providers = config.providers ?? {};
119
+ const result = [];
120
+ for (const [name, entry] of Object.entries(providers)) {
121
+ const hasToken = entry?.authMethod === "gcm" ||
122
+ (!!entry?.token && entry.token.length > 0);
123
+ result.push({ name, hasToken });
124
+ }
125
+ return result;
126
+ }
127
+ // ─── Command ──────────────────────────────────────────────────────────────────
128
+ export function registerAskCommand(program) {
129
+ program
130
+ .command("ask")
131
+ .description("💬 Ask a question about your repo or gitx setup using AI")
132
+ .argument("<question>", "Your question (wrap in quotes for multi-word questions)")
133
+ .option("--pr", "Include open pull requests in the context (requires a provider token)")
134
+ .option("--no-color", "Disable colored output")
135
+ .action(async (question, options) => {
136
+ const cwd = process.cwd();
137
+ const gitx = await Gitx.fromCwd(cwd);
138
+ // ── 1. Build gitx setup diagnostics ───────────────────────────────────
139
+ const aiSetup = buildAiSetupStatus(gitx.config);
140
+ const gitProviders = buildGitProviderStatus(gitx.config);
141
+ const defaultBranch = gitx.config.defaultBranch;
142
+ // ── 2. Gather live git context ─────────────────────────────────────────
143
+ const contextSpinner = ora("🔍 Gathering context…").start();
144
+ let inRepo = false;
145
+ let currentBranch = "unknown";
146
+ let gitStatus = "";
147
+ let recentCommits = [];
148
+ let stashes = [];
149
+ try {
150
+ inRepo = await isInsideGitRepo(cwd);
151
+ if (inRepo) {
152
+ [currentBranch, gitStatus, recentCommits, stashes] = await Promise.all([
153
+ getCurrentBranch(cwd),
154
+ getGitStatus(cwd),
155
+ getRecentCommits(cwd, 10),
156
+ getStashList(cwd),
157
+ ]);
158
+ }
159
+ contextSpinner.succeed("Context gathered.");
160
+ }
161
+ catch {
162
+ contextSpinner.warn("Could not read full git context — proceeding with partial info.");
163
+ }
164
+ const context = {
165
+ isInsideGitRepo: inRepo,
166
+ currentBranch,
167
+ recentCommits,
168
+ gitStatus,
169
+ stashes: stashes.length > 0 ? stashes : undefined,
170
+ aiSetup,
171
+ gitProviders,
172
+ defaultBranch,
173
+ };
174
+ // ── 3. Optionally fetch open PRs ───────────────────────────────────────
175
+ const mentionsPR = /\bpr\b|pull request/i.test(question);
176
+ if (options.pr || mentionsPR) {
177
+ const prSpinner = ora("📋 Fetching open PRs…").start();
178
+ try {
179
+ const repoCtx = await gitx.getRepoContext();
180
+ const provider = createProvider(repoCtx);
181
+ const allPRs = await provider.listPRs(repoCtx.repoSlug);
182
+ const prs = allPRs.filter((pr) => pr.state === "open");
183
+ context.openPRs = prs.map((pr) => ({
184
+ number: pr.number,
185
+ title: pr.title,
186
+ state: pr.state,
187
+ branch: pr.head,
188
+ }));
189
+ prSpinner.succeed(`Found ${prs.length} open PR${prs.length !== 1 ? "s" : ""}.`);
190
+ }
191
+ catch {
192
+ prSpinner.warn("Could not fetch PRs — provider token may not be configured.");
193
+ }
194
+ }
195
+ // ── 4. Ask AI ──────────────────────────────────────────────────────────
196
+ const aiSpinner = ora("🤖 Thinking…").start();
197
+ let answer = "";
198
+ let suggestedCommands = [];
199
+ try {
200
+ const result = await gitx.ai.ask(question, context);
201
+ answer = result.answer;
202
+ suggestedCommands = result.suggestedCommands ?? [];
203
+ aiSpinner.succeed("Answer ready.");
204
+ }
205
+ catch (err) {
206
+ aiSpinner.fail("AI query failed.");
207
+ logger.error(err instanceof Error ? err.message : String(err));
208
+ process.exitCode = 1;
209
+ return;
210
+ }
211
+ // ── 5. Display answer ──────────────────────────────────────────────────
212
+ console.log("");
213
+ console.log(chalk.bold.cyan("╭─ gitx ask ─────────────────────────────────────────"));
214
+ console.log(chalk.gray("│ Q: ") + chalk.white(question));
215
+ console.log(chalk.bold.cyan("│"));
216
+ answer.split("\n").forEach((line) => {
217
+ console.log(chalk.bold.cyan("│") + " " + line);
218
+ });
219
+ if (suggestedCommands.length > 0) {
220
+ console.log(chalk.bold.cyan("│"));
221
+ console.log(chalk.bold.cyan("│") + " " + chalk.yellow.bold("💡 Suggested commands:"));
222
+ suggestedCommands.forEach((cmd) => {
223
+ console.log(chalk.bold.cyan("│") + " " + chalk.green(`$ ${cmd}`));
224
+ });
225
+ }
226
+ console.log(chalk.bold.cyan("╰────────────────────────────────────────────────────"));
227
+ console.log("");
228
+ });
229
+ }
230
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../../src/cli/commands/ask.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `gitx ask \"<question>\"` — Smart support assistant for your repo.\n *\n * Acts as a support agent that can answer three types of questions:\n *\n * 1. SETUP / DIAGNOSTIC — \"is my AI provider set up?\", \"why isn't gitx working?\",\n * \"do I have a GitHub token configured?\"\n * → Reads your live gitx config and reports real status (no fabrication).\n *\n * 2. REPO STATE — \"what did I last commit?\", \"do I have unstaged changes?\",\n * \"show me all open PRs\"\n * → Reads live git state (branch, commits, status, stashes).\n *\n * 3. HOW-TO — \"how do I sync with main?\", \"how do I undo my last commit?\",\n * \"what command creates a PR?\"\n * → Uses built-in gitx command reference embedded in every prompt.\n *\n * Examples:\n * gitx ask \"is my AI provider set up?\"\n * gitx ask \"what did I last commit?\"\n * gitx ask \"how do I sync my branch with main?\"\n * gitx ask \"do I have any open PRs?\" --pr\n * gitx ask \"why is gitx not working?\"\n */\n\nimport type { Command } from \"commander\";\nimport ora from \"ora\";\nimport chalk from \"chalk\";\nimport { Gitx } from \"../../core/gitx.js\";\nimport { logger } from \"../../logger/logger.js\";\nimport {\n getCurrentBranch,\n getGitStatus,\n getRecentCommits,\n getStashList,\n} from \"../../utils/gitOps.js\";\nimport { isInsideGitRepo } from \"../../utils/git.js\";\nimport { createProvider } from \"../../providers/factory.js\";\nimport type { AiAskContext, AiSetupStatus, GitProviderStatus } from \"../../ai/types.js\";\nimport type { GitxConfig } from \"../../types/config.js\";\n\n// ─── Config diagnostic helpers ────────────────────────────────────────────────\n\n/**\n * Inspect the loaded config + environment variables and return a plain-English\n * snapshot of which AI provider is active — WITHOUT exposing actual key values.\n */\nfunction buildAiSetupStatus(config: GitxConfig): AiSetupStatus {\n // 1. ANTHROPIC_API_KEY env var (highest priority)\n if (process.env[\"ANTHROPIC_API_KEY\"]) {\n const model = process.env[\"GITX_AI_MODEL\"] ?? config.aiProviders?.claude?.model ?? \"claude-3-5-haiku-20241022\";\n return {\n provider: \"claude (Anthropic API)\",\n model,\n keySource: \"ANTHROPIC_API_KEY env var\",\n isConfigured: true,\n };\n }\n\n // 2. OPENAI_API_KEY env var\n if (process.env[\"OPENAI_API_KEY\"]) {\n const model = process.env[\"GITX_AI_MODEL\"] ?? config.aiProviders?.openai?.model ?? \"gpt-4o\";\n return {\n provider: \"openai\",\n model,\n keySource: \"OPENAI_API_KEY env var\",\n isConfigured: true,\n };\n }\n\n // 3. defaultAiProvider in config\n const defaultProv = config.defaultAiProvider;\n if (defaultProv) {\n const entry = config.aiProviders?.[defaultProv];\n if (defaultProv === \"claude-cli\") {\n return {\n provider: \"claude-cli (local)\",\n keySource: \"local CLI\",\n isConfigured: true,\n };\n }\n if (entry?.apiKey) {\n const model = process.env[\"GITX_AI_MODEL\"] ?? entry.model ?? (defaultProv === \"claude\" ? \"claude-3-5-haiku-20241022\" : \"gpt-4o\");\n return {\n provider: defaultProv === \"claude\" ? \"claude (Anthropic API)\" : defaultProv,\n model,\n keySource: \"config file\",\n isConfigured: true,\n };\n }\n // defaultAiProvider set but key is missing\n return {\n provider: `${defaultProv} (key missing)`,\n keySource: \"config file (key missing — needs to be set)\",\n isConfigured: false,\n };\n }\n\n // 4. Scan all aiProviders entries\n const entries = Object.entries(config.aiProviders ?? {}) as Array<[string, { apiKey?: string; model?: string }]>;\n for (const [kind, entry] of entries) {\n if (kind === \"claude-cli\") {\n return {\n provider: \"claude-cli (local)\",\n keySource: \"config file\",\n isConfigured: true,\n };\n }\n if (entry?.apiKey) {\n const model = process.env[\"GITX_AI_MODEL\"] ?? entry.model;\n return {\n provider: kind === \"claude\" ? \"claude (Anthropic API)\" : kind,\n model,\n keySource: \"config file\",\n isConfigured: true,\n };\n }\n }\n\n // 5. No provider found\n return {\n provider: \"none (not configured)\",\n keySource: \"none\",\n isConfigured: false,\n };\n}\n\n/**\n * Return the list of configured git hosting providers with a simple\n * \"has auth / missing auth\" status. Never exposes actual token values.\n * Recognises both PAT tokens and GCM (OAuth) as \"configured\".\n */\nfunction buildGitProviderStatus(config: GitxConfig): GitProviderStatus[] {\n const providers = config.providers ?? {};\n const result: GitProviderStatus[] = [];\n for (const [name, entry] of Object.entries(providers)) {\n const hasToken =\n entry?.authMethod === \"gcm\" ||\n (!!entry?.token && entry.token.length > 0);\n result.push({ name, hasToken });\n }\n return result;\n}\n\n// ─── Command ──────────────────────────────────────────────────────────────────\n\nexport function registerAskCommand(program: Command): void {\n program\n .command(\"ask\")\n .description(\"💬 Ask a question about your repo or gitx setup using AI\")\n .argument(\"<question>\", \"Your question (wrap in quotes for multi-word questions)\")\n .option(\"--pr\", \"Include open pull requests in the context (requires a provider token)\")\n .option(\"--no-color\", \"Disable colored output\")\n .action(async (question: string, options: { pr?: boolean }) => {\n const cwd = process.cwd();\n const gitx = await Gitx.fromCwd(cwd);\n\n // ── 1. Build gitx setup diagnostics ───────────────────────────────────\n const aiSetup = buildAiSetupStatus(gitx.config);\n const gitProviders = buildGitProviderStatus(gitx.config);\n const defaultBranch = gitx.config.defaultBranch;\n\n // ── 2. Gather live git context ─────────────────────────────────────────\n const contextSpinner = ora(\"🔍 Gathering context…\").start();\n\n let inRepo = false;\n let currentBranch = \"unknown\";\n let gitStatus = \"\";\n let recentCommits: string[] = [];\n let stashes: string[] = [];\n\n try {\n inRepo = await isInsideGitRepo(cwd);\n\n if (inRepo) {\n [currentBranch, gitStatus, recentCommits, stashes] = await Promise.all([\n getCurrentBranch(cwd),\n getGitStatus(cwd),\n getRecentCommits(cwd, 10),\n getStashList(cwd),\n ]);\n }\n contextSpinner.succeed(\"Context gathered.\");\n } catch {\n contextSpinner.warn(\"Could not read full git context — proceeding with partial info.\");\n }\n\n const context: AiAskContext = {\n isInsideGitRepo: inRepo,\n currentBranch,\n recentCommits,\n gitStatus,\n stashes: stashes.length > 0 ? stashes : undefined,\n aiSetup,\n gitProviders,\n defaultBranch,\n };\n\n // ── 3. Optionally fetch open PRs ───────────────────────────────────────\n const mentionsPR = /\\bpr\\b|pull request/i.test(question);\n if (options.pr || mentionsPR) {\n const prSpinner = ora(\"📋 Fetching open PRs…\").start();\n try {\n const repoCtx = await gitx.getRepoContext();\n const provider = createProvider(repoCtx);\n const allPRs = await provider.listPRs(repoCtx.repoSlug);\n const prs = allPRs.filter((pr) => pr.state === \"open\");\n context.openPRs = prs.map((pr) => ({\n number: pr.number,\n title: pr.title,\n state: pr.state,\n branch: pr.head,\n }));\n prSpinner.succeed(`Found ${prs.length} open PR${prs.length !== 1 ? \"s\" : \"\"}.`);\n } catch {\n prSpinner.warn(\"Could not fetch PRs — provider token may not be configured.\");\n }\n }\n\n // ── 4. Ask AI ──────────────────────────────────────────────────────────\n const aiSpinner = ora(\"🤖 Thinking…\").start();\n let answer = \"\";\n let suggestedCommands: string[] = [];\n\n try {\n const result = await gitx.ai.ask(question, context);\n answer = result.answer;\n suggestedCommands = result.suggestedCommands ?? [];\n aiSpinner.succeed(\"Answer ready.\");\n } catch (err) {\n aiSpinner.fail(\"AI query failed.\");\n logger.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n return;\n }\n\n // ── 5. Display answer ──────────────────────────────────────────────────\n console.log(\"\");\n console.log(chalk.bold.cyan(\"╭─ gitx ask ─────────────────────────────────────────\"));\n console.log(chalk.gray(\"│ Q: \") + chalk.white(question));\n console.log(chalk.bold.cyan(\"│\"));\n answer.split(\"\\n\").forEach((line) => {\n console.log(chalk.bold.cyan(\"│\") + \" \" + line);\n });\n\n if (suggestedCommands.length > 0) {\n console.log(chalk.bold.cyan(\"│\"));\n console.log(chalk.bold.cyan(\"│\") + \" \" + chalk.yellow.bold(\"💡 Suggested commands:\"));\n suggestedCommands.forEach((cmd) => {\n console.log(chalk.bold.cyan(\"│\") + \" \" + chalk.green(`$ ${cmd}`));\n });\n }\n\n console.log(chalk.bold.cyan(\"╰────────────────────────────────────────────────────\"));\n console.log(\"\");\n });\n}\n"]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * gitx commit
3
+ *
4
+ * AI-powered commit: detects what changed, generates a meaningful
5
+ * conventional-commit message, commits, and optionally pushes.
6
+ *
7
+ * Usage:
8
+ * gitx commit # AI generates message, prompts to confirm
9
+ * gitx commit -m "fix: typo" # use custom message, skip AI
10
+ * gitx commit --push # commit + push in one step
11
+ * gitx commit --no-push # commit only (default)
12
+ * gitx commit --dry-run # preview message, do not commit
13
+ */
14
+ import type { Command } from "commander";
15
+ export declare function registerCommitCommand(program: Command): void;
16
+ //# sourceMappingURL=commit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/commit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+J5D"}