@compilr-dev/agents-coding 0.0.1
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/README.md +788 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +75 -0
- package/dist/skills/index.d.ts +39 -0
- package/dist/skills/index.js +322 -0
- package/dist/tools/git/branch.d.ts +17 -0
- package/dist/tools/git/branch.js +264 -0
- package/dist/tools/git/commit.d.ts +23 -0
- package/dist/tools/git/commit.js +280 -0
- package/dist/tools/git/diff.d.ts +19 -0
- package/dist/tools/git/diff.js +221 -0
- package/dist/tools/git/index.d.ts +10 -0
- package/dist/tools/git/index.js +11 -0
- package/dist/tools/git/log.d.ts +19 -0
- package/dist/tools/git/log.js +235 -0
- package/dist/tools/git/stash.d.ts +17 -0
- package/dist/tools/git/stash.js +294 -0
- package/dist/tools/git/status.d.ts +19 -0
- package/dist/tools/git/status.js +160 -0
- package/dist/tools/git/types.d.ts +293 -0
- package/dist/tools/git/types.js +4 -0
- package/dist/tools/git/utils.d.ts +58 -0
- package/dist/tools/git/utils.js +197 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/project/detect.d.ts +19 -0
- package/dist/tools/project/detect.js +341 -0
- package/dist/tools/project/find-root.d.ts +21 -0
- package/dist/tools/project/find-root.js +239 -0
- package/dist/tools/project/index.d.ts +6 -0
- package/dist/tools/project/index.js +5 -0
- package/dist/tools/project/types.d.ts +83 -0
- package/dist/tools/project/types.js +4 -0
- package/dist/tools/runners/build.d.ts +19 -0
- package/dist/tools/runners/build.js +306 -0
- package/dist/tools/runners/format.d.ts +19 -0
- package/dist/tools/runners/format.js +376 -0
- package/dist/tools/runners/index.d.ts +9 -0
- package/dist/tools/runners/index.js +9 -0
- package/dist/tools/runners/lint.d.ts +19 -0
- package/dist/tools/runners/lint.js +356 -0
- package/dist/tools/runners/test.d.ts +19 -0
- package/dist/tools/runners/test.js +386 -0
- package/dist/tools/runners/types.d.ts +97 -0
- package/dist/tools/runners/types.js +4 -0
- package/dist/tools/runners/utils.d.ts +69 -0
- package/dist/tools/runners/utils.js +179 -0
- package/dist/tools/search/definition.d.ts +19 -0
- package/dist/tools/search/definition.js +305 -0
- package/dist/tools/search/index.d.ts +8 -0
- package/dist/tools/search/index.js +8 -0
- package/dist/tools/search/references.d.ts +19 -0
- package/dist/tools/search/references.js +179 -0
- package/dist/tools/search/todos.d.ts +19 -0
- package/dist/tools/search/todos.js +269 -0
- package/dist/tools/search/types.d.ts +132 -0
- package/dist/tools/search/types.js +4 -0
- package/dist/tools/search/utils.d.ts +45 -0
- package/dist/tools/search/utils.js +152 -0
- package/package.json +88 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for git tools
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Git file status indicator
|
|
6
|
+
*/
|
|
7
|
+
export type GitFileStatusType = 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'untracked';
|
|
8
|
+
/**
|
|
9
|
+
* Git file status entry
|
|
10
|
+
*/
|
|
11
|
+
export interface GitFileStatus {
|
|
12
|
+
/** File path */
|
|
13
|
+
path: string;
|
|
14
|
+
/** Status type */
|
|
15
|
+
status: GitFileStatusType;
|
|
16
|
+
/** Original path (for renames) */
|
|
17
|
+
oldPath?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Input for gitStatus tool
|
|
21
|
+
*/
|
|
22
|
+
export interface GitStatusInput {
|
|
23
|
+
/** Working directory path (default: current directory) */
|
|
24
|
+
path?: string;
|
|
25
|
+
/** Include untracked files (default: true) */
|
|
26
|
+
includeUntracked?: boolean;
|
|
27
|
+
/** Short format output (default: false) */
|
|
28
|
+
short?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Result of git status
|
|
32
|
+
*/
|
|
33
|
+
export interface GitStatusResult {
|
|
34
|
+
/** Current branch name */
|
|
35
|
+
branch: string;
|
|
36
|
+
/** Tracking branch info */
|
|
37
|
+
tracking?: {
|
|
38
|
+
remote: string;
|
|
39
|
+
ahead: number;
|
|
40
|
+
behind: number;
|
|
41
|
+
};
|
|
42
|
+
/** Staged files */
|
|
43
|
+
staged: GitFileStatus[];
|
|
44
|
+
/** Unstaged modified files */
|
|
45
|
+
modified: GitFileStatus[];
|
|
46
|
+
/** Untracked files */
|
|
47
|
+
untracked: string[];
|
|
48
|
+
/** Is working tree clean? */
|
|
49
|
+
isClean: boolean;
|
|
50
|
+
/** Short status output (if requested) */
|
|
51
|
+
shortStatus?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Input for gitDiff tool
|
|
55
|
+
*/
|
|
56
|
+
export interface GitDiffInput {
|
|
57
|
+
/** Working directory path */
|
|
58
|
+
path?: string;
|
|
59
|
+
/** Compare staged changes (default: false, shows unstaged) */
|
|
60
|
+
staged?: boolean;
|
|
61
|
+
/** Specific file to diff */
|
|
62
|
+
file?: string;
|
|
63
|
+
/** Compare with specific commit/branch */
|
|
64
|
+
ref?: string;
|
|
65
|
+
/** Compare two refs (use with refB) */
|
|
66
|
+
refA?: string;
|
|
67
|
+
/** Second ref to compare */
|
|
68
|
+
refB?: string;
|
|
69
|
+
/** Context lines (default: 3) */
|
|
70
|
+
context?: number;
|
|
71
|
+
/** Stat only, no content (default: false) */
|
|
72
|
+
statOnly?: boolean;
|
|
73
|
+
/** Name only, just list changed files */
|
|
74
|
+
nameOnly?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* File change stats in diff
|
|
78
|
+
*/
|
|
79
|
+
export interface DiffFileStats {
|
|
80
|
+
path: string;
|
|
81
|
+
additions: number;
|
|
82
|
+
deletions: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Result of git diff
|
|
86
|
+
*/
|
|
87
|
+
export interface GitDiffResult {
|
|
88
|
+
/** Diff output (empty if statOnly) */
|
|
89
|
+
diff: string;
|
|
90
|
+
/** Files changed */
|
|
91
|
+
files: DiffFileStats[];
|
|
92
|
+
/** Summary stats */
|
|
93
|
+
stats: {
|
|
94
|
+
filesChanged: number;
|
|
95
|
+
insertions: number;
|
|
96
|
+
deletions: number;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Input for gitLog tool
|
|
101
|
+
*/
|
|
102
|
+
export interface GitLogInput {
|
|
103
|
+
/** Working directory path */
|
|
104
|
+
path?: string;
|
|
105
|
+
/** Number of commits to return (default: 10) */
|
|
106
|
+
limit?: number;
|
|
107
|
+
/** Filter by file path */
|
|
108
|
+
file?: string;
|
|
109
|
+
/** Filter by author */
|
|
110
|
+
author?: string;
|
|
111
|
+
/** Since date (ISO format or relative like "2 weeks ago") */
|
|
112
|
+
since?: string;
|
|
113
|
+
/** Until date (ISO format or relative) */
|
|
114
|
+
until?: string;
|
|
115
|
+
/** One-line format (hash + message only) */
|
|
116
|
+
oneline?: boolean;
|
|
117
|
+
/** Include diff stat */
|
|
118
|
+
stat?: boolean;
|
|
119
|
+
/** Filter by grep pattern in commit message */
|
|
120
|
+
grep?: string;
|
|
121
|
+
/** Branch or ref to show log for */
|
|
122
|
+
ref?: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Git commit entry
|
|
126
|
+
*/
|
|
127
|
+
export interface GitCommit {
|
|
128
|
+
/** Full commit hash */
|
|
129
|
+
hash: string;
|
|
130
|
+
/** Short commit hash (7 chars) */
|
|
131
|
+
shortHash: string;
|
|
132
|
+
/** Author name */
|
|
133
|
+
author: string;
|
|
134
|
+
/** Author email */
|
|
135
|
+
email: string;
|
|
136
|
+
/** Commit date (ISO format) */
|
|
137
|
+
date: string;
|
|
138
|
+
/** Commit subject (first line) */
|
|
139
|
+
message: string;
|
|
140
|
+
/** Commit body (remaining lines) */
|
|
141
|
+
body?: string;
|
|
142
|
+
/** Stat info if requested */
|
|
143
|
+
stat?: string;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Result of git log
|
|
147
|
+
*/
|
|
148
|
+
export interface GitLogResult {
|
|
149
|
+
/** List of commits */
|
|
150
|
+
commits: GitCommit[];
|
|
151
|
+
/** Total commits found (may be more than returned if limit applied) */
|
|
152
|
+
totalCount?: number;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Input for gitCommit tool
|
|
156
|
+
*/
|
|
157
|
+
export interface GitCommitInput {
|
|
158
|
+
/** Working directory path */
|
|
159
|
+
path?: string;
|
|
160
|
+
/** Commit message (required) */
|
|
161
|
+
message: string;
|
|
162
|
+
/** Files to add before commit (specific files only) */
|
|
163
|
+
files?: string[];
|
|
164
|
+
/** Add all modified/deleted files (git add -u) */
|
|
165
|
+
addModified?: boolean;
|
|
166
|
+
/** Add all files including untracked (git add -A) */
|
|
167
|
+
addAll?: boolean;
|
|
168
|
+
/** Allow empty commit */
|
|
169
|
+
allowEmpty?: boolean;
|
|
170
|
+
/** Amend previous commit (use with caution!) */
|
|
171
|
+
amend?: boolean;
|
|
172
|
+
/** Skip pre-commit hooks (use with caution!) */
|
|
173
|
+
noVerify?: boolean;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Result of git commit
|
|
177
|
+
*/
|
|
178
|
+
export interface GitCommitResult {
|
|
179
|
+
/** Commit hash */
|
|
180
|
+
hash: string;
|
|
181
|
+
/** Short hash */
|
|
182
|
+
shortHash: string;
|
|
183
|
+
/** Branch committed to */
|
|
184
|
+
branch: string;
|
|
185
|
+
/** Number of files committed */
|
|
186
|
+
filesCommitted: number;
|
|
187
|
+
/** Lines inserted */
|
|
188
|
+
insertions: number;
|
|
189
|
+
/** Lines deleted */
|
|
190
|
+
deletions: number;
|
|
191
|
+
/** Commit message used */
|
|
192
|
+
message: string;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Safety warning from commit tool
|
|
196
|
+
*/
|
|
197
|
+
export interface CommitSafetyWarning {
|
|
198
|
+
type: 'secrets' | 'large_file' | 'binary';
|
|
199
|
+
file: string;
|
|
200
|
+
message: string;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Branch action types
|
|
204
|
+
*/
|
|
205
|
+
export type GitBranchAction = 'list' | 'create' | 'delete' | 'switch' | 'rename';
|
|
206
|
+
/**
|
|
207
|
+
* Input for gitBranch tool
|
|
208
|
+
*/
|
|
209
|
+
export interface GitBranchInput {
|
|
210
|
+
/** Working directory path */
|
|
211
|
+
path?: string;
|
|
212
|
+
/** Action to perform */
|
|
213
|
+
action: GitBranchAction;
|
|
214
|
+
/** Branch name (for create/delete/switch/rename) */
|
|
215
|
+
name?: string;
|
|
216
|
+
/** New name (for rename action) */
|
|
217
|
+
newName?: string;
|
|
218
|
+
/** Include remote branches in list */
|
|
219
|
+
remotes?: boolean;
|
|
220
|
+
/** Force delete even if not merged */
|
|
221
|
+
force?: boolean;
|
|
222
|
+
/** Start point for new branch (commit/branch) */
|
|
223
|
+
startPoint?: string;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Branch info entry
|
|
227
|
+
*/
|
|
228
|
+
export interface GitBranchInfo {
|
|
229
|
+
/** Branch name */
|
|
230
|
+
name: string;
|
|
231
|
+
/** Is this a remote branch? */
|
|
232
|
+
isRemote: boolean;
|
|
233
|
+
/** Is this the current branch? */
|
|
234
|
+
isCurrent: boolean;
|
|
235
|
+
/** Tracking remote branch */
|
|
236
|
+
tracking?: string;
|
|
237
|
+
/** Last commit hash */
|
|
238
|
+
lastCommit?: string;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Result of gitBranch tool
|
|
242
|
+
*/
|
|
243
|
+
export interface GitBranchResult {
|
|
244
|
+
/** Current branch (for list action) */
|
|
245
|
+
current?: string;
|
|
246
|
+
/** All branches (for list action) */
|
|
247
|
+
branches?: GitBranchInfo[];
|
|
248
|
+
/** Success message */
|
|
249
|
+
message: string;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Stash action types
|
|
253
|
+
*/
|
|
254
|
+
export type GitStashAction = 'push' | 'pop' | 'apply' | 'list' | 'drop' | 'clear' | 'show';
|
|
255
|
+
/**
|
|
256
|
+
* Input for gitStash tool
|
|
257
|
+
*/
|
|
258
|
+
export interface GitStashInput {
|
|
259
|
+
/** Working directory path */
|
|
260
|
+
path?: string;
|
|
261
|
+
/** Action to perform */
|
|
262
|
+
action: GitStashAction;
|
|
263
|
+
/** Stash message (for push) */
|
|
264
|
+
message?: string;
|
|
265
|
+
/** Include untracked files (for push) */
|
|
266
|
+
includeUntracked?: boolean;
|
|
267
|
+
/** Stash index (for pop/apply/drop/show, default: 0) */
|
|
268
|
+
index?: number;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Stash entry info
|
|
272
|
+
*/
|
|
273
|
+
export interface GitStashEntry {
|
|
274
|
+
/** Stash index (0 = most recent) */
|
|
275
|
+
index: number;
|
|
276
|
+
/** Branch where stash was created */
|
|
277
|
+
branch: string;
|
|
278
|
+
/** Stash message */
|
|
279
|
+
message: string;
|
|
280
|
+
/** Stash ref (e.g., stash@{0}) */
|
|
281
|
+
ref: string;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Result of gitStash tool
|
|
285
|
+
*/
|
|
286
|
+
export interface GitStashResult {
|
|
287
|
+
/** Stash list (for list action) */
|
|
288
|
+
stashes?: GitStashEntry[];
|
|
289
|
+
/** Stash diff (for show action) */
|
|
290
|
+
diff?: string;
|
|
291
|
+
/** Success message */
|
|
292
|
+
message: string;
|
|
293
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git utilities - shared functions for git tools
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Result of running a git command
|
|
6
|
+
*/
|
|
7
|
+
export interface GitCommandResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
stdout: string;
|
|
10
|
+
stderr: string;
|
|
11
|
+
exitCode: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Run a git command and return the result
|
|
15
|
+
*/
|
|
16
|
+
export declare function runGitCommand(args: string[], options?: {
|
|
17
|
+
cwd?: string;
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}): Promise<GitCommandResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Check if a directory is a git repository
|
|
22
|
+
*/
|
|
23
|
+
export declare function isGitRepository(path: string): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Check if a path exists and is a directory
|
|
26
|
+
*/
|
|
27
|
+
export declare function isDirectory(path: string): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Parse porcelain v2 status output for a single entry
|
|
30
|
+
*/
|
|
31
|
+
export interface PorcelainEntry {
|
|
32
|
+
type: 'changed' | 'untracked' | 'ignored' | 'renamed' | 'copied';
|
|
33
|
+
staged: boolean;
|
|
34
|
+
path: string;
|
|
35
|
+
oldPath?: string;
|
|
36
|
+
xy: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse git status --porcelain=v2 output
|
|
40
|
+
*/
|
|
41
|
+
export declare function parsePorcelainStatus(output: string): PorcelainEntry[];
|
|
42
|
+
/**
|
|
43
|
+
* Convert XY status to file status type
|
|
44
|
+
*/
|
|
45
|
+
export declare function xyToStatusType(xy: string, isStaged: boolean): 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'untracked';
|
|
46
|
+
/**
|
|
47
|
+
* Parse branch info from git status --porcelain=v2 --branch output
|
|
48
|
+
*/
|
|
49
|
+
export interface BranchInfo {
|
|
50
|
+
branch: string;
|
|
51
|
+
upstream?: string;
|
|
52
|
+
ahead: number;
|
|
53
|
+
behind: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parse branch headers from porcelain v2 output
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseBranchInfo(output: string): BranchInfo;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git utilities - shared functions for git tools
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { access, stat } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
/**
|
|
8
|
+
* Maximum output size (50KB)
|
|
9
|
+
*/
|
|
10
|
+
const MAX_OUTPUT_SIZE = 50 * 1024;
|
|
11
|
+
/**
|
|
12
|
+
* Run a git command and return the result
|
|
13
|
+
*/
|
|
14
|
+
export async function runGitCommand(args, options = {}) {
|
|
15
|
+
const { cwd = process.cwd(), timeout = 30000 } = options;
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
let stdout = '';
|
|
18
|
+
let stderr = '';
|
|
19
|
+
let killed = false;
|
|
20
|
+
const proc = spawn('git', args, {
|
|
21
|
+
cwd,
|
|
22
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
23
|
+
});
|
|
24
|
+
// Timeout handler
|
|
25
|
+
const timeoutId = setTimeout(() => {
|
|
26
|
+
killed = true;
|
|
27
|
+
proc.kill('SIGTERM');
|
|
28
|
+
}, timeout);
|
|
29
|
+
proc.stdout.on('data', (data) => {
|
|
30
|
+
const chunk = data.toString();
|
|
31
|
+
if (stdout.length + chunk.length <= MAX_OUTPUT_SIZE) {
|
|
32
|
+
stdout += chunk;
|
|
33
|
+
}
|
|
34
|
+
else if (stdout.length < MAX_OUTPUT_SIZE) {
|
|
35
|
+
stdout += chunk.slice(0, MAX_OUTPUT_SIZE - stdout.length);
|
|
36
|
+
stdout += '\n... [output truncated]';
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
proc.stderr.on('data', (data) => {
|
|
40
|
+
const chunk = data.toString();
|
|
41
|
+
if (stderr.length + chunk.length <= MAX_OUTPUT_SIZE) {
|
|
42
|
+
stderr += chunk;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
proc.on('close', (code) => {
|
|
46
|
+
clearTimeout(timeoutId);
|
|
47
|
+
if (killed) {
|
|
48
|
+
resolve({
|
|
49
|
+
success: false,
|
|
50
|
+
stdout,
|
|
51
|
+
stderr: 'Command timed out',
|
|
52
|
+
exitCode: -1,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
resolve({
|
|
57
|
+
success: code === 0,
|
|
58
|
+
stdout: stdout.trim(),
|
|
59
|
+
stderr: stderr.trim(),
|
|
60
|
+
exitCode: code ?? -1,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
proc.on('error', (error) => {
|
|
65
|
+
clearTimeout(timeoutId);
|
|
66
|
+
resolve({
|
|
67
|
+
success: false,
|
|
68
|
+
stdout: '',
|
|
69
|
+
stderr: error.message,
|
|
70
|
+
exitCode: -1,
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if a directory is a git repository
|
|
77
|
+
*/
|
|
78
|
+
export async function isGitRepository(path) {
|
|
79
|
+
try {
|
|
80
|
+
const gitDir = join(path, '.git');
|
|
81
|
+
await access(gitDir);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Try running git rev-parse to check (handles worktrees)
|
|
86
|
+
const result = await runGitCommand(['rev-parse', '--git-dir'], { cwd: path });
|
|
87
|
+
return result.success;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if a path exists and is a directory
|
|
92
|
+
*/
|
|
93
|
+
export async function isDirectory(path) {
|
|
94
|
+
try {
|
|
95
|
+
const stats = await stat(path);
|
|
96
|
+
return stats.isDirectory();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Parse git status --porcelain=v2 output
|
|
104
|
+
*/
|
|
105
|
+
export function parsePorcelainStatus(output) {
|
|
106
|
+
const entries = [];
|
|
107
|
+
const lines = output.split('\n').filter(Boolean);
|
|
108
|
+
for (const line of lines) {
|
|
109
|
+
if (line.startsWith('1 ') || line.startsWith('2 ')) {
|
|
110
|
+
// Changed entry (1) or renamed/copied entry (2)
|
|
111
|
+
const parts = line.split(' ');
|
|
112
|
+
const xy = parts[1];
|
|
113
|
+
const isRenamed = line.startsWith('2 ');
|
|
114
|
+
if (isRenamed) {
|
|
115
|
+
// Format: 2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><TAB><origPath>
|
|
116
|
+
const pathPart = parts.slice(9).join(' ');
|
|
117
|
+
const [path, oldPath] = pathPart.split('\t');
|
|
118
|
+
entries.push({
|
|
119
|
+
type: xy[0] === 'C' ? 'copied' : 'renamed',
|
|
120
|
+
staged: xy[0] !== '.',
|
|
121
|
+
path,
|
|
122
|
+
oldPath,
|
|
123
|
+
xy,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Format: 1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
|
|
128
|
+
const path = parts.slice(8).join(' ');
|
|
129
|
+
entries.push({
|
|
130
|
+
type: 'changed',
|
|
131
|
+
staged: xy[0] !== '.',
|
|
132
|
+
path,
|
|
133
|
+
xy,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (line.startsWith('? ')) {
|
|
138
|
+
// Untracked entry
|
|
139
|
+
const path = line.slice(2);
|
|
140
|
+
entries.push({
|
|
141
|
+
type: 'untracked',
|
|
142
|
+
staged: false,
|
|
143
|
+
path,
|
|
144
|
+
xy: '??',
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return entries;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Convert XY status to file status type
|
|
152
|
+
*/
|
|
153
|
+
export function xyToStatusType(xy, isStaged) {
|
|
154
|
+
const char = isStaged ? xy[0] : xy[1];
|
|
155
|
+
switch (char) {
|
|
156
|
+
case 'A':
|
|
157
|
+
return 'added';
|
|
158
|
+
case 'M':
|
|
159
|
+
return 'modified';
|
|
160
|
+
case 'D':
|
|
161
|
+
return 'deleted';
|
|
162
|
+
case 'R':
|
|
163
|
+
return 'renamed';
|
|
164
|
+
case 'C':
|
|
165
|
+
return 'copied';
|
|
166
|
+
case '?':
|
|
167
|
+
return 'untracked';
|
|
168
|
+
default:
|
|
169
|
+
return 'modified';
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Parse branch headers from porcelain v2 output
|
|
174
|
+
*/
|
|
175
|
+
export function parseBranchInfo(output) {
|
|
176
|
+
const lines = output.split('\n');
|
|
177
|
+
let branch = 'HEAD';
|
|
178
|
+
let upstream;
|
|
179
|
+
let ahead = 0;
|
|
180
|
+
let behind = 0;
|
|
181
|
+
for (const line of lines) {
|
|
182
|
+
if (line.startsWith('# branch.head ')) {
|
|
183
|
+
branch = line.slice('# branch.head '.length);
|
|
184
|
+
}
|
|
185
|
+
else if (line.startsWith('# branch.upstream ')) {
|
|
186
|
+
upstream = line.slice('# branch.upstream '.length);
|
|
187
|
+
}
|
|
188
|
+
else if (line.startsWith('# branch.ab ')) {
|
|
189
|
+
const match = line.match(/# branch\.ab \+(\d+) -(\d+)/);
|
|
190
|
+
if (match) {
|
|
191
|
+
ahead = parseInt(match[1], 10);
|
|
192
|
+
behind = parseInt(match[2], 10);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return { branch, upstream, ahead, behind };
|
|
197
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Detection Tool
|
|
3
|
+
* Detects project type, package manager, and available tools
|
|
4
|
+
*/
|
|
5
|
+
import type { Tool } from '@compilr-dev/agents';
|
|
6
|
+
import type { DetectProjectInput, ProjectDetectionRule } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Detect project tool
|
|
9
|
+
*/
|
|
10
|
+
export declare const detectProjectTool: Tool<DetectProjectInput>;
|
|
11
|
+
/**
|
|
12
|
+
* Factory function to create detect project tool with custom options
|
|
13
|
+
*/
|
|
14
|
+
export declare function createDetectProjectTool(options?: {
|
|
15
|
+
/** Base directory for relative paths */
|
|
16
|
+
baseDir?: string;
|
|
17
|
+
/** Additional project detection rules */
|
|
18
|
+
additionalRules?: ProjectDetectionRule[];
|
|
19
|
+
}): Tool<DetectProjectInput>;
|