@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,295 @@
1
+ /**
2
+ * Skill Forge - Architect Agent
3
+ *
4
+ * 역할: 스킬 구조 설계
5
+ * 모델: Sonnet 4 (빠른 구조화)
6
+ *
7
+ * 입력: 사용자 요청 (스킬 이름, 설명, 트리거 등)
8
+ * 출력: ArchitectOutput (구조, 워크플로우, 파일 구조)
9
+ */
10
+
11
+ import { SkillRequest, ArchitectOutput } from '../types';
12
+
13
+ // ===== Architect System Prompt =====
14
+
15
+ const ARCHITECT_SYSTEM_PROMPT = `당신은 Skill Forge의 **Architect 에이전트**입니다.
16
+
17
+ ## 역할
18
+ OpenClaw 스킬의 구조를 설계합니다. 코드를 작성하지 않고, **설계도**만 제공합니다.
19
+
20
+ ## 출력 형식 (JSON)
21
+ {
22
+ "skillName": "스킬 영문 이름 (kebab-case)",
23
+ "purpose": "스킬의 목적 (1-2문장)",
24
+ "triggers": ["트리거1", "트리거2"],
25
+ "workflow": [
26
+ {"step": 1, "action": "동사", "description": "설명"},
27
+ ...
28
+ ],
29
+ "fileStructure": [
30
+ {"path": "상대경로", "purpose": "용도"},
31
+ ...
32
+ ],
33
+ "toolsRequired": ["Read", "Write", ...],
34
+ "estimatedComplexity": "simple | medium | complex"
35
+ }
36
+
37
+ ## 설계 원칙
38
+ 1. **단순함 우선**: 최소한의 파일로 시작
39
+ 2. **명확한 워크플로우**: 3-7단계 이내
40
+ 3. **기존 도구 활용**: OpenClaw의 기존 도구 사용
41
+ 4. **확장 가능성**: 나중에 확장할 수 있는 구조
42
+
43
+ ## 복잡도 기준
44
+ - **simple**: 단일 파일, 1-3 워크플로우 단계
45
+ - **medium**: 2-3 파일, 4-5 워크플로우 단계
46
+ - **complex**: 4+ 파일, 6+ 워크플로우 단계, 외부 API 연동
47
+
48
+ ## 예시 입력
49
+ 스킬명: weather-check
50
+ 설명: 날씨 정보를 조회합니다
51
+ 트리거: /weather, 날씨 알려줘
52
+
53
+ ## 예시 출력
54
+ {
55
+ "skillName": "weather-check",
56
+ "purpose": "OpenWeatherMap API를 통해 현재 날씨 정보를 조회하고 사용자에게 알려줍니다",
57
+ "triggers": ["/weather", "날씨 알려줘", "오늘 날씨"],
58
+ "workflow": [
59
+ {"step": 1, "action": "parse", "description": "도시명 추출 (기본값: Seoul)"},
60
+ {"step": 2, "action": "fetch", "description": "OpenWeatherMap API 호출"},
61
+ {"step": 3, "action": "format", "description": "응답을 사용자 친화적으로 포맷"},
62
+ {"step": 4, "action": "respond", "description": "Discord로 결과 전송"}
63
+ ],
64
+ "fileStructure": [
65
+ {"path": "skills/weather-check/index.ts", "purpose": "메인 진입점"},
66
+ {"path": "skills/weather-check/api.ts", "purpose": "API 호출 로직"},
67
+ {"path": "skills/weather-check/README.md", "purpose": "사용법 문서"}
68
+ ],
69
+ "toolsRequired": ["WebFetch", "discord_send"],
70
+ "estimatedComplexity": "medium"
71
+ }
72
+
73
+ JSON만 출력하세요. 설명이나 마크다운 블록 없이 순수 JSON만.`;
74
+
75
+ // ===== Architect Agent Class =====
76
+
77
+ export class ArchitectAgent {
78
+ private systemPrompt: string;
79
+
80
+ constructor() {
81
+ this.systemPrompt = ARCHITECT_SYSTEM_PROMPT;
82
+ }
83
+
84
+ /**
85
+ * 스킬 요청을 받아 구조를 설계합니다
86
+ */
87
+ async design(request: SkillRequest): Promise<ArchitectOutput> {
88
+ const userPrompt = this.buildUserPrompt(request);
89
+
90
+ // Claude API 호출 (Sonnet 4)
91
+ // 현재는 mock 구현, 실제 API 연동은 Phase 2에서
92
+ const response = await this.callClaude(userPrompt);
93
+
94
+ return this.parseResponse(response);
95
+ }
96
+
97
+ private buildUserPrompt(request: SkillRequest): string {
98
+ return `스킬명: ${request.name}
99
+ 설명: ${request.description}
100
+ 트리거: ${request.triggers.join(', ')}
101
+ 기능: ${request.capabilities.join(', ')}
102
+
103
+ 원본 입력: ${request.rawInput}`;
104
+ }
105
+
106
+ private async callClaude(userPrompt: string): Promise<string> {
107
+ // TODO: 실제 Claude API 호출
108
+ // Phase 2에서 구현
109
+
110
+ // Mock 응답 - 프롬프트 기반으로 구조 생성
111
+ const skillName = this.extractSkillName(userPrompt);
112
+
113
+ return JSON.stringify({
114
+ skillName,
115
+ purpose: this.extractPurpose(userPrompt),
116
+ triggers: this.extractTriggers(userPrompt),
117
+ workflow: this.generateWorkflow(userPrompt),
118
+ fileStructure: this.generateFileStructure(skillName),
119
+ toolsRequired: this.inferTools(userPrompt),
120
+ estimatedComplexity: this.estimateComplexity(userPrompt),
121
+ });
122
+ }
123
+
124
+ private parseResponse(response: string): ArchitectOutput {
125
+ try {
126
+ // JSON 블록 추출 (```json ... ``` 형식 지원)
127
+ let jsonStr = response;
128
+ const jsonMatch = response.match(/```(?:json)?\s*([\s\S]*?)```/);
129
+ if (jsonMatch) {
130
+ jsonStr = jsonMatch[1];
131
+ }
132
+
133
+ const parsed = JSON.parse(jsonStr.trim());
134
+
135
+ // 필수 필드 검증
136
+ return {
137
+ skillName: parsed.skillName || 'unnamed-skill',
138
+ purpose: parsed.purpose || '목적 미정의',
139
+ triggers: parsed.triggers || [],
140
+ workflow: parsed.workflow || [],
141
+ fileStructure: parsed.fileStructure || [],
142
+ toolsRequired: parsed.toolsRequired || [],
143
+ estimatedComplexity: parsed.estimatedComplexity || 'simple',
144
+ };
145
+ } catch (error) {
146
+ console.error('[ArchitectAgent] JSON parse error:', error);
147
+ throw new Error(`Architect 응답 파싱 실패: ${error}`);
148
+ }
149
+ }
150
+
151
+ // ===== Mock Helpers (실제 API 연동 전까지 사용) =====
152
+
153
+ private extractSkillName(prompt: string): string {
154
+ const match = prompt.match(/스킬명:\s*([^\n]+)/);
155
+ if (match) {
156
+ return match[1].trim().toLowerCase().replace(/\s+/g, '-');
157
+ }
158
+ return 'unnamed-skill';
159
+ }
160
+
161
+ private extractPurpose(prompt: string): string {
162
+ const match = prompt.match(/설명:\s*([^\n]+)/);
163
+ return match ? match[1].trim() : '목적 미정의';
164
+ }
165
+
166
+ private extractTriggers(prompt: string): string[] {
167
+ const match = prompt.match(/트리거:\s*([^\n]+)/);
168
+ if (match) {
169
+ return match[1]
170
+ .split(',')
171
+ .map((t) => t.trim())
172
+ .filter(Boolean);
173
+ }
174
+ return [];
175
+ }
176
+
177
+ private generateWorkflow(
178
+ prompt: string
179
+ ): Array<{ step: number; action: string; description: string }> {
180
+ // 기본 워크플로우 템플릿
181
+ return [
182
+ { step: 1, action: 'parse', description: '사용자 입력 파싱' },
183
+ { step: 2, action: 'validate', description: '입력 검증' },
184
+ { step: 3, action: 'execute', description: '핵심 로직 실행' },
185
+ { step: 4, action: 'format', description: '결과 포맷팅' },
186
+ { step: 5, action: 'respond', description: '응답 반환' },
187
+ ];
188
+ }
189
+
190
+ private generateFileStructure(skillName: string): Array<{ path: string; purpose: string }> {
191
+ return [
192
+ { path: `skills/${skillName}/index.ts`, purpose: '메인 진입점' },
193
+ { path: `skills/${skillName}/types.ts`, purpose: '타입 정의' },
194
+ { path: `skills/${skillName}/README.md`, purpose: '사용법 문서' },
195
+ ];
196
+ }
197
+
198
+ private inferTools(prompt: string): string[] {
199
+ const tools: string[] = ['discord_send']; // 기본
200
+
201
+ const lowerPrompt = prompt.toLowerCase();
202
+
203
+ if (
204
+ lowerPrompt.includes('파일') ||
205
+ lowerPrompt.includes('읽') ||
206
+ lowerPrompt.includes('read')
207
+ ) {
208
+ tools.push('Read');
209
+ }
210
+ if (
211
+ lowerPrompt.includes('작성') ||
212
+ lowerPrompt.includes('쓰') ||
213
+ lowerPrompt.includes('write')
214
+ ) {
215
+ tools.push('Write');
216
+ }
217
+ if (
218
+ lowerPrompt.includes('api') ||
219
+ lowerPrompt.includes('fetch') ||
220
+ lowerPrompt.includes('http')
221
+ ) {
222
+ tools.push('WebFetch');
223
+ }
224
+ if (
225
+ lowerPrompt.includes('검색') ||
226
+ lowerPrompt.includes('search') ||
227
+ lowerPrompt.includes('grep')
228
+ ) {
229
+ tools.push('Grep');
230
+ }
231
+ if (
232
+ lowerPrompt.includes('명령') ||
233
+ lowerPrompt.includes('bash') ||
234
+ lowerPrompt.includes('실행')
235
+ ) {
236
+ tools.push('Bash');
237
+ }
238
+
239
+ return [...new Set(tools)]; // 중복 제거
240
+ }
241
+
242
+ private estimateComplexity(prompt: string): 'simple' | 'medium' | 'complex' {
243
+ const lowerPrompt = prompt.toLowerCase();
244
+
245
+ // 복잡도 키워드 체크
246
+ const complexKeywords = ['api', 'database', 'auth', 'multi', '연동', '통합'];
247
+ const mediumKeywords = ['검색', '파싱', 'parsing', 'format', '변환'];
248
+
249
+ for (const kw of complexKeywords) {
250
+ if (lowerPrompt.includes(kw)) return 'complex';
251
+ }
252
+
253
+ for (const kw of mediumKeywords) {
254
+ if (lowerPrompt.includes(kw)) return 'medium';
255
+ }
256
+
257
+ return 'simple';
258
+ }
259
+ }
260
+
261
+ // ===== Factory Function =====
262
+
263
+ export function createArchitectAgent(): ArchitectAgent {
264
+ return new ArchitectAgent();
265
+ }
266
+
267
+ // ===== 테스트 =====
268
+
269
+ async function runTest() {
270
+ console.log('🏗️ Architect Agent Test\n');
271
+
272
+ const agent = createArchitectAgent();
273
+
274
+ const request: SkillRequest = {
275
+ name: 'code-review',
276
+ description: '코드 리뷰를 수행하고 피드백을 제공합니다',
277
+ triggers: ['/review', '코드 리뷰해줘'],
278
+ capabilities: ['파일 읽기', '분석', '피드백 제공'],
279
+ rawInput: '/forge code-review - 코드 리뷰를 수행하고 피드백을 제공합니다',
280
+ };
281
+
282
+ try {
283
+ const output = await agent.design(request);
284
+ console.log('✅ Architect Output:\n');
285
+ console.log(JSON.stringify(output, null, 2));
286
+ } catch (error) {
287
+ console.error('❌ Error:', error);
288
+ }
289
+ }
290
+
291
+ // ESM entry point
292
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`;
293
+ if (isMainModule) {
294
+ runTest();
295
+ }
@@ -0,0 +1,364 @@
1
+ /**
2
+ * Skill Forge - Developer Agent
3
+ *
4
+ * 역할: 실제 스킬 코드 생성
5
+ * 모델: Opus 4.5 (복잡한 코드 생성)
6
+ *
7
+ * 입력: ArchitectOutput (구조 설계)
8
+ * 출력: DeveloperOutput (생성된 파일들)
9
+ */
10
+
11
+ import { ArchitectOutput, DeveloperOutput, GeneratedFile, SkillRequest } from '../types';
12
+
13
+ // ===== Developer System Prompt =====
14
+
15
+ const DEVELOPER_SYSTEM_PROMPT = `당신은 Skill Forge의 **Developer 에이전트**입니다.
16
+
17
+ ## 역할
18
+ Architect가 설계한 구조를 바탕으로 **실제 동작하는 코드**를 생성합니다.
19
+
20
+ ## 입력
21
+ 1. Architect의 설계 (구조, 워크플로우, 파일 구조)
22
+ 2. 원본 사용자 요청
23
+
24
+ ## 출력 형식 (JSON)
25
+ {
26
+ "files": [
27
+ {
28
+ "path": "skills/skill-name/index.ts",
29
+ "content": "... 전체 코드 ...",
30
+ "language": "typescript"
31
+ },
32
+ ...
33
+ ],
34
+ "installInstructions": [
35
+ "npm install 필요한-패키지",
36
+ ...
37
+ ],
38
+ "testCommands": [
39
+ "npx tsx skills/skill-name/index.ts",
40
+ ...
41
+ ]
42
+ }
43
+
44
+ ## 코드 작성 원칙
45
+
46
+ ### 1. OpenClaw 스킬 구조 준수
47
+ \`\`\`typescript
48
+ // skills/my-skill/index.ts
49
+ export const skill = {
50
+ name: 'my-skill',
51
+ description: '스킬 설명',
52
+ triggers: ['/my-skill', '트리거'],
53
+
54
+ async execute(context: SkillContext) {
55
+ // 구현
56
+ }
57
+ };
58
+ \`\`\`
59
+
60
+ ### 2. 에러 핸들링 필수
61
+ - try-catch 사용
62
+ - 사용자 친화적 에러 메시지
63
+ - 디버깅용 console.error
64
+
65
+ ### 3. 타입 안전성
66
+ - TypeScript strict mode
67
+ - 명시적 타입 선언
68
+ - 인터페이스 정의
69
+
70
+ ### 4. 모듈화
71
+ - 단일 책임 원칙
72
+ - 재사용 가능한 헬퍼 함수
73
+ - 명확한 export
74
+
75
+ JSON만 출력하세요.`;
76
+
77
+ // ===== Developer Agent Class =====
78
+
79
+ export class DeveloperAgent {
80
+ private systemPrompt: string;
81
+
82
+ constructor() {
83
+ this.systemPrompt = DEVELOPER_SYSTEM_PROMPT;
84
+ }
85
+
86
+ /**
87
+ * Architect 출력을 받아 실제 코드를 생성합니다
88
+ */
89
+ async develop(
90
+ architectOutput: ArchitectOutput,
91
+ originalRequest: SkillRequest
92
+ ): Promise<DeveloperOutput> {
93
+ const userPrompt = this.buildUserPrompt(architectOutput, originalRequest);
94
+ const response = await this.callClaude(userPrompt);
95
+ return this.parseResponse(response);
96
+ }
97
+
98
+ private buildUserPrompt(arch: ArchitectOutput, req: SkillRequest): string {
99
+ return `## Architect 설계
100
+
101
+ \`\`\`json
102
+ ${JSON.stringify(arch, null, 2)}
103
+ \`\`\`
104
+
105
+ ## 원본 요청
106
+ - 스킬명: ${req.name}
107
+ - 설명: ${req.description}
108
+ - 트리거: ${req.triggers.join(', ')}
109
+ - 기능: ${req.capabilities.join(', ')}
110
+
111
+ ## 지시사항
112
+ 위 설계를 바탕으로 실제 동작하는 코드를 생성하세요.`;
113
+ }
114
+
115
+ private async callClaude(userPrompt: string): Promise<string> {
116
+ // TODO: 실제 Claude API 호출 (Phase 3)
117
+ const output = this.generateCode(userPrompt);
118
+ return JSON.stringify(output);
119
+ }
120
+
121
+ private parseResponse(response: string): DeveloperOutput {
122
+ try {
123
+ let jsonStr = response;
124
+ const jsonMatch = response.match(/\`\`\`(?:json)?\s*([\s\S]*?)\`\`\`/);
125
+ if (jsonMatch) {
126
+ jsonStr = jsonMatch[1];
127
+ }
128
+ const parsed = JSON.parse(jsonStr.trim());
129
+ return {
130
+ files: parsed.files || [],
131
+ installInstructions: parsed.installInstructions || [],
132
+ testCommands: parsed.testCommands || [],
133
+ };
134
+ } catch (error) {
135
+ console.error('[DeveloperAgent] JSON parse error:', error);
136
+ throw new Error(`Developer 응답 파싱 실패: ${error}`);
137
+ }
138
+ }
139
+
140
+ // ===== Code Generation (Template-based) =====
141
+
142
+ private generateCode(userPrompt: string): DeveloperOutput {
143
+ const archMatch = userPrompt.match(/\`\`\`json\n([\s\S]*?)\`\`\`/);
144
+ if (!archMatch) {
145
+ throw new Error('Architect 출력을 찾을 수 없습니다');
146
+ }
147
+
148
+ const arch: ArchitectOutput = JSON.parse(archMatch[1]);
149
+ const files: GeneratedFile[] = [];
150
+
151
+ // 1. 메인 index.ts
152
+ files.push(this.generateMainFile(arch));
153
+
154
+ // 2. types.ts
155
+ files.push(this.generateTypesFile(arch));
156
+
157
+ // 3. README.md
158
+ files.push(this.generateReadmeFile(arch));
159
+
160
+ // 4. API 파일 (필요시)
161
+ if (arch.toolsRequired.includes('WebFetch')) {
162
+ files.push(this.generateApiFile(arch));
163
+ }
164
+
165
+ return {
166
+ files,
167
+ installInstructions: this.generateInstallInstructions(arch),
168
+ testCommands: this.generateTestCommands(arch),
169
+ };
170
+ }
171
+
172
+ private generateMainFile(arch: ArchitectOutput): GeneratedFile {
173
+ const skillName = arch.skillName;
174
+
175
+ const content = `/**
176
+ * ${arch.skillName} - ${arch.purpose}
177
+ *
178
+ * @triggers ${arch.triggers.join(', ')}
179
+ * @complexity ${arch.estimatedComplexity}
180
+ */
181
+
182
+ import { SkillContext, SkillResult } from './types';
183
+
184
+ // ===== Skill Definition =====
185
+
186
+ export const skill = {
187
+ name: '${skillName}',
188
+ description: '${arch.purpose}',
189
+ triggers: ${JSON.stringify(arch.triggers)},
190
+
191
+ async execute(context: SkillContext): Promise<SkillResult> {
192
+ try {
193
+ console.log('[${skillName}] 시작:', context.input);
194
+
195
+ // Workflow Steps
196
+ ${arch.workflow
197
+ .map(
198
+ (w) => ` // Step ${w.step}: ${w.action} - ${w.description}
199
+ const step${w.step} = await ${w.action}(${w.step === 1 ? 'context.input' : `step${w.step - 1}`});`
200
+ )
201
+ .join('\n')}
202
+
203
+ return {
204
+ success: true,
205
+ message: String(step${arch.workflow.length}),
206
+ };
207
+ } catch (error) {
208
+ console.error('[${skillName}] 에러:', error);
209
+ return {
210
+ success: false,
211
+ error: error instanceof Error ? error.message : '알 수 없는 에러',
212
+ };
213
+ }
214
+ },
215
+ };
216
+
217
+ // ===== Helper Functions =====
218
+
219
+ ${arch.workflow
220
+ .map(
221
+ (w) => `async function ${w.action}(input: unknown): Promise<unknown> {
222
+ // ${w.description}
223
+ console.log('[${w.action}]', input);
224
+ return input;
225
+ }`
226
+ )
227
+ .join('\n\n')}
228
+
229
+ export default skill;
230
+ `;
231
+
232
+ return { path: `skills/${skillName}/index.ts`, content, language: 'typescript' };
233
+ }
234
+
235
+ private generateTypesFile(arch: ArchitectOutput): GeneratedFile {
236
+ const content = `/**
237
+ * ${arch.skillName} - Type Definitions
238
+ */
239
+
240
+ export interface SkillContext {
241
+ input: string;
242
+ channelId?: string;
243
+ userId?: string;
244
+ metadata?: Record<string, unknown>;
245
+ }
246
+
247
+ export interface SkillResult {
248
+ success: boolean;
249
+ message?: string;
250
+ error?: string;
251
+ data?: unknown;
252
+ }
253
+ `;
254
+ return { path: `skills/${arch.skillName}/types.ts`, content, language: 'typescript' };
255
+ }
256
+
257
+ private generateReadmeFile(arch: ArchitectOutput): GeneratedFile {
258
+ const content = `# ${arch.skillName}
259
+
260
+ > ${arch.purpose}
261
+
262
+ ## 트리거
263
+
264
+ ${arch.triggers.map((t) => `- \`${t}\``).join('\n')}
265
+
266
+ ## 워크플로우
267
+
268
+ ${arch.workflow.map((w) => `${w.step}. **${w.action}**: ${w.description}`).join('\n')}
269
+
270
+ ## 필요한 도구
271
+
272
+ ${arch.toolsRequired.map((t) => `- ${t}`).join('\n')}
273
+
274
+ ---
275
+ Generated by Skill Forge 🔥
276
+ `;
277
+ return { path: `skills/${arch.skillName}/README.md`, content, language: 'markdown' };
278
+ }
279
+
280
+ private generateApiFile(arch: ArchitectOutput): GeneratedFile {
281
+ const content = `/**
282
+ * ${arch.skillName} - API Module
283
+ */
284
+
285
+ export interface ApiResponse<T = unknown> {
286
+ success: boolean;
287
+ data?: T;
288
+ error?: string;
289
+ }
290
+
291
+ export async function fetchData<T>(url: string): Promise<ApiResponse<T>> {
292
+ try {
293
+ const response = await fetch(url);
294
+ if (!response.ok) {
295
+ return { success: false, error: \`HTTP \${response.status}\` };
296
+ }
297
+ const data = await response.json();
298
+ return { success: true, data };
299
+ } catch (error) {
300
+ return { success: false, error: String(error) };
301
+ }
302
+ }
303
+ `;
304
+ return { path: `skills/${arch.skillName}/api.ts`, content, language: 'typescript' };
305
+ }
306
+
307
+ private generateInstallInstructions(arch: ArchitectOutput): string[] {
308
+ const instructions: string[] = [];
309
+ if (arch.toolsRequired.includes('WebFetch')) {
310
+ instructions.push('npm install node-fetch');
311
+ }
312
+ return instructions;
313
+ }
314
+
315
+ private generateTestCommands(arch: ArchitectOutput): string[] {
316
+ return [`npx tsx skills/${arch.skillName}/index.ts`];
317
+ }
318
+ }
319
+
320
+ // ===== Factory =====
321
+
322
+ export function createDeveloperAgent(): DeveloperAgent {
323
+ return new DeveloperAgent();
324
+ }
325
+
326
+ // ===== Test =====
327
+
328
+ async function runTest() {
329
+ console.log('💻 Developer Agent Test\n');
330
+
331
+ const agent = createDeveloperAgent();
332
+
333
+ const archOutput: ArchitectOutput = {
334
+ skillName: 'code-review',
335
+ purpose: '코드 리뷰를 수행하고 피드백을 제공',
336
+ triggers: ['/review', '코드 리뷰해줘'],
337
+ workflow: [
338
+ { step: 1, action: 'parse', description: '파일 경로 추출' },
339
+ { step: 2, action: 'read', description: '파일 읽기' },
340
+ { step: 3, action: 'analyze', description: '분석' },
341
+ { step: 4, action: 'respond', description: '응답' },
342
+ ],
343
+ fileStructure: [{ path: 'skills/code-review/index.ts', purpose: '메인' }],
344
+ toolsRequired: ['Read', 'discord_send'],
345
+ estimatedComplexity: 'medium',
346
+ };
347
+
348
+ const request = {
349
+ name: 'code-review',
350
+ description: '코드 리뷰',
351
+ triggers: ['/review'],
352
+ capabilities: ['분석'],
353
+ rawInput: '/forge code-review',
354
+ };
355
+
356
+ const output = await agent.develop(archOutput, request);
357
+ console.log(`✅ Generated ${output.files.length} files`);
358
+ output.files.forEach((f) => console.log(` - ${f.path}`));
359
+ }
360
+
361
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`;
362
+ if (isMainModule) {
363
+ runTest();
364
+ }