@hasna/skills 0.1.59 → 0.1.61

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 (1059) hide show
  1. package/README.md +189 -60
  2. package/agent-skills/README.md +41 -0
  3. package/agent-skills/fleet-package-rollout/SKILL.md +169 -0
  4. package/agent-skills/inbox/SKILL.md +25 -0
  5. package/agent-skills/inbox/scripts/inbox +109 -0
  6. package/agent-skills/inbox/tests/test_registered_sender_id.sh +92 -0
  7. package/agent-skills/inbox-monitor/SKILL.md +41 -0
  8. package/agent-skills/inbox-monitor/scripts/inbox_monitor.sh +91 -0
  9. package/agent-skills/inbox-monitor/scripts/test_inbox_monitor.sh +71 -0
  10. package/agent-skills/merge-pr/SKILL.md +85 -0
  11. package/agent-skills/merge-pr/references/merge-safety.md +82 -0
  12. package/agent-skills/merge-pr/scripts/merge_pr_guard.py +694 -0
  13. package/agent-skills/merge-pr/scripts/test_merge_pr_guard.py +647 -0
  14. package/agent-skills/merge-pr/tests/fixtures/multi-commit-synthesized.json +28 -0
  15. package/agent-skills/merge-pr/tests/fixtures/trailer-free-provider.json +28 -0
  16. package/agent-skills/skill-goal-execute/SKILL.md +115 -0
  17. package/agent-skills/skill-login/SKILL.md +109 -0
  18. package/agent-skills/skill-project-create/SKILL.md +91 -0
  19. package/agent-skills/skill-publish/SKILL.md +207 -0
  20. package/bin/index.js +2457 -3344
  21. package/bin/mcp.js +1127 -2641
  22. package/bin/migrate.js +955 -33
  23. package/bin/server.js +2367 -1989
  24. package/bin/worker.js +2089 -151
  25. package/dist/cli/cli.test-utils.d.ts +13 -2
  26. package/dist/cli/commands/publish.d.ts +30 -0
  27. package/dist/cli/commands/registry.d.ts +8 -0
  28. package/dist/index.d.ts +8 -6
  29. package/dist/index.js +1734 -2720
  30. package/dist/lib/agent-sync.d.ts +123 -0
  31. package/dist/lib/api-url.d.ts +34 -0
  32. package/dist/lib/auth-store.d.ts +21 -5
  33. package/dist/lib/blog-article.d.ts +37 -0
  34. package/dist/lib/config.d.ts +56 -2
  35. package/dist/lib/content-scan.d.ts +62 -9
  36. package/dist/lib/discovery.d.ts +10 -10
  37. package/dist/lib/doc-derived-counts.d.ts +56 -0
  38. package/dist/lib/feedback.d.ts +7 -0
  39. package/dist/lib/file-bytes.d.ts +43 -0
  40. package/dist/lib/hosted-skill-set.d.ts +69 -0
  41. package/dist/lib/infra-identifiers.d.ts +144 -0
  42. package/dist/lib/installer.d.ts +20 -6
  43. package/dist/lib/native-storage.d.ts +14 -11
  44. package/dist/lib/packlist.d.ts +13 -0
  45. package/dist/lib/portable-skills-files.d.ts +25 -0
  46. package/dist/lib/portable-skills-types.d.ts +105 -0
  47. package/dist/lib/portable-skills.d.ts +52 -103
  48. package/dist/lib/pull.d.ts +41 -0
  49. package/dist/lib/registry-merge.d.ts +57 -0
  50. package/dist/lib/registry-types.d.ts +1 -14
  51. package/dist/lib/registry.d.ts +6 -3
  52. package/dist/lib/remote-client.d.ts +15 -1
  53. package/dist/lib/remote-registry.d.ts +1 -1
  54. package/dist/lib/remote-run-contract.d.ts +0 -7
  55. package/dist/lib/retired-settings.d.ts +100 -0
  56. package/dist/lib/run-state.d.ts +14 -0
  57. package/dist/lib/skill-aliases.d.ts +0 -12
  58. package/dist/lib/skill-bundle.d.ts +37 -0
  59. package/dist/lib/vendor-host-code-scan.d.ts +66 -0
  60. package/dist/lib/vendor-host-folding.d.ts +40 -0
  61. package/dist/lib/vendor-host-guard.d.ts +47 -0
  62. package/dist/lib/vendor-host-package.d.ts +42 -0
  63. package/dist/lib/vendor-host-policy.d.ts +96 -0
  64. package/dist/lib/vendor-host-url.d.ts +81 -0
  65. package/dist/mcp/mcp-test-client.d.ts +18 -0
  66. package/dist/storage.d.ts +1 -1
  67. package/dist/storage.js +104 -51
  68. package/docs/skill-standard.md +1 -1
  69. package/migrations/postgres/0002_org_scoped_skill_registry.sql +72 -0
  70. package/migrations/sqlite/0001_open_skills_self_hosted.sql +150 -0
  71. package/migrations/sqlite/0002_org_scoped_skill_registry.sql +47 -0
  72. package/package.json +4 -4
  73. package/skills/_common/http-client.ts +17 -2
  74. package/skills/_common/install.sh +2 -2
  75. package/skills/_common/installer.ts +4 -5
  76. package/skills/_common/skill-install.ts +3 -3
  77. package/skills/ad-creative-pack/SKILL.md +28 -18
  78. package/skills/ad-creative-pack/package.json +1 -2
  79. package/skills/analyze-data/SKILL.md +1 -1
  80. package/skills/analyze-data/src/formatters.ts +2 -2
  81. package/skills/api-docs-portal/SKILL.md +62 -24
  82. package/skills/api-docs-portal/package.json +28 -4
  83. package/skills/api-docs-portal/src/index.ts +919 -0
  84. package/skills/audio-extract/SKILL.md +1 -1
  85. package/skills/blog-article/SKILL.md +32 -22
  86. package/skills/blog-article/package.json +1 -2
  87. package/skills/brand-assets/SKILL.md +94 -33
  88. package/skills/brand-assets/package.json +28 -4
  89. package/skills/brand-assets/src/cli.ts +155 -0
  90. package/skills/brand-assets/src/constants.ts +8 -0
  91. package/skills/brand-assets/src/extract.ts +236 -0
  92. package/skills/brand-assets/src/index.ts +668 -0
  93. package/skills/brand-assets/src/types.ts +59 -0
  94. package/skills/brand-kit/SKILL.md +27 -18
  95. package/skills/brand-kit/package.json +1 -2
  96. package/skills/compress-video/SKILL.md +1 -1
  97. package/skills/contract-review-report/SKILL.md +27 -18
  98. package/skills/contract-review-report/package.json +1 -2
  99. package/skills/customer-feedback-report/SKILL.md +27 -19
  100. package/skills/customer-feedback-report/package.json +1 -2
  101. package/skills/email-sequence/SKILL.md +26 -17
  102. package/skills/email-sequence/package.json +1 -2
  103. package/skills/generate-sitemap/src/index.ts +1 -1
  104. package/skills/invoice-reconciliation/SKILL.md +75 -19
  105. package/skills/invoice-reconciliation/package.json +29 -4
  106. package/skills/invoice-reconciliation/src/index.ts +743 -0
  107. package/skills/{convert → invoice-reconciliation}/tsconfig.json +3 -1
  108. package/skills/landing-page-pack/SKILL.md +27 -19
  109. package/skills/landing-page-pack/package.json +1 -2
  110. package/skills/logo-design/SKILL.md +69 -26
  111. package/skills/logo-design/package.json +28 -4
  112. package/skills/logo-design/src/cli.ts +132 -0
  113. package/skills/logo-design/src/constants.ts +5 -0
  114. package/skills/logo-design/src/docs.ts +102 -0
  115. package/skills/logo-design/src/geometry.ts +324 -0
  116. package/skills/logo-design/src/index.ts +212 -0
  117. package/skills/logo-design/src/palette.ts +258 -0
  118. package/skills/logo-design/src/types.ts +50 -0
  119. package/skills/logo-design/tsconfig.json +11 -2
  120. package/skills/market-research-report/SKILL.md +28 -18
  121. package/skills/market-research-report/package.json +2 -3
  122. package/skills/meeting-pack/SKILL.md +26 -17
  123. package/skills/meeting-pack/package.json +1 -2
  124. package/skills/merge-pdfs/src/index.ts +1 -1
  125. package/skills/migration-plan-pack/SKILL.md +30 -19
  126. package/skills/migration-plan-pack/package.json +1 -2
  127. package/skills/one-page-website/SKILL.md +105 -23
  128. package/skills/one-page-website/package.json +27 -4
  129. package/skills/one-page-website/src/design.ts +336 -0
  130. package/skills/one-page-website/src/docs.ts +159 -0
  131. package/skills/one-page-website/src/index.ts +357 -0
  132. package/skills/one-page-website/src/page.ts +340 -0
  133. package/skills/one-page-website/src/styles.ts +508 -0
  134. package/skills/one-page-website/src/types.ts +78 -0
  135. package/skills/one-page-website/tsconfig.json +11 -2
  136. package/skills/pdf-generate/SKILL.md +1 -1
  137. package/skills/pdf-to-dataset/SKILL.md +64 -21
  138. package/skills/pdf-to-dataset/package.json +30 -4
  139. package/skills/pdf-to-dataset/src/index.ts +790 -0
  140. package/skills/{emoji → pdf-to-dataset}/tsconfig.json +3 -4
  141. package/skills/pdf-to-markdown/SKILL.md +55 -23
  142. package/skills/pdf-to-markdown/package.json +28 -4
  143. package/skills/pdf-to-markdown/src/index.ts +694 -0
  144. package/skills/pdf-to-markdown/tsconfig.json +11 -4
  145. package/skills/performance-audit-report/SKILL.md +24 -17
  146. package/skills/performance-audit-report/package.json +1 -2
  147. package/skills/pitch-deck/SKILL.md +27 -19
  148. package/skills/pitch-deck/package.json +1 -2
  149. package/skills/product-mockup/SKILL.md +85 -23
  150. package/skills/product-mockup/package.json +25 -4
  151. package/skills/product-mockup/src/cli.ts +150 -0
  152. package/skills/product-mockup/src/design.ts +151 -0
  153. package/skills/product-mockup/src/docs.ts +134 -0
  154. package/skills/product-mockup/src/index.ts +182 -0
  155. package/skills/product-mockup/src/render.ts +407 -0
  156. package/skills/product-mockup/src/types.ts +66 -0
  157. package/skills/product-mockup/tsconfig.json +11 -2
  158. package/skills/proposal-pack/SKILL.md +27 -19
  159. package/skills/proposal-pack/package.json +2 -3
  160. package/skills/repo-onboarding-report/SKILL.md +26 -16
  161. package/skills/repo-onboarding-report/package.json +1 -2
  162. package/skills/security-audit/src/index.ts +1 -1
  163. package/skills/security-audit-report/SKILL.md +28 -16
  164. package/skills/security-audit-report/package.json +2 -3
  165. package/skills/seo-content-pack/SKILL.md +27 -17
  166. package/skills/seo-content-pack/package.json +1 -2
  167. package/skills/slide-deck-generator/SKILL.md +70 -21
  168. package/skills/slide-deck-generator/package.json +31 -4
  169. package/skills/slide-deck-generator/src/cli.ts +133 -0
  170. package/skills/slide-deck-generator/src/index.ts +148 -0
  171. package/skills/slide-deck-generator/src/model.ts +307 -0
  172. package/skills/slide-deck-generator/src/pptx.ts +143 -0
  173. package/skills/slide-deck-generator/src/render.ts +248 -0
  174. package/skills/slide-deck-generator/src/types.ts +114 -0
  175. package/skills/slide-deck-generator/src/utils.ts +53 -0
  176. package/skills/slide-deck-generator/tsconfig.json +17 -0
  177. package/skills/social-content-calendar/SKILL.md +27 -18
  178. package/skills/social-content-calendar/package.json +1 -2
  179. package/skills/split-pdf/src/index.ts +1 -1
  180. package/skills/test-suite-generator/SKILL.md +26 -16
  181. package/skills/test-suite-generator/package.json +2 -3
  182. package/skills/todos-plan/SKILL.md +339 -170
  183. package/skills/video-highlight-pack/SKILL.md +27 -17
  184. package/skills/video-highlight-pack/package.json +1 -2
  185. package/dist/cli/onboarding.d.ts +0 -13
  186. package/dist/lib/hosted-availability.d.ts +0 -13
  187. package/dist/lib/pricing.d.ts +0 -89
  188. package/skills/academic-journal-matcher/CLAUDE.md +0 -19
  189. package/skills/academic-journal-matcher/package.json +0 -27
  190. package/skills/academic-journal-matcher/src/index.ts +0 -86
  191. package/skills/academic-journal-matcher/tsconfig.json +0 -10
  192. package/skills/action-item-router/CLAUDE.md +0 -19
  193. package/skills/action-item-router/package.json +0 -27
  194. package/skills/action-item-router/src/index.ts +0 -304
  195. package/skills/action-item-router/tsconfig.json +0 -10
  196. package/skills/ad-creative-generator/CLAUDE.md +0 -19
  197. package/skills/ad-creative-generator/package.json +0 -27
  198. package/skills/ad-creative-generator/src/index.ts +0 -419
  199. package/skills/ad-creative-generator/tsconfig.json +0 -10
  200. package/skills/advanced-math/CLAUDE.md +0 -19
  201. package/skills/advanced-math/package.json +0 -29
  202. package/skills/advanced-math/src/calculators.ts +0 -118
  203. package/skills/advanced-math/src/cli.ts +0 -130
  204. package/skills/advanced-math/src/conversion.ts +0 -90
  205. package/skills/advanced-math/src/finance.ts +0 -75
  206. package/skills/advanced-math/src/formatting.ts +0 -95
  207. package/skills/advanced-math/src/index.ts +0 -133
  208. package/skills/advanced-math/src/runtime.ts +0 -49
  209. package/skills/advanced-math/src/symbolic.ts +0 -110
  210. package/skills/advanced-math/src/types.ts +0 -36
  211. package/skills/advanced-math/tsconfig.json +0 -10
  212. package/skills/anomaly-investigator/CLAUDE.md +0 -19
  213. package/skills/anomaly-investigator/package.json +0 -27
  214. package/skills/anomaly-investigator/src/index.ts +0 -311
  215. package/skills/anomaly-investigator/tsconfig.json +0 -10
  216. package/skills/apidocs/.env.example +0 -8
  217. package/skills/apidocs/CLAUDE.md +0 -278
  218. package/skills/apidocs/LICENSE +0 -192
  219. package/skills/apidocs/README.md +0 -196
  220. package/skills/apidocs/api-docs-list.json +0 -186
  221. package/skills/apidocs/package.json +0 -53
  222. package/skills/apidocs/scripts/crawl-all.ts +0 -157
  223. package/skills/apidocs/scripts/publish.ts +0 -210
  224. package/skills/apidocs/src/commands/add.ts +0 -279
  225. package/skills/apidocs/src/commands/endpoints.ts +0 -157
  226. package/skills/apidocs/src/commands/list.ts +0 -51
  227. package/skills/apidocs/src/commands/query.ts +0 -63
  228. package/skills/apidocs/src/commands/remove.ts +0 -39
  229. package/skills/apidocs/src/commands/sync.ts +0 -227
  230. package/skills/apidocs/src/index.ts +0 -3
  231. package/skills/apidocs/src/lib/crawler.ts +0 -427
  232. package/skills/apidocs/src/lib/discovery.ts +0 -244
  233. package/skills/apidocs/src/lib/embeddings.ts +0 -136
  234. package/skills/apidocs/src/lib/endpoint-extractor.ts +0 -359
  235. package/skills/apidocs/src/lib/html-to-md.ts +0 -163
  236. package/skills/apidocs/src/lib/parser.ts +0 -288
  237. package/skills/apidocs/src/lib/search.ts +0 -189
  238. package/skills/apidocs/src/lib/storage.ts +0 -242
  239. package/skills/apidocs/src/lib/vectors-local.ts +0 -220
  240. package/skills/apidocs/src/lib/vectors-s3.ts +0 -255
  241. package/skills/apidocs/src/lib/vectors.ts +0 -97
  242. package/skills/apidocs/src/types/index.ts +0 -297
  243. package/skills/apidocs/src/utils/output.ts +0 -132
  244. package/skills/apidocs/src/utils/paths.ts +0 -126
  245. package/skills/apidocs/tsconfig.json +0 -24
  246. package/skills/audio/SKILL.md +0 -35
  247. package/skills/audio/package.json +0 -11
  248. package/skills/audio-cleanup-lab/CLAUDE.md +0 -3
  249. package/skills/audio-cleanup-lab/SKILL.md +0 -81
  250. package/skills/audio-cleanup-lab/package.json +0 -23
  251. package/skills/audio-cleanup-lab/src/index.ts +0 -274
  252. package/skills/audio-cleanup-lab/tsconfig.json +0 -14
  253. package/skills/audio-transcript-pack/SKILL.md +0 -43
  254. package/skills/audio-transcript-pack/package.json +0 -11
  255. package/skills/banner-ad-suite/CLAUDE.md +0 -19
  256. package/skills/banner-ad-suite/package.json +0 -27
  257. package/skills/banner-ad-suite/src/index.ts +0 -331
  258. package/skills/banner-ad-suite/tsconfig.json +0 -10
  259. package/skills/benchmark-finder/CLAUDE.md +0 -19
  260. package/skills/benchmark-finder/package.json +0 -27
  261. package/skills/benchmark-finder/src/index.ts +0 -294
  262. package/skills/benchmark-finder/tsconfig.json +0 -10
  263. package/skills/blog-topic-cluster/CLAUDE.md +0 -19
  264. package/skills/blog-topic-cluster/package.json +0 -27
  265. package/skills/blog-topic-cluster/src/index.ts +0 -274
  266. package/skills/blog-topic-cluster/tsconfig.json +0 -10
  267. package/skills/brand-photo-shoot/SKILL.md +0 -28
  268. package/skills/brand-photo-shoot/package.json +0 -11
  269. package/skills/brand-style-guide/CLAUDE.md +0 -20
  270. package/skills/brand-style-guide/SKILL.md +0 -13
  271. package/skills/brand-style-guide/package.json +0 -26
  272. package/skills/brand-style-guide/src/index.ts +0 -288
  273. package/skills/brand-style-guide/tsconfig.json +0 -22
  274. package/skills/brand-voice-audit/CLAUDE.md +0 -19
  275. package/skills/brand-voice-audit/package.json +0 -27
  276. package/skills/brand-voice-audit/src/index.ts +0 -302
  277. package/skills/brand-voice-audit/tsconfig.json +0 -10
  278. package/skills/browse/LICENSE +0 -192
  279. package/skills/browse/README.md +0 -25
  280. package/skills/browse/SKILL.md +0 -35
  281. package/skills/browse/package.json +0 -11
  282. package/skills/browse/tsconfig.json +0 -22
  283. package/skills/budget-variance-analyzer/CLAUDE.md +0 -16
  284. package/skills/budget-variance-analyzer/SKILL.md +0 -83
  285. package/skills/budget-variance-analyzer/package.json +0 -24
  286. package/skills/budget-variance-analyzer/src/index.ts +0 -298
  287. package/skills/budget-variance-analyzer/tsconfig.json +0 -21
  288. package/skills/calendar-events/CLAUDE.md +0 -19
  289. package/skills/calendar-events/package.json +0 -27
  290. package/skills/calendar-events/src/ai-parser.ts +0 -103
  291. package/skills/calendar-events/src/api.ts +0 -157
  292. package/skills/calendar-events/src/auth.ts +0 -22
  293. package/skills/calendar-events/src/config.ts +0 -6
  294. package/skills/calendar-events/src/format.ts +0 -96
  295. package/skills/calendar-events/src/help.ts +0 -54
  296. package/skills/calendar-events/src/index.ts +0 -415
  297. package/skills/calendar-events/src/logger.ts +0 -34
  298. package/skills/calendar-events/src/types.ts +0 -67
  299. package/skills/calendar-events/tsconfig.json +0 -10
  300. package/skills/campaign-metric-brief/CLAUDE.md +0 -19
  301. package/skills/campaign-metric-brief/package.json +0 -27
  302. package/skills/campaign-metric-brief/src/index.ts +0 -307
  303. package/skills/campaign-metric-brief/tsconfig.json +0 -10
  304. package/skills/campaign-moodboard/CLAUDE.md +0 -19
  305. package/skills/campaign-moodboard/package.json +0 -27
  306. package/skills/campaign-moodboard/src/index.ts +0 -288
  307. package/skills/campaign-moodboard/tsconfig.json +0 -10
  308. package/skills/caption-style-stylist/CLAUDE.md +0 -19
  309. package/skills/caption-style-stylist/package.json +0 -27
  310. package/skills/caption-style-stylist/src/index.ts +0 -275
  311. package/skills/caption-style-stylist/tsconfig.json +0 -10
  312. package/skills/chemistry-calculator/CLAUDE.md +0 -19
  313. package/skills/chemistry-calculator/package.json +0 -27
  314. package/skills/chemistry-calculator/src/index.ts +0 -110
  315. package/skills/chemistry-calculator/tsconfig.json +0 -10
  316. package/skills/churn-risk-notifier/CLAUDE.md +0 -19
  317. package/skills/churn-risk-notifier/package.json +0 -27
  318. package/skills/churn-risk-notifier/src/index.ts +0 -308
  319. package/skills/churn-risk-notifier/tsconfig.json +0 -10
  320. package/skills/citation-formatter/CLAUDE.md +0 -19
  321. package/skills/citation-formatter/package.json +0 -27
  322. package/skills/citation-formatter/src/index.ts +0 -83
  323. package/skills/citation-formatter/tsconfig.json +0 -10
  324. package/skills/classroom-newsletter-kit/CLAUDE.md +0 -19
  325. package/skills/classroom-newsletter-kit/package.json +0 -27
  326. package/skills/classroom-newsletter-kit/src/index.ts +0 -293
  327. package/skills/classroom-newsletter-kit/tsconfig.json +0 -10
  328. package/skills/color-palette-harmonizer/CLAUDE.md +0 -19
  329. package/skills/color-palette-harmonizer/package.json +0 -27
  330. package/skills/color-palette-harmonizer/src/index.ts +0 -278
  331. package/skills/color-palette-harmonizer/tsconfig.json +0 -10
  332. package/skills/colorextract/SKILL.md +0 -35
  333. package/skills/colorextract/bun.lock +0 -102
  334. package/skills/colorextract/package.json +0 -25
  335. package/skills/colorextract/src/index.ts +0 -405
  336. package/skills/competitor-ad-analyzer/CLAUDE.md +0 -19
  337. package/skills/competitor-ad-analyzer/package.json +0 -27
  338. package/skills/competitor-ad-analyzer/src/index.ts +0 -350
  339. package/skills/competitor-ad-analyzer/tsconfig.json +0 -10
  340. package/skills/compliance-copy-check/CLAUDE.md +0 -19
  341. package/skills/compliance-copy-check/package.json +0 -27
  342. package/skills/compliance-copy-check/src/index.ts +0 -289
  343. package/skills/compliance-copy-check/tsconfig.json +0 -10
  344. package/skills/compliance-report-pack/CLAUDE.md +0 -19
  345. package/skills/compliance-report-pack/package.json +0 -27
  346. package/skills/compliance-report-pack/src/index.ts +0 -301
  347. package/skills/compliance-report-pack/tsconfig.json +0 -10
  348. package/skills/consolelog/.env.example +0 -19
  349. package/skills/consolelog/CLAUDE.md +0 -157
  350. package/skills/consolelog/LICENSE +0 -192
  351. package/skills/consolelog/README.md +0 -239
  352. package/skills/consolelog/data/.gitkeep +0 -0
  353. package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.csv +0 -16
  354. package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.json +0 -227
  355. package/skills/consolelog/package.json +0 -40
  356. package/skills/consolelog/scripts/migrate.ts +0 -26
  357. package/skills/consolelog/scripts/seed.ts +0 -48
  358. package/skills/consolelog/src/db/index.ts +0 -44
  359. package/skills/consolelog/src/db/queries.ts +0 -348
  360. package/skills/consolelog/src/db/schema.ts +0 -93
  361. package/skills/consolelog/src/index.ts +0 -3
  362. package/skills/consolelog/src/lib/config.ts +0 -110
  363. package/skills/consolelog/src/lib/installer.ts +0 -294
  364. package/skills/consolelog/src/lib/monitor.ts +0 -194
  365. package/skills/consolelog/src/lib/types.ts +0 -189
  366. package/skills/consolelog/src/lib/watcher.ts +0 -207
  367. package/skills/consolelog/tests/api.test.ts +0 -154
  368. package/skills/consolelog/tests/config.test.ts +0 -192
  369. package/skills/consolelog/tests/db.test.ts +0 -447
  370. package/skills/consolelog/tests/installer.test.ts +0 -155
  371. package/skills/consolelog/tsconfig.json +0 -24
  372. package/skills/contract-plainlanguage/CLAUDE.md +0 -19
  373. package/skills/contract-plainlanguage/package.json +0 -27
  374. package/skills/contract-plainlanguage/src/index.ts +0 -294
  375. package/skills/contract-plainlanguage/tsconfig.json +0 -10
  376. package/skills/convert/.env.example +0 -7
  377. package/skills/convert/LICENSE +0 -192
  378. package/skills/convert/README.md +0 -250
  379. package/skills/convert/SKILL.md +0 -106
  380. package/skills/convert/package.json +0 -37
  381. package/skills/convert/src/converters/ai.ts +0 -375
  382. package/skills/convert/src/converters/data.ts +0 -339
  383. package/skills/convert/src/converters/document.ts +0 -189
  384. package/skills/convert/src/converters/image.ts +0 -227
  385. package/skills/convert/src/converters/index.ts +0 -9
  386. package/skills/convert/src/converters/pdf.ts +0 -255
  387. package/skills/convert/src/index-local.ts +0 -568
  388. package/skills/convert/src/index.ts +0 -4
  389. package/skills/convert/src/types.ts +0 -192
  390. package/skills/copytone-translator/CLAUDE.md +0 -19
  391. package/skills/copytone-translator/package.json +0 -27
  392. package/skills/copytone-translator/src/index.ts +0 -295
  393. package/skills/copytone-translator/tsconfig.json +0 -10
  394. package/skills/create-ebook/CLAUDE.md +0 -19
  395. package/skills/create-ebook/package.json +0 -27
  396. package/skills/create-ebook/src/index.ts +0 -637
  397. package/skills/create-ebook/tsconfig.json +0 -10
  398. package/skills/crm-note-enhancer/CLAUDE.md +0 -19
  399. package/skills/crm-note-enhancer/package.json +0 -27
  400. package/skills/crm-note-enhancer/src/index.ts +0 -317
  401. package/skills/crm-note-enhancer/tsconfig.json +0 -10
  402. package/skills/customer-journey-mapper/CLAUDE.md +0 -19
  403. package/skills/customer-journey-mapper/package.json +0 -27
  404. package/skills/customer-journey-mapper/src/index.ts +0 -312
  405. package/skills/customer-journey-mapper/tsconfig.json +0 -10
  406. package/skills/dashboard-narrator/CLAUDE.md +0 -19
  407. package/skills/dashboard-narrator/package.json +0 -27
  408. package/skills/dashboard-narrator/src/index.ts +0 -307
  409. package/skills/dashboard-narrator/tsconfig.json +0 -10
  410. package/skills/dataset-health-check/CLAUDE.md +0 -19
  411. package/skills/dataset-health-check/package.json +0 -27
  412. package/skills/dataset-health-check/src/index.ts +0 -323
  413. package/skills/dataset-health-check/tsconfig.json +0 -10
  414. package/skills/decision-journal/CLAUDE.md +0 -19
  415. package/skills/decision-journal/package.json +0 -27
  416. package/skills/decision-journal/src/index.ts +0 -313
  417. package/skills/decision-journal/tsconfig.json +0 -10
  418. package/skills/deepresearch/CLAUDE.md +0 -11
  419. package/skills/deepresearch/README.md +0 -26
  420. package/skills/deepresearch/SKILL.md +0 -41
  421. package/skills/deepresearch/package.json +0 -11
  422. package/skills/deepresearch/tsconfig.json +0 -29
  423. package/skills/delegation-brief-writer/CLAUDE.md +0 -19
  424. package/skills/delegation-brief-writer/package.json +0 -27
  425. package/skills/delegation-brief-writer/src/index.ts +0 -314
  426. package/skills/delegation-brief-writer/tsconfig.json +0 -10
  427. package/skills/deploy/LICENSE +0 -192
  428. package/skills/deploy/README.md +0 -382
  429. package/skills/deploy/SKILL.md +0 -138
  430. package/skills/deploy/package.json +0 -18
  431. package/skills/deploy/src/deployer.ts +0 -256
  432. package/skills/deploy/src/health.ts +0 -103
  433. package/skills/deploy/src/hosts.ts +0 -45
  434. package/skills/deploy/src/http-client.ts +0 -128
  435. package/skills/deploy/src/index-local.ts +0 -366
  436. package/skills/deploy/src/index.ts +0 -4
  437. package/skills/deploy/src/types.ts +0 -56
  438. package/skills/deploy/tsconfig.json +0 -18
  439. package/skills/destination-briefing/CLAUDE.md +0 -19
  440. package/skills/destination-briefing/package.json +0 -27
  441. package/skills/destination-briefing/src/index.ts +0 -291
  442. package/skills/destination-briefing/tsconfig.json +0 -10
  443. package/skills/doc-generate/CLAUDE.md +0 -19
  444. package/skills/doc-generate/SKILL.md +0 -295
  445. package/skills/doc-generate/package.json +0 -23
  446. package/skills/doc-generate/src/ai.ts +0 -50
  447. package/skills/doc-generate/src/cli.ts +0 -203
  448. package/skills/doc-generate/src/dependencies.ts +0 -44
  449. package/skills/doc-generate/src/document-builder.ts +0 -299
  450. package/skills/doc-generate/src/index.ts +0 -90
  451. package/skills/doc-generate/src/markdown-parser.ts +0 -125
  452. package/skills/doc-generate/src/types.ts +0 -68
  453. package/skills/doc-generate/tsconfig.json +0 -16
  454. package/skills/domainsearch/.env.example +0 -7
  455. package/skills/domainsearch/LICENSE +0 -192
  456. package/skills/domainsearch/SKILL.md +0 -41
  457. package/skills/domainsearch/package.json +0 -33
  458. package/skills/domainsearch/src/index.ts +0 -3
  459. package/skills/domainsearch/src/lib/api-client.ts +0 -181
  460. package/skills/domainsearch/src/lib/config.ts +0 -72
  461. package/skills/domainsearch/src/lib/installer.ts +0 -164
  462. package/skills/domainsearch/tsconfig.json +0 -22
  463. package/skills/educational-resource-finder/CLAUDE.md +0 -19
  464. package/skills/educational-resource-finder/package.json +0 -27
  465. package/skills/educational-resource-finder/src/index.ts +0 -289
  466. package/skills/educational-resource-finder/tsconfig.json +0 -10
  467. package/skills/email-campaign/CLAUDE.md +0 -19
  468. package/skills/email-campaign/package.json +0 -27
  469. package/skills/email-campaign/src/index.ts +0 -339
  470. package/skills/email-campaign/tsconfig.json +0 -10
  471. package/skills/emoji/.env.example +0 -7
  472. package/skills/emoji/QUICKSTART.md +0 -52
  473. package/skills/emoji/README.md +0 -175
  474. package/skills/emoji/SKILL.md +0 -63
  475. package/skills/emoji/package.json +0 -31
  476. package/skills/emoji/src/image-processor.ts +0 -143
  477. package/skills/emoji/src/index.ts +0 -282
  478. package/skills/emoji/src/prompt-generator.ts +0 -181
  479. package/skills/emoji/src/providers/gemini.ts +0 -58
  480. package/skills/emoji/src/providers/openai.ts +0 -55
  481. package/skills/emoji/src/types.ts +0 -72
  482. package/skills/exam-readiness-check/CLAUDE.md +0 -19
  483. package/skills/exam-readiness-check/package.json +0 -27
  484. package/skills/exam-readiness-check/src/index.ts +0 -289
  485. package/skills/exam-readiness-check/tsconfig.json +0 -10
  486. package/skills/excel/CLAUDE.md +0 -19
  487. package/skills/excel/SKILL.md +0 -38
  488. package/skills/excel/package.json +0 -30
  489. package/skills/excel/src/index.ts +0 -644
  490. package/skills/excel/tsconfig.json +0 -10
  491. package/skills/extract/.env.example +0 -3
  492. package/skills/extract/LICENSE +0 -192
  493. package/skills/extract/README.md +0 -61
  494. package/skills/extract/SKILL.md +0 -91
  495. package/skills/extract/package.json +0 -35
  496. package/skills/extract/src/extractors/image.ts +0 -42
  497. package/skills/extract/src/extractors/pdf.ts +0 -96
  498. package/skills/extract/src/index-local.ts +0 -258
  499. package/skills/extract/src/index.ts +0 -4
  500. package/skills/extract/src/providers/openai.ts +0 -222
  501. package/skills/extract/src/types.ts +0 -61
  502. package/skills/extract/tsconfig.json +0 -19
  503. package/skills/extract-invoice/CLAUDE.md +0 -19
  504. package/skills/extract-invoice/package.json +0 -27
  505. package/skills/extract-invoice/src/cli.ts +0 -97
  506. package/skills/extract-invoice/src/extractor.ts +0 -170
  507. package/skills/extract-invoice/src/file-utils.ts +0 -46
  508. package/skills/extract-invoice/src/formatters.ts +0 -144
  509. package/skills/extract-invoice/src/index.ts +0 -129
  510. package/skills/extract-invoice/src/runtime.ts +0 -46
  511. package/skills/extract-invoice/src/types.ts +0 -88
  512. package/skills/extract-invoice/tsconfig.json +0 -10
  513. package/skills/family-activity-curator/CLAUDE.md +0 -19
  514. package/skills/family-activity-curator/package.json +0 -27
  515. package/skills/family-activity-curator/src/index.ts +0 -293
  516. package/skills/family-activity-curator/tsconfig.json +0 -10
  517. package/skills/faq-packager/CLAUDE.md +0 -19
  518. package/skills/faq-packager/package.json +0 -27
  519. package/skills/faq-packager/src/index.ts +0 -292
  520. package/skills/faq-packager/tsconfig.json +0 -10
  521. package/skills/feedback-survey-designer/CLAUDE.md +0 -19
  522. package/skills/feedback-survey-designer/package.json +0 -27
  523. package/skills/feedback-survey-designer/src/index.ts +0 -299
  524. package/skills/feedback-survey-designer/tsconfig.json +0 -10
  525. package/skills/field-trip-planner/CLAUDE.md +0 -19
  526. package/skills/field-trip-planner/package.json +0 -27
  527. package/skills/field-trip-planner/src/index.ts +0 -289
  528. package/skills/field-trip-planner/tsconfig.json +0 -10
  529. package/skills/forecast-scenario-lab/CLAUDE.md +0 -19
  530. package/skills/forecast-scenario-lab/package.json +0 -27
  531. package/skills/forecast-scenario-lab/src/index.ts +0 -314
  532. package/skills/forecast-scenario-lab/tsconfig.json +0 -10
  533. package/skills/generate-book-cover/CLAUDE.md +0 -19
  534. package/skills/generate-book-cover/package.json +0 -11
  535. package/skills/generate-book-cover/tsconfig.json +0 -10
  536. package/skills/generate-diagram/CLAUDE.md +0 -19
  537. package/skills/generate-diagram/package.json +0 -27
  538. package/skills/generate-diagram/src/index.ts +0 -514
  539. package/skills/generate-diagram/tsconfig.json +0 -10
  540. package/skills/generate-documentation/CLAUDE.md +0 -19
  541. package/skills/generate-documentation/package.json +0 -27
  542. package/skills/generate-documentation/src/ai.ts +0 -131
  543. package/skills/generate-documentation/src/cli.ts +0 -71
  544. package/skills/generate-documentation/src/code-parser.ts +0 -300
  545. package/skills/generate-documentation/src/file-processing.ts +0 -182
  546. package/skills/generate-documentation/src/index.ts +0 -65
  547. package/skills/generate-documentation/src/runtime.ts +0 -35
  548. package/skills/generate-documentation/src/types.ts +0 -30
  549. package/skills/generate-documentation/tsconfig.json +0 -10
  550. package/skills/generate-mock-data/CLAUDE.md +0 -19
  551. package/skills/generate-mock-data/package.json +0 -29
  552. package/skills/generate-mock-data/src/ai.ts +0 -102
  553. package/skills/generate-mock-data/src/formatters.ts +0 -84
  554. package/skills/generate-mock-data/src/generator.ts +0 -377
  555. package/skills/generate-mock-data/src/index.ts +0 -201
  556. package/skills/generate-mock-data/src/logger.ts +0 -37
  557. package/skills/generate-mock-data/src/presets.ts +0 -110
  558. package/skills/generate-mock-data/src/types.ts +0 -21
  559. package/skills/generate-mock-data/tsconfig.json +0 -10
  560. package/skills/generate-pr-description/CLAUDE.md +0 -19
  561. package/skills/generate-pr-description/package.json +0 -27
  562. package/skills/generate-pr-description/src/ai.ts +0 -144
  563. package/skills/generate-pr-description/src/cli.ts +0 -80
  564. package/skills/generate-pr-description/src/clipboard.ts +0 -30
  565. package/skills/generate-pr-description/src/formatters.ts +0 -231
  566. package/skills/generate-pr-description/src/git.ts +0 -153
  567. package/skills/generate-pr-description/src/index.ts +0 -114
  568. package/skills/generate-pr-description/src/types.ts +0 -49
  569. package/skills/generate-pr-description/tsconfig.json +0 -10
  570. package/skills/generate-presentation/CLAUDE.md +0 -19
  571. package/skills/generate-presentation/package.json +0 -27
  572. package/skills/generate-presentation/src/ai-clients.ts +0 -61
  573. package/skills/generate-presentation/src/cli.ts +0 -126
  574. package/skills/generate-presentation/src/index.ts +0 -44
  575. package/skills/generate-presentation/src/logger.ts +0 -67
  576. package/skills/generate-presentation/src/presentation-generator.ts +0 -425
  577. package/skills/generate-presentation/src/runtime.ts +0 -6
  578. package/skills/generate-presentation/src/security.ts +0 -12
  579. package/skills/generate-presentation/src/types.ts +0 -28
  580. package/skills/generate-presentation/tsconfig.json +0 -10
  581. package/skills/generate-regex/CLAUDE.md +0 -19
  582. package/skills/generate-regex/package.json +0 -29
  583. package/skills/generate-regex/src/index.ts +0 -669
  584. package/skills/generate-regex/tsconfig.json +0 -10
  585. package/skills/generate-social-posts/CLAUDE.md +0 -19
  586. package/skills/generate-social-posts/package.json +0 -27
  587. package/skills/generate-social-posts/src/ai.ts +0 -88
  588. package/skills/generate-social-posts/src/cli.ts +0 -118
  589. package/skills/generate-social-posts/src/exporters.ts +0 -126
  590. package/skills/generate-social-posts/src/generator.ts +0 -130
  591. package/skills/generate-social-posts/src/index.ts +0 -78
  592. package/skills/generate-social-posts/src/platforms.ts +0 -39
  593. package/skills/generate-social-posts/src/runtime.ts +0 -34
  594. package/skills/generate-social-posts/src/source.ts +0 -116
  595. package/skills/generate-social-posts/src/types.ts +0 -58
  596. package/skills/generate-social-posts/tsconfig.json +0 -10
  597. package/skills/generate-sql/CLAUDE.md +0 -19
  598. package/skills/generate-sql/package.json +0 -27
  599. package/skills/generate-sql/src/index.ts +0 -636
  600. package/skills/generate-sql/tsconfig.json +0 -10
  601. package/skills/github-manager/CLAUDE.md +0 -19
  602. package/skills/github-manager/package.json +0 -29
  603. package/skills/github-manager/src/index.ts +0 -101
  604. package/skills/github-manager/tsconfig.json +0 -10
  605. package/skills/gmail/CLAUDE.md +0 -19
  606. package/skills/gmail/package.json +0 -27
  607. package/skills/gmail/src/index.ts +0 -410
  608. package/skills/gmail/tsconfig.json +0 -10
  609. package/skills/goal-quarterly-roadmap/CLAUDE.md +0 -19
  610. package/skills/goal-quarterly-roadmap/package.json +0 -27
  611. package/skills/goal-quarterly-roadmap/src/index.ts +0 -305
  612. package/skills/goal-quarterly-roadmap/tsconfig.json +0 -10
  613. package/skills/grant-application-drafter/CLAUDE.md +0 -19
  614. package/skills/grant-application-drafter/package.json +0 -27
  615. package/skills/grant-application-drafter/src/index.ts +0 -309
  616. package/skills/grant-application-drafter/tsconfig.json +0 -10
  617. package/skills/grocery-basket-optimizer/CLAUDE.md +0 -19
  618. package/skills/grocery-basket-optimizer/package.json +0 -27
  619. package/skills/grocery-basket-optimizer/src/index.ts +0 -304
  620. package/skills/grocery-basket-optimizer/tsconfig.json +0 -10
  621. package/skills/guest-communication-suite/CLAUDE.md +0 -19
  622. package/skills/guest-communication-suite/package.json +0 -27
  623. package/skills/guest-communication-suite/src/index.ts +0 -312
  624. package/skills/guest-communication-suite/tsconfig.json +0 -10
  625. package/skills/habit-reflection-digest/CLAUDE.md +0 -19
  626. package/skills/habit-reflection-digest/package.json +0 -27
  627. package/skills/habit-reflection-digest/src/index.ts +0 -308
  628. package/skills/habit-reflection-digest/tsconfig.json +0 -10
  629. package/skills/highlight-reel-generator/CLAUDE.md +0 -19
  630. package/skills/highlight-reel-generator/package.json +0 -27
  631. package/skills/highlight-reel-generator/src/index.ts +0 -286
  632. package/skills/highlight-reel-generator/tsconfig.json +0 -10
  633. package/skills/homework-feedback-coach/CLAUDE.md +0 -19
  634. package/skills/homework-feedback-coach/package.json +0 -27
  635. package/skills/homework-feedback-coach/src/index.ts +0 -316
  636. package/skills/homework-feedback-coach/tsconfig.json +0 -10
  637. package/skills/household-maintenance-mgr/CLAUDE.md +0 -19
  638. package/skills/household-maintenance-mgr/package.json +0 -27
  639. package/skills/household-maintenance-mgr/src/index.ts +0 -293
  640. package/skills/household-maintenance-mgr/tsconfig.json +0 -10
  641. package/skills/icon-pack/README.md +0 -28
  642. package/skills/icon-pack/SKILL.md +0 -23
  643. package/skills/icon-pack/package.json +0 -11
  644. package/skills/icon-pack/tsconfig.json +0 -20
  645. package/skills/image/LICENSE +0 -192
  646. package/skills/image/README.md +0 -25
  647. package/skills/image/SKILL.md +0 -49
  648. package/skills/image/examples/aurora-examples.sh +0 -33
  649. package/skills/image/examples/google-examples.sh +0 -37
  650. package/skills/image/examples/openai-examples.sh +0 -35
  651. package/skills/image/package.json +0 -11
  652. package/skills/image/tsconfig.json +0 -19
  653. package/skills/implementation-agent/CLAUDE.md +0 -19
  654. package/skills/implementation-agent/package.json +0 -29
  655. package/skills/implementation-agent/src/ai-generation.ts +0 -225
  656. package/skills/implementation-agent/src/index.ts +0 -608
  657. package/skills/implementation-agent/src/minimist.d.ts +0 -15
  658. package/skills/implementation-agent/src/templates.ts +0 -686
  659. package/skills/implementation-agent/src/types.ts +0 -53
  660. package/skills/implementation-agent/tsconfig.json +0 -10
  661. package/skills/inbox-priority-planner/CLAUDE.md +0 -19
  662. package/skills/inbox-priority-planner/package.json +0 -27
  663. package/skills/inbox-priority-planner/src/index.ts +0 -309
  664. package/skills/inbox-priority-planner/tsconfig.json +0 -10
  665. package/skills/invoice-dispute-helper/CLAUDE.md +0 -19
  666. package/skills/invoice-dispute-helper/package.json +0 -27
  667. package/skills/invoice-dispute-helper/src/index.ts +0 -304
  668. package/skills/invoice-dispute-helper/tsconfig.json +0 -10
  669. package/skills/itinerary-architect/CLAUDE.md +0 -19
  670. package/skills/itinerary-architect/package.json +0 -27
  671. package/skills/itinerary-architect/src/index.ts +0 -313
  672. package/skills/itinerary-architect/tsconfig.json +0 -10
  673. package/skills/kpi-digest-generator/CLAUDE.md +0 -19
  674. package/skills/kpi-digest-generator/package.json +0 -27
  675. package/skills/kpi-digest-generator/src/index.ts +0 -318
  676. package/skills/kpi-digest-generator/tsconfig.json +0 -10
  677. package/skills/lab-notebook-formatter/CLAUDE.md +0 -19
  678. package/skills/lab-notebook-formatter/package.json +0 -27
  679. package/skills/lab-notebook-formatter/src/index.ts +0 -88
  680. package/skills/lab-notebook-formatter/tsconfig.json +0 -10
  681. package/skills/landing-page-copy/CLAUDE.md +0 -19
  682. package/skills/landing-page-copy/package.json +0 -27
  683. package/skills/landing-page-copy/src/index.ts +0 -400
  684. package/skills/landing-page-copy/tsconfig.json +0 -10
  685. package/skills/learning-style-profiler/CLAUDE.md +0 -19
  686. package/skills/learning-style-profiler/package.json +0 -27
  687. package/skills/learning-style-profiler/src/index.ts +0 -291
  688. package/skills/learning-style-profiler/tsconfig.json +0 -10
  689. package/skills/lesson-plan-customizer/CLAUDE.md +0 -19
  690. package/skills/lesson-plan-customizer/package.json +0 -27
  691. package/skills/lesson-plan-customizer/src/index.ts +0 -303
  692. package/skills/lesson-plan-customizer/tsconfig.json +0 -10
  693. package/skills/livestream-runofshow/CLAUDE.md +0 -19
  694. package/skills/livestream-runofshow/package.json +0 -27
  695. package/skills/livestream-runofshow/src/index.ts +0 -299
  696. package/skills/livestream-runofshow/tsconfig.json +0 -10
  697. package/skills/longform-structurer/CLAUDE.md +0 -19
  698. package/skills/longform-structurer/package.json +0 -27
  699. package/skills/longform-structurer/src/index.ts +0 -293
  700. package/skills/longform-structurer/tsconfig.json +0 -10
  701. package/skills/managehook/.env.example +0 -16
  702. package/skills/managehook/CLAUDE.md +0 -48
  703. package/skills/managehook/README.md +0 -210
  704. package/skills/managehook/package.json +0 -24
  705. package/skills/managehook/scripts/migrate.ts +0 -57
  706. package/skills/managehook/scripts/seed.ts +0 -58
  707. package/skills/managehook/src/db/index.ts +0 -37
  708. package/skills/managehook/src/index.ts +0 -3
  709. package/skills/managehook/src/lib/api-client.ts +0 -108
  710. package/skills/managehook/src/lib/config.ts +0 -34
  711. package/skills/managehook/src/lib/installer.ts +0 -140
  712. package/skills/managehook/src/lib/service-dir.ts +0 -119
  713. package/skills/managehook/tsconfig.json +0 -29
  714. package/skills/manageskill/.env.example +0 -16
  715. package/skills/manageskill/CLAUDE.md +0 -48
  716. package/skills/manageskill/README.md +0 -210
  717. package/skills/manageskill/package.json +0 -24
  718. package/skills/manageskill/scripts/migrate.ts +0 -57
  719. package/skills/manageskill/scripts/seed.ts +0 -58
  720. package/skills/manageskill/src/db/index.ts +0 -37
  721. package/skills/manageskill/src/index.ts +0 -3
  722. package/skills/manageskill/src/lib/api-client.ts +0 -108
  723. package/skills/manageskill/src/lib/config.ts +0 -34
  724. package/skills/manageskill/src/lib/installer.ts +0 -140
  725. package/skills/manageskill/src/lib/service-dir.ts +0 -119
  726. package/skills/manageskill/tsconfig.json +0 -29
  727. package/skills/mcp-builder/CLAUDE.md +0 -19
  728. package/skills/mcp-builder/package.json +0 -30
  729. package/skills/mcp-builder/src/ai-descriptions.ts +0 -37
  730. package/skills/mcp-builder/src/generators.ts +0 -513
  731. package/skills/mcp-builder/src/index.ts +0 -62
  732. package/skills/mcp-builder/src/minimist.d.ts +0 -15
  733. package/skills/mcp-builder/src/naming.ts +0 -12
  734. package/skills/mcp-builder/src/options.ts +0 -170
  735. package/skills/mcp-builder/src/templates.ts +0 -149
  736. package/skills/mcp-builder/src/types.ts +0 -42
  737. package/skills/mcp-builder/tsconfig.json +0 -10
  738. package/skills/meal-plan-designer/CLAUDE.md +0 -19
  739. package/skills/meal-plan-designer/package.json +0 -27
  740. package/skills/meal-plan-designer/src/index.ts +0 -301
  741. package/skills/meal-plan-designer/tsconfig.json +0 -10
  742. package/skills/meeting-insight-summarizer/CLAUDE.md +0 -19
  743. package/skills/meeting-insight-summarizer/package.json +0 -27
  744. package/skills/meeting-insight-summarizer/src/index.ts +0 -316
  745. package/skills/meeting-insight-summarizer/tsconfig.json +0 -10
  746. package/skills/microcopy-generator/CLAUDE.md +0 -19
  747. package/skills/microcopy-generator/package.json +0 -27
  748. package/skills/microcopy-generator/src/index.ts +0 -303
  749. package/skills/microcopy-generator/tsconfig.json +0 -10
  750. package/skills/mindfulness-prompt-cache/CLAUDE.md +0 -19
  751. package/skills/mindfulness-prompt-cache/package.json +0 -27
  752. package/skills/mindfulness-prompt-cache/src/index.ts +0 -290
  753. package/skills/mindfulness-prompt-cache/tsconfig.json +0 -10
  754. package/skills/music/SKILL.md +0 -33
  755. package/skills/music/package.json +0 -11
  756. package/skills/music-album/SKILL.md +0 -37
  757. package/skills/music-album/package.json +0 -11
  758. package/skills/notion-manager/CLAUDE.md +0 -19
  759. package/skills/notion-manager/package.json +0 -29
  760. package/skills/notion-manager/src/index.ts +0 -105
  761. package/skills/notion-manager/tsconfig.json +0 -10
  762. package/skills/npmpublish/CLAUDE.md +0 -30
  763. package/skills/npmpublish/README.md +0 -83
  764. package/skills/npmpublish/SKILL.md +0 -70
  765. package/skills/npmpublish/package.json +0 -41
  766. package/skills/npmpublish/src/index.ts +0 -192
  767. package/skills/npmpublish/tsconfig.json +0 -18
  768. package/skills/onboarding-sequence-builder/CLAUDE.md +0 -19
  769. package/skills/onboarding-sequence-builder/package.json +0 -27
  770. package/skills/onboarding-sequence-builder/src/index.ts +0 -321
  771. package/skills/onboarding-sequence-builder/tsconfig.json +0 -10
  772. package/skills/onsite-ops-checklist/CLAUDE.md +0 -19
  773. package/skills/onsite-ops-checklist/package.json +0 -27
  774. package/skills/onsite-ops-checklist/src/index.ts +0 -307
  775. package/skills/onsite-ops-checklist/tsconfig.json +0 -10
  776. package/skills/outreach-cadence-designer/CLAUDE.md +0 -19
  777. package/skills/outreach-cadence-designer/package.json +0 -27
  778. package/skills/outreach-cadence-designer/src/index.ts +0 -330
  779. package/skills/outreach-cadence-designer/tsconfig.json +0 -10
  780. package/skills/packaging-concept-studio/CLAUDE.md +0 -19
  781. package/skills/packaging-concept-studio/package.json +0 -27
  782. package/skills/packaging-concept-studio/src/index.ts +0 -296
  783. package/skills/packaging-concept-studio/tsconfig.json +0 -10
  784. package/skills/packing-plan-pro/CLAUDE.md +0 -19
  785. package/skills/packing-plan-pro/package.json +0 -27
  786. package/skills/packing-plan-pro/src/index.ts +0 -306
  787. package/skills/packing-plan-pro/tsconfig.json +0 -10
  788. package/skills/parent-teacher-brief/CLAUDE.md +0 -19
  789. package/skills/parent-teacher-brief/package.json +0 -27
  790. package/skills/parent-teacher-brief/src/index.ts +0 -290
  791. package/skills/parent-teacher-brief/tsconfig.json +0 -10
  792. package/skills/partner-kit-assembler/CLAUDE.md +0 -19
  793. package/skills/partner-kit-assembler/package.json +0 -27
  794. package/skills/partner-kit-assembler/src/index.ts +0 -313
  795. package/skills/partner-kit-assembler/tsconfig.json +0 -10
  796. package/skills/payroll-change-prepper/CLAUDE.md +0 -19
  797. package/skills/payroll-change-prepper/package.json +0 -27
  798. package/skills/payroll-change-prepper/src/index.ts +0 -304
  799. package/skills/payroll-change-prepper/tsconfig.json +0 -10
  800. package/skills/pdf-read/SKILL.md +0 -56
  801. package/skills/pdf-read/package.json +0 -11
  802. package/skills/pdf-read/tsconfig.json +0 -8
  803. package/skills/persona-based-adwriter/CLAUDE.md +0 -19
  804. package/skills/persona-based-adwriter/package.json +0 -27
  805. package/skills/persona-based-adwriter/src/index.ts +0 -285
  806. package/skills/persona-based-adwriter/tsconfig.json +0 -10
  807. package/skills/persona-generator/CLAUDE.md +0 -19
  808. package/skills/persona-generator/package.json +0 -27
  809. package/skills/persona-generator/src/index.ts +0 -443
  810. package/skills/persona-generator/tsconfig.json +0 -10
  811. package/skills/personal-daily-ops/CLAUDE.md +0 -19
  812. package/skills/personal-daily-ops/package.json +0 -27
  813. package/skills/personal-daily-ops/src/index.ts +0 -324
  814. package/skills/personal-daily-ops/tsconfig.json +0 -10
  815. package/skills/pet-care-scheduler/CLAUDE.md +0 -19
  816. package/skills/pet-care-scheduler/package.json +0 -27
  817. package/skills/pet-care-scheduler/src/index.ts +0 -298
  818. package/skills/pet-care-scheduler/tsconfig.json +0 -10
  819. package/skills/photo-album/SKILL.md +0 -29
  820. package/skills/photo-album/package.json +0 -11
  821. package/skills/photo-album/tsconfig.json +0 -4
  822. package/skills/playlist-maker/SKILL.md +0 -33
  823. package/skills/playlist-maker/package.json +0 -11
  824. package/skills/playlist-maker/tsconfig.json +0 -4
  825. package/skills/podcast-show-notes/CLAUDE.md +0 -19
  826. package/skills/podcast-show-notes/package.json +0 -27
  827. package/skills/podcast-show-notes/src/index.ts +0 -302
  828. package/skills/podcast-show-notes/tsconfig.json +0 -10
  829. package/skills/presentation-theme-maker/CLAUDE.md +0 -19
  830. package/skills/presentation-theme-maker/package.json +0 -27
  831. package/skills/presentation-theme-maker/src/index.ts +0 -292
  832. package/skills/presentation-theme-maker/tsconfig.json +0 -10
  833. package/skills/press-release-drafter/CLAUDE.md +0 -19
  834. package/skills/press-release-drafter/package.json +0 -27
  835. package/skills/press-release-drafter/src/index.ts +0 -291
  836. package/skills/press-release-drafter/tsconfig.json +0 -10
  837. package/skills/print-collateral-designer/CLAUDE.md +0 -19
  838. package/skills/print-collateral-designer/package.json +0 -27
  839. package/skills/print-collateral-designer/src/index.ts +0 -298
  840. package/skills/print-collateral-designer/tsconfig.json +0 -10
  841. package/skills/procurement-scorecard/CLAUDE.md +0 -19
  842. package/skills/procurement-scorecard/package.json +0 -27
  843. package/skills/procurement-scorecard/src/index.ts +0 -338
  844. package/skills/procurement-scorecard/tsconfig.json +0 -10
  845. package/skills/product-demo-script/CLAUDE.md +0 -19
  846. package/skills/product-demo-script/package.json +0 -27
  847. package/skills/product-demo-script/src/index.ts +0 -326
  848. package/skills/product-demo-script/tsconfig.json +0 -10
  849. package/skills/project-dashboard-reports/SKILL.md +0 -78
  850. package/skills/project-dashboard-reports/package.json +0 -25
  851. package/skills/project-dashboard-reports/src/index.ts +0 -67
  852. package/skills/project-retro-companion/CLAUDE.md +0 -19
  853. package/skills/project-retro-companion/package.json +0 -27
  854. package/skills/project-retro-companion/src/index.ts +0 -298
  855. package/skills/project-retro-companion/tsconfig.json +0 -10
  856. package/skills/proposal-redline-advisor/CLAUDE.md +0 -19
  857. package/skills/proposal-redline-advisor/package.json +0 -27
  858. package/skills/proposal-redline-advisor/src/index.ts +0 -320
  859. package/skills/proposal-redline-advisor/tsconfig.json +0 -10
  860. package/skills/read-image/SKILL.md +0 -47
  861. package/skills/read-image/package.json +0 -33
  862. package/skills/read-image/src/index.ts +0 -264
  863. package/skills/read-pdf/SKILL.md +0 -53
  864. package/skills/read-pdf/package.json +0 -11
  865. package/skills/remove-background/CLAUDE.md +0 -19
  866. package/skills/remove-background/package.json +0 -11
  867. package/skills/remove-background/tsconfig.json +0 -10
  868. package/skills/risk-disclosure-kit/CLAUDE.md +0 -19
  869. package/skills/risk-disclosure-kit/package.json +0 -27
  870. package/skills/risk-disclosure-kit/src/index.ts +0 -307
  871. package/skills/risk-disclosure-kit/tsconfig.json +0 -10
  872. package/skills/roi-comparison-tool/CLAUDE.md +0 -19
  873. package/skills/roi-comparison-tool/package.json +0 -27
  874. package/skills/roi-comparison-tool/src/index.ts +0 -322
  875. package/skills/roi-comparison-tool/tsconfig.json +0 -10
  876. package/skills/sales-call-recapper/CLAUDE.md +0 -19
  877. package/skills/sales-call-recapper/package.json +0 -27
  878. package/skills/sales-call-recapper/src/index.ts +0 -300
  879. package/skills/sales-call-recapper/tsconfig.json +0 -10
  880. package/skills/salescopy/.env.example +0 -2
  881. package/skills/salescopy/CLAUDE.md +0 -23
  882. package/skills/salescopy/LICENSE +0 -192
  883. package/skills/salescopy/README.md +0 -72
  884. package/skills/salescopy/package.json +0 -27
  885. package/skills/salescopy/src/commands/config.ts +0 -115
  886. package/skills/salescopy/src/commands/generate.ts +0 -179
  887. package/skills/salescopy/src/commands/sessions.ts +0 -169
  888. package/skills/salescopy/src/commands/templates.ts +0 -99
  889. package/skills/salescopy/src/index.ts +0 -3
  890. package/skills/salescopy/src/lib/generator.ts +0 -197
  891. package/skills/salescopy/src/lib/storage.ts +0 -191
  892. package/skills/salescopy/src/types/index.ts +0 -74
  893. package/skills/salescopy/src/utils/logger.ts +0 -33
  894. package/skills/salescopy/src/utils/paths.ts +0 -25
  895. package/skills/salescopy/tsconfig.json +0 -23
  896. package/skills/scaffold-project/CLAUDE.md +0 -19
  897. package/skills/scaffold-project/package.json +0 -29
  898. package/skills/scaffold-project/src/ai-detect.ts +0 -136
  899. package/skills/scaffold-project/src/file-generators.ts +0 -292
  900. package/skills/scaffold-project/src/index.ts +0 -240
  901. package/skills/scaffold-project/src/project-config.ts +0 -338
  902. package/skills/scaffold-project/src/templates.ts +0 -173
  903. package/skills/scaffold-project/src/types.ts +0 -58
  904. package/skills/scaffold-project/tsconfig.json +0 -10
  905. package/skills/scholarship-tracker/CLAUDE.md +0 -19
  906. package/skills/scholarship-tracker/package.json +0 -27
  907. package/skills/scholarship-tracker/src/index.ts +0 -298
  908. package/skills/scholarship-tracker/tsconfig.json +0 -10
  909. package/skills/sdk-generator/SKILL.md +0 -45
  910. package/skills/sdk-generator/package.json +0 -11
  911. package/skills/sdk-generator/tsconfig.json +0 -8
  912. package/skills/seating-chart-maker/CLAUDE.md +0 -19
  913. package/skills/seating-chart-maker/package.json +0 -27
  914. package/skills/seating-chart-maker/src/index.ts +0 -312
  915. package/skills/seating-chart-maker/tsconfig.json +0 -10
  916. package/skills/seo-brief-builder/CLAUDE.md +0 -19
  917. package/skills/seo-brief-builder/package.json +0 -27
  918. package/skills/seo-brief-builder/src/index.ts +0 -288
  919. package/skills/seo-brief-builder/tsconfig.json +0 -10
  920. package/skills/short-video-pack/SKILL.md +0 -30
  921. package/skills/short-video-pack/package.json +0 -11
  922. package/skills/slack-assistant/CLAUDE.md +0 -19
  923. package/skills/slack-assistant/package.json +0 -29
  924. package/skills/slack-assistant/src/index.ts +0 -79
  925. package/skills/slack-assistant/tsconfig.json +0 -10
  926. package/skills/sleep-routine-analyzer/CLAUDE.md +0 -19
  927. package/skills/sleep-routine-analyzer/package.json +0 -27
  928. package/skills/sleep-routine-analyzer/src/index.ts +0 -293
  929. package/skills/sleep-routine-analyzer/tsconfig.json +0 -10
  930. package/skills/sms/README.md +0 -33
  931. package/skills/sms/package.json +0 -35
  932. package/skills/sms/src/index.ts +0 -335
  933. package/skills/sms/tsconfig.json +0 -21
  934. package/skills/social-media-kit/CLAUDE.md +0 -19
  935. package/skills/social-media-kit/package.json +0 -27
  936. package/skills/social-media-kit/src/index.ts +0 -281
  937. package/skills/social-media-kit/tsconfig.json +0 -10
  938. package/skills/sponsorship-proposal-lab/CLAUDE.md +0 -19
  939. package/skills/sponsorship-proposal-lab/package.json +0 -27
  940. package/skills/sponsorship-proposal-lab/src/index.ts +0 -300
  941. package/skills/sponsorship-proposal-lab/tsconfig.json +0 -10
  942. package/skills/spreadsheet-cleanroom/CLAUDE.md +0 -19
  943. package/skills/spreadsheet-cleanroom/package.json +0 -27
  944. package/skills/spreadsheet-cleanroom/src/index.ts +0 -331
  945. package/skills/spreadsheet-cleanroom/tsconfig.json +0 -10
  946. package/skills/stress-relief-playbook/CLAUDE.md +0 -19
  947. package/skills/stress-relief-playbook/package.json +0 -27
  948. package/skills/stress-relief-playbook/src/index.ts +0 -298
  949. package/skills/stress-relief-playbook/tsconfig.json +0 -10
  950. package/skills/study-guide-builder/CLAUDE.md +0 -19
  951. package/skills/study-guide-builder/package.json +0 -27
  952. package/skills/study-guide-builder/src/index.ts +0 -298
  953. package/skills/study-guide-builder/tsconfig.json +0 -10
  954. package/skills/subscription-spend-watcher/CLAUDE.md +0 -19
  955. package/skills/subscription-spend-watcher/package.json +0 -27
  956. package/skills/subscription-spend-watcher/src/index.ts +0 -312
  957. package/skills/subscription-spend-watcher/tsconfig.json +0 -10
  958. package/skills/subtitle/.env.example +0 -2
  959. package/skills/subtitle/CLAUDE.md +0 -37
  960. package/skills/subtitle/LICENSE +0 -192
  961. package/skills/subtitle/README.md +0 -63
  962. package/skills/subtitle/package.json +0 -43
  963. package/skills/subtitle/src/commands/config.ts +0 -53
  964. package/skills/subtitle/src/commands/generate.ts +0 -61
  965. package/skills/subtitle/src/index.ts +0 -3
  966. package/skills/subtitle/src/lib/generator.ts +0 -216
  967. package/skills/subtitle/src/lib/storage.ts +0 -62
  968. package/skills/subtitle/src/types/index.ts +0 -68
  969. package/skills/subtitle/src/utils/logger.ts +0 -34
  970. package/skills/subtitle/src/utils/paths.ts +0 -51
  971. package/skills/subtitle/tsconfig.json +0 -21
  972. package/skills/survey-insight-extractor/CLAUDE.md +0 -19
  973. package/skills/survey-insight-extractor/package.json +0 -27
  974. package/skills/survey-insight-extractor/src/index.ts +0 -317
  975. package/skills/survey-insight-extractor/tsconfig.json +0 -10
  976. package/skills/terraform-generator/CLAUDE.md +0 -19
  977. package/skills/terraform-generator/package.json +0 -29
  978. package/skills/terraform-generator/src/index.ts +0 -99
  979. package/skills/terraform-generator/tsconfig.json +0 -10
  980. package/skills/testimonial-graphics/CLAUDE.md +0 -19
  981. package/skills/testimonial-graphics/package.json +0 -27
  982. package/skills/testimonial-graphics/src/index.ts +0 -303
  983. package/skills/testimonial-graphics/tsconfig.json +0 -10
  984. package/skills/timesheet/.env.example +0 -25
  985. package/skills/timesheet/README.md +0 -235
  986. package/skills/timesheet/package.json +0 -47
  987. package/skills/timesheet/scripts/publish.ts +0 -210
  988. package/skills/timesheet/src/commands/employee.ts +0 -96
  989. package/skills/timesheet/src/commands/export.ts +0 -29
  990. package/skills/timesheet/src/commands/generate.ts +0 -102
  991. package/skills/timesheet/src/commands/holiday.ts +0 -74
  992. package/skills/timesheet/src/commands/profile.ts +0 -133
  993. package/skills/timesheet/src/commands/setup.ts +0 -21
  994. package/skills/timesheet/src/commands/vacation.ts +0 -93
  995. package/skills/timesheet/src/index.ts +0 -3
  996. package/skills/timesheet/src/lib/employees.ts +0 -56
  997. package/skills/timesheet/src/lib/export.ts +0 -123
  998. package/skills/timesheet/src/lib/holidays.ts +0 -79
  999. package/skills/timesheet/src/lib/paths.ts +0 -59
  1000. package/skills/timesheet/src/lib/profiles.ts +0 -168
  1001. package/skills/timesheet/src/lib/storage.ts +0 -83
  1002. package/skills/timesheet/src/lib/timesheet.ts +0 -130
  1003. package/skills/timesheet/src/lib/vacations.ts +0 -70
  1004. package/skills/timesheet/src/types/index.ts +0 -96
  1005. package/skills/timesheet/tsconfig.json +0 -29
  1006. package/skills/transcript/LICENSE +0 -192
  1007. package/skills/transcript/README.md +0 -17
  1008. package/skills/transcript/SKILL.md +0 -80
  1009. package/skills/transcript/package.json +0 -11
  1010. package/skills/transcript/tsconfig.json +0 -18
  1011. package/skills/travel-budget-balancer/CLAUDE.md +0 -19
  1012. package/skills/travel-budget-balancer/package.json +0 -27
  1013. package/skills/travel-budget-balancer/src/index.ts +0 -297
  1014. package/skills/travel-budget-balancer/tsconfig.json +0 -10
  1015. package/skills/video/SKILL.md +0 -37
  1016. package/skills/video/package.json +0 -11
  1017. package/skills/video-cut-suggester/CLAUDE.md +0 -19
  1018. package/skills/video-cut-suggester/package.json +0 -27
  1019. package/skills/video-cut-suggester/src/index.ts +0 -304
  1020. package/skills/video-cut-suggester/tsconfig.json +0 -10
  1021. package/skills/video-thumbnail/CLAUDE.md +0 -19
  1022. package/skills/video-thumbnail/package.json +0 -27
  1023. package/skills/video-thumbnail/src/index.ts +0 -356
  1024. package/skills/video-thumbnail/tsconfig.json +0 -10
  1025. package/skills/voiceover-jingle-pack/SKILL.md +0 -28
  1026. package/skills/voiceover-jingle-pack/package.json +0 -11
  1027. package/skills/webcrawling/CLAUDE.md +0 -11
  1028. package/skills/webcrawling/LICENSE +0 -192
  1029. package/skills/webcrawling/README.md +0 -24
  1030. package/skills/webcrawling/package.json +0 -11
  1031. package/skills/webcrawling/tsconfig.json +0 -22
  1032. package/skills/webinar-script-coach/CLAUDE.md +0 -19
  1033. package/skills/webinar-script-coach/package.json +0 -27
  1034. package/skills/webinar-script-coach/src/index.ts +0 -296
  1035. package/skills/webinar-script-coach/tsconfig.json +0 -10
  1036. package/skills/wellness-progress-reporter/CLAUDE.md +0 -19
  1037. package/skills/wellness-progress-reporter/package.json +0 -27
  1038. package/skills/wellness-progress-reporter/src/index.ts +0 -298
  1039. package/skills/wellness-progress-reporter/tsconfig.json +0 -10
  1040. package/skills/workout-cycle-planner/CLAUDE.md +0 -19
  1041. package/skills/workout-cycle-planner/package.json +0 -27
  1042. package/skills/workout-cycle-planner/src/index.ts +0 -299
  1043. package/skills/workout-cycle-planner/tsconfig.json +0 -10
  1044. package/skills/write/.env.example +0 -9
  1045. package/skills/write/LICENSE +0 -192
  1046. package/skills/write/README.md +0 -17
  1047. package/skills/write/SKILL.md +0 -90
  1048. package/skills/write/package.json +0 -32
  1049. package/skills/write/src/agents/image-generator.ts +0 -186
  1050. package/skills/write/src/agents/researcher.ts +0 -61
  1051. package/skills/write/src/agents/writer.ts +0 -99
  1052. package/skills/write/src/index-local.ts +0 -248
  1053. package/skills/write/src/index.ts +0 -4
  1054. package/skills/write/src/orchestrator.ts +0 -171
  1055. package/skills/write/src/types.ts +0 -65
  1056. package/skills/write/tsconfig.json +0 -18
  1057. /package/migrations/{0001_open_skills_self_hosted.sql → postgres/0001_open_skills_self_hosted.sql} +0 -0
  1058. /package/skills/{read-image → api-docs-portal}/tsconfig.json +0 -0
  1059. /package/skills/{read-pdf → brand-assets}/tsconfig.json +0 -0
package/bin/worker.js CHANGED
@@ -9724,7 +9724,7 @@ var require_es5 = __commonJS((exports, module) => {
9724
9724
 
9725
9725
  // node_modules/@aws-sdk/core/dist-cjs/submodules/client/index.js
9726
9726
  var require_client2 = __commonJS((exports) => {
9727
- var __dirname = "/home/hasna/.hasna/repos/worktrees/skills-release-0159/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
9727
+ var __dirname = "/tmp/cossus-skills-release-85552597/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
9728
9728
  var { Retry, RETRY_MODES } = require_retry();
9729
9729
  var { HttpRequest, parseUrl } = require_protocols();
9730
9730
  var { InvokeStore } = require_invoke_store();
@@ -20671,7 +20671,7 @@ var init_dist_es9 = __esm(() => {
20671
20671
  });
20672
20672
 
20673
20673
  // src/server/worker.ts
20674
- import { randomUUID as randomUUID2 } from "crypto";
20674
+ import { randomUUID as randomUUID4 } from "crypto";
20675
20675
 
20676
20676
  // node_modules/@aws-sdk/checksums/dist-cjs/submodules/flexible-checksums/index.js
20677
20677
  var { setFeature } = require_client2();
@@ -30259,6 +30259,10 @@ class S3Client extends import_client24.Client {
30259
30259
  }
30260
30260
  }
30261
30261
 
30262
+ // node_modules/@aws-sdk/client-s3/dist-es/commands/DeleteObjectCommand.js
30263
+ class DeleteObjectCommand extends command(_ep0, _mw0, "DeleteObject", DeleteObject$) {
30264
+ }
30265
+
30262
30266
  // node_modules/@aws-sdk/client-s3/dist-es/commands/GetObjectCommand.js
30263
30267
  class GetObjectCommand extends command(_ep0, _mw7, "GetObject", GetObject$) {
30264
30268
  }
@@ -30267,7 +30271,137 @@ class GetObjectCommand extends command(_ep0, _mw7, "GetObject", GetObject$) {
30267
30271
  class PutObjectCommand extends command(_ep0, _mw11, "PutObject", PutObject$) {
30268
30272
  }
30269
30273
 
30274
+ // src/lib/skill-bundle.ts
30275
+ var ANY_SEGMENT_EXCLUDES = new Set([
30276
+ ".git",
30277
+ ".ds_store",
30278
+ ".system",
30279
+ "node_modules",
30280
+ ".aws",
30281
+ ".ssh",
30282
+ ".gnupg",
30283
+ ".docker"
30284
+ ]);
30285
+ var ROOT_EXCLUDES = new Set(["dist", "build", ".turbo"]);
30286
+ var CREDENTIAL_FILENAMES = new Set([
30287
+ ".npmrc",
30288
+ ".pypirc",
30289
+ ".netrc",
30290
+ ".envrc",
30291
+ ".pgpass",
30292
+ ".git-credentials",
30293
+ "credentials",
30294
+ "id_rsa",
30295
+ "id_dsa",
30296
+ "id_ecdsa",
30297
+ "id_ed25519"
30298
+ ]);
30299
+ var ENV_TEMPLATE_NAMES = new Set([".env.example", ".env.sample", ".env.template", ".env.dist"]);
30300
+ var NON_DOTENV_EXTENSIONS = new Set([
30301
+ "ts",
30302
+ "tsx",
30303
+ "mts",
30304
+ "cts",
30305
+ "js",
30306
+ "jsx",
30307
+ "mjs",
30308
+ "cjs",
30309
+ "json",
30310
+ "jsonc",
30311
+ "json5",
30312
+ "py",
30313
+ "rb",
30314
+ "go",
30315
+ "rs",
30316
+ "java",
30317
+ "kt",
30318
+ "kts",
30319
+ "swift",
30320
+ "c",
30321
+ "h",
30322
+ "cc",
30323
+ "cpp",
30324
+ "hpp",
30325
+ "cs",
30326
+ "php",
30327
+ "sh",
30328
+ "bash",
30329
+ "zsh",
30330
+ "fish",
30331
+ "ps1",
30332
+ "bat",
30333
+ "cmd",
30334
+ "lua",
30335
+ "pl",
30336
+ "pm",
30337
+ "r",
30338
+ "jl",
30339
+ "dart",
30340
+ "ex",
30341
+ "exs",
30342
+ "scala",
30343
+ "clj",
30344
+ "cljs",
30345
+ "groovy",
30346
+ "gradle",
30347
+ "vb",
30348
+ "fs",
30349
+ "yaml",
30350
+ "yml",
30351
+ "toml",
30352
+ "ini",
30353
+ "xml",
30354
+ "csv",
30355
+ "tsv",
30356
+ "html",
30357
+ "htm",
30358
+ "css",
30359
+ "scss",
30360
+ "sass",
30361
+ "less",
30362
+ "md",
30363
+ "mdx",
30364
+ "txt",
30365
+ "rst",
30366
+ "adoc",
30367
+ "sql",
30368
+ "graphql",
30369
+ "gql",
30370
+ "proto",
30371
+ "d",
30372
+ "png",
30373
+ "jpg",
30374
+ "jpeg",
30375
+ "gif",
30376
+ "svg",
30377
+ "webp",
30378
+ "ico",
30379
+ "bmp",
30380
+ "pdf",
30381
+ "woff",
30382
+ "woff2",
30383
+ "ttf",
30384
+ "otf",
30385
+ "eot",
30386
+ "mp3",
30387
+ "mp4",
30388
+ "wav",
30389
+ "webm",
30390
+ "zip",
30391
+ "gz",
30392
+ "tar",
30393
+ "wasm"
30394
+ ]);
30395
+ function ownBytes(view) {
30396
+ const source = view instanceof ArrayBuffer ? new Uint8Array(view) : view;
30397
+ const out = new Uint8Array(new ArrayBuffer(source.byteLength));
30398
+ out.set(source);
30399
+ return out;
30400
+ }
30401
+
30270
30402
  // src/server/artifact-storage.ts
30403
+ var SHA256_HEX = /^[0-9a-f]{64}$/;
30404
+
30271
30405
  class ArtifactStorage {
30272
30406
  bucket;
30273
30407
  prefix;
@@ -30312,10 +30446,74 @@ class ArtifactStorage {
30312
30446
  }));
30313
30447
  return await bodyToText(response.Body);
30314
30448
  }
30449
+ async putBundle(orgId, sha256, bytes, contentType = "application/gzip") {
30450
+ assertSha256(sha256);
30451
+ if (!this.bucket)
30452
+ return { storageKind: "db", bytes };
30453
+ const key = this.bundleKeyFor(orgId, sha256);
30454
+ await this.s3.send(new PutObjectCommand({
30455
+ Bucket: this.bucket,
30456
+ Key: key,
30457
+ Body: bytes,
30458
+ ContentType: contentType
30459
+ }));
30460
+ return { storageKind: "s3", storageKey: key };
30461
+ }
30462
+ async readBundle(bundle) {
30463
+ if (bundle.storageKind === "db")
30464
+ return bundle.bytes ?? null;
30465
+ if (!this.bucket || !this.s3 || !bundle.storageKey)
30466
+ return null;
30467
+ const response = await this.s3.send(new GetObjectCommand({
30468
+ Bucket: this.bucket,
30469
+ Key: bundle.storageKey
30470
+ }));
30471
+ return await bodyToBytes(response.Body);
30472
+ }
30473
+ async deleteBundle(orgId, sha256) {
30474
+ if (!this.bucket || !this.s3)
30475
+ return;
30476
+ assertSha256(sha256);
30477
+ await this.s3.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: this.bundleKeyFor(orgId, sha256) }));
30478
+ }
30315
30479
  keyFor(run, relativePath) {
30316
30480
  const safeRelativePath = relativePath.replace(/^\/+/, "").replace(/\.\.(?:\/|$)/g, "");
30317
30481
  return `${this.prefix}/${run.orgId}/${run.id}/${safeRelativePath}`;
30318
30482
  }
30483
+ bundleKeyFor(orgId, sha256) {
30484
+ return `${this.prefix}/bundles/${encodeURIComponent(orgId)}/${sha256}.tar.gz`;
30485
+ }
30486
+ }
30487
+ function assertSha256(value) {
30488
+ if (!SHA256_HEX.test(value)) {
30489
+ throw new Error("bundle digest must be a lowercase hex sha-256; refusing to build a storage key from it");
30490
+ }
30491
+ }
30492
+ async function bodyToBytes(body) {
30493
+ if (!body)
30494
+ return ownBytes(new Uint8Array(0));
30495
+ if (body instanceof Uint8Array)
30496
+ return ownBytes(body);
30497
+ if (typeof body.transformToByteArray === "function") {
30498
+ return ownBytes(await body.transformToByteArray());
30499
+ }
30500
+ if (typeof body.getReader === "function") {
30501
+ const reader = body.getReader();
30502
+ const chunks2 = [];
30503
+ while (true) {
30504
+ const { value, done } = await reader.read();
30505
+ if (done)
30506
+ break;
30507
+ if (value)
30508
+ chunks2.push(value);
30509
+ }
30510
+ return concat(chunks2);
30511
+ }
30512
+ const chunks = [];
30513
+ for await (const chunk of body) {
30514
+ chunks.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
30515
+ }
30516
+ return concat(chunks);
30319
30517
  }
30320
30518
  async function bodyToText(body) {
30321
30519
  if (!body)
@@ -30347,7 +30545,7 @@ async function bodyToText(body) {
30347
30545
  }
30348
30546
  function concat(chunks) {
30349
30547
  const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
30350
- const merged = new Uint8Array(total);
30548
+ const merged = new Uint8Array(new ArrayBuffer(total));
30351
30549
  let offset = 0;
30352
30550
  for (const chunk of chunks) {
30353
30551
  merged.set(chunk, offset);
@@ -30356,23 +30554,89 @@ function concat(chunks) {
30356
30554
  return merged;
30357
30555
  }
30358
30556
 
30557
+ // src/server/auth.ts
30558
+ import { createHash as createHash3 } from "crypto";
30559
+ function hashApiKey(token) {
30560
+ return createHash3("sha256").update(token).digest("hex");
30561
+ }
30562
+ function publicPrincipal(partial = {}) {
30563
+ return {
30564
+ apiKeyId: partial.apiKeyId || "key_dev",
30565
+ orgId: partial.orgId || "org_dev",
30566
+ orgSlug: partial.orgSlug || "dev",
30567
+ orgName: partial.orgName || "Development",
30568
+ userId: partial.userId || "user_dev",
30569
+ email: partial.email || "dev@example.com",
30570
+ role: partial.role || "owner",
30571
+ scopes: partial.scopes || ["skills:read", "runs:write"]
30572
+ };
30573
+ }
30574
+
30575
+ // src/lib/retired-settings.ts
30576
+ var RETIRED_ENV_SUFFIXES = ["_STORAGE_MODE", "_DEPLOYMENT_MODE", "_CLOUD_MODE"];
30577
+ class RetiredSettingError extends Error {
30578
+ code = "RETIRED_SETTING";
30579
+ setting;
30580
+ constructor(setting, message) {
30581
+ super(message);
30582
+ this.name = "RetiredSettingError";
30583
+ this.setting = setting;
30584
+ }
30585
+ }
30586
+ function isRetiredModeEnvVar(name, app) {
30587
+ const upper = name.toUpperCase();
30588
+ if (!upper.includes(app.toUpperCase()))
30589
+ return false;
30590
+ return RETIRED_ENV_SUFFIXES.some((suffix) => upper.endsWith(suffix));
30591
+ }
30592
+ function findRetiredModeEnvVars(env, app) {
30593
+ const found = [];
30594
+ for (const [name, value] of Object.entries(env)) {
30595
+ if (value === undefined || value === "")
30596
+ continue;
30597
+ if (isRetiredModeEnvVar(name, app))
30598
+ found.push({ name, value });
30599
+ }
30600
+ return found.sort((a3, b3) => a3.name.localeCompare(b3.name));
30601
+ }
30602
+ function assertNoRetiredModeEnvVars(env, options) {
30603
+ const found = findRetiredModeEnvVars(env, options.app);
30604
+ if (found.length === 0)
30605
+ return;
30606
+ const names = found.map((entry) => entry.name);
30607
+ throw new RetiredSettingError(names[0], `${names.join(", ")} ${names.length === 1 ? "is" : "are"} no longer read. ` + "Deployment modes were removed: where a server keeps its data is decided by the " + `database it is given, not by a declared label. Set ${options.replacement} to a ` + "postgres:// URL to use PostgreSQL, or leave it unset for the on-box SQLite database. " + `Then unset ${names.join(" and ")}. ` + "Refused rather than ignored, because a discarded setting looks exactly like a " + "working one until something needs the data.");
30608
+ }
30609
+
30359
30610
  // src/server/config.ts
30360
- var DEFAULT_SELF_HOSTED_API_URL = "https://skills.md";
30611
+ var DATABASE_URL_ENV = "HASNA_SKILLS_DATABASE_URL";
30612
+ var SKILLS_ENV_NAMESPACE = "SKILLS";
30361
30613
  function resolveServerConfig(env = process.env) {
30614
+ assertNoRetiredModeEnvVars(env, {
30615
+ app: SKILLS_ENV_NAMESPACE,
30616
+ replacement: DATABASE_URL_ENV
30617
+ });
30362
30618
  const nodeEnv = env.NODE_ENV || "development";
30619
+ const host = env.HOST || env.SKILLS_HOST || "0.0.0.0";
30620
+ const port = parsePositiveInt(env.PORT || env.SKILLS_PORT, 8787);
30363
30621
  return {
30364
- host: env.HOST || env.SKILLS_HOST || "0.0.0.0",
30365
- port: parsePositiveInt(env.PORT || env.SKILLS_PORT, 8787),
30366
- databaseUrl: env.HASNA_SKILLS_DATABASE_URL || env.DATABASE_URL || undefined,
30622
+ host,
30623
+ port,
30624
+ databaseUrl: env[DATABASE_URL_ENV] || env.DATABASE_URL || undefined,
30367
30625
  bootstrapApiKey: env.HASNA_SKILLS_BOOTSTRAP_API_KEY || undefined,
30368
30626
  artifactBucket: env.HASNA_SKILLS_S3_BUCKET || env.SKILLS_S3_BUCKET || undefined,
30369
30627
  artifactPrefix: normalizePrefix(env.HASNA_SKILLS_S3_PREFIX || env.SKILLS_S3_PREFIX || "skills/artifacts"),
30370
30628
  inlineWorker: env.HASNA_SKILLS_INLINE_WORKER === "1",
30371
30629
  requestBodyLimitBytes: parsePositiveInt(env.HASNA_SKILLS_REQUEST_BODY_LIMIT_BYTES, 1e6),
30372
- publicBaseUrl: (env.SKILLS_PUBLIC_BASE_URL || DEFAULT_SELF_HOSTED_API_URL).replace(/\/+$/, ""),
30373
- nodeEnv
30630
+ skillBundleLimitBytes: parsePositiveInt(env.HASNA_SKILLS_BUNDLE_LIMIT_BYTES, 25000000),
30631
+ publicBaseUrl: (env.SKILLS_PUBLIC_BASE_URL || localOrigin(host, port)).replace(/\/+$/, ""),
30632
+ nodeEnv,
30633
+ allowEphemeralStore: env.HASNA_SKILLS_ALLOW_EPHEMERAL_STORE === "1"
30374
30634
  };
30375
30635
  }
30636
+ function localOrigin(host, port) {
30637
+ const hostname = host === "0.0.0.0" || host === "::" ? "localhost" : host;
30638
+ return `http://${hostname.includes(":") ? `[${hostname}]` : hostname}:${port}`;
30639
+ }
30376
30640
  function parsePositiveInt(value, fallback) {
30377
30641
  const parsed = Number.parseInt(value ?? "", 10);
30378
30642
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
@@ -30381,78 +30645,772 @@ function normalizePrefix(value) {
30381
30645
  return value.replace(/^\/+|\/+$/g, "") || "skills/artifacts";
30382
30646
  }
30383
30647
 
30384
- // src/server/handlers.ts
30385
- import { createHash as createHash4 } from "crypto";
30648
+ // src/server/database-url.ts
30649
+ import { isAbsolute, join as join3 } from "path";
30650
+ import { fileURLToPath } from "url";
30386
30651
 
30387
- // src/server/store.ts
30388
- import { randomUUID } from "crypto";
30652
+ // src/lib/config.ts
30653
+ import { existsSync, readFileSync as readFileSync2, writeFileSync, mkdirSync, copyFileSync, readdirSync, statSync } from "fs";
30654
+ import { join as join2, dirname as dirname2 } from "path";
30655
+ import { homedir as homedir2 } from "os";
30656
+ function mergeDirectoryContents(sourceDir, targetDir) {
30657
+ if (!existsSync(sourceDir))
30658
+ return;
30659
+ mkdirSync(targetDir, { recursive: true });
30660
+ for (const entry of readdirSync(sourceDir)) {
30661
+ const sourcePath = join2(sourceDir, entry);
30662
+ const targetPath = join2(targetDir, entry);
30663
+ try {
30664
+ const sourceStat = statSync(sourcePath);
30665
+ if (sourceStat.isDirectory()) {
30666
+ mergeDirectoryContents(sourcePath, targetPath);
30667
+ continue;
30668
+ }
30669
+ if (!existsSync(targetPath))
30670
+ copyFileSync(sourcePath, targetPath);
30671
+ } catch {}
30672
+ }
30673
+ }
30674
+ var DATA_DIR_ENV = "HASNA_SKILLS_DIR";
30675
+ function getDataDir() {
30676
+ const override = process.env[DATA_DIR_ENV];
30677
+ if (override) {
30678
+ try {
30679
+ mkdirSync(override, { recursive: true });
30680
+ } catch {}
30681
+ return override;
30682
+ }
30683
+ const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
30684
+ const newDir = join2(home, ".hasna", "skills");
30685
+ const oldDir = join2(home, ".skills");
30686
+ const oldConfigFile = join2(home, ".skillsrc");
30687
+ mkdirSync(newDir, { recursive: true });
30688
+ try {
30689
+ mergeDirectoryContents(oldDir, newDir);
30690
+ } catch {}
30691
+ if (existsSync(oldConfigFile) && !existsSync(join2(newDir, "config.json"))) {
30692
+ try {
30693
+ copyFileSync(oldConfigFile, join2(newDir, "config.json"));
30694
+ } catch {}
30695
+ }
30696
+ return newDir;
30697
+ }
30389
30698
 
30390
- // src/server/auth.ts
30391
- import { createHash as createHash3 } from "crypto";
30392
- function hashApiKey(token) {
30393
- return createHash3("sha256").update(token).digest("hex");
30699
+ // src/server/database-url.ts
30700
+ var DEFAULT_SQLITE_FILENAME = "server.db";
30701
+ var SQLITE_MEMORY_PATH = ":memory:";
30702
+ var POSTGRES_SCHEMES = new Set(["postgres", "postgresql"]);
30703
+ var SQLITE_SCHEMES = new Set(["sqlite", "sqlite3", "file"]);
30704
+ var MEMORY_SCHEMES = new Set(["memory"]);
30705
+ var SQLITE_EXTENSIONS = [".db", ".sqlite", ".sqlite3", ".db3"];
30706
+ function defaultSqlitePath() {
30707
+ return join3(getDataDir(), DEFAULT_SQLITE_FILENAME);
30394
30708
  }
30395
- function publicPrincipal(partial = {}) {
30396
- return {
30397
- apiKeyId: partial.apiKeyId || "key_dev",
30398
- orgId: partial.orgId || "org_dev",
30399
- orgSlug: partial.orgSlug || "dev",
30400
- orgName: partial.orgName || "Development",
30401
- userId: partial.userId || "user_dev",
30402
- email: partial.email || "dev@example.com",
30403
- role: partial.role || "owner",
30404
- scopes: partial.scopes || ["skills:read", "runs:write"]
30405
- };
30709
+ function resolveDatabaseTarget(raw) {
30710
+ const value = raw?.trim();
30711
+ if (!value) {
30712
+ const path = defaultSqlitePath();
30713
+ return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
30714
+ }
30715
+ if (value === SQLITE_MEMORY_PATH) {
30716
+ return { kind: "sqlite", path: SQLITE_MEMORY_PATH, durable: false, label: "sqlite (in-memory)" };
30717
+ }
30718
+ const schemeMatch = value.match(/^([a-z][a-z0-9+.-]+):/i);
30719
+ const scheme = schemeMatch?.[1]?.toLowerCase();
30720
+ if (scheme && POSTGRES_SCHEMES.has(scheme)) {
30721
+ return { kind: "postgres", url: value, durable: true, label: "postgres" };
30722
+ }
30723
+ if (scheme && MEMORY_SCHEMES.has(scheme)) {
30724
+ return { kind: "memory", durable: false, label: "memory (non-durable)" };
30725
+ }
30726
+ if (scheme && SQLITE_SCHEMES.has(scheme)) {
30727
+ const path = sqlitePathFromUrl(value, scheme);
30728
+ return path === SQLITE_MEMORY_PATH ? { kind: "sqlite", path, durable: false, label: "sqlite (in-memory)" } : { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
30729
+ }
30730
+ if (scheme) {
30731
+ throw new Error(`unsupported database scheme "${scheme}:". Supported: postgres://, postgresql://, sqlite:, file:, ` + `an absolute or relative path to a .db/.sqlite file, ":memory:", or "memory:" (non-durable, tests only). ` + `Leave the setting empty to use the default SQLite database at ${defaultSqlitePath()}.`);
30732
+ }
30733
+ if (looksLikeSqlitePath(value)) {
30734
+ const path = isAbsolute(value) ? value : join3(process.cwd(), value);
30735
+ return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
30736
+ }
30737
+ throw new Error(`could not resolve a database backend from "${value}". Use postgres://\u2026, sqlite:\u2026, an absolute or ` + `relative path ending in ${SQLITE_EXTENSIONS.join("/")}, ":memory:", or leave it empty for the ` + `default SQLite database at ${defaultSqlitePath()}.`);
30406
30738
  }
30739
+ function sqlitePathFromUrl(value, scheme) {
30740
+ const rest = value.slice(scheme.length + 1).replace(/[?#].*$/, "");
30741
+ if (rest.startsWith(SQLITE_MEMORY_PATH))
30742
+ return SQLITE_MEMORY_PATH;
30743
+ if (rest === "" || rest === "//") {
30744
+ throw new Error(`"${value}" names no database file. Give a path (${scheme}:///var/lib/skills/server.db), ` + `or ":memory:" if a non-durable database is genuinely what you want. ` + "An empty path here usually means an unset variable in a templated URL.");
30745
+ }
30746
+ if (rest.startsWith("//")) {
30747
+ if (!rest.startsWith("///")) {
30748
+ const authority = rest.slice(2).split("/")[0];
30749
+ throw new Error(`"${value}" has a host ("${authority}") where a path was expected. Remote SQLite files are not a thing; ` + `for an absolute path use ${scheme}:///${rest.slice(2)}, and for a relative one use ${scheme}:${rest.slice(2)}.`);
30750
+ }
30751
+ if (scheme === "file") {
30752
+ try {
30753
+ return fileURLToPath(new URL(value));
30754
+ } catch {}
30755
+ }
30756
+ return rest.slice(2).replace(/^\/\/+/, "/");
30757
+ }
30758
+ return isAbsolute(rest) ? rest : join3(process.cwd(), rest);
30759
+ }
30760
+ function looksLikeSqlitePath(value) {
30761
+ if (value.includes("/"))
30762
+ return true;
30763
+ return SQLITE_EXTENSIONS.some((extension) => value.toLowerCase().endsWith(extension));
30764
+ }
30765
+
30766
+ // src/server/handlers.ts
30767
+ import { createHash as createHash4 } from "crypto";
30407
30768
 
30408
30769
  // src/server/store.ts
30409
- function resolvePoolMax(env = process.env) {
30410
- const parsed = Number.parseInt(env.HASNA_SKILLS_DATABASE_POOL_MAX || env.SKILLS_DATABASE_POOL_MAX || "", 10);
30411
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 4;
30412
- }
30770
+ import { randomUUID as randomUUID3 } from "crypto";
30771
+
30772
+ // src/server/rows.ts
30773
+ import { randomUUID } from "crypto";
30413
30774
  function nowIso() {
30414
30775
  return new Date().toISOString();
30415
30776
  }
30777
+ function normalizeLimit(limit) {
30778
+ return Number.isFinite(limit) ? Math.max(0, Math.trunc(limit)) : 0;
30779
+ }
30416
30780
  function runId() {
30417
30781
  return `run_${Date.now().toString(36)}_${randomUUID().slice(0, 8)}`;
30418
30782
  }
30419
30783
  function artifactId() {
30420
30784
  return `art_${randomUUID().replace(/-/g, "").slice(0, 20)}`;
30421
30785
  }
30422
- function createArtifactId() {
30423
- return artifactId();
30786
+ function rowToRun(row) {
30787
+ return {
30788
+ id: String(row.id),
30789
+ orgId: String(row.org_id),
30790
+ userId: String(row.user_id),
30791
+ skill: String(row.skill_slug),
30792
+ requestedSlug: String(row.requested_slug),
30793
+ status: String(row.status),
30794
+ input: parseJsonObject(row.input_json),
30795
+ args: parseJsonArray(row.args_json),
30796
+ ...typeof row.idempotency_key === "string" ? { idempotencyKey: row.idempotency_key } : {},
30797
+ correlationId: String(row.correlation_id),
30798
+ costCents: Number(row.cost_cents ?? 0),
30799
+ ...typeof row.output_type === "string" ? { outputType: row.output_type } : {},
30800
+ ...typeof row.output_preview === "string" ? { outputPreview: row.output_preview } : {},
30801
+ ...typeof row.error_code === "string" ? { errorCode: row.error_code } : {},
30802
+ ...typeof row.error_message === "string" ? { errorMessage: row.error_message } : {},
30803
+ createdAt: dateString(row.created_at),
30804
+ ...row.started_at ? { startedAt: dateString(row.started_at) } : {},
30805
+ ...row.completed_at ? { completedAt: dateString(row.completed_at) } : {}
30806
+ };
30424
30807
  }
30425
- async function createStore(options = {}) {
30426
- const store = options.databaseUrl ? new PostgresSkillsStore(options.databaseUrl) : new MemorySkillsStore;
30427
- if (options.bootstrapApiKey && store.ensureBootstrapApiKey) {
30428
- await store.ensureBootstrapApiKey(options.bootstrapApiKey);
30808
+ function rowToLog(row) {
30809
+ return {
30810
+ runId: String(row.run_id),
30811
+ sequence: Number(row.sequence),
30812
+ level: String(row.level),
30813
+ message: String(row.message),
30814
+ createdAt: dateString(row.created_at)
30815
+ };
30816
+ }
30817
+ function rowToArtifact(row) {
30818
+ return {
30819
+ id: String(row.id),
30820
+ runId: String(row.run_id),
30821
+ orgId: String(row.org_id),
30822
+ fileName: String(row.file_name),
30823
+ relativePath: String(row.relative_path),
30824
+ contentType: String(row.content_type),
30825
+ byteSize: Number(row.byte_size),
30826
+ sha256: String(row.sha256),
30827
+ storageKind: String(row.storage_kind),
30828
+ ...typeof row.storage_key === "string" ? { storageKey: row.storage_key } : {},
30829
+ ...typeof row.body_text === "string" ? { bodyText: row.body_text } : {},
30830
+ createdAt: dateString(row.created_at)
30831
+ };
30832
+ }
30833
+ function rowToSkill(row) {
30834
+ return {
30835
+ orgId: String(row.org_id),
30836
+ slug: String(row.slug),
30837
+ displayName: String(row.display_name),
30838
+ description: String(row.description ?? ""),
30839
+ category: String(row.category),
30840
+ tags: parseJsonArray(row.tags_json),
30841
+ source: String(row.source),
30842
+ kind: String(row.kind) === "instruction" ? "instruction" : "executable",
30843
+ ...typeof row.version === "string" ? { version: row.version } : {},
30844
+ ...typeof row.skill_md === "string" ? { skillMd: row.skill_md } : {},
30845
+ ...typeof row.bundle_sha256 === "string" ? { bundleSha256: row.bundle_sha256 } : {},
30846
+ ...row.bundle_byte_size === null || row.bundle_byte_size === undefined ? {} : { bundleByteSize: Number(row.bundle_byte_size) },
30847
+ ...typeof row.published_by_user_id === "string" ? { publishedByUserId: row.published_by_user_id } : {},
30848
+ createdAt: dateString(row.created_at),
30849
+ updatedAt: dateString(row.updated_at)
30850
+ };
30851
+ }
30852
+ function rowToSkillBundle(row) {
30853
+ return {
30854
+ orgId: String(row.org_id),
30855
+ sha256: String(row.sha256),
30856
+ byteSize: Number(row.byte_size),
30857
+ contentType: String(row.content_type),
30858
+ storageKind: String(row.storage_kind),
30859
+ ...typeof row.storage_key === "string" ? { storageKey: row.storage_key } : {},
30860
+ ...toBytes(row.body_blob) ? { bytes: toBytes(row.body_blob) } : {},
30861
+ createdAt: dateString(row.created_at)
30862
+ };
30863
+ }
30864
+ function toBytes(value) {
30865
+ if (value == null)
30866
+ return null;
30867
+ if (value instanceof Uint8Array)
30868
+ return ownBytes(value);
30869
+ if (value instanceof ArrayBuffer)
30870
+ return ownBytes(value);
30871
+ return null;
30872
+ }
30873
+ function parseJsonObject(value) {
30874
+ if (value && typeof value === "object" && !Array.isArray(value))
30875
+ return value;
30876
+ if (typeof value === "string") {
30877
+ try {
30878
+ const parsed = JSON.parse(value);
30879
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
30880
+ } catch {}
30429
30881
  }
30430
- return store;
30882
+ return {};
30883
+ }
30884
+ function parseJsonArray(value) {
30885
+ const parsed = typeof value === "string" ? safeParse(value) : value;
30886
+ return Array.isArray(parsed) ? parsed.map(String) : [];
30887
+ }
30888
+ function safeParse(value) {
30889
+ try {
30890
+ return JSON.parse(value);
30891
+ } catch {
30892
+ return;
30893
+ }
30894
+ }
30895
+ function dateString(value) {
30896
+ if (value instanceof Date)
30897
+ return value.toISOString();
30898
+ return String(value);
30431
30899
  }
30432
30900
 
30433
- class MemorySkillsStore {
30434
- apiKeys = new Map;
30435
- runs = new Map;
30436
- logs = new Map;
30437
- artifacts = new Map;
30438
- idempotency = new Map;
30439
- constructor(apiKeys = []) {
30440
- for (const key of apiKeys)
30441
- this.addApiKey(key.token, key.principal);
30901
+ // src/server/sqlite-store.ts
30902
+ import { Database } from "bun:sqlite";
30903
+ import { randomUUID as randomUUID2 } from "crypto";
30904
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
30905
+ import { dirname as dirname4, join as join5 } from "path";
30906
+
30907
+ // src/server/migrations-dir.ts
30908
+ import { existsSync as existsSync2 } from "fs";
30909
+ import { dirname as dirname3, join as join4 } from "path";
30910
+ var MIGRATION_DIALECTS = ["postgres", "sqlite"];
30911
+ var MAX_WALK_UP = 6;
30912
+ function findMigrationsRoot(startDirs = defaultStartDirs()) {
30913
+ for (const start of startDirs) {
30914
+ let dir = start;
30915
+ for (let level = 0;level < MAX_WALK_UP; level += 1) {
30916
+ const candidate = join4(dir, "migrations");
30917
+ if (MIGRATION_DIALECTS.some((dialect) => existsSync2(join4(candidate, dialect))))
30918
+ return candidate;
30919
+ const parent = dirname3(dir);
30920
+ if (parent === dir)
30921
+ break;
30922
+ dir = parent;
30923
+ }
30442
30924
  }
30443
- addApiKey(token, principal) {
30444
- const resolved = publicPrincipal(principal);
30445
- this.apiKeys.set(hashApiKey(token), resolved);
30446
- return resolved;
30925
+ return null;
30926
+ }
30927
+ function resolveMigrationsDir(dialect, root3 = findMigrationsRoot()) {
30928
+ if (!root3) {
30929
+ throw new Error(`could not locate the migrations directory for dialect "${dialect}". ` + `Expected a migrations/${dialect}/ folder alongside the package root.`);
30930
+ }
30931
+ const dir = join4(root3, dialect);
30932
+ if (!existsSync2(dir)) {
30933
+ throw new Error(`migrations directory not found: ${dir}`);
30934
+ }
30935
+ return dir;
30936
+ }
30937
+ function defaultStartDirs() {
30938
+ const dirs = [import.meta.dir];
30939
+ const cwd = process.cwd();
30940
+ if (cwd && cwd !== import.meta.dir)
30941
+ dirs.push(cwd);
30942
+ return dirs;
30943
+ }
30944
+
30945
+ // src/server/sqlite-store.ts
30946
+ var CLAIM_ATTEMPTS = 8;
30947
+ var CLAIMABLE_STATUSES = ["queued", "retrying"];
30948
+ var LAST_USED_RESOLUTION_MS = 60000;
30949
+
30950
+ class SqliteSkillsStore {
30951
+ backend;
30952
+ db;
30953
+ closed = false;
30954
+ constructor(path = SQLITE_MEMORY_PATH, options = {}) {
30955
+ const inMemory = path === SQLITE_MEMORY_PATH;
30956
+ if (!inMemory)
30957
+ mkdirSync2(dirname4(path), { recursive: true });
30958
+ this.db = openDatabase(path);
30959
+ this.db.exec(`PRAGMA busy_timeout = ${Math.max(0, options.busyTimeoutMs ?? 5000)}`);
30960
+ if (!inMemory)
30961
+ enableWalMode(this.db);
30962
+ this.db.exec("PRAGMA foreign_keys = ON");
30963
+ this.db.exec("PRAGMA synchronous = NORMAL");
30964
+ if (options.migrate !== false) {
30965
+ applySqliteMigrations(this.db, options.migrationsDir);
30966
+ }
30967
+ this.backend = {
30968
+ kind: "sqlite",
30969
+ durable: !inMemory,
30970
+ label: inMemory ? "sqlite (in-memory)" : `sqlite (${path})`
30971
+ };
30972
+ }
30973
+ get database() {
30974
+ return this.db;
30975
+ }
30976
+ async close() {
30977
+ if (this.closed)
30978
+ return;
30979
+ this.closed = true;
30980
+ this.db.close(false);
30447
30981
  }
30448
30982
  async ensureBootstrapApiKey(token, principal) {
30449
- this.addApiKey(token, principal);
30983
+ const resolved = publicPrincipal(principal);
30984
+ this.db.transaction(() => {
30985
+ this.db.run(`INSERT INTO organizations (id, slug, name) VALUES (?, ?, ?)
30986
+ ON CONFLICT (id) DO UPDATE SET slug = excluded.slug, name = excluded.name`, [resolved.orgId, resolved.orgSlug, resolved.orgName]);
30987
+ this.db.run(`INSERT INTO users (id, email, name) VALUES (?, ?, ?)
30988
+ ON CONFLICT (id) DO UPDATE SET email = excluded.email`, [resolved.userId, resolved.email, resolved.email]);
30989
+ this.db.run(`INSERT INTO organization_members (org_id, user_id, role) VALUES (?, ?, ?)
30990
+ ON CONFLICT (org_id, user_id) DO UPDATE SET role = excluded.role`, [resolved.orgId, resolved.userId, resolved.role]);
30991
+ this.db.run(`INSERT INTO api_keys (id, org_id, user_id, name, key_hash, scopes_json)
30992
+ VALUES (?, ?, ?, ?, ?, ?)
30993
+ ON CONFLICT (key_hash) DO NOTHING`, [resolved.apiKeyId, resolved.orgId, resolved.userId, "bootstrap", hashApiKey(token), JSON.stringify(resolved.scopes)]);
30994
+ })();
30450
30995
  }
30451
30996
  async authenticateApiKeyHash(hash) {
30452
- return this.apiKeys.get(hash) ?? null;
30453
- }
30454
- async createRun(input) {
30455
- const idemKey = input.idempotencyKey?.trim();
30997
+ const row = this.get(`SELECT k.id AS api_key_id, k.scopes_json, k.last_used_at, o.id AS org_id, o.slug AS org_slug, o.name AS org_name,
30998
+ u.id AS user_id, u.email, m.role
30999
+ FROM api_keys k
31000
+ JOIN organizations o ON o.id = k.org_id
31001
+ JOIN users u ON u.id = k.user_id
31002
+ LEFT JOIN organization_members m ON m.org_id = k.org_id AND m.user_id = k.user_id
31003
+ WHERE k.key_hash = ? AND k.revoked_at IS NULL
31004
+ LIMIT 1`, [hash]);
31005
+ if (!row)
31006
+ return null;
31007
+ const lastUsed = typeof row.last_used_at === "string" ? Date.parse(row.last_used_at) : Number.NaN;
31008
+ if (!Number.isFinite(lastUsed) || Date.now() - lastUsed >= LAST_USED_RESOLUTION_MS) {
31009
+ this.db.run("UPDATE api_keys SET last_used_at = ? WHERE id = ?", [nowIso(), String(row.api_key_id)]);
31010
+ }
31011
+ return {
31012
+ apiKeyId: String(row.api_key_id),
31013
+ orgId: String(row.org_id),
31014
+ orgSlug: String(row.org_slug),
31015
+ orgName: String(row.org_name),
31016
+ userId: String(row.user_id),
31017
+ email: String(row.email),
31018
+ role: typeof row.role === "string" ? row.role : "member",
31019
+ scopes: parseScopes(row.scopes_json)
31020
+ };
31021
+ }
31022
+ async createRun(input) {
31023
+ if (input.idempotencyKey) {
31024
+ const existing = this.get("SELECT * FROM skills_runs WHERE org_id = ? AND idempotency_key = ? LIMIT 1", [input.principal.orgId, input.idempotencyKey]);
31025
+ if (existing)
31026
+ return rowToRun(existing);
31027
+ }
31028
+ const row = this.get(`INSERT INTO skills_runs (id, org_id, user_id, skill_slug, requested_slug, status, input_json, args_json, idempotency_key, correlation_id, created_at)
31029
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
31030
+ RETURNING *`, [
31031
+ runId(),
31032
+ input.principal.orgId,
31033
+ input.principal.userId,
31034
+ input.slug,
31035
+ input.slug,
31036
+ "queued",
31037
+ JSON.stringify(input.input),
31038
+ JSON.stringify(input.args),
31039
+ input.idempotencyKey ?? null,
31040
+ randomUUID2(),
31041
+ nowIso()
31042
+ ]);
31043
+ return rowToRun(row);
31044
+ }
31045
+ async listRuns(principal, limit) {
31046
+ return this.all("SELECT * FROM skills_runs WHERE org_id = ? ORDER BY created_at DESC, rowid DESC LIMIT ?", [principal.orgId, normalizeLimit(limit)]).map(rowToRun);
31047
+ }
31048
+ async getRun(principal, id) {
31049
+ const row = this.get("SELECT * FROM skills_runs WHERE id = ? AND org_id = ? LIMIT 1", [id, principal.orgId]);
31050
+ return row ? rowToRun(row) : null;
31051
+ }
31052
+ async claimNextRun(input) {
31053
+ const lost = new Set;
31054
+ for (let attempt = 0;attempt < CLAIM_ATTEMPTS; attempt += 1) {
31055
+ const claimed = this.claimOnce(input.workerId, lost);
31056
+ if (claimed === "empty")
31057
+ return null;
31058
+ if (claimed)
31059
+ return claimed;
31060
+ }
31061
+ return null;
31062
+ }
31063
+ claimOnce(workerId, lost) {
31064
+ this.db.exec("BEGIN IMMEDIATE");
31065
+ try {
31066
+ const excluded = [...lost];
31067
+ const candidate = this.get(`SELECT id FROM skills_runs
31068
+ WHERE status IN (${CLAIMABLE_STATUSES.map(() => "?").join(", ")})
31069
+ ${excluded.length ? `AND id NOT IN (${excluded.map(() => "?").join(", ")})` : ""}
31070
+ ORDER BY created_at ASC, rowid ASC
31071
+ LIMIT 1`, [...CLAIMABLE_STATUSES, ...excluded]);
31072
+ if (!candidate) {
31073
+ this.db.exec("COMMIT");
31074
+ return "empty";
31075
+ }
31076
+ const id = String(candidate.id);
31077
+ const now = nowIso();
31078
+ const result = this.db.run(`UPDATE skills_runs
31079
+ SET status = 'running', started_at = COALESCE(started_at, ?), locked_by = ?, locked_at = ?
31080
+ WHERE id = ? AND status IN (${CLAIMABLE_STATUSES.map(() => "?").join(", ")})`, [now, workerId, now, id, ...CLAIMABLE_STATUSES]);
31081
+ if (result.changes !== 1) {
31082
+ this.db.exec("ROLLBACK");
31083
+ lost.add(id);
31084
+ return null;
31085
+ }
31086
+ const row = this.get("SELECT * FROM skills_runs WHERE id = ? LIMIT 1", [id]);
31087
+ if (!row) {
31088
+ this.db.exec("ROLLBACK");
31089
+ throw new Error(`claimed run ${id} vanished within its own transaction; refusing to report a lost claim as an empty queue`);
31090
+ }
31091
+ this.db.exec("COMMIT");
31092
+ return rowToRun(row);
31093
+ } catch (error) {
31094
+ this.rollbackQuietly();
31095
+ throw error;
31096
+ }
31097
+ }
31098
+ async updateRun(id, patch) {
31099
+ const current = this.get("SELECT * FROM skills_runs WHERE id = ? LIMIT 1", [id]);
31100
+ if (!current)
31101
+ return null;
31102
+ const run = { ...rowToRun(current), ...patch };
31103
+ const row = this.get(`UPDATE skills_runs
31104
+ SET status = ?, output_type = ?, output_preview = ?, error_code = ?, error_message = ?, started_at = ?, completed_at = ?
31105
+ WHERE id = ?
31106
+ RETURNING *`, [
31107
+ run.status,
31108
+ run.outputType ?? null,
31109
+ run.outputPreview ?? null,
31110
+ run.errorCode ?? null,
31111
+ run.errorMessage ?? null,
31112
+ run.startedAt ?? null,
31113
+ run.completedAt ?? null,
31114
+ id
31115
+ ]);
31116
+ return row ? rowToRun(row) : null;
31117
+ }
31118
+ async appendLog(id, orgId, level, message) {
31119
+ const row = this.get(`INSERT INTO skills_run_logs (run_id, org_id, sequence, level, message, created_at)
31120
+ VALUES (?, ?, (SELECT COALESCE(MAX(sequence), 0) + 1 FROM skills_run_logs WHERE run_id = ?), ?, ?, ?)
31121
+ RETURNING *`, [id, orgId, id, level, message, nowIso()]);
31122
+ return rowToLog(row);
31123
+ }
31124
+ async listLogs(principal, id) {
31125
+ return this.all(`SELECT l.* FROM skills_run_logs l
31126
+ JOIN skills_runs r ON r.id = l.run_id AND r.org_id = ?
31127
+ WHERE l.run_id = ?
31128
+ ORDER BY l.sequence ASC`, [principal.orgId, id]).map(rowToLog);
31129
+ }
31130
+ async addArtifact(artifact) {
31131
+ const row = this.get(`INSERT INTO skills_artifacts (id, run_id, org_id, file_name, relative_path, content_type, byte_size, sha256, storage_kind, storage_key, body_text, created_at)
31132
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
31133
+ RETURNING *`, [
31134
+ artifact.id,
31135
+ artifact.runId,
31136
+ artifact.orgId,
31137
+ artifact.fileName,
31138
+ artifact.relativePath,
31139
+ artifact.contentType,
31140
+ artifact.byteSize,
31141
+ artifact.sha256,
31142
+ artifact.storageKind,
31143
+ artifact.storageKey ?? null,
31144
+ artifact.bodyText ?? null,
31145
+ nowIso()
31146
+ ]);
31147
+ return rowToArtifact(row);
31148
+ }
31149
+ async listArtifacts(principal, id) {
31150
+ return this.all(`SELECT a.* FROM skills_artifacts a
31151
+ JOIN skills_runs r ON r.id = a.run_id AND r.org_id = ?
31152
+ WHERE a.run_id = ?
31153
+ ORDER BY a.created_at ASC, a.rowid ASC`, [principal.orgId, id]).map(rowToArtifact);
31154
+ }
31155
+ async getArtifact(principal, id, artifact) {
31156
+ const row = this.get(`SELECT a.* FROM skills_artifacts a
31157
+ JOIN skills_runs r ON r.id = a.run_id AND r.org_id = ?
31158
+ WHERE a.run_id = ? AND a.id = ?
31159
+ LIMIT 1`, [principal.orgId, id, artifact]);
31160
+ return row ? rowToArtifact(row) : null;
31161
+ }
31162
+ async publishSkill(input) {
31163
+ const orgId = input.principal.orgId;
31164
+ const now = nowIso();
31165
+ return this.db.transaction(() => {
31166
+ const previous = this.get("SELECT bundle_sha256 FROM skills_registry WHERE org_id = ? AND slug = ?", [orgId, input.slug]);
31167
+ const previousSha = typeof previous?.bundle_sha256 === "string" ? previous.bundle_sha256 : null;
31168
+ if (input.bundle) {
31169
+ this.db.run(`INSERT INTO skills_bundles (org_id, sha256, byte_size, content_type, storage_kind, storage_key, body_blob, created_at)
31170
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
31171
+ ON CONFLICT (org_id, sha256) DO UPDATE SET
31172
+ byte_size = excluded.byte_size,
31173
+ content_type = excluded.content_type,
31174
+ storage_kind = excluded.storage_kind,
31175
+ storage_key = excluded.storage_key,
31176
+ body_blob = excluded.body_blob`, [
31177
+ orgId,
31178
+ input.bundle.sha256,
31179
+ input.bundle.byteSize,
31180
+ input.bundle.contentType,
31181
+ input.bundle.storageKind,
31182
+ input.bundle.storageKey ?? null,
31183
+ input.bundle.bytes ?? null,
31184
+ now
31185
+ ]);
31186
+ }
31187
+ const row = this.get(`INSERT INTO skills_registry (org_id, slug, display_name, description, category, tags_json, source, kind, version, skill_md,
31188
+ bundle_sha256, bundle_byte_size, published_by_user_id, created_at, updated_at)
31189
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
31190
+ ON CONFLICT (org_id, slug) DO UPDATE SET
31191
+ display_name = excluded.display_name,
31192
+ description = excluded.description,
31193
+ category = excluded.category,
31194
+ tags_json = excluded.tags_json,
31195
+ source = excluded.source,
31196
+ kind = excluded.kind,
31197
+ version = excluded.version,
31198
+ skill_md = excluded.skill_md,
31199
+ -- COALESCE, not a straight assignment. A publish that carries no bundle is a
31200
+ -- metadata update, not an instruction to discard the stored one: the plain
31201
+ -- assignment nulled bundle_sha256 and then handed the old digest to orphan
31202
+ -- collection, so re-publishing metadata over an existing skill deleted its
31203
+ -- tarball and left every client with a 404.
31204
+ bundle_sha256 = COALESCE(excluded.bundle_sha256, skills_registry.bundle_sha256),
31205
+ bundle_byte_size = COALESCE(excluded.bundle_byte_size, skills_registry.bundle_byte_size),
31206
+ published_by_user_id = excluded.published_by_user_id,
31207
+ updated_at = excluded.updated_at
31208
+ RETURNING *`, [
31209
+ orgId,
31210
+ input.slug,
31211
+ input.displayName,
31212
+ input.description,
31213
+ input.category,
31214
+ JSON.stringify(input.tags),
31215
+ input.source,
31216
+ input.kind,
31217
+ input.version ?? null,
31218
+ input.skillMd ?? null,
31219
+ input.bundle?.sha256 ?? null,
31220
+ input.bundle?.byteSize ?? null,
31221
+ input.principal.userId,
31222
+ now,
31223
+ now
31224
+ ]);
31225
+ if (previousSha && input.bundle && previousSha !== input.bundle.sha256)
31226
+ this.collectOrphanBundle(orgId, previousSha);
31227
+ return rowToSkill(row);
31228
+ })();
31229
+ }
31230
+ async listSkills(principal) {
31231
+ return this.all("SELECT * FROM skills_registry WHERE org_id = ? ORDER BY slug ASC", [principal.orgId]).map(rowToSkill);
31232
+ }
31233
+ async getSkill(principal, slug) {
31234
+ const row = this.get("SELECT * FROM skills_registry WHERE org_id = ? AND slug = ? LIMIT 1", [principal.orgId, slug]);
31235
+ return row ? rowToSkill(row) : null;
31236
+ }
31237
+ async updateSkill(principal, slug, patch) {
31238
+ const current = await this.getSkill(principal, slug);
31239
+ if (!current)
31240
+ return null;
31241
+ const next = { ...current, ...patch };
31242
+ const row = this.get(`UPDATE skills_registry
31243
+ SET display_name = ?, description = ?, category = ?, tags_json = ?, kind = ?, version = ?, skill_md = ?, updated_at = ?
31244
+ WHERE org_id = ? AND slug = ?
31245
+ RETURNING *`, [
31246
+ next.displayName,
31247
+ next.description,
31248
+ next.category,
31249
+ JSON.stringify(next.tags),
31250
+ next.kind,
31251
+ next.version ?? null,
31252
+ next.skillMd ?? null,
31253
+ nowIso(),
31254
+ principal.orgId,
31255
+ slug
31256
+ ]);
31257
+ return row ? rowToSkill(row) : null;
31258
+ }
31259
+ async deleteSkill(principal, slug) {
31260
+ return this.db.transaction(() => {
31261
+ const existing = this.get("SELECT bundle_sha256 FROM skills_registry WHERE org_id = ? AND slug = ?", [principal.orgId, slug]);
31262
+ if (!existing)
31263
+ return false;
31264
+ this.db.run("DELETE FROM skills_registry WHERE org_id = ? AND slug = ?", [principal.orgId, slug]);
31265
+ if (typeof existing.bundle_sha256 === "string")
31266
+ this.collectOrphanBundle(principal.orgId, existing.bundle_sha256);
31267
+ return true;
31268
+ })();
31269
+ }
31270
+ async getSkillBundle(principal, sha256) {
31271
+ const row = this.get("SELECT * FROM skills_bundles WHERE org_id = ? AND sha256 = ? LIMIT 1", [principal.orgId, sha256]);
31272
+ return row ? rowToSkillBundle(row) : null;
31273
+ }
31274
+ collectOrphanBundle(orgId, sha256) {
31275
+ const referenced = this.get("SELECT 1 AS present FROM skills_registry WHERE org_id = ? AND bundle_sha256 = ? LIMIT 1", [orgId, sha256]);
31276
+ if (referenced)
31277
+ return;
31278
+ this.db.run("DELETE FROM skills_bundles WHERE org_id = ? AND sha256 = ?", [orgId, sha256]);
31279
+ }
31280
+ get(sql, params) {
31281
+ return this.db.query(sql).get(...params) ?? null;
31282
+ }
31283
+ all(sql, params) {
31284
+ return this.db.query(sql).all(...params);
31285
+ }
31286
+ rollbackQuietly() {
31287
+ try {
31288
+ this.db.exec("ROLLBACK");
31289
+ } catch {}
31290
+ }
31291
+ }
31292
+ function applySqliteMigrations(db, migrationsDir = resolveMigrationsDir("sqlite")) {
31293
+ db.exec(`CREATE TABLE IF NOT EXISTS schema_migrations (
31294
+ version text PRIMARY KEY,
31295
+ applied_at text NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
31296
+ )`);
31297
+ const files = readdirSync2(migrationsDir).filter((name) => name.endsWith(".sql")).sort();
31298
+ if (files.length === 0) {
31299
+ throw new Error(`no .sql migrations found in ${migrationsDir}`);
31300
+ }
31301
+ const appliedNow = [];
31302
+ for (const file of files) {
31303
+ const version2 = file.replace(/\.sql$/, "");
31304
+ const text = readFileSync3(join5(migrationsDir, file), "utf8");
31305
+ const apply = db.transaction(() => {
31306
+ const already = db.query("SELECT 1 AS present FROM schema_migrations WHERE version = ? LIMIT 1").get(version2);
31307
+ if (already)
31308
+ return false;
31309
+ db.exec(text);
31310
+ db.run("INSERT INTO schema_migrations (version) VALUES (?)", [version2]);
31311
+ return true;
31312
+ });
31313
+ if (apply.immediate())
31314
+ appliedNow.push(version2);
31315
+ }
31316
+ return appliedNow;
31317
+ }
31318
+ function enableWalMode(db, attempts = 50, pauseMs = 10) {
31319
+ for (let attempt = 0;attempt < attempts; attempt += 1) {
31320
+ if (journalMode(db) === "wal")
31321
+ return true;
31322
+ try {
31323
+ if (String(db.query("PRAGMA journal_mode = WAL").get()?.journal_mode).toLowerCase() === "wal") {
31324
+ return true;
31325
+ }
31326
+ } catch {}
31327
+ Bun.sleepSync(pauseMs);
31328
+ }
31329
+ return false;
31330
+ }
31331
+ function journalMode(db) {
31332
+ try {
31333
+ return String(db.query("PRAGMA journal_mode").get()?.journal_mode ?? "").toLowerCase();
31334
+ } catch {
31335
+ return "";
31336
+ }
31337
+ }
31338
+ function openDatabase(path) {
31339
+ try {
31340
+ return new Database(path, { create: true, readwrite: true });
31341
+ } catch (error) {
31342
+ const reason = error instanceof Error ? error.message : String(error);
31343
+ throw new Error(`cannot open the skills database at ${path}: ${reason}. ` + "Check that the directory exists and is writable. Set HASNA_SKILLS_DATABASE_URL to choose a " + "different path or a postgres:// URL, or HASNA_SKILLS_DIR to relocate the whole data directory.", { cause: error });
31344
+ }
31345
+ }
31346
+ function parseScopes(value) {
31347
+ if (Array.isArray(value))
31348
+ return value.map(String);
31349
+ if (typeof value !== "string")
31350
+ return [];
31351
+ try {
31352
+ const parsed = JSON.parse(value);
31353
+ return Array.isArray(parsed) ? parsed.map(String) : [];
31354
+ } catch {
31355
+ return [];
31356
+ }
31357
+ }
31358
+
31359
+ // src/server/store.ts
31360
+ function resolvePoolMax(env = process.env) {
31361
+ const parsed = Number.parseInt(env.HASNA_SKILLS_DATABASE_POOL_MAX || env.SKILLS_DATABASE_POOL_MAX || "", 10);
31362
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 4;
31363
+ }
31364
+ var LOG_SEQUENCE_ATTEMPTS = 12;
31365
+ function createArtifactId() {
31366
+ return artifactId();
31367
+ }
31368
+ async function createStore(options = {}) {
31369
+ const target = resolveDatabaseTarget(options.databaseUrl);
31370
+ const store = instantiateStore(target, options.sqlite);
31371
+ await store.verifyConnectivity?.();
31372
+ if (options.bootstrapApiKey && store.ensureBootstrapApiKey) {
31373
+ await store.ensureBootstrapApiKey(options.bootstrapApiKey);
31374
+ }
31375
+ return store;
31376
+ }
31377
+ function instantiateStore(target, sqliteOptions) {
31378
+ switch (target.kind) {
31379
+ case "postgres":
31380
+ return new PostgresSkillsStore(target.url);
31381
+ case "sqlite":
31382
+ return new SqliteSkillsStore(target.path, sqliteOptions);
31383
+ case "memory":
31384
+ return new MemorySkillsStore;
31385
+ }
31386
+ }
31387
+
31388
+ class MemorySkillsStore {
31389
+ backend = { kind: "memory", durable: false, label: "memory (non-durable)" };
31390
+ apiKeys = new Map;
31391
+ runs = new Map;
31392
+ logs = new Map;
31393
+ artifacts = new Map;
31394
+ idempotency = new Map;
31395
+ skills = new Map;
31396
+ bundles = new Map;
31397
+ constructor(apiKeys = []) {
31398
+ for (const key of apiKeys)
31399
+ this.addApiKey(key.token, key.principal);
31400
+ }
31401
+ addApiKey(token, principal) {
31402
+ const resolved = publicPrincipal(principal);
31403
+ this.apiKeys.set(hashApiKey(token), resolved);
31404
+ return resolved;
31405
+ }
31406
+ async ensureBootstrapApiKey(token, principal) {
31407
+ this.addApiKey(token, principal);
31408
+ }
31409
+ async authenticateApiKeyHash(hash) {
31410
+ return this.apiKeys.get(hash) ?? null;
31411
+ }
31412
+ async createRun(input) {
31413
+ const idemKey = input.idempotencyKey?.trim();
30456
31414
  const idemMapKey = idemKey ? `${input.principal.orgId}:${idemKey}` : undefined;
30457
31415
  if (idemMapKey) {
30458
31416
  const existing = this.idempotency.get(idemMapKey);
@@ -30470,7 +31428,7 @@ class MemorySkillsStore {
30470
31428
  input: input.input,
30471
31429
  args: input.args,
30472
31430
  ...idemKey ? { idempotencyKey: idemKey } : {},
30473
- correlationId: randomUUID(),
31431
+ correlationId: randomUUID3(),
30474
31432
  costCents: 0,
30475
31433
  createdAt: now
30476
31434
  };
@@ -30482,17 +31440,17 @@ class MemorySkillsStore {
30482
31440
  return run;
30483
31441
  }
30484
31442
  async listRuns(principal, limit) {
30485
- return Array.from(this.runs.values()).filter((run) => run.orgId === principal.orgId).sort((a3, b3) => b3.createdAt.localeCompare(a3.createdAt)).slice(0, limit);
31443
+ return Array.from(this.runs.values()).filter((run) => run.orgId === principal.orgId).sort((a3, b3) => b3.createdAt.localeCompare(a3.createdAt)).slice(0, normalizeLimit(limit));
30486
31444
  }
30487
31445
  async getRun(principal, runId2) {
30488
31446
  const run = this.runs.get(runId2);
30489
31447
  return run && run.orgId === principal.orgId ? run : null;
30490
31448
  }
30491
- async claimNextRun(input) {
31449
+ async claimNextRun(_input) {
30492
31450
  const run = Array.from(this.runs.values()).filter((candidate) => candidate.status === "queued" || candidate.status === "retrying").sort((a3, b3) => a3.createdAt.localeCompare(b3.createdAt))[0];
30493
31451
  if (!run)
30494
31452
  return null;
30495
- return this.patchRun(run.id, { status: "running", startedAt: nowIso() });
31453
+ return this.patchRun(run.id, { status: "running", startedAt: run.startedAt ?? nowIso() });
30496
31454
  }
30497
31455
  async updateRun(runId2, patch) {
30498
31456
  return this.patchRun(runId2, patch);
@@ -30523,6 +31481,74 @@ class MemorySkillsStore {
30523
31481
  const artifacts = await this.listArtifacts(principal, runId2);
30524
31482
  return artifacts.find((artifact) => artifact.id === id) ?? null;
30525
31483
  }
31484
+ async publishSkill(input) {
31485
+ const key = skillKey(input.principal.orgId, input.slug);
31486
+ const now = nowIso();
31487
+ const previous = this.skills.get(key);
31488
+ if (input.bundle) {
31489
+ const bundleMapKey = skillKey(input.principal.orgId, input.bundle.sha256);
31490
+ this.bundles.set(bundleMapKey, {
31491
+ ...this.bundles.get(bundleMapKey),
31492
+ ...input.bundle,
31493
+ orgId: input.principal.orgId,
31494
+ createdAt: this.bundles.get(bundleMapKey)?.createdAt ?? now
31495
+ });
31496
+ }
31497
+ const record = {
31498
+ orgId: input.principal.orgId,
31499
+ slug: input.slug,
31500
+ displayName: input.displayName,
31501
+ description: input.description,
31502
+ category: input.category,
31503
+ tags: [...input.tags],
31504
+ source: input.source,
31505
+ kind: input.kind,
31506
+ ...input.version ? { version: input.version } : {},
31507
+ ...input.skillMd ? { skillMd: input.skillMd } : {},
31508
+ ...input.bundle ? { bundleSha256: input.bundle.sha256, bundleByteSize: input.bundle.byteSize } : previous?.bundleSha256 ? { bundleSha256: previous.bundleSha256, ...previous.bundleByteSize === undefined ? {} : { bundleByteSize: previous.bundleByteSize } } : {},
31509
+ publishedByUserId: input.principal.userId,
31510
+ createdAt: previous?.createdAt ?? now,
31511
+ updatedAt: now
31512
+ };
31513
+ this.skills.set(key, record);
31514
+ if (previous?.bundleSha256 && input.bundle && previous.bundleSha256 !== input.bundle.sha256) {
31515
+ this.collectOrphanBundle(input.principal.orgId, previous.bundleSha256);
31516
+ }
31517
+ return record;
31518
+ }
31519
+ async listSkills(principal) {
31520
+ return Array.from(this.skills.values()).filter((skill) => skill.orgId === principal.orgId).sort((a3, b3) => a3.slug.localeCompare(b3.slug));
31521
+ }
31522
+ async getSkill(principal, slug) {
31523
+ const skill = this.skills.get(skillKey(principal.orgId, slug));
31524
+ return skill && skill.orgId === principal.orgId ? skill : null;
31525
+ }
31526
+ async updateSkill(principal, slug, patch) {
31527
+ const current = await this.getSkill(principal, slug);
31528
+ if (!current)
31529
+ return null;
31530
+ const next = { ...current, ...patch, updatedAt: nowIso() };
31531
+ this.skills.set(skillKey(principal.orgId, slug), next);
31532
+ return next;
31533
+ }
31534
+ async deleteSkill(principal, slug) {
31535
+ const current = await this.getSkill(principal, slug);
31536
+ if (!current)
31537
+ return false;
31538
+ this.skills.delete(skillKey(principal.orgId, slug));
31539
+ if (current.bundleSha256)
31540
+ this.collectOrphanBundle(principal.orgId, current.bundleSha256);
31541
+ return true;
31542
+ }
31543
+ async getSkillBundle(principal, sha256) {
31544
+ const bundle = this.bundles.get(skillKey(principal.orgId, sha256));
31545
+ return bundle && bundle.orgId === principal.orgId ? bundle : null;
31546
+ }
31547
+ collectOrphanBundle(orgId, sha256) {
31548
+ const referenced = Array.from(this.skills.values()).some((skill) => skill.orgId === orgId && skill.bundleSha256 === sha256);
31549
+ if (!referenced)
31550
+ this.bundles.delete(skillKey(orgId, sha256));
31551
+ }
30526
31552
  patchRun(runId2, patch) {
30527
31553
  const run = this.runs.get(runId2);
30528
31554
  if (!run)
@@ -30532,13 +31558,32 @@ class MemorySkillsStore {
30532
31558
  return next;
30533
31559
  }
30534
31560
  }
31561
+ function skillKey(orgId, slug) {
31562
+ return `${orgId.length}:${orgId}:${slug}`;
31563
+ }
30535
31564
 
30536
31565
  class PostgresSkillsStore {
31566
+ backend = { kind: "postgres", durable: true, label: "postgres" };
30537
31567
  sql;
30538
31568
  constructor(databaseUrl) {
30539
31569
  const bunWithSql = Bun;
30540
31570
  this.sql = new bunWithSql.SQL(databaseUrl, { max: resolvePoolMax() });
30541
31571
  }
31572
+ async verifyConnectivity() {
31573
+ try {
31574
+ await this.sql`SELECT 1`;
31575
+ } catch (error) {
31576
+ throw new Error("cannot reach the configured Postgres database. The server will not start with an unreachable " + "database rather than fall back to another backend and silently split your data across two stores. " + `Check HASNA_SKILLS_DATABASE_URL and that the instance is accepting connections. Driver reported: ${connectionFailureSummary(error)}`);
31577
+ }
31578
+ try {
31579
+ await this.sql`SELECT 1 FROM api_keys LIMIT 0`;
31580
+ } catch (error) {
31581
+ throw new Error("the configured Postgres database is reachable but has no skills schema. Run `skills-migrate` against it " + "before starting the server - unlike SQLite, Postgres is not migrated automatically, so that several " + `replicas cannot race to migrate a shared database. Driver reported: ${connectionFailureSummary(error)}`);
31582
+ }
31583
+ }
31584
+ async close() {
31585
+ await this.sql.close?.();
31586
+ }
30542
31587
  async ensureBootstrapApiKey(token, principal) {
30543
31588
  const resolved = publicPrincipal(principal);
30544
31589
  await this.sql`
@@ -30601,7 +31646,7 @@ class PostgresSkillsStore {
30601
31646
  const id = runId();
30602
31647
  const rows = await this.sql`
30603
31648
  INSERT INTO skills_runs (id, org_id, user_id, skill_slug, requested_slug, status, input_json, args_json, idempotency_key, correlation_id)
30604
- VALUES (${id}, ${input.principal.orgId}, ${input.principal.userId}, ${input.slug}, ${input.slug}, ${"queued"}, ${JSON.stringify(input.input)}::jsonb, ${JSON.stringify(input.args)}::jsonb, ${input.idempotencyKey ?? null}, ${randomUUID()})
31649
+ VALUES (${id}, ${input.principal.orgId}, ${input.principal.userId}, ${input.slug}, ${input.slug}, ${"queued"}, ${JSON.stringify(input.input)}::jsonb, ${JSON.stringify(input.args)}::jsonb, ${input.idempotencyKey ?? null}, ${randomUUID3()})
30605
31650
  RETURNING *
30606
31651
  `;
30607
31652
  return rowToRun(rows[0]);
@@ -30609,7 +31654,7 @@ class PostgresSkillsStore {
30609
31654
  async listRuns(principal, limit) {
30610
31655
  const rows = await this.sql`
30611
31656
  SELECT * FROM skills_runs WHERE org_id = ${principal.orgId}
30612
- ORDER BY created_at DESC LIMIT ${limit}
31657
+ ORDER BY created_at DESC LIMIT ${normalizeLimit(limit)}
30613
31658
  `;
30614
31659
  return rows.map(rowToRun);
30615
31660
  }
@@ -30654,14 +31699,28 @@ class PostgresSkillsStore {
30654
31699
  return rows[0] ? rowToRun(rows[0]) : null;
30655
31700
  }
30656
31701
  async appendLog(runId2, orgId, level, message) {
30657
- const seqRows = await this.sql`SELECT COALESCE(MAX(sequence), 0) + 1 AS next_sequence FROM skills_run_logs WHERE run_id = ${runId2}`;
30658
- const sequence = Number(seqRows[0]?.next_sequence ?? 1);
30659
- const rows = await this.sql`
30660
- INSERT INTO skills_run_logs (run_id, org_id, sequence, level, message)
30661
- VALUES (${runId2}, ${orgId}, ${sequence}, ${level}, ${message})
30662
- RETURNING *
30663
- `;
30664
- return rowToLog(rows[0]);
31702
+ let lastError;
31703
+ for (let attempt = 0;attempt < LOG_SEQUENCE_ATTEMPTS; attempt += 1) {
31704
+ try {
31705
+ const rows = await this.sql`
31706
+ INSERT INTO skills_run_logs (run_id, org_id, sequence, level, message)
31707
+ VALUES (
31708
+ ${runId2},
31709
+ ${orgId},
31710
+ (SELECT COALESCE(MAX(sequence), 0) + 1 FROM skills_run_logs WHERE run_id = ${runId2}),
31711
+ ${level},
31712
+ ${message}
31713
+ )
31714
+ RETURNING *
31715
+ `;
31716
+ return rowToLog(rows[0]);
31717
+ } catch (error) {
31718
+ if (!isUniqueViolation(error))
31719
+ throw error;
31720
+ lastError = error;
31721
+ }
31722
+ }
31723
+ throw lastError;
30665
31724
  }
30666
31725
  async listLogs(principal, runId2) {
30667
31726
  const rows = await this.sql`
@@ -30698,80 +31757,121 @@ class PostgresSkillsStore {
30698
31757
  `;
30699
31758
  return rows[0] ? rowToArtifact(rows[0]) : null;
30700
31759
  }
30701
- }
30702
- function rowToRun(row) {
30703
- return {
30704
- id: String(row.id),
30705
- orgId: String(row.org_id),
30706
- userId: String(row.user_id),
30707
- skill: String(row.skill_slug),
30708
- requestedSlug: String(row.requested_slug),
30709
- status: String(row.status),
30710
- input: parseJsonObject(row.input_json),
30711
- args: parseJsonArray(row.args_json),
30712
- ...typeof row.idempotency_key === "string" ? { idempotencyKey: row.idempotency_key } : {},
30713
- correlationId: String(row.correlation_id),
30714
- costCents: Number(row.cost_cents ?? 0),
30715
- ...typeof row.output_type === "string" ? { outputType: row.output_type } : {},
30716
- ...typeof row.output_preview === "string" ? { outputPreview: row.output_preview } : {},
30717
- ...typeof row.error_code === "string" ? { errorCode: row.error_code } : {},
30718
- ...typeof row.error_message === "string" ? { errorMessage: row.error_message } : {},
30719
- createdAt: dateString(row.created_at),
30720
- ...row.started_at ? { startedAt: dateString(row.started_at) } : {},
30721
- ...row.completed_at ? { completedAt: dateString(row.completed_at) } : {}
30722
- };
30723
- }
30724
- function rowToLog(row) {
30725
- return {
30726
- runId: String(row.run_id),
30727
- sequence: Number(row.sequence),
30728
- level: String(row.level),
30729
- message: String(row.message),
30730
- createdAt: dateString(row.created_at)
30731
- };
30732
- }
30733
- function rowToArtifact(row) {
30734
- return {
30735
- id: String(row.id),
30736
- runId: String(row.run_id),
30737
- orgId: String(row.org_id),
30738
- fileName: String(row.file_name),
30739
- relativePath: String(row.relative_path),
30740
- contentType: String(row.content_type),
30741
- byteSize: Number(row.byte_size),
30742
- sha256: String(row.sha256),
30743
- storageKind: String(row.storage_kind),
30744
- ...typeof row.storage_key === "string" ? { storageKey: row.storage_key } : {},
30745
- ...typeof row.body_text === "string" ? { bodyText: row.body_text } : {},
30746
- createdAt: dateString(row.created_at)
30747
- };
30748
- }
30749
- function parseJsonObject(value) {
30750
- if (value && typeof value === "object" && !Array.isArray(value))
30751
- return value;
30752
- if (typeof value === "string") {
30753
- try {
30754
- const parsed = JSON.parse(value);
30755
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
30756
- } catch {}
31760
+ async publishSkill(input) {
31761
+ const orgId = input.principal.orgId;
31762
+ return await this.sql.begin(async (tx) => {
31763
+ const previousRows = await tx`SELECT bundle_sha256 FROM skills_registry WHERE org_id = ${orgId} AND slug = ${input.slug} LIMIT 1`;
31764
+ const previousSha = typeof previousRows[0]?.bundle_sha256 === "string" ? String(previousRows[0].bundle_sha256) : null;
31765
+ if (input.bundle) {
31766
+ await tx`
31767
+ INSERT INTO skills_bundles (org_id, sha256, byte_size, content_type, storage_kind, storage_key, body_blob)
31768
+ VALUES (${orgId}, ${input.bundle.sha256}, ${input.bundle.byteSize}, ${input.bundle.contentType}, ${input.bundle.storageKind}, ${input.bundle.storageKey ?? null}, ${input.bundle.bytes ?? null})
31769
+ ON CONFLICT (org_id, sha256) DO UPDATE SET
31770
+ byte_size = EXCLUDED.byte_size,
31771
+ content_type = EXCLUDED.content_type,
31772
+ storage_kind = EXCLUDED.storage_kind,
31773
+ storage_key = EXCLUDED.storage_key,
31774
+ body_blob = EXCLUDED.body_blob
31775
+ `;
31776
+ }
31777
+ const rows = await tx`
31778
+ INSERT INTO skills_registry (org_id, slug, display_name, description, category, tags_json, source, kind, version, skill_md,
31779
+ bundle_sha256, bundle_byte_size, published_by_user_id, updated_at)
31780
+ VALUES (${orgId}, ${input.slug}, ${input.displayName}, ${input.description}, ${input.category}, ${JSON.stringify(input.tags)}::jsonb,
31781
+ ${input.source}, ${input.kind}, ${input.version ?? null}, ${input.skillMd ?? null},
31782
+ ${input.bundle?.sha256 ?? null}, ${input.bundle?.byteSize ?? null}, ${input.principal.userId}, now())
31783
+ ON CONFLICT (org_id, slug) DO UPDATE SET
31784
+ display_name = EXCLUDED.display_name,
31785
+ description = EXCLUDED.description,
31786
+ category = EXCLUDED.category,
31787
+ tags_json = EXCLUDED.tags_json,
31788
+ source = EXCLUDED.source,
31789
+ kind = EXCLUDED.kind,
31790
+ version = EXCLUDED.version,
31791
+ skill_md = EXCLUDED.skill_md,
31792
+ -- COALESCE: see the SQLite twin. A bundle-less publish is a metadata update,
31793
+ -- not an instruction to discard the stored tarball.
31794
+ bundle_sha256 = COALESCE(EXCLUDED.bundle_sha256, skills_registry.bundle_sha256),
31795
+ bundle_byte_size = COALESCE(EXCLUDED.bundle_byte_size, skills_registry.bundle_byte_size),
31796
+ published_by_user_id = EXCLUDED.published_by_user_id,
31797
+ updated_at = EXCLUDED.updated_at
31798
+ RETURNING *
31799
+ `;
31800
+ if (previousSha && input.bundle && previousSha !== input.bundle.sha256) {
31801
+ await tx`
31802
+ DELETE FROM skills_bundles
31803
+ WHERE org_id = ${orgId} AND sha256 = ${previousSha}
31804
+ AND NOT EXISTS (SELECT 1 FROM skills_registry WHERE org_id = ${orgId} AND bundle_sha256 = ${previousSha})
31805
+ `;
31806
+ }
31807
+ return rowToSkill(rows[0]);
31808
+ });
30757
31809
  }
30758
- return {};
30759
- }
30760
- function parseJsonArray(value) {
30761
- const parsed = typeof value === "string" ? safeParse(value) : value;
30762
- return Array.isArray(parsed) ? parsed.map(String) : [];
30763
- }
30764
- function safeParse(value) {
30765
- try {
30766
- return JSON.parse(value);
30767
- } catch {
30768
- return;
31810
+ async listSkills(principal) {
31811
+ const rows = await this.sql`SELECT * FROM skills_registry WHERE org_id = ${principal.orgId} ORDER BY slug ASC`;
31812
+ return rows.map(rowToSkill);
31813
+ }
31814
+ async getSkill(principal, slug) {
31815
+ const rows = await this.sql`SELECT * FROM skills_registry WHERE org_id = ${principal.orgId} AND slug = ${slug} LIMIT 1`;
31816
+ return rows[0] ? rowToSkill(rows[0]) : null;
31817
+ }
31818
+ async updateSkill(principal, slug, patch) {
31819
+ const current = await this.getSkill(principal, slug);
31820
+ if (!current)
31821
+ return null;
31822
+ const next = { ...current, ...patch };
31823
+ const rows = await this.sql`
31824
+ UPDATE skills_registry
31825
+ SET display_name = ${next.displayName}, description = ${next.description}, category = ${next.category},
31826
+ tags_json = ${JSON.stringify(next.tags)}::jsonb, kind = ${next.kind}, version = ${next.version ?? null},
31827
+ skill_md = ${next.skillMd ?? null}, updated_at = now()
31828
+ WHERE org_id = ${principal.orgId} AND slug = ${slug}
31829
+ RETURNING *
31830
+ `;
31831
+ return rows[0] ? rowToSkill(rows[0]) : null;
31832
+ }
31833
+ async deleteSkill(principal, slug) {
31834
+ return await this.sql.begin(async (tx) => {
31835
+ const rows = await tx`
31836
+ DELETE FROM skills_registry WHERE org_id = ${principal.orgId} AND slug = ${slug}
31837
+ RETURNING bundle_sha256
31838
+ `;
31839
+ if (!rows[0])
31840
+ return false;
31841
+ const sha = rows[0].bundle_sha256;
31842
+ if (typeof sha === "string") {
31843
+ await tx`
31844
+ DELETE FROM skills_bundles
31845
+ WHERE org_id = ${principal.orgId} AND sha256 = ${sha}
31846
+ AND NOT EXISTS (SELECT 1 FROM skills_registry WHERE org_id = ${principal.orgId} AND bundle_sha256 = ${sha})
31847
+ `;
31848
+ }
31849
+ return true;
31850
+ });
31851
+ }
31852
+ async getSkillBundle(principal, sha256) {
31853
+ const rows = await this.sql`SELECT * FROM skills_bundles WHERE org_id = ${principal.orgId} AND sha256 = ${sha256} LIMIT 1`;
31854
+ return rows[0] ? rowToSkillBundle(rows[0]) : null;
31855
+ }
31856
+ async collectOrphanBundle(orgId, sha256) {
31857
+ await this.sql`
31858
+ DELETE FROM skills_bundles
31859
+ WHERE org_id = ${orgId} AND sha256 = ${sha256}
31860
+ AND NOT EXISTS (SELECT 1 FROM skills_registry WHERE org_id = ${orgId} AND bundle_sha256 = ${sha256})
31861
+ `;
30769
31862
  }
30770
31863
  }
30771
- function dateString(value) {
30772
- if (value instanceof Date)
30773
- return value.toISOString();
30774
- return String(value);
31864
+ function isUniqueViolation(error) {
31865
+ const code = error?.code;
31866
+ if (code === "23505" || code === 23505)
31867
+ return true;
31868
+ const message = error instanceof Error ? error.message : String(error);
31869
+ return /duplicate key value violates unique constraint/i.test(message);
31870
+ }
31871
+ function connectionFailureSummary(error) {
31872
+ const message = error instanceof Error ? error.message : String(error);
31873
+ return message.replace(/[a-z][a-z0-9+.-]*:\/\/\S*/gi, "<redacted-url>").split(`
31874
+ `)[0].slice(0, 200);
30775
31875
  }
30776
31876
 
30777
31877
  // src/server/redaction.ts
@@ -30799,16 +31899,16 @@ var DETERMINISTIC_TEXT_HANDLERS = new Set([
30799
31899
  ]);
30800
31900
  async function executeRun(store, run, storage = new ArtifactStorage) {
30801
31901
  try {
30802
- await store.appendLog(run.id, run.orgId, "info", redactForClient(`starting self-hosted run ${run.skill}`));
31902
+ await store.appendLog(run.id, run.orgId, "info", redactForClient(`starting run ${run.skill}`));
30803
31903
  if (!DETERMINISTIC_TEXT_HANDLERS.has(run.skill)) {
30804
- await store.appendLog(run.id, run.orgId, "warn", `${run.skill} has no self-hosted provider-free handler yet`);
30805
- return await failRun(store, run, "HANDLER_UNAVAILABLE", "This self-hosted deployment has no safe provider-free handler for that skill yet.");
31904
+ await store.appendLog(run.id, run.orgId, "warn", `${run.skill} has no provider-free handler yet`);
31905
+ return await failRun(store, run, "HANDLER_UNAVAILABLE", "This deployment has no safe provider-free handler for that skill yet.");
30806
31906
  }
30807
31907
  const text = extractText(run);
30808
31908
  if (!text.trim()) {
30809
31909
  return await failRun(store, run, "INVALID_INPUT", "Provide transcript text with input.transcript, input.text, --text, --source, or positional text.");
30810
31910
  }
30811
- const title = extractOption(run.args, "--title") || stringInput(run.input, "title") || "Self-hosted Skills run";
31911
+ const title = extractOption(run.args, "--title") || stringInput(run.input, "title") || "Skills run";
30812
31912
  const summary = summarize(text);
30813
31913
  const artifacts = [
30814
31914
  textArtifact(run, "transcript.md", `# ${title}
@@ -30822,7 +31922,7 @@ ${summary}
30822
31922
  textArtifact(run, "show-notes.md", `# Show Notes
30823
31923
 
30824
31924
  - ${summary}
30825
- - Generated by open-skills self-hosted deterministic worker.
31925
+ - Generated by the open-skills deterministic worker.
30826
31926
  `),
30827
31927
  textArtifact(run, "clips.csv", `start,end,title,summary
30828
31928
  00:00,00:30,"Opening","${csv(summary)}"
@@ -30907,8 +32007,831 @@ function csv(value) {
30907
32007
  return value.replace(/"/g, '""');
30908
32008
  }
30909
32009
 
32010
+ // src/lib/registry-data/development-tools.ts
32011
+ var DEVELOPMENT_TOOLS_SKILLS = [
32012
+ {
32013
+ name: "repo-onboarding-report",
32014
+ displayName: "Repo Onboarding Report",
32015
+ description: "Generate repository onboarding packages with architecture maps, setup guides, risk registers, and first-week plans",
32016
+ category: "Development Tools",
32017
+ kind: "instruction",
32018
+ tags: ["repository", "onboarding", "architecture", "developer-tools"]
32019
+ },
32020
+ {
32021
+ name: "security-audit-report",
32022
+ displayName: "Security Audit Report",
32023
+ description: "Generate application security hardening reports covering auth, secrets, headers, webhooks, RLS, permissions, dependencies, and prioritized fixes",
32024
+ category: "Development Tools",
32025
+ kind: "instruction",
32026
+ tags: ["security", "audit", "hardening", "rls", "webhooks"]
32027
+ },
32028
+ {
32029
+ name: "performance-audit-report",
32030
+ displayName: "Performance Audit Report",
32031
+ description: "Generate performance audit reports with metrics, findings, budgets, remediation plans, and manifest artifacts",
32032
+ category: "Development Tools",
32033
+ kind: "instruction",
32034
+ tags: ["performance", "audit", "latency", "budget", "web"]
32035
+ },
32036
+ {
32037
+ name: "migration-plan-pack",
32038
+ displayName: "Migration Plan Pack",
32039
+ description: "Generate migration plans for frameworks, libraries, databases, infrastructure, and architecture upgrades with risk matrix, checklist, rollout, and test strategy artifacts",
32040
+ category: "Development Tools",
32041
+ kind: "instruction",
32042
+ tags: ["migration", "upgrade", "planning", "frameworks", "databases"]
32043
+ },
32044
+ {
32045
+ name: "test-suite-generator",
32046
+ displayName: "Test Suite Generator",
32047
+ description: "Generate runnable API, unit, and browser test suite packages with coverage notes",
32048
+ category: "Development Tools",
32049
+ kind: "instruction",
32050
+ tags: ["testing", "qa", "api-tests", "browser-tests", "coverage"]
32051
+ },
32052
+ {
32053
+ name: "api-test-suite",
32054
+ displayName: "API Test Suite",
32055
+ description: "Generate and run API test suites with comprehensive endpoint coverage",
32056
+ category: "Development Tools",
32057
+ tags: ["api", "testing", "automation", "qa"]
32058
+ },
32059
+ {
32060
+ name: "api-docs-portal",
32061
+ displayName: "API Docs Portal",
32062
+ description: "Generate static API documentation portals from OpenAPI specs, route lists, and endpoint examples",
32063
+ category: "Development Tools",
32064
+ tags: ["api", "documentation", "openapi", "portal"]
32065
+ },
32066
+ {
32067
+ name: "codefix",
32068
+ displayName: "Code Fix",
32069
+ description: "Code quality CLI for auto-linting, formatting, fixing, and style enforcement",
32070
+ category: "Development Tools",
32071
+ tags: ["code", "linting", "formatting", "quality"]
32072
+ },
32073
+ {
32074
+ name: "commitpush",
32075
+ displayName: "Commit Push",
32076
+ description: "Create logical commits from repo changes and push directly to the main branch",
32077
+ category: "Development Tools",
32078
+ tags: ["git", "commit", "push", "automation"]
32079
+ },
32080
+ {
32081
+ name: "commitpushpr",
32082
+ displayName: "Commit Push PR",
32083
+ description: "Create logical commits, push a feature branch, and open a GitHub pull request",
32084
+ category: "Development Tools",
32085
+ dependencies: ["commitpush"],
32086
+ tags: ["git", "commit", "pull-request", "github", "automation"]
32087
+ },
32088
+ {
32089
+ name: "database-explorer",
32090
+ displayName: "Database Explorer",
32091
+ description: "Explore and query databases with an interactive interface",
32092
+ category: "Development Tools",
32093
+ tags: ["database", "explorer", "sql", "query"]
32094
+ },
32095
+ {
32096
+ name: "diff-viewer",
32097
+ displayName: "Diff Viewer",
32098
+ description: "View and analyze file differences with visual diff representation",
32099
+ category: "Development Tools",
32100
+ tags: ["diff", "comparison", "files", "code-review"]
32101
+ },
32102
+ {
32103
+ name: "generate-api-client",
32104
+ displayName: "Generate API Client",
32105
+ description: "Generate API client libraries from OpenAPI specs and documentation",
32106
+ category: "Development Tools",
32107
+ tags: ["api", "client", "code-generation", "openapi"]
32108
+ },
32109
+ {
32110
+ name: "generate-dockerfile",
32111
+ displayName: "Generate Dockerfile",
32112
+ description: "Generate optimized Dockerfiles for containerized applications",
32113
+ category: "Development Tools",
32114
+ tags: ["docker", "dockerfile", "containers", "devops"]
32115
+ },
32116
+ {
32117
+ name: "generate-env",
32118
+ displayName: "Generate Env",
32119
+ description: "Generate environment variable files from templates and configurations",
32120
+ category: "Development Tools",
32121
+ tags: ["env", "environment", "configuration", "dotenv"]
32122
+ },
32123
+ {
32124
+ name: "generate-sitemap",
32125
+ displayName: "Generate Sitemap",
32126
+ description: "Generate XML sitemaps for websites and web applications",
32127
+ category: "Development Tools",
32128
+ tags: ["sitemap", "seo", "xml", "web"]
32129
+ },
32130
+ {
32131
+ name: "hook",
32132
+ displayName: "Hook",
32133
+ description: "Claude Code hook creation skill - generates standardized hook scaffolds",
32134
+ category: "Development Tools",
32135
+ tags: ["hooks", "scaffold", "claude-code", "automation"]
32136
+ },
32137
+ {
32138
+ name: "http-server",
32139
+ displayName: "HTTP Server",
32140
+ description: "Spin up local HTTP servers for development and testing",
32141
+ category: "Development Tools",
32142
+ tags: ["http", "server", "development", "local"]
32143
+ },
32144
+ {
32145
+ name: "lorem-generator",
32146
+ displayName: "Lorem Generator",
32147
+ description: "Generate placeholder text in various styles and lengths",
32148
+ category: "Development Tools",
32149
+ tags: ["lorem", "placeholder", "text", "mockup"]
32150
+ },
32151
+ {
32152
+ name: "managemcp",
32153
+ displayName: "Manage MCP",
32154
+ description: "Manage MCP servers with install, configure, and lifecycle operations",
32155
+ category: "Development Tools",
32156
+ tags: ["mcp", "management", "servers", "configuration"]
32157
+ },
32158
+ {
32159
+ name: "markdown-validator",
32160
+ displayName: "Markdown Validator",
32161
+ description: "Validate markdown files for syntax, links, and formatting issues",
32162
+ category: "Development Tools",
32163
+ tags: ["markdown", "validation", "linting", "formatting"]
32164
+ },
32165
+ {
32166
+ name: "monitor",
32167
+ displayName: "Monitor",
32168
+ description: "Operate the open-monitor MCP for machine health, processes, cron jobs, and cleanup workflows",
32169
+ category: "Development Tools",
32170
+ tags: ["monitoring", "mcp", "processes", "operations"]
32171
+ },
32172
+ {
32173
+ name: "regex-tester",
32174
+ displayName: "Regex Tester",
32175
+ description: "Test and validate regular expressions with sample inputs",
32176
+ category: "Development Tools",
32177
+ tags: ["regex", "testing", "validation", "patterns"]
32178
+ },
32179
+ {
32180
+ name: "scancommitpr",
32181
+ displayName: "Scan Commit PR",
32182
+ description: "Scan repo changes, group into logical commits, push, and optionally create a PR",
32183
+ category: "Development Tools",
32184
+ dependencies: ["scancommitpush"],
32185
+ tags: ["git", "commit", "push", "pull-request", "automation"]
32186
+ },
32187
+ {
32188
+ name: "scancommitpush",
32189
+ displayName: "Scan Commit Push",
32190
+ description: "Scan repo changes, group into logical commits with conventional messages, and push to GitHub",
32191
+ category: "Development Tools",
32192
+ tags: ["git", "commit", "push", "automation"]
32193
+ },
32194
+ {
32195
+ name: "security-audit",
32196
+ displayName: "Security Audit",
32197
+ description: "Perform security audits on codebases and infrastructure configurations",
32198
+ category: "Development Tools",
32199
+ tags: ["security", "audit", "vulnerabilities", "scanning"]
32200
+ },
32201
+ {
32202
+ name: "tmux-session",
32203
+ displayName: "Tmux Session",
32204
+ description: "Create and manage grouped tmux sessions with workspace-aware naming and window layout guidance",
32205
+ category: "Development Tools",
32206
+ tags: ["tmux", "terminal", "sessions", "workspace"]
32207
+ },
32208
+ {
32209
+ name: "validate-config",
32210
+ displayName: "Validate Config",
32211
+ description: "Validate configuration files for syntax and schema compliance",
32212
+ category: "Development Tools",
32213
+ tags: ["config", "validation", "schema", "linting"]
32214
+ }
32215
+ ];
32216
+
32217
+ // src/lib/registry-data/business-marketing.ts
32218
+ var BUSINESS_MARKETING_SKILLS = [
32219
+ {
32220
+ name: "customer-feedback-report",
32221
+ displayName: "Customer Feedback Report",
32222
+ description: "Generate customer feedback reports with clusters, sentiment, root causes, roadmap recommendations, evidence, and PDF/Markdown artifacts",
32223
+ category: "Business & Marketing",
32224
+ kind: "instruction",
32225
+ tags: ["feedback", "customer", "sentiment", "roadmap", "report"]
32226
+ },
32227
+ {
32228
+ name: "pitch-deck",
32229
+ displayName: "Pitch Deck",
32230
+ description: "Generate investor and sales deck packages with slides, speaker notes, design direction, PDF, and PPTX artifacts",
32231
+ category: "Business & Marketing",
32232
+ kind: "instruction",
32233
+ dependencies: ["market-research-report"],
32234
+ tags: ["deck", "presentation", "investor", "sales", "pptx"]
32235
+ },
32236
+ {
32237
+ name: "proposal-pack",
32238
+ displayName: "Proposal Pack",
32239
+ description: "Generate client proposal packages with proposal, statement of work, pricing, timeline, assumptions, cover email, and PDF/Markdown artifacts",
32240
+ category: "Business & Marketing",
32241
+ kind: "instruction",
32242
+ tags: ["proposal", "sow", "sales", "pricing", "timeline"]
32243
+ },
32244
+ {
32245
+ name: "seo-content-pack",
32246
+ displayName: "SEO Content Pack",
32247
+ description: "Generate SEO content packages with topic clusters, articles, metadata, internal links, FAQs, and publishing cadence",
32248
+ category: "Business & Marketing",
32249
+ kind: "instruction",
32250
+ tags: ["seo", "content", "articles", "metadata"]
32251
+ },
32252
+ {
32253
+ name: "landing-page-pack",
32254
+ displayName: "Landing Page Pack",
32255
+ description: "Generate landing page packages with conversion copy, wireframes, CTA maps, experiments, preview HTML, and implementation notes",
32256
+ category: "Business & Marketing",
32257
+ kind: "instruction",
32258
+ tags: ["landing-page", "sales", "copywriting", "conversion"]
32259
+ },
32260
+ {
32261
+ name: "ad-creative-pack",
32262
+ displayName: "Ad Creative Pack",
32263
+ description: "Generate paid ad packages with platform copy, creative concepts, image prompts, audience angles, and test matrices",
32264
+ category: "Business & Marketing",
32265
+ kind: "instruction",
32266
+ tags: ["ads", "creative", "marketing", "copywriting"]
32267
+ },
32268
+ {
32269
+ name: "email-sequence",
32270
+ displayName: "Email Sequence",
32271
+ description: "Generate email campaign packages with subject lines, preview text, body copy, segmentation notes, CTA variants, HTML emails, and send plans",
32272
+ category: "Business & Marketing",
32273
+ kind: "instruction",
32274
+ tags: ["email", "marketing", "campaign", "copywriting"]
32275
+ },
32276
+ {
32277
+ name: "social-content-calendar",
32278
+ displayName: "Social Content Calendar",
32279
+ description: "Generate social content calendars with daily posts, channel strategy, asset briefs, hooks, publishing schedules, and repurposing maps",
32280
+ category: "Business & Marketing",
32281
+ kind: "instruction",
32282
+ tags: ["social", "content", "calendar", "marketing"]
32283
+ },
32284
+ {
32285
+ name: "one-page-website",
32286
+ displayName: "One Page Website",
32287
+ description: "Generate static one-page website bundles with HTML, CSS, JavaScript, copy, section maps, deploy notes, and manifest",
32288
+ category: "Business & Marketing",
32289
+ tags: ["website", "landing-page", "static-site", "html"]
32290
+ }
32291
+ ];
32292
+
32293
+ // src/lib/registry-data/productivity-organization.ts
32294
+ var PRODUCTIVITY_ORGANIZATION_SKILLS = [
32295
+ {
32296
+ name: "meeting-pack",
32297
+ displayName: "Meeting Pack",
32298
+ description: "Generate meeting artifact packages with summaries, decisions, action items, follow-up email, timeline, project export, and manifest",
32299
+ category: "Productivity & Organization",
32300
+ kind: "instruction",
32301
+ tags: ["meeting", "summary", "action-items", "decisions"]
32302
+ },
32303
+ {
32304
+ name: "file-organizer",
32305
+ displayName: "File Organizer",
32306
+ description: "Organize files into structured directories based on type, date, or content",
32307
+ category: "Productivity & Organization",
32308
+ tags: ["files", "organization", "sorting", "cleanup"]
32309
+ },
32310
+ {
32311
+ name: "folder-tree",
32312
+ displayName: "Folder Tree",
32313
+ description: "Generate and display folder tree structures for documentation",
32314
+ category: "Productivity & Organization",
32315
+ tags: ["folder", "tree", "structure", "visualization"]
32316
+ },
32317
+ {
32318
+ name: "form-filler",
32319
+ displayName: "Form Filler",
32320
+ description: "Automatically fill out web forms and document templates",
32321
+ category: "Productivity & Organization",
32322
+ tags: ["forms", "automation", "filling", "data-entry"]
32323
+ },
32324
+ {
32325
+ name: "merge-pdfs",
32326
+ displayName: "Merge PDFs",
32327
+ description: "Merge multiple PDF files into a single document",
32328
+ category: "Productivity & Organization",
32329
+ tags: ["pdf", "merge", "documents", "combining"]
32330
+ },
32331
+ {
32332
+ name: "split-pdf",
32333
+ displayName: "Split PDF",
32334
+ description: "Split PDF documents into separate pages or sections",
32335
+ category: "Productivity & Organization",
32336
+ tags: ["pdf", "split", "documents", "pages"]
32337
+ }
32338
+ ];
32339
+
32340
+ // src/lib/registry-data/project-management.ts
32341
+ var PROJECT_MANAGEMENT_SKILLS = [
32342
+ {
32343
+ name: "businessactivity",
32344
+ displayName: "Business Activity",
32345
+ description: "Business activity, workflow, and ownership management service",
32346
+ category: "Project Management",
32347
+ tags: ["business", "workflow", "activities", "management"]
32348
+ },
32349
+ {
32350
+ name: "implementation",
32351
+ displayName: "Implementation",
32352
+ description: "Create .implementation scaffold for project development tracking",
32353
+ category: "Project Management",
32354
+ tags: ["implementation", "tracking", "scaffold", "project"]
32355
+ },
32356
+ {
32357
+ name: "implementation-plan",
32358
+ displayName: "Implementation Plan",
32359
+ description: "Generate detailed implementation plans with phases and milestones",
32360
+ category: "Project Management",
32361
+ tags: ["implementation", "planning", "milestones", "phases"]
32362
+ },
32363
+ {
32364
+ name: "implementation-todo",
32365
+ displayName: "Implementation Todo",
32366
+ description: "Manage implementation task lists and todo items",
32367
+ category: "Project Management",
32368
+ tags: ["implementation", "todo", "tasks", "tracking"]
32369
+ },
32370
+ {
32371
+ name: "todos-plan",
32372
+ displayName: "Todos Plan",
32373
+ description: "Author, sync, route, and verify Todos plans using Todos CLI plan IDs as source of truth",
32374
+ category: "Project Management",
32375
+ tags: ["todos", "plans", "tasks", "verification", "workflow"]
32376
+ }
32377
+ ];
32378
+
32379
+ // src/lib/registry-data/content-generation.ts
32380
+ var CONTENT_GENERATION_SKILLS = [
32381
+ {
32382
+ name: "pdf-generate",
32383
+ displayName: "PDF Generate",
32384
+ description: "Generate PDF documents with rich formatting and layouts",
32385
+ category: "Content Generation",
32386
+ tags: ["pdf", "document", "generation", "formatting"]
32387
+ },
32388
+ {
32389
+ name: "slide-deck-generator",
32390
+ displayName: "Slide Deck Generator",
32391
+ description: "Generate slide decks from briefs, docs, or outlines with PDF, PPTX, speaker notes, and structured slide metadata",
32392
+ category: "Content Generation",
32393
+ tags: ["presentation", "slides", "deck", "documents"]
32394
+ },
32395
+ {
32396
+ name: "generate-qrcode",
32397
+ displayName: "Generate QR Code",
32398
+ description: "Generate QR codes with custom styling and embedded data",
32399
+ category: "Content Generation",
32400
+ tags: ["qrcode", "generation", "encoding", "visual"]
32401
+ },
32402
+ {
32403
+ name: "generate-resume",
32404
+ displayName: "Generate Resume",
32405
+ description: "Generate professional resumes with formatting and content optimization",
32406
+ category: "Content Generation",
32407
+ tags: ["resume", "cv", "career", "generation"]
32408
+ }
32409
+ ];
32410
+
32411
+ // src/lib/registry-data/finance-compliance.ts
32412
+ var FINANCE_COMPLIANCE_SKILLS = [
32413
+ {
32414
+ name: "contract-review-report",
32415
+ displayName: "Contract Review Report",
32416
+ description: "Generate contract review reports with risk register, clause summary, redline suggestions, negotiation email, and manifest artifacts",
32417
+ category: "Finance & Compliance",
32418
+ kind: "instruction",
32419
+ tags: ["contract", "legal", "review", "risk"]
32420
+ },
32421
+ {
32422
+ name: "invoice",
32423
+ displayName: "Invoice",
32424
+ description: "Generate professional invoices with company management and PDF export",
32425
+ category: "Finance & Compliance",
32426
+ tags: ["invoice", "billing", "pdf", "finance"]
32427
+ },
32428
+ {
32429
+ name: "invoice-reconciliation",
32430
+ displayName: "Invoice Reconciliation",
32431
+ description: "Generate invoice reconciliation reports with matched payments, discrepancies, anomaly notes, summaries, and manifest artifacts",
32432
+ category: "Finance & Compliance",
32433
+ tags: ["invoice", "payments", "reconciliation", "finance"]
32434
+ }
32435
+ ];
32436
+
32437
+ // src/lib/registry-data/data-analysis.ts
32438
+ var DATA_ANALYSIS_SKILLS = [
32439
+ {
32440
+ name: "analyze-data",
32441
+ displayName: "Analyze Data",
32442
+ description: "Data science insights for CSV and JSON datasets with statistical analysis",
32443
+ category: "Data & Analysis",
32444
+ tags: ["data", "analysis", "csv", "json", "statistics"]
32445
+ },
32446
+ {
32447
+ name: "dashboard-builder",
32448
+ displayName: "Dashboard Builder",
32449
+ description: "Build data dashboards with charts, metrics, and visualizations",
32450
+ category: "Data & Analysis",
32451
+ tags: ["dashboard", "visualization", "charts", "metrics"]
32452
+ },
32453
+ {
32454
+ name: "data-anonymizer",
32455
+ displayName: "Data Anonymizer",
32456
+ description: "Anonymize sensitive data in datasets for privacy compliance",
32457
+ category: "Data & Analysis",
32458
+ tags: ["anonymization", "privacy", "data", "compliance"]
32459
+ },
32460
+ {
32461
+ name: "generate-chart",
32462
+ displayName: "Generate Chart",
32463
+ description: "Generate data charts and visualizations from datasets",
32464
+ category: "Data & Analysis",
32465
+ tags: ["charts", "visualization", "data", "graphs"]
32466
+ },
32467
+ {
32468
+ name: "read-csv",
32469
+ displayName: "Read CSV",
32470
+ description: "Parse CSV files into structured JSON with delimiter and encoding detection",
32471
+ category: "Data & Analysis",
32472
+ tags: ["csv", "parsing", "tabular", "data"]
32473
+ },
32474
+ {
32475
+ name: "read-excel",
32476
+ displayName: "Read Excel",
32477
+ description: "Parse XLS and XLSX workbooks into structured JSON with sheet and formatted cell metadata",
32478
+ category: "Data & Analysis",
32479
+ tags: ["excel", "spreadsheet", "xlsx", "data"]
32480
+ },
32481
+ {
32482
+ name: "pdf-to-markdown",
32483
+ displayName: "PDF to Markdown",
32484
+ description: "Convert PDFs into clean markdown with remote extraction and structure cleanup",
32485
+ category: "Data & Analysis",
32486
+ tags: ["pdf", "markdown", "conversion"]
32487
+ },
32488
+ {
32489
+ name: "pdf-to-dataset",
32490
+ displayName: "PDF to Dataset",
32491
+ description: "Extract PDF tables, forms, invoices, and semi-structured content into CSV and JSON datasets",
32492
+ category: "Data & Analysis",
32493
+ tags: ["pdf", "dataset", "csv", "json", "extraction"]
32494
+ },
32495
+ {
32496
+ name: "doc-read",
32497
+ displayName: "Doc Read",
32498
+ description: "Read and extract text from DOCX files with section parsing and metadata extraction",
32499
+ category: "Data & Analysis",
32500
+ tags: ["docx", "reader", "extraction", "word"]
32501
+ }
32502
+ ];
32503
+
32504
+ // src/lib/registry-data/media-processing.ts
32505
+ var MEDIA_PROCESSING_SKILLS = [
32506
+ {
32507
+ name: "video-highlight-pack",
32508
+ displayName: "Video Highlight Pack",
32509
+ description: "Generate video highlight packages with clip plans, captions, thumbnail briefs, chapter markers, social posts, and edit decisions",
32510
+ category: "Media Processing",
32511
+ kind: "instruction",
32512
+ tags: ["video", "highlights", "clips", "captions"]
32513
+ },
32514
+ {
32515
+ name: "compress-video",
32516
+ displayName: "Compress Video",
32517
+ description: "Compress video files while preserving visual quality using ffmpeg",
32518
+ category: "Media Processing",
32519
+ tags: ["video", "compression", "ffmpeg", "optimization"]
32520
+ },
32521
+ {
32522
+ name: "audio-extract",
32523
+ displayName: "Audio Extract",
32524
+ description: "Extract audio tracks from video files with multiple format support",
32525
+ category: "Media Processing",
32526
+ tags: ["audio", "extraction", "video", "conversion"]
32527
+ },
32528
+ {
32529
+ name: "extract-frames",
32530
+ displayName: "Extract Frames",
32531
+ description: "Extract frames from video files at specified intervals or timestamps",
32532
+ category: "Media Processing",
32533
+ tags: ["frames", "video", "extraction", "images"]
32534
+ },
32535
+ {
32536
+ name: "gif-maker",
32537
+ displayName: "GIF Maker",
32538
+ description: "Create animated GIFs from images, videos, or screen recordings",
32539
+ category: "Media Processing",
32540
+ tags: ["gif", "animation", "images", "video"]
32541
+ },
32542
+ {
32543
+ name: "video-downloader",
32544
+ displayName: "Video Downloader",
32545
+ description: "Download videos from various online platforms and services",
32546
+ category: "Media Processing",
32547
+ tags: ["video", "download", "platforms", "media"]
32548
+ },
32549
+ {
32550
+ name: "watermark",
32551
+ displayName: "Watermark",
32552
+ description: "Add watermarks to images and documents for copyright protection",
32553
+ category: "Media Processing",
32554
+ tags: ["watermark", "protection", "copyright", "images"]
32555
+ }
32556
+ ];
32557
+
32558
+ // src/lib/registry-data/design-branding.ts
32559
+ var DESIGN_BRANDING_SKILLS = [
32560
+ {
32561
+ name: "brand-kit",
32562
+ displayName: "Brand Kit",
32563
+ description: "Generate brand kits with logo usage, palette, typography, brand voice, sample applications, Markdown guide, PDF guide, and SVG assets",
32564
+ category: "Design & Branding",
32565
+ kind: "instruction",
32566
+ tags: ["brand", "design", "palette", "typography"]
32567
+ },
32568
+ {
32569
+ name: "brand-assets",
32570
+ displayName: "Brand Assets",
32571
+ description: "Fetch official brand assets from a website or brand name with logos, PNG sizes, palette, typography, source metadata, and manifests",
32572
+ category: "Design & Branding",
32573
+ tags: ["brand", "logo", "assets", "palette", "typography"]
32574
+ },
32575
+ {
32576
+ name: "logo-design",
32577
+ displayName: "Logo Design",
32578
+ description: "Generate multi-variant logo packages with transparent PNGs, vector-style SVGs, usage notes, and manifests",
32579
+ category: "Design & Branding",
32580
+ tags: ["logo", "design", "branding", "identity"]
32581
+ },
32582
+ {
32583
+ name: "generate-favicon",
32584
+ displayName: "Generate Favicon",
32585
+ description: "Generate favicons in multiple sizes and formats for websites",
32586
+ category: "Design & Branding",
32587
+ tags: ["favicon", "icon", "design", "web"]
32588
+ },
32589
+ {
32590
+ name: "product-mockup",
32591
+ displayName: "Product Mockup",
32592
+ description: "Generate product mockup packages with visual variants, prompts, usage notes, and asset metadata",
32593
+ category: "Design & Branding",
32594
+ tags: ["product", "mockup", "visualization", "marketing"]
32595
+ },
32596
+ {
32597
+ name: "siteanalyze",
32598
+ displayName: "Site Analyze",
32599
+ description: "Analyze any website's design system \u2014 detects shadcn/ui, Tailwind, extracts colors, typography, and components via Playwright + Claude Vision.",
32600
+ category: "Design & Branding",
32601
+ tags: ["design", "shadcn", "tailwind", "colors", "typography", "playwright", "analysis", "open-styles"]
32602
+ }
32603
+ ];
32604
+
32605
+ // src/lib/registry-data/web-browser.ts
32606
+ var WEB_BROWSER_SKILLS = [
32607
+ {
32608
+ name: "domainpurchase",
32609
+ displayName: "Domain Purchase",
32610
+ description: "Purchase and manage domains via registrar connectors",
32611
+ category: "Web & Browser",
32612
+ tags: ["domain", "purchase", "registrar", "management"]
32613
+ }
32614
+ ];
32615
+
32616
+ // src/lib/registry-data/research-writing.ts
32617
+ var RESEARCH_WRITING_SKILLS = [
32618
+ {
32619
+ name: "blog-article",
32620
+ displayName: "Blog Article",
32621
+ description: "Create SEO-optimized blog article artifact packages",
32622
+ category: "Research & Writing",
32623
+ kind: "instruction",
32624
+ tags: ["blog", "article", "writing", "seo"]
32625
+ },
32626
+ {
32627
+ name: "market-research-report",
32628
+ displayName: "Market Research Report",
32629
+ description: "Generate market research packages with competitor tables, positioning, pricing notes, source notes, and PDF/Markdown artifacts",
32630
+ category: "Research & Writing",
32631
+ kind: "instruction",
32632
+ tags: ["market-research", "competitors", "positioning", "pricing", "report"]
32633
+ }
32634
+ ];
32635
+
32636
+ // src/lib/registry-data/science-academic.ts
32637
+ var SCIENCE_ACADEMIC_SKILLS = [
32638
+ {
32639
+ name: "bio-sequence-tool",
32640
+ displayName: "Bio Sequence Tool",
32641
+ description: "Analyze and manipulate biological sequences including DNA, RNA, and protein data",
32642
+ category: "Science & Academic",
32643
+ tags: ["biology", "dna", "sequence", "bioinformatics"]
32644
+ },
32645
+ {
32646
+ name: "experiment-power-calculator",
32647
+ displayName: "Experiment Power Calculator",
32648
+ description: "Calculate statistical power and sample size for experiments",
32649
+ category: "Science & Academic",
32650
+ tags: ["experiment", "statistics", "power-analysis", "sample-size"]
32651
+ },
32652
+ {
32653
+ name: "latex-table-generator",
32654
+ displayName: "LaTeX Table Generator",
32655
+ description: "Generate formatted LaTeX tables from data for academic papers",
32656
+ category: "Science & Academic",
32657
+ tags: ["latex", "tables", "academic", "formatting"]
32658
+ },
32659
+ {
32660
+ name: "scientific-figure-check",
32661
+ displayName: "Scientific Figure Check",
32662
+ description: "Validate scientific figures for accuracy, formatting, and publication standards",
32663
+ category: "Science & Academic",
32664
+ tags: ["scientific", "figures", "validation", "publishing"]
32665
+ },
32666
+ {
32667
+ name: "statistical-test-selector",
32668
+ displayName: "Statistical Test Selector",
32669
+ description: "Recommend appropriate statistical tests based on data and research questions",
32670
+ category: "Science & Academic",
32671
+ tags: ["statistics", "test-selection", "research", "analysis"]
32672
+ }
32673
+ ];
32674
+
32675
+ // src/lib/registry-data/education-learning.ts
32676
+ var EDUCATION_LEARNING_SKILLS = [];
32677
+
32678
+ // src/lib/registry-data/communication.ts
32679
+ var COMMUNICATION_SKILLS = [];
32680
+
32681
+ // src/lib/registry-data/health-wellness.ts
32682
+ var HEALTH_WELLNESS_SKILLS = [];
32683
+
32684
+ // src/lib/registry-data/travel-lifestyle.ts
32685
+ var TRAVEL_LIFESTYLE_SKILLS = [];
32686
+
32687
+ // src/lib/registry-data/event-management.ts
32688
+ var EVENT_MANAGEMENT_SKILLS = [];
32689
+
32690
+ // src/lib/registry-data/index.ts
32691
+ var SKILLS = [
32692
+ ...DEVELOPMENT_TOOLS_SKILLS,
32693
+ ...BUSINESS_MARKETING_SKILLS,
32694
+ ...PRODUCTIVITY_ORGANIZATION_SKILLS,
32695
+ ...PROJECT_MANAGEMENT_SKILLS,
32696
+ ...CONTENT_GENERATION_SKILLS,
32697
+ ...FINANCE_COMPLIANCE_SKILLS,
32698
+ ...DATA_ANALYSIS_SKILLS,
32699
+ ...MEDIA_PROCESSING_SKILLS,
32700
+ ...DESIGN_BRANDING_SKILLS,
32701
+ ...WEB_BROWSER_SKILLS,
32702
+ ...RESEARCH_WRITING_SKILLS,
32703
+ ...SCIENCE_ACADEMIC_SKILLS,
32704
+ ...EDUCATION_LEARNING_SKILLS,
32705
+ ...COMMUNICATION_SKILLS,
32706
+ ...HEALTH_WELLNESS_SKILLS,
32707
+ ...TRAVEL_LIFESTYLE_SKILLS,
32708
+ ...EVENT_MANAGEMENT_SKILLS
32709
+ ];
32710
+
32711
+ // src/lib/hosted-skill-set.ts
32712
+ var HOSTED_RUNTIMES = new Set(["hosted"]);
32713
+ var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
32714
+ var HOSTED_METADATA_SET_EMPTY_ERROR = [
32715
+ "The hosted metadata skill set is empty, but the packaging guards that depend on it",
32716
+ "only mean anything while it is non-empty: an empty set makes every one of them pass",
32717
+ "vacuously and silently removes the protection that keeps hosted implementation source",
32718
+ "out of the published package.",
32719
+ "",
32720
+ "If emptying the set is intentional (every hosted skill was deleted or converted to a",
32721
+ "runnable in-repo skill), retire the derived guards in the SAME change \u2014 do not let them",
32722
+ "stay green and empty."
32723
+ ].join(`
32724
+ `);
32725
+ var SLUG = "[^,{}/]+";
32726
+ var BRACE_SOURCE_EXCLUSION = new RegExp(`^!skills/\\{(${SLUG}(?:,${SLUG})+)\\}/src$`);
32727
+ var SINGLE_SOURCE_EXCLUSION = new RegExp(`^!skills/(${SLUG})/src$`);
32728
+
32729
+ // src/lib/skill-validation.ts
32730
+ var RESERVED_SKILL_ENTRIES = new Set([
32731
+ ".env",
32732
+ ".npmrc",
32733
+ ".pypirc",
32734
+ ".netrc",
32735
+ "id_rsa",
32736
+ "id_ed25519"
32737
+ ]);
32738
+ var KNOWN_TOP_LEVEL_ENTRIES = new Set([
32739
+ ".claude",
32740
+ ".env.example",
32741
+ ".gitignore",
32742
+ ".skills",
32743
+ "CLAUDE.md",
32744
+ "AGENTS.md",
32745
+ "LICENSE",
32746
+ "PROJECT_OVERVIEW.md",
32747
+ "QUICKSTART.md",
32748
+ "README.md",
32749
+ "SKILL.md",
32750
+ "api-docs-list.json",
32751
+ "auth.ts",
32752
+ "bun.lock",
32753
+ "bunfig.toml",
32754
+ "data",
32755
+ "dist",
32756
+ "examples",
32757
+ "exports",
32758
+ "http-client.ts",
32759
+ "index.ts",
32760
+ "install.sh",
32761
+ "installer.ts",
32762
+ "logs",
32763
+ "node_modules",
32764
+ "package.json",
32765
+ "scripts",
32766
+ "skill-install.ts",
32767
+ "skill.json",
32768
+ "src",
32769
+ "tests",
32770
+ "references",
32771
+ "assets",
32772
+ "tsconfig.json",
32773
+ "vision.ts"
32774
+ ]);
32775
+ var VALID_PROVENANCE_SOURCES = new Set(["official", "custom", "remote", "private", "private-hosted", "upstream", "extension"]);
32776
+
32777
+ // src/lib/portable-skills-files.ts
32778
+ var ANY_SEGMENT_COPY_EXCLUDES = new Set([
32779
+ ".git",
32780
+ ".DS_Store",
32781
+ ".system",
32782
+ "node_modules"
32783
+ ]);
32784
+ var FIRST_SEGMENT_COPY_EXCLUDES = new Set([
32785
+ "dist",
32786
+ "build",
32787
+ ".turbo"
32788
+ ]);
32789
+ // src/lib/portable-skills.ts
32790
+ var OFFICIAL_SKILL_NAMES = new Set(SKILLS.map((skill) => skill.name));
32791
+ // src/lib/installer.ts
32792
+ import { existsSync as existsSync3, readFileSync as readFileSync4, rmSync } from "fs";
32793
+ import { dirname as dirname6, join as join7 } from "path";
32794
+ import { fileURLToPath as fileURLToPath3 } from "url";
32795
+
32796
+ // src/lib/agent-sync.ts
32797
+ import { basename, dirname as dirname5, join as join6 } from "path";
32798
+ import { fileURLToPath as fileURLToPath2 } from "url";
32799
+ var __dirname2 = dirname5(fileURLToPath2(import.meta.url));
32800
+
32801
+ // src/lib/installer.ts
32802
+ var __dirname3 = dirname6(fileURLToPath3(import.meta.url));
32803
+ function findSkillsDir() {
32804
+ let dir = __dirname3;
32805
+ for (let i3 = 0;i3 < 5; i3++) {
32806
+ const candidate = join7(dir, "skills");
32807
+ if (existsSync3(candidate) && !dir.includes(".skills"))
32808
+ return candidate;
32809
+ dir = dirname6(dir);
32810
+ }
32811
+ return join7(__dirname3, "..", "skills");
32812
+ }
32813
+ var SKILLS_DIR = findSkillsDir();
32814
+
32815
+ // src/server/skills-api.ts
32816
+ var MAX_SKILL_MD_BYTES = 512000;
32817
+ var MAX_MANIFEST_BYTES = MAX_SKILL_MD_BYTES + 64000;
32818
+ var ALLOWED_PUBLISH_PARTS = new Set(["manifest", "bundle"]);
32819
+
32820
+ // src/server/app.ts
32821
+ function assertDurableStore(store, config) {
32822
+ const backend = store.backend;
32823
+ if (!backend || backend.durable)
32824
+ return;
32825
+ assertDurableTarget(backend, config);
32826
+ }
32827
+ function assertDurableTarget(target, config) {
32828
+ if (target.durable || config.allowEphemeralStore)
32829
+ return;
32830
+ throw new Error(`refusing to start: the configured store is ${target.label} and does not survive a restart. ` + "Leave HASNA_SKILLS_DATABASE_URL unset to use the durable SQLite database in the skills data " + "directory, or point it at a postgres:// URL. Set HASNA_SKILLS_ALLOW_EPHEMERAL_STORE=1 only if " + "losing every run on restart is genuinely what you want.");
32831
+ }
32832
+
30910
32833
  // src/server/worker.ts
30911
- async function runWorkerOnce(store, workerId = `worker_${randomUUID2().slice(0, 8)}`, storage = new ArtifactStorage) {
32834
+ async function runWorkerOnce(store, workerId = `worker_${randomUUID4().slice(0, 8)}`, storage = new ArtifactStorage) {
30912
32835
  const run = await store.claimNextRun({ workerId });
30913
32836
  if (!run)
30914
32837
  return false;
@@ -30922,16 +32845,31 @@ async function runWorkerOnce(store, workerId = `worker_${randomUUID2().slice(0,
30922
32845
  if (import.meta.main) {
30923
32846
  const config = resolveServerConfig();
30924
32847
  const store = await createStore({ databaseUrl: config.databaseUrl, bootstrapApiKey: config.bootstrapApiKey });
32848
+ assertDurableStore(store, config);
30925
32849
  const storage = new ArtifactStorage({ bucket: config.artifactBucket, prefix: config.artifactPrefix });
30926
- const workerId = process.env.HASNA_SKILLS_WORKER_ID || `worker_${randomUUID2().slice(0, 8)}`;
32850
+ console.log(`skills worker ${process.env.HASNA_SKILLS_WORKER_ID || ""} storage: ${resolveDatabaseTarget(config.databaseUrl).label}`);
32851
+ const workerId = process.env.HASNA_SKILLS_WORKER_ID || `worker_${randomUUID4().slice(0, 8)}`;
30927
32852
  const once = process.argv.includes("--once");
30928
32853
  const idleMs = Number.parseInt(process.env.HASNA_SKILLS_WORKER_IDLE_MS || "1000", 10);
32854
+ const pause = Number.isFinite(idleMs) ? idleMs : 1000;
32855
+ let consecutiveErrors = 0;
30929
32856
  do {
30930
- const processed = await runWorkerOnce(store, workerId, storage);
32857
+ let processed = false;
32858
+ try {
32859
+ processed = await runWorkerOnce(store, workerId, storage);
32860
+ consecutiveErrors = 0;
32861
+ } catch (error) {
32862
+ consecutiveErrors += 1;
32863
+ console.error(`worker ${workerId}: claim/execute failed (${consecutiveErrors} in a row):`, error.message);
32864
+ if (once)
32865
+ process.exit(1);
32866
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pause * consecutiveErrors, 30000)));
32867
+ continue;
32868
+ }
30931
32869
  if (once)
30932
32870
  process.exit(processed ? 0 : 2);
30933
32871
  if (!processed)
30934
- await new Promise((resolve) => setTimeout(resolve, Number.isFinite(idleMs) ? idleMs : 1000));
32872
+ await new Promise((resolve) => setTimeout(resolve, pause));
30935
32873
  } while (true);
30936
32874
  }
30937
32875
  export {