opencode-agora 0.3.0 → 0.4.1

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 (280) hide show
  1. package/README.md +86 -255
  2. package/dist/atomic-write.d.ts +10 -0
  3. package/dist/atomic-write.d.ts.map +1 -0
  4. package/dist/atomic-write.js +23 -0
  5. package/dist/atomic-write.js.map +1 -0
  6. package/dist/auth/refresh.d.ts +17 -0
  7. package/dist/auth/refresh.d.ts.map +1 -0
  8. package/dist/auth/refresh.js +50 -0
  9. package/dist/auth/refresh.js.map +1 -0
  10. package/dist/cli/app.d.ts +13 -18
  11. package/dist/cli/app.d.ts.map +1 -1
  12. package/dist/cli/app.js +184 -1187
  13. package/dist/cli/app.js.map +1 -1
  14. package/dist/cli/chat-renderer.d.ts +31 -0
  15. package/dist/cli/chat-renderer.d.ts.map +1 -0
  16. package/dist/cli/chat-renderer.js +275 -0
  17. package/dist/cli/chat-renderer.js.map +1 -0
  18. package/dist/cli/commands/browse.d.ts +4 -0
  19. package/dist/cli/commands/browse.d.ts.map +1 -0
  20. package/dist/cli/commands/browse.js +80 -0
  21. package/dist/cli/commands/browse.js.map +1 -0
  22. package/dist/cli/commands/chat.d.ts +4 -0
  23. package/dist/cli/commands/chat.d.ts.map +1 -0
  24. package/dist/cli/commands/chat.js +125 -0
  25. package/dist/cli/commands/chat.js.map +1 -0
  26. package/dist/cli/commands/community.d.ts +12 -0
  27. package/dist/cli/commands/community.d.ts.map +1 -0
  28. package/dist/cli/commands/community.js +453 -0
  29. package/dist/cli/commands/community.js.map +1 -0
  30. package/dist/cli/commands/export.d.ts +3 -0
  31. package/dist/cli/commands/export.d.ts.map +1 -0
  32. package/dist/cli/commands/export.js +108 -0
  33. package/dist/cli/commands/export.js.map +1 -0
  34. package/dist/cli/commands/init.d.ts +4 -0
  35. package/dist/cli/commands/init.d.ts.map +1 -0
  36. package/dist/cli/commands/init.js +299 -0
  37. package/dist/cli/commands/init.js.map +1 -0
  38. package/dist/cli/commands/learn.d.ts +4 -0
  39. package/dist/cli/commands/learn.d.ts.map +1 -0
  40. package/dist/cli/commands/learn.js +62 -0
  41. package/dist/cli/commands/learn.js.map +1 -0
  42. package/dist/cli/commands/marketplace.d.ts +9 -0
  43. package/dist/cli/commands/marketplace.d.ts.map +1 -0
  44. package/dist/cli/commands/marketplace.js +321 -0
  45. package/dist/cli/commands/marketplace.js.map +1 -0
  46. package/dist/cli/commands/notify.d.ts +3 -0
  47. package/dist/cli/commands/notify.d.ts.map +1 -0
  48. package/dist/cli/commands/notify.js +59 -0
  49. package/dist/cli/commands/notify.js.map +1 -0
  50. package/dist/cli/commands/operations.d.ts +16 -0
  51. package/dist/cli/commands/operations.d.ts.map +1 -0
  52. package/dist/cli/commands/operations.js +1006 -0
  53. package/dist/cli/commands/operations.js.map +1 -0
  54. package/dist/cli/commands/ping.d.ts +3 -0
  55. package/dist/cli/commands/ping.d.ts.map +1 -0
  56. package/dist/cli/commands/ping.js +56 -0
  57. package/dist/cli/commands/ping.js.map +1 -0
  58. package/dist/cli/commands/today.d.ts +3 -0
  59. package/dist/cli/commands/today.d.ts.map +1 -0
  60. package/dist/cli/commands/today.js +142 -0
  61. package/dist/cli/commands/today.js.map +1 -0
  62. package/dist/cli/commands/types.d.ts +5 -0
  63. package/dist/cli/commands/types.d.ts.map +1 -0
  64. package/dist/cli/commands/types.js +2 -0
  65. package/dist/cli/commands/types.js.map +1 -0
  66. package/dist/cli/commands/watch.d.ts +3 -0
  67. package/dist/cli/commands/watch.d.ts.map +1 -0
  68. package/dist/cli/commands/watch.js +41 -0
  69. package/dist/cli/commands/watch.js.map +1 -0
  70. package/dist/cli/commands/welcome.d.ts +3 -0
  71. package/dist/cli/commands/welcome.d.ts.map +1 -0
  72. package/dist/cli/commands/welcome.js +97 -0
  73. package/dist/cli/commands/welcome.js.map +1 -0
  74. package/dist/cli/commands-meta.d.ts +21 -0
  75. package/dist/cli/commands-meta.d.ts.map +1 -0
  76. package/dist/cli/commands-meta.js +828 -0
  77. package/dist/cli/commands-meta.js.map +1 -0
  78. package/dist/cli/completions-gen.d.ts +2 -0
  79. package/dist/cli/completions-gen.d.ts.map +1 -0
  80. package/dist/cli/completions-gen.js +195 -0
  81. package/dist/cli/completions-gen.js.map +1 -0
  82. package/dist/cli/completions.d.ts +18 -0
  83. package/dist/cli/completions.d.ts.map +1 -0
  84. package/dist/cli/completions.js +227 -0
  85. package/dist/cli/completions.js.map +1 -0
  86. package/dist/cli/flags.d.ts +19 -0
  87. package/dist/cli/flags.d.ts.map +1 -0
  88. package/dist/cli/flags.js +91 -0
  89. package/dist/cli/flags.js.map +1 -0
  90. package/dist/cli/format.d.ts +19 -0
  91. package/dist/cli/format.d.ts.map +1 -0
  92. package/dist/cli/format.js +249 -0
  93. package/dist/cli/format.js.map +1 -0
  94. package/dist/cli/helpers.d.ts +95 -0
  95. package/dist/cli/helpers.d.ts.map +1 -0
  96. package/dist/cli/helpers.js +301 -0
  97. package/dist/cli/helpers.js.map +1 -0
  98. package/dist/cli/mcp-server.d.ts +4 -0
  99. package/dist/cli/mcp-server.d.ts.map +1 -0
  100. package/dist/cli/mcp-server.js +277 -0
  101. package/dist/cli/mcp-server.js.map +1 -0
  102. package/dist/cli/menu.d.ts +7 -0
  103. package/dist/cli/menu.d.ts.map +1 -0
  104. package/dist/cli/menu.js +172 -0
  105. package/dist/cli/menu.js.map +1 -0
  106. package/dist/cli/pages/community.d.ts +9 -0
  107. package/dist/cli/pages/community.d.ts.map +1 -0
  108. package/dist/cli/pages/community.js +1094 -0
  109. package/dist/cli/pages/community.js.map +1 -0
  110. package/dist/cli/pages/helpers.d.ts +37 -0
  111. package/dist/cli/pages/helpers.d.ts.map +1 -0
  112. package/dist/cli/pages/helpers.js +98 -0
  113. package/dist/cli/pages/helpers.js.map +1 -0
  114. package/dist/cli/pages/home.d.ts +4 -0
  115. package/dist/cli/pages/home.d.ts.map +1 -0
  116. package/dist/cli/pages/home.js +231 -0
  117. package/dist/cli/pages/home.js.map +1 -0
  118. package/dist/cli/pages/marketplace.d.ts +5 -0
  119. package/dist/cli/pages/marketplace.d.ts.map +1 -0
  120. package/dist/cli/pages/marketplace.js +583 -0
  121. package/dist/cli/pages/marketplace.js.map +1 -0
  122. package/dist/cli/pages/news.d.ts +31 -0
  123. package/dist/cli/pages/news.d.ts.map +1 -0
  124. package/dist/cli/pages/news.js +688 -0
  125. package/dist/cli/pages/news.js.map +1 -0
  126. package/dist/cli/pages/settings.d.ts +3 -0
  127. package/dist/cli/pages/settings.d.ts.map +1 -0
  128. package/dist/cli/pages/settings.js +296 -0
  129. package/dist/cli/pages/settings.js.map +1 -0
  130. package/dist/cli/pages/types.d.ts +67 -0
  131. package/dist/cli/pages/types.d.ts.map +1 -0
  132. package/dist/cli/pages/types.js +2 -0
  133. package/dist/cli/pages/types.js.map +1 -0
  134. package/dist/cli/prompter.d.ts +135 -0
  135. package/dist/cli/prompter.d.ts.map +1 -0
  136. package/dist/cli/prompter.js +710 -0
  137. package/dist/cli/prompter.js.map +1 -0
  138. package/dist/cli/shell.d.ts +23 -0
  139. package/dist/cli/shell.d.ts.map +1 -0
  140. package/dist/cli/shell.js +1106 -0
  141. package/dist/cli/shell.js.map +1 -0
  142. package/dist/cli/tui.d.ts +7 -0
  143. package/dist/cli/tui.d.ts.map +1 -0
  144. package/dist/cli/tui.js +419 -0
  145. package/dist/cli/tui.js.map +1 -0
  146. package/dist/cli.js +1 -1
  147. package/dist/cli.js.map +1 -1
  148. package/dist/commands.d.ts +14 -0
  149. package/dist/commands.d.ts.map +1 -0
  150. package/dist/commands.js +28 -0
  151. package/dist/commands.js.map +1 -0
  152. package/dist/community/client.d.ts +84 -0
  153. package/dist/community/client.d.ts.map +1 -0
  154. package/dist/community/client.js +340 -0
  155. package/dist/community/client.js.map +1 -0
  156. package/dist/community/search.d.ts +25 -0
  157. package/dist/community/search.d.ts.map +1 -0
  158. package/dist/community/search.js +62 -0
  159. package/dist/community/search.js.map +1 -0
  160. package/dist/community/types.d.ts +71 -0
  161. package/dist/community/types.d.ts.map +1 -0
  162. package/dist/community/types.js +11 -0
  163. package/dist/community/types.js.map +1 -0
  164. package/dist/config.d.ts +1 -7
  165. package/dist/config.d.ts.map +1 -1
  166. package/dist/config.js +0 -32
  167. package/dist/config.js.map +1 -1
  168. package/dist/data.d.ts +1 -1
  169. package/dist/data.d.ts.map +1 -1
  170. package/dist/data.js +778 -40
  171. package/dist/data.js.map +1 -1
  172. package/dist/format.d.ts +5 -39
  173. package/dist/format.d.ts.map +1 -1
  174. package/dist/format.js +5 -120
  175. package/dist/format.js.map +1 -1
  176. package/dist/history.d.ts +13 -0
  177. package/dist/history.d.ts.map +1 -0
  178. package/dist/history.js +37 -0
  179. package/dist/history.js.map +1 -0
  180. package/dist/hubs/cache.d.ts +6 -0
  181. package/dist/hubs/cache.d.ts.map +1 -0
  182. package/dist/hubs/cache.js +46 -0
  183. package/dist/hubs/cache.js.map +1 -0
  184. package/dist/hubs/enrichment.d.ts +43 -0
  185. package/dist/hubs/enrichment.d.ts.map +1 -0
  186. package/dist/hubs/enrichment.js +239 -0
  187. package/dist/hubs/enrichment.js.map +1 -0
  188. package/dist/hubs/github.d.ts +12 -0
  189. package/dist/hubs/github.d.ts.map +1 -0
  190. package/dist/hubs/github.js +54 -0
  191. package/dist/hubs/github.js.map +1 -0
  192. package/dist/hubs/huggingface.d.ts +27 -0
  193. package/dist/hubs/huggingface.d.ts.map +1 -0
  194. package/dist/hubs/huggingface.js +88 -0
  195. package/dist/hubs/huggingface.js.map +1 -0
  196. package/dist/hubs/quality.d.ts +26 -0
  197. package/dist/hubs/quality.d.ts.map +1 -0
  198. package/dist/hubs/quality.js +57 -0
  199. package/dist/hubs/quality.js.map +1 -0
  200. package/dist/hubs/types.d.ts +30 -0
  201. package/dist/hubs/types.d.ts.map +1 -0
  202. package/dist/hubs/types.js +2 -0
  203. package/dist/hubs/types.js.map +1 -0
  204. package/dist/index.d.ts.map +1 -1
  205. package/dist/index.js +188 -224
  206. package/dist/index.js.map +1 -1
  207. package/dist/init.d.ts.map +1 -1
  208. package/dist/init.js +6 -11
  209. package/dist/init.js.map +1 -1
  210. package/dist/live.d.ts +14 -0
  211. package/dist/live.d.ts.map +1 -1
  212. package/dist/live.js +35 -3
  213. package/dist/live.js.map +1 -1
  214. package/dist/marketplace.d.ts +25 -3
  215. package/dist/marketplace.d.ts.map +1 -1
  216. package/dist/marketplace.js +279 -22
  217. package/dist/marketplace.js.map +1 -1
  218. package/dist/news/cache.d.ts +13 -0
  219. package/dist/news/cache.d.ts.map +1 -0
  220. package/dist/news/cache.js +66 -0
  221. package/dist/news/cache.js.map +1 -0
  222. package/dist/news/score.d.ts +4 -0
  223. package/dist/news/score.d.ts.map +1 -0
  224. package/dist/news/score.js +43 -0
  225. package/dist/news/score.js.map +1 -0
  226. package/dist/news/sources/arxiv.d.ts +9 -0
  227. package/dist/news/sources/arxiv.d.ts.map +1 -0
  228. package/dist/news/sources/arxiv.js +107 -0
  229. package/dist/news/sources/arxiv.js.map +1 -0
  230. package/dist/news/sources/github-trending.d.ts +9 -0
  231. package/dist/news/sources/github-trending.d.ts.map +1 -0
  232. package/dist/news/sources/github-trending.js +97 -0
  233. package/dist/news/sources/github-trending.js.map +1 -0
  234. package/dist/news/sources/hn.d.ts +9 -0
  235. package/dist/news/sources/hn.d.ts.map +1 -0
  236. package/dist/news/sources/hn.js +57 -0
  237. package/dist/news/sources/hn.js.map +1 -0
  238. package/dist/news/sources/reddit.d.ts +9 -0
  239. package/dist/news/sources/reddit.d.ts.map +1 -0
  240. package/dist/news/sources/reddit.js +69 -0
  241. package/dist/news/sources/reddit.js.map +1 -0
  242. package/dist/news/sources/rss.d.ts +13 -0
  243. package/dist/news/sources/rss.d.ts.map +1 -0
  244. package/dist/news/sources/rss.js +14 -0
  245. package/dist/news/sources/rss.js.map +1 -0
  246. package/dist/news/types.d.ts +42 -0
  247. package/dist/news/types.d.ts.map +1 -0
  248. package/dist/news/types.js +56 -0
  249. package/dist/news/types.js.map +1 -0
  250. package/dist/preferences.d.ts +14 -0
  251. package/dist/preferences.d.ts.map +1 -0
  252. package/dist/preferences.js +31 -0
  253. package/dist/preferences.js.map +1 -0
  254. package/dist/settings.d.ts +26 -0
  255. package/dist/settings.d.ts.map +1 -0
  256. package/dist/settings.js +251 -0
  257. package/dist/settings.js.map +1 -0
  258. package/dist/state.d.ts +9 -2
  259. package/dist/state.d.ts.map +1 -1
  260. package/dist/state.js +41 -19
  261. package/dist/state.js.map +1 -1
  262. package/dist/transcript.d.ts +28 -0
  263. package/dist/transcript.d.ts.map +1 -0
  264. package/dist/transcript.js +79 -0
  265. package/dist/transcript.js.map +1 -0
  266. package/dist/types.d.ts +19 -1
  267. package/dist/types.d.ts.map +1 -1
  268. package/dist/ui.d.ts +157 -0
  269. package/dist/ui.d.ts.map +1 -0
  270. package/dist/ui.js +296 -0
  271. package/dist/ui.js.map +1 -0
  272. package/package.json +11 -9
  273. package/dist/api.d.ts +0 -72
  274. package/dist/api.d.ts.map +0 -1
  275. package/dist/api.js +0 -109
  276. package/dist/api.js.map +0 -1
  277. package/dist/logger.d.ts +0 -20
  278. package/dist/logger.d.ts.map +0 -1
  279. package/dist/logger.js +0 -59
  280. package/dist/logger.js.map +0 -1
@@ -0,0 +1,239 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { atomicWriteFile } from '../atomic-write.js';
3
+ import { join } from 'node:path';
4
+ import { spawn } from 'node:child_process';
5
+ import { FREE_MODELS } from '../cli/commands/chat.js';
6
+ import { extractPostInstallHint } from '../marketplace.js';
7
+ export function enrichmentPath(dataDir) {
8
+ return join(dataDir, 'hubs-enrichment.json');
9
+ }
10
+ export function readEnrichmentStore(dataDir) {
11
+ const path = enrichmentPath(dataDir);
12
+ if (!existsSync(path))
13
+ return {};
14
+ try {
15
+ const raw = readFileSync(path, 'utf8');
16
+ return JSON.parse(raw);
17
+ }
18
+ catch {
19
+ return {};
20
+ }
21
+ }
22
+ export function writeEnrichmentStore(dataDir, store) {
23
+ atomicWriteFile(enrichmentPath(dataDir), JSON.stringify(store, null, 2));
24
+ }
25
+ export function getEnrichment(store, repoId, commitSha) {
26
+ return store[`${repoId}@${commitSha}`];
27
+ }
28
+ export function setEnrichment(store, entry) {
29
+ return { ...store, [`${entry.repoId}@${entry.commitSha}`]: entry };
30
+ }
31
+ export async function fetchRepoMetadata(repoId, opts = {}) {
32
+ const fetcher = opts.fetcher ?? globalThis.fetch;
33
+ const token = opts.token ?? process.env.AGORA_GITHUB_TOKEN;
34
+ const headers = {
35
+ Accept: 'application/vnd.github+json',
36
+ 'X-GitHub-Api-Version': '2022-11-28',
37
+ 'User-Agent': 'agora-cli'
38
+ };
39
+ if (token)
40
+ headers.Authorization = `Bearer ${token}`;
41
+ try {
42
+ const commitsUrl = `https://api.github.com/repos/${repoId}/commits?per_page=1`;
43
+ const commitsRes = await fetcher(commitsUrl, { headers, signal: opts.signal });
44
+ if (!commitsRes.ok)
45
+ return null;
46
+ const commitsJson = (await commitsRes.json());
47
+ const commitSha = commitsJson[0]?.sha;
48
+ if (!commitSha)
49
+ return null;
50
+ const readmeUrl = `https://api.github.com/repos/${repoId}/readme`;
51
+ const readmeRes = await fetcher(readmeUrl, { headers, signal: opts.signal });
52
+ if (!readmeRes.ok)
53
+ return null;
54
+ const readmeJson = (await readmeRes.json());
55
+ if (!readmeJson.content)
56
+ return null;
57
+ const readme = Buffer.from(readmeJson.content, 'base64').toString('utf8');
58
+ return { commitSha, readme };
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ export async function fetchHfRepoMetadata(repoId, opts = {}) {
65
+ const fetcher = opts.fetcher ?? globalThis.fetch;
66
+ const headers = {
67
+ Accept: 'application/json',
68
+ 'User-Agent': 'agora-cli'
69
+ };
70
+ const cardRes = await fetcher(`https://huggingface.co/api/models/${repoId}`, {
71
+ headers,
72
+ signal: opts.signal
73
+ });
74
+ if (!cardRes.ok)
75
+ return null;
76
+ const card = (await cardRes.json());
77
+ const version = card.lastModified;
78
+ if (!version)
79
+ return null;
80
+ const endpoints = ['models', 'datasets', 'spaces'];
81
+ let readme = null;
82
+ for (const ep of endpoints) {
83
+ const url = ep === 'models'
84
+ ? `https://huggingface.co/${repoId}/raw/main/README.md`
85
+ : `https://huggingface.co/${ep}/${repoId}/raw/main/README.md`;
86
+ const res = await fetcher(url, { headers, signal: opts.signal });
87
+ if (res.ok) {
88
+ readme = await res.text();
89
+ break;
90
+ }
91
+ }
92
+ if (!readme)
93
+ return null;
94
+ const maxChars = 8000;
95
+ const trimmed = readme.length > maxChars ? readme.slice(0, maxChars) + '\n...(truncated)' : readme;
96
+ return { version, readme: trimmed };
97
+ }
98
+ async function callOpencode(prompt) {
99
+ const model = FREE_MODELS[0];
100
+ const modelArg = model.includes('/') ? model : `opencode/${model}`;
101
+ return new Promise((resolve) => {
102
+ const child = spawn('opencode', ['run', '--format', 'json', '--model', modelArg, prompt], {
103
+ stdio: ['ignore', 'pipe', 'pipe'],
104
+ shell: false
105
+ });
106
+ let response = '';
107
+ const timer = setTimeout(() => {
108
+ child.kill();
109
+ resolve(null);
110
+ }, 30000);
111
+ child.stdout.on('data', (chunk) => {
112
+ for (const line of chunk.toString().split('\n').filter(Boolean)) {
113
+ try {
114
+ const ev = JSON.parse(line);
115
+ if (ev.type === 'text' && ev.part?.text)
116
+ response += ev.part.text;
117
+ }
118
+ catch {
119
+ /* skip */
120
+ }
121
+ }
122
+ });
123
+ child.on('close', () => {
124
+ clearTimeout(timer);
125
+ resolve(response || null);
126
+ });
127
+ child.on('error', () => {
128
+ clearTimeout(timer);
129
+ resolve(null);
130
+ });
131
+ });
132
+ }
133
+ export async function generateDescription(readme, opencodeFn) {
134
+ const maxChars = 8000;
135
+ const trimmed = readme.length > maxChars ? readme.slice(0, maxChars) + '\n...(truncated)' : readme;
136
+ const prompt = `<system>\nYou are summarizing an open-source repository's README. Write ONE sentence (max 20 words) describing what this repo does. Be concrete; no marketing language.\n<user>\n${trimmed}`;
137
+ const result = await (opencodeFn ?? callOpencode)(prompt);
138
+ if (!result)
139
+ return null;
140
+ const trimmedResult = result.trim();
141
+ return trimmedResult || null;
142
+ }
143
+ export async function generateInstallHint(readme, opencodeFn) {
144
+ const maxChars = 8000;
145
+ const trimmed = readme.length > maxChars ? readme.slice(0, maxChars) + '\n...(truncated)' : readme;
146
+ const prompt = `<system>\nExtract the single install command or step from this README. Return ONE line, max 100 chars. If unclear, return 'UNKNOWN'. Do not add commentary.\n<user>\n${trimmed}`;
147
+ const result = await (opencodeFn ?? callOpencode)(prompt);
148
+ if (!result)
149
+ return null;
150
+ const trimmedResult = result.trim();
151
+ if (!trimmedResult || trimmedResult.toUpperCase() === 'UNKNOWN')
152
+ return null;
153
+ return trimmedResult;
154
+ }
155
+ export async function enrichItem(repoId, dataDir, opts = {}) {
156
+ const store = readEnrichmentStore(dataDir);
157
+ // Check if we already have a cached entry for this repoId
158
+ const existingEntry = Object.values(store).find((e) => e.repoId === repoId);
159
+ // Fetch the latest commit sha (cheap call)
160
+ const fetcher = opts.fetcher ?? globalThis.fetch;
161
+ const token = opts.token ?? process.env.AGORA_GITHUB_TOKEN;
162
+ const headers = {
163
+ Accept: 'application/vnd.github+json',
164
+ 'X-GitHub-Api-Version': '2022-11-28',
165
+ 'User-Agent': 'agora-cli'
166
+ };
167
+ if (token)
168
+ headers.Authorization = `Bearer ${token}`;
169
+ let latestSha = null;
170
+ try {
171
+ const commitsUrl = `https://api.github.com/repos/${repoId}/commits?per_page=1`;
172
+ const commitsRes = await fetcher(commitsUrl, { headers });
173
+ if (commitsRes.ok) {
174
+ const commitsJson = (await commitsRes.json());
175
+ latestSha = commitsJson[0]?.sha ?? null;
176
+ }
177
+ }
178
+ catch {
179
+ // If we can't fetch SHA, return cached if available
180
+ if (existingEntry)
181
+ return existingEntry;
182
+ return null;
183
+ }
184
+ if (!latestSha) {
185
+ if (existingEntry)
186
+ return existingEntry;
187
+ return null;
188
+ }
189
+ // Cache hit: sha matches
190
+ if (existingEntry && existingEntry.commitSha === latestSha) {
191
+ return existingEntry;
192
+ }
193
+ // Need to fetch full metadata
194
+ const meta = await fetchRepoMetadata(repoId, { fetcher, token });
195
+ if (!meta)
196
+ return null;
197
+ const [description, aiHint] = await Promise.all([
198
+ generateDescription(meta.readme, opts.opencode),
199
+ generateInstallHint(meta.readme, opts.opencode)
200
+ ]);
201
+ const installHint = aiHint ?? extractPostInstallHint(meta.readme);
202
+ const entry = {
203
+ repoId,
204
+ commitSha: meta.commitSha,
205
+ description: description ?? undefined,
206
+ installHint: installHint ?? undefined,
207
+ fetchedAt: new Date().toISOString()
208
+ };
209
+ const updated = setEnrichment(store, entry);
210
+ writeEnrichmentStore(dataDir, updated);
211
+ return entry;
212
+ }
213
+ export async function enrichHfItem(repoId, dataDir, opts = {}) {
214
+ const storeRepoId = `hf:${repoId}`;
215
+ const store = readEnrichmentStore(dataDir);
216
+ const existingEntry = Object.values(store).find((e) => e.repoId === storeRepoId);
217
+ const meta = await fetchHfRepoMetadata(repoId, { fetcher: opts.fetcher });
218
+ if (!meta) {
219
+ return existingEntry ?? null;
220
+ }
221
+ if (existingEntry && existingEntry.commitSha === meta.version) {
222
+ return existingEntry;
223
+ }
224
+ const [description, installHint] = await Promise.all([
225
+ generateDescription(meta.readme, opts.opencode),
226
+ generateInstallHint(meta.readme, opts.opencode)
227
+ ]);
228
+ const entry = {
229
+ repoId: storeRepoId,
230
+ commitSha: meta.version,
231
+ description: description ?? undefined,
232
+ installHint: installHint ?? undefined,
233
+ fetchedAt: new Date().toISOString()
234
+ };
235
+ const updated = setEnrichment(store, entry);
236
+ writeEnrichmentStore(dataDir, updated);
237
+ return entry;
238
+ }
239
+ //# sourceMappingURL=enrichment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment.js","sourceRoot":"","sources":["../../src/hubs/enrichment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { HubItem } from './types.js';
2
+ export declare const TOPICS: string[];
3
+ export type FetchLike = (input: string | URL, init?: RequestInit) => Promise<Response>;
4
+ export interface GithubSearchOptions {
5
+ fetcher?: FetchLike;
6
+ signal?: AbortSignal;
7
+ token?: string;
8
+ topics?: string[];
9
+ now?: Date;
10
+ }
11
+ export declare function searchGithub(opts?: GithubSearchOptions): Promise<HubItem[]>;
12
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/hubs/github.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,eAAO,MAAM,MAAM,UASlB,CAAC;AAIF,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvF,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,wBAAsB,YAAY,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAwCrF"}
@@ -0,0 +1,54 @@
1
+ import { passes, toHubItem } from './quality.js';
2
+ export const TOPICS = [
3
+ 'mcp',
4
+ 'model-context-protocol',
5
+ 'claude-skill',
6
+ 'claude-code',
7
+ 'agent-tools',
8
+ 'llm-tools',
9
+ 'langchain',
10
+ 'opencode'
11
+ ];
12
+ const PER_TOPIC = 30;
13
+ export async function searchGithub(opts = {}) {
14
+ const fetcher = opts.fetcher ?? globalThis.fetch;
15
+ const topics = opts.topics ?? TOPICS;
16
+ const now = opts.now ?? new Date();
17
+ const fetchedAt = now.toISOString();
18
+ const token = opts.token ?? process.env.AGORA_GITHUB_TOKEN;
19
+ const headers = {
20
+ Accept: 'application/vnd.github+json',
21
+ 'X-GitHub-Api-Version': '2022-11-28',
22
+ 'User-Agent': 'agora-cli'
23
+ };
24
+ if (token)
25
+ headers.Authorization = `Bearer ${token}`;
26
+ const byId = new Map();
27
+ for (const topic of topics) {
28
+ const q = `topic:${topic}+stars:>=10`;
29
+ const url = `https://api.github.com/search/repositories?q=${q}&sort=stars&order=desc&per_page=${PER_TOPIC}`;
30
+ try {
31
+ const res = await fetcher(url, { headers, signal: opts.signal });
32
+ if (!res.ok)
33
+ continue;
34
+ const json = (await res.json());
35
+ for (const repo of json.items ?? []) {
36
+ if (!byId.has(repo.id))
37
+ byId.set(repo.id, repo);
38
+ }
39
+ }
40
+ catch {
41
+ continue; // graceful; we have cache fallback
42
+ }
43
+ }
44
+ const items = [];
45
+ for (const repo of byId.values()) {
46
+ if (!passes(repo, now))
47
+ continue;
48
+ items.push(toHubItem(repo, fetchedAt));
49
+ }
50
+ // Sort by stars descending for simplicity
51
+ items.sort((a, b) => b.stars - a.stars);
52
+ return items;
53
+ }
54
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/hubs/github.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAsB,MAAM,cAAc,CAAC;AAErE,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK;IACL,wBAAwB;IACxB,cAAc;IACd,aAAa;IACb,aAAa;IACb,WAAW;IACX,WAAW;IACX,UAAU;CACX,CAAC;AAEF,MAAM,SAAS,GAAG,EAAE,CAAC;AAYrB,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B,EAAE;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAE3D,MAAM,OAAO,GAA2B;QACtC,MAAM,EAAE,6BAA6B;QACrC,sBAAsB,EAAE,YAAY;QACpC,YAAY,EAAE,WAAW;KAC1B,CAAC;IACF,IAAI,KAAK;QAAE,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;IAErD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,SAAS,KAAK,aAAa,CAAC;QACtC,MAAM,GAAG,GAAG,gDAAgD,CAAC,mCAAmC,SAAS,EAAE,CAAC;QAC5G,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACjE,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,SAAS;YACtB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgC,CAAC;YAC/D,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;gBACpC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,mCAAmC;QAC/C,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAc,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC;YAAE,SAAS;QACjC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAExC,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { HubItem } from './types.js';
2
+ export type FetchLike = (input: string | URL, init?: RequestInit) => Promise<Response>;
3
+ export interface HfSearchOptions {
4
+ fetcher?: FetchLike;
5
+ signal?: AbortSignal;
6
+ now?: Date;
7
+ }
8
+ export declare const HF_QUERIES: {
9
+ endpoint: string;
10
+ filter: string;
11
+ limit: number;
12
+ }[];
13
+ export interface RawHfItem {
14
+ id: string;
15
+ modelId?: string;
16
+ author?: string;
17
+ downloads?: number;
18
+ likes?: number;
19
+ tags?: string[];
20
+ pipeline_tag?: string;
21
+ library_name?: string;
22
+ createdAt?: string;
23
+ lastModified?: string;
24
+ private?: boolean;
25
+ }
26
+ export declare function searchHuggingFace(opts?: HfSearchOptions): Promise<HubItem[]>;
27
+ //# sourceMappingURL=huggingface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"huggingface.d.ts","sourceRoot":"","sources":["../../src/hubs/huggingface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,GAAG,CAAC,EAAE,IAAI,CAAC;CAEZ;AAGD,eAAO,MAAM,UAAU;;;;GAMtB,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CAEnB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAuCtF"}
@@ -0,0 +1,88 @@
1
+ // Categories we care about, mapped to HF API endpoints
2
+ export const HF_QUERIES = [
3
+ { endpoint: 'models', filter: 'text-generation', limit: 50 },
4
+ { endpoint: 'models', filter: 'feature-extraction', limit: 25 },
5
+ { endpoint: 'models', filter: 'text2text-generation', limit: 25 },
6
+ { endpoint: 'datasets', filter: 'instruction-tuning', limit: 25 },
7
+ { endpoint: 'spaces', filter: 'chatbot', limit: 25 }
8
+ ];
9
+ export async function searchHuggingFace(opts = {}) {
10
+ const fetcher = opts.fetcher ?? globalThis.fetch;
11
+ const now = opts.now ?? new Date();
12
+ const fetchedAt = now.toISOString();
13
+ const headers = {
14
+ Accept: 'application/json',
15
+ 'User-Agent': 'agora-cli'
16
+ };
17
+ const byId = new Map();
18
+ for (const query of HF_QUERIES) {
19
+ const url = `https://huggingface.co/api/${query.endpoint}?filter=${query.filter}&sort=downloads&direction=-1&limit=${query.limit}`;
20
+ try {
21
+ const res = await fetcher(url, { headers, signal: opts.signal });
22
+ if (!res.ok)
23
+ continue;
24
+ const json = (await res.json());
25
+ for (const item of json ?? []) {
26
+ if (!item.id || !item.id.includes('/'))
27
+ continue;
28
+ if (!byId.has(item.id)) {
29
+ byId.set(item.id, { raw: item, endpoint: query.endpoint });
30
+ }
31
+ }
32
+ }
33
+ catch {
34
+ continue; // graceful; we have cache fallback
35
+ }
36
+ }
37
+ const items = [];
38
+ for (const { raw, endpoint } of byId.values()) {
39
+ if (!passesHf(raw, now))
40
+ continue;
41
+ items.push(toHubItem(raw, endpoint, fetchedAt));
42
+ }
43
+ // Sort by downloads (installs) descending
44
+ items.sort((a, b) => b.installs - a.installs);
45
+ return items;
46
+ }
47
+ function passesHf(item, _now) {
48
+ if (item.private)
49
+ return false;
50
+ if (!item.id || !item.author)
51
+ return false;
52
+ const downloads = item.downloads ?? 0;
53
+ const likes = item.likes ?? 0;
54
+ // Lower threshold than GitHub stars — HF downloads are noisier
55
+ if (downloads < 100 && likes < 5)
56
+ return false;
57
+ return true;
58
+ }
59
+ function toHubItem(raw, endpoint, fetchedAt) {
60
+ const [author, name] = raw.id.split('/');
61
+ return {
62
+ id: `hf:${raw.id}`,
63
+ source: 'hf',
64
+ name: name ?? raw.id,
65
+ description: raw.pipeline_tag
66
+ ? `${raw.pipeline_tag} ${endpoint.slice(0, -1)}` // 'text-generation model'
67
+ : endpoint.slice(0, -1), // fallback
68
+ author: author ?? raw.author ?? 'unknown',
69
+ version: 'main',
70
+ category: categorizeHf(endpoint, raw),
71
+ tags: Array.from(new Set([...(raw.tags ?? []), raw.pipeline_tag, raw.library_name].filter(Boolean))),
72
+ stars: raw.likes ?? 0,
73
+ installs: raw.downloads ?? 0,
74
+ repository: `https://huggingface.co/${raw.id}`,
75
+ createdAt: raw.createdAt ?? fetchedAt,
76
+ pricing: { kind: 'free' },
77
+ fetchedAt,
78
+ pushedAt: raw.lastModified ?? fetchedAt,
79
+ license: null, // HF licenses are buried — leave null for v1
80
+ topics: raw.tags ?? []
81
+ };
82
+ }
83
+ function categorizeHf(_endpoint, _raw) {
84
+ // Models/datasets/spaces all map to 'workflow' for v1 — they're not MCP/skills/prompts.
85
+ // Refine later if needed.
86
+ return 'workflow';
87
+ }
88
+ //# sourceMappingURL=huggingface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"huggingface.js","sourceRoot":"","sources":["../../src/hubs/huggingface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { HubItem } from './types.js';
2
+ export interface RawGithubRepo {
3
+ id: number;
4
+ full_name: string;
5
+ name: string;
6
+ owner: {
7
+ login: string;
8
+ };
9
+ description: string | null;
10
+ html_url: string;
11
+ stargazers_count: number;
12
+ forks_count: number;
13
+ pushed_at: string;
14
+ created_at: string;
15
+ archived: boolean;
16
+ license: {
17
+ spdx_id: string | null;
18
+ } | null;
19
+ topics: string[];
20
+ default_branch: string;
21
+ }
22
+ export declare function passes(repo: RawGithubRepo, now: Date): boolean;
23
+ export declare function score(repo: RawGithubRepo, now: Date): number;
24
+ export declare function categorize(repo: RawGithubRepo): HubItem['category'];
25
+ export declare function toHubItem(repo: RawGithubRepo, fetchedAt: string): HubItem;
26
+ //# sourceMappingURL=quality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/hubs/quality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAS9D;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,GAAG,MAAM,CAO5D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAWnE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAoBzE"}
@@ -0,0 +1,57 @@
1
+ export function passes(repo, now) {
2
+ if (repo.archived)
3
+ return false;
4
+ if (repo.stargazers_count < 10)
5
+ return false;
6
+ if (!repo.description || repo.description.trim().length < 10)
7
+ return false;
8
+ if (!repo.license || !repo.license.spdx_id)
9
+ return false;
10
+ const pushed = new Date(repo.pushed_at).getTime();
11
+ const ageDays = (now.getTime() - pushed) / (1000 * 60 * 60 * 24);
12
+ if (ageDays > 365)
13
+ return false; // not abandoned
14
+ return true;
15
+ }
16
+ export function score(repo, now) {
17
+ // Stars (log-scaled) + recency boost. Used for sorting; not a hard gate.
18
+ const stars = Math.log10(Math.max(1, repo.stargazers_count));
19
+ const pushed = new Date(repo.pushed_at).getTime();
20
+ const ageDays = Math.max(1, (now.getTime() - pushed) / (1000 * 60 * 60 * 24));
21
+ const recency = 1 / Math.log10(ageDays + 10);
22
+ return stars * 0.7 + recency * 0.3;
23
+ }
24
+ export function categorize(repo) {
25
+ const topics = repo.topics.map((t) => t.toLowerCase());
26
+ const desc = (repo.description ?? '').toLowerCase();
27
+ if (topics.some((t) => t === 'mcp' || t === 'model-context-protocol') ||
28
+ desc.includes('mcp server'))
29
+ return 'mcp';
30
+ if (topics.some((t) => t === 'claude-skill' || t === 'skill'))
31
+ return 'skill';
32
+ if (topics.some((t) => t === 'prompt' || t === 'prompts'))
33
+ return 'prompt';
34
+ return 'workflow';
35
+ }
36
+ export function toHubItem(repo, fetchedAt) {
37
+ return {
38
+ id: `gh:${repo.full_name}`,
39
+ source: 'github',
40
+ name: repo.name,
41
+ description: repo.description ?? '',
42
+ author: repo.owner.login,
43
+ version: repo.default_branch,
44
+ category: categorize(repo),
45
+ tags: Array.from(new Set([...repo.topics, repo.license?.spdx_id ?? ''].filter(Boolean))),
46
+ stars: repo.stargazers_count,
47
+ installs: repo.stargazers_count, // proxy for v1
48
+ repository: repo.html_url,
49
+ createdAt: repo.created_at,
50
+ pricing: { kind: 'free' },
51
+ fetchedAt,
52
+ pushedAt: repo.pushed_at,
53
+ license: repo.license?.spdx_id ?? null,
54
+ topics: repo.topics
55
+ };
56
+ }
57
+ //# sourceMappingURL=quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.js","sourceRoot":"","sources":["../../src/hubs/quality.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export type Pricing = {
2
+ kind: 'free';
3
+ } | {
4
+ kind: 'paid';
5
+ amountCents: number;
6
+ currency: string;
7
+ provider: 'stripe' | 'lemon';
8
+ };
9
+ export type InstallKind = 'git-clone' | 'mcp-config-patch' | 'package-install';
10
+ export interface HubItem {
11
+ id: string;
12
+ source: 'github' | 'hf';
13
+ name: string;
14
+ description: string;
15
+ author: string;
16
+ version: string;
17
+ category: 'mcp' | 'prompt' | 'workflow' | 'skill';
18
+ tags: string[];
19
+ stars: number;
20
+ installs: number;
21
+ repository: string;
22
+ npmPackage?: string;
23
+ createdAt: string;
24
+ pricing: Pricing;
25
+ fetchedAt: string;
26
+ pushedAt: string;
27
+ license: string | null;
28
+ topics: string[];
29
+ }
30
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/hubs/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAA;CAAE,CAAC;AAE1F,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AAE/E,MAAM,WAAW,OAAO;IAGtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;IAClD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAElB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/hubs/types.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAmBlD,eAAO,MAAM,KAAK,EAAE,MAufnB,CAAC;AAEF,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAmBlD,eAAO,MAAM,KAAK,EAAE,MAsdnB,CAAC;AAEF,eAAe,KAAK,CAAC"}