pilothub 0.0.1 → 0.0.2

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 (388) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +36 -129
  3. package/dist/browserAuth.d.ts +20 -0
  4. package/dist/browserAuth.js +156 -0
  5. package/dist/browserAuth.js.map +1 -0
  6. package/dist/browserAuth.test.d.ts +1 -0
  7. package/dist/browserAuth.test.js +83 -0
  8. package/dist/browserAuth.test.js.map +1 -0
  9. package/dist/cli/buildInfo.d.ts +3 -0
  10. package/dist/cli/buildInfo.js +103 -0
  11. package/dist/cli/buildInfo.js.map +1 -0
  12. package/dist/cli/commands/auth.d.ts +9 -0
  13. package/dist/cli/commands/auth.js +75 -0
  14. package/dist/cli/commands/auth.js.map +1 -0
  15. package/dist/cli/commands/delete.d.ts +11 -0
  16. package/dist/cli/commands/delete.js +67 -0
  17. package/dist/cli/commands/delete.js.map +1 -0
  18. package/dist/cli/commands/delete.test.d.ts +1 -0
  19. package/dist/cli/commands/delete.test.js +52 -0
  20. package/dist/cli/commands/delete.test.js.map +1 -0
  21. package/dist/cli/commands/publish.d.ts +9 -0
  22. package/dist/cli/commands/publish.js +87 -0
  23. package/dist/cli/commands/publish.js.map +1 -0
  24. package/dist/cli/commands/publish.test.d.ts +1 -0
  25. package/dist/cli/commands/publish.test.js +104 -0
  26. package/dist/cli/commands/publish.test.js.map +1 -0
  27. package/dist/cli/commands/skills.d.ts +23 -0
  28. package/dist/cli/commands/skills.js +298 -0
  29. package/dist/cli/commands/skills.js.map +1 -0
  30. package/dist/cli/commands/skills.test.d.ts +1 -0
  31. package/dist/cli/commands/skills.test.js +156 -0
  32. package/dist/cli/commands/skills.test.js.map +1 -0
  33. package/dist/cli/commands/star.d.ts +8 -0
  34. package/dist/cli/commands/star.js +38 -0
  35. package/dist/cli/commands/star.js.map +1 -0
  36. package/dist/cli/commands/sync.d.ts +3 -0
  37. package/dist/cli/commands/sync.js +160 -0
  38. package/dist/cli/commands/sync.js.map +1 -0
  39. package/dist/cli/commands/sync.test.d.ts +1 -0
  40. package/dist/cli/commands/sync.test.js +277 -0
  41. package/dist/cli/commands/sync.test.js.map +1 -0
  42. package/dist/cli/commands/syncHelpers.d.ts +76 -0
  43. package/dist/cli/commands/syncHelpers.js +349 -0
  44. package/dist/cli/commands/syncHelpers.js.map +1 -0
  45. package/dist/cli/commands/syncHelpers.test.d.ts +1 -0
  46. package/dist/cli/commands/syncHelpers.test.js +22 -0
  47. package/dist/cli/commands/syncHelpers.test.js.map +1 -0
  48. package/dist/cli/commands/syncTypes.d.ts +24 -0
  49. package/dist/cli/commands/syncTypes.js +2 -0
  50. package/dist/cli/commands/syncTypes.js.map +1 -0
  51. package/dist/cli/commands/unstar.d.ts +8 -0
  52. package/dist/cli/commands/unstar.js +38 -0
  53. package/dist/cli/commands/unstar.js.map +1 -0
  54. package/dist/cli/helpStyle.d.ts +13 -0
  55. package/dist/cli/helpStyle.js +38 -0
  56. package/dist/cli/helpStyle.js.map +1 -0
  57. package/dist/cli/pilotbotConfig.d.ts +6 -0
  58. package/dist/cli/pilotbotConfig.js +110 -0
  59. package/dist/cli/pilotbotConfig.js.map +1 -0
  60. package/dist/cli/pilotbotConfig.test.d.ts +1 -0
  61. package/dist/cli/pilotbotConfig.test.js +133 -0
  62. package/dist/cli/pilotbotConfig.test.js.map +1 -0
  63. package/dist/cli/registry.d.ts +7 -0
  64. package/dist/cli/registry.js +42 -0
  65. package/dist/cli/registry.js.map +1 -0
  66. package/dist/cli/registry.test.d.ts +1 -0
  67. package/dist/cli/registry.test.js +48 -0
  68. package/dist/cli/registry.test.js.map +1 -0
  69. package/dist/cli/scanSkills.d.ts +7 -0
  70. package/dist/cli/scanSkills.js +75 -0
  71. package/dist/cli/scanSkills.js.map +1 -0
  72. package/dist/cli/scanSkills.test.d.ts +1 -0
  73. package/dist/cli/scanSkills.test.js +60 -0
  74. package/dist/cli/scanSkills.test.js.map +1 -0
  75. package/dist/cli/slug.d.ts +2 -0
  76. package/dist/cli/slug.js +16 -0
  77. package/dist/cli/slug.js.map +1 -0
  78. package/dist/cli/types.d.ts +15 -0
  79. package/dist/cli/types.js +2 -0
  80. package/dist/cli/types.js.map +1 -0
  81. package/dist/cli/ui.d.ts +7 -0
  82. package/dist/cli/ui.js +72 -0
  83. package/dist/cli/ui.js.map +1 -0
  84. package/dist/cli.d.ts +2 -0
  85. package/dist/cli.js +268 -0
  86. package/dist/cli.js.map +1 -0
  87. package/dist/config.d.ts +4 -0
  88. package/dist/config.js +38 -0
  89. package/dist/config.js.map +1 -0
  90. package/dist/discovery.d.ts +5 -0
  91. package/dist/discovery.js +21 -0
  92. package/dist/discovery.js.map +1 -0
  93. package/dist/discovery.test.d.ts +1 -0
  94. package/dist/discovery.test.js +46 -0
  95. package/dist/discovery.test.js.map +1 -0
  96. package/dist/http.d.ts +32 -0
  97. package/dist/http.js +261 -0
  98. package/dist/http.js.map +1 -0
  99. package/dist/http.test.d.ts +1 -0
  100. package/dist/http.test.js +135 -0
  101. package/dist/http.test.js.map +1 -0
  102. package/dist/schema/ark.js.map +1 -0
  103. package/dist/schema/index.js.map +1 -0
  104. package/dist/schema/routes.js.map +1 -0
  105. package/{packages/schema/dist → dist/schema}/schemas.d.ts +0 -39
  106. package/{packages/schema/dist → dist/schema}/schemas.js +0 -22
  107. package/dist/schema/schemas.js.map +1 -0
  108. package/dist/schema/textFiles.js.map +1 -0
  109. package/dist/schema/textFiles.test.d.ts +1 -0
  110. package/dist/schema/textFiles.test.js +20 -0
  111. package/dist/schema/textFiles.test.js.map +1 -0
  112. package/dist/skills.d.ts +43 -0
  113. package/dist/skills.js +163 -0
  114. package/dist/skills.js.map +1 -0
  115. package/dist/skills.test.d.ts +1 -0
  116. package/dist/skills.test.js +144 -0
  117. package/dist/skills.test.js.map +1 -0
  118. package/dist/types.d.ts +7 -0
  119. package/dist/types.js +2 -0
  120. package/dist/types.js.map +1 -0
  121. package/package.json +27 -70
  122. package/.env.local.example +0 -19
  123. package/.github/workflows/ci.yml +0 -40
  124. package/.oxlintrc.json +0 -3
  125. package/AGENTS.md +0 -45
  126. package/CHANGELOG.md +0 -138
  127. package/DEPRECATIONS.md +0 -7
  128. package/biome.json +0 -41
  129. package/convex/_generated/api.d.ts +0 -153
  130. package/convex/_generated/api.js +0 -23
  131. package/convex/_generated/dataModel.d.ts +0 -60
  132. package/convex/_generated/server.d.ts +0 -143
  133. package/convex/_generated/server.js +0 -93
  134. package/convex/auth.config.ts +0 -8
  135. package/convex/auth.ts +0 -19
  136. package/convex/comments.ts +0 -88
  137. package/convex/crons.ts +0 -34
  138. package/convex/devSeed.ts +0 -459
  139. package/convex/devSeedExtra.ts +0 -541
  140. package/convex/downloads.ts +0 -78
  141. package/convex/githubBackups.ts +0 -170
  142. package/convex/githubBackupsNode.ts +0 -183
  143. package/convex/githubImport.ts +0 -317
  144. package/convex/githubSoulBackups.ts +0 -170
  145. package/convex/githubSoulBackupsNode.ts +0 -186
  146. package/convex/http.ts +0 -194
  147. package/convex/httpApi.handlers.test.ts +0 -488
  148. package/convex/httpApi.test.ts +0 -70
  149. package/convex/httpApi.ts +0 -305
  150. package/convex/httpApiV1.handlers.test.ts +0 -584
  151. package/convex/httpApiV1.ts +0 -1172
  152. package/convex/leaderboards.ts +0 -39
  153. package/convex/lib/access.ts +0 -36
  154. package/convex/lib/apiTokenAuth.ts +0 -36
  155. package/convex/lib/badges.ts +0 -50
  156. package/convex/lib/changelog.test.ts +0 -34
  157. package/convex/lib/changelog.ts +0 -278
  158. package/convex/lib/embeddings.ts +0 -38
  159. package/convex/lib/githubBackup.ts +0 -443
  160. package/convex/lib/githubImport.test.ts +0 -247
  161. package/convex/lib/githubImport.ts +0 -425
  162. package/convex/lib/githubSoulBackup.ts +0 -443
  163. package/convex/lib/leaderboards.ts +0 -103
  164. package/convex/lib/moderation.ts +0 -42
  165. package/convex/lib/public.ts +0 -89
  166. package/convex/lib/searchText.test.ts +0 -46
  167. package/convex/lib/searchText.ts +0 -27
  168. package/convex/lib/skillBackfill.test.ts +0 -34
  169. package/convex/lib/skillBackfill.ts +0 -67
  170. package/convex/lib/skillPublish.test.ts +0 -28
  171. package/convex/lib/skillPublish.ts +0 -284
  172. package/convex/lib/skillStats.ts +0 -80
  173. package/convex/lib/skills.test.ts +0 -197
  174. package/convex/lib/skills.ts +0 -273
  175. package/convex/lib/soulChangelog.ts +0 -273
  176. package/convex/lib/soulPublish.ts +0 -236
  177. package/convex/lib/tokens.test.ts +0 -33
  178. package/convex/lib/tokens.ts +0 -51
  179. package/convex/lib/webhooks.test.ts +0 -91
  180. package/convex/lib/webhooks.ts +0 -112
  181. package/convex/maintenance.test.ts +0 -270
  182. package/convex/maintenance.ts +0 -840
  183. package/convex/rateLimits.ts +0 -50
  184. package/convex/schema.ts +0 -472
  185. package/convex/search.test.ts +0 -12
  186. package/convex/search.ts +0 -254
  187. package/convex/seed.test.ts +0 -37
  188. package/convex/seed.ts +0 -254
  189. package/convex/seedSouls.ts +0 -111
  190. package/convex/skillStatEvents.ts +0 -568
  191. package/convex/skills.ts +0 -1606
  192. package/convex/soulComments.ts +0 -88
  193. package/convex/soulDownloads.ts +0 -14
  194. package/convex/soulStars.ts +0 -71
  195. package/convex/souls.ts +0 -570
  196. package/convex/stars.ts +0 -108
  197. package/convex/statsMaintenance.ts +0 -205
  198. package/convex/telemetry.ts +0 -434
  199. package/convex/tokens.ts +0 -88
  200. package/convex/tsconfig.json +0 -7
  201. package/convex/uploads.ts +0 -20
  202. package/convex/users.ts +0 -122
  203. package/convex/webhooks.ts +0 -50
  204. package/convex.json +0 -3
  205. package/docs/README.md +0 -32
  206. package/docs/api.md +0 -51
  207. package/docs/architecture.md +0 -61
  208. package/docs/auth.md +0 -54
  209. package/docs/cli.md +0 -117
  210. package/docs/deploy.md +0 -78
  211. package/docs/diffing.md +0 -84
  212. package/docs/github-import.md +0 -171
  213. package/docs/http-api.md +0 -187
  214. package/docs/manual-testing.md +0 -64
  215. package/docs/mintlify.md +0 -43
  216. package/docs/quickstart.md +0 -120
  217. package/docs/skill-format.md +0 -58
  218. package/docs/soul-format.md +0 -37
  219. package/docs/spec.md +0 -177
  220. package/docs/telemetry.md +0 -91
  221. package/docs/troubleshooting.md +0 -49
  222. package/docs/webhook.md +0 -51
  223. package/e2e/menu-smoke.pw.test.ts +0 -49
  224. package/e2e/pilothub.e2e.test.ts +0 -494
  225. package/e2e/search-exact.pw.test.ts +0 -97
  226. package/packages/pilothub/LICENSE +0 -22
  227. package/packages/pilothub/README.md +0 -57
  228. package/packages/pilothub/package.json +0 -41
  229. package/packages/pilothub/src/browserAuth.test.ts +0 -96
  230. package/packages/pilothub/src/browserAuth.ts +0 -174
  231. package/packages/pilothub/src/cli/buildInfo.ts +0 -94
  232. package/packages/pilothub/src/cli/commands/auth.ts +0 -97
  233. package/packages/pilothub/src/cli/commands/delete.test.ts +0 -73
  234. package/packages/pilothub/src/cli/commands/delete.ts +0 -83
  235. package/packages/pilothub/src/cli/commands/publish.test.ts +0 -122
  236. package/packages/pilothub/src/cli/commands/publish.ts +0 -108
  237. package/packages/pilothub/src/cli/commands/skills.test.ts +0 -191
  238. package/packages/pilothub/src/cli/commands/skills.ts +0 -380
  239. package/packages/pilothub/src/cli/commands/star.ts +0 -46
  240. package/packages/pilothub/src/cli/commands/sync.test.ts +0 -310
  241. package/packages/pilothub/src/cli/commands/sync.ts +0 -200
  242. package/packages/pilothub/src/cli/commands/syncHelpers.test.ts +0 -26
  243. package/packages/pilothub/src/cli/commands/syncHelpers.ts +0 -427
  244. package/packages/pilothub/src/cli/commands/syncTypes.ts +0 -27
  245. package/packages/pilothub/src/cli/commands/unstar.ts +0 -48
  246. package/packages/pilothub/src/cli/helpStyle.ts +0 -45
  247. package/packages/pilothub/src/cli/pilotbotConfig.test.ts +0 -159
  248. package/packages/pilothub/src/cli/pilotbotConfig.ts +0 -147
  249. package/packages/pilothub/src/cli/registry.test.ts +0 -63
  250. package/packages/pilothub/src/cli/registry.ts +0 -43
  251. package/packages/pilothub/src/cli/scanSkills.test.ts +0 -64
  252. package/packages/pilothub/src/cli/scanSkills.ts +0 -84
  253. package/packages/pilothub/src/cli/slug.ts +0 -16
  254. package/packages/pilothub/src/cli/types.ts +0 -12
  255. package/packages/pilothub/src/cli/ui.ts +0 -75
  256. package/packages/pilothub/src/cli.ts +0 -311
  257. package/packages/pilothub/src/config.ts +0 -36
  258. package/packages/pilothub/src/discovery.test.ts +0 -75
  259. package/packages/pilothub/src/discovery.ts +0 -19
  260. package/packages/pilothub/src/http.test.ts +0 -156
  261. package/packages/pilothub/src/http.ts +0 -301
  262. package/packages/pilothub/src/schema/ark.ts +0 -29
  263. package/packages/pilothub/src/schema/index.ts +0 -5
  264. package/packages/pilothub/src/schema/routes.ts +0 -22
  265. package/packages/pilothub/src/schema/schemas.ts +0 -260
  266. package/packages/pilothub/src/schema/textFiles.test.ts +0 -23
  267. package/packages/pilothub/src/schema/textFiles.ts +0 -66
  268. package/packages/pilothub/src/skills.test.ts +0 -191
  269. package/packages/pilothub/src/skills.ts +0 -172
  270. package/packages/pilothub/src/types.ts +0 -10
  271. package/packages/pilothub/tsconfig.json +0 -14
  272. package/packages/schema/README.md +0 -3
  273. package/packages/schema/dist/ark.js.map +0 -1
  274. package/packages/schema/dist/index.js.map +0 -1
  275. package/packages/schema/dist/routes.js.map +0 -1
  276. package/packages/schema/dist/schemas.js.map +0 -1
  277. package/packages/schema/dist/textFiles.js.map +0 -1
  278. package/packages/schema/package.json +0 -26
  279. package/packages/schema/src/ark.ts +0 -29
  280. package/packages/schema/src/index.ts +0 -5
  281. package/packages/schema/src/routes.ts +0 -22
  282. package/packages/schema/src/schemas.test.ts +0 -123
  283. package/packages/schema/src/schemas.ts +0 -287
  284. package/packages/schema/src/textFiles.test.ts +0 -23
  285. package/packages/schema/src/textFiles.ts +0 -66
  286. package/packages/schema/tsconfig.json +0 -15
  287. package/pilothub +0 -46
  288. package/playwright.config.ts +0 -33
  289. package/public/.well-known/pilothub.json +0 -6
  290. package/public/api/v1/openapi.json +0 -379
  291. package/public/favicon.ico +0 -0
  292. package/public/logo192.png +0 -0
  293. package/public/logo512.png +0 -0
  294. package/public/manifest.json +0 -25
  295. package/public/og.png +0 -0
  296. package/public/og.svg +0 -98
  297. package/public/pilot-logo.png +0 -0
  298. package/public/pilot-mark.png +0 -0
  299. package/public/robots.txt +0 -3
  300. package/public/tanstack-circle-logo.png +0 -0
  301. package/public/tanstack-word-logo-white.svg +0 -1
  302. package/scripts/check-peer-deps.ts +0 -56
  303. package/scripts/docs-list.ts +0 -148
  304. package/scripts/run-playwright-local.sh +0 -14
  305. package/server/og/fetchSkillOgMeta.ts +0 -27
  306. package/server/og/fetchSoulOgMeta.ts +0 -27
  307. package/server/og/ogAssets.ts +0 -80
  308. package/server/og/skillOgSvg.test.ts +0 -59
  309. package/server/og/skillOgSvg.ts +0 -258
  310. package/server/og/soulOgSvg.ts +0 -209
  311. package/server/routes/og/skill.png.ts +0 -103
  312. package/server/routes/og/soul.png.ts +0 -111
  313. package/src/__tests__/skill-detail-page.test.tsx +0 -86
  314. package/src/__tests__/skills-index.test.tsx +0 -145
  315. package/src/__tests__/upload.route.test.tsx +0 -228
  316. package/src/components/AppProviders.tsx +0 -19
  317. package/src/components/ClientOnly.tsx +0 -18
  318. package/src/components/Footer.tsx +0 -29
  319. package/src/components/Header.tsx +0 -295
  320. package/src/components/InstallSwitcher.tsx +0 -53
  321. package/src/components/SkillCard.tsx +0 -36
  322. package/src/components/SkillDetailPage.tsx +0 -817
  323. package/src/components/SkillDiffCard.tsx +0 -485
  324. package/src/components/SoulCard.tsx +0 -19
  325. package/src/components/SoulDetailPage.tsx +0 -263
  326. package/src/components/UserBootstrap.tsx +0 -18
  327. package/src/components/ui/dropdown-menu.tsx +0 -67
  328. package/src/components/ui/toggle-group.tsx +0 -35
  329. package/src/convex/client.ts +0 -3
  330. package/src/lib/badges.ts +0 -29
  331. package/src/lib/diffing.test.ts +0 -163
  332. package/src/lib/diffing.ts +0 -106
  333. package/src/lib/gravatar.test.ts +0 -9
  334. package/src/lib/gravatar.ts +0 -158
  335. package/src/lib/og.test.ts +0 -142
  336. package/src/lib/og.ts +0 -156
  337. package/src/lib/publicUser.ts +0 -39
  338. package/src/lib/roles.ts +0 -19
  339. package/src/lib/site.test.ts +0 -130
  340. package/src/lib/site.ts +0 -84
  341. package/src/lib/theme-transition.test.ts +0 -134
  342. package/src/lib/theme-transition.ts +0 -134
  343. package/src/lib/theme.test.tsx +0 -88
  344. package/src/lib/theme.ts +0 -43
  345. package/src/lib/uploadFiles.jsdom.test.ts +0 -33
  346. package/src/lib/uploadFiles.test.ts +0 -123
  347. package/src/lib/uploadFiles.ts +0 -245
  348. package/src/lib/uploadUtils.test.ts +0 -78
  349. package/src/lib/uploadUtils.ts +0 -93
  350. package/src/lib/useAuthStatus.ts +0 -12
  351. package/src/lib/utils.test.ts +0 -9
  352. package/src/lib/utils.ts +0 -6
  353. package/src/logo.svg +0 -12
  354. package/src/routeTree.gen.ts +0 -345
  355. package/src/router.tsx +0 -17
  356. package/src/routes/$owner/$slug.tsx +0 -55
  357. package/src/routes/__root.tsx +0 -136
  358. package/src/routes/admin.tsx +0 -11
  359. package/src/routes/cli/auth.tsx +0 -168
  360. package/src/routes/dashboard.tsx +0 -97
  361. package/src/routes/import.tsx +0 -415
  362. package/src/routes/index.tsx +0 -252
  363. package/src/routes/management.tsx +0 -529
  364. package/src/routes/settings.tsx +0 -203
  365. package/src/routes/skills/index.tsx +0 -422
  366. package/src/routes/souls/$slug.tsx +0 -55
  367. package/src/routes/souls/index.tsx +0 -243
  368. package/src/routes/stars.tsx +0 -68
  369. package/src/routes/u/$handle.tsx +0 -307
  370. package/src/routes/upload/utils.ts +0 -81
  371. package/src/routes/upload.tsx +0 -499
  372. package/src/styles.css +0 -2718
  373. package/tsconfig.json +0 -24
  374. package/tsconfig.oxlint.json +0 -16
  375. package/vercel.json +0 -8
  376. package/vite.config.ts +0 -48
  377. package/vitest.config.ts +0 -47
  378. package/vitest.e2e.config.ts +0 -11
  379. package/vitest.setup.ts +0 -1
  380. /package/{packages/pilothub/bin → bin}/pilothub.js +0 -0
  381. /package/{packages/schema/dist → dist/schema}/ark.d.ts +0 -0
  382. /package/{packages/schema/dist → dist/schema}/ark.js +0 -0
  383. /package/{packages/schema/dist → dist/schema}/index.d.ts +0 -0
  384. /package/{packages/schema/dist → dist/schema}/index.js +0 -0
  385. /package/{packages/schema/dist → dist/schema}/routes.d.ts +0 -0
  386. /package/{packages/schema/dist → dist/schema}/routes.js +0 -0
  387. /package/{packages/schema/dist → dist/schema}/textFiles.d.ts +0 -0
  388. /package/{packages/schema/dist → dist/schema}/textFiles.js +0 -0
@@ -1,494 +0,0 @@
1
- /* @vitest-environment node */
2
-
3
- import { spawnSync } from 'node:child_process'
4
- import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
5
- import { tmpdir } from 'node:os'
6
- import { join } from 'node:path'
7
- import { unzipSync } from 'fflate'
8
- import {
9
- ApiRoutes,
10
- ApiV1SearchResponseSchema,
11
- ApiV1WhoamiResponseSchema,
12
- parseArk,
13
- } from 'pilothub-schema'
14
- import { Agent, setGlobalDispatcher } from 'undici'
15
- import { describe, expect, it } from 'vitest'
16
- import { readGlobalConfig } from '../packages/pilothub/src/config'
17
-
18
- const REQUEST_TIMEOUT_MS = 15_000
19
-
20
- try {
21
- setGlobalDispatcher(
22
- new Agent({
23
- allowH2: true,
24
- connect: { timeout: REQUEST_TIMEOUT_MS },
25
- }),
26
- )
27
- } catch {
28
- // ignore dispatcher setup failures
29
- }
30
-
31
- function mustGetToken() {
32
- const fromEnv = process.env.PILOTHUB_E2E_TOKEN?.trim()
33
- if (fromEnv) return fromEnv
34
- return null
35
- }
36
-
37
- async function makeTempConfig(registry: string, token: string | null) {
38
- const dir = await mkdtemp(join(tmpdir(), 'pilothub-e2e-'))
39
- const path = join(dir, 'config.json')
40
- await writeFile(
41
- path,
42
- `${JSON.stringify({ registry, token: token || undefined }, null, 2)}\n`,
43
- 'utf8',
44
- )
45
- return { dir, path }
46
- }
47
-
48
- async function fetchWithTimeout(input: RequestInfo | URL, init?: RequestInit) {
49
- const controller = new AbortController()
50
- const timeout = setTimeout(() => controller.abort('Timeout'), REQUEST_TIMEOUT_MS)
51
- try {
52
- return await fetch(input, { ...init, signal: controller.signal })
53
- } finally {
54
- clearTimeout(timeout)
55
- }
56
- }
57
-
58
- describe('pilothub e2e', () => {
59
- it('prints CLI version via --cli-version', async () => {
60
- const result = spawnSync('bun', ['pilothub', '--cli-version'], {
61
- cwd: process.cwd(),
62
- encoding: 'utf8',
63
- })
64
- expect(result.status).toBe(0)
65
- expect(result.stdout.trim()).toMatch(/^\d+\.\d+\.\d+/)
66
- })
67
-
68
- it('search endpoint returns a results array (schema parse)', async () => {
69
- const registry = process.env.PILOTHUB_REGISTRY?.trim() || 'https://pilothub.com'
70
- const url = new URL(ApiRoutes.search, registry)
71
- url.searchParams.set('q', 'gif')
72
- url.searchParams.set('limit', '5')
73
-
74
- const response = await fetchWithTimeout(url.toString(), {
75
- headers: { Accept: 'application/json' },
76
- })
77
- expect(response.ok).toBe(true)
78
- const json = (await response.json()) as unknown
79
- const parsed = parseArk(ApiV1SearchResponseSchema, json, 'API response')
80
- expect(Array.isArray(parsed.results)).toBe(true)
81
- })
82
-
83
- it('cli search does not error on multi-result responses', async () => {
84
- const registry = process.env.PILOTHUB_REGISTRY?.trim() || 'https://pilothub.com'
85
- const site = process.env.PILOTHUB_SITE?.trim() || 'https://pilothub.com'
86
- const token = mustGetToken() ?? (await readGlobalConfig())?.token ?? null
87
-
88
- const cfg = await makeTempConfig(registry, token)
89
- try {
90
- const workdir = await mkdtemp(join(tmpdir(), 'pilothub-e2e-workdir-'))
91
- const result = spawnSync(
92
- 'bun',
93
- [
94
- 'pilothub',
95
- 'search',
96
- 'gif',
97
- '--limit',
98
- '5',
99
- '--site',
100
- site,
101
- '--registry',
102
- registry,
103
- '--workdir',
104
- workdir,
105
- ],
106
- {
107
- cwd: process.cwd(),
108
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
109
- encoding: 'utf8',
110
- },
111
- )
112
- await rm(workdir, { recursive: true, force: true })
113
-
114
- expect(result.status).toBe(0)
115
- expect(result.stderr).not.toMatch(/API response:/)
116
- } finally {
117
- await rm(cfg.dir, { recursive: true, force: true })
118
- }
119
- })
120
-
121
- it('assumes a logged-in user (whoami succeeds)', async () => {
122
- const registry = process.env.PILOTHUB_REGISTRY?.trim() || 'https://pilothub.com'
123
- const site = process.env.PILOTHUB_SITE?.trim() || 'https://pilothub.com'
124
- const token = mustGetToken() ?? (await readGlobalConfig())?.token ?? null
125
- if (!token) {
126
- throw new Error('Missing token. Set PILOTHUB_E2E_TOKEN or run: bun pilothub auth login')
127
- }
128
-
129
- const cfg = await makeTempConfig(registry, token)
130
- try {
131
- const whoamiUrl = new URL(ApiRoutes.whoami, registry)
132
- const whoamiRes = await fetchWithTimeout(whoamiUrl.toString(), {
133
- headers: { Accept: 'application/json', Authorization: `Bearer ${token}` },
134
- })
135
- expect(whoamiRes.ok).toBe(true)
136
- const whoami = parseArk(
137
- ApiV1WhoamiResponseSchema,
138
- (await whoamiRes.json()) as unknown,
139
- 'Whoami',
140
- )
141
- expect(whoami.user).toBeTruthy()
142
-
143
- const result = spawnSync(
144
- 'bun',
145
- ['pilothub', 'whoami', '--site', site, '--registry', registry],
146
- {
147
- cwd: process.cwd(),
148
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
149
- encoding: 'utf8',
150
- },
151
- )
152
- expect(result.status).toBe(0)
153
- expect(result.stderr).not.toMatch(/not logged in|unauthorized|error:/i)
154
- } finally {
155
- await rm(cfg.dir, { recursive: true, force: true })
156
- }
157
- })
158
-
159
- it('sync dry-run finds skills from an explicit root', async () => {
160
- const registry = process.env.PILOTHUB_REGISTRY?.trim() || 'https://pilothub.com'
161
- const site = process.env.PILOTHUB_SITE?.trim() || 'https://pilothub.com'
162
- const token = mustGetToken() ?? (await readGlobalConfig())?.token ?? null
163
- if (!token) {
164
- throw new Error('Missing token. Set PILOTHUB_E2E_TOKEN or run: bun pilothub auth login')
165
- }
166
-
167
- const cfg = await makeTempConfig(registry, token)
168
- const root = await mkdtemp(join(tmpdir(), 'pilothub-e2e-sync-'))
169
- try {
170
- const skillDir = join(root, 'cool-skill')
171
- await mkdir(skillDir, { recursive: true })
172
- await writeFile(join(skillDir, 'SKILL.md'), '# Skill\n', 'utf8')
173
-
174
- const result = spawnSync(
175
- 'bun',
176
- [
177
- 'pilothub',
178
- 'sync',
179
- '--dry-run',
180
- '--all',
181
- '--root',
182
- root,
183
- '--site',
184
- site,
185
- '--registry',
186
- registry,
187
- ],
188
- {
189
- cwd: process.cwd(),
190
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
191
- encoding: 'utf8',
192
- },
193
- )
194
- expect(result.status).toBe(0)
195
- expect(result.stderr).not.toMatch(/error:/i)
196
- expect(result.stdout).toMatch(/Dry run/i)
197
- } finally {
198
- await rm(root, { recursive: true, force: true })
199
- await rm(cfg.dir, { recursive: true, force: true })
200
- }
201
- })
202
-
203
- it('sync dry-run finds skills from pilotbot.json roots', async () => {
204
- const registry = process.env.PILOTHUB_REGISTRY?.trim() || 'https://pilothub.com'
205
- const site = process.env.PILOTHUB_SITE?.trim() || 'https://pilothub.com'
206
- const token = mustGetToken() ?? (await readGlobalConfig())?.token ?? null
207
- if (!token) {
208
- throw new Error('Missing token. Set PILOTHUB_E2E_TOKEN or run: bun pilothub auth login')
209
- }
210
-
211
- const cfg = await makeTempConfig(registry, token)
212
- const root = await mkdtemp(join(tmpdir(), 'pilothub-e2e-pilotbot-'))
213
- const stateDir = join(root, 'state')
214
- const configPath = join(root, 'pilotbot.json')
215
- const workspace = join(root, 'pilot-work')
216
- const skillsRoot = join(workspace, 'skills')
217
- const skillDir = join(skillsRoot, 'auto-skill')
218
-
219
- try {
220
- await mkdir(skillDir, { recursive: true })
221
- await writeFile(join(skillDir, 'SKILL.md'), '# Skill\n', 'utf8')
222
-
223
- const config = `{
224
- // JSON5-style comments + trailing commas
225
- routing: {
226
- agents: {
227
- work: { name: 'Work', workspace: '${workspace}', },
228
- },
229
- },
230
- }`
231
- await writeFile(configPath, config, 'utf8')
232
-
233
- const result = spawnSync(
234
- 'bun',
235
- ['pilothub', 'sync', '--dry-run', '--all', '--site', site, '--registry', registry],
236
- {
237
- cwd: process.cwd(),
238
- env: {
239
- ...process.env,
240
- PILOTHUB_CONFIG_PATH: cfg.path,
241
- PILOTHUB_DISABLE_TELEMETRY: '1',
242
- PILOTBOT_CONFIG_PATH: configPath,
243
- PILOTBOT_STATE_DIR: stateDir,
244
- },
245
- encoding: 'utf8',
246
- },
247
- )
248
- expect(result.status).toBe(0)
249
- expect(result.stderr).not.toMatch(/error:/i)
250
- expect(result.stdout).toMatch(/Dry run/i)
251
- expect(result.stdout).toMatch(/auto-skill/i)
252
- } finally {
253
- await rm(root, { recursive: true, force: true })
254
- await rm(cfg.dir, { recursive: true, force: true })
255
- }
256
- })
257
-
258
- it('publishes, deletes, and undeletes a skill (logged-in)', async () => {
259
- const registry = process.env.PILOTHUB_REGISTRY?.trim() || 'https://pilothub.com'
260
- const site = process.env.PILOTHUB_SITE?.trim() || 'https://pilothub.com'
261
- const token = mustGetToken() ?? (await readGlobalConfig())?.token ?? null
262
- if (!token) {
263
- throw new Error('Missing token. Set PILOTHUB_E2E_TOKEN or run: bun pilothub auth login')
264
- }
265
-
266
- const cfg = await makeTempConfig(registry, token)
267
- const workdir = await mkdtemp(join(tmpdir(), 'pilothub-e2e-publish-'))
268
- const installWorkdir = await mkdtemp(join(tmpdir(), 'pilothub-e2e-install-'))
269
- const slug = `e2e-${Date.now()}`
270
- const skillDir = join(workdir, slug)
271
-
272
- try {
273
- await mkdir(skillDir, { recursive: true })
274
- await writeFile(join(skillDir, 'SKILL.md'), `# ${slug}\n\nHello.\n`, 'utf8')
275
-
276
- const publish1 = spawnSync(
277
- 'bun',
278
- [
279
- 'pilothub',
280
- 'publish',
281
- skillDir,
282
- '--slug',
283
- slug,
284
- '--name',
285
- `E2E ${slug}`,
286
- '--version',
287
- '1.0.0',
288
- '--tags',
289
- 'latest',
290
- '--site',
291
- site,
292
- '--registry',
293
- registry,
294
- '--workdir',
295
- workdir,
296
- ],
297
- {
298
- cwd: process.cwd(),
299
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
300
- encoding: 'utf8',
301
- },
302
- )
303
- expect(publish1.status).toBe(0)
304
- expect(publish1.stderr).not.toMatch(/changelog required/i)
305
-
306
- const publish2 = spawnSync(
307
- 'bun',
308
- [
309
- 'pilothub',
310
- 'publish',
311
- skillDir,
312
- '--slug',
313
- slug,
314
- '--name',
315
- `E2E ${slug}`,
316
- '--version',
317
- '1.0.1',
318
- '--tags',
319
- 'latest',
320
- '--site',
321
- site,
322
- '--registry',
323
- registry,
324
- '--workdir',
325
- workdir,
326
- ],
327
- {
328
- cwd: process.cwd(),
329
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
330
- encoding: 'utf8',
331
- },
332
- )
333
- expect(publish2.status).toBe(0)
334
- expect(publish2.stderr).not.toMatch(/changelog required/i)
335
-
336
- const downloadUrl = new URL(ApiRoutes.download, registry)
337
- downloadUrl.searchParams.set('slug', slug)
338
- downloadUrl.searchParams.set('version', '1.0.1')
339
- const zipRes = await fetchWithTimeout(downloadUrl.toString())
340
- expect(zipRes.ok).toBe(true)
341
- const zipBytes = new Uint8Array(await zipRes.arrayBuffer())
342
- const unzipped = unzipSync(zipBytes)
343
- expect(Object.keys(unzipped)).toContain('SKILL.md')
344
-
345
- const install = spawnSync(
346
- 'bun',
347
- [
348
- 'pilothub',
349
- 'install',
350
- slug,
351
- '--version',
352
- '1.0.0',
353
- '--force',
354
- '--site',
355
- site,
356
- '--registry',
357
- registry,
358
- '--workdir',
359
- installWorkdir,
360
- ],
361
- {
362
- cwd: process.cwd(),
363
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
364
- encoding: 'utf8',
365
- },
366
- )
367
- expect(install.status).toBe(0)
368
-
369
- const list = spawnSync(
370
- 'bun',
371
- ['pilothub', 'list', '--site', site, '--registry', registry, '--workdir', installWorkdir],
372
- {
373
- cwd: process.cwd(),
374
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
375
- encoding: 'utf8',
376
- },
377
- )
378
- expect(list.status).toBe(0)
379
- expect(list.stdout).toMatch(new RegExp(`${slug}\\s+1\\.0\\.0`))
380
-
381
- const update = spawnSync(
382
- 'bun',
383
- [
384
- 'pilothub',
385
- 'update',
386
- slug,
387
- '--force',
388
- '--site',
389
- site,
390
- '--registry',
391
- registry,
392
- '--workdir',
393
- installWorkdir,
394
- ],
395
- {
396
- cwd: process.cwd(),
397
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
398
- encoding: 'utf8',
399
- },
400
- )
401
- expect(update.status).toBe(0)
402
-
403
- const metaUrl = new URL(`${ApiRoutes.skills}/${slug}`, registry)
404
- const metaRes = await fetchWithTimeout(metaUrl.toString(), {
405
- headers: { Accept: 'application/json' },
406
- })
407
- expect(metaRes.status).toBe(200)
408
-
409
- const del = spawnSync(
410
- 'bun',
411
- [
412
- 'pilothub',
413
- 'delete',
414
- slug,
415
- '--yes',
416
- '--site',
417
- site,
418
- '--registry',
419
- registry,
420
- '--workdir',
421
- workdir,
422
- ],
423
- {
424
- cwd: process.cwd(),
425
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
426
- encoding: 'utf8',
427
- },
428
- )
429
- expect(del.status).toBe(0)
430
-
431
- const metaAfterDelete = await fetchWithTimeout(metaUrl.toString(), {
432
- headers: { Accept: 'application/json' },
433
- })
434
- expect(metaAfterDelete.status).toBe(404)
435
-
436
- const downloadAfterDelete = await fetchWithTimeout(downloadUrl.toString())
437
- expect(downloadAfterDelete.status).toBe(404)
438
-
439
- const undelete = spawnSync(
440
- 'bun',
441
- [
442
- 'pilothub',
443
- 'undelete',
444
- slug,
445
- '--yes',
446
- '--site',
447
- site,
448
- '--registry',
449
- registry,
450
- '--workdir',
451
- workdir,
452
- ],
453
- {
454
- cwd: process.cwd(),
455
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
456
- encoding: 'utf8',
457
- },
458
- )
459
- expect(undelete.status).toBe(0)
460
-
461
- const metaAfterUndelete = await fetchWithTimeout(metaUrl.toString(), {
462
- headers: { Accept: 'application/json' },
463
- })
464
- expect(metaAfterUndelete.status).toBe(200)
465
- } finally {
466
- const cleanup = spawnSync(
467
- 'bun',
468
- [
469
- 'pilothub',
470
- 'delete',
471
- slug,
472
- '--yes',
473
- '--site',
474
- site,
475
- '--registry',
476
- registry,
477
- '--workdir',
478
- workdir,
479
- ],
480
- {
481
- cwd: process.cwd(),
482
- env: { ...process.env, PILOTHUB_CONFIG_PATH: cfg.path, PILOTHUB_DISABLE_TELEMETRY: '1' },
483
- encoding: 'utf8',
484
- },
485
- )
486
- if (cleanup.status !== 0) {
487
- // best-effort cleanup
488
- }
489
- await rm(workdir, { recursive: true, force: true })
490
- await rm(installWorkdir, { recursive: true, force: true })
491
- await rm(cfg.dir, { recursive: true, force: true })
492
- }
493
- }, 180_000)
494
- })
@@ -1,97 +0,0 @@
1
- import { expect, test } from '@playwright/test'
2
-
3
- test('skills search paginates exact results', async ({ page }) => {
4
- await page.addInitScript(() => {
5
- const makeSearchResults = (count: number) =>
6
- Array.from({ length: count }, (_, index) => ({
7
- score: 0.9,
8
- skill: {
9
- _id: `skill_${index}`,
10
- slug: `skill-${index}`,
11
- displayName: `Skill ${index}`,
12
- summary: `Summary ${index}`,
13
- tags: {},
14
- stats: {
15
- downloads: 0,
16
- installsCurrent: 0,
17
- installsAllTime: 0,
18
- stars: 0,
19
- versions: 1,
20
- comments: 0,
21
- },
22
- createdAt: 0,
23
- updatedAt: 0,
24
- },
25
- version: null,
26
- }))
27
-
28
- class MockWebSocket {
29
- url: string
30
- readyState = 0
31
- onopen?: () => void
32
- onmessage?: (event: { data: string }) => void
33
- onclose?: (event: { code: number; reason: string }) => void
34
- onerror?: () => void
35
-
36
- constructor(url: string) {
37
- this.url = url
38
- window.setTimeout(() => {
39
- this.readyState = 1
40
- this.onopen?.()
41
- }, 0)
42
- }
43
-
44
- send(data: string) {
45
- try {
46
- const message = JSON.parse(data) as {
47
- type?: string
48
- requestId?: number
49
- udfPath?: string
50
- args?: Array<Record<string, unknown>>
51
- }
52
- if (message.type === 'Action' && message.udfPath?.includes('searchSkills')) {
53
- const [args] = message.args ?? []
54
- const limit = typeof args?.limit === 'number' ? args.limit : 10
55
- const limits = (window as typeof window & { __searchLimits: number[] }).__searchLimits
56
- limits.push(limit)
57
- const response = {
58
- type: 'ActionResponse',
59
- requestId: message.requestId,
60
- success: true,
61
- result: makeSearchResults(limit),
62
- logLines: [],
63
- }
64
- window.setTimeout(() => {
65
- this.onmessage?.({ data: JSON.stringify(response) })
66
- }, 0)
67
- }
68
- } catch {
69
- this.onerror?.()
70
- }
71
- }
72
-
73
- close(code = 1000, reason = 'closed') {
74
- this.readyState = 3
75
- this.onclose?.({ code, reason })
76
- }
77
- }
78
-
79
- ;(window as typeof window & { __searchLimits: number[] }).__searchLimits = []
80
- window.WebSocket = MockWebSocket as unknown as typeof WebSocket
81
- })
82
-
83
- await page.goto('/skills', { waitUntil: 'domcontentloaded' })
84
- await expect(page.getByRole('heading', { name: 'Skills' })).toBeVisible()
85
-
86
- const input = page.getByPlaceholder('Filter by name, slug, or summary…')
87
- await input.fill('remind')
88
- await expect(page.getByText('Skill 0')).toBeVisible()
89
- await expect(page.getByText('Scroll to load more')).toBeVisible()
90
-
91
- await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight))
92
- await expect(page.getByText('Skill 75')).toBeVisible()
93
- const limits = await page.evaluate(
94
- () => (window as typeof window & { __searchLimits: number[] }).__searchLimits,
95
- )
96
- expect(limits).toEqual([50, 100])
97
- })
@@ -1,22 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Peter Steinberger
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
22
-
@@ -1,57 +0,0 @@
1
- # `pilothub`
2
-
3
- PilotHub CLI — install, update, search, and publish agent skills as folders.
4
-
5
- ## Install
6
-
7
- ```bash
8
- # From this repo (shortcut script at repo root)
9
- bun pilothub --help
10
-
11
- # Once published to npm
12
- # npm i -g pilothub
13
- ```
14
-
15
- ## Auth (publish)
16
-
17
- ```bash
18
- pilothub login
19
- # or
20
- pilothub auth login
21
-
22
- # Headless / token paste
23
- # or (token paste / headless)
24
- pilothub login --token clh_...
25
- ```
26
-
27
- Notes:
28
-
29
- - Browser login opens `https://pilothub.com/cli/auth` and completes via a loopback callback.
30
- - Token stored in `~/Library/Application Support/pilothub/config.json` on macOS (override via `PILOTHUB_CONFIG_PATH`).
31
-
32
- ## Examples
33
-
34
- ```bash
35
- pilothub search "postgres backups"
36
- pilothub install my-skill-pack
37
- pilothub update --all
38
- pilothub update --all --no-input --force
39
- pilothub publish ./my-skill-pack --slug my-skill-pack --name "My Skill Pack" --version 1.2.0 --changelog "Fixes + docs"
40
- ```
41
-
42
- ## Sync (upload local skills)
43
-
44
- ```bash
45
- # Start anywhere; scans workdir first, then legacy Pilotbot/Pilot locations.
46
- pilothub sync
47
-
48
- # Explicit roots + non-interactive dry-run
49
- pilothub sync --root ../pilotbot/skills --all --dry-run
50
- ```
51
-
52
- ## Defaults
53
-
54
- - Site: `https://pilothub.com` (override via `--site` or `PILOTHUB_SITE`)
55
- - Registry: discovered from `/.well-known/pilothub.json` on the site (override via `--registry` or `PILOTHUB_REGISTRY`)
56
- - Workdir: current directory (falls back to Pilotbot workspace if configured; override via `--workdir` or `PILOTHUB_WORKDIR`)
57
- - Install dir: `./skills` under workdir (override via `--dir`)