@aigne/afs-github 1.11.0-beta.7 → 1.11.0-beta.8
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/index.d.mts +84 -103
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +34 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Octokit } from "@octokit/rest";
|
|
2
|
-
import { AFSEntry, AFSExecOptions, AFSExecResult, AFSExplainOptions, AFSExplainResult, AFSListOptions, AFSListResult, AFSModule, AFSReadOptions, AFSReadResult, AFSRoot, AFSSearchOptions, AFSSearchResult, AFSStatOptions, AFSStatResult, AFSWorldMappingCapable, ExternalRef, MappingStatus, MutateAction, MutateResult, ProjectionContext } from "@aigne/afs";
|
|
2
|
+
import { AFSEntry, AFSExecOptions, AFSExecResult, AFSExplainOptions, AFSExplainResult, AFSListOptions, AFSListResult, AFSModule, AFSReadOptions, AFSReadResult, AFSRoot, AFSSearchOptions, AFSSearchResult, AFSStatOptions, AFSStatResult, AFSWorldMappingCapable, ExternalRef, MappingStatus, MutateAction, MutateResult, ProjectionContext, ProviderManifest } from "@aigne/afs";
|
|
3
3
|
import { WorldMappingCore } from "@aigne/afs-world-mapping";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
@@ -8,45 +8,32 @@ import { z } from "zod";
|
|
|
8
8
|
* Authentication options
|
|
9
9
|
*/
|
|
10
10
|
declare const authOptionsSchema: z.ZodObject<{
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
token?: string | undefined;
|
|
14
|
-
}, {
|
|
15
|
-
token?: string | undefined;
|
|
16
|
-
}>;
|
|
11
|
+
token: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, z.core.$strip>;
|
|
17
13
|
type AuthOptions = z.infer<typeof authOptionsSchema>;
|
|
18
14
|
/**
|
|
19
15
|
* Cache configuration
|
|
20
16
|
*/
|
|
21
17
|
declare const cacheOptionsSchema: z.ZodObject<{
|
|
22
|
-
|
|
18
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
23
19
|
ttl: z.ZodDefault<z.ZodNumber>;
|
|
24
|
-
},
|
|
25
|
-
enabled: boolean;
|
|
26
|
-
ttl: number;
|
|
27
|
-
}, {
|
|
28
|
-
enabled?: boolean | undefined;
|
|
29
|
-
ttl?: number | undefined;
|
|
30
|
-
}>;
|
|
20
|
+
}, z.core.$strip>;
|
|
31
21
|
type CacheOptions = z.infer<typeof cacheOptionsSchema>;
|
|
32
22
|
/**
|
|
33
23
|
* Rate limiting configuration
|
|
34
24
|
*/
|
|
35
25
|
declare const rateLimitOptionsSchema: z.ZodObject<{
|
|
36
|
-
|
|
26
|
+
autoRetry: z.ZodDefault<z.ZodBoolean>;
|
|
37
27
|
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
38
|
-
},
|
|
39
|
-
autoRetry: boolean;
|
|
40
|
-
maxRetries: number;
|
|
41
|
-
}, {
|
|
42
|
-
autoRetry?: boolean | undefined;
|
|
43
|
-
maxRetries?: number | undefined;
|
|
44
|
-
}>;
|
|
28
|
+
}, z.core.$strip>;
|
|
45
29
|
type RateLimitOptions = z.infer<typeof rateLimitOptionsSchema>;
|
|
46
30
|
/**
|
|
47
31
|
* Access mode for the provider
|
|
48
32
|
*/
|
|
49
|
-
declare const accessModeSchema: z.ZodDefault<z.ZodEnum<
|
|
33
|
+
declare const accessModeSchema: z.ZodDefault<z.ZodEnum<{
|
|
34
|
+
readonly: "readonly";
|
|
35
|
+
readwrite: "readwrite";
|
|
36
|
+
}>>;
|
|
50
37
|
type AccessMode = z.infer<typeof accessModeSchema>;
|
|
51
38
|
/**
|
|
52
39
|
* Repository mode
|
|
@@ -54,7 +41,11 @@ type AccessMode = z.infer<typeof accessModeSchema>;
|
|
|
54
41
|
* - multi-repo: Access multiple repositories with full paths
|
|
55
42
|
* - org: Access all repositories in an organization (requires owner only)
|
|
56
43
|
*/
|
|
57
|
-
declare const repoModeSchema: z.ZodDefault<z.ZodEnum<
|
|
44
|
+
declare const repoModeSchema: z.ZodDefault<z.ZodEnum<{
|
|
45
|
+
"single-repo": "single-repo";
|
|
46
|
+
"multi-repo": "multi-repo";
|
|
47
|
+
org: "org";
|
|
48
|
+
}>>;
|
|
58
49
|
type RepoMode = z.infer<typeof repoModeSchema>;
|
|
59
50
|
/**
|
|
60
51
|
* Owner type for org mode
|
|
@@ -62,94 +53,47 @@ type RepoMode = z.infer<typeof repoModeSchema>;
|
|
|
62
53
|
* - user: GitHub user account (uses /users/{username}/repos endpoint)
|
|
63
54
|
* - undefined: Auto-detect (tries org first, falls back to user)
|
|
64
55
|
*/
|
|
65
|
-
declare const ownerTypeSchema: z.ZodOptional<z.ZodEnum<
|
|
56
|
+
declare const ownerTypeSchema: z.ZodOptional<z.ZodEnum<{
|
|
57
|
+
org: "org";
|
|
58
|
+
user: "user";
|
|
59
|
+
}>>;
|
|
66
60
|
type OwnerType = z.infer<typeof ownerTypeSchema>;
|
|
67
61
|
/**
|
|
68
62
|
* Full options schema for AFSGitHub
|
|
69
63
|
*/
|
|
70
64
|
declare const afsGitHubOptionsSchema: z.ZodObject<{
|
|
71
|
-
|
|
72
|
-
description: z.ZodOptional<z.ZodString>;
|
|
65
|
+
name: z.ZodDefault<z.ZodString>;
|
|
66
|
+
description: z.ZodOptional<z.ZodString>;
|
|
73
67
|
auth: z.ZodOptional<z.ZodObject<{
|
|
74
|
-
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
68
|
+
token: z.ZodOptional<z.ZodString>;
|
|
69
|
+
}, z.core.$strip>>;
|
|
70
|
+
owner: z.ZodOptional<z.ZodString>;
|
|
71
|
+
repo: z.ZodOptional<z.ZodString>;
|
|
72
|
+
accessMode: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
73
|
+
readonly: "readonly";
|
|
74
|
+
readwrite: "readwrite";
|
|
75
|
+
}>>>;
|
|
76
|
+
mode: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
77
|
+
"single-repo": "single-repo";
|
|
78
|
+
"multi-repo": "multi-repo";
|
|
79
|
+
org: "org";
|
|
80
|
+
}>>>;
|
|
81
|
+
ownerType: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
|
|
82
|
+
org: "org";
|
|
83
|
+
user: "user";
|
|
84
|
+
}>>>;
|
|
85
|
+
baseUrl: z.ZodDefault<z.ZodString>;
|
|
86
|
+
mappingPath: z.ZodOptional<z.ZodString>;
|
|
87
87
|
cache: z.ZodOptional<z.ZodObject<{
|
|
88
|
-
|
|
88
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
89
89
|
ttl: z.ZodDefault<z.ZodNumber>;
|
|
90
|
-
},
|
|
91
|
-
enabled: boolean;
|
|
92
|
-
ttl: number;
|
|
93
|
-
}, {
|
|
94
|
-
enabled?: boolean | undefined;
|
|
95
|
-
ttl?: number | undefined;
|
|
96
|
-
}>>; /** Rate limiting configuration */
|
|
90
|
+
}, z.core.$strip>>;
|
|
97
91
|
rateLimit: z.ZodOptional<z.ZodObject<{
|
|
98
|
-
|
|
92
|
+
autoRetry: z.ZodDefault<z.ZodBoolean>;
|
|
99
93
|
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
100
|
-
},
|
|
101
|
-
autoRetry: boolean;
|
|
102
|
-
maxRetries: number;
|
|
103
|
-
}, {
|
|
104
|
-
autoRetry?: boolean | undefined;
|
|
105
|
-
maxRetries?: number | undefined;
|
|
106
|
-
}>>; /** Default branch/ref for Contents API (optional) */
|
|
94
|
+
}, z.core.$strip>>;
|
|
107
95
|
ref: z.ZodOptional<z.ZodString>;
|
|
108
|
-
},
|
|
109
|
-
name: string;
|
|
110
|
-
baseUrl: string;
|
|
111
|
-
description?: string | undefined;
|
|
112
|
-
auth?: {
|
|
113
|
-
token?: string | undefined;
|
|
114
|
-
} | undefined;
|
|
115
|
-
owner?: string | undefined;
|
|
116
|
-
repo?: string | undefined;
|
|
117
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
118
|
-
mode?: "single-repo" | "multi-repo" | "org" | undefined;
|
|
119
|
-
ownerType?: "org" | "user" | undefined;
|
|
120
|
-
mappingPath?: string | undefined;
|
|
121
|
-
cache?: {
|
|
122
|
-
enabled: boolean;
|
|
123
|
-
ttl: number;
|
|
124
|
-
} | undefined;
|
|
125
|
-
rateLimit?: {
|
|
126
|
-
autoRetry: boolean;
|
|
127
|
-
maxRetries: number;
|
|
128
|
-
} | undefined;
|
|
129
|
-
ref?: string | undefined;
|
|
130
|
-
}, {
|
|
131
|
-
name?: string | undefined;
|
|
132
|
-
description?: string | undefined;
|
|
133
|
-
auth?: {
|
|
134
|
-
token?: string | undefined;
|
|
135
|
-
} | undefined;
|
|
136
|
-
owner?: string | undefined;
|
|
137
|
-
repo?: string | undefined;
|
|
138
|
-
accessMode?: "readonly" | "readwrite" | undefined;
|
|
139
|
-
mode?: "single-repo" | "multi-repo" | "org" | undefined;
|
|
140
|
-
ownerType?: "org" | "user" | undefined;
|
|
141
|
-
baseUrl?: string | undefined;
|
|
142
|
-
mappingPath?: string | undefined;
|
|
143
|
-
cache?: {
|
|
144
|
-
enabled?: boolean | undefined;
|
|
145
|
-
ttl?: number | undefined;
|
|
146
|
-
} | undefined;
|
|
147
|
-
rateLimit?: {
|
|
148
|
-
autoRetry?: boolean | undefined;
|
|
149
|
-
maxRetries?: number | undefined;
|
|
150
|
-
} | undefined;
|
|
151
|
-
ref?: string | undefined;
|
|
152
|
-
}>;
|
|
96
|
+
}, z.core.$strip>;
|
|
153
97
|
/**
|
|
154
98
|
* Input options type (what users provide, with optional fields)
|
|
155
99
|
*/
|
|
@@ -319,7 +263,44 @@ declare class AFSGitHub implements AFSModule, AFSWorldMappingCapable {
|
|
|
319
263
|
private mappingError?;
|
|
320
264
|
/** World mapping core for schema-level path resolution and field projection (Level 1) */
|
|
321
265
|
readonly worldCore: WorldMappingCore;
|
|
322
|
-
|
|
266
|
+
static schema(): z.ZodObject<{
|
|
267
|
+
name: z.ZodDefault<z.ZodString>;
|
|
268
|
+
description: z.ZodOptional<z.ZodString>;
|
|
269
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
270
|
+
token: z.ZodOptional<z.ZodString>;
|
|
271
|
+
}, z.core.$strip>>;
|
|
272
|
+
owner: z.ZodOptional<z.ZodString>;
|
|
273
|
+
repo: z.ZodOptional<z.ZodString>;
|
|
274
|
+
accessMode: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
275
|
+
readonly: "readonly";
|
|
276
|
+
readwrite: "readwrite";
|
|
277
|
+
}>>>;
|
|
278
|
+
mode: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
|
|
279
|
+
"single-repo": "single-repo";
|
|
280
|
+
"multi-repo": "multi-repo";
|
|
281
|
+
org: "org";
|
|
282
|
+
}>>>;
|
|
283
|
+
ownerType: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
|
|
284
|
+
org: "org";
|
|
285
|
+
user: "user";
|
|
286
|
+
}>>>;
|
|
287
|
+
baseUrl: z.ZodDefault<z.ZodString>;
|
|
288
|
+
mappingPath: z.ZodOptional<z.ZodString>;
|
|
289
|
+
cache: z.ZodOptional<z.ZodObject<{
|
|
290
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
291
|
+
ttl: z.ZodDefault<z.ZodNumber>;
|
|
292
|
+
}, z.core.$strip>>;
|
|
293
|
+
rateLimit: z.ZodOptional<z.ZodObject<{
|
|
294
|
+
autoRetry: z.ZodDefault<z.ZodBoolean>;
|
|
295
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
296
|
+
}, z.core.$strip>>;
|
|
297
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
298
|
+
}, z.core.$strip>;
|
|
299
|
+
static manifest(): ProviderManifest;
|
|
300
|
+
constructor(options: AFSGitHubOptions & {
|
|
301
|
+
token?: string;
|
|
302
|
+
uri?: string;
|
|
303
|
+
});
|
|
323
304
|
/**
|
|
324
305
|
* Load the default mapping configuration
|
|
325
306
|
*/
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/client.ts","../src/github.ts"],"mappings":";;;;;;;;AASA;cAAa,iBAAA,EAAiB,CAAA,CAAA,SAAA
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/client.ts","../src/github.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -196,7 +196,11 @@ var GitHubClient = class {
|
|
|
196
196
|
/**
|
|
197
197
|
* Authentication options
|
|
198
198
|
*/
|
|
199
|
-
const authOptionsSchema = z.object({ token: z.string().optional()
|
|
199
|
+
const authOptionsSchema = z.object({ token: z.string().optional().meta({
|
|
200
|
+
sensitive: true,
|
|
201
|
+
env: ["GITHUB_TOKEN", "GH_TOKEN"],
|
|
202
|
+
description: "GitHub personal access token"
|
|
203
|
+
}) });
|
|
200
204
|
/**
|
|
201
205
|
* Cache configuration
|
|
202
206
|
*/
|
|
@@ -293,7 +297,36 @@ var AFSGitHub = class {
|
|
|
293
297
|
mappingError;
|
|
294
298
|
/** World mapping core for schema-level path resolution and field projection (Level 1) */
|
|
295
299
|
worldCore;
|
|
300
|
+
static schema() {
|
|
301
|
+
return afsGitHubOptionsSchema;
|
|
302
|
+
}
|
|
303
|
+
static manifest() {
|
|
304
|
+
return {
|
|
305
|
+
name: "github",
|
|
306
|
+
description: "GitHub Issues, Pull Requests, and Actions",
|
|
307
|
+
uriTemplate: "github://{owner}/{repo}",
|
|
308
|
+
category: "integration",
|
|
309
|
+
schema: z.object({
|
|
310
|
+
owner: z.string(),
|
|
311
|
+
repo: z.string(),
|
|
312
|
+
token: z.string().meta({ sensitive: true }).optional()
|
|
313
|
+
}),
|
|
314
|
+
tags: [
|
|
315
|
+
"github",
|
|
316
|
+
"git",
|
|
317
|
+
"integration"
|
|
318
|
+
]
|
|
319
|
+
};
|
|
320
|
+
}
|
|
296
321
|
constructor(options) {
|
|
322
|
+
if (options.token && !options.auth?.token) options.auth = {
|
|
323
|
+
...options.auth || {},
|
|
324
|
+
token: options.token
|
|
325
|
+
};
|
|
326
|
+
if (!options.mode) {
|
|
327
|
+
if (options.owner && options.repo) options.mode = "single-repo";
|
|
328
|
+
else if (options.owner && !options.repo) options.mode = "org";
|
|
329
|
+
}
|
|
297
330
|
const parsed = afsGitHubOptionsSchema.parse(options);
|
|
298
331
|
this.options = {
|
|
299
332
|
name: parsed.name,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["entryPath"],"sources":["../src/client.ts","../src/types.ts","../src/github.ts"],"sourcesContent":["/**\n * GitHub API Client\n *\n * Wraps Octokit with throttling, retry, and caching.\n */\n\nimport { retry } from \"@octokit/plugin-retry\";\nimport { throttling } from \"@octokit/plugin-throttling\";\nimport { Octokit } from \"@octokit/rest\";\nimport type { AuthOptions, CacheOptions, RateLimitOptions } from \"./types.js\";\n\n/**\n * Cache entry\n */\ninterface CacheEntry {\n data: unknown;\n expiresAt: number;\n}\n\n/**\n * GitHub Contents API item\n */\nexport interface ContentsItem {\n name: string;\n path: string;\n type: \"file\" | \"dir\" | \"symlink\" | \"submodule\";\n size: number;\n sha: string;\n download_url: string | null;\n /** Base64 encoded content, only for files <1MB */\n content?: string;\n /** Encoding type, typically \"base64\" when content is present */\n encoding?: string;\n}\n\n/**\n * Response from Contents API - can be single item or array\n */\nexport type ContentsResponse = ContentsItem | ContentsItem[];\n\n/**\n * GitHub Branch item\n */\nexport interface BranchItem {\n name: string;\n commit: {\n sha: string;\n url: string;\n };\n protected: boolean;\n}\n\n/**\n * Options for GitHubClient\n */\nexport interface GitHubClientOptions {\n auth?: AuthOptions;\n baseUrl?: string;\n cache?: CacheOptions;\n rateLimit?: RateLimitOptions;\n}\n\n/**\n * GitHub API client with throttling, retry, and caching\n */\nexport class GitHubClient {\n private octokit: Octokit;\n private cache: Map<string, CacheEntry> = new Map();\n private cacheConfig: CacheOptions;\n\n constructor(options: GitHubClientOptions) {\n this.cacheConfig = {\n enabled: options.cache?.enabled ?? true,\n ttl: options.cache?.ttl ?? 60000,\n };\n\n const maxRetries = options.rateLimit?.maxRetries ?? 3;\n\n // Create Octokit with plugins\n const OctokitWithPlugins = Octokit.plugin(throttling, retry);\n\n this.octokit = new OctokitWithPlugins({\n auth: options.auth?.token,\n baseUrl: options.baseUrl ?? \"https://api.github.com\",\n // Suppress Octokit's built-in request logging (from @octokit/plugin-request-log)\n // We handle errors ourselves with user-friendly messages\n log: {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n },\n throttle: {\n onRateLimit: (retryAfter, _options, _octokit, retryCount) => {\n if (retryCount < maxRetries) {\n console.warn(`Rate limited. Retrying after ${retryAfter} seconds.`);\n return true;\n }\n return false;\n },\n onSecondaryRateLimit: (retryAfter, _options, _octokit, retryCount) => {\n if (retryCount < maxRetries) {\n console.warn(`Secondary rate limit. Retrying after ${retryAfter} seconds.`);\n return true;\n }\n return false;\n },\n },\n retry: {\n enabled: options.rateLimit?.autoRetry ?? true,\n retries: maxRetries,\n },\n });\n }\n\n /**\n * Make a request to the GitHub API\n */\n async request<T = unknown>(\n route: string,\n params?: Record<string, unknown>,\n ): Promise<{ data: T; status: number; headers: Record<string, string> }> {\n // Only cache GET requests\n const isGet = route.startsWith(\"GET \");\n\n if (isGet && this.cacheConfig.enabled) {\n const cacheKey = this.getCacheKey(route, params);\n const cached = this.getFromCache(cacheKey);\n if (cached !== undefined) {\n return cached as { data: T; status: number; headers: Record<string, string> };\n }\n }\n\n const response = await this.octokit.request(route, params);\n\n const result = {\n data: response.data as T,\n status: response.status,\n headers: response.headers as Record<string, string>,\n };\n\n // Cache GET responses\n if (isGet && this.cacheConfig.enabled) {\n const cacheKey = this.getCacheKey(route, params);\n this.setCache(cacheKey, result);\n }\n\n return result;\n }\n\n /**\n * Generate cache key from route and params\n */\n private getCacheKey(route: string, params?: Record<string, unknown>): string {\n return `${route}:${JSON.stringify(params ?? {})}`;\n }\n\n /**\n * Get from cache if not expired\n */\n private getFromCache(key: string): unknown | undefined {\n const entry = this.cache.get(key);\n if (!entry) return undefined;\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return undefined;\n }\n\n return entry.data;\n }\n\n /**\n * Set cache entry\n */\n private setCache(key: string, data: unknown): void {\n this.cache.set(key, {\n data,\n expiresAt: Date.now() + this.cacheConfig.ttl,\n });\n }\n\n /**\n * Clear the cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Get the underlying Octokit instance (for advanced usage)\n */\n getOctokit(): Octokit {\n return this.octokit;\n }\n\n // ============ Contents API Methods ============\n\n /**\n * Get repository contents at a path\n * @param owner Repository owner\n * @param repo Repository name\n * @param path Path within the repository (empty string for root)\n * @param ref Optional branch, tag, or commit SHA\n * @returns Contents item(s) - array for directories, single item for files\n */\n async getContents(\n owner: string,\n repo: string,\n path: string,\n ref?: string,\n ): Promise<ContentsResponse> {\n const params: Record<string, unknown> = {\n owner,\n repo,\n path: path || \"\",\n };\n\n if (ref) {\n params.ref = ref;\n }\n\n const response = await this.request<ContentsResponse>(\n \"GET /repos/{owner}/{repo}/contents/{path}\",\n params,\n );\n\n return response.data;\n }\n\n /**\n * Get blob content for large files (>1MB)\n * @param owner Repository owner\n * @param repo Repository name\n * @param sha Blob SHA\n * @returns Decoded content as string\n */\n async getBlob(owner: string, repo: string, sha: string): Promise<string> {\n const response = await this.request<{ content: string; encoding: string }>(\n \"GET /repos/{owner}/{repo}/git/blobs/{sha}\",\n { owner, repo, sha },\n );\n\n // Blob API always returns base64 encoded content\n return Buffer.from(response.data.content, \"base64\").toString(\"utf-8\");\n }\n\n /**\n * Get repository branches\n * @param owner Repository owner\n * @param repo Repository name\n * @returns Array of branch items\n */\n async getBranches(owner: string, repo: string): Promise<BranchItem[]> {\n const allBranches: BranchItem[] = [];\n let page = 1;\n const perPage = 100;\n\n while (true) {\n const response = await this.request<BranchItem[]>(\"GET /repos/{owner}/{repo}/branches\", {\n owner,\n repo,\n per_page: perPage,\n page,\n });\n\n allBranches.push(...response.data);\n\n if (response.data.length < perPage) {\n break;\n }\n page++;\n }\n\n return allBranches;\n }\n\n /**\n * Get default branch for a repository\n * @param owner Repository owner\n * @param repo Repository name\n * @returns Default branch name\n */\n async getDefaultBranch(owner: string, repo: string): Promise<string> {\n const response = await this.request<{ default_branch: string }>(\"GET /repos/{owner}/{repo}\", {\n owner,\n repo,\n });\n\n return response.data.default_branch;\n }\n}\n","/**\n * Type definitions for AFSGitHub provider\n */\n\nimport { z } from \"zod\";\n\n/**\n * Authentication options\n */\nexport const authOptionsSchema = z.object({\n /** Personal Access Token */\n token: z.string().optional(),\n});\n\nexport type AuthOptions = z.infer<typeof authOptionsSchema>;\n\n/**\n * Cache configuration\n */\nexport const cacheOptionsSchema = z.object({\n /** Enable caching */\n enabled: z.boolean().default(true),\n /** Cache TTL in milliseconds */\n ttl: z.number().default(60000),\n});\n\nexport type CacheOptions = z.infer<typeof cacheOptionsSchema>;\n\n/**\n * Rate limiting configuration\n */\nexport const rateLimitOptionsSchema = z.object({\n /** Enable automatic retry on rate limit */\n autoRetry: z.boolean().default(true),\n /** Maximum retry attempts */\n maxRetries: z.number().default(3),\n});\n\nexport type RateLimitOptions = z.infer<typeof rateLimitOptionsSchema>;\n\n/**\n * Access mode for the provider\n */\nexport const accessModeSchema = z.enum([\"readonly\", \"readwrite\"]).default(\"readonly\");\n\nexport type AccessMode = z.infer<typeof accessModeSchema>;\n\n/**\n * Repository mode\n * - single-repo: Access a single repository (requires owner and repo)\n * - multi-repo: Access multiple repositories with full paths\n * - org: Access all repositories in an organization (requires owner only)\n */\nexport const repoModeSchema = z.enum([\"single-repo\", \"multi-repo\", \"org\"]).default(\"single-repo\");\n\nexport type RepoMode = z.infer<typeof repoModeSchema>;\n\n/**\n * Owner type for org mode\n * - org: GitHub organization (uses /orgs/{org}/repos endpoint)\n * - user: GitHub user account (uses /users/{username}/repos endpoint)\n * - undefined: Auto-detect (tries org first, falls back to user)\n */\nexport const ownerTypeSchema = z.enum([\"org\", \"user\"]).optional();\n\nexport type OwnerType = z.infer<typeof ownerTypeSchema>;\n\n/**\n * Full options schema for AFSGitHub\n */\nexport const afsGitHubOptionsSchema = z.object({\n /** Module name */\n name: z.string().default(\"github\"),\n\n /** Module description */\n description: z.string().optional(),\n\n /** Authentication */\n auth: authOptionsSchema.optional(),\n\n /** Repository owner (required for single-repo mode) */\n owner: z.string().optional(),\n\n /** Repository name (required for single-repo mode) */\n repo: z.string().optional(),\n\n /** Access mode */\n accessMode: accessModeSchema.optional(),\n\n /** Repository mode */\n mode: repoModeSchema.optional(),\n\n /** Owner type (org or user). If not set, auto-detects by trying org first. */\n ownerType: ownerTypeSchema.optional(),\n\n /** GitHub API base URL (for Enterprise) */\n baseUrl: z.string().default(\"https://api.github.com\"),\n\n /** Custom mapping path (overrides default) */\n mappingPath: z.string().optional(),\n\n /** Cache configuration */\n cache: cacheOptionsSchema.optional(),\n\n /** Rate limiting configuration */\n rateLimit: rateLimitOptionsSchema.optional(),\n\n /** Default branch/ref for Contents API (optional) */\n ref: z.string().optional(),\n});\n\n/**\n * Input options type (what users provide, with optional fields)\n */\nexport type AFSGitHubOptions = z.input<typeof afsGitHubOptionsSchema>;\n\n/**\n * Output options type (after Zod parsing, with defaults applied)\n */\nexport type AFSGitHubOptionsParsed = z.infer<typeof afsGitHubOptionsSchema>;\n\n/**\n * Validated options with defaults applied\n */\nexport interface AFSGitHubOptionsResolved {\n name: string;\n description?: string;\n auth?: AuthOptions;\n owner?: string;\n repo?: string;\n accessMode: AccessMode;\n mode: RepoMode;\n ownerType?: OwnerType;\n baseUrl: string;\n mappingPath?: string;\n cache: CacheOptions;\n rateLimit: RateLimitOptions;\n ref?: string;\n}\n","/**\n * AFSGitHub Provider\n *\n * AFS module for accessing GitHub Issues, PRs, and Actions.\n * Implements AFSModule and AFSWorldMappingCapable interfaces.\n */\n\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n type AFSEntry,\n type AFSExecOptions,\n type AFSExecResult,\n type AFSExplainOptions,\n type AFSExplainResult,\n type AFSListOptions,\n type AFSListResult,\n type AFSModule,\n AFSNotFoundError,\n type AFSReadOptions,\n AFSReadonlyError,\n type AFSReadResult,\n type AFSRoot,\n type AFSSearchOptions,\n type AFSSearchResult,\n type AFSStatOptions,\n type AFSStatResult,\n type AFSWorldMappingCapable,\n type CapabilitiesManifest,\n type ExternalRef,\n type MappingStatus,\n type MutateAction,\n type MutateResult,\n type OperationsDeclaration,\n type ProjectionContext,\n} from \"@aigne/afs\";\nimport { type CompiledMapping, MappingCompiler, type RouteDefinition } from \"@aigne/afs-mapping\";\nimport { type WorldBinding, WorldMappingCore } from \"@aigne/afs-world-mapping\";\nimport { GitHubClient } from \"./client.js\";\nimport {\n type AFSGitHubOptions,\n type AFSGitHubOptionsResolved,\n afsGitHubOptionsSchema,\n} from \"./types.js\";\n\n// Get the directory of this module for default mapping\nconst __dirname = fileURLToPath(new URL(\".\", import.meta.url));\nconst DEFAULT_MAPPING_PATH = join(__dirname, \"default-mapping\");\n\n/**\n * AFSGitHub Provider\n *\n * Provides access to GitHub Issues, Pull Requests, and Actions through AFS.\n *\n * @example\n * ```typescript\n * const github = new AFSGitHub({\n * auth: { token: process.env.GITHUB_TOKEN },\n * owner: \"aigne\",\n * repo: \"afs\",\n * });\n *\n * // Mount to AFS\n * afs.mount(\"/github\", github);\n *\n * // List issues\n * const issues = await afs.list(\"/github/issues\");\n * ```\n */\nexport class AFSGitHub implements AFSModule, AFSWorldMappingCapable {\n readonly name: string;\n readonly description?: string;\n readonly accessMode: \"readonly\" | \"readwrite\";\n\n private options: AFSGitHubOptionsResolved;\n private client: GitHubClient;\n private compiled: CompiledMapping | null = null;\n private mappingPath: string | null = null;\n private mappingLoadedAt?: Date;\n private mappingError?: string;\n\n /** World mapping core for schema-level path resolution and field projection (Level 1) */\n readonly worldCore: WorldMappingCore;\n\n constructor(options: AFSGitHubOptions) {\n // Validate and apply defaults\n const parsed = afsGitHubOptionsSchema.parse(options);\n\n this.options = {\n name: parsed.name,\n description: parsed.description,\n auth: parsed.auth,\n owner: parsed.owner,\n repo: parsed.repo,\n accessMode: parsed.accessMode ?? \"readonly\",\n mode: parsed.mode ?? \"single-repo\",\n ownerType: parsed.ownerType,\n baseUrl: parsed.baseUrl,\n mappingPath: parsed.mappingPath,\n cache: {\n enabled: parsed.cache?.enabled ?? true,\n ttl: parsed.cache?.ttl ?? 60000,\n },\n rateLimit: {\n autoRetry: parsed.rateLimit?.autoRetry ?? true,\n maxRetries: parsed.rateLimit?.maxRetries ?? 3,\n },\n ref: parsed.ref,\n };\n\n this.name = this.options.name;\n this.description = this.options.description;\n this.accessMode = this.options.accessMode;\n\n // Validate mode requirements\n if (this.options.mode === \"single-repo\") {\n if (!this.options.owner || !this.options.repo) {\n throw new Error(\"owner and repo are required in single-repo mode\");\n }\n } else if (this.options.mode === \"org\") {\n if (!this.options.owner) {\n throw new Error(\"owner is required in org mode\");\n }\n // Trim whitespace from owner\n this.options.owner = this.options.owner.trim();\n }\n\n // Create GitHub client\n this.client = new GitHubClient({\n auth: this.options.auth,\n baseUrl: this.options.baseUrl,\n cache: this.options.cache,\n rateLimit: this.options.rateLimit,\n });\n\n // Initialize world mapping core (Level 1: Library usage)\n this.worldCore = new WorldMappingCore(\n this.getDefaultWorldSchema(),\n this.getDefaultWorldBinding(),\n );\n\n // Load default mapping synchronously\n this.loadDefaultMapping();\n }\n\n /**\n * Load the default mapping configuration\n */\n private loadDefaultMapping(): void {\n try {\n const compiler = new MappingCompiler();\n // Use synchronous file reading for constructor\n // In practice, we compile from the directory\n const mappingPath = this.options.mappingPath ?? DEFAULT_MAPPING_PATH;\n this.mappingPath = mappingPath;\n\n // Load synchronously by reading files directly\n // This is a simplified version - in production, we'd use async\n this.compiled = compiler.compileConfig({\n name: \"github\",\n version: \"1.0\",\n defaults: {\n baseUrl: this.options.baseUrl,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n },\n },\n routes: this.getDefaultRoutes(),\n });\n\n this.mappingLoadedAt = new Date();\n this.mappingError = undefined;\n } catch (error) {\n this.mappingError = error instanceof Error ? error.message : String(error);\n }\n }\n\n /**\n * Get default route definitions\n * This is used when loading mapping synchronously\n */\n private getDefaultRoutes(): Record<string, RouteDefinition> {\n return {\n \"/{owner}/{repo}/issues\": {\n list: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/issues\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n state: 'query.state | default(\"open\")',\n per_page: \"query.limit | default(30)\",\n },\n transform: {\n items: \"$\",\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/issues/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n meta: {\n kind: \"github:issue\",\n type: \"issue\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/issues/{number}\": {\n read: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/issues/{number}\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n number: \"path.number\",\n },\n transform: {\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/issues/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n meta: {\n type: \"issue\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/pulls\": {\n list: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/pulls\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n state: 'query.state | default(\"open\")',\n per_page: \"query.limit | default(30)\",\n },\n transform: {\n items: \"$\",\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/pulls/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n meta: {\n kind: \"github:pull-request\",\n type: \"pull_request\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/pulls/{number}\": {\n read: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/pulls/{number}\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n number: \"path.number\",\n },\n transform: {\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/pulls/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n meta: {\n type: \"pull_request\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n };\n }\n\n /**\n * Get default world schema for GitHub\n * Defines Issue, PullRequest, Comment as world kinds\n */\n private getDefaultWorldSchema(): any {\n return {\n world: \"github\",\n version: \"1.0\",\n kinds: {\n Issue: {\n key: \"number\",\n path: \"/{owner}/{repo}/issues/{number}\",\n fields: {\n number: \"int\",\n title: \"string\",\n body: \"text\",\n state: \"string\",\n author: \"string\",\n labels: \"string\",\n assignees: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n comments_count: \"int\",\n },\n },\n PullRequest: {\n key: \"number\",\n path: \"/{owner}/{repo}/pulls/{number}\",\n fields: {\n number: \"int\",\n title: \"string\",\n body: \"text\",\n state: \"string\",\n author: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n },\n },\n Comment: {\n key: \"id\",\n path: \"/{owner}/{repo}/issues/{number}/comments/{id}\",\n fields: {\n id: \"int\",\n body: \"text\",\n author: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n },\n },\n },\n };\n }\n\n /**\n * Get default world binding for GitHub\n * Maps world fields to GitHub API response fields\n */\n private getDefaultWorldBinding(): WorldBinding {\n return {\n source: \"/github\",\n mappings: {\n Issue: {\n path: \"/{owner}/{repo}/issues/{number}\",\n fieldMap: {\n author: \"user_login\",\n comments_count: \"comments\",\n },\n },\n PullRequest: {\n path: \"/{owner}/{repo}/pulls/{number}\",\n fieldMap: {\n author: \"user_login\",\n },\n },\n Comment: {\n path: \"/{owner}/{repo}/issues/{number}/comments/{id}\",\n fieldMap: {\n author: \"user_login\",\n },\n },\n },\n };\n }\n\n // ============ AFSModule Methods ============\n\n onMount?(_root: AFSRoot): void {\n // Optional: Initialize resources when mounted\n }\n\n /**\n * Resolve a path based on mode\n * - single-repo: prepend owner/repo\n * - org: prepend owner (org name)\n * - multi-repo: pass through\n */\n resolvePath(path: string): string {\n // First, try to decode URL-encoded characters\n let decodedPath: string;\n try {\n decodedPath = decodeURIComponent(path);\n } catch {\n decodedPath = path;\n }\n\n // Normalize: split by slashes, filter empty and traversal segments, rejoin\n const segments = decodedPath\n .split(\"/\")\n .filter((segment) => segment !== \"\" && segment !== \".\" && segment !== \"..\");\n\n const cleanPath = segments.join(\"/\");\n\n if (this.options.mode === \"single-repo\" && this.options.owner && this.options.repo) {\n // Prepend owner/repo to path\n if (!cleanPath) {\n return `/${this.options.owner}/${this.options.repo}`;\n }\n return `/${this.options.owner}/${this.options.repo}/${cleanPath}`;\n }\n\n if (this.options.mode === \"org\" && this.options.owner) {\n // For org mode:\n // - \"/\" or \"\" -> \"/\" (org root, will list repos)\n // - \"/repo\" -> \"/owner/repo\" (repo root)\n // - \"/repo/issues\" -> \"/owner/repo/issues\"\n if (!cleanPath) {\n return \"/\";\n }\n return `/${this.options.owner}/${cleanPath}`;\n }\n\n // multi-repo mode: pass through (with normalization)\n return cleanPath ? `/${cleanPath}` : \"/\";\n }\n\n /**\n * Get virtual directory structure for root path\n * Returns the available resource types (issues, pulls, repo)\n */\n private getVirtualDirectories(): AFSEntry[] {\n return [\n {\n id: \"issues\",\n path: \"/issues\",\n summary: \"Repository Issues\",\n meta: {\n kind: \"github:directory\",\n childrenCount: -1, // Dynamic, unknown until fetched\n description: \"List and read repository issues\",\n },\n },\n {\n id: \"pulls\",\n path: \"/pulls\",\n summary: \"Pull Requests\",\n meta: {\n kind: \"github:directory\",\n childrenCount: -1,\n description: \"List and read pull requests\",\n },\n },\n {\n id: \"repo\",\n path: \"/repo\",\n summary: \"Repository Code\",\n meta: {\n kind: \"github:directory\",\n childrenCount: -1,\n description: \"Repository source code (via Contents API)\",\n },\n },\n ];\n }\n\n /**\n * Check if path points to a file (leaf node) like /issues/{n} or /pulls/{n}\n * These are individual issues/PRs that don't have children.\n */\n private isFilePath(path: string): boolean {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /issues/{number} or /pulls/{number}\n if (segments.length === 2 && (segments[0] === \"issues\" || segments[0] === \"pulls\")) {\n return /^\\d+$/.test(segments[1]!);\n }\n } else if (this.options.mode === \"org\") {\n // /{repo}/issues/{number} or /{repo}/pulls/{number}\n if (segments.length === 3 && (segments[1] === \"issues\" || segments[1] === \"pulls\")) {\n return /^\\d+$/.test(segments[2]!);\n }\n }\n\n return false;\n }\n\n /**\n * Check if path is root or empty\n */\n private isRootPath(path: string): boolean {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n return normalized === \"\";\n }\n\n /**\n * Get root entry (the mount point itself)\n */\n private getRootEntry(): AFSEntry {\n let summary: string;\n let childrenCount: number | undefined;\n\n if (this.options.mode === \"org\") {\n summary = this.description ?? `GitHub Organization: ${this.options.owner}`;\n childrenCount = -1; // Unknown until repos are fetched\n } else if (this.options.mode === \"single-repo\") {\n summary = this.description ?? `GitHub: ${this.options.owner}/${this.options.repo}`;\n childrenCount = 3; // issues, pulls, repo\n } else {\n summary = this.description ?? \"GitHub\";\n childrenCount = undefined;\n }\n\n return {\n id: this.name,\n path: \"/\",\n summary,\n meta: {\n childrenCount,\n description: summary,\n },\n };\n }\n\n /**\n * Get virtual directories for a repo (issues, pulls, repo)\n */\n private getRepoVirtualDirectories(repoPath: string): AFSEntry[] {\n return [\n {\n id: `${repoPath}/issues`,\n path: `${repoPath}/issues`,\n summary: \"Repository Issues\",\n meta: {\n childrenCount: -1,\n description: \"List and read repository issues\",\n },\n },\n {\n id: `${repoPath}/pulls`,\n path: `${repoPath}/pulls`,\n summary: \"Pull Requests\",\n meta: {\n childrenCount: -1,\n description: \"List and read pull requests\",\n },\n },\n {\n id: `${repoPath}/repo`,\n path: `${repoPath}/repo`,\n summary: \"Repository Code\",\n meta: {\n childrenCount: -1,\n description: \"Repository source code (via Contents API)\",\n },\n },\n ];\n }\n\n /**\n * Check if a path represents a repo root in org mode\n * e.g., \"/reponame\" without /issues or /pulls suffix\n */\n private isRepoRootPath(path: string): boolean {\n const segments = path\n .replace(/^\\/+|\\/+$/g, \"\")\n .split(\"/\")\n .filter(Boolean);\n return segments.length === 1;\n }\n\n /**\n * Format a user-friendly error message based on the error type\n */\n private formatErrorMessage(error: unknown, context: string): string {\n const status = (error as { status?: number })?.status;\n const message = error instanceof Error ? error.message : String(error);\n\n // Sanitize any tokens from the message\n const sanitized = message.replace(/ghp_[a-zA-Z0-9]+/g, \"[REDACTED]\");\n\n if (status === 401 || message.includes(\"Bad credentials\")) {\n if (!this.options.auth?.token) {\n return `GitHub authentication required for ${context}. Set GITHUB_TOKEN environment variable or provide auth.token in config.`;\n }\n return `GitHub token is invalid or expired. Please check your GITHUB_TOKEN and ensure it has the required permissions.`;\n }\n\n if (status === 403) {\n if (message.includes(\"rate limit\")) {\n return `GitHub API rate limit exceeded. ${this.options.auth?.token ? \"Your token may have hit its limit.\" : \"Set GITHUB_TOKEN for higher rate limits (5000/hour vs 60/hour).\"} Try again later.`;\n }\n return `GitHub access forbidden for ${context}. Check that your token has the required permissions (repo scope for private repos).`;\n }\n\n if (status === 404) {\n return `GitHub ${context} not found. Check that the organization/user name is correct and accessible.`;\n }\n\n if (message.includes(\"ENOTFOUND\") || message.toLowerCase().includes(\"network\")) {\n return `Network error connecting to GitHub. Check your internet connection.`;\n }\n\n return `GitHub API error: ${sanitized}`;\n }\n\n // ============ Contents API Methods ============\n\n /**\n * Check if a path is a repo path (should be routed to Contents API)\n * - Single-repo mode: /repo or /repo/*\n * - Org mode: /{repoName}/repo or /{repoName}/repo/*\n */\n private isRepoPath(path: string): boolean {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /repo or /repo/*\n return segments[0] === \"repo\";\n }\n\n if (this.options.mode === \"org\") {\n // /{repoName}/repo or /{repoName}/repo/*\n return segments.length >= 2 && segments[1] === \"repo\";\n }\n\n return false;\n }\n\n /**\n * Parse a repo path into owner, repo name, branch, and file path\n * Structure: /repo/{branch}/{filePath}\n * - Single-repo mode: /repo/main/src/index.ts -> { owner, repo, branch: \"main\", filePath: \"src/index.ts\" }\n * - Org mode: /afs/repo/main/src/index.ts -> { owner, repo: \"afs\", branch: \"main\", filePath: \"src/index.ts\" }\n */\n private parseRepoPath(path: string): {\n owner: string;\n repo: string;\n branch?: string;\n filePath: string;\n } {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /repo -> list branches\n // /repo/{branch} -> list branch root\n // /repo/{branch}/... -> access files\n const branch = segments[1]; // undefined if just /repo\n const filePath = segments.slice(2).join(\"/\");\n return {\n owner: this.options.owner!,\n repo: this.options.repo!,\n branch,\n filePath,\n };\n }\n\n if (this.options.mode === \"org\") {\n // /{repoName}/repo -> list branches\n // /{repoName}/repo/{branch} -> list branch root\n // /{repoName}/repo/{branch}/... -> access files\n const repoName = segments[0]!;\n const branch = segments[2]; // undefined if just /{repoName}/repo\n const filePath = segments.slice(3).join(\"/\");\n return {\n owner: this.options.owner!,\n repo: repoName,\n branch,\n filePath,\n };\n }\n\n // multi-repo mode - shouldn't normally reach here\n return {\n owner: this.options.owner!,\n repo: this.options.repo!,\n branch: undefined,\n filePath: \"\",\n };\n }\n\n /**\n * Build the path prefix for a repo entry\n */\n private getRepoPathPrefix(repo: string): string {\n return this.options.mode === \"single-repo\" ? \"/repo\" : `/${repo}/repo`;\n }\n\n /**\n * List repository contents via GitHub Contents API\n * - /repo -> list all branches\n * - /repo/{branch} -> list branch root\n * - /repo/{branch}/path -> list contents at path\n *\n * @throws AFSNotFoundError if path does not exist\n */\n private async listViaContentsAPI(\n path: string,\n _options?: AFSListOptions,\n ): Promise<AFSListResult> {\n const { owner, repo, branch, filePath } = this.parseRepoPath(path);\n const repoPrefix = this.getRepoPathPrefix(repo);\n\n // Case 1: No branch specified - list all branches\n if (!branch) {\n try {\n const branches = await this.client.getBranches(owner, repo);\n const defaultBranch = await this.client.getDefaultBranch(owner, repo);\n\n const entries: AFSEntry[] = branches.map((b) => ({\n id: `${repoPrefix}/${b.name}`,\n path: `${repoPrefix}/${b.name}`,\n summary: b.name + (b.name === defaultBranch ? \" (default)\" : \"\"),\n meta: {\n kind: \"github:branch\",\n type: \"branch\",\n sha: b.commit.sha,\n protected: b.protected,\n isDefault: b.name === defaultBranch,\n childrenCount: -1,\n },\n }));\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n // Case 2 & 3: Branch specified - list contents (root or path)\n try {\n const contents = await this.client.getContents(owner, repo, filePath, branch);\n\n // Handle single file response - files have no children to list\n if (!Array.isArray(contents)) {\n if (contents.type === \"file\") {\n return { data: [] };\n }\n // For directory type, shouldn't normally happen, but handle gracefully\n const entryPath = filePath\n ? `${repoPrefix}/${branch}/${contents.path}`\n : `${repoPrefix}/${branch}/${contents.name}`;\n return {\n data: [\n {\n id: entryPath,\n path: entryPath,\n summary: contents.name,\n meta: {\n kind: contents.type === \"dir\" ? \"github:directory\" : \"github:file\",\n type: contents.type,\n size: contents.size,\n sha: contents.sha,\n },\n },\n ],\n };\n }\n\n const entries: AFSEntry[] = contents.map((item) => {\n const entryPath = filePath\n ? `${repoPrefix}/${branch}/${filePath}/${item.name}`\n : `${repoPrefix}/${branch}/${item.name}`;\n return {\n id: entryPath,\n path: entryPath,\n summary: item.name,\n meta: {\n kind: item.type === \"dir\" ? \"github:directory\" : \"github:file\",\n type: item.type,\n size: item.size,\n sha: item.sha,\n },\n };\n });\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path, `Path not found: ${branch}/${filePath || \"\"}`);\n }\n throw error;\n }\n }\n\n /**\n * Read via GitHub Contents API\n * Supports:\n * - /repo - return repo virtual directory\n * - /repo/{branch} - return branch directory entry\n * - /repo/{branch}/{path} - return file/directory entry\n *\n * @throws AFSNotFoundError if path does not exist\n */\n private async readViaContentsAPI(\n path: string,\n _options?: AFSReadOptions,\n ): Promise<AFSReadResult> {\n const { owner, repo, branch, filePath } = this.parseRepoPath(path);\n const repoPrefix = this.getRepoPathPrefix(repo);\n\n // /repo - return the repo virtual directory\n if (!branch) {\n return {\n data: {\n id: `${repoPrefix}`,\n path: repoPrefix,\n summary: \"Repository Code\",\n meta: {\n description: \"Repository source code (via Contents API)\",\n },\n },\n };\n }\n\n // /repo/{branch} - return branch directory entry\n if (!filePath) {\n try {\n const branches = await this.client.getBranches(owner, repo);\n const defaultBranch = await this.client.getDefaultBranch(owner, repo);\n const branchInfo = branches.find((b) => b.name === branch);\n\n if (!branchInfo) {\n throw new AFSNotFoundError(path, `Branch not found: ${branch}`);\n }\n\n // Fetch branch root contents to get childrenCount\n let childrenCount: number | undefined;\n try {\n const contents = await this.client.getContents(owner, repo, \"\", branch);\n if (Array.isArray(contents)) {\n childrenCount = contents.length;\n }\n } catch {\n // If contents fetch fails, leave childrenCount undefined\n }\n\n const entryPath = `${repoPrefix}/${branch}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: branch + (branch === defaultBranch ? \" (default)\" : \"\"),\n meta: {\n type: \"branch\",\n sha: branchInfo.commit.sha,\n protected: branchInfo.protected,\n isDefault: branch === defaultBranch,\n childrenCount,\n },\n },\n };\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n // /repo/{branch}/{path} - return file/directory entry\n try {\n const contents = await this.client.getContents(owner, repo, filePath, branch);\n\n // Handle directory response - return directory entry\n if (Array.isArray(contents)) {\n const entryPath = `${repoPrefix}/${branch}/${filePath}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: filePath.split(\"/\").pop() || filePath,\n meta: {\n type: \"dir\",\n childrenCount: contents.length,\n branch,\n },\n },\n };\n }\n\n // Handle directory type\n if (contents.type === \"dir\") {\n const entryPath = `${repoPrefix}/${branch}/${filePath}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: contents.name,\n meta: {\n type: \"dir\",\n sha: contents.sha,\n branch,\n },\n },\n };\n }\n\n // Handle file\n if (contents.type !== \"file\") {\n throw new AFSNotFoundError(path, `Unsupported type: ${contents.type}`);\n }\n\n // Get file content\n let content: string;\n if (contents.content) {\n content = Buffer.from(contents.content, \"base64\").toString(\"utf-8\");\n } else {\n content = await this.client.getBlob(owner, repo, contents.sha);\n }\n\n const entryPath = `${repoPrefix}/${branch}/${filePath}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: contents.name,\n content,\n meta: {\n type: \"file\",\n size: contents.size,\n sha: contents.sha,\n branch,\n },\n },\n };\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path, `Path not found: ${branch}/${filePath}`);\n }\n throw error;\n }\n }\n\n /**\n * List organization or user repositories\n * Uses ownerType if specified, otherwise tries org endpoint first and falls back to user\n */\n private async listOrgRepos(includePrivate: boolean): Promise<AFSListResult> {\n const owner = this.options.owner!;\n const ownerType = this.options.ownerType;\n let allRepos: Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }> = [];\n\n // If ownerType is explicitly set, use it directly without fallback\n if (ownerType) {\n try {\n allRepos = await this.fetchAllRepos(ownerType, owner, includePrivate);\n } catch (error) {\n const context = ownerType === \"org\" ? `organization \"${owner}\"` : `user \"${owner}\"`;\n return { data: [], message: this.formatErrorMessage(error, context) };\n }\n } else {\n // Auto-detect: try org first, fall back to user\n try {\n allRepos = await this.fetchAllRepos(\"org\", owner, includePrivate);\n } catch (error) {\n // If 404, try user endpoint (could be a user account, not an org)\n const is404 =\n (error instanceof Error && error.message.includes(\"404\")) ||\n (error as { status?: number })?.status === 404;\n if (is404) {\n try {\n allRepos = await this.fetchAllRepos(\"user\", owner, includePrivate);\n } catch (userError) {\n // Both org and user endpoints failed\n const status = (userError as { status?: number })?.status;\n if (status === 404) {\n return {\n data: [],\n message: `GitHub organization or user \"${owner}\" not found. Check that the name is correct.`,\n };\n }\n return { data: [], message: this.formatErrorMessage(userError, `user \"${owner}\"`) };\n }\n } else {\n return { data: [], message: this.formatErrorMessage(error, `organization \"${owner}\"`) };\n }\n }\n }\n\n // Filter out private repos if no auth token\n const filteredRepos = this.options.auth?.token ? allRepos : allRepos.filter((r) => !r.private);\n\n const entries: AFSEntry[] = filteredRepos.map((repo) => ({\n id: repo.name,\n path: `/${repo.name}`,\n summary: repo.description || repo.name,\n meta: {\n childrenCount: 3, // issues, pulls, repo\n description: repo.description,\n private: repo.private,\n },\n }));\n\n return { data: entries };\n }\n\n /**\n * Fetch all repos with pagination support\n */\n private async fetchAllRepos(\n type: \"org\" | \"user\",\n owner: string,\n includePrivate: boolean,\n ): Promise<\n Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }>\n > {\n const allRepos: Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }> = [];\n\n let page = 1;\n const perPage = 100;\n\n while (true) {\n let response: { data: unknown; status: number; headers: Record<string, string> };\n if (type === \"org\") {\n response = await this.client.request(\"GET /orgs/{org}/repos\", {\n org: owner,\n per_page: perPage,\n page,\n type: includePrivate ? \"all\" : \"public\",\n });\n } else {\n response = await this.client.request(\"GET /users/{username}/repos\", {\n username: owner,\n per_page: perPage,\n page,\n type: includePrivate ? \"all\" : \"public\",\n });\n }\n\n const repos = response.data as Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }>;\n\n allRepos.push(...repos);\n\n // If we got fewer than perPage, we've reached the end\n if (repos.length < perPage) {\n break;\n }\n page++;\n }\n\n return allRepos;\n }\n\n /**\n * Apply limit to entries array\n */\n private applyLimit(entries: AFSEntry[], limit?: number): AFSEntry[] {\n if (limit !== undefined && limit > 0 && entries.length > limit) {\n return entries.slice(0, limit);\n }\n return entries;\n }\n\n /**\n * List immediate children at a path (maxDepth=1 only)\n */\n private async listImmediate(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n // Handle .actions paths\n const actionsResult = this.listActions(path);\n if (actionsResult) {\n return actionsResult;\n }\n\n // Check if path is a file (issue/PR) - return empty array for list on file paths\n if (this.isFilePath(path)) {\n return { data: [] };\n }\n\n // Route /repo paths to Contents API\n if (this.isRepoPath(path)) {\n return this.listViaContentsAPI(path, options);\n }\n\n // Handle root path\n if (this.isRootPath(path)) {\n // For org mode, list repositories\n if (this.options.mode === \"org\") {\n return this.listOrgRepos(!!this.options.auth?.token);\n }\n\n // For single-repo mode, return virtual directories (issues, pulls)\n return { data: this.getVirtualDirectories() };\n }\n\n // In org mode, check if this is a repo root (e.g., \"/afs\")\n if (this.options.mode === \"org\" && this.isRepoRootPath(path)) {\n const repoName = path.replace(/^\\/+|\\/+$/g, \"\");\n // Return virtual directories for this repo\n return { data: this.getRepoVirtualDirectories(`/${repoName}`) };\n }\n\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) {\n throw new AFSNotFoundError(path, \"Mapping not loaded\");\n }\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved || !resolved.operations.list) {\n throw new AFSNotFoundError(path, `No list operation for path: ${fullPath}`);\n }\n\n const request = this.compiled.buildRequest(fullPath, \"list\", {\n query: options?.filter as Record<string, string> | undefined,\n });\n\n if (!request) {\n throw new AFSNotFoundError(path, \"Failed to build request\");\n }\n\n try {\n const response = await this.client.request(\n `${request.method} ${request.path}`,\n request.params as Record<string, unknown>,\n );\n\n // Filter out PRs from issues list\n // GitHub's issues API returns both issues and PRs, but PRs have a `pull_request` field\n let responseData = response.data;\n if (Array.isArray(responseData) && fullPath.endsWith(\"/issues\")) {\n responseData = responseData.filter(\n (item: { pull_request?: unknown }) => !item.pull_request,\n );\n }\n\n const entries = this.compiled.projectResponse(fullPath, \"list\", responseData);\n\n // Adjust paths based on mode\n if (this.options.mode === \"single-repo\") {\n const prefix = `/${this.options.owner}/${this.options.repo}`;\n for (const entry of entries) {\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n } else if (this.options.mode === \"org\") {\n // In org mode, strip the owner prefix to show paths like /repo/issues/123\n const prefix = `/${this.options.owner}`;\n for (const entry of entries) {\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n }\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n /**\n * Check if a path represents a directory (has children)\n */\n private isDirectoryPath(path: string): boolean {\n if (this.isRootPath(path)) return true;\n if (this.isFilePath(path)) return false;\n if (this.getVirtualDirectoryEntry(path)) return true;\n if (this.isRepoPath(path)) return true;\n\n // Check for mapped list routes (e.g., /issues, /pulls)\n const fullPath = this.resolvePath(path);\n if (this.compiled) {\n const resolved = this.compiled.resolve(fullPath);\n if (resolved?.operations.list) return true;\n }\n return false;\n }\n\n /**\n * List entries at a path\n *\n * Per AFS semantics:\n * - maxDepth=0: return empty array (no children)\n * - maxDepth=1: return immediate children\n * - maxDepth>1: recursively include deeper levels\n * - limit: maximum number of entries to return\n *\n * @throws AFSNotFoundError if path does not exist\n */\n async list(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n const maxDepth = options?.maxDepth ?? 1;\n const limit = options?.limit;\n\n // maxDepth=0 means \"no children levels\", always return empty array\n if (maxDepth === 0) {\n return { data: [] };\n }\n\n // Get immediate children\n const result = await this.listImmediate(path, options);\n let entries = result.data;\n\n // If maxDepth > 1, recursively list children of directory entries\n if (maxDepth > 1) {\n const childEntries: AFSEntry[] = [];\n for (const entry of entries) {\n if (this.isDirectoryPath(entry.path)) {\n try {\n const childResult = await this.listImmediate(entry.path, options);\n childEntries.push(...childResult.data);\n } catch {\n // Skip entries that can't be listed (e.g., leaf nodes)\n }\n }\n }\n entries = [...entries, ...childEntries];\n }\n\n return { data: this.applyLimit(entries, limit), message: result.message };\n }\n\n /**\n * Check if path is a .meta path and extract the target path\n */\n private isMetaPath(path: string): { isMeta: boolean; targetPath: string } {\n const normalized = path.replace(/\\/+$/, \"\");\n if (normalized.endsWith(\"/.meta\")) {\n return { isMeta: true, targetPath: normalized.slice(0, -6) || \"/\" };\n }\n return { isMeta: false, targetPath: path };\n }\n\n /**\n * Get entry info for a virtual directory path\n */\n private getVirtualDirectoryEntry(path: string): AFSEntry | undefined {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n // Root path\n if (segments.length === 0) {\n return this.getRootEntry();\n }\n\n // Single-repo mode: /issues, /pulls, /repo\n if (this.options.mode === \"single-repo\") {\n if (segments.length === 1) {\n const dir = this.getVirtualDirectories().find((d) => d.path === `/${segments[0]}`);\n if (dir) return dir;\n }\n }\n\n // Org mode: /{repo}, /{repo}/issues, /{repo}/pulls, /{repo}/repo\n if (this.options.mode === \"org\") {\n if (segments.length === 1) {\n // Repo root\n return {\n id: segments[0]!,\n path: `/${segments[0]}`,\n summary: `Repository: ${this.options.owner}/${segments[0]}`,\n meta: {\n childrenCount: 3,\n },\n };\n }\n if (segments.length === 2) {\n const repoName = segments[0]!;\n const dirs = this.getRepoVirtualDirectories(`/${repoName}`);\n const dir = dirs.find((d) => d.path === `/${repoName}/${segments[1]}`);\n if (dir) return dir;\n }\n }\n\n return undefined;\n }\n\n /**\n * Read a single entry\n *\n * Supports:\n * - Directory paths (returns entry info)\n * - .meta paths (returns metadata)\n * - Issue/PR paths (returns content via API)\n * - Repo file paths (returns content via Contents API)\n *\n * @throws AFSNotFoundError if path does not exist\n */\n async read(path: string, options?: AFSReadOptions): Promise<AFSReadResult> {\n // Handle /.meta/.capabilities\n if (path === \"/.meta/.capabilities\") {\n return this.readCapabilities();\n }\n\n // WORKAROUND: AFSGitHub implements AFSModule directly (not BaseProvider),\n // so it lacks automatic .actions/:name read routing. Remove if migrated to BaseProvider.\n const actionsMatch = path.match(/^(.*)\\/\\.actions\\/([^/]+)$/);\n if (actionsMatch) {\n const actionsListPath = `${actionsMatch[1] || \"\"}/.actions`;\n const actionName = actionsMatch[2];\n const actionsResult = this.listActions(actionsListPath);\n if (actionsResult) {\n const actionEntry = actionsResult.data.find((entry) => entry.id === actionName);\n if (actionEntry) {\n return { data: actionEntry };\n }\n }\n throw new AFSNotFoundError(path);\n }\n\n // Handle .meta paths\n const { isMeta, targetPath } = this.isMetaPath(path);\n if (isMeta) {\n return this.readMeta(targetPath);\n }\n\n // Handle virtual directory paths (/, /issues, /pulls, /repo)\n const virtualEntry = this.getVirtualDirectoryEntry(path);\n if (virtualEntry) {\n // For directories with unknown childrenCount (-1 or undefined), fetch the actual count\n const cc = virtualEntry.meta?.childrenCount;\n if ((cc === undefined || cc === -1) && this.isDirectoryPath(path)) {\n try {\n const children = await this.listImmediate(path);\n virtualEntry.meta = {\n ...virtualEntry.meta,\n childrenCount: children.data.length,\n };\n } catch {\n // If listing fails, keep existing childrenCount\n }\n }\n return { data: virtualEntry };\n }\n\n // Route /repo paths to Contents API\n if (this.isRepoPath(path)) {\n return this.readViaContentsAPI(path, options);\n }\n\n // Security: validate path segments for numeric IDs where expected\n if (this.options.mode === \"org\" || this.options.mode === \"single-repo\") {\n const segments = path.replace(/^\\/+|\\/+$/g, \"\").split(\"/\");\n // Check for issues/{number} or pulls/{number} pattern\n const issuesIdx = segments.indexOf(\"issues\");\n const pullsIdx = segments.indexOf(\"pulls\");\n\n if (issuesIdx !== -1 && segments[issuesIdx + 1]) {\n const issueNum = segments[issuesIdx + 1];\n if (!/^\\d+$/.test(issueNum!)) {\n throw new AFSNotFoundError(path, \"Invalid issue number\");\n }\n }\n if (pullsIdx !== -1 && segments[pullsIdx + 1]) {\n const prNum = segments[pullsIdx + 1];\n if (!/^\\d+$/.test(prNum!)) {\n throw new AFSNotFoundError(path, \"Invalid pull request number\");\n }\n }\n }\n\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) {\n throw new AFSNotFoundError(path, \"Mapping not loaded\");\n }\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved || !resolved.operations.read) {\n throw new AFSNotFoundError(path, `No read operation for path: ${fullPath}`);\n }\n\n const request = this.compiled.buildRequest(fullPath, \"read\", {});\n\n if (!request) {\n throw new AFSNotFoundError(path, \"Failed to build request\");\n }\n\n try {\n const response = await this.client.request(\n `${request.method} ${request.path}`,\n request.params as Record<string, unknown>,\n );\n\n const entries = this.compiled.projectResponse(fullPath, \"read\", response.data);\n\n if (entries.length === 0) {\n throw new AFSNotFoundError(path, \"No data returned\");\n }\n\n const entry = entries[0]!;\n\n // Adjust path based on mode\n if (this.options.mode === \"single-repo\") {\n const prefix = `/${this.options.owner}/${this.options.repo}`;\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n } else if (this.options.mode === \"org\") {\n const prefix = `/${this.options.owner}`;\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n\n return { data: entry };\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n /**\n * Read metadata for a path\n * Returns an entry with meta field containing the metadata\n *\n * @throws AFSNotFoundError if path does not exist\n */\n private async readMeta(targetPath: string): Promise<AFSReadResult> {\n const metaPath = targetPath === \"/\" ? \"/.meta\" : `${targetPath}/.meta`;\n\n // Get the entry for the target path\n const virtualEntry = this.getVirtualDirectoryEntry(targetPath);\n if (virtualEntry) {\n return {\n data: {\n id: `${virtualEntry.id}/.meta`,\n path: metaPath,\n summary: `Metadata for ${targetPath}`,\n meta: virtualEntry.meta ?? {},\n },\n };\n }\n\n // Check if this is an issue or PR path — enrich meta with labels, assignees, milestone, reactions\n const enrichedMeta = await this.getEnrichedMeta(targetPath);\n if (enrichedMeta) {\n return {\n data: {\n id: `${targetPath}/.meta`,\n path: metaPath,\n summary: `Metadata for ${targetPath}`,\n meta: enrichedMeta,\n },\n };\n }\n\n // Try to read the actual entry to get its metadata\n // This will throw AFSNotFoundError if the path doesn't exist\n const readResult = await this.read(targetPath);\n return {\n data: {\n id: `${readResult.data!.id}/.meta`,\n path: metaPath,\n summary: `Metadata for ${targetPath}`,\n meta: readResult.data!.meta ?? {},\n },\n };\n }\n\n // ============ AFSWorldMappingCapable Methods ============\n\n async loadMapping(mappingPath: string): Promise<void> {\n const compiler = new MappingCompiler();\n try {\n this.compiled = await compiler.compileDirectory(mappingPath);\n this.mappingPath = mappingPath;\n this.mappingLoadedAt = new Date();\n this.mappingError = undefined;\n } catch (error) {\n this.mappingError = error instanceof Error ? error.message : String(error);\n throw error;\n }\n }\n\n async reloadMapping(): Promise<void> {\n if (!this.mappingPath) {\n throw new Error(\"No mapping path configured\");\n }\n\n const previousCompiled = this.compiled;\n try {\n await this.loadMapping(this.mappingPath);\n } catch (error) {\n // Rollback\n this.compiled = previousCompiled;\n throw error;\n }\n }\n\n getMappingStatus(): MappingStatus {\n return {\n loaded: this.compiled !== null,\n loadedAt: this.mappingLoadedAt,\n mappingPath: this.mappingPath ?? undefined,\n compiled: this.compiled !== null,\n error: this.mappingError,\n stats: this.compiled\n ? {\n routes: this.compiled.routeCount,\n operations: this.compiled.operationCount,\n }\n : undefined,\n };\n }\n\n resolve(path: string): ExternalRef | null {\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) return null;\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved) return null;\n\n // Determine operation type\n const operation = resolved.operations.read ?? resolved.operations.list;\n if (!operation) return null;\n\n const request = this.compiled.buildRequest(\n fullPath,\n resolved.operations.read ? \"read\" : \"list\",\n {},\n );\n\n if (!request) return null;\n\n return {\n type: \"http\",\n target: `${this.options.baseUrl}${request.path}`,\n method: request.method,\n params: { ...resolved.params, ...request.params },\n headers: request.headers,\n };\n }\n\n project(externalData: unknown, context: ProjectionContext): AFSEntry[] {\n if (!this.compiled) return [];\n\n const operationType = context.rule === \"list\" ? \"list\" : \"read\";\n return this.compiled.projectResponse(context.path, operationType, externalData);\n }\n\n async mutate(_path: string, _action: MutateAction, _payload: unknown): Promise<MutateResult> {\n // MVP: write operations not implemented yet\n return {\n success: false,\n error: \"Write operations not yet implemented\",\n };\n }\n\n // ============ Stat ============\n\n /**\n * Get metadata for a path without content.\n * Supports issues, PRs, and virtual directories.\n */\n async stat(path: string, _options?: AFSStatOptions): Promise<AFSStatResult> {\n // Parse path to determine what we're stat-ing\n const parsed = this.parseIssuePRPath(path);\n\n if (parsed?.type === \"issue\") {\n return this.statIssue(parsed.number);\n }\n\n if (parsed?.type === \"pull\") {\n return this.statPR(parsed.number);\n }\n\n // Virtual directories\n const virtualEntry = this.getVirtualDirectoryEntry(path);\n if (virtualEntry) {\n return { data: virtualEntry };\n }\n\n throw new AFSNotFoundError(path);\n }\n\n private async statIssue(issueNumber: number): Promise<AFSStatResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/issues/{issue_number}\",\n { owner, repo, issue_number: issueNumber },\n );\n\n const issue = response.data;\n return {\n data: {\n id: String(issue.number),\n path: `/issues/${issue.number}`,\n summary: issue.title as string,\n meta: {\n type: \"issue\",\n state: issue.state as string,\n title: issue.title as string,\n author: (issue.user as Record<string, unknown>)?.login as string,\n commentCount: issue.comments as number,\n labels: ((issue.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n ),\n created_at: issue.created_at as string,\n updated_at: issue.updated_at as string,\n },\n },\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(`/issues/${issueNumber}`);\n }\n throw error;\n }\n }\n\n private async statPR(prNumber: number): Promise<AFSStatResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/pulls/{pull_number}\",\n { owner, repo, pull_number: prNumber },\n );\n\n const pr = response.data;\n return {\n data: {\n id: String(pr.number),\n path: `/pulls/${pr.number}`,\n summary: pr.title as string,\n meta: {\n type: \"pull_request\",\n state: pr.state as string,\n title: pr.title as string,\n author: (pr.user as Record<string, unknown>)?.login as string,\n draft: pr.draft as boolean,\n reviewers: ((pr.requested_reviewers as Array<Record<string, unknown>>) ?? []).map(\n (r) => r.login as string,\n ),\n labels: ((pr.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n ),\n created_at: pr.created_at as string,\n updated_at: pr.updated_at as string,\n merged_at: pr.merged_at as string | null,\n },\n },\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(`/pulls/${prNumber}`);\n }\n throw error;\n }\n }\n\n // ============ Search ============\n\n /**\n * Search issues and PRs using the GitHub Search API.\n * Path determines scope: /issues searches issues, /pulls searches PRs, / searches both.\n */\n async search(path: string, query: string, options?: AFSSearchOptions): Promise<AFSSearchResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n // Sanitize query: remove newlines and potential injection characters\n const sanitizedQuery = query.replace(/[\\r\\n]+/g, \" \").replace(/ghp_[a-zA-Z0-9]+/g, \"\");\n\n // Determine search type from path\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const isPulls = normalized === \"pulls\" || normalized.endsWith(\"/pulls\");\n const isIssues = normalized === \"issues\" || normalized.endsWith(\"/issues\");\n\n // Build GitHub search query\n let q = sanitizedQuery.trim();\n q += ` repo:${owner}/${repo}`;\n if (isPulls) {\n q += \" is:pr\";\n } else if (isIssues) {\n q += \" is:issue\";\n }\n\n try {\n const response = await this.client.request<{\n total_count: number;\n items: Array<Record<string, unknown>>;\n }>(\"GET /search/issues\", {\n q: q.trim(),\n per_page: options?.limit ?? 30,\n });\n\n const entries: AFSEntry[] = response.data.items.map((item) => {\n const hasPR = \"pull_request\" in item;\n const type = hasPR ? \"pulls\" : \"issues\";\n return {\n id: String(item.number),\n path: `/${type}/${item.number}`,\n summary: item.title as string,\n meta: {\n type: hasPR ? \"pull_request\" : \"issue\",\n state: item.state as string,\n author: (item.user as Record<string, unknown>)?.login as string,\n },\n };\n });\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 422) {\n return { data: [], message: \"Invalid search query\" };\n }\n throw error;\n }\n }\n\n // ============ Explain ============\n\n /**\n * Provide human/LLM-readable explanation of a path.\n */\n async explain(path: string, _options?: AFSExplainOptions): Promise<AFSExplainResult> {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n\n if (normalized === \"\") {\n return this.explainRoot();\n }\n\n if (normalized === \"issues\") {\n return this.explainIssuesDir();\n }\n\n if (normalized === \"pulls\") {\n return this.explainPullsDir();\n }\n\n // Check if this is a specific issue or PR\n const parsed = this.parseIssuePRPath(path);\n if (parsed?.type === \"issue\") {\n return this.explainIssue(parsed.number);\n }\n if (parsed?.type === \"pull\") {\n return this.explainPR(parsed.number);\n }\n\n throw new AFSNotFoundError(path);\n }\n\n private async explainRoot(): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}\",\n { owner, repo },\n );\n\n const data = response.data;\n const lines: string[] = [\n `# ${data.full_name}`,\n \"\",\n data.description ? `${data.description}` : \"\",\n \"\",\n `- **Language**: ${data.language ?? \"N/A\"}`,\n `- **Stars**: ${data.stargazers_count ?? 0} ⭐`,\n `- **Forks**: ${data.forks_count ?? 0}`,\n `- **Open Issues**: ${data.open_issues_count ?? 0}`,\n `- **Default Branch**: ${data.default_branch ?? \"main\"}`,\n `- **License**: ${(data.license as Record<string, unknown>)?.spdx_id ?? \"N/A\"}`,\n `- **Visibility**: ${data.private ? \"Private\" : \"Public\"}`,\n \"\",\n \"## Structure\",\n \"\",\n \"- `/issues` — Repository issues\",\n \"- `/pulls` — Pull requests\",\n \"- `/repo` — Repository source code\",\n ];\n\n const topics = data.topics as string[] | undefined;\n if (topics && topics.length > 0) {\n lines.push(\"\", `**Topics**: ${topics.join(\", \")}`);\n }\n\n return {\n format: \"markdown\",\n content: lines.filter((l) => l !== undefined).join(\"\\n\"),\n };\n }\n\n private async explainIssuesDir(): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n // Fetch open and closed counts using search API\n const [openResult, closedResult] = await Promise.all([\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:issue is:open`,\n per_page: 1,\n }),\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:issue is:closed`,\n per_page: 1,\n }),\n ]);\n\n const openCount = openResult.data.total_count;\n const closedCount = closedResult.data.total_count;\n\n return {\n format: \"markdown\",\n content: [\n `# Issues — ${owner}/${repo}`,\n \"\",\n `- **Open**: ${openCount}`,\n `- **Closed**: ${closedCount}`,\n `- **Total**: ${openCount + closedCount}`,\n \"\",\n \"Use `list /issues` to browse issues.\",\n \"Use `search /issues <query>` to find specific issues.\",\n ].join(\"\\n\"),\n };\n }\n\n private async explainPullsDir(): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n const [openResult, closedResult, mergedResult] = await Promise.all([\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:pr is:open`,\n per_page: 1,\n }),\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:pr is:closed`,\n per_page: 1,\n }),\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:pr is:merged`,\n per_page: 1,\n }),\n ]);\n\n const openCount = openResult.data.total_count;\n const closedCount = closedResult.data.total_count;\n const mergedCount = mergedResult.data.total_count;\n\n return {\n format: \"markdown\",\n content: [\n `# Pull Requests — ${owner}/${repo}`,\n \"\",\n `- **Open**: ${openCount}`,\n `- **Closed**: ${closedCount}`,\n `- **Merged**: ${mergedCount}`,\n \"\",\n \"Use `list /pulls` to browse pull requests.\",\n \"Use `search /pulls <query>` to find specific PRs.\",\n ].join(\"\\n\"),\n };\n }\n\n private async explainIssue(issueNumber: number): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/issues/{issue_number}\",\n { owner, repo, issue_number: issueNumber },\n );\n\n const issue = response.data;\n const labels = ((issue.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n );\n const assignees = ((issue.assignees as Array<Record<string, unknown>>) ?? []).map(\n (a) => a.login as string,\n );\n\n return {\n format: \"markdown\",\n content: [\n `# Issue #${issue.number}: ${issue.title}`,\n \"\",\n `- **State**: ${issue.state}`,\n `- **Author**: ${(issue.user as Record<string, unknown>)?.login}`,\n `- **Created**: ${issue.created_at}`,\n `- **Updated**: ${issue.updated_at}`,\n labels.length > 0 ? `- **Labels**: ${labels.join(\", \")}` : null,\n assignees.length > 0 ? `- **Assignees**: ${assignees.join(\", \")}` : null,\n `- **Comments**: ${issue.comments}`,\n ]\n .filter((l) => l !== null)\n .join(\"\\n\"),\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(`/issues/${issueNumber}`);\n }\n throw error;\n }\n }\n\n private async explainPR(prNumber: number): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/pulls/{pull_number}\",\n { owner, repo, pull_number: prNumber },\n );\n\n const pr = response.data;\n const labels = ((pr.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n );\n const reviewers = ((pr.requested_reviewers as Array<Record<string, unknown>>) ?? []).map(\n (r) => r.login as string,\n );\n\n return {\n format: \"markdown\",\n content: [\n `# PR #${pr.number}: ${pr.title}`,\n \"\",\n `- **State**: ${pr.state}${pr.draft ? \" (draft)\" : \"\"}`,\n `- **Author**: ${(pr.user as Record<string, unknown>)?.login}`,\n `- **Created**: ${pr.created_at}`,\n `- **Updated**: ${pr.updated_at}`,\n pr.merged_at ? `- **Merged**: ${pr.merged_at}` : null,\n labels.length > 0 ? `- **Labels**: ${labels.join(\", \")}` : null,\n reviewers.length > 0 ? `- **Reviewers**: ${reviewers.join(\", \")}` : null,\n `- **Head**: ${(pr.head as Record<string, unknown>)?.ref} → **Base**: ${(pr.base as Record<string, unknown>)?.ref}`,\n ]\n .filter((l) => l !== null)\n .join(\"\\n\"),\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(`/pulls/${prNumber}`);\n }\n throw error;\n }\n }\n\n // ============ Capabilities ============\n\n private async readCapabilities(): Promise<AFSReadResult> {\n const operations: OperationsDeclaration = {\n read: true,\n list: true,\n write: false,\n delete: false,\n search: true,\n exec: true,\n stat: true,\n explain: true,\n };\n\n const manifest: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: this.name,\n description: this.description ?? `GitHub: ${this.options.owner}/${this.options.repo}`,\n tools: [],\n operations,\n actions: [\n {\n kind: \"github:issue\",\n description: \"Issue lifecycle actions\",\n catalog: [\n { name: \"close-issue\", description: \"Close an issue\" },\n { name: \"reopen-issue\", description: \"Reopen a closed issue\" },\n { name: \"add-comment\", description: \"Add a comment to an issue\" },\n { name: \"add-label\", description: \"Add a label to an issue\" },\n { name: \"remove-label\", description: \"Remove a label from an issue\" },\n ],\n discovery: { pathTemplate: \"/issues/:number/.actions\" },\n },\n {\n kind: \"github:pull_request\",\n description: \"Pull request lifecycle actions\",\n catalog: [\n { name: \"merge-pr\", description: \"Merge a pull request\" },\n { name: \"approve-pr\", description: \"Approve a pull request\" },\n { name: \"request-changes\", description: \"Request changes on a pull request\" },\n { name: \"add-comment\", description: \"Add a comment to a pull request\" },\n { name: \"add-label\", description: \"Add a label to a pull request\" },\n { name: \"remove-label\", description: \"Remove a label from a pull request\" },\n ],\n discovery: { pathTemplate: \"/pulls/:number/.actions\" },\n },\n {\n kind: \"github:repo\",\n description: \"Repository file operations\",\n catalog: [\n { name: \"read-file\", description: \"Read a file from the repository\" },\n { name: \"write-file\", description: \"Write a file to the repository\" },\n { name: \"create-branch\", description: \"Create a new branch\" },\n ],\n discovery: { pathTemplate: \"/repo/:branch/.actions\" },\n },\n ],\n };\n\n return {\n data: {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n summary: \"Provider capabilities manifest\",\n content: manifest as unknown as string,\n },\n };\n }\n\n // ============ Enriched Meta ============\n\n /**\n * Get enriched metadata for an issue or PR path.\n * Returns labels, assignees, milestone, reactions from GitHub API.\n */\n private async getEnrichedMeta(path: string): Promise<Record<string, unknown> | null> {\n const parsed = this.parseIssuePRPath(path);\n if (!parsed) return null;\n\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n if (parsed.type === \"issue\") {\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/issues/{issue_number}\",\n { owner, repo, issue_number: parsed.number },\n );\n\n const issue = response.data;\n return {\n type: \"issue\",\n state: issue.state,\n author: (issue.user as Record<string, unknown>)?.login,\n labels: ((issue.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n ),\n assignees: ((issue.assignees as Array<Record<string, unknown>>) ?? []).map(\n (a) => a.login as string,\n ),\n milestone: (issue.milestone as Record<string, unknown>)?.title ?? null,\n reactions: issue.reactions\n ? this.extractReactions(issue.reactions as Record<string, unknown>)\n : this.zeroReactions(),\n commentCount: issue.comments,\n created_at: issue.created_at,\n updated_at: issue.updated_at,\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n if (parsed.type === \"pull\") {\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/pulls/{pull_number}\",\n { owner, repo, pull_number: parsed.number },\n );\n\n const pr = response.data;\n return {\n type: \"pull_request\",\n state: pr.state,\n author: (pr.user as Record<string, unknown>)?.login,\n draft: pr.draft,\n labels: ((pr.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n ),\n assignees: ((pr.assignees as Array<Record<string, unknown>>) ?? []).map(\n (a) => a.login as string,\n ),\n milestone: (pr.milestone as Record<string, unknown>)?.title ?? null,\n reactions: pr.reactions\n ? this.extractReactions(pr.reactions as Record<string, unknown>)\n : this.zeroReactions(),\n reviewers: ((pr.requested_reviewers as Array<Record<string, unknown>>) ?? []).map(\n (r) => r.login as string,\n ),\n commentCount: pr.comments,\n merged_at: pr.merged_at,\n created_at: pr.created_at,\n updated_at: pr.updated_at,\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n return null;\n }\n\n private extractReactions(reactions: Record<string, unknown>): Record<string, number> {\n return {\n \"+1\": (reactions[\"+1\"] as number) ?? 0,\n \"-1\": (reactions[\"-1\"] as number) ?? 0,\n laugh: (reactions.laugh as number) ?? 0,\n hooray: (reactions.hooray as number) ?? 0,\n confused: (reactions.confused as number) ?? 0,\n heart: (reactions.heart as number) ?? 0,\n rocket: (reactions.rocket as number) ?? 0,\n eyes: (reactions.eyes as number) ?? 0,\n };\n }\n\n private zeroReactions(): Record<string, number> {\n return {\n \"+1\": 0,\n \"-1\": 0,\n laugh: 0,\n hooray: 0,\n confused: 0,\n heart: 0,\n rocket: 0,\n eyes: 0,\n };\n }\n\n // ============ Path Parsing Helpers ============\n\n /**\n * Parse a path to determine if it's an issue or PR path.\n * Returns { type, number } or null.\n */\n private parseIssuePRPath(path: string): { type: \"issue\" | \"pull\"; number: number } | null {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /issues/{number} or /pulls/{number}\n if (segments.length === 2 && segments[0] === \"issues\" && /^\\d+$/.test(segments[1]!)) {\n return { type: \"issue\", number: Number.parseInt(segments[1]!, 10) };\n }\n if (segments.length === 2 && segments[0] === \"pulls\" && /^\\d+$/.test(segments[1]!)) {\n return { type: \"pull\", number: Number.parseInt(segments[1]!, 10) };\n }\n } else if (this.options.mode === \"org\") {\n // /{repo}/issues/{number} or /{repo}/pulls/{number}\n if (segments.length === 3 && segments[1] === \"issues\" && /^\\d+$/.test(segments[2]!)) {\n return { type: \"issue\", number: Number.parseInt(segments[2]!, 10) };\n }\n if (segments.length === 3 && segments[1] === \"pulls\" && /^\\d+$/.test(segments[2]!)) {\n return { type: \"pull\", number: Number.parseInt(segments[2]!, 10) };\n }\n }\n\n return null;\n }\n\n // ============ Actions: List ============\n\n /**\n * List available actions at a path.\n * Returns null if the path is not an .actions path.\n */\n private listActions(path: string): AFSListResult | null {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n\n // Root actions: /.actions\n if (normalized === \".actions\") {\n return {\n data: [\n {\n id: \"create-issue\",\n path: \"/.actions/create-issue\",\n summary: \"Create a new issue\",\n meta: { kind: \"afs:executable\", name: \"create-issue\" },\n },\n {\n id: \"create-pr\",\n path: \"/.actions/create-pr\",\n summary: \"Create a new pull request\",\n meta: { kind: \"afs:executable\", name: \"create-pr\" },\n },\n {\n id: \"create-file\",\n path: \"/.actions/create-file\",\n summary: \"Create a file in the repository\",\n meta: { kind: \"afs:executable\", name: \"create-file\" },\n },\n {\n id: \"update-file\",\n path: \"/.actions/update-file\",\n summary: \"Update a file in the repository\",\n meta: { kind: \"afs:executable\", name: \"update-file\" },\n },\n ],\n };\n }\n\n // Issue actions: /issues/{number}/.actions\n const issueActionsMatch = normalized.match(/^issues\\/(\\d+)\\/\\.actions$/);\n if (issueActionsMatch) {\n const num = issueActionsMatch[1];\n return {\n data: [\n {\n id: \"close-issue\",\n path: `/issues/${num}/.actions/close-issue`,\n summary: \"Close this issue\",\n meta: { kind: \"afs:executable\", name: \"close-issue\" },\n },\n {\n id: \"reopen-issue\",\n path: `/issues/${num}/.actions/reopen-issue`,\n summary: \"Reopen this issue\",\n meta: { kind: \"afs:executable\", name: \"reopen-issue\" },\n },\n {\n id: \"add-comment\",\n path: `/issues/${num}/.actions/add-comment`,\n summary: \"Add a comment\",\n meta: { kind: \"afs:executable\", name: \"add-comment\" },\n },\n {\n id: \"add-label\",\n path: `/issues/${num}/.actions/add-label`,\n summary: \"Add a label\",\n meta: { kind: \"afs:executable\", name: \"add-label\" },\n },\n {\n id: \"remove-label\",\n path: `/issues/${num}/.actions/remove-label`,\n summary: \"Remove a label\",\n meta: { kind: \"afs:executable\", name: \"remove-label\" },\n },\n ],\n };\n }\n\n // PR actions: /pulls/{number}/.actions\n const prActionsMatch = normalized.match(/^pulls\\/(\\d+)\\/\\.actions$/);\n if (prActionsMatch) {\n const num = prActionsMatch[1];\n return {\n data: [\n {\n id: \"merge-pr\",\n path: `/pulls/${num}/.actions/merge-pr`,\n summary: \"Merge this pull request\",\n meta: { kind: \"afs:executable\", name: \"merge-pr\" },\n },\n {\n id: \"request-review\",\n path: `/pulls/${num}/.actions/request-review`,\n summary: \"Request a review\",\n meta: { kind: \"afs:executable\", name: \"request-review\" },\n },\n {\n id: \"add-comment\",\n path: `/pulls/${num}/.actions/add-comment`,\n summary: \"Add a comment\",\n meta: { kind: \"afs:executable\", name: \"add-comment\" },\n },\n {\n id: \"add-label\",\n path: `/pulls/${num}/.actions/add-label`,\n summary: \"Add a label\",\n meta: { kind: \"afs:executable\", name: \"add-label\" },\n },\n {\n id: \"remove-label\",\n path: `/pulls/${num}/.actions/remove-label`,\n summary: \"Remove a label\",\n meta: { kind: \"afs:executable\", name: \"remove-label\" },\n },\n ],\n };\n }\n\n return null;\n }\n\n // ============ Actions: Exec ============\n\n /**\n * Execute an action at a path.\n * Path format: /{resource}/.actions/{action-name}\n */\n async exec(\n path: string,\n args: Record<string, unknown>,\n _options: AFSExecOptions,\n ): Promise<AFSExecResult> {\n if (this.accessMode === \"readonly\") {\n throw new AFSReadonlyError(\"Cannot exec on a readonly provider\");\n }\n\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n\n // Parse: {prefix}/.actions/{actionName}\n // Handle both \"prefix/.actions/name\" and \".actions/name\" (root)\n const actionMatch = normalized.match(/^(?:(.+)\\/)?\\.actions\\/([^/]+)$/);\n if (!actionMatch) {\n return {\n success: false,\n error: { code: \"INVALID_PATH\", message: `Invalid action path: ${path}` },\n };\n }\n\n const resourcePath = actionMatch[1] || \"\";\n const actionName = actionMatch[2]!;\n\n try {\n // Route to appropriate action handler\n // Root actions\n if (resourcePath === \"\") {\n return await this.execRootAction(actionName, args);\n }\n\n // Issue actions: issues/{number}\n const issueMatch = resourcePath.match(/^issues\\/(\\d+)$/);\n if (issueMatch) {\n const issueNumber = Number.parseInt(issueMatch[1]!, 10);\n return await this.execIssueAction(issueNumber, actionName, args);\n }\n\n // PR actions: pulls/{number}\n const prMatch = resourcePath.match(/^pulls\\/(\\d+)$/);\n if (prMatch) {\n const prNumber = Number.parseInt(prMatch[1]!, 10);\n return await this.execPRAction(prNumber, actionName, args);\n }\n\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `No actions for path: /${resourcePath}` },\n };\n } catch (error) {\n return this.handleExecError(error);\n }\n }\n\n private async execRootAction(\n actionName: string,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n switch (actionName) {\n case \"create-issue\": {\n const title = args.title as string | undefined;\n if (!title) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"title is required\" },\n };\n }\n const response = await this.client.request(\"POST /repos/{owner}/{repo}/issues\", {\n owner,\n repo,\n title,\n body: (args.body as string) ?? undefined,\n labels: (args.labels as string[]) ?? undefined,\n assignees: (args.assignees as string[]) ?? undefined,\n });\n const issue = response.data as Record<string, unknown>;\n return {\n success: true,\n data: {\n number: issue.number as number,\n url: issue.html_url as string,\n },\n };\n }\n\n case \"create-pr\": {\n const title = args.title as string | undefined;\n const head = args.head as string | undefined;\n const base = args.base as string | undefined;\n if (!title || !head || !base) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"title, head, and base are required\" },\n };\n }\n if (head === base) {\n return {\n success: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"head and base must be different branches\",\n },\n };\n }\n const response = await this.client.request(\"POST /repos/{owner}/{repo}/pulls\", {\n owner,\n repo,\n title,\n body: (args.body as string) ?? undefined,\n head,\n base,\n draft: (args.draft as boolean) ?? false,\n });\n const pr = response.data as Record<string, unknown>;\n return {\n success: true,\n data: {\n number: pr.number as number,\n url: pr.html_url as string,\n },\n };\n }\n\n case \"create-file\": {\n const filePath = args.path as string | undefined;\n if (!filePath) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"path is required\" },\n };\n }\n // Security: validate path against traversal\n if (filePath.includes(\"..\") || filePath.startsWith(\"/\")) {\n return {\n success: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"path must not contain '..' or start with '/'\",\n },\n };\n }\n const content = (args.content as string) ?? \"\";\n const message = (args.message as string) ?? `Create ${filePath}`;\n const response = await this.client.request(\"PUT /repos/{owner}/{repo}/contents/{path}\", {\n owner,\n repo,\n path: filePath,\n message,\n content: Buffer.from(content).toString(\"base64\"),\n branch: (args.branch as string) ?? undefined,\n });\n const result = response.data as Record<string, unknown>;\n const fileInfo = result.content as Record<string, unknown> | undefined;\n const commitInfo = result.commit as Record<string, unknown> | undefined;\n return {\n success: true,\n data: {\n sha: fileInfo?.sha as string,\n commitSha: commitInfo?.sha as string,\n },\n };\n }\n\n case \"update-file\": {\n const filePath = args.path as string | undefined;\n const sha = args.sha as string | undefined;\n if (!filePath) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"path is required\" },\n };\n }\n if (!sha) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"sha is required (optimistic lock)\" },\n };\n }\n if (filePath.includes(\"..\") || filePath.startsWith(\"/\")) {\n return {\n success: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"path must not contain '..' or start with '/'\",\n },\n };\n }\n const content = (args.content as string) ?? \"\";\n const message = (args.message as string) ?? `Update ${filePath}`;\n const response = await this.client.request(\"PUT /repos/{owner}/{repo}/contents/{path}\", {\n owner,\n repo,\n path: filePath,\n message,\n content: Buffer.from(content).toString(\"base64\"),\n sha,\n branch: (args.branch as string) ?? undefined,\n });\n const result = response.data as Record<string, unknown>;\n const fileInfo = result.content as Record<string, unknown> | undefined;\n const commitInfo = result.commit as Record<string, unknown> | undefined;\n return {\n success: true,\n data: {\n sha: fileInfo?.sha as string,\n commitSha: commitInfo?.sha as string,\n },\n };\n }\n\n default:\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Unknown action: ${actionName}` },\n };\n }\n }\n\n private async execIssueAction(\n issueNumber: number,\n actionName: string,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n switch (actionName) {\n case \"close-issue\": {\n const response = await this.client.request(\n \"PATCH /repos/{owner}/{repo}/issues/{issue_number}\",\n {\n owner,\n repo,\n issue_number: issueNumber,\n state: \"closed\",\n state_reason: (args.reason as string) ?? undefined,\n },\n );\n const issue = response.data as Record<string, unknown>;\n return {\n success: true,\n data: { state: issue.state as string },\n };\n }\n\n case \"reopen-issue\": {\n const response = await this.client.request(\n \"PATCH /repos/{owner}/{repo}/issues/{issue_number}\",\n {\n owner,\n repo,\n issue_number: issueNumber,\n state: \"open\",\n },\n );\n const issue = response.data as Record<string, unknown>;\n return {\n success: true,\n data: { state: issue.state as string },\n };\n }\n\n case \"add-comment\": {\n const body = args.body as string | undefined;\n if (!body) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"body is required\" },\n };\n }\n const response = await this.client.request(\n \"POST /repos/{owner}/{repo}/issues/{issue_number}/comments\",\n {\n owner,\n repo,\n issue_number: issueNumber,\n body,\n },\n );\n const comment = response.data as Record<string, unknown>;\n return {\n success: true,\n data: { id: comment.id as number },\n };\n }\n\n case \"add-label\": {\n const label = args.label as string | undefined;\n if (!label) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"label is required\" },\n };\n }\n if (label.length > 200) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"label name exceeds maximum length (200)\" },\n };\n }\n await this.client.request(\"POST /repos/{owner}/{repo}/issues/{issue_number}/labels\", {\n owner,\n repo,\n issue_number: issueNumber,\n labels: [label],\n });\n return { success: true, data: { label } };\n }\n\n case \"remove-label\": {\n const label = args.label as string | undefined;\n if (!label) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"label is required\" },\n };\n }\n try {\n await this.client.request(\n \"DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}\",\n {\n owner,\n repo,\n issue_number: issueNumber,\n name: label,\n },\n );\n return { success: true, data: { label } };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Label \"${label}\" not found` },\n };\n }\n throw error;\n }\n }\n\n default:\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Unknown issue action: ${actionName}` },\n };\n }\n }\n\n private async execPRAction(\n prNumber: number,\n actionName: string,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n switch (actionName) {\n case \"merge-pr\": {\n const method = (args.method as string) ?? \"merge\";\n const response = await this.client.request(\n \"PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge\",\n {\n owner,\n repo,\n pull_number: prNumber,\n merge_method: method,\n commit_title: (args.commitTitle as string) ?? undefined,\n commit_message: (args.commitMessage as string) ?? undefined,\n },\n );\n const result = response.data as Record<string, unknown>;\n return {\n success: true,\n data: {\n merged: result.merged as boolean,\n sha: result.sha as string,\n },\n };\n }\n\n case \"request-review\": {\n const reviewers = args.reviewers as string[] | undefined;\n if (!reviewers || reviewers.length === 0) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"reviewers is required\" },\n };\n }\n await this.client.request(\n \"POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers\",\n {\n owner,\n repo,\n pull_number: prNumber,\n reviewers,\n },\n );\n return { success: true, data: { reviewers } };\n }\n\n case \"add-comment\": {\n // PRs use the issues API for comments\n return this.execIssueAction(prNumber, \"add-comment\", args);\n }\n\n case \"add-label\": {\n return this.execIssueAction(prNumber, \"add-label\", args);\n }\n\n case \"remove-label\": {\n return this.execIssueAction(prNumber, \"remove-label\", args);\n }\n\n default:\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Unknown PR action: ${actionName}` },\n };\n }\n }\n\n /**\n * Handle errors from action execution.\n * Sanitizes error messages to prevent token leaks.\n */\n private handleExecError(error: unknown): AFSExecResult {\n const status = (error as { status?: number })?.status;\n const message = error instanceof Error ? error.message : String(error);\n const sanitized = message.replace(/ghp_[a-zA-Z0-9]+/g, \"[REDACTED]\");\n\n if (status === 403) {\n return {\n success: false,\n error: {\n code: \"FORBIDDEN\",\n message: `Insufficient permissions. Check that your token has the required access.`,\n },\n };\n }\n\n if (status === 404) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Resource not found: ${sanitized}` },\n };\n }\n\n if (status === 405 || status === 409) {\n return {\n success: false,\n error: { code: \"CONFLICT\", message: sanitized },\n };\n }\n\n if (status === 422) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: sanitized },\n };\n }\n\n return {\n success: false,\n error: { code: \"INTERNAL_ERROR\", message: sanitized },\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["entryPath"],"sources":["../src/client.ts","../src/types.ts","../src/github.ts"],"sourcesContent":["/**\n * GitHub API Client\n *\n * Wraps Octokit with throttling, retry, and caching.\n */\n\nimport { retry } from \"@octokit/plugin-retry\";\nimport { throttling } from \"@octokit/plugin-throttling\";\nimport { Octokit } from \"@octokit/rest\";\nimport type { AuthOptions, CacheOptions, RateLimitOptions } from \"./types.js\";\n\n/**\n * Cache entry\n */\ninterface CacheEntry {\n data: unknown;\n expiresAt: number;\n}\n\n/**\n * GitHub Contents API item\n */\nexport interface ContentsItem {\n name: string;\n path: string;\n type: \"file\" | \"dir\" | \"symlink\" | \"submodule\";\n size: number;\n sha: string;\n download_url: string | null;\n /** Base64 encoded content, only for files <1MB */\n content?: string;\n /** Encoding type, typically \"base64\" when content is present */\n encoding?: string;\n}\n\n/**\n * Response from Contents API - can be single item or array\n */\nexport type ContentsResponse = ContentsItem | ContentsItem[];\n\n/**\n * GitHub Branch item\n */\nexport interface BranchItem {\n name: string;\n commit: {\n sha: string;\n url: string;\n };\n protected: boolean;\n}\n\n/**\n * Options for GitHubClient\n */\nexport interface GitHubClientOptions {\n auth?: AuthOptions;\n baseUrl?: string;\n cache?: CacheOptions;\n rateLimit?: RateLimitOptions;\n}\n\n/**\n * GitHub API client with throttling, retry, and caching\n */\nexport class GitHubClient {\n private octokit: Octokit;\n private cache: Map<string, CacheEntry> = new Map();\n private cacheConfig: CacheOptions;\n\n constructor(options: GitHubClientOptions) {\n this.cacheConfig = {\n enabled: options.cache?.enabled ?? true,\n ttl: options.cache?.ttl ?? 60000,\n };\n\n const maxRetries = options.rateLimit?.maxRetries ?? 3;\n\n // Create Octokit with plugins\n const OctokitWithPlugins = Octokit.plugin(throttling, retry);\n\n this.octokit = new OctokitWithPlugins({\n auth: options.auth?.token,\n baseUrl: options.baseUrl ?? \"https://api.github.com\",\n // Suppress Octokit's built-in request logging (from @octokit/plugin-request-log)\n // We handle errors ourselves with user-friendly messages\n log: {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n },\n throttle: {\n onRateLimit: (retryAfter, _options, _octokit, retryCount) => {\n if (retryCount < maxRetries) {\n console.warn(`Rate limited. Retrying after ${retryAfter} seconds.`);\n return true;\n }\n return false;\n },\n onSecondaryRateLimit: (retryAfter, _options, _octokit, retryCount) => {\n if (retryCount < maxRetries) {\n console.warn(`Secondary rate limit. Retrying after ${retryAfter} seconds.`);\n return true;\n }\n return false;\n },\n },\n retry: {\n enabled: options.rateLimit?.autoRetry ?? true,\n retries: maxRetries,\n },\n });\n }\n\n /**\n * Make a request to the GitHub API\n */\n async request<T = unknown>(\n route: string,\n params?: Record<string, unknown>,\n ): Promise<{ data: T; status: number; headers: Record<string, string> }> {\n // Only cache GET requests\n const isGet = route.startsWith(\"GET \");\n\n if (isGet && this.cacheConfig.enabled) {\n const cacheKey = this.getCacheKey(route, params);\n const cached = this.getFromCache(cacheKey);\n if (cached !== undefined) {\n return cached as { data: T; status: number; headers: Record<string, string> };\n }\n }\n\n const response = await this.octokit.request(route, params);\n\n const result = {\n data: response.data as T,\n status: response.status,\n headers: response.headers as Record<string, string>,\n };\n\n // Cache GET responses\n if (isGet && this.cacheConfig.enabled) {\n const cacheKey = this.getCacheKey(route, params);\n this.setCache(cacheKey, result);\n }\n\n return result;\n }\n\n /**\n * Generate cache key from route and params\n */\n private getCacheKey(route: string, params?: Record<string, unknown>): string {\n return `${route}:${JSON.stringify(params ?? {})}`;\n }\n\n /**\n * Get from cache if not expired\n */\n private getFromCache(key: string): unknown | undefined {\n const entry = this.cache.get(key);\n if (!entry) return undefined;\n\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return undefined;\n }\n\n return entry.data;\n }\n\n /**\n * Set cache entry\n */\n private setCache(key: string, data: unknown): void {\n this.cache.set(key, {\n data,\n expiresAt: Date.now() + this.cacheConfig.ttl,\n });\n }\n\n /**\n * Clear the cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Get the underlying Octokit instance (for advanced usage)\n */\n getOctokit(): Octokit {\n return this.octokit;\n }\n\n // ============ Contents API Methods ============\n\n /**\n * Get repository contents at a path\n * @param owner Repository owner\n * @param repo Repository name\n * @param path Path within the repository (empty string for root)\n * @param ref Optional branch, tag, or commit SHA\n * @returns Contents item(s) - array for directories, single item for files\n */\n async getContents(\n owner: string,\n repo: string,\n path: string,\n ref?: string,\n ): Promise<ContentsResponse> {\n const params: Record<string, unknown> = {\n owner,\n repo,\n path: path || \"\",\n };\n\n if (ref) {\n params.ref = ref;\n }\n\n const response = await this.request<ContentsResponse>(\n \"GET /repos/{owner}/{repo}/contents/{path}\",\n params,\n );\n\n return response.data;\n }\n\n /**\n * Get blob content for large files (>1MB)\n * @param owner Repository owner\n * @param repo Repository name\n * @param sha Blob SHA\n * @returns Decoded content as string\n */\n async getBlob(owner: string, repo: string, sha: string): Promise<string> {\n const response = await this.request<{ content: string; encoding: string }>(\n \"GET /repos/{owner}/{repo}/git/blobs/{sha}\",\n { owner, repo, sha },\n );\n\n // Blob API always returns base64 encoded content\n return Buffer.from(response.data.content, \"base64\").toString(\"utf-8\");\n }\n\n /**\n * Get repository branches\n * @param owner Repository owner\n * @param repo Repository name\n * @returns Array of branch items\n */\n async getBranches(owner: string, repo: string): Promise<BranchItem[]> {\n const allBranches: BranchItem[] = [];\n let page = 1;\n const perPage = 100;\n\n while (true) {\n const response = await this.request<BranchItem[]>(\"GET /repos/{owner}/{repo}/branches\", {\n owner,\n repo,\n per_page: perPage,\n page,\n });\n\n allBranches.push(...response.data);\n\n if (response.data.length < perPage) {\n break;\n }\n page++;\n }\n\n return allBranches;\n }\n\n /**\n * Get default branch for a repository\n * @param owner Repository owner\n * @param repo Repository name\n * @returns Default branch name\n */\n async getDefaultBranch(owner: string, repo: string): Promise<string> {\n const response = await this.request<{ default_branch: string }>(\"GET /repos/{owner}/{repo}\", {\n owner,\n repo,\n });\n\n return response.data.default_branch;\n }\n}\n","/**\n * Type definitions for AFSGitHub provider\n */\n\nimport { z } from \"zod\";\n\n/**\n * Authentication options\n */\nexport const authOptionsSchema = z.object({\n /** Personal Access Token */\n token: z\n .string()\n .optional()\n .meta({\n sensitive: true,\n env: [\"GITHUB_TOKEN\", \"GH_TOKEN\"],\n description: \"GitHub personal access token\",\n }),\n});\n\nexport type AuthOptions = z.infer<typeof authOptionsSchema>;\n\n/**\n * Cache configuration\n */\nexport const cacheOptionsSchema = z.object({\n /** Enable caching */\n enabled: z.boolean().default(true),\n /** Cache TTL in milliseconds */\n ttl: z.number().default(60000),\n});\n\nexport type CacheOptions = z.infer<typeof cacheOptionsSchema>;\n\n/**\n * Rate limiting configuration\n */\nexport const rateLimitOptionsSchema = z.object({\n /** Enable automatic retry on rate limit */\n autoRetry: z.boolean().default(true),\n /** Maximum retry attempts */\n maxRetries: z.number().default(3),\n});\n\nexport type RateLimitOptions = z.infer<typeof rateLimitOptionsSchema>;\n\n/**\n * Access mode for the provider\n */\nexport const accessModeSchema = z.enum([\"readonly\", \"readwrite\"]).default(\"readonly\");\n\nexport type AccessMode = z.infer<typeof accessModeSchema>;\n\n/**\n * Repository mode\n * - single-repo: Access a single repository (requires owner and repo)\n * - multi-repo: Access multiple repositories with full paths\n * - org: Access all repositories in an organization (requires owner only)\n */\nexport const repoModeSchema = z.enum([\"single-repo\", \"multi-repo\", \"org\"]).default(\"single-repo\");\n\nexport type RepoMode = z.infer<typeof repoModeSchema>;\n\n/**\n * Owner type for org mode\n * - org: GitHub organization (uses /orgs/{org}/repos endpoint)\n * - user: GitHub user account (uses /users/{username}/repos endpoint)\n * - undefined: Auto-detect (tries org first, falls back to user)\n */\nexport const ownerTypeSchema = z.enum([\"org\", \"user\"]).optional();\n\nexport type OwnerType = z.infer<typeof ownerTypeSchema>;\n\n/**\n * Full options schema for AFSGitHub\n */\nexport const afsGitHubOptionsSchema = z.object({\n /** Module name */\n name: z.string().default(\"github\"),\n\n /** Module description */\n description: z.string().optional(),\n\n /** Authentication */\n auth: authOptionsSchema.optional(),\n\n /** Repository owner (required for single-repo mode) */\n owner: z.string().optional(),\n\n /** Repository name (required for single-repo mode) */\n repo: z.string().optional(),\n\n /** Access mode */\n accessMode: accessModeSchema.optional(),\n\n /** Repository mode */\n mode: repoModeSchema.optional(),\n\n /** Owner type (org or user). If not set, auto-detects by trying org first. */\n ownerType: ownerTypeSchema.optional(),\n\n /** GitHub API base URL (for Enterprise) */\n baseUrl: z.string().default(\"https://api.github.com\"),\n\n /** Custom mapping path (overrides default) */\n mappingPath: z.string().optional(),\n\n /** Cache configuration */\n cache: cacheOptionsSchema.optional(),\n\n /** Rate limiting configuration */\n rateLimit: rateLimitOptionsSchema.optional(),\n\n /** Default branch/ref for Contents API (optional) */\n ref: z.string().optional(),\n});\n\n/**\n * Input options type (what users provide, with optional fields)\n */\nexport type AFSGitHubOptions = z.input<typeof afsGitHubOptionsSchema>;\n\n/**\n * Output options type (after Zod parsing, with defaults applied)\n */\nexport type AFSGitHubOptionsParsed = z.infer<typeof afsGitHubOptionsSchema>;\n\n/**\n * Validated options with defaults applied\n */\nexport interface AFSGitHubOptionsResolved {\n name: string;\n description?: string;\n auth?: AuthOptions;\n owner?: string;\n repo?: string;\n accessMode: AccessMode;\n mode: RepoMode;\n ownerType?: OwnerType;\n baseUrl: string;\n mappingPath?: string;\n cache: CacheOptions;\n rateLimit: RateLimitOptions;\n ref?: string;\n}\n","/**\n * AFSGitHub Provider\n *\n * AFS module for accessing GitHub Issues, PRs, and Actions.\n * Implements AFSModule and AFSWorldMappingCapable interfaces.\n */\n\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n type AFSEntry,\n type AFSExecOptions,\n type AFSExecResult,\n type AFSExplainOptions,\n type AFSExplainResult,\n type AFSListOptions,\n type AFSListResult,\n type AFSModule,\n AFSNotFoundError,\n type AFSReadOptions,\n AFSReadonlyError,\n type AFSReadResult,\n type AFSRoot,\n type AFSSearchOptions,\n type AFSSearchResult,\n type AFSStatOptions,\n type AFSStatResult,\n type AFSWorldMappingCapable,\n type CapabilitiesManifest,\n type ExternalRef,\n type MappingStatus,\n type MutateAction,\n type MutateResult,\n type OperationsDeclaration,\n type ProjectionContext,\n type ProviderManifest,\n} from \"@aigne/afs\";\nimport { type CompiledMapping, MappingCompiler, type RouteDefinition } from \"@aigne/afs-mapping\";\nimport { type WorldBinding, WorldMappingCore } from \"@aigne/afs-world-mapping\";\nimport { z } from \"zod\";\nimport { GitHubClient } from \"./client.js\";\nimport {\n type AFSGitHubOptions,\n type AFSGitHubOptionsResolved,\n afsGitHubOptionsSchema,\n} from \"./types.js\";\n\n// Get the directory of this module for default mapping\nconst __dirname = fileURLToPath(new URL(\".\", import.meta.url));\nconst DEFAULT_MAPPING_PATH = join(__dirname, \"default-mapping\");\n\n/**\n * AFSGitHub Provider\n *\n * Provides access to GitHub Issues, Pull Requests, and Actions through AFS.\n *\n * @example\n * ```typescript\n * const github = new AFSGitHub({\n * auth: { token: process.env.GITHUB_TOKEN },\n * owner: \"aigne\",\n * repo: \"afs\",\n * });\n *\n * // Mount to AFS\n * afs.mount(\"/github\", github);\n *\n * // List issues\n * const issues = await afs.list(\"/github/issues\");\n * ```\n */\nexport class AFSGitHub implements AFSModule, AFSWorldMappingCapable {\n readonly name: string;\n readonly description?: string;\n readonly accessMode: \"readonly\" | \"readwrite\";\n\n private options: AFSGitHubOptionsResolved;\n private client: GitHubClient;\n private compiled: CompiledMapping | null = null;\n private mappingPath: string | null = null;\n private mappingLoadedAt?: Date;\n private mappingError?: string;\n\n /** World mapping core for schema-level path resolution and field projection (Level 1) */\n readonly worldCore: WorldMappingCore;\n\n static schema() {\n return afsGitHubOptionsSchema;\n }\n\n static manifest(): ProviderManifest {\n return {\n name: \"github\",\n description: \"GitHub Issues, Pull Requests, and Actions\",\n uriTemplate: \"github://{owner}/{repo}\",\n category: \"integration\",\n schema: z.object({\n owner: z.string(),\n repo: z.string(),\n token: z.string().meta({ sensitive: true }).optional(),\n }),\n tags: [\"github\", \"git\", \"integration\"],\n };\n }\n\n constructor(options: AFSGitHubOptions & { token?: string; uri?: string }) {\n // Normalize registry-passed options: top-level token → auth.token\n if ((options as any).token && !options.auth?.token) {\n options.auth = { ...(options.auth || {}), token: (options as any).token };\n }\n\n // Auto-detect mode from provided owner/repo\n if (!options.mode) {\n if (options.owner && options.repo) {\n options.mode = \"single-repo\";\n } else if (options.owner && !options.repo) {\n options.mode = \"org\";\n }\n }\n\n // Validate and apply defaults\n const parsed = afsGitHubOptionsSchema.parse(options);\n\n this.options = {\n name: parsed.name,\n description: parsed.description,\n auth: parsed.auth,\n owner: parsed.owner,\n repo: parsed.repo,\n accessMode: parsed.accessMode ?? \"readonly\",\n mode: parsed.mode ?? \"single-repo\",\n ownerType: parsed.ownerType,\n baseUrl: parsed.baseUrl,\n mappingPath: parsed.mappingPath,\n cache: {\n enabled: parsed.cache?.enabled ?? true,\n ttl: parsed.cache?.ttl ?? 60000,\n },\n rateLimit: {\n autoRetry: parsed.rateLimit?.autoRetry ?? true,\n maxRetries: parsed.rateLimit?.maxRetries ?? 3,\n },\n ref: parsed.ref,\n };\n\n this.name = this.options.name;\n this.description = this.options.description;\n this.accessMode = this.options.accessMode;\n\n // Validate mode requirements\n if (this.options.mode === \"single-repo\") {\n if (!this.options.owner || !this.options.repo) {\n throw new Error(\"owner and repo are required in single-repo mode\");\n }\n } else if (this.options.mode === \"org\") {\n if (!this.options.owner) {\n throw new Error(\"owner is required in org mode\");\n }\n // Trim whitespace from owner\n this.options.owner = this.options.owner.trim();\n }\n\n // Create GitHub client\n this.client = new GitHubClient({\n auth: this.options.auth,\n baseUrl: this.options.baseUrl,\n cache: this.options.cache,\n rateLimit: this.options.rateLimit,\n });\n\n // Initialize world mapping core (Level 1: Library usage)\n this.worldCore = new WorldMappingCore(\n this.getDefaultWorldSchema(),\n this.getDefaultWorldBinding(),\n );\n\n // Load default mapping synchronously\n this.loadDefaultMapping();\n }\n\n /**\n * Load the default mapping configuration\n */\n private loadDefaultMapping(): void {\n try {\n const compiler = new MappingCompiler();\n // Use synchronous file reading for constructor\n // In practice, we compile from the directory\n const mappingPath = this.options.mappingPath ?? DEFAULT_MAPPING_PATH;\n this.mappingPath = mappingPath;\n\n // Load synchronously by reading files directly\n // This is a simplified version - in production, we'd use async\n this.compiled = compiler.compileConfig({\n name: \"github\",\n version: \"1.0\",\n defaults: {\n baseUrl: this.options.baseUrl,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n },\n },\n routes: this.getDefaultRoutes(),\n });\n\n this.mappingLoadedAt = new Date();\n this.mappingError = undefined;\n } catch (error) {\n this.mappingError = error instanceof Error ? error.message : String(error);\n }\n }\n\n /**\n * Get default route definitions\n * This is used when loading mapping synchronously\n */\n private getDefaultRoutes(): Record<string, RouteDefinition> {\n return {\n \"/{owner}/{repo}/issues\": {\n list: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/issues\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n state: 'query.state | default(\"open\")',\n per_page: \"query.limit | default(30)\",\n },\n transform: {\n items: \"$\",\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/issues/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n meta: {\n kind: \"github:issue\",\n type: \"issue\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/issues/{number}\": {\n read: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/issues/{number}\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n number: \"path.number\",\n },\n transform: {\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/issues/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n meta: {\n type: \"issue\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/pulls\": {\n list: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/pulls\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n state: 'query.state | default(\"open\")',\n per_page: \"query.limit | default(30)\",\n },\n transform: {\n items: \"$\",\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/pulls/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n meta: {\n kind: \"github:pull-request\",\n type: \"pull_request\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n \"/{owner}/{repo}/pulls/{number}\": {\n read: {\n method: \"GET\",\n path: \"/repos/{owner}/{repo}/pulls/{number}\",\n params: {\n owner: \"path.owner\",\n repo: \"path.repo\",\n number: \"path.number\",\n },\n transform: {\n entry: {\n id: \"$.number | string\",\n path: \"/{owner}/{repo}/pulls/{$.number}\",\n summary: \"$.title\",\n content: \"$.body\",\n meta: {\n type: \"pull_request\",\n state: \"$.state\",\n author: \"$.user.login\",\n },\n },\n },\n },\n },\n };\n }\n\n /**\n * Get default world schema for GitHub\n * Defines Issue, PullRequest, Comment as world kinds\n */\n private getDefaultWorldSchema(): any {\n return {\n world: \"github\",\n version: \"1.0\",\n kinds: {\n Issue: {\n key: \"number\",\n path: \"/{owner}/{repo}/issues/{number}\",\n fields: {\n number: \"int\",\n title: \"string\",\n body: \"text\",\n state: \"string\",\n author: \"string\",\n labels: \"string\",\n assignees: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n comments_count: \"int\",\n },\n },\n PullRequest: {\n key: \"number\",\n path: \"/{owner}/{repo}/pulls/{number}\",\n fields: {\n number: \"int\",\n title: \"string\",\n body: \"text\",\n state: \"string\",\n author: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n },\n },\n Comment: {\n key: \"id\",\n path: \"/{owner}/{repo}/issues/{number}/comments/{id}\",\n fields: {\n id: \"int\",\n body: \"text\",\n author: \"string\",\n created_at: \"datetime\",\n updated_at: \"datetime\",\n },\n },\n },\n };\n }\n\n /**\n * Get default world binding for GitHub\n * Maps world fields to GitHub API response fields\n */\n private getDefaultWorldBinding(): WorldBinding {\n return {\n source: \"/github\",\n mappings: {\n Issue: {\n path: \"/{owner}/{repo}/issues/{number}\",\n fieldMap: {\n author: \"user_login\",\n comments_count: \"comments\",\n },\n },\n PullRequest: {\n path: \"/{owner}/{repo}/pulls/{number}\",\n fieldMap: {\n author: \"user_login\",\n },\n },\n Comment: {\n path: \"/{owner}/{repo}/issues/{number}/comments/{id}\",\n fieldMap: {\n author: \"user_login\",\n },\n },\n },\n };\n }\n\n // ============ AFSModule Methods ============\n\n onMount?(_root: AFSRoot): void {\n // Optional: Initialize resources when mounted\n }\n\n /**\n * Resolve a path based on mode\n * - single-repo: prepend owner/repo\n * - org: prepend owner (org name)\n * - multi-repo: pass through\n */\n resolvePath(path: string): string {\n // First, try to decode URL-encoded characters\n let decodedPath: string;\n try {\n decodedPath = decodeURIComponent(path);\n } catch {\n decodedPath = path;\n }\n\n // Normalize: split by slashes, filter empty and traversal segments, rejoin\n const segments = decodedPath\n .split(\"/\")\n .filter((segment) => segment !== \"\" && segment !== \".\" && segment !== \"..\");\n\n const cleanPath = segments.join(\"/\");\n\n if (this.options.mode === \"single-repo\" && this.options.owner && this.options.repo) {\n // Prepend owner/repo to path\n if (!cleanPath) {\n return `/${this.options.owner}/${this.options.repo}`;\n }\n return `/${this.options.owner}/${this.options.repo}/${cleanPath}`;\n }\n\n if (this.options.mode === \"org\" && this.options.owner) {\n // For org mode:\n // - \"/\" or \"\" -> \"/\" (org root, will list repos)\n // - \"/repo\" -> \"/owner/repo\" (repo root)\n // - \"/repo/issues\" -> \"/owner/repo/issues\"\n if (!cleanPath) {\n return \"/\";\n }\n return `/${this.options.owner}/${cleanPath}`;\n }\n\n // multi-repo mode: pass through (with normalization)\n return cleanPath ? `/${cleanPath}` : \"/\";\n }\n\n /**\n * Get virtual directory structure for root path\n * Returns the available resource types (issues, pulls, repo)\n */\n private getVirtualDirectories(): AFSEntry[] {\n return [\n {\n id: \"issues\",\n path: \"/issues\",\n summary: \"Repository Issues\",\n meta: {\n kind: \"github:directory\",\n childrenCount: -1, // Dynamic, unknown until fetched\n description: \"List and read repository issues\",\n },\n },\n {\n id: \"pulls\",\n path: \"/pulls\",\n summary: \"Pull Requests\",\n meta: {\n kind: \"github:directory\",\n childrenCount: -1,\n description: \"List and read pull requests\",\n },\n },\n {\n id: \"repo\",\n path: \"/repo\",\n summary: \"Repository Code\",\n meta: {\n kind: \"github:directory\",\n childrenCount: -1,\n description: \"Repository source code (via Contents API)\",\n },\n },\n ];\n }\n\n /**\n * Check if path points to a file (leaf node) like /issues/{n} or /pulls/{n}\n * These are individual issues/PRs that don't have children.\n */\n private isFilePath(path: string): boolean {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /issues/{number} or /pulls/{number}\n if (segments.length === 2 && (segments[0] === \"issues\" || segments[0] === \"pulls\")) {\n return /^\\d+$/.test(segments[1]!);\n }\n } else if (this.options.mode === \"org\") {\n // /{repo}/issues/{number} or /{repo}/pulls/{number}\n if (segments.length === 3 && (segments[1] === \"issues\" || segments[1] === \"pulls\")) {\n return /^\\d+$/.test(segments[2]!);\n }\n }\n\n return false;\n }\n\n /**\n * Check if path is root or empty\n */\n private isRootPath(path: string): boolean {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n return normalized === \"\";\n }\n\n /**\n * Get root entry (the mount point itself)\n */\n private getRootEntry(): AFSEntry {\n let summary: string;\n let childrenCount: number | undefined;\n\n if (this.options.mode === \"org\") {\n summary = this.description ?? `GitHub Organization: ${this.options.owner}`;\n childrenCount = -1; // Unknown until repos are fetched\n } else if (this.options.mode === \"single-repo\") {\n summary = this.description ?? `GitHub: ${this.options.owner}/${this.options.repo}`;\n childrenCount = 3; // issues, pulls, repo\n } else {\n summary = this.description ?? \"GitHub\";\n childrenCount = undefined;\n }\n\n return {\n id: this.name,\n path: \"/\",\n summary,\n meta: {\n childrenCount,\n description: summary,\n },\n };\n }\n\n /**\n * Get virtual directories for a repo (issues, pulls, repo)\n */\n private getRepoVirtualDirectories(repoPath: string): AFSEntry[] {\n return [\n {\n id: `${repoPath}/issues`,\n path: `${repoPath}/issues`,\n summary: \"Repository Issues\",\n meta: {\n childrenCount: -1,\n description: \"List and read repository issues\",\n },\n },\n {\n id: `${repoPath}/pulls`,\n path: `${repoPath}/pulls`,\n summary: \"Pull Requests\",\n meta: {\n childrenCount: -1,\n description: \"List and read pull requests\",\n },\n },\n {\n id: `${repoPath}/repo`,\n path: `${repoPath}/repo`,\n summary: \"Repository Code\",\n meta: {\n childrenCount: -1,\n description: \"Repository source code (via Contents API)\",\n },\n },\n ];\n }\n\n /**\n * Check if a path represents a repo root in org mode\n * e.g., \"/reponame\" without /issues or /pulls suffix\n */\n private isRepoRootPath(path: string): boolean {\n const segments = path\n .replace(/^\\/+|\\/+$/g, \"\")\n .split(\"/\")\n .filter(Boolean);\n return segments.length === 1;\n }\n\n /**\n * Format a user-friendly error message based on the error type\n */\n private formatErrorMessage(error: unknown, context: string): string {\n const status = (error as { status?: number })?.status;\n const message = error instanceof Error ? error.message : String(error);\n\n // Sanitize any tokens from the message\n const sanitized = message.replace(/ghp_[a-zA-Z0-9]+/g, \"[REDACTED]\");\n\n if (status === 401 || message.includes(\"Bad credentials\")) {\n if (!this.options.auth?.token) {\n return `GitHub authentication required for ${context}. Set GITHUB_TOKEN environment variable or provide auth.token in config.`;\n }\n return `GitHub token is invalid or expired. Please check your GITHUB_TOKEN and ensure it has the required permissions.`;\n }\n\n if (status === 403) {\n if (message.includes(\"rate limit\")) {\n return `GitHub API rate limit exceeded. ${this.options.auth?.token ? \"Your token may have hit its limit.\" : \"Set GITHUB_TOKEN for higher rate limits (5000/hour vs 60/hour).\"} Try again later.`;\n }\n return `GitHub access forbidden for ${context}. Check that your token has the required permissions (repo scope for private repos).`;\n }\n\n if (status === 404) {\n return `GitHub ${context} not found. Check that the organization/user name is correct and accessible.`;\n }\n\n if (message.includes(\"ENOTFOUND\") || message.toLowerCase().includes(\"network\")) {\n return `Network error connecting to GitHub. Check your internet connection.`;\n }\n\n return `GitHub API error: ${sanitized}`;\n }\n\n // ============ Contents API Methods ============\n\n /**\n * Check if a path is a repo path (should be routed to Contents API)\n * - Single-repo mode: /repo or /repo/*\n * - Org mode: /{repoName}/repo or /{repoName}/repo/*\n */\n private isRepoPath(path: string): boolean {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /repo or /repo/*\n return segments[0] === \"repo\";\n }\n\n if (this.options.mode === \"org\") {\n // /{repoName}/repo or /{repoName}/repo/*\n return segments.length >= 2 && segments[1] === \"repo\";\n }\n\n return false;\n }\n\n /**\n * Parse a repo path into owner, repo name, branch, and file path\n * Structure: /repo/{branch}/{filePath}\n * - Single-repo mode: /repo/main/src/index.ts -> { owner, repo, branch: \"main\", filePath: \"src/index.ts\" }\n * - Org mode: /afs/repo/main/src/index.ts -> { owner, repo: \"afs\", branch: \"main\", filePath: \"src/index.ts\" }\n */\n private parseRepoPath(path: string): {\n owner: string;\n repo: string;\n branch?: string;\n filePath: string;\n } {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /repo -> list branches\n // /repo/{branch} -> list branch root\n // /repo/{branch}/... -> access files\n const branch = segments[1]; // undefined if just /repo\n const filePath = segments.slice(2).join(\"/\");\n return {\n owner: this.options.owner!,\n repo: this.options.repo!,\n branch,\n filePath,\n };\n }\n\n if (this.options.mode === \"org\") {\n // /{repoName}/repo -> list branches\n // /{repoName}/repo/{branch} -> list branch root\n // /{repoName}/repo/{branch}/... -> access files\n const repoName = segments[0]!;\n const branch = segments[2]; // undefined if just /{repoName}/repo\n const filePath = segments.slice(3).join(\"/\");\n return {\n owner: this.options.owner!,\n repo: repoName,\n branch,\n filePath,\n };\n }\n\n // multi-repo mode - shouldn't normally reach here\n return {\n owner: this.options.owner!,\n repo: this.options.repo!,\n branch: undefined,\n filePath: \"\",\n };\n }\n\n /**\n * Build the path prefix for a repo entry\n */\n private getRepoPathPrefix(repo: string): string {\n return this.options.mode === \"single-repo\" ? \"/repo\" : `/${repo}/repo`;\n }\n\n /**\n * List repository contents via GitHub Contents API\n * - /repo -> list all branches\n * - /repo/{branch} -> list branch root\n * - /repo/{branch}/path -> list contents at path\n *\n * @throws AFSNotFoundError if path does not exist\n */\n private async listViaContentsAPI(\n path: string,\n _options?: AFSListOptions,\n ): Promise<AFSListResult> {\n const { owner, repo, branch, filePath } = this.parseRepoPath(path);\n const repoPrefix = this.getRepoPathPrefix(repo);\n\n // Case 1: No branch specified - list all branches\n if (!branch) {\n try {\n const branches = await this.client.getBranches(owner, repo);\n const defaultBranch = await this.client.getDefaultBranch(owner, repo);\n\n const entries: AFSEntry[] = branches.map((b) => ({\n id: `${repoPrefix}/${b.name}`,\n path: `${repoPrefix}/${b.name}`,\n summary: b.name + (b.name === defaultBranch ? \" (default)\" : \"\"),\n meta: {\n kind: \"github:branch\",\n type: \"branch\",\n sha: b.commit.sha,\n protected: b.protected,\n isDefault: b.name === defaultBranch,\n childrenCount: -1,\n },\n }));\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n // Case 2 & 3: Branch specified - list contents (root or path)\n try {\n const contents = await this.client.getContents(owner, repo, filePath, branch);\n\n // Handle single file response - files have no children to list\n if (!Array.isArray(contents)) {\n if (contents.type === \"file\") {\n return { data: [] };\n }\n // For directory type, shouldn't normally happen, but handle gracefully\n const entryPath = filePath\n ? `${repoPrefix}/${branch}/${contents.path}`\n : `${repoPrefix}/${branch}/${contents.name}`;\n return {\n data: [\n {\n id: entryPath,\n path: entryPath,\n summary: contents.name,\n meta: {\n kind: contents.type === \"dir\" ? \"github:directory\" : \"github:file\",\n type: contents.type,\n size: contents.size,\n sha: contents.sha,\n },\n },\n ],\n };\n }\n\n const entries: AFSEntry[] = contents.map((item) => {\n const entryPath = filePath\n ? `${repoPrefix}/${branch}/${filePath}/${item.name}`\n : `${repoPrefix}/${branch}/${item.name}`;\n return {\n id: entryPath,\n path: entryPath,\n summary: item.name,\n meta: {\n kind: item.type === \"dir\" ? \"github:directory\" : \"github:file\",\n type: item.type,\n size: item.size,\n sha: item.sha,\n },\n };\n });\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path, `Path not found: ${branch}/${filePath || \"\"}`);\n }\n throw error;\n }\n }\n\n /**\n * Read via GitHub Contents API\n * Supports:\n * - /repo - return repo virtual directory\n * - /repo/{branch} - return branch directory entry\n * - /repo/{branch}/{path} - return file/directory entry\n *\n * @throws AFSNotFoundError if path does not exist\n */\n private async readViaContentsAPI(\n path: string,\n _options?: AFSReadOptions,\n ): Promise<AFSReadResult> {\n const { owner, repo, branch, filePath } = this.parseRepoPath(path);\n const repoPrefix = this.getRepoPathPrefix(repo);\n\n // /repo - return the repo virtual directory\n if (!branch) {\n return {\n data: {\n id: `${repoPrefix}`,\n path: repoPrefix,\n summary: \"Repository Code\",\n meta: {\n description: \"Repository source code (via Contents API)\",\n },\n },\n };\n }\n\n // /repo/{branch} - return branch directory entry\n if (!filePath) {\n try {\n const branches = await this.client.getBranches(owner, repo);\n const defaultBranch = await this.client.getDefaultBranch(owner, repo);\n const branchInfo = branches.find((b) => b.name === branch);\n\n if (!branchInfo) {\n throw new AFSNotFoundError(path, `Branch not found: ${branch}`);\n }\n\n // Fetch branch root contents to get childrenCount\n let childrenCount: number | undefined;\n try {\n const contents = await this.client.getContents(owner, repo, \"\", branch);\n if (Array.isArray(contents)) {\n childrenCount = contents.length;\n }\n } catch {\n // If contents fetch fails, leave childrenCount undefined\n }\n\n const entryPath = `${repoPrefix}/${branch}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: branch + (branch === defaultBranch ? \" (default)\" : \"\"),\n meta: {\n type: \"branch\",\n sha: branchInfo.commit.sha,\n protected: branchInfo.protected,\n isDefault: branch === defaultBranch,\n childrenCount,\n },\n },\n };\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n // /repo/{branch}/{path} - return file/directory entry\n try {\n const contents = await this.client.getContents(owner, repo, filePath, branch);\n\n // Handle directory response - return directory entry\n if (Array.isArray(contents)) {\n const entryPath = `${repoPrefix}/${branch}/${filePath}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: filePath.split(\"/\").pop() || filePath,\n meta: {\n type: \"dir\",\n childrenCount: contents.length,\n branch,\n },\n },\n };\n }\n\n // Handle directory type\n if (contents.type === \"dir\") {\n const entryPath = `${repoPrefix}/${branch}/${filePath}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: contents.name,\n meta: {\n type: \"dir\",\n sha: contents.sha,\n branch,\n },\n },\n };\n }\n\n // Handle file\n if (contents.type !== \"file\") {\n throw new AFSNotFoundError(path, `Unsupported type: ${contents.type}`);\n }\n\n // Get file content\n let content: string;\n if (contents.content) {\n content = Buffer.from(contents.content, \"base64\").toString(\"utf-8\");\n } else {\n content = await this.client.getBlob(owner, repo, contents.sha);\n }\n\n const entryPath = `${repoPrefix}/${branch}/${filePath}`;\n return {\n data: {\n id: entryPath,\n path: entryPath,\n summary: contents.name,\n content,\n meta: {\n type: \"file\",\n size: contents.size,\n sha: contents.sha,\n branch,\n },\n },\n };\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path, `Path not found: ${branch}/${filePath}`);\n }\n throw error;\n }\n }\n\n /**\n * List organization or user repositories\n * Uses ownerType if specified, otherwise tries org endpoint first and falls back to user\n */\n private async listOrgRepos(includePrivate: boolean): Promise<AFSListResult> {\n const owner = this.options.owner!;\n const ownerType = this.options.ownerType;\n let allRepos: Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }> = [];\n\n // If ownerType is explicitly set, use it directly without fallback\n if (ownerType) {\n try {\n allRepos = await this.fetchAllRepos(ownerType, owner, includePrivate);\n } catch (error) {\n const context = ownerType === \"org\" ? `organization \"${owner}\"` : `user \"${owner}\"`;\n return { data: [], message: this.formatErrorMessage(error, context) };\n }\n } else {\n // Auto-detect: try org first, fall back to user\n try {\n allRepos = await this.fetchAllRepos(\"org\", owner, includePrivate);\n } catch (error) {\n // If 404, try user endpoint (could be a user account, not an org)\n const is404 =\n (error instanceof Error && error.message.includes(\"404\")) ||\n (error as { status?: number })?.status === 404;\n if (is404) {\n try {\n allRepos = await this.fetchAllRepos(\"user\", owner, includePrivate);\n } catch (userError) {\n // Both org and user endpoints failed\n const status = (userError as { status?: number })?.status;\n if (status === 404) {\n return {\n data: [],\n message: `GitHub organization or user \"${owner}\" not found. Check that the name is correct.`,\n };\n }\n return { data: [], message: this.formatErrorMessage(userError, `user \"${owner}\"`) };\n }\n } else {\n return { data: [], message: this.formatErrorMessage(error, `organization \"${owner}\"`) };\n }\n }\n }\n\n // Filter out private repos if no auth token\n const filteredRepos = this.options.auth?.token ? allRepos : allRepos.filter((r) => !r.private);\n\n const entries: AFSEntry[] = filteredRepos.map((repo) => ({\n id: repo.name,\n path: `/${repo.name}`,\n summary: repo.description || repo.name,\n meta: {\n childrenCount: 3, // issues, pulls, repo\n description: repo.description,\n private: repo.private,\n },\n }));\n\n return { data: entries };\n }\n\n /**\n * Fetch all repos with pagination support\n */\n private async fetchAllRepos(\n type: \"org\" | \"user\",\n owner: string,\n includePrivate: boolean,\n ): Promise<\n Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }>\n > {\n const allRepos: Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }> = [];\n\n let page = 1;\n const perPage = 100;\n\n while (true) {\n let response: { data: unknown; status: number; headers: Record<string, string> };\n if (type === \"org\") {\n response = await this.client.request(\"GET /orgs/{org}/repos\", {\n org: owner,\n per_page: perPage,\n page,\n type: includePrivate ? \"all\" : \"public\",\n });\n } else {\n response = await this.client.request(\"GET /users/{username}/repos\", {\n username: owner,\n per_page: perPage,\n page,\n type: includePrivate ? \"all\" : \"public\",\n });\n }\n\n const repos = response.data as Array<{\n name: string;\n full_name: string;\n description?: string;\n private: boolean;\n }>;\n\n allRepos.push(...repos);\n\n // If we got fewer than perPage, we've reached the end\n if (repos.length < perPage) {\n break;\n }\n page++;\n }\n\n return allRepos;\n }\n\n /**\n * Apply limit to entries array\n */\n private applyLimit(entries: AFSEntry[], limit?: number): AFSEntry[] {\n if (limit !== undefined && limit > 0 && entries.length > limit) {\n return entries.slice(0, limit);\n }\n return entries;\n }\n\n /**\n * List immediate children at a path (maxDepth=1 only)\n */\n private async listImmediate(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n // Handle .actions paths\n const actionsResult = this.listActions(path);\n if (actionsResult) {\n return actionsResult;\n }\n\n // Check if path is a file (issue/PR) - return empty array for list on file paths\n if (this.isFilePath(path)) {\n return { data: [] };\n }\n\n // Route /repo paths to Contents API\n if (this.isRepoPath(path)) {\n return this.listViaContentsAPI(path, options);\n }\n\n // Handle root path\n if (this.isRootPath(path)) {\n // For org mode, list repositories\n if (this.options.mode === \"org\") {\n return this.listOrgRepos(!!this.options.auth?.token);\n }\n\n // For single-repo mode, return virtual directories (issues, pulls)\n return { data: this.getVirtualDirectories() };\n }\n\n // In org mode, check if this is a repo root (e.g., \"/afs\")\n if (this.options.mode === \"org\" && this.isRepoRootPath(path)) {\n const repoName = path.replace(/^\\/+|\\/+$/g, \"\");\n // Return virtual directories for this repo\n return { data: this.getRepoVirtualDirectories(`/${repoName}`) };\n }\n\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) {\n throw new AFSNotFoundError(path, \"Mapping not loaded\");\n }\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved || !resolved.operations.list) {\n throw new AFSNotFoundError(path, `No list operation for path: ${fullPath}`);\n }\n\n const request = this.compiled.buildRequest(fullPath, \"list\", {\n query: options?.filter as Record<string, string> | undefined,\n });\n\n if (!request) {\n throw new AFSNotFoundError(path, \"Failed to build request\");\n }\n\n try {\n const response = await this.client.request(\n `${request.method} ${request.path}`,\n request.params as Record<string, unknown>,\n );\n\n // Filter out PRs from issues list\n // GitHub's issues API returns both issues and PRs, but PRs have a `pull_request` field\n let responseData = response.data;\n if (Array.isArray(responseData) && fullPath.endsWith(\"/issues\")) {\n responseData = responseData.filter(\n (item: { pull_request?: unknown }) => !item.pull_request,\n );\n }\n\n const entries = this.compiled.projectResponse(fullPath, \"list\", responseData);\n\n // Adjust paths based on mode\n if (this.options.mode === \"single-repo\") {\n const prefix = `/${this.options.owner}/${this.options.repo}`;\n for (const entry of entries) {\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n } else if (this.options.mode === \"org\") {\n // In org mode, strip the owner prefix to show paths like /repo/issues/123\n const prefix = `/${this.options.owner}`;\n for (const entry of entries) {\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n }\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n /**\n * Check if a path represents a directory (has children)\n */\n private isDirectoryPath(path: string): boolean {\n if (this.isRootPath(path)) return true;\n if (this.isFilePath(path)) return false;\n if (this.getVirtualDirectoryEntry(path)) return true;\n if (this.isRepoPath(path)) return true;\n\n // Check for mapped list routes (e.g., /issues, /pulls)\n const fullPath = this.resolvePath(path);\n if (this.compiled) {\n const resolved = this.compiled.resolve(fullPath);\n if (resolved?.operations.list) return true;\n }\n return false;\n }\n\n /**\n * List entries at a path\n *\n * Per AFS semantics:\n * - maxDepth=0: return empty array (no children)\n * - maxDepth=1: return immediate children\n * - maxDepth>1: recursively include deeper levels\n * - limit: maximum number of entries to return\n *\n * @throws AFSNotFoundError if path does not exist\n */\n async list(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n const maxDepth = options?.maxDepth ?? 1;\n const limit = options?.limit;\n\n // maxDepth=0 means \"no children levels\", always return empty array\n if (maxDepth === 0) {\n return { data: [] };\n }\n\n // Get immediate children\n const result = await this.listImmediate(path, options);\n let entries = result.data;\n\n // If maxDepth > 1, recursively list children of directory entries\n if (maxDepth > 1) {\n const childEntries: AFSEntry[] = [];\n for (const entry of entries) {\n if (this.isDirectoryPath(entry.path)) {\n try {\n const childResult = await this.listImmediate(entry.path, options);\n childEntries.push(...childResult.data);\n } catch {\n // Skip entries that can't be listed (e.g., leaf nodes)\n }\n }\n }\n entries = [...entries, ...childEntries];\n }\n\n return { data: this.applyLimit(entries, limit), message: result.message };\n }\n\n /**\n * Check if path is a .meta path and extract the target path\n */\n private isMetaPath(path: string): { isMeta: boolean; targetPath: string } {\n const normalized = path.replace(/\\/+$/, \"\");\n if (normalized.endsWith(\"/.meta\")) {\n return { isMeta: true, targetPath: normalized.slice(0, -6) || \"/\" };\n }\n return { isMeta: false, targetPath: path };\n }\n\n /**\n * Get entry info for a virtual directory path\n */\n private getVirtualDirectoryEntry(path: string): AFSEntry | undefined {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n // Root path\n if (segments.length === 0) {\n return this.getRootEntry();\n }\n\n // Single-repo mode: /issues, /pulls, /repo\n if (this.options.mode === \"single-repo\") {\n if (segments.length === 1) {\n const dir = this.getVirtualDirectories().find((d) => d.path === `/${segments[0]}`);\n if (dir) return dir;\n }\n }\n\n // Org mode: /{repo}, /{repo}/issues, /{repo}/pulls, /{repo}/repo\n if (this.options.mode === \"org\") {\n if (segments.length === 1) {\n // Repo root\n return {\n id: segments[0]!,\n path: `/${segments[0]}`,\n summary: `Repository: ${this.options.owner}/${segments[0]}`,\n meta: {\n childrenCount: 3,\n },\n };\n }\n if (segments.length === 2) {\n const repoName = segments[0]!;\n const dirs = this.getRepoVirtualDirectories(`/${repoName}`);\n const dir = dirs.find((d) => d.path === `/${repoName}/${segments[1]}`);\n if (dir) return dir;\n }\n }\n\n return undefined;\n }\n\n /**\n * Read a single entry\n *\n * Supports:\n * - Directory paths (returns entry info)\n * - .meta paths (returns metadata)\n * - Issue/PR paths (returns content via API)\n * - Repo file paths (returns content via Contents API)\n *\n * @throws AFSNotFoundError if path does not exist\n */\n async read(path: string, options?: AFSReadOptions): Promise<AFSReadResult> {\n // Handle /.meta/.capabilities\n if (path === \"/.meta/.capabilities\") {\n return this.readCapabilities();\n }\n\n // WORKAROUND: AFSGitHub implements AFSModule directly (not BaseProvider),\n // so it lacks automatic .actions/:name read routing. Remove if migrated to BaseProvider.\n const actionsMatch = path.match(/^(.*)\\/\\.actions\\/([^/]+)$/);\n if (actionsMatch) {\n const actionsListPath = `${actionsMatch[1] || \"\"}/.actions`;\n const actionName = actionsMatch[2];\n const actionsResult = this.listActions(actionsListPath);\n if (actionsResult) {\n const actionEntry = actionsResult.data.find((entry) => entry.id === actionName);\n if (actionEntry) {\n return { data: actionEntry };\n }\n }\n throw new AFSNotFoundError(path);\n }\n\n // Handle .meta paths\n const { isMeta, targetPath } = this.isMetaPath(path);\n if (isMeta) {\n return this.readMeta(targetPath);\n }\n\n // Handle virtual directory paths (/, /issues, /pulls, /repo)\n const virtualEntry = this.getVirtualDirectoryEntry(path);\n if (virtualEntry) {\n // For directories with unknown childrenCount (-1 or undefined), fetch the actual count\n const cc = virtualEntry.meta?.childrenCount;\n if ((cc === undefined || cc === -1) && this.isDirectoryPath(path)) {\n try {\n const children = await this.listImmediate(path);\n virtualEntry.meta = {\n ...virtualEntry.meta,\n childrenCount: children.data.length,\n };\n } catch {\n // If listing fails, keep existing childrenCount\n }\n }\n return { data: virtualEntry };\n }\n\n // Route /repo paths to Contents API\n if (this.isRepoPath(path)) {\n return this.readViaContentsAPI(path, options);\n }\n\n // Security: validate path segments for numeric IDs where expected\n if (this.options.mode === \"org\" || this.options.mode === \"single-repo\") {\n const segments = path.replace(/^\\/+|\\/+$/g, \"\").split(\"/\");\n // Check for issues/{number} or pulls/{number} pattern\n const issuesIdx = segments.indexOf(\"issues\");\n const pullsIdx = segments.indexOf(\"pulls\");\n\n if (issuesIdx !== -1 && segments[issuesIdx + 1]) {\n const issueNum = segments[issuesIdx + 1];\n if (!/^\\d+$/.test(issueNum!)) {\n throw new AFSNotFoundError(path, \"Invalid issue number\");\n }\n }\n if (pullsIdx !== -1 && segments[pullsIdx + 1]) {\n const prNum = segments[pullsIdx + 1];\n if (!/^\\d+$/.test(prNum!)) {\n throw new AFSNotFoundError(path, \"Invalid pull request number\");\n }\n }\n }\n\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) {\n throw new AFSNotFoundError(path, \"Mapping not loaded\");\n }\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved || !resolved.operations.read) {\n throw new AFSNotFoundError(path, `No read operation for path: ${fullPath}`);\n }\n\n const request = this.compiled.buildRequest(fullPath, \"read\", {});\n\n if (!request) {\n throw new AFSNotFoundError(path, \"Failed to build request\");\n }\n\n try {\n const response = await this.client.request(\n `${request.method} ${request.path}`,\n request.params as Record<string, unknown>,\n );\n\n const entries = this.compiled.projectResponse(fullPath, \"read\", response.data);\n\n if (entries.length === 0) {\n throw new AFSNotFoundError(path, \"No data returned\");\n }\n\n const entry = entries[0]!;\n\n // Adjust path based on mode\n if (this.options.mode === \"single-repo\") {\n const prefix = `/${this.options.owner}/${this.options.repo}`;\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n } else if (this.options.mode === \"org\") {\n const prefix = `/${this.options.owner}`;\n if (entry.path.startsWith(prefix)) {\n entry.path = entry.path.slice(prefix.length) || \"/\";\n }\n }\n\n return { data: entry };\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n /**\n * Read metadata for a path\n * Returns an entry with meta field containing the metadata\n *\n * @throws AFSNotFoundError if path does not exist\n */\n private async readMeta(targetPath: string): Promise<AFSReadResult> {\n const metaPath = targetPath === \"/\" ? \"/.meta\" : `${targetPath}/.meta`;\n\n // Get the entry for the target path\n const virtualEntry = this.getVirtualDirectoryEntry(targetPath);\n if (virtualEntry) {\n return {\n data: {\n id: `${virtualEntry.id}/.meta`,\n path: metaPath,\n summary: `Metadata for ${targetPath}`,\n meta: virtualEntry.meta ?? {},\n },\n };\n }\n\n // Check if this is an issue or PR path — enrich meta with labels, assignees, milestone, reactions\n const enrichedMeta = await this.getEnrichedMeta(targetPath);\n if (enrichedMeta) {\n return {\n data: {\n id: `${targetPath}/.meta`,\n path: metaPath,\n summary: `Metadata for ${targetPath}`,\n meta: enrichedMeta,\n },\n };\n }\n\n // Try to read the actual entry to get its metadata\n // This will throw AFSNotFoundError if the path doesn't exist\n const readResult = await this.read(targetPath);\n return {\n data: {\n id: `${readResult.data!.id}/.meta`,\n path: metaPath,\n summary: `Metadata for ${targetPath}`,\n meta: readResult.data!.meta ?? {},\n },\n };\n }\n\n // ============ AFSWorldMappingCapable Methods ============\n\n async loadMapping(mappingPath: string): Promise<void> {\n const compiler = new MappingCompiler();\n try {\n this.compiled = await compiler.compileDirectory(mappingPath);\n this.mappingPath = mappingPath;\n this.mappingLoadedAt = new Date();\n this.mappingError = undefined;\n } catch (error) {\n this.mappingError = error instanceof Error ? error.message : String(error);\n throw error;\n }\n }\n\n async reloadMapping(): Promise<void> {\n if (!this.mappingPath) {\n throw new Error(\"No mapping path configured\");\n }\n\n const previousCompiled = this.compiled;\n try {\n await this.loadMapping(this.mappingPath);\n } catch (error) {\n // Rollback\n this.compiled = previousCompiled;\n throw error;\n }\n }\n\n getMappingStatus(): MappingStatus {\n return {\n loaded: this.compiled !== null,\n loadedAt: this.mappingLoadedAt,\n mappingPath: this.mappingPath ?? undefined,\n compiled: this.compiled !== null,\n error: this.mappingError,\n stats: this.compiled\n ? {\n routes: this.compiled.routeCount,\n operations: this.compiled.operationCount,\n }\n : undefined,\n };\n }\n\n resolve(path: string): ExternalRef | null {\n const fullPath = this.resolvePath(path);\n\n if (!this.compiled) return null;\n\n const resolved = this.compiled.resolve(fullPath);\n if (!resolved) return null;\n\n // Determine operation type\n const operation = resolved.operations.read ?? resolved.operations.list;\n if (!operation) return null;\n\n const request = this.compiled.buildRequest(\n fullPath,\n resolved.operations.read ? \"read\" : \"list\",\n {},\n );\n\n if (!request) return null;\n\n return {\n type: \"http\",\n target: `${this.options.baseUrl}${request.path}`,\n method: request.method,\n params: { ...resolved.params, ...request.params },\n headers: request.headers,\n };\n }\n\n project(externalData: unknown, context: ProjectionContext): AFSEntry[] {\n if (!this.compiled) return [];\n\n const operationType = context.rule === \"list\" ? \"list\" : \"read\";\n return this.compiled.projectResponse(context.path, operationType, externalData);\n }\n\n async mutate(_path: string, _action: MutateAction, _payload: unknown): Promise<MutateResult> {\n // MVP: write operations not implemented yet\n return {\n success: false,\n error: \"Write operations not yet implemented\",\n };\n }\n\n // ============ Stat ============\n\n /**\n * Get metadata for a path without content.\n * Supports issues, PRs, and virtual directories.\n */\n async stat(path: string, _options?: AFSStatOptions): Promise<AFSStatResult> {\n // Parse path to determine what we're stat-ing\n const parsed = this.parseIssuePRPath(path);\n\n if (parsed?.type === \"issue\") {\n return this.statIssue(parsed.number);\n }\n\n if (parsed?.type === \"pull\") {\n return this.statPR(parsed.number);\n }\n\n // Virtual directories\n const virtualEntry = this.getVirtualDirectoryEntry(path);\n if (virtualEntry) {\n return { data: virtualEntry };\n }\n\n throw new AFSNotFoundError(path);\n }\n\n private async statIssue(issueNumber: number): Promise<AFSStatResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/issues/{issue_number}\",\n { owner, repo, issue_number: issueNumber },\n );\n\n const issue = response.data;\n return {\n data: {\n id: String(issue.number),\n path: `/issues/${issue.number}`,\n summary: issue.title as string,\n meta: {\n type: \"issue\",\n state: issue.state as string,\n title: issue.title as string,\n author: (issue.user as Record<string, unknown>)?.login as string,\n commentCount: issue.comments as number,\n labels: ((issue.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n ),\n created_at: issue.created_at as string,\n updated_at: issue.updated_at as string,\n },\n },\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(`/issues/${issueNumber}`);\n }\n throw error;\n }\n }\n\n private async statPR(prNumber: number): Promise<AFSStatResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/pulls/{pull_number}\",\n { owner, repo, pull_number: prNumber },\n );\n\n const pr = response.data;\n return {\n data: {\n id: String(pr.number),\n path: `/pulls/${pr.number}`,\n summary: pr.title as string,\n meta: {\n type: \"pull_request\",\n state: pr.state as string,\n title: pr.title as string,\n author: (pr.user as Record<string, unknown>)?.login as string,\n draft: pr.draft as boolean,\n reviewers: ((pr.requested_reviewers as Array<Record<string, unknown>>) ?? []).map(\n (r) => r.login as string,\n ),\n labels: ((pr.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n ),\n created_at: pr.created_at as string,\n updated_at: pr.updated_at as string,\n merged_at: pr.merged_at as string | null,\n },\n },\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(`/pulls/${prNumber}`);\n }\n throw error;\n }\n }\n\n // ============ Search ============\n\n /**\n * Search issues and PRs using the GitHub Search API.\n * Path determines scope: /issues searches issues, /pulls searches PRs, / searches both.\n */\n async search(path: string, query: string, options?: AFSSearchOptions): Promise<AFSSearchResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n // Sanitize query: remove newlines and potential injection characters\n const sanitizedQuery = query.replace(/[\\r\\n]+/g, \" \").replace(/ghp_[a-zA-Z0-9]+/g, \"\");\n\n // Determine search type from path\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const isPulls = normalized === \"pulls\" || normalized.endsWith(\"/pulls\");\n const isIssues = normalized === \"issues\" || normalized.endsWith(\"/issues\");\n\n // Build GitHub search query\n let q = sanitizedQuery.trim();\n q += ` repo:${owner}/${repo}`;\n if (isPulls) {\n q += \" is:pr\";\n } else if (isIssues) {\n q += \" is:issue\";\n }\n\n try {\n const response = await this.client.request<{\n total_count: number;\n items: Array<Record<string, unknown>>;\n }>(\"GET /search/issues\", {\n q: q.trim(),\n per_page: options?.limit ?? 30,\n });\n\n const entries: AFSEntry[] = response.data.items.map((item) => {\n const hasPR = \"pull_request\" in item;\n const type = hasPR ? \"pulls\" : \"issues\";\n return {\n id: String(item.number),\n path: `/${type}/${item.number}`,\n summary: item.title as string,\n meta: {\n type: hasPR ? \"pull_request\" : \"issue\",\n state: item.state as string,\n author: (item.user as Record<string, unknown>)?.login as string,\n },\n };\n });\n\n return { data: entries };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 422) {\n return { data: [], message: \"Invalid search query\" };\n }\n throw error;\n }\n }\n\n // ============ Explain ============\n\n /**\n * Provide human/LLM-readable explanation of a path.\n */\n async explain(path: string, _options?: AFSExplainOptions): Promise<AFSExplainResult> {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n\n if (normalized === \"\") {\n return this.explainRoot();\n }\n\n if (normalized === \"issues\") {\n return this.explainIssuesDir();\n }\n\n if (normalized === \"pulls\") {\n return this.explainPullsDir();\n }\n\n // Check if this is a specific issue or PR\n const parsed = this.parseIssuePRPath(path);\n if (parsed?.type === \"issue\") {\n return this.explainIssue(parsed.number);\n }\n if (parsed?.type === \"pull\") {\n return this.explainPR(parsed.number);\n }\n\n throw new AFSNotFoundError(path);\n }\n\n private async explainRoot(): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}\",\n { owner, repo },\n );\n\n const data = response.data;\n const lines: string[] = [\n `# ${data.full_name}`,\n \"\",\n data.description ? `${data.description}` : \"\",\n \"\",\n `- **Language**: ${data.language ?? \"N/A\"}`,\n `- **Stars**: ${data.stargazers_count ?? 0} ⭐`,\n `- **Forks**: ${data.forks_count ?? 0}`,\n `- **Open Issues**: ${data.open_issues_count ?? 0}`,\n `- **Default Branch**: ${data.default_branch ?? \"main\"}`,\n `- **License**: ${(data.license as Record<string, unknown>)?.spdx_id ?? \"N/A\"}`,\n `- **Visibility**: ${data.private ? \"Private\" : \"Public\"}`,\n \"\",\n \"## Structure\",\n \"\",\n \"- `/issues` — Repository issues\",\n \"- `/pulls` — Pull requests\",\n \"- `/repo` — Repository source code\",\n ];\n\n const topics = data.topics as string[] | undefined;\n if (topics && topics.length > 0) {\n lines.push(\"\", `**Topics**: ${topics.join(\", \")}`);\n }\n\n return {\n format: \"markdown\",\n content: lines.filter((l) => l !== undefined).join(\"\\n\"),\n };\n }\n\n private async explainIssuesDir(): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n // Fetch open and closed counts using search API\n const [openResult, closedResult] = await Promise.all([\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:issue is:open`,\n per_page: 1,\n }),\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:issue is:closed`,\n per_page: 1,\n }),\n ]);\n\n const openCount = openResult.data.total_count;\n const closedCount = closedResult.data.total_count;\n\n return {\n format: \"markdown\",\n content: [\n `# Issues — ${owner}/${repo}`,\n \"\",\n `- **Open**: ${openCount}`,\n `- **Closed**: ${closedCount}`,\n `- **Total**: ${openCount + closedCount}`,\n \"\",\n \"Use `list /issues` to browse issues.\",\n \"Use `search /issues <query>` to find specific issues.\",\n ].join(\"\\n\"),\n };\n }\n\n private async explainPullsDir(): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n const [openResult, closedResult, mergedResult] = await Promise.all([\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:pr is:open`,\n per_page: 1,\n }),\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:pr is:closed`,\n per_page: 1,\n }),\n this.client.request<{ total_count: number }>(\"GET /search/issues\", {\n q: `repo:${owner}/${repo} is:pr is:merged`,\n per_page: 1,\n }),\n ]);\n\n const openCount = openResult.data.total_count;\n const closedCount = closedResult.data.total_count;\n const mergedCount = mergedResult.data.total_count;\n\n return {\n format: \"markdown\",\n content: [\n `# Pull Requests — ${owner}/${repo}`,\n \"\",\n `- **Open**: ${openCount}`,\n `- **Closed**: ${closedCount}`,\n `- **Merged**: ${mergedCount}`,\n \"\",\n \"Use `list /pulls` to browse pull requests.\",\n \"Use `search /pulls <query>` to find specific PRs.\",\n ].join(\"\\n\"),\n };\n }\n\n private async explainIssue(issueNumber: number): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/issues/{issue_number}\",\n { owner, repo, issue_number: issueNumber },\n );\n\n const issue = response.data;\n const labels = ((issue.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n );\n const assignees = ((issue.assignees as Array<Record<string, unknown>>) ?? []).map(\n (a) => a.login as string,\n );\n\n return {\n format: \"markdown\",\n content: [\n `# Issue #${issue.number}: ${issue.title}`,\n \"\",\n `- **State**: ${issue.state}`,\n `- **Author**: ${(issue.user as Record<string, unknown>)?.login}`,\n `- **Created**: ${issue.created_at}`,\n `- **Updated**: ${issue.updated_at}`,\n labels.length > 0 ? `- **Labels**: ${labels.join(\", \")}` : null,\n assignees.length > 0 ? `- **Assignees**: ${assignees.join(\", \")}` : null,\n `- **Comments**: ${issue.comments}`,\n ]\n .filter((l) => l !== null)\n .join(\"\\n\"),\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(`/issues/${issueNumber}`);\n }\n throw error;\n }\n }\n\n private async explainPR(prNumber: number): Promise<AFSExplainResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/pulls/{pull_number}\",\n { owner, repo, pull_number: prNumber },\n );\n\n const pr = response.data;\n const labels = ((pr.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n );\n const reviewers = ((pr.requested_reviewers as Array<Record<string, unknown>>) ?? []).map(\n (r) => r.login as string,\n );\n\n return {\n format: \"markdown\",\n content: [\n `# PR #${pr.number}: ${pr.title}`,\n \"\",\n `- **State**: ${pr.state}${pr.draft ? \" (draft)\" : \"\"}`,\n `- **Author**: ${(pr.user as Record<string, unknown>)?.login}`,\n `- **Created**: ${pr.created_at}`,\n `- **Updated**: ${pr.updated_at}`,\n pr.merged_at ? `- **Merged**: ${pr.merged_at}` : null,\n labels.length > 0 ? `- **Labels**: ${labels.join(\", \")}` : null,\n reviewers.length > 0 ? `- **Reviewers**: ${reviewers.join(\", \")}` : null,\n `- **Head**: ${(pr.head as Record<string, unknown>)?.ref} → **Base**: ${(pr.base as Record<string, unknown>)?.ref}`,\n ]\n .filter((l) => l !== null)\n .join(\"\\n\"),\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(`/pulls/${prNumber}`);\n }\n throw error;\n }\n }\n\n // ============ Capabilities ============\n\n private async readCapabilities(): Promise<AFSReadResult> {\n const operations: OperationsDeclaration = {\n read: true,\n list: true,\n write: false,\n delete: false,\n search: true,\n exec: true,\n stat: true,\n explain: true,\n };\n\n const manifest: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: this.name,\n description: this.description ?? `GitHub: ${this.options.owner}/${this.options.repo}`,\n tools: [],\n operations,\n actions: [\n {\n kind: \"github:issue\",\n description: \"Issue lifecycle actions\",\n catalog: [\n { name: \"close-issue\", description: \"Close an issue\" },\n { name: \"reopen-issue\", description: \"Reopen a closed issue\" },\n { name: \"add-comment\", description: \"Add a comment to an issue\" },\n { name: \"add-label\", description: \"Add a label to an issue\" },\n { name: \"remove-label\", description: \"Remove a label from an issue\" },\n ],\n discovery: { pathTemplate: \"/issues/:number/.actions\" },\n },\n {\n kind: \"github:pull_request\",\n description: \"Pull request lifecycle actions\",\n catalog: [\n { name: \"merge-pr\", description: \"Merge a pull request\" },\n { name: \"approve-pr\", description: \"Approve a pull request\" },\n { name: \"request-changes\", description: \"Request changes on a pull request\" },\n { name: \"add-comment\", description: \"Add a comment to a pull request\" },\n { name: \"add-label\", description: \"Add a label to a pull request\" },\n { name: \"remove-label\", description: \"Remove a label from a pull request\" },\n ],\n discovery: { pathTemplate: \"/pulls/:number/.actions\" },\n },\n {\n kind: \"github:repo\",\n description: \"Repository file operations\",\n catalog: [\n { name: \"read-file\", description: \"Read a file from the repository\" },\n { name: \"write-file\", description: \"Write a file to the repository\" },\n { name: \"create-branch\", description: \"Create a new branch\" },\n ],\n discovery: { pathTemplate: \"/repo/:branch/.actions\" },\n },\n ],\n };\n\n return {\n data: {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n summary: \"Provider capabilities manifest\",\n content: manifest as unknown as string,\n },\n };\n }\n\n // ============ Enriched Meta ============\n\n /**\n * Get enriched metadata for an issue or PR path.\n * Returns labels, assignees, milestone, reactions from GitHub API.\n */\n private async getEnrichedMeta(path: string): Promise<Record<string, unknown> | null> {\n const parsed = this.parseIssuePRPath(path);\n if (!parsed) return null;\n\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n if (parsed.type === \"issue\") {\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/issues/{issue_number}\",\n { owner, repo, issue_number: parsed.number },\n );\n\n const issue = response.data;\n return {\n type: \"issue\",\n state: issue.state,\n author: (issue.user as Record<string, unknown>)?.login,\n labels: ((issue.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n ),\n assignees: ((issue.assignees as Array<Record<string, unknown>>) ?? []).map(\n (a) => a.login as string,\n ),\n milestone: (issue.milestone as Record<string, unknown>)?.title ?? null,\n reactions: issue.reactions\n ? this.extractReactions(issue.reactions as Record<string, unknown>)\n : this.zeroReactions(),\n commentCount: issue.comments,\n created_at: issue.created_at,\n updated_at: issue.updated_at,\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n if (parsed.type === \"pull\") {\n try {\n const response = await this.client.request<Record<string, unknown>>(\n \"GET /repos/{owner}/{repo}/pulls/{pull_number}\",\n { owner, repo, pull_number: parsed.number },\n );\n\n const pr = response.data;\n return {\n type: \"pull_request\",\n state: pr.state,\n author: (pr.user as Record<string, unknown>)?.login,\n draft: pr.draft,\n labels: ((pr.labels as Array<Record<string, unknown>>) ?? []).map(\n (l) => l.name as string,\n ),\n assignees: ((pr.assignees as Array<Record<string, unknown>>) ?? []).map(\n (a) => a.login as string,\n ),\n milestone: (pr.milestone as Record<string, unknown>)?.title ?? null,\n reactions: pr.reactions\n ? this.extractReactions(pr.reactions as Record<string, unknown>)\n : this.zeroReactions(),\n reviewers: ((pr.requested_reviewers as Array<Record<string, unknown>>) ?? []).map(\n (r) => r.login as string,\n ),\n commentCount: pr.comments,\n merged_at: pr.merged_at,\n created_at: pr.created_at,\n updated_at: pr.updated_at,\n };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n throw new AFSNotFoundError(path);\n }\n throw error;\n }\n }\n\n return null;\n }\n\n private extractReactions(reactions: Record<string, unknown>): Record<string, number> {\n return {\n \"+1\": (reactions[\"+1\"] as number) ?? 0,\n \"-1\": (reactions[\"-1\"] as number) ?? 0,\n laugh: (reactions.laugh as number) ?? 0,\n hooray: (reactions.hooray as number) ?? 0,\n confused: (reactions.confused as number) ?? 0,\n heart: (reactions.heart as number) ?? 0,\n rocket: (reactions.rocket as number) ?? 0,\n eyes: (reactions.eyes as number) ?? 0,\n };\n }\n\n private zeroReactions(): Record<string, number> {\n return {\n \"+1\": 0,\n \"-1\": 0,\n laugh: 0,\n hooray: 0,\n confused: 0,\n heart: 0,\n rocket: 0,\n eyes: 0,\n };\n }\n\n // ============ Path Parsing Helpers ============\n\n /**\n * Parse a path to determine if it's an issue or PR path.\n * Returns { type, number } or null.\n */\n private parseIssuePRPath(path: string): { type: \"issue\" | \"pull\"; number: number } | null {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n const segments = normalized.split(\"/\").filter(Boolean);\n\n if (this.options.mode === \"single-repo\") {\n // /issues/{number} or /pulls/{number}\n if (segments.length === 2 && segments[0] === \"issues\" && /^\\d+$/.test(segments[1]!)) {\n return { type: \"issue\", number: Number.parseInt(segments[1]!, 10) };\n }\n if (segments.length === 2 && segments[0] === \"pulls\" && /^\\d+$/.test(segments[1]!)) {\n return { type: \"pull\", number: Number.parseInt(segments[1]!, 10) };\n }\n } else if (this.options.mode === \"org\") {\n // /{repo}/issues/{number} or /{repo}/pulls/{number}\n if (segments.length === 3 && segments[1] === \"issues\" && /^\\d+$/.test(segments[2]!)) {\n return { type: \"issue\", number: Number.parseInt(segments[2]!, 10) };\n }\n if (segments.length === 3 && segments[1] === \"pulls\" && /^\\d+$/.test(segments[2]!)) {\n return { type: \"pull\", number: Number.parseInt(segments[2]!, 10) };\n }\n }\n\n return null;\n }\n\n // ============ Actions: List ============\n\n /**\n * List available actions at a path.\n * Returns null if the path is not an .actions path.\n */\n private listActions(path: string): AFSListResult | null {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n\n // Root actions: /.actions\n if (normalized === \".actions\") {\n return {\n data: [\n {\n id: \"create-issue\",\n path: \"/.actions/create-issue\",\n summary: \"Create a new issue\",\n meta: { kind: \"afs:executable\", name: \"create-issue\" },\n },\n {\n id: \"create-pr\",\n path: \"/.actions/create-pr\",\n summary: \"Create a new pull request\",\n meta: { kind: \"afs:executable\", name: \"create-pr\" },\n },\n {\n id: \"create-file\",\n path: \"/.actions/create-file\",\n summary: \"Create a file in the repository\",\n meta: { kind: \"afs:executable\", name: \"create-file\" },\n },\n {\n id: \"update-file\",\n path: \"/.actions/update-file\",\n summary: \"Update a file in the repository\",\n meta: { kind: \"afs:executable\", name: \"update-file\" },\n },\n ],\n };\n }\n\n // Issue actions: /issues/{number}/.actions\n const issueActionsMatch = normalized.match(/^issues\\/(\\d+)\\/\\.actions$/);\n if (issueActionsMatch) {\n const num = issueActionsMatch[1];\n return {\n data: [\n {\n id: \"close-issue\",\n path: `/issues/${num}/.actions/close-issue`,\n summary: \"Close this issue\",\n meta: { kind: \"afs:executable\", name: \"close-issue\" },\n },\n {\n id: \"reopen-issue\",\n path: `/issues/${num}/.actions/reopen-issue`,\n summary: \"Reopen this issue\",\n meta: { kind: \"afs:executable\", name: \"reopen-issue\" },\n },\n {\n id: \"add-comment\",\n path: `/issues/${num}/.actions/add-comment`,\n summary: \"Add a comment\",\n meta: { kind: \"afs:executable\", name: \"add-comment\" },\n },\n {\n id: \"add-label\",\n path: `/issues/${num}/.actions/add-label`,\n summary: \"Add a label\",\n meta: { kind: \"afs:executable\", name: \"add-label\" },\n },\n {\n id: \"remove-label\",\n path: `/issues/${num}/.actions/remove-label`,\n summary: \"Remove a label\",\n meta: { kind: \"afs:executable\", name: \"remove-label\" },\n },\n ],\n };\n }\n\n // PR actions: /pulls/{number}/.actions\n const prActionsMatch = normalized.match(/^pulls\\/(\\d+)\\/\\.actions$/);\n if (prActionsMatch) {\n const num = prActionsMatch[1];\n return {\n data: [\n {\n id: \"merge-pr\",\n path: `/pulls/${num}/.actions/merge-pr`,\n summary: \"Merge this pull request\",\n meta: { kind: \"afs:executable\", name: \"merge-pr\" },\n },\n {\n id: \"request-review\",\n path: `/pulls/${num}/.actions/request-review`,\n summary: \"Request a review\",\n meta: { kind: \"afs:executable\", name: \"request-review\" },\n },\n {\n id: \"add-comment\",\n path: `/pulls/${num}/.actions/add-comment`,\n summary: \"Add a comment\",\n meta: { kind: \"afs:executable\", name: \"add-comment\" },\n },\n {\n id: \"add-label\",\n path: `/pulls/${num}/.actions/add-label`,\n summary: \"Add a label\",\n meta: { kind: \"afs:executable\", name: \"add-label\" },\n },\n {\n id: \"remove-label\",\n path: `/pulls/${num}/.actions/remove-label`,\n summary: \"Remove a label\",\n meta: { kind: \"afs:executable\", name: \"remove-label\" },\n },\n ],\n };\n }\n\n return null;\n }\n\n // ============ Actions: Exec ============\n\n /**\n * Execute an action at a path.\n * Path format: /{resource}/.actions/{action-name}\n */\n async exec(\n path: string,\n args: Record<string, unknown>,\n _options: AFSExecOptions,\n ): Promise<AFSExecResult> {\n if (this.accessMode === \"readonly\") {\n throw new AFSReadonlyError(\"Cannot exec on a readonly provider\");\n }\n\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n\n // Parse: {prefix}/.actions/{actionName}\n // Handle both \"prefix/.actions/name\" and \".actions/name\" (root)\n const actionMatch = normalized.match(/^(?:(.+)\\/)?\\.actions\\/([^/]+)$/);\n if (!actionMatch) {\n return {\n success: false,\n error: { code: \"INVALID_PATH\", message: `Invalid action path: ${path}` },\n };\n }\n\n const resourcePath = actionMatch[1] || \"\";\n const actionName = actionMatch[2]!;\n\n try {\n // Route to appropriate action handler\n // Root actions\n if (resourcePath === \"\") {\n return await this.execRootAction(actionName, args);\n }\n\n // Issue actions: issues/{number}\n const issueMatch = resourcePath.match(/^issues\\/(\\d+)$/);\n if (issueMatch) {\n const issueNumber = Number.parseInt(issueMatch[1]!, 10);\n return await this.execIssueAction(issueNumber, actionName, args);\n }\n\n // PR actions: pulls/{number}\n const prMatch = resourcePath.match(/^pulls\\/(\\d+)$/);\n if (prMatch) {\n const prNumber = Number.parseInt(prMatch[1]!, 10);\n return await this.execPRAction(prNumber, actionName, args);\n }\n\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `No actions for path: /${resourcePath}` },\n };\n } catch (error) {\n return this.handleExecError(error);\n }\n }\n\n private async execRootAction(\n actionName: string,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n switch (actionName) {\n case \"create-issue\": {\n const title = args.title as string | undefined;\n if (!title) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"title is required\" },\n };\n }\n const response = await this.client.request(\"POST /repos/{owner}/{repo}/issues\", {\n owner,\n repo,\n title,\n body: (args.body as string) ?? undefined,\n labels: (args.labels as string[]) ?? undefined,\n assignees: (args.assignees as string[]) ?? undefined,\n });\n const issue = response.data as Record<string, unknown>;\n return {\n success: true,\n data: {\n number: issue.number as number,\n url: issue.html_url as string,\n },\n };\n }\n\n case \"create-pr\": {\n const title = args.title as string | undefined;\n const head = args.head as string | undefined;\n const base = args.base as string | undefined;\n if (!title || !head || !base) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"title, head, and base are required\" },\n };\n }\n if (head === base) {\n return {\n success: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"head and base must be different branches\",\n },\n };\n }\n const response = await this.client.request(\"POST /repos/{owner}/{repo}/pulls\", {\n owner,\n repo,\n title,\n body: (args.body as string) ?? undefined,\n head,\n base,\n draft: (args.draft as boolean) ?? false,\n });\n const pr = response.data as Record<string, unknown>;\n return {\n success: true,\n data: {\n number: pr.number as number,\n url: pr.html_url as string,\n },\n };\n }\n\n case \"create-file\": {\n const filePath = args.path as string | undefined;\n if (!filePath) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"path is required\" },\n };\n }\n // Security: validate path against traversal\n if (filePath.includes(\"..\") || filePath.startsWith(\"/\")) {\n return {\n success: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"path must not contain '..' or start with '/'\",\n },\n };\n }\n const content = (args.content as string) ?? \"\";\n const message = (args.message as string) ?? `Create ${filePath}`;\n const response = await this.client.request(\"PUT /repos/{owner}/{repo}/contents/{path}\", {\n owner,\n repo,\n path: filePath,\n message,\n content: Buffer.from(content).toString(\"base64\"),\n branch: (args.branch as string) ?? undefined,\n });\n const result = response.data as Record<string, unknown>;\n const fileInfo = result.content as Record<string, unknown> | undefined;\n const commitInfo = result.commit as Record<string, unknown> | undefined;\n return {\n success: true,\n data: {\n sha: fileInfo?.sha as string,\n commitSha: commitInfo?.sha as string,\n },\n };\n }\n\n case \"update-file\": {\n const filePath = args.path as string | undefined;\n const sha = args.sha as string | undefined;\n if (!filePath) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"path is required\" },\n };\n }\n if (!sha) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"sha is required (optimistic lock)\" },\n };\n }\n if (filePath.includes(\"..\") || filePath.startsWith(\"/\")) {\n return {\n success: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"path must not contain '..' or start with '/'\",\n },\n };\n }\n const content = (args.content as string) ?? \"\";\n const message = (args.message as string) ?? `Update ${filePath}`;\n const response = await this.client.request(\"PUT /repos/{owner}/{repo}/contents/{path}\", {\n owner,\n repo,\n path: filePath,\n message,\n content: Buffer.from(content).toString(\"base64\"),\n sha,\n branch: (args.branch as string) ?? undefined,\n });\n const result = response.data as Record<string, unknown>;\n const fileInfo = result.content as Record<string, unknown> | undefined;\n const commitInfo = result.commit as Record<string, unknown> | undefined;\n return {\n success: true,\n data: {\n sha: fileInfo?.sha as string,\n commitSha: commitInfo?.sha as string,\n },\n };\n }\n\n default:\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Unknown action: ${actionName}` },\n };\n }\n }\n\n private async execIssueAction(\n issueNumber: number,\n actionName: string,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n switch (actionName) {\n case \"close-issue\": {\n const response = await this.client.request(\n \"PATCH /repos/{owner}/{repo}/issues/{issue_number}\",\n {\n owner,\n repo,\n issue_number: issueNumber,\n state: \"closed\",\n state_reason: (args.reason as string) ?? undefined,\n },\n );\n const issue = response.data as Record<string, unknown>;\n return {\n success: true,\n data: { state: issue.state as string },\n };\n }\n\n case \"reopen-issue\": {\n const response = await this.client.request(\n \"PATCH /repos/{owner}/{repo}/issues/{issue_number}\",\n {\n owner,\n repo,\n issue_number: issueNumber,\n state: \"open\",\n },\n );\n const issue = response.data as Record<string, unknown>;\n return {\n success: true,\n data: { state: issue.state as string },\n };\n }\n\n case \"add-comment\": {\n const body = args.body as string | undefined;\n if (!body) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"body is required\" },\n };\n }\n const response = await this.client.request(\n \"POST /repos/{owner}/{repo}/issues/{issue_number}/comments\",\n {\n owner,\n repo,\n issue_number: issueNumber,\n body,\n },\n );\n const comment = response.data as Record<string, unknown>;\n return {\n success: true,\n data: { id: comment.id as number },\n };\n }\n\n case \"add-label\": {\n const label = args.label as string | undefined;\n if (!label) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"label is required\" },\n };\n }\n if (label.length > 200) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"label name exceeds maximum length (200)\" },\n };\n }\n await this.client.request(\"POST /repos/{owner}/{repo}/issues/{issue_number}/labels\", {\n owner,\n repo,\n issue_number: issueNumber,\n labels: [label],\n });\n return { success: true, data: { label } };\n }\n\n case \"remove-label\": {\n const label = args.label as string | undefined;\n if (!label) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"label is required\" },\n };\n }\n try {\n await this.client.request(\n \"DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}\",\n {\n owner,\n repo,\n issue_number: issueNumber,\n name: label,\n },\n );\n return { success: true, data: { label } };\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Label \"${label}\" not found` },\n };\n }\n throw error;\n }\n }\n\n default:\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Unknown issue action: ${actionName}` },\n };\n }\n }\n\n private async execPRAction(\n prNumber: number,\n actionName: string,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const owner = this.options.owner!;\n const repo = this.options.repo!;\n\n switch (actionName) {\n case \"merge-pr\": {\n const method = (args.method as string) ?? \"merge\";\n const response = await this.client.request(\n \"PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge\",\n {\n owner,\n repo,\n pull_number: prNumber,\n merge_method: method,\n commit_title: (args.commitTitle as string) ?? undefined,\n commit_message: (args.commitMessage as string) ?? undefined,\n },\n );\n const result = response.data as Record<string, unknown>;\n return {\n success: true,\n data: {\n merged: result.merged as boolean,\n sha: result.sha as string,\n },\n };\n }\n\n case \"request-review\": {\n const reviewers = args.reviewers as string[] | undefined;\n if (!reviewers || reviewers.length === 0) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: \"reviewers is required\" },\n };\n }\n await this.client.request(\n \"POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers\",\n {\n owner,\n repo,\n pull_number: prNumber,\n reviewers,\n },\n );\n return { success: true, data: { reviewers } };\n }\n\n case \"add-comment\": {\n // PRs use the issues API for comments\n return this.execIssueAction(prNumber, \"add-comment\", args);\n }\n\n case \"add-label\": {\n return this.execIssueAction(prNumber, \"add-label\", args);\n }\n\n case \"remove-label\": {\n return this.execIssueAction(prNumber, \"remove-label\", args);\n }\n\n default:\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Unknown PR action: ${actionName}` },\n };\n }\n }\n\n /**\n * Handle errors from action execution.\n * Sanitizes error messages to prevent token leaks.\n */\n private handleExecError(error: unknown): AFSExecResult {\n const status = (error as { status?: number })?.status;\n const message = error instanceof Error ? error.message : String(error);\n const sanitized = message.replace(/ghp_[a-zA-Z0-9]+/g, \"[REDACTED]\");\n\n if (status === 403) {\n return {\n success: false,\n error: {\n code: \"FORBIDDEN\",\n message: `Insufficient permissions. Check that your token has the required access.`,\n },\n };\n }\n\n if (status === 404) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Resource not found: ${sanitized}` },\n };\n }\n\n if (status === 405 || status === 409) {\n return {\n success: false,\n error: { code: \"CONFLICT\", message: sanitized },\n };\n }\n\n if (status === 422) {\n return {\n success: false,\n error: { code: \"VALIDATION_ERROR\", message: sanitized },\n };\n }\n\n return {\n success: false,\n error: { code: \"INTERNAL_ERROR\", message: sanitized },\n };\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/afs-github",
|
|
3
|
-
"version": "1.11.0-beta.
|
|
3
|
+
"version": "1.11.0-beta.8",
|
|
4
4
|
"description": "AFS GitHub Provider - Access GitHub Issues, PRs, and Actions as AFS paths",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"publishConfig": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"@octokit/plugin-retry": "^7.2.1",
|
|
37
37
|
"@octokit/plugin-throttling": "^9.6.1",
|
|
38
38
|
"@octokit/rest": "^21.1.1",
|
|
39
|
-
"zod": "^
|
|
40
|
-
"@aigne/afs": "^1.11.0-beta.
|
|
41
|
-
"@aigne/afs
|
|
42
|
-
"@aigne/afs-world-mapping": "^1.11.0-beta.
|
|
39
|
+
"zod": "^4.0.0",
|
|
40
|
+
"@aigne/afs-mapping": "^1.11.0-beta.8",
|
|
41
|
+
"@aigne/afs": "^1.11.0-beta.8",
|
|
42
|
+
"@aigne/afs-world-mapping": "^1.11.0-beta.8"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/bun": "^1.3.6",
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"rimraf": "^6.1.2",
|
|
48
48
|
"tsdown": "0.20.0-beta.3",
|
|
49
49
|
"typescript": "5.9.2",
|
|
50
|
-
"@aigne/afs-testing": "1.11.0-beta.
|
|
51
|
-
"@aigne/
|
|
52
|
-
"@aigne/
|
|
50
|
+
"@aigne/afs-testing": "1.11.0-beta.8",
|
|
51
|
+
"@aigne/typescript-config": "0.0.0",
|
|
52
|
+
"@aigne/scripts": "0.0.0"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "tsdown",
|