@triedotdev/mcp 1.0.169 → 1.0.171

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.
Files changed (145) hide show
  1. package/README.md +62 -540
  2. package/dist/chunk-2YXOBNKW.js +619 -0
  3. package/dist/chunk-2YXOBNKW.js.map +1 -0
  4. package/dist/chunk-QR64Y5TI.js +363 -0
  5. package/dist/chunk-QR64Y5TI.js.map +1 -0
  6. package/dist/cli/main.d.ts +0 -15
  7. package/dist/cli/main.js +356 -3098
  8. package/dist/cli/main.js.map +1 -1
  9. package/dist/index.js +2 -34
  10. package/dist/index.js.map +1 -1
  11. package/dist/server/mcp-server.js +2 -34
  12. package/package.json +8 -31
  13. package/dist/autonomy-config-FSERX3O3.js +0 -30
  14. package/dist/autonomy-config-FSERX3O3.js.map +0 -1
  15. package/dist/chat-store-JNGNTDSN.js +0 -15
  16. package/dist/chat-store-JNGNTDSN.js.map +0 -1
  17. package/dist/chunk-2HF65EHQ.js +0 -311
  18. package/dist/chunk-2HF65EHQ.js.map +0 -1
  19. package/dist/chunk-3XR6WVAW.js +0 -4011
  20. package/dist/chunk-3XR6WVAW.js.map +0 -1
  21. package/dist/chunk-43X6JBEM.js +0 -36
  22. package/dist/chunk-43X6JBEM.js.map +0 -1
  23. package/dist/chunk-6NLHFIYA.js +0 -344
  24. package/dist/chunk-6NLHFIYA.js.map +0 -1
  25. package/dist/chunk-7IO4YUI3.js +0 -1827
  26. package/dist/chunk-7IO4YUI3.js.map +0 -1
  27. package/dist/chunk-AHD2CBQ7.js +0 -846
  28. package/dist/chunk-AHD2CBQ7.js.map +0 -1
  29. package/dist/chunk-BUTOP5EB.js +0 -931
  30. package/dist/chunk-BUTOP5EB.js.map +0 -1
  31. package/dist/chunk-DGUM43GV.js +0 -11
  32. package/dist/chunk-DGUM43GV.js.map +0 -1
  33. package/dist/chunk-EFWVF6TI.js +0 -267
  34. package/dist/chunk-EFWVF6TI.js.map +0 -1
  35. package/dist/chunk-F6WFNUAY.js +0 -216
  36. package/dist/chunk-F6WFNUAY.js.map +0 -1
  37. package/dist/chunk-FBNURWRY.js +0 -662
  38. package/dist/chunk-FBNURWRY.js.map +0 -1
  39. package/dist/chunk-FQ45QP5A.js +0 -361
  40. package/dist/chunk-FQ45QP5A.js.map +0 -1
  41. package/dist/chunk-FVRO5RN3.js +0 -1306
  42. package/dist/chunk-FVRO5RN3.js.map +0 -1
  43. package/dist/chunk-G2TGF6TR.js +0 -573
  44. package/dist/chunk-G2TGF6TR.js.map +0 -1
  45. package/dist/chunk-G3I7SZLW.js +0 -354
  46. package/dist/chunk-G3I7SZLW.js.map +0 -1
  47. package/dist/chunk-GTKYBOXL.js +0 -700
  48. package/dist/chunk-GTKYBOXL.js.map +0 -1
  49. package/dist/chunk-HVCDY3AK.js +0 -850
  50. package/dist/chunk-HVCDY3AK.js.map +0 -1
  51. package/dist/chunk-I2O5OYQT.js +0 -727
  52. package/dist/chunk-I2O5OYQT.js.map +0 -1
  53. package/dist/chunk-JVMBCWKS.js +0 -348
  54. package/dist/chunk-JVMBCWKS.js.map +0 -1
  55. package/dist/chunk-KCUOWRPX.js +0 -816
  56. package/dist/chunk-KCUOWRPX.js.map +0 -1
  57. package/dist/chunk-KDHN2ZQE.js +0 -313
  58. package/dist/chunk-KDHN2ZQE.js.map +0 -1
  59. package/dist/chunk-ME2OERF5.js +0 -345
  60. package/dist/chunk-ME2OERF5.js.map +0 -1
  61. package/dist/chunk-OBQ74FOU.js +0 -27
  62. package/dist/chunk-OBQ74FOU.js.map +0 -1
  63. package/dist/chunk-Q5EKA5YA.js +0 -254
  64. package/dist/chunk-Q5EKA5YA.js.map +0 -1
  65. package/dist/chunk-Q63FFI6D.js +0 -132
  66. package/dist/chunk-Q63FFI6D.js.map +0 -1
  67. package/dist/chunk-SASNMSB5.js +0 -12597
  68. package/dist/chunk-SASNMSB5.js.map +0 -1
  69. package/dist/chunk-T63OHG4Q.js +0 -440
  70. package/dist/chunk-T63OHG4Q.js.map +0 -1
  71. package/dist/chunk-TN5WEKWI.js +0 -173
  72. package/dist/chunk-TN5WEKWI.js.map +0 -1
  73. package/dist/chunk-VUL52BQL.js +0 -402
  74. package/dist/chunk-VUL52BQL.js.map +0 -1
  75. package/dist/chunk-VVITXIHN.js +0 -189
  76. package/dist/chunk-VVITXIHN.js.map +0 -1
  77. package/dist/chunk-WCN7S3EI.js +0 -14
  78. package/dist/chunk-WCN7S3EI.js.map +0 -1
  79. package/dist/chunk-XPZZFPBZ.js +0 -491
  80. package/dist/chunk-XPZZFPBZ.js.map +0 -1
  81. package/dist/chunk-ZJF5FTBX.js +0 -1396
  82. package/dist/chunk-ZJF5FTBX.js.map +0 -1
  83. package/dist/chunk-ZV2K6M7T.js +0 -74
  84. package/dist/chunk-ZV2K6M7T.js.map +0 -1
  85. package/dist/cli/create-agent.d.ts +0 -1
  86. package/dist/cli/create-agent.js +0 -1050
  87. package/dist/cli/create-agent.js.map +0 -1
  88. package/dist/cli/yolo-daemon.d.ts +0 -1
  89. package/dist/cli/yolo-daemon.js +0 -421
  90. package/dist/cli/yolo-daemon.js.map +0 -1
  91. package/dist/client-NJPZE5JT.js +0 -28
  92. package/dist/client-NJPZE5JT.js.map +0 -1
  93. package/dist/codebase-index-VAPF32XX.js +0 -12
  94. package/dist/codebase-index-VAPF32XX.js.map +0 -1
  95. package/dist/fast-analyzer-3GCCZMLK.js +0 -216
  96. package/dist/fast-analyzer-3GCCZMLK.js.map +0 -1
  97. package/dist/git-EO5SRFMN.js +0 -28
  98. package/dist/git-EO5SRFMN.js.map +0 -1
  99. package/dist/github-ingester-ZOKK6GRS.js +0 -11
  100. package/dist/github-ingester-ZOKK6GRS.js.map +0 -1
  101. package/dist/goal-manager-QUKX2W6C.js +0 -25
  102. package/dist/goal-manager-QUKX2W6C.js.map +0 -1
  103. package/dist/goal-validator-2SFSKKVU.js +0 -24
  104. package/dist/goal-validator-2SFSKKVU.js.map +0 -1
  105. package/dist/graph-B3NA4S7I.js +0 -10
  106. package/dist/graph-B3NA4S7I.js.map +0 -1
  107. package/dist/hypothesis-KCPBR652.js +0 -23
  108. package/dist/hypothesis-KCPBR652.js.map +0 -1
  109. package/dist/incident-index-EFNUSGWL.js +0 -11
  110. package/dist/incident-index-EFNUSGWL.js.map +0 -1
  111. package/dist/insight-store-EC4PLSAW.js +0 -22
  112. package/dist/insight-store-EC4PLSAW.js.map +0 -1
  113. package/dist/issue-store-YAXTNRRY.js +0 -36
  114. package/dist/issue-store-YAXTNRRY.js.map +0 -1
  115. package/dist/ledger-TWZTGDFA.js +0 -58
  116. package/dist/ledger-TWZTGDFA.js.map +0 -1
  117. package/dist/linear-ingester-XXPAZZRW.js +0 -11
  118. package/dist/linear-ingester-XXPAZZRW.js.map +0 -1
  119. package/dist/output-manager-RVJ37XKA.js +0 -13
  120. package/dist/output-manager-RVJ37XKA.js.map +0 -1
  121. package/dist/parse-goal-violation-SACGFG3C.js +0 -8
  122. package/dist/parse-goal-violation-SACGFG3C.js.map +0 -1
  123. package/dist/pattern-discovery-F7LU5K6E.js +0 -8
  124. package/dist/pattern-discovery-F7LU5K6E.js.map +0 -1
  125. package/dist/progress-SRQ2V3BP.js +0 -18
  126. package/dist/progress-SRQ2V3BP.js.map +0 -1
  127. package/dist/project-state-AHPA77SM.js +0 -28
  128. package/dist/project-state-AHPA77SM.js.map +0 -1
  129. package/dist/sync-M2FSWPBC.js +0 -12
  130. package/dist/sync-M2FSWPBC.js.map +0 -1
  131. package/dist/terminal-spawn-5YXDMUCF.js +0 -157
  132. package/dist/terminal-spawn-5YXDMUCF.js.map +0 -1
  133. package/dist/tiered-storage-DYNC5CQ6.js +0 -13
  134. package/dist/tiered-storage-DYNC5CQ6.js.map +0 -1
  135. package/dist/trie-agent-I3HAHY2G.js +0 -26
  136. package/dist/trie-agent-I3HAHY2G.js.map +0 -1
  137. package/dist/ui/chat.html +0 -1014
  138. package/dist/ui/goals.html +0 -967
  139. package/dist/ui/hypotheses.html +0 -1011
  140. package/dist/ui/ledger.html +0 -954
  141. package/dist/ui/nudges.html +0 -995
  142. package/dist/vibe-code-signatures-5ZULYP3D.js +0 -987
  143. package/dist/vibe-code-signatures-5ZULYP3D.js.map +0 -1
  144. package/dist/vulnerability-signatures-2URZSXAQ.js +0 -983
  145. package/dist/vulnerability-signatures-2URZSXAQ.js.map +0 -1
@@ -1,216 +0,0 @@
1
- import {
2
- loadConfig
3
- } from "./chunk-XPZZFPBZ.js";
4
-
5
- // src/ingest/github-ingester.ts
6
- import path from "path";
7
- import { execSync } from "child_process";
8
- var TICKET_PATTERN = /\b([A-Z]{2,10}-\d+)\b/g;
9
- var GitHubIngester = class {
10
- graph;
11
- constructor(graph) {
12
- this.graph = graph;
13
- }
14
- async getApiToken() {
15
- const config = await loadConfig();
16
- return config.apiKeys?.github ?? process.env.GITHUB_TOKEN ?? null;
17
- }
18
- getRepoInfo(projectPath) {
19
- try {
20
- const url = execSync("git remote get-url origin", {
21
- cwd: projectPath,
22
- encoding: "utf-8",
23
- stdio: ["pipe", "pipe", "pipe"]
24
- }).trim();
25
- const sshMatch = url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
26
- if (sshMatch) {
27
- return { owner: sshMatch[1], name: sshMatch[2] };
28
- }
29
- const httpsMatch = url.match(/github\.com\/([^/]+)\/([^/.]+)/);
30
- if (httpsMatch) {
31
- return { owner: httpsMatch[1], name: httpsMatch[2] };
32
- }
33
- return null;
34
- } catch {
35
- return null;
36
- }
37
- }
38
- async syncPullRequests(owner, repo, token) {
39
- const prs = await this.fetchJson(
40
- `https://api.github.com/repos/${owner}/${repo}/pulls?state=open&per_page=50`,
41
- token
42
- );
43
- let linkedTickets = 0;
44
- let linkedFiles = 0;
45
- for (const pr of prs) {
46
- const filesChanged = await this.fetchPRFiles(owner, repo, pr.number, token);
47
- const reviewStatus = await this.fetchReviewStatus(owner, repo, pr.number, token);
48
- const ciStatus = await this.fetchCIStatus(owner, repo, pr.head.ref, token);
49
- const linkedTicketIds = this.extractTicketIds(pr.title, pr.body);
50
- const state = pr.draft ? "draft" : pr.state === "open" ? "open" : "closed";
51
- const data = {
52
- prNumber: pr.number,
53
- title: pr.title,
54
- url: pr.html_url,
55
- state,
56
- author: pr.user.login,
57
- branch: pr.head.ref,
58
- baseBranch: pr.base.ref,
59
- isDraft: pr.draft,
60
- filesChanged,
61
- linkedTicketIds,
62
- ciStatus,
63
- reviewStatus,
64
- createdAt: pr.created_at,
65
- updatedAt: pr.updated_at,
66
- ...pr.merged_at != null && { mergedAt: pr.merged_at }
67
- };
68
- const prNodeId = `pr:${pr.number}`;
69
- const existingNode = await this.graph.getNode("pull-request", prNodeId);
70
- if (existingNode) {
71
- await this.graph.updateNode("pull-request", prNodeId, data);
72
- } else {
73
- await this.graph.addNode("pull-request", data);
74
- }
75
- for (const file of filesChanged) {
76
- const resolvedPath = path.resolve(this.graph.projectRoot, file);
77
- const fileNode = await this.graph.getNode("file", resolvedPath);
78
- if (fileNode) {
79
- linkedFiles++;
80
- await this.graph.addEdge(prNodeId, fileNode.id, "affects");
81
- }
82
- }
83
- for (const ticketId of linkedTicketIds) {
84
- const ticketNodeId = `linear:${ticketId}`;
85
- const ticketNode = await this.graph.getNode("linear-ticket", ticketNodeId);
86
- if (ticketNode) {
87
- linkedTickets++;
88
- await this.graph.addEdge(ticketNodeId, prNodeId, "implements");
89
- }
90
- }
91
- }
92
- return { prs: prs.length, linkedTickets, linkedFiles };
93
- }
94
- async syncIssues(owner, repo, token) {
95
- const allItems = await this.fetchJson(
96
- `https://api.github.com/repos/${owner}/${repo}/issues?state=open&per_page=50`,
97
- token
98
- );
99
- const issues = allItems.filter((item) => !item.pull_request);
100
- for (const issue of issues) {
101
- const linkedTicketIds = this.extractTicketIds(issue.title, issue.body);
102
- const data = {
103
- issueNumber: issue.number,
104
- title: issue.title,
105
- url: issue.html_url,
106
- state: issue.state,
107
- labels: issue.labels.map((l) => l.name),
108
- assignees: issue.assignees.map((a) => a.login),
109
- body: issue.body ?? "",
110
- linkedTicketIds,
111
- createdAt: issue.created_at,
112
- updatedAt: issue.updated_at,
113
- ...issue.closed_at != null && { closedAt: issue.closed_at }
114
- };
115
- const issueNodeId = `gh-issue:${issue.number}`;
116
- const existingNode = await this.graph.getNode("github-issue", issueNodeId);
117
- if (existingNode) {
118
- await this.graph.updateNode("github-issue", issueNodeId, data);
119
- } else {
120
- await this.graph.addNode("github-issue", data);
121
- }
122
- for (const ticketId of linkedTicketIds) {
123
- const ticketNodeId = `linear:${ticketId}`;
124
- const ticketNode = await this.graph.getNode("linear-ticket", ticketNodeId);
125
- if (ticketNode) {
126
- await this.graph.addEdge(issueNodeId, ticketNodeId, "relatedTo");
127
- }
128
- }
129
- }
130
- return { issues: issues.length };
131
- }
132
- async fetchPRFiles(owner, repo, prNumber, token) {
133
- try {
134
- const files = await this.fetchJson(
135
- `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/files?per_page=100`,
136
- token
137
- );
138
- return files.map((f) => f.filename);
139
- } catch {
140
- return [];
141
- }
142
- }
143
- async fetchReviewStatus(owner, repo, prNumber, token) {
144
- try {
145
- const reviews = await this.fetchJson(
146
- `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/reviews`,
147
- token
148
- );
149
- if (reviews.length === 0) return "none";
150
- const states = reviews.map((r) => r.state);
151
- if (states.includes("CHANGES_REQUESTED")) return "changes_requested";
152
- if (states.includes("APPROVED")) return "approved";
153
- return "pending";
154
- } catch {
155
- return "none";
156
- }
157
- }
158
- async fetchCIStatus(owner, repo, ref, token) {
159
- try {
160
- const status = await this.fetchJson(
161
- `https://api.github.com/repos/${owner}/${repo}/commits/${ref}/status`,
162
- token
163
- );
164
- switch (status.state) {
165
- case "success":
166
- return "passing";
167
- case "failure":
168
- case "error":
169
- return "failing";
170
- case "pending":
171
- return "pending";
172
- default:
173
- return "unknown";
174
- }
175
- } catch {
176
- return "unknown";
177
- }
178
- }
179
- extractTicketIds(title, body) {
180
- const text = `${title} ${body ?? ""}`;
181
- const matches = text.match(TICKET_PATTERN);
182
- return matches ? [...new Set(matches)] : [];
183
- }
184
- async fetchJson(url, token) {
185
- const response = await fetch(url, {
186
- headers: {
187
- "Accept": "application/vnd.github.v3+json",
188
- "Authorization": `Bearer ${token}`,
189
- "User-Agent": "trie-agents",
190
- "X-GitHub-Api-Version": "2022-11-28"
191
- }
192
- });
193
- if (response.status === 401) {
194
- throw new Error(
195
- "GitHub token is invalid or expired. Set a valid token:\n \u2022 Environment: GITHUB_TOKEN=ghp_...\n \u2022 Config: trie config \u2192 API Keys \u2192 GitHub"
196
- );
197
- }
198
- if (response.status === 403) {
199
- const resetHeader = response.headers.get("X-RateLimit-Reset");
200
- const resetTime = resetHeader ? new Date(parseInt(resetHeader, 10) * 1e3).toLocaleTimeString() : "unknown";
201
- throw new Error(`GitHub API rate limit exceeded. Resets at ${resetTime}.`);
202
- }
203
- if (response.status === 404) {
204
- throw new Error("Repository not found or token lacks access. Ensure the token has `repo` scope.");
205
- }
206
- if (!response.ok) {
207
- throw new Error(`GitHub API error ${response.status}: ${response.statusText}`);
208
- }
209
- return await response.json();
210
- }
211
- };
212
-
213
- export {
214
- GitHubIngester
215
- };
216
- //# sourceMappingURL=chunk-F6WFNUAY.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ingest/github-ingester.ts"],"sourcesContent":["import path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { loadConfig } from '../config/loader.js';\nimport { ContextGraph } from '../context/graph.js';\nimport type { PullRequestNodeData, GitHubIssueNodeData } from '../context/nodes.js';\n\nconst TICKET_PATTERN = /\\b([A-Z]{2,10}-\\d+)\\b/g;\n\ninterface GitHubPR {\n number: number;\n title: string;\n html_url: string;\n state: string;\n draft: boolean;\n user: { login: string };\n head: { ref: string };\n base: { ref: string };\n body: string | null;\n created_at: string;\n updated_at: string;\n merged_at: string | null;\n}\n\ninterface GitHubFile {\n filename: string;\n}\n\ninterface GitHubReview {\n state: string;\n}\n\ninterface GitHubIssue {\n number: number;\n title: string;\n html_url: string;\n state: string;\n labels: Array<{ name: string }>;\n assignees: Array<{ login: string }>;\n body: string | null;\n pull_request?: unknown;\n created_at: string;\n updated_at: string;\n closed_at: string | null;\n}\n\ninterface GitHubCommitStatus {\n state: string;\n}\n\nexport interface GitHubSyncResult {\n prs: number;\n issues: number;\n linkedTickets: number;\n linkedFiles: number;\n}\n\nexport class GitHubIngester {\n private readonly graph: ContextGraph;\n\n constructor(graph: ContextGraph) {\n this.graph = graph;\n }\n\n async getApiToken(): Promise<string | null> {\n const config = await loadConfig();\n return config.apiKeys?.github ?? process.env.GITHUB_TOKEN ?? null;\n }\n\n getRepoInfo(projectPath: string): { owner: string; name: string } | null {\n try {\n const url = execSync('git remote get-url origin', {\n cwd: projectPath,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n // SSH: git@github.com:owner/repo.git\n const sshMatch = url.match(/github\\.com[:/]([^/]+)\\/([^/.]+)/);\n if (sshMatch) {\n return { owner: sshMatch[1]!, name: sshMatch[2]! };\n }\n\n // HTTPS: https://github.com/owner/repo.git\n const httpsMatch = url.match(/github\\.com\\/([^/]+)\\/([^/.]+)/);\n if (httpsMatch) {\n return { owner: httpsMatch[1]!, name: httpsMatch[2]! };\n }\n\n return null;\n } catch {\n return null;\n }\n }\n\n async syncPullRequests(owner: string, repo: string, token: string): Promise<{ prs: number; linkedTickets: number; linkedFiles: number }> {\n const prs = await this.fetchJson<GitHubPR[]>(\n `https://api.github.com/repos/${owner}/${repo}/pulls?state=open&per_page=50`,\n token,\n );\n\n let linkedTickets = 0;\n let linkedFiles = 0;\n\n for (const pr of prs) {\n const filesChanged = await this.fetchPRFiles(owner, repo, pr.number, token);\n const reviewStatus = await this.fetchReviewStatus(owner, repo, pr.number, token);\n const ciStatus = await this.fetchCIStatus(owner, repo, pr.head.ref, token);\n const linkedTicketIds = this.extractTicketIds(pr.title, pr.body);\n\n const state: PullRequestNodeData['state'] = pr.draft ? 'draft' : pr.state === 'open' ? 'open' : 'closed';\n\n const data: PullRequestNodeData = {\n prNumber: pr.number,\n title: pr.title,\n url: pr.html_url,\n state,\n author: pr.user.login,\n branch: pr.head.ref,\n baseBranch: pr.base.ref,\n isDraft: pr.draft,\n filesChanged,\n linkedTicketIds,\n ciStatus,\n reviewStatus,\n createdAt: pr.created_at,\n updatedAt: pr.updated_at,\n ...(pr.merged_at != null && { mergedAt: pr.merged_at }),\n };\n\n const prNodeId = `pr:${pr.number}`;\n\n const existingNode = await this.graph.getNode('pull-request', prNodeId);\n if (existingNode) {\n await this.graph.updateNode('pull-request', prNodeId, data);\n } else {\n await this.graph.addNode('pull-request', data);\n }\n\n // Link PR to files it touches (file node IDs are normalized absolute paths)\n for (const file of filesChanged) {\n const resolvedPath = path.resolve(this.graph.projectRoot, file);\n const fileNode = await this.graph.getNode('file', resolvedPath);\n if (fileNode) {\n linkedFiles++;\n await this.graph.addEdge(prNodeId, fileNode.id, 'affects');\n }\n }\n\n // Link Linear tickets to this PR\n for (const ticketId of linkedTicketIds) {\n const ticketNodeId = `linear:${ticketId}`;\n const ticketNode = await this.graph.getNode('linear-ticket', ticketNodeId);\n if (ticketNode) {\n linkedTickets++;\n await this.graph.addEdge(ticketNodeId, prNodeId, 'implements');\n }\n }\n }\n\n return { prs: prs.length, linkedTickets, linkedFiles };\n }\n\n async syncIssues(owner: string, repo: string, token: string): Promise<{ issues: number }> {\n const allItems = await this.fetchJson<GitHubIssue[]>(\n `https://api.github.com/repos/${owner}/${repo}/issues?state=open&per_page=50`,\n token,\n );\n\n // GitHub returns PRs in the issues endpoint — filter them out\n const issues = allItems.filter(item => !item.pull_request);\n\n for (const issue of issues) {\n const linkedTicketIds = this.extractTicketIds(issue.title, issue.body);\n\n const data: GitHubIssueNodeData = {\n issueNumber: issue.number,\n title: issue.title,\n url: issue.html_url,\n state: issue.state as 'open' | 'closed',\n labels: issue.labels.map(l => l.name),\n assignees: issue.assignees.map(a => a.login),\n body: issue.body ?? '',\n linkedTicketIds,\n createdAt: issue.created_at,\n updatedAt: issue.updated_at,\n ...(issue.closed_at != null && { closedAt: issue.closed_at }),\n };\n\n const issueNodeId = `gh-issue:${issue.number}`;\n\n const existingNode = await this.graph.getNode('github-issue', issueNodeId);\n if (existingNode) {\n await this.graph.updateNode('github-issue', issueNodeId, data);\n } else {\n await this.graph.addNode('github-issue', data);\n }\n\n // Link to related Linear tickets\n for (const ticketId of linkedTicketIds) {\n const ticketNodeId = `linear:${ticketId}`;\n const ticketNode = await this.graph.getNode('linear-ticket', ticketNodeId);\n if (ticketNode) {\n await this.graph.addEdge(issueNodeId, ticketNodeId, 'relatedTo');\n }\n }\n }\n\n return { issues: issues.length };\n }\n\n private async fetchPRFiles(owner: string, repo: string, prNumber: number, token: string): Promise<string[]> {\n try {\n const files = await this.fetchJson<GitHubFile[]>(\n `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/files?per_page=100`,\n token,\n );\n return files.map(f => f.filename);\n } catch {\n return [];\n }\n }\n\n private async fetchReviewStatus(\n owner: string,\n repo: string,\n prNumber: number,\n token: string,\n ): Promise<PullRequestNodeData['reviewStatus']> {\n try {\n const reviews = await this.fetchJson<GitHubReview[]>(\n `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/reviews`,\n token,\n );\n if (reviews.length === 0) return 'none';\n\n const states = reviews.map(r => r.state);\n if (states.includes('CHANGES_REQUESTED')) return 'changes_requested';\n if (states.includes('APPROVED')) return 'approved';\n return 'pending';\n } catch {\n return 'none';\n }\n }\n\n private async fetchCIStatus(\n owner: string,\n repo: string,\n ref: string,\n token: string,\n ): Promise<PullRequestNodeData['ciStatus']> {\n try {\n const status = await this.fetchJson<GitHubCommitStatus>(\n `https://api.github.com/repos/${owner}/${repo}/commits/${ref}/status`,\n token,\n );\n switch (status.state) {\n case 'success': return 'passing';\n case 'failure': case 'error': return 'failing';\n case 'pending': return 'pending';\n default: return 'unknown';\n }\n } catch {\n return 'unknown';\n }\n }\n\n private extractTicketIds(title: string, body: string | null): string[] {\n const text = `${title} ${body ?? ''}`;\n const matches = text.match(TICKET_PATTERN);\n return matches ? [...new Set(matches)] : [];\n }\n\n private async fetchJson<T>(url: string, token: string): Promise<T> {\n const response = await fetch(url, {\n headers: {\n 'Accept': 'application/vnd.github.v3+json',\n 'Authorization': `Bearer ${token}`,\n 'User-Agent': 'trie-agents',\n 'X-GitHub-Api-Version': '2022-11-28',\n },\n });\n\n if (response.status === 401) {\n throw new Error(\n 'GitHub token is invalid or expired. Set a valid token:\\n' +\n ' • Environment: GITHUB_TOKEN=ghp_...\\n' +\n ' • Config: trie config → API Keys → GitHub',\n );\n }\n\n if (response.status === 403) {\n const resetHeader = response.headers.get('X-RateLimit-Reset');\n const resetTime = resetHeader\n ? new Date(parseInt(resetHeader, 10) * 1000).toLocaleTimeString()\n : 'unknown';\n throw new Error(`GitHub API rate limit exceeded. Resets at ${resetTime}.`);\n }\n\n if (response.status === 404) {\n throw new Error('Repository not found or token lacks access. Ensure the token has `repo` scope.');\n }\n\n if (!response.ok) {\n throw new Error(`GitHub API error ${response.status}: ${response.statusText}`);\n }\n\n return (await response.json()) as T;\n }\n}\n"],"mappings":"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","names":[]}