edsger 0.65.0 → 0.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,44 +1,32 @@
1
1
  /**
2
2
  * Phase: sync-org-repos
3
3
  *
4
- * Fetches all repositories from a GitHub organization using the local `gh` CLI,
5
- * then upserts a row into the team-scoped `repositories` table for each repo.
6
- * Products are NOT created here a product is a higher-level grouping that a
7
- * user links one or more repositories to afterwards.
4
+ * Fetches all repositories from a GitHub organization via the Edsger GitHub
5
+ * App (server-side, through the MCP `github/org_repos` endpoint), then upserts
6
+ * a row into the team-scoped `repositories` table for each repo. Products are
7
+ * NOT created here a product is a higher-level grouping that a user links one
8
+ * or more repositories to afterwards.
8
9
  *
9
- * Uses `gh api --paginate` for truly unlimited pagination (no hardcoded cap).
10
- * Forks and archived repos are filtered out client-side.
10
+ * Repos are listed with a short-lived GitHub App installation token minted on
11
+ * the server, so this no longer depends on the user's machine having the `gh`
12
+ * CLI installed, authenticated, and on PATH. Forks and archived repos are
13
+ * filtered out server-side.
11
14
  */
12
- import { execFile } from 'child_process';
13
- import { promisify } from 'util';
15
+ import { callMcpEndpoint } from '../../api/mcp-client.js';
14
16
  import { getSupabase, hasSupabaseSession } from '../../supabase/client.js';
15
17
  import { logDebug, logError, logInfo, logWarning } from '../../utils/logger.js';
16
- const execFileAsync = promisify(execFile);
17
18
  const ORG_NAME_RE = /^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/;
18
- async function fetchOrgRepos(orgLogin, verbose) {
19
- logInfo(`Fetching repos for org "${orgLogin}" via gh CLI...`);
20
- const { stdout } = await execFileAsync('gh', [
21
- 'api',
22
- `--paginate`,
23
- `/orgs/${encodeURIComponent(orgLogin)}/repos?per_page=100&type=sources&sort=updated`,
24
- '--jq',
25
- '.[] | select(.archived == false) | {id, name, full_name, description, html_url, default_branch, private, language}',
26
- ], { timeout: 120_000 });
27
- if (!stdout.trim()) {
28
- return [];
29
- }
30
- const repos = [];
31
- for (const line of stdout.trim().split('\n')) {
32
- if (!line) {
33
- continue;
34
- }
35
- try {
36
- repos.push(JSON.parse(line));
37
- }
38
- catch {
39
- // skip malformed lines
40
- }
19
+ async function fetchOrgRepos(teamId, orgLogin, verbose) {
20
+ logInfo(`Fetching repos for org "${orgLogin}" via Edsger GitHub App...`);
21
+ const result = (await callMcpEndpoint('github/org_repos', {
22
+ team_id: teamId,
23
+ org: orgLogin,
24
+ }));
25
+ if (!result.configured) {
26
+ throw new Error(result.message ||
27
+ `The Edsger GitHub App is not configured for "${orgLogin}".`);
41
28
  }
29
+ const repos = result.repos ?? [];
42
30
  if (verbose) {
43
31
  logDebug(`Fetched ${repos.length} source repos from ${orgLogin}`);
44
32
  }
@@ -67,14 +55,14 @@ export async function syncOrgRepos(opts) {
67
55
  const supabase = getSupabase();
68
56
  let orgRepos;
69
57
  try {
70
- orgRepos = await fetchOrgRepos(orgLogin, verbose);
58
+ orgRepos = await fetchOrgRepos(teamId, orgLogin, verbose);
71
59
  }
72
60
  catch (err) {
73
61
  const msg = err instanceof Error ? err.message : String(err);
74
62
  logError(`Failed to fetch repos: ${msg}`);
75
63
  return {
76
64
  status: 'error',
77
- message: `Failed to fetch repos from GitHub CLI: ${msg}`,
65
+ message: `Failed to fetch repos from GitHub: ${msg}`,
78
66
  total: 0,
79
67
  created: 0,
80
68
  skipped: 0,
@@ -204,34 +204,3 @@ export interface ChatReadStatus {
204
204
  last_read_message_id: string | null;
205
205
  last_read_at: string;
206
206
  }
207
- export interface ChatWorkerInitMessage {
208
- type: 'init';
209
- config: EdsgerConfig;
210
- verbose?: boolean;
211
- }
212
- export interface ChatWorkerPhaseEvent {
213
- type: 'event:phase_completed' | 'event:phase_failed' | 'event:issue_done' | 'event:issue_started';
214
- issueId: string;
215
- phase?: string;
216
- summary?: string;
217
- phaseOutput?: unknown;
218
- error?: string;
219
- repoPath?: string;
220
- }
221
- export interface ChatWorkerCommand {
222
- type: 'command:pause_issue' | 'command:resume_issue';
223
- issueId: string;
224
- }
225
- export interface ChatWorkerQuery {
226
- type: 'query:active_issues';
227
- }
228
- export interface ChatWorkerReply {
229
- type: 'reply:active_issues';
230
- issues: {
231
- id: string;
232
- name: string;
233
- phase: string;
234
- }[];
235
- }
236
- export type ChatWorkerParentMessage = ChatWorkerInitMessage | ChatWorkerPhaseEvent;
237
- export type ChatWorkerChildMessage = ChatWorkerCommand | ChatWorkerQuery;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.65.0",
3
+ "version": "0.67.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"
@@ -51,7 +51,7 @@
51
51
  "cosmiconfig": "^9.0.0",
52
52
  "dotenv": "^16.4.5",
53
53
  "edsger-contract": "0.7.0",
54
- "edsger-tools": "0.8.0",
54
+ "edsger-tools": "0.9.0",
55
55
  "gray-matter": "^4.0.3",
56
56
  "zod": "^4.0.0"
57
57
  },