@aigne/afs-git 1.11.0-beta.7 → 1.11.0-beta.9
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/dist/_virtual/rolldown_runtime.mjs +7 -0
- package/dist/index.cjs +25 -0
- package/dist/index.d.cts +39 -120
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +39 -120
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +26 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -38,6 +38,20 @@ var AFSGit = class AFSGit extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
38
38
|
static schema() {
|
|
39
39
|
return afsGitOptionsSchema;
|
|
40
40
|
}
|
|
41
|
+
static manifest() {
|
|
42
|
+
return {
|
|
43
|
+
name: "git",
|
|
44
|
+
description: "Mount a local Git repository",
|
|
45
|
+
uriTemplate: "git://{localPath+}",
|
|
46
|
+
category: "version-control",
|
|
47
|
+
schema: zod.z.object({
|
|
48
|
+
localPath: zod.z.string(),
|
|
49
|
+
branch: zod.z.string().optional(),
|
|
50
|
+
remoteUrl: zod.z.string().optional()
|
|
51
|
+
}),
|
|
52
|
+
tags: ["git", "version-control"]
|
|
53
|
+
};
|
|
54
|
+
}
|
|
41
55
|
static async load({ basePath, config } = {}) {
|
|
42
56
|
const instance = new AFSGit({
|
|
43
57
|
...await AFSGit.schema().parseAsync(config),
|
|
@@ -60,6 +74,8 @@ var AFSGit = class AFSGit extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
60
74
|
constructor(options) {
|
|
61
75
|
super();
|
|
62
76
|
this.options = options;
|
|
77
|
+
if (options.localPath && !options.repoPath) options.repoPath = options.localPath;
|
|
78
|
+
if (options.branch && !options.branches) options.branches = [options.branch];
|
|
63
79
|
(0, _aigne_afs_utils_zod.zodParse)(afsGitOptionsSchema, options);
|
|
64
80
|
let repoPath;
|
|
65
81
|
let repoName;
|
|
@@ -72,6 +88,15 @@ var AFSGit = class AFSGit extends _aigne_afs_provider.AFSBaseProvider {
|
|
|
72
88
|
const repoHash = (0, node_crypto.createHash)("md5").update(options.remoteUrl).digest("hex").substring(0, 8);
|
|
73
89
|
repoPath = (0, node_path.join)((0, node_os.tmpdir)(), `afs-git-remote-${repoHash}`);
|
|
74
90
|
} else throw new Error("Either repoPath or remoteUrl must be provided");
|
|
91
|
+
if (options.repoPath && !options.remoteUrl) {
|
|
92
|
+
const { existsSync, mkdirSync } = require("node:fs");
|
|
93
|
+
const { execSync } = require("node:child_process");
|
|
94
|
+
if (!existsSync(repoPath)) mkdirSync(repoPath, { recursive: true });
|
|
95
|
+
if (!existsSync((0, node_path.join)(repoPath, ".git"))) execSync("git init -b main", {
|
|
96
|
+
cwd: repoPath,
|
|
97
|
+
stdio: "ignore"
|
|
98
|
+
});
|
|
99
|
+
}
|
|
75
100
|
this.repoPath = repoPath;
|
|
76
101
|
this.name = options.name || repoName;
|
|
77
102
|
this.description = options.description;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AFSAccessMode, AFSEntry, AFSExecResult, AFSExplainResult, AFSListResult, AFSModuleLoadParams, AFSSearchOptions, AFSStatResult, AFSWriteEntryPayload } from "@aigne/afs";
|
|
1
|
+
import { AFSAccessMode, AFSEntry, AFSExecResult, AFSExplainResult, AFSListResult, AFSModuleLoadParams, AFSSearchOptions, AFSStatResult, AFSWriteEntryPayload, ProviderManifest } from "@aigne/afs";
|
|
2
2
|
import { AFSBaseProvider, RouteContext } from "@aigne/afs/provider";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
@@ -74,136 +74,52 @@ interface AFSGitOptions {
|
|
|
74
74
|
declare class AFSGit extends AFSBaseProvider {
|
|
75
75
|
options: AFSGitOptions & {
|
|
76
76
|
cwd?: string;
|
|
77
|
+
localPath?: string;
|
|
78
|
+
branch?: string;
|
|
79
|
+
uri?: string;
|
|
77
80
|
};
|
|
78
|
-
static schema(): z.
|
|
79
|
-
name:
|
|
80
|
-
repoPath:
|
|
81
|
-
remoteUrl:
|
|
82
|
-
description:
|
|
83
|
-
branches:
|
|
84
|
-
accessMode:
|
|
85
|
-
autoCommit:
|
|
86
|
-
commitAuthor:
|
|
87
|
-
name: string;
|
|
88
|
-
email: string;
|
|
89
|
-
} | undefined, z.ZodTypeDef, {
|
|
90
|
-
name: string;
|
|
91
|
-
email: string;
|
|
92
|
-
} | undefined>;
|
|
93
|
-
depth: z.ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
|
|
94
|
-
autoCleanup: z.ZodType<boolean | undefined, z.ZodTypeDef, boolean | undefined>;
|
|
95
|
-
cloneOptions: z.ZodType<{
|
|
96
|
-
auth?: {
|
|
97
|
-
username?: string | undefined;
|
|
98
|
-
password?: string | undefined;
|
|
99
|
-
} | undefined;
|
|
100
|
-
} | undefined, z.ZodTypeDef, {
|
|
101
|
-
auth?: {
|
|
102
|
-
username?: string | undefined;
|
|
103
|
-
password?: string | undefined;
|
|
104
|
-
} | undefined;
|
|
105
|
-
} | undefined>;
|
|
106
|
-
}, "strip", z.ZodTypeAny, {
|
|
107
|
-
name?: string | undefined;
|
|
108
|
-
repoPath?: string | undefined;
|
|
109
|
-
remoteUrl?: string | undefined;
|
|
110
|
-
description?: string | undefined;
|
|
111
|
-
branches?: string[] | undefined;
|
|
112
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
113
|
-
autoCommit?: boolean | undefined;
|
|
114
|
-
commitAuthor?: {
|
|
115
|
-
name: string;
|
|
116
|
-
email: string;
|
|
117
|
-
} | undefined;
|
|
118
|
-
depth?: number | undefined;
|
|
119
|
-
autoCleanup?: boolean | undefined;
|
|
120
|
-
cloneOptions?: {
|
|
121
|
-
auth?: {
|
|
122
|
-
username?: string | undefined;
|
|
123
|
-
password?: string | undefined;
|
|
124
|
-
} | undefined;
|
|
125
|
-
} | undefined;
|
|
126
|
-
}, {
|
|
127
|
-
name?: string | undefined;
|
|
128
|
-
repoPath?: string | undefined;
|
|
129
|
-
remoteUrl?: string | undefined;
|
|
130
|
-
description?: string | undefined;
|
|
131
|
-
branches?: string[] | undefined;
|
|
132
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
133
|
-
autoCommit?: boolean | undefined;
|
|
134
|
-
commitAuthor?: {
|
|
135
|
-
name: string;
|
|
136
|
-
email: string;
|
|
137
|
-
} | undefined;
|
|
138
|
-
depth?: number | undefined;
|
|
139
|
-
autoCleanup?: boolean | undefined;
|
|
140
|
-
cloneOptions?: {
|
|
141
|
-
auth?: {
|
|
142
|
-
username?: string | undefined;
|
|
143
|
-
password?: string | undefined;
|
|
144
|
-
} | undefined;
|
|
145
|
-
} | undefined;
|
|
146
|
-
}>, {
|
|
147
|
-
name?: string | undefined;
|
|
148
|
-
repoPath?: string | undefined;
|
|
149
|
-
remoteUrl?: string | undefined;
|
|
150
|
-
description?: string | undefined;
|
|
151
|
-
branches?: string[] | undefined;
|
|
152
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
153
|
-
autoCommit?: boolean | undefined;
|
|
154
|
-
commitAuthor?: {
|
|
155
|
-
name: string;
|
|
156
|
-
email: string;
|
|
157
|
-
} | undefined;
|
|
158
|
-
depth?: number | undefined;
|
|
159
|
-
autoCleanup?: boolean | undefined;
|
|
160
|
-
cloneOptions?: {
|
|
161
|
-
auth?: {
|
|
162
|
-
username?: string | undefined;
|
|
163
|
-
password?: string | undefined;
|
|
164
|
-
} | undefined;
|
|
165
|
-
} | undefined;
|
|
166
|
-
}, {
|
|
167
|
-
name?: string | undefined;
|
|
168
|
-
repoPath?: string | undefined;
|
|
169
|
-
remoteUrl?: string | undefined;
|
|
170
|
-
description?: string | undefined;
|
|
171
|
-
branches?: string[] | undefined;
|
|
172
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
173
|
-
autoCommit?: boolean | undefined;
|
|
174
|
-
commitAuthor?: {
|
|
81
|
+
static schema(): z.ZodType<{
|
|
82
|
+
name: string | undefined;
|
|
83
|
+
repoPath: string | undefined;
|
|
84
|
+
remoteUrl: string | undefined;
|
|
85
|
+
description: string | undefined;
|
|
86
|
+
branches: string[] | undefined;
|
|
87
|
+
accessMode: "readonly" | "readwrite" | undefined;
|
|
88
|
+
autoCommit: boolean | undefined;
|
|
89
|
+
commitAuthor: {
|
|
175
90
|
name: string;
|
|
176
91
|
email: string;
|
|
177
92
|
} | undefined;
|
|
178
|
-
depth
|
|
179
|
-
autoCleanup
|
|
180
|
-
cloneOptions
|
|
181
|
-
auth
|
|
182
|
-
username
|
|
183
|
-
password
|
|
93
|
+
depth: number | undefined;
|
|
94
|
+
autoCleanup: boolean | undefined;
|
|
95
|
+
cloneOptions: {
|
|
96
|
+
auth: {
|
|
97
|
+
username: string | undefined;
|
|
98
|
+
password: string | undefined;
|
|
184
99
|
} | undefined;
|
|
185
100
|
} | undefined;
|
|
186
|
-
}
|
|
187
|
-
name
|
|
188
|
-
repoPath
|
|
189
|
-
remoteUrl
|
|
190
|
-
description
|
|
191
|
-
branches
|
|
192
|
-
accessMode
|
|
193
|
-
autoCommit
|
|
194
|
-
commitAuthor
|
|
101
|
+
}, unknown, z.core.$ZodTypeInternals<{
|
|
102
|
+
name: string | undefined;
|
|
103
|
+
repoPath: string | undefined;
|
|
104
|
+
remoteUrl: string | undefined;
|
|
105
|
+
description: string | undefined;
|
|
106
|
+
branches: string[] | undefined;
|
|
107
|
+
accessMode: "readonly" | "readwrite" | undefined;
|
|
108
|
+
autoCommit: boolean | undefined;
|
|
109
|
+
commitAuthor: {
|
|
195
110
|
name: string;
|
|
196
111
|
email: string;
|
|
197
112
|
} | undefined;
|
|
198
|
-
depth
|
|
199
|
-
autoCleanup
|
|
200
|
-
cloneOptions
|
|
201
|
-
auth
|
|
202
|
-
username
|
|
203
|
-
password
|
|
113
|
+
depth: number | undefined;
|
|
114
|
+
autoCleanup: boolean | undefined;
|
|
115
|
+
cloneOptions: {
|
|
116
|
+
auth: {
|
|
117
|
+
username: string | undefined;
|
|
118
|
+
password: string | undefined;
|
|
204
119
|
} | undefined;
|
|
205
120
|
} | undefined;
|
|
206
|
-
},
|
|
121
|
+
}, unknown>>;
|
|
122
|
+
static manifest(): ProviderManifest;
|
|
207
123
|
static load({
|
|
208
124
|
basePath,
|
|
209
125
|
config
|
|
@@ -221,6 +137,9 @@ declare class AFSGit extends AFSBaseProvider {
|
|
|
221
137
|
private repoPath;
|
|
222
138
|
constructor(options: AFSGitOptions & {
|
|
223
139
|
cwd?: string;
|
|
140
|
+
localPath?: string;
|
|
141
|
+
branch?: string;
|
|
142
|
+
uri?: string;
|
|
224
143
|
});
|
|
225
144
|
/**
|
|
226
145
|
* Wait for async initialization to complete
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AFSAccessMode, AFSEntry, AFSExecResult, AFSExplainResult, AFSListResult, AFSModuleLoadParams, AFSSearchOptions, AFSStatResult, AFSWriteEntryPayload } from "@aigne/afs";
|
|
1
|
+
import { AFSAccessMode, AFSEntry, AFSExecResult, AFSExplainResult, AFSListResult, AFSModuleLoadParams, AFSSearchOptions, AFSStatResult, AFSWriteEntryPayload, ProviderManifest } from "@aigne/afs";
|
|
2
2
|
import { AFSBaseProvider, RouteContext } from "@aigne/afs/provider";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
@@ -74,136 +74,52 @@ interface AFSGitOptions {
|
|
|
74
74
|
declare class AFSGit extends AFSBaseProvider {
|
|
75
75
|
options: AFSGitOptions & {
|
|
76
76
|
cwd?: string;
|
|
77
|
+
localPath?: string;
|
|
78
|
+
branch?: string;
|
|
79
|
+
uri?: string;
|
|
77
80
|
};
|
|
78
|
-
static schema(): z.
|
|
79
|
-
name:
|
|
80
|
-
repoPath:
|
|
81
|
-
remoteUrl:
|
|
82
|
-
description:
|
|
83
|
-
branches:
|
|
84
|
-
accessMode:
|
|
85
|
-
autoCommit:
|
|
86
|
-
commitAuthor:
|
|
87
|
-
name: string;
|
|
88
|
-
email: string;
|
|
89
|
-
} | undefined, z.ZodTypeDef, {
|
|
90
|
-
name: string;
|
|
91
|
-
email: string;
|
|
92
|
-
} | undefined>;
|
|
93
|
-
depth: z.ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
|
|
94
|
-
autoCleanup: z.ZodType<boolean | undefined, z.ZodTypeDef, boolean | undefined>;
|
|
95
|
-
cloneOptions: z.ZodType<{
|
|
96
|
-
auth?: {
|
|
97
|
-
username?: string | undefined;
|
|
98
|
-
password?: string | undefined;
|
|
99
|
-
} | undefined;
|
|
100
|
-
} | undefined, z.ZodTypeDef, {
|
|
101
|
-
auth?: {
|
|
102
|
-
username?: string | undefined;
|
|
103
|
-
password?: string | undefined;
|
|
104
|
-
} | undefined;
|
|
105
|
-
} | undefined>;
|
|
106
|
-
}, "strip", z.ZodTypeAny, {
|
|
107
|
-
name?: string | undefined;
|
|
108
|
-
repoPath?: string | undefined;
|
|
109
|
-
remoteUrl?: string | undefined;
|
|
110
|
-
description?: string | undefined;
|
|
111
|
-
branches?: string[] | undefined;
|
|
112
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
113
|
-
autoCommit?: boolean | undefined;
|
|
114
|
-
commitAuthor?: {
|
|
115
|
-
name: string;
|
|
116
|
-
email: string;
|
|
117
|
-
} | undefined;
|
|
118
|
-
depth?: number | undefined;
|
|
119
|
-
autoCleanup?: boolean | undefined;
|
|
120
|
-
cloneOptions?: {
|
|
121
|
-
auth?: {
|
|
122
|
-
username?: string | undefined;
|
|
123
|
-
password?: string | undefined;
|
|
124
|
-
} | undefined;
|
|
125
|
-
} | undefined;
|
|
126
|
-
}, {
|
|
127
|
-
name?: string | undefined;
|
|
128
|
-
repoPath?: string | undefined;
|
|
129
|
-
remoteUrl?: string | undefined;
|
|
130
|
-
description?: string | undefined;
|
|
131
|
-
branches?: string[] | undefined;
|
|
132
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
133
|
-
autoCommit?: boolean | undefined;
|
|
134
|
-
commitAuthor?: {
|
|
135
|
-
name: string;
|
|
136
|
-
email: string;
|
|
137
|
-
} | undefined;
|
|
138
|
-
depth?: number | undefined;
|
|
139
|
-
autoCleanup?: boolean | undefined;
|
|
140
|
-
cloneOptions?: {
|
|
141
|
-
auth?: {
|
|
142
|
-
username?: string | undefined;
|
|
143
|
-
password?: string | undefined;
|
|
144
|
-
} | undefined;
|
|
145
|
-
} | undefined;
|
|
146
|
-
}>, {
|
|
147
|
-
name?: string | undefined;
|
|
148
|
-
repoPath?: string | undefined;
|
|
149
|
-
remoteUrl?: string | undefined;
|
|
150
|
-
description?: string | undefined;
|
|
151
|
-
branches?: string[] | undefined;
|
|
152
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
153
|
-
autoCommit?: boolean | undefined;
|
|
154
|
-
commitAuthor?: {
|
|
155
|
-
name: string;
|
|
156
|
-
email: string;
|
|
157
|
-
} | undefined;
|
|
158
|
-
depth?: number | undefined;
|
|
159
|
-
autoCleanup?: boolean | undefined;
|
|
160
|
-
cloneOptions?: {
|
|
161
|
-
auth?: {
|
|
162
|
-
username?: string | undefined;
|
|
163
|
-
password?: string | undefined;
|
|
164
|
-
} | undefined;
|
|
165
|
-
} | undefined;
|
|
166
|
-
}, {
|
|
167
|
-
name?: string | undefined;
|
|
168
|
-
repoPath?: string | undefined;
|
|
169
|
-
remoteUrl?: string | undefined;
|
|
170
|
-
description?: string | undefined;
|
|
171
|
-
branches?: string[] | undefined;
|
|
172
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
173
|
-
autoCommit?: boolean | undefined;
|
|
174
|
-
commitAuthor?: {
|
|
81
|
+
static schema(): z.ZodType<{
|
|
82
|
+
name: string | undefined;
|
|
83
|
+
repoPath: string | undefined;
|
|
84
|
+
remoteUrl: string | undefined;
|
|
85
|
+
description: string | undefined;
|
|
86
|
+
branches: string[] | undefined;
|
|
87
|
+
accessMode: "readonly" | "readwrite" | undefined;
|
|
88
|
+
autoCommit: boolean | undefined;
|
|
89
|
+
commitAuthor: {
|
|
175
90
|
name: string;
|
|
176
91
|
email: string;
|
|
177
92
|
} | undefined;
|
|
178
|
-
depth
|
|
179
|
-
autoCleanup
|
|
180
|
-
cloneOptions
|
|
181
|
-
auth
|
|
182
|
-
username
|
|
183
|
-
password
|
|
93
|
+
depth: number | undefined;
|
|
94
|
+
autoCleanup: boolean | undefined;
|
|
95
|
+
cloneOptions: {
|
|
96
|
+
auth: {
|
|
97
|
+
username: string | undefined;
|
|
98
|
+
password: string | undefined;
|
|
184
99
|
} | undefined;
|
|
185
100
|
} | undefined;
|
|
186
|
-
}
|
|
187
|
-
name
|
|
188
|
-
repoPath
|
|
189
|
-
remoteUrl
|
|
190
|
-
description
|
|
191
|
-
branches
|
|
192
|
-
accessMode
|
|
193
|
-
autoCommit
|
|
194
|
-
commitAuthor
|
|
101
|
+
}, unknown, z.core.$ZodTypeInternals<{
|
|
102
|
+
name: string | undefined;
|
|
103
|
+
repoPath: string | undefined;
|
|
104
|
+
remoteUrl: string | undefined;
|
|
105
|
+
description: string | undefined;
|
|
106
|
+
branches: string[] | undefined;
|
|
107
|
+
accessMode: "readonly" | "readwrite" | undefined;
|
|
108
|
+
autoCommit: boolean | undefined;
|
|
109
|
+
commitAuthor: {
|
|
195
110
|
name: string;
|
|
196
111
|
email: string;
|
|
197
112
|
} | undefined;
|
|
198
|
-
depth
|
|
199
|
-
autoCleanup
|
|
200
|
-
cloneOptions
|
|
201
|
-
auth
|
|
202
|
-
username
|
|
203
|
-
password
|
|
113
|
+
depth: number | undefined;
|
|
114
|
+
autoCleanup: boolean | undefined;
|
|
115
|
+
cloneOptions: {
|
|
116
|
+
auth: {
|
|
117
|
+
username: string | undefined;
|
|
118
|
+
password: string | undefined;
|
|
204
119
|
} | undefined;
|
|
205
120
|
} | undefined;
|
|
206
|
-
},
|
|
121
|
+
}, unknown>>;
|
|
122
|
+
static manifest(): ProviderManifest;
|
|
207
123
|
static load({
|
|
208
124
|
basePath,
|
|
209
125
|
config
|
|
@@ -221,6 +137,9 @@ declare class AFSGit extends AFSBaseProvider {
|
|
|
221
137
|
private repoPath;
|
|
222
138
|
constructor(options: AFSGitOptions & {
|
|
223
139
|
cwd?: string;
|
|
140
|
+
localPath?: string;
|
|
141
|
+
branch?: string;
|
|
142
|
+
uri?: string;
|
|
224
143
|
});
|
|
225
144
|
/**
|
|
226
145
|
* Wait for async initialization to complete
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { __require } from "./_virtual/rolldown_runtime.mjs";
|
|
1
2
|
import { __decorate } from "./_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs";
|
|
2
3
|
import { execFile } from "node:child_process";
|
|
3
4
|
import { createHash } from "node:crypto";
|
|
@@ -37,6 +38,20 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
37
38
|
static schema() {
|
|
38
39
|
return afsGitOptionsSchema;
|
|
39
40
|
}
|
|
41
|
+
static manifest() {
|
|
42
|
+
return {
|
|
43
|
+
name: "git",
|
|
44
|
+
description: "Mount a local Git repository",
|
|
45
|
+
uriTemplate: "git://{localPath+}",
|
|
46
|
+
category: "version-control",
|
|
47
|
+
schema: z.object({
|
|
48
|
+
localPath: z.string(),
|
|
49
|
+
branch: z.string().optional(),
|
|
50
|
+
remoteUrl: z.string().optional()
|
|
51
|
+
}),
|
|
52
|
+
tags: ["git", "version-control"]
|
|
53
|
+
};
|
|
54
|
+
}
|
|
40
55
|
static async load({ basePath, config } = {}) {
|
|
41
56
|
const instance = new AFSGit({
|
|
42
57
|
...await AFSGit.schema().parseAsync(config),
|
|
@@ -59,6 +74,8 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
59
74
|
constructor(options) {
|
|
60
75
|
super();
|
|
61
76
|
this.options = options;
|
|
77
|
+
if (options.localPath && !options.repoPath) options.repoPath = options.localPath;
|
|
78
|
+
if (options.branch && !options.branches) options.branches = [options.branch];
|
|
62
79
|
zodParse(afsGitOptionsSchema, options);
|
|
63
80
|
let repoPath;
|
|
64
81
|
let repoName;
|
|
@@ -71,6 +88,15 @@ var AFSGit = class AFSGit extends AFSBaseProvider {
|
|
|
71
88
|
const repoHash = createHash("md5").update(options.remoteUrl).digest("hex").substring(0, 8);
|
|
72
89
|
repoPath = join(tmpdir(), `afs-git-remote-${repoHash}`);
|
|
73
90
|
} else throw new Error("Either repoPath or remoteUrl must be provided");
|
|
91
|
+
if (options.repoPath && !options.remoteUrl) {
|
|
92
|
+
const { existsSync, mkdirSync } = __require("node:fs");
|
|
93
|
+
const { execSync } = __require("node:child_process");
|
|
94
|
+
if (!existsSync(repoPath)) mkdirSync(repoPath, { recursive: true });
|
|
95
|
+
if (!existsSync(join(repoPath, ".git"))) execSync("git init -b main", {
|
|
96
|
+
cwd: repoPath,
|
|
97
|
+
stdio: "ignore"
|
|
98
|
+
});
|
|
99
|
+
}
|
|
74
100
|
this.repoPath = repoPath;
|
|
75
101
|
this.name = options.name || repoName;
|
|
76
102
|
this.description = options.description;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["afsPath","mimeType","isBinary","content","meta"],"sources":["../src/index.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readdir, readFile, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { basename, dirname, isAbsolute, join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n type AFSAccessMode,\n type AFSDeleteOptions,\n type AFSEntry,\n type AFSEntryMetadata,\n type AFSExecResult,\n type AFSExplainOptions,\n type AFSExplainResult,\n type AFSListResult,\n type AFSModuleClass,\n type AFSModuleLoadParams,\n AFSNotFoundError,\n type AFSRenameOptions,\n type AFSSearchOptions,\n type AFSStatResult,\n type AFSWriteEntryPayload,\n type CapabilitiesManifest,\n} from \"@aigne/afs\";\nimport {\n Actions,\n AFSBaseProvider,\n Delete,\n Explain,\n List,\n Meta,\n Read,\n Rename,\n type RouteContext,\n Search,\n Stat,\n Write,\n} from \"@aigne/afs/provider\";\nimport { camelize, optionalize, zodParse } from \"@aigne/afs/utils/zod\";\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport { z } from \"zod\";\n\nconst LIST_MAX_LIMIT = 1000;\n\nconst execFileAsync = promisify(execFile);\n\nexport interface AFSGitOptions {\n name?: string;\n /**\n * Local path to git repository.\n * If remoteUrl is provided and repoPath doesn't exist, will clone to this path.\n * If remoteUrl is provided and repoPath is not specified, clones to temp directory.\n */\n repoPath?: string;\n /**\n * Remote repository URL (https or git protocol).\n * If provided, will clone the repository if repoPath doesn't exist.\n * Examples:\n * - https://github.com/user/repo.git\n * - git@github.com:user/repo.git\n */\n remoteUrl?: string;\n description?: string;\n /**\n * List of branches to expose/access.\n * Also used for clone optimization when cloning from remoteUrl:\n * - Single branch (e.g., ['main']): Uses --single-branch for faster clone\n * - Multiple branches: Clones all branches, filters access to specified ones\n * - Not specified: All branches are accessible\n */\n branches?: string[];\n /**\n * Access mode for this module.\n * - \"readonly\": Only read operations are allowed, uses git commands (no worktree)\n * - \"readwrite\": All operations are allowed, creates worktrees as needed\n * @default \"readonly\"\n */\n accessMode?: AFSAccessMode;\n /**\n * Automatically commit changes after write operations\n * @default false\n */\n autoCommit?: boolean;\n /**\n * Author information for commits when autoCommit is enabled\n */\n commitAuthor?: {\n name: string;\n email: string;\n };\n /**\n * Clone depth for shallow clone (only used when cloning from remoteUrl)\n * @default 1\n */\n depth?: number;\n /**\n * Automatically clean up cloned repository on cleanup()\n * Only applies when repository was auto-cloned to temp directory\n * @default true\n */\n autoCleanup?: boolean;\n /**\n * Git clone options (only used when cloning from remoteUrl)\n */\n cloneOptions?: {\n /**\n * Authentication credentials for private repositories\n */\n auth?: {\n username?: string;\n password?: string;\n };\n };\n}\n\nconst afsGitOptionsSchema = camelize(\n z\n .object({\n name: optionalize(z.string()),\n repoPath: optionalize(z.string().describe(\"The path to the git repository\")),\n remoteUrl: optionalize(z.string().describe(\"Remote repository URL (https or git protocol)\")),\n description: optionalize(z.string().describe(\"A description of the repository\")),\n branches: optionalize(z.array(z.string()).describe(\"List of branches to expose\")),\n accessMode: optionalize(\n z.enum([\"readonly\", \"readwrite\"]).describe(\"Access mode for this module\"),\n ),\n autoCommit: optionalize(\n z.boolean().describe(\"Automatically commit changes after write operations\"),\n ),\n commitAuthor: optionalize(\n z.object({\n name: z.string(),\n email: z.string(),\n }),\n ),\n depth: optionalize(z.number().describe(\"Clone depth for shallow clone\")),\n autoCleanup: optionalize(\n z.boolean().describe(\"Automatically clean up cloned repository on cleanup()\"),\n ),\n cloneOptions: optionalize(\n z.object({\n auth: optionalize(\n z.object({\n username: optionalize(z.string()),\n password: optionalize(z.string()),\n }),\n ),\n }),\n ),\n })\n .refine((data) => data.repoPath || data.remoteUrl, {\n message: \"Either repoPath or remoteUrl must be provided\",\n }),\n);\n\nexport class AFSGit extends AFSBaseProvider {\n static schema() {\n return afsGitOptionsSchema;\n }\n\n static async load({ basePath, config }: AFSModuleLoadParams = {}) {\n const valid = await AFSGit.schema().parseAsync(config);\n const instance = new AFSGit({ ...valid, cwd: basePath });\n await instance.ready();\n return instance;\n }\n\n readonly name: string;\n readonly description?: string;\n readonly accessMode: AFSAccessMode;\n\n private initPromise: Promise<void>;\n private git: SimpleGit;\n private tempBase: string;\n private worktrees: Map<string, string> = new Map();\n private repoHash: string;\n private isAutoCloned = false;\n private clonedPath?: string;\n private repoPath: string;\n\n constructor(public options: AFSGitOptions & { cwd?: string }) {\n super();\n zodParse(afsGitOptionsSchema, options);\n\n // Synchronously determine repoPath to initialize name\n let repoPath: string;\n let repoName: string;\n\n if (options.repoPath) {\n // Use provided repoPath\n repoPath = isAbsolute(options.repoPath)\n ? options.repoPath\n : join(options.cwd || process.cwd(), options.repoPath);\n repoName = basename(repoPath);\n } else if (options.remoteUrl) {\n // Extract repo name from URL for temporary name\n const urlParts = options.remoteUrl.split(\"/\");\n const lastPart = urlParts[urlParts.length - 1];\n repoName = lastPart?.replace(/\\.git$/, \"\") || \"git\";\n\n // Will be updated during async init, use temp path for now\n const repoHash = createHash(\"md5\").update(options.remoteUrl).digest(\"hex\").substring(0, 8);\n repoPath = join(tmpdir(), `afs-git-remote-${repoHash}`);\n } else {\n // This should never happen due to schema validation\n throw new Error(\"Either repoPath or remoteUrl must be provided\");\n }\n\n // Initialize basic properties immediately\n this.repoPath = repoPath;\n this.name = options.name || repoName;\n this.description = options.description;\n this.accessMode = options.accessMode ?? \"readonly\";\n\n // Calculate hash for temp directories\n this.repoHash = createHash(\"md5\").update(repoPath).digest(\"hex\").substring(0, 8);\n this.tempBase = join(tmpdir(), `afs-git-${this.repoHash}`);\n\n // Note: git and other properties will be initialized in initialize() after cloning\n // We need to delay simpleGit() initialization until the directory exists\n this.git = null as any; // Will be set in initialize()\n\n // Start async initialization (cloning if needed)\n this.initPromise = this.initialize();\n }\n\n /**\n * Wait for async initialization to complete\n */\n async ready(): Promise<void> {\n await this.initPromise;\n }\n\n /**\n * Async initialization logic (runs in constructor)\n * Handles cloning remote repositories if needed\n */\n private async initialize(): Promise<void> {\n const options = this.options;\n\n // If remoteUrl is provided, handle cloning\n if (options.remoteUrl) {\n const targetPath = options.repoPath\n ? isAbsolute(options.repoPath)\n ? options.repoPath\n : join(options.cwd || process.cwd(), options.repoPath)\n : this.repoPath; // Use temp path set in constructor\n\n // Mark as auto-cloned if we're using temp directory\n if (!options.repoPath) {\n this.isAutoCloned = true;\n }\n\n // Check if targetPath exists and is a valid git repository\n const exists = await stat(targetPath)\n .then(() => true)\n .catch(() => false);\n\n let needsClone = !exists;\n\n // If directory exists but is not a valid git repo, clean it up and re-clone\n if (exists) {\n const tempGit = simpleGit(targetPath);\n const isValidRepo = await tempGit.checkIsRepo().catch(() => false);\n if (!isValidRepo) {\n // Remove invalid directory and re-clone\n await rm(targetPath, { recursive: true, force: true });\n needsClone = true;\n }\n }\n\n if (needsClone) {\n // Determine if single-branch optimization should be used\n const singleBranch = options.branches?.length === 1 ? options.branches[0] : undefined;\n\n await AFSGit.cloneRepository(options.remoteUrl, targetPath, {\n depth: options.depth ?? 1,\n branch: singleBranch,\n auth: options.cloneOptions?.auth,\n });\n }\n\n // Update properties if targetPath differs from constructor initialization\n if (targetPath !== this.repoPath) {\n this.repoPath = targetPath;\n this.repoHash = createHash(\"md5\").update(targetPath).digest(\"hex\").substring(0, 8);\n this.tempBase = join(tmpdir(), `afs-git-${this.repoHash}`);\n }\n\n this.clonedPath = this.isAutoCloned ? targetPath : undefined;\n }\n\n // Now that the directory exists (either it was there or we cloned it), initialize git\n this.git = simpleGit(this.repoPath);\n\n // Validate that the directory is actually a git repository\n const isRepo = await this.git.checkIsRepo();\n if (!isRepo) {\n throw new Error(`Not a git repository: ${this.repoPath}`);\n }\n }\n\n /**\n * Clone a remote repository to local path\n */\n private static async cloneRepository(\n remoteUrl: string,\n targetPath: string,\n options: {\n depth?: number;\n branch?: string;\n auth?: { username?: string; password?: string };\n } = {},\n ): Promise<void> {\n const git = simpleGit();\n\n // Build clone options\n const cloneArgs: string[] = [];\n\n if (options.depth) {\n cloneArgs.push(\"--depth\", options.depth.toString());\n }\n\n if (options.branch) {\n cloneArgs.push(\"--branch\", options.branch, \"--single-branch\");\n }\n\n // Handle authentication in URL if provided\n let cloneUrl = remoteUrl;\n if (options.auth?.username && options.auth?.password) {\n // Insert credentials into HTTPS URL\n if (remoteUrl.startsWith(\"https://\")) {\n const url = new URL(remoteUrl);\n url.username = encodeURIComponent(options.auth.username);\n url.password = encodeURIComponent(options.auth.password);\n cloneUrl = url.toString();\n }\n }\n\n await git.clone(cloneUrl, targetPath, cloneArgs);\n }\n\n // ========== Route Handlers ==========\n\n /**\n * List root (branches)\n * Note: list() returns only children (branches), never the path itself (per new semantics)\n */\n @List(\"/\", { handleDepth: true })\n async listRootHandler(ctx: RouteContext): Promise<AFSListResult & { noExpand?: string[] }> {\n await this.ready();\n\n const options = ctx.options as { limit?: number; maxDepth?: number };\n const maxDepth = options?.maxDepth ?? 1;\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n\n // maxDepth: 0 means return no children\n if (maxDepth === 0) {\n return { data: [] };\n }\n\n const branches = await this.getBranches();\n const entries: AFSEntry[] = [];\n\n for (const name of branches) {\n if (entries.length >= limit) break;\n\n const encodedPath = this.buildBranchPath(name);\n\n // Get children count for this branch\n const branchChildrenCount = await this.getChildrenCount(name, \"\");\n\n entries.push(\n this.buildEntry(encodedPath, {\n meta: { kind: \"git:branch\", childrenCount: branchChildrenCount },\n }),\n );\n\n // If maxDepth > 1, also list contents of each branch\n if (maxDepth > 1) {\n const branchResult = await this.listWithGitLsTree(name, \"\", {\n maxDepth: maxDepth - 1,\n limit: limit - entries.length,\n });\n entries.push(...branchResult.data);\n }\n }\n\n return { data: entries };\n }\n\n /**\n * List branch root (matches /main, /develop, etc.)\n */\n @List(\"/:branch\", { handleDepth: true })\n async listBranchRootHandler(\n ctx: RouteContext<{ branch: string }>,\n ): Promise<AFSListResult & { noExpand?: string[] }> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n\n return this.listWithGitLsTree(branch, \"\", ctx.options as { maxDepth?: number; limit?: number });\n }\n\n /**\n * List files in branch with subpath (matches /main/src, /main/src/foo, etc.)\n */\n @List(\"/:branch/:path+\", { handleDepth: true })\n async listBranchHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<AFSListResult & { noExpand?: string[] }> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const filePath = ctx.params.path;\n\n return this.listWithGitLsTree(\n branch,\n filePath,\n ctx.options as { maxDepth?: number; limit?: number },\n );\n }\n\n // ========== Meta Handlers ==========\n // These handlers provide metadata access for all paths via .meta suffix\n\n /**\n * Read root metadata (introspection only, read-only)\n */\n @Meta(\"/\")\n async readRootMetaHandler(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branches = await this.getBranches();\n return this.buildEntry(\"/.meta\", {\n meta: { childrenCount: branches.length, type: \"root\" },\n });\n }\n\n /**\n * Read branch root metadata (introspection only, read-only)\n */\n @Meta(\"/:branch\")\n async readBranchMetaHandler(\n ctx: RouteContext<{ branch: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const childrenCount = await this.getChildrenCount(branch, \"\");\n const branchPath = `/${this.encodeBranchName(branch)}`;\n const metaPath = `${branchPath}/.meta`;\n const lastCommit = await this.getLastCommit(branch);\n\n return this.buildEntry(metaPath, {\n meta: { childrenCount, type: \"branch\", lastCommit },\n });\n }\n\n /**\n * Read file or directory metadata in branch (introspection only, read-only)\n */\n @Meta(\"/:branch/:path+\")\n async readPathMetaHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const filePath = ctx.params.path;\n\n // Check if the path exists\n const objectType = await this.git\n .raw([\"cat-file\", \"-t\", `${branch}:${filePath}`])\n .then((t) => t.trim())\n .catch(() => null);\n\n if (objectType === null) {\n throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));\n }\n\n const isDir = objectType === \"tree\";\n const metaPath = `/${this.encodeBranchName(branch)}/${filePath}/.meta`;\n\n let childrenCount: number | undefined;\n if (isDir) {\n childrenCount = await this.getChildrenCount(branch, filePath);\n }\n\n return this.buildEntry(metaPath, {\n meta: {\n childrenCount,\n type: isDir ? \"directory\" : \"file\",\n gitObjectType: objectType,\n },\n });\n }\n\n // ========== Regular Read Handlers ==========\n\n /**\n * Read root\n */\n @Read(\"/\")\n async readRootHandler(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branches = await this.getBranches();\n return this.buildEntry(\"/\", {\n meta: { childrenCount: branches.length },\n });\n }\n\n /**\n * Read branch root\n */\n @Read(\"/:branch\")\n async readBranchRootHandler(\n ctx: RouteContext<{ branch: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const branchPath = this.buildBranchPath(branch);\n const childrenCount = await this.getChildrenCount(branch, \"\");\n const lastCommit = await this.getLastCommit(branch);\n return this.buildEntry(branchPath, {\n meta: { childrenCount, lastCommit },\n });\n }\n\n /**\n * Read file or directory in branch\n */\n @Read(\"/:branch/:path+\")\n async readBranchHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const filePath = ctx.params.path;\n\n // Check if there's an active worktree for this branch - read from there first\n // This handles files that were written but may be in a different state than git index\n const worktreePath = this.worktrees.get(branch);\n if (worktreePath) {\n try {\n const fullPath = join(worktreePath, filePath);\n const stats = await stat(fullPath);\n\n if (stats.isDirectory()) {\n // It's a directory - count children\n const files = await readdir(fullPath);\n const afsPath = this.buildBranchPath(branch, filePath);\n return this.buildEntry(afsPath, {\n meta: { childrenCount: files.length },\n });\n }\n\n // It's a file - read content\n const mimeType = this.getMimeType(filePath);\n const isBinary = this.isBinaryFile(filePath);\n\n let content: string;\n const meta: AFSEntryMetadata = {\n size: stats.size,\n mimeType,\n };\n\n if (isBinary) {\n const buffer = await readFile(fullPath);\n content = buffer.toString(\"base64\");\n meta.contentType = \"base64\";\n } else {\n content = await readFile(fullPath, \"utf8\");\n }\n\n const afsPath = this.buildBranchPath(branch, filePath);\n return this.buildEntry(afsPath, {\n content,\n meta,\n createdAt: stats.birthtime,\n updatedAt: stats.mtime,\n });\n } catch {\n // File doesn't exist in worktree, fall through to git\n }\n }\n\n // Read from git repository\n // Check if path is a blob (file) or tree (directory)\n const objectType = await this.git\n .raw([\"cat-file\", \"-t\", `${branch}:${filePath}`])\n .then((t) => t.trim())\n .catch(() => null);\n\n if (objectType === null) {\n // Path doesn't exist in git\n throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));\n }\n\n if (objectType === \"tree\") {\n // It's a directory\n const afsPath = this.buildBranchPath(branch, filePath);\n const childrenCount = await this.getChildrenCount(branch, filePath);\n return this.buildEntry(afsPath, {\n meta: { childrenCount },\n });\n }\n\n // It's a file, get content\n const size = await this.git\n .raw([\"cat-file\", \"-s\", `${branch}:${filePath}`])\n .then((s) => Number.parseInt(s.trim(), 10));\n\n // Determine mimeType based on file extension\n const mimeType = this.getMimeType(filePath);\n const isBinary = this.isBinaryFile(filePath);\n\n let content: string;\n const meta: AFSEntryMetadata = {\n size,\n mimeType,\n };\n\n if (isBinary) {\n // For binary files, use execFileAsync to get raw buffer\n const { stdout } = await execFileAsync(\"git\", [\"cat-file\", \"-p\", `${branch}:${filePath}`], {\n cwd: this.options.repoPath,\n encoding: \"buffer\",\n maxBuffer: 10 * 1024 * 1024, // 10MB max\n });\n // Store only base64 string without data URL prefix\n content = (stdout as Buffer).toString(\"base64\");\n // Mark content as base64 in metadata\n meta.contentType = \"base64\";\n } else {\n // For text files, use git.show\n content = await this.git.show([`${branch}:${filePath}`]);\n }\n\n const afsPath = this.buildBranchPath(branch, filePath);\n return this.buildEntry(afsPath, {\n content,\n meta,\n });\n }\n\n /**\n * Write to root is not allowed\n */\n @Write(\"/\")\n async writeRootHandler(): Promise<never> {\n throw new Error(\"Cannot write to root\");\n }\n\n /**\n * Write to branch root is not allowed\n */\n @Write(\"/:branch\")\n async writeBranchRootHandler(): Promise<never> {\n throw new Error(\"Cannot write to branch root\");\n }\n\n /**\n * Write file in branch\n */\n @Write(\"/:branch/:path+\")\n async writeHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n payload: AFSWriteEntryPayload,\n ): Promise<{ data: AFSEntry }> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n const filePath = ctx.params.path;\n const options = ctx.options as { append?: boolean };\n const append = options?.append ?? false;\n\n // Create worktree for write operations\n const worktreePath = await this.ensureWorktree(branch);\n const fullPath = join(worktreePath, filePath);\n\n // Ensure parent directory exists\n const parentDir = dirname(fullPath);\n await mkdir(parentDir, { recursive: true });\n\n // Write content\n if (payload.content !== undefined) {\n let contentToWrite: string;\n if (typeof payload.content === \"string\") {\n contentToWrite = payload.content;\n } else {\n contentToWrite = JSON.stringify(payload.content, null, 2);\n }\n await writeFile(fullPath, contentToWrite, { encoding: \"utf8\", flag: append ? \"a\" : \"w\" });\n }\n\n // Auto commit if enabled\n if (this.options.autoCommit) {\n const gitInstance = simpleGit(worktreePath);\n await gitInstance.add(filePath);\n\n if (this.options.commitAuthor) {\n await gitInstance.addConfig(\n \"user.name\",\n this.options.commitAuthor.name,\n undefined,\n \"local\",\n );\n await gitInstance.addConfig(\n \"user.email\",\n this.options.commitAuthor.email,\n undefined,\n \"local\",\n );\n }\n\n await gitInstance.commit(`Update ${filePath}`);\n }\n\n // Get file stats\n const stats = await stat(fullPath);\n\n const afsPath = this.buildBranchPath(branch, filePath);\n const writtenEntry: AFSEntry = {\n id: afsPath,\n path: afsPath,\n content: payload.content,\n summary: payload.summary,\n createdAt: stats.birthtime,\n updatedAt: stats.mtime,\n meta: {\n ...payload.meta,\n size: stats.size,\n } as AFSEntryMetadata,\n userId: payload.userId,\n sessionId: payload.sessionId,\n linkTo: payload.linkTo,\n };\n\n return { data: writtenEntry };\n }\n\n /**\n * Delete root is not allowed\n */\n @Delete(\"/\")\n async deleteRootHandler(): Promise<never> {\n throw new Error(\"Cannot delete root\");\n }\n\n /**\n * Delete branch root is not allowed\n */\n @Delete(\"/:branch\")\n async deleteBranchRootHandler(ctx: RouteContext<{ branch: string }>): Promise<never> {\n await this.ready();\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n throw new Error(\"Cannot delete branch root\");\n }\n\n /**\n * Delete file in branch\n */\n @Delete(\"/:branch/:path+\")\n async deleteHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<{ message: string }> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n const filePath = ctx.params.path;\n const options = ctx.options as AFSDeleteOptions | undefined;\n const recursive = options?.recursive ?? false;\n\n // Create worktree for delete operations\n const worktreePath = await this.ensureWorktree(branch);\n const fullPath = join(worktreePath, filePath);\n\n let stats: Awaited<ReturnType<typeof stat>>;\n try {\n stats = await stat(fullPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));\n }\n throw error;\n }\n\n if (stats.isDirectory() && !recursive) {\n throw new Error(\n `Cannot delete directory '/${ctx.params.branch}/${filePath}' without recursive option. Set recursive: true to delete directories.`,\n );\n }\n\n await rm(fullPath, { recursive, force: true });\n\n // Auto commit if enabled\n if (this.options.autoCommit) {\n const gitInstance = simpleGit(worktreePath);\n await gitInstance.add(filePath);\n\n if (this.options.commitAuthor) {\n await gitInstance.addConfig(\n \"user.name\",\n this.options.commitAuthor.name,\n undefined,\n \"local\",\n );\n await gitInstance.addConfig(\n \"user.email\",\n this.options.commitAuthor.email,\n undefined,\n \"local\",\n );\n }\n\n await gitInstance.commit(`Delete ${filePath}`);\n }\n\n return { message: `Successfully deleted: /${ctx.params.branch}/${filePath}` };\n }\n\n /**\n * Rename file in branch\n */\n @Rename(\"/:branch/:path+\")\n async renameHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n newPath: string,\n ): Promise<{ message: string }> {\n await this.ready();\n\n const oldBranch = this.decodeBranchName(ctx.params.branch);\n const oldFilePath = ctx.params.path;\n\n // Parse new path\n const { branch: newBranch, filePath: newFilePath } = this.parsePath(newPath);\n const options = ctx.options as AFSRenameOptions | undefined;\n const overwrite = options?.overwrite ?? false;\n\n if (!newBranch || !newFilePath) {\n throw new Error(\"Cannot rename to root or branch root\");\n }\n\n if (oldBranch !== newBranch) {\n throw new Error(\"Cannot rename across branches\");\n }\n\n // Create worktree for rename operations\n const worktreePath = await this.ensureWorktree(oldBranch);\n const oldFullPath = join(worktreePath, oldFilePath);\n const newFullPath = join(worktreePath, newFilePath);\n\n // Check if source exists\n try {\n await stat(oldFullPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new AFSNotFoundError(this.buildBranchPath(oldBranch, oldFilePath));\n }\n throw error;\n }\n\n // Check if destination exists\n try {\n await stat(newFullPath);\n if (!overwrite) {\n throw new Error(\n `Destination '${newPath}' already exists. Set overwrite: true to replace it.`,\n );\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n\n // Ensure parent directory exists\n const newParentDir = dirname(newFullPath);\n await mkdir(newParentDir, { recursive: true });\n\n // Perform rename\n await rename(oldFullPath, newFullPath);\n\n // Auto commit if enabled\n if (this.options.autoCommit) {\n const gitInstance = simpleGit(worktreePath);\n await gitInstance.add([oldFilePath, newFilePath]);\n\n if (this.options.commitAuthor) {\n await gitInstance.addConfig(\n \"user.name\",\n this.options.commitAuthor.name,\n undefined,\n \"local\",\n );\n await gitInstance.addConfig(\n \"user.email\",\n this.options.commitAuthor.email,\n undefined,\n \"local\",\n );\n }\n\n await gitInstance.commit(`Rename ${oldFilePath} to ${newFilePath}`);\n }\n\n return {\n message: `Successfully renamed '/${ctx.params.branch}/${oldFilePath}' to '${newPath}'`,\n };\n }\n\n /**\n * Search files in branch root\n */\n @Search(\"/:branch\")\n async searchBranchRootHandler(\n ctx: RouteContext<{ branch: string }>,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<{ data: AFSEntry[]; message?: string }> {\n return this.searchInBranch(ctx.params.branch, \"\", query, options);\n }\n\n /**\n * Search files in branch path\n */\n @Search(\"/:branch/:path+\")\n async searchHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<{ data: AFSEntry[]; message?: string }> {\n return this.searchInBranch(ctx.params.branch, ctx.params.path, query, options);\n }\n\n /**\n * Internal search implementation\n */\n private async searchInBranch(\n encodedBranch: string,\n filePath: string,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<{ data: AFSEntry[]; message?: string }> {\n await this.ready();\n\n const branch = this.decodeBranchName(encodedBranch);\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n\n try {\n // Use git grep for searching (no worktree needed)\n const args = [\"grep\", \"-n\", \"-I\"]; // -n for line numbers, -I to skip binary files\n\n if (options?.caseSensitive === false) {\n args.push(\"-i\");\n }\n\n args.push(query, branch);\n\n // Add path filter if specified\n if (filePath) {\n args.push(\"--\", filePath);\n }\n\n const output = await this.git.raw(args);\n const lines = output.split(\"\\n\").filter((line) => line.trim());\n\n const entries: AFSEntry[] = [];\n const processedFiles = new Set<string>();\n\n for (const line of lines) {\n // Format when searching in branch: branch:path:linenum:content\n // Try the format with branch prefix first\n let matchPath: string;\n let lineNum: string;\n let content: string;\n\n const matchWithBranch = line.match(/^[^:]+:([^:]+):(\\d+):(.+)$/);\n if (matchWithBranch) {\n matchPath = matchWithBranch[1]!;\n lineNum = matchWithBranch[2]!;\n content = matchWithBranch[3]!;\n } else {\n // Try format without branch: path:linenum:content\n const matchNoBranch = line.match(/^([^:]+):(\\d+):(.+)$/);\n if (!matchNoBranch) continue;\n matchPath = matchNoBranch[1]!;\n lineNum = matchNoBranch[2]!;\n content = matchNoBranch[3]!;\n }\n\n const afsPath = this.buildBranchPath(branch, matchPath);\n\n if (processedFiles.has(afsPath)) continue;\n processedFiles.add(afsPath);\n\n const entry = this.buildEntry(afsPath);\n entry.summary = `Line ${lineNum}: ${content}`;\n entries.push(entry);\n\n if (entries.length >= limit) {\n break;\n }\n }\n\n return {\n data: entries,\n message: entries.length >= limit ? `Results truncated to limit ${limit}` : undefined,\n };\n } catch (error) {\n // git grep returns exit code 1 if no matches found\n if ((error as Error).message.includes(\"did not match any file(s)\")) {\n return { data: [] };\n }\n return { data: [], message: (error as Error).message };\n }\n }\n\n /**\n * Stat root\n */\n @Stat(\"/\")\n async statRootHandler(_ctx: RouteContext): Promise<AFSStatResult> {\n const entry = await this.readRootHandler(_ctx);\n if (!entry) {\n return { data: undefined };\n }\n // Return entry without content\n const { content: _content, ...rest } = entry;\n return { data: rest };\n }\n\n /**\n * Stat branch root\n */\n @Stat(\"/:branch\")\n async statBranchRootHandler(ctx: RouteContext<{ branch: string }>): Promise<AFSStatResult> {\n const entry = await this.readBranchRootHandler(ctx);\n if (!entry) {\n return { data: undefined };\n }\n // Return entry without content\n const { content: _content, ...rest } = entry;\n return { data: rest };\n }\n\n /**\n * Stat file or directory in branch\n */\n @Stat(\"/:branch/:path+\")\n async statHandler(ctx: RouteContext<{ branch: string; path: string }>): Promise<AFSStatResult> {\n const entry = await this.readBranchHandler(ctx);\n if (!entry) {\n return { data: undefined };\n }\n // Return entry without content\n const { content: _content, ...rest } = entry;\n return { data: rest };\n }\n\n // ========== Explain Handlers ==========\n\n /**\n * Explain root → repo info, branch list, default branch\n */\n @Explain(\"/\")\n async explainRootHandler(_ctx: RouteContext): Promise<AFSExplainResult> {\n await this.ready();\n\n const format = (_ctx.options as AFSExplainOptions)?.format || \"markdown\";\n const branches = await this.getBranches();\n const currentBranch = await this.git.revparse([\"--abbrev-ref\", \"HEAD\"]).then((b) => b.trim());\n\n let remoteUrl: string | undefined;\n try {\n remoteUrl = await this.git.remote([\"get-url\", \"origin\"]).then((u) => u?.trim());\n } catch {\n // No remote configured\n }\n\n const lines: string[] = [];\n lines.push(\"# Git Repository\");\n lines.push(\"\");\n lines.push(`**Provider:** ${this.name}`);\n if (this.description) {\n lines.push(`**Description:** ${this.description}`);\n }\n lines.push(`**Default Branch:** ${currentBranch}`);\n if (remoteUrl) {\n lines.push(`**Remote:** ${remoteUrl}`);\n }\n lines.push(`**Branches:** ${branches.length}`);\n lines.push(\"\");\n lines.push(\"## Branches\");\n lines.push(\"\");\n for (const branch of branches) {\n lines.push(`- ${branch}`);\n }\n\n return { content: lines.join(\"\\n\"), format };\n }\n\n /**\n * Explain branch → branch name, HEAD commit, file count\n */\n @Explain(\"/:branch\")\n async explainBranchHandler(ctx: RouteContext<{ branch: string }>): Promise<AFSExplainResult> {\n await this.ready();\n\n const format = (ctx.options as AFSExplainOptions)?.format || \"markdown\";\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n\n const lastCommit = await this.getLastCommit(branch);\n const fileCount = await this.getTreeFileCount(branch, \"\");\n\n const lines: string[] = [];\n lines.push(`# Branch: ${branch}`);\n lines.push(\"\");\n lines.push(`**HEAD Commit:** ${lastCommit.shortHash} - ${lastCommit.message}`);\n lines.push(`**Author:** ${lastCommit.author}`);\n lines.push(`**Date:** ${lastCommit.date}`);\n lines.push(`**Files:** ${fileCount} entries in tree`);\n\n return { content: lines.join(\"\\n\"), format };\n }\n\n /**\n * Explain file or directory → path, size, last modified commit\n */\n @Explain(\"/:branch/:path+\")\n async explainPathHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<AFSExplainResult> {\n await this.ready();\n\n const format = (ctx.options as AFSExplainOptions)?.format || \"markdown\";\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const filePath = ctx.params.path;\n\n const objectType = await this.git\n .raw([\"cat-file\", \"-t\", `${branch}:${filePath}`])\n .then((t) => t.trim())\n .catch(() => null);\n\n if (objectType === null) {\n throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));\n }\n\n const isDir = objectType === \"tree\";\n const lines: string[] = [];\n\n lines.push(`# ${basename(filePath)}`);\n lines.push(\"\");\n lines.push(`**Path:** ${filePath}`);\n lines.push(`**Type:** ${isDir ? \"directory\" : \"file\"}`);\n\n if (!isDir) {\n const size = await this.git\n .raw([\"cat-file\", \"-s\", `${branch}:${filePath}`])\n .then((s) => Number.parseInt(s.trim(), 10));\n lines.push(`**Size:** ${size} bytes`);\n }\n\n // Get last commit that modified this path\n try {\n const logOutput = await this.git.raw([\n \"log\",\n \"-1\",\n \"--format=%H%n%h%n%an%n%aI%n%s\",\n branch,\n \"--\",\n filePath,\n ]);\n const logLines = logOutput.trim().split(\"\\n\");\n if (logLines.length >= 5) {\n lines.push(\"\");\n lines.push(\"## Last Modified\");\n lines.push(`**Commit:** ${logLines[1]} - ${logLines[4]}`);\n lines.push(`**Author:** ${logLines[2]}`);\n lines.push(`**Date:** ${logLines[3]}`);\n }\n } catch {\n // Ignore log errors\n }\n\n return { content: lines.join(\"\\n\"), format };\n }\n\n // ========== Capabilities ==========\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilitiesHandler(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n const operations = [\"list\", \"read\", \"stat\", \"explain\", \"search\"];\n if (this.accessMode === \"readwrite\") {\n operations.push(\"write\", \"delete\", \"rename\");\n }\n\n const actionCatalogs: CapabilitiesManifest[\"actions\"] = [];\n\n // diff is available in both modes conceptually, but exec() enforces readwrite\n // Include all actions in readwrite mode\n if (this.accessMode === \"readwrite\") {\n actionCatalogs.push({\n description: \"Git workflow actions\",\n catalog: [\n {\n name: \"diff\",\n description: \"Compare two branches or refs\",\n inputSchema: {\n type: \"object\",\n properties: {\n from: { type: \"string\", description: \"Source ref\" },\n to: { type: \"string\", description: \"Target ref\" },\n path: { type: \"string\", description: \"Optional path filter\" },\n },\n required: [\"from\", \"to\"],\n },\n },\n {\n name: \"create-branch\",\n description: \"Create a new branch\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"New branch name\" },\n from: { type: \"string\", description: \"Source ref (defaults to current HEAD)\" },\n },\n required: [\"name\"],\n },\n },\n {\n name: \"commit\",\n description: \"Commit staged changes\",\n inputSchema: {\n type: \"object\",\n properties: {\n message: { type: \"string\", description: \"Commit message\" },\n author: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n email: { type: \"string\" },\n },\n },\n },\n required: [\"message\"],\n },\n },\n {\n name: \"merge\",\n description: \"Merge a branch into the current branch\",\n inputSchema: {\n type: \"object\",\n properties: {\n branch: { type: \"string\", description: \"Branch to merge\" },\n message: { type: \"string\", description: \"Custom merge message\" },\n },\n required: [\"branch\"],\n },\n },\n ],\n discovery: {\n pathTemplate: \"/:branch/.actions\",\n note: \"Git workflow actions (readwrite mode only)\",\n },\n });\n }\n\n const manifest: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: this.name,\n description: this.description || \"Git repository provider\",\n tools: [],\n actions: actionCatalogs,\n operations: this.getOperationsDeclaration(),\n };\n\n return {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n content: manifest,\n meta: { kind: \"afs:capabilities\", operations },\n };\n }\n\n // ========== Git Actions ==========\n\n /**\n * List available actions for a branch\n */\n @Actions(\"/:branch\")\n async listBranchActions(ctx: RouteContext<{ branch: string }>): Promise<AFSListResult> {\n if (this.accessMode !== \"readwrite\") {\n return { data: [] };\n }\n\n const basePath = `/${ctx.params.branch}/.actions`;\n return {\n data: [\n {\n id: \"diff\",\n path: `${basePath}/diff`,\n summary: \"Compare two branches or refs\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n from: { type: \"string\", description: \"Source ref\" },\n to: { type: \"string\", description: \"Target ref\" },\n path: { type: \"string\", description: \"Optional path filter\" },\n },\n required: [\"from\", \"to\"],\n },\n },\n },\n {\n id: \"create-branch\",\n path: `${basePath}/create-branch`,\n summary: \"Create a new branch from this ref\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"New branch name\" },\n from: { type: \"string\", description: \"Source ref (defaults to current HEAD)\" },\n },\n required: [\"name\"],\n },\n },\n },\n {\n id: \"commit\",\n path: `${basePath}/commit`,\n summary: \"Commit staged changes\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n message: { type: \"string\", description: \"Commit message\" },\n author: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n email: { type: \"string\" },\n },\n },\n },\n required: [\"message\"],\n },\n },\n },\n {\n id: \"merge\",\n path: `${basePath}/merge`,\n summary: \"Merge another branch into this branch\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n branch: { type: \"string\", description: \"Branch to merge\" },\n message: { type: \"string\", description: \"Custom merge message\" },\n },\n required: [\"branch\"],\n },\n },\n },\n ],\n };\n }\n\n /**\n * diff action — compare two branches or refs\n */\n @Actions.Exec(\"/:branch\", \"diff\")\n async diffAction(\n _ctx: RouteContext<{ branch: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ready();\n\n const from = args.from as string;\n const to = args.to as string;\n const pathFilter = args.path as string | undefined;\n\n if (!from || !to) {\n return {\n success: false,\n error: { code: \"INVALID_ARGS\", message: \"from and to are required\" },\n };\n }\n\n try {\n // Get diff stat\n const diffArgs = [\"diff\", \"--stat\", \"--name-only\", `${from}...${to}`];\n if (pathFilter) {\n diffArgs.push(\"--\", pathFilter);\n }\n const statOutput = await this.git.raw(diffArgs);\n const fileLines = statOutput\n .trim()\n .split(\"\\n\")\n .filter((l) => l.trim());\n const files = fileLines.map((path) => ({ path }));\n\n // Get diff patch\n const patchArgs = [\"diff\", `${from}...${to}`];\n if (pathFilter) {\n patchArgs.push(\"--\", pathFilter);\n }\n const patch = await this.git.raw(patchArgs);\n\n return {\n success: true,\n data: {\n from,\n to,\n files,\n patch,\n filesChanged: files.length,\n },\n };\n } catch (error) {\n return {\n success: false,\n error: {\n code: \"DIFF_FAILED\",\n message: (error as Error).message.replace(this.repoPath, \"<repo>\"),\n },\n };\n }\n }\n\n /**\n * create-branch action — create a new branch\n */\n @Actions.Exec(\"/:branch\", \"create-branch\")\n async createBranchAction(\n _ctx: RouteContext<{ branch: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ready();\n\n const name = args.name as string;\n const from = args.from as string | undefined;\n\n if (!name) {\n return { success: false, error: { code: \"INVALID_ARGS\", message: \"name is required\" } };\n }\n\n // Validate branch name - reject path traversal\n if (name.includes(\"..\")) {\n return {\n success: false,\n error: { code: \"INVALID_NAME\", message: \"Branch name contains invalid characters\" },\n };\n }\n\n try {\n if (from) {\n await this.git.raw([\"branch\", name, from]);\n } else {\n await this.git.raw([\"branch\", name]);\n }\n\n // Get the hash of the new branch\n const hash = await this.git.revparse([name]).then((h) => h.trim());\n\n return {\n success: true,\n data: { branch: name, hash },\n };\n } catch (error) {\n return {\n success: false,\n error: {\n code: \"CREATE_BRANCH_FAILED\",\n message: (error as Error).message.replace(this.repoPath, \"<repo>\"),\n },\n };\n }\n }\n\n /**\n * commit action — commit staged changes\n */\n @Actions.Exec(\"/:branch\", \"commit\")\n async commitAction(\n _ctx: RouteContext<{ branch: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ready();\n\n const message = args.message as string;\n if (!message) {\n return { success: false, error: { code: \"INVALID_ARGS\", message: \"message is required\" } };\n }\n\n const author = args.author as { name?: string; email?: string } | undefined;\n\n try {\n const git = simpleGit(this.repoPath);\n\n // Check for staged changes\n const status = await git.status();\n if (\n status.staged.length === 0 &&\n status.files.filter((f) => f.index !== \" \" && f.index !== \"?\").length === 0\n ) {\n return {\n success: false,\n error: { code: \"NO_CHANGES\", message: \"No staged changes to commit\" },\n };\n }\n\n // Configure author if provided\n if (author?.name) {\n await git.addConfig(\"user.name\", author.name, undefined, \"local\");\n }\n if (author?.email) {\n await git.addConfig(\"user.email\", author.email, undefined, \"local\");\n }\n\n const result = await git.commit(message);\n\n return {\n success: true,\n data: {\n hash: result.commit || \"\",\n message,\n filesChanged: result.summary.changes,\n },\n };\n } catch (error) {\n return {\n success: false,\n error: {\n code: \"COMMIT_FAILED\",\n message: (error as Error).message.replace(this.repoPath, \"<repo>\"),\n },\n };\n }\n }\n\n /**\n * merge action — merge a branch into current branch\n */\n @Actions.Exec(\"/:branch\", \"merge\")\n async mergeAction(\n _ctx: RouteContext<{ branch: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ready();\n\n const branch = args.branch as string;\n if (!branch) {\n return { success: false, error: { code: \"INVALID_ARGS\", message: \"branch is required\" } };\n }\n\n const customMessage = args.message as string | undefined;\n\n try {\n const git = simpleGit(this.repoPath);\n\n // Verify the branch exists\n const branches = await git.branchLocal();\n if (!branches.all.includes(branch)) {\n return {\n success: false,\n error: { code: \"BRANCH_NOT_FOUND\", message: `Branch '${branch}' not found` },\n };\n }\n\n const mergeArgs = [branch];\n if (customMessage) {\n mergeArgs.push(\"-m\", customMessage);\n }\n\n const result = await git.merge(mergeArgs);\n\n // Get the resulting commit hash\n const hash = await git.revparse([\"HEAD\"]).then((h) => h.trim());\n\n return {\n success: true,\n data: {\n hash,\n merged: branch,\n conflicts: result.conflicts || [],\n },\n };\n } catch (error) {\n // Abort merge if there was a conflict\n try {\n const git = simpleGit(this.repoPath);\n await git.merge([\"--abort\"]);\n } catch {\n // Ignore abort errors\n }\n\n return {\n success: false,\n error: {\n code: \"MERGE_FAILED\",\n message: (error as Error).message.replace(this.repoPath, \"<repo>\"),\n },\n };\n }\n }\n\n // ========== .log/ Virtual Tree ==========\n\n /**\n * List .log/ → commit list with pagination\n */\n @List(\"/:branch/.log\")\n async listLogHandler(ctx: RouteContext<{ branch: string }>): Promise<AFSListResult> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n\n const options = ctx.options as { limit?: number; offset?: number };\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n const offset = options?.offset || 0;\n\n const commits = await this.getCommitList(branch, limit, offset);\n const branchEncoded = this.encodeBranchName(branch);\n\n const entries: AFSEntry[] = commits.map((commit, i) =>\n this.buildEntry(`/${branchEncoded}/.log/${offset + i}`, {\n meta: {\n hash: commit.hash,\n shortHash: commit.shortHash,\n author: commit.author,\n date: commit.date,\n message: commit.message,\n },\n }),\n );\n\n return { data: entries };\n }\n\n /**\n * Read .log/{index} → commit diff/patch content\n */\n @Read(\"/:branch/.log/:index\")\n async readLogEntryHandler(\n ctx: RouteContext<{ branch: string; index: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const index = Number.parseInt(ctx.params.index, 10);\n\n if (Number.isNaN(index) || index < 0) {\n throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${ctx.params.index}`);\n }\n\n const commits = await this.getCommitList(branch, 1, index);\n if (commits.length === 0) {\n throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${index}`);\n }\n\n const commit = commits[0]!;\n\n // Get diff for this commit\n let diff: string;\n try {\n diff = await this.git.raw([\"show\", \"--stat\", \"--patch\", commit.hash]);\n } catch {\n diff = \"\";\n }\n\n const branchEncoded = this.encodeBranchName(branch);\n return this.buildEntry(`/${branchEncoded}/.log/${index}`, {\n content: diff,\n meta: {\n hash: commit.hash,\n shortHash: commit.shortHash,\n author: commit.author,\n date: commit.date,\n message: commit.message,\n },\n });\n }\n\n /**\n * Read .log/{index}/.meta → commit metadata only (no diff)\n */\n @Read(\"/:branch/.log/:index/.meta\")\n async readLogEntryMetaHandler(\n ctx: RouteContext<{ branch: string; index: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const index = Number.parseInt(ctx.params.index, 10);\n\n if (Number.isNaN(index) || index < 0) {\n throw new AFSNotFoundError(\n `/${this.encodeBranchName(branch)}/.log/${ctx.params.index}/.meta`,\n );\n }\n\n const commits = await this.getCommitList(branch, 1, index);\n if (commits.length === 0) {\n throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${index}/.meta`);\n }\n\n const commit = commits[0]!;\n const branchEncoded = this.encodeBranchName(branch);\n return this.buildEntry(`/${branchEncoded}/.log/${index}/.meta`, {\n meta: {\n hash: commit.hash,\n shortHash: commit.shortHash,\n author: commit.author,\n date: commit.date,\n message: commit.message,\n },\n });\n }\n\n // ========== Private Helper Methods ==========\n\n /**\n * Decode branch name (replace ~ with /)\n */\n private decodeBranchName(encoded: string): string {\n return encoded.replace(/~/g, \"/\");\n }\n\n /**\n * Encode branch name (replace / with ~)\n */\n private encodeBranchName(branch: string): string {\n return branch.replace(/\\//g, \"~\");\n }\n\n /**\n * Parse AFS path into branch and file path\n * Branch names may contain slashes and are encoded with ~ in paths\n */\n private parsePath(path: string): { branch?: string; filePath: string } {\n const normalized = join(\"/\", path); // Ensure leading slash\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (segments.length === 0) {\n return { branch: undefined, filePath: \"\" };\n }\n\n // Decode branch name (first segment): replace ~ with /\n const branch = segments[0]!.replace(/~/g, \"/\");\n const filePath = segments.slice(1).join(\"/\");\n\n return { branch, filePath };\n }\n\n /**\n * Build AFS path with encoded branch name\n * Branch names with slashes are encoded by replacing / with ~\n */\n private buildBranchPath(branch: string, filePath?: string): string {\n const encodedBranch = this.encodeBranchName(branch);\n if (!filePath) {\n return `/${encodedBranch}`;\n }\n return `/${encodedBranch}/${filePath}`;\n }\n\n /**\n * Get list of available branches\n */\n private async getBranches(): Promise<string[]> {\n const branchSummary = await this.git.branchLocal();\n const allBranches = branchSummary.all;\n\n // Filter by allowed branches if specified\n if (this.options.branches && this.options.branches.length > 0) {\n return allBranches.filter((branch) => this.options.branches!.includes(branch));\n }\n\n return allBranches;\n }\n\n /**\n * Check if a branch exists, throw AFSNotFoundError if not\n */\n private async ensureBranchExists(branch: string): Promise<void> {\n const branches = await this.getBranches();\n if (!branches.includes(branch)) {\n throw new AFSNotFoundError(this.buildBranchPath(branch));\n }\n }\n\n /**\n * Get the number of children for a tree (directory) in git\n */\n private async getChildrenCount(branch: string, path: string): Promise<number> {\n try {\n const treeish = path ? `${branch}:${path}` : branch;\n const output = await this.git.raw([\"ls-tree\", treeish]);\n const lines = output.split(\"\\n\").filter((line) => line.trim());\n return lines.length;\n } catch {\n return 0;\n }\n }\n\n /**\n * Get the last commit on a branch\n */\n private async getLastCommit(\n branch: string,\n ): Promise<{ hash: string; shortHash: string; author: string; date: string; message: string }> {\n const output = await this.git.raw([\"log\", \"-1\", \"--format=%H%n%h%n%an%n%aI%n%s\", branch]);\n const lines = output.trim().split(\"\\n\");\n return {\n hash: lines[0] || \"\",\n shortHash: lines[1] || \"\",\n author: lines[2] || \"\",\n date: lines[3] || \"\",\n message: lines[4] || \"\",\n };\n }\n\n /**\n * Count total files in a tree (recursively)\n */\n private async getTreeFileCount(branch: string, path: string): Promise<number> {\n try {\n const treeish = path ? `${branch}:${path}` : branch;\n const output = await this.git.raw([\"ls-tree\", \"-r\", treeish]);\n const lines = output.split(\"\\n\").filter((line) => line.trim());\n return lines.length;\n } catch {\n return 0;\n }\n }\n\n /**\n * Get a list of commits on a branch with limit/offset\n */\n private async getCommitList(\n branch: string,\n limit: number,\n offset: number,\n ): Promise<{ hash: string; shortHash: string; author: string; date: string; message: string }[]> {\n try {\n const args = [\n \"log\",\n `--skip=${offset}`,\n `-${limit}`,\n \"--format=%H%n%h%n%an%n%aI%n%s%n---COMMIT_SEP---\",\n branch,\n ];\n const output = await this.git.raw(args);\n const blocks = output.split(\"---COMMIT_SEP---\").filter((b) => b.trim());\n\n return blocks.map((block) => {\n const lines = block.trim().split(\"\\n\");\n return {\n hash: lines[0] || \"\",\n shortHash: lines[1] || \"\",\n author: lines[2] || \"\",\n date: lines[3] || \"\",\n message: lines[4] || \"\",\n };\n });\n } catch {\n return [];\n }\n }\n\n /**\n * Ensure worktree exists for a branch (lazy creation)\n */\n private async ensureWorktree(branch: string): Promise<string> {\n if (this.worktrees.has(branch)) {\n return this.worktrees.get(branch)!;\n }\n\n // Check if this is the current branch in the main repo\n const currentBranch = await this.git.revparse([\"--abbrev-ref\", \"HEAD\"]);\n if (currentBranch.trim() === branch) {\n // Use the main repo path for the current branch\n this.worktrees.set(branch, this.repoPath);\n return this.repoPath;\n }\n\n const worktreePath = join(this.tempBase, branch);\n\n // Check if worktree directory already exists\n const exists = await stat(worktreePath)\n .then(() => true)\n .catch(() => false);\n\n if (!exists) {\n await mkdir(this.tempBase, { recursive: true });\n await this.git.raw([\"worktree\", \"add\", worktreePath, branch]);\n }\n\n this.worktrees.set(branch, worktreePath);\n return worktreePath;\n }\n\n /**\n * List files using git ls-tree (no worktree needed)\n * Note: list() returns only children, never the path itself (per new semantics)\n */\n private async listWithGitLsTree(\n branch: string,\n path: string,\n options?: { maxDepth?: number; limit?: number },\n ): Promise<AFSListResult> {\n const maxDepth = options?.maxDepth ?? 1;\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n\n const entries: AFSEntry[] = [];\n const targetPath = path || \"\";\n const treeish = targetPath ? `${branch}:${targetPath}` : branch;\n\n try {\n // Check if the path exists and is a directory\n const pathType = await this.git\n .raw([\"cat-file\", \"-t\", treeish])\n .then((t) => t.trim())\n .catch(() => null);\n\n if (pathType === null) {\n // Path doesn't exist\n throw new AFSNotFoundError(this.buildBranchPath(branch, path));\n }\n\n // If it's a file (blob), it has no children\n if (pathType === \"blob\") {\n return { data: [] };\n }\n\n // It's a directory\n // maxDepth: 0 means return no children\n if (maxDepth === 0) {\n return { data: [] };\n }\n\n // List directory contents via BFS\n interface QueueItem {\n path: string;\n depth: number;\n }\n\n const queue: QueueItem[] = [{ path: targetPath, depth: 0 }];\n\n while (queue.length > 0) {\n const item = queue.shift()!;\n const { path: itemPath, depth } = item;\n\n // List directory contents\n const itemTreeish = itemPath ? `${branch}:${itemPath}` : branch;\n const output = await this.git.raw([\"ls-tree\", \"-l\", itemTreeish]);\n\n const lines = output\n .split(\"\\n\")\n .filter((line) => line.trim())\n .slice(0, limit - entries.length);\n\n for (const line of lines) {\n // Format: <mode> <type> <hash> <size (with padding)> <name>\n const match = line.match(/^(\\d+)\\s+(blob|tree)\\s+(\\w+)\\s+(-|\\d+)\\s+(.+)$/);\n if (!match) continue;\n\n const type = match[2]!;\n const sizeStr = match[4]!;\n const name = match[5]!;\n const isDirectory = type === \"tree\";\n const size = sizeStr === \"-\" ? undefined : Number.parseInt(sizeStr, 10);\n\n const fullPath = itemPath ? `${itemPath}/${name}` : name;\n const afsPath = this.buildBranchPath(branch, fullPath);\n\n // For directories, get children count\n const childrenCount = isDirectory\n ? await this.getChildrenCount(branch, fullPath)\n : undefined;\n\n entries.push(\n this.buildEntry(afsPath, {\n meta: { kind: isDirectory ? \"git:directory\" : \"git:file\", size, childrenCount },\n }),\n );\n\n // Add to queue if it's a directory and we haven't reached max depth\n if (isDirectory && depth + 1 < maxDepth) {\n queue.push({ path: fullPath, depth: depth + 1 });\n }\n\n // Check limit\n if (entries.length >= limit) {\n return { data: entries };\n }\n }\n }\n\n return { data: entries };\n } catch (error) {\n // Re-throw AFSNotFoundError as-is\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n throw new Error(`Failed to list: ${(error as Error).message}`);\n }\n }\n\n /**\n * Detect MIME type based on file extension\n */\n private getMimeType(filePath: string): string {\n const ext = filePath.split(\".\").pop()?.toLowerCase();\n const mimeTypes: Record<string, string> = {\n // Images\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n bmp: \"image/bmp\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n ico: \"image/x-icon\",\n // Documents\n pdf: \"application/pdf\",\n txt: \"text/plain\",\n md: \"text/markdown\",\n // Code\n js: \"text/javascript\",\n ts: \"text/typescript\",\n json: \"application/json\",\n html: \"text/html\",\n css: \"text/css\",\n xml: \"text/xml\",\n };\n return mimeTypes[ext || \"\"] || \"application/octet-stream\";\n }\n\n /**\n * Check if file is likely binary based on extension\n */\n private isBinaryFile(filePath: string): boolean {\n const ext = filePath.split(\".\").pop()?.toLowerCase();\n const binaryExtensions = [\n \"png\",\n \"jpg\",\n \"jpeg\",\n \"gif\",\n \"bmp\",\n \"webp\",\n \"ico\",\n \"pdf\",\n \"zip\",\n \"tar\",\n \"gz\",\n \"exe\",\n \"dll\",\n \"so\",\n \"dylib\",\n \"wasm\",\n ];\n return binaryExtensions.includes(ext || \"\");\n }\n\n // ========== Public Git Operations ==========\n\n /**\n * Fetch latest changes from remote\n */\n async fetch(): Promise<void> {\n await this.ready();\n await this.git.fetch();\n }\n\n /**\n * Pull latest changes from remote for current branch\n */\n async pull(): Promise<void> {\n await this.ready();\n await this.git.pull();\n }\n\n /**\n * Push local changes to remote\n */\n async push(branch?: string): Promise<void> {\n await this.ready();\n if (branch) {\n await this.git.push(\"origin\", branch);\n } else {\n await this.git.push();\n }\n }\n\n /**\n * Cleanup all worktrees (useful when unmounting)\n */\n async cleanup(): Promise<void> {\n await this.ready();\n for (const [_branch, worktreePath] of this.worktrees) {\n try {\n await this.git.raw([\"worktree\", \"remove\", worktreePath, \"--force\"]);\n } catch (_error) {\n // Ignore errors during cleanup\n }\n }\n this.worktrees.clear();\n\n // Remove temp directory\n try {\n await rm(this.tempBase, { recursive: true, force: true });\n } catch {\n // Ignore errors\n }\n\n // Cleanup cloned repository if auto-cloned and autoCleanup enabled\n const autoCleanup = this.options.autoCleanup ?? true;\n if (this.isAutoCloned && autoCleanup && this.clonedPath) {\n try {\n await rm(this.clonedPath, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n}\n\nconst _typeCheck: AFSModuleClass<AFSGit, AFSGitOptions> = AFSGit;\n\nexport default AFSGit;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["afsPath","mimeType","isBinary","content","meta"],"sources":["../src/index.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readdir, readFile, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { basename, dirname, isAbsolute, join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n type AFSAccessMode,\n type AFSDeleteOptions,\n type AFSEntry,\n type AFSEntryMetadata,\n type AFSExecResult,\n type AFSExplainOptions,\n type AFSExplainResult,\n type AFSListResult,\n type AFSModuleClass,\n type AFSModuleLoadParams,\n AFSNotFoundError,\n type AFSRenameOptions,\n type AFSSearchOptions,\n type AFSStatResult,\n type AFSWriteEntryPayload,\n type CapabilitiesManifest,\n type ProviderManifest,\n} from \"@aigne/afs\";\nimport {\n Actions,\n AFSBaseProvider,\n Delete,\n Explain,\n List,\n Meta,\n Read,\n Rename,\n type RouteContext,\n Search,\n Stat,\n Write,\n} from \"@aigne/afs/provider\";\nimport { camelize, optionalize, zodParse } from \"@aigne/afs/utils/zod\";\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport { z } from \"zod\";\n\nconst LIST_MAX_LIMIT = 1000;\n\nconst execFileAsync = promisify(execFile);\n\nexport interface AFSGitOptions {\n name?: string;\n /**\n * Local path to git repository.\n * If remoteUrl is provided and repoPath doesn't exist, will clone to this path.\n * If remoteUrl is provided and repoPath is not specified, clones to temp directory.\n */\n repoPath?: string;\n /**\n * Remote repository URL (https or git protocol).\n * If provided, will clone the repository if repoPath doesn't exist.\n * Examples:\n * - https://github.com/user/repo.git\n * - git@github.com:user/repo.git\n */\n remoteUrl?: string;\n description?: string;\n /**\n * List of branches to expose/access.\n * Also used for clone optimization when cloning from remoteUrl:\n * - Single branch (e.g., ['main']): Uses --single-branch for faster clone\n * - Multiple branches: Clones all branches, filters access to specified ones\n * - Not specified: All branches are accessible\n */\n branches?: string[];\n /**\n * Access mode for this module.\n * - \"readonly\": Only read operations are allowed, uses git commands (no worktree)\n * - \"readwrite\": All operations are allowed, creates worktrees as needed\n * @default \"readonly\"\n */\n accessMode?: AFSAccessMode;\n /**\n * Automatically commit changes after write operations\n * @default false\n */\n autoCommit?: boolean;\n /**\n * Author information for commits when autoCommit is enabled\n */\n commitAuthor?: {\n name: string;\n email: string;\n };\n /**\n * Clone depth for shallow clone (only used when cloning from remoteUrl)\n * @default 1\n */\n depth?: number;\n /**\n * Automatically clean up cloned repository on cleanup()\n * Only applies when repository was auto-cloned to temp directory\n * @default true\n */\n autoCleanup?: boolean;\n /**\n * Git clone options (only used when cloning from remoteUrl)\n */\n cloneOptions?: {\n /**\n * Authentication credentials for private repositories\n */\n auth?: {\n username?: string;\n password?: string;\n };\n };\n}\n\nconst afsGitOptionsSchema = camelize(\n z\n .object({\n name: optionalize(z.string()),\n repoPath: optionalize(z.string().describe(\"The path to the git repository\")),\n remoteUrl: optionalize(z.string().describe(\"Remote repository URL (https or git protocol)\")),\n description: optionalize(z.string().describe(\"A description of the repository\")),\n branches: optionalize(z.array(z.string()).describe(\"List of branches to expose\")),\n accessMode: optionalize(\n z.enum([\"readonly\", \"readwrite\"]).describe(\"Access mode for this module\"),\n ),\n autoCommit: optionalize(\n z.boolean().describe(\"Automatically commit changes after write operations\"),\n ),\n commitAuthor: optionalize(\n z.object({\n name: z.string(),\n email: z.string(),\n }),\n ),\n depth: optionalize(z.number().describe(\"Clone depth for shallow clone\")),\n autoCleanup: optionalize(\n z.boolean().describe(\"Automatically clean up cloned repository on cleanup()\"),\n ),\n cloneOptions: optionalize(\n z.object({\n auth: optionalize(\n z.object({\n username: optionalize(z.string()),\n password: optionalize(z.string()),\n }),\n ),\n }),\n ),\n })\n .refine((data) => data.repoPath || data.remoteUrl, {\n message: \"Either repoPath or remoteUrl must be provided\",\n }),\n);\n\nexport class AFSGit extends AFSBaseProvider {\n static schema() {\n return afsGitOptionsSchema;\n }\n\n static manifest(): ProviderManifest {\n return {\n name: \"git\",\n description: \"Mount a local Git repository\",\n uriTemplate: \"git://{localPath+}\",\n category: \"version-control\",\n schema: z.object({\n localPath: z.string(),\n branch: z.string().optional(),\n remoteUrl: z.string().optional(),\n }),\n tags: [\"git\", \"version-control\"],\n };\n }\n\n static async load({ basePath, config }: AFSModuleLoadParams = {}) {\n const valid = await AFSGit.schema().parseAsync(config);\n const instance = new AFSGit({ ...valid, cwd: basePath });\n await instance.ready();\n return instance;\n }\n\n readonly name: string;\n readonly description?: string;\n readonly accessMode: AFSAccessMode;\n\n private initPromise: Promise<void>;\n private git: SimpleGit;\n private tempBase: string;\n private worktrees: Map<string, string> = new Map();\n private repoHash: string;\n private isAutoCloned = false;\n private clonedPath?: string;\n private repoPath: string;\n\n constructor(\n public options: AFSGitOptions & {\n cwd?: string;\n localPath?: string;\n branch?: string;\n uri?: string;\n },\n ) {\n super();\n\n // Normalize registry-passed template vars\n if ((options as any).localPath && !options.repoPath) {\n options.repoPath = (options as any).localPath;\n }\n if ((options as any).branch && !options.branches) {\n options.branches = [(options as any).branch];\n }\n\n zodParse(afsGitOptionsSchema, options);\n\n // Synchronously determine repoPath to initialize name\n let repoPath: string;\n let repoName: string;\n\n if (options.repoPath) {\n // Use provided repoPath\n repoPath = isAbsolute(options.repoPath)\n ? options.repoPath\n : join(options.cwd || process.cwd(), options.repoPath);\n repoName = basename(repoPath);\n } else if (options.remoteUrl) {\n // Extract repo name from URL for temporary name\n const urlParts = options.remoteUrl.split(\"/\");\n const lastPart = urlParts[urlParts.length - 1];\n repoName = lastPart?.replace(/\\.git$/, \"\") || \"git\";\n\n // Will be updated during async init, use temp path for now\n const repoHash = createHash(\"md5\").update(options.remoteUrl).digest(\"hex\").substring(0, 8);\n repoPath = join(tmpdir(), `afs-git-remote-${repoHash}`);\n } else {\n // This should never happen due to schema validation\n throw new Error(\"Either repoPath or remoteUrl must be provided\");\n }\n\n // Auto-create local repository if it doesn't exist (skip for remoteUrl — will be cloned)\n if (options.repoPath && !options.remoteUrl) {\n const { existsSync, mkdirSync } = require(\"node:fs\") as typeof import(\"node:fs\");\n const { execSync } = require(\"node:child_process\") as typeof import(\"node:child_process\");\n if (!existsSync(repoPath)) {\n mkdirSync(repoPath, { recursive: true });\n }\n if (!existsSync(join(repoPath, \".git\"))) {\n execSync(\"git init -b main\", { cwd: repoPath, stdio: \"ignore\" });\n }\n }\n\n // Initialize basic properties immediately\n this.repoPath = repoPath;\n this.name = options.name || repoName;\n this.description = options.description;\n this.accessMode = options.accessMode ?? \"readonly\";\n\n // Calculate hash for temp directories\n this.repoHash = createHash(\"md5\").update(repoPath).digest(\"hex\").substring(0, 8);\n this.tempBase = join(tmpdir(), `afs-git-${this.repoHash}`);\n\n // Note: git and other properties will be initialized in initialize() after cloning\n // We need to delay simpleGit() initialization until the directory exists\n this.git = null as any; // Will be set in initialize()\n\n // Start async initialization (cloning if needed)\n this.initPromise = this.initialize();\n }\n\n /**\n * Wait for async initialization to complete\n */\n async ready(): Promise<void> {\n await this.initPromise;\n }\n\n /**\n * Async initialization logic (runs in constructor)\n * Handles cloning remote repositories if needed\n */\n private async initialize(): Promise<void> {\n const options = this.options;\n\n // If remoteUrl is provided, handle cloning\n if (options.remoteUrl) {\n const targetPath = options.repoPath\n ? isAbsolute(options.repoPath)\n ? options.repoPath\n : join(options.cwd || process.cwd(), options.repoPath)\n : this.repoPath; // Use temp path set in constructor\n\n // Mark as auto-cloned if we're using temp directory\n if (!options.repoPath) {\n this.isAutoCloned = true;\n }\n\n // Check if targetPath exists and is a valid git repository\n const exists = await stat(targetPath)\n .then(() => true)\n .catch(() => false);\n\n let needsClone = !exists;\n\n // If directory exists but is not a valid git repo, clean it up and re-clone\n if (exists) {\n const tempGit = simpleGit(targetPath);\n const isValidRepo = await tempGit.checkIsRepo().catch(() => false);\n if (!isValidRepo) {\n // Remove invalid directory and re-clone\n await rm(targetPath, { recursive: true, force: true });\n needsClone = true;\n }\n }\n\n if (needsClone) {\n // Determine if single-branch optimization should be used\n const singleBranch = options.branches?.length === 1 ? options.branches[0] : undefined;\n\n await AFSGit.cloneRepository(options.remoteUrl, targetPath, {\n depth: options.depth ?? 1,\n branch: singleBranch,\n auth: options.cloneOptions?.auth,\n });\n }\n\n // Update properties if targetPath differs from constructor initialization\n if (targetPath !== this.repoPath) {\n this.repoPath = targetPath;\n this.repoHash = createHash(\"md5\").update(targetPath).digest(\"hex\").substring(0, 8);\n this.tempBase = join(tmpdir(), `afs-git-${this.repoHash}`);\n }\n\n this.clonedPath = this.isAutoCloned ? targetPath : undefined;\n }\n\n // Now that the directory exists (either it was there or we cloned it), initialize git\n this.git = simpleGit(this.repoPath);\n\n // Validate that the directory is actually a git repository\n const isRepo = await this.git.checkIsRepo();\n if (!isRepo) {\n throw new Error(`Not a git repository: ${this.repoPath}`);\n }\n }\n\n /**\n * Clone a remote repository to local path\n */\n private static async cloneRepository(\n remoteUrl: string,\n targetPath: string,\n options: {\n depth?: number;\n branch?: string;\n auth?: { username?: string; password?: string };\n } = {},\n ): Promise<void> {\n const git = simpleGit();\n\n // Build clone options\n const cloneArgs: string[] = [];\n\n if (options.depth) {\n cloneArgs.push(\"--depth\", options.depth.toString());\n }\n\n if (options.branch) {\n cloneArgs.push(\"--branch\", options.branch, \"--single-branch\");\n }\n\n // Handle authentication in URL if provided\n let cloneUrl = remoteUrl;\n if (options.auth?.username && options.auth?.password) {\n // Insert credentials into HTTPS URL\n if (remoteUrl.startsWith(\"https://\")) {\n const url = new URL(remoteUrl);\n url.username = encodeURIComponent(options.auth.username);\n url.password = encodeURIComponent(options.auth.password);\n cloneUrl = url.toString();\n }\n }\n\n await git.clone(cloneUrl, targetPath, cloneArgs);\n }\n\n // ========== Route Handlers ==========\n\n /**\n * List root (branches)\n * Note: list() returns only children (branches), never the path itself (per new semantics)\n */\n @List(\"/\", { handleDepth: true })\n async listRootHandler(ctx: RouteContext): Promise<AFSListResult & { noExpand?: string[] }> {\n await this.ready();\n\n const options = ctx.options as { limit?: number; maxDepth?: number };\n const maxDepth = options?.maxDepth ?? 1;\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n\n // maxDepth: 0 means return no children\n if (maxDepth === 0) {\n return { data: [] };\n }\n\n const branches = await this.getBranches();\n const entries: AFSEntry[] = [];\n\n for (const name of branches) {\n if (entries.length >= limit) break;\n\n const encodedPath = this.buildBranchPath(name);\n\n // Get children count for this branch\n const branchChildrenCount = await this.getChildrenCount(name, \"\");\n\n entries.push(\n this.buildEntry(encodedPath, {\n meta: { kind: \"git:branch\", childrenCount: branchChildrenCount },\n }),\n );\n\n // If maxDepth > 1, also list contents of each branch\n if (maxDepth > 1) {\n const branchResult = await this.listWithGitLsTree(name, \"\", {\n maxDepth: maxDepth - 1,\n limit: limit - entries.length,\n });\n entries.push(...branchResult.data);\n }\n }\n\n return { data: entries };\n }\n\n /**\n * List branch root (matches /main, /develop, etc.)\n */\n @List(\"/:branch\", { handleDepth: true })\n async listBranchRootHandler(\n ctx: RouteContext<{ branch: string }>,\n ): Promise<AFSListResult & { noExpand?: string[] }> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n\n return this.listWithGitLsTree(branch, \"\", ctx.options as { maxDepth?: number; limit?: number });\n }\n\n /**\n * List files in branch with subpath (matches /main/src, /main/src/foo, etc.)\n */\n @List(\"/:branch/:path+\", { handleDepth: true })\n async listBranchHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<AFSListResult & { noExpand?: string[] }> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const filePath = ctx.params.path;\n\n return this.listWithGitLsTree(\n branch,\n filePath,\n ctx.options as { maxDepth?: number; limit?: number },\n );\n }\n\n // ========== Meta Handlers ==========\n // These handlers provide metadata access for all paths via .meta suffix\n\n /**\n * Read root metadata (introspection only, read-only)\n */\n @Meta(\"/\")\n async readRootMetaHandler(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branches = await this.getBranches();\n return this.buildEntry(\"/.meta\", {\n meta: { childrenCount: branches.length, type: \"root\" },\n });\n }\n\n /**\n * Read branch root metadata (introspection only, read-only)\n */\n @Meta(\"/:branch\")\n async readBranchMetaHandler(\n ctx: RouteContext<{ branch: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const childrenCount = await this.getChildrenCount(branch, \"\");\n const branchPath = `/${this.encodeBranchName(branch)}`;\n const metaPath = `${branchPath}/.meta`;\n const lastCommit = await this.getLastCommit(branch);\n\n return this.buildEntry(metaPath, {\n meta: { childrenCount, type: \"branch\", lastCommit },\n });\n }\n\n /**\n * Read file or directory metadata in branch (introspection only, read-only)\n */\n @Meta(\"/:branch/:path+\")\n async readPathMetaHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const filePath = ctx.params.path;\n\n // Check if the path exists\n const objectType = await this.git\n .raw([\"cat-file\", \"-t\", `${branch}:${filePath}`])\n .then((t) => t.trim())\n .catch(() => null);\n\n if (objectType === null) {\n throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));\n }\n\n const isDir = objectType === \"tree\";\n const metaPath = `/${this.encodeBranchName(branch)}/${filePath}/.meta`;\n\n let childrenCount: number | undefined;\n if (isDir) {\n childrenCount = await this.getChildrenCount(branch, filePath);\n }\n\n return this.buildEntry(metaPath, {\n meta: {\n childrenCount,\n type: isDir ? \"directory\" : \"file\",\n gitObjectType: objectType,\n },\n });\n }\n\n // ========== Regular Read Handlers ==========\n\n /**\n * Read root\n */\n @Read(\"/\")\n async readRootHandler(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branches = await this.getBranches();\n return this.buildEntry(\"/\", {\n meta: { childrenCount: branches.length },\n });\n }\n\n /**\n * Read branch root\n */\n @Read(\"/:branch\")\n async readBranchRootHandler(\n ctx: RouteContext<{ branch: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const branchPath = this.buildBranchPath(branch);\n const childrenCount = await this.getChildrenCount(branch, \"\");\n const lastCommit = await this.getLastCommit(branch);\n return this.buildEntry(branchPath, {\n meta: { childrenCount, lastCommit },\n });\n }\n\n /**\n * Read file or directory in branch\n */\n @Read(\"/:branch/:path+\")\n async readBranchHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const filePath = ctx.params.path;\n\n // Check if there's an active worktree for this branch - read from there first\n // This handles files that were written but may be in a different state than git index\n const worktreePath = this.worktrees.get(branch);\n if (worktreePath) {\n try {\n const fullPath = join(worktreePath, filePath);\n const stats = await stat(fullPath);\n\n if (stats.isDirectory()) {\n // It's a directory - count children\n const files = await readdir(fullPath);\n const afsPath = this.buildBranchPath(branch, filePath);\n return this.buildEntry(afsPath, {\n meta: { childrenCount: files.length },\n });\n }\n\n // It's a file - read content\n const mimeType = this.getMimeType(filePath);\n const isBinary = this.isBinaryFile(filePath);\n\n let content: string;\n const meta: AFSEntryMetadata = {\n size: stats.size,\n mimeType,\n };\n\n if (isBinary) {\n const buffer = await readFile(fullPath);\n content = buffer.toString(\"base64\");\n meta.contentType = \"base64\";\n } else {\n content = await readFile(fullPath, \"utf8\");\n }\n\n const afsPath = this.buildBranchPath(branch, filePath);\n return this.buildEntry(afsPath, {\n content,\n meta,\n createdAt: stats.birthtime,\n updatedAt: stats.mtime,\n });\n } catch {\n // File doesn't exist in worktree, fall through to git\n }\n }\n\n // Read from git repository\n // Check if path is a blob (file) or tree (directory)\n const objectType = await this.git\n .raw([\"cat-file\", \"-t\", `${branch}:${filePath}`])\n .then((t) => t.trim())\n .catch(() => null);\n\n if (objectType === null) {\n // Path doesn't exist in git\n throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));\n }\n\n if (objectType === \"tree\") {\n // It's a directory\n const afsPath = this.buildBranchPath(branch, filePath);\n const childrenCount = await this.getChildrenCount(branch, filePath);\n return this.buildEntry(afsPath, {\n meta: { childrenCount },\n });\n }\n\n // It's a file, get content\n const size = await this.git\n .raw([\"cat-file\", \"-s\", `${branch}:${filePath}`])\n .then((s) => Number.parseInt(s.trim(), 10));\n\n // Determine mimeType based on file extension\n const mimeType = this.getMimeType(filePath);\n const isBinary = this.isBinaryFile(filePath);\n\n let content: string;\n const meta: AFSEntryMetadata = {\n size,\n mimeType,\n };\n\n if (isBinary) {\n // For binary files, use execFileAsync to get raw buffer\n const { stdout } = await execFileAsync(\"git\", [\"cat-file\", \"-p\", `${branch}:${filePath}`], {\n cwd: this.options.repoPath,\n encoding: \"buffer\",\n maxBuffer: 10 * 1024 * 1024, // 10MB max\n });\n // Store only base64 string without data URL prefix\n content = (stdout as Buffer).toString(\"base64\");\n // Mark content as base64 in metadata\n meta.contentType = \"base64\";\n } else {\n // For text files, use git.show\n content = await this.git.show([`${branch}:${filePath}`]);\n }\n\n const afsPath = this.buildBranchPath(branch, filePath);\n return this.buildEntry(afsPath, {\n content,\n meta,\n });\n }\n\n /**\n * Write to root is not allowed\n */\n @Write(\"/\")\n async writeRootHandler(): Promise<never> {\n throw new Error(\"Cannot write to root\");\n }\n\n /**\n * Write to branch root is not allowed\n */\n @Write(\"/:branch\")\n async writeBranchRootHandler(): Promise<never> {\n throw new Error(\"Cannot write to branch root\");\n }\n\n /**\n * Write file in branch\n */\n @Write(\"/:branch/:path+\")\n async writeHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n payload: AFSWriteEntryPayload,\n ): Promise<{ data: AFSEntry }> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n const filePath = ctx.params.path;\n const options = ctx.options as { append?: boolean };\n const append = options?.append ?? false;\n\n // Create worktree for write operations\n const worktreePath = await this.ensureWorktree(branch);\n const fullPath = join(worktreePath, filePath);\n\n // Ensure parent directory exists\n const parentDir = dirname(fullPath);\n await mkdir(parentDir, { recursive: true });\n\n // Write content\n if (payload.content !== undefined) {\n let contentToWrite: string;\n if (typeof payload.content === \"string\") {\n contentToWrite = payload.content;\n } else {\n contentToWrite = JSON.stringify(payload.content, null, 2);\n }\n await writeFile(fullPath, contentToWrite, { encoding: \"utf8\", flag: append ? \"a\" : \"w\" });\n }\n\n // Auto commit if enabled\n if (this.options.autoCommit) {\n const gitInstance = simpleGit(worktreePath);\n await gitInstance.add(filePath);\n\n if (this.options.commitAuthor) {\n await gitInstance.addConfig(\n \"user.name\",\n this.options.commitAuthor.name,\n undefined,\n \"local\",\n );\n await gitInstance.addConfig(\n \"user.email\",\n this.options.commitAuthor.email,\n undefined,\n \"local\",\n );\n }\n\n await gitInstance.commit(`Update ${filePath}`);\n }\n\n // Get file stats\n const stats = await stat(fullPath);\n\n const afsPath = this.buildBranchPath(branch, filePath);\n const writtenEntry: AFSEntry = {\n id: afsPath,\n path: afsPath,\n content: payload.content,\n summary: payload.summary,\n createdAt: stats.birthtime,\n updatedAt: stats.mtime,\n meta: {\n ...payload.meta,\n size: stats.size,\n } as AFSEntryMetadata,\n userId: payload.userId,\n sessionId: payload.sessionId,\n linkTo: payload.linkTo,\n };\n\n return { data: writtenEntry };\n }\n\n /**\n * Delete root is not allowed\n */\n @Delete(\"/\")\n async deleteRootHandler(): Promise<never> {\n throw new Error(\"Cannot delete root\");\n }\n\n /**\n * Delete branch root is not allowed\n */\n @Delete(\"/:branch\")\n async deleteBranchRootHandler(ctx: RouteContext<{ branch: string }>): Promise<never> {\n await this.ready();\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n throw new Error(\"Cannot delete branch root\");\n }\n\n /**\n * Delete file in branch\n */\n @Delete(\"/:branch/:path+\")\n async deleteHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<{ message: string }> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n const filePath = ctx.params.path;\n const options = ctx.options as AFSDeleteOptions | undefined;\n const recursive = options?.recursive ?? false;\n\n // Create worktree for delete operations\n const worktreePath = await this.ensureWorktree(branch);\n const fullPath = join(worktreePath, filePath);\n\n let stats: Awaited<ReturnType<typeof stat>>;\n try {\n stats = await stat(fullPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));\n }\n throw error;\n }\n\n if (stats.isDirectory() && !recursive) {\n throw new Error(\n `Cannot delete directory '/${ctx.params.branch}/${filePath}' without recursive option. Set recursive: true to delete directories.`,\n );\n }\n\n await rm(fullPath, { recursive, force: true });\n\n // Auto commit if enabled\n if (this.options.autoCommit) {\n const gitInstance = simpleGit(worktreePath);\n await gitInstance.add(filePath);\n\n if (this.options.commitAuthor) {\n await gitInstance.addConfig(\n \"user.name\",\n this.options.commitAuthor.name,\n undefined,\n \"local\",\n );\n await gitInstance.addConfig(\n \"user.email\",\n this.options.commitAuthor.email,\n undefined,\n \"local\",\n );\n }\n\n await gitInstance.commit(`Delete ${filePath}`);\n }\n\n return { message: `Successfully deleted: /${ctx.params.branch}/${filePath}` };\n }\n\n /**\n * Rename file in branch\n */\n @Rename(\"/:branch/:path+\")\n async renameHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n newPath: string,\n ): Promise<{ message: string }> {\n await this.ready();\n\n const oldBranch = this.decodeBranchName(ctx.params.branch);\n const oldFilePath = ctx.params.path;\n\n // Parse new path\n const { branch: newBranch, filePath: newFilePath } = this.parsePath(newPath);\n const options = ctx.options as AFSRenameOptions | undefined;\n const overwrite = options?.overwrite ?? false;\n\n if (!newBranch || !newFilePath) {\n throw new Error(\"Cannot rename to root or branch root\");\n }\n\n if (oldBranch !== newBranch) {\n throw new Error(\"Cannot rename across branches\");\n }\n\n // Create worktree for rename operations\n const worktreePath = await this.ensureWorktree(oldBranch);\n const oldFullPath = join(worktreePath, oldFilePath);\n const newFullPath = join(worktreePath, newFilePath);\n\n // Check if source exists\n try {\n await stat(oldFullPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new AFSNotFoundError(this.buildBranchPath(oldBranch, oldFilePath));\n }\n throw error;\n }\n\n // Check if destination exists\n try {\n await stat(newFullPath);\n if (!overwrite) {\n throw new Error(\n `Destination '${newPath}' already exists. Set overwrite: true to replace it.`,\n );\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n\n // Ensure parent directory exists\n const newParentDir = dirname(newFullPath);\n await mkdir(newParentDir, { recursive: true });\n\n // Perform rename\n await rename(oldFullPath, newFullPath);\n\n // Auto commit if enabled\n if (this.options.autoCommit) {\n const gitInstance = simpleGit(worktreePath);\n await gitInstance.add([oldFilePath, newFilePath]);\n\n if (this.options.commitAuthor) {\n await gitInstance.addConfig(\n \"user.name\",\n this.options.commitAuthor.name,\n undefined,\n \"local\",\n );\n await gitInstance.addConfig(\n \"user.email\",\n this.options.commitAuthor.email,\n undefined,\n \"local\",\n );\n }\n\n await gitInstance.commit(`Rename ${oldFilePath} to ${newFilePath}`);\n }\n\n return {\n message: `Successfully renamed '/${ctx.params.branch}/${oldFilePath}' to '${newPath}'`,\n };\n }\n\n /**\n * Search files in branch root\n */\n @Search(\"/:branch\")\n async searchBranchRootHandler(\n ctx: RouteContext<{ branch: string }>,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<{ data: AFSEntry[]; message?: string }> {\n return this.searchInBranch(ctx.params.branch, \"\", query, options);\n }\n\n /**\n * Search files in branch path\n */\n @Search(\"/:branch/:path+\")\n async searchHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<{ data: AFSEntry[]; message?: string }> {\n return this.searchInBranch(ctx.params.branch, ctx.params.path, query, options);\n }\n\n /**\n * Internal search implementation\n */\n private async searchInBranch(\n encodedBranch: string,\n filePath: string,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<{ data: AFSEntry[]; message?: string }> {\n await this.ready();\n\n const branch = this.decodeBranchName(encodedBranch);\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n\n try {\n // Use git grep for searching (no worktree needed)\n const args = [\"grep\", \"-n\", \"-I\"]; // -n for line numbers, -I to skip binary files\n\n if (options?.caseSensitive === false) {\n args.push(\"-i\");\n }\n\n args.push(query, branch);\n\n // Add path filter if specified\n if (filePath) {\n args.push(\"--\", filePath);\n }\n\n const output = await this.git.raw(args);\n const lines = output.split(\"\\n\").filter((line) => line.trim());\n\n const entries: AFSEntry[] = [];\n const processedFiles = new Set<string>();\n\n for (const line of lines) {\n // Format when searching in branch: branch:path:linenum:content\n // Try the format with branch prefix first\n let matchPath: string;\n let lineNum: string;\n let content: string;\n\n const matchWithBranch = line.match(/^[^:]+:([^:]+):(\\d+):(.+)$/);\n if (matchWithBranch) {\n matchPath = matchWithBranch[1]!;\n lineNum = matchWithBranch[2]!;\n content = matchWithBranch[3]!;\n } else {\n // Try format without branch: path:linenum:content\n const matchNoBranch = line.match(/^([^:]+):(\\d+):(.+)$/);\n if (!matchNoBranch) continue;\n matchPath = matchNoBranch[1]!;\n lineNum = matchNoBranch[2]!;\n content = matchNoBranch[3]!;\n }\n\n const afsPath = this.buildBranchPath(branch, matchPath);\n\n if (processedFiles.has(afsPath)) continue;\n processedFiles.add(afsPath);\n\n const entry = this.buildEntry(afsPath);\n entry.summary = `Line ${lineNum}: ${content}`;\n entries.push(entry);\n\n if (entries.length >= limit) {\n break;\n }\n }\n\n return {\n data: entries,\n message: entries.length >= limit ? `Results truncated to limit ${limit}` : undefined,\n };\n } catch (error) {\n // git grep returns exit code 1 if no matches found\n if ((error as Error).message.includes(\"did not match any file(s)\")) {\n return { data: [] };\n }\n return { data: [], message: (error as Error).message };\n }\n }\n\n /**\n * Stat root\n */\n @Stat(\"/\")\n async statRootHandler(_ctx: RouteContext): Promise<AFSStatResult> {\n const entry = await this.readRootHandler(_ctx);\n if (!entry) {\n return { data: undefined };\n }\n // Return entry without content\n const { content: _content, ...rest } = entry;\n return { data: rest };\n }\n\n /**\n * Stat branch root\n */\n @Stat(\"/:branch\")\n async statBranchRootHandler(ctx: RouteContext<{ branch: string }>): Promise<AFSStatResult> {\n const entry = await this.readBranchRootHandler(ctx);\n if (!entry) {\n return { data: undefined };\n }\n // Return entry without content\n const { content: _content, ...rest } = entry;\n return { data: rest };\n }\n\n /**\n * Stat file or directory in branch\n */\n @Stat(\"/:branch/:path+\")\n async statHandler(ctx: RouteContext<{ branch: string; path: string }>): Promise<AFSStatResult> {\n const entry = await this.readBranchHandler(ctx);\n if (!entry) {\n return { data: undefined };\n }\n // Return entry without content\n const { content: _content, ...rest } = entry;\n return { data: rest };\n }\n\n // ========== Explain Handlers ==========\n\n /**\n * Explain root → repo info, branch list, default branch\n */\n @Explain(\"/\")\n async explainRootHandler(_ctx: RouteContext): Promise<AFSExplainResult> {\n await this.ready();\n\n const format = (_ctx.options as AFSExplainOptions)?.format || \"markdown\";\n const branches = await this.getBranches();\n const currentBranch = await this.git.revparse([\"--abbrev-ref\", \"HEAD\"]).then((b) => b.trim());\n\n let remoteUrl: string | undefined;\n try {\n remoteUrl = await this.git.remote([\"get-url\", \"origin\"]).then((u) => u?.trim());\n } catch {\n // No remote configured\n }\n\n const lines: string[] = [];\n lines.push(\"# Git Repository\");\n lines.push(\"\");\n lines.push(`**Provider:** ${this.name}`);\n if (this.description) {\n lines.push(`**Description:** ${this.description}`);\n }\n lines.push(`**Default Branch:** ${currentBranch}`);\n if (remoteUrl) {\n lines.push(`**Remote:** ${remoteUrl}`);\n }\n lines.push(`**Branches:** ${branches.length}`);\n lines.push(\"\");\n lines.push(\"## Branches\");\n lines.push(\"\");\n for (const branch of branches) {\n lines.push(`- ${branch}`);\n }\n\n return { content: lines.join(\"\\n\"), format };\n }\n\n /**\n * Explain branch → branch name, HEAD commit, file count\n */\n @Explain(\"/:branch\")\n async explainBranchHandler(ctx: RouteContext<{ branch: string }>): Promise<AFSExplainResult> {\n await this.ready();\n\n const format = (ctx.options as AFSExplainOptions)?.format || \"markdown\";\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n\n const lastCommit = await this.getLastCommit(branch);\n const fileCount = await this.getTreeFileCount(branch, \"\");\n\n const lines: string[] = [];\n lines.push(`# Branch: ${branch}`);\n lines.push(\"\");\n lines.push(`**HEAD Commit:** ${lastCommit.shortHash} - ${lastCommit.message}`);\n lines.push(`**Author:** ${lastCommit.author}`);\n lines.push(`**Date:** ${lastCommit.date}`);\n lines.push(`**Files:** ${fileCount} entries in tree`);\n\n return { content: lines.join(\"\\n\"), format };\n }\n\n /**\n * Explain file or directory → path, size, last modified commit\n */\n @Explain(\"/:branch/:path+\")\n async explainPathHandler(\n ctx: RouteContext<{ branch: string; path: string }>,\n ): Promise<AFSExplainResult> {\n await this.ready();\n\n const format = (ctx.options as AFSExplainOptions)?.format || \"markdown\";\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const filePath = ctx.params.path;\n\n const objectType = await this.git\n .raw([\"cat-file\", \"-t\", `${branch}:${filePath}`])\n .then((t) => t.trim())\n .catch(() => null);\n\n if (objectType === null) {\n throw new AFSNotFoundError(this.buildBranchPath(branch, filePath));\n }\n\n const isDir = objectType === \"tree\";\n const lines: string[] = [];\n\n lines.push(`# ${basename(filePath)}`);\n lines.push(\"\");\n lines.push(`**Path:** ${filePath}`);\n lines.push(`**Type:** ${isDir ? \"directory\" : \"file\"}`);\n\n if (!isDir) {\n const size = await this.git\n .raw([\"cat-file\", \"-s\", `${branch}:${filePath}`])\n .then((s) => Number.parseInt(s.trim(), 10));\n lines.push(`**Size:** ${size} bytes`);\n }\n\n // Get last commit that modified this path\n try {\n const logOutput = await this.git.raw([\n \"log\",\n \"-1\",\n \"--format=%H%n%h%n%an%n%aI%n%s\",\n branch,\n \"--\",\n filePath,\n ]);\n const logLines = logOutput.trim().split(\"\\n\");\n if (logLines.length >= 5) {\n lines.push(\"\");\n lines.push(\"## Last Modified\");\n lines.push(`**Commit:** ${logLines[1]} - ${logLines[4]}`);\n lines.push(`**Author:** ${logLines[2]}`);\n lines.push(`**Date:** ${logLines[3]}`);\n }\n } catch {\n // Ignore log errors\n }\n\n return { content: lines.join(\"\\n\"), format };\n }\n\n // ========== Capabilities ==========\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilitiesHandler(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n const operations = [\"list\", \"read\", \"stat\", \"explain\", \"search\"];\n if (this.accessMode === \"readwrite\") {\n operations.push(\"write\", \"delete\", \"rename\");\n }\n\n const actionCatalogs: CapabilitiesManifest[\"actions\"] = [];\n\n // diff is available in both modes conceptually, but exec() enforces readwrite\n // Include all actions in readwrite mode\n if (this.accessMode === \"readwrite\") {\n actionCatalogs.push({\n description: \"Git workflow actions\",\n catalog: [\n {\n name: \"diff\",\n description: \"Compare two branches or refs\",\n inputSchema: {\n type: \"object\",\n properties: {\n from: { type: \"string\", description: \"Source ref\" },\n to: { type: \"string\", description: \"Target ref\" },\n path: { type: \"string\", description: \"Optional path filter\" },\n },\n required: [\"from\", \"to\"],\n },\n },\n {\n name: \"create-branch\",\n description: \"Create a new branch\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"New branch name\" },\n from: { type: \"string\", description: \"Source ref (defaults to current HEAD)\" },\n },\n required: [\"name\"],\n },\n },\n {\n name: \"commit\",\n description: \"Commit staged changes\",\n inputSchema: {\n type: \"object\",\n properties: {\n message: { type: \"string\", description: \"Commit message\" },\n author: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n email: { type: \"string\" },\n },\n },\n },\n required: [\"message\"],\n },\n },\n {\n name: \"merge\",\n description: \"Merge a branch into the current branch\",\n inputSchema: {\n type: \"object\",\n properties: {\n branch: { type: \"string\", description: \"Branch to merge\" },\n message: { type: \"string\", description: \"Custom merge message\" },\n },\n required: [\"branch\"],\n },\n },\n ],\n discovery: {\n pathTemplate: \"/:branch/.actions\",\n note: \"Git workflow actions (readwrite mode only)\",\n },\n });\n }\n\n const manifest: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: this.name,\n description: this.description || \"Git repository provider\",\n tools: [],\n actions: actionCatalogs,\n operations: this.getOperationsDeclaration(),\n };\n\n return {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n content: manifest,\n meta: { kind: \"afs:capabilities\", operations },\n };\n }\n\n // ========== Git Actions ==========\n\n /**\n * List available actions for a branch\n */\n @Actions(\"/:branch\")\n async listBranchActions(ctx: RouteContext<{ branch: string }>): Promise<AFSListResult> {\n if (this.accessMode !== \"readwrite\") {\n return { data: [] };\n }\n\n const basePath = `/${ctx.params.branch}/.actions`;\n return {\n data: [\n {\n id: \"diff\",\n path: `${basePath}/diff`,\n summary: \"Compare two branches or refs\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n from: { type: \"string\", description: \"Source ref\" },\n to: { type: \"string\", description: \"Target ref\" },\n path: { type: \"string\", description: \"Optional path filter\" },\n },\n required: [\"from\", \"to\"],\n },\n },\n },\n {\n id: \"create-branch\",\n path: `${basePath}/create-branch`,\n summary: \"Create a new branch from this ref\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"New branch name\" },\n from: { type: \"string\", description: \"Source ref (defaults to current HEAD)\" },\n },\n required: [\"name\"],\n },\n },\n },\n {\n id: \"commit\",\n path: `${basePath}/commit`,\n summary: \"Commit staged changes\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n message: { type: \"string\", description: \"Commit message\" },\n author: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n email: { type: \"string\" },\n },\n },\n },\n required: [\"message\"],\n },\n },\n },\n {\n id: \"merge\",\n path: `${basePath}/merge`,\n summary: \"Merge another branch into this branch\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n branch: { type: \"string\", description: \"Branch to merge\" },\n message: { type: \"string\", description: \"Custom merge message\" },\n },\n required: [\"branch\"],\n },\n },\n },\n ],\n };\n }\n\n /**\n * diff action — compare two branches or refs\n */\n @Actions.Exec(\"/:branch\", \"diff\")\n async diffAction(\n _ctx: RouteContext<{ branch: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ready();\n\n const from = args.from as string;\n const to = args.to as string;\n const pathFilter = args.path as string | undefined;\n\n if (!from || !to) {\n return {\n success: false,\n error: { code: \"INVALID_ARGS\", message: \"from and to are required\" },\n };\n }\n\n try {\n // Get diff stat\n const diffArgs = [\"diff\", \"--stat\", \"--name-only\", `${from}...${to}`];\n if (pathFilter) {\n diffArgs.push(\"--\", pathFilter);\n }\n const statOutput = await this.git.raw(diffArgs);\n const fileLines = statOutput\n .trim()\n .split(\"\\n\")\n .filter((l) => l.trim());\n const files = fileLines.map((path) => ({ path }));\n\n // Get diff patch\n const patchArgs = [\"diff\", `${from}...${to}`];\n if (pathFilter) {\n patchArgs.push(\"--\", pathFilter);\n }\n const patch = await this.git.raw(patchArgs);\n\n return {\n success: true,\n data: {\n from,\n to,\n files,\n patch,\n filesChanged: files.length,\n },\n };\n } catch (error) {\n return {\n success: false,\n error: {\n code: \"DIFF_FAILED\",\n message: (error as Error).message.replace(this.repoPath, \"<repo>\"),\n },\n };\n }\n }\n\n /**\n * create-branch action — create a new branch\n */\n @Actions.Exec(\"/:branch\", \"create-branch\")\n async createBranchAction(\n _ctx: RouteContext<{ branch: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ready();\n\n const name = args.name as string;\n const from = args.from as string | undefined;\n\n if (!name) {\n return { success: false, error: { code: \"INVALID_ARGS\", message: \"name is required\" } };\n }\n\n // Validate branch name - reject path traversal\n if (name.includes(\"..\")) {\n return {\n success: false,\n error: { code: \"INVALID_NAME\", message: \"Branch name contains invalid characters\" },\n };\n }\n\n try {\n if (from) {\n await this.git.raw([\"branch\", name, from]);\n } else {\n await this.git.raw([\"branch\", name]);\n }\n\n // Get the hash of the new branch\n const hash = await this.git.revparse([name]).then((h) => h.trim());\n\n return {\n success: true,\n data: { branch: name, hash },\n };\n } catch (error) {\n return {\n success: false,\n error: {\n code: \"CREATE_BRANCH_FAILED\",\n message: (error as Error).message.replace(this.repoPath, \"<repo>\"),\n },\n };\n }\n }\n\n /**\n * commit action — commit staged changes\n */\n @Actions.Exec(\"/:branch\", \"commit\")\n async commitAction(\n _ctx: RouteContext<{ branch: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ready();\n\n const message = args.message as string;\n if (!message) {\n return { success: false, error: { code: \"INVALID_ARGS\", message: \"message is required\" } };\n }\n\n const author = args.author as { name?: string; email?: string } | undefined;\n\n try {\n const git = simpleGit(this.repoPath);\n\n // Check for staged changes\n const status = await git.status();\n if (\n status.staged.length === 0 &&\n status.files.filter((f) => f.index !== \" \" && f.index !== \"?\").length === 0\n ) {\n return {\n success: false,\n error: { code: \"NO_CHANGES\", message: \"No staged changes to commit\" },\n };\n }\n\n // Configure author if provided\n if (author?.name) {\n await git.addConfig(\"user.name\", author.name, undefined, \"local\");\n }\n if (author?.email) {\n await git.addConfig(\"user.email\", author.email, undefined, \"local\");\n }\n\n const result = await git.commit(message);\n\n return {\n success: true,\n data: {\n hash: result.commit || \"\",\n message,\n filesChanged: result.summary.changes,\n },\n };\n } catch (error) {\n return {\n success: false,\n error: {\n code: \"COMMIT_FAILED\",\n message: (error as Error).message.replace(this.repoPath, \"<repo>\"),\n },\n };\n }\n }\n\n /**\n * merge action — merge a branch into current branch\n */\n @Actions.Exec(\"/:branch\", \"merge\")\n async mergeAction(\n _ctx: RouteContext<{ branch: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ready();\n\n const branch = args.branch as string;\n if (!branch) {\n return { success: false, error: { code: \"INVALID_ARGS\", message: \"branch is required\" } };\n }\n\n const customMessage = args.message as string | undefined;\n\n try {\n const git = simpleGit(this.repoPath);\n\n // Verify the branch exists\n const branches = await git.branchLocal();\n if (!branches.all.includes(branch)) {\n return {\n success: false,\n error: { code: \"BRANCH_NOT_FOUND\", message: `Branch '${branch}' not found` },\n };\n }\n\n const mergeArgs = [branch];\n if (customMessage) {\n mergeArgs.push(\"-m\", customMessage);\n }\n\n const result = await git.merge(mergeArgs);\n\n // Get the resulting commit hash\n const hash = await git.revparse([\"HEAD\"]).then((h) => h.trim());\n\n return {\n success: true,\n data: {\n hash,\n merged: branch,\n conflicts: result.conflicts || [],\n },\n };\n } catch (error) {\n // Abort merge if there was a conflict\n try {\n const git = simpleGit(this.repoPath);\n await git.merge([\"--abort\"]);\n } catch {\n // Ignore abort errors\n }\n\n return {\n success: false,\n error: {\n code: \"MERGE_FAILED\",\n message: (error as Error).message.replace(this.repoPath, \"<repo>\"),\n },\n };\n }\n }\n\n // ========== .log/ Virtual Tree ==========\n\n /**\n * List .log/ → commit list with pagination\n */\n @List(\"/:branch/.log\")\n async listLogHandler(ctx: RouteContext<{ branch: string }>): Promise<AFSListResult> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n\n const options = ctx.options as { limit?: number; offset?: number };\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n const offset = options?.offset || 0;\n\n const commits = await this.getCommitList(branch, limit, offset);\n const branchEncoded = this.encodeBranchName(branch);\n\n const entries: AFSEntry[] = commits.map((commit, i) =>\n this.buildEntry(`/${branchEncoded}/.log/${offset + i}`, {\n meta: {\n hash: commit.hash,\n shortHash: commit.shortHash,\n author: commit.author,\n date: commit.date,\n message: commit.message,\n },\n }),\n );\n\n return { data: entries };\n }\n\n /**\n * Read .log/{index} → commit diff/patch content\n */\n @Read(\"/:branch/.log/:index\")\n async readLogEntryHandler(\n ctx: RouteContext<{ branch: string; index: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const index = Number.parseInt(ctx.params.index, 10);\n\n if (Number.isNaN(index) || index < 0) {\n throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${ctx.params.index}`);\n }\n\n const commits = await this.getCommitList(branch, 1, index);\n if (commits.length === 0) {\n throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${index}`);\n }\n\n const commit = commits[0]!;\n\n // Get diff for this commit\n let diff: string;\n try {\n diff = await this.git.raw([\"show\", \"--stat\", \"--patch\", commit.hash]);\n } catch {\n diff = \"\";\n }\n\n const branchEncoded = this.encodeBranchName(branch);\n return this.buildEntry(`/${branchEncoded}/.log/${index}`, {\n content: diff,\n meta: {\n hash: commit.hash,\n shortHash: commit.shortHash,\n author: commit.author,\n date: commit.date,\n message: commit.message,\n },\n });\n }\n\n /**\n * Read .log/{index}/.meta → commit metadata only (no diff)\n */\n @Read(\"/:branch/.log/:index/.meta\")\n async readLogEntryMetaHandler(\n ctx: RouteContext<{ branch: string; index: string }>,\n ): Promise<AFSEntry | undefined> {\n await this.ready();\n\n const branch = this.decodeBranchName(ctx.params.branch);\n await this.ensureBranchExists(branch);\n const index = Number.parseInt(ctx.params.index, 10);\n\n if (Number.isNaN(index) || index < 0) {\n throw new AFSNotFoundError(\n `/${this.encodeBranchName(branch)}/.log/${ctx.params.index}/.meta`,\n );\n }\n\n const commits = await this.getCommitList(branch, 1, index);\n if (commits.length === 0) {\n throw new AFSNotFoundError(`/${this.encodeBranchName(branch)}/.log/${index}/.meta`);\n }\n\n const commit = commits[0]!;\n const branchEncoded = this.encodeBranchName(branch);\n return this.buildEntry(`/${branchEncoded}/.log/${index}/.meta`, {\n meta: {\n hash: commit.hash,\n shortHash: commit.shortHash,\n author: commit.author,\n date: commit.date,\n message: commit.message,\n },\n });\n }\n\n // ========== Private Helper Methods ==========\n\n /**\n * Decode branch name (replace ~ with /)\n */\n private decodeBranchName(encoded: string): string {\n return encoded.replace(/~/g, \"/\");\n }\n\n /**\n * Encode branch name (replace / with ~)\n */\n private encodeBranchName(branch: string): string {\n return branch.replace(/\\//g, \"~\");\n }\n\n /**\n * Parse AFS path into branch and file path\n * Branch names may contain slashes and are encoded with ~ in paths\n */\n private parsePath(path: string): { branch?: string; filePath: string } {\n const normalized = join(\"/\", path); // Ensure leading slash\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (segments.length === 0) {\n return { branch: undefined, filePath: \"\" };\n }\n\n // Decode branch name (first segment): replace ~ with /\n const branch = segments[0]!.replace(/~/g, \"/\");\n const filePath = segments.slice(1).join(\"/\");\n\n return { branch, filePath };\n }\n\n /**\n * Build AFS path with encoded branch name\n * Branch names with slashes are encoded by replacing / with ~\n */\n private buildBranchPath(branch: string, filePath?: string): string {\n const encodedBranch = this.encodeBranchName(branch);\n if (!filePath) {\n return `/${encodedBranch}`;\n }\n return `/${encodedBranch}/${filePath}`;\n }\n\n /**\n * Get list of available branches\n */\n private async getBranches(): Promise<string[]> {\n const branchSummary = await this.git.branchLocal();\n const allBranches = branchSummary.all;\n\n // Filter by allowed branches if specified\n if (this.options.branches && this.options.branches.length > 0) {\n return allBranches.filter((branch) => this.options.branches!.includes(branch));\n }\n\n return allBranches;\n }\n\n /**\n * Check if a branch exists, throw AFSNotFoundError if not\n */\n private async ensureBranchExists(branch: string): Promise<void> {\n const branches = await this.getBranches();\n if (!branches.includes(branch)) {\n throw new AFSNotFoundError(this.buildBranchPath(branch));\n }\n }\n\n /**\n * Get the number of children for a tree (directory) in git\n */\n private async getChildrenCount(branch: string, path: string): Promise<number> {\n try {\n const treeish = path ? `${branch}:${path}` : branch;\n const output = await this.git.raw([\"ls-tree\", treeish]);\n const lines = output.split(\"\\n\").filter((line) => line.trim());\n return lines.length;\n } catch {\n return 0;\n }\n }\n\n /**\n * Get the last commit on a branch\n */\n private async getLastCommit(\n branch: string,\n ): Promise<{ hash: string; shortHash: string; author: string; date: string; message: string }> {\n const output = await this.git.raw([\"log\", \"-1\", \"--format=%H%n%h%n%an%n%aI%n%s\", branch]);\n const lines = output.trim().split(\"\\n\");\n return {\n hash: lines[0] || \"\",\n shortHash: lines[1] || \"\",\n author: lines[2] || \"\",\n date: lines[3] || \"\",\n message: lines[4] || \"\",\n };\n }\n\n /**\n * Count total files in a tree (recursively)\n */\n private async getTreeFileCount(branch: string, path: string): Promise<number> {\n try {\n const treeish = path ? `${branch}:${path}` : branch;\n const output = await this.git.raw([\"ls-tree\", \"-r\", treeish]);\n const lines = output.split(\"\\n\").filter((line) => line.trim());\n return lines.length;\n } catch {\n return 0;\n }\n }\n\n /**\n * Get a list of commits on a branch with limit/offset\n */\n private async getCommitList(\n branch: string,\n limit: number,\n offset: number,\n ): Promise<{ hash: string; shortHash: string; author: string; date: string; message: string }[]> {\n try {\n const args = [\n \"log\",\n `--skip=${offset}`,\n `-${limit}`,\n \"--format=%H%n%h%n%an%n%aI%n%s%n---COMMIT_SEP---\",\n branch,\n ];\n const output = await this.git.raw(args);\n const blocks = output.split(\"---COMMIT_SEP---\").filter((b) => b.trim());\n\n return blocks.map((block) => {\n const lines = block.trim().split(\"\\n\");\n return {\n hash: lines[0] || \"\",\n shortHash: lines[1] || \"\",\n author: lines[2] || \"\",\n date: lines[3] || \"\",\n message: lines[4] || \"\",\n };\n });\n } catch {\n return [];\n }\n }\n\n /**\n * Ensure worktree exists for a branch (lazy creation)\n */\n private async ensureWorktree(branch: string): Promise<string> {\n if (this.worktrees.has(branch)) {\n return this.worktrees.get(branch)!;\n }\n\n // Check if this is the current branch in the main repo\n const currentBranch = await this.git.revparse([\"--abbrev-ref\", \"HEAD\"]);\n if (currentBranch.trim() === branch) {\n // Use the main repo path for the current branch\n this.worktrees.set(branch, this.repoPath);\n return this.repoPath;\n }\n\n const worktreePath = join(this.tempBase, branch);\n\n // Check if worktree directory already exists\n const exists = await stat(worktreePath)\n .then(() => true)\n .catch(() => false);\n\n if (!exists) {\n await mkdir(this.tempBase, { recursive: true });\n await this.git.raw([\"worktree\", \"add\", worktreePath, branch]);\n }\n\n this.worktrees.set(branch, worktreePath);\n return worktreePath;\n }\n\n /**\n * List files using git ls-tree (no worktree needed)\n * Note: list() returns only children, never the path itself (per new semantics)\n */\n private async listWithGitLsTree(\n branch: string,\n path: string,\n options?: { maxDepth?: number; limit?: number },\n ): Promise<AFSListResult> {\n const maxDepth = options?.maxDepth ?? 1;\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n\n const entries: AFSEntry[] = [];\n const targetPath = path || \"\";\n const treeish = targetPath ? `${branch}:${targetPath}` : branch;\n\n try {\n // Check if the path exists and is a directory\n const pathType = await this.git\n .raw([\"cat-file\", \"-t\", treeish])\n .then((t) => t.trim())\n .catch(() => null);\n\n if (pathType === null) {\n // Path doesn't exist\n throw new AFSNotFoundError(this.buildBranchPath(branch, path));\n }\n\n // If it's a file (blob), it has no children\n if (pathType === \"blob\") {\n return { data: [] };\n }\n\n // It's a directory\n // maxDepth: 0 means return no children\n if (maxDepth === 0) {\n return { data: [] };\n }\n\n // List directory contents via BFS\n interface QueueItem {\n path: string;\n depth: number;\n }\n\n const queue: QueueItem[] = [{ path: targetPath, depth: 0 }];\n\n while (queue.length > 0) {\n const item = queue.shift()!;\n const { path: itemPath, depth } = item;\n\n // List directory contents\n const itemTreeish = itemPath ? `${branch}:${itemPath}` : branch;\n const output = await this.git.raw([\"ls-tree\", \"-l\", itemTreeish]);\n\n const lines = output\n .split(\"\\n\")\n .filter((line) => line.trim())\n .slice(0, limit - entries.length);\n\n for (const line of lines) {\n // Format: <mode> <type> <hash> <size (with padding)> <name>\n const match = line.match(/^(\\d+)\\s+(blob|tree)\\s+(\\w+)\\s+(-|\\d+)\\s+(.+)$/);\n if (!match) continue;\n\n const type = match[2]!;\n const sizeStr = match[4]!;\n const name = match[5]!;\n const isDirectory = type === \"tree\";\n const size = sizeStr === \"-\" ? undefined : Number.parseInt(sizeStr, 10);\n\n const fullPath = itemPath ? `${itemPath}/${name}` : name;\n const afsPath = this.buildBranchPath(branch, fullPath);\n\n // For directories, get children count\n const childrenCount = isDirectory\n ? await this.getChildrenCount(branch, fullPath)\n : undefined;\n\n entries.push(\n this.buildEntry(afsPath, {\n meta: { kind: isDirectory ? \"git:directory\" : \"git:file\", size, childrenCount },\n }),\n );\n\n // Add to queue if it's a directory and we haven't reached max depth\n if (isDirectory && depth + 1 < maxDepth) {\n queue.push({ path: fullPath, depth: depth + 1 });\n }\n\n // Check limit\n if (entries.length >= limit) {\n return { data: entries };\n }\n }\n }\n\n return { data: entries };\n } catch (error) {\n // Re-throw AFSNotFoundError as-is\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n throw new Error(`Failed to list: ${(error as Error).message}`);\n }\n }\n\n /**\n * Detect MIME type based on file extension\n */\n private getMimeType(filePath: string): string {\n const ext = filePath.split(\".\").pop()?.toLowerCase();\n const mimeTypes: Record<string, string> = {\n // Images\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n bmp: \"image/bmp\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n ico: \"image/x-icon\",\n // Documents\n pdf: \"application/pdf\",\n txt: \"text/plain\",\n md: \"text/markdown\",\n // Code\n js: \"text/javascript\",\n ts: \"text/typescript\",\n json: \"application/json\",\n html: \"text/html\",\n css: \"text/css\",\n xml: \"text/xml\",\n };\n return mimeTypes[ext || \"\"] || \"application/octet-stream\";\n }\n\n /**\n * Check if file is likely binary based on extension\n */\n private isBinaryFile(filePath: string): boolean {\n const ext = filePath.split(\".\").pop()?.toLowerCase();\n const binaryExtensions = [\n \"png\",\n \"jpg\",\n \"jpeg\",\n \"gif\",\n \"bmp\",\n \"webp\",\n \"ico\",\n \"pdf\",\n \"zip\",\n \"tar\",\n \"gz\",\n \"exe\",\n \"dll\",\n \"so\",\n \"dylib\",\n \"wasm\",\n ];\n return binaryExtensions.includes(ext || \"\");\n }\n\n // ========== Public Git Operations ==========\n\n /**\n * Fetch latest changes from remote\n */\n async fetch(): Promise<void> {\n await this.ready();\n await this.git.fetch();\n }\n\n /**\n * Pull latest changes from remote for current branch\n */\n async pull(): Promise<void> {\n await this.ready();\n await this.git.pull();\n }\n\n /**\n * Push local changes to remote\n */\n async push(branch?: string): Promise<void> {\n await this.ready();\n if (branch) {\n await this.git.push(\"origin\", branch);\n } else {\n await this.git.push();\n }\n }\n\n /**\n * Cleanup all worktrees (useful when unmounting)\n */\n async cleanup(): Promise<void> {\n await this.ready();\n for (const [_branch, worktreePath] of this.worktrees) {\n try {\n await this.git.raw([\"worktree\", \"remove\", worktreePath, \"--force\"]);\n } catch (_error) {\n // Ignore errors during cleanup\n }\n }\n this.worktrees.clear();\n\n // Remove temp directory\n try {\n await rm(this.tempBase, { recursive: true, force: true });\n } catch {\n // Ignore errors\n }\n\n // Cleanup cloned repository if auto-cloned and autoCleanup enabled\n const autoCleanup = this.options.autoCleanup ?? true;\n if (this.isAutoCloned && autoCleanup && this.clonedPath) {\n try {\n await rm(this.clonedPath, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n}\n\nconst _typeCheck: AFSModuleClass<AFSGit, AFSGitOptions> = AFSGit;\n\nexport default AFSGit;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/afs-git",
|
|
3
|
-
"version": "1.11.0-beta.
|
|
3
|
+
"version": "1.11.0-beta.9",
|
|
4
4
|
"description": "AIGNE AFS module for git storage",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"simple-git": "^3.27.0",
|
|
37
|
-
"zod": "^
|
|
38
|
-
"@aigne/afs": "^1.11.0-beta.
|
|
37
|
+
"zod": "^4.0.0",
|
|
38
|
+
"@aigne/afs": "^1.11.0-beta.9"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/bun": "^1.3.6",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"typescript": "5.9.2",
|
|
46
46
|
"@aigne/scripts": "0.0.0",
|
|
47
47
|
"@aigne/typescript-config": "0.0.0",
|
|
48
|
-
"@aigne/afs-testing": "1.11.0-beta.
|
|
48
|
+
"@aigne/afs-testing": "1.11.0-beta.9"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "tsdown",
|