sales-frontend-ju-hong-e 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/dist/be.cjs +4446 -0
  2. package/dist/be.cjs.map +1 -0
  3. package/dist/be.js +4432 -0
  4. package/dist/be.js.map +1 -0
  5. package/dist/cli.cjs +4446 -0
  6. package/dist/cli.cjs.map +1 -0
  7. package/dist/cli.js +4432 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/command-modules/ju-hong-e/change-service/index.cjs +2311 -0
  10. package/dist/command-modules/ju-hong-e/change-service/index.cjs.map +1 -0
  11. package/dist/command-modules/ju-hong-e/change-service/index.js +2301 -0
  12. package/dist/command-modules/ju-hong-e/change-service/index.js.map +1 -0
  13. package/dist/command-modules/ju-hong-e/commit/action.cjs +2304 -0
  14. package/dist/command-modules/ju-hong-e/commit/action.cjs.map +1 -0
  15. package/dist/command-modules/ju-hong-e/commit/action.js +2294 -0
  16. package/dist/command-modules/ju-hong-e/commit/action.js.map +1 -0
  17. package/dist/command-modules/ju-hong-e/commit/index.cjs +2527 -0
  18. package/dist/command-modules/ju-hong-e/commit/index.cjs.map +1 -0
  19. package/dist/command-modules/ju-hong-e/commit/index.js +2515 -0
  20. package/dist/command-modules/ju-hong-e/commit/index.js.map +1 -0
  21. package/dist/command-modules/ju-hong-e/exit/index.cjs +2070 -0
  22. package/dist/command-modules/ju-hong-e/exit/index.cjs.map +1 -0
  23. package/dist/command-modules/ju-hong-e/exit/index.js +2058 -0
  24. package/dist/command-modules/ju-hong-e/exit/index.js.map +1 -0
  25. package/dist/command-modules/ju-hong-e/gen-html/action.cjs +4260 -0
  26. package/dist/command-modules/ju-hong-e/gen-html/action.cjs.map +1 -0
  27. package/dist/command-modules/ju-hong-e/gen-html/action.js +4248 -0
  28. package/dist/command-modules/ju-hong-e/gen-html/action.js.map +1 -0
  29. package/dist/command-modules/ju-hong-e/gen-html/index.cjs +4435 -0
  30. package/dist/command-modules/ju-hong-e/gen-html/index.cjs.map +1 -0
  31. package/dist/command-modules/ju-hong-e/gen-html/index.js +4421 -0
  32. package/dist/command-modules/ju-hong-e/gen-html/index.js.map +1 -0
  33. package/dist/command-modules/ju-hong-e/gen-html/runtime.cjs +335 -0
  34. package/dist/command-modules/ju-hong-e/gen-html/runtime.cjs.map +1 -0
  35. package/dist/command-modules/ju-hong-e/gen-html/runtime.js +324 -0
  36. package/dist/command-modules/ju-hong-e/gen-html/runtime.js.map +1 -0
  37. package/dist/command-modules/ju-hong-e/gen-storybook/action.cjs +2542 -0
  38. package/dist/command-modules/ju-hong-e/gen-storybook/action.cjs.map +1 -0
  39. package/dist/command-modules/ju-hong-e/gen-storybook/action.js +2532 -0
  40. package/dist/command-modules/ju-hong-e/gen-storybook/action.js.map +1 -0
  41. package/dist/command-modules/ju-hong-e/gen-storybook/index.cjs +2724 -0
  42. package/dist/command-modules/ju-hong-e/gen-storybook/index.cjs.map +1 -0
  43. package/dist/command-modules/ju-hong-e/gen-storybook/index.js +2712 -0
  44. package/dist/command-modules/ju-hong-e/gen-storybook/index.js.map +1 -0
  45. package/dist/command-modules/ju-hong-e/gen-storybook/runtime.cjs +287 -0
  46. package/dist/command-modules/ju-hong-e/gen-storybook/runtime.cjs.map +1 -0
  47. package/dist/command-modules/ju-hong-e/gen-storybook/runtime.js +278 -0
  48. package/dist/command-modules/ju-hong-e/gen-storybook/runtime.js.map +1 -0
  49. package/dist/command-modules/ju-hong-e/help/index.cjs +2107 -0
  50. package/dist/command-modules/ju-hong-e/help/index.cjs.map +1 -0
  51. package/dist/command-modules/ju-hong-e/help/index.js +2097 -0
  52. package/dist/command-modules/ju-hong-e/help/index.js.map +1 -0
  53. package/dist/command-modules/ju-hong-e/local-server/action.cjs +2212 -0
  54. package/dist/command-modules/ju-hong-e/local-server/action.cjs.map +1 -0
  55. package/dist/command-modules/ju-hong-e/local-server/action.js +2199 -0
  56. package/dist/command-modules/ju-hong-e/local-server/action.js.map +1 -0
  57. package/dist/command-modules/ju-hong-e/mcp/action.cjs +1684 -0
  58. package/dist/command-modules/ju-hong-e/mcp/action.cjs.map +1 -0
  59. package/dist/command-modules/ju-hong-e/mcp/action.js +1672 -0
  60. package/dist/command-modules/ju-hong-e/mcp/action.js.map +1 -0
  61. package/dist/command-modules/ju-hong-e/mcp/index.cjs +2194 -0
  62. package/dist/command-modules/ju-hong-e/mcp/index.cjs.map +1 -0
  63. package/dist/command-modules/ju-hong-e/mcp/index.js +2182 -0
  64. package/dist/command-modules/ju-hong-e/mcp/index.js.map +1 -0
  65. package/dist/command-modules/ju-hong-e/mcp/runtime.cjs +554 -0
  66. package/dist/command-modules/ju-hong-e/mcp/runtime.cjs.map +1 -0
  67. package/dist/command-modules/ju-hong-e/mcp/runtime.js +538 -0
  68. package/dist/command-modules/ju-hong-e/mcp/runtime.js.map +1 -0
  69. package/dist/command-modules/ju-hong-e/mcp-health-check/index.cjs +2617 -0
  70. package/dist/command-modules/ju-hong-e/mcp-health-check/index.cjs.map +1 -0
  71. package/dist/command-modules/ju-hong-e/mcp-health-check/index.js +2605 -0
  72. package/dist/command-modules/ju-hong-e/mcp-health-check/index.js.map +1 -0
  73. package/dist/command-modules/ju-hong-e/mcp-register/index.cjs +2591 -0
  74. package/dist/command-modules/ju-hong-e/mcp-register/index.cjs.map +1 -0
  75. package/dist/command-modules/ju-hong-e/mcp-register/index.js +2579 -0
  76. package/dist/command-modules/ju-hong-e/mcp-register/index.js.map +1 -0
  77. package/dist/command-modules/ju-hong-e/mcp-unregister/index.cjs +2649 -0
  78. package/dist/command-modules/ju-hong-e/mcp-unregister/index.cjs.map +1 -0
  79. package/dist/command-modules/ju-hong-e/mcp-unregister/index.js +2637 -0
  80. package/dist/command-modules/ju-hong-e/mcp-unregister/index.js.map +1 -0
  81. package/dist/command-modules/ju-hong-e/restart-local-server/index.cjs +3490 -0
  82. package/dist/command-modules/ju-hong-e/restart-local-server/index.cjs.map +1 -0
  83. package/dist/command-modules/ju-hong-e/restart-local-server/index.js +3476 -0
  84. package/dist/command-modules/ju-hong-e/restart-local-server/index.js.map +1 -0
  85. package/dist/command-modules/ju-hong-e/review/action.cjs +2360 -0
  86. package/dist/command-modules/ju-hong-e/review/action.cjs.map +1 -0
  87. package/dist/command-modules/ju-hong-e/review/action.js +2350 -0
  88. package/dist/command-modules/ju-hong-e/review/action.js.map +1 -0
  89. package/dist/command-modules/ju-hong-e/review/index.cjs +2548 -0
  90. package/dist/command-modules/ju-hong-e/review/index.cjs.map +1 -0
  91. package/dist/command-modules/ju-hong-e/review/index.js +2536 -0
  92. package/dist/command-modules/ju-hong-e/review/index.js.map +1 -0
  93. package/dist/command-modules/ju-hong-e/security-policy/action.cjs +871 -0
  94. package/dist/command-modules/ju-hong-e/security-policy/action.cjs.map +1 -0
  95. package/dist/command-modules/ju-hong-e/security-policy/action.js +861 -0
  96. package/dist/command-modules/ju-hong-e/security-policy/action.js.map +1 -0
  97. package/dist/command-modules/ju-hong-e/security-policy/index.cjs +2341 -0
  98. package/dist/command-modules/ju-hong-e/security-policy/index.cjs.map +1 -0
  99. package/dist/command-modules/ju-hong-e/security-policy/index.js +2329 -0
  100. package/dist/command-modules/ju-hong-e/security-policy/index.js.map +1 -0
  101. package/dist/command-modules/ju-hong-e/setting-local-server/index.cjs +3135 -0
  102. package/dist/command-modules/ju-hong-e/setting-local-server/index.cjs.map +1 -0
  103. package/dist/command-modules/ju-hong-e/setting-local-server/index.js +3120 -0
  104. package/dist/command-modules/ju-hong-e/setting-local-server/index.js.map +1 -0
  105. package/dist/command-modules/ju-hong-e/show-stream/action.cjs +679 -0
  106. package/dist/command-modules/ju-hong-e/show-stream/action.cjs.map +1 -0
  107. package/dist/command-modules/ju-hong-e/show-stream/action.js +669 -0
  108. package/dist/command-modules/ju-hong-e/show-stream/action.js.map +1 -0
  109. package/dist/command-modules/ju-hong-e/show-stream/index.cjs +2190 -0
  110. package/dist/command-modules/ju-hong-e/show-stream/index.cjs.map +1 -0
  111. package/dist/command-modules/ju-hong-e/show-stream/index.js +2178 -0
  112. package/dist/command-modules/ju-hong-e/show-stream/index.js.map +1 -0
  113. package/dist/command-modules/ju-hong-e/toggle-storybook-mode/index.cjs +3514 -0
  114. package/dist/command-modules/ju-hong-e/toggle-storybook-mode/index.cjs.map +1 -0
  115. package/dist/command-modules/ju-hong-e/toggle-storybook-mode/index.js +3500 -0
  116. package/dist/command-modules/ju-hong-e/toggle-storybook-mode/index.js.map +1 -0
  117. package/dist/command-modules/native/claude/catalog/index.cjs +2111 -0
  118. package/dist/command-modules/native/claude/catalog/index.cjs.map +1 -0
  119. package/dist/command-modules/native/claude/catalog/index.js +2099 -0
  120. package/dist/command-modules/native/claude/catalog/index.js.map +1 -0
  121. package/dist/command-modules/native/codex/catalog/index.cjs +2087 -0
  122. package/dist/command-modules/native/codex/catalog/index.cjs.map +1 -0
  123. package/dist/command-modules/native/codex/catalog/index.js +2075 -0
  124. package/dist/command-modules/native/codex/catalog/index.js.map +1 -0
  125. package/dist/command-modules/native/gemini/catalog/index.cjs +2107 -0
  126. package/dist/command-modules/native/gemini/catalog/index.cjs.map +1 -0
  127. package/dist/command-modules/native/gemini/catalog/index.js +2095 -0
  128. package/dist/command-modules/native/gemini/catalog/index.js.map +1 -0
  129. package/dist/common/actions/chat.cjs +2049 -0
  130. package/dist/common/actions/chat.cjs.map +1 -0
  131. package/dist/common/actions/chat.js +2039 -0
  132. package/dist/common/actions/chat.js.map +1 -0
  133. package/dist/common/actions/native-command.cjs +1994 -0
  134. package/dist/common/actions/native-command.cjs.map +1 -0
  135. package/dist/common/actions/native-command.js +1984 -0
  136. package/dist/common/actions/native-command.js.map +1 -0
  137. package/dist/common/actions/shared.cjs +1475 -0
  138. package/dist/common/actions/shared.cjs.map +1 -0
  139. package/dist/common/actions/shared.js +1462 -0
  140. package/dist/common/actions/shared.js.map +1 -0
  141. package/dist/common/ai-services/builders/claude.cjs +185 -0
  142. package/dist/common/ai-services/builders/claude.cjs.map +1 -0
  143. package/dist/common/ai-services/builders/claude.js +178 -0
  144. package/dist/common/ai-services/builders/claude.js.map +1 -0
  145. package/dist/common/ai-services/builders/codex.cjs +160 -0
  146. package/dist/common/ai-services/builders/codex.cjs.map +1 -0
  147. package/dist/common/ai-services/builders/codex.js +153 -0
  148. package/dist/common/ai-services/builders/codex.js.map +1 -0
  149. package/dist/common/ai-services/builders/gemini.cjs +183 -0
  150. package/dist/common/ai-services/builders/gemini.cjs.map +1 -0
  151. package/dist/common/ai-services/builders/gemini.js +176 -0
  152. package/dist/common/ai-services/builders/gemini.js.map +1 -0
  153. package/dist/common/ai-services/index.cjs +1428 -0
  154. package/dist/common/ai-services/index.cjs.map +1 -0
  155. package/dist/common/ai-services/index.js +1417 -0
  156. package/dist/common/ai-services/index.js.map +1 -0
  157. package/dist/common/ai-services/internal/build-service-command.cjs +270 -0
  158. package/dist/common/ai-services/internal/build-service-command.cjs.map +1 -0
  159. package/dist/common/ai-services/internal/build-service-command.js +263 -0
  160. package/dist/common/ai-services/internal/build-service-command.js.map +1 -0
  161. package/dist/common/ai-services/internal/cli-management.cjs +94 -0
  162. package/dist/common/ai-services/internal/cli-management.cjs.map +1 -0
  163. package/dist/common/ai-services/internal/cli-management.js +90 -0
  164. package/dist/common/ai-services/internal/cli-management.js.map +1 -0
  165. package/dist/common/ai-services/internal/execute-attempt.cjs +241 -0
  166. package/dist/common/ai-services/internal/execute-attempt.cjs.map +1 -0
  167. package/dist/common/ai-services/internal/execute-attempt.js +232 -0
  168. package/dist/common/ai-services/internal/execute-attempt.js.map +1 -0
  169. package/dist/common/ai-services/internal/shared.cjs +60 -0
  170. package/dist/common/ai-services/internal/shared.cjs.map +1 -0
  171. package/dist/common/ai-services/internal/shared.js +50 -0
  172. package/dist/common/ai-services/internal/shared.js.map +1 -0
  173. package/dist/common/ai-services/internal/types.cjs +4 -0
  174. package/dist/common/ai-services/internal/types.cjs.map +1 -0
  175. package/dist/common/ai-services/internal/types.js +3 -0
  176. package/dist/common/ai-services/internal/types.js.map +1 -0
  177. package/dist/common/ai-services/stream-output.cjs +62 -0
  178. package/dist/common/ai-services/stream-output.cjs.map +1 -0
  179. package/dist/common/ai-services/stream-output.js +53 -0
  180. package/dist/common/ai-services/stream-output.js.map +1 -0
  181. package/dist/common/analytics/posthog.cjs +212 -0
  182. package/dist/common/analytics/posthog.cjs.map +1 -0
  183. package/dist/common/analytics/posthog.js +204 -0
  184. package/dist/common/analytics/posthog.js.map +1 -0
  185. package/dist/common/app/run-cli-app.cjs +4440 -0
  186. package/dist/common/app/run-cli-app.cjs.map +1 -0
  187. package/dist/common/app/run-cli-app.js +4426 -0
  188. package/dist/common/app/run-cli-app.js.map +1 -0
  189. package/dist/common/app/service-selection.cjs +553 -0
  190. package/dist/common/app/service-selection.cjs.map +1 -0
  191. package/dist/common/app/service-selection.js +541 -0
  192. package/dist/common/app/service-selection.js.map +1 -0
  193. package/dist/common/command-runtime/help.cjs +40 -0
  194. package/dist/common/command-runtime/help.cjs.map +1 -0
  195. package/dist/common/command-runtime/help.js +38 -0
  196. package/dist/common/command-runtime/help.js.map +1 -0
  197. package/dist/common/command-runtime/index.cjs +2549 -0
  198. package/dist/common/command-runtime/index.cjs.map +1 -0
  199. package/dist/common/command-runtime/index.js +2525 -0
  200. package/dist/common/command-runtime/index.js.map +1 -0
  201. package/dist/common/command-runtime/loader.cjs +145 -0
  202. package/dist/common/command-runtime/loader.cjs.map +1 -0
  203. package/dist/common/command-runtime/loader.js +135 -0
  204. package/dist/common/command-runtime/loader.js.map +1 -0
  205. package/dist/common/command-runtime/parser.cjs +57 -0
  206. package/dist/common/command-runtime/parser.cjs.map +1 -0
  207. package/dist/common/command-runtime/parser.js +55 -0
  208. package/dist/common/command-runtime/parser.js.map +1 -0
  209. package/dist/common/command-runtime/registry.cjs +2379 -0
  210. package/dist/common/command-runtime/registry.cjs.map +1 -0
  211. package/dist/common/command-runtime/registry.js +2357 -0
  212. package/dist/common/command-runtime/registry.js.map +1 -0
  213. package/dist/common/command-runtime/types.cjs +4 -0
  214. package/dist/common/command-runtime/types.cjs.map +1 -0
  215. package/dist/common/command-runtime/types.js +3 -0
  216. package/dist/common/command-runtime/types.js.map +1 -0
  217. package/dist/common/core/cancellation.cjs +34 -0
  218. package/dist/common/core/cancellation.cjs.map +1 -0
  219. package/dist/common/core/cancellation.js +29 -0
  220. package/dist/common/core/cancellation.js.map +1 -0
  221. package/dist/common/core/helpers.cjs +678 -0
  222. package/dist/common/core/helpers.cjs.map +1 -0
  223. package/dist/common/core/helpers.js +633 -0
  224. package/dist/common/core/helpers.js.map +1 -0
  225. package/dist/common/core/types.cjs +4 -0
  226. package/dist/common/core/types.cjs.map +1 -0
  227. package/dist/common/core/types.js +3 -0
  228. package/dist/common/core/types.js.map +1 -0
  229. package/dist/common/local-server/index.cjs +1665 -0
  230. package/dist/common/local-server/index.cjs.map +1 -0
  231. package/dist/common/local-server/index.js +1647 -0
  232. package/dist/common/local-server/index.js.map +1 -0
  233. package/dist/common/prompts/index.cjs +215 -0
  234. package/dist/common/prompts/index.cjs.map +1 -0
  235. package/dist/common/prompts/index.js +204 -0
  236. package/dist/common/prompts/index.js.map +1 -0
  237. package/dist/common/prompts/render.cjs +90 -0
  238. package/dist/common/prompts/render.cjs.map +1 -0
  239. package/dist/common/prompts/render.js +83 -0
  240. package/dist/common/prompts/render.js.map +1 -0
  241. package/dist/common/runtime-profile.cjs +46 -0
  242. package/dist/common/runtime-profile.cjs.map +1 -0
  243. package/dist/common/runtime-profile.js +40 -0
  244. package/dist/common/runtime-profile.js.map +1 -0
  245. package/dist/common/security/default-rules.cjs +49 -0
  246. package/dist/common/security/default-rules.cjs.map +1 -0
  247. package/dist/common/security/default-rules.js +42 -0
  248. package/dist/common/security/default-rules.js.map +1 -0
  249. package/dist/common/security/guard.cjs +784 -0
  250. package/dist/common/security/guard.cjs.map +1 -0
  251. package/dist/common/security/guard.js +775 -0
  252. package/dist/common/security/guard.js.map +1 -0
  253. package/dist/common/security/policy.cjs +117 -0
  254. package/dist/common/security/policy.cjs.map +1 -0
  255. package/dist/common/security/policy.js +105 -0
  256. package/dist/common/security/policy.js.map +1 -0
  257. package/dist/common/security/registry.cjs +456 -0
  258. package/dist/common/security/registry.cjs.map +1 -0
  259. package/dist/common/security/registry.js +445 -0
  260. package/dist/common/security/registry.js.map +1 -0
  261. package/dist/common/security/resource-resolver.cjs +314 -0
  262. package/dist/common/security/resource-resolver.cjs.map +1 -0
  263. package/dist/common/security/resource-resolver.js +306 -0
  264. package/dist/common/security/resource-resolver.js.map +1 -0
  265. package/dist/common/security/types.cjs +4 -0
  266. package/dist/common/security/types.cjs.map +1 -0
  267. package/dist/common/security/types.js +3 -0
  268. package/dist/common/security/types.js.map +1 -0
  269. package/dist/common/types/app.cjs +4 -0
  270. package/dist/common/types/app.cjs.map +1 -0
  271. package/dist/common/types/app.js +3 -0
  272. package/dist/common/types/app.js.map +1 -0
  273. package/dist/common/types/command.cjs +4 -0
  274. package/dist/common/types/command.cjs.map +1 -0
  275. package/dist/common/types/command.js +3 -0
  276. package/dist/common/types/command.js.map +1 -0
  277. package/dist/common/types/history.cjs +4 -0
  278. package/dist/common/types/history.cjs.map +1 -0
  279. package/dist/common/types/history.js +3 -0
  280. package/dist/common/types/history.js.map +1 -0
  281. package/dist/common/types/index.cjs +4 -0
  282. package/dist/common/types/index.cjs.map +1 -0
  283. package/dist/common/types/index.js +3 -0
  284. package/dist/common/types/index.js.map +1 -0
  285. package/dist/common/types/prompt.cjs +4 -0
  286. package/dist/common/types/prompt.cjs.map +1 -0
  287. package/dist/common/types/prompt.js +3 -0
  288. package/dist/common/types/prompt.js.map +1 -0
  289. package/dist/common/types/security.cjs +4 -0
  290. package/dist/common/types/security.cjs.map +1 -0
  291. package/dist/common/types/security.js +3 -0
  292. package/dist/common/types/security.js.map +1 -0
  293. package/dist/common/types/service-run.cjs +4 -0
  294. package/dist/common/types/service-run.cjs.map +1 -0
  295. package/dist/common/types/service-run.js +3 -0
  296. package/dist/common/types/service-run.js.map +1 -0
  297. package/dist/common/types/storage.cjs +4 -0
  298. package/dist/common/types/storage.cjs.map +1 -0
  299. package/dist/common/types/storage.js +3 -0
  300. package/dist/common/types/storage.js.map +1 -0
  301. package/dist/common/types/ui.cjs +4 -0
  302. package/dist/common/types/ui.cjs.map +1 -0
  303. package/dist/common/types/ui.js +3 -0
  304. package/dist/common/types/ui.js.map +1 -0
  305. package/dist/common/ui/index.cjs +854 -0
  306. package/dist/common/ui/index.cjs.map +1 -0
  307. package/dist/common/ui/index.js +836 -0
  308. package/dist/common/ui/index.js.map +1 -0
  309. package/dist/fe.cjs +4446 -0
  310. package/dist/fe.cjs.map +1 -0
  311. package/dist/fe.js +4432 -0
  312. package/dist/fe.js.map +1 -0
  313. package/package.json +52 -0
  314. package/src/common/context/rules/be/commit.md +50 -0
  315. package/src/common/context/rules/be/dsp-be-guide.md +184 -0
  316. package/src/common/context/rules/be/reference-summary.md +130 -0
  317. package/src/common/context/rules/fe/base.md +280 -0
  318. package/src/common/context/rules/fe/clean-architecture-diagram.html +189 -0
  319. package/src/common/context/rules/fe/clean-architecture-diagram.md +114 -0
  320. package/src/common/context/rules/fe/clean-architecture-diagram.png +0 -0
  321. package/src/common/context/rules/fe/clean-architecture.md +488 -0
  322. package/src/common/context/rules/fe/coding-convention.md +617 -0
  323. package/src/common/context/rules/fe/commit.md +48 -0
  324. package/src/common/context/rules/fe/figma-to-code.md +502 -0
  325. package/src/common/context/rules/fe/naming-rule.md +345 -0
  326. package/src/common/context/rules/fe/testing-guide.md +415 -0
  327. package/src/common/prompts/assets/chat/forms/chat-response.md +3 -0
  328. package/src/common/prompts/assets/chat/instructions/chat-request.md +5 -0
  329. package/src/common/prompts/assets/common/base-instructions.md +4 -0
package/dist/be.cjs ADDED
@@ -0,0 +1,4446 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ var child_process = require('child_process');
5
+ var fs7 = require('fs');
6
+ var path6 = require('path');
7
+ var util = require('util');
8
+ var fs2 = require('fs/promises');
9
+ var os = require('os');
10
+ var url = require('url');
11
+ var process$1 = require('process');
12
+ var readline = require('readline');
13
+ var posthogNode = require('posthog-node');
14
+ require('crypto');
15
+ require('http');
16
+ var module$1 = require('module');
17
+ require('net');
18
+
19
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
20
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
21
+
22
+ var fs7__default = /*#__PURE__*/_interopDefault(fs7);
23
+ var path6__default = /*#__PURE__*/_interopDefault(path6);
24
+ var fs2__default = /*#__PURE__*/_interopDefault(fs2);
25
+ var os__default = /*#__PURE__*/_interopDefault(os);
26
+ var readline__default = /*#__PURE__*/_interopDefault(readline);
27
+
28
+ var AI_SERVICES = ["codex", "gemini", "claude"];
29
+ var DEFAULT_HISTORY_LIMIT = 5;
30
+ var DEFAULT_HISTORY_CHAR_LIMIT = 14e3;
31
+ var PROMPT_HISTORY_LIMIT = 100;
32
+ var CONVERSATION_HISTORY_SCOPES = [
33
+ "chat",
34
+ "commit",
35
+ "review",
36
+ "gen-html",
37
+ "gen-storybook",
38
+ "local-server",
39
+ "mcp",
40
+ "native-command",
41
+ "security-policy",
42
+ "show-stream",
43
+ "service-change"
44
+ ];
45
+ var TRACE_MESSAGES = [];
46
+ function pad(value) {
47
+ return String(value).padStart(2, "0");
48
+ }
49
+ function getTimestampParts(now = /* @__PURE__ */ new Date()) {
50
+ return {
51
+ year: now.getFullYear(),
52
+ month: pad(now.getMonth() + 1),
53
+ day: pad(now.getDate()),
54
+ hour: pad(now.getHours()),
55
+ minute: pad(now.getMinutes()),
56
+ second: pad(now.getSeconds())
57
+ };
58
+ }
59
+ function getNowString(now = /* @__PURE__ */ new Date()) {
60
+ const { year, month, day, hour, minute, second } = getTimestampParts(now);
61
+ return `${year}-${month}-${day}_${hour}-${minute}-${second}`;
62
+ }
63
+ function getHumanReadableNow(now = /* @__PURE__ */ new Date()) {
64
+ const { year, month, day, hour, minute, second } = getTimestampParts(now);
65
+ return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
66
+ }
67
+ function getStoragePaths(rootDir = process.cwd()) {
68
+ const baseDir = path6__default.default.join(rootDir, ".ju-hong-e");
69
+ const codeReviewDir = path6__default.default.join(baseDir, "code-review");
70
+ const historyDir = path6__default.default.join(baseDir, "ai-history");
71
+ const mcpDir = path6__default.default.join(baseDir, "mcp");
72
+ return {
73
+ baseDir,
74
+ codeReviewDir,
75
+ conversationHistoryPath: path6__default.default.join(baseDir, "conversation-history.jsonl"),
76
+ errorDir: path6__default.default.join(baseDir, "error"),
77
+ historyDir,
78
+ historyIndexPath: path6__default.default.join(historyDir, "index.md"),
79
+ mcpDir,
80
+ mcpRegistryPath: path6__default.default.join(mcpDir, "servers.json"),
81
+ promptHistoryPath: path6__default.default.join(baseDir, "prompt-history.json"),
82
+ rootDir,
83
+ securityPolicyPath: path6__default.default.join(baseDir, "security-policy.json"),
84
+ serviceFilePath: path6__default.default.join(baseDir, "service"),
85
+ servicesDir: path6__default.default.join(historyDir, "services"),
86
+ streamOutputConfigPath: path6__default.default.join(baseDir, "show-stream.json"),
87
+ testDir: path6__default.default.join(baseDir, "test"),
88
+ tmpDir: path6__default.default.join(baseDir, "tmp"),
89
+ turnsDir: path6__default.default.join(historyDir, "turns")
90
+ };
91
+ }
92
+ function ensureStorageDirectories(paths) {
93
+ [paths.baseDir, paths.codeReviewDir, paths.historyDir, paths.turnsDir, paths.servicesDir, paths.testDir, paths.errorDir, paths.tmpDir, paths.mcpDir].forEach((directory) => {
94
+ fs7__default.default.mkdirSync(directory, { recursive: true });
95
+ });
96
+ }
97
+ function parseCliArgs(args = process.argv.slice(2)) {
98
+ const parsed = {
99
+ help: false,
100
+ testMode: false,
101
+ traceMode: false
102
+ };
103
+ const getNextValue = (index) => {
104
+ const value = args[index + 1];
105
+ if (!value || value.startsWith("--")) {
106
+ return "";
107
+ }
108
+ return value;
109
+ };
110
+ args.forEach((arg, index) => {
111
+ if (arg === "--help" || arg === "-h") {
112
+ parsed.help = true;
113
+ }
114
+ if (arg === "--test") {
115
+ parsed.testMode = true;
116
+ }
117
+ if (arg === "--trace") {
118
+ parsed.traceMode = true;
119
+ }
120
+ if (arg === "--model") {
121
+ parsed.model = getNextValue(index) || void 0;
122
+ }
123
+ if (arg === "--service") {
124
+ const service = getNextValue(index);
125
+ if (AI_SERVICES.includes(service)) {
126
+ parsed.service = service;
127
+ }
128
+ }
129
+ if (arg === "--reasoning-effort") {
130
+ const effort = getNextValue(index);
131
+ if (["minimal", "low", "medium", "high"].includes(effort)) {
132
+ parsed.reasoningEffort = effort;
133
+ }
134
+ }
135
+ });
136
+ return parsed;
137
+ }
138
+ function clearTraceMessages() {
139
+ TRACE_MESSAGES.length = 0;
140
+ }
141
+ function getTraceMessages() {
142
+ return [...TRACE_MESSAGES];
143
+ }
144
+ function createTraceLogger(scope, args) {
145
+ const enabled = args.testMode || args.traceMode;
146
+ return (step, detail) => {
147
+ const message = `[${(/* @__PURE__ */ new Date()).toISOString()}][TRACE][${scope}] ${step}${detail ? ` | ${detail}` : ""}`;
148
+ TRACE_MESSAGES.push(message);
149
+ if (enabled) {
150
+ console.log(message);
151
+ }
152
+ };
153
+ }
154
+ function shellQuote(value) {
155
+ return `'${value.replace(/'/g, `'\\''`)}'`;
156
+ }
157
+ function stringifyUnknown(value) {
158
+ if (value === void 0 || value === null) {
159
+ return "";
160
+ }
161
+ if (typeof value === "string") {
162
+ return value;
163
+ }
164
+ if (Buffer.isBuffer(value)) {
165
+ return value.toString("utf8");
166
+ }
167
+ if (value instanceof Error) {
168
+ return value.stack || value.message;
169
+ }
170
+ return util.inspect(value, { depth: 6, breakLength: 120 });
171
+ }
172
+ function getErrorSummary(error) {
173
+ if (error instanceof Error) {
174
+ return `${error.name}: ${error.message}`;
175
+ }
176
+ return stringifyUnknown(error) || "Unknown error";
177
+ }
178
+ function serializeError(error) {
179
+ const serialized = {
180
+ summary: getErrorSummary(error)
181
+ };
182
+ if (error instanceof Error) {
183
+ serialized.name = error.name;
184
+ serialized.message = error.message;
185
+ serialized.stack = error.stack;
186
+ } else {
187
+ serialized.value = stringifyUnknown(error);
188
+ }
189
+ if (error && typeof error === "object") {
190
+ const errorLike = error;
191
+ ["code", "errno", "syscall", "path", "cmd", "status", "signal"].forEach((key) => {
192
+ if (errorLike[key] !== void 0) {
193
+ serialized[key] = errorLike[key];
194
+ }
195
+ });
196
+ const stdout2 = stringifyUnknown(errorLike.stdout);
197
+ if (stdout2) {
198
+ serialized.stdout = stdout2;
199
+ }
200
+ const stderr = stringifyUnknown(errorLike.stderr);
201
+ if (stderr) {
202
+ serialized.stderr = stderr;
203
+ }
204
+ }
205
+ return serialized;
206
+ }
207
+ function runGitCommand(rootDir, command) {
208
+ return child_process.execSync(command, {
209
+ cwd: rootDir,
210
+ encoding: "utf8",
211
+ maxBuffer: 1024 * 1024 * 20,
212
+ stdio: ["ignore", "pipe", "pipe"]
213
+ }).trim();
214
+ }
215
+ function isGitRepository(rootDir) {
216
+ try {
217
+ runGitCommand(rootDir, "git rev-parse --show-toplevel");
218
+ return true;
219
+ } catch {
220
+ return false;
221
+ }
222
+ }
223
+ function captureWorkspaceSnapshot(rootDir) {
224
+ if (!isGitRepository(rootDir)) {
225
+ return {
226
+ available: false,
227
+ branch: "",
228
+ diffNameStatus: "",
229
+ diffStat: "",
230
+ gitRoot: "",
231
+ note: "\uD604\uC7AC \uC791\uC5C5 \uACBD\uB85C\uAC00 Git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
232
+ recentCommits: [],
233
+ statusLines: []
234
+ };
235
+ }
236
+ const gitRoot = runGitCommand(rootDir, "git rev-parse --show-toplevel");
237
+ const branch = runGitCommand(rootDir, "git branch --show-current");
238
+ const statusOutput = runGitCommand(rootDir, "git status --short");
239
+ const diffStat = runGitCommand(rootDir, "git diff --stat");
240
+ const diffNameStatus = runGitCommand(rootDir, "git diff --name-status");
241
+ const recentCommits = runGitCommand(rootDir, "git log --oneline -5");
242
+ return {
243
+ available: true,
244
+ branch,
245
+ diffNameStatus,
246
+ diffStat,
247
+ gitRoot,
248
+ note: "",
249
+ recentCommits: recentCommits ? recentCommits.split("\n").filter(Boolean) : [],
250
+ statusLines: statusOutput ? statusOutput.split("\n").filter(Boolean) : []
251
+ };
252
+ }
253
+ function statusLineToPath(statusLine) {
254
+ const normalized = statusLine.trim();
255
+ if (!normalized) {
256
+ return "";
257
+ }
258
+ const pathValue = normalized.slice(3).split(" -> ").pop();
259
+ return pathValue?.trim() || normalized;
260
+ }
261
+ function diffWorkspaceSnapshots(before, after) {
262
+ const beforeSet = new Set(before.statusLines);
263
+ const afterSet = new Set(after.statusLines);
264
+ const beforeOnly = before.statusLines.filter((line) => !afterSet.has(line));
265
+ const afterOnly = after.statusLines.filter((line) => !beforeSet.has(line));
266
+ const touchedFiles = Array.from(
267
+ new Set([...beforeOnly.map(statusLineToPath), ...afterOnly.map(statusLineToPath)].filter(Boolean))
268
+ );
269
+ return {
270
+ afterOnly,
271
+ beforeOnly,
272
+ touchedFiles
273
+ };
274
+ }
275
+ function formatCodeBlock(content, language = "") {
276
+ return `\`\`\`${language}
277
+ ${content || "(\uC5C6\uC74C)"}
278
+ \`\`\``;
279
+ }
280
+ function formatWorkspaceSnapshot(snapshot) {
281
+ if (!snapshot.available) {
282
+ return snapshot.note;
283
+ }
284
+ return [
285
+ `- Git Root: \`${snapshot.gitRoot}\``,
286
+ `- Branch: \`${snapshot.branch || "(detached)"}\``,
287
+ "",
288
+ "### git status --short",
289
+ formatCodeBlock(snapshot.statusLines.join("\n")),
290
+ "",
291
+ "### git diff --stat",
292
+ formatCodeBlock(snapshot.diffStat),
293
+ "",
294
+ "### git diff --name-status",
295
+ formatCodeBlock(snapshot.diffNameStatus),
296
+ "",
297
+ "### \uCD5C\uADFC \uCEE4\uBC0B",
298
+ formatCodeBlock(snapshot.recentCommits.join("\n"))
299
+ ].join("\n");
300
+ }
301
+ function formatWorkspaceDelta(delta) {
302
+ return [
303
+ "### \uC0C8\uB85C \uAC10\uC9C0\uB41C \uC0C1\uD0DC",
304
+ formatCodeBlock(delta.afterOnly.join("\n")),
305
+ "",
306
+ "### \uC0AC\uB77C\uC9C4 \uC774\uC804 \uC0C1\uD0DC",
307
+ formatCodeBlock(delta.beforeOnly.join("\n")),
308
+ "",
309
+ "### \uC601\uD5A5 \uD30C\uC77C",
310
+ formatCodeBlock(delta.touchedFiles.join("\n"))
311
+ ].join("\n");
312
+ }
313
+ function safeExcerpt(content, limit = 3e3) {
314
+ if (!content) {
315
+ return "";
316
+ }
317
+ if (content.length <= limit) {
318
+ return content;
319
+ }
320
+ return `${content.slice(0, limit)}
321
+ ... (truncated ${content.length - limit} chars)`;
322
+ }
323
+ function isConversationHistoryScope(value) {
324
+ return CONVERSATION_HISTORY_SCOPES.includes(value);
325
+ }
326
+ function parseConversationHistoryEntry(raw) {
327
+ try {
328
+ const parsed = JSON.parse(raw);
329
+ if (!parsed || typeof parsed !== "object") {
330
+ return void 0;
331
+ }
332
+ if (typeof parsed.timestamp !== "string" || typeof parsed.title !== "string" || typeof parsed.summary !== "string" || typeof parsed.scope !== "string" || typeof parsed.service !== "string") {
333
+ return void 0;
334
+ }
335
+ if (!isConversationHistoryScope(parsed.scope) || !AI_SERVICES.includes(parsed.service)) {
336
+ return void 0;
337
+ }
338
+ const previousService = typeof parsed.previousService === "string" && (parsed.previousService === "" || AI_SERVICES.includes(parsed.previousService)) ? parsed.previousService : void 0;
339
+ const nextService = typeof parsed.nextService === "string" && AI_SERVICES.includes(parsed.nextService) ? parsed.nextService : void 0;
340
+ return {
341
+ input: typeof parsed.input === "string" ? parsed.input : void 0,
342
+ nextService,
343
+ output: typeof parsed.output === "string" ? parsed.output : void 0,
344
+ previousService,
345
+ scope: parsed.scope,
346
+ service: parsed.service,
347
+ summary: parsed.summary,
348
+ timestamp: parsed.timestamp,
349
+ title: parsed.title
350
+ };
351
+ } catch {
352
+ return void 0;
353
+ }
354
+ }
355
+ function appendConversationHistory(paths, entry) {
356
+ const normalizedEntry = {
357
+ ...entry,
358
+ summary: entry.summary.trim() || entry.title.trim(),
359
+ timestamp: entry.timestamp || getHumanReadableNow(),
360
+ title: entry.title.trim()
361
+ };
362
+ fs7__default.default.appendFileSync(paths.conversationHistoryPath, `${JSON.stringify(normalizedEntry)}
363
+ `, "utf8");
364
+ return normalizedEntry;
365
+ }
366
+ function loadConversationHistory(paths, limit = DEFAULT_HISTORY_LIMIT) {
367
+ if (!fs7__default.default.existsSync(paths.conversationHistoryPath)) {
368
+ return [];
369
+ }
370
+ const lines = fs7__default.default.readFileSync(paths.conversationHistoryPath, "utf8").split("\n").map((line) => line.trim()).filter(Boolean);
371
+ if (lines.length === 0) {
372
+ return [];
373
+ }
374
+ return lines.map(parseConversationHistoryEntry).filter((entry) => entry !== void 0).slice(-limit);
375
+ }
376
+ function formatConversationHistoryEntry(entry, limit) {
377
+ const inputLimit = Math.max(180, Math.floor(limit * 0.35));
378
+ const outputLimit = Math.max(220, limit - inputLimit);
379
+ const lines = [`## ${entry.timestamp} | ${entry.scope} | ${entry.service}`, `\uC81C\uBAA9: ${entry.title}`];
380
+ if (entry.scope === "service-change") {
381
+ lines.push(`\uC11C\uBE44\uC2A4 \uBCC0\uACBD: ${entry.previousService || "(\uC5C6\uC74C)"} -> ${entry.nextService || entry.service}`);
382
+ lines.push(`\uC694\uC57D: ${safeExcerpt(entry.summary, outputLimit)}`);
383
+ return lines.join("\n");
384
+ }
385
+ if (entry.input) {
386
+ lines.push("");
387
+ lines.push("\uC0AC\uC6A9\uC790 \uC785\uB825");
388
+ lines.push(formatCodeBlock(safeExcerpt(entry.input, inputLimit)));
389
+ }
390
+ if (entry.output) {
391
+ lines.push("");
392
+ lines.push("\uC774\uC804 \uACB0\uACFC \uC694\uC57D");
393
+ lines.push(formatCodeBlock(safeExcerpt(entry.output, outputLimit)));
394
+ } else if (entry.summary) {
395
+ lines.push("");
396
+ lines.push("\uACB0\uACFC \uC694\uC57D");
397
+ lines.push(formatCodeBlock(safeExcerpt(entry.summary, outputLimit)));
398
+ }
399
+ return lines.join("\n");
400
+ }
401
+ function formatConversationHistory(entries, charLimit) {
402
+ if (entries.length === 0) {
403
+ return "";
404
+ }
405
+ const entryLimit = Math.max(400, Math.floor(charLimit / Math.max(entries.length, 1)));
406
+ const content = entries.map((entry) => formatConversationHistoryEntry(entry, entryLimit)).join("\n\n");
407
+ return safeExcerpt(content, charLimit);
408
+ }
409
+ function loadRecentHistoryContext(paths, limit = DEFAULT_HISTORY_LIMIT, charLimit = DEFAULT_HISTORY_CHAR_LIMIT) {
410
+ const conversationEntries = loadConversationHistory(paths, limit);
411
+ return formatConversationHistory(conversationEntries, charLimit);
412
+ }
413
+ function getAvailableFilePath(directory, baseName, extension) {
414
+ const first = path6__default.default.join(directory, `${baseName}${extension}`);
415
+ if (!fs7__default.default.existsSync(first)) {
416
+ return first;
417
+ }
418
+ let next = first;
419
+ let count = 1;
420
+ while (fs7__default.default.existsSync(next)) {
421
+ next = path6__default.default.join(directory, `${baseName}-${count}${extension}`);
422
+ if (!fs7__default.default.existsSync(next)) {
423
+ break;
424
+ }
425
+ count += 1;
426
+ }
427
+ return next;
428
+ }
429
+ function readSavedService(paths) {
430
+ if (!fs7__default.default.existsSync(paths.serviceFilePath)) {
431
+ return "";
432
+ }
433
+ const service = fs7__default.default.readFileSync(paths.serviceFilePath, "utf8").trim();
434
+ return AI_SERVICES.includes(service) ? service : "";
435
+ }
436
+ function saveService(paths, service) {
437
+ fs7__default.default.writeFileSync(paths.serviceFilePath, `${service}
438
+ `, "utf8");
439
+ }
440
+ function loadPromptHistory(paths, limit = PROMPT_HISTORY_LIMIT) {
441
+ if (!fs7__default.default.existsSync(paths.promptHistoryPath)) {
442
+ return [];
443
+ }
444
+ try {
445
+ const parsed = JSON.parse(fs7__default.default.readFileSync(paths.promptHistoryPath, "utf8"));
446
+ if (!Array.isArray(parsed)) {
447
+ return [];
448
+ }
449
+ return parsed.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean).slice(-limit);
450
+ } catch {
451
+ return [];
452
+ }
453
+ }
454
+ function savePromptHistory(paths, history) {
455
+ const normalized = history.map((entry) => entry.trim()).filter(Boolean).slice(-100);
456
+ fs7__default.default.writeFileSync(paths.promptHistoryPath, JSON.stringify(normalized, null, 2), "utf8");
457
+ }
458
+ function appendPromptHistory(paths, value) {
459
+ const normalizedValue = value.trim();
460
+ if (!normalizedValue) {
461
+ return loadPromptHistory(paths);
462
+ }
463
+ const existing = loadPromptHistory(paths).filter((entry) => entry !== normalizedValue);
464
+ const nextHistory = [...existing, normalizedValue].slice(-100);
465
+ savePromptHistory(paths, nextHistory);
466
+ return nextHistory;
467
+ }
468
+ function appendHistoryIndex(paths, summary, relativeFilePath) {
469
+ const line = `- ${getHumanReadableNow()} | ${summary} | file: \`${relativeFilePath}\`
470
+ `;
471
+ fs7__default.default.appendFileSync(paths.historyIndexPath, line, "utf8");
472
+ }
473
+ function renderSections(sections = []) {
474
+ if (sections.length === 0) {
475
+ return "";
476
+ }
477
+ return sections.map((section) => `
478
+ ## ${section.heading}
479
+
480
+ ${section.markdown}
481
+ `).join("\n");
482
+ }
483
+ function writeTurnHistory(paths, record) {
484
+ const baseName = `${getNowString()}-${record.scope}`;
485
+ const filePath = getAvailableFilePath(paths.turnsDir, baseName, ".md");
486
+ const markdown = `# ${record.title}
487
+
488
+ - \uC2DC\uAC01: ${getHumanReadableNow()}
489
+ - scope: \`${record.scope}\`
490
+ - service: \`${record.service}\`
491
+ - skipped: \`${record.skipped}\`
492
+
493
+ ## \uC0AC\uC6A9\uC790 \uC785\uB825
494
+
495
+ ${formatCodeBlock(record.input)}
496
+
497
+ ## AI \uC751\uB2F5
498
+
499
+ ${record.output || "(\uC751\uB2F5 \uC5C6\uC74C)"}
500
+
501
+ ## \uCD5C\uADFC \uD788\uC2A4\uD1A0\uB9AC \uC8FC\uC785
502
+
503
+ ${formatCodeBlock(record.historyContext)}
504
+
505
+ ## \uC2E4\uD589 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30
506
+
507
+ ${formatCodeBlock(record.previewCommand, "sh")}
508
+
509
+ ## \uC791\uC5C5 \uC804 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4
510
+
511
+ ${formatWorkspaceSnapshot(record.workspaceBefore)}
512
+
513
+ ## \uC791\uC5C5 \uD6C4 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4
514
+
515
+ ${formatWorkspaceSnapshot(record.workspaceAfter)}
516
+
517
+ ## \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uBCC0\uD654
518
+
519
+ ${formatWorkspaceDelta(record.workspaceDelta)}${renderSections(record.extraSections)}
520
+ `;
521
+ fs7__default.default.writeFileSync(filePath, markdown, "utf8");
522
+ appendHistoryIndex(paths, `${record.scope} | ${record.service} | ${record.title}`, path6__default.default.relative(paths.rootDir, filePath));
523
+ return filePath;
524
+ }
525
+ function writeServiceChangeHistory(paths, previousService, nextService, historyContext) {
526
+ const baseName = `${getNowString()}-service-change`;
527
+ const filePath = getAvailableFilePath(paths.servicesDir, baseName, ".md");
528
+ const markdown = `# Service Change
529
+
530
+ - \uC2DC\uAC01: ${getHumanReadableNow()}
531
+ - \uC774\uC804 \uC11C\uBE44\uC2A4: \`${previousService || "(\uC5C6\uC74C)"}\`
532
+ - \uB2E4\uC74C \uC11C\uBE44\uC2A4: \`${nextService}\`
533
+
534
+ ## \uC8FC\uC785 \uC608\uC815 \uD788\uC2A4\uD1A0\uB9AC
535
+
536
+ ${formatCodeBlock(historyContext)}
537
+ `;
538
+ fs7__default.default.writeFileSync(filePath, markdown, "utf8");
539
+ appendHistoryIndex(paths, `service-change | ${previousService || "(\uC5C6\uC74C)"} -> ${nextService}`, path6__default.default.relative(paths.rootDir, filePath));
540
+ return filePath;
541
+ }
542
+ function writeTestReport(paths, title, markdown) {
543
+ const filePath = getAvailableFilePath(paths.testDir, `${getNowString()}-test`, ".md");
544
+ const content = `# ${title}
545
+
546
+ - \uC2DC\uAC01: ${getHumanReadableNow()}
547
+
548
+ ${markdown}
549
+ `;
550
+ fs7__default.default.writeFileSync(filePath, content, "utf8");
551
+ return filePath;
552
+ }
553
+ function writeErrorReport(paths, error, options) {
554
+ const filePath = getAvailableFilePath(paths.errorDir, `${getNowString()}-error`, ".md");
555
+ const serializedError = serializeError(error);
556
+ const traceMessages = options.traceMessages ?? getTraceMessages();
557
+ const markdown = `# Error Report
558
+
559
+ - \uC2DC\uAC01: ${getHumanReadableNow()}
560
+ - scope: \`${options.scope}\`
561
+ - \uC791\uC5C5 \uACBD\uB85C: \`${paths.rootDir}\`
562
+ - \uC2E4\uD589 \uC778\uC790: \`${JSON.stringify(options.args ?? process.argv.slice(2))}\`
563
+
564
+ ## Summary
565
+
566
+ ${serializedError.summary || "Unknown error"}
567
+
568
+ ## Error
569
+
570
+ \`\`\`json
571
+ ${JSON.stringify(serializedError, null, 2)}
572
+ \`\`\`
573
+
574
+ ## Trace
575
+
576
+ \`\`\`json
577
+ ${JSON.stringify(traceMessages, null, 2)}
578
+ \`\`\`${renderSections(options.extraSections)}
579
+ `;
580
+ fs7__default.default.writeFileSync(filePath, markdown, "utf8");
581
+ return filePath;
582
+ }
583
+
584
+ // src/common/prompts/assets/chat/forms/chat-response.md
585
+ var chat_response_default = "- \uBCC0\uACBD\uD55C \uD30C\uC77C \uBAA9\uB85D\n- \uD575\uC2EC \uACB0\uACFC 3\uC904 \uC774\uB0B4 \uC694\uC57D\n- \uCD94\uAC00 \uD655\uC778\uC774 \uD544\uC694\uD55C \uD56D\uBAA9\n";
586
+
587
+ // src/common/prompts/assets/chat/instructions/chat-request.md
588
+ var chat_request_default = "\uC0AC\uC6A9\uC790 \uC694\uCCAD\uC744 \uD574\uACB0\uD55C\uB2E4.\n\n- \uD544\uC694\uD55C \uACBD\uC6B0 \uC9C1\uC811 \uD30C\uC77C\uC744 \uC218\uC815\uD55C\uB2E4.\n- \uCF54\uB4DC\uB098 \uAD6C\uC870\uB97C \uC124\uBA85\uD560 \uB54C\uB294 \uC2E4\uC81C \uBCC0\uACBD \uB0B4\uC6A9 \uAE30\uC900\uC73C\uB85C \uC815\uB9AC\uD55C\uB2E4.\n- \uC751\uB2F5\uC740 \uC2E4\uD589 \uAC00\uB2A5\uD55C \uB2E4\uC74C \uC561\uC158\uC774 \uB4DC\uB7EC\uB098\uB3C4\uB85D \uC791\uC131\uD55C\uB2E4.\n";
589
+
590
+ // src/common/prompts/assets/common/base-instructions.md
591
+ var base_instructions_default = "- \uBAA8\uB4E0 \uC751\uB2F5\uC740 \uD55C\uAD6D\uC5B4\uB85C \uC791\uC131\uD55C\uB2E4.\n- \uD604\uC7AC \uC791\uC5C5 \uB514\uB809\uD130\uB9AC \uAE30\uC900\uC73C\uB85C \uD544\uC694\uD55C \uD30C\uC77C\uC744 \uC9C1\uC811 \uC218\uC815\uD560 \uC218 \uC788\uC73C\uBA74 \uC218\uC815\uD55C\uB2E4.\n- \uC218\uC815\uC774 \uC5B4\uB835\uAC70\uB098 \uB3C4\uAD6C \uC81C\uC57D\uC774 \uC788\uC73C\uBA74 \uC0DD\uC131\uD574\uC57C \uD560 \uD30C\uC77C\uACFC \uCF54\uB4DC \uB0B4\uC6A9\uC744 \uBA85\uD655\uD788 \uC81C\uC2DC\uD55C\uB2E4.\n- \uBCC0\uACBD\uC0AC\uD56D\uC740 \uC720\uC9C0\uBCF4\uC218\uC640 \uD655\uC7A5\uC131\uC744 \uC6B0\uC120\uC73C\uB85C \uACE0\uB824\uD55C\uB2E4.\n";
592
+
593
+ // src/common/prompts/index.ts
594
+ function buildCommonPrompt(options) {
595
+ return {
596
+ forms: options.forms,
597
+ historyContext: options.historyContext,
598
+ instructions: [base_instructions_default, ...options.instructions || []],
599
+ rules: options.rules,
600
+ sections: options.sections,
601
+ service: options.service,
602
+ title: options.title,
603
+ workspaceSnapshot: options.workspaceSnapshot
604
+ };
605
+ }
606
+ function buildChatPrompt(options) {
607
+ return buildCommonPrompt({
608
+ forms: [chat_response_default],
609
+ historyContext: options.historyContext,
610
+ instructions: [chat_request_default],
611
+ sections: [
612
+ {
613
+ heading: "\uC0AC\uC6A9\uC790 \uC694\uCCAD",
614
+ markdown: options.userInput
615
+ }
616
+ ],
617
+ service: options.service,
618
+ title: "Ju-hong-e Chat",
619
+ workspaceSnapshot: options.workspaceSnapshot
620
+ });
621
+ }
622
+ var execFileAsync = util.promisify(child_process.execFile);
623
+ var MAX_REFERENCED_RESOURCES = 16;
624
+ var MAX_TEXT_LENGTH = 12e4;
625
+ var MAX_FILE_BUFFER = 1024 * 1024 * 4;
626
+ var MAX_REMOTE_BUFFER = 1024 * 1024 * 5;
627
+ var COMMAND_TIMEOUT_MS = 15e3;
628
+ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
629
+ ".cjs",
630
+ ".conf",
631
+ ".css",
632
+ ".csv",
633
+ ".d.ts",
634
+ ".env",
635
+ ".html",
636
+ ".htm",
637
+ ".ini",
638
+ ".java",
639
+ ".js",
640
+ ".json",
641
+ ".jsx",
642
+ ".kt",
643
+ ".less",
644
+ ".log",
645
+ ".md",
646
+ ".mjs",
647
+ ".php",
648
+ ".py",
649
+ ".rb",
650
+ ".rs",
651
+ ".scss",
652
+ ".sh",
653
+ ".sql",
654
+ ".svg",
655
+ ".swift",
656
+ ".ts",
657
+ ".tsx",
658
+ ".txt",
659
+ ".xml",
660
+ ".yaml",
661
+ ".yml",
662
+ ".zsh"
663
+ ]);
664
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".bmp", ".gif", ".heic", ".jpeg", ".jpg", ".png", ".tif", ".tiff", ".webp"]);
665
+ var TEXTUTIL_EXTENSIONS = /* @__PURE__ */ new Set([".doc", ".docx", ".odt", ".rtf", ".rtfd", ".webarchive"]);
666
+ var REMOTE_URL_PATTERN = /\bhttps?:\/\/[^\s<>()"'`]+/gi;
667
+ var FILE_URL_PATTERN = /\bfile:\/\/[^\s<>()"'`]+/gi;
668
+ var LOCAL_PATH_WITH_PREFIX_PATTERN = /(?:^|[\s("'`])((?:~|\.{1,2}\/|\/)[^\s<>()"'`]+)/g;
669
+ var RELATIVE_PATH_WITH_SEPARATOR_PATTERN = /(?:^|[\s("'`])((?:[A-Za-z0-9._-]+\/)+[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+)/g;
670
+ function trimTrailingPunctuation(value) {
671
+ return value.replace(/[),.;:!?`'"\]}]+$/g, "").trim();
672
+ }
673
+ function limitTextContent(value) {
674
+ if (!value) {
675
+ return "";
676
+ }
677
+ const normalized = value.replace(/\0/g, "").trim();
678
+ if (normalized.length <= MAX_TEXT_LENGTH) {
679
+ return normalized;
680
+ }
681
+ return normalized.slice(0, MAX_TEXT_LENGTH);
682
+ }
683
+ function isLikelyTextMimeType(mimeType) {
684
+ return mimeType.startsWith("text/") || mimeType.includes("json") || mimeType.includes("javascript") || mimeType.includes("xml") || mimeType.includes("yaml") || mimeType.includes("svg");
685
+ }
686
+ function isLikelyImageMimeType(mimeType) {
687
+ return mimeType.startsWith("image/");
688
+ }
689
+ function collectMatches(text, pattern) {
690
+ const values = [];
691
+ for (const match of text.matchAll(pattern)) {
692
+ const candidate = trimTrailingPunctuation((match[1] || match[0] || "").trim());
693
+ if (!candidate) {
694
+ continue;
695
+ }
696
+ values.push(candidate);
697
+ }
698
+ return values;
699
+ }
700
+ function resolveLocalResource(value, rootDir) {
701
+ try {
702
+ if (value.startsWith("file://")) {
703
+ return path6__default.default.normalize(url.fileURLToPath(value));
704
+ }
705
+ } catch {
706
+ return void 0;
707
+ }
708
+ if (value.startsWith("~")) {
709
+ return path6__default.default.normalize(path6__default.default.join(os__default.default.homedir(), value.slice(1)));
710
+ }
711
+ if (path6__default.default.isAbsolute(value)) {
712
+ return path6__default.default.normalize(value);
713
+ }
714
+ if (!rootDir) {
715
+ return void 0;
716
+ }
717
+ return path6__default.default.normalize(path6__default.default.resolve(rootDir, value));
718
+ }
719
+ function toReferencedResources(values, rootDir) {
720
+ const seen = /* @__PURE__ */ new Set();
721
+ const resources = [];
722
+ for (const value of values) {
723
+ for (const candidate of collectMatches(value, REMOTE_URL_PATTERN)) {
724
+ const normalized = trimTrailingPunctuation(candidate);
725
+ if (!normalized || seen.has(normalized)) {
726
+ continue;
727
+ }
728
+ seen.add(normalized);
729
+ resources.push({
730
+ kind: "remote-url",
731
+ location: normalized
732
+ });
733
+ }
734
+ for (const candidate of [...collectMatches(value, FILE_URL_PATTERN), ...collectMatches(value, LOCAL_PATH_WITH_PREFIX_PATTERN), ...collectMatches(value, RELATIVE_PATH_WITH_SEPARATOR_PATTERN)]) {
735
+ const resolved = resolveLocalResource(candidate, rootDir);
736
+ if (!resolved || seen.has(resolved)) {
737
+ continue;
738
+ }
739
+ seen.add(resolved);
740
+ resources.push({
741
+ kind: "local-file",
742
+ location: resolved
743
+ });
744
+ }
745
+ if (resources.length >= MAX_REFERENCED_RESOURCES) {
746
+ return resources.slice(0, MAX_REFERENCED_RESOURCES);
747
+ }
748
+ }
749
+ return resources;
750
+ }
751
+ async function detectLocalMimeType(filePath) {
752
+ try {
753
+ const { stdout: stdout2 } = await execFileAsync("file", ["--brief", "--mime-type", filePath], {
754
+ maxBuffer: 64 * 1024,
755
+ timeout: COMMAND_TIMEOUT_MS
756
+ });
757
+ return stdout2.trim().toLowerCase();
758
+ } catch {
759
+ return "";
760
+ }
761
+ }
762
+ async function readTextFile(filePath) {
763
+ try {
764
+ const buffer = await fs2__default.default.readFile(filePath);
765
+ return limitTextContent(buffer.subarray(0, MAX_FILE_BUFFER).toString("utf8"));
766
+ } catch {
767
+ return "";
768
+ }
769
+ }
770
+ async function readTextViaTextutil(filePath) {
771
+ try {
772
+ const { stdout: stdout2 } = await execFileAsync("textutil", ["-convert", "txt", "-stdout", filePath], {
773
+ maxBuffer: MAX_FILE_BUFFER,
774
+ timeout: COMMAND_TIMEOUT_MS
775
+ });
776
+ return limitTextContent(stdout2);
777
+ } catch {
778
+ return "";
779
+ }
780
+ }
781
+ async function readTextViaMetadata(filePath) {
782
+ try {
783
+ const { stdout: stdout2 } = await execFileAsync("mdls", ["-raw", "-name", "kMDItemTextContent", filePath], {
784
+ maxBuffer: MAX_FILE_BUFFER,
785
+ timeout: COMMAND_TIMEOUT_MS
786
+ });
787
+ const normalized = stdout2.trim();
788
+ if (!normalized || normalized === "(null)") {
789
+ return "";
790
+ }
791
+ return limitTextContent(normalized);
792
+ } catch {
793
+ return "";
794
+ }
795
+ }
796
+ async function readTextViaStrings(filePath) {
797
+ try {
798
+ const { stdout: stdout2 } = await execFileAsync("strings", ["-n", "6", filePath], {
799
+ maxBuffer: MAX_FILE_BUFFER,
800
+ timeout: COMMAND_TIMEOUT_MS
801
+ });
802
+ return limitTextContent(stdout2);
803
+ } catch {
804
+ return "";
805
+ }
806
+ }
807
+ async function readTextViaTesseract(filePath) {
808
+ try {
809
+ const { stdout: stdout2 } = await execFileAsync("tesseract", [filePath, "stdout", "--psm", "6"], {
810
+ maxBuffer: MAX_FILE_BUFFER,
811
+ timeout: COMMAND_TIMEOUT_MS
812
+ });
813
+ return limitTextContent(stdout2);
814
+ } catch {
815
+ return "";
816
+ }
817
+ }
818
+ async function readLocalResourceText(filePath) {
819
+ try {
820
+ const stats = await fs2__default.default.stat(filePath);
821
+ if (!stats.isFile()) {
822
+ return "";
823
+ }
824
+ } catch {
825
+ return "";
826
+ }
827
+ const extension = path6__default.default.extname(filePath).toLowerCase();
828
+ const mimeType = await detectLocalMimeType(filePath);
829
+ if (IMAGE_EXTENSIONS.has(extension) || isLikelyImageMimeType(mimeType)) {
830
+ return await readTextViaTesseract(filePath) || await readTextViaMetadata(filePath);
831
+ }
832
+ if (TEXT_EXTENSIONS.has(extension) || isLikelyTextMimeType(mimeType)) {
833
+ return readTextFile(filePath);
834
+ }
835
+ if (TEXTUTIL_EXTENSIONS.has(extension)) {
836
+ return await readTextViaTextutil(filePath) || await readTextViaMetadata(filePath);
837
+ }
838
+ return await readTextViaMetadata(filePath) || await readTextViaStrings(filePath);
839
+ }
840
+ async function readRemoteBuffer(location) {
841
+ const controller = new AbortController();
842
+ const timer = setTimeout(() => controller.abort(), COMMAND_TIMEOUT_MS);
843
+ try {
844
+ const response = await fetch(location, {
845
+ redirect: "follow",
846
+ signal: controller.signal
847
+ });
848
+ if (!response.ok) {
849
+ return void 0;
850
+ }
851
+ const contentLength = Number(response.headers.get("content-length") || "0");
852
+ if (contentLength > MAX_REMOTE_BUFFER) {
853
+ return void 0;
854
+ }
855
+ const arrayBuffer = await response.arrayBuffer();
856
+ const buffer = Buffer.from(arrayBuffer);
857
+ if (buffer.byteLength > MAX_REMOTE_BUFFER) {
858
+ return void 0;
859
+ }
860
+ return {
861
+ buffer,
862
+ contentType: (response.headers.get("content-type") || "").toLowerCase()
863
+ };
864
+ } catch {
865
+ return void 0;
866
+ } finally {
867
+ clearTimeout(timer);
868
+ }
869
+ }
870
+ async function withTemporaryFile(extension, buffer, task) {
871
+ const tempPath = path6__default.default.join(os__default.default.tmpdir(), `ju-hong-e-security-${Date.now()}-${Math.random().toString(16).slice(2)}${extension}`);
872
+ try {
873
+ await fs2__default.default.writeFile(tempPath, buffer);
874
+ return await task(tempPath);
875
+ } finally {
876
+ await fs2__default.default.rm(tempPath, { force: true });
877
+ }
878
+ }
879
+ async function readRemoteResourceText(location) {
880
+ const response = await readRemoteBuffer(location);
881
+ if (!response) {
882
+ return "";
883
+ }
884
+ let extension = "";
885
+ try {
886
+ extension = path6__default.default.extname(new URL(location).pathname).toLowerCase();
887
+ } catch {
888
+ extension = "";
889
+ }
890
+ if (IMAGE_EXTENSIONS.has(extension) || isLikelyImageMimeType(response.contentType)) {
891
+ return withTemporaryFile(extension || ".img", response.buffer, readTextViaTesseract);
892
+ }
893
+ if (TEXT_EXTENSIONS.has(extension) || isLikelyTextMimeType(response.contentType)) {
894
+ return limitTextContent(response.buffer.toString("utf8"));
895
+ }
896
+ if (TEXTUTIL_EXTENSIONS.has(extension)) {
897
+ return withTemporaryFile(extension, response.buffer, async (filePath) => await readTextViaTextutil(filePath) || await readTextViaMetadata(filePath));
898
+ }
899
+ return "";
900
+ }
901
+ async function collectReferencedResourceContents(values, rootDir) {
902
+ const resources = toReferencedResources(values, rootDir);
903
+ const contents = [];
904
+ for (const resource of resources) {
905
+ const content = resource.kind === "local-file" ? await readLocalResourceText(resource.location) : await readRemoteResourceText(resource.location);
906
+ if (!content) {
907
+ continue;
908
+ }
909
+ contents.push({
910
+ location: resource.location,
911
+ value: content
912
+ });
913
+ }
914
+ return contents;
915
+ }
916
+
917
+ // src/common/security/registry.ts
918
+ var securityRegistryState = globalThis.__JUHONG_E_SECURITY_REGISTRY__ ?? (globalThis.__JUHONG_E_SECURITY_REGISTRY__ = {
919
+ patternRules: /* @__PURE__ */ new Map(),
920
+ validatorRules: /* @__PURE__ */ new Map()
921
+ });
922
+ var GLOBAL_PATTERN_RULES = securityRegistryState.patternRules;
923
+ var GLOBAL_VALIDATOR_RULES = securityRegistryState.validatorRules;
924
+ function resetRegex(pattern) {
925
+ pattern.lastIndex = 0;
926
+ return pattern;
927
+ }
928
+ function collectStringValues(value) {
929
+ if (typeof value === "string") {
930
+ return value.trim() ? [value] : [];
931
+ }
932
+ if (Array.isArray(value)) {
933
+ return value.flatMap((item) => collectStringValues(item));
934
+ }
935
+ if (value && typeof value === "object") {
936
+ return Object.values(value).flatMap((item) => collectStringValues(item));
937
+ }
938
+ return [];
939
+ }
940
+ function collectCandidateValues(value, source) {
941
+ return collectStringValues(value).map((entry) => ({
942
+ source,
943
+ value: entry
944
+ }));
945
+ }
946
+ async function collectSecurityStringValues(payload, options) {
947
+ const directValues = [
948
+ ...collectCandidateValues(payload.input, "input"),
949
+ ...collectCandidateValues(payload.rawCommand, "rawCommand"),
950
+ ...collectCandidateValues(payload.rawArgs, "rawArgs"),
951
+ ...collectCandidateValues(payload.args, "args"),
952
+ ...options.inspectPrompt ? collectCandidateValues(payload.prompt, "prompt") : []
953
+ ];
954
+ if (!options.inspectResources) {
955
+ return directValues;
956
+ }
957
+ const referencedContents = await collectReferencedResourceContents(
958
+ directValues.map((entry) => entry.value),
959
+ payload.promptRootDir
960
+ );
961
+ return [
962
+ ...directValues,
963
+ ...referencedContents.map(
964
+ (entry) => ({
965
+ location: entry.location,
966
+ source: "resource",
967
+ value: entry.value
968
+ })
969
+ )
970
+ ];
971
+ }
972
+ function getPatternRules(config) {
973
+ return [...GLOBAL_PATTERN_RULES.values(), ...config?.patterns || []];
974
+ }
975
+ function getValidatorRules(config) {
976
+ return [...GLOBAL_VALIDATOR_RULES.values(), ...config?.validators || []];
977
+ }
978
+ function addGlobalSecurityPattern(rule) {
979
+ GLOBAL_PATTERN_RULES.set(rule.name, rule);
980
+ }
981
+ async function validateSecurityPayload(payload, config, options = {
982
+ inspectPrompt: true,
983
+ inspectResources: true,
984
+ mode: "prompt-with-resources"
985
+ }) {
986
+ const stringValues = await collectSecurityStringValues(payload, options);
987
+ for (const rule of getPatternRules(config)) {
988
+ const matched = findMatchedCandidate(stringValues, rule);
989
+ if (matched) {
990
+ return {
991
+ detail: {
992
+ location: matched.location,
993
+ matchedText: matched.matchedText,
994
+ source: matched.source
995
+ },
996
+ message: rule.message,
997
+ ok: false,
998
+ ruleName: rule.name
999
+ };
1000
+ }
1001
+ }
1002
+ for (const rule of getValidatorRules(config)) {
1003
+ const result = await rule.validate(payload);
1004
+ if (result === true) {
1005
+ continue;
1006
+ }
1007
+ return {
1008
+ detail: {
1009
+ source: payload.prompt ? "prompt" : payload.input ? "input" : "args"
1010
+ },
1011
+ message: typeof result === "string" && result.trim() ? result : rule.message,
1012
+ ok: false,
1013
+ ruleName: rule.name
1014
+ };
1015
+ }
1016
+ return {
1017
+ ok: true
1018
+ };
1019
+ }
1020
+ function findMatchedCandidate(stringValues, rule) {
1021
+ for (const candidate of stringValues) {
1022
+ const matchedText = extractMatchedText(candidate.value, rule);
1023
+ if (!matchedText) {
1024
+ continue;
1025
+ }
1026
+ return {
1027
+ location: candidate.location,
1028
+ matchedText,
1029
+ source: candidate.source
1030
+ };
1031
+ }
1032
+ return void 0;
1033
+ }
1034
+ function extractMatchedText(value, rule) {
1035
+ const match = resetRegex(rule.pattern).exec(value);
1036
+ if (!match?.[0]) {
1037
+ return "";
1038
+ }
1039
+ const formattedMatch = rule.formatMatch ? rule.formatMatch(match[0]) : match[0];
1040
+ return safeExcerpt(formattedMatch, 120);
1041
+ }
1042
+
1043
+ // src/common/security/default-rules.ts
1044
+ var initialized = false;
1045
+ function formatResidentRegistrationNumber(matchedText) {
1046
+ const digits = matchedText.replace(/\D/g, "");
1047
+ if (digits.length !== 13) {
1048
+ return `${matchedText.slice(0, 3)}***`;
1049
+ }
1050
+ return `${digits.slice(0, 6)}-${digits[6]}******`;
1051
+ }
1052
+ function ensureDefaultSecurityRules() {
1053
+ if (initialized) {
1054
+ return;
1055
+ }
1056
+ initialized = true;
1057
+ addGlobalSecurityPattern({
1058
+ formatMatch: formatResidentRegistrationNumber,
1059
+ message: "\uBCF4\uC548 \uC815\uCC45\uC5D0 \uC758\uD574 \uC8FC\uBBFC\uB4F1\uB85D\uBC88\uD638 \uD615\uD0DC\uC758 \uAC12\uC774 \uD3EC\uD568\uB41C \uC785\uB825\uC740 \uC2E4\uD589\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
1060
+ name: "resident-registration-number",
1061
+ pattern: /\b\d{6}[- ]?[1-4]\d{6}\b/
1062
+ });
1063
+ }
1064
+ var DEFAULT_SECURITY_POLICY_MODE = "prompt-with-resources";
1065
+ var SECURITY_POLICY_OPTIONS = [
1066
+ {
1067
+ description: "\uBCF4\uC548 \uAC80\uC0AC\uB97C \uC644\uC804\uD788 \uBE44\uD65C\uC131\uD654\uD569\uB2C8\uB2E4. \uBBFC\uAC10\uC815\uBCF4\uAC00 \uD3EC\uD568\uB418\uC5B4\uB3C4 \uCC28\uB2E8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
1068
+ label: "\uBCF4\uC548 \uAC80\uC0AC \uC0AC\uC6A9 \uC548 \uD568",
1069
+ mode: "disabled",
1070
+ summary: "\uBCF4\uC548 \uAC80\uC0AC \uBE44\uD65C\uC131\uD654"
1071
+ },
1072
+ {
1073
+ description: "\uC0AC\uC6A9\uC790 \uC785\uB825\uACFC \uBA85\uB839 \uC778\uC790\uB9CC \uAC80\uC0AC\uD569\uB2C8\uB2E4. \uD504\uB86C\uD504\uD2B8 \uBCF8\uBB38\uACFC \uCC38\uC870 \uB9AC\uC18C\uC2A4\uB294 \uC77D\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
1074
+ label: "\uC785\uB825/\uBA85\uB839\uB9CC \uAC80\uC0AC",
1075
+ mode: "input-only",
1076
+ summary: "\uC785\uB825/\uBA85\uB839 \uBB38\uC790\uC5F4\uB9CC \uAC80\uC0AC"
1077
+ },
1078
+ {
1079
+ description: "\uC785\uB825\uACFC AI \uD504\uB86C\uD504\uD2B8 \uBB38\uC790\uC5F4\uAE4C\uC9C0 \uAC80\uC0AC\uD569\uB2C8\uB2E4. \uACBD\uB85C/URL\uC774 \uAC00\uB9AC\uD0A4\uB294 \uB0B4\uC6A9\uC740 \uC77D\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
1080
+ label: "\uD504\uB86C\uD504\uD2B8 \uD14D\uC2A4\uD2B8\uAE4C\uC9C0 \uAC80\uC0AC",
1081
+ mode: "prompt-only",
1082
+ summary: "\uD504\uB86C\uD504\uD2B8 \uBB38\uC790\uC5F4\uAE4C\uC9C0 \uAC80\uC0AC"
1083
+ },
1084
+ {
1085
+ description: "\uC785\uB825, \uD504\uB86C\uD504\uD2B8, \uACBD\uB85C/URL\uC774 \uAC00\uB9AC\uD0A4\uB294 \uCC38\uC870 \uB9AC\uC18C\uC2A4 \uB0B4\uC6A9\uAE4C\uC9C0 \uD568\uAED8 \uAC80\uC0AC\uD569\uB2C8\uB2E4.",
1086
+ label: "\uD504\uB86C\uD504\uD2B8\uC640 \uCC38\uC870 \uB9AC\uC18C\uC2A4\uAE4C\uC9C0 \uC2EC\uCE35 \uAC80\uC0AC",
1087
+ mode: "prompt-with-resources",
1088
+ summary: "\uD504\uB86C\uD504\uD2B8\uC640 \uCC38\uC870 \uB9AC\uC18C\uC2A4\uAE4C\uC9C0 \uC2EC\uCE35 \uAC80\uC0AC"
1089
+ }
1090
+ ];
1091
+ function createDefaultSecurityPolicy() {
1092
+ return {
1093
+ mode: DEFAULT_SECURITY_POLICY_MODE
1094
+ };
1095
+ }
1096
+ function isSecurityPolicyMode(value) {
1097
+ return SECURITY_POLICY_OPTIONS.some((option) => option.mode === value);
1098
+ }
1099
+ function readSecurityPolicy(paths) {
1100
+ if (!paths?.securityPolicyPath || !fs7__default.default.existsSync(paths.securityPolicyPath)) {
1101
+ return createDefaultSecurityPolicy();
1102
+ }
1103
+ try {
1104
+ const parsed = JSON.parse(fs7__default.default.readFileSync(paths.securityPolicyPath, "utf8"));
1105
+ if (!isSecurityPolicyMode(parsed.mode)) {
1106
+ return createDefaultSecurityPolicy();
1107
+ }
1108
+ return {
1109
+ mode: parsed.mode
1110
+ };
1111
+ } catch {
1112
+ return createDefaultSecurityPolicy();
1113
+ }
1114
+ }
1115
+ function getSecurityPolicyOption(mode) {
1116
+ return SECURITY_POLICY_OPTIONS.find((option) => option.mode === mode) || SECURITY_POLICY_OPTIONS.at(-1);
1117
+ }
1118
+ function describeSecurityPolicyMode(mode) {
1119
+ return getSecurityPolicyOption(mode).label;
1120
+ }
1121
+ function isSecurityPolicyEnabled(mode) {
1122
+ return mode !== "disabled";
1123
+ }
1124
+ function resolveSecurityValidationOptions(mode) {
1125
+ switch (mode) {
1126
+ case "disabled":
1127
+ return {
1128
+ inspectPrompt: false,
1129
+ inspectResources: false,
1130
+ mode
1131
+ };
1132
+ case "input-only":
1133
+ return {
1134
+ inspectPrompt: false,
1135
+ inspectResources: false,
1136
+ mode
1137
+ };
1138
+ case "prompt-only":
1139
+ return {
1140
+ inspectPrompt: true,
1141
+ inspectResources: false,
1142
+ mode
1143
+ };
1144
+ case "prompt-with-resources":
1145
+ default:
1146
+ return {
1147
+ inspectPrompt: true,
1148
+ inspectResources: true,
1149
+ mode
1150
+ };
1151
+ }
1152
+ }
1153
+
1154
+ // src/common/security/guard.ts
1155
+ function toSecuritySourceLabel(source, location) {
1156
+ switch (source) {
1157
+ case "input":
1158
+ return "\uC0AC\uC6A9\uC790 \uC785\uB825";
1159
+ case "rawCommand":
1160
+ return "\uC6D0\uBCF8 \uBA85\uB839\uC5B4";
1161
+ case "rawArgs":
1162
+ return "\uC6D0\uBCF8 \uBA85\uB839 \uC778\uC790";
1163
+ case "args":
1164
+ return "\uBA85\uB839 \uC778\uC790";
1165
+ case "prompt":
1166
+ return "AI \uD504\uB86C\uD504\uD2B8";
1167
+ case "resource":
1168
+ return location ? `\uCC38\uC870 \uB9AC\uC18C\uC2A4 (${location})` : "\uCC38\uC870 \uB9AC\uC18C\uC2A4";
1169
+ default:
1170
+ return source;
1171
+ }
1172
+ }
1173
+ function buildSecurityBlockSections(result, policyModeLabel) {
1174
+ const detailLines = [`- policyMode: ${policyModeLabel}`, `- rule: \`${result.ruleName}\``, `- message: ${result.message}`];
1175
+ if (result.detail) {
1176
+ detailLines.push(`- source: ${toSecuritySourceLabel(result.detail.source, result.detail.location)}`);
1177
+ if (result.detail.matchedText) {
1178
+ detailLines.push(`- matched: \`${result.detail.matchedText}\``);
1179
+ }
1180
+ }
1181
+ return [
1182
+ {
1183
+ heading: "Security Block",
1184
+ markdown: detailLines.join("\n")
1185
+ }
1186
+ ];
1187
+ }
1188
+ function buildSecurityBlockUserMessage(result, policyModeLabel, errorReportPath) {
1189
+ const lines = ["\uBCF4\uC548 \uC815\uCC45\uC5D0 \uC758\uD574 \uC694\uCCAD\uC744 \uC911\uB2E8\uD588\uC2B5\uB2C8\uB2E4.", result.message, `- \uD604\uC7AC \uC815\uCC45: ${policyModeLabel}`, `- \uBCF4\uC548 \uADDC\uCE59: \`${result.ruleName}\``];
1190
+ if (result.detail) {
1191
+ lines.push(`- \uAC10\uC9C0 \uC704\uCE58: ${toSecuritySourceLabel(result.detail.source, result.detail.location)}`);
1192
+ if (result.detail.matchedText) {
1193
+ lines.push(`- \uAC10\uC9C0 \uB0B4\uC6A9: \`${result.detail.matchedText}\``);
1194
+ }
1195
+ }
1196
+ if (errorReportPath) {
1197
+ lines.push(`- \uC5D0\uB7EC \uB9AC\uD3EC\uD2B8: ${errorReportPath}`);
1198
+ }
1199
+ return lines.join("\n");
1200
+ }
1201
+ async function guardSecurityPayload(options) {
1202
+ ensureDefaultSecurityRules();
1203
+ const policy = readSecurityPolicy(options.paths);
1204
+ const policyModeLabel = describeSecurityPolicyMode(policy.mode);
1205
+ if (!isSecurityPolicyEnabled(policy.mode)) {
1206
+ options.trace("security:skip", `${options.traceLabel} | ${policy.mode}`);
1207
+ return {
1208
+ ok: true
1209
+ };
1210
+ }
1211
+ const validationOptions = resolveSecurityValidationOptions(policy.mode);
1212
+ const result = await validateSecurityPayload(options.payload, options.config, validationOptions);
1213
+ if (!result.ok) {
1214
+ options.trace("security:block", `${options.traceLabel} | ${result.ruleName}`);
1215
+ const errorReportPath = options.paths ? writeErrorReport(
1216
+ options.paths,
1217
+ {
1218
+ detail: result.detail,
1219
+ message: result.message,
1220
+ name: "SecurityPolicyBlockedError",
1221
+ payload: {
1222
+ command: options.payload.command,
1223
+ requestedService: options.payload.requestedService,
1224
+ service: options.payload.service
1225
+ },
1226
+ ruleName: result.ruleName
1227
+ },
1228
+ {
1229
+ extraSections: buildSecurityBlockSections(result, policyModeLabel),
1230
+ scope: options.reportScope || `security:${options.traceLabel}`
1231
+ }
1232
+ ) : void 0;
1233
+ const userMessage = buildSecurityBlockUserMessage(result, policyModeLabel, errorReportPath);
1234
+ console.error(userMessage);
1235
+ return {
1236
+ ...result,
1237
+ errorReportPath,
1238
+ userMessage
1239
+ };
1240
+ }
1241
+ return result;
1242
+ }
1243
+ var POSTHOG_API_KEY = "phc_MX929Nca94SLcOo7b5Mdvhv9KQi7lSESFNKRhAJRKi9";
1244
+ var POSTHOG_HOST = "https://us.i.posthog.com";
1245
+ var POSTHOG_SHUTDOWN_TIMEOUT_MS = 5e3;
1246
+ var telemetryRuntimeState = globalThis.__JU_HONG_E_POSTHOG_RUNTIME_STATE__ ?? (globalThis.__JU_HONG_E_POSTHOG_RUNTIME_STATE__ = {});
1247
+ function getPostHogClient() {
1248
+ if (!telemetryRuntimeState.posthogClient) {
1249
+ telemetryRuntimeState.posthogClient = new posthogNode.PostHog(POSTHOG_API_KEY, {
1250
+ host: POSTHOG_HOST
1251
+ });
1252
+ }
1253
+ return telemetryRuntimeState.posthogClient;
1254
+ }
1255
+ function readGitConfigValue(rootDir, configKey) {
1256
+ if (!isGitRepository(rootDir)) {
1257
+ return null;
1258
+ }
1259
+ try {
1260
+ return runGitCommand(rootDir, `git config --get ${configKey}`) || null;
1261
+ } catch {
1262
+ return null;
1263
+ }
1264
+ }
1265
+ function resolveDistinctId(gitUserName, gitUserEmail) {
1266
+ if (gitUserEmail) {
1267
+ return `git-email:${gitUserEmail}`;
1268
+ }
1269
+ if (gitUserName) {
1270
+ return `git-name:${gitUserName}`;
1271
+ }
1272
+ try {
1273
+ const currentUser = os.userInfo();
1274
+ return `os-user:${currentUser.username}@${os.hostname()}`;
1275
+ } catch {
1276
+ return `host:${os.hostname()}`;
1277
+ }
1278
+ }
1279
+ function resolveGitTelemetryMetadata(rootDir) {
1280
+ const gitUserName = readGitConfigValue(rootDir, "user.name");
1281
+ const gitUserEmail = readGitConfigValue(rootDir, "user.email");
1282
+ return {
1283
+ distinctId: resolveDistinctId(gitUserName, gitUserEmail),
1284
+ gitUserEmail,
1285
+ gitUserName
1286
+ };
1287
+ }
1288
+ function resolveUserIpAddressValue() {
1289
+ const ipAddresses = /* @__PURE__ */ new Set();
1290
+ Object.values(os.networkInterfaces()).forEach((records) => {
1291
+ records?.forEach((record) => {
1292
+ if (!record || record.internal) {
1293
+ return;
1294
+ }
1295
+ ipAddresses.add(record.address);
1296
+ });
1297
+ });
1298
+ return [...ipAddresses].join(", ");
1299
+ }
1300
+ function buildCommandParameterProperties(args) {
1301
+ const parameterProperties = {};
1302
+ if (args.length === 0) {
1303
+ parameterProperties["\uBA85\uB839\uC5B4\uC5D0\uC0AC\uC6A9\uB41C\uD30C\uB77C\uBBF8\uD1301"] = null;
1304
+ return parameterProperties;
1305
+ }
1306
+ args.forEach((arg, index) => {
1307
+ parameterProperties[`\uBA85\uB839\uC5B4\uC5D0\uC0AC\uC6A9\uB41C\uD30C\uB77C\uBBF8\uD130${index + 1}`] = arg;
1308
+ });
1309
+ return parameterProperties;
1310
+ }
1311
+ function beginSlashCommandTelemetryInputCollection(initialArgs) {
1312
+ telemetryRuntimeState.slashCommandTelemetryInputValues = [...initialArgs];
1313
+ }
1314
+ function appendSlashCommandTelemetryInputValue(value) {
1315
+ if (!telemetryRuntimeState.slashCommandTelemetryInputValues) {
1316
+ return;
1317
+ }
1318
+ telemetryRuntimeState.slashCommandTelemetryInputValues.push(...normalizeSlashCommandTelemetryValues(value));
1319
+ }
1320
+ function endSlashCommandTelemetryInputCollection() {
1321
+ const values = [...telemetryRuntimeState.slashCommandTelemetryInputValues || []];
1322
+ telemetryRuntimeState.slashCommandTelemetryInputValues = void 0;
1323
+ return values;
1324
+ }
1325
+ function normalizeSlashCommandTelemetryValues(value) {
1326
+ if (value === void 0) {
1327
+ return [];
1328
+ }
1329
+ if (value === null) {
1330
+ return [null];
1331
+ }
1332
+ if (Array.isArray(value)) {
1333
+ return value.flatMap((item) => normalizeSlashCommandTelemetryValues(item));
1334
+ }
1335
+ if (typeof value === "string") {
1336
+ return [value];
1337
+ }
1338
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
1339
+ return [String(value)];
1340
+ }
1341
+ if (typeof value === "object") {
1342
+ const objectValue = value;
1343
+ if (typeof objectValue.url === "string" && objectValue.url) {
1344
+ return [objectValue.url];
1345
+ }
1346
+ if (typeof objectValue.hash === "string" && objectValue.hash) {
1347
+ return [objectValue.hash];
1348
+ }
1349
+ if (typeof objectValue.name === "string" && objectValue.name) {
1350
+ return [objectValue.name];
1351
+ }
1352
+ if (typeof objectValue.label === "string" && objectValue.label) {
1353
+ return [objectValue.label];
1354
+ }
1355
+ try {
1356
+ return [JSON.stringify(objectValue)];
1357
+ } catch {
1358
+ return ["[object]"];
1359
+ }
1360
+ }
1361
+ return [String(value)];
1362
+ }
1363
+ function trackSlashCommandExecution(options) {
1364
+ try {
1365
+ const gitMetadata = resolveGitTelemetryMetadata(options.rootDir);
1366
+ getPostHogClient().capture({
1367
+ distinctId: gitMetadata.distinctId,
1368
+ event: options.command,
1369
+ properties: {
1370
+ "userinfo-git-user-email": gitMetadata.gitUserEmail,
1371
+ "userinfo-git-user-name": gitMetadata.gitUserName,
1372
+ "userinfo-ip": resolveUserIpAddressValue(),
1373
+ "command-kind": options.kind,
1374
+ "command-service": options.service,
1375
+ "command-status": options.status,
1376
+ "requested-service": options.requestedService ?? null,
1377
+ ...buildCommandParameterProperties(options.args)
1378
+ }
1379
+ });
1380
+ options.trace?.("posthog:slash-command:capture", `${options.command} status=${options.status}`);
1381
+ } catch (error) {
1382
+ options.trace?.("posthog:slash-command:skip", getErrorSummary(error));
1383
+ }
1384
+ }
1385
+ async function shutdownPostHogClient() {
1386
+ if (!telemetryRuntimeState.posthogClient) {
1387
+ return;
1388
+ }
1389
+ if (!telemetryRuntimeState.shutdownPromise) {
1390
+ const client = telemetryRuntimeState.posthogClient;
1391
+ telemetryRuntimeState.shutdownPromise = Promise.resolve(client.shutdown(POSTHOG_SHUTDOWN_TIMEOUT_MS)).catch(() => void 0).finally(() => {
1392
+ telemetryRuntimeState.posthogClient = void 0;
1393
+ telemetryRuntimeState.shutdownPromise = void 0;
1394
+ });
1395
+ }
1396
+ await telemetryRuntimeState.shutdownPromise;
1397
+ }
1398
+
1399
+ // src/common/core/cancellation.ts
1400
+ var USER_CANCELLED_ERROR_CODE = "JUHONG_E_USER_CANCELLED";
1401
+ var USER_TERMINATED_ERROR_CODE = "JUHONG_E_USER_TERMINATED";
1402
+ function createUserCancelledError(message = "\uC0AC\uC6A9\uC790\uAC00 \uD604\uC7AC \uC791\uC5C5\uC744 \uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4.") {
1403
+ const error = new Error(message);
1404
+ error.name = "UserCancelledError";
1405
+ error.code = USER_CANCELLED_ERROR_CODE;
1406
+ return error;
1407
+ }
1408
+ function isUserCancelledError(error) {
1409
+ return Boolean(
1410
+ error && typeof error === "object" && "code" in error && error.code === USER_CANCELLED_ERROR_CODE
1411
+ );
1412
+ }
1413
+ function createUserTerminatedError(message = "\uC0AC\uC6A9\uC790\uAC00 \uC138\uC158 \uC885\uB8CC\uB97C \uC694\uCCAD\uD588\uC2B5\uB2C8\uB2E4.") {
1414
+ const error = new Error(message);
1415
+ error.name = "UserTerminatedError";
1416
+ error.code = USER_TERMINATED_ERROR_CODE;
1417
+ return error;
1418
+ }
1419
+ function isUserTerminatedError(error) {
1420
+ return Boolean(
1421
+ error && typeof error === "object" && "code" in error && error.code === USER_TERMINATED_ERROR_CODE
1422
+ );
1423
+ }
1424
+
1425
+ // src/common/ui/index.ts
1426
+ var ANSI = {
1427
+ blue: "\x1B[34m",
1428
+ bold: "\x1B[1m",
1429
+ cyan: "\x1B[36m",
1430
+ dim: "\x1B[2m",
1431
+ gray: "\x1B[90m",
1432
+ green: "\x1B[32m",
1433
+ red: "\x1B[31m",
1434
+ reset: "\x1B[0m",
1435
+ yellow: "\x1B[33m"
1436
+ };
1437
+ var ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
1438
+ var COMBINING_MARK_PATTERN = /\p{Mark}/u;
1439
+ var GRAPHEME_SEGMENTER = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter("ko", { granularity: "grapheme" }) : null;
1440
+ var STATUS_FRAMES = ["-", "\\", "|", "/"];
1441
+ function colorize(text, color) {
1442
+ return `${color}${text}${ANSI.reset}`;
1443
+ }
1444
+ function formatStatusPrefix(title) {
1445
+ return `${colorize(`[${title}]`, `${ANSI.bold}${ANSI.cyan}`)}`;
1446
+ }
1447
+ function formatElapsed(startedAt) {
1448
+ return `${Math.max(0, Math.floor((Date.now() - startedAt) / 1e3))}s`;
1449
+ }
1450
+ function buildStatusRenderLayout(prefix, body) {
1451
+ return buildPromptRenderLayout(`${prefix} `, body);
1452
+ }
1453
+ function clearRenderedStatus(previousState) {
1454
+ if (previousState?.totalLines && previousState.totalLines > 1) {
1455
+ readline__default.default.moveCursor(process$1.stdout, 0, -(previousState.totalLines - 1));
1456
+ }
1457
+ readline__default.default.cursorTo(process$1.stdout, 0);
1458
+ readline__default.default.clearScreenDown(process$1.stdout);
1459
+ }
1460
+ function renderStatusLayout(layout, previousState) {
1461
+ clearRenderedStatus(previousState);
1462
+ process$1.stdout.write(layout.lines.join("\n"));
1463
+ return {
1464
+ totalLines: layout.totalLines
1465
+ };
1466
+ }
1467
+ function createSessionActionStatus(title) {
1468
+ const prefix = formatStatusPrefix(title);
1469
+ const print = (message) => {
1470
+ console.log(`${prefix} ${message}`);
1471
+ };
1472
+ return {
1473
+ fail(message) {
1474
+ print(colorize(message, ANSI.red));
1475
+ },
1476
+ step(message) {
1477
+ print(message);
1478
+ },
1479
+ async track(message, task) {
1480
+ if (!process$1.stdout.isTTY) {
1481
+ print(`${message}...`);
1482
+ return task();
1483
+ }
1484
+ const startedAt = Date.now();
1485
+ let frameIndex = 0;
1486
+ let renderState;
1487
+ const render = () => {
1488
+ const frame = STATUS_FRAMES[frameIndex % STATUS_FRAMES.length];
1489
+ frameIndex += 1;
1490
+ renderState = renderStatusLayout(buildStatusRenderLayout(`${prefix} ${frame}`, `${message} (${formatElapsed(startedAt)})`), renderState);
1491
+ };
1492
+ render();
1493
+ const timer = setInterval(render, 120);
1494
+ try {
1495
+ const result = await task();
1496
+ clearInterval(timer);
1497
+ renderState = renderStatusLayout(
1498
+ buildStatusRenderLayout(`${prefix} done`, `${message} (${formatElapsed(startedAt)})`),
1499
+ renderState
1500
+ );
1501
+ process$1.stdout.write("\n");
1502
+ return result;
1503
+ } catch (error) {
1504
+ clearInterval(timer);
1505
+ renderState = renderStatusLayout(
1506
+ buildStatusRenderLayout(`${prefix} fail`, `${message} (${formatElapsed(startedAt)})`),
1507
+ renderState
1508
+ );
1509
+ process$1.stdout.write("\n");
1510
+ throw error;
1511
+ }
1512
+ }
1513
+ };
1514
+ }
1515
+ function segmentGraphemes(value) {
1516
+ if (!GRAPHEME_SEGMENTER) {
1517
+ return [...value];
1518
+ }
1519
+ return [...GRAPHEME_SEGMENTER.segment(value)].map(({ segment }) => segment);
1520
+ }
1521
+ function getGraphemeWidth(grapheme) {
1522
+ let width = 0;
1523
+ for (const character of grapheme) {
1524
+ const codePoint = character.codePointAt(0);
1525
+ if (!codePoint || COMBINING_MARK_PATTERN.test(character) || codePoint === 8205) {
1526
+ continue;
1527
+ }
1528
+ if (codePoint >= 65024 && codePoint <= 65039 || codePoint >= 917760 && codePoint <= 917999) {
1529
+ continue;
1530
+ }
1531
+ if (isWideCodePoint(codePoint) || isEmojiCodePoint(codePoint)) {
1532
+ width = Math.max(width, 2);
1533
+ continue;
1534
+ }
1535
+ width = Math.max(width, 1);
1536
+ }
1537
+ return width;
1538
+ }
1539
+ function tokenizeVisibleText(value) {
1540
+ const tokens = [];
1541
+ let lastIndex = 0;
1542
+ for (const match of value.matchAll(ANSI_PATTERN)) {
1543
+ const index = match.index ?? 0;
1544
+ if (index > lastIndex) {
1545
+ tokens.push(...tokenizePlainText(value.slice(lastIndex, index)));
1546
+ }
1547
+ tokens.push({
1548
+ value: match[0],
1549
+ visibleWidth: 0
1550
+ });
1551
+ lastIndex = index + match[0].length;
1552
+ }
1553
+ if (lastIndex < value.length) {
1554
+ tokens.push(...tokenizePlainText(value.slice(lastIndex)));
1555
+ }
1556
+ return tokens;
1557
+ }
1558
+ function tokenizePlainText(value) {
1559
+ return segmentGraphemes(value).map((segment) => ({
1560
+ value: segment,
1561
+ visibleWidth: getGraphemeWidth(segment)
1562
+ }));
1563
+ }
1564
+ function isWideCodePoint(codePoint) {
1565
+ return codePoint >= 4352 && (codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || codePoint >= 11904 && codePoint <= 12871 && codePoint !== 12351 || codePoint >= 12880 && codePoint <= 19903 || codePoint >= 19968 && codePoint <= 42182 || codePoint >= 43360 && codePoint <= 43388 || codePoint >= 44032 && codePoint <= 55203 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 65040 && codePoint <= 65049 || codePoint >= 65072 && codePoint <= 65131 || codePoint >= 65281 && codePoint <= 65376 || codePoint >= 65504 && codePoint <= 65510 || codePoint >= 127488 && codePoint <= 127569 || codePoint >= 131072 && codePoint <= 262141);
1566
+ }
1567
+ function isEmojiCodePoint(codePoint) {
1568
+ return codePoint >= 127462 && codePoint <= 127487 || codePoint >= 127744 && codePoint <= 129791 || codePoint >= 9728 && codePoint <= 10175;
1569
+ }
1570
+ function visibleLength(value) {
1571
+ return tokenizeVisibleText(value).reduce((total, token) => total + token.visibleWidth, 0);
1572
+ }
1573
+ function sliceVisible(value, width) {
1574
+ if (width <= 0) {
1575
+ return "";
1576
+ }
1577
+ let currentWidth = 0;
1578
+ let output = "";
1579
+ let truncated = false;
1580
+ let containsAnsi = false;
1581
+ for (const token of tokenizeVisibleText(value)) {
1582
+ if (token.visibleWidth === 0) {
1583
+ output += token.value;
1584
+ containsAnsi = true;
1585
+ continue;
1586
+ }
1587
+ if (currentWidth + token.visibleWidth > width) {
1588
+ truncated = true;
1589
+ break;
1590
+ }
1591
+ output += token.value;
1592
+ currentWidth += token.visibleWidth;
1593
+ }
1594
+ if (truncated && containsAnsi && !output.endsWith(ANSI.reset)) {
1595
+ output += ANSI.reset;
1596
+ }
1597
+ return output;
1598
+ }
1599
+ function padVisible(value, width) {
1600
+ const slicedValue = sliceVisible(value, width);
1601
+ const length = visibleLength(slicedValue);
1602
+ if (length >= width) {
1603
+ return slicedValue;
1604
+ }
1605
+ return `${slicedValue}${" ".repeat(width - length)}`;
1606
+ }
1607
+ function getViewportWidth() {
1608
+ const columns = process$1.stdout.columns || 100;
1609
+ return Math.max(Math.min(columns - 2, 108), 4);
1610
+ }
1611
+ function getTerminalColumns() {
1612
+ return Math.max(process$1.stdout.columns || 100, 4);
1613
+ }
1614
+ function renderBadge(text, tone) {
1615
+ const theme = tone === "service" ? ANSI.cyan : tone === "accent" ? ANSI.green : tone === "warn" ? ANSI.yellow : ANSI.gray;
1616
+ return colorize(`[${text}]`, theme);
1617
+ }
1618
+ function createBox(title, lines, footerLines = []) {
1619
+ const contentLines = lines.length > 0 ? lines : [""];
1620
+ const footer = footerLines.length > 0 ? ["", ...footerLines] : [];
1621
+ const width = getViewportWidth();
1622
+ const top = `+${"-".repeat(width - 2)}+`;
1623
+ const titleLine = `| ${padVisible(colorize(title, ANSI.bold), width - 4)} |`;
1624
+ const body = [...contentLines, ...footer].map((line) => `| ${padVisible(line, width - 4)} |`);
1625
+ return [top, titleLine, top, ...body, top];
1626
+ }
1627
+ function renderScreenBox(title, lines, footerLines = []) {
1628
+ console.clear();
1629
+ console.log(createBox(title, lines, footerLines).join("\n"));
1630
+ }
1631
+ function getPromptPrefix(service, testMode = false, traceMode = false) {
1632
+ return [
1633
+ colorize("ju-hong-e", `${ANSI.bold}${ANSI.cyan}`),
1634
+ renderBadge(service, "service"),
1635
+ testMode ? renderBadge("TEST", "warn") : "",
1636
+ traceMode ? renderBadge("TRACE", "muted") : ""
1637
+ ].filter(Boolean).join(" ");
1638
+ }
1639
+ function isSlashCommandQuery(input) {
1640
+ const trimmed = input.trimStart();
1641
+ return trimmed.startsWith("/") || /^\[(codex|gemini|claude)\]\s+\/?/i.test(trimmed);
1642
+ }
1643
+ function getVisibleCommandOptions(commands, input) {
1644
+ if (!isSlashCommandQuery(input)) {
1645
+ return [];
1646
+ }
1647
+ const keyword = input.toLowerCase();
1648
+ return commands.filter((command) => {
1649
+ const candidates = [command.command, command.insertValue, ...command.matchKeywords || []].filter((candidate) => Boolean(candidate)).map((candidate) => candidate.toLowerCase());
1650
+ return candidates.some((candidate) => candidate.startsWith(keyword));
1651
+ });
1652
+ }
1653
+ function renderCommandPalette(commands, cursor) {
1654
+ const windowSize = 8;
1655
+ const start = Math.max(0, Math.min(cursor - Math.floor(windowSize / 2), Math.max(commands.length - windowSize, 0)));
1656
+ const visible = commands.slice(start, start + windowSize);
1657
+ return createBox(
1658
+ "Slash Commands",
1659
+ visible.map((command, index) => {
1660
+ const commandIndex = start + index;
1661
+ const prefix = cursor === commandIndex ? colorize(">", ANSI.green) : " ";
1662
+ const label = cursor === commandIndex ? colorize(command.command, ANSI.green) : command.command;
1663
+ const description = colorize(command.description, ANSI.gray);
1664
+ return `${prefix} ${padVisible(label, 28)} ${description}`;
1665
+ }),
1666
+ [
1667
+ `${colorize("\uD45C\uC2DC \uBC94\uC704", ANSI.gray)} ${start + 1}-${Math.min(start + visible.length, commands.length)} / ${commands.length}`,
1668
+ `${colorize("Tab", ANSI.yellow)} \uC120\uD0DD \uC801\uC6A9`,
1669
+ `${colorize("Up/Down", ANSI.yellow)} \uBA85\uB839 \uC774\uB3D9`,
1670
+ `${colorize("Shift+Up/Down", ANSI.yellow)} \uD788\uC2A4\uD1A0\uB9AC \uC774\uB3D9`,
1671
+ `${colorize("ESC", ANSI.yellow)} \uD604\uC7AC \uC785\uB825 \uC9C0\uC6B0\uAE30`,
1672
+ `${colorize("Ctrl+C", ANSI.yellow)} \uC138\uC158 \uC885\uB8CC`,
1673
+ `${colorize("Enter", ANSI.yellow)} \uD604\uC7AC \uC785\uB825 \uC2E4\uD589`
1674
+ ]
1675
+ );
1676
+ }
1677
+ function commitInteractiveLine(prefix, buffer) {
1678
+ readline__default.default.cursorTo(process$1.stdout, 0);
1679
+ readline__default.default.clearScreenDown(process$1.stdout);
1680
+ process$1.stdout.write(`${prefix} ${colorize(">", ANSI.blue)} ${buffer}
1681
+ `);
1682
+ }
1683
+ function wrapPlainText(value, firstLineWidth, continuationLineWidth) {
1684
+ const renderedLines = [];
1685
+ const safeFirstLineWidth = Math.max(firstLineWidth, 1);
1686
+ const safeContinuationLineWidth = Math.max(continuationLineWidth, 1);
1687
+ const normalizedValue = value.replace(/\r\n?/g, "\n");
1688
+ const pushWrappedLine = (line) => {
1689
+ if (line.length === 0) {
1690
+ renderedLines.push("");
1691
+ return;
1692
+ }
1693
+ let currentLine = "";
1694
+ let currentWidth = 0;
1695
+ let currentLineWidth = renderedLines.length === 0 ? safeFirstLineWidth : safeContinuationLineWidth;
1696
+ for (const segment of segmentGraphemes(line)) {
1697
+ const segmentWidth = Math.max(getGraphemeWidth(segment), 1);
1698
+ if (currentLine && currentWidth + segmentWidth > currentLineWidth) {
1699
+ renderedLines.push(currentLine);
1700
+ currentLine = "";
1701
+ currentWidth = 0;
1702
+ currentLineWidth = safeContinuationLineWidth;
1703
+ }
1704
+ currentLine += segment;
1705
+ currentWidth += segmentWidth;
1706
+ }
1707
+ renderedLines.push(currentLine);
1708
+ };
1709
+ normalizedValue.split("\n").forEach(pushWrappedLine);
1710
+ return renderedLines.length > 0 ? renderedLines : [""];
1711
+ }
1712
+ function buildPromptRenderLayout(promptLabel, buffer, placeholder) {
1713
+ const columns = getTerminalColumns();
1714
+ const promptLabelWidth = visibleLength(promptLabel);
1715
+ const continuationIndentWidth = Math.min(promptLabelWidth, Math.max(columns - 1, 0));
1716
+ const continuationIndent = " ".repeat(continuationIndentWidth);
1717
+ const firstLineWidth = Math.max(columns - promptLabelWidth, 1);
1718
+ const continuationLineWidth = Math.max(columns - continuationIndentWidth, 1);
1719
+ const hasBuffer = buffer.length > 0;
1720
+ const contentLines = hasBuffer ? wrapPlainText(buffer, firstLineWidth, continuationLineWidth) : wrapPlainText(placeholder || "", firstLineWidth, continuationLineWidth);
1721
+ const cursorLines = hasBuffer ? contentLines : [""];
1722
+ const renderedPromptLines = contentLines.map((line, index) => {
1723
+ const linePrefix = index === 0 ? promptLabel : continuationIndent;
1724
+ return `${linePrefix}${hasBuffer ? line : colorize(line, ANSI.dim)}`;
1725
+ });
1726
+ const activeCursorLine = cursorLines.at(-1) || "";
1727
+ const activeCursorLinePrefixWidth = cursorLines.length <= 1 ? promptLabelWidth : continuationIndentWidth;
1728
+ return {
1729
+ cursorColumn: activeCursorLinePrefixWidth + visibleLength(activeCursorLine),
1730
+ cursorRowOffset: Math.max(cursorLines.length - 1, 0),
1731
+ lines: renderedPromptLines,
1732
+ totalLines: renderedPromptLines.length
1733
+ };
1734
+ }
1735
+ function clearRenderedPrompt(previousState) {
1736
+ if (previousState?.cursorRowOffset) {
1737
+ readline__default.default.moveCursor(process$1.stdout, 0, -previousState.cursorRowOffset);
1738
+ }
1739
+ readline__default.default.cursorTo(process$1.stdout, 0);
1740
+ readline__default.default.clearScreenDown(process$1.stdout);
1741
+ }
1742
+ function renderPromptLayout(layout, previousState) {
1743
+ clearRenderedPrompt(previousState);
1744
+ process$1.stdout.write(layout.lines.join("\n"));
1745
+ const linesBelowCursor = layout.totalLines - 1 - layout.cursorRowOffset;
1746
+ if (linesBelowCursor > 0) {
1747
+ readline__default.default.moveCursor(process$1.stdout, 0, -linesBelowCursor);
1748
+ }
1749
+ readline__default.default.cursorTo(process$1.stdout, layout.cursorColumn);
1750
+ return {
1751
+ cursorRowOffset: layout.cursorRowOffset
1752
+ };
1753
+ }
1754
+ function renderInteractivePrompt(prefix, buffer, commands, commandCursor, testMode = false, previousState) {
1755
+ const promptLabel = `${prefix} ${colorize(">", ANSI.blue)} `;
1756
+ const paletteLines = commands.length > 0 ? renderCommandPalette(commands, commandCursor) : [];
1757
+ const hintLines = commands.length === 0 ? wrapPlainText("Tip: '/' \uB85C \uBA85\uB839 \uBA54\uB274\uB97C \uC5F4\uACE0, \uC11C\uBE44\uC2A4 \uBA85\uB839\uC740 [service] prefix\uB85C \uC801\uC6A9\uB429\uB2C8\uB2E4.", getTerminalColumns(), getTerminalColumns()).map(
1758
+ (line) => colorize(line, ANSI.gray)
1759
+ ) : [];
1760
+ const promptLayout = buildPromptRenderLayout(promptLabel, buffer, "\uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694. '/' \uB85C \uBA85\uB839 \uBA54\uB274 \uC5F4\uAE30");
1761
+ const lines = [...promptLayout.lines, ...hintLines, ...paletteLines];
1762
+ if (testMode && !buffer && commands.length === 0) {
1763
+ process$1.stdout.write("");
1764
+ }
1765
+ return renderPromptLayout(
1766
+ {
1767
+ ...promptLayout,
1768
+ lines,
1769
+ totalLines: lines.length
1770
+ },
1771
+ previousState
1772
+ );
1773
+ }
1774
+ function restoreHistoryBuffer(history, historyCursor) {
1775
+ if (historyCursor < 0 || historyCursor >= history.length) {
1776
+ return "";
1777
+ }
1778
+ return history[historyCursor] || "";
1779
+ }
1780
+ function getHistoryNavigationDirection(key) {
1781
+ if (key.shift && key.name === "up") {
1782
+ return "up";
1783
+ }
1784
+ if (key.shift && key.name === "down") {
1785
+ return "down";
1786
+ }
1787
+ return null;
1788
+ }
1789
+ function printSessionBanner(options) {
1790
+ const commandSummary = options.commands.map((command) => `${command.command} ${colorize("-", ANSI.gray)} ${command.description}`);
1791
+ console.log(
1792
+ createBox(
1793
+ "Ju-hong-e Interactive Session( \uD55C\uD654\uC0DD\uBA85 \uD1B5\uD569 AI-Tool )",
1794
+ [
1795
+ `${colorize("Service", ANSI.gray)} ${renderBadge(options.service, "service")}`,
1796
+ `${colorize("Mode", ANSI.gray)} ${options.testMode ? renderBadge("TEST", "warn") : renderBadge("LIVE", "accent")}${options.traceMode ? ` ${renderBadge("TRACE", "muted")}` : ""}`,
1797
+ `${colorize("AI Stream", ANSI.gray)} ${options.streamOutputEnabled ? renderBadge("ON", "accent") : renderBadge("OFF", "muted")}`,
1798
+ "",
1799
+ ...commandSummary
1800
+ ],
1801
+ [
1802
+ colorize("Slash \uBA85\uB839\uC740 '/' \uC785\uB825 \uC2DC \uBCFC \uC218 \uC788\uACE0, \uC11C\uBE44\uC2A4 \uACE0\uC720 \uBA85\uB839\uC740 [service] prefix\uB85C \uD45C\uC2DC\uB429\uB2C8\uB2E4.", ANSI.gray),
1803
+ colorize("\uC2E4\uC2DC\uAC04 \uC751\uB2F5 \uCD9C\uB825\uC740 /show-stream \uC73C\uB85C \uCF1C\uACE0 \uB04C \uC218 \uC788\uC2B5\uB2C8\uB2E4.", ANSI.gray),
1804
+ colorize("ESC\uB294 \uD604\uC7AC \uC791\uC5C5 \uCDE8\uC18C, Ctrl+C\uB294 \uC138\uC158 \uC885\uB8CC\uC785\uB2C8\uB2E4.", ANSI.gray)
1805
+ ]
1806
+ ).join("\n")
1807
+ );
1808
+ }
1809
+ function promptSessionInput(options) {
1810
+ return new Promise((resolve, reject) => {
1811
+ const { stdin } = process;
1812
+ const rawState = "isRaw" in stdin ? Boolean(stdin.isRaw) : false;
1813
+ const prefix = getPromptPrefix(options.service, options.testMode, options.traceMode);
1814
+ let buffer = "";
1815
+ let historyCursor = -1;
1816
+ let historyDraft = "";
1817
+ let commandCursor = 0;
1818
+ let renderState;
1819
+ const cleanup = () => {
1820
+ stdin.removeListener("keypress", onKeyPress);
1821
+ if (stdin.isTTY) {
1822
+ stdin.setRawMode(rawState);
1823
+ }
1824
+ stdin.pause();
1825
+ };
1826
+ const applySelectedCommand = () => {
1827
+ const commands = getVisibleCommandOptions(options.commands, buffer);
1828
+ const selectedCommand = commands[commandCursor];
1829
+ if (!selectedCommand) {
1830
+ return false;
1831
+ }
1832
+ buffer = selectedCommand.insertValue || selectedCommand.command;
1833
+ commandCursor = 0;
1834
+ historyCursor = -1;
1835
+ historyDraft = "";
1836
+ return true;
1837
+ };
1838
+ const render = () => {
1839
+ const commands = getVisibleCommandOptions(options.commands, buffer);
1840
+ commandCursor = Math.max(0, Math.min(commandCursor, Math.max(commands.length - 1, 0)));
1841
+ renderState = renderInteractivePrompt(prefix, buffer, commands, commandCursor, options.testMode, renderState);
1842
+ };
1843
+ const moveHistory = (direction) => {
1844
+ if (options.history.length === 0) {
1845
+ return;
1846
+ }
1847
+ if (historyCursor === -1) {
1848
+ historyDraft = buffer;
1849
+ }
1850
+ if (direction === "up") {
1851
+ historyCursor = historyCursor === -1 ? options.history.length - 1 : Math.max(historyCursor - 1, 0);
1852
+ buffer = restoreHistoryBuffer(options.history, historyCursor);
1853
+ return;
1854
+ }
1855
+ if (historyCursor === -1) {
1856
+ return;
1857
+ }
1858
+ if (historyCursor >= options.history.length - 1) {
1859
+ historyCursor = -1;
1860
+ buffer = historyDraft;
1861
+ return;
1862
+ }
1863
+ historyCursor += 1;
1864
+ buffer = restoreHistoryBuffer(options.history, historyCursor);
1865
+ };
1866
+ const onKeyPress = (input, key) => {
1867
+ const visibleCommands = getVisibleCommandOptions(options.commands, buffer);
1868
+ const historyDirection = getHistoryNavigationDirection(key);
1869
+ if (key.ctrl && key.name === "c") {
1870
+ clearRenderedPrompt(renderState);
1871
+ cleanup();
1872
+ reject(createUserTerminatedError("\uC0AC\uC6A9\uC790\uAC00 \uC138\uC158 \uC885\uB8CC\uB97C \uC694\uCCAD\uD588\uC2B5\uB2C8\uB2E4."));
1873
+ return;
1874
+ }
1875
+ if (key.name === "return" || key.name === "enter") {
1876
+ if (buffer.trim() === "/" && visibleCommands.length > 0) {
1877
+ applySelectedCommand();
1878
+ render();
1879
+ return;
1880
+ }
1881
+ const resolved = buffer.trim();
1882
+ clearRenderedPrompt(renderState);
1883
+ commitInteractiveLine(prefix, resolved);
1884
+ cleanup();
1885
+ resolve(resolved);
1886
+ return;
1887
+ }
1888
+ if (key.name === "tab") {
1889
+ if (applySelectedCommand()) {
1890
+ render();
1891
+ }
1892
+ return;
1893
+ }
1894
+ if (key.name === "escape") {
1895
+ if (buffer.length > 0) {
1896
+ buffer = "";
1897
+ commandCursor = 0;
1898
+ historyCursor = -1;
1899
+ historyDraft = "";
1900
+ render();
1901
+ }
1902
+ return;
1903
+ }
1904
+ if (key.name === "backspace") {
1905
+ if (buffer.length > 0) {
1906
+ buffer = buffer.slice(0, -1);
1907
+ historyCursor = -1;
1908
+ historyDraft = "";
1909
+ commandCursor = 0;
1910
+ render();
1911
+ }
1912
+ return;
1913
+ }
1914
+ if (historyDirection) {
1915
+ moveHistory(historyDirection);
1916
+ render();
1917
+ return;
1918
+ }
1919
+ if (key.name === "up") {
1920
+ if (visibleCommands.length > 0) {
1921
+ commandCursor = commandCursor === 0 ? visibleCommands.length - 1 : commandCursor - 1;
1922
+ }
1923
+ render();
1924
+ return;
1925
+ }
1926
+ if (key.name === "down") {
1927
+ if (visibleCommands.length > 0) {
1928
+ commandCursor = commandCursor === visibleCommands.length - 1 ? 0 : commandCursor + 1;
1929
+ }
1930
+ render();
1931
+ return;
1932
+ }
1933
+ if (input && !key.ctrl && !key.meta) {
1934
+ buffer += input;
1935
+ historyCursor = -1;
1936
+ historyDraft = "";
1937
+ commandCursor = 0;
1938
+ render();
1939
+ }
1940
+ };
1941
+ readline__default.default.emitKeypressEvents(stdin);
1942
+ if (stdin.isTTY) {
1943
+ stdin.setRawMode(true);
1944
+ }
1945
+ stdin.resume();
1946
+ stdin.on("keypress", onKeyPress);
1947
+ render();
1948
+ });
1949
+ }
1950
+ function selectSingleOption(title, options) {
1951
+ return new Promise((resolve, reject) => {
1952
+ if (options.length === 0) {
1953
+ reject(new Error("\uC120\uD0DD \uAC00\uB2A5\uD55C \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
1954
+ return;
1955
+ }
1956
+ const { stdin } = process;
1957
+ const rawState = "isRaw" in stdin ? Boolean(stdin.isRaw) : false;
1958
+ let cursor = 0;
1959
+ const cleanup = () => {
1960
+ stdin.removeListener("keypress", onKeyPress);
1961
+ if (stdin.isTTY) {
1962
+ stdin.setRawMode(rawState);
1963
+ }
1964
+ stdin.pause();
1965
+ console.clear();
1966
+ };
1967
+ const render = () => {
1968
+ renderScreenBox(
1969
+ title,
1970
+ options.map((option, index) => {
1971
+ const prefix = cursor === index ? colorize(">", ANSI.green) : " ";
1972
+ const label = cursor === index ? colorize(option.label, ANSI.green) : option.label;
1973
+ return `${prefix} ${padVisible(label, 24)} ${colorize(option.description || "", ANSI.gray)}`;
1974
+ }),
1975
+ [
1976
+ `${colorize("Up/Down", ANSI.yellow)} \uC774\uB3D9`,
1977
+ `${colorize("Enter", ANSI.yellow)} \uC120\uD0DD`,
1978
+ `${colorize("ESC", ANSI.yellow)} \uCDE8\uC18C`,
1979
+ `${colorize("Ctrl+C", ANSI.yellow)} \uC138\uC158 \uC885\uB8CC`
1980
+ ]
1981
+ );
1982
+ };
1983
+ const onKeyPress = (_input, key) => {
1984
+ if (key.ctrl && key.name === "c") {
1985
+ cleanup();
1986
+ reject(createUserTerminatedError("\uC0AC\uC6A9\uC790\uAC00 \uC120\uD0DD \uC785\uB825 \uC911 \uC138\uC158 \uC885\uB8CC\uB97C \uC694\uCCAD\uD588\uC2B5\uB2C8\uB2E4."));
1987
+ return;
1988
+ }
1989
+ if (key.name === "escape") {
1990
+ cleanup();
1991
+ reject(createUserCancelledError("\uC0AC\uC6A9\uC790\uAC00 \uC120\uD0DD \uC785\uB825\uC744 \uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4."));
1992
+ return;
1993
+ }
1994
+ if (key.name === "up") {
1995
+ cursor = cursor === 0 ? options.length - 1 : cursor - 1;
1996
+ render();
1997
+ return;
1998
+ }
1999
+ if (key.name === "down") {
2000
+ cursor = cursor === options.length - 1 ? 0 : cursor + 1;
2001
+ render();
2002
+ return;
2003
+ }
2004
+ if (key.name === "return" || key.name === "enter") {
2005
+ const selected = options[cursor];
2006
+ if (!selected) {
2007
+ cleanup();
2008
+ reject(new Error("\uC120\uD0DD\uD55C \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
2009
+ return;
2010
+ }
2011
+ cleanup();
2012
+ appendSlashCommandTelemetryInputValue(selected.value);
2013
+ resolve(selected.value);
2014
+ }
2015
+ };
2016
+ readline__default.default.emitKeypressEvents(stdin);
2017
+ if (stdin.isTTY) {
2018
+ stdin.setRawMode(true);
2019
+ }
2020
+ stdin.resume();
2021
+ stdin.on("keypress", onKeyPress);
2022
+ render();
2023
+ });
2024
+ }
2025
+
2026
+ // src/common/prompts/render.ts
2027
+ function normalizeMarkdown(markdown) {
2028
+ return markdown.trim();
2029
+ }
2030
+ function renderMarkdownBlocks(markdownBlocks) {
2031
+ const blocks = (markdownBlocks || []).map(normalizeMarkdown).filter(Boolean);
2032
+ if (blocks.length === 0) {
2033
+ return "";
2034
+ }
2035
+ return blocks.join("\n\n");
2036
+ }
2037
+ function renderLabeledSection(section) {
2038
+ const markdown = normalizeMarkdown(section.markdown);
2039
+ if (!markdown) {
2040
+ return "";
2041
+ }
2042
+ return [`[${section.heading}]`, markdown].join("\n");
2043
+ }
2044
+ function toPromptSections(prompt) {
2045
+ const sections = [
2046
+ {
2047
+ heading: "\uC9C0\uCE68",
2048
+ markdown: renderMarkdownBlocks(prompt.instructions)
2049
+ },
2050
+ {
2051
+ heading: "\uCD5C\uADFC \uD788\uC2A4\uD1A0\uB9AC",
2052
+ markdown: prompt.historyContext || "(\uC5C6\uC74C)"
2053
+ },
2054
+ {
2055
+ heading: "\uD604\uC7AC \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uC0C1\uD0DC",
2056
+ markdown: prompt.workspaceSnapshot.available ? [
2057
+ `Git Root: ${prompt.workspaceSnapshot.gitRoot}`,
2058
+ `Branch: ${prompt.workspaceSnapshot.branch || "(detached)"}`,
2059
+ "",
2060
+ "[git status --short]",
2061
+ prompt.workspaceSnapshot.statusLines.join("\n") || "(\uC5C6\uC74C)",
2062
+ "",
2063
+ "[git diff --stat]",
2064
+ prompt.workspaceSnapshot.diffStat || "(\uC5C6\uC74C)",
2065
+ "",
2066
+ "[\uCD5C\uADFC \uCEE4\uBC0B]",
2067
+ prompt.workspaceSnapshot.recentCommits.join("\n") || "(\uC5C6\uC74C)"
2068
+ ].join("\n") : prompt.workspaceSnapshot.note
2069
+ },
2070
+ {
2071
+ heading: "\uADDC\uCE59",
2072
+ markdown: renderMarkdownBlocks(prompt.rules)
2073
+ },
2074
+ {
2075
+ heading: "\uC751\uB2F5 \uC591\uC2DD",
2076
+ markdown: renderMarkdownBlocks(prompt.forms)
2077
+ },
2078
+ ...prompt.sections || []
2079
+ ];
2080
+ return sections.filter((section) => normalizeMarkdown(section.markdown));
2081
+ }
2082
+ function renderPromptForService(prompt) {
2083
+ if (typeof prompt === "string") {
2084
+ return safeExcerpt(prompt, 2e5);
2085
+ }
2086
+ return [
2087
+ `# ${prompt.title}`,
2088
+ "",
2089
+ `\uD604\uC7AC \uC120\uD0DD\uB41C AI \uC11C\uBE44\uC2A4: ${prompt.service}`,
2090
+ ...toPromptSections(prompt).flatMap((section) => ["", renderLabeledSection(section)])
2091
+ ].join("\n");
2092
+ }
2093
+
2094
+ // src/common/ai-services/internal/shared.ts
2095
+ function quoteArgs(args) {
2096
+ return args.map((arg) => shellQuote(arg)).join(" ");
2097
+ }
2098
+ function toUnique(values) {
2099
+ const seen = /* @__PURE__ */ new Set();
2100
+ return values.filter((value) => {
2101
+ if (!value || seen.has(value)) {
2102
+ return false;
2103
+ }
2104
+ seen.add(value);
2105
+ return true;
2106
+ });
2107
+ }
2108
+ function createServiceCommandSpec(command, attempts) {
2109
+ const normalizedAttempts = attempts.map(({ args, label }) => ({
2110
+ args,
2111
+ label,
2112
+ preview: `${command} ${quoteArgs(args)}`
2113
+ }));
2114
+ return {
2115
+ attempts: normalizedAttempts,
2116
+ command,
2117
+ preview: normalizedAttempts.map((attempt) => attempt.preview).join(" || ")
2118
+ };
2119
+ }
2120
+ function getDefaultReasoningEffort(mode) {
2121
+ if (mode === "review") {
2122
+ return "high";
2123
+ }
2124
+ if (mode === "commit") {
2125
+ return "medium";
2126
+ }
2127
+ if (mode === "gen-html") {
2128
+ return "medium";
2129
+ }
2130
+ if (mode === "gen-storybook") {
2131
+ return "medium";
2132
+ }
2133
+ return "low";
2134
+ }
2135
+
2136
+ // src/common/ai-services/builders/claude.ts
2137
+ function normalizeClaudeEffort(effort) {
2138
+ if (effort === "minimal") {
2139
+ return "low";
2140
+ }
2141
+ return effort;
2142
+ }
2143
+ function resolveClaudePrimaryAlias(mode) {
2144
+ if (mode === "review") {
2145
+ return "opus";
2146
+ }
2147
+ return "sonnet";
2148
+ }
2149
+ function getClaudeAliasFallbacks(primaryAlias) {
2150
+ if (primaryAlias === "opus") {
2151
+ return ["opus", "sonnet", "haiku"];
2152
+ }
2153
+ if (primaryAlias === "haiku") {
2154
+ return ["haiku", "sonnet"];
2155
+ }
2156
+ return [primaryAlias, "sonnet", "haiku"];
2157
+ }
2158
+ function buildClaudeArgs(prompt, effort, model, fallbackModel) {
2159
+ const args = ["--permission-mode", "acceptEdits", "--effort", effort];
2160
+ if (model) {
2161
+ args.push("--model", model);
2162
+ }
2163
+ if (model && fallbackModel) {
2164
+ args.push("--fallback-model", fallbackModel);
2165
+ }
2166
+ args.push("-p", prompt);
2167
+ return args;
2168
+ }
2169
+ function buildClaudeCommand(prompt, mode, parsedArgs) {
2170
+ const renderedPrompt = renderPromptForService(prompt);
2171
+ const effort = normalizeClaudeEffort(parsedArgs.reasoningEffort ?? getDefaultReasoningEffort(mode));
2172
+ const primaryAlias = resolveClaudePrimaryAlias(mode);
2173
+ const aliasFallbacks = toUnique(getClaudeAliasFallbacks(primaryAlias));
2174
+ const modelCandidates = toUnique(parsedArgs.model ? [parsedArgs.model, ...aliasFallbacks] : aliasFallbacks);
2175
+ const attempts = modelCandidates.map((model, index) => ({
2176
+ args: buildClaudeArgs(renderedPrompt, effort, model, modelCandidates[index + 1]),
2177
+ label: `model:${model}`
2178
+ }));
2179
+ attempts.push({
2180
+ args: buildClaudeArgs(renderedPrompt, effort),
2181
+ label: "model:account-default"
2182
+ });
2183
+ return createServiceCommandSpec("claude", attempts);
2184
+ }
2185
+
2186
+ // src/common/ai-services/builders/codex.ts
2187
+ function buildCodexArgs(prompt, reasoningEffort, model) {
2188
+ const args = ["exec", "--full-auto"];
2189
+ if (model) {
2190
+ args.push("--model", model);
2191
+ }
2192
+ args.push("-c", `model_reasoning_effort="${reasoningEffort}"`, prompt);
2193
+ return args;
2194
+ }
2195
+ function buildCodexCommand(prompt, mode, parsedArgs) {
2196
+ const renderedPrompt = renderPromptForService(prompt);
2197
+ const effort = parsedArgs.reasoningEffort ?? getDefaultReasoningEffort(mode);
2198
+ const preferredModelAlias = "gpt-5";
2199
+ const modelCandidates = toUnique(parsedArgs.model ? [parsedArgs.model, preferredModelAlias] : [preferredModelAlias]);
2200
+ const attempts = modelCandidates.map((model) => ({
2201
+ args: buildCodexArgs(renderedPrompt, effort, model),
2202
+ label: `model:${model}`
2203
+ }));
2204
+ attempts.push({
2205
+ args: buildCodexArgs(renderedPrompt, effort),
2206
+ label: "model:account-default"
2207
+ });
2208
+ return createServiceCommandSpec("codex", attempts);
2209
+ }
2210
+
2211
+ // src/common/ai-services/builders/gemini.ts
2212
+ function resolveGeminiPrimaryAlias(mode, reasoningEffort) {
2213
+ if (mode === "review" || mode === "gen-html" || mode === "gen-storybook") {
2214
+ return "pro";
2215
+ }
2216
+ if (reasoningEffort === "high") {
2217
+ return "pro";
2218
+ }
2219
+ if (reasoningEffort === "minimal" || reasoningEffort === "low") {
2220
+ return "flash";
2221
+ }
2222
+ return "auto";
2223
+ }
2224
+ function getGeminiAliasFallbacks(primaryAlias) {
2225
+ if (primaryAlias === "pro") {
2226
+ return ["pro", "flash", "auto"];
2227
+ }
2228
+ if (primaryAlias === "flash") {
2229
+ return ["flash", "auto", "pro"];
2230
+ }
2231
+ return [primaryAlias, "auto", "flash", "pro"];
2232
+ }
2233
+ function buildGeminiArgs(prompt, model) {
2234
+ const args = ["--approval-mode", "auto_edit", "--sandbox"];
2235
+ if (!model) {
2236
+ args.push("-p", prompt);
2237
+ return args;
2238
+ }
2239
+ args.push("--model", model, "-p", prompt);
2240
+ return args;
2241
+ }
2242
+ function buildGeminiCommand(prompt, mode, parsedArgs) {
2243
+ const renderedPrompt = renderPromptForService(prompt);
2244
+ const reasoningEffort = parsedArgs.reasoningEffort ?? getDefaultReasoningEffort(mode);
2245
+ const primaryAlias = resolveGeminiPrimaryAlias(mode, reasoningEffort);
2246
+ const aliasFallbacks = toUnique(getGeminiAliasFallbacks(primaryAlias));
2247
+ const modelCandidates = toUnique(parsedArgs.model ? [parsedArgs.model, ...aliasFallbacks] : aliasFallbacks);
2248
+ const attempts = modelCandidates.map((model) => ({
2249
+ args: buildGeminiArgs(renderedPrompt, model),
2250
+ label: `model:${model}`
2251
+ }));
2252
+ attempts.push({
2253
+ args: buildGeminiArgs(renderedPrompt),
2254
+ label: "model:account-default"
2255
+ });
2256
+ return createServiceCommandSpec("gemini", attempts);
2257
+ }
2258
+
2259
+ // src/common/ai-services/internal/build-service-command.ts
2260
+ function buildServiceCommand(options) {
2261
+ switch (options.service) {
2262
+ case "codex":
2263
+ return buildCodexCommand(options.prompt, options.mode, options.parsedArgs);
2264
+ case "gemini":
2265
+ return buildGeminiCommand(options.prompt, options.mode, options.parsedArgs);
2266
+ case "claude":
2267
+ return buildClaudeCommand(options.prompt, options.mode, options.parsedArgs);
2268
+ }
2269
+ }
2270
+ function getBinaryName(service) {
2271
+ switch (service) {
2272
+ case "codex":
2273
+ return "codex";
2274
+ case "gemini":
2275
+ return "gemini";
2276
+ case "claude":
2277
+ return "claude";
2278
+ }
2279
+ }
2280
+ function getInstallPackageName(service) {
2281
+ switch (service) {
2282
+ case "codex":
2283
+ return "@openai/codex";
2284
+ case "gemini":
2285
+ return "@google/gemini-cli";
2286
+ case "claude":
2287
+ return "@anthropic-ai/claude-code";
2288
+ }
2289
+ }
2290
+ function isCliAvailable(service, trace) {
2291
+ const binaryName = getBinaryName(service);
2292
+ trace("cli-check:start", `${service} -> ${binaryName} --version`);
2293
+ const result = child_process.spawnSync(binaryName, ["--version"], {
2294
+ encoding: "utf8",
2295
+ maxBuffer: 1024 * 1024 * 2
2296
+ });
2297
+ if (result.error || result.status !== 0) {
2298
+ trace("cli-check:missing", getErrorSummary(result.error || result.stderr || result.status));
2299
+ return false;
2300
+ }
2301
+ trace("cli-check:ok", `${service}`);
2302
+ return true;
2303
+ }
2304
+ function installCli(service, trace) {
2305
+ const packageName = getInstallPackageName(service);
2306
+ trace("cli-install:start", `${service} -> ${packageName}`);
2307
+ const result = child_process.spawnSync("npm", ["install", "-g", packageName], {
2308
+ encoding: "utf8",
2309
+ maxBuffer: 1024 * 1024 * 20,
2310
+ stdio: "inherit"
2311
+ });
2312
+ if (result.error || result.status !== 0) {
2313
+ trace("cli-install:failed", getErrorSummary(result.error || result.stderr || result.status));
2314
+ throw new Error(`${service} CLI \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. package=${packageName}`);
2315
+ }
2316
+ trace("cli-install:done", `${service}`);
2317
+ }
2318
+ function ensureServiceCli(service, parsedArgs, trace) {
2319
+ if (isCliAvailable(service, trace)) {
2320
+ return true;
2321
+ }
2322
+ if (parsedArgs.testMode) {
2323
+ trace("cli-install:skip:test-mode", service);
2324
+ return false;
2325
+ }
2326
+ installCli(service, trace);
2327
+ return isCliAvailable(service, trace);
2328
+ }
2329
+ function killServiceProcessTree(child, signal) {
2330
+ if (!child.pid) {
2331
+ return;
2332
+ }
2333
+ if (process.platform !== "win32") {
2334
+ try {
2335
+ process.kill(-child.pid, signal ?? "SIGTERM");
2336
+ return;
2337
+ } catch {
2338
+ }
2339
+ }
2340
+ try {
2341
+ child.kill(signal);
2342
+ } catch {
2343
+ }
2344
+ }
2345
+ function writeStreamChunk(chunk, streamOutput, writer, updateTrailingState) {
2346
+ if (!streamOutput) {
2347
+ return;
2348
+ }
2349
+ writer.write(chunk);
2350
+ updateTrailingState(!chunk.endsWith("\n"), writer);
2351
+ }
2352
+ function executeServiceCommandAttempt(command, args, trace, streamOutput = false) {
2353
+ return new Promise((resolve, reject) => {
2354
+ const child = child_process.spawn(command, args, {
2355
+ cwd: process.cwd(),
2356
+ detached: process.platform !== "win32",
2357
+ env: process.env,
2358
+ stdio: ["ignore", "pipe", "pipe"]
2359
+ });
2360
+ const { stdin } = process;
2361
+ const rawState = "isRaw" in stdin ? Boolean(stdin.isRaw) : false;
2362
+ let stopReason = null;
2363
+ let settled = false;
2364
+ let stdout2 = "";
2365
+ let stderr = "";
2366
+ let forceKillTimer;
2367
+ let lastStreamWriter;
2368
+ let needsTrailingNewline = false;
2369
+ const flushTrailingNewline = () => {
2370
+ if (!streamOutput || !needsTrailingNewline) {
2371
+ return;
2372
+ }
2373
+ (lastStreamWriter || process.stdout).write("\n");
2374
+ needsTrailingNewline = false;
2375
+ lastStreamWriter = void 0;
2376
+ };
2377
+ const cleanup = () => {
2378
+ stdin.removeListener("keypress", onKeyPress);
2379
+ if (forceKillTimer) {
2380
+ clearTimeout(forceKillTimer);
2381
+ }
2382
+ if (stdin.isTTY) {
2383
+ stdin.setRawMode(rawState);
2384
+ }
2385
+ stdin.pause();
2386
+ };
2387
+ const finish = (handler) => {
2388
+ if (settled) {
2389
+ return;
2390
+ }
2391
+ settled = true;
2392
+ flushTrailingNewline();
2393
+ cleanup();
2394
+ handler();
2395
+ };
2396
+ const requestStop = (reason) => {
2397
+ if (stopReason) {
2398
+ return;
2399
+ }
2400
+ stopReason = reason;
2401
+ trace(`service-command:${reason}:requested`, `${command} ${quoteArgs(args)}`);
2402
+ killServiceProcessTree(child, process.platform === "win32" ? void 0 : "SIGTERM");
2403
+ forceKillTimer = setTimeout(() => {
2404
+ if (!settled) {
2405
+ killServiceProcessTree(child, "SIGKILL");
2406
+ }
2407
+ }, 1500);
2408
+ forceKillTimer.unref?.();
2409
+ };
2410
+ const onKeyPress = (_input, key) => {
2411
+ if (key.name === "escape") {
2412
+ requestStop("cancel");
2413
+ }
2414
+ if (key.ctrl && key.name === "c") {
2415
+ requestStop("terminate");
2416
+ }
2417
+ };
2418
+ child.stdout?.setEncoding("utf8");
2419
+ child.stdout?.on("data", (chunk) => {
2420
+ stdout2 += chunk;
2421
+ writeStreamChunk(chunk, streamOutput, process.stdout, (nextNeedsTrailingNewline, nextWriter) => {
2422
+ needsTrailingNewline = nextNeedsTrailingNewline;
2423
+ lastStreamWriter = nextWriter;
2424
+ });
2425
+ });
2426
+ child.stderr?.setEncoding("utf8");
2427
+ child.stderr?.on("data", (chunk) => {
2428
+ stderr += chunk;
2429
+ writeStreamChunk(chunk, streamOutput, process.stderr, (nextNeedsTrailingNewline, nextWriter) => {
2430
+ needsTrailingNewline = nextNeedsTrailingNewline;
2431
+ lastStreamWriter = nextWriter;
2432
+ });
2433
+ });
2434
+ child.on("error", (error) => {
2435
+ finish(() => {
2436
+ if (stopReason === "cancel") {
2437
+ reject(createUserCancelledError("ESC \uC785\uB825\uC73C\uB85C \uD604\uC7AC AI \uC791\uC5C5\uC744 \uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4."));
2438
+ return;
2439
+ }
2440
+ if (stopReason === "terminate") {
2441
+ reject(createUserTerminatedError("Ctrl+C \uC785\uB825\uC73C\uB85C \uC138\uC158 \uC885\uB8CC\uB97C \uC694\uCCAD\uD588\uC2B5\uB2C8\uB2E4."));
2442
+ return;
2443
+ }
2444
+ resolve({
2445
+ status: null,
2446
+ stderr: getErrorSummary(error),
2447
+ streamedOutput: streamOutput,
2448
+ stdout: stdout2
2449
+ });
2450
+ });
2451
+ });
2452
+ child.on("close", (status) => {
2453
+ finish(() => {
2454
+ if (stopReason === "cancel") {
2455
+ reject(createUserCancelledError("ESC \uC785\uB825\uC73C\uB85C \uD604\uC7AC AI \uC791\uC5C5\uC744 \uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4."));
2456
+ return;
2457
+ }
2458
+ if (stopReason === "terminate") {
2459
+ reject(createUserTerminatedError("Ctrl+C \uC785\uB825\uC73C\uB85C \uC138\uC158 \uC885\uB8CC\uB97C \uC694\uCCAD\uD588\uC2B5\uB2C8\uB2E4."));
2460
+ return;
2461
+ }
2462
+ resolve({
2463
+ status,
2464
+ stderr,
2465
+ streamedOutput: streamOutput,
2466
+ stdout: stdout2
2467
+ });
2468
+ });
2469
+ });
2470
+ readline__default.default.emitKeypressEvents(stdin);
2471
+ if (stdin.isTTY) {
2472
+ stdin.setRawMode(true);
2473
+ }
2474
+ stdin.resume();
2475
+ stdin.on("keypress", onKeyPress);
2476
+ });
2477
+ }
2478
+ function createAttemptFailureError(service, failures) {
2479
+ const failureSummary = failures.map(({ attempt, result }, index) => {
2480
+ const status = result.status === null ? "spawn-error" : String(result.status);
2481
+ const excerpt = safeExcerpt(result.stderr || result.stdout || `exit status ${status}`, 1200);
2482
+ return [`[${index + 1}/${failures.length}] ${attempt.label}`, `status: ${status}`, excerpt].join("\n");
2483
+ }).join("\n\n");
2484
+ const lastFailure = failures.at(-1);
2485
+ const error = new Error(`\uBAA8\uB4E0 ${service} \uBAA8\uB378 \uC2DC\uB3C4\uAC00 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
2486
+
2487
+ ${failureSummary}`);
2488
+ Object.assign(error, {
2489
+ status: lastFailure?.result.status ?? 1,
2490
+ stderr: failureSummary,
2491
+ stdout: lastFailure?.result.stdout || ""
2492
+ });
2493
+ return error;
2494
+ }
2495
+ var DEFAULT_STREAM_OUTPUT_STATE = {
2496
+ enabled: false
2497
+ };
2498
+ var streamOutputRuntimeState = globalThis.__JU_HONG_E_STREAM_OUTPUT_STATE__ ?? (globalThis.__JU_HONG_E_STREAM_OUTPUT_STATE__ = {
2499
+ ...DEFAULT_STREAM_OUTPUT_STATE
2500
+ });
2501
+ function normalizeStreamOutputState(value) {
2502
+ if (!value || typeof value !== "object") {
2503
+ return { ...DEFAULT_STREAM_OUTPUT_STATE };
2504
+ }
2505
+ const enabled = "enabled" in value ? Boolean(value.enabled) : DEFAULT_STREAM_OUTPUT_STATE.enabled;
2506
+ return {
2507
+ enabled
2508
+ };
2509
+ }
2510
+ function readStreamOutputConfig(paths) {
2511
+ if (!fs7__default.default.existsSync(paths.streamOutputConfigPath)) {
2512
+ return { ...DEFAULT_STREAM_OUTPUT_STATE };
2513
+ }
2514
+ try {
2515
+ const parsed = JSON.parse(fs7__default.default.readFileSync(paths.streamOutputConfigPath, "utf8"));
2516
+ return normalizeStreamOutputState(parsed);
2517
+ } catch {
2518
+ return { ...DEFAULT_STREAM_OUTPUT_STATE };
2519
+ }
2520
+ }
2521
+ function hydrateStreamOutputState(paths) {
2522
+ const nextState = readStreamOutputConfig(paths);
2523
+ streamOutputRuntimeState.enabled = nextState.enabled;
2524
+ return streamOutputRuntimeState.enabled;
2525
+ }
2526
+ function isStreamOutputEnabled(paths) {
2527
+ if (paths) {
2528
+ return hydrateStreamOutputState(paths);
2529
+ }
2530
+ return streamOutputRuntimeState.enabled;
2531
+ }
2532
+
2533
+ // src/common/ai-services/index.ts
2534
+ async function runAIService(options) {
2535
+ const streamOutputEnabled = hydrateStreamOutputState(options.paths);
2536
+ const securityResult = await guardSecurityPayload({
2537
+ paths: options.paths,
2538
+ payload: {
2539
+ args: [],
2540
+ command: options.mode,
2541
+ input: "",
2542
+ prompt: options.prompt,
2543
+ promptRootDir: options.paths.rootDir,
2544
+ rawArgs: "",
2545
+ rawCommand: "",
2546
+ service: options.service
2547
+ },
2548
+ reportScope: `security:service:${options.mode}`,
2549
+ trace: options.trace,
2550
+ traceLabel: `service:${options.mode}`
2551
+ });
2552
+ if (!securityResult.ok) {
2553
+ options.trace("service-command:blocked", options.mode);
2554
+ return {
2555
+ blocked: true,
2556
+ cliAvailable: true,
2557
+ exitCode: 0,
2558
+ preview: "",
2559
+ service: options.service,
2560
+ skipped: true,
2561
+ stderr: "",
2562
+ streamedOutput: false,
2563
+ stdout: securityResult.userMessage || ""
2564
+ };
2565
+ }
2566
+ const cliAvailable = ensureServiceCli(options.service, options.parsedArgs, options.trace);
2567
+ const commandSpec = buildServiceCommand({
2568
+ mode: options.mode,
2569
+ parsedArgs: options.parsedArgs,
2570
+ prompt: options.prompt,
2571
+ service: options.service
2572
+ });
2573
+ options.trace("service-command:prepared", commandSpec.preview);
2574
+ if (options.parsedArgs.testMode || !cliAvailable) {
2575
+ options.trace("service-command:skipped", options.parsedArgs.testMode ? "test-mode" : "cli-missing");
2576
+ return {
2577
+ blocked: false,
2578
+ cliAvailable,
2579
+ exitCode: 0,
2580
+ preview: commandSpec.preview,
2581
+ service: options.service,
2582
+ skipped: true,
2583
+ stderr: "",
2584
+ streamedOutput: false,
2585
+ stdout: [
2586
+ "[TEST MODE] \uC2E4\uC81C AI \uD638\uCD9C\uC740 \uC0DD\uB7B5\uB418\uC5C8\uC2B5\uB2C8\uB2E4.",
2587
+ "",
2588
+ `service: ${options.service}`,
2589
+ `cliAvailable: ${cliAvailable}`,
2590
+ "",
2591
+ "\uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:",
2592
+ commandSpec.preview
2593
+ ].join("\n")
2594
+ };
2595
+ }
2596
+ options.trace("service-command:exec:start", `attempts=${commandSpec.attempts.length}`);
2597
+ const failures = [];
2598
+ for (const [index, attempt] of commandSpec.attempts.entries()) {
2599
+ const attemptOrder = `${index + 1}/${commandSpec.attempts.length}`;
2600
+ options.trace("service-command:attempt:start", `${attemptOrder} ${attempt.label}`);
2601
+ let result;
2602
+ try {
2603
+ result = await executeServiceCommandAttempt(
2604
+ commandSpec.command,
2605
+ attempt.args,
2606
+ options.trace,
2607
+ streamOutputEnabled
2608
+ );
2609
+ } catch (error) {
2610
+ if (isUserCancelledError(error) || isUserTerminatedError(error)) {
2611
+ options.trace(
2612
+ isUserTerminatedError(error) ? "service-command:terminated" : "service-command:cancelled",
2613
+ `${attemptOrder} ${attempt.label}`
2614
+ );
2615
+ }
2616
+ throw error;
2617
+ }
2618
+ options.trace(
2619
+ "service-command:attempt:end",
2620
+ `${attemptOrder} ${attempt.label} status=${result.status ?? "spawn-error"}`
2621
+ );
2622
+ if (result.status === 0) {
2623
+ options.trace("service-command:exec:end", `status=0 attempt=${attemptOrder} ${attempt.label}`);
2624
+ return {
2625
+ blocked: false,
2626
+ cliAvailable,
2627
+ exitCode: result.status ?? 0,
2628
+ preview: commandSpec.preview,
2629
+ service: options.service,
2630
+ skipped: false,
2631
+ stderr: result.stderr || "",
2632
+ streamedOutput: result.streamedOutput,
2633
+ stdout: result.stdout || ""
2634
+ };
2635
+ }
2636
+ failures.push({ attempt, result });
2637
+ options.trace(
2638
+ "service-command:attempt:failed",
2639
+ `${attemptOrder} ${attempt.label} ${safeExcerpt(result.stderr || result.stdout || "Unknown failure", 240)}`
2640
+ );
2641
+ }
2642
+ options.trace("service-command:exec:end", `status=${failures.at(-1)?.result.status ?? 1}`);
2643
+ throw createAttemptFailureError(options.service, failures);
2644
+ }
2645
+
2646
+ // src/common/actions/shared.ts
2647
+ function formatActionError(error) {
2648
+ return getErrorSummary(error);
2649
+ }
2650
+ async function runAIServiceWithStatus(options) {
2651
+ if (isStreamOutputEnabled(options.paths)) {
2652
+ options.status.step(options.streamingMessage || `${options.loadingMessage} - \uC2E4\uC2DC\uAC04 \uC751\uB2F5\uC744 \uADF8\uB300\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4.`);
2653
+ return runAIService({
2654
+ mode: options.mode,
2655
+ parsedArgs: options.parsedArgs,
2656
+ paths: options.paths,
2657
+ prompt: options.prompt,
2658
+ service: options.service,
2659
+ trace: options.trace
2660
+ });
2661
+ }
2662
+ return options.status.track(
2663
+ options.loadingMessage,
2664
+ () => runAIService({
2665
+ mode: options.mode,
2666
+ parsedArgs: options.parsedArgs,
2667
+ paths: options.paths,
2668
+ prompt: options.prompt,
2669
+ service: options.service,
2670
+ trace: options.trace
2671
+ })
2672
+ );
2673
+ }
2674
+ function printBufferedAIOutput(output, result, fallback = "(\uC751\uB2F5 \uC5C6\uC74C)") {
2675
+ if (result.streamedOutput) {
2676
+ return;
2677
+ }
2678
+ console.log(output || fallback);
2679
+ }
2680
+
2681
+ // src/common/actions/chat.ts
2682
+ async function runChatAction(options) {
2683
+ const securityResult = await guardSecurityPayload({
2684
+ paths: options.paths,
2685
+ payload: {
2686
+ args: [],
2687
+ command: "chat",
2688
+ input: options.input,
2689
+ rawArgs: "",
2690
+ rawCommand: options.input,
2691
+ service: options.service
2692
+ },
2693
+ reportScope: "security:chat",
2694
+ trace: options.trace,
2695
+ traceLabel: "chat"
2696
+ });
2697
+ if (!securityResult.ok) {
2698
+ return void 0;
2699
+ }
2700
+ const status = createSessionActionStatus("\uB300\uD654");
2701
+ status.step("1/4 \uB300\uD654 \uCEE8\uD14D\uC2A4\uD2B8\uC640 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uC0C1\uD0DC\uB97C \uC900\uBE44\uD558\uB294 \uC911\uC785\uB2C8\uB2E4.");
2702
+ const workspaceBefore = captureWorkspaceSnapshot(options.paths.rootDir);
2703
+ const historyContext = loadRecentHistoryContext(options.paths);
2704
+ status.step("2/4 AI \uC694\uCCAD \uD504\uB86C\uD504\uD2B8\uB97C \uAD6C\uC131\uD558\uB294 \uC911\uC785\uB2C8\uB2E4.");
2705
+ const prompt = buildChatPrompt({
2706
+ historyContext,
2707
+ service: options.service,
2708
+ userInput: options.input,
2709
+ workspaceSnapshot: workspaceBefore
2710
+ });
2711
+ const result = await runAIServiceWithStatus({
2712
+ loadingMessage: `3/4 ${options.service} \uC751\uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uC911\uC785\uB2C8\uB2E4`,
2713
+ mode: "chat",
2714
+ parsedArgs: options.parsedArgs,
2715
+ paths: options.paths,
2716
+ prompt,
2717
+ service: options.service,
2718
+ status,
2719
+ streamingMessage: `3/4 ${options.service} \uC2E4\uC2DC\uAC04 \uC751\uB2F5\uC744 \uCD9C\uB825\uD558\uB294 \uC911\uC785\uB2C8\uB2E4. ESC \uCDE8\uC18C, Ctrl+C \uC138\uC158 \uC885\uB8CC`,
2720
+ trace: options.trace
2721
+ });
2722
+ if (result.blocked) {
2723
+ status.step("4/4 \uBCF4\uC548 \uC815\uCC45\uC73C\uB85C \uC778\uD574 AI \uD638\uCD9C\uC744 \uC911\uB2E8\uD588\uC2B5\uB2C8\uB2E4.");
2724
+ return void 0;
2725
+ }
2726
+ status.step("4/4 \uC751\uB2F5\uC744 \uBC1B\uC558\uC2B5\uB2C8\uB2E4. \uC791\uC5C5 \uC774\uB825\uC744 \uC800\uC7A5\uD558\uB294 \uC911\uC785\uB2C8\uB2E4.");
2727
+ const workspaceAfter = captureWorkspaceSnapshot(options.paths.rootDir);
2728
+ const workspaceDelta = diffWorkspaceSnapshots(workspaceBefore, workspaceAfter);
2729
+ const historyPath = writeTurnHistory(options.paths, {
2730
+ historyContext,
2731
+ input: options.input,
2732
+ output: result.stdout,
2733
+ previewCommand: result.preview,
2734
+ scope: "chat",
2735
+ service: options.service,
2736
+ skipped: result.skipped,
2737
+ title: `\uB300\uD654: ${safeExcerpt(options.input, 80)}`,
2738
+ workspaceAfter,
2739
+ workspaceBefore,
2740
+ workspaceDelta
2741
+ });
2742
+ appendConversationHistory(options.paths, {
2743
+ input: options.input,
2744
+ output: result.stdout,
2745
+ scope: "chat",
2746
+ service: options.service,
2747
+ summary: `\uB300\uD654 \uCC98\uB9AC \uC644\uB8CC: ${safeExcerpt(options.input, 60)}`,
2748
+ title: `\uB300\uD654: ${safeExcerpt(options.input, 80)}`
2749
+ });
2750
+ printBufferedAIOutput(result.stdout, result);
2751
+ return {
2752
+ historyPath,
2753
+ previewCommand: result.preview,
2754
+ scope: "chat",
2755
+ service: options.service,
2756
+ skipped: result.skipped,
2757
+ summary: `\uB300\uD654 \uCC98\uB9AC \uC644\uB8CC: ${safeExcerpt(options.input, 60)}`,
2758
+ title: "\uB300\uD654",
2759
+ traceMessages: []
2760
+ };
2761
+ }
2762
+
2763
+ // src/common/command-runtime/help.ts
2764
+ function formatSlashCommands(commands) {
2765
+ return commands.map((command) => ` ${command.command.padEnd(24)} ${command.description}`).join("\n");
2766
+ }
2767
+ function createCliHelpText(commands, currentService, binaryName = "ju-hong-e") {
2768
+ const serviceSection = "";
2769
+ return `
2770
+ Usage: ${binaryName} [options]
2771
+
2772
+ Options:
2773
+ --service <codex|gemini|claude> \uC2DC\uC791 \uC11C\uBE44\uC2A4 \uC9C0\uC815
2774
+ --model <name> \uC11C\uBE44\uC2A4\uBCC4 \uBAA8\uB378 \uC9C0\uC815
2775
+ --reasoning-effort <level> minimal|low|medium|high
2776
+ --test \uC2E4\uC81C AI \uD638\uCD9C \uC5C6\uC774 \uC804\uCCB4 \uD750\uB984 \uD14C\uC2A4\uD2B8
2777
+ --trace trace \uB85C\uADF8\uB97C \uCF58\uC194\uC5D0 \uCD9C\uB825
2778
+ --help \uB3C4\uC6C0\uB9D0 \uCD9C\uB825
2779
+
2780
+ Slash Commands:
2781
+ ${formatSlashCommands(commands)}
2782
+
2783
+ Service Native Slash Commands:
2784
+ /<command> ... \uB0B4\uC7A5 \uBA85\uB839\uC774 \uC544\uB2C8\uBA74 \uD604\uC7AC \uC11C\uBE44\uC2A4 CLI\uC758 slash command\uB85C \uC704\uC784
2785
+ [service] /<command> ... \uC774\uB984\uC774 \uACB9\uCE58\uB294 \uACBD\uC6B0 \uD604\uC7AC \uC11C\uBE44\uC2A4 native command\uB97C \uBA85\uC2DC\uC801\uC73C\uB85C \uC2E4\uD589
2786
+
2787
+ Shortcuts:
2788
+ ESC \uD604\uC7AC \uC791\uC5C5 \uB610\uB294 \uC785\uB825\uB9CC \uCDE8\uC18C
2789
+ Ctrl+C \uC138\uC158 \uC885\uB8CC
2790
+ Shift+Up/Down \uC785\uB825 \uD788\uC2A4\uD1A0\uB9AC \uC774\uB3D9
2791
+
2792
+ ${serviceSection}`.trim();
2793
+ }
2794
+
2795
+ // src/common/runtime-profile.ts
2796
+ var runtimeState = globalThis.__JU_HONG_E_RUNTIME_PROFILE__ ?? (globalThis.__JU_HONG_E_RUNTIME_PROFILE__ = {
2797
+ binaryName: "ju-hong-e",
2798
+ profile: "all"
2799
+ });
2800
+ var ALL_PROFILE_CONFIGS = {
2801
+ all: {
2802
+ enableLocalServer: true
2803
+ },
2804
+ be: {
2805
+ allowedBuiltinCommands: /* @__PURE__ */ new Set(["/review", "/commit", "/change-service", "/security-policy", "/show-stream", "/help", "/exit"]),
2806
+ enableLocalServer: false
2807
+ },
2808
+ fe: {
2809
+ enableLocalServer: true
2810
+ }
2811
+ };
2812
+ function getProfileConfig(profile = runtimeState.profile) {
2813
+ return ALL_PROFILE_CONFIGS[profile];
2814
+ }
2815
+ function configureCliRuntime(options) {
2816
+ runtimeState.binaryName = options.binaryName;
2817
+ runtimeState.profile = options.profile;
2818
+ }
2819
+ function shouldEnableLocalServer(profile = runtimeState.profile) {
2820
+ return getProfileConfig(profile).enableLocalServer;
2821
+ }
2822
+ function getAllowedBuiltinCommands(profile = runtimeState.profile) {
2823
+ return getProfileConfig(profile).allowedBuiltinCommands;
2824
+ }
2825
+
2826
+ // src/common/actions/native-command.ts
2827
+ async function runNativeCommandAction(options) {
2828
+ const status = createSessionActionStatus("\uB124\uC774\uD2F0\uBE0C \uBA85\uB839");
2829
+ status.step("1/4 \uC11C\uBE44\uC2A4 \uB124\uC774\uD2F0\uBE0C \uBA85\uB839 \uC2E4\uD589\uC744 \uC900\uBE44\uD558\uB294 \uC911\uC785\uB2C8\uB2E4.");
2830
+ const workspaceBefore = captureWorkspaceSnapshot(options.paths.rootDir);
2831
+ const historyContext = loadRecentHistoryContext(options.paths);
2832
+ status.step("2/4 \uC120\uD0DD\uB41C \uC11C\uBE44\uC2A4 CLI\uB85C \uC6D0\uBCF8 slash command\uB97C \uC804\uB2EC\uD558\uB294 \uC911\uC785\uB2C8\uB2E4.");
2833
+ const result = await runAIServiceWithStatus({
2834
+ loadingMessage: `3/4 ${options.service} \uB124\uC774\uD2F0\uBE0C \uBA85\uB839 \uC751\uB2F5\uC744 \uAE30\uB2E4\uB9AC\uB294 \uC911\uC785\uB2C8\uB2E4`,
2835
+ mode: "native-command",
2836
+ parsedArgs: options.parsedArgs,
2837
+ paths: options.paths,
2838
+ prompt: options.rawCommand,
2839
+ service: options.service,
2840
+ status,
2841
+ streamingMessage: `3/4 ${options.service} \uB124\uC774\uD2F0\uBE0C \uBA85\uB839 \uC2E4\uC2DC\uAC04 \uC751\uB2F5\uC744 \uCD9C\uB825\uD558\uB294 \uC911\uC785\uB2C8\uB2E4. ESC \uCDE8\uC18C, Ctrl+C \uC138\uC158 \uC885\uB8CC`,
2842
+ trace: options.trace
2843
+ });
2844
+ if (result.blocked) {
2845
+ status.step("4/4 \uBCF4\uC548 \uC815\uCC45\uC73C\uB85C \uC778\uD574 \uB124\uC774\uD2F0\uBE0C \uBA85\uB839 \uC2E4\uD589\uC744 \uC911\uB2E8\uD588\uC2B5\uB2C8\uB2E4.");
2846
+ return void 0;
2847
+ }
2848
+ status.step("4/4 \uC751\uB2F5\uACFC \uC791\uC5C5 \uC774\uB825\uC744 \uC800\uC7A5\uD558\uB294 \uC911\uC785\uB2C8\uB2E4.");
2849
+ const workspaceAfter = captureWorkspaceSnapshot(options.paths.rootDir);
2850
+ const workspaceDelta = diffWorkspaceSnapshots(workspaceBefore, workspaceAfter);
2851
+ const output = result.stdout || result.stderr || "(\uC751\uB2F5 \uC5C6\uC74C)";
2852
+ const historyPath = writeTurnHistory(options.paths, {
2853
+ extraSections: [
2854
+ {
2855
+ heading: "\uC11C\uBE44\uC2A4 \uB124\uC774\uD2F0\uBE0C \uBA85\uB839",
2856
+ markdown: [`- \uC0AC\uC6A9\uC790 \uC785\uB825: \`${options.input}\``, `- \uC2E4\uC81C \uC804\uB2EC \uBA85\uB839: \`${options.rawCommand}\``].join("\n")
2857
+ }
2858
+ ],
2859
+ historyContext,
2860
+ input: options.input,
2861
+ output,
2862
+ previewCommand: result.preview,
2863
+ scope: "native-command",
2864
+ service: options.service,
2865
+ skipped: result.skipped,
2866
+ title: `\uB124\uC774\uD2F0\uBE0C \uBA85\uB839: ${safeExcerpt(options.rawCommand, 80)}`,
2867
+ workspaceAfter,
2868
+ workspaceBefore,
2869
+ workspaceDelta
2870
+ });
2871
+ appendConversationHistory(options.paths, {
2872
+ input: options.input,
2873
+ output,
2874
+ scope: "native-command",
2875
+ service: options.service,
2876
+ summary: `\uC11C\uBE44\uC2A4 \uB124\uC774\uD2F0\uBE0C \uBA85\uB839 \uC2E4\uD589: ${safeExcerpt(options.rawCommand, 60)}`,
2877
+ title: `\uB124\uC774\uD2F0\uBE0C \uBA85\uB839: ${safeExcerpt(options.rawCommand, 80)}`
2878
+ });
2879
+ printBufferedAIOutput(output, result);
2880
+ return {
2881
+ historyPath,
2882
+ previewCommand: result.preview,
2883
+ scope: "native-command",
2884
+ service: options.service,
2885
+ skipped: result.skipped,
2886
+ summary: `\uC11C\uBE44\uC2A4 \uB124\uC774\uD2F0\uBE0C \uBA85\uB839 \uC2E4\uD589: ${safeExcerpt(options.rawCommand, 60)}`,
2887
+ title: "\uB124\uC774\uD2F0\uBE0C \uBA85\uB839",
2888
+ traceMessages: []
2889
+ };
2890
+ }
2891
+
2892
+ // src/common/command-runtime/registry.ts
2893
+ var registryState = globalThis.__JU_HONG_E_COMMAND_REGISTRY__ ?? (globalThis.__JU_HONG_E_COMMAND_REGISTRY__ = {
2894
+ juHongECommands: /* @__PURE__ */ new Map(),
2895
+ nativeCommands: /* @__PURE__ */ new Map()
2896
+ });
2897
+ var JU_HONG_E_COMMANDS = registryState.juHongECommands;
2898
+ var NATIVE_COMMANDS = registryState.nativeCommands;
2899
+ function sortByOrder(commands) {
2900
+ return [...commands].sort((left, right) => {
2901
+ const leftOrder = left.order ?? Number.MAX_SAFE_INTEGER;
2902
+ const rightOrder = right.order ?? Number.MAX_SAFE_INTEGER;
2903
+ if (leftOrder !== rightOrder) {
2904
+ return leftOrder - rightOrder;
2905
+ }
2906
+ return left.command.localeCompare(right.command);
2907
+ });
2908
+ }
2909
+ function toBuiltinSlashCommandOption(command) {
2910
+ return {
2911
+ command: command.command,
2912
+ description: command.description,
2913
+ insertValue: command.insertValue || command.command,
2914
+ matchKeywords: command.matchKeywords
2915
+ };
2916
+ }
2917
+ function toNativeSlashCommandOption(service, command) {
2918
+ const prefixedCommand = `[${service}] ${command.command}`;
2919
+ return {
2920
+ command: prefixedCommand,
2921
+ description: command.description,
2922
+ insertValue: prefixedCommand,
2923
+ matchKeywords: [command.command, prefixedCommand, ...command.matchKeywords || []]
2924
+ };
2925
+ }
2926
+ function resolveTelemetryStatusFromError(error) {
2927
+ if (isUserCancelledError(error)) {
2928
+ return "cancelled";
2929
+ }
2930
+ if (isUserTerminatedError(error)) {
2931
+ return "terminated";
2932
+ }
2933
+ return "error";
2934
+ }
2935
+ async function validateCommand(context, security) {
2936
+ const result = await guardSecurityPayload({
2937
+ config: security,
2938
+ paths: context.paths,
2939
+ payload: {
2940
+ args: context.args,
2941
+ command: context.command,
2942
+ input: context.input,
2943
+ rawArgs: context.rawArgs,
2944
+ rawCommand: context.rawCommand,
2945
+ requestedService: "requestedService" in context ? context.requestedService : void 0,
2946
+ service: context.service
2947
+ },
2948
+ reportScope: `security:${context.command}`,
2949
+ trace: context.trace,
2950
+ traceLabel: context.command
2951
+ });
2952
+ return result.ok;
2953
+ }
2954
+ function clearCommandRegistry() {
2955
+ JU_HONG_E_COMMANDS.clear();
2956
+ NATIVE_COMMANDS.clear();
2957
+ }
2958
+ function applyBuiltinCommandFilter(allowedCommands) {
2959
+ if (!allowedCommands) {
2960
+ return;
2961
+ }
2962
+ for (const commandName of [...JU_HONG_E_COMMANDS.keys()]) {
2963
+ if (!allowedCommands.has(commandName)) {
2964
+ JU_HONG_E_COMMANDS.delete(commandName);
2965
+ }
2966
+ }
2967
+ }
2968
+ function getBuiltinCommands() {
2969
+ return sortByOrder([...JU_HONG_E_COMMANDS.values()]);
2970
+ }
2971
+ function getBuiltinCommandNames() {
2972
+ return getBuiltinCommands().map((command) => command.command);
2973
+ }
2974
+ function getNativeCommands(service) {
2975
+ return sortByOrder([...NATIVE_COMMANDS.get(service)?.values() || []]);
2976
+ }
2977
+ function getBuiltinSlashCommands() {
2978
+ return getBuiltinCommands().map(toBuiltinSlashCommandOption);
2979
+ }
2980
+ function getSessionCommandCatalog(service) {
2981
+ const builtinCommands = getBuiltinCommands();
2982
+ const nativeCommands = getNativeCommands(service);
2983
+ return {
2984
+ builtinCommands,
2985
+ nativeCommands,
2986
+ slashCommands: [...builtinCommands.map(toBuiltinSlashCommandOption), ...nativeCommands.map((command) => toNativeSlashCommandOption(service, command))]
2987
+ };
2988
+ }
2989
+ function findJuHongECommand(command) {
2990
+ return JU_HONG_E_COMMANDS.get(command);
2991
+ }
2992
+ function findNativeCommand(service, command) {
2993
+ return NATIVE_COMMANDS.get(service)?.get(command);
2994
+ }
2995
+ async function executeJuHongECommand(definition, context) {
2996
+ beginSlashCommandTelemetryInputCollection(context.args);
2997
+ const resolveTelemetryArgs = () => endSlashCommandTelemetryInputCollection();
2998
+ try {
2999
+ const canExecute = await validateCommand(context, definition.security);
3000
+ if (!canExecute) {
3001
+ trackSlashCommandExecution({
3002
+ args: resolveTelemetryArgs(),
3003
+ command: context.command,
3004
+ kind: "builtin",
3005
+ rootDir: context.paths.rootDir,
3006
+ service: context.service,
3007
+ status: "blocked",
3008
+ trace: context.trace
3009
+ });
3010
+ return {};
3011
+ }
3012
+ const result = await definition.execute({
3013
+ ...context,
3014
+ definition
3015
+ });
3016
+ trackSlashCommandExecution({
3017
+ args: resolveTelemetryArgs(),
3018
+ command: context.command,
3019
+ kind: "builtin",
3020
+ rootDir: context.paths.rootDir,
3021
+ service: context.service,
3022
+ status: "success",
3023
+ trace: context.trace
3024
+ });
3025
+ return result;
3026
+ } catch (error) {
3027
+ trackSlashCommandExecution({
3028
+ args: resolveTelemetryArgs(),
3029
+ command: context.command,
3030
+ kind: "builtin",
3031
+ rootDir: context.paths.rootDir,
3032
+ service: context.service,
3033
+ status: resolveTelemetryStatusFromError(error),
3034
+ trace: context.trace
3035
+ });
3036
+ throw error;
3037
+ }
3038
+ }
3039
+ async function executeNativeCommand(definition, context) {
3040
+ beginSlashCommandTelemetryInputCollection(context.args);
3041
+ const resolveTelemetryArgs = () => endSlashCommandTelemetryInputCollection();
3042
+ try {
3043
+ const canExecute = await validateCommand(context, definition?.security);
3044
+ if (!canExecute) {
3045
+ trackSlashCommandExecution({
3046
+ args: resolveTelemetryArgs(),
3047
+ command: context.command,
3048
+ kind: "native",
3049
+ requestedService: context.requestedService,
3050
+ rootDir: context.paths.rootDir,
3051
+ service: context.service,
3052
+ status: "blocked",
3053
+ trace: context.trace
3054
+ });
3055
+ return {};
3056
+ }
3057
+ if (definition) {
3058
+ const result = await definition.execute(context);
3059
+ trackSlashCommandExecution({
3060
+ args: resolveTelemetryArgs(),
3061
+ command: context.command,
3062
+ kind: "native",
3063
+ requestedService: context.requestedService,
3064
+ rootDir: context.paths.rootDir,
3065
+ service: context.service,
3066
+ status: "success",
3067
+ trace: context.trace
3068
+ });
3069
+ return result;
3070
+ }
3071
+ const record = await runNativeCommandAction({
3072
+ input: context.input,
3073
+ parsedArgs: context.parsedArgs,
3074
+ paths: context.paths,
3075
+ rawCommand: context.rawCommand,
3076
+ service: context.service,
3077
+ trace: context.trace
3078
+ });
3079
+ trackSlashCommandExecution({
3080
+ args: resolveTelemetryArgs(),
3081
+ command: context.command,
3082
+ kind: "native",
3083
+ requestedService: context.requestedService,
3084
+ rootDir: context.paths.rootDir,
3085
+ service: context.service,
3086
+ status: "success",
3087
+ trace: context.trace
3088
+ });
3089
+ return {
3090
+ record
3091
+ };
3092
+ } catch (error) {
3093
+ trackSlashCommandExecution({
3094
+ args: resolveTelemetryArgs(),
3095
+ command: context.command,
3096
+ kind: "native",
3097
+ requestedService: context.requestedService,
3098
+ rootDir: context.paths.rootDir,
3099
+ service: context.service,
3100
+ status: resolveTelemetryStatusFromError(error),
3101
+ trace: context.trace
3102
+ });
3103
+ throw error;
3104
+ }
3105
+ }
3106
+
3107
+ // src/common/command-runtime/loader.ts
3108
+ var loadPromise;
3109
+ async function collectCommandModulePaths(directoryPath) {
3110
+ const entries = await fs2__default.default.readdir(directoryPath, { withFileTypes: true });
3111
+ const modulePaths = [];
3112
+ for (const entry of entries) {
3113
+ const nextPath = path6__default.default.join(directoryPath, entry.name);
3114
+ if (entry.isDirectory()) {
3115
+ modulePaths.push(...await collectCommandModulePaths(nextPath));
3116
+ continue;
3117
+ }
3118
+ if (entry.isFile() && entry.name === "index.js") {
3119
+ modulePaths.push(nextPath);
3120
+ }
3121
+ }
3122
+ return modulePaths;
3123
+ }
3124
+ async function isCommandModuleRootDirectory(directoryPath) {
3125
+ try {
3126
+ const entries = await fs2__default.default.readdir(directoryPath, { withFileTypes: true });
3127
+ const directoryNames = new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
3128
+ return directoryNames.has("ju-hong-e") || directoryNames.has("native");
3129
+ } catch {
3130
+ return false;
3131
+ }
3132
+ }
3133
+ async function resolveCommandModuleRootDirectoryPath() {
3134
+ let currentDirectoryPath = path6__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('be.cjs', document.baseURI).href))));
3135
+ for (let depth = 0; depth < 8; depth += 1) {
3136
+ const candidatePath = path6__default.default.join(currentDirectoryPath, "command-modules");
3137
+ if (await isCommandModuleRootDirectory(candidatePath)) {
3138
+ return candidatePath;
3139
+ }
3140
+ const parentDirectoryPath = path6__default.default.dirname(currentDirectoryPath);
3141
+ if (parentDirectoryPath === currentDirectoryPath) {
3142
+ break;
3143
+ }
3144
+ currentDirectoryPath = parentDirectoryPath;
3145
+ }
3146
+ throw new Error(`command-modules \uB8E8\uD2B8\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. start=${url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('be.cjs', document.baseURI).href)))}`);
3147
+ }
3148
+ async function loadCommandModulesInternal() {
3149
+ clearCommandRegistry();
3150
+ const commandModuleRootDirectoryPath = await resolveCommandModuleRootDirectoryPath();
3151
+ const modulePaths = (await collectCommandModulePaths(commandModuleRootDirectoryPath)).sort(
3152
+ (left, right) => left.localeCompare(right)
3153
+ );
3154
+ for (const modulePath of modulePaths) {
3155
+ await import(url.pathToFileURL(modulePath).href);
3156
+ }
3157
+ applyBuiltinCommandFilter(getAllowedBuiltinCommands());
3158
+ }
3159
+ async function loadCommandModules() {
3160
+ if (!loadPromise) {
3161
+ loadPromise = loadCommandModulesInternal();
3162
+ }
3163
+ return loadPromise;
3164
+ }
3165
+
3166
+ // src/common/command-runtime/parser.ts
3167
+ var SERVICE_PREFIX_PATTERN = /^\[(codex|gemini|claude)\]\s+(\/\S+)(?:\s+(.*))?$/i;
3168
+ function splitCommandParts(commandLine) {
3169
+ const trimmed = commandLine.trim();
3170
+ if (!trimmed.startsWith("/")) {
3171
+ return void 0;
3172
+ }
3173
+ const [command = "", ...args] = trimmed.split(/\s+/);
3174
+ const rawArgs = trimmed.slice(command.length).trim();
3175
+ return {
3176
+ args,
3177
+ command,
3178
+ rawArgs,
3179
+ rawCommand: trimmed
3180
+ };
3181
+ }
3182
+ function resolveSlashCommandInput(input, builtinCommands) {
3183
+ const trimmed = input.trim();
3184
+ if (!trimmed) {
3185
+ return void 0;
3186
+ }
3187
+ const prefixedMatch = trimmed.match(SERVICE_PREFIX_PATTERN);
3188
+ if (prefixedMatch) {
3189
+ const [, requestedService = "", command = "", rawArgs = ""] = prefixedMatch;
3190
+ const normalized2 = splitCommandParts([command, rawArgs].filter(Boolean).join(" "));
3191
+ if (!normalized2) {
3192
+ return void 0;
3193
+ }
3194
+ return {
3195
+ ...normalized2,
3196
+ kind: "native",
3197
+ prefixed: true,
3198
+ requestedService: requestedService.toLowerCase()
3199
+ };
3200
+ }
3201
+ const normalized = splitCommandParts(trimmed);
3202
+ if (!normalized) {
3203
+ return void 0;
3204
+ }
3205
+ if (builtinCommands.includes(normalized.command)) {
3206
+ return {
3207
+ ...normalized,
3208
+ kind: "builtin"
3209
+ };
3210
+ }
3211
+ return {
3212
+ ...normalized,
3213
+ kind: "native",
3214
+ prefixed: false
3215
+ };
3216
+ }
3217
+ var STORY_FILE_PATTERN = /\.stories\.[cm]?[jt]sx?$/i;
3218
+ function normalizeOutputRelativePath(outputDirectory, filePath) {
3219
+ return path6__default.default.relative(outputDirectory, filePath).split(path6__default.default.sep).join("/");
3220
+ }
3221
+ function listOutputFiles(outputDirectory) {
3222
+ if (!fs7__default.default.existsSync(outputDirectory) || !fs7__default.default.statSync(outputDirectory).isDirectory()) {
3223
+ return [];
3224
+ }
3225
+ const files = [];
3226
+ const visitDirectory = (directoryPath) => {
3227
+ const entries = fs7__default.default.readdirSync(directoryPath, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
3228
+ for (const entry of entries) {
3229
+ const entryPath = path6__default.default.join(directoryPath, entry.name);
3230
+ if (entry.isDirectory()) {
3231
+ visitDirectory(entryPath);
3232
+ continue;
3233
+ }
3234
+ if (entry.isFile()) {
3235
+ files.push(normalizeOutputRelativePath(outputDirectory, entryPath));
3236
+ }
3237
+ }
3238
+ };
3239
+ visitDirectory(outputDirectory);
3240
+ return files.sort((left, right) => left.localeCompare(right));
3241
+ }
3242
+ function isGenHtmlPreviewDirectoryCandidate(outputDirectory) {
3243
+ return listOutputFiles(outputDirectory).some((filePath) => STORY_FILE_PATTERN.test(filePath));
3244
+ }
3245
+
3246
+ // src/common/local-server/index.ts
3247
+ var LOCAL_SERVER_NPM_VIEW_TIMEOUT_MS = 1e4;
3248
+ var LOCAL_SERVER_SASS_VERSION = "^1.86.3";
3249
+ var STORYBOOK_VERSION = "8.6.14";
3250
+ var LOCAL_SERVER_LEGACY_FILE_NAMES = ["server.mjs"];
3251
+ var LOCAL_SERVER_STYLE_EXPORT_FILE_PATTERN = /\.(?:css|s[ac]ss)$/i;
3252
+ var REQUIRED_LOCAL_SERVER_PUBLISHED_DEPENDENCIES = {
3253
+ "sales-frontend-assets": "0.0.22",
3254
+ "sales-frontend-components": "1.0.7",
3255
+ "sales-frontend-design-system": "0.1.5"
3256
+ };
3257
+ var WORKSPACE_PACKAGE_GROUP_NAMES = ["apps", "packages"];
3258
+ var WORKSPACE_ROOT_MARKER_FILE_NAMES = ["pnpm-workspace.yaml", "pnpm-workspace.yml"];
3259
+ var LOCAL_SERVER_RUNTIME_PACKAGE_NAMES = ["react", "react-dom"];
3260
+ new Set(
3261
+ module$1.builtinModules.flatMap((moduleName) => [moduleName, moduleName.replace(/^node:/, ""), `node:${moduleName.replace(/^node:/, "")}`])
3262
+ );
3263
+ var LOCAL_SERVER_DEFAULT_PACKAGE_JSON = {
3264
+ dependencies: {
3265
+ "@storybook/addon-essentials": STORYBOOK_VERSION,
3266
+ "@storybook/react": STORYBOOK_VERSION,
3267
+ "@storybook/react-vite": STORYBOOK_VERSION,
3268
+ react: "^19.1.0",
3269
+ "react-dom": "^19.1.0",
3270
+ sass: LOCAL_SERVER_SASS_VERSION,
3271
+ storybook: STORYBOOK_VERSION
3272
+ },
3273
+ name: "ju-hong-e-local-server",
3274
+ private: true,
3275
+ scripts: {
3276
+ dev: "storybook dev -c ./.storybook",
3277
+ start: "storybook dev -c ./.storybook"
3278
+ },
3279
+ type: "commonjs"
3280
+ };
3281
+ function getLocalServerPaths(paths) {
3282
+ const directoryPath = path6__default.default.join(paths.baseDir, "local-server");
3283
+ const storybookConfigDirectoryPath = path6__default.default.join(directoryPath, ".storybook");
3284
+ return {
3285
+ directoryPath,
3286
+ logPath: path6__default.default.join(directoryPath, "server.log"),
3287
+ packageJsonPath: path6__default.default.join(directoryPath, "package.json"),
3288
+ previewTargetPath: path6__default.default.join(directoryPath, "preview-target.json"),
3289
+ statePath: path6__default.default.join(directoryPath, "server-state.json"),
3290
+ storybookConfigDirectoryPath,
3291
+ storybookMainConfigPath: path6__default.default.join(storybookConfigDirectoryPath, "main.ts"),
3292
+ storybookPreviewConfigPath: path6__default.default.join(storybookConfigDirectoryPath, "preview.ts")
3293
+ };
3294
+ }
3295
+ function isRecord(value) {
3296
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3297
+ }
3298
+ function normalizeDependencies(value) {
3299
+ if (!isRecord(value)) {
3300
+ return {};
3301
+ }
3302
+ return Object.entries(value).reduce((accumulator, [key, dependencyValue]) => {
3303
+ if (typeof dependencyValue === "string" && dependencyValue.trim()) {
3304
+ accumulator[key] = dependencyValue;
3305
+ }
3306
+ return accumulator;
3307
+ }, {});
3308
+ }
3309
+ function mergeLocalServerPackageJson(value, extraDependencies = {}) {
3310
+ const current = isRecord(value) ? value : {};
3311
+ const dependencies = normalizeDependencies(current.dependencies);
3312
+ const scripts = normalizeDependencies(current.scripts);
3313
+ return {
3314
+ ...current,
3315
+ dependencies: {
3316
+ ...LOCAL_SERVER_DEFAULT_PACKAGE_JSON.dependencies,
3317
+ ...extraDependencies,
3318
+ ...dependencies
3319
+ },
3320
+ name: typeof current.name === "string" && current.name.trim() ? current.name : LOCAL_SERVER_DEFAULT_PACKAGE_JSON.name,
3321
+ private: typeof current.private === "boolean" ? current.private : LOCAL_SERVER_DEFAULT_PACKAGE_JSON.private,
3322
+ scripts: {
3323
+ ...scripts,
3324
+ ...LOCAL_SERVER_DEFAULT_PACKAGE_JSON.scripts
3325
+ },
3326
+ type: LOCAL_SERVER_DEFAULT_PACKAGE_JSON.type
3327
+ };
3328
+ }
3329
+ function normalizePublishedPackageVersion(value) {
3330
+ if (typeof value === "string" && value.trim()) {
3331
+ return value.trim();
3332
+ }
3333
+ if (Array.isArray(value)) {
3334
+ return value.find((entry) => typeof entry === "string" && entry.trim().length > 0)?.trim() || "";
3335
+ }
3336
+ return "";
3337
+ }
3338
+ function fetchLatestPublishedPackageVersion(packageName, trace) {
3339
+ const result = child_process.spawnSync("npm", ["view", packageName, "version", "--json"], {
3340
+ encoding: "utf8",
3341
+ maxBuffer: 1024 * 1024,
3342
+ stdio: ["ignore", "pipe", "pipe"],
3343
+ timeout: LOCAL_SERVER_NPM_VIEW_TIMEOUT_MS
3344
+ });
3345
+ if (result.error || result.status !== 0) {
3346
+ trace("local-server:setup:published-version:failed", `${packageName} ${getErrorSummary(result.error || result.stderr || result.status)}`);
3347
+ return "";
3348
+ }
3349
+ try {
3350
+ const parsed = JSON.parse(result.stdout || '""');
3351
+ const normalizedVersion = normalizePublishedPackageVersion(parsed);
3352
+ if (normalizedVersion) {
3353
+ trace("local-server:setup:published-version:resolved", `${packageName}@${normalizedVersion}`);
3354
+ }
3355
+ return normalizedVersion;
3356
+ } catch (error) {
3357
+ trace("local-server:setup:published-version:parse-failed", `${packageName} ${getErrorSummary(error)}`);
3358
+ return "";
3359
+ }
3360
+ }
3361
+ function resolveRequiredLocalServerPublishedDependencies(paths, trace, options = {}) {
3362
+ const packageJsonPaths = collectWorkspacePackageJsonPaths(paths.rootDir);
3363
+ const workspaceVersions = /* @__PURE__ */ new Map();
3364
+ for (const packageJsonPath of packageJsonPaths) {
3365
+ const manifest = readJsonFile(packageJsonPath);
3366
+ const packageName = typeof manifest?.name === "string" ? manifest.name.trim() : "";
3367
+ const packageVersion = typeof manifest?.version === "string" ? manifest.version.trim() : "";
3368
+ if (!packageName || !packageVersion) {
3369
+ continue;
3370
+ }
3371
+ workspaceVersions.set(packageName, packageVersion);
3372
+ }
3373
+ const resolvedDependencies = {};
3374
+ const unresolvedDependencyNames = [];
3375
+ for (const [dependencyName, fallbackVersion] of Object.entries(REQUIRED_LOCAL_SERVER_PUBLISHED_DEPENDENCIES)) {
3376
+ const latestVersion = options.refreshPublishedDependencies ? fetchLatestPublishedPackageVersion(dependencyName, trace) : "";
3377
+ const resolvedVersion = latestVersion || workspaceVersions.get(dependencyName) || fallbackVersion;
3378
+ if (!resolvedVersion) {
3379
+ unresolvedDependencyNames.push(dependencyName);
3380
+ continue;
3381
+ }
3382
+ resolvedDependencies[dependencyName] = resolvedVersion;
3383
+ }
3384
+ if (Object.keys(resolvedDependencies).length > 0) {
3385
+ trace(
3386
+ "local-server:setup:required-published-dependencies",
3387
+ Object.entries(resolvedDependencies).map(([dependencyName, version]) => `${dependencyName}@${version}`).join(", ")
3388
+ );
3389
+ }
3390
+ if (unresolvedDependencyNames.length > 0) {
3391
+ trace("local-server:setup:missing-required-workspace-dependencies", unresolvedDependencyNames.join(", "));
3392
+ }
3393
+ return resolvedDependencies;
3394
+ }
3395
+ function readJsonFile(filePath) {
3396
+ if (!fs7__default.default.existsSync(filePath)) {
3397
+ return void 0;
3398
+ }
3399
+ const raw = fs7__default.default.readFileSync(filePath, "utf8").trim();
3400
+ if (!raw) {
3401
+ return void 0;
3402
+ }
3403
+ return JSON.parse(raw);
3404
+ }
3405
+ function writeJsonFile(filePath, value) {
3406
+ fs7__default.default.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
3407
+ `, "utf8");
3408
+ }
3409
+ function resolveLocalServerStyleExportTarget(value) {
3410
+ if (typeof value === "string") {
3411
+ return LOCAL_SERVER_STYLE_EXPORT_FILE_PATTERN.test(value) ? value : "";
3412
+ }
3413
+ if (Array.isArray(value)) {
3414
+ for (const entry of value) {
3415
+ const resolvedTarget = resolveLocalServerStyleExportTarget(entry);
3416
+ if (resolvedTarget) {
3417
+ return resolvedTarget;
3418
+ }
3419
+ }
3420
+ return "";
3421
+ }
3422
+ if (isRecord(value)) {
3423
+ return resolveLocalServerStyleExportTarget(value.default) || resolveLocalServerStyleExportTarget(value.import) || resolveLocalServerStyleExportTarget(value.require);
3424
+ }
3425
+ return "";
3426
+ }
3427
+ function buildLocalServerStyleExportBridgeContent(bridgeFilePath, targetFilePath) {
3428
+ const relativeTargetPath = path6__default.default.relative(path6__default.default.dirname(bridgeFilePath), targetFilePath).split(path6__default.default.sep).join("/");
3429
+ const normalizedTargetPath = relativeTargetPath.startsWith(".") ? relativeTargetPath : `./${relativeTargetPath}`;
3430
+ if (path6__default.default.extname(targetFilePath).toLowerCase() === ".css") {
3431
+ return `@import '${normalizedTargetPath}';
3432
+ `;
3433
+ }
3434
+ return `@forward '${normalizedTargetPath}';
3435
+ `;
3436
+ }
3437
+ function synchronizeLocalServerStyleExportBridges(paths, trace) {
3438
+ const { directoryPath, packageJsonPath } = getLocalServerPaths(paths);
3439
+ const localServerPackageJson = readJsonFile(packageJsonPath);
3440
+ const dependencyNames = Object.keys(normalizeDependencies(localServerPackageJson?.dependencies));
3441
+ for (const dependencyName of dependencyNames) {
3442
+ const dependencyDirectoryPath = path6__default.default.join(directoryPath, "node_modules", ...dependencyName.split("/"));
3443
+ const dependencyPackageJsonPath = path6__default.default.join(dependencyDirectoryPath, "package.json");
3444
+ const dependencyPackageJson = readJsonFile(dependencyPackageJsonPath);
3445
+ const dependencyExports = isRecord(dependencyPackageJson?.exports) ? dependencyPackageJson.exports : {};
3446
+ for (const [exportKey, exportValue] of Object.entries(dependencyExports)) {
3447
+ if (!exportKey.startsWith("./")) {
3448
+ continue;
3449
+ }
3450
+ const exportTargetPath = resolveLocalServerStyleExportTarget(exportValue);
3451
+ if (!exportTargetPath) {
3452
+ continue;
3453
+ }
3454
+ const exportSubpath = exportKey.slice(2);
3455
+ if (!exportSubpath) {
3456
+ continue;
3457
+ }
3458
+ const targetFilePath = path6__default.default.resolve(dependencyDirectoryPath, exportTargetPath);
3459
+ if (!fs7__default.default.existsSync(targetFilePath) || !fs7__default.default.statSync(targetFilePath).isFile()) {
3460
+ trace("local-server:style-export-bridge:missing-target", `${dependencyName} ${exportKey} -> ${targetFilePath}`);
3461
+ continue;
3462
+ }
3463
+ const bridgeFilePath = path6__default.default.join(
3464
+ dependencyDirectoryPath,
3465
+ ...exportSubpath.split("/").filter(Boolean)
3466
+ ) + path6__default.default.extname(targetFilePath);
3467
+ const bridgeContent = buildLocalServerStyleExportBridgeContent(bridgeFilePath, targetFilePath);
3468
+ const currentBridgeContent = fs7__default.default.existsSync(bridgeFilePath) ? fs7__default.default.readFileSync(bridgeFilePath, "utf8") : "";
3469
+ if (currentBridgeContent === bridgeContent) {
3470
+ continue;
3471
+ }
3472
+ fs7__default.default.mkdirSync(path6__default.default.dirname(bridgeFilePath), { recursive: true });
3473
+ fs7__default.default.writeFileSync(bridgeFilePath, bridgeContent, "utf8");
3474
+ trace("local-server:style-export-bridge:written", `${dependencyName} ${exportKey} -> ${bridgeFilePath}`);
3475
+ }
3476
+ }
3477
+ }
3478
+ function normalizePreviewTargetDirectory(directoryPath) {
3479
+ if (typeof directoryPath !== "string" || !directoryPath.trim()) {
3480
+ return void 0;
3481
+ }
3482
+ return path6__default.default.resolve(directoryPath);
3483
+ }
3484
+ function normalizePreviewTargetDirectories(directoryPaths) {
3485
+ if (!Array.isArray(directoryPaths)) {
3486
+ return [];
3487
+ }
3488
+ return Array.from(
3489
+ new Set(
3490
+ directoryPaths.map((directoryPath) => normalizePreviewTargetDirectory(directoryPath)).filter((directoryPath) => Boolean(directoryPath))
3491
+ )
3492
+ ).sort((left, right) => left.localeCompare(right));
3493
+ }
3494
+ function toLocalServerPreviewMode(target) {
3495
+ return target.mode === "directory" ? "latest" : "all";
3496
+ }
3497
+ function buildPreviewTargetConfig(options = {}) {
3498
+ const resolvedOutputDirectory = normalizePreviewTargetDirectory(options.outputDirectory);
3499
+ const resolvedPreviousDirectory = normalizePreviewTargetDirectory(options.previousTarget?.directory);
3500
+ const resolvedDirectories = normalizePreviewTargetDirectories(options.directories ?? options.previousTarget?.directories);
3501
+ const targetDirectory = resolvedOutputDirectory || resolvedPreviousDirectory;
3502
+ const targetMode = options.mode || toLocalServerPreviewMode(options.previousTarget || { mode: "all" });
3503
+ if (targetMode === "all") {
3504
+ return targetDirectory || resolvedDirectories.length > 0 ? {
3505
+ ...targetDirectory ? { directory: targetDirectory } : {},
3506
+ ...resolvedDirectories.length > 0 ? { directories: resolvedDirectories } : {},
3507
+ mode: "all"
3508
+ } : { mode: "all" };
3509
+ }
3510
+ if (!targetDirectory) {
3511
+ return { mode: "all" };
3512
+ }
3513
+ return {
3514
+ directory: targetDirectory,
3515
+ mode: "directory"
3516
+ };
3517
+ }
3518
+ function readPreviewTargetConfig(filePath) {
3519
+ const parsed = readJsonFile(filePath);
3520
+ const normalizedDirectory = normalizePreviewTargetDirectory(parsed?.directory);
3521
+ const normalizedDirectories = normalizePreviewTargetDirectories(parsed?.directories);
3522
+ if (parsed?.mode === "directory" && normalizedDirectory) {
3523
+ return {
3524
+ directory: normalizedDirectory,
3525
+ mode: "directory"
3526
+ };
3527
+ }
3528
+ if (parsed?.mode === "all") {
3529
+ return normalizedDirectory ? {
3530
+ directory: normalizedDirectory,
3531
+ ...normalizedDirectories.length > 0 ? { directories: normalizedDirectories } : {},
3532
+ mode: "all"
3533
+ } : normalizedDirectories.length > 0 ? {
3534
+ directories: normalizedDirectories,
3535
+ mode: "all"
3536
+ } : { mode: "all" };
3537
+ }
3538
+ return { mode: "all" };
3539
+ }
3540
+ function listGeneratedOutputDirectories(paths) {
3541
+ const generatedRootPath = path6__default.default.join(paths.baseDir, "generated");
3542
+ if (!fs7__default.default.existsSync(generatedRootPath) || !fs7__default.default.statSync(generatedRootPath).isDirectory()) {
3543
+ return [];
3544
+ }
3545
+ return fs7__default.default.readdirSync(generatedRootPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path6__default.default.join(generatedRootPath, entry.name)).sort((left, right) => left.localeCompare(right));
3546
+ }
3547
+ function resolveValidGeneratedPreviewDirectories(paths) {
3548
+ return listGeneratedOutputDirectories(paths).filter((directoryPath) => isGenHtmlPreviewDirectoryCandidate(directoryPath));
3549
+ }
3550
+ function selectPreviewTargetDirectory(preferredDirectory, validDirectories) {
3551
+ if (preferredDirectory && validDirectories.includes(preferredDirectory)) {
3552
+ return preferredDirectory;
3553
+ }
3554
+ return validDirectories.length > 0 ? validDirectories[validDirectories.length - 1] : void 0;
3555
+ }
3556
+ function setLocalServerPreviewTarget(paths, options = {}) {
3557
+ const localServerPaths = getLocalServerPaths(paths);
3558
+ const currentTarget = fs7__default.default.existsSync(localServerPaths.previewTargetPath) ? readPreviewTargetConfig(localServerPaths.previewTargetPath) : buildPreviewTargetConfig();
3559
+ const resolvedMode = options.mode || toLocalServerPreviewMode(currentTarget);
3560
+ const validDirectories = resolvedMode === "all" ? resolveValidGeneratedPreviewDirectories(paths) : [];
3561
+ const resolvedOutputDirectory = normalizePreviewTargetDirectory(options.outputDirectory);
3562
+ const effectiveDirectory = resolvedMode === "all" ? selectPreviewTargetDirectory(resolvedOutputDirectory || currentTarget.directory, validDirectories) : resolvedOutputDirectory || currentTarget.directory;
3563
+ const nextTarget = buildPreviewTargetConfig({
3564
+ directories: validDirectories,
3565
+ mode: resolvedMode,
3566
+ outputDirectory: effectiveDirectory,
3567
+ previousTarget: currentTarget
3568
+ });
3569
+ writeJsonFile(localServerPaths.previewTargetPath, nextTarget);
3570
+ }
3571
+ function collectWorkspacePackageJsonPaths(rootDir) {
3572
+ const workspaceRootDir = resolveWorkspaceRootDirectory(rootDir);
3573
+ const packageJsonPaths = [path6__default.default.join(workspaceRootDir, "package.json")].filter((filePath) => fs7__default.default.existsSync(filePath));
3574
+ for (const groupName of WORKSPACE_PACKAGE_GROUP_NAMES) {
3575
+ const groupDirectoryPath = path6__default.default.join(workspaceRootDir, groupName);
3576
+ if (!fs7__default.default.existsSync(groupDirectoryPath) || !fs7__default.default.statSync(groupDirectoryPath).isDirectory()) {
3577
+ continue;
3578
+ }
3579
+ for (const entry of fs7__default.default.readdirSync(groupDirectoryPath, { withFileTypes: true })) {
3580
+ if (!entry.isDirectory()) {
3581
+ continue;
3582
+ }
3583
+ const packageJsonPath = path6__default.default.join(groupDirectoryPath, entry.name, "package.json");
3584
+ if (fs7__default.default.existsSync(packageJsonPath)) {
3585
+ packageJsonPaths.push(packageJsonPath);
3586
+ }
3587
+ }
3588
+ }
3589
+ return packageJsonPaths.sort((left, right) => left.localeCompare(right));
3590
+ }
3591
+ function isWorkspaceRootDirectory(directoryPath) {
3592
+ if (!directoryPath) {
3593
+ return false;
3594
+ }
3595
+ if (WORKSPACE_ROOT_MARKER_FILE_NAMES.some((fileName) => fs7__default.default.existsSync(path6__default.default.join(directoryPath, fileName)))) {
3596
+ return true;
3597
+ }
3598
+ const packageJsonPath = path6__default.default.join(directoryPath, "package.json");
3599
+ const manifest = readJsonFile(packageJsonPath);
3600
+ if (!isRecord(manifest)) {
3601
+ return false;
3602
+ }
3603
+ return Boolean(manifest.workspaces);
3604
+ }
3605
+ function resolveWorkspaceRootDirectory(startDirectory) {
3606
+ let currentDirectoryPath = path6__default.default.resolve(startDirectory);
3607
+ while (true) {
3608
+ if (isWorkspaceRootDirectory(currentDirectoryPath)) {
3609
+ return currentDirectoryPath;
3610
+ }
3611
+ const parentDirectoryPath = path6__default.default.dirname(currentDirectoryPath);
3612
+ if (parentDirectoryPath === currentDirectoryPath) {
3613
+ return path6__default.default.resolve(startDirectory);
3614
+ }
3615
+ currentDirectoryPath = parentDirectoryPath;
3616
+ }
3617
+ }
3618
+ function listAncestorDirectories(startDirectory) {
3619
+ const directories = [];
3620
+ let currentDirectoryPath = path6__default.default.resolve(startDirectory);
3621
+ while (true) {
3622
+ directories.push(currentDirectoryPath);
3623
+ const parentDirectoryPath = path6__default.default.dirname(currentDirectoryPath);
3624
+ if (parentDirectoryPath === currentDirectoryPath) {
3625
+ break;
3626
+ }
3627
+ currentDirectoryPath = parentDirectoryPath;
3628
+ }
3629
+ return directories;
3630
+ }
3631
+ function resolveInstalledPackageVersion(dependencyName, startDirectories) {
3632
+ const candidateDirectories = Array.from(
3633
+ new Set(
3634
+ startDirectories.flatMap((directoryPath) => {
3635
+ if (!directoryPath) {
3636
+ return [];
3637
+ }
3638
+ return listAncestorDirectories(directoryPath);
3639
+ })
3640
+ )
3641
+ );
3642
+ for (const directoryPath of candidateDirectories) {
3643
+ const packageJsonPath = path6__default.default.join(directoryPath, "node_modules", ...dependencyName.split("/"), "package.json");
3644
+ const manifest = readJsonFile(packageJsonPath);
3645
+ const version = typeof manifest?.version === "string" ? manifest.version.trim() : "";
3646
+ if (version) {
3647
+ return version;
3648
+ }
3649
+ }
3650
+ return "";
3651
+ }
3652
+ function resolvePreferredManifestDependencyEntry(manifest, dependencyName) {
3653
+ if (!isRecord(manifest)) {
3654
+ return void 0;
3655
+ }
3656
+ const dependencyFields = [
3657
+ { fieldName: "dependencies", priority: 1 },
3658
+ { fieldName: "devDependencies", priority: 2 },
3659
+ { fieldName: "optionalDependencies", priority: 3 },
3660
+ { fieldName: "peerDependencies", priority: 4 }
3661
+ ];
3662
+ for (const { fieldName, priority } of dependencyFields) {
3663
+ const dependencies = normalizeDependencies(manifest[fieldName]);
3664
+ const version = dependencies[dependencyName]?.trim();
3665
+ if (!version || version.startsWith("workspace:") || version.startsWith("file:")) {
3666
+ continue;
3667
+ }
3668
+ return {
3669
+ priority,
3670
+ version
3671
+ };
3672
+ }
3673
+ return void 0;
3674
+ }
3675
+ function resolvePreferredWorkspaceDependencyVersions(rootDir, dependencyNames) {
3676
+ const packageJsonPaths = collectWorkspacePackageJsonPaths(rootDir);
3677
+ const resolvedEntries = /* @__PURE__ */ new Map();
3678
+ for (const packageJsonPath of packageJsonPaths) {
3679
+ const manifest = readJsonFile(packageJsonPath);
3680
+ for (const dependencyName of dependencyNames) {
3681
+ const candidate = resolvePreferredManifestDependencyEntry(manifest, dependencyName);
3682
+ const current = resolvedEntries.get(dependencyName);
3683
+ if (!candidate) {
3684
+ continue;
3685
+ }
3686
+ if (!current || candidate.priority < current.priority) {
3687
+ resolvedEntries.set(dependencyName, candidate);
3688
+ }
3689
+ }
3690
+ }
3691
+ return Object.fromEntries(
3692
+ dependencyNames.map((dependencyName) => [dependencyName, resolvedEntries.get(dependencyName)?.version || ""]).filter(([, version]) => Boolean(version))
3693
+ );
3694
+ }
3695
+ function resolveLocalServerRuntimeDependencies(paths, localServerDirectoryPath, trace) {
3696
+ const dependencyNames = [...LOCAL_SERVER_RUNTIME_PACKAGE_NAMES];
3697
+ const workspaceResolved = resolvePreferredWorkspaceDependencyVersions(paths.rootDir, dependencyNames);
3698
+ const workspaceRootDir = resolveWorkspaceRootDirectory(paths.rootDir);
3699
+ const resolvedDependencies = dependencyNames.reduce((accumulator, dependencyName) => {
3700
+ const version = workspaceResolved[dependencyName] || resolveInstalledPackageVersion(dependencyName, [paths.rootDir, workspaceRootDir, localServerDirectoryPath]);
3701
+ if (version) {
3702
+ accumulator[dependencyName] = version;
3703
+ }
3704
+ return accumulator;
3705
+ }, {});
3706
+ if (Object.keys(resolvedDependencies).length > 0) {
3707
+ trace(
3708
+ "local-server:setup:runtime-dependencies",
3709
+ Object.entries(resolvedDependencies).map(([dependencyName, version]) => `${dependencyName}@${version}`).join(", ")
3710
+ );
3711
+ }
3712
+ return resolvedDependencies;
3713
+ }
3714
+ function installLocalServerDependencies(directoryPath, trace) {
3715
+ trace("local-server:install:start", directoryPath);
3716
+ const result = child_process.spawnSync("npm", ["install"], {
3717
+ cwd: directoryPath,
3718
+ encoding: "utf8",
3719
+ maxBuffer: 1024 * 1024 * 20,
3720
+ stdio: "inherit"
3721
+ });
3722
+ if (result.error || result.status !== 0) {
3723
+ trace("local-server:install:failed", getErrorSummary(result.error || result.stderr || result.status));
3724
+ throw new Error("\uB85C\uCEEC \uD504\uB9AC\uBDF0 \uC11C\uBC84 \uC758\uC874\uC131 \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
3725
+ }
3726
+ trace("local-server:install:done", directoryPath);
3727
+ }
3728
+ function hasAllLocalServerDependencies(directoryPath) {
3729
+ const packageJsonPath = path6__default.default.join(directoryPath, "package.json");
3730
+ const packageJson = readJsonFile(packageJsonPath);
3731
+ const dependencies = Object.keys(normalizeDependencies(packageJson?.dependencies));
3732
+ if (dependencies.length === 0) {
3733
+ return true;
3734
+ }
3735
+ return dependencies.every((dependencyName) => fs7__default.default.existsSync(path6__default.default.join(directoryPath, "node_modules", ...dependencyName.split("/"))));
3736
+ }
3737
+ function ensureLocalServerDependencies(paths, trace, forceInstall = false) {
3738
+ const { directoryPath } = getLocalServerPaths(paths);
3739
+ const nodeModulesPath = path6__default.default.join(directoryPath, "node_modules");
3740
+ const hasNodeModules = fs7__default.default.existsSync(nodeModulesPath);
3741
+ const hasRequiredDependencies = hasNodeModules ? hasAllLocalServerDependencies(directoryPath) : false;
3742
+ const shouldInstall = forceInstall || !hasNodeModules || !hasRequiredDependencies;
3743
+ if (hasNodeModules && !hasRequiredDependencies) {
3744
+ trace("local-server:install:repair", directoryPath);
3745
+ }
3746
+ if (shouldInstall) {
3747
+ installLocalServerDependencies(directoryPath, trace);
3748
+ }
3749
+ synchronizeLocalServerStyleExportBridges(paths, trace);
3750
+ }
3751
+ function toSortedDependencies(dependencies) {
3752
+ return Object.fromEntries(Object.entries(dependencies).sort(([left], [right]) => left.localeCompare(right)));
3753
+ }
3754
+ function getStorybookMainConfigContent() {
3755
+ return `import fs from 'node:fs';
3756
+ import path from 'node:path';
3757
+ import type { StorybookConfig } from '@storybook/react-vite';
3758
+ import type { Alias, Plugin } from 'vite';
3759
+
3760
+ const localServerRoot = path.resolve(__dirname, '..');
3761
+ const localServerPackageJsonPath = path.resolve(localServerRoot, 'package.json');
3762
+ const previewTargetPath = path.resolve(__dirname, '../preview-target.json');
3763
+ const workspaceRoot = path.resolve(__dirname, '..', '..');
3764
+ const generatedFileEndpointPath = '/__ju_hong_e__/generated-file';
3765
+ const dependencyAliasExcludeNames = new Set(['react', 'react-dom', 'sass', 'storybook']);
3766
+ const dependencyAliasExcludePrefixes = ['@storybook/'];
3767
+
3768
+ function toPosix(value: string) {
3769
+ return value.split(path.sep).join('/');
3770
+ }
3771
+
3772
+ function readLocalServerDependencies() {
3773
+ try {
3774
+ const raw = fs.readFileSync(localServerPackageJsonPath, 'utf8').trim();
3775
+
3776
+ if (!raw) {
3777
+ return {};
3778
+ }
3779
+
3780
+ const parsed = JSON.parse(raw) as { dependencies?: Record<string, string> };
3781
+
3782
+ return parsed.dependencies && typeof parsed.dependencies === 'object' ? parsed.dependencies : {};
3783
+ } catch {
3784
+ return {};
3785
+ }
3786
+ }
3787
+
3788
+ function isRecord(value: unknown): value is Record<string, unknown> {
3789
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
3790
+ }
3791
+
3792
+ function resolveExportTarget(value: unknown): string {
3793
+ if (typeof value === 'string' && value.trim()) {
3794
+ return value.trim();
3795
+ }
3796
+
3797
+ if (Array.isArray(value)) {
3798
+ for (const entry of value) {
3799
+ const resolvedTarget = resolveExportTarget(entry);
3800
+
3801
+ if (resolvedTarget) {
3802
+ return resolvedTarget;
3803
+ }
3804
+ }
3805
+
3806
+ return '';
3807
+ }
3808
+
3809
+ if (isRecord(value)) {
3810
+ return resolveExportTarget(value.import) || resolveExportTarget(value.default) || resolveExportTarget(value.require);
3811
+ }
3812
+
3813
+ return '';
3814
+ }
3815
+
3816
+ function escapeRegExp(value: string) {
3817
+ return value.replace(/[][\\\\^$.*+?(){}|]/g, '\\\\$&');
3818
+ }
3819
+
3820
+ function buildDependencyAliases() {
3821
+ return Object.keys(readLocalServerDependencies()).reduce<Alias[]>((accumulator, dependencyName) => {
3822
+ if (dependencyAliasExcludeNames.has(dependencyName) || dependencyAliasExcludePrefixes.some((prefix) => dependencyName.startsWith(prefix))) {
3823
+ return accumulator;
3824
+ }
3825
+
3826
+ const dependencyPath = path.resolve(localServerRoot, 'node_modules', ...dependencyName.split('/'));
3827
+ const dependencyPackageJsonPath = path.resolve(dependencyPath, 'package.json');
3828
+
3829
+ if (fs.existsSync(dependencyPath)) {
3830
+ try {
3831
+ const dependencyPackageJson = JSON.parse(fs.readFileSync(dependencyPackageJsonPath, 'utf8')) as { exports?: Record<string, unknown> };
3832
+ const dependencyExports = isRecord(dependencyPackageJson.exports) ? dependencyPackageJson.exports : {};
3833
+ const rootExportTarget = resolveExportTarget(dependencyExports['.']);
3834
+ const rootReplacement = rootExportTarget ? path.resolve(dependencyPath, rootExportTarget) : dependencyPath;
3835
+ const dependencyNamePattern = escapeRegExp(dependencyName);
3836
+
3837
+ accumulator.push({
3838
+ find: new RegExp(\`^\${dependencyNamePattern}$\`),
3839
+ replacement: rootReplacement
3840
+ });
3841
+
3842
+ for (const [exportKey, exportValue] of Object.entries(dependencyExports)) {
3843
+ if (!exportKey.startsWith('./')) {
3844
+ continue;
3845
+ }
3846
+
3847
+ const exportTarget = resolveExportTarget(exportValue);
3848
+
3849
+ if (!exportTarget) {
3850
+ continue;
3851
+ }
3852
+
3853
+ accumulator.push({
3854
+ find: new RegExp(\`^\${escapeRegExp(\`\${dependencyName}/\${exportKey.slice(2)}\`)}$\`),
3855
+ replacement: path.resolve(dependencyPath, exportTarget)
3856
+ });
3857
+ }
3858
+ } catch {
3859
+ accumulator.push({
3860
+ find: new RegExp(\`^\${escapeRegExp(dependencyName)}$\`),
3861
+ replacement: dependencyPath
3862
+ });
3863
+ }
3864
+
3865
+ accumulator.push({
3866
+ find: new RegExp(\`^\${escapeRegExp(dependencyName)}/(.+)$\`),
3867
+ replacement: \`\${dependencyPath}/$1\`
3868
+ });
3869
+ }
3870
+
3871
+ return accumulator;
3872
+ }, []);
3873
+ }
3874
+
3875
+ function readPreviewTarget() {
3876
+ try {
3877
+ const raw = fs.readFileSync(previewTargetPath, 'utf8').trim();
3878
+
3879
+ if (!raw) {
3880
+ return { mode: 'all' } as const;
3881
+ }
3882
+
3883
+ const parsed = JSON.parse(raw) as { directory?: string; directories?: string[]; mode?: string };
3884
+ const directory = typeof parsed.directory === 'string' && parsed.directory.trim() ? path.resolve(parsed.directory) : undefined;
3885
+ const directories = Array.isArray(parsed.directories)
3886
+ ? Array.from(
3887
+ new Set(
3888
+ parsed.directories
3889
+ .filter((value): value is string => typeof value === 'string' && value.trim())
3890
+ .map((value) => path.resolve(value))
3891
+ )
3892
+ ).sort((left, right) => left.localeCompare(right))
3893
+ : undefined;
3894
+
3895
+ if (parsed.mode === 'directory' && directory) {
3896
+ return {
3897
+ directory,
3898
+ mode: 'directory'
3899
+ } as const;
3900
+ }
3901
+
3902
+ if (parsed.mode === 'all') {
3903
+ return {
3904
+ ...(directory ? { directory } : {}),
3905
+ ...(directories ? { directories } : {}),
3906
+ mode: 'all'
3907
+ } as const;
3908
+ }
3909
+ } catch {
3910
+ return { mode: 'all' } as const;
3911
+ }
3912
+
3913
+ return { mode: 'all' } as const;
3914
+ }
3915
+
3916
+ function getAllowedGeneratedDirectories() {
3917
+ const target = readPreviewTarget();
3918
+
3919
+ if (target.mode === 'all') {
3920
+ if (Array.isArray(target.directories) && target.directories.length > 0) {
3921
+ return target.directories;
3922
+ }
3923
+
3924
+ return [path.resolve(localServerRoot, '..', 'generated')];
3925
+ }
3926
+
3927
+ if (target.directory) {
3928
+ return [target.directory];
3929
+ }
3930
+
3931
+ return [path.resolve(localServerRoot, '..', 'generated')];
3932
+ }
3933
+
3934
+ function isPathInsideDirectory(directoryPath: string, filePath: string) {
3935
+ const relativePath = path.relative(directoryPath, filePath);
3936
+
3937
+ return relativePath === '' || (!relativePath.startsWith('..') && !path.isAbsolute(relativePath));
3938
+ }
3939
+
3940
+ function resolveGeneratedFilePath(source: string) {
3941
+ const normalizedSource = source.trim();
3942
+
3943
+ if (!normalizedSource) {
3944
+ return '';
3945
+ }
3946
+
3947
+ let candidate = normalizedSource;
3948
+
3949
+ try {
3950
+ if (/^https?:\\/\\//i.test(candidate)) {
3951
+ candidate = new URL(candidate).pathname;
3952
+ }
3953
+ } catch {
3954
+ return '';
3955
+ }
3956
+
3957
+ if (candidate.startsWith('/@fs/')) {
3958
+ return path.resolve('/', candidate.slice('/@fs/'.length));
3959
+ }
3960
+
3961
+ if (candidate.startsWith('/')) {
3962
+ return path.resolve(candidate);
3963
+ }
3964
+
3965
+ return path.resolve(workspaceRoot, candidate);
3966
+ }
3967
+
3968
+ function createGeneratedFileProxyPlugin(): Plugin {
3969
+ return {
3970
+ configureServer(server) {
3971
+ server.middlewares.use((request, response, next) => {
3972
+ if (!request.url) {
3973
+ next();
3974
+
3975
+ return;
3976
+ }
3977
+
3978
+ const requestUrl = new URL(request.url, 'http://127.0.0.1');
3979
+
3980
+ if (requestUrl.pathname !== generatedFileEndpointPath) {
3981
+ next();
3982
+
3983
+ return;
3984
+ }
3985
+
3986
+ const filePath = resolveGeneratedFilePath(requestUrl.searchParams.get('source') || '');
3987
+ const allowedDirectories = getAllowedGeneratedDirectories();
3988
+ const isAllowedFile =
3989
+ Boolean(filePath) &&
3990
+ fs.existsSync(filePath) &&
3991
+ fs.statSync(filePath).isFile() &&
3992
+ allowedDirectories.some((directoryPath) => isPathInsideDirectory(directoryPath, filePath));
3993
+
3994
+ if (!isAllowedFile) {
3995
+ response.statusCode = 404;
3996
+ response.setHeader('Content-Type', 'text/plain; charset=utf-8');
3997
+ response.end('\uC0DD\uC131\uB41C \uD30C\uC77C\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.');
3998
+
3999
+ return;
4000
+ }
4001
+
4002
+ const shouldDownload = requestUrl.searchParams.get('download') === '1';
4003
+ const content = fs.readFileSync(filePath, 'utf8');
4004
+
4005
+ response.statusCode = 200;
4006
+ response.setHeader('Cache-Control', 'no-store');
4007
+ response.setHeader('Content-Type', 'text/plain; charset=utf-8');
4008
+ response.setHeader('X-Content-Type-Options', 'nosniff');
4009
+ response.setHeader(
4010
+ 'Content-Disposition',
4011
+ \`\${shouldDownload ? 'attachment' : 'inline'}; filename*=UTF-8''\${encodeURIComponent(path.basename(filePath))}\`
4012
+ );
4013
+ response.end(content);
4014
+ });
4015
+ },
4016
+ name: 'ju-hong-e-generated-file-proxy'
4017
+ };
4018
+ }
4019
+
4020
+ function resolveStories() {
4021
+ const target = readPreviewTarget();
4022
+
4023
+ if (target.mode === 'directory' && target.directory) {
4024
+ const relativePattern = toPosix(path.relative(__dirname, target.directory));
4025
+
4026
+ return [\`\${relativePattern}/**/*.stories.@(js|jsx|ts|tsx)\`];
4027
+ }
4028
+
4029
+ if (target.mode === 'all' && Array.isArray(target.directories)) {
4030
+ return target.directories.map((directory) => \`\${toPosix(path.relative(__dirname, directory))}/**/*.stories.@(js|jsx|ts|tsx)\`);
4031
+ }
4032
+
4033
+ return ['../../generated/**/*.stories.@(js|jsx|ts|tsx)'];
4034
+ }
4035
+
4036
+ const dependencyAliases = buildDependencyAliases();
4037
+
4038
+ const config: StorybookConfig = {
4039
+ stories: resolveStories(),
4040
+ addons: ['@storybook/addon-essentials'],
4041
+ framework: {
4042
+ name: '@storybook/react-vite',
4043
+ options: {}
4044
+ },
4045
+ docs: {
4046
+ autodocs: false
4047
+ },
4048
+ viteFinal: async (config) => {
4049
+ const currentAllow = Array.isArray(config.server?.fs?.allow) ? config.server.fs.allow : [];
4050
+ const currentPlugins = Array.isArray(config.plugins) ? config.plugins : config.plugins ? [config.plugins] : [];
4051
+ const currentResolveAlias = config.resolve?.alias;
4052
+ const currentResolveAliasArray = Array.isArray(currentResolveAlias)
4053
+ ? currentResolveAlias
4054
+ : Object.entries(currentResolveAlias || {}).map(([find, replacement]) => ({ find, replacement }));
4055
+ const mergedAlias = [...dependencyAliases, ...currentResolveAliasArray];
4056
+
4057
+ config.server = {
4058
+ ...(config.server || {}),
4059
+ fs: {
4060
+ ...(config.server?.fs || {}),
4061
+ allow: Array.from(new Set([...currentAllow, workspaceRoot]))
4062
+ }
4063
+ };
4064
+ config.resolve = {
4065
+ ...(config.resolve || {}),
4066
+ alias: mergedAlias
4067
+ };
4068
+ config.plugins = [...currentPlugins, createGeneratedFileProxyPlugin()];
4069
+
4070
+ return config;
4071
+ }
4072
+ };
4073
+
4074
+ export default config;
4075
+ `;
4076
+ }
4077
+ function getStorybookPreviewConfigContent() {
4078
+ return `import type { Preview } from '@storybook/react';
4079
+ import 'sales-frontend-design-system/core-styles';
4080
+
4081
+ const preview: Preview = {
4082
+ parameters: {
4083
+ layout: 'fullscreen',
4084
+ controls: {
4085
+ matchers: {
4086
+ color: /(background|color)$/i,
4087
+ date: /Date$/i
4088
+ }
4089
+ },
4090
+ options: {
4091
+ storySort: {
4092
+ method: 'alphabetical'
4093
+ }
4094
+ }
4095
+ }
4096
+ };
4097
+
4098
+ export default preview;
4099
+ `;
4100
+ }
4101
+ function removeLegacyLocalServerFiles(localServerPaths, trace) {
4102
+ for (const fileName of LOCAL_SERVER_LEGACY_FILE_NAMES) {
4103
+ const targetPath = path6__default.default.join(localServerPaths.directoryPath, fileName);
4104
+ if (!fs7__default.default.existsSync(targetPath)) {
4105
+ continue;
4106
+ }
4107
+ fs7__default.default.unlinkSync(targetPath);
4108
+ trace("local-server:cleanup:legacy-file", targetPath);
4109
+ }
4110
+ }
4111
+ function ensureLocalServerSetup(paths, trace, outputDirectory, options = {}) {
4112
+ const localServerPaths = getLocalServerPaths(paths);
4113
+ const requiredWorkspaceDependencies = resolveRequiredLocalServerPublishedDependencies(paths, trace, options);
4114
+ const runtimeDependencies = resolveLocalServerRuntimeDependencies(paths, localServerPaths.directoryPath, trace);
4115
+ const generatedDependencies = {};
4116
+ fs7__default.default.mkdirSync(localServerPaths.directoryPath, { recursive: true });
4117
+ fs7__default.default.mkdirSync(localServerPaths.storybookConfigDirectoryPath, { recursive: true });
4118
+ removeLegacyLocalServerFiles(localServerPaths, trace);
4119
+ trace("local-server:setup:dir", localServerPaths.directoryPath);
4120
+ let packageJson = mergeLocalServerPackageJson(void 0, generatedDependencies);
4121
+ if (fs7__default.default.existsSync(localServerPaths.packageJsonPath)) {
4122
+ try {
4123
+ packageJson = mergeLocalServerPackageJson(readJsonFile(localServerPaths.packageJsonPath), generatedDependencies);
4124
+ } catch (error) {
4125
+ throw new Error(`\uB85C\uCEEC \uD504\uB9AC\uBDF0 \uC11C\uBC84 package.json\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. ${getErrorSummary(error)}`);
4126
+ }
4127
+ }
4128
+ packageJson = {
4129
+ ...packageJson,
4130
+ dependencies: {
4131
+ ...normalizeDependencies(packageJson.dependencies),
4132
+ ...requiredWorkspaceDependencies,
4133
+ ...runtimeDependencies
4134
+ }
4135
+ };
4136
+ const normalizedPackageJson = {
4137
+ ...packageJson,
4138
+ dependencies: toSortedDependencies(normalizeDependencies(packageJson.dependencies))
4139
+ };
4140
+ const nextPackageJsonContent = `${JSON.stringify(normalizedPackageJson, null, 2)}
4141
+ `;
4142
+ const previousPackageJsonContent = fs7__default.default.existsSync(localServerPaths.packageJsonPath) ? fs7__default.default.readFileSync(localServerPaths.packageJsonPath, "utf8") : "";
4143
+ const packageJsonChanged = previousPackageJsonContent !== nextPackageJsonContent;
4144
+ if (packageJsonChanged) {
4145
+ fs7__default.default.writeFileSync(localServerPaths.packageJsonPath, nextPackageJsonContent, "utf8");
4146
+ trace("local-server:setup:package-json-updated", localServerPaths.packageJsonPath);
4147
+ }
4148
+ fs7__default.default.writeFileSync(localServerPaths.storybookMainConfigPath, getStorybookMainConfigContent(), "utf8");
4149
+ fs7__default.default.writeFileSync(localServerPaths.storybookPreviewConfigPath, getStorybookPreviewConfigContent(), "utf8");
4150
+ setLocalServerPreviewTarget(paths, { outputDirectory });
4151
+ trace("local-server:setup:files", localServerPaths.storybookConfigDirectoryPath);
4152
+ ensureLocalServerDependencies(paths, trace, packageJsonChanged);
4153
+ return {
4154
+ dependencies: toSortedDependencies(normalizeDependencies(normalizedPackageJson.dependencies)),
4155
+ packageJsonPath: localServerPaths.packageJsonPath
4156
+ };
4157
+ }
4158
+
4159
+ // src/common/app/service-selection.ts
4160
+ async function chooseService(title) {
4161
+ return selectSingleOption(
4162
+ title,
4163
+ AI_SERVICES.map((service) => ({
4164
+ description: service === "codex" ? "OpenAI Codex CLI" : service === "gemini" ? "Google Gemini CLI" : "Anthropic Claude CLI",
4165
+ label: service,
4166
+ value: service
4167
+ }))
4168
+ );
4169
+ }
4170
+ async function resolveInitialService(paths, parsedArgs, trace) {
4171
+ const savedService = readSavedService(paths);
4172
+ if (parsedArgs.service) {
4173
+ trace("service:from-args", parsedArgs.service);
4174
+ saveService(paths, parsedArgs.service);
4175
+ if (savedService !== parsedArgs.service) {
4176
+ const summary = savedService ? `\uC11C\uBE44\uC2A4 \uBCC0\uACBD: ${savedService} -> ${parsedArgs.service}` : `\uCD08\uAE30 \uC11C\uBE44\uC2A4 \uC120\uD0DD: ${parsedArgs.service}`;
4177
+ writeServiceChangeHistory(paths, savedService, parsedArgs.service, loadRecentHistoryContext(paths));
4178
+ appendConversationHistory(paths, {
4179
+ nextService: parsedArgs.service,
4180
+ previousService: savedService,
4181
+ scope: "service-change",
4182
+ service: parsedArgs.service,
4183
+ summary,
4184
+ title: "\uC11C\uBE44\uC2A4 \uBCC0\uACBD"
4185
+ });
4186
+ }
4187
+ return parsedArgs.service;
4188
+ }
4189
+ if (savedService) {
4190
+ trace("service:from-file", savedService);
4191
+ return savedService;
4192
+ }
4193
+ trace("service:interactive:start");
4194
+ const selected = await chooseService("\uC0AC\uC6A9\uD560 AI \uC11C\uBE44\uC2A4\uB97C \uC120\uD0DD\uD558\uC138\uC694.");
4195
+ trace("service:interactive:end", selected);
4196
+ saveService(paths, selected);
4197
+ writeServiceChangeHistory(paths, "", selected, loadRecentHistoryContext(paths));
4198
+ appendConversationHistory(paths, {
4199
+ nextService: selected,
4200
+ previousService: "",
4201
+ scope: "service-change",
4202
+ service: selected,
4203
+ summary: `\uCD08\uAE30 \uC11C\uBE44\uC2A4 \uC120\uD0DD: ${selected}`,
4204
+ title: "\uC11C\uBE44\uC2A4 \uBCC0\uACBD"
4205
+ });
4206
+ return selected;
4207
+ }
4208
+
4209
+ // src/common/app/run-cli-app.ts
4210
+ async function runCliApp(options) {
4211
+ configureCliRuntime({
4212
+ binaryName: options.binaryName,
4213
+ profile: options.profile
4214
+ });
4215
+ try {
4216
+ await runCliAppInternal(options);
4217
+ } catch (error) {
4218
+ if (isUserTerminatedError(error)) {
4219
+ console.log("\uC0AC\uC6A9\uC790 \uC694\uCCAD\uC73C\uB85C \uC138\uC158\uC744 \uC885\uB8CC\uD569\uB2C8\uB2E4.");
4220
+ return;
4221
+ }
4222
+ if (isUserCancelledError(error)) {
4223
+ console.log("\uC0AC\uC6A9\uC790 \uCDE8\uC18C\uB85C \uC138\uC158\uC744 \uC885\uB8CC\uD569\uB2C8\uB2E4.");
4224
+ return;
4225
+ }
4226
+ const paths = getStoragePaths(process.cwd());
4227
+ ensureStorageDirectories(paths);
4228
+ const errorReportPath = writeErrorReport(paths, error, {
4229
+ args: process.argv.slice(2),
4230
+ scope: `${options.traceScope}:main`,
4231
+ traceMessages: getTraceMessages()
4232
+ });
4233
+ console.error("\uC8FC\uD64D\uC774 \uC2E4\uD589 \uC911 \uCE58\uBA85\uC801\uC778 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
4234
+ console.error(formatActionError(error));
4235
+ console.error(`\uC5D0\uB7EC \uB9AC\uD3EC\uD2B8: ${errorReportPath}`);
4236
+ process.exitCode = 1;
4237
+ } finally {
4238
+ await shutdownPostHogClient();
4239
+ }
4240
+ }
4241
+ async function runCliAppInternal(options) {
4242
+ const parsedArgs = parseCliArgs();
4243
+ await loadCommandModules();
4244
+ const builtinCommands = getBuiltinCommands();
4245
+ const builtinSlashCommands = getBuiltinSlashCommands();
4246
+ const builtinCommandNames = getBuiltinCommandNames();
4247
+ if (parsedArgs.help) {
4248
+ console.log(createCliHelpText(builtinCommands, void 0, options.binaryName));
4249
+ return;
4250
+ }
4251
+ clearTraceMessages();
4252
+ const trace = createTraceLogger(options.traceScope, parsedArgs);
4253
+ const paths = getStoragePaths(process.cwd());
4254
+ ensureStorageDirectories(paths);
4255
+ trace("main:start", JSON.stringify({ ...parsedArgs, profile: options.profile }));
4256
+ hydrateStreamOutputState(paths);
4257
+ if (shouldEnableLocalServer(options.profile)) {
4258
+ try {
4259
+ ensureLocalServerSetup(paths, trace, void 0, {
4260
+ refreshPublishedDependencies: true
4261
+ });
4262
+ } catch (error) {
4263
+ trace("local-server:setup:skip", formatActionError(error));
4264
+ }
4265
+ }
4266
+ const sessionRecords = [];
4267
+ let currentService = await resolveInitialService(paths, parsedArgs, trace);
4268
+ let promptHistory = loadPromptHistory(paths);
4269
+ printSessionBanner({
4270
+ commands: builtinSlashCommands,
4271
+ service: currentService,
4272
+ streamOutputEnabled: isStreamOutputEnabled(),
4273
+ testMode: parsedArgs.testMode,
4274
+ traceMode: parsedArgs.traceMode
4275
+ });
4276
+ let isRunning = true;
4277
+ while (isRunning) {
4278
+ const sessionCatalog = getSessionCommandCatalog(currentService);
4279
+ let input = "";
4280
+ try {
4281
+ input = await promptSessionInput({
4282
+ commands: sessionCatalog.slashCommands,
4283
+ history: promptHistory,
4284
+ service: currentService,
4285
+ testMode: parsedArgs.testMode,
4286
+ traceMode: parsedArgs.traceMode
4287
+ });
4288
+ } catch (error) {
4289
+ if (isUserTerminatedError(error)) {
4290
+ trace("session:input:terminated");
4291
+ console.log("\uC138\uC158\uC744 \uC885\uB8CC\uD569\uB2C8\uB2E4.");
4292
+ break;
4293
+ }
4294
+ throw error;
4295
+ }
4296
+ if (!input) {
4297
+ continue;
4298
+ }
4299
+ promptHistory = appendPromptHistory(paths, input);
4300
+ const resolvedSlashInput = resolveSlashCommandInput(input, builtinCommandNames);
4301
+ const traceStartIndex = getTraceMessages().length;
4302
+ try {
4303
+ let record;
4304
+ let shouldPrintBanner = false;
4305
+ let shouldExit = false;
4306
+ if (resolvedSlashInput?.kind === "builtin") {
4307
+ const definition = findJuHongECommand(resolvedSlashInput.command);
4308
+ if (!definition) {
4309
+ throw new Error(`\uB4F1\uB85D\uB41C \uC8FC\uD64D\uC774 \uBA85\uB839\uC5B4\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. command=${resolvedSlashInput.command}`);
4310
+ }
4311
+ const result = await executeJuHongECommand(definition, {
4312
+ args: resolvedSlashInput.args,
4313
+ catalog: sessionCatalog,
4314
+ command: resolvedSlashInput.command,
4315
+ input,
4316
+ parsedArgs,
4317
+ paths,
4318
+ rawArgs: resolvedSlashInput.rawArgs,
4319
+ rawCommand: resolvedSlashInput.rawCommand,
4320
+ service: currentService,
4321
+ trace
4322
+ });
4323
+ if (result.nextService) {
4324
+ currentService = result.nextService;
4325
+ }
4326
+ record = result.record;
4327
+ shouldExit = Boolean(result.shouldExit);
4328
+ shouldPrintBanner = Boolean(result.shouldPrintBanner);
4329
+ } else if (resolvedSlashInput?.kind === "native") {
4330
+ if (resolvedSlashInput.requestedService && resolvedSlashInput.requestedService !== currentService) {
4331
+ console.log(`\uD604\uC7AC \uC120\uD0DD\uB41C \uC11C\uBE44\uC2A4\uB294 ${currentService} \uC785\uB2C8\uB2E4. [${currentService}] prefix\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`);
4332
+ } else {
4333
+ const result = await executeNativeCommand(findNativeCommand(currentService, resolvedSlashInput.command), {
4334
+ args: resolvedSlashInput.args,
4335
+ catalog: sessionCatalog,
4336
+ command: resolvedSlashInput.command,
4337
+ input,
4338
+ parsedArgs,
4339
+ paths,
4340
+ rawArgs: resolvedSlashInput.rawArgs,
4341
+ rawCommand: resolvedSlashInput.rawCommand,
4342
+ requestedService: resolvedSlashInput.requestedService,
4343
+ service: currentService,
4344
+ trace
4345
+ });
4346
+ record = result.record;
4347
+ shouldExit = Boolean(result.shouldExit);
4348
+ shouldPrintBanner = Boolean(result.shouldPrintBanner);
4349
+ }
4350
+ } else {
4351
+ record = await runChatAction({
4352
+ input,
4353
+ parsedArgs,
4354
+ paths,
4355
+ service: currentService,
4356
+ trace
4357
+ });
4358
+ }
4359
+ if (shouldPrintBanner) {
4360
+ printSessionBanner({
4361
+ commands: builtinSlashCommands,
4362
+ service: currentService,
4363
+ streamOutputEnabled: isStreamOutputEnabled(),
4364
+ testMode: parsedArgs.testMode,
4365
+ traceMode: parsedArgs.traceMode
4366
+ });
4367
+ }
4368
+ if (shouldExit) {
4369
+ trace("session:exit");
4370
+ isRunning = false;
4371
+ }
4372
+ if (record) {
4373
+ record.traceMessages = getTraceMessages().slice(traceStartIndex);
4374
+ sessionRecords.push(record);
4375
+ }
4376
+ } catch (error) {
4377
+ if (isUserTerminatedError(error)) {
4378
+ trace("session:terminated", input);
4379
+ console.log("\uC138\uC158\uC744 \uC885\uB8CC\uD569\uB2C8\uB2E4.");
4380
+ break;
4381
+ }
4382
+ if (isUserCancelledError(error)) {
4383
+ trace("action:cancelled", input);
4384
+ console.log("\uD604\uC7AC \uC791\uC5C5\uC744 \uCDE8\uC18C\uD558\uACE0 \uB300\uD654 \uC785\uB825 \uC0C1\uD0DC\uB85C \uB3CC\uC544\uAC11\uB2C8\uB2E4.");
4385
+ continue;
4386
+ }
4387
+ const errorTrace = getTraceMessages().slice(traceStartIndex);
4388
+ const errorReportPath = writeErrorReport(paths, error, {
4389
+ args: process.argv.slice(2),
4390
+ extraSections: [
4391
+ {
4392
+ heading: "Current Service",
4393
+ markdown: `\`${currentService}\``
4394
+ }
4395
+ ],
4396
+ scope: `${options.traceScope}:action`,
4397
+ traceMessages: errorTrace
4398
+ });
4399
+ console.error("\uC791\uC5C5 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
4400
+ console.error(formatActionError(error));
4401
+ console.error(`\uC5D0\uB7EC \uB9AC\uD3EC\uD2B8: ${errorReportPath}`);
4402
+ }
4403
+ }
4404
+ if (parsedArgs.testMode) {
4405
+ const reportPath = writeTestReport(
4406
+ paths,
4407
+ options.testReportTitle,
4408
+ [
4409
+ `- \uC2DC\uC791 \uC11C\uBE44\uC2A4: \`${readSavedService(paths) || currentService}\``,
4410
+ `- \uCD1D \uC561\uC158 \uC218: \`${sessionRecords.length}\``,
4411
+ "",
4412
+ ...sessionRecords.map(
4413
+ (record, index) => [
4414
+ `## ${index + 1}. ${record.title}`,
4415
+ "",
4416
+ `- scope: \`${record.scope}\``,
4417
+ `- service: \`${record.service}\``,
4418
+ `- skipped: \`${record.skipped}\``,
4419
+ `- summary: ${record.summary}`,
4420
+ record.historyPath ? `- history: \`${record.historyPath}\`` : "",
4421
+ record.previewCommand ? `- preview:
4422
+ \`\`\`sh
4423
+ ${record.previewCommand}
4424
+ \`\`\`` : "",
4425
+ `- trace:
4426
+ \`\`\`json
4427
+ ${JSON.stringify(record.traceMessages, null, 2)}
4428
+ \`\`\``
4429
+ ].filter(Boolean).join("\n")
4430
+ )
4431
+ ].join("\n")
4432
+ );
4433
+ console.log(`\uD14C\uC2A4\uD2B8 \uB9AC\uD3EC\uD2B8: ${reportPath}`);
4434
+ }
4435
+ trace("main:end", `service=${currentService}`);
4436
+ }
4437
+
4438
+ // src/be.ts
4439
+ void runCliApp({
4440
+ binaryName: "ju-hong-be",
4441
+ profile: "be",
4442
+ testReportTitle: "Ju-hong-be Test Session",
4443
+ traceScope: "be"
4444
+ });
4445
+ //# sourceMappingURL=be.cjs.map
4446
+ //# sourceMappingURL=be.cjs.map