glirastes 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +146 -9
  3. package/codegen/package.json +5 -0
  4. package/dist/cjs/codegen/asset-sync.d.ts +20 -0
  5. package/dist/cjs/codegen/asset-sync.js +28 -0
  6. package/dist/cjs/codegen/coverage.d.ts +66 -0
  7. package/dist/cjs/codegen/coverage.js +408 -0
  8. package/dist/cjs/codegen/endpoint-scanner.d.ts +16 -0
  9. package/dist/cjs/codegen/endpoint-scanner.js +197 -0
  10. package/dist/cjs/codegen/format.d.ts +17 -0
  11. package/dist/cjs/codegen/format.js +34 -0
  12. package/dist/cjs/codegen/fs-utils.d.ts +45 -0
  13. package/dist/cjs/codegen/fs-utils.js +165 -0
  14. package/dist/cjs/codegen/index.d.ts +13 -0
  15. package/dist/cjs/codegen/index.js +33 -0
  16. package/dist/cjs/codegen/mcp-generator.d.ts +50 -0
  17. package/dist/cjs/codegen/mcp-generator.js +803 -0
  18. package/dist/cjs/codegen/module-generator.d.ts +11 -0
  19. package/dist/cjs/codegen/module-generator.js +353 -0
  20. package/dist/cjs/codegen/nestjs-scanner.d.ts +43 -0
  21. package/dist/cjs/codegen/nestjs-scanner.js +241 -0
  22. package/dist/cjs/codegen/output-recommender.d.ts +23 -0
  23. package/dist/cjs/codegen/output-recommender.js +33 -0
  24. package/dist/cjs/codegen/scaffolder.d.ts +36 -0
  25. package/dist/cjs/codegen/scaffolder.js +262 -0
  26. package/dist/cjs/codegen/skill-generator.d.ts +49 -0
  27. package/dist/cjs/codegen/skill-generator.js +967 -0
  28. package/dist/cjs/codegen/types.d.ts +52 -0
  29. package/dist/cjs/codegen/types.js +16 -0
  30. package/dist/cjs/codegen/ui-scanner.d.ts +24 -0
  31. package/dist/cjs/codegen/ui-scanner.js +202 -0
  32. package/dist/cjs/codegen/validator.d.ts +35 -0
  33. package/dist/cjs/codegen/validator.js +292 -0
  34. package/dist/cjs/index.d.ts +1 -0
  35. package/dist/cjs/index.js +23 -0
  36. package/dist/cjs/openapi/index.d.ts +78 -0
  37. package/dist/cjs/openapi/index.js +347 -0
  38. package/dist/cjs/package.json +1 -0
  39. package/dist/cjs/react/audio-worklet-processor.d.ts +16 -0
  40. package/dist/cjs/react/audio-worklet-processor.js +27 -0
  41. package/dist/cjs/react/bridges/rest-session-bridge.d.ts +113 -0
  42. package/dist/cjs/react/bridges/rest-session-bridge.js +209 -0
  43. package/dist/cjs/react/components/ai-chat-panel.d.ts +12 -0
  44. package/dist/cjs/react/components/ai-chat-panel.js +67 -0
  45. package/dist/cjs/react/components/ai-trigger-button.d.ts +2 -0
  46. package/dist/cjs/react/components/ai-trigger-button.js +239 -0
  47. package/dist/cjs/react/components/approval-card.d.ts +9 -0
  48. package/dist/cjs/react/components/approval-card.js +24 -0
  49. package/dist/cjs/react/components/bulk-approval-card.d.ts +9 -0
  50. package/dist/cjs/react/components/bulk-approval-card.js +36 -0
  51. package/dist/cjs/react/components/chat-input.d.ts +10 -0
  52. package/dist/cjs/react/components/chat-input.js +60 -0
  53. package/dist/cjs/react/components/chat-window.d.ts +2 -0
  54. package/dist/cjs/react/components/chat-window.js +134 -0
  55. package/dist/cjs/react/components/confirm-dialog.d.ts +32 -0
  56. package/dist/cjs/react/components/confirm-dialog.js +48 -0
  57. package/dist/cjs/react/components/floating-chat-ui.d.ts +90 -0
  58. package/dist/cjs/react/components/floating-chat-ui.js +163 -0
  59. package/dist/cjs/react/components/mention-chip.d.ts +16 -0
  60. package/dist/cjs/react/components/mention-chip.js +42 -0
  61. package/dist/cjs/react/components/mention-input.d.ts +8 -0
  62. package/dist/cjs/react/components/mention-input.js +117 -0
  63. package/dist/cjs/react/components/message-bubble.d.ts +11 -0
  64. package/dist/cjs/react/components/message-bubble.js +171 -0
  65. package/dist/cjs/react/components/message-list.d.ts +8 -0
  66. package/dist/cjs/react/components/message-list.js +52 -0
  67. package/dist/cjs/react/components/pipeline-timeline.d.ts +7 -0
  68. package/dist/cjs/react/components/pipeline-timeline.js +72 -0
  69. package/dist/cjs/react/components/recording-bar.d.ts +2 -0
  70. package/dist/cjs/react/components/recording-bar.js +81 -0
  71. package/dist/cjs/react/components/recording-controls.d.ts +18 -0
  72. package/dist/cjs/react/components/recording-controls.js +38 -0
  73. package/dist/cjs/react/components/rich-mention-input.d.ts +2 -0
  74. package/dist/cjs/react/components/rich-mention-input.js +571 -0
  75. package/dist/cjs/react/components/session-switcher.d.ts +14 -0
  76. package/dist/cjs/react/components/session-switcher.js +133 -0
  77. package/dist/cjs/react/components/suggestion-bar.d.ts +9 -0
  78. package/dist/cjs/react/components/suggestion-bar.js +47 -0
  79. package/dist/cjs/react/components/suggestion-chip.d.ts +9 -0
  80. package/dist/cjs/react/components/suggestion-chip.js +14 -0
  81. package/dist/cjs/react/components/voice-input-addon.d.ts +13 -0
  82. package/dist/cjs/react/components/voice-input-addon.js +31 -0
  83. package/dist/cjs/react/components/voice-input-button.d.ts +2 -0
  84. package/dist/cjs/react/components/voice-input-button.js +55 -0
  85. package/dist/cjs/react/components/wavesurfer-loader.d.ts +5 -0
  86. package/dist/cjs/react/components/wavesurfer-loader.js +36 -0
  87. package/dist/cjs/react/hooks/use-ai-chat.d.ts +22 -0
  88. package/dist/cjs/react/hooks/use-ai-chat.js +51 -0
  89. package/dist/cjs/react/hooks/use-approvals.d.ts +23 -0
  90. package/dist/cjs/react/hooks/use-approvals.js +63 -0
  91. package/dist/cjs/react/hooks/use-deepgram-transcription.d.ts +2 -0
  92. package/dist/cjs/react/hooks/use-deepgram-transcription.js +329 -0
  93. package/dist/cjs/react/hooks/use-drag-resize-panel.d.ts +48 -0
  94. package/dist/cjs/react/hooks/use-drag-resize-panel.js +308 -0
  95. package/dist/cjs/react/hooks/use-draggable-position.d.ts +25 -0
  96. package/dist/cjs/react/hooks/use-draggable-position.js +134 -0
  97. package/dist/cjs/react/hooks/use-keyboard-shortcut.d.ts +20 -0
  98. package/dist/cjs/react/hooks/use-keyboard-shortcut.js +93 -0
  99. package/dist/cjs/react/hooks/use-mentions.d.ts +23 -0
  100. package/dist/cjs/react/hooks/use-mentions.js +42 -0
  101. package/dist/cjs/react/hooks/use-suggestions.d.ts +22 -0
  102. package/dist/cjs/react/hooks/use-suggestions.js +39 -0
  103. package/dist/cjs/react/index.d.ts +43 -0
  104. package/dist/cjs/react/index.js +111 -0
  105. package/dist/cjs/react/provider/ai-chat-provider.d.ts +45 -0
  106. package/dist/cjs/react/provider/ai-chat-provider.js +1024 -0
  107. package/dist/cjs/react/provider/chat-context.d.ts +84 -0
  108. package/dist/cjs/react/provider/chat-context.js +13 -0
  109. package/dist/cjs/react/template.d.ts +84 -0
  110. package/dist/cjs/react/template.js +90 -0
  111. package/dist/cjs/react/themes.d.ts +24 -0
  112. package/dist/cjs/react/themes.js +273 -0
  113. package/dist/cjs/react/transports/langgraph/index.d.ts +2 -0
  114. package/dist/cjs/react/transports/langgraph/index.js +8 -0
  115. package/dist/cjs/react/transports/langgraph/langgraph-ai-chat.d.ts +62 -0
  116. package/dist/cjs/react/transports/langgraph/langgraph-ai-chat.js +94 -0
  117. package/dist/cjs/react/transports/langgraph.d.ts +71 -0
  118. package/dist/cjs/react/transports/langgraph.js +369 -0
  119. package/dist/cjs/react/transports/vercel/index.d.ts +2 -0
  120. package/dist/cjs/react/transports/vercel/index.js +8 -0
  121. package/dist/cjs/react/transports/vercel/vercel-ai-chat.d.ts +49 -0
  122. package/dist/cjs/react/transports/vercel/vercel-ai-chat.js +81 -0
  123. package/dist/cjs/react/transports/vercel.d.ts +30 -0
  124. package/dist/cjs/react/transports/vercel.js +69 -0
  125. package/dist/cjs/react/types.d.ts +760 -0
  126. package/dist/cjs/react/types.js +2 -0
  127. package/dist/cjs/react/ui.d.ts +73 -0
  128. package/dist/cjs/react/ui.js +183 -0
  129. package/dist/cjs/react/utils/create-approval-description.d.ts +53 -0
  130. package/dist/cjs/react/utils/create-approval-description.js +122 -0
  131. package/dist/cjs/react/utils/create-tool-result-handler.d.ts +90 -0
  132. package/dist/cjs/react/utils/create-tool-result-handler.js +168 -0
  133. package/dist/cjs/react/utils/mention-markup.d.ts +13 -0
  134. package/dist/cjs/react/utils/mention-markup.js +117 -0
  135. package/dist/cjs/react/utils/merge-pipeline-steps.d.ts +19 -0
  136. package/dist/cjs/react/utils/merge-pipeline-steps.js +81 -0
  137. package/dist/cjs/react/utils/sanitize-stored-messages.d.ts +23 -0
  138. package/dist/cjs/react/utils/sanitize-stored-messages.js +52 -0
  139. package/dist/cjs/server/adapters/nestjs/chat/ai-chat-auth.guard.d.ts +10 -0
  140. package/dist/cjs/server/adapters/nestjs/chat/ai-chat-auth.guard.js +42 -0
  141. package/dist/cjs/server/adapters/nestjs/chat/ai-chat-module-options.interface.d.ts +32 -0
  142. package/dist/cjs/server/adapters/nestjs/chat/ai-chat-module-options.interface.js +4 -0
  143. package/dist/cjs/server/adapters/nestjs/chat/ai-chat.controller.d.ts +11 -0
  144. package/dist/cjs/server/adapters/nestjs/chat/ai-chat.controller.js +80 -0
  145. package/dist/cjs/server/adapters/nestjs/chat/ai-chat.module.d.ts +9 -0
  146. package/dist/cjs/server/adapters/nestjs/chat/ai-chat.module.js +119 -0
  147. package/dist/cjs/server/adapters/nestjs/chat/ai-chat.service.d.ts +13 -0
  148. package/dist/cjs/server/adapters/nestjs/chat/ai-chat.service.js +131 -0
  149. package/dist/cjs/server/adapters/nestjs/chat/dto/ai-chat-request.dto.d.ts +7 -0
  150. package/dist/cjs/server/adapters/nestjs/chat/dto/ai-chat-request.dto.js +52 -0
  151. package/dist/cjs/server/adapters/nestjs/chat/dto/chat-message-part.dto.d.ts +19 -0
  152. package/dist/cjs/server/adapters/nestjs/chat/dto/chat-message-part.dto.js +108 -0
  153. package/dist/cjs/server/adapters/nestjs/chat/dto/chat-message.dto.d.ts +8 -0
  154. package/dist/cjs/server/adapters/nestjs/chat/dto/chat-message.dto.js +59 -0
  155. package/dist/cjs/server/adapters/nestjs/chat/dto/index.d.ts +3 -0
  156. package/dist/cjs/server/adapters/nestjs/chat/dto/index.js +9 -0
  157. package/dist/cjs/server/adapters/nestjs/chat/index.d.ts +3 -0
  158. package/dist/cjs/server/adapters/nestjs/chat/index.js +9 -0
  159. package/dist/cjs/server/adapters/nestjs/chat/speech-stream.gateway.d.ts +4 -0
  160. package/dist/cjs/server/adapters/nestjs/chat/speech-stream.gateway.js +73 -0
  161. package/dist/cjs/server/adapters/nestjs/chat/ws-loader.d.ts +5 -0
  162. package/dist/cjs/server/adapters/nestjs/chat/ws-loader.js +72 -0
  163. package/dist/cjs/server/adapters/nestjs/decorators/ai-module.decorator.d.ts +6 -0
  164. package/dist/cjs/server/adapters/nestjs/decorators/ai-module.decorator.js +13 -0
  165. package/dist/cjs/server/adapters/nestjs/decorators/ai-param.decorator.d.ts +5 -0
  166. package/dist/cjs/server/adapters/nestjs/decorators/ai-param.decorator.js +15 -0
  167. package/dist/cjs/server/adapters/nestjs/decorators/ai-tool.decorator.d.ts +6 -0
  168. package/dist/cjs/server/adapters/nestjs/decorators/ai-tool.decorator.js +22 -0
  169. package/dist/cjs/server/adapters/nestjs/decorators/constants.d.ts +4 -0
  170. package/dist/cjs/server/adapters/nestjs/decorators/constants.js +7 -0
  171. package/dist/cjs/server/adapters/nestjs/index.d.ts +14 -0
  172. package/dist/cjs/server/adapters/nestjs/index.js +42 -0
  173. package/dist/cjs/server/adapters/nestjs/metadata.d.ts +39 -0
  174. package/dist/cjs/server/adapters/nestjs/metadata.js +36 -0
  175. package/dist/cjs/server/adapters/nestjs/module/ai-tools-explorer.service.d.ts +36 -0
  176. package/dist/cjs/server/adapters/nestjs/module/ai-tools-explorer.service.js +159 -0
  177. package/dist/cjs/server/adapters/nestjs/module/ai-tools.module.d.ts +37 -0
  178. package/dist/cjs/server/adapters/nestjs/module/ai-tools.module.js +44 -0
  179. package/dist/cjs/server/adapters/nestjs/module/ai-tools.service.d.ts +28 -0
  180. package/dist/cjs/server/adapters/nestjs/module/ai-tools.service.js +41 -0
  181. package/dist/cjs/server/adapters/nestjs/scanner/nestjs-scanner.d.ts +16 -0
  182. package/dist/cjs/server/adapters/nestjs/scanner/nestjs-scanner.js +117 -0
  183. package/dist/cjs/server/adapters/nestjs/scanner/schema-builder.d.ts +26 -0
  184. package/dist/cjs/server/adapters/nestjs/scanner/schema-builder.js +259 -0
  185. package/dist/cjs/server/adapters/nestjs/swagger.d.ts +7 -0
  186. package/dist/cjs/server/adapters/nestjs/swagger.js +39 -0
  187. package/dist/cjs/server/adapters/nextjs/context-helpers.d.ts +22 -0
  188. package/dist/cjs/server/adapters/nextjs/context-helpers.js +60 -0
  189. package/dist/cjs/server/adapters/nextjs/create-ai-chat-handler.d.ts +94 -0
  190. package/dist/cjs/server/adapters/nextjs/create-ai-chat-handler.js +965 -0
  191. package/dist/cjs/server/adapters/nextjs/filter-fallback-error.d.ts +11 -0
  192. package/dist/cjs/server/adapters/nextjs/filter-fallback-error.js +41 -0
  193. package/dist/cjs/server/adapters/nextjs/index.d.ts +8 -0
  194. package/dist/cjs/server/adapters/nextjs/index.js +22 -0
  195. package/dist/cjs/server/adapters/nextjs/prepare-model-messages.d.ts +58 -0
  196. package/dist/cjs/server/adapters/nextjs/prepare-model-messages.js +114 -0
  197. package/dist/cjs/server/adapters/nextjs/sanitize-model-messages.d.ts +64 -0
  198. package/dist/cjs/server/adapters/nextjs/sanitize-model-messages.js +489 -0
  199. package/dist/cjs/server/adapters/nextjs/server-action-helper.d.ts +7 -0
  200. package/dist/cjs/server/adapters/nextjs/server-action-helper.js +40 -0
  201. package/dist/cjs/server/adapters/nextjs/types.d.ts +246 -0
  202. package/dist/cjs/server/adapters/nextjs/types.js +2 -0
  203. package/dist/cjs/server/adapters/nextjs/with-ai-tool.d.ts +9 -0
  204. package/dist/cjs/server/adapters/nextjs/with-ai-tool.js +12 -0
  205. package/dist/cjs/server/core/followup-tool.d.ts +9 -0
  206. package/dist/cjs/server/core/followup-tool.js +82 -0
  207. package/dist/cjs/server/core/index.d.ts +139 -0
  208. package/dist/cjs/server/core/index.js +818 -0
  209. package/dist/cjs/server/core/intent-classifier.d.ts +94 -0
  210. package/dist/cjs/server/core/intent-classifier.js +324 -0
  211. package/dist/cjs/server/core/model-selector.d.ts +12 -0
  212. package/dist/cjs/server/core/model-selector.js +48 -0
  213. package/dist/cjs/server/core/module-router.d.ts +14 -0
  214. package/dist/cjs/server/core/module-router.js +110 -0
  215. package/dist/cjs/server/core/zod-compact.d.ts +18 -0
  216. package/dist/cjs/server/core/zod-compact.js +129 -0
  217. package/dist/cjs/server/index.d.ts +6 -0
  218. package/dist/cjs/server/index.js +28 -0
  219. package/dist/cjs/server/lancer/cache.d.ts +9 -0
  220. package/dist/cjs/server/lancer/cache.js +33 -0
  221. package/dist/cjs/server/lancer/client.d.ts +2 -0
  222. package/dist/cjs/server/lancer/client.js +279 -0
  223. package/dist/cjs/server/lancer/errors.d.ts +13 -0
  224. package/dist/cjs/server/lancer/errors.js +21 -0
  225. package/dist/cjs/server/lancer/index.d.ts +3 -0
  226. package/dist/cjs/server/lancer/index.js +7 -0
  227. package/dist/cjs/server/lancer/telemetry-buffer.d.ts +15 -0
  228. package/dist/cjs/server/lancer/telemetry-buffer.js +64 -0
  229. package/dist/cjs/server/lancer/types.d.ts +201 -0
  230. package/dist/cjs/server/lancer/types.js +5 -0
  231. package/dist/cjs/server/pii-shield/aegis-detector.d.ts +26 -0
  232. package/dist/cjs/server/pii-shield/aegis-detector.js +26 -0
  233. package/dist/cjs/server/pii-shield/create-pii-shield.d.ts +2 -0
  234. package/dist/cjs/server/pii-shield/create-pii-shield.js +191 -0
  235. package/dist/cjs/server/pii-shield/deep-walk.d.ts +1 -0
  236. package/dist/cjs/server/pii-shield/deep-walk.js +19 -0
  237. package/dist/cjs/server/pii-shield/fake-data.d.ts +5 -0
  238. package/dist/cjs/server/pii-shield/fake-data.js +170 -0
  239. package/dist/cjs/server/pii-shield/index.d.ts +4 -0
  240. package/dist/cjs/server/pii-shield/index.js +9 -0
  241. package/dist/cjs/server/pii-shield/leakage.d.ts +1 -0
  242. package/dist/cjs/server/pii-shield/leakage.js +15 -0
  243. package/dist/cjs/server/pii-shield/session-mapping.d.ts +12 -0
  244. package/dist/cjs/server/pii-shield/session-mapping.js +70 -0
  245. package/dist/cjs/server/pipeline.d.ts +26 -0
  246. package/dist/cjs/server/pipeline.js +127 -0
  247. package/dist/cjs/server/testing/approvals.d.ts +11 -0
  248. package/dist/cjs/server/testing/approvals.js +41 -0
  249. package/dist/cjs/server/testing/combination.d.ts +3 -0
  250. package/dist/cjs/server/testing/combination.js +83 -0
  251. package/dist/cjs/server/testing/create-test-suite.d.ts +29 -0
  252. package/dist/cjs/server/testing/create-test-suite.js +81 -0
  253. package/dist/cjs/server/testing/edge-cases.d.ts +8 -0
  254. package/dist/cjs/server/testing/edge-cases.js +277 -0
  255. package/dist/cjs/server/testing/guardrails.d.ts +14 -0
  256. package/dist/cjs/server/testing/guardrails.js +152 -0
  257. package/dist/cjs/server/testing/helpers.d.ts +14 -0
  258. package/dist/cjs/server/testing/helpers.js +119 -0
  259. package/dist/cjs/server/testing/index.d.ts +12 -0
  260. package/dist/cjs/server/testing/index.js +37 -0
  261. package/dist/cjs/server/testing/mock-executor.d.ts +8 -0
  262. package/dist/cjs/server/testing/mock-executor.js +40 -0
  263. package/dist/cjs/server/testing/regression.d.ts +7 -0
  264. package/dist/cjs/server/testing/regression.js +27 -0
  265. package/dist/cjs/server/testing/routing.d.ts +12 -0
  266. package/dist/cjs/server/testing/routing.js +63 -0
  267. package/dist/cjs/server/testing/schema-consistency.d.ts +6 -0
  268. package/dist/cjs/server/testing/schema-consistency.js +56 -0
  269. package/dist/cjs/server/testing/smoke.d.ts +11 -0
  270. package/dist/cjs/server/testing/smoke.js +64 -0
  271. package/dist/cjs/server/testing/types.d.ts +156 -0
  272. package/dist/cjs/server/testing/types.js +2 -0
  273. package/dist/cjs/types.d.ts +696 -0
  274. package/dist/cjs/types.js +91 -0
  275. package/dist/cli/commands/install-skills.d.ts +17 -0
  276. package/dist/cli/commands/install-skills.js +185 -0
  277. package/dist/cli/commands/install-skills.js.map +1 -0
  278. package/dist/cli/index.js +25 -0
  279. package/dist/cli/index.js.map +1 -1
  280. package/dist/react/components/ai-trigger-button.js +4 -6
  281. package/dist/react/components/ai-trigger-button.js.map +1 -1
  282. package/dist/react/components/recording-bar.js +4 -6
  283. package/dist/react/components/recording-bar.js.map +1 -1
  284. package/dist/react/components/wavesurfer-loader.d.ts +5 -0
  285. package/dist/react/components/wavesurfer-loader.js +34 -0
  286. package/dist/react/components/wavesurfer-loader.js.map +1 -0
  287. package/dist/server/adapters/nestjs/chat/ai-chat.module.d.ts +1 -1
  288. package/dist/server/adapters/nestjs/chat/ai-chat.module.js +3 -2
  289. package/dist/server/adapters/nestjs/chat/ai-chat.module.js.map +1 -1
  290. package/dist/server/adapters/nestjs/chat/speech-stream.gateway.d.ts +1 -1
  291. package/dist/server/adapters/nestjs/chat/speech-stream.gateway.js +10 -8
  292. package/dist/server/adapters/nestjs/chat/speech-stream.gateway.js.map +1 -1
  293. package/dist/server/adapters/nestjs/chat/ws-loader.d.ts +5 -0
  294. package/dist/server/adapters/nestjs/chat/ws-loader.js +37 -0
  295. package/dist/server/adapters/nestjs/chat/ws-loader.js.map +1 -0
  296. package/openapi/package.json +5 -0
  297. package/package.json +59 -16
  298. package/react/langgraph/package.json +5 -0
  299. package/react/package.json +5 -0
  300. package/react/vercel/package.json +5 -0
  301. package/server/nestjs/package.json +5 -0
  302. package/server/nextjs/package.json +5 -0
  303. package/server/package.json +5 -0
  304. package/server/testing/package.json +5 -0
  305. package/skills/README.md +107 -0
  306. package/skills/building-glirastes-chat-ui/SKILL.md +378 -0
  307. package/skills/integrating-glirastes-nestjs/SKILL.md +346 -0
  308. package/skills/integrating-glirastes-nextjs/SKILL.md +306 -0
  309. package/skills/integrating-glirastes-nextjs-with-nestjs-backend/SKILL.md +359 -0
  310. package/skills/maintaining-glirastes-tools/SKILL.md +463 -0
@@ -0,0 +1,408 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.checkAiCoverage = checkAiCoverage;
37
+ exports.formatCoverageReport = formatCoverageReport;
38
+ const node_path_1 = require("node:path");
39
+ const promises_1 = require("node:fs/promises");
40
+ const fs_utils_js_1 = require("./fs-utils.js");
41
+ const endpoint_scanner_js_1 = require("./endpoint-scanner.js");
42
+ const ui_scanner_js_1 = require("./ui-scanner.js");
43
+ const types_js_1 = require("./types.js");
44
+ const format_js_1 = require("./format.js");
45
+ /**
46
+ * Check AI tool coverage across the project.
47
+ * Reports on endpoint tools, UI tools, route coverage,
48
+ * component coverage, and sharedWith configurations.
49
+ */
50
+ async function checkAiCoverage(options) {
51
+ const opts = (0, types_js_1.resolveDefaults)(options);
52
+ // Scan tools
53
+ const endpointScan = await (0, endpoint_scanner_js_1.scanEndpointTools)(options);
54
+ const uiScan = await (0, ui_scanner_js_1.scanUiTools)(options);
55
+ const actionIds = await (0, ui_scanner_js_1.extractActionIds)(options);
56
+ // NestJS controller coverage
57
+ let nestControllerTotal = 0;
58
+ let nestControllerCovered = 0;
59
+ let nestControllerIgnored = 0;
60
+ let nestToolCount = 0;
61
+ const uncoveredNestControllers = [];
62
+ if (opts.nestjsDirs.length > 0) {
63
+ const { scanNestControllers } = await Promise.resolve().then(() => __importStar(require('./nestjs-scanner.js')));
64
+ const nestResult = await scanNestControllers(opts.nestjsDirs, opts.nestjsApiPrefix);
65
+ // Count unique controller files that have tools
66
+ const coveredFiles = new Set(nestResult.tools.map(t => t.controllerFile));
67
+ nestControllerCovered = coveredFiles.size;
68
+ nestToolCount = nestResult.tools.length;
69
+ uncoveredNestControllers.push(...nestResult.uncoveredControllers);
70
+ nestControllerTotal = nestControllerCovered + uncoveredNestControllers.length;
71
+ }
72
+ // Route coverage
73
+ const apiDir = (0, node_path_1.join)(opts.rootDir, opts.apiDir);
74
+ const routeFiles = await (0, fs_utils_js_1.findRouteFiles)(apiDir);
75
+ const toolFiles = new Set((await (0, fs_utils_js_1.findFiles)(apiDir, opts.endpointToolFileName)).map((f) => f.replace(`/${opts.endpointToolFileName}`, '')));
76
+ let routeCovered = 0;
77
+ let routeIgnored = 0;
78
+ const uncoveredRoutes = [];
79
+ for (const routeFile of routeFiles) {
80
+ const routeDir = routeFile.replace('/route.ts', '');
81
+ const routeContent = await (0, fs_utils_js_1.readFileSafe)(routeFile);
82
+ if (routeContent.includes('@ai-ignore') || await (0, fs_utils_js_1.isDirAiIgnored)(routeDir)) {
83
+ routeIgnored++;
84
+ continue;
85
+ }
86
+ if (toolFiles.has(routeDir) || routeContent.includes('withAiTool(')) {
87
+ routeCovered++;
88
+ }
89
+ else {
90
+ uncoveredRoutes.push(routeFile.replace(opts.rootDir + '/', ''));
91
+ }
92
+ }
93
+ const routeTotal = routeFiles.length - routeIgnored;
94
+ // Component coverage
95
+ const componentsDir = (0, node_path_1.join)(opts.rootDir, opts.componentsDir);
96
+ const componentDirs = await (0, fs_utils_js_1.getSubdirectories)(componentsDir);
97
+ const uiToolDirs = new Set((await (0, fs_utils_js_1.findFiles)(componentsDir, opts.uiToolFileName)).map((f) => f.replace(`/${opts.uiToolFileName}`, '')));
98
+ let componentDirCovered = 0;
99
+ let componentDirIgnored = 0;
100
+ const uncoveredComponents = [];
101
+ for (const dir of componentDirs) {
102
+ if (await (0, fs_utils_js_1.isDirAiIgnored)(dir)) {
103
+ componentDirIgnored++;
104
+ continue;
105
+ }
106
+ if (uiToolDirs.has(dir)) {
107
+ componentDirCovered++;
108
+ }
109
+ else {
110
+ uncoveredComponents.push(dir.replace(opts.rootDir + '/', ''));
111
+ }
112
+ }
113
+ const componentDirTotal = componentDirs.length - componentDirIgnored;
114
+ // SharedWith analysis
115
+ const sharedWithConfigs = [];
116
+ for (const file of endpointScan.files) {
117
+ const content = await (0, fs_utils_js_1.readFileSafe)(file.absolutePath);
118
+ const toolBlocksArr = (0, fs_utils_js_1.extractBalancedBlocks)(content, /define(?:Ai)?EndpointTool\(\s*/);
119
+ for (const block of toolBlocksArr) {
120
+ const sharedMatch = block.match(/sharedWith\s*:\s*\[([^\]]*)\]/);
121
+ if (!sharedMatch)
122
+ continue;
123
+ const toolNameMatch = block.match(/toolName\s*:\s*['"`]([^'"`]+)['"`]/);
124
+ const moduleMatch = block.match(/module\s*:\s*['"`]([^'"`]+)['"`]/);
125
+ if (!toolNameMatch)
126
+ continue;
127
+ const sharedWith = sharedMatch[1]
128
+ .match(/['"`]([^'"`]+)['"`]/g)
129
+ ?.map((s) => s.replace(/['"`]/g, ''));
130
+ if (sharedWith && sharedWith.length > 0) {
131
+ sharedWithConfigs.push({
132
+ toolName: toolNameMatch[1],
133
+ primaryModule: moduleMatch?.[1] ?? 'unknown',
134
+ sharedWith,
135
+ });
136
+ }
137
+ }
138
+ }
139
+ // Handler source-scan: find useAiClientAction() calls in .tsx files
140
+ // In monorepos, scan all configured dirs + default src/
141
+ const handlerScanDirs = [
142
+ (0, node_path_1.join)(opts.rootDir, 'src'),
143
+ ...(opts.nestjsDirs ?? []),
144
+ (0, node_path_1.join)(opts.rootDir, opts.componentsDir),
145
+ ].filter((d, i, arr) => arr.indexOf(d) === i); // dedupe
146
+ const tsxFiles = [];
147
+ for (const dir of handlerScanDirs) {
148
+ tsxFiles.push(...await findTsxFiles(dir));
149
+ }
150
+ const requiredActionIds = new Set(actionIds.map((a) => a.actionId));
151
+ const foundHandlerIds = new Set();
152
+ const allSourceHandlers = [];
153
+ for (const tsxFile of tsxFiles) {
154
+ const content = await (0, fs_utils_js_1.readFileSafe)(tsxFile);
155
+ if (content.includes('@ai-ignore'))
156
+ continue;
157
+ // Match useAiClientAction('actionId', ...) calls
158
+ const handlerMatches = content.matchAll(/useAiClientAction\(\s*['"`]([^'"`]+)['"`]/g);
159
+ for (const m of handlerMatches) {
160
+ const actionId = m[1];
161
+ foundHandlerIds.add(actionId);
162
+ allSourceHandlers.push({
163
+ actionId,
164
+ sourceFile: tsxFile.replace(opts.rootDir + '/', ''),
165
+ });
166
+ }
167
+ }
168
+ const handlerCoveredCount = Array.from(requiredActionIds).filter((id) => foundHandlerIds.has(id)).length;
169
+ const handlerTotalCount = requiredActionIds.size;
170
+ // Orphan handlers: registered in source but no matching UI tool actionId
171
+ const orphanHandlers = allSourceHandlers.filter((h) => !requiredActionIds.has(h.actionId));
172
+ // Missing handlers: actionIds defined in UI tools but no useAiClientAction found
173
+ const missingHandlers = actionIds
174
+ .filter((a) => !foundHandlerIds.has(a.actionId))
175
+ .map((a) => ({
176
+ actionId: a.actionId,
177
+ toolName: a.toolName,
178
+ sourceFile: a.sourceFile,
179
+ }));
180
+ return {
181
+ endpointToolCount: endpointScan.toolCount,
182
+ endpointFileCount: endpointScan.files.length,
183
+ uiToolCount: uiScan.toolCount,
184
+ uiFileCount: uiScan.files.length,
185
+ actionIdCount: actionIds.length,
186
+ routeTotal,
187
+ routeCovered,
188
+ routeIgnored,
189
+ routeCoveragePercent: routeTotal > 0 ? Math.round((routeCovered / routeTotal) * 100) : 100,
190
+ componentDirTotal,
191
+ componentDirCovered,
192
+ componentDirIgnored,
193
+ componentCoveragePercent: componentDirTotal > 0
194
+ ? Math.round((componentDirCovered / componentDirTotal) * 100)
195
+ : 100,
196
+ sharedWithConfigs,
197
+ handlerActionIds: Array.from(foundHandlerIds),
198
+ handlerCoveredCount,
199
+ handlerTotalCount,
200
+ handlerCoveragePercent: handlerTotalCount > 0
201
+ ? Math.round((handlerCoveredCount / handlerTotalCount) * 100)
202
+ : 100,
203
+ orphanHandlers,
204
+ uncoveredRoutes,
205
+ uncoveredComponents,
206
+ missingHandlers,
207
+ nestControllerTotal,
208
+ nestControllerCovered,
209
+ nestControllerIgnored,
210
+ nestControllerCoveragePercent: nestControllerTotal > 0
211
+ ? Math.round((nestControllerCovered / nestControllerTotal) * 100)
212
+ : 100,
213
+ nestToolCount,
214
+ uncoveredNestControllers,
215
+ };
216
+ }
217
+ /**
218
+ * Recursively find all .tsx files in a directory.
219
+ */
220
+ async function findTsxFiles(dir) {
221
+ const results = [];
222
+ async function walk(currentDir) {
223
+ let entries;
224
+ try {
225
+ entries = await (0, promises_1.readdir)(currentDir, { withFileTypes: true });
226
+ }
227
+ catch {
228
+ return;
229
+ }
230
+ for (const entry of entries) {
231
+ const fullPath = (0, node_path_1.join)(currentDir, entry.name);
232
+ if (entry.isDirectory()) {
233
+ if (entry.name === 'node_modules' || entry.name === '.git')
234
+ continue;
235
+ await walk(fullPath);
236
+ }
237
+ else if (entry.name.endsWith('.tsx')) {
238
+ results.push(fullPath);
239
+ }
240
+ }
241
+ }
242
+ await walk(dir);
243
+ return results.sort();
244
+ }
245
+ /**
246
+ * Format a coverage report as a rich, color-coded human-readable string.
247
+ */
248
+ function formatCoverageReport(report, options) {
249
+ if (options?.quiet) {
250
+ return formatCoverageReportQuiet(report);
251
+ }
252
+ const lines = [];
253
+ const hasHandlerIssues = report.missingHandlers.length > 0;
254
+ const hasOrphanHandlers = report.orphanHandlers.length > 0;
255
+ const hasRouteIssues = report.uncoveredRoutes.length > 0;
256
+ const hasComponentIssues = report.uncoveredComponents.length > 0;
257
+ const hasNestIssues = report.uncoveredNestControllers.length > 0;
258
+ const hasIssues = hasHandlerIssues || hasOrphanHandlers || hasRouteIssues || hasComponentIssues || hasNestIssues;
259
+ // Detect active frameworks from scan results
260
+ const hasNextRoutes = report.routeTotal > 0 || report.endpointFileCount > 0;
261
+ const hasNest = report.nestControllerTotal > 0 || report.nestToolCount > 0;
262
+ // Header
263
+ lines.push((0, format_js_1.header)('AI Tools Coverage Summary'));
264
+ // Endpoint Tools — framework-adaptive detail
265
+ const totalEndpointTools = report.endpointToolCount + report.nestToolCount;
266
+ const endpointParts = [];
267
+ if (hasNextRoutes || (!hasNest && report.endpointFileCount === 0)) {
268
+ endpointParts.push(`${report.endpointFileCount} route files`);
269
+ }
270
+ if (hasNest) {
271
+ endpointParts.push(`${report.nestControllerCovered} controllers`);
272
+ }
273
+ lines.push((0, format_js_1.metricLine)('\u2713', format_js_1.colors.green, 'Endpoint Tools:', totalEndpointTools, endpointParts.join(' + ')));
274
+ lines.push((0, format_js_1.metricLine)('\u2713', format_js_1.colors.green, 'UI Tools (ai-ui-tool.ts):', report.uiToolCount, `${report.uiFileCount} files`));
275
+ const handlerIcon = hasHandlerIssues ? '\u26A0' : '\u2713';
276
+ const handlerColor = hasHandlerIssues ? format_js_1.colors.yellow : format_js_1.colors.green;
277
+ lines.push((0, format_js_1.metricLine)(handlerIcon, handlerColor, 'Handler Coverage:', `${report.handlerCoveragePercent}%`, `${report.handlerCoveredCount}/${report.handlerTotalCount}`));
278
+ // Route Coverage — only show when Next.js routes exist or are expected
279
+ if (hasNextRoutes) {
280
+ const routeIcon = hasRouteIssues ? '\u26A0' : '\u2713';
281
+ const routeColor = hasRouteIssues ? format_js_1.colors.yellow : format_js_1.colors.green;
282
+ lines.push((0, format_js_1.metricLine)(routeIcon, routeColor, 'Route Coverage:', `${report.routeCoveragePercent}%`, `${report.routeCovered}/${report.routeTotal} routes${report.routeIgnored > 0 ? `, ${report.routeIgnored} ignored` : ''}`));
283
+ }
284
+ const componentIcon = hasComponentIssues ? '\u26A0' : '\u2713';
285
+ const componentColor = hasComponentIssues ? format_js_1.colors.yellow : format_js_1.colors.green;
286
+ lines.push((0, format_js_1.metricLine)(componentIcon, componentColor, 'Component Coverage:', `${report.componentCoveragePercent}%`, `${report.componentDirCovered}/${report.componentDirTotal} dirs${report.componentDirIgnored > 0 ? `, ${report.componentDirIgnored} ignored` : ''}`));
287
+ // NestJS Decorator Coverage — only show when NestJS is detected
288
+ if (hasNest) {
289
+ const nestIcon = report.uncoveredNestControllers.length > 0 ? '\u26A0' : '\u2713';
290
+ const nestColor = report.uncoveredNestControllers.length > 0 ? format_js_1.colors.yellow : format_js_1.colors.green;
291
+ lines.push((0, format_js_1.metricLine)(nestIcon, nestColor, 'Decorator Coverage (@AiTool):', `${report.nestControllerCoveragePercent}%`, `${report.nestControllerCovered}/${report.nestControllerTotal} controllers`));
292
+ }
293
+ const sharedCount = report.sharedWithConfigs.length;
294
+ lines.push((0, format_js_1.metricLine)('\u2713', format_js_1.colors.green, 'Cross-Module Sharing:', sharedCount > 0 ? `${sharedCount} Tools` : 'None'));
295
+ lines.push('');
296
+ lines.push((0, format_js_1.separator)());
297
+ // --- Detail sections (conditional) ---
298
+ // Missing handlers
299
+ if (hasHandlerIssues) {
300
+ lines.push('');
301
+ lines.push((0, format_js_1.sectionHeader)('Missing Handlers', report.missingHandlers.length, format_js_1.colors.red));
302
+ for (const h of report.missingHandlers) {
303
+ lines.push(` ${format_js_1.colors.red}\u2717${format_js_1.colors.reset} ${format_js_1.colors.bold}${h.actionId}${format_js_1.colors.reset}` +
304
+ ` ${format_js_1.colors.dim}\u2190 ${h.toolName}${format_js_1.colors.reset}`);
305
+ lines.push(` ${format_js_1.colors.dim}Defined in: ${h.sourceFile}${format_js_1.colors.reset}`);
306
+ }
307
+ }
308
+ // Orphan handlers
309
+ if (hasOrphanHandlers) {
310
+ lines.push('');
311
+ lines.push((0, format_js_1.sectionHeader)('Orphan Handlers', report.orphanHandlers.length, format_js_1.colors.yellow));
312
+ lines.push(`${format_js_1.colors.dim}These handlers have no corresponding UI tool definition:${format_js_1.colors.reset}`);
313
+ for (const o of report.orphanHandlers) {
314
+ lines.push(` ${format_js_1.colors.yellow}\u26A0${format_js_1.colors.reset} ${format_js_1.colors.bold}${o.actionId}${format_js_1.colors.reset}` +
315
+ ` ${format_js_1.colors.dim}\u2192 ${o.sourceFile}${format_js_1.colors.reset}`);
316
+ }
317
+ }
318
+ // Uncovered routes
319
+ if (hasRouteIssues) {
320
+ lines.push('');
321
+ lines.push((0, format_js_1.sectionHeader)('Routes without ai-tool.ts', report.uncoveredRoutes.length, format_js_1.colors.yellow));
322
+ for (const route of report.uncoveredRoutes) {
323
+ lines.push(` ${format_js_1.colors.yellow}\u26A0${format_js_1.colors.reset} ${route}`);
324
+ lines.push(` ${format_js_1.colors.cyan}\u2192 glirastes scaffold --route "${route}"${format_js_1.colors.reset}`);
325
+ }
326
+ lines.push(`\n${format_js_1.colors.dim}Or add // @ai-ignore to route.ts to exclude${format_js_1.colors.reset}`);
327
+ }
328
+ // Uncovered components
329
+ if (hasComponentIssues) {
330
+ lines.push('');
331
+ lines.push((0, format_js_1.sectionHeader)('Components without ai-ui-tool.ts', report.uncoveredComponents.length, format_js_1.colors.yellow));
332
+ for (const dir of report.uncoveredComponents) {
333
+ lines.push(` ${format_js_1.colors.yellow}\u26A0${format_js_1.colors.reset} ${dir}/`);
334
+ lines.push(` ${format_js_1.colors.cyan}\u2192 Create ${dir}/ai-ui-tool.ts${format_js_1.colors.reset}`);
335
+ }
336
+ lines.push(`\n${format_js_1.colors.dim}Or add // @ai-ignore to any .ts/.tsx file or create .ai-ignore to exclude${format_js_1.colors.reset}`);
337
+ }
338
+ // Uncovered NestJS controllers
339
+ if (report.uncoveredNestControllers.length > 0) {
340
+ lines.push('');
341
+ lines.push((0, format_js_1.sectionHeader)('NestJS controllers without @AiTool', report.uncoveredNestControllers.length, format_js_1.colors.yellow));
342
+ lines.push(`${format_js_1.colors.dim}These controllers have HTTP endpoints but no @AiTool decorators:${format_js_1.colors.reset}`);
343
+ for (const ctrl of report.uncoveredNestControllers) {
344
+ const relPath = ctrl.controllerFile.includes('/src/')
345
+ ? ctrl.controllerFile.slice(ctrl.controllerFile.indexOf('/src/') + 1)
346
+ : ctrl.controllerFile;
347
+ lines.push(` ${format_js_1.colors.yellow}\u26A0${format_js_1.colors.reset} ${format_js_1.colors.bold}${ctrl.controllerName}${format_js_1.colors.reset}` +
348
+ ` ${format_js_1.colors.dim}(${ctrl.httpMethodCount} endpoints)${format_js_1.colors.reset}`);
349
+ lines.push(` ${format_js_1.colors.dim}${relPath}${format_js_1.colors.reset}`);
350
+ lines.push(` ${format_js_1.colors.cyan}\u2192 Add @AiModule + @AiTool decorators, or create .ai-ignore to exclude${format_js_1.colors.reset}`);
351
+ }
352
+ }
353
+ // SharedWith configurations (when no issues — show as positive info)
354
+ if (sharedCount > 0 && !hasIssues) {
355
+ lines.push('');
356
+ lines.push((0, format_js_1.sectionHeader)('Cross-Module Sharing', sharedCount, format_js_1.colors.green));
357
+ for (const config of report.sharedWithConfigs) {
358
+ lines.push(` ${format_js_1.colors.green}\u2713${format_js_1.colors.reset} ${format_js_1.colors.bold}${config.toolName}${format_js_1.colors.reset}` +
359
+ ` ${format_js_1.colors.dim}(${config.primaryModule})${format_js_1.colors.reset}` +
360
+ ` \u2192 ${config.sharedWith.join(', ')}`);
361
+ }
362
+ }
363
+ // Final summary
364
+ lines.push('');
365
+ lines.push((0, format_js_1.separator)());
366
+ lines.push('');
367
+ const totalTools = report.endpointToolCount + report.uiToolCount + report.nestToolCount;
368
+ const summaryIcon = hasIssues ? '\u26A0\uFE0F' : '\u2705';
369
+ const summaryColor = hasIssues ? format_js_1.colors.yellow : format_js_1.colors.green;
370
+ lines.push(`${summaryColor}${summaryIcon} Total: ${format_js_1.colors.bold}${totalTools} AI Tools${format_js_1.colors.reset}`);
371
+ lines.push('');
372
+ // Framework-adaptive summary lines
373
+ if (hasNextRoutes) {
374
+ lines.push(` ${format_js_1.colors.dim}Routes: ${report.routeCovered}/${report.routeTotal} have ai-tool.ts (${report.endpointToolCount} tools)${format_js_1.colors.reset}`);
375
+ }
376
+ if (hasNest) {
377
+ lines.push(` ${format_js_1.colors.dim}Controllers: ${report.nestControllerCovered}/${report.nestControllerTotal} have @AiTool decorators (${report.nestToolCount} tools)${format_js_1.colors.reset}`);
378
+ }
379
+ lines.push(` ${format_js_1.colors.dim}Components: ${report.componentDirCovered}/${report.componentDirTotal} have ai-ui-tool.ts (${report.uiToolCount} tools)${format_js_1.colors.reset}`);
380
+ lines.push(` ${format_js_1.colors.dim}Handlers: ${report.handlerCoveredCount}/${report.handlerTotalCount} actionIds have useAiClientAction${format_js_1.colors.reset}`);
381
+ lines.push('');
382
+ return lines.join('\n');
383
+ }
384
+ /**
385
+ * Minimal quiet output for predev/prebuild hooks.
386
+ */
387
+ function formatCoverageReportQuiet(report) {
388
+ const issues = [];
389
+ if (report.uncoveredRoutes.length > 0) {
390
+ issues.push(`${report.uncoveredRoutes.length} uncovered routes`);
391
+ }
392
+ if (report.uncoveredComponents.length > 0) {
393
+ issues.push(`${report.uncoveredComponents.length} uncovered components`);
394
+ }
395
+ if (report.missingHandlers.length > 0) {
396
+ issues.push(`${report.missingHandlers.length} missing handlers`);
397
+ }
398
+ if (report.orphanHandlers.length > 0) {
399
+ issues.push(`${report.orphanHandlers.length} orphan handlers`);
400
+ }
401
+ if (report.uncoveredNestControllers.length > 0) {
402
+ issues.push(`${report.uncoveredNestControllers.length} uncovered NestJS controllers`);
403
+ }
404
+ if (issues.length === 0) {
405
+ return `${format_js_1.colors.green}\u2713${format_js_1.colors.reset} AI coverage: ${report.endpointToolCount + report.uiToolCount + report.nestToolCount} tools, all OK`;
406
+ }
407
+ return `${format_js_1.colors.yellow}\u26A0${format_js_1.colors.reset} AI coverage: ${issues.join(', ')}`;
408
+ }
@@ -0,0 +1,16 @@
1
+ import type { GenerateOptions, ScanResult } from './types.js';
2
+ /**
3
+ * Scan for endpoint tool files (ai-tool.ts) in the API directory.
4
+ * Also detects route.ts files using withAiTool() from glirastes/server/nextjs.
5
+ */
6
+ export declare function scanEndpointTools(options: GenerateOptions): Promise<ScanResult>;
7
+ /**
8
+ * Generate the endpoint tools registry file.
9
+ *
10
+ * Output: a TypeScript file that imports all discovered endpoint tools and
11
+ * combines them into a single registry via endpointToolsToRegistry().
12
+ */
13
+ export declare function generateEndpointRegistry(options: GenerateOptions): Promise<{
14
+ outputPath: string;
15
+ toolCount: number;
16
+ }>;
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.scanEndpointTools = scanEndpointTools;
37
+ exports.generateEndpointRegistry = generateEndpointRegistry;
38
+ const promises_1 = require("node:fs/promises");
39
+ const node_path_1 = require("node:path");
40
+ const fs_utils_js_1 = require("./fs-utils.js");
41
+ const types_js_1 = require("./types.js");
42
+ /**
43
+ * Scan for endpoint tool files (ai-tool.ts) in the API directory.
44
+ * Also detects route.ts files using withAiTool() from glirastes/server/nextjs.
45
+ */
46
+ async function scanEndpointTools(options) {
47
+ const opts = (0, types_js_1.resolveDefaults)(options);
48
+ const apiDir = (0, node_path_1.join)(opts.rootDir, opts.apiDir);
49
+ const files = await (0, fs_utils_js_1.findFiles)(apiDir, opts.endpointToolFileName);
50
+ const discovered = [];
51
+ const discoveredDirs = new Set();
52
+ // 1. Standard ai-tool.ts files
53
+ for (const absolutePath of files) {
54
+ const content = await (0, fs_utils_js_1.readFileSafe)(absolutePath);
55
+ if (content.includes('@ai-ignore'))
56
+ continue;
57
+ if (await (0, fs_utils_js_1.isDirAiIgnored)((0, node_path_1.dirname)(absolutePath)))
58
+ continue;
59
+ const hasArray = /export\s+const\s+aiTools\s*[=:]/m.test(content);
60
+ const hasSingle = /export\s+const\s+aiTool\s*[=:]/m.test(content);
61
+ if (!hasArray && !hasSingle)
62
+ continue;
63
+ discovered.push({
64
+ absolutePath,
65
+ relativePath: absolutePath.replace(opts.rootDir + '/', ''),
66
+ importPath: (0, fs_utils_js_1.toImportPath)(absolutePath, opts.rootDir),
67
+ exportType: hasArray ? 'array' : 'single',
68
+ });
69
+ discoveredDirs.add((0, node_path_1.dirname)(absolutePath));
70
+ }
71
+ // 2. route.ts files with withAiTool() (inline tool definitions)
72
+ const routeFiles = await (0, fs_utils_js_1.findRouteFiles)(apiDir);
73
+ for (const routeFile of routeFiles) {
74
+ const routeDir = (0, node_path_1.dirname)(routeFile);
75
+ if (discoveredDirs.has(routeDir))
76
+ continue; // Already has ai-tool.ts
77
+ const content = await (0, fs_utils_js_1.readFileSafe)(routeFile);
78
+ if (content.includes('@ai-ignore'))
79
+ continue;
80
+ if (await (0, fs_utils_js_1.isDirAiIgnored)(routeDir))
81
+ continue;
82
+ if (!content.includes('withAiTool('))
83
+ continue;
84
+ discovered.push({
85
+ absolutePath: routeFile,
86
+ relativePath: routeFile.replace(opts.rootDir + '/', ''),
87
+ importPath: (0, fs_utils_js_1.toImportPath)(routeFile, opts.rootDir),
88
+ exportType: 'single', // withAiTool wraps a single handler
89
+ });
90
+ }
91
+ // Count tools (rough estimate: arrays have multiple, singles have 1)
92
+ let toolCount = 0;
93
+ for (const file of discovered) {
94
+ if (file.exportType === 'array') {
95
+ const content = await (0, fs_utils_js_1.readFileSafe)(file.absolutePath);
96
+ // Count defineEndpointTool or defineAiEndpointTool calls
97
+ const matches = content.match(/define(?:Ai)?EndpointTool\(/g);
98
+ toolCount += matches?.length ?? 1;
99
+ }
100
+ else {
101
+ toolCount += 1;
102
+ }
103
+ }
104
+ return { files: discovered, toolCount };
105
+ }
106
+ /**
107
+ * Generate the endpoint tools registry file.
108
+ *
109
+ * Output: a TypeScript file that imports all discovered endpoint tools and
110
+ * combines them into a single registry via endpointToolsToRegistry().
111
+ */
112
+ async function generateEndpointRegistry(options) {
113
+ const opts = (0, types_js_1.resolveDefaults)(options);
114
+ const scan = await scanEndpointTools(options);
115
+ // NestJS @AiTool decorated controllers
116
+ let nestTools = [];
117
+ if (opts.nestjsDirs.length > 0) {
118
+ const { scanNestControllers } = await Promise.resolve().then(() => __importStar(require('./nestjs-scanner.js')));
119
+ const nestResult = await scanNestControllers(opts.nestjsDirs, opts.nestjsApiPrefix);
120
+ nestTools = nestResult.tools;
121
+ }
122
+ const imports = [];
123
+ const spreadParts = [];
124
+ scan.files.forEach((file, index) => {
125
+ if (file.exportType === 'array') {
126
+ const alias = `endpointTools${index}`;
127
+ imports.push(`import { aiTools as ${alias} } from '${file.importPath}';`);
128
+ spreadParts.push(`...${alias}`);
129
+ }
130
+ else {
131
+ const alias = `endpointTool${index}`;
132
+ imports.push(`import { aiTool as ${alias} } from '${file.importPath}';`);
133
+ spreadParts.push(alias);
134
+ }
135
+ });
136
+ // Generate inline defineEndpointTool() calls for NestJS tools
137
+ const nestInlineDefs = [];
138
+ const nestSpreadParts = [];
139
+ nestTools.forEach((tool, index) => {
140
+ const alias = `nestTool${index}`;
141
+ const desc = tool.description.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
142
+ // Build path param schema fields (e.g. { id: z.string() })
143
+ const paramFields = tool.pathParams.map(p => `${p}: z.string()`).join(', ');
144
+ const inputSchema = paramFields
145
+ ? `z.object({ ${paramFields} }).passthrough()`
146
+ : 'z.object({}).passthrough()';
147
+ const lines = [
148
+ ` id: '${tool.name}'`,
149
+ ` toolName: '${tool.name}'`,
150
+ ` description: '${desc}'`,
151
+ ` path: '${tool.path}'`,
152
+ ` method: '${tool.method}'`,
153
+ ` inputSchema: ${inputSchema}`,
154
+ ];
155
+ if (tool.module)
156
+ lines.push(` module: '${tool.module}'`);
157
+ if (tool.needsApproval !== undefined)
158
+ lines.push(` needsApproval: ${tool.needsApproval}`);
159
+ if (tool.allowedRoles && tool.allowedRoles.length > 0) {
160
+ lines.push(` allowedRoles: ${JSON.stringify(tool.allowedRoles)}`);
161
+ }
162
+ nestInlineDefs.push(`const ${alias} = defineEndpointTool({\n${lines.join(',\n')},\n});`);
163
+ nestSpreadParts.push(alias);
164
+ });
165
+ const allSpreadParts = [...spreadParts, ...nestSpreadParts];
166
+ const totalToolCount = scan.toolCount + nestTools.length;
167
+ const contractsImport = nestTools.length > 0
168
+ ? `import { z } from 'zod';\nimport { defineEndpointTool } from 'glirastes';\n`
169
+ : '';
170
+ const nestInlineBlock = nestInlineDefs.length > 0
171
+ ? `\n// From NestJS @AiTool decorators\n${nestInlineDefs.join('\n\n')}\n`
172
+ : '';
173
+ const code = `/* eslint-disable */
174
+ /**
175
+ * AUTO-GENERATED FILE — do not edit manually.
176
+ * Generated by glirastes
177
+ *
178
+ * Sources: ${scan.files.length} ai-tool.ts files, ${nestTools.length} NestJS @AiTool decorators
179
+ * Tools: ${totalToolCount}
180
+ */
181
+
182
+ ${imports.join('\n')}
183
+ import { endpointToolsToRegistry } from 'glirastes/server';
184
+ ${contractsImport}${nestInlineBlock}
185
+ const endpointTools = [${allSpreadParts.join(', ')}] as const;
186
+
187
+ export { endpointTools };
188
+ export const endpointToolRegistry = endpointToolsToRegistry(endpointTools);
189
+ `;
190
+ const outputPath = (0, node_path_1.join)(opts.rootDir, opts.outputDir, 'endpoint.generated.ts');
191
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(outputPath), { recursive: true });
192
+ await (0, promises_1.writeFile)(outputPath, code, 'utf-8');
193
+ if (!opts.quiet) {
194
+ console.log(`✓ Generated ${outputPath} (${totalToolCount} endpoint tools from ${scan.files.length} files + ${nestTools.length} NestJS controllers)`);
195
+ }
196
+ return { outputPath, toolCount: totalToolCount };
197
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Shared ANSI color codes and formatting utilities for CLI output.
3
+ */
4
+ export declare const colors: {
5
+ reset: string;
6
+ bold: string;
7
+ dim: string;
8
+ red: string;
9
+ green: string;
10
+ yellow: string;
11
+ blue: string;
12
+ cyan: string;
13
+ };
14
+ export declare function separator(width?: number): string;
15
+ export declare function header(title: string): string;
16
+ export declare function sectionHeader(title: string, count: number, color: string): string;
17
+ export declare function metricLine(icon: string, iconColor: string, label: string, value: string | number, detail?: string): string;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * Shared ANSI color codes and formatting utilities for CLI output.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.colors = void 0;
7
+ exports.separator = separator;
8
+ exports.header = header;
9
+ exports.sectionHeader = sectionHeader;
10
+ exports.metricLine = metricLine;
11
+ exports.colors = {
12
+ reset: '\x1b[0m',
13
+ bold: '\x1b[1m',
14
+ dim: '\x1b[2m',
15
+ red: '\x1b[31m',
16
+ green: '\x1b[32m',
17
+ yellow: '\x1b[33m',
18
+ blue: '\x1b[34m',
19
+ cyan: '\x1b[36m',
20
+ };
21
+ function separator(width = 50) {
22
+ return `${exports.colors.dim}${'─'.repeat(width)}${exports.colors.reset}`;
23
+ }
24
+ function header(title) {
25
+ return `\n${exports.colors.blue}${exports.colors.bold}${title}${exports.colors.reset}\n\n${separator()}\n`;
26
+ }
27
+ function sectionHeader(title, count, color) {
28
+ return `${color}${exports.colors.bold}${title} (${count}):${exports.colors.reset}\n`;
29
+ }
30
+ function metricLine(icon, iconColor, label, value, detail) {
31
+ const paddedLabel = label.padEnd(35);
32
+ const detailStr = detail ? ` ${exports.colors.dim}(${detail})${exports.colors.reset}` : '';
33
+ return ` ${iconColor}${icon}${exports.colors.reset} ${paddedLabel}${exports.colors.bold}${value}${exports.colors.reset}${detailStr}`;
34
+ }