@jungjaehoon/mama-os 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +643 -0
  3. package/dist/agent/agent-loop.d.ts +98 -0
  4. package/dist/agent/agent-loop.d.ts.map +1 -0
  5. package/dist/agent/agent-loop.js +417 -0
  6. package/dist/agent/agent-loop.js.map +1 -0
  7. package/dist/agent/auto-recall.d.ts +48 -0
  8. package/dist/agent/auto-recall.d.ts.map +1 -0
  9. package/dist/agent/auto-recall.js +178 -0
  10. package/dist/agent/auto-recall.js.map +1 -0
  11. package/dist/agent/claude-cli-wrapper.d.ts +130 -0
  12. package/dist/agent/claude-cli-wrapper.d.ts.map +1 -0
  13. package/dist/agent/claude-cli-wrapper.js +227 -0
  14. package/dist/agent/claude-cli-wrapper.js.map +1 -0
  15. package/dist/agent/claude-client.d.ts +50 -0
  16. package/dist/agent/claude-client.d.ts.map +1 -0
  17. package/dist/agent/claude-client.js +214 -0
  18. package/dist/agent/claude-client.js.map +1 -0
  19. package/dist/agent/gateway-tool-executor.d.ts +75 -0
  20. package/dist/agent/gateway-tool-executor.d.ts.map +1 -0
  21. package/dist/agent/gateway-tool-executor.js +348 -0
  22. package/dist/agent/gateway-tool-executor.js.map +1 -0
  23. package/dist/agent/index.d.ts +13 -0
  24. package/dist/agent/index.d.ts.map +1 -0
  25. package/dist/agent/index.js +18 -0
  26. package/dist/agent/index.js.map +1 -0
  27. package/dist/agent/mcp-executor.d.ts +75 -0
  28. package/dist/agent/mcp-executor.d.ts.map +1 -0
  29. package/dist/agent/mcp-executor.js +307 -0
  30. package/dist/agent/mcp-executor.js.map +1 -0
  31. package/dist/agent/session-pool.d.ts +148 -0
  32. package/dist/agent/session-pool.d.ts.map +1 -0
  33. package/dist/agent/session-pool.js +272 -0
  34. package/dist/agent/session-pool.js.map +1 -0
  35. package/dist/agent/streaming-callback-manager.d.ts +85 -0
  36. package/dist/agent/streaming-callback-manager.d.ts.map +1 -0
  37. package/dist/agent/streaming-callback-manager.js +103 -0
  38. package/dist/agent/streaming-callback-manager.js.map +1 -0
  39. package/dist/agent/types.d.ts +437 -0
  40. package/dist/agent/types.d.ts.map +1 -0
  41. package/dist/agent/types.js +29 -0
  42. package/dist/agent/types.js.map +1 -0
  43. package/dist/api/cron-handler.d.ts +44 -0
  44. package/dist/api/cron-handler.d.ts.map +1 -0
  45. package/dist/api/cron-handler.js +195 -0
  46. package/dist/api/cron-handler.js.map +1 -0
  47. package/dist/api/error-handler.d.ts +22 -0
  48. package/dist/api/error-handler.d.ts.map +1 -0
  49. package/dist/api/error-handler.js +104 -0
  50. package/dist/api/error-handler.js.map +1 -0
  51. package/dist/api/heartbeat-handler.d.ts +49 -0
  52. package/dist/api/heartbeat-handler.d.ts.map +1 -0
  53. package/dist/api/heartbeat-handler.js +91 -0
  54. package/dist/api/heartbeat-handler.js.map +1 -0
  55. package/dist/api/index.d.ts +61 -0
  56. package/dist/api/index.d.ts.map +1 -0
  57. package/dist/api/index.js +145 -0
  58. package/dist/api/index.js.map +1 -0
  59. package/dist/api/types.d.ts +156 -0
  60. package/dist/api/types.d.ts.map +1 -0
  61. package/dist/api/types.js +62 -0
  62. package/dist/api/types.js.map +1 -0
  63. package/dist/auth/index.d.ts +7 -0
  64. package/dist/auth/index.d.ts.map +1 -0
  65. package/dist/auth/index.js +11 -0
  66. package/dist/auth/index.js.map +1 -0
  67. package/dist/auth/oauth-manager.d.ts +59 -0
  68. package/dist/auth/oauth-manager.d.ts.map +1 -0
  69. package/dist/auth/oauth-manager.js +237 -0
  70. package/dist/auth/oauth-manager.js.map +1 -0
  71. package/dist/auth/types.d.ts +92 -0
  72. package/dist/auth/types.d.ts.map +1 -0
  73. package/dist/auth/types.js +23 -0
  74. package/dist/auth/types.js.map +1 -0
  75. package/dist/cli/commands/init.d.ts +19 -0
  76. package/dist/cli/commands/init.d.ts.map +1 -0
  77. package/dist/cli/commands/init.js +155 -0
  78. package/dist/cli/commands/init.js.map +1 -0
  79. package/dist/cli/commands/run.d.ts +19 -0
  80. package/dist/cli/commands/run.d.ts.map +1 -0
  81. package/dist/cli/commands/run.js +89 -0
  82. package/dist/cli/commands/run.js.map +1 -0
  83. package/dist/cli/commands/setup.d.ts +19 -0
  84. package/dist/cli/commands/setup.d.ts.map +1 -0
  85. package/dist/cli/commands/setup.js +134 -0
  86. package/dist/cli/commands/setup.js.map +1 -0
  87. package/dist/cli/commands/start.d.ts +24 -0
  88. package/dist/cli/commands/start.d.ts.map +1 -0
  89. package/dist/cli/commands/start.js +1073 -0
  90. package/dist/cli/commands/start.js.map +1 -0
  91. package/dist/cli/commands/status.d.ts +10 -0
  92. package/dist/cli/commands/status.d.ts.map +1 -0
  93. package/dist/cli/commands/status.js +85 -0
  94. package/dist/cli/commands/status.js.map +1 -0
  95. package/dist/cli/commands/stop.d.ts +10 -0
  96. package/dist/cli/commands/stop.d.ts.map +1 -0
  97. package/dist/cli/commands/stop.js +65 -0
  98. package/dist/cli/commands/stop.js.map +1 -0
  99. package/dist/cli/config/config-manager.d.ts +51 -0
  100. package/dist/cli/config/config-manager.d.ts.map +1 -0
  101. package/dist/cli/config/config-manager.js +216 -0
  102. package/dist/cli/config/config-manager.js.map +1 -0
  103. package/dist/cli/config/types.d.ts +172 -0
  104. package/dist/cli/config/types.d.ts.map +1 -0
  105. package/dist/cli/config/types.js +48 -0
  106. package/dist/cli/config/types.js.map +1 -0
  107. package/dist/cli/index.d.ts +8 -0
  108. package/dist/cli/index.d.ts.map +1 -0
  109. package/dist/cli/index.js +92 -0
  110. package/dist/cli/index.js.map +1 -0
  111. package/dist/cli/utils/pid-manager.d.ts +66 -0
  112. package/dist/cli/utils/pid-manager.d.ts.map +1 -0
  113. package/dist/cli/utils/pid-manager.js +167 -0
  114. package/dist/cli/utils/pid-manager.js.map +1 -0
  115. package/dist/concurrency/index.d.ts +13 -0
  116. package/dist/concurrency/index.d.ts.map +1 -0
  117. package/dist/concurrency/index.js +22 -0
  118. package/dist/concurrency/index.js.map +1 -0
  119. package/dist/concurrency/lane-manager.d.ts +113 -0
  120. package/dist/concurrency/lane-manager.d.ts.map +1 -0
  121. package/dist/concurrency/lane-manager.js +245 -0
  122. package/dist/concurrency/lane-manager.js.map +1 -0
  123. package/dist/concurrency/session-key.d.ts +41 -0
  124. package/dist/concurrency/session-key.d.ts.map +1 -0
  125. package/dist/concurrency/session-key.js +61 -0
  126. package/dist/concurrency/session-key.js.map +1 -0
  127. package/dist/concurrency/types.d.ts +69 -0
  128. package/dist/concurrency/types.d.ts.map +1 -0
  129. package/dist/concurrency/types.js +16 -0
  130. package/dist/concurrency/types.js.map +1 -0
  131. package/dist/gateways/channel-history.d.ts +102 -0
  132. package/dist/gateways/channel-history.d.ts.map +1 -0
  133. package/dist/gateways/channel-history.js +181 -0
  134. package/dist/gateways/channel-history.js.map +1 -0
  135. package/dist/gateways/context-injector.d.ts +74 -0
  136. package/dist/gateways/context-injector.d.ts.map +1 -0
  137. package/dist/gateways/context-injector.js +121 -0
  138. package/dist/gateways/context-injector.js.map +1 -0
  139. package/dist/gateways/discord.d.ts +122 -0
  140. package/dist/gateways/discord.d.ts.map +1 -0
  141. package/dist/gateways/discord.js +602 -0
  142. package/dist/gateways/discord.js.map +1 -0
  143. package/dist/gateways/index.d.ts +30 -0
  144. package/dist/gateways/index.d.ts.map +1 -0
  145. package/dist/gateways/index.js +49 -0
  146. package/dist/gateways/index.js.map +1 -0
  147. package/dist/gateways/message-router.d.ts +116 -0
  148. package/dist/gateways/message-router.d.ts.map +1 -0
  149. package/dist/gateways/message-router.js +315 -0
  150. package/dist/gateways/message-router.js.map +1 -0
  151. package/dist/gateways/message-splitter.d.ts +54 -0
  152. package/dist/gateways/message-splitter.d.ts.map +1 -0
  153. package/dist/gateways/message-splitter.js +146 -0
  154. package/dist/gateways/message-splitter.js.map +1 -0
  155. package/dist/gateways/plugin-loader.d.ts +76 -0
  156. package/dist/gateways/plugin-loader.d.ts.map +1 -0
  157. package/dist/gateways/plugin-loader.js +221 -0
  158. package/dist/gateways/plugin-loader.js.map +1 -0
  159. package/dist/gateways/session-store.d.ts +77 -0
  160. package/dist/gateways/session-store.d.ts.map +1 -0
  161. package/dist/gateways/session-store.js +233 -0
  162. package/dist/gateways/session-store.js.map +1 -0
  163. package/dist/gateways/slack.d.ts +90 -0
  164. package/dist/gateways/slack.d.ts.map +1 -0
  165. package/dist/gateways/slack.js +281 -0
  166. package/dist/gateways/slack.js.map +1 -0
  167. package/dist/gateways/telegram.d.ts +79 -0
  168. package/dist/gateways/telegram.d.ts.map +1 -0
  169. package/dist/gateways/telegram.js +207 -0
  170. package/dist/gateways/telegram.js.map +1 -0
  171. package/dist/gateways/types.d.ts +340 -0
  172. package/dist/gateways/types.d.ts.map +1 -0
  173. package/dist/gateways/types.js +6 -0
  174. package/dist/gateways/types.js.map +1 -0
  175. package/dist/index.d.ts +7 -0
  176. package/dist/index.d.ts.map +1 -0
  177. package/dist/index.js +26 -0
  178. package/dist/index.js.map +1 -0
  179. package/dist/memory/memory-logger.d.ts +47 -0
  180. package/dist/memory/memory-logger.d.ts.map +1 -0
  181. package/dist/memory/memory-logger.js +126 -0
  182. package/dist/memory/memory-logger.js.map +1 -0
  183. package/dist/onboarding/all-tools.d.ts +18 -0
  184. package/dist/onboarding/all-tools.d.ts.map +1 -0
  185. package/dist/onboarding/all-tools.js +149 -0
  186. package/dist/onboarding/all-tools.js.map +1 -0
  187. package/dist/onboarding/autonomous-discovery-tools.d.ts +13 -0
  188. package/dist/onboarding/autonomous-discovery-tools.d.ts.map +1 -0
  189. package/dist/onboarding/autonomous-discovery-tools.js +268 -0
  190. package/dist/onboarding/autonomous-discovery-tools.js.map +1 -0
  191. package/dist/onboarding/bootstrap-template.d.ts +5 -0
  192. package/dist/onboarding/bootstrap-template.d.ts.map +1 -0
  193. package/dist/onboarding/bootstrap-template.js +142 -0
  194. package/dist/onboarding/bootstrap-template.js.map +1 -0
  195. package/dist/onboarding/complete-autonomous-prompt.d.ts +13 -0
  196. package/dist/onboarding/complete-autonomous-prompt.d.ts.map +1 -0
  197. package/dist/onboarding/complete-autonomous-prompt.js +1220 -0
  198. package/dist/onboarding/complete-autonomous-prompt.js.map +1 -0
  199. package/dist/onboarding/onboarding-state.d.ts +70 -0
  200. package/dist/onboarding/onboarding-state.d.ts.map +1 -0
  201. package/dist/onboarding/onboarding-state.js +184 -0
  202. package/dist/onboarding/onboarding-state.js.map +1 -0
  203. package/dist/onboarding/personality-quiz.d.ts +35 -0
  204. package/dist/onboarding/personality-quiz.d.ts.map +1 -0
  205. package/dist/onboarding/personality-quiz.js +219 -0
  206. package/dist/onboarding/personality-quiz.js.map +1 -0
  207. package/dist/onboarding/phase-5-summary.d.ts +22 -0
  208. package/dist/onboarding/phase-5-summary.d.ts.map +1 -0
  209. package/dist/onboarding/phase-5-summary.js +151 -0
  210. package/dist/onboarding/phase-5-summary.js.map +1 -0
  211. package/dist/onboarding/phase-6-security.d.ts +33 -0
  212. package/dist/onboarding/phase-6-security.d.ts.map +1 -0
  213. package/dist/onboarding/phase-6-security.js +473 -0
  214. package/dist/onboarding/phase-6-security.js.map +1 -0
  215. package/dist/onboarding/phase-7-integrations.d.ts +66 -0
  216. package/dist/onboarding/phase-7-integrations.d.ts.map +1 -0
  217. package/dist/onboarding/phase-7-integrations.js +619 -0
  218. package/dist/onboarding/phase-7-integrations.js.map +1 -0
  219. package/dist/onboarding/phase-8-demo.d.ts +43 -0
  220. package/dist/onboarding/phase-8-demo.d.ts.map +1 -0
  221. package/dist/onboarding/phase-8-demo.js +346 -0
  222. package/dist/onboarding/phase-8-demo.js.map +1 -0
  223. package/dist/onboarding/phase-9-finalization.d.ts +22 -0
  224. package/dist/onboarding/phase-9-finalization.d.ts.map +1 -0
  225. package/dist/onboarding/phase-9-finalization.js +375 -0
  226. package/dist/onboarding/phase-9-finalization.js.map +1 -0
  227. package/dist/onboarding/ritual-prompt.d.ts +2 -0
  228. package/dist/onboarding/ritual-prompt.d.ts.map +1 -0
  229. package/dist/onboarding/ritual-prompt.js +285 -0
  230. package/dist/onboarding/ritual-prompt.js.map +1 -0
  231. package/dist/onboarding/ritual-tools.d.ts +13 -0
  232. package/dist/onboarding/ritual-tools.d.ts.map +1 -0
  233. package/dist/onboarding/ritual-tools.js +93 -0
  234. package/dist/onboarding/ritual-tools.js.map +1 -0
  235. package/dist/runners/cli-runner.d.ts +59 -0
  236. package/dist/runners/cli-runner.d.ts.map +1 -0
  237. package/dist/runners/cli-runner.js +190 -0
  238. package/dist/runners/cli-runner.js.map +1 -0
  239. package/dist/runners/index.d.ts +11 -0
  240. package/dist/runners/index.d.ts.map +1 -0
  241. package/dist/runners/index.js +15 -0
  242. package/dist/runners/index.js.map +1 -0
  243. package/dist/runners/types.d.ts +81 -0
  244. package/dist/runners/types.d.ts.map +1 -0
  245. package/dist/runners/types.js +31 -0
  246. package/dist/runners/types.js.map +1 -0
  247. package/dist/scheduler/cron-scheduler.d.ts +115 -0
  248. package/dist/scheduler/cron-scheduler.d.ts.map +1 -0
  249. package/dist/scheduler/cron-scheduler.js +320 -0
  250. package/dist/scheduler/cron-scheduler.js.map +1 -0
  251. package/dist/scheduler/heartbeat.d.ts +53 -0
  252. package/dist/scheduler/heartbeat.d.ts.map +1 -0
  253. package/dist/scheduler/heartbeat.js +160 -0
  254. package/dist/scheduler/heartbeat.js.map +1 -0
  255. package/dist/scheduler/index.d.ts +22 -0
  256. package/dist/scheduler/index.d.ts.map +1 -0
  257. package/dist/scheduler/index.js +31 -0
  258. package/dist/scheduler/index.js.map +1 -0
  259. package/dist/scheduler/job-lock.d.ts +85 -0
  260. package/dist/scheduler/job-lock.d.ts.map +1 -0
  261. package/dist/scheduler/job-lock.js +137 -0
  262. package/dist/scheduler/job-lock.js.map +1 -0
  263. package/dist/scheduler/recovery.d.ts +78 -0
  264. package/dist/scheduler/recovery.d.ts.map +1 -0
  265. package/dist/scheduler/recovery.js +124 -0
  266. package/dist/scheduler/recovery.js.map +1 -0
  267. package/dist/scheduler/schedule-store.d.ts +112 -0
  268. package/dist/scheduler/schedule-store.d.ts.map +1 -0
  269. package/dist/scheduler/schedule-store.js +259 -0
  270. package/dist/scheduler/schedule-store.js.map +1 -0
  271. package/dist/scheduler/token-keep-alive.d.ts +49 -0
  272. package/dist/scheduler/token-keep-alive.d.ts.map +1 -0
  273. package/dist/scheduler/token-keep-alive.js +102 -0
  274. package/dist/scheduler/token-keep-alive.js.map +1 -0
  275. package/dist/scheduler/types.d.ts +96 -0
  276. package/dist/scheduler/types.d.ts.map +1 -0
  277. package/dist/scheduler/types.js +21 -0
  278. package/dist/scheduler/types.js.map +1 -0
  279. package/dist/setup/setup-prompt.d.ts +2 -0
  280. package/dist/setup/setup-prompt.d.ts.map +1 -0
  281. package/dist/setup/setup-prompt.js +138 -0
  282. package/dist/setup/setup-prompt.js.map +1 -0
  283. package/dist/setup/setup-server.d.ts +8 -0
  284. package/dist/setup/setup-server.d.ts.map +1 -0
  285. package/dist/setup/setup-server.js +71 -0
  286. package/dist/setup/setup-server.js.map +1 -0
  287. package/dist/setup/setup-tools.d.ts +13 -0
  288. package/dist/setup/setup-tools.d.ts.map +1 -0
  289. package/dist/setup/setup-tools.js +103 -0
  290. package/dist/setup/setup-tools.js.map +1 -0
  291. package/dist/setup/setup-websocket.d.ts +6 -0
  292. package/dist/setup/setup-websocket.d.ts.map +1 -0
  293. package/dist/setup/setup-websocket.js +312 -0
  294. package/dist/setup/setup-websocket.js.map +1 -0
  295. package/dist/skills/index.d.ts +10 -0
  296. package/dist/skills/index.d.ts.map +1 -0
  297. package/dist/skills/index.js +26 -0
  298. package/dist/skills/index.js.map +1 -0
  299. package/dist/skills/skill-executor.d.ts +48 -0
  300. package/dist/skills/skill-executor.d.ts.map +1 -0
  301. package/dist/skills/skill-executor.js +483 -0
  302. package/dist/skills/skill-executor.js.map +1 -0
  303. package/dist/skills/skill-loader.d.ts +40 -0
  304. package/dist/skills/skill-loader.d.ts.map +1 -0
  305. package/dist/skills/skill-loader.js +225 -0
  306. package/dist/skills/skill-loader.js.map +1 -0
  307. package/dist/skills/skill-matcher.d.ts +33 -0
  308. package/dist/skills/skill-matcher.d.ts.map +1 -0
  309. package/dist/skills/skill-matcher.js +190 -0
  310. package/dist/skills/skill-matcher.js.map +1 -0
  311. package/dist/skills/types.d.ts +123 -0
  312. package/dist/skills/types.d.ts.map +1 -0
  313. package/dist/skills/types.js +12 -0
  314. package/dist/skills/types.js.map +1 -0
  315. package/dist/tools/browser-tool.d.ts +149 -0
  316. package/dist/tools/browser-tool.d.ts.map +1 -0
  317. package/dist/tools/browser-tool.js +257 -0
  318. package/dist/tools/browser-tool.js.map +1 -0
  319. package/package.json +84 -0
  320. package/public/favicon.ico +0 -0
  321. package/public/setup.html +1026 -0
  322. package/public/viewer/icons/icon-192.png +0 -0
  323. package/public/viewer/icons/icon-512.png +0 -0
  324. package/public/viewer/js/modules/chat.js +1587 -0
  325. package/public/viewer/js/modules/dashboard.js +275 -0
  326. package/public/viewer/js/modules/graph.js +997 -0
  327. package/public/viewer/js/modules/memory.js +353 -0
  328. package/public/viewer/js/modules/settings.js +255 -0
  329. package/public/viewer/js/utils/api.js +169 -0
  330. package/public/viewer/js/utils/dom.js +92 -0
  331. package/public/viewer/js/utils/format.js +192 -0
  332. package/public/viewer/manifest.json +26 -0
  333. package/public/viewer/sw.js +131 -0
  334. package/public/viewer/viewer.css +500 -0
  335. package/public/viewer/viewer.html +1535 -0
  336. package/scripts/postinstall.js +118 -0
  337. package/templates/skills/document-analyze.md +63 -0
  338. package/templates/skills/heartbeat-report.md +75 -0
  339. package/templates/skills/image-translate.md +67 -0
  340. package/templates/workspace/skill-forge/DESIGN.md +115 -0
  341. package/templates/workspace/skill-forge/agents/architect.ts +295 -0
  342. package/templates/workspace/skill-forge/agents/developer.ts +364 -0
  343. package/templates/workspace/skill-forge/agents/qa.ts +313 -0
  344. package/templates/workspace/skill-forge/claude-api.ts +353 -0
  345. package/templates/workspace/skill-forge/discord-ui.ts +580 -0
  346. package/templates/workspace/skill-forge/error-handler.ts +354 -0
  347. package/templates/workspace/skill-forge/mama-integration.ts +357 -0
  348. package/templates/workspace/skill-forge/orchestrator.ts +495 -0
  349. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/README.md +24 -0
  350. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/index.ts +79 -0
  351. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/types.ts +17 -0
  352. package/templates/workspace/skill-forge/package.json +21 -0
  353. package/templates/workspace/skill-forge/state/session.json +132 -0
  354. package/templates/workspace/skill-forge/test-e2e.ts +139 -0
  355. package/templates/workspace/skill-forge/tsconfig.json +20 -0
  356. package/templates/workspace/skill-forge/types.ts +159 -0
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Skill Forge - QA Agent
3
+ *
4
+ * ์—ญํ• : ์ƒ์„ฑ๋œ ์Šคํ‚ฌ ๊ฒ€์ฆ
5
+ * ๋ชจ๋ธ: Haiku (๋น ๋ฅธ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ๊ฒ€์ฆ)
6
+ *
7
+ * ์ž…๋ ฅ: DeveloperOutput + ArchitectOutput
8
+ * ์ถœ๋ ฅ: QAOutput (์ฒดํฌ๋ฆฌ์ŠคํŠธ, ์ด์Šˆ, ๊ถŒ๊ณ )
9
+ */
10
+
11
+ import { ArchitectOutput, DeveloperOutput, QAOutput, ChecklistItem, QAIssue } from '../types';
12
+
13
+ // ===== QA System Prompt =====
14
+
15
+ const QA_SYSTEM_PROMPT = `๋‹น์‹ ์€ Skill Forge์˜ **QA ์—์ด์ „ํŠธ**์ž…๋‹ˆ๋‹ค.
16
+
17
+ ## ์—ญํ• 
18
+ Developer๊ฐ€ ์ƒ์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ๊ฒ€์ฆํ•˜๊ณ  ํ’ˆ์งˆ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
19
+
20
+ ## ์ฒดํฌ๋ฆฌ์ŠคํŠธ
21
+
22
+ ### 1. ๊ตฌ์กฐ ๊ฒ€์ฆ
23
+ - [ ] ๋ชจ๋“  ํ•„์ˆ˜ ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜์—ˆ๋Š”๊ฐ€
24
+ - [ ] ํŒŒ์ผ ๊ตฌ์กฐ๊ฐ€ ์„ค๊ณ„์™€ ์ผ์น˜ํ•˜๋Š”๊ฐ€
25
+ - [ ] export๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋˜์–ด์žˆ๋Š”๊ฐ€
26
+
27
+ ### 2. ์ฝ”๋“œ ํ’ˆ์งˆ
28
+ - [ ] TypeScript ํƒ€์ž…์ด ๋ช…์‹œ๋˜์–ด์žˆ๋Š”๊ฐ€
29
+ - [ ] ์—๋Ÿฌ ํ•ธ๋“ค๋ง์ด ์žˆ๋Š”๊ฐ€ (try-catch)
30
+ - [ ] ์ ์ ˆํ•œ ์ฃผ์„์ด ์žˆ๋Š”๊ฐ€
31
+
32
+ ### 3. ๊ธฐ๋Šฅ ๊ฒ€์ฆ
33
+ - [ ] ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ •์˜๋˜์—ˆ๋Š”๊ฐ€
34
+ - [ ] ์›Œํฌํ”Œ๋กœ์šฐ ๋‹จ๊ณ„๊ฐ€ ๊ตฌํ˜„๋˜์—ˆ๋Š”๊ฐ€
35
+ - [ ] ํ•„์š”ํ•œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€
36
+
37
+ ### 4. ๋ณด์•ˆ/์•ˆ์ „
38
+ - [ ] ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋น„๋ฐ€์ด ์—†๋Š”๊ฐ€
39
+ - [ ] ์ž…๋ ฅ ๊ฒ€์ฆ์ด ์žˆ๋Š”๊ฐ€
40
+ - [ ] ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ์•ˆ์ „ํ•œ๊ฐ€
41
+
42
+ ## ์ถœ๋ ฅ ํ˜•์‹ (JSON)
43
+ {
44
+ "passed": true/false,
45
+ "checklist": [
46
+ {"item": "๊ฒ€์‚ฌ ํ•ญ๋ชฉ", "passed": true/false, "note": "์„ ํƒ์  ์„ค๋ช…"}
47
+ ],
48
+ "issues": [
49
+ {"severity": "critical|warning|suggestion", "description": "์„ค๋ช…", "location": "ํŒŒ์ผ:๋ผ์ธ"}
50
+ ],
51
+ "recommendation": "approve|revise|reject"
52
+ }
53
+
54
+ JSON๋งŒ ์ถœ๋ ฅํ•˜์„ธ์š”.`;
55
+
56
+ // ===== QA Agent Class =====
57
+
58
+ export class QAAgent {
59
+ private systemPrompt: string;
60
+
61
+ constructor() {
62
+ this.systemPrompt = QA_SYSTEM_PROMPT;
63
+ }
64
+
65
+ /**
66
+ * Developer ์ถœ๋ ฅ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค
67
+ */
68
+ async verify(
69
+ developerOutput: DeveloperOutput,
70
+ architectOutput: ArchitectOutput
71
+ ): Promise<QAOutput> {
72
+ const userPrompt = this.buildUserPrompt(developerOutput, architectOutput);
73
+ const response = await this.callClaude(userPrompt);
74
+ return this.parseResponse(response);
75
+ }
76
+
77
+ private buildUserPrompt(dev: DeveloperOutput, arch: ArchitectOutput): string {
78
+ return `## Architect ์„ค๊ณ„
79
+
80
+ \`\`\`json
81
+ ${JSON.stringify(arch, null, 2)}
82
+ \`\`\`
83
+
84
+ ## Developer ์ถœ๋ ฅ
85
+
86
+ ### ์ƒ์„ฑ๋œ ํŒŒ์ผ๋“ค
87
+ ${dev.files
88
+ .map(
89
+ (f) => `#### ${f.path}
90
+ \`\`\`${f.language}
91
+ ${f.content}
92
+ \`\`\``
93
+ )
94
+ .join('\n\n')}
95
+
96
+ ### ์„ค์น˜ ์ง€์นจ
97
+ ${dev.installInstructions.join('\n') || '์—†์Œ'}
98
+
99
+ ### ํ…Œ์ŠคํŠธ ๋ช…๋ น
100
+ ${dev.testCommands.join('\n') || '์—†์Œ'}
101
+
102
+ ---
103
+
104
+ ์œ„ ์ฝ”๋“œ๋ฅผ ์ฒดํฌ๋ฆฌ์ŠคํŠธ์— ๋”ฐ๋ผ ๊ฒ€์ฆํ•˜์„ธ์š”.`;
105
+ }
106
+
107
+ private async callClaude(userPrompt: string): Promise<string> {
108
+ // TODO: ์‹ค์ œ Claude API ํ˜ธ์ถœ (Phase 3)
109
+ const output = this.runChecklist(userPrompt);
110
+ return JSON.stringify(output);
111
+ }
112
+
113
+ private parseResponse(response: string): QAOutput {
114
+ try {
115
+ let jsonStr = response;
116
+ const jsonMatch = response.match(/\`\`\`(?:json)?\s*([\s\S]*?)\`\`\`/);
117
+ if (jsonMatch) {
118
+ jsonStr = jsonMatch[1];
119
+ }
120
+ const parsed = JSON.parse(jsonStr.trim());
121
+ return {
122
+ passed: parsed.passed ?? false,
123
+ checklist: parsed.checklist || [],
124
+ issues: parsed.issues || [],
125
+ recommendation: parsed.recommendation || 'revise',
126
+ };
127
+ } catch (error) {
128
+ console.error('[QAAgent] JSON parse error:', error);
129
+ throw new Error(`QA ์‘๋‹ต ํŒŒ์‹ฑ ์‹คํŒจ: ${error}`);
130
+ }
131
+ }
132
+
133
+ // ===== Checklist Runner (Local) =====
134
+
135
+ private runChecklist(userPrompt: string): QAOutput {
136
+ const checklist: ChecklistItem[] = [];
137
+ const issues: QAIssue[] = [];
138
+
139
+ // ํŒŒ์ผ ์ถ”์ถœ
140
+ const fileMatches = userPrompt.matchAll(/#### ([\w\-\/\.]+)\n\`\`\`(\w+)\n([\s\S]*?)\`\`\`/g);
141
+ const files: Array<{ path: string; lang: string; content: string }> = [];
142
+
143
+ for (const match of fileMatches) {
144
+ files.push({ path: match[1], lang: match[2], content: match[3] });
145
+ }
146
+
147
+ // 1. ๊ตฌ์กฐ ๊ฒ€์ฆ
148
+ checklist.push({
149
+ item: 'ํ•„์ˆ˜ ํŒŒ์ผ ์ƒ์„ฑ๋จ',
150
+ passed: files.length >= 2,
151
+ note: `${files.length}๊ฐœ ํŒŒ์ผ`,
152
+ });
153
+
154
+ const hasIndex = files.some((f) => f.path.includes('index.ts'));
155
+ checklist.push({
156
+ item: 'index.ts ์กด์žฌ',
157
+ passed: hasIndex,
158
+ });
159
+
160
+ const hasTypes = files.some((f) => f.path.includes('types.ts'));
161
+ checklist.push({
162
+ item: 'types.ts ์กด์žฌ',
163
+ passed: hasTypes,
164
+ });
165
+
166
+ // 2. ์ฝ”๋“œ ํ’ˆ์งˆ
167
+ const indexFile = files.find((f) => f.path.includes('index.ts'));
168
+ if (indexFile) {
169
+ const hasExport = indexFile.content.includes('export');
170
+ checklist.push({
171
+ item: 'export ๋ฌธ ์กด์žฌ',
172
+ passed: hasExport,
173
+ });
174
+
175
+ const hasTryCatch = indexFile.content.includes('try') && indexFile.content.includes('catch');
176
+ checklist.push({
177
+ item: '์—๋Ÿฌ ํ•ธ๋“ค๋ง (try-catch)',
178
+ passed: hasTryCatch,
179
+ });
180
+
181
+ const hasTypeAnnotation = indexFile.content.includes(': ') || indexFile.content.includes('<');
182
+ checklist.push({
183
+ item: 'ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜',
184
+ passed: hasTypeAnnotation,
185
+ });
186
+
187
+ // ๋ณด์•ˆ ์ฒดํฌ
188
+ const hasHardcodedSecrets = /api[_-]?key|password|secret/i.test(indexFile.content);
189
+ if (hasHardcodedSecrets) {
190
+ issues.push({
191
+ severity: 'warning',
192
+ description: 'ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๋น„๋ฐ€ ํ‚ค์›Œ๋“œ ๋ฐœ๊ฒฌ',
193
+ location: indexFile.path,
194
+ });
195
+ }
196
+ checklist.push({
197
+ item: 'ํ•˜๋“œ์ฝ”๋”ฉ ๋น„๋ฐ€ ์—†์Œ',
198
+ passed: !hasHardcodedSecrets,
199
+ });
200
+ }
201
+
202
+ // 3. ํŠธ๋ฆฌ๊ฑฐ ๊ฒ€์ฆ
203
+ const hasTriggers = files.some((f) => f.content.includes('triggers'));
204
+ checklist.push({
205
+ item: 'ํŠธ๋ฆฌ๊ฑฐ ์ •์˜๋จ',
206
+ passed: hasTriggers,
207
+ });
208
+
209
+ // 4. README ์ฒดํฌ
210
+ const hasReadme = files.some((f) => f.path.includes('README'));
211
+ checklist.push({
212
+ item: 'README ์กด์žฌ',
213
+ passed: hasReadme,
214
+ });
215
+
216
+ // ๊ฒฐ๊ณผ ๊ณ„์‚ฐ
217
+ const passedCount = checklist.filter((c) => c.passed).length;
218
+ const totalCount = checklist.length;
219
+ const passRate = passedCount / totalCount;
220
+
221
+ const criticalIssues = issues.filter((i) => i.severity === 'critical').length;
222
+
223
+ let recommendation: 'approve' | 'revise' | 'reject';
224
+ if (criticalIssues > 0) {
225
+ recommendation = 'reject';
226
+ } else if (passRate >= 0.8) {
227
+ recommendation = 'approve';
228
+ } else {
229
+ recommendation = 'revise';
230
+ }
231
+
232
+ return {
233
+ passed: passRate >= 0.8 && criticalIssues === 0,
234
+ checklist,
235
+ issues,
236
+ recommendation,
237
+ };
238
+ }
239
+ }
240
+
241
+ // ===== Factory =====
242
+
243
+ export function createQAAgent(): QAAgent {
244
+ return new QAAgent();
245
+ }
246
+
247
+ // ===== Test =====
248
+
249
+ async function runTest() {
250
+ console.log('๐Ÿ” QA Agent Test\n');
251
+
252
+ const agent = createQAAgent();
253
+
254
+ const devOutput: DeveloperOutput = {
255
+ files: [
256
+ {
257
+ path: 'skills/code-review/index.ts',
258
+ language: 'typescript',
259
+ content: `export const skill = {
260
+ name: 'code-review',
261
+ triggers: ['/review'],
262
+ async execute(ctx: any) {
263
+ try {
264
+ return { success: true };
265
+ } catch (e) {
266
+ return { success: false };
267
+ }
268
+ }
269
+ };`,
270
+ },
271
+ {
272
+ path: 'skills/code-review/types.ts',
273
+ language: 'typescript',
274
+ content: `export interface SkillContext { input: string; }`,
275
+ },
276
+ {
277
+ path: 'skills/code-review/README.md',
278
+ language: 'markdown',
279
+ content: `# code-review\n\nCode review skill.`,
280
+ },
281
+ ],
282
+ installInstructions: [],
283
+ testCommands: ['npx tsx skills/code-review/index.ts'],
284
+ };
285
+
286
+ const archOutput: ArchitectOutput = {
287
+ skillName: 'code-review',
288
+ purpose: '์ฝ”๋“œ ๋ฆฌ๋ทฐ',
289
+ triggers: ['/review'],
290
+ workflow: [{ step: 1, action: 'analyze', description: '๋ถ„์„' }],
291
+ fileStructure: [],
292
+ toolsRequired: [],
293
+ estimatedComplexity: 'simple',
294
+ };
295
+
296
+ const output = await agent.verify(devOutput, archOutput);
297
+ console.log('โœ… QA Result:\n');
298
+ console.log(`Passed: ${output.passed}`);
299
+ console.log(`Recommendation: ${output.recommendation}`);
300
+ console.log(`\nChecklist:`);
301
+ output.checklist.forEach((c) => {
302
+ console.log(` ${c.passed ? 'โœ…' : 'โŒ'} ${c.item}${c.note ? ` (${c.note})` : ''}`);
303
+ });
304
+ if (output.issues.length > 0) {
305
+ console.log(`\nIssues:`);
306
+ output.issues.forEach((i) => console.log(` โš ๏ธ [${i.severity}] ${i.description}`));
307
+ }
308
+ }
309
+
310
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`;
311
+ if (isMainModule) {
312
+ runTest();
313
+ }
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Skill Forge - Claude API Integration
3
+ *
4
+ * ์‹ค์ œ Claude API ์—ฐ๋™์œผ๋กœ ๊ฐ ์—์ด์ „ํŠธ ์‹คํ–‰
5
+ * ํ™˜๊ฒฝ๋ณ€์ˆ˜: ANTHROPIC_API_KEY
6
+ */
7
+
8
+ import { AgentModel, ArchitectOutput, DeveloperOutput, QAOutput, SkillRequest } from './types';
9
+
10
+ // ===== API Types =====
11
+
12
+ export interface ClaudeMessage {
13
+ role: 'user' | 'assistant';
14
+ content: string;
15
+ }
16
+
17
+ export interface ClaudeRequest {
18
+ model: string;
19
+ max_tokens: number;
20
+ system?: string;
21
+ messages: ClaudeMessage[];
22
+ }
23
+
24
+ export interface ClaudeResponse {
25
+ id: string;
26
+ type: 'message';
27
+ role: 'assistant';
28
+ content: Array<{
29
+ type: 'text';
30
+ text: string;
31
+ }>;
32
+ model: string;
33
+ stop_reason: string;
34
+ usage: {
35
+ input_tokens: number;
36
+ output_tokens: number;
37
+ };
38
+ }
39
+
40
+ // ===== Model Mapping =====
41
+
42
+ const MODEL_MAP: Record<AgentModel, string> = {
43
+ sonnet: 'claude-sonnet-4-20250514',
44
+ opus: 'claude-sonnet-4-20250514', // Opus ๋ฏธ์ถœ์‹œ๋กœ Sonnet ์‚ฌ์šฉ
45
+ haiku: 'claude-3-5-haiku-20241022',
46
+ };
47
+
48
+ // ===== API Client =====
49
+
50
+ export class ClaudeAPIClient {
51
+ private apiKey: string;
52
+ private baseUrl = 'https://api.anthropic.com/v1/messages';
53
+
54
+ constructor(apiKey?: string) {
55
+ this.apiKey = apiKey || process.env.ANTHROPIC_API_KEY || '';
56
+ if (!this.apiKey) {
57
+ console.warn('[ClaudeAPI] No API key found - using mock mode');
58
+ }
59
+ }
60
+
61
+ async call(
62
+ model: AgentModel,
63
+ systemPrompt: string,
64
+ userMessage: string,
65
+ maxTokens: number = 4096
66
+ ): Promise<string> {
67
+ // Mock mode for testing without API key
68
+ if (!this.apiKey) {
69
+ return this.mockResponse(model, userMessage);
70
+ }
71
+
72
+ const request: ClaudeRequest = {
73
+ model: MODEL_MAP[model],
74
+ max_tokens: maxTokens,
75
+ system: systemPrompt,
76
+ messages: [{ role: 'user', content: userMessage }],
77
+ };
78
+
79
+ try {
80
+ const response = await fetch(this.baseUrl, {
81
+ method: 'POST',
82
+ headers: {
83
+ 'Content-Type': 'application/json',
84
+ 'x-api-key': this.apiKey,
85
+ 'anthropic-version': '2023-06-01',
86
+ },
87
+ body: JSON.stringify(request),
88
+ });
89
+
90
+ if (!response.ok) {
91
+ const error = await response.text();
92
+ throw new Error(`API error ${response.status}: ${error}`);
93
+ }
94
+
95
+ const data = (await response.json()) as ClaudeResponse;
96
+ return data.content[0]?.text || '';
97
+ } catch (error) {
98
+ console.error('[ClaudeAPI] Error:', error);
99
+ throw error;
100
+ }
101
+ }
102
+
103
+ private mockResponse(model: AgentModel, userMessage: string): string {
104
+ console.log(`[ClaudeAPI] Mock mode - ${model}`);
105
+ return `Mock response for ${model}`;
106
+ }
107
+ }
108
+
109
+ // ===== System Prompts =====
110
+
111
+ export const ARCHITECT_SYSTEM_PROMPT = `You are the Architect agent in Skill Forge.
112
+ Your role is to design the structure of a skill based on user requirements.
113
+
114
+ You MUST respond with valid JSON in this exact format:
115
+ {
116
+ "skillName": "skill-name-here",
117
+ "purpose": "One line description",
118
+ "triggers": ["/command", "keyword"],
119
+ "workflow": [
120
+ {"step": 1, "action": "action-name", "description": "What this step does"}
121
+ ],
122
+ "fileStructure": [
123
+ {"path": "skills/name/index.ts", "purpose": "Main entry point"}
124
+ ],
125
+ "toolsRequired": ["Read", "Write"],
126
+ "estimatedComplexity": "simple|medium|complex"
127
+ }
128
+
129
+ Be concise. Focus on practical implementation.`;
130
+
131
+ export const DEVELOPER_SYSTEM_PROMPT = `You are the Developer agent in Skill Forge.
132
+ Your role is to implement code based on the Architect's design.
133
+
134
+ You MUST respond with valid JSON in this exact format:
135
+ {
136
+ "files": [
137
+ {
138
+ "path": "skills/name/index.ts",
139
+ "content": "// Full TypeScript code here",
140
+ "language": "typescript"
141
+ }
142
+ ],
143
+ "installInstructions": ["npm install"],
144
+ "testCommands": ["npm test"]
145
+ }
146
+
147
+ Write clean, typed TypeScript code. Include proper error handling.`;
148
+
149
+ export const QA_SYSTEM_PROMPT = `You are the QA agent in Skill Forge.
150
+ Your role is to verify the quality of generated code.
151
+
152
+ You MUST respond with valid JSON in this exact format:
153
+ {
154
+ "passed": true|false,
155
+ "checklist": [
156
+ {"item": "Check description", "passed": true|false, "note": "Optional note"}
157
+ ],
158
+ "issues": [
159
+ {"severity": "critical|warning|suggestion", "description": "Issue description", "location": "file.ts:10"}
160
+ ],
161
+ "recommendation": "approve|revise|reject"
162
+ }
163
+
164
+ Be thorough but practical. Focus on actual issues.`;
165
+
166
+ // ===== Agent API Wrappers =====
167
+
168
+ export async function callArchitect(
169
+ client: ClaudeAPIClient,
170
+ request: SkillRequest
171
+ ): Promise<ArchitectOutput> {
172
+ const userMessage = `Design a skill with these requirements:
173
+
174
+ Name: ${request.name}
175
+ Description: ${request.description}
176
+ Triggers: ${request.triggers.join(', ')}
177
+ Capabilities: ${request.capabilities.join(', ')}
178
+
179
+ Original request: ${request.rawInput}
180
+
181
+ Respond with JSON only.`;
182
+
183
+ const response = await client.call('sonnet', ARCHITECT_SYSTEM_PROMPT, userMessage);
184
+ return parseJSON<ArchitectOutput>(response, 'Architect');
185
+ }
186
+
187
+ export async function callDeveloper(
188
+ client: ClaudeAPIClient,
189
+ architectOutput: ArchitectOutput,
190
+ request: SkillRequest
191
+ ): Promise<DeveloperOutput> {
192
+ const userMessage = `Implement this skill design:
193
+
194
+ ${JSON.stringify(architectOutput, null, 2)}
195
+
196
+ Original request: ${request.rawInput}
197
+
198
+ Create all files specified in fileStructure. Respond with JSON only.`;
199
+
200
+ const response = await client.call('sonnet', DEVELOPER_SYSTEM_PROMPT, userMessage, 8192);
201
+ return parseJSON<DeveloperOutput>(response, 'Developer');
202
+ }
203
+
204
+ export async function callQA(
205
+ client: ClaudeAPIClient,
206
+ developerOutput: DeveloperOutput,
207
+ architectOutput: ArchitectOutput
208
+ ): Promise<QAOutput> {
209
+ const userMessage = `Verify this implementation:
210
+
211
+ ## Architect Design
212
+ ${JSON.stringify(architectOutput, null, 2)}
213
+
214
+ ## Developer Output
215
+ ${JSON.stringify(developerOutput, null, 2)}
216
+
217
+ Check for:
218
+ 1. All files from design are implemented
219
+ 2. Code is valid TypeScript
220
+ 3. Error handling exists
221
+ 4. Workflow is followed
222
+ 5. Types are properly defined
223
+
224
+ Respond with JSON only.`;
225
+
226
+ const response = await client.call('haiku', QA_SYSTEM_PROMPT, userMessage);
227
+ return parseJSON<QAOutput>(response, 'QA');
228
+ }
229
+
230
+ // ===== JSON Parser =====
231
+
232
+ function parseJSON<T>(response: string, agentName: string): T {
233
+ // Extract JSON from response (handle markdown code blocks)
234
+ let jsonStr = response;
235
+
236
+ // Remove markdown code block if present
237
+ const jsonMatch = response.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
238
+ if (jsonMatch) {
239
+ jsonStr = jsonMatch[1];
240
+ }
241
+
242
+ // Try to find JSON object
243
+ const objectMatch = jsonStr.match(/\{[\s\S]*\}/);
244
+ if (objectMatch) {
245
+ jsonStr = objectMatch[0];
246
+ }
247
+
248
+ try {
249
+ return JSON.parse(jsonStr) as T;
250
+ } catch (error) {
251
+ console.error(`[${agentName}] Failed to parse JSON:`, jsonStr.slice(0, 200));
252
+ throw new Error(`${agentName} returned invalid JSON`);
253
+ }
254
+ }
255
+
256
+ // ===== Integration with Agents =====
257
+
258
+ export function createAPIArchitectAgent(client: ClaudeAPIClient) {
259
+ return {
260
+ async design(request: SkillRequest): Promise<ArchitectOutput> {
261
+ console.log('[Architect] Calling Claude API...');
262
+ const output = await callArchitect(client, request);
263
+ console.log('[Architect] Design complete:', output.skillName);
264
+ return output;
265
+ },
266
+ };
267
+ }
268
+
269
+ export function createAPIDeveloperAgent(client: ClaudeAPIClient) {
270
+ return {
271
+ async develop(
272
+ architectOutput: ArchitectOutput,
273
+ request: SkillRequest
274
+ ): Promise<DeveloperOutput> {
275
+ console.log('[Developer] Calling Claude API...');
276
+ const output = await callDeveloper(client, architectOutput, request);
277
+ console.log('[Developer] Generated', output.files.length, 'files');
278
+ return output;
279
+ },
280
+ };
281
+ }
282
+
283
+ export function createAPIQAAgent(client: ClaudeAPIClient) {
284
+ return {
285
+ async verify(
286
+ developerOutput: DeveloperOutput,
287
+ architectOutput: ArchitectOutput
288
+ ): Promise<QAOutput> {
289
+ console.log('[QA] Calling Claude API...');
290
+ const output = await callQA(client, developerOutput, architectOutput);
291
+ console.log('[QA] Result:', output.passed ? 'PASSED' : 'FAILED');
292
+ return output;
293
+ },
294
+ };
295
+ }
296
+
297
+ // ===== Test =====
298
+
299
+ async function runTest() {
300
+ console.log('๐Ÿ”Œ Claude API Integration Test\n');
301
+
302
+ const client = new ClaudeAPIClient();
303
+
304
+ const testRequest: SkillRequest = {
305
+ name: 'weather-check',
306
+ description: '๋‚ ์”จ ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ์Šคํ‚ฌ',
307
+ triggers: ['/weather', '๋‚ ์”จ'],
308
+ capabilities: ['ํ˜„์žฌ ๋‚ ์”จ ์กฐํšŒ', '์ง€์—ญ๋ณ„ ๋‚ ์”จ'],
309
+ rawInput: '/forge weather-check - ๋‚ ์”จ ์ •๋ณด ์กฐํšŒ',
310
+ };
311
+
312
+ if (!process.env.ANTHROPIC_API_KEY) {
313
+ console.log('โš ๏ธ ANTHROPIC_API_KEY not set - using mock mode\n');
314
+
315
+ // Mock test
316
+ const architect = createAPIArchitectAgent(client);
317
+ console.log('Testing mock architect...');
318
+
319
+ // In mock mode, this will fail with invalid JSON
320
+ // That's expected behavior
321
+ console.log('Mock mode active - API calls will return placeholder text');
322
+ console.log('\nโœ… Test setup complete (set ANTHROPIC_API_KEY for real API test)');
323
+ return;
324
+ }
325
+
326
+ console.log('๐Ÿ”‘ API key found - running real API test\n');
327
+
328
+ try {
329
+ // Test Architect
330
+ console.log('=== Architect ===');
331
+ const architectOutput = await callArchitect(client, testRequest);
332
+ console.log(JSON.stringify(architectOutput, null, 2));
333
+
334
+ // Test Developer
335
+ console.log('\n=== Developer ===');
336
+ const developerOutput = await callDeveloper(client, architectOutput, testRequest);
337
+ console.log(`Generated ${developerOutput.files.length} files`);
338
+
339
+ // Test QA
340
+ console.log('\n=== QA ===');
341
+ const qaOutput = await callQA(client, developerOutput, architectOutput);
342
+ console.log(JSON.stringify(qaOutput, null, 2));
343
+
344
+ console.log('\nโœ… All API tests passed');
345
+ } catch (error) {
346
+ console.error('\nโŒ Test failed:', error);
347
+ }
348
+ }
349
+
350
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`;
351
+ if (isMainModule) {
352
+ runTest();
353
+ }