@syrin/cli 1.3.0

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 (438) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +302 -0
  3. package/dist/cli/commands/analyse.d.ts +16 -0
  4. package/dist/cli/commands/analyse.js +61 -0
  5. package/dist/cli/commands/dev.d.ts +23 -0
  6. package/dist/cli/commands/dev.js +419 -0
  7. package/dist/cli/commands/doctor.d.ts +10 -0
  8. package/dist/cli/commands/doctor.js +195 -0
  9. package/dist/cli/commands/index.d.ts +12 -0
  10. package/dist/cli/commands/index.js +12 -0
  11. package/dist/cli/commands/init.d.ts +16 -0
  12. package/dist/cli/commands/init.js +90 -0
  13. package/dist/cli/commands/list.d.ts +15 -0
  14. package/dist/cli/commands/list.js +50 -0
  15. package/dist/cli/commands/rollback.d.ts +12 -0
  16. package/dist/cli/commands/rollback.js +101 -0
  17. package/dist/cli/commands/test.d.ts +31 -0
  18. package/dist/cli/commands/test.js +88 -0
  19. package/dist/cli/commands/update.d.ts +9 -0
  20. package/dist/cli/commands/update.js +76 -0
  21. package/dist/cli/index.d.ts +13 -0
  22. package/dist/cli/index.js +342 -0
  23. package/dist/cli/prompts/index.d.ts +5 -0
  24. package/dist/cli/prompts/index.js +5 -0
  25. package/dist/cli/prompts/init-prompt.d.ts +17 -0
  26. package/dist/cli/prompts/init-prompt.js +263 -0
  27. package/dist/cli/utils/command-error-handler.d.ts +14 -0
  28. package/dist/cli/utils/command-error-handler.js +35 -0
  29. package/dist/cli/utils/common-types.d.ts +24 -0
  30. package/dist/cli/utils/common-types.js +6 -0
  31. package/dist/cli/utils/connection-handler.d.ts +37 -0
  32. package/dist/cli/utils/connection-handler.js +90 -0
  33. package/dist/cli/utils/index.d.ts +11 -0
  34. package/dist/cli/utils/index.js +11 -0
  35. package/dist/cli/utils/option-parsers.d.ts +41 -0
  36. package/dist/cli/utils/option-parsers.js +92 -0
  37. package/dist/cli/utils/output-utils.d.ts +12 -0
  38. package/dist/cli/utils/output-utils.js +21 -0
  39. package/dist/cli/utils/transport-resolver.d.ts +33 -0
  40. package/dist/cli/utils/transport-resolver.js +82 -0
  41. package/dist/cli/utils/version-banner.d.ts +10 -0
  42. package/dist/cli/utils/version-banner.js +26 -0
  43. package/dist/config/env-checker.d.ts +37 -0
  44. package/dist/config/env-checker.js +136 -0
  45. package/dist/config/generator.d.ts +19 -0
  46. package/dist/config/generator.js +196 -0
  47. package/dist/config/index.d.ts +9 -0
  48. package/dist/config/index.js +9 -0
  49. package/dist/config/loader.d.ts +19 -0
  50. package/dist/config/loader.js +57 -0
  51. package/dist/config/schema.d.ts +42 -0
  52. package/dist/config/schema.js +181 -0
  53. package/dist/config/syrin.template.yaml +127 -0
  54. package/dist/config/types.d.ts +87 -0
  55. package/dist/config/types.js +6 -0
  56. package/dist/constants/app.d.ts +9 -0
  57. package/dist/constants/app.js +9 -0
  58. package/dist/constants/commands.d.ts +43 -0
  59. package/dist/constants/commands.js +43 -0
  60. package/dist/constants/defaults.d.ts +18 -0
  61. package/dist/constants/defaults.js +18 -0
  62. package/dist/constants/env-vars.d.ts +11 -0
  63. package/dist/constants/env-vars.js +11 -0
  64. package/dist/constants/icons.d.ts +23 -0
  65. package/dist/constants/icons.js +23 -0
  66. package/dist/constants/index.d.ts +17 -0
  67. package/dist/constants/index.js +17 -0
  68. package/dist/constants/labels.d.ts +38 -0
  69. package/dist/constants/labels.js +42 -0
  70. package/dist/constants/links.d.ts +10 -0
  71. package/dist/constants/links.js +11 -0
  72. package/dist/constants/list.d.ts +10 -0
  73. package/dist/constants/list.js +9 -0
  74. package/dist/constants/llm.d.ts +26 -0
  75. package/dist/constants/llm.js +25 -0
  76. package/dist/constants/messages.d.ts +107 -0
  77. package/dist/constants/messages.js +138 -0
  78. package/dist/constants/paths.d.ts +29 -0
  79. package/dist/constants/paths.js +29 -0
  80. package/dist/constants/transport.d.ts +9 -0
  81. package/dist/constants/transport.js +8 -0
  82. package/dist/events/emitter.d.ts +64 -0
  83. package/dist/events/emitter.js +142 -0
  84. package/dist/events/event-type.d.ts +66 -0
  85. package/dist/events/event-type.js +81 -0
  86. package/dist/events/payloads/diagnostics.d.ts +24 -0
  87. package/dist/events/payloads/diagnostics.js +5 -0
  88. package/dist/events/payloads/index.d.ts +15 -0
  89. package/dist/events/payloads/index.js +6 -0
  90. package/dist/events/payloads/llm.d.ts +58 -0
  91. package/dist/events/payloads/llm.js +6 -0
  92. package/dist/events/payloads/registry.d.ts +28 -0
  93. package/dist/events/payloads/registry.js +5 -0
  94. package/dist/events/payloads/session.d.ts +32 -0
  95. package/dist/events/payloads/session.js +5 -0
  96. package/dist/events/payloads/testing.d.ts +17 -0
  97. package/dist/events/payloads/testing.js +5 -0
  98. package/dist/events/payloads/tool.d.ts +29 -0
  99. package/dist/events/payloads/tool.js +5 -0
  100. package/dist/events/payloads/transport.d.ts +30 -0
  101. package/dist/events/payloads/transport.js +5 -0
  102. package/dist/events/payloads/validation.d.ts +37 -0
  103. package/dist/events/payloads/validation.js +5 -0
  104. package/dist/events/payloads/workflow.d.ts +45 -0
  105. package/dist/events/payloads/workflow.js +5 -0
  106. package/dist/events/store/file-store.d.ts +37 -0
  107. package/dist/events/store/file-store.js +113 -0
  108. package/dist/events/store/index.d.ts +7 -0
  109. package/dist/events/store/index.js +6 -0
  110. package/dist/events/store/memory-store.d.ts +26 -0
  111. package/dist/events/store/memory-store.js +39 -0
  112. package/dist/events/store.d.ts +11 -0
  113. package/dist/events/store.js +2 -0
  114. package/dist/events/types.d.ts +14 -0
  115. package/dist/events/types.js +2 -0
  116. package/dist/index.d.ts +8 -0
  117. package/dist/index.js +30 -0
  118. package/dist/presentation/analysis-ui.d.ts +24 -0
  119. package/dist/presentation/analysis-ui.js +158 -0
  120. package/dist/presentation/dev/chat-ui-types.d.ts +68 -0
  121. package/dist/presentation/dev/chat-ui-types.js +5 -0
  122. package/dist/presentation/dev/chat-ui.d.ts +61 -0
  123. package/dist/presentation/dev/chat-ui.js +714 -0
  124. package/dist/presentation/dev/components/assistant-message.d.ts +19 -0
  125. package/dist/presentation/dev/components/assistant-message.js +36 -0
  126. package/dist/presentation/dev/components/header.d.ts +16 -0
  127. package/dist/presentation/dev/components/header.js +22 -0
  128. package/dist/presentation/dev/components/index.d.ts +13 -0
  129. package/dist/presentation/dev/components/index.js +13 -0
  130. package/dist/presentation/dev/components/input-panel.d.ts +22 -0
  131. package/dist/presentation/dev/components/input-panel.js +43 -0
  132. package/dist/presentation/dev/components/message-component.d.ts +16 -0
  133. package/dist/presentation/dev/components/message-component.js +51 -0
  134. package/dist/presentation/dev/components/messages-list.d.ts +24 -0
  135. package/dist/presentation/dev/components/messages-list.js +48 -0
  136. package/dist/presentation/dev/components/system-message.d.ts +16 -0
  137. package/dist/presentation/dev/components/system-message.js +26 -0
  138. package/dist/presentation/dev/components/user-message.d.ts +21 -0
  139. package/dist/presentation/dev/components/user-message.js +35 -0
  140. package/dist/presentation/dev/components/welcome-banner.d.ts +24 -0
  141. package/dist/presentation/dev/components/welcome-banner.js +146 -0
  142. package/dist/presentation/dev/goodbye-messages.d.ts +31 -0
  143. package/dist/presentation/dev/goodbye-messages.js +100 -0
  144. package/dist/presentation/dev/index.d.ts +5 -0
  145. package/dist/presentation/dev/index.js +5 -0
  146. package/dist/presentation/dev/text-wrapper.d.ts +30 -0
  147. package/dist/presentation/dev/text-wrapper.js +74 -0
  148. package/dist/presentation/dev-ui.d.ts +33 -0
  149. package/dist/presentation/dev-ui.js +246 -0
  150. package/dist/presentation/doctor-ui.d.ts +40 -0
  151. package/dist/presentation/doctor-ui.js +157 -0
  152. package/dist/presentation/init-ui.d.ts +14 -0
  153. package/dist/presentation/init-ui.js +41 -0
  154. package/dist/presentation/list-ui.d.ts +44 -0
  155. package/dist/presentation/list-ui.js +139 -0
  156. package/dist/presentation/test-ui.d.ts +49 -0
  157. package/dist/presentation/test-ui.js +358 -0
  158. package/dist/runtime/analysis/analyser.d.ts +14 -0
  159. package/dist/runtime/analysis/analyser.js +88 -0
  160. package/dist/runtime/analysis/dependencies.d.ts +10 -0
  161. package/dist/runtime/analysis/dependencies.js +140 -0
  162. package/dist/runtime/analysis/index.d.ts +10 -0
  163. package/dist/runtime/analysis/index.js +10 -0
  164. package/dist/runtime/analysis/indexer.d.ts +10 -0
  165. package/dist/runtime/analysis/indexer.js +62 -0
  166. package/dist/runtime/analysis/loader.d.ts +15 -0
  167. package/dist/runtime/analysis/loader.js +47 -0
  168. package/dist/runtime/analysis/normalizer.d.ts +14 -0
  169. package/dist/runtime/analysis/normalizer.js +184 -0
  170. package/dist/runtime/analysis/rules/__test-helpers__.d.ts +18 -0
  171. package/dist/runtime/analysis/rules/__test-helpers__.js +40 -0
  172. package/dist/runtime/analysis/rules/base.d.ts +38 -0
  173. package/dist/runtime/analysis/rules/base.js +23 -0
  174. package/dist/runtime/analysis/rules/error-codes.d.ts +64 -0
  175. package/dist/runtime/analysis/rules/error-codes.js +73 -0
  176. package/dist/runtime/analysis/rules/errors/e000-tool-not-found.d.ts +35 -0
  177. package/dist/runtime/analysis/rules/errors/e000-tool-not-found.js +32 -0
  178. package/dist/runtime/analysis/rules/errors/e001-missing-output-schema.d.ts +22 -0
  179. package/dist/runtime/analysis/rules/errors/e001-missing-output-schema.js +30 -0
  180. package/dist/runtime/analysis/rules/errors/e002-underspecified-input.d.ts +24 -0
  181. package/dist/runtime/analysis/rules/errors/e002-underspecified-input.js +52 -0
  182. package/dist/runtime/analysis/rules/errors/e003-type-mismatch.d.ts +23 -0
  183. package/dist/runtime/analysis/rules/errors/e003-type-mismatch.js +73 -0
  184. package/dist/runtime/analysis/rules/errors/e004-free-text-propagation.d.ts +23 -0
  185. package/dist/runtime/analysis/rules/errors/e004-free-text-propagation.js +47 -0
  186. package/dist/runtime/analysis/rules/errors/e005-tool-ambiguity.d.ts +25 -0
  187. package/dist/runtime/analysis/rules/errors/e005-tool-ambiguity.js +73 -0
  188. package/dist/runtime/analysis/rules/errors/e006-param-not-in-description.d.ts +22 -0
  189. package/dist/runtime/analysis/rules/errors/e006-param-not-in-description.js +57 -0
  190. package/dist/runtime/analysis/rules/errors/e007-output-not-guaranteed.d.ts +23 -0
  191. package/dist/runtime/analysis/rules/errors/e007-output-not-guaranteed.js +56 -0
  192. package/dist/runtime/analysis/rules/errors/e008-circular-dependency.d.ts +22 -0
  193. package/dist/runtime/analysis/rules/errors/e008-circular-dependency.js +84 -0
  194. package/dist/runtime/analysis/rules/errors/e009-implicit-user-input.d.ts +23 -0
  195. package/dist/runtime/analysis/rules/errors/e009-implicit-user-input.js +89 -0
  196. package/dist/runtime/analysis/rules/errors/e010-non-serializable.d.ts +25 -0
  197. package/dist/runtime/analysis/rules/errors/e010-non-serializable.js +46 -0
  198. package/dist/runtime/analysis/rules/errors/e011-missing-tool-description.d.ts +24 -0
  199. package/dist/runtime/analysis/rules/errors/e011-missing-tool-description.js +33 -0
  200. package/dist/runtime/analysis/rules/errors/e012-side-effect-detected.d.ts +39 -0
  201. package/dist/runtime/analysis/rules/errors/e012-side-effect-detected.js +40 -0
  202. package/dist/runtime/analysis/rules/errors/e013-non-deterministic-output.d.ts +37 -0
  203. package/dist/runtime/analysis/rules/errors/e013-non-deterministic-output.js +34 -0
  204. package/dist/runtime/analysis/rules/errors/e013-output-explosion.d.ts +39 -0
  205. package/dist/runtime/analysis/rules/errors/e013-output-explosion.js +36 -0
  206. package/dist/runtime/analysis/rules/errors/e014-hidden-dependency.d.ts +42 -0
  207. package/dist/runtime/analysis/rules/errors/e014-hidden-dependency.js +46 -0
  208. package/dist/runtime/analysis/rules/errors/e014-output-explosion.d.ts +39 -0
  209. package/dist/runtime/analysis/rules/errors/e014-output-explosion.js +36 -0
  210. package/dist/runtime/analysis/rules/errors/e015-hidden-dependency.d.ts +42 -0
  211. package/dist/runtime/analysis/rules/errors/e015-hidden-dependency.js +46 -0
  212. package/dist/runtime/analysis/rules/errors/e015-unbounded-execution.d.ts +44 -0
  213. package/dist/runtime/analysis/rules/errors/e015-unbounded-execution.js +66 -0
  214. package/dist/runtime/analysis/rules/errors/e016-output-validation-failed.d.ts +43 -0
  215. package/dist/runtime/analysis/rules/errors/e016-output-validation-failed.js +42 -0
  216. package/dist/runtime/analysis/rules/errors/e016-unbounded-execution.d.ts +44 -0
  217. package/dist/runtime/analysis/rules/errors/e016-unbounded-execution.js +66 -0
  218. package/dist/runtime/analysis/rules/errors/e017-input-validation-failed.d.ts +57 -0
  219. package/dist/runtime/analysis/rules/errors/e017-input-validation-failed.js +80 -0
  220. package/dist/runtime/analysis/rules/errors/e017-output-validation-failed.d.ts +43 -0
  221. package/dist/runtime/analysis/rules/errors/e017-output-validation-failed.js +42 -0
  222. package/dist/runtime/analysis/rules/errors/e018-input-validation-failed.d.ts +57 -0
  223. package/dist/runtime/analysis/rules/errors/e018-input-validation-failed.js +80 -0
  224. package/dist/runtime/analysis/rules/errors/e018-tool-execution-failed.d.ts +38 -0
  225. package/dist/runtime/analysis/rules/errors/e018-tool-execution-failed.js +37 -0
  226. package/dist/runtime/analysis/rules/errors/e019-tool-execution-failed.d.ts +38 -0
  227. package/dist/runtime/analysis/rules/errors/e019-tool-execution-failed.js +37 -0
  228. package/dist/runtime/analysis/rules/errors/e019-unexpected-test-result.d.ts +65 -0
  229. package/dist/runtime/analysis/rules/errors/e019-unexpected-test-result.js +109 -0
  230. package/dist/runtime/analysis/rules/errors/e020-unexpected-test-result.d.ts +65 -0
  231. package/dist/runtime/analysis/rules/errors/e020-unexpected-test-result.js +109 -0
  232. package/dist/runtime/analysis/rules/errors/e100-missing-output-schema.d.ts +22 -0
  233. package/dist/runtime/analysis/rules/errors/e100-missing-output-schema.js +30 -0
  234. package/dist/runtime/analysis/rules/errors/e101-missing-tool-description.d.ts +24 -0
  235. package/dist/runtime/analysis/rules/errors/e101-missing-tool-description.js +33 -0
  236. package/dist/runtime/analysis/rules/errors/e102-underspecified-input.d.ts +24 -0
  237. package/dist/runtime/analysis/rules/errors/e102-underspecified-input.js +52 -0
  238. package/dist/runtime/analysis/rules/errors/e103-type-mismatch.d.ts +23 -0
  239. package/dist/runtime/analysis/rules/errors/e103-type-mismatch.js +72 -0
  240. package/dist/runtime/analysis/rules/errors/e104-param-not-in-description.d.ts +22 -0
  241. package/dist/runtime/analysis/rules/errors/e104-param-not-in-description.js +57 -0
  242. package/dist/runtime/analysis/rules/errors/e105-free-text-propagation.d.ts +23 -0
  243. package/dist/runtime/analysis/rules/errors/e105-free-text-propagation.js +47 -0
  244. package/dist/runtime/analysis/rules/errors/e106-output-not-guaranteed.d.ts +23 -0
  245. package/dist/runtime/analysis/rules/errors/e106-output-not-guaranteed.js +58 -0
  246. package/dist/runtime/analysis/rules/errors/e107-circular-dependency.d.ts +22 -0
  247. package/dist/runtime/analysis/rules/errors/e107-circular-dependency.js +84 -0
  248. package/dist/runtime/analysis/rules/errors/e108-implicit-user-input.d.ts +23 -0
  249. package/dist/runtime/analysis/rules/errors/e108-implicit-user-input.js +94 -0
  250. package/dist/runtime/analysis/rules/errors/e109-non-serializable.d.ts +25 -0
  251. package/dist/runtime/analysis/rules/errors/e109-non-serializable.js +44 -0
  252. package/dist/runtime/analysis/rules/errors/e110-tool-ambiguity.d.ts +25 -0
  253. package/dist/runtime/analysis/rules/errors/e110-tool-ambiguity.js +73 -0
  254. package/dist/runtime/analysis/rules/errors/e200-input-validation-failed.d.ts +57 -0
  255. package/dist/runtime/analysis/rules/errors/e200-input-validation-failed.js +71 -0
  256. package/dist/runtime/analysis/rules/errors/e300-output-validation-failed.d.ts +43 -0
  257. package/dist/runtime/analysis/rules/errors/e300-output-validation-failed.js +44 -0
  258. package/dist/runtime/analysis/rules/errors/e301-output-explosion.d.ts +39 -0
  259. package/dist/runtime/analysis/rules/errors/e301-output-explosion.js +36 -0
  260. package/dist/runtime/analysis/rules/errors/e400-tool-execution-failed.d.ts +38 -0
  261. package/dist/runtime/analysis/rules/errors/e400-tool-execution-failed.js +37 -0
  262. package/dist/runtime/analysis/rules/errors/e403-unbounded-execution.d.ts +44 -0
  263. package/dist/runtime/analysis/rules/errors/e403-unbounded-execution.js +66 -0
  264. package/dist/runtime/analysis/rules/errors/e500-side-effect-detected.d.ts +39 -0
  265. package/dist/runtime/analysis/rules/errors/e500-side-effect-detected.js +40 -0
  266. package/dist/runtime/analysis/rules/errors/e501-hidden-dependency.d.ts +47 -0
  267. package/dist/runtime/analysis/rules/errors/e501-hidden-dependency.js +46 -0
  268. package/dist/runtime/analysis/rules/errors/e600-unexpected-test-result.d.ts +65 -0
  269. package/dist/runtime/analysis/rules/errors/e600-unexpected-test-result.js +109 -0
  270. package/dist/runtime/analysis/rules/index.d.ts +18 -0
  271. package/dist/runtime/analysis/rules/index.js +94 -0
  272. package/dist/runtime/analysis/rules/warnings/w001-implicit-dependency.d.ts +22 -0
  273. package/dist/runtime/analysis/rules/warnings/w001-implicit-dependency.js +39 -0
  274. package/dist/runtime/analysis/rules/warnings/w002-free-text-without-normalization.d.ts +24 -0
  275. package/dist/runtime/analysis/rules/warnings/w002-free-text-without-normalization.js +40 -0
  276. package/dist/runtime/analysis/rules/warnings/w003-missing-examples.d.ts +22 -0
  277. package/dist/runtime/analysis/rules/warnings/w003-missing-examples.js +84 -0
  278. package/dist/runtime/analysis/rules/warnings/w004-overloaded-responsibility.d.ts +23 -0
  279. package/dist/runtime/analysis/rules/warnings/w004-overloaded-responsibility.js +96 -0
  280. package/dist/runtime/analysis/rules/warnings/w005-generic-description.d.ts +53 -0
  281. package/dist/runtime/analysis/rules/warnings/w005-generic-description.js +108 -0
  282. package/dist/runtime/analysis/rules/warnings/w006-optional-as-required.d.ts +22 -0
  283. package/dist/runtime/analysis/rules/warnings/w006-optional-as-required.js +44 -0
  284. package/dist/runtime/analysis/rules/warnings/w007-broad-output-schema.d.ts +23 -0
  285. package/dist/runtime/analysis/rules/warnings/w007-broad-output-schema.js +37 -0
  286. package/dist/runtime/analysis/rules/warnings/w008-multiple-entry-points.d.ts +22 -0
  287. package/dist/runtime/analysis/rules/warnings/w008-multiple-entry-points.js +97 -0
  288. package/dist/runtime/analysis/rules/warnings/w009-hidden-side-effects.d.ts +23 -0
  289. package/dist/runtime/analysis/rules/warnings/w009-hidden-side-effects.js +88 -0
  290. package/dist/runtime/analysis/rules/warnings/w010-output-not-reusable.d.ts +22 -0
  291. package/dist/runtime/analysis/rules/warnings/w010-output-not-reusable.js +81 -0
  292. package/dist/runtime/analysis/rules/warnings/w021-weak-schema.d.ts +40 -0
  293. package/dist/runtime/analysis/rules/warnings/w021-weak-schema.js +32 -0
  294. package/dist/runtime/analysis/rules/warnings/w022-high-entropy-output.d.ts +39 -0
  295. package/dist/runtime/analysis/rules/warnings/w022-high-entropy-output.js +36 -0
  296. package/dist/runtime/analysis/rules/warnings/w023-unstable-defaults.d.ts +38 -0
  297. package/dist/runtime/analysis/rules/warnings/w023-unstable-defaults.js +36 -0
  298. package/dist/runtime/analysis/rules/warnings/w100-implicit-dependency.d.ts +22 -0
  299. package/dist/runtime/analysis/rules/warnings/w100-implicit-dependency.js +89 -0
  300. package/dist/runtime/analysis/rules/warnings/w101-free-text-without-normalization.d.ts +24 -0
  301. package/dist/runtime/analysis/rules/warnings/w101-free-text-without-normalization.js +40 -0
  302. package/dist/runtime/analysis/rules/warnings/w102-missing-examples.d.ts +22 -0
  303. package/dist/runtime/analysis/rules/warnings/w102-missing-examples.js +76 -0
  304. package/dist/runtime/analysis/rules/warnings/w103-overloaded-responsibility.d.ts +23 -0
  305. package/dist/runtime/analysis/rules/warnings/w103-overloaded-responsibility.js +91 -0
  306. package/dist/runtime/analysis/rules/warnings/w104-generic-description.d.ts +53 -0
  307. package/dist/runtime/analysis/rules/warnings/w104-generic-description.js +108 -0
  308. package/dist/runtime/analysis/rules/warnings/w105-optional-as-required.d.ts +22 -0
  309. package/dist/runtime/analysis/rules/warnings/w105-optional-as-required.js +45 -0
  310. package/dist/runtime/analysis/rules/warnings/w106-broad-output-schema.d.ts +23 -0
  311. package/dist/runtime/analysis/rules/warnings/w106-broad-output-schema.js +37 -0
  312. package/dist/runtime/analysis/rules/warnings/w107-multiple-entry-points.d.ts +22 -0
  313. package/dist/runtime/analysis/rules/warnings/w107-multiple-entry-points.js +97 -0
  314. package/dist/runtime/analysis/rules/warnings/w108-hidden-side-effects.d.ts +23 -0
  315. package/dist/runtime/analysis/rules/warnings/w108-hidden-side-effects.js +94 -0
  316. package/dist/runtime/analysis/rules/warnings/w109-output-not-reusable.d.ts +22 -0
  317. package/dist/runtime/analysis/rules/warnings/w109-output-not-reusable.js +63 -0
  318. package/dist/runtime/analysis/rules/warnings/w110-weak-schema.d.ts +40 -0
  319. package/dist/runtime/analysis/rules/warnings/w110-weak-schema.js +32 -0
  320. package/dist/runtime/analysis/rules/warnings/w300-high-entropy-output.d.ts +39 -0
  321. package/dist/runtime/analysis/rules/warnings/w300-high-entropy-output.js +47 -0
  322. package/dist/runtime/analysis/rules/warnings/w301-unstable-defaults.d.ts +38 -0
  323. package/dist/runtime/analysis/rules/warnings/w301-unstable-defaults.js +36 -0
  324. package/dist/runtime/analysis/strict-mode.d.ts +21 -0
  325. package/dist/runtime/analysis/strict-mode.js +44 -0
  326. package/dist/runtime/analysis/types.d.ts +133 -0
  327. package/dist/runtime/analysis/types.js +6 -0
  328. package/dist/runtime/analysis/utils.d.ts +19 -0
  329. package/dist/runtime/analysis/utils.js +21 -0
  330. package/dist/runtime/dev/data-manager.d.ts +55 -0
  331. package/dist/runtime/dev/data-manager.js +87 -0
  332. package/dist/runtime/dev/event-mapper.d.ts +100 -0
  333. package/dist/runtime/dev/event-mapper.js +400 -0
  334. package/dist/runtime/dev/formatter.d.ts +94 -0
  335. package/dist/runtime/dev/formatter.js +236 -0
  336. package/dist/runtime/dev/index.d.ts +9 -0
  337. package/dist/runtime/dev/index.js +9 -0
  338. package/dist/runtime/dev/repl.d.ts +114 -0
  339. package/dist/runtime/dev/repl.js +310 -0
  340. package/dist/runtime/dev/session.d.ts +86 -0
  341. package/dist/runtime/dev/session.js +447 -0
  342. package/dist/runtime/dev/stack-trace.d.ts +77 -0
  343. package/dist/runtime/dev/stack-trace.js +286 -0
  344. package/dist/runtime/dev/types.d.ts +54 -0
  345. package/dist/runtime/dev/types.js +5 -0
  346. package/dist/runtime/llm/claude.d.ts +27 -0
  347. package/dist/runtime/llm/claude.js +150 -0
  348. package/dist/runtime/llm/factory.d.ts +30 -0
  349. package/dist/runtime/llm/factory.js +78 -0
  350. package/dist/runtime/llm/index.d.ts +10 -0
  351. package/dist/runtime/llm/index.js +10 -0
  352. package/dist/runtime/llm/ollama.d.ts +45 -0
  353. package/dist/runtime/llm/ollama.js +449 -0
  354. package/dist/runtime/llm/openai.d.ts +27 -0
  355. package/dist/runtime/llm/openai.js +170 -0
  356. package/dist/runtime/llm/provider.d.ts +32 -0
  357. package/dist/runtime/llm/provider.js +6 -0
  358. package/dist/runtime/llm/types.d.ts +55 -0
  359. package/dist/runtime/llm/types.js +6 -0
  360. package/dist/runtime/mcp/client/base.d.ts +40 -0
  361. package/dist/runtime/mcp/client/base.js +157 -0
  362. package/dist/runtime/mcp/client/manager.d.ts +91 -0
  363. package/dist/runtime/mcp/client/manager.js +248 -0
  364. package/dist/runtime/mcp/client/process.d.ts +31 -0
  365. package/dist/runtime/mcp/client/process.js +82 -0
  366. package/dist/runtime/mcp/connection.d.ts +63 -0
  367. package/dist/runtime/mcp/connection.js +449 -0
  368. package/dist/runtime/mcp/index.d.ts +9 -0
  369. package/dist/runtime/mcp/index.js +9 -0
  370. package/dist/runtime/mcp/list.d.ts +50 -0
  371. package/dist/runtime/mcp/list.js +65 -0
  372. package/dist/runtime/mcp/stdio-transport.d.ts +23 -0
  373. package/dist/runtime/mcp/stdio-transport.js +71 -0
  374. package/dist/runtime/mcp/types.d.ts +85 -0
  375. package/dist/runtime/mcp/types.js +6 -0
  376. package/dist/runtime/sandbox/executor.d.ts +102 -0
  377. package/dist/runtime/sandbox/executor.js +537 -0
  378. package/dist/runtime/sandbox/index.d.ts +9 -0
  379. package/dist/runtime/sandbox/index.js +9 -0
  380. package/dist/runtime/sandbox/io-monitor.d.ts +78 -0
  381. package/dist/runtime/sandbox/io-monitor.js +98 -0
  382. package/dist/runtime/sandbox/time-parser.d.ts +19 -0
  383. package/dist/runtime/sandbox/time-parser.js +67 -0
  384. package/dist/runtime/sandbox/types.d.ts +58 -0
  385. package/dist/runtime/sandbox/types.js +23 -0
  386. package/dist/runtime/test/behavior-observer.d.ts +61 -0
  387. package/dist/runtime/test/behavior-observer.js +140 -0
  388. package/dist/runtime/test/contract-loader.d.ts +41 -0
  389. package/dist/runtime/test/contract-loader.js +158 -0
  390. package/dist/runtime/test/contract-schema.d.ts +46 -0
  391. package/dist/runtime/test/contract-schema.js +107 -0
  392. package/dist/runtime/test/contract-types.d.ts +106 -0
  393. package/dist/runtime/test/contract-types.js +6 -0
  394. package/dist/runtime/test/dependency-tracker.d.ts +66 -0
  395. package/dist/runtime/test/dependency-tracker.js +80 -0
  396. package/dist/runtime/test/formatters.d.ts +18 -0
  397. package/dist/runtime/test/formatters.js +172 -0
  398. package/dist/runtime/test/index.d.ts +12 -0
  399. package/dist/runtime/test/index.js +13 -0
  400. package/dist/runtime/test/input-generator.d.ts +33 -0
  401. package/dist/runtime/test/input-generator.js +498 -0
  402. package/dist/runtime/test/mcp-root-detector.d.ts +31 -0
  403. package/dist/runtime/test/mcp-root-detector.js +105 -0
  404. package/dist/runtime/test/orchestrator.d.ts +131 -0
  405. package/dist/runtime/test/orchestrator.js +738 -0
  406. package/dist/runtime/test/output-validator.d.ts +44 -0
  407. package/dist/runtime/test/output-validator.js +262 -0
  408. package/dist/runtime/test/retry-tester.d.ts +44 -0
  409. package/dist/runtime/test/retry-tester.js +103 -0
  410. package/dist/runtime/test/runner.d.ts +28 -0
  411. package/dist/runtime/test/runner.js +55 -0
  412. package/dist/runtime/test/synthetic-input-generator.d.ts +11 -0
  413. package/dist/runtime/test/synthetic-input-generator.js +154 -0
  414. package/dist/runtime/test/test-runner.d.ts +28 -0
  415. package/dist/runtime/test/test-runner.js +55 -0
  416. package/dist/types/factories.d.ts +16 -0
  417. package/dist/types/factories.js +43 -0
  418. package/dist/types/ids.d.ts +16 -0
  419. package/dist/types/ids.js +2 -0
  420. package/dist/types/opaque.d.ts +4 -0
  421. package/dist/types/opaque.js +2 -0
  422. package/dist/utils/errors.d.ts +92 -0
  423. package/dist/utils/errors.js +97 -0
  424. package/dist/utils/gitignore.d.ts +11 -0
  425. package/dist/utils/gitignore.js +59 -0
  426. package/dist/utils/json-file-saver.d.ts +17 -0
  427. package/dist/utils/json-file-saver.js +81 -0
  428. package/dist/utils/json-formatter.d.ts +63 -0
  429. package/dist/utils/json-formatter.js +344 -0
  430. package/dist/utils/logger.d.ts +184 -0
  431. package/dist/utils/logger.js +330 -0
  432. package/dist/utils/package-manager.d.ts +30 -0
  433. package/dist/utils/package-manager.js +157 -0
  434. package/dist/utils/version-checker.d.ts +47 -0
  435. package/dist/utils/version-checker.js +167 -0
  436. package/dist/utils/version-display.d.ts +10 -0
  437. package/dist/utils/version-display.js +20 -0
  438. package/package.json +106 -0
@@ -0,0 +1,419 @@
1
+ /**
2
+ * `syrin dev` command implementation.
3
+ * Interactive development mode for testing MCP tools with LLMs.
4
+ */
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import { loadConfig } from '../../config/loader.js';
8
+ import { getLLMProvider } from '../../runtime/llm/factory.js';
9
+ import { createMCPClientManager } from '../../runtime/mcp/client/manager.js';
10
+ import { RuntimeEventEmitter } from '../../events/emitter.js';
11
+ import { MemoryEventStore } from '../../events/store/memory-store.js';
12
+ import { FileEventStore } from '../../events/store/file-store.js';
13
+ import { DevSession } from '../../runtime/dev/session.js';
14
+ import { ChatUI } from '../../presentation/dev/chat-ui.js';
15
+ import { DevEventMapper } from '../../runtime/dev/event-mapper.js';
16
+ import { ConfigurationError } from '../../utils/errors.js';
17
+ import { handleCommandError } from '../../cli/utils/index.js';
18
+ import { logger, log } from '../../utils/logger.js';
19
+ import { Messages, Paths, TransportTypes, FileExtensions } from '../../constants/index.js';
20
+ import { makeSessionID } from '../../types/factories.js';
21
+ import { v4 as uuidv4 } from 'uuid';
22
+ import { buildDevWelcomeMessages, formatToolsList, formatCommandHistory, } from '../../presentation/dev-ui.js';
23
+ /**
24
+ * Resolve the server command to use based on config and run-script flag.
25
+ * @param config - Syrin configuration
26
+ * @param runScript - Whether to run the script (spawn server)
27
+ * @returns Resolved command and whether to spawn the server
28
+ */
29
+ function resolveServerCommand(config, runScript) {
30
+ // If run-script flag is provided, spawn using config.script
31
+ if (runScript) {
32
+ if (!config.script) {
33
+ throw new ConfigurationError(Messages.TRANSPORT_SCRIPT_REQUIRED_RUN_FLAG);
34
+ }
35
+ return { command: config.script, shouldSpawn: true };
36
+ }
37
+ // No run-script flag provided
38
+ if (config.transport === TransportTypes.STDIO) {
39
+ // For stdio, always spawn using script
40
+ if (!config.script) {
41
+ throw new ConfigurationError(Messages.TRANSPORT_SCRIPT_REQUIRED);
42
+ }
43
+ return { command: config.script, shouldSpawn: true };
44
+ }
45
+ // For HTTP without run-script flag, don't spawn (connect to existing server)
46
+ return { command: undefined, shouldSpawn: false };
47
+ }
48
+ /**
49
+ * Execute the dev command.
50
+ */
51
+ export async function executeDev(options = {}) {
52
+ const projectRoot = options.projectRoot || process.cwd();
53
+ try {
54
+ // Load configuration
55
+ const config = loadConfig(projectRoot);
56
+ // Validate transport configuration
57
+ if (config.transport === TransportTypes.HTTP && !config.mcp_url) {
58
+ throw new ConfigurationError(Messages.TRANSPORT_URL_REQUIRED_CONFIG);
59
+ }
60
+ // Resolve server command based on transport and run-script flag
61
+ const { command: serverCommand, shouldSpawn } = resolveServerCommand(config, options.runScript || false);
62
+ // For stdio, server command is always required
63
+ if (config.transport === TransportTypes.STDIO && !serverCommand) {
64
+ throw new ConfigurationError(Messages.TRANSPORT_SCRIPT_REQUIRED);
65
+ }
66
+ // Create session ID
67
+ const sessionId = makeSessionID(`dev-${uuidv4()}`);
68
+ // Create event store
69
+ let eventStore;
70
+ if (options.saveEvents) {
71
+ // Determine events directory
72
+ // If eventFile is provided, treat it as a directory path
73
+ // If it looks like a file path (ends with .jsonl), use its directory
74
+ let eventsDir;
75
+ if (options.eventFile) {
76
+ if (options.eventFile.endsWith(FileExtensions.JSONL)) {
77
+ // User provided a file path, use its directory
78
+ eventsDir = path.dirname(options.eventFile);
79
+ }
80
+ else {
81
+ // User provided a directory path
82
+ eventsDir = options.eventFile;
83
+ }
84
+ }
85
+ else {
86
+ // Default to .syrin/events in project root
87
+ eventsDir = path.join(projectRoot, Paths.EVENTS_DIR);
88
+ }
89
+ eventStore = new FileEventStore(eventsDir);
90
+ const eventFilePath = path.join(eventsDir, `${sessionId}${FileExtensions.JSONL}`);
91
+ logger.info(`Events will be saved to: ${eventFilePath}`);
92
+ log.blank();
93
+ log.info(`Events are being saved to: ${eventFilePath}`);
94
+ log.blank();
95
+ }
96
+ else {
97
+ eventStore = new MemoryEventStore();
98
+ }
99
+ // Create event emitter
100
+ const eventEmitter = new RuntimeEventEmitter(eventStore, sessionId, null, // workflowId
101
+ null // promptId
102
+ );
103
+ // Create LLM provider
104
+ const llmProvider = getLLMProvider(options.llm, config, projectRoot);
105
+ // Create MCP client manager
106
+ const mcpClientManager = createMCPClientManager(config.transport, config.mcp_url, serverCommand, eventEmitter, shouldSpawn);
107
+ // Set up cleanup handlers for all exit scenarios
108
+ // This ensures child processes are always killed, even on unexpected exits
109
+ const cleanup = async () => {
110
+ try {
111
+ // Always disconnect (this kills the child process)
112
+ await mcpClientManager.disconnect();
113
+ // Close event store if used
114
+ if (options.saveEvents && eventStore instanceof FileEventStore) {
115
+ await eventStore.close();
116
+ }
117
+ }
118
+ catch (error) {
119
+ const err = error instanceof Error ? error : new Error(String(error));
120
+ logger.error('Error during cleanup', err);
121
+ // Even if disconnect fails, try to kill the process directly
122
+ // This is a safety net to ensure cleanup happens
123
+ }
124
+ };
125
+ // Note: SIGINT handling is now done in the ChatUI section below
126
+ // Handle SIGTERM
127
+ process.on('SIGTERM', () => {
128
+ void (async () => {
129
+ await cleanup();
130
+ process.exit(0);
131
+ })();
132
+ });
133
+ // Handle uncaught exceptions
134
+ process.on('uncaughtException', (error) => {
135
+ void (async () => {
136
+ logger.error('Uncaught exception', error);
137
+ await cleanup();
138
+ process.exit(1);
139
+ })();
140
+ });
141
+ // Handle unhandled promise rejections
142
+ process.on('unhandledRejection', (reason) => {
143
+ void (async () => {
144
+ logger.error('Unhandled rejection', reason instanceof Error ? reason : new Error(String(reason)));
145
+ await cleanup();
146
+ process.exit(1);
147
+ })();
148
+ });
149
+ // Connect to MCP server
150
+ await mcpClientManager.connect();
151
+ // Get available tools
152
+ const availableTools = await mcpClientManager.getAvailableTools();
153
+ // Create dev session
154
+ const session = new DevSession({
155
+ config,
156
+ llmProvider,
157
+ mcpClientManager,
158
+ eventEmitter,
159
+ executionMode: options.exec || false,
160
+ projectRoot,
161
+ });
162
+ // Initialize session
163
+ await session.initialize();
164
+ // Build initial info messages for chat UI (will scroll away when user starts typing)
165
+ const displayCommand = shouldSpawn && serverCommand ? serverCommand : undefined;
166
+ const initialMessages = buildDevWelcomeMessages();
167
+ // Get version info for welcome banner - use same approach as other commands
168
+ const versionChecker = (await import('../../utils/version-checker.js'));
169
+ const versionInfo = await versionChecker.checkSyrinVersion();
170
+ const versionDisplayString = versionChecker.formatVersionWithUpdate(versionInfo);
171
+ // Create Chat UI
172
+ const historyFile = path.join(projectRoot, Paths.DEV_HISTORY_FILE);
173
+ // Bind the method to avoid closure type inference issues
174
+ const addToHistory = session.addUserMessageToHistory.bind(session);
175
+ // Declare event mapper variable (will be initialized after ChatUI starts)
176
+ // We need it in the onExit closure, so declare it here before ChatUI constructor
177
+ let eventMapper;
178
+ // Create ChatUI first (event mapper needs it)
179
+ const chatUI = new ChatUI({
180
+ agentName: config.agent_name,
181
+ llmProviderName: llmProvider.getName(),
182
+ showTimestamps: false,
183
+ initialMessages,
184
+ welcomeBanner: {
185
+ versionDisplay: versionDisplayString,
186
+ llmProvider: llmProvider.getName(),
187
+ toolCount: availableTools.length,
188
+ transport: config.transport,
189
+ mcpUrl: config.mcp_url,
190
+ command: displayCommand,
191
+ },
192
+ historyFile,
193
+ maxHistorySize: 1000,
194
+ getSessionState: () => {
195
+ const state = session.getState();
196
+ return {
197
+ totalToolCalls: state.totalToolCalls,
198
+ toolCalls: state.toolCalls.map(tc => ({
199
+ name: tc.name,
200
+ timestamp: tc.timestamp,
201
+ })),
202
+ startTime: state.startTime,
203
+ };
204
+ },
205
+ llmProvider: {
206
+ chat: async (request) => {
207
+ // Convert minimal request to LLMRequest format
208
+ const llmRequest = {
209
+ messages: request.messages.map(msg => ({
210
+ role: msg.role,
211
+ content: msg.content,
212
+ })),
213
+ temperature: request.temperature,
214
+ maxTokens: request.maxTokens,
215
+ };
216
+ const response = await llmProvider.chat(llmRequest);
217
+ // Convert LLMResponse to minimal format
218
+ return {
219
+ content: typeof response.content === 'string'
220
+ ? response.content
221
+ : JSON.stringify(response.content),
222
+ };
223
+ },
224
+ },
225
+ onMessage: async (input) => {
226
+ // Add user input to session conversation history (even for special commands)
227
+ // This ensures all commands are saved in chat history
228
+ addToHistory(input);
229
+ // Handle special commands
230
+ if (input === '/tools') {
231
+ const tools = session.getAvailableTools();
232
+ const toolsList = formatToolsList(tools);
233
+ chatUI.addMessage('system', toolsList);
234
+ return;
235
+ }
236
+ if (input.startsWith('/save-json')) {
237
+ // Save tool result JSON to file
238
+ // Usage: /save-json [tool-name-or-index]
239
+ // If no argument, saves the last tool result
240
+ const parts = input.split(/\s+/);
241
+ const toolIdentifier = parts[1]; // Optional: tool name or index
242
+ try {
243
+ const sessionState = session.getState();
244
+ const toolCalls = sessionState.toolCalls;
245
+ if (toolCalls.length === 0) {
246
+ chatUI.addMessage('system', 'No tool calls found. Run a tool first to save its result.');
247
+ return;
248
+ }
249
+ // Find the tool call to save
250
+ let toolCallToSave;
251
+ if (toolIdentifier) {
252
+ // Try to find by index first
253
+ const index = parseInt(toolIdentifier, 10);
254
+ if (!isNaN(index) && index > 0 && index <= toolCalls.length) {
255
+ // 1-indexed for user convenience
256
+ toolCallToSave = toolCalls[index - 1];
257
+ }
258
+ else {
259
+ // Try to find by name (case-insensitive, partial match)
260
+ const matchingCalls = toolCalls.filter(tc => tc.name.toLowerCase().includes(toolIdentifier.toLowerCase()));
261
+ if (matchingCalls.length === 0) {
262
+ chatUI.addMessage('system', `No tool found matching "${toolIdentifier}". Use /save-json without arguments to save the last result, or use a tool index (1-${toolCalls.length}).`);
263
+ return;
264
+ }
265
+ else if (matchingCalls.length > 1) {
266
+ // Multiple matches - show list
267
+ const toolList = matchingCalls
268
+ .map(tc => ` ${toolCalls.indexOf(tc) + 1}. ${tc.name} (${tc.timestamp.toLocaleTimeString()})`)
269
+ .join('\n');
270
+ chatUI.addMessage('system', `Multiple tools found matching "${toolIdentifier}":\n${toolList}\n\nUse /save-json <index> to save a specific one.`);
271
+ return;
272
+ }
273
+ else {
274
+ toolCallToSave = matchingCalls[0];
275
+ }
276
+ }
277
+ }
278
+ else {
279
+ // No identifier - use last tool call
280
+ toolCallToSave = toolCalls[toolCalls.length - 1];
281
+ }
282
+ if (!toolCallToSave) {
283
+ chatUI.addMessage('system', 'No tool result available to save.');
284
+ return;
285
+ }
286
+ // Check if result is available (either direct or via reference)
287
+ if (!toolCallToSave.result && !toolCallToSave.resultReference) {
288
+ chatUI.addMessage('system', 'No tool result available to save.');
289
+ return;
290
+ }
291
+ try {
292
+ // Get the result (load from file if externalized)
293
+ const result = session.getToolResult(toolCallToSave);
294
+ const { saveJSONToFile, getFileSize } = await import('../../utils/json-file-saver.js');
295
+ // Save to .syrin/data directory
296
+ const dataDir = path.join(projectRoot, '.syrin', 'data');
297
+ const filePath = saveJSONToFile(result, toolCallToSave.name, dataDir);
298
+ const fileSize = getFileSize(filePath);
299
+ chatUI.addMessage('system', `✅ JSON saved to file:\n ${filePath}\n Size: ${fileSize}\n Tool: ${toolCallToSave.name}\n\n💡 You can open this file with: cat "${filePath}" | jq .`);
300
+ }
301
+ catch (error) {
302
+ const errorMessage = error instanceof Error ? error.message : String(error);
303
+ chatUI.addMessage('system', `❌ Error loading tool result: ${errorMessage}`);
304
+ const err = error instanceof Error ? error : new Error(String(error));
305
+ logger.error('Error loading tool result for save', err);
306
+ }
307
+ }
308
+ catch (error) {
309
+ const errorMessage = error instanceof Error ? error.message : String(error);
310
+ chatUI.addMessage('system', `❌ Error saving JSON: ${errorMessage}`);
311
+ const err = error instanceof Error ? error : new Error(String(error));
312
+ logger.error('Error saving JSON to file', err);
313
+ }
314
+ return;
315
+ }
316
+ if (input === '/history') {
317
+ // Read history from .syrin/.dev-history file
318
+ try {
319
+ if (fs.existsSync(historyFile)) {
320
+ const content = fs.readFileSync(historyFile, 'utf-8');
321
+ const historyLines = content
322
+ .split('\n')
323
+ .filter((line) => line.trim())
324
+ .slice(-100); // Show last 100 entries
325
+ const historyDisplay = formatCommandHistory(historyLines);
326
+ chatUI.addMessage('system', historyDisplay);
327
+ }
328
+ else {
329
+ chatUI.addMessage('system', Messages.DEV_NO_HISTORY);
330
+ }
331
+ }
332
+ catch (error) {
333
+ const errorMessage = error instanceof Error ? error.message : String(error);
334
+ chatUI.addMessage('system', Messages.DEV_ERROR_READING_HISTORY(errorMessage));
335
+ const err = error instanceof Error ? error : new Error(String(error));
336
+ logger.error('Error reading history file', err);
337
+ }
338
+ return;
339
+ }
340
+ // Process user input through session
341
+ try {
342
+ await session.processUserInput(input);
343
+ // Get the latest assistant response from conversation history
344
+ // Note: Tool call events are already displayed incrementally by the event mapper
345
+ const stateAfter = session.getState();
346
+ const lastMessage = stateAfter.conversationHistory[stateAfter.conversationHistory.length - 1];
347
+ if (lastMessage && lastMessage.role === 'assistant') {
348
+ chatUI.addMessage('assistant', lastMessage.content);
349
+ }
350
+ }
351
+ catch (error) {
352
+ const errorMessage = error instanceof Error ? error.message : String(error);
353
+ chatUI.addMessage('system', `❌ Error: ${errorMessage}`);
354
+ const err = error instanceof Error ? error : new Error(String(error));
355
+ logger.error('Error processing user input', err);
356
+ }
357
+ },
358
+ onExit: async () => {
359
+ // Stop event mapper (it's guaranteed to be defined by this point)
360
+ eventMapper?.stop();
361
+ // Cleanup on exit
362
+ try {
363
+ await session.complete();
364
+ await mcpClientManager.disconnect();
365
+ // Close file event store if used
366
+ if (options.saveEvents && eventStore instanceof FileEventStore) {
367
+ await eventStore.close();
368
+ logger.info('Event store closed');
369
+ }
370
+ }
371
+ catch (error) {
372
+ const err = error instanceof Error ? error : new Error(String(error));
373
+ logger.error('Error during cleanup', err);
374
+ }
375
+ },
376
+ });
377
+ // Start Chat UI first to ensure refs are ready
378
+ // Start Chat UI (header message is already set in options)
379
+ await chatUI.start();
380
+ // Create and start event mapper for incremental visibility
381
+ // This provides real-time event updates to the UI as events are emitted
382
+ // Must be started AFTER ChatUI is started so refs are ready
383
+ eventMapper = new DevEventMapper(eventEmitter, chatUI, llmProvider.getName());
384
+ eventMapper.start(); // Now it's defined, we can call start
385
+ // Handle SIGINT (Ctrl+C) - ensure cleanup happens
386
+ let isExiting = false;
387
+ process.once('SIGINT', () => {
388
+ if (isExiting) {
389
+ return; // Already handling exit
390
+ }
391
+ isExiting = true;
392
+ log.plain(Messages.DEV_GOODBYE);
393
+ // Stop event mapper (it's guaranteed to be defined by this point)
394
+ eventMapper?.stop();
395
+ chatUI.stop();
396
+ void (async () => {
397
+ try {
398
+ await session.complete();
399
+ await mcpClientManager.disconnect();
400
+ // Close file event store if used
401
+ if (options.saveEvents && eventStore instanceof FileEventStore) {
402
+ await eventStore.close();
403
+ }
404
+ // Give a small delay to ensure process is killed
405
+ await new Promise(resolve => setTimeout(resolve, 100));
406
+ }
407
+ catch (error) {
408
+ const err = error instanceof Error ? error : new Error(String(error));
409
+ logger.error('Error during SIGINT cleanup', err);
410
+ }
411
+ process.exit(0);
412
+ })();
413
+ });
414
+ }
415
+ catch (error) {
416
+ handleCommandError(error, Messages.DEV_ERROR_START);
417
+ }
418
+ }
419
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `syrin doctor` command implementation.
3
+ * Validates the Syrin project configuration and setup.
4
+ */
5
+ /**
6
+ * Execute the doctor command.
7
+ * @param projectRoot - Project root directory (defaults to current working directory)
8
+ */
9
+ export declare function executeDoctor(projectRoot?: string): Promise<void>;
10
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1,195 @@
1
+ /**
2
+ * `syrin doctor` command implementation.
3
+ * Validates the Syrin project configuration and setup.
4
+ */
5
+ import { loadConfig } from '../../config/loader.js';
6
+ import { checkEnvVar, checkCommandExists, extractCommandName, } from '../../config/env-checker.js';
7
+ import { handleCommandError } from '../../cli/utils/index.js';
8
+ import { Messages, TransportTypes, Defaults, LLMProviders } from '../../constants/index.js';
9
+ import { displayDoctorReport } from '../../presentation/doctor-ui.js';
10
+ /**
11
+ * Check transport configuration.
12
+ */
13
+ function checkTransport(config) {
14
+ if (config.transport === TransportTypes.HTTP) {
15
+ if (!config.mcp_url) {
16
+ return {
17
+ isValid: false,
18
+ message: 'MCP URL is missing',
19
+ fix: Messages.CONFIG_ADD_MCP_URL,
20
+ };
21
+ }
22
+ return {
23
+ isValid: true,
24
+ message: Messages.DOCTOR_MCP_URL_INFO(String(config.mcp_url)),
25
+ };
26
+ }
27
+ else {
28
+ // stdio transport
29
+ if (!config.script) {
30
+ return {
31
+ isValid: false,
32
+ message: Messages.DOCTOR_SCRIPT_MISSING,
33
+ fix: Messages.CONFIG_ADD_SCRIPT_STDIO,
34
+ };
35
+ }
36
+ const commandName = extractCommandName(String(config.script));
37
+ const commandExists = checkCommandExists(commandName);
38
+ if (!commandExists) {
39
+ return {
40
+ isValid: false,
41
+ message: Messages.DOCTOR_COMMAND_NOT_FOUND(commandName),
42
+ fix: Messages.DOCTOR_COMMAND_INSTALL(commandName),
43
+ };
44
+ }
45
+ return {
46
+ isValid: true,
47
+ message: Messages.DOCTOR_SCRIPT_INFO(String(config.script)),
48
+ };
49
+ }
50
+ }
51
+ /**
52
+ * Check script command.
53
+ */
54
+ function checkScript(config) {
55
+ if (!config.script) {
56
+ // Script is optional for HTTP transport
57
+ return null;
58
+ }
59
+ const script = String(config.script);
60
+ // Skip validation for scripts that contain shell built-ins or compound commands
61
+ // These are typically complex shell scripts that can't be validated with simple command checking
62
+ // Common shell built-ins: source, cd, export, unset, alias, etc.
63
+ const shellBuiltIns = [
64
+ 'source',
65
+ 'cd',
66
+ 'export',
67
+ 'unset',
68
+ 'alias',
69
+ 'set',
70
+ 'unsetenv',
71
+ ];
72
+ const commandName = extractCommandName(script);
73
+ // If the first command is a shell built-in, skip validation
74
+ // Scripts with shell built-ins are expected to be run in a shell context
75
+ if (shellBuiltIns.includes(commandName)) {
76
+ return {
77
+ isValid: true, // Assume valid if it uses shell built-ins (will be executed in shell)
78
+ message: Defaults.WORKING,
79
+ };
80
+ }
81
+ const commandExists = checkCommandExists(commandName);
82
+ return {
83
+ isValid: commandExists,
84
+ message: commandExists
85
+ ? Defaults.WORKING
86
+ : Messages.DOCTOR_COMMAND_NOT_FOUND(commandName),
87
+ fix: commandExists
88
+ ? undefined
89
+ : Messages.DOCTOR_COMMAND_INSTALL(commandName),
90
+ };
91
+ }
92
+ /**
93
+ * Check LLM provider configuration.
94
+ */
95
+ function checkLLMProviders(config, projectRoot) {
96
+ const checks = [];
97
+ for (const [providerName, providerConfig] of Object.entries(config.llm)) {
98
+ if (providerName === LLMProviders.OLLAMA) {
99
+ // Ollama provider - skip API key checks (only MODEL_NAME is needed)
100
+ continue;
101
+ }
102
+ // Cloud provider - check API key and model name
103
+ const apiKeyVar = providerConfig.API_KEY
104
+ ? String(providerConfig.API_KEY)
105
+ : '';
106
+ const modelVar = providerConfig.MODEL_NAME
107
+ ? String(providerConfig.MODEL_NAME)
108
+ : '';
109
+ const apiKeyCheck = checkEnvVar(apiKeyVar, projectRoot);
110
+ const modelCheck = checkEnvVar(modelVar, projectRoot);
111
+ checks.push({
112
+ provider: providerName,
113
+ apiKeyCheck: {
114
+ isValid: apiKeyCheck.isSet,
115
+ message: apiKeyVar, // Always show the env var name
116
+ value: apiKeyCheck.value, // Actual API key value (for masking)
117
+ fix: apiKeyCheck.isSet
118
+ ? undefined
119
+ : apiKeyCheck.errorMessage ||
120
+ Messages.ENV_SET_INSTRUCTIONS(apiKeyVar),
121
+ },
122
+ modelCheck: {
123
+ isValid: modelCheck.isSet,
124
+ message: modelVar, // Always show the env var name
125
+ value: modelCheck.value, // Actual model name value
126
+ fix: modelCheck.isSet
127
+ ? undefined
128
+ : modelCheck.errorMessage || Messages.ENV_SET_INSTRUCTIONS(modelVar),
129
+ },
130
+ isDefault: providerConfig.default === true,
131
+ });
132
+ }
133
+ return checks;
134
+ }
135
+ /**
136
+ * Check local LLM providers.
137
+ */
138
+ function checkLocalLLMProviders(config, projectRoot) {
139
+ const checks = [];
140
+ for (const [providerName, providerConfig] of Object.entries(config.llm)) {
141
+ if (providerName === LLMProviders.OLLAMA) {
142
+ // Get model name for Ollama
143
+ const modelVar = providerConfig.MODEL_NAME
144
+ ? String(providerConfig.MODEL_NAME)
145
+ : '';
146
+ const modelCheck = checkEnvVar(modelVar, projectRoot);
147
+ checks.push({
148
+ provider: providerName,
149
+ check: {
150
+ isValid: modelCheck.isSet,
151
+ message: Defaults.WORKING,
152
+ },
153
+ modelName: modelCheck.value, // Actual model name
154
+ });
155
+ }
156
+ }
157
+ return checks.length > 0 ? checks : undefined;
158
+ }
159
+ /**
160
+ * Generate doctor report.
161
+ */
162
+ function generateReport(config, projectRoot) {
163
+ return {
164
+ config,
165
+ transportCheck: checkTransport(config),
166
+ scriptCheck: checkScript(config),
167
+ llmChecks: checkLLMProviders(config, projectRoot),
168
+ localLlmChecks: checkLocalLLMProviders(config, projectRoot),
169
+ };
170
+ }
171
+ /**
172
+ * Execute the doctor command.
173
+ * @param projectRoot - Project root directory (defaults to current working directory)
174
+ */
175
+ export async function executeDoctor(projectRoot = process.cwd()) {
176
+ try {
177
+ // Load configuration
178
+ const config = loadConfig(projectRoot);
179
+ // Generate report
180
+ const report = generateReport(config, projectRoot);
181
+ // Display report using Ink UI
182
+ await displayDoctorReport(report);
183
+ // Exit with appropriate code
184
+ const allValid = report.transportCheck.isValid &&
185
+ (report.scriptCheck === null || report.scriptCheck.isValid) &&
186
+ report.llmChecks.every(l => l.apiKeyCheck.isValid && l.modelCheck.isValid);
187
+ if (!allValid) {
188
+ process.exit(1);
189
+ }
190
+ }
191
+ catch (error) {
192
+ handleCommandError(error);
193
+ }
194
+ }
195
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * CLI commands exports.
3
+ */
4
+ export * from './init.js';
5
+ export * from './doctor.js';
6
+ export * from './test.js';
7
+ export * from './list.js';
8
+ export * from './dev.js';
9
+ export * from './update.js';
10
+ export * from './rollback.js';
11
+ export * from './analyse.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * CLI commands exports.
3
+ */
4
+ export * from './init.js';
5
+ export * from './doctor.js';
6
+ export * from './test.js';
7
+ export * from './list.js';
8
+ export * from './dev.js';
9
+ export * from './update.js';
10
+ export * from './rollback.js';
11
+ export * from './analyse.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `syrin init` command implementation.
3
+ * Initializes a new Syrin project with configuration.
4
+ */
5
+ export interface InitCommandOptions {
6
+ /** Skip interactive prompts, use defaults */
7
+ yes?: boolean;
8
+ /** Project root directory (defaults to current working directory) */
9
+ projectRoot?: string;
10
+ }
11
+ /**
12
+ * Execute the init command.
13
+ * @param options - Command options
14
+ */
15
+ export declare function executeInit(options?: InitCommandOptions): Promise<void>;
16
+ //# sourceMappingURL=init.d.ts.map