@aigne/example-afs-git 0.0.0 → 1.0.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/README.md +171 -241
- package/index.ts +13 -7
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# AFS
|
|
1
|
+
# AFS Git Example
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<picture>
|
|
@@ -8,28 +8,26 @@
|
|
|
8
8
|
</picture>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
This example demonstrates how to create a chatbot that can interact with
|
|
11
|
+
This example demonstrates how to create a chatbot that can interact with Git repositories using the [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework) and [AIGNE CLI](https://github.com/AIGNE-io/aigne-framework/blob/main/packages/cli/README.md). The example utilizes the `AFSGit` module to provide Git repository access to AI agents through the **AIGNE File System (AFS)** interface.
|
|
12
12
|
|
|
13
13
|
**AIGNE File System (AFS)** is a virtual file system abstraction that provides AI agents with unified access to various storage backends. For comprehensive documentation, see [AFS Documentation](../../afs/README.md).
|
|
14
14
|
|
|
15
|
-
**Note:** The AFSJSON module supports both JSON and YAML formats. File format is automatically detected based on the file extension (.json, .yaml, .yml).
|
|
16
|
-
|
|
17
15
|
## What You'll See
|
|
18
16
|
|
|
19
|
-
**User asks:** "What
|
|
17
|
+
**User asks:** "What changed in the authentication code between main and develop?"
|
|
20
18
|
|
|
21
19
|
**Behind the scenes:**
|
|
22
|
-
1. LLM calls `afs_list` → lists
|
|
23
|
-
2.
|
|
24
|
-
3. LLM calls `afs_read("/
|
|
25
|
-
4. LLM presents: "The
|
|
20
|
+
1. LLM calls `afs_list` → lists branches (`/main`, `/develop`)
|
|
21
|
+
2. LLM calls `afs_read("/main/src/auth/index.ts")` → reads from main branch
|
|
22
|
+
3. LLM calls `afs_read("/develop/src/auth/index.ts")` → reads from develop branch
|
|
23
|
+
4. LLM compares and presents: "The develop branch added OAuth support with three new functions..."
|
|
26
24
|
|
|
27
|
-
**The power:** AI agents can navigate
|
|
25
|
+
**The power:** AI agents can intelligently navigate Git branches, compare code across versions, and search through repository history!
|
|
28
26
|
|
|
29
27
|
## Prerequisites
|
|
30
28
|
|
|
31
29
|
* [Node.js](https://nodejs.org) (>=20.0) and npm installed on your machine
|
|
32
|
-
* A
|
|
30
|
+
* A Git repository to explore
|
|
33
31
|
* An [OpenAI API key](https://platform.openai.com/api-keys) for interacting with OpenAI's services
|
|
34
32
|
* Optional dependencies (if running the example from source code):
|
|
35
33
|
* [Pnpm](https://pnpm.io) for package management
|
|
@@ -42,68 +40,72 @@ This example demonstrates how to create a chatbot that can interact with JSON an
|
|
|
42
40
|
```bash
|
|
43
41
|
export OPENAI_API_KEY=YOUR_OPENAI_API_KEY
|
|
44
42
|
|
|
45
|
-
# Mount
|
|
46
|
-
npx -y @aigne/example-afs-
|
|
43
|
+
# Mount current Git repository (read-only by default)
|
|
44
|
+
npx -y @aigne/example-afs-git --interactive
|
|
47
45
|
|
|
48
|
-
# Mount a
|
|
49
|
-
npx -y @aigne/example-afs-
|
|
46
|
+
# Mount a specific repository
|
|
47
|
+
npx -y @aigne/example-afs-git --path /path/to/repo --interactive
|
|
50
48
|
|
|
51
49
|
# Ask a specific question
|
|
52
|
-
npx -y @aigne/example-afs-
|
|
50
|
+
npx -y @aigne/example-afs-git --input "What files changed in the last commit on main?"
|
|
51
|
+
|
|
52
|
+
# Limit to specific branches
|
|
53
|
+
npx -y @aigne/example-afs-git --branches main,develop --interactive
|
|
53
54
|
|
|
54
|
-
#
|
|
55
|
-
npx -y @aigne/example-afs-
|
|
55
|
+
# Enable read-write mode with auto-commit
|
|
56
|
+
npx -y @aigne/example-afs-git --access-mode readwrite --auto-commit --interactive
|
|
56
57
|
|
|
57
|
-
# Read-
|
|
58
|
-
npx -y @aigne/example-afs-
|
|
58
|
+
# Read-write mode without auto-commit (manual commit control)
|
|
59
|
+
npx -y @aigne/example-afs-git --access-mode readwrite --interactive
|
|
59
60
|
```
|
|
60
61
|
|
|
61
62
|
## See It In Action
|
|
62
63
|
|
|
63
|
-
Here's what happens when you ask about
|
|
64
|
+
Here's what happens when you ask about code differences:
|
|
64
65
|
|
|
65
66
|
```
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
{ "name": "Bob", "email": "bob@example.com", "age": 30 },
|
|
70
|
-
{ "name": "Alice", "email": "alice@example.com", "age": 25 },
|
|
71
|
-
{ "name": "Charlie", "email": "charlie@example.com", "age": 35 }
|
|
72
|
-
],
|
|
73
|
-
"config": {
|
|
74
|
-
"appName": "MyApp",
|
|
75
|
-
"version": "1.0.0"
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
👤 You: "What's the email of the second user?"
|
|
80
|
-
|
|
81
|
-
🤖 Agent thinks: Let me explore the JSON structure...
|
|
67
|
+
👤 You: "What changed in the authentication code between main and develop?"
|
|
68
|
+
|
|
69
|
+
🤖 Agent thinks: I should list the available branches first...
|
|
82
70
|
→ Calls: afs_list("/")
|
|
83
71
|
|
|
84
|
-
📁 Found
|
|
85
|
-
• /
|
|
86
|
-
• /
|
|
72
|
+
📁 Found branches:
|
|
73
|
+
• /main
|
|
74
|
+
• /develop
|
|
75
|
+
• /feature-oauth
|
|
76
|
+
|
|
77
|
+
🤖 Agent thinks: Let me search for auth files in both branches...
|
|
78
|
+
→ Calls: afs_search("/main", "auth")
|
|
79
|
+
→ Calls: afs_search("/develop", "auth")
|
|
80
|
+
|
|
81
|
+
📄 Found files:
|
|
82
|
+
• /main/src/auth/index.ts
|
|
83
|
+
• /develop/src/auth/index.ts
|
|
84
|
+
• /develop/src/auth/oauth.ts (new!)
|
|
87
85
|
|
|
88
|
-
🤖 Agent thinks:
|
|
89
|
-
→ Calls:
|
|
86
|
+
🤖 Agent thinks: Let me read both versions...
|
|
87
|
+
→ Calls: afs_read("/main/src/auth/index.ts")
|
|
88
|
+
→ Calls: afs_read("/develop/src/auth/index.ts")
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
• /users/0 (first user)
|
|
93
|
-
• /users/1 (second user)
|
|
94
|
-
• /users/2 (third user)
|
|
90
|
+
🤖 AI: "The develop branch has added OAuth support to the authentication system:
|
|
95
91
|
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
Key Changes:
|
|
93
|
+
• Added a new oauth.ts module with OAuth 2.0 flow
|
|
94
|
+
• Updated index.ts with three new functions:
|
|
95
|
+
- initOAuthFlow()
|
|
96
|
+
- handleOAuthCallback()
|
|
97
|
+
- refreshOAuthToken()
|
|
98
|
+
• Added support for Google and GitHub providers
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
The main branch still uses the original JWT-only authentication.
|
|
101
|
+
Would you like me to explain how the OAuth flow works?"
|
|
100
102
|
```
|
|
101
103
|
|
|
102
|
-
**Key insight:**
|
|
104
|
+
**Key insight:** The agent can navigate between branches like directories, compare code, and identify what's new!
|
|
103
105
|
|
|
104
106
|
### Connect to an AI Model
|
|
105
107
|
|
|
106
|
-
As an example, running `npx -y @aigne/example-afs-
|
|
108
|
+
As an example, running `npx -y @aigne/example-afs-git --input "What branches exist?"` requires an AI model. If this is your first run, you need to connect one.
|
|
107
109
|
|
|
108
110
|
- Connect via the official AIGNE Hub
|
|
109
111
|
- Connect via a self-hosted AIGNE Hub
|
|
@@ -126,7 +128,7 @@ git clone https://github.com/AIGNE-io/aigne-framework
|
|
|
126
128
|
### Install Dependencies
|
|
127
129
|
|
|
128
130
|
```bash
|
|
129
|
-
cd aigne-framework/examples/afs-
|
|
131
|
+
cd aigne-framework/examples/afs-git
|
|
130
132
|
|
|
131
133
|
pnpm install
|
|
132
134
|
```
|
|
@@ -134,51 +136,47 @@ pnpm install
|
|
|
134
136
|
### Run the Example
|
|
135
137
|
|
|
136
138
|
```bash
|
|
137
|
-
# Run with
|
|
138
|
-
pnpm start
|
|
139
|
+
# Run with current repository (read-only by default)
|
|
140
|
+
pnpm start
|
|
141
|
+
|
|
142
|
+
# Run with a specific repository
|
|
143
|
+
pnpm start --path /path/to/repo
|
|
139
144
|
|
|
140
145
|
# Run in interactive chat mode
|
|
141
|
-
pnpm start --
|
|
146
|
+
pnpm start --interactive
|
|
147
|
+
|
|
148
|
+
# Limit to specific branches
|
|
149
|
+
pnpm start --branches main,develop --interactive
|
|
142
150
|
|
|
143
|
-
#
|
|
144
|
-
pnpm start --
|
|
151
|
+
# Enable read-write mode with auto-commit
|
|
152
|
+
pnpm start --access-mode readwrite --auto-commit --interactive
|
|
153
|
+
|
|
154
|
+
# Read-write mode without auto-commit
|
|
155
|
+
pnpm start --access-mode readwrite --interactive
|
|
145
156
|
```
|
|
146
157
|
|
|
147
158
|
### Command Line Options
|
|
148
159
|
|
|
149
160
|
| Option | Description | Default | Example |
|
|
150
161
|
|--------|-------------|---------|---------|
|
|
151
|
-
| `--path` | Path to the
|
|
152
|
-
| `--
|
|
162
|
+
| `--path` | Path to the git repository | Current directory | `--path /path/to/repo` |
|
|
163
|
+
| `--branches` | Comma-separated list of branches to access | All branches | `--branches main,develop` |
|
|
164
|
+
| `--access-mode` | Access mode: `readonly` or `readwrite` | `readonly` | `--access-mode readwrite` |
|
|
165
|
+
| `--auto-commit` | Automatically commit changes (requires `readwrite` mode) | `false` | `--auto-commit` |
|
|
153
166
|
| `--interactive` | Run in interactive chat mode | `false` | `--interactive` |
|
|
154
|
-
| `--input` | Single question to ask | - | `--input "What
|
|
155
|
-
|
|
156
|
-
**Supported file formats:**
|
|
157
|
-
- `.json` - JSON files
|
|
158
|
-
- `.yaml` - YAML files
|
|
159
|
-
- `.yml` - YAML files
|
|
160
|
-
|
|
161
|
-
File format is automatically detected from the extension.
|
|
167
|
+
| `--input` | Single question to ask | - | `--input "What branches exist?"` |
|
|
162
168
|
|
|
163
169
|
## How It Works: 3 Simple Steps
|
|
164
170
|
|
|
165
|
-
### 1. Create
|
|
171
|
+
### 1. Create AFSGit Module
|
|
166
172
|
|
|
167
173
|
```typescript
|
|
168
|
-
import {
|
|
169
|
-
|
|
170
|
-
// Works with JSON files
|
|
171
|
-
const afsJson = new AFSJSON({
|
|
172
|
-
jsonPath: './data.json',
|
|
173
|
-
name: 'data', // optional: module name
|
|
174
|
-
accessMode: 'readwrite' // or 'readonly'
|
|
175
|
-
});
|
|
174
|
+
import { AFSGit } from "@aigne/afs-git";
|
|
176
175
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
accessMode: 'readwrite'
|
|
176
|
+
const afsGit = new AFSGit({
|
|
177
|
+
repoPath: process.cwd(),
|
|
178
|
+
accessMode: 'readonly', // or 'readwrite' for modifications
|
|
179
|
+
branches: ['main', 'develop'] // optional: limit branches
|
|
182
180
|
});
|
|
183
181
|
```
|
|
184
182
|
|
|
@@ -190,7 +188,7 @@ import { AFSHistory } from "@aigne/afs-history";
|
|
|
190
188
|
|
|
191
189
|
const afs = new AFS()
|
|
192
190
|
.mount(new AFSHistory({ storage: { url: ":memory:" } }))
|
|
193
|
-
.mount(
|
|
191
|
+
.mount(afsGit); // Mounted at /modules/{repo-name}
|
|
194
192
|
```
|
|
195
193
|
|
|
196
194
|
### 3. Create an AI Agent
|
|
@@ -199,238 +197,170 @@ const afs = new AFS()
|
|
|
199
197
|
import { AIAgent } from "@aigne/core";
|
|
200
198
|
|
|
201
199
|
const agent = AIAgent.from({
|
|
202
|
-
instructions: "Help users
|
|
200
|
+
instructions: "Help users navigate and understand Git repositories.",
|
|
203
201
|
inputKey: "message",
|
|
204
|
-
afs, // Agent gets: afs_list, afs_read,
|
|
202
|
+
afs, // Agent gets: afs_list, afs_read, afs_search
|
|
205
203
|
});
|
|
206
204
|
```
|
|
207
205
|
|
|
208
|
-
**That's it!** The agent can now navigate
|
|
206
|
+
**That's it!** The agent can now intelligently navigate branches and search through repository files.
|
|
209
207
|
|
|
210
208
|
### What the Agent Can Do
|
|
211
209
|
|
|
212
|
-
**Read
|
|
213
|
-
- **`afs_list`** - List
|
|
214
|
-
- **`afs_read`** - Read
|
|
215
|
-
- **`afs_search`** -
|
|
216
|
-
|
|
217
|
-
**Write Operations (readwrite mode):**
|
|
218
|
-
- **`afs_write`** - Update or create properties
|
|
219
|
-
- **`afs_delete`** - Delete properties or array elements
|
|
220
|
-
- **`afs_rename`** - Rename properties
|
|
210
|
+
**Read-Only Mode (default):**
|
|
211
|
+
- **`afs_list`** - List branches and files (with recursive depth control)
|
|
212
|
+
- **`afs_read`** - Read file contents from any branch
|
|
213
|
+
- **`afs_search`** - Fast search using git grep (regex support)
|
|
221
214
|
|
|
222
|
-
|
|
215
|
+
**Read-Write Mode:**
|
|
216
|
+
- **`afs_write`** - Create or modify files (uses git worktrees)
|
|
217
|
+
- **`afs_delete`** - Delete files with auto-commit
|
|
218
|
+
- **`afs_rename`** - Rename/move files with auto-commit
|
|
223
219
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
```json
|
|
227
|
-
// Given this JSON:
|
|
228
|
-
{
|
|
229
|
-
"users": [
|
|
230
|
-
{ "name": "Bob", "email": "bob@example.com" },
|
|
231
|
-
{ "name": "Alice", "email": "alice@example.com" }
|
|
232
|
-
],
|
|
233
|
-
"config": {
|
|
234
|
-
"theme": "dark",
|
|
235
|
-
"lang": "en"
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Mapped to AFS paths:
|
|
240
|
-
/ # Root
|
|
241
|
-
├── users/ # Array (directory)
|
|
242
|
-
│ ├── 0/ # First user (directory)
|
|
243
|
-
│ │ ├── name # File: "Bob"
|
|
244
|
-
│ │ └── email # File: "bob@example.com"
|
|
245
|
-
│ └── 1/ # Second user (directory)
|
|
246
|
-
│ ├── name # File: "Alice"
|
|
247
|
-
│ └── email # File: "alice@example.com"
|
|
248
|
-
└── config/ # Object (directory)
|
|
249
|
-
├── theme # File: "dark"
|
|
250
|
-
└── lang # File: "en"
|
|
251
|
-
```
|
|
220
|
+
All operations use efficient git commands - no workspace pollution!
|
|
252
221
|
|
|
253
222
|
## Try These Examples
|
|
254
223
|
|
|
255
224
|
```bash
|
|
256
|
-
#
|
|
257
|
-
npx -y @aigne/example-afs-
|
|
258
|
-
|
|
259
|
-
# Query YAML configuration
|
|
260
|
-
npx -y @aigne/example-afs-json --path ./config.yaml --input "What's the database host?"
|
|
225
|
+
# List all branches
|
|
226
|
+
npx -y @aigne/example-afs-git --input "What branches exist?"
|
|
261
227
|
|
|
262
|
-
#
|
|
263
|
-
npx -y @aigne/example-afs-
|
|
228
|
+
# Compare branches
|
|
229
|
+
npx -y @aigne/example-afs-git --input "What files are different between main and develop?"
|
|
264
230
|
|
|
265
|
-
# Search
|
|
266
|
-
npx -y @aigne/example-afs-
|
|
231
|
+
# Search across branches
|
|
232
|
+
npx -y @aigne/example-afs-git --input "Find all TODO comments in the main branch"
|
|
267
233
|
|
|
268
|
-
#
|
|
269
|
-
npx -y @aigne/example-afs-
|
|
270
|
-
|
|
271
|
-
# Update YAML file
|
|
272
|
-
npx -y @aigne/example-afs-json --path ./config.yaml --input "Change the database port to 3306"
|
|
234
|
+
# Code review
|
|
235
|
+
npx -y @aigne/example-afs-git --input "Review the authentication code in src/auth/"
|
|
273
236
|
|
|
274
237
|
# Interactive mode - ask follow-up questions
|
|
275
|
-
npx -y @aigne/example-afs-
|
|
238
|
+
npx -y @aigne/example-afs-git --interactive
|
|
276
239
|
```
|
|
277
240
|
|
|
278
241
|
**In chat mode, try:**
|
|
279
|
-
- "What
|
|
280
|
-
- "Show me
|
|
281
|
-
- "
|
|
282
|
-
- "
|
|
283
|
-
- "
|
|
284
|
-
- "
|
|
242
|
+
- "What branches are available?"
|
|
243
|
+
- "Show me the README from the main branch"
|
|
244
|
+
- "Search for 'authentication' in the develop branch"
|
|
245
|
+
- "What files exist in /main/src?"
|
|
246
|
+
- "Compare the package.json between main and feature-oauth"
|
|
247
|
+
- "What TypeScript files changed recently?"
|
|
285
248
|
|
|
286
249
|
## Use Cases
|
|
287
250
|
|
|
288
|
-
###
|
|
289
|
-
Let AI help
|
|
251
|
+
### Code Review Assistance
|
|
252
|
+
Let AI help review code across branches:
|
|
290
253
|
```typescript
|
|
291
|
-
// JSON configuration
|
|
292
|
-
const afs = new AFS()
|
|
293
|
-
.mount(new AFSJSON({
|
|
294
|
-
jsonPath: './config.json',
|
|
295
|
-
accessMode: 'readwrite'
|
|
296
|
-
}));
|
|
297
|
-
|
|
298
|
-
// YAML configuration (common in Kubernetes, Docker Compose)
|
|
299
254
|
const afs = new AFS()
|
|
300
|
-
.mount(new
|
|
301
|
-
|
|
302
|
-
|
|
255
|
+
.mount(new AFSGit({
|
|
256
|
+
repoPath: './my-project',
|
|
257
|
+
branches: ['main', 'feature-branch']
|
|
303
258
|
}));
|
|
304
|
-
// Ask: "
|
|
259
|
+
// Ask: "Review the changes in feature-branch compared to main"
|
|
305
260
|
```
|
|
306
261
|
|
|
307
|
-
###
|
|
308
|
-
|
|
262
|
+
### Multi-Branch Documentation
|
|
263
|
+
Access documentation from different versions:
|
|
309
264
|
```typescript
|
|
310
265
|
const afs = new AFS()
|
|
311
|
-
.mount(new
|
|
312
|
-
|
|
313
|
-
|
|
266
|
+
.mount(new AFSGit({
|
|
267
|
+
repoPath: './docs-repo',
|
|
268
|
+
branches: ['v1.0', 'v2.0', 'latest']
|
|
314
269
|
}));
|
|
315
|
-
// Ask: "What's the
|
|
270
|
+
// Ask: "What's the difference in API docs between v1.0 and v2.0?"
|
|
316
271
|
```
|
|
317
272
|
|
|
318
|
-
###
|
|
319
|
-
|
|
273
|
+
### Repository Analysis
|
|
274
|
+
Analyze code patterns across branches:
|
|
320
275
|
```typescript
|
|
321
276
|
const afs = new AFS()
|
|
322
|
-
.mount(new
|
|
323
|
-
|
|
277
|
+
.mount(new AFSGit({
|
|
278
|
+
repoPath: './codebase',
|
|
324
279
|
accessMode: 'readonly'
|
|
325
280
|
}));
|
|
326
|
-
// Ask: "Find all
|
|
281
|
+
// Ask: "Find all deprecated functions across all branches"
|
|
327
282
|
```
|
|
328
283
|
|
|
329
|
-
###
|
|
330
|
-
|
|
284
|
+
### Multi-Repository Access
|
|
285
|
+
Mount multiple repositories simultaneously:
|
|
331
286
|
```typescript
|
|
332
287
|
const afs = new AFS()
|
|
333
|
-
.mount(new
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
// Ask: "Enable dark mode and set font size to 14"
|
|
288
|
+
.mount("/frontend", new AFSGit({ repoPath: './frontend' }))
|
|
289
|
+
.mount("/backend", new AFSGit({ repoPath: './backend' }))
|
|
290
|
+
.mount("/docs", new AFSGit({ repoPath: './docs' }));
|
|
291
|
+
// Agent can search across all repositories
|
|
338
292
|
```
|
|
339
293
|
|
|
340
|
-
###
|
|
341
|
-
|
|
294
|
+
### Automated Code Modifications (Read-Write Mode)
|
|
295
|
+
Let AI make commits with auto-commit:
|
|
342
296
|
```typescript
|
|
343
297
|
const afs = new AFS()
|
|
344
|
-
.mount(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
298
|
+
.mount(new AFSGit({
|
|
299
|
+
repoPath: './my-project',
|
|
300
|
+
accessMode: 'readwrite',
|
|
301
|
+
autoCommit: true,
|
|
302
|
+
commitAuthor: {
|
|
303
|
+
name: 'AI Agent',
|
|
304
|
+
email: 'agent@example.com'
|
|
305
|
+
}
|
|
306
|
+
}));
|
|
307
|
+
// Ask: "Update the version in package.json to 2.0.0"
|
|
349
308
|
```
|
|
350
309
|
|
|
351
|
-
##
|
|
352
|
-
|
|
353
|
-
### Objects as Directories
|
|
354
|
-
```json
|
|
355
|
-
{ "name": "Bob", "age": 30 }
|
|
356
|
-
```
|
|
357
|
-
→ `/name` (file), `/age` (file)
|
|
310
|
+
## Path Structure
|
|
358
311
|
|
|
359
|
-
### Arrays as Directories
|
|
360
|
-
```json
|
|
361
|
-
["apple", "banana", "orange"]
|
|
362
|
-
```
|
|
363
|
-
→ `/0` (file: "apple"), `/1` (file: "banana"), `/2` (file: "orange")
|
|
364
|
-
|
|
365
|
-
### Nested Structures
|
|
366
|
-
```json
|
|
367
|
-
{
|
|
368
|
-
"user": {
|
|
369
|
-
"profile": {
|
|
370
|
-
"name": "Bob"
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
312
|
```
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
313
|
+
/ # Root - lists all branches
|
|
314
|
+
├── main/ # Branch directory
|
|
315
|
+
│ ├── src/
|
|
316
|
+
│ │ └── index.ts # Files: /main/src/index.ts
|
|
317
|
+
│ ├── package.json
|
|
318
|
+
│ └── README.md
|
|
319
|
+
├── develop/ # Another branch
|
|
320
|
+
│ └── ...
|
|
321
|
+
└── feature-auth/ # Feature branch
|
|
322
|
+
└── ...
|
|
385
323
|
```
|
|
386
|
-
→ `/users/0/name` (file: "Bob")
|
|
387
|
-
→ `/users/0/email` (file: "bob@example.com")
|
|
388
|
-
→ `/users/1/name` (file: "Alice")
|
|
389
|
-
→ `/users/1/email` (file: "alice@example.com")
|
|
390
324
|
|
|
391
325
|
## Advanced Features
|
|
392
326
|
|
|
393
|
-
###
|
|
394
|
-
|
|
327
|
+
### Branch Filtering
|
|
328
|
+
Only expose specific branches:
|
|
395
329
|
```typescript
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
330
|
+
const afsGit = new AFSGit({
|
|
331
|
+
repoPath: './repo',
|
|
332
|
+
branches: ['main', 'develop'] // Only these branches visible
|
|
399
333
|
});
|
|
400
334
|
```
|
|
401
335
|
|
|
402
|
-
###
|
|
403
|
-
|
|
336
|
+
### Read-Write with Manual Control
|
|
337
|
+
Make modifications without auto-commit:
|
|
404
338
|
```typescript
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
339
|
+
const afsGit = new AFSGit({
|
|
340
|
+
repoPath: './repo',
|
|
341
|
+
accessMode: 'readwrite',
|
|
342
|
+
autoCommit: false // Agent can write, you commit manually
|
|
343
|
+
});
|
|
408
344
|
```
|
|
409
345
|
|
|
410
|
-
###
|
|
411
|
-
|
|
346
|
+
### Efficient Search
|
|
347
|
+
Uses git grep for fast searching:
|
|
412
348
|
```typescript
|
|
413
|
-
//
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
// Delete array element (indices shift automatically)
|
|
417
|
-
// Ask: "Remove the second user"
|
|
418
|
-
|
|
419
|
-
// Update array element
|
|
420
|
-
// Ask: "Update the first user's email to newemail@example.com"
|
|
349
|
+
// Agent automatically uses optimized git grep
|
|
350
|
+
await afsGit.search('/main/src', 'TODO');
|
|
351
|
+
// Much faster than reading every file!
|
|
421
352
|
```
|
|
422
353
|
|
|
423
354
|
## Related Examples
|
|
424
355
|
|
|
425
356
|
- [AFS LocalFS Example](../afs-local-fs/README.md) - Local file system access
|
|
426
|
-
- [AFS Git Example](../afs-git/README.md) - Git repository access
|
|
427
357
|
- [AFS Memory Example](../afs-memory/README.md) - Conversational memory with user profiles
|
|
428
358
|
- [AFS MCP Server Example](../afs-mcp-server/README.md) - Integration with MCP servers
|
|
429
359
|
|
|
430
360
|
## Related Packages
|
|
431
361
|
|
|
432
362
|
- [@aigne/afs](../../afs/README.md) - AFS core package
|
|
433
|
-
- [@aigne/afs-
|
|
363
|
+
- [@aigne/afs-git](../../afs/git/README.md) - AFSGit module documentation
|
|
434
364
|
|
|
435
365
|
## TypeScript Support
|
|
436
366
|
|
package/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env npx -y bun
|
|
2
2
|
|
|
3
3
|
import { AFS, type AFSAccessMode } from "@aigne/afs";
|
|
4
|
+
import { AFSGit } from "@aigne/afs-git";
|
|
4
5
|
import { AFSHistory } from "@aigne/afs-history";
|
|
5
|
-
import { AFSJSON } from "@aigne/afs-json";
|
|
6
6
|
import { loadAIGNEWithCmdOptions, runWithAIGNE } from "@aigne/cli/utils/run-with-aigne.js";
|
|
7
7
|
import { AIAgent } from "@aigne/core";
|
|
8
8
|
import yargs from "yargs";
|
|
@@ -10,7 +10,7 @@ import yargs from "yargs";
|
|
|
10
10
|
const argv = yargs()
|
|
11
11
|
.option("path", {
|
|
12
12
|
type: "string",
|
|
13
|
-
describe: "Path to the
|
|
13
|
+
describe: "Path to the git repo to mount",
|
|
14
14
|
default: ".",
|
|
15
15
|
})
|
|
16
16
|
.option("description", {
|
|
@@ -22,7 +22,12 @@ const argv = yargs()
|
|
|
22
22
|
type: "string",
|
|
23
23
|
choices: ["readonly", "readwrite"],
|
|
24
24
|
default: "readonly",
|
|
25
|
-
describe: "Access mode for the mounted
|
|
25
|
+
describe: "Access mode for the mounted repo",
|
|
26
|
+
})
|
|
27
|
+
.option("auto-commit", {
|
|
28
|
+
type: "boolean",
|
|
29
|
+
default: false,
|
|
30
|
+
describe: "Automatically commit changes to the mounted repo",
|
|
26
31
|
})
|
|
27
32
|
.demandOption("path")
|
|
28
33
|
.strict(false)
|
|
@@ -33,10 +38,11 @@ const aigne = await loadAIGNEWithCmdOptions();
|
|
|
33
38
|
const afs = new AFS()
|
|
34
39
|
.mount(new AFSHistory({ storage: { url: ":memory:" } })) // In-memory history for this example
|
|
35
40
|
.mount(
|
|
36
|
-
new
|
|
37
|
-
|
|
41
|
+
new AFSGit({
|
|
42
|
+
repoPath: argv.path,
|
|
38
43
|
description: argv.description,
|
|
39
44
|
accessMode: argv.accessMode as AFSAccessMode,
|
|
45
|
+
autoCommit: argv.autoCommit,
|
|
40
46
|
}),
|
|
41
47
|
);
|
|
42
48
|
|
|
@@ -50,7 +56,7 @@ You should use the provided functions to list, search, and read files as needed
|
|
|
50
56
|
|
|
51
57
|
{{ $afs.modules | yaml.stringify }}
|
|
52
58
|
</afs_modules>
|
|
53
|
-
`,
|
|
59
|
+
`,
|
|
54
60
|
inputKey: "message",
|
|
55
61
|
afs,
|
|
56
62
|
});
|
|
@@ -59,6 +65,6 @@ await runWithAIGNE(agent, {
|
|
|
59
65
|
aigne,
|
|
60
66
|
chatLoopOptions: {
|
|
61
67
|
welcome:
|
|
62
|
-
"Hello! I'm a chatbot that can help you interact with a
|
|
68
|
+
"Hello! I'm a chatbot that can help you interact with a git repo mounted on AFS. Ask me anything about the repo!",
|
|
63
69
|
},
|
|
64
70
|
});
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/example-afs-git",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A demonstration of using AIGNE Framework with AFS
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A demonstration of using AIGNE Framework with AFS git module",
|
|
5
5
|
"author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
|
|
6
|
-
"homepage": "https://github.com/AIGNE-io/aigne-framework/tree/main/examples/afs-
|
|
6
|
+
"homepage": "https://github.com/AIGNE-io/aigne-framework/tree/main/examples/afs-git",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"yargs": "^18.0.0",
|
|
20
|
-
"@aigne/afs-history": "^1.2.0-beta.11",
|
|
21
20
|
"@aigne/afs": "^1.4.0-beta.10",
|
|
22
|
-
"@aigne/afs-
|
|
21
|
+
"@aigne/afs-history": "^1.2.0-beta.11",
|
|
22
|
+
"@aigne/afs-git": "^1.0.0",
|
|
23
23
|
"@aigne/cli": "^1.59.0-beta.30",
|
|
24
24
|
"@aigne/core": "^1.72.0-beta.24"
|
|
25
25
|
},
|