gencode-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +11 -0
- package/CLAUDE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agent/agent.d.ts +84 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +233 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/types.d.ts +47 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/components/App.d.ts +14 -0
- package/dist/cli/components/App.d.ts.map +1 -0
- package/dist/cli/components/App.js +395 -0
- package/dist/cli/components/App.js.map +1 -0
- package/dist/cli/components/CommandSuggestions.d.ts +13 -0
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/cli/components/CommandSuggestions.js +32 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -0
- package/dist/cli/components/Header.d.ts +9 -0
- package/dist/cli/components/Header.d.ts.map +1 -0
- package/dist/cli/components/Header.js +13 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/Input.d.ts +13 -0
- package/dist/cli/components/Input.d.ts.map +1 -0
- package/dist/cli/components/Input.js +27 -0
- package/dist/cli/components/Input.js.map +1 -0
- package/dist/cli/components/Logo.d.ts +2 -0
- package/dist/cli/components/Logo.d.ts.map +1 -0
- package/dist/cli/components/Logo.js +8 -0
- package/dist/cli/components/Logo.js.map +1 -0
- package/dist/cli/components/Messages.d.ts +37 -0
- package/dist/cli/components/Messages.d.ts.map +1 -0
- package/dist/cli/components/Messages.js +106 -0
- package/dist/cli/components/Messages.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +13 -0
- package/dist/cli/components/ModelSelector.d.ts.map +1 -0
- package/dist/cli/components/ModelSelector.js +72 -0
- package/dist/cli/components/ModelSelector.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +12 -0
- package/dist/cli/components/Spinner.d.ts.map +1 -0
- package/dist/cli/components/Spinner.js +45 -0
- package/dist/cli/components/Spinner.js.map +1 -0
- package/dist/cli/components/index.d.ts +12 -0
- package/dist/cli/components/index.d.ts.map +1 -0
- package/dist/cli/components/index.js +12 -0
- package/dist/cli/components/index.js.map +1 -0
- package/dist/cli/components/theme.d.ts +31 -0
- package/dist/cli/components/theme.d.ts.map +1 -0
- package/dist/cli/components/theme.js +36 -0
- package/dist/cli/components/theme.js.map +1 -0
- package/dist/cli/index-legacy.d.ts +7 -0
- package/dist/cli/index-legacy.d.ts.map +1 -0
- package/dist/cli/index-legacy.js +431 -0
- package/dist/cli/index-legacy.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +116 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ink-cli.d.ts +7 -0
- package/dist/cli/ink-cli.d.ts.map +1 -0
- package/dist/cli/ink-cli.js +105 -0
- package/dist/cli/ink-cli.js.map +1 -0
- package/dist/cli/session-picker.d.ts +16 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +280 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/ui.d.ts +61 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +364 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +31 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +65 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/init.d.ts +20 -0
- package/dist/memory/init.d.ts.map +1 -0
- package/dist/memory/init.js +332 -0
- package/dist/memory/init.js.map +1 -0
- package/dist/memory/manager.d.ts +85 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +234 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/types.d.ts +74 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +6 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/index.d.ts +7 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +6 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +32 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +79 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/types.d.ts +14 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +20 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +185 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +21 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +241 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +34 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +19 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +221 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +125 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +101 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +295 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +39 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +7 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +80 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +7 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +32 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +7 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +36 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +7 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +59 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +7 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +29 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +7 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +24 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +22 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +62 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +126 -0
- package/dist/tools/types.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/proposals/0001-web-fetch-tool.md +293 -0
- package/docs/proposals/0002-web-search-tool.md +306 -0
- package/docs/proposals/0003-task-subagents.md +333 -0
- package/docs/proposals/0004-plan-mode.md +338 -0
- package/docs/proposals/0005-todo-system.md +299 -0
- package/docs/proposals/0006-memory-system.md +539 -0
- package/docs/proposals/0007-context-management.md +429 -0
- package/docs/proposals/0008-checkpointing.md +327 -0
- package/docs/proposals/0009-hooks-system.md +343 -0
- package/docs/proposals/0010-mcp-integration.md +382 -0
- package/docs/proposals/0011-custom-commands.md +374 -0
- package/docs/proposals/0012-ask-user-question.md +317 -0
- package/docs/proposals/0013-multi-edit-tool.md +345 -0
- package/docs/proposals/0014-lsp-tool.md +478 -0
- package/docs/proposals/0015-ls-tool.md +407 -0
- package/docs/proposals/0016-kill-shell-tool.md +455 -0
- package/docs/proposals/0017-background-tasks.md +489 -0
- package/docs/proposals/0018-parallel-tool-execution.md +415 -0
- package/docs/proposals/0019-session-enhancements.md +462 -0
- package/docs/proposals/0020-session-summarization.md +447 -0
- package/docs/proposals/0021-skills-system.md +409 -0
- package/docs/proposals/0022-plugin-system.md +467 -0
- package/docs/proposals/0023-permission-enhancements.md +470 -0
- package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
- package/docs/proposals/0025-cost-tracking.md +447 -0
- package/docs/proposals/0026-git-integration.md +475 -0
- package/docs/proposals/0027-enhanced-read-tool.md +514 -0
- package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
- package/docs/proposals/0029-notebook-edit-tool.md +413 -0
- package/docs/proposals/0030-plugin-marketplace.md +360 -0
- package/docs/proposals/0031-command-suggestions.md +295 -0
- package/docs/proposals/0032-ide-integrations.md +328 -0
- package/docs/proposals/0033-enterprise-deployment.md +221 -0
- package/docs/proposals/0034-sandboxing.md +273 -0
- package/docs/proposals/0035-auto-updater.md +311 -0
- package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
- package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
- package/docs/proposals/0038-interactive-cli-ui.md +373 -0
- package/docs/proposals/0039-streaming-enhancements.md +359 -0
- package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
- package/docs/proposals/README.md +84 -0
- package/docs/proposals/TEMPLATE.md +57 -0
- package/docs/proposals/research/claude-code-research.md +307 -0
- package/examples/agent-demo.ts +115 -0
- package/examples/basic.ts +166 -0
- package/package.json +50 -0
- package/src/agent/agent.ts +276 -0
- package/src/agent/index.ts +6 -0
- package/src/agent/types.ts +62 -0
- package/src/cli/components/App.tsx +565 -0
- package/src/cli/components/CommandSuggestions.tsx +58 -0
- package/src/cli/components/Header.tsx +36 -0
- package/src/cli/components/Input.tsx +60 -0
- package/src/cli/components/Logo.tsx +16 -0
- package/src/cli/components/Messages.tsx +210 -0
- package/src/cli/components/ModelSelector.tsx +135 -0
- package/src/cli/components/Spinner.tsx +72 -0
- package/src/cli/components/index.ts +21 -0
- package/src/cli/components/theme.ts +36 -0
- package/src/cli/index.tsx +136 -0
- package/src/config/index.ts +7 -0
- package/src/config/manager.ts +77 -0
- package/src/config/types.ts +25 -0
- package/src/index.ts +86 -0
- package/src/permissions/index.ts +7 -0
- package/src/permissions/manager.ts +97 -0
- package/src/permissions/types.ts +29 -0
- package/src/providers/anthropic.ts +224 -0
- package/src/providers/gemini.ts +295 -0
- package/src/providers/index.ts +97 -0
- package/src/providers/openai.ts +261 -0
- package/src/providers/types.ts +181 -0
- package/src/session/index.ts +6 -0
- package/src/session/manager.ts +354 -0
- package/src/session/types.ts +49 -0
- package/src/tools/builtin/bash.ts +92 -0
- package/src/tools/builtin/edit.ts +37 -0
- package/src/tools/builtin/glob.ts +42 -0
- package/src/tools/builtin/grep.ts +67 -0
- package/src/tools/builtin/read.ts +34 -0
- package/src/tools/builtin/write.ts +27 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/registry.ts +83 -0
- package/src/tools/types.ts +172 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
# Proposal: Git Integration
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0026
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement native Git integration with specialized tools and workflows for version control operations. This provides the agent with git-aware context and safe commit/PR creation capabilities.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Currently, mycode uses Bash for all git operations:
|
|
16
|
+
|
|
17
|
+
1. **No git awareness**: Agent doesn't know repo state
|
|
18
|
+
2. **Unsafe operations**: Easy to run destructive commands
|
|
19
|
+
3. **Manual workflows**: PR creation is multi-step
|
|
20
|
+
4. **No diff context**: Agent doesn't see changes
|
|
21
|
+
5. **Repetitive prompts**: Same git patterns repeated
|
|
22
|
+
|
|
23
|
+
Native git integration enables safe, efficient version control.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code provides extensive git integration:
|
|
28
|
+
|
|
29
|
+
### Git Safety Protocol
|
|
30
|
+
```
|
|
31
|
+
- NEVER update the git config
|
|
32
|
+
- NEVER run destructive/irreversible commands (force push, hard reset)
|
|
33
|
+
- NEVER skip hooks (--no-verify)
|
|
34
|
+
- NEVER force push to main/master
|
|
35
|
+
- Avoid git commit --amend unless conditions are met
|
|
36
|
+
- NEVER commit unless explicitly asked
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Commit Workflow
|
|
40
|
+
```
|
|
41
|
+
1. Run git status (never use -uall flag)
|
|
42
|
+
2. Run git diff for staged/unstaged changes
|
|
43
|
+
3. Run git log for recent commit style
|
|
44
|
+
4. Analyze changes, draft commit message
|
|
45
|
+
5. Add files, create commit with:
|
|
46
|
+
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
47
|
+
6. Run git status to verify
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### PR Creation Workflow
|
|
51
|
+
```
|
|
52
|
+
1. git status, git diff, check remote tracking
|
|
53
|
+
2. git log and git diff [base]...HEAD for commit history
|
|
54
|
+
3. Create branch if needed
|
|
55
|
+
4. Push with -u flag
|
|
56
|
+
5. Create PR with gh pr create
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Detailed Design
|
|
60
|
+
|
|
61
|
+
### API Design
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// src/git/types.ts
|
|
65
|
+
interface GitContext {
|
|
66
|
+
isRepo: boolean;
|
|
67
|
+
branch: string;
|
|
68
|
+
remoteBranch?: string;
|
|
69
|
+
defaultBranch: string;
|
|
70
|
+
hasUncommittedChanges: boolean;
|
|
71
|
+
hasUntrackedFiles: boolean;
|
|
72
|
+
aheadBehind?: { ahead: number; behind: number };
|
|
73
|
+
lastCommit?: {
|
|
74
|
+
hash: string;
|
|
75
|
+
message: string;
|
|
76
|
+
author: string;
|
|
77
|
+
date: Date;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface GitStatus {
|
|
82
|
+
staged: FileChange[];
|
|
83
|
+
unstaged: FileChange[];
|
|
84
|
+
untracked: string[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface FileChange {
|
|
88
|
+
path: string;
|
|
89
|
+
status: 'added' | 'modified' | 'deleted' | 'renamed';
|
|
90
|
+
oldPath?: string; // For renames
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface CommitOptions {
|
|
94
|
+
message: string;
|
|
95
|
+
files?: string[]; // Specific files (default: staged)
|
|
96
|
+
coAuthor?: string; // Co-author for attribution
|
|
97
|
+
signOff?: boolean; // DCO sign-off
|
|
98
|
+
allowEmpty?: boolean;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface PROptions {
|
|
102
|
+
title: string;
|
|
103
|
+
body: string;
|
|
104
|
+
base?: string; // Base branch
|
|
105
|
+
draft?: boolean;
|
|
106
|
+
labels?: string[];
|
|
107
|
+
reviewers?: string[];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Safety constraints
|
|
111
|
+
interface GitSafetyConfig {
|
|
112
|
+
blockDestructive: boolean; // Block force push, hard reset
|
|
113
|
+
requireConfirmation: string[]; // Commands needing confirmation
|
|
114
|
+
protectedBranches: string[]; // Branches that can't be modified
|
|
115
|
+
requireSignOff: boolean;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Git Tool
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// src/tools/git/git-tool.ts
|
|
123
|
+
const gitTool: Tool<GitInput> = {
|
|
124
|
+
name: 'Git',
|
|
125
|
+
description: `Perform git operations safely.
|
|
126
|
+
|
|
127
|
+
Operations:
|
|
128
|
+
- status: Get repository status
|
|
129
|
+
- diff: Show changes (staged, unstaged, or between refs)
|
|
130
|
+
- log: Show commit history
|
|
131
|
+
- add: Stage files for commit
|
|
132
|
+
- commit: Create a commit
|
|
133
|
+
- branch: List, create, or switch branches
|
|
134
|
+
- push: Push commits to remote
|
|
135
|
+
- pull: Pull changes from remote
|
|
136
|
+
- stash: Stash/unstash changes
|
|
137
|
+
- pr: Create a pull request (requires gh)
|
|
138
|
+
|
|
139
|
+
Safety features:
|
|
140
|
+
- Blocks destructive operations (force push, hard reset)
|
|
141
|
+
- Requires confirmation for commits
|
|
142
|
+
- Never modifies git config
|
|
143
|
+
- Protects main/master branches
|
|
144
|
+
|
|
145
|
+
Use this tool instead of Bash for git operations.
|
|
146
|
+
`,
|
|
147
|
+
parameters: z.object({
|
|
148
|
+
operation: z.enum([
|
|
149
|
+
'status', 'diff', 'log', 'add', 'commit',
|
|
150
|
+
'branch', 'push', 'pull', 'stash', 'pr'
|
|
151
|
+
]),
|
|
152
|
+
args: z.record(z.unknown()).optional()
|
|
153
|
+
}),
|
|
154
|
+
execute: async (input, context) => {
|
|
155
|
+
return await gitService.execute(input.operation, input.args, context);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Git Service
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
// src/git/service.ts
|
|
164
|
+
class GitService {
|
|
165
|
+
private safety: GitSafetyConfig;
|
|
166
|
+
private gitContext: GitContext | null = null;
|
|
167
|
+
|
|
168
|
+
constructor(safety?: Partial<GitSafetyConfig>) {
|
|
169
|
+
this.safety = {
|
|
170
|
+
blockDestructive: true,
|
|
171
|
+
requireConfirmation: ['commit', 'push', 'reset'],
|
|
172
|
+
protectedBranches: ['main', 'master'],
|
|
173
|
+
requireSignOff: false,
|
|
174
|
+
...safety
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async execute(
|
|
179
|
+
operation: string,
|
|
180
|
+
args: Record<string, unknown> = {},
|
|
181
|
+
context: ToolContext
|
|
182
|
+
): Promise<ToolResult> {
|
|
183
|
+
// Refresh context
|
|
184
|
+
this.gitContext = await this.getContext(context.cwd);
|
|
185
|
+
|
|
186
|
+
if (!this.gitContext.isRepo) {
|
|
187
|
+
return { success: false, error: 'Not a git repository' };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
switch (operation) {
|
|
191
|
+
case 'status':
|
|
192
|
+
return this.status(context.cwd);
|
|
193
|
+
case 'diff':
|
|
194
|
+
return this.diff(args, context.cwd);
|
|
195
|
+
case 'log':
|
|
196
|
+
return this.log(args, context.cwd);
|
|
197
|
+
case 'add':
|
|
198
|
+
return this.add(args, context.cwd);
|
|
199
|
+
case 'commit':
|
|
200
|
+
return this.commit(args as CommitOptions, context.cwd);
|
|
201
|
+
case 'branch':
|
|
202
|
+
return this.branch(args, context.cwd);
|
|
203
|
+
case 'push':
|
|
204
|
+
return this.push(args, context.cwd);
|
|
205
|
+
case 'pull':
|
|
206
|
+
return this.pull(context.cwd);
|
|
207
|
+
case 'stash':
|
|
208
|
+
return this.stash(args, context.cwd);
|
|
209
|
+
case 'pr':
|
|
210
|
+
return this.createPR(args as PROptions, context.cwd);
|
|
211
|
+
default:
|
|
212
|
+
return { success: false, error: `Unknown operation: ${operation}` };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private async status(cwd: string): Promise<ToolResult> {
|
|
217
|
+
const result = await this.runGit(['status', '--porcelain=v2', '--branch'], cwd);
|
|
218
|
+
|
|
219
|
+
if (!result.success) return result;
|
|
220
|
+
|
|
221
|
+
const status = this.parseStatus(result.output);
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
success: true,
|
|
225
|
+
output: this.formatStatus(status)
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private async diff(args: Record<string, unknown>, cwd: string): Promise<ToolResult> {
|
|
230
|
+
const gitArgs = ['diff'];
|
|
231
|
+
|
|
232
|
+
if (args.staged) gitArgs.push('--staged');
|
|
233
|
+
if (args.ref) gitArgs.push(args.ref as string);
|
|
234
|
+
if (args.stat) gitArgs.push('--stat');
|
|
235
|
+
|
|
236
|
+
return this.runGit(gitArgs, cwd);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private async commit(options: CommitOptions, cwd: string): Promise<ToolResult> {
|
|
240
|
+
// Safety checks
|
|
241
|
+
if (!options.message) {
|
|
242
|
+
return { success: false, error: 'Commit message required' };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Build commit message with co-author
|
|
246
|
+
let message = options.message;
|
|
247
|
+
if (options.coAuthor) {
|
|
248
|
+
message += `\n\nCo-Authored-By: ${options.coAuthor}`;
|
|
249
|
+
}
|
|
250
|
+
if (options.signOff || this.safety.requireSignOff) {
|
|
251
|
+
// Add DCO sign-off
|
|
252
|
+
const user = await this.getGitConfig('user.name', cwd);
|
|
253
|
+
const email = await this.getGitConfig('user.email', cwd);
|
|
254
|
+
message += `\n\nSigned-off-by: ${user} <${email}>`;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Add specific files if provided
|
|
258
|
+
if (options.files?.length) {
|
|
259
|
+
const addResult = await this.runGit(['add', ...options.files], cwd);
|
|
260
|
+
if (!addResult.success) return addResult;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Create commit using heredoc for message
|
|
264
|
+
const commitArgs = ['commit', '-m', message];
|
|
265
|
+
if (options.allowEmpty) commitArgs.push('--allow-empty');
|
|
266
|
+
|
|
267
|
+
return this.runGit(commitArgs, cwd);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private async createPR(options: PROptions, cwd: string): Promise<ToolResult> {
|
|
271
|
+
// Check for gh CLI
|
|
272
|
+
const ghCheck = await this.runCommand('which', ['gh'], cwd);
|
|
273
|
+
if (!ghCheck.success) {
|
|
274
|
+
return { success: false, error: 'GitHub CLI (gh) not installed' };
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const args = [
|
|
278
|
+
'pr', 'create',
|
|
279
|
+
'--title', options.title,
|
|
280
|
+
'--body', options.body
|
|
281
|
+
];
|
|
282
|
+
|
|
283
|
+
if (options.base) args.push('--base', options.base);
|
|
284
|
+
if (options.draft) args.push('--draft');
|
|
285
|
+
if (options.labels?.length) args.push('--label', options.labels.join(','));
|
|
286
|
+
if (options.reviewers?.length) args.push('--reviewer', options.reviewers.join(','));
|
|
287
|
+
|
|
288
|
+
return this.runCommand('gh', args, cwd);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private async push(args: Record<string, unknown>, cwd: string): Promise<ToolResult> {
|
|
292
|
+
// Safety: block force push
|
|
293
|
+
if (args.force && this.safety.blockDestructive) {
|
|
294
|
+
return { success: false, error: 'Force push is blocked for safety. Use --force explicitly in Bash if needed.' };
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Safety: protect main branches
|
|
298
|
+
const branch = this.gitContext?.branch;
|
|
299
|
+
if (branch && this.safety.protectedBranches.includes(branch) && args.force) {
|
|
300
|
+
return { success: false, error: `Force push to ${branch} is not allowed` };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const gitArgs = ['push'];
|
|
304
|
+
if (args.upstream) gitArgs.push('-u', 'origin', branch || 'HEAD');
|
|
305
|
+
if (args.tags) gitArgs.push('--tags');
|
|
306
|
+
|
|
307
|
+
return this.runGit(gitArgs, cwd);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async getContext(cwd: string): Promise<GitContext> {
|
|
311
|
+
// ... implementation
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private async runGit(args: string[], cwd: string): Promise<ToolResult> {
|
|
315
|
+
return this.runCommand('git', args, cwd);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export const gitService = new GitService();
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### File Changes
|
|
323
|
+
|
|
324
|
+
| File | Action | Description |
|
|
325
|
+
|------|--------|-------------|
|
|
326
|
+
| `src/git/types.ts` | Create | Type definitions |
|
|
327
|
+
| `src/git/service.ts` | Create | Git operations |
|
|
328
|
+
| `src/git/safety.ts` | Create | Safety checks |
|
|
329
|
+
| `src/git/parsers.ts` | Create | Output parsing |
|
|
330
|
+
| `src/git/index.ts` | Create | Module exports |
|
|
331
|
+
| `src/tools/git/git-tool.ts` | Create | Git tool |
|
|
332
|
+
| `src/agent/agent.ts` | Modify | Inject git context |
|
|
333
|
+
|
|
334
|
+
## User Experience
|
|
335
|
+
|
|
336
|
+
### Git Status in Prompt
|
|
337
|
+
```
|
|
338
|
+
┌─ mycode [main ↑2] ────────────────────────────────────────┐
|
|
339
|
+
│ > help me commit these changes │
|
|
340
|
+
└───────────────────────────────────────────────────────────┘
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Safe Commit Workflow
|
|
344
|
+
```
|
|
345
|
+
User: Commit these changes
|
|
346
|
+
|
|
347
|
+
Agent: Let me check the current repository status.
|
|
348
|
+
|
|
349
|
+
[Git: status]
|
|
350
|
+
|
|
351
|
+
Current branch: feature/auth
|
|
352
|
+
Changes to commit:
|
|
353
|
+
M src/auth.ts
|
|
354
|
+
M src/auth.test.ts
|
|
355
|
+
A src/types/auth.ts
|
|
356
|
+
|
|
357
|
+
[Git: diff staged]
|
|
358
|
+
|
|
359
|
+
I can see you've:
|
|
360
|
+
- Added JWT token validation
|
|
361
|
+
- Created new auth types
|
|
362
|
+
- Updated tests
|
|
363
|
+
|
|
364
|
+
Suggested commit message:
|
|
365
|
+
"feat: add JWT token validation to auth module"
|
|
366
|
+
|
|
367
|
+
[Git: commit message="feat: add JWT token validation..." coAuthor="Claude..."]
|
|
368
|
+
|
|
369
|
+
✓ Commit created: abc1234
|
|
370
|
+
|
|
371
|
+
[Git: status]
|
|
372
|
+
|
|
373
|
+
Branch is ahead of origin/feature/auth by 1 commit.
|
|
374
|
+
Push to remote?
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### PR Creation
|
|
378
|
+
```
|
|
379
|
+
User: Create a PR for this
|
|
380
|
+
|
|
381
|
+
Agent: I'll create a pull request for your changes.
|
|
382
|
+
|
|
383
|
+
[Git: log base=main]
|
|
384
|
+
[Git: diff main...HEAD stat=true]
|
|
385
|
+
|
|
386
|
+
This PR includes 3 commits:
|
|
387
|
+
- feat: add JWT validation
|
|
388
|
+
- test: add auth tests
|
|
389
|
+
- docs: update auth README
|
|
390
|
+
|
|
391
|
+
[Git: pr
|
|
392
|
+
title="feat: JWT token validation"
|
|
393
|
+
body="## Summary\n- Added JWT validation..."
|
|
394
|
+
base="main"
|
|
395
|
+
]
|
|
396
|
+
|
|
397
|
+
✓ Pull request created: https://github.com/org/repo/pull/123
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Safety Block
|
|
401
|
+
```
|
|
402
|
+
Agent: [Git: push force=true]
|
|
403
|
+
|
|
404
|
+
⚠️ Operation Blocked
|
|
405
|
+
|
|
406
|
+
Force push is not allowed for safety.
|
|
407
|
+
If you really need to force push, use Bash:
|
|
408
|
+
bash: git push --force
|
|
409
|
+
|
|
410
|
+
This requires explicit user confirmation.
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Alternatives Considered
|
|
414
|
+
|
|
415
|
+
### Alternative 1: Bash Only
|
|
416
|
+
Continue using Bash for all git operations.
|
|
417
|
+
|
|
418
|
+
**Pros**: Simpler, full git access
|
|
419
|
+
**Cons**: No safety, no context awareness
|
|
420
|
+
**Decision**: Rejected - Safety is important
|
|
421
|
+
|
|
422
|
+
### Alternative 2: Read-only Git
|
|
423
|
+
Only provide git status/diff/log.
|
|
424
|
+
|
|
425
|
+
**Pros**: Maximum safety
|
|
426
|
+
**Cons**: Too limiting for workflows
|
|
427
|
+
**Decision**: Rejected - Need commit/push
|
|
428
|
+
|
|
429
|
+
### Alternative 3: External Git UI
|
|
430
|
+
Integrate with GitKraken/Tower.
|
|
431
|
+
|
|
432
|
+
**Pros**: Rich UI
|
|
433
|
+
**Cons**: Heavy dependency
|
|
434
|
+
**Decision**: Rejected - CLI-first approach
|
|
435
|
+
|
|
436
|
+
## Security Considerations
|
|
437
|
+
|
|
438
|
+
1. **Credential Handling**: Use git credential helpers
|
|
439
|
+
2. **Remote Validation**: Verify remote URLs
|
|
440
|
+
3. **Branch Protection**: Honor branch rules
|
|
441
|
+
4. **Commit Signing**: Support GPG signing
|
|
442
|
+
5. **Token Exposure**: Don't log auth tokens
|
|
443
|
+
|
|
444
|
+
## Testing Strategy
|
|
445
|
+
|
|
446
|
+
1. **Unit Tests**:
|
|
447
|
+
- Status parsing
|
|
448
|
+
- Safety checks
|
|
449
|
+
- Command building
|
|
450
|
+
|
|
451
|
+
2. **Integration Tests**:
|
|
452
|
+
- Full commit workflow
|
|
453
|
+
- PR creation
|
|
454
|
+
- Branch operations
|
|
455
|
+
|
|
456
|
+
3. **Safety Tests**:
|
|
457
|
+
- Destructive command blocking
|
|
458
|
+
- Protected branch enforcement
|
|
459
|
+
|
|
460
|
+
## Migration Path
|
|
461
|
+
|
|
462
|
+
1. **Phase 1**: Basic status/diff/log
|
|
463
|
+
2. **Phase 2**: Add/commit with safety
|
|
464
|
+
3. **Phase 3**: Push/pull operations
|
|
465
|
+
4. **Phase 4**: PR creation (gh integration)
|
|
466
|
+
5. **Phase 5**: Advanced workflows
|
|
467
|
+
|
|
468
|
+
Bash git commands remain available.
|
|
469
|
+
|
|
470
|
+
## References
|
|
471
|
+
|
|
472
|
+
- [Git Documentation](https://git-scm.com/doc)
|
|
473
|
+
- [GitHub CLI](https://cli.github.com/)
|
|
474
|
+
- [Conventional Commits](https://www.conventionalcommits.org/)
|
|
475
|
+
- [DCO Sign-off](https://developercertificate.org/)
|