@aigne/afs-git 1.1.0-beta → 1.2.0-beta

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/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.2.0-beta](https://github.com/AIGNE-io/aigne-framework/compare/afs-git-v1.1.0...afs-git-v1.2.0-beta) (2026-01-20)
4
+
5
+
6
+ ### Features
7
+
8
+ * **afs-git:** support mount remote repo to AFS ([#926](https://github.com/AIGNE-io/aigne-framework/issues/926)) ([e4c78aa](https://github.com/AIGNE-io/aigne-framework/commit/e4c78aa207d76a8f15874931375f4b30b4c9af7f))
9
+ * **afs:** add @aigne/afs-utils package ([#927](https://github.com/AIGNE-io/aigne-framework/issues/927)) ([3922635](https://github.com/AIGNE-io/aigne-framework/commit/3922635981aab4578607c5bf1fb882c8e45725ce))
10
+
11
+
12
+ ### Dependencies
13
+
14
+ * The following workspace dependencies were updated
15
+ * dependencies
16
+ * @aigne/afs-utils bumped to 1.0.0
17
+ * devDependencies
18
+ * @aigne/test-utils bumped to 0.5.70-beta
19
+
20
+ ## [1.1.0](https://github.com/AIGNE-io/aigne-framework/compare/afs-git-v1.1.0-beta...afs-git-v1.1.0) (2026-01-16)
21
+
22
+
23
+ ### Dependencies
24
+
25
+ * The following workspace dependencies were updated
26
+ * dependencies
27
+ * @aigne/afs bumped to 1.4.0
28
+ * @aigne/core bumped to 1.72.0
29
+ * devDependencies
30
+ * @aigne/test-utils bumped to 0.5.69
31
+
3
32
  ## [1.1.0-beta](https://github.com/AIGNE-io/aigne-framework/compare/afs-git-v1.0.0...afs-git-v1.1.0-beta) (2026-01-16)
4
33
 
5
34
 
package/README.md CHANGED
@@ -20,6 +20,73 @@ npm install @aigne/afs-git
20
20
 
21
21
  ## Usage
22
22
 
23
+ ### Remote Repository
24
+
25
+ Mount a remote Git repository by cloning it to a temporary directory or a specified path:
26
+
27
+ ```typescript
28
+ import { AFS } from "@aigne/afs";
29
+ import { AFSGit } from "@aigne/afs-git";
30
+
31
+ const afs = new AFS();
32
+
33
+ // Clone and mount a remote repository (clones to temp directory)
34
+ const gitRemote = new AFSGit({
35
+ remoteUrl: 'https://github.com/user/repo.git',
36
+ depth: 1, // Shallow clone
37
+ branches: ['main'], // Single branch = --single-branch optimization
38
+ accessMode: 'readonly'
39
+ });
40
+
41
+ afs.mount(gitRemote);
42
+
43
+ // Access files from remote repository
44
+ const content = await afs.read('/modules/git/main/README.md');
45
+
46
+ // Cleanup when done (removes cloned temp directory)
47
+ await gitRemote.cleanup();
48
+ ```
49
+
50
+ #### Private Repository with Authentication
51
+
52
+ ```typescript
53
+ const gitRemote = new AFSGit({
54
+ remoteUrl: 'https://github.com/user/private-repo.git',
55
+ depth: 1,
56
+ cloneOptions: {
57
+ auth: {
58
+ username: 'your-username',
59
+ password: process.env.GITHUB_TOKEN // Use personal access token
60
+ }
61
+ }
62
+ });
63
+ ```
64
+
65
+ #### Use Existing or Custom Clone Path
66
+
67
+ If you already have a local clone or want to specify where to clone:
68
+
69
+ ```typescript
70
+ const gitRemote = new AFSGit({
71
+ remoteUrl: 'https://github.com/user/repo.git',
72
+ repoPath: '/path/to/clone', // Clone to this path if doesn't exist
73
+ autoCleanup: false // Don't delete on cleanup()
74
+ });
75
+ ```
76
+
77
+ #### Remote Operations
78
+
79
+ ```typescript
80
+ // Fetch latest changes from remote
81
+ await gitRemote.fetch();
82
+
83
+ // Pull latest changes for current branch
84
+ await gitRemote.pull();
85
+
86
+ // Push local changes (if accessMode is 'readwrite')
87
+ await gitRemote.push();
88
+ ```
89
+
23
90
  ### Basic Setup (Read-Only)
24
91
 
25
92
  ```typescript
@@ -28,11 +95,13 @@ import { AFSGit } from "@aigne/afs-git";
28
95
 
29
96
  const afs = new AFS();
30
97
 
31
- // Mount a git repository in read-only mode
32
- afs.mount(new AFSGit({
98
+ // Mount a local git repository in read-only mode
99
+ const git = new AFSGit({
33
100
  repoPath: '/path/to/repo',
34
101
  accessMode: 'readonly' // default
35
- }));
102
+ });
103
+
104
+ afs.mount(git);
36
105
  ```
37
106
 
38
107
  ### Path Structure
@@ -112,6 +181,7 @@ await afs.rename('/modules/git/main/old.txt', '/modules/git/main/new.txt');
112
181
  ### Advanced Configuration
113
182
 
114
183
  ```typescript
184
+ // Local repository with advanced options
115
185
  const afsGit = new AFSGit({
116
186
  repoPath: '/path/to/repo',
117
187
  name: 'my-repo',
@@ -135,6 +205,35 @@ const afsGit = new AFSGit({
135
205
  await afsGit.cleanup();
136
206
  ```
137
207
 
208
+ ```typescript
209
+ // Remote repository with all options
210
+ const afsGit = new AFSGit({
211
+ remoteUrl: 'https://github.com/user/repo.git',
212
+ repoPath: '/custom/clone/path', // Optional: specify clone location
213
+ name: 'my-remote-repo',
214
+ description: 'Remote repository',
215
+
216
+ // Clone options
217
+ depth: 1, // Shallow clone
218
+ branches: ['main'], // Single branch = --single-branch optimization
219
+ // Multiple: ['main', 'develop'] = clone all, filter access
220
+
221
+ // Access control
222
+ accessMode: 'readonly',
223
+
224
+ // Auto cleanup
225
+ autoCleanup: true, // Remove clone on cleanup()
226
+
227
+ // Authentication for private repos
228
+ cloneOptions: {
229
+ auth: {
230
+ username: 'user',
231
+ password: process.env.GIT_TOKEN
232
+ }
233
+ }
234
+ });
235
+ ```
236
+
138
237
  ## How It Works
139
238
 
140
239
  ### Read-Only Mode
@@ -180,6 +279,50 @@ interface AFSGitOptions {
180
279
  }
181
280
  ```
182
281
 
282
+ ### Remote Repository Options
283
+
284
+ When using `remoteUrl`, additional options are available:
285
+
286
+ ```typescript
287
+ interface AFSGitOptions {
288
+ // Either repoPath or remoteUrl is required
289
+ repoPath?: string; // Local repository path
290
+ remoteUrl?: string; // Remote repository URL (https or git)
291
+
292
+ // Basic options
293
+ name?: string; // Module name (default: repo basename)
294
+ description?: string; // Module description
295
+ branches?: string[]; // Branch access control & clone optimization
296
+ // Single: ['main'] = --single-branch clone
297
+ // Multiple: ['main', 'dev'] = clone all, filter access
298
+ accessMode?: 'readonly' | 'readwrite'; // Default: 'readonly'
299
+
300
+ // Commit options
301
+ autoCommit?: boolean; // Auto-commit changes (default: false)
302
+ commitAuthor?: { // Author for commits
303
+ name: string;
304
+ email: string;
305
+ };
306
+
307
+ // Remote clone options (only used with remoteUrl)
308
+ depth?: number; // Clone depth for shallow clone (default: 1)
309
+ autoCleanup?: boolean; // Auto cleanup cloned repo (default: true)
310
+ cloneOptions?: {
311
+ auth?: { // Authentication for private repos
312
+ username?: string;
313
+ password?: string; // Use personal access token
314
+ };
315
+ };
316
+ }
317
+ ```
318
+
319
+ **Note:** When `remoteUrl` is provided:
320
+ - If `repoPath` is not specified, clones to a temporary directory
321
+ - If `repoPath` is specified and doesn't exist, clones to that path
322
+ - If `repoPath` exists, uses the existing clone
323
+ - `autoCleanup` only applies when repository was auto-cloned to temp directory
324
+ - `branches` with single element uses `--single-branch` for faster clone
325
+
183
326
  ## Performance
184
327
 
185
328
  - **Read operations**: Very fast, uses direct git commands
@@ -196,16 +339,19 @@ interface AFSGitOptions {
196
339
 
197
340
  ## Example: AI Agent Code Review
198
341
 
342
+ ### Review Local Repository
343
+
199
344
  ```typescript
200
345
  import { AIGNE } from "@aigne/core";
201
346
  import { AFS } from "@aigne/afs";
202
347
  import { AFSGit } from "@aigne/afs-git";
203
348
 
204
349
  const afs = new AFS();
205
- afs.mount(new AFSGit({
350
+ const git = new AFSGit({
206
351
  repoPath: process.cwd(),
207
352
  accessMode: 'readonly'
208
- }));
353
+ });
354
+ afs.mount(git);
209
355
 
210
356
  const aigne = new AIGNE({});
211
357
 
@@ -222,6 +368,39 @@ await aigne.invoke(agent, {
222
368
  });
223
369
  ```
224
370
 
371
+ ### Review Remote Repository
372
+
373
+ ```typescript
374
+ import { AIGNE } from "@aigne/core";
375
+ import { AFS } from "@aigne/afs";
376
+ import { AFSGit } from "@aigne/afs-git";
377
+
378
+ const afs = new AFS();
379
+
380
+ // Clone and mount remote repository
381
+ const git = new AFSGit({
382
+ remoteUrl: 'https://github.com/user/project.git',
383
+ depth: 1,
384
+ branches: ['main']
385
+ });
386
+ afs.mount(git);
387
+
388
+ const aigne = new AIGNE({});
389
+
390
+ const agent = AIAgent.from({
391
+ name: "CodeReviewer",
392
+ instructions: "Review open source code and provide feedback",
393
+ afs
394
+ });
395
+
396
+ await aigne.invoke(agent, {
397
+ message: "Analyze the security of the authentication implementation"
398
+ });
399
+
400
+ // Cleanup cloned repository
401
+ await git.cleanup();
402
+ ```
403
+
225
404
  ## License
226
405
 
227
406
  This project is licensed under the [Elastic-2.0](../../LICENSE.md) License.
@@ -2,8 +2,28 @@ import type { AFSAccessMode, AFSDeleteOptions, AFSDeleteResult, AFSListOptions,
2
2
  import { z } from "zod";
3
3
  export interface AFSGitOptions {
4
4
  name?: string;
5
- repoPath: string;
5
+ /**
6
+ * Local path to git repository.
7
+ * If remoteUrl is provided and repoPath doesn't exist, will clone to this path.
8
+ * If remoteUrl is provided and repoPath is not specified, clones to temp directory.
9
+ */
10
+ repoPath?: string;
11
+ /**
12
+ * Remote repository URL (https or git protocol).
13
+ * If provided, will clone the repository if repoPath doesn't exist.
14
+ * Examples:
15
+ * - https://github.com/user/repo.git
16
+ * - git@github.com:user/repo.git
17
+ */
18
+ remoteUrl?: string;
6
19
  description?: string;
20
+ /**
21
+ * List of branches to expose/access.
22
+ * Also used for clone optimization when cloning from remoteUrl:
23
+ * - Single branch (e.g., ['main']): Uses --single-branch for faster clone
24
+ * - Multiple branches: Clones all branches, filters access to specified ones
25
+ * - Not specified: All branches are accessible
26
+ */
7
27
  branches?: string[];
8
28
  /**
9
29
  * Access mode for this module.
@@ -24,14 +44,38 @@ export interface AFSGitOptions {
24
44
  name: string;
25
45
  email: string;
26
46
  };
47
+ /**
48
+ * Clone depth for shallow clone (only used when cloning from remoteUrl)
49
+ * @default 1
50
+ */
51
+ depth?: number;
52
+ /**
53
+ * Automatically clean up cloned repository on cleanup()
54
+ * Only applies when repository was auto-cloned to temp directory
55
+ * @default true
56
+ */
57
+ autoCleanup?: boolean;
58
+ /**
59
+ * Git clone options (only used when cloning from remoteUrl)
60
+ */
61
+ cloneOptions?: {
62
+ /**
63
+ * Authentication credentials for private repositories
64
+ */
65
+ auth?: {
66
+ username?: string;
67
+ password?: string;
68
+ };
69
+ };
27
70
  }
28
71
  export declare class AFSGit implements AFSModule {
29
72
  options: AFSGitOptions & {
30
73
  cwd?: string;
31
74
  };
32
- static schema(): z.ZodObject<{
75
+ static schema(): z.ZodEffects<z.ZodEffects<z.ZodObject<{
33
76
  name: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
34
- repoPath: z.ZodString;
77
+ repoPath: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
78
+ remoteUrl: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
35
79
  description: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
36
80
  branches: z.ZodType<string[] | undefined, z.ZodTypeDef, string[] | undefined>;
37
81
  accessMode: z.ZodType<"readonly" | "readwrite" | undefined, z.ZodTypeDef, "readonly" | "readwrite" | undefined>;
@@ -43,9 +87,23 @@ export declare class AFSGit implements AFSModule {
43
87
  name: string;
44
88
  email: string;
45
89
  } | undefined>;
90
+ depth: z.ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
91
+ autoCleanup: z.ZodType<boolean | undefined, z.ZodTypeDef, boolean | undefined>;
92
+ cloneOptions: z.ZodType<{
93
+ auth?: {
94
+ username?: string | undefined;
95
+ password?: string | undefined;
96
+ } | undefined;
97
+ } | undefined, z.ZodTypeDef, {
98
+ auth?: {
99
+ username?: string | undefined;
100
+ password?: string | undefined;
101
+ } | undefined;
102
+ } | undefined>;
46
103
  }, "strip", z.ZodTypeAny, {
47
- repoPath: string;
48
104
  name?: string | undefined;
105
+ repoPath?: string | undefined;
106
+ remoteUrl?: string | undefined;
49
107
  description?: string | undefined;
50
108
  branches?: string[] | undefined;
51
109
  accessMode?: "readonly" | "readwrite" | undefined;
@@ -54,9 +112,18 @@ export declare class AFSGit implements AFSModule {
54
112
  name: string;
55
113
  email: string;
56
114
  } | undefined;
115
+ depth?: number | undefined;
116
+ autoCleanup?: boolean | undefined;
117
+ cloneOptions?: {
118
+ auth?: {
119
+ username?: string | undefined;
120
+ password?: string | undefined;
121
+ } | undefined;
122
+ } | undefined;
57
123
  }, {
58
- repoPath: string;
59
124
  name?: string | undefined;
125
+ repoPath?: string | undefined;
126
+ remoteUrl?: string | undefined;
60
127
  description?: string | undefined;
61
128
  branches?: string[] | undefined;
62
129
  accessMode?: "readonly" | "readwrite" | undefined;
@@ -65,15 +132,100 @@ export declare class AFSGit implements AFSModule {
65
132
  name: string;
66
133
  email: string;
67
134
  } | undefined;
68
- }>;
135
+ depth?: number | undefined;
136
+ autoCleanup?: boolean | undefined;
137
+ cloneOptions?: {
138
+ auth?: {
139
+ username?: string | undefined;
140
+ password?: string | undefined;
141
+ } | undefined;
142
+ } | undefined;
143
+ }>, {
144
+ name?: string | undefined;
145
+ repoPath?: string | undefined;
146
+ remoteUrl?: string | undefined;
147
+ description?: string | undefined;
148
+ branches?: string[] | undefined;
149
+ accessMode?: "readonly" | "readwrite" | undefined;
150
+ autoCommit?: boolean | undefined;
151
+ commitAuthor?: {
152
+ name: string;
153
+ email: string;
154
+ } | undefined;
155
+ depth?: number | undefined;
156
+ autoCleanup?: boolean | undefined;
157
+ cloneOptions?: {
158
+ auth?: {
159
+ username?: string | undefined;
160
+ password?: string | undefined;
161
+ } | undefined;
162
+ } | undefined;
163
+ }, {
164
+ name?: string | undefined;
165
+ repoPath?: string | undefined;
166
+ remoteUrl?: string | undefined;
167
+ description?: string | undefined;
168
+ branches?: string[] | undefined;
169
+ accessMode?: "readonly" | "readwrite" | undefined;
170
+ autoCommit?: boolean | undefined;
171
+ commitAuthor?: {
172
+ name: string;
173
+ email: string;
174
+ } | undefined;
175
+ depth?: number | undefined;
176
+ autoCleanup?: boolean | undefined;
177
+ cloneOptions?: {
178
+ auth?: {
179
+ username?: string | undefined;
180
+ password?: string | undefined;
181
+ } | undefined;
182
+ } | undefined;
183
+ }>, {
184
+ name?: string | undefined;
185
+ repoPath?: string | undefined;
186
+ remoteUrl?: string | undefined;
187
+ description?: string | undefined;
188
+ branches?: string[] | undefined;
189
+ accessMode?: "readonly" | "readwrite" | undefined;
190
+ autoCommit?: boolean | undefined;
191
+ commitAuthor?: {
192
+ name: string;
193
+ email: string;
194
+ } | undefined;
195
+ depth?: number | undefined;
196
+ autoCleanup?: boolean | undefined;
197
+ cloneOptions?: {
198
+ auth?: {
199
+ username?: string | undefined;
200
+ password?: string | undefined;
201
+ } | undefined;
202
+ } | undefined;
203
+ }, any>;
69
204
  static load({ filepath, parsed }: AFSModuleLoadParams): Promise<AFSGit>;
205
+ private initPromise;
70
206
  private git;
71
207
  private tempBase;
72
208
  private worktrees;
73
209
  private repoHash;
210
+ private isAutoCloned;
211
+ private clonedPath?;
212
+ private repoPath;
74
213
  constructor(options: AFSGitOptions & {
75
214
  cwd?: string;
76
215
  });
216
+ /**
217
+ * Wait for async initialization to complete
218
+ */
219
+ ready(): Promise<void>;
220
+ /**
221
+ * Async initialization logic (runs in constructor)
222
+ * Handles cloning remote repositories if needed
223
+ */
224
+ private initialize;
225
+ /**
226
+ * Clone a remote repository to local path
227
+ */
228
+ private static cloneRepository;
77
229
  name: string;
78
230
  description?: string;
79
231
  accessMode: AFSAccessMode;
@@ -122,6 +274,18 @@ export declare class AFSGit implements AFSModule {
122
274
  message?: string;
123
275
  }>;
124
276
  search(path: string, query: string, options?: AFSSearchOptions): Promise<AFSSearchResult>;
277
+ /**
278
+ * Fetch latest changes from remote
279
+ */
280
+ fetch(): Promise<void>;
281
+ /**
282
+ * Pull latest changes from remote for current branch
283
+ */
284
+ pull(): Promise<void>;
285
+ /**
286
+ * Push local changes to remote
287
+ */
288
+ push(branch?: string): Promise<void>;
125
289
  /**
126
290
  * Cleanup all worktrees (useful when unmounting)
127
291
  */