@sudocode-ai/integration-github 0.1.14

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.
@@ -0,0 +1,153 @@
1
+ /**
2
+ * GitHub CLI (gh) wrapper for API calls
3
+ *
4
+ * Uses the `gh` CLI for authentication and API requests.
5
+ * This avoids managing tokens directly - users authenticate via `gh auth login`.
6
+ */
7
+ /**
8
+ * Error thrown when gh CLI is not authenticated
9
+ */
10
+ export declare class GhAuthError extends Error {
11
+ constructor(message?: string);
12
+ }
13
+ /**
14
+ * Error thrown when a GitHub resource is not found
15
+ */
16
+ export declare class GhNotFoundError extends Error {
17
+ constructor(resource: string);
18
+ }
19
+ /**
20
+ * Error thrown when rate limited by GitHub API
21
+ */
22
+ export declare class GhRateLimitError extends Error {
23
+ constructor(retryAfter?: number);
24
+ retryAfter?: number;
25
+ }
26
+ /**
27
+ * Error thrown when gh CLI is not installed
28
+ */
29
+ export declare class GhNotInstalledError extends Error {
30
+ constructor();
31
+ }
32
+ /**
33
+ * Options for gh API calls
34
+ */
35
+ export interface GhApiOptions {
36
+ /** HTTP method (default: GET) */
37
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
38
+ /** Request body for POST/PUT/PATCH */
39
+ body?: Record<string, unknown>;
40
+ /** Additional headers */
41
+ headers?: Record<string, string>;
42
+ }
43
+ /**
44
+ * Execute a gh api command and parse JSON response
45
+ *
46
+ * @param endpoint - API endpoint (e.g., "/repos/owner/repo/issues/123")
47
+ * @param options - Optional API options
48
+ * @returns Parsed JSON response
49
+ */
50
+ export declare function ghApi<T>(endpoint: string, options?: GhApiOptions): Promise<T>;
51
+ /**
52
+ * Check if gh CLI is authenticated
53
+ *
54
+ * @returns true if authenticated, false otherwise
55
+ */
56
+ export declare function ghAuthStatus(): Promise<boolean>;
57
+ /**
58
+ * Check if gh CLI is installed and available
59
+ *
60
+ * @returns true if gh CLI is available
61
+ */
62
+ export declare function isGhInstalled(): Promise<boolean>;
63
+ /**
64
+ * Get the authenticated user's login
65
+ *
66
+ * @returns GitHub username or null if not authenticated
67
+ */
68
+ export declare function getAuthenticatedUser(): Promise<string | null>;
69
+ /**
70
+ * GitHub user/author from API
71
+ */
72
+ export interface GitHubUser {
73
+ login: string;
74
+ id: number;
75
+ avatar_url: string;
76
+ html_url: string;
77
+ }
78
+ /**
79
+ * GitHub label from API
80
+ */
81
+ export interface GitHubLabel {
82
+ id: number;
83
+ name: string;
84
+ color: string;
85
+ description?: string;
86
+ }
87
+ /**
88
+ * GitHub issue from API
89
+ */
90
+ export interface GitHubIssue {
91
+ id: number;
92
+ number: number;
93
+ title: string;
94
+ body: string | null;
95
+ state: "open" | "closed";
96
+ state_reason?: "completed" | "not_planned" | "reopened" | null;
97
+ html_url: string;
98
+ user: GitHubUser | null;
99
+ labels: GitHubLabel[];
100
+ comments: number;
101
+ created_at: string;
102
+ updated_at: string;
103
+ closed_at: string | null;
104
+ /** Present only on pull requests - used to filter them out */
105
+ pull_request?: {
106
+ url: string;
107
+ };
108
+ }
109
+ /**
110
+ * GitHub issue comment from API
111
+ */
112
+ export interface GitHubComment {
113
+ id: number;
114
+ body: string;
115
+ user: GitHubUser | null;
116
+ html_url: string;
117
+ created_at: string;
118
+ updated_at: string;
119
+ }
120
+ /**
121
+ * GitHub discussion from API (GraphQL structure)
122
+ */
123
+ export interface GitHubDiscussion {
124
+ id: string;
125
+ number: number;
126
+ title: string;
127
+ body: string;
128
+ url: string;
129
+ author: {
130
+ login: string;
131
+ } | null;
132
+ category: {
133
+ name: string;
134
+ };
135
+ comments: {
136
+ totalCount: number;
137
+ };
138
+ createdAt: string;
139
+ updatedAt: string;
140
+ }
141
+ /**
142
+ * GitHub discussion comment from GraphQL
143
+ */
144
+ export interface GitHubDiscussionComment {
145
+ id: string;
146
+ body: string;
147
+ author: {
148
+ login: string;
149
+ } | null;
150
+ url: string;
151
+ createdAt: string;
152
+ }
153
+ //# sourceMappingURL=gh-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh-client.d.ts","sourceRoot":"","sources":["../src/gh-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * GitHub CLI (gh) wrapper for API calls
3
+ *
4
+ * Uses the `gh` CLI for authentication and API requests.
5
+ * This avoids managing tokens directly - users authenticate via `gh auth login`.
6
+ */
7
+ import { exec } from "child_process";
8
+ import { promisify } from "util";
9
+ const execAsync = promisify(exec);
10
+ /**
11
+ * Error thrown when gh CLI is not authenticated
12
+ */
13
+ export class GhAuthError extends Error {
14
+ constructor(message = "GitHub CLI not authenticated. Run: gh auth login") {
15
+ super(message);
16
+ this.name = "GhAuthError";
17
+ }
18
+ }
19
+ /**
20
+ * Error thrown when a GitHub resource is not found
21
+ */
22
+ export class GhNotFoundError extends Error {
23
+ constructor(resource) {
24
+ super(`GitHub resource not found: ${resource}`);
25
+ this.name = "GhNotFoundError";
26
+ }
27
+ }
28
+ /**
29
+ * Error thrown when rate limited by GitHub API
30
+ */
31
+ export class GhRateLimitError extends Error {
32
+ constructor(retryAfter) {
33
+ super(retryAfter
34
+ ? `GitHub API rate limit exceeded. Retry after ${retryAfter} seconds.`
35
+ : "GitHub API rate limit exceeded.");
36
+ this.name = "GhRateLimitError";
37
+ this.retryAfter = retryAfter;
38
+ }
39
+ retryAfter;
40
+ }
41
+ /**
42
+ * Error thrown when gh CLI is not installed
43
+ */
44
+ export class GhNotInstalledError extends Error {
45
+ constructor() {
46
+ super("GitHub CLI (gh) is not installed. Install from: https://cli.github.com/");
47
+ this.name = "GhNotInstalledError";
48
+ }
49
+ }
50
+ /**
51
+ * Execute a gh CLI command and return the output
52
+ *
53
+ * @param args - Arguments to pass to gh
54
+ * @returns Command output
55
+ * @throws GhNotInstalledError if gh is not installed
56
+ * @throws GhAuthError if not authenticated
57
+ */
58
+ async function execGh(args) {
59
+ const command = `gh ${args.join(" ")}`;
60
+ try {
61
+ const { stdout } = await execAsync(command, {
62
+ maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large responses
63
+ });
64
+ return stdout;
65
+ }
66
+ catch (error) {
67
+ const execError = error;
68
+ const stderr = execError.stderr || execError.message || "";
69
+ // Check for common error conditions
70
+ if (stderr.includes("command not found") || stderr.includes("not recognized")) {
71
+ throw new GhNotInstalledError();
72
+ }
73
+ if (stderr.includes("not logged in") ||
74
+ stderr.includes("authentication") ||
75
+ stderr.includes("gh auth login")) {
76
+ throw new GhAuthError();
77
+ }
78
+ if (stderr.includes("404") || stderr.includes("Not Found")) {
79
+ throw new GhNotFoundError(args.join(" "));
80
+ }
81
+ if (stderr.includes("rate limit") || stderr.includes("403")) {
82
+ // Try to extract retry-after from error
83
+ const retryMatch = stderr.match(/retry after (\d+)/i);
84
+ const retryAfter = retryMatch ? parseInt(retryMatch[1], 10) : undefined;
85
+ throw new GhRateLimitError(retryAfter);
86
+ }
87
+ // Re-throw with better context
88
+ throw new Error(`gh command failed: ${stderr}`);
89
+ }
90
+ }
91
+ /**
92
+ * Execute a gh api command and parse JSON response
93
+ *
94
+ * @param endpoint - API endpoint (e.g., "/repos/owner/repo/issues/123")
95
+ * @param options - Optional API options
96
+ * @returns Parsed JSON response
97
+ */
98
+ export async function ghApi(endpoint, options) {
99
+ const args = ["api"];
100
+ // Add method if not GET
101
+ if (options?.method && options.method !== "GET") {
102
+ args.push("-X", options.method);
103
+ }
104
+ // Add headers
105
+ if (options?.headers) {
106
+ for (const [key, value] of Object.entries(options.headers)) {
107
+ args.push("-H", `${key}: ${value}`);
108
+ }
109
+ }
110
+ // Add body for POST/PUT/PATCH
111
+ if (options?.body) {
112
+ args.push("-f", JSON.stringify(options.body));
113
+ }
114
+ // Add endpoint (escape special characters)
115
+ args.push(`"${endpoint}"`);
116
+ const output = await execGh(args);
117
+ return JSON.parse(output);
118
+ }
119
+ /**
120
+ * Check if gh CLI is authenticated
121
+ *
122
+ * @returns true if authenticated, false otherwise
123
+ */
124
+ export async function ghAuthStatus() {
125
+ try {
126
+ await execGh(["auth", "status"]);
127
+ return true;
128
+ }
129
+ catch (error) {
130
+ if (error instanceof GhNotInstalledError) {
131
+ throw error; // Re-throw if not installed
132
+ }
133
+ return false;
134
+ }
135
+ }
136
+ /**
137
+ * Check if gh CLI is installed and available
138
+ *
139
+ * @returns true if gh CLI is available
140
+ */
141
+ export async function isGhInstalled() {
142
+ try {
143
+ await execGh(["--version"]);
144
+ return true;
145
+ }
146
+ catch {
147
+ return false;
148
+ }
149
+ }
150
+ /**
151
+ * Get the authenticated user's login
152
+ *
153
+ * @returns GitHub username or null if not authenticated
154
+ */
155
+ export async function getAuthenticatedUser() {
156
+ try {
157
+ const output = await execGh(["auth", "status", "-t"]);
158
+ const match = output.match(/Logged in to github\.com account (\S+)/);
159
+ return match ? match[1] : null;
160
+ }
161
+ catch {
162
+ return null;
163
+ }
164
+ }
165
+ //# sourceMappingURL=gh-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh-client.js","sourceRoot":"","sources":["../src/gh-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * GitHub Integration Plugin for sudocode
3
+ *
4
+ * Provides on-demand import of GitHub issues and discussions into sudocode specs.
5
+ * Uses the `gh` CLI for authentication and API calls - no token management required.
6
+ */
7
+ import type { IntegrationPlugin, IntegrationProvider, OnDemandImportCapable, ExternalEntity, ExternalComment, ExternalChange, SearchOptions, SearchResult, Spec, Issue } from "@sudocode-ai/types";
8
+ import { GITHUB_URL_PATTERNS, type GitHubEntityType } from "./url-parser.js";
9
+ /**
10
+ * GitHub-specific configuration options
11
+ * Currently empty since we use gh CLI for auth
12
+ */
13
+ export interface GitHubOptions {
14
+ }
15
+ /**
16
+ * GitHub integration plugin
17
+ */
18
+ declare const githubPlugin: IntegrationPlugin;
19
+ /**
20
+ * GitHub provider implementation
21
+ *
22
+ * Implements IntegrationProvider + OnDemandImportCapable for importing
23
+ * GitHub issues and discussions into sudocode specs.
24
+ */
25
+ declare class GitHubProvider implements IntegrationProvider, OnDemandImportCapable {
26
+ readonly name = "github";
27
+ readonly supportsWatch = false;
28
+ readonly supportsPolling = false;
29
+ readonly supportsOnDemandImport = true;
30
+ readonly supportsSearch = true;
31
+ readonly supportsPush = false;
32
+ private initialized;
33
+ constructor(_options: GitHubOptions);
34
+ initialize(): Promise<void>;
35
+ validate(): Promise<{
36
+ valid: boolean;
37
+ errors: string[];
38
+ }>;
39
+ dispose(): Promise<void>;
40
+ canHandleUrl(url: string): boolean;
41
+ parseUrl(url: string): {
42
+ externalId: string;
43
+ metadata?: Record<string, unknown>;
44
+ } | null;
45
+ fetchByUrl(url: string): Promise<ExternalEntity | null>;
46
+ fetchEntity(externalId: string): Promise<ExternalEntity | null>;
47
+ fetchComments(externalId: string): Promise<ExternalComment[]>;
48
+ refreshEntities(externalIds: string[]): Promise<(ExternalEntity | null)[]>;
49
+ searchEntities(query?: string, options?: SearchOptions): Promise<ExternalEntity[] | SearchResult>;
50
+ createEntity(_entity: Partial<Spec | Issue>): Promise<string>;
51
+ updateEntity(_externalId: string, _entity: Partial<Spec | Issue>): Promise<void>;
52
+ deleteEntity(_externalId: string): Promise<void>;
53
+ getChangesSince(_timestamp: Date): Promise<ExternalChange[]>;
54
+ mapToSudocode(external: ExternalEntity): {
55
+ spec?: Partial<Spec>;
56
+ issue?: Partial<Issue>;
57
+ };
58
+ mapFromSudocode(_entity: Spec | Issue): Partial<ExternalEntity>;
59
+ }
60
+ export type { GitHubEntityType };
61
+ export { GITHUB_URL_PATTERNS };
62
+ export { GhAuthError, GhNotFoundError, GhNotInstalledError, GhRateLimitError } from "./gh-client.js";
63
+ export { canHandleUrl, parseUrl, parseGitHubUrl, parseExternalId } from "./url-parser.js";
64
+ export { ghApi, ghAuthStatus, isGhInstalled } from "./gh-client.js";
65
+ export { mapGitHubIssueToExternal, mapGitHubCommentToExternal, mapToSudocodeSpec, type ImportedSpecData, } from "./mappers.js";
66
+ export { GitHubProvider };
67
+ export default githubPlugin;
68
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,297 @@
1
+ /**
2
+ * GitHub Integration Plugin for sudocode
3
+ *
4
+ * Provides on-demand import of GitHub issues and discussions into sudocode specs.
5
+ * Uses the `gh` CLI for authentication and API calls - no token management required.
6
+ */
7
+ // Internal utilities
8
+ import { canHandleUrl as canHandle, parseUrl as parse, parseGitHubUrl, parseExternalId, GITHUB_URL_PATTERNS, } from "./url-parser.js";
9
+ import { ghApi, ghAuthStatus, isGhInstalled, GhAuthError, GhNotFoundError, GhNotInstalledError, } from "./gh-client.js";
10
+ import { mapGitHubIssueToExternal, mapGitHubCommentToExternal, mapToSudocodeSpec, } from "./mappers.js";
11
+ /**
12
+ * GitHub integration plugin
13
+ */
14
+ const githubPlugin = {
15
+ name: "github",
16
+ displayName: "GitHub Issues",
17
+ version: "0.1.0",
18
+ description: "Import GitHub issues and discussions into sudocode specs using gh CLI",
19
+ configSchema: {
20
+ type: "object",
21
+ properties: {},
22
+ // No required properties - auth handled by gh CLI
23
+ },
24
+ validateConfig(_options) {
25
+ // No configuration to validate - auth is via gh CLI
26
+ return {
27
+ valid: true,
28
+ errors: [],
29
+ warnings: [],
30
+ };
31
+ },
32
+ async testConnection(_options, _projectPath) {
33
+ // Check if gh CLI is installed
34
+ const installed = await isGhInstalled();
35
+ if (!installed) {
36
+ return {
37
+ success: false,
38
+ configured: false,
39
+ enabled: true,
40
+ error: "GitHub CLI (gh) is not installed. Install from: https://cli.github.com/",
41
+ };
42
+ }
43
+ // Check if authenticated
44
+ const authenticated = await ghAuthStatus();
45
+ if (!authenticated) {
46
+ return {
47
+ success: false,
48
+ configured: false,
49
+ enabled: true,
50
+ error: "GitHub CLI not authenticated. Run: gh auth login",
51
+ };
52
+ }
53
+ return {
54
+ success: true,
55
+ configured: true,
56
+ enabled: true,
57
+ details: {
58
+ authMethod: "gh-cli",
59
+ },
60
+ };
61
+ },
62
+ createProvider(options, _projectPath) {
63
+ return new GitHubProvider(options);
64
+ },
65
+ };
66
+ /**
67
+ * GitHub provider implementation
68
+ *
69
+ * Implements IntegrationProvider + OnDemandImportCapable for importing
70
+ * GitHub issues and discussions into sudocode specs.
71
+ */
72
+ class GitHubProvider {
73
+ name = "github";
74
+ // Capability flags
75
+ supportsWatch = false; // No real-time watching (would need webhooks)
76
+ supportsPolling = false; // No polling (on-demand only)
77
+ supportsOnDemandImport = true; // Primary capability
78
+ supportsSearch = true; // Can search repositories
79
+ supportsPush = false; // Read-only integration
80
+ initialized = false;
81
+ constructor(_options) {
82
+ // Options currently unused - auth handled by gh CLI
83
+ }
84
+ // ===========================================================================
85
+ // Lifecycle
86
+ // ===========================================================================
87
+ async initialize() {
88
+ // Verify gh CLI is available and authenticated
89
+ const installed = await isGhInstalled();
90
+ if (!installed) {
91
+ throw new GhNotInstalledError();
92
+ }
93
+ const authenticated = await ghAuthStatus();
94
+ if (!authenticated) {
95
+ throw new GhAuthError();
96
+ }
97
+ this.initialized = true;
98
+ console.log("[github] Provider initialized successfully");
99
+ }
100
+ async validate() {
101
+ const errors = [];
102
+ const installed = await isGhInstalled();
103
+ if (!installed) {
104
+ errors.push("GitHub CLI (gh) is not installed");
105
+ return { valid: false, errors };
106
+ }
107
+ const authenticated = await ghAuthStatus();
108
+ if (!authenticated) {
109
+ errors.push("GitHub CLI not authenticated. Run: gh auth login");
110
+ return { valid: false, errors };
111
+ }
112
+ return { valid: true, errors: [] };
113
+ }
114
+ async dispose() {
115
+ this.initialized = false;
116
+ console.log("[github] Provider disposed");
117
+ }
118
+ // ===========================================================================
119
+ // OnDemandImportCapable Implementation
120
+ // ===========================================================================
121
+ canHandleUrl(url) {
122
+ return canHandle(url);
123
+ }
124
+ parseUrl(url) {
125
+ return parse(url);
126
+ }
127
+ async fetchByUrl(url) {
128
+ const parsed = parseGitHubUrl(url);
129
+ if (!parsed) {
130
+ return null;
131
+ }
132
+ return this.fetchEntity(parsed.externalId);
133
+ }
134
+ async fetchEntity(externalId) {
135
+ const parsed = parseExternalId(externalId);
136
+ if (!parsed) {
137
+ console.warn(`[github] Invalid external ID format: ${externalId}`);
138
+ return null;
139
+ }
140
+ const { owner, repo, number } = parsed;
141
+ try {
142
+ // Fetch issue via gh api
143
+ const issue = await ghApi(`/repos/${owner}/${repo}/issues/${number}`);
144
+ return mapGitHubIssueToExternal(issue, owner, repo);
145
+ }
146
+ catch (error) {
147
+ if (error instanceof GhNotFoundError) {
148
+ console.log(`[github] Entity not found: ${externalId}`);
149
+ return null;
150
+ }
151
+ throw error;
152
+ }
153
+ }
154
+ async fetchComments(externalId) {
155
+ const parsed = parseExternalId(externalId);
156
+ if (!parsed) {
157
+ console.warn(`[github] Invalid external ID format: ${externalId}`);
158
+ return [];
159
+ }
160
+ const { owner, repo, number } = parsed;
161
+ try {
162
+ const comments = await ghApi(`/repos/${owner}/${repo}/issues/${number}/comments`);
163
+ return comments.map(mapGitHubCommentToExternal);
164
+ }
165
+ catch (error) {
166
+ if (error instanceof GhNotFoundError) {
167
+ return [];
168
+ }
169
+ throw error;
170
+ }
171
+ }
172
+ async refreshEntities(externalIds) {
173
+ // Fetch entities in sequence (to avoid rate limiting)
174
+ const results = [];
175
+ for (const id of externalIds) {
176
+ try {
177
+ const entity = await this.fetchEntity(id);
178
+ results.push(entity);
179
+ }
180
+ catch {
181
+ results.push(null);
182
+ }
183
+ }
184
+ return results;
185
+ }
186
+ // ===========================================================================
187
+ // IntegrationProvider Implementation
188
+ // ===========================================================================
189
+ async searchEntities(query, options) {
190
+ const page = options?.page || 1;
191
+ const perPage = Math.min(options?.perPage || 20, 100);
192
+ try {
193
+ // If we have a repo but no query, list issues from that repo
194
+ if (!query && options?.repo) {
195
+ const [owner, repo] = options.repo.split("/");
196
+ if (!owner || !repo) {
197
+ console.warn("[github] Invalid repo format, expected owner/repo");
198
+ return { results: [], pagination: { page, perPage, hasMore: false } };
199
+ }
200
+ // Use GitHub Issues API to list repo issues
201
+ // Note: GitHub's Issues API returns both issues and PRs, so we filter out PRs
202
+ const allItems = await ghApi(`/repos/${owner}/${repo}/issues?state=all&per_page=${perPage}&page=${page}&sort=updated&direction=desc`);
203
+ // Filter out pull requests (they have a pull_request property)
204
+ const issues = allItems.filter((item) => !item.pull_request);
205
+ const results = issues.map((issue) => mapGitHubIssueToExternal(issue, owner, repo));
206
+ return {
207
+ results,
208
+ pagination: {
209
+ page,
210
+ perPage,
211
+ // Note: hasMore may be inaccurate since we filter client-side
212
+ hasMore: allItems.length === perPage,
213
+ },
214
+ };
215
+ }
216
+ // If no query and no repo, return empty
217
+ if (!query) {
218
+ console.warn("[github] Search requires a query or repo");
219
+ return [];
220
+ }
221
+ // Use GitHub search API with pagination
222
+ // Add is:issue to exclude PRs from search results
223
+ const searchQuery = query.includes("is:issue") || query.includes("is:pr")
224
+ ? query
225
+ : `${query} is:issue`;
226
+ const result = await ghApi(`/search/issues?q=${encodeURIComponent(searchQuery)}&per_page=${perPage}&page=${page}`);
227
+ // Filter out any PRs that might still come through
228
+ const issues = result.items.filter((item) => !item.pull_request);
229
+ const results = issues.map((issue) => {
230
+ // Extract owner/repo from html_url
231
+ const urlMatch = issue.html_url.match(/github\.com\/([^/]+)\/([^/]+)\/issues\/\d+/);
232
+ const owner = urlMatch?.[1] || "unknown";
233
+ const repo = urlMatch?.[2] || "unknown";
234
+ return mapGitHubIssueToExternal(issue, owner, repo);
235
+ });
236
+ // If options were provided, return SearchResult with pagination
237
+ if (options) {
238
+ return {
239
+ results,
240
+ pagination: {
241
+ page,
242
+ perPage,
243
+ hasMore: result.total_count > page * perPage,
244
+ totalCount: result.total_count,
245
+ },
246
+ };
247
+ }
248
+ // For backward compatibility, return just the array if no options
249
+ return results;
250
+ }
251
+ catch (error) {
252
+ console.error("[github] Search failed:", error);
253
+ return options ? { results: [], pagination: { page, perPage, hasMore: false } } : [];
254
+ }
255
+ }
256
+ async createEntity(_entity) {
257
+ // Read-only integration - push not supported
258
+ throw new Error("GitHub integration is read-only. Push not supported.");
259
+ }
260
+ async updateEntity(_externalId, _entity) {
261
+ // Read-only integration - push not supported
262
+ throw new Error("GitHub integration is read-only. Push not supported.");
263
+ }
264
+ async deleteEntity(_externalId) {
265
+ // Read-only integration - push not supported
266
+ throw new Error("GitHub integration is read-only. Delete not supported.");
267
+ }
268
+ async getChangesSince(_timestamp) {
269
+ // No polling support - on-demand only
270
+ return [];
271
+ }
272
+ mapToSudocode(external) {
273
+ // GitHub entities always map to specs
274
+ // ImportedSpecData extends Partial<Spec> with optional labels field
275
+ const specData = mapToSudocodeSpec(external);
276
+ // Extract labels separately as they're stored as tags at a different layer
277
+ const { labels: _labels, ...spec } = specData;
278
+ return { spec };
279
+ }
280
+ mapFromSudocode(_entity) {
281
+ // Read-only integration - reverse mapping not needed
282
+ throw new Error("GitHub integration is read-only. Reverse mapping not supported.");
283
+ }
284
+ }
285
+ // Export URL pattern constants for external use
286
+ export { GITHUB_URL_PATTERNS };
287
+ // Export error classes
288
+ export { GhAuthError, GhNotFoundError, GhNotInstalledError, GhRateLimitError } from "./gh-client.js";
289
+ // Export utility functions
290
+ export { canHandleUrl, parseUrl, parseGitHubUrl, parseExternalId } from "./url-parser.js";
291
+ export { ghApi, ghAuthStatus, isGhInstalled } from "./gh-client.js";
292
+ export { mapGitHubIssueToExternal, mapGitHubCommentToExternal, mapToSudocodeSpec, } from "./mappers.js";
293
+ // Export provider class for direct instantiation
294
+ export { GitHubProvider };
295
+ // Default export is the plugin
296
+ export default githubPlugin;
297
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkBH,qBAAqB;AACrB,OAAO,EACL,YAAY,IAAI,SAAS,EACzB,QAAQ,IAAI,KAAK,EACjB,cAAc,EACd,eAAe,EACf,mBAAmB,GAEpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,KAAK,EACL,YAAY,EACZ,aAAa,EACb,WAAW,EACX,eAAe,EACf,mBAAmB,GAGpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,iBAAiB,GAElB,MAAM,cAAc,CAAC;AAUtB;;GAEG;AACH,MAAM,YAAY,GAAsB;IACtC,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,eAAe;IAC5B,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,uEAAuE;IAEpF,YAAY,EAAE;QACZ,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE;QACd,kDAAkD;KAC7B;IAEvB,cAAc,CAAC,QAAiC;QAC9C,oDAAoD;QACpD,OAAO;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,EAAE;SACb,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,QAAiC,EACjC,YAAoB;QAEpB,+BAA+B;QAC/B,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;QACxC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,UAAU,EAAE,KAAK;gBACjB,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,yEAAyE;aACjF,CAAC;QACJ,CAAC;QAED,yBAAyB;QACzB,MAAM,aAAa,GAAG,MAAM,YAAY,EAAE,CAAC;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,UAAU,EAAE,KAAK;gBACjB,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,kDAAkD;aAC1D,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE;gBACP,UAAU,EAAE,QAAQ;aACrB;SACF,CAAC;IACJ,CAAC;IAED,cAAc,CACZ,OAAgC,EAChC,YAAoB;QAEpB,OAAO,IAAI,cAAc,CAAC,OAAmC,CAAC,CAAC;IACjE,CAAC;CACF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,cAAc;IACT,IAAI,GAAG,QAAQ,CAAC;IAEzB,mBAAmB;IACV,aAAa,GAAG,KAAK,CAAC,CAAC,8CAA8C;IACrE,eAAe,GAAG,KAAK,CAAC,CAAC,8BAA8B;IACvD,sBAAsB,GAAG,IAAI,CAAC,CAAC,qBAAqB;IACpD,cAAc,GAAG,IAAI,CAAC,CAAC,0BAA0B;IACjD,YAAY,GAAG,KAAK,CAAC,CAAC,wBAAwB;IAE/C,WAAW,GAAG,KAAK,CAAC;IAE5B,YAAY,QAAuB;QACjC,oDAAoD;IACtD,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E,KAAK,CAAC,UAAU;QACd,+CAA+C;QAC/C,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;QACxC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,mBAAmB,EAAE,CAAC;QAClC,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,YAAY,EAAE,CAAC;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,WAAW,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;QACxC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;YAChD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAClC,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,YAAY,EAAE,CAAC;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YAChE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAClC,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC5C,CAAC;IAED,8EAA8E;IAC9E,uCAAuC;IACvC,8EAA8E;IAE9E,YAAY,CAAC,GAAW;QACtB,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,QAAQ,CAAC,GAAW;QAClB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW;QAC1B,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,UAAkB;QAClC,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,wCAAwC,UAAU,EAAE,CAAC,CAAC;YACnE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QAEvC,IAAI,CAAC;YACH,yBAAyB;YACzB,MAAM,KAAK,GAAG,MAAM,KAAK,CACvB,UAAU,KAAK,IAAI,IAAI,WAAW,MAAM,EAAE,CAC3C,CAAC;YAEF,OAAO,wBAAwB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;gBACrC,OAAO,CAAC,GAAG,CAAC,8BAA8B,UAAU,EAAE,CAAC,CAAC;gBACxD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,UAAkB;QACpC,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,wCAAwC,UAAU,EAAE,CAAC,CAAC;YACnE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,UAAU,KAAK,IAAI,IAAI,WAAW,MAAM,WAAW,CACpD,CAAC;YAEF,OAAO,QAAQ,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;gBACrC,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,WAAqB;QACzC,sDAAsD;QACtD,MAAM,OAAO,GAA8B,EAAE,CAAC;QAE9C,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBAC1C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,8EAA8E;IAC9E,qCAAqC;IACrC,8EAA8E;IAE9E,KAAK,CAAC,cAAc,CAClB,KAAc,EACd,OAAuB;QAEvB,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;QAEtD,IAAI,CAAC;YACH,6DAA6D;YAC7D,IAAI,CAAC,KAAK,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;gBAC5B,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC9C,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;oBACpB,OAAO,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;oBAClE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;gBACxE,CAAC;gBAED,4CAA4C;gBAC5C,8EAA8E;gBAC9E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,UAAU,KAAK,IAAI,IAAI,8BAA8B,OAAO,SAAS,IAAI,8BAA8B,CACxG,CAAC;gBAEF,+DAA+D;gBAC/D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAE7D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACnC,wBAAwB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAC7C,CAAC;gBAEF,OAAO;oBACL,OAAO;oBACP,UAAU,EAAE;wBACV,IAAI;wBACJ,OAAO;wBACP,8DAA8D;wBAC9D,OAAO,EAAE,QAAQ,CAAC,MAAM,KAAK,OAAO;qBACrC;iBACF,CAAC;YACJ,CAAC;YAED,wCAAwC;YACxC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;gBACzD,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,wCAAwC;YACxC,kDAAkD;YAClD,MAAM,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACvE,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,GAAG,KAAK,WAAW,CAAC;YACxB,MAAM,MAAM,GAAG,MAAM,KAAK,CACxB,oBAAoB,kBAAkB,CAAC,WAAW,CAAC,aAAa,OAAO,SAAS,IAAI,EAAE,CACvF,CAAC;YAEF,mDAAmD;YACnD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAEjE,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBACnC,mCAAmC;gBACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CACnC,4CAA4C,CAC7C,CAAC;gBACF,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;gBACzC,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;gBACxC,OAAO,wBAAwB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACtD,CAAC,CAAC,CAAC;YAEH,gEAAgE;YAChE,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;oBACL,OAAO;oBACP,UAAU,EAAE;wBACV,IAAI;wBACJ,OAAO;wBACP,OAAO,EAAE,MAAM,CAAC,WAAW,GAAG,IAAI,GAAG,OAAO;wBAC5C,UAAU,EAAE,MAAM,CAAC,WAAW;qBAC/B;iBACF,CAAC;YACJ,CAAC;YAED,kEAAkE;YAClE,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAA8B;QAC/C,6CAA6C;QAC7C,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,WAAmB,EACnB,OAA8B;QAE9B,6CAA6C;QAC7C,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,WAAmB;QACpC,6CAA6C;QAC7C,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,UAAgB;QACpC,sCAAsC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,aAAa,CAAC,QAAwB;QAIpC,sCAAsC;QACtC,oEAAoE;QACpE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC7C,2EAA2E;QAC3E,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;QAC9C,OAAO,EAAE,IAAI,EAAE,CAAC;IAClB,CAAC;IAED,eAAe,CAAC,OAAqB;QACnC,qDAAqD;QACrD,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;CACF;AAKD,gDAAgD;AAChD,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAErG,2BAA2B;AAC3B,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,iBAAiB,GAElB,MAAM,cAAc,CAAC;AAEtB,iDAAiD;AACjD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,+BAA+B;AAC/B,eAAe,YAAY,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Entity mapping utilities for GitHub API → sudocode
3
+ *
4
+ * Converts GitHub API responses to ExternalEntity format
5
+ * and maps to sudocode Spec format.
6
+ */
7
+ import type { ExternalEntity, ExternalComment, Spec } from "@sudocode-ai/types";
8
+ import type { GitHubIssue, GitHubComment, GitHubDiscussion, GitHubDiscussionComment } from "./gh-client.js";
9
+ import { type GitHubEntityType } from "./url-parser.js";
10
+ /**
11
+ * Map a GitHub issue to ExternalEntity
12
+ *
13
+ * @param issue - GitHub issue from API
14
+ * @param owner - Repository owner
15
+ * @param repo - Repository name
16
+ * @returns ExternalEntity
17
+ */
18
+ export declare function mapGitHubIssueToExternal(issue: GitHubIssue, owner: string, repo: string): ExternalEntity;
19
+ /**
20
+ * Map a GitHub discussion to ExternalEntity
21
+ *
22
+ * @param discussion - GitHub discussion from GraphQL API
23
+ * @param owner - Repository owner
24
+ * @param repo - Repository name
25
+ * @returns ExternalEntity
26
+ */
27
+ export declare function mapGitHubDiscussionToExternal(discussion: GitHubDiscussion, owner: string, repo: string): ExternalEntity;
28
+ /**
29
+ * Map a GitHub comment to ExternalComment
30
+ *
31
+ * @param comment - GitHub comment from API
32
+ * @returns ExternalComment
33
+ */
34
+ export declare function mapGitHubCommentToExternal(comment: GitHubComment): ExternalComment;
35
+ /**
36
+ * Map a GitHub discussion comment to ExternalComment
37
+ *
38
+ * @param comment - GitHub discussion comment from GraphQL API
39
+ * @returns ExternalComment
40
+ */
41
+ export declare function mapGitHubDiscussionCommentToExternal(comment: GitHubDiscussionComment): ExternalComment;
42
+ /**
43
+ * Format content for imported spec with attribution header
44
+ *
45
+ * @param external - External entity to format
46
+ * @returns Formatted content string
47
+ */
48
+ export declare function formatSpecContent(external: ExternalEntity): string;
49
+ /**
50
+ * Extended spec data including labels for import
51
+ * Note: tags are stored in SpecJSONL, not the base Spec type
52
+ */
53
+ export interface ImportedSpecData extends Partial<Spec> {
54
+ /** GitHub labels to be stored as tags */
55
+ labels?: string[];
56
+ }
57
+ /**
58
+ * Map ExternalEntity to sudocode Spec format
59
+ *
60
+ * @param external - External entity from GitHub
61
+ * @returns Partial Spec for creation/update, with labels stored separately
62
+ */
63
+ export declare function mapToSudocodeSpec(external: ExternalEntity): ImportedSpecData;
64
+ /**
65
+ * Map priority from sudocode format (0-4) to GitHub labels
66
+ *
67
+ * This is used when pushing back to GitHub (not implemented in this version)
68
+ *
69
+ * @param priority - sudocode priority (0=highest, 4=lowest)
70
+ * @returns GitHub priority label or undefined
71
+ */
72
+ export declare function mapPriorityToLabel(priority: number): string | undefined;
73
+ /**
74
+ * Extract priority from GitHub labels
75
+ *
76
+ * @param labels - Array of label names
77
+ * @returns Mapped priority (0-4) or undefined
78
+ */
79
+ export declare function extractPriorityFromLabels(labels: string[]): number | undefined;
80
+ /**
81
+ * Build external link metadata for storage
82
+ *
83
+ * @param external - External entity
84
+ * @param entityType - Type of GitHub entity (issue/discussion)
85
+ * @returns External link metadata
86
+ */
87
+ export declare function buildExternalLinkMetadata(external: ExternalEntity, entityType: GitHubEntityType): Record<string, unknown>;
88
+ //# sourceMappingURL=mappers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../src/mappers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAUhF,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC5G,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE1F;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,cAAc,CAmBhB;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,gBAAgB,EAC5B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,cAAc,CAkBhB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,aAAa,GAAG,eAAe,CAQlF;AAED;;;;;GAKG;AACH,wBAAgB,oCAAoC,CAClD,OAAO,EAAE,uBAAuB,GAC/B,eAAe,CAQjB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAqBlE;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAiB,SAAQ,OAAO,CAAC,IAAI,CAAC;IACrD,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,gBAAgB,CAU5E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASvE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CA0B9E;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,cAAc,EACxB,UAAU,EAAE,gBAAgB,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAazB"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Entity mapping utilities for GitHub API → sudocode
3
+ *
4
+ * Converts GitHub API responses to ExternalEntity format
5
+ * and maps to sudocode Spec format.
6
+ */
7
+ import { formatExternalId } from "./url-parser.js";
8
+ /**
9
+ * Map a GitHub issue to ExternalEntity
10
+ *
11
+ * @param issue - GitHub issue from API
12
+ * @param owner - Repository owner
13
+ * @param repo - Repository name
14
+ * @returns ExternalEntity
15
+ */
16
+ export function mapGitHubIssueToExternal(issue, owner, repo) {
17
+ return {
18
+ id: formatExternalId(owner, repo, issue.number),
19
+ type: "spec", // GitHub issues map to specs in sudocode
20
+ title: issue.title,
21
+ description: issue.body || "",
22
+ status: issue.state,
23
+ url: issue.html_url,
24
+ created_at: issue.created_at,
25
+ updated_at: issue.updated_at,
26
+ raw: {
27
+ labels: issue.labels.map((l) => l.name),
28
+ author: issue.user?.login,
29
+ comments_count: issue.comments,
30
+ state_reason: issue.state_reason,
31
+ github_id: issue.id,
32
+ entity_type: "issue",
33
+ },
34
+ };
35
+ }
36
+ /**
37
+ * Map a GitHub discussion to ExternalEntity
38
+ *
39
+ * @param discussion - GitHub discussion from GraphQL API
40
+ * @param owner - Repository owner
41
+ * @param repo - Repository name
42
+ * @returns ExternalEntity
43
+ */
44
+ export function mapGitHubDiscussionToExternal(discussion, owner, repo) {
45
+ return {
46
+ id: formatExternalId(owner, repo, discussion.number),
47
+ type: "spec",
48
+ title: discussion.title,
49
+ description: discussion.body || "",
50
+ status: "open", // Discussions don't have a closed state like issues
51
+ url: discussion.url,
52
+ created_at: discussion.createdAt,
53
+ updated_at: discussion.updatedAt,
54
+ raw: {
55
+ category: discussion.category.name,
56
+ author: discussion.author?.login,
57
+ comments_count: discussion.comments.totalCount,
58
+ github_id: discussion.id,
59
+ entity_type: "discussion",
60
+ },
61
+ };
62
+ }
63
+ /**
64
+ * Map a GitHub comment to ExternalComment
65
+ *
66
+ * @param comment - GitHub comment from API
67
+ * @returns ExternalComment
68
+ */
69
+ export function mapGitHubCommentToExternal(comment) {
70
+ return {
71
+ id: String(comment.id),
72
+ author: comment.user?.login || "unknown",
73
+ body: comment.body,
74
+ created_at: comment.created_at,
75
+ url: comment.html_url,
76
+ };
77
+ }
78
+ /**
79
+ * Map a GitHub discussion comment to ExternalComment
80
+ *
81
+ * @param comment - GitHub discussion comment from GraphQL API
82
+ * @returns ExternalComment
83
+ */
84
+ export function mapGitHubDiscussionCommentToExternal(comment) {
85
+ return {
86
+ id: comment.id,
87
+ author: comment.author?.login || "unknown",
88
+ body: comment.body,
89
+ created_at: comment.createdAt,
90
+ url: comment.url,
91
+ };
92
+ }
93
+ /**
94
+ * Format content for imported spec with attribution header
95
+ *
96
+ * @param external - External entity to format
97
+ * @returns Formatted content string
98
+ */
99
+ export function formatSpecContent(external) {
100
+ const lines = [];
101
+ // Add source attribution
102
+ lines.push(`> Imported from [${external.id}](${external.url})`);
103
+ // Add author if available
104
+ const raw = external.raw;
105
+ if (raw?.author) {
106
+ lines.push(`> Author: @${raw.author}`);
107
+ }
108
+ // Add empty line separator
109
+ lines.push("");
110
+ // Add original content
111
+ if (external.description) {
112
+ lines.push(external.description);
113
+ }
114
+ return lines.join("\n");
115
+ }
116
+ /**
117
+ * Map ExternalEntity to sudocode Spec format
118
+ *
119
+ * @param external - External entity from GitHub
120
+ * @returns Partial Spec for creation/update, with labels stored separately
121
+ */
122
+ export function mapToSudocodeSpec(external) {
123
+ const raw = external.raw;
124
+ const labels = raw?.labels || [];
125
+ return {
126
+ title: external.title,
127
+ content: formatSpecContent(external),
128
+ priority: 2, // Default priority
129
+ labels, // Stored as labels, caller converts to tags
130
+ };
131
+ }
132
+ /**
133
+ * Map priority from sudocode format (0-4) to GitHub labels
134
+ *
135
+ * This is used when pushing back to GitHub (not implemented in this version)
136
+ *
137
+ * @param priority - sudocode priority (0=highest, 4=lowest)
138
+ * @returns GitHub priority label or undefined
139
+ */
140
+ export function mapPriorityToLabel(priority) {
141
+ const labels = {
142
+ 0: "priority: critical",
143
+ 1: "priority: high",
144
+ 2: "priority: medium",
145
+ 3: "priority: low",
146
+ 4: "priority: lowest",
147
+ };
148
+ return labels[priority];
149
+ }
150
+ /**
151
+ * Extract priority from GitHub labels
152
+ *
153
+ * @param labels - Array of label names
154
+ * @returns Mapped priority (0-4) or undefined
155
+ */
156
+ export function extractPriorityFromLabels(labels) {
157
+ const priorityMap = {
158
+ "priority: critical": 0,
159
+ "priority: high": 1,
160
+ "priority: medium": 2,
161
+ "priority: low": 3,
162
+ "priority: lowest": 4,
163
+ "p0": 0,
164
+ "p1": 1,
165
+ "p2": 2,
166
+ "p3": 3,
167
+ "p4": 4,
168
+ "critical": 0,
169
+ "high": 1,
170
+ "medium": 2,
171
+ "low": 3,
172
+ };
173
+ for (const label of labels) {
174
+ const normalized = label.toLowerCase();
175
+ if (normalized in priorityMap) {
176
+ return priorityMap[normalized];
177
+ }
178
+ }
179
+ return undefined;
180
+ }
181
+ /**
182
+ * Build external link metadata for storage
183
+ *
184
+ * @param external - External entity
185
+ * @param entityType - Type of GitHub entity (issue/discussion)
186
+ * @returns External link metadata
187
+ */
188
+ export function buildExternalLinkMetadata(external, entityType) {
189
+ const parsed = external.id.match(/^([\w.-]+)\/([\w.-]+)#(\d+)$/);
190
+ if (!parsed) {
191
+ return { type: entityType };
192
+ }
193
+ const [, owner, repo] = parsed;
194
+ return {
195
+ owner,
196
+ repo,
197
+ type: entityType,
198
+ comments_imported: false,
199
+ };
200
+ }
201
+ //# sourceMappingURL=mappers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.js","sourceRoot":"","sources":["../src/mappers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * URL parsing utilities for GitHub URLs
3
+ *
4
+ * Supports parsing GitHub issue and discussion URLs to extract
5
+ * owner, repo, and entity number.
6
+ */
7
+ /**
8
+ * Supported GitHub URL patterns
9
+ */
10
+ export declare const GITHUB_URL_PATTERNS: {
11
+ readonly issue: RegExp;
12
+ readonly discussion: RegExp;
13
+ readonly pullRequest: RegExp;
14
+ };
15
+ /**
16
+ * Entity types that can be parsed from GitHub URLs
17
+ */
18
+ export type GitHubEntityType = "issue" | "discussion" | "pull_request";
19
+ /**
20
+ * Result of parsing a GitHub URL
21
+ */
22
+ export interface ParsedGitHubUrl {
23
+ /** Repository owner (user or organization) */
24
+ owner: string;
25
+ /** Repository name */
26
+ repo: string;
27
+ /** Entity number (issue/discussion/PR number) */
28
+ number: number;
29
+ /** Type of entity */
30
+ type: GitHubEntityType;
31
+ /** External ID in format "owner/repo#number" */
32
+ externalId: string;
33
+ /** Original URL */
34
+ url: string;
35
+ }
36
+ /**
37
+ * Check if a URL is a GitHub URL that this provider can handle
38
+ *
39
+ * @param url - URL to check
40
+ * @returns true if URL matches a supported GitHub pattern
41
+ */
42
+ export declare function canHandleUrl(url: string): boolean;
43
+ /**
44
+ * Parse a GitHub URL to extract entity information
45
+ *
46
+ * @param url - GitHub URL to parse
47
+ * @returns Parsed URL info or null if URL cannot be parsed
48
+ */
49
+ export declare function parseUrl(url: string): {
50
+ externalId: string;
51
+ metadata?: Record<string, unknown>;
52
+ } | null;
53
+ /**
54
+ * Parse a GitHub URL to extract full details
55
+ *
56
+ * @param url - GitHub URL to parse
57
+ * @returns Full parsed URL details or null if URL cannot be parsed
58
+ */
59
+ export declare function parseGitHubUrl(url: string): ParsedGitHubUrl | null;
60
+ /**
61
+ * Parse an external ID in format "owner/repo#number"
62
+ *
63
+ * @param externalId - External ID to parse
64
+ * @returns Parsed components or null if invalid format
65
+ */
66
+ export declare function parseExternalId(externalId: string): {
67
+ owner: string;
68
+ repo: string;
69
+ number: number;
70
+ } | null;
71
+ /**
72
+ * Build a GitHub URL from parsed components
73
+ *
74
+ * @param owner - Repository owner
75
+ * @param repo - Repository name
76
+ * @param number - Entity number
77
+ * @param type - Entity type (defaults to issue)
78
+ * @returns GitHub URL
79
+ */
80
+ export declare function buildGitHubUrl(owner: string, repo: string, number: number, type?: GitHubEntityType): string;
81
+ /**
82
+ * Format an external ID from components
83
+ *
84
+ * @param owner - Repository owner
85
+ * @param repo - Repository name
86
+ * @param number - Entity number
87
+ * @returns External ID in format "owner/repo#number"
88
+ */
89
+ export declare function formatExternalId(owner: string, repo: string, number: number): string;
90
+ //# sourceMappingURL=url-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-parser.d.ts","sourceRoot":"","sources":["../src/url-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;CAItB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,YAAY,GAAG,cAAc,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,IAAI,EAAE,gBAAgB,CAAC;IACvB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,GACV;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,IAAI,CAkDnE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAqBlE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,GACjB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAYxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,gBAA0B,GAC/B,MAAM,CAQR;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM,CAER"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * URL parsing utilities for GitHub URLs
3
+ *
4
+ * Supports parsing GitHub issue and discussion URLs to extract
5
+ * owner, repo, and entity number.
6
+ */
7
+ /**
8
+ * Supported GitHub URL patterns
9
+ */
10
+ export const GITHUB_URL_PATTERNS = {
11
+ issue: /^https:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/issues\/(\d+)(?:\/.*)?(?:\?.*)?(?:#.*)?$/,
12
+ discussion: /^https:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/discussions\/(\d+)(?:\/.*)?(?:\?.*)?(?:#.*)?$/,
13
+ pullRequest: /^https:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/pull\/(\d+)(?:\/.*)?(?:\?.*)?(?:#.*)?$/,
14
+ };
15
+ /**
16
+ * Check if a URL is a GitHub URL that this provider can handle
17
+ *
18
+ * @param url - URL to check
19
+ * @returns true if URL matches a supported GitHub pattern
20
+ */
21
+ export function canHandleUrl(url) {
22
+ return Object.values(GITHUB_URL_PATTERNS).some((pattern) => pattern.test(url));
23
+ }
24
+ /**
25
+ * Parse a GitHub URL to extract entity information
26
+ *
27
+ * @param url - GitHub URL to parse
28
+ * @returns Parsed URL info or null if URL cannot be parsed
29
+ */
30
+ export function parseUrl(url) {
31
+ // Try issue pattern
32
+ const issueMatch = url.match(GITHUB_URL_PATTERNS.issue);
33
+ if (issueMatch) {
34
+ const [, owner, repo, number] = issueMatch;
35
+ return {
36
+ externalId: `${owner}/${repo}#${number}`,
37
+ metadata: {
38
+ owner,
39
+ repo,
40
+ number: parseInt(number, 10),
41
+ type: "issue",
42
+ url,
43
+ },
44
+ };
45
+ }
46
+ // Try discussion pattern
47
+ const discussionMatch = url.match(GITHUB_URL_PATTERNS.discussion);
48
+ if (discussionMatch) {
49
+ const [, owner, repo, number] = discussionMatch;
50
+ return {
51
+ externalId: `${owner}/${repo}#${number}`,
52
+ metadata: {
53
+ owner,
54
+ repo,
55
+ number: parseInt(number, 10),
56
+ type: "discussion",
57
+ url,
58
+ },
59
+ };
60
+ }
61
+ // Try PR pattern
62
+ const prMatch = url.match(GITHUB_URL_PATTERNS.pullRequest);
63
+ if (prMatch) {
64
+ const [, owner, repo, number] = prMatch;
65
+ return {
66
+ externalId: `${owner}/${repo}#${number}`,
67
+ metadata: {
68
+ owner,
69
+ repo,
70
+ number: parseInt(number, 10),
71
+ type: "pull_request",
72
+ url,
73
+ },
74
+ };
75
+ }
76
+ return null;
77
+ }
78
+ /**
79
+ * Parse a GitHub URL to extract full details
80
+ *
81
+ * @param url - GitHub URL to parse
82
+ * @returns Full parsed URL details or null if URL cannot be parsed
83
+ */
84
+ export function parseGitHubUrl(url) {
85
+ const result = parseUrl(url);
86
+ if (!result || !result.metadata) {
87
+ return null;
88
+ }
89
+ const { owner, repo, number, type } = result.metadata;
90
+ return {
91
+ owner,
92
+ repo,
93
+ number,
94
+ type,
95
+ externalId: result.externalId,
96
+ url,
97
+ };
98
+ }
99
+ /**
100
+ * Parse an external ID in format "owner/repo#number"
101
+ *
102
+ * @param externalId - External ID to parse
103
+ * @returns Parsed components or null if invalid format
104
+ */
105
+ export function parseExternalId(externalId) {
106
+ const match = externalId.match(/^([\w.-]+)\/([\w.-]+)#(\d+)$/);
107
+ if (!match) {
108
+ return null;
109
+ }
110
+ const [, owner, repo, number] = match;
111
+ return {
112
+ owner,
113
+ repo,
114
+ number: parseInt(number, 10),
115
+ };
116
+ }
117
+ /**
118
+ * Build a GitHub URL from parsed components
119
+ *
120
+ * @param owner - Repository owner
121
+ * @param repo - Repository name
122
+ * @param number - Entity number
123
+ * @param type - Entity type (defaults to issue)
124
+ * @returns GitHub URL
125
+ */
126
+ export function buildGitHubUrl(owner, repo, number, type = "issue") {
127
+ const typeMap = {
128
+ issue: "issues",
129
+ discussion: "discussions",
130
+ pull_request: "pull",
131
+ };
132
+ return `https://github.com/${owner}/${repo}/${typeMap[type]}/${number}`;
133
+ }
134
+ /**
135
+ * Format an external ID from components
136
+ *
137
+ * @param owner - Repository owner
138
+ * @param repo - Repository name
139
+ * @param number - Entity number
140
+ * @returns External ID in format "owner/repo#number"
141
+ */
142
+ export function formatExternalId(owner, repo, number) {
143
+ return `${owner}/${repo}#${number}`;
144
+ }
145
+ //# sourceMappingURL=url-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-parser.js","sourceRoot":"","sources":["../src/url-parser.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@sudocode-ai/integration-github",
3
+ "version": "0.1.14",
4
+ "description": "GitHub integration plugin for sudocode using gh CLI",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "test": "vitest --run",
20
+ "test:cli": "RUN_CLI_TESTS=true vitest --run",
21
+ "clean": "rm -rf dist"
22
+ },
23
+ "keywords": [
24
+ "sudocode",
25
+ "integration",
26
+ "github",
27
+ "plugin",
28
+ "gh-cli"
29
+ ],
30
+ "author": "sudocode-ai",
31
+ "license": "Apache-2.0",
32
+ "peerDependencies": {
33
+ "@sudocode-ai/types": "^0.1.14"
34
+ },
35
+ "devDependencies": {
36
+ "@sudocode-ai/types": "^0.1.14",
37
+ "@types/node": "^22.10.2",
38
+ "typescript": "^5.8.3",
39
+ "vitest": "^3.2.4"
40
+ }
41
+ }