briyah 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/.prettierrc +7 -0
  2. package/dist/ai/LLM/anthropic.module.d.ts +2 -0
  3. package/dist/ai/LLM/anthropic.module.js +21 -0
  4. package/dist/ai/LLM/anthropic.service.d.ts +27 -0
  5. package/dist/ai/LLM/anthropic.service.js +329 -0
  6. package/dist/ai/LLM/base-ai.service.d.ts +45 -0
  7. package/dist/ai/LLM/base-ai.service.js +409 -0
  8. package/dist/ai/LLM/deepseek.module.d.ts +2 -0
  9. package/dist/ai/LLM/deepseek.module.js +21 -0
  10. package/dist/ai/LLM/deepseek.service.d.ts +15 -0
  11. package/dist/ai/LLM/deepseek.service.js +279 -0
  12. package/dist/ai/LLM/fal.module.d.ts +2 -0
  13. package/dist/ai/LLM/fal.module.js +21 -0
  14. package/dist/ai/LLM/fal.service.d.ts +17 -0
  15. package/dist/ai/LLM/fal.service.js +314 -0
  16. package/dist/ai/LLM/googleai.module.d.ts +2 -0
  17. package/dist/ai/LLM/googleai.module.js +21 -0
  18. package/dist/ai/LLM/googleai.service.d.ts +20 -0
  19. package/dist/ai/LLM/googleai.service.js +271 -0
  20. package/dist/ai/LLM/grok.module.d.ts +2 -0
  21. package/dist/ai/LLM/grok.module.js +21 -0
  22. package/dist/ai/LLM/grok.service.d.ts +14 -0
  23. package/dist/ai/LLM/grok.service.js +263 -0
  24. package/dist/ai/LLM/mock.module.d.ts +2 -0
  25. package/dist/ai/LLM/mock.module.js +21 -0
  26. package/dist/ai/LLM/mock.service.d.ts +13 -0
  27. package/dist/ai/LLM/mock.service.js +194 -0
  28. package/dist/ai/LLM/openai.module.d.ts +2 -0
  29. package/dist/ai/LLM/openai.module.js +21 -0
  30. package/dist/ai/LLM/openai.service.d.ts +21 -0
  31. package/dist/ai/LLM/openai.service.js +421 -0
  32. package/dist/ai/LLM/together.module.d.ts +2 -0
  33. package/dist/ai/LLM/together.module.js +21 -0
  34. package/dist/ai/LLM/together.service.d.ts +18 -0
  35. package/dist/ai/LLM/together.service.js +285 -0
  36. package/dist/ai/LLM/vertexai.module.d.ts +2 -0
  37. package/dist/ai/LLM/vertexai.module.js +21 -0
  38. package/dist/ai/LLM/vertexai.service.d.ts +17 -0
  39. package/dist/ai/LLM/vertexai.service.js +323 -0
  40. package/dist/ai/agent-config.d.ts +32 -0
  41. package/dist/ai/agent-config.js +2 -0
  42. package/dist/ai/agent-factory.d.ts +15 -0
  43. package/dist/ai/agent-factory.js +24 -0
  44. package/dist/ai/agent-message.service.d.ts +9 -0
  45. package/dist/ai/agent-message.service.js +56 -0
  46. package/dist/ai/agent-store.module.d.ts +2 -0
  47. package/dist/ai/agent-store.module.js +21 -0
  48. package/dist/ai/agent-store.service.d.ts +31 -0
  49. package/dist/ai/agent-store.service.js +352 -0
  50. package/dist/ai/agent.d.ts +75 -0
  51. package/dist/ai/agent.js +174 -0
  52. package/dist/ai/ai-factory.module.d.ts +2 -0
  53. package/dist/ai/ai-factory.module.js +40 -0
  54. package/dist/ai/ai-factory.service.d.ts +24 -0
  55. package/dist/ai/ai-factory.service.js +94 -0
  56. package/dist/ai/artifact.module.d.ts +2 -0
  57. package/dist/ai/artifact.module.js +22 -0
  58. package/dist/ai/artifact.service.d.ts +21 -0
  59. package/dist/ai/artifact.service.js +239 -0
  60. package/dist/ai/attached-file.module.d.ts +2 -0
  61. package/dist/ai/attached-file.module.js +22 -0
  62. package/dist/ai/attached-file.service.d.ts +35 -0
  63. package/dist/ai/attached-file.service.js +253 -0
  64. package/dist/ai/model_prices.d.ts +2 -0
  65. package/dist/ai/model_prices.js +54 -0
  66. package/dist/ai/published-agents.service.d.ts +13 -0
  67. package/dist/ai/published-agents.service.js +118 -0
  68. package/dist/app/balance-message.service.d.ts +8 -0
  69. package/dist/app/balance-message.service.js +45 -0
  70. package/dist/app/balance.module.d.ts +2 -0
  71. package/dist/app/balance.module.js +20 -0
  72. package/dist/app/balance.service.d.ts +18 -0
  73. package/dist/app/balance.service.js +158 -0
  74. package/dist/app/stripe.controller.d.ts +31 -0
  75. package/dist/app/stripe.controller.js +150 -0
  76. package/dist/app/stripe.module.d.ts +2 -0
  77. package/dist/app/stripe.module.js +22 -0
  78. package/dist/app/stripe.service.d.ts +28 -0
  79. package/dist/app/stripe.service.js +198 -0
  80. package/dist/app/transaction.service.d.ts +15 -0
  81. package/dist/app/transaction.service.js +139 -0
  82. package/dist/app/user-service-factory.d.ts +21 -0
  83. package/dist/app/user-service-factory.js +81 -0
  84. package/dist/app/user-service-manager.d.ts +28 -0
  85. package/dist/app/user-service-manager.js +102 -0
  86. package/dist/app.controller.d.ts +232 -0
  87. package/dist/app.controller.js +2536 -0
  88. package/dist/app.module.d.ts +2 -0
  89. package/dist/app.module.js +45 -0
  90. package/dist/app.service.d.ts +186 -0
  91. package/dist/app.service.js +1334 -0
  92. package/dist/auth/agent-access.decorator.d.ts +2 -0
  93. package/dist/auth/agent-access.decorator.js +10 -0
  94. package/dist/auth/auth.controller.d.ts +38 -0
  95. package/dist/auth/auth.controller.js +356 -0
  96. package/dist/auth/auth.module.d.ts +2 -0
  97. package/dist/auth/auth.module.js +55 -0
  98. package/dist/auth/auth.service.d.ts +14 -0
  99. package/dist/auth/auth.service.js +84 -0
  100. package/dist/auth/dto/bot-login.dto.d.ts +4 -0
  101. package/dist/auth/dto/bot-login.dto.js +2 -0
  102. package/dist/auth/dto/password-reset.dto.d.ts +11 -0
  103. package/dist/auth/dto/password-reset.dto.js +2 -0
  104. package/dist/auth/dto/phone-login.dto.d.ts +8 -0
  105. package/dist/auth/dto/phone-login.dto.js +2 -0
  106. package/dist/auth/dto/phone-verification.dto.d.ts +9 -0
  107. package/dist/auth/dto/phone-verification.dto.js +2 -0
  108. package/dist/auth/jwt-auth.guard.d.ts +13 -0
  109. package/dist/auth/jwt-auth.guard.js +143 -0
  110. package/dist/auth/jwt.strategy.d.ts +17 -0
  111. package/dist/auth/jwt.strategy.js +45 -0
  112. package/dist/auth/phone-validation.service.d.ts +7 -0
  113. package/dist/auth/phone-validation.service.js +50 -0
  114. package/dist/auth/public.decorator.d.ts +2 -0
  115. package/dist/auth/public.decorator.js +7 -0
  116. package/dist/auth/rate-limit.service.d.ts +16 -0
  117. package/dist/auth/rate-limit.service.js +84 -0
  118. package/dist/auth/room-access.decorator.d.ts +2 -0
  119. package/dist/auth/room-access.decorator.js +10 -0
  120. package/dist/auth/scopes.decorator.d.ts +2 -0
  121. package/dist/auth/scopes.decorator.js +7 -0
  122. package/dist/auth/scopes.guard.d.ts +9 -0
  123. package/dist/auth/scopes.guard.js +82 -0
  124. package/dist/auth/session.guard.d.ts +7 -0
  125. package/dist/auth/session.guard.js +55 -0
  126. package/dist/auth/twilio.service.d.ts +15 -0
  127. package/dist/auth/twilio.service.js +139 -0
  128. package/dist/auth/users.service.d.ts +24 -0
  129. package/dist/auth/users.service.js +149 -0
  130. package/dist/common/errors.d.ts +12 -0
  131. package/dist/common/errors.js +43 -0
  132. package/dist/config/configuration.module.d.ts +2 -0
  133. package/dist/config/configuration.module.js +20 -0
  134. package/dist/config/configuration.service.d.ts +26 -0
  135. package/dist/config/configuration.service.js +131 -0
  136. package/dist/main.js +15749 -0
  137. package/dist/room/artifact-store.service.d.ts +15 -0
  138. package/dist/room/artifact-store.service.js +226 -0
  139. package/dist/room/artifact.d.ts +6 -0
  140. package/dist/room/artifact.js +2 -0
  141. package/dist/room/message.d.ts +19 -0
  142. package/dist/room/message.js +70 -0
  143. package/dist/room/published-rooms.service.d.ts +12 -0
  144. package/dist/room/published-rooms.service.js +108 -0
  145. package/dist/room/room-config.d.ts +12 -0
  146. package/dist/room/room-config.js +2 -0
  147. package/dist/room/room-factory.d.ts +7 -0
  148. package/dist/room/room-factory.js +16 -0
  149. package/dist/room/room-message.module.d.ts +2 -0
  150. package/dist/room/room-message.module.js +21 -0
  151. package/dist/room/room-message.service.d.ts +8 -0
  152. package/dist/room/room-message.service.js +44 -0
  153. package/dist/room/room-store.module.d.ts +2 -0
  154. package/dist/room/room-store.module.js +25 -0
  155. package/dist/room/room-store.service.d.ts +38 -0
  156. package/dist/room/room-store.service.js +353 -0
  157. package/dist/room/room.d.ts +107 -0
  158. package/dist/room/room.js +833 -0
  159. package/dist/sdk/briyah-config.d.ts +13 -0
  160. package/dist/sdk/briyah-config.js +32 -0
  161. package/dist/sdk/briyah.d.ts +36 -0
  162. package/dist/sdk/briyah.js +122 -0
  163. package/dist/sdk/index.d.ts +6 -0
  164. package/dist/sdk/index.js +11 -0
  165. package/dist/server/src/ai/LLM/anthropic.module.d.ts +2 -0
  166. package/dist/server/src/ai/LLM/anthropic.module.js +21 -0
  167. package/dist/server/src/ai/LLM/anthropic.service.d.ts +27 -0
  168. package/dist/server/src/ai/LLM/anthropic.service.js +329 -0
  169. package/dist/server/src/ai/LLM/base-ai.service.d.ts +45 -0
  170. package/dist/server/src/ai/LLM/base-ai.service.js +409 -0
  171. package/dist/server/src/ai/LLM/deepseek.module.d.ts +2 -0
  172. package/dist/server/src/ai/LLM/deepseek.module.js +21 -0
  173. package/dist/server/src/ai/LLM/deepseek.service.d.ts +15 -0
  174. package/dist/server/src/ai/LLM/deepseek.service.js +279 -0
  175. package/dist/server/src/ai/LLM/fal.module.d.ts +2 -0
  176. package/dist/server/src/ai/LLM/fal.module.js +21 -0
  177. package/dist/server/src/ai/LLM/fal.service.d.ts +17 -0
  178. package/dist/server/src/ai/LLM/fal.service.js +314 -0
  179. package/dist/server/src/ai/LLM/googleai.module.d.ts +2 -0
  180. package/dist/server/src/ai/LLM/googleai.module.js +21 -0
  181. package/dist/server/src/ai/LLM/googleai.service.d.ts +20 -0
  182. package/dist/server/src/ai/LLM/googleai.service.js +271 -0
  183. package/dist/server/src/ai/LLM/grok.module.d.ts +2 -0
  184. package/dist/server/src/ai/LLM/grok.module.js +21 -0
  185. package/dist/server/src/ai/LLM/grok.service.d.ts +14 -0
  186. package/dist/server/src/ai/LLM/grok.service.js +263 -0
  187. package/dist/server/src/ai/LLM/mock.module.d.ts +2 -0
  188. package/dist/server/src/ai/LLM/mock.module.js +21 -0
  189. package/dist/server/src/ai/LLM/mock.service.d.ts +13 -0
  190. package/dist/server/src/ai/LLM/mock.service.js +194 -0
  191. package/dist/server/src/ai/LLM/openai.module.d.ts +2 -0
  192. package/dist/server/src/ai/LLM/openai.module.js +21 -0
  193. package/dist/server/src/ai/LLM/openai.service.d.ts +21 -0
  194. package/dist/server/src/ai/LLM/openai.service.js +421 -0
  195. package/dist/server/src/ai/LLM/together.module.d.ts +2 -0
  196. package/dist/server/src/ai/LLM/together.module.js +21 -0
  197. package/dist/server/src/ai/LLM/together.service.d.ts +18 -0
  198. package/dist/server/src/ai/LLM/together.service.js +285 -0
  199. package/dist/server/src/ai/LLM/vertexai.module.d.ts +2 -0
  200. package/dist/server/src/ai/LLM/vertexai.module.js +21 -0
  201. package/dist/server/src/ai/LLM/vertexai.service.d.ts +17 -0
  202. package/dist/server/src/ai/LLM/vertexai.service.js +323 -0
  203. package/dist/server/src/ai/agent-config.d.ts +32 -0
  204. package/dist/server/src/ai/agent-config.js +2 -0
  205. package/dist/server/src/ai/agent-factory.d.ts +15 -0
  206. package/dist/server/src/ai/agent-factory.js +24 -0
  207. package/dist/server/src/ai/agent-message.service.d.ts +9 -0
  208. package/dist/server/src/ai/agent-message.service.js +56 -0
  209. package/dist/server/src/ai/agent-store.module.d.ts +2 -0
  210. package/dist/server/src/ai/agent-store.module.js +21 -0
  211. package/dist/server/src/ai/agent-store.service.d.ts +31 -0
  212. package/dist/server/src/ai/agent-store.service.js +352 -0
  213. package/dist/server/src/ai/agent.d.ts +75 -0
  214. package/dist/server/src/ai/agent.js +174 -0
  215. package/dist/server/src/ai/ai-factory.module.d.ts +2 -0
  216. package/dist/server/src/ai/ai-factory.module.js +40 -0
  217. package/dist/server/src/ai/ai-factory.service.d.ts +24 -0
  218. package/dist/server/src/ai/ai-factory.service.js +94 -0
  219. package/dist/server/src/ai/artifact.module.d.ts +2 -0
  220. package/dist/server/src/ai/artifact.module.js +22 -0
  221. package/dist/server/src/ai/artifact.service.d.ts +21 -0
  222. package/dist/server/src/ai/artifact.service.js +239 -0
  223. package/dist/server/src/ai/attached-file.module.d.ts +2 -0
  224. package/dist/server/src/ai/attached-file.module.js +22 -0
  225. package/dist/server/src/ai/attached-file.service.d.ts +35 -0
  226. package/dist/server/src/ai/attached-file.service.js +253 -0
  227. package/dist/server/src/ai/model_prices.d.ts +2 -0
  228. package/dist/server/src/ai/model_prices.js +54 -0
  229. package/dist/server/src/ai/published-agents.service.d.ts +13 -0
  230. package/dist/server/src/ai/published-agents.service.js +118 -0
  231. package/dist/server/src/app/balance-message.service.d.ts +8 -0
  232. package/dist/server/src/app/balance-message.service.js +45 -0
  233. package/dist/server/src/app/balance.module.d.ts +2 -0
  234. package/dist/server/src/app/balance.module.js +20 -0
  235. package/dist/server/src/app/balance.service.d.ts +18 -0
  236. package/dist/server/src/app/balance.service.js +158 -0
  237. package/dist/server/src/app/stripe.controller.d.ts +31 -0
  238. package/dist/server/src/app/stripe.controller.js +148 -0
  239. package/dist/server/src/app/stripe.module.d.ts +2 -0
  240. package/dist/server/src/app/stripe.module.js +22 -0
  241. package/dist/server/src/app/stripe.service.d.ts +28 -0
  242. package/dist/server/src/app/stripe.service.js +198 -0
  243. package/dist/server/src/app/transaction.service.d.ts +15 -0
  244. package/dist/server/src/app/transaction.service.js +139 -0
  245. package/dist/server/src/app/user-service-factory.d.ts +21 -0
  246. package/dist/server/src/app/user-service-factory.js +81 -0
  247. package/dist/server/src/app/user-service-manager.d.ts +28 -0
  248. package/dist/server/src/app/user-service-manager.js +102 -0
  249. package/dist/server/src/app.controller.d.ts +232 -0
  250. package/dist/server/src/app.controller.js +2534 -0
  251. package/dist/server/src/app.module.d.ts +2 -0
  252. package/dist/server/src/app.module.js +45 -0
  253. package/dist/server/src/app.service.d.ts +186 -0
  254. package/dist/server/src/app.service.js +1334 -0
  255. package/dist/server/src/auth/agent-access.decorator.d.ts +2 -0
  256. package/dist/server/src/auth/agent-access.decorator.js +10 -0
  257. package/dist/server/src/auth/auth.controller.d.ts +38 -0
  258. package/dist/server/src/auth/auth.controller.js +356 -0
  259. package/dist/server/src/auth/auth.module.d.ts +2 -0
  260. package/dist/server/src/auth/auth.module.js +55 -0
  261. package/dist/server/src/auth/auth.service.d.ts +14 -0
  262. package/dist/server/src/auth/auth.service.js +84 -0
  263. package/dist/server/src/auth/dto/bot-login.dto.d.ts +4 -0
  264. package/dist/server/src/auth/dto/bot-login.dto.js +2 -0
  265. package/dist/server/src/auth/dto/password-reset.dto.d.ts +11 -0
  266. package/dist/server/src/auth/dto/password-reset.dto.js +2 -0
  267. package/dist/server/src/auth/dto/phone-login.dto.d.ts +8 -0
  268. package/dist/server/src/auth/dto/phone-login.dto.js +2 -0
  269. package/dist/server/src/auth/dto/phone-verification.dto.d.ts +9 -0
  270. package/dist/server/src/auth/dto/phone-verification.dto.js +2 -0
  271. package/dist/server/src/auth/jwt-auth.guard.d.ts +13 -0
  272. package/dist/server/src/auth/jwt-auth.guard.js +143 -0
  273. package/dist/server/src/auth/jwt.strategy.d.ts +17 -0
  274. package/dist/server/src/auth/jwt.strategy.js +45 -0
  275. package/dist/server/src/auth/phone-validation.service.d.ts +7 -0
  276. package/dist/server/src/auth/phone-validation.service.js +50 -0
  277. package/dist/server/src/auth/public.decorator.d.ts +2 -0
  278. package/dist/server/src/auth/public.decorator.js +7 -0
  279. package/dist/server/src/auth/rate-limit.service.d.ts +16 -0
  280. package/dist/server/src/auth/rate-limit.service.js +84 -0
  281. package/dist/server/src/auth/room-access.decorator.d.ts +2 -0
  282. package/dist/server/src/auth/room-access.decorator.js +10 -0
  283. package/dist/server/src/auth/scopes.decorator.d.ts +2 -0
  284. package/dist/server/src/auth/scopes.decorator.js +7 -0
  285. package/dist/server/src/auth/scopes.guard.d.ts +9 -0
  286. package/dist/server/src/auth/scopes.guard.js +82 -0
  287. package/dist/server/src/auth/session.guard.d.ts +7 -0
  288. package/dist/server/src/auth/session.guard.js +55 -0
  289. package/dist/server/src/auth/twilio.service.d.ts +15 -0
  290. package/dist/server/src/auth/twilio.service.js +139 -0
  291. package/dist/server/src/auth/users.service.d.ts +24 -0
  292. package/dist/server/src/auth/users.service.js +149 -0
  293. package/dist/server/src/common/errors.d.ts +12 -0
  294. package/dist/server/src/common/errors.js +43 -0
  295. package/dist/server/src/config/configuration.module.d.ts +2 -0
  296. package/dist/server/src/config/configuration.module.js +20 -0
  297. package/dist/server/src/config/configuration.service.d.ts +26 -0
  298. package/dist/server/src/config/configuration.service.js +131 -0
  299. package/dist/server/src/room/artifact-store.service.d.ts +15 -0
  300. package/dist/server/src/room/artifact-store.service.js +226 -0
  301. package/dist/server/src/room/artifact.d.ts +6 -0
  302. package/dist/server/src/room/artifact.js +2 -0
  303. package/dist/server/src/room/message.d.ts +19 -0
  304. package/dist/server/src/room/message.js +70 -0
  305. package/dist/server/src/room/published-rooms.service.d.ts +12 -0
  306. package/dist/server/src/room/published-rooms.service.js +108 -0
  307. package/dist/server/src/room/room-config.d.ts +12 -0
  308. package/dist/server/src/room/room-config.js +2 -0
  309. package/dist/server/src/room/room-factory.d.ts +7 -0
  310. package/dist/server/src/room/room-factory.js +16 -0
  311. package/dist/server/src/room/room-message.module.d.ts +2 -0
  312. package/dist/server/src/room/room-message.module.js +21 -0
  313. package/dist/server/src/room/room-message.service.d.ts +8 -0
  314. package/dist/server/src/room/room-message.service.js +44 -0
  315. package/dist/server/src/room/room-store.module.d.ts +2 -0
  316. package/dist/server/src/room/room-store.module.js +25 -0
  317. package/dist/server/src/room/room-store.service.d.ts +38 -0
  318. package/dist/server/src/room/room-store.service.js +353 -0
  319. package/dist/server/src/room/room.d.ts +107 -0
  320. package/dist/server/src/room/room.js +833 -0
  321. package/dist/server/src/sdk/briyah-config.d.ts +13 -0
  322. package/dist/server/src/sdk/briyah-config.js +32 -0
  323. package/dist/server/src/sdk/briyah.d.ts +36 -0
  324. package/dist/server/src/sdk/briyah.js +122 -0
  325. package/dist/server/src/sdk/index.d.ts +6 -0
  326. package/dist/server/src/sdk/index.js +11 -0
  327. package/dist/server/src/shared/shared.module.d.ts +2 -0
  328. package/dist/server/src/shared/shared.module.js +46 -0
  329. package/dist/server/src/story/story-message.service.d.ts +10 -0
  330. package/dist/server/src/story/story-message.service.js +57 -0
  331. package/dist/server/src/story/story-progress.service.d.ts +8 -0
  332. package/dist/server/src/story/story-progress.service.js +44 -0
  333. package/dist/server/src/story/story-store.module.d.ts +2 -0
  334. package/dist/server/src/story/story-store.module.js +22 -0
  335. package/dist/server/src/story/story-store.service.d.ts +23 -0
  336. package/dist/server/src/story/story-store.service.js +392 -0
  337. package/dist/server/src/story/story.service.d.ts +94 -0
  338. package/dist/server/src/story/story.service.js +1797 -0
  339. package/dist/shared/shared.module.d.ts +2 -0
  340. package/dist/shared/shared.module.js +46 -0
  341. package/dist/shared/types/app.types.d.ts +296 -0
  342. package/dist/shared/types/app.types.js +17 -0
  343. package/dist/story/story-message.service.d.ts +10 -0
  344. package/dist/story/story-message.service.js +57 -0
  345. package/dist/story/story-progress.service.d.ts +8 -0
  346. package/dist/story/story-progress.service.js +44 -0
  347. package/dist/story/story-store.module.d.ts +2 -0
  348. package/dist/story/story-store.module.js +22 -0
  349. package/dist/story/story-store.service.d.ts +23 -0
  350. package/dist/story/story-store.service.js +392 -0
  351. package/dist/story/story.service.d.ts +94 -0
  352. package/dist/story/story.service.js +1797 -0
  353. package/eslint.config.js +29 -0
  354. package/package.json +125 -0
@@ -0,0 +1,1797 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.StoryService = void 0;
49
+ const common_1 = require("@nestjs/common");
50
+ const story_store_service_1 = require("./story-store.service");
51
+ const story_progress_service_1 = require("./story-progress.service");
52
+ const story_message_service_1 = require("./story-message.service");
53
+ const agent_store_service_1 = require("../ai/agent-store.service");
54
+ const agent_factory_1 = require("../ai/agent-factory");
55
+ const room_factory_1 = require("../room/room-factory");
56
+ const room_store_service_1 = require("../room/room-store.service");
57
+ const app_types_1 = require("@shared/types/app.types");
58
+ const configuration_service_1 = require("../config/configuration.service");
59
+ const artifact_service_1 = require("../ai/artifact.service");
60
+ const path = __importStar(require("path"));
61
+ const fs = __importStar(require("fs"));
62
+ const archiver_1 = __importDefault(require("archiver"));
63
+ const yauzl = __importStar(require("yauzl"));
64
+ const message_1 = require("../room/message");
65
+ const errors_1 = require("../common/errors");
66
+ let StoryService = class StoryService {
67
+ storyStore;
68
+ agentStore;
69
+ roomStore;
70
+ progressService;
71
+ messageService;
72
+ configService;
73
+ agentFactory;
74
+ roomFactory;
75
+ storyArtifactServices = new Map();
76
+ constructor(storyStore, agentStore, roomStore, progressService, messageService, configService, agentFactory, roomFactory) {
77
+ this.storyStore = storyStore;
78
+ this.agentStore = agentStore;
79
+ this.roomStore = roomStore;
80
+ this.progressService = progressService;
81
+ this.messageService = messageService;
82
+ this.configService = configService;
83
+ this.agentFactory = agentFactory;
84
+ this.roomFactory = roomFactory;
85
+ }
86
+ getProgressEmitter(storyId) {
87
+ return this.progressService.getProgressEmitter(storyId);
88
+ }
89
+ getMessageEmitter(storyId) {
90
+ return this.messageService.getOrCreateEmitter(storyId);
91
+ }
92
+ cleanupProgressEmitter(storyId) {
93
+ this.progressService.cleanup(storyId);
94
+ }
95
+ cleanupMessageEmitter(storyId) {
96
+ this.messageService.cleanup(storyId);
97
+ }
98
+ getStoryArtifactService(storyId) {
99
+ let artifactService = this.storyArtifactServices.get(storyId);
100
+ if (!artifactService) {
101
+ const { artifactsDir } = this.getStoryStorageDirs(storyId);
102
+ artifactService = new artifact_service_1.ArtifactService(this.configService, artifactsDir);
103
+ this.storyArtifactServices.set(storyId, artifactService);
104
+ }
105
+ return artifactService;
106
+ }
107
+ async emitStoryStateUpdate(storyId) {
108
+ try {
109
+ let story = await this.ensureStoryLoaded(storyId);
110
+ if (!story) {
111
+ console.error(`Story ${storyId} not found for state update`);
112
+ return;
113
+ }
114
+ const room = await this.roomStore.getRoom(story.roomId);
115
+ if (!room) {
116
+ console.error(`Room ${story.roomId} not found for story ${storyId}`);
117
+ return;
118
+ }
119
+ await this.updateStoryCost(storyId);
120
+ story = await this.getStoryInfo(storyId);
121
+ const humanAgent = room.getAgents().find((agent) => agent.isControlledByHuman);
122
+ if (!humanAgent) {
123
+ console.error(`No human agent found for story ${storyId}`);
124
+ return;
125
+ }
126
+ const roomMessages = room.getLatestRoomMessages(0, true);
127
+ const latestMessage = roomMessages[roomMessages.length - 1];
128
+ const currentSpeaker = room.getCurrentSpeaker();
129
+ const humanPrompt = this.getHumanPrompt(room);
130
+ const stateUpdate = {
131
+ storyId: story.id,
132
+ latestRoomMessage: latestMessage,
133
+ userAgentName: humanAgent.agentNickname,
134
+ humanPrompt: humanPrompt,
135
+ currentSpeaker: currentSpeaker,
136
+ totalCost: story.totalCost || 0,
137
+ totalInputTokens: story.totalInputTokens || 0,
138
+ totalOutputTokens: story.totalOutputTokens || 0,
139
+ };
140
+ this.messageService.emitUpdate(storyId, {
141
+ type: 'state',
142
+ state: stateUpdate
143
+ });
144
+ }
145
+ catch (error) {
146
+ console.error(`Error emitting story state update for ${storyId}:`, error);
147
+ }
148
+ }
149
+ getHumanPrompt(room) {
150
+ const humanAgent = room.getAgents().find((a) => a.isControlledByHuman);
151
+ if (!humanAgent) {
152
+ return '';
153
+ }
154
+ if (room.getCurrentSpeaker() === humanAgent.agentNickname) {
155
+ return `What does ${humanAgent.agentNickname} do or say next?`;
156
+ }
157
+ else if (room.getCurrentSpeaker() !== null) {
158
+ return `Waiting for ${room.getCurrentSpeaker()}...`;
159
+ }
160
+ else if (room.isProcessingInProgress()) {
161
+ return 'Processing...';
162
+ }
163
+ else {
164
+ return '';
165
+ }
166
+ }
167
+ handleRoomError(storyId, error) {
168
+ console.log(`Room error for story ${storyId}: ${error.name} - ${error.message}`);
169
+ this.messageService.emitError(storyId, error);
170
+ }
171
+ getRandomWord() {
172
+ const randomWordsPath = path.join(this.configService.getCommonConfigDir(), 'random_words.txt');
173
+ const content = fs.readFileSync(randomWordsPath, 'utf-8');
174
+ const words = content.split('\n').filter((word) => word.trim().length > 0);
175
+ const randomIndex = Math.floor(Math.random() * words.length);
176
+ return words[randomIndex];
177
+ }
178
+ getStoryStorageDirs(storyId) {
179
+ const userStoriesDir = path.join(this.configService.getUserDataDir(), 'stories');
180
+ return {
181
+ agentsDir: path.join(userStoriesDir, storyId, 'agents'),
182
+ roomsDir: path.join(userStoriesDir, storyId, 'rooms'),
183
+ artifactsDir: path.join(userStoriesDir, storyId, 'artifacts'),
184
+ };
185
+ }
186
+ getStoryModelConfig(storyModel) {
187
+ const storyModelsPath = path.join(this.configService.getCommonConfigDir(), 'story_models.json');
188
+ try {
189
+ const storyModels = JSON.parse(fs.readFileSync(storyModelsPath, 'utf8'));
190
+ const modelConfig = storyModels.find((m) => m.name === storyModel);
191
+ if (modelConfig) {
192
+ return {
193
+ service: modelConfig.service,
194
+ model: modelConfig.model,
195
+ };
196
+ }
197
+ console.warn(`Story model "${storyModel}" not found in story_models.json`);
198
+ return null;
199
+ }
200
+ catch (error) {
201
+ console.error(`Error reading story_models.json:`, error);
202
+ return null;
203
+ }
204
+ }
205
+ async getStoryRoom(storyId) {
206
+ const story = await this.ensureStoryLoaded(storyId);
207
+ if (!story) {
208
+ throw new Error('Story not found');
209
+ }
210
+ const room = await this.roomStore.getRoom(story.roomId);
211
+ if (!room) {
212
+ throw new Error('Story room not found');
213
+ }
214
+ return room;
215
+ }
216
+ async ensureStoryLoaded(storyId) {
217
+ const story = this.storyStore.getStory(storyId);
218
+ if (!story)
219
+ return null;
220
+ if (!story.roomId) {
221
+ console.error(`Story ${storyId} has no roomId. Deleting story from storage...`);
222
+ this.storyStore.removeStory(storyId);
223
+ return null;
224
+ }
225
+ let room = await this.roomStore.getRoom(story.roomId);
226
+ if (room) {
227
+ return story;
228
+ }
229
+ const { agentsDir, roomsDir } = this.getStoryStorageDirs(storyId);
230
+ const storyArtifactService = this.getStoryArtifactService(storyId);
231
+ await this.agentStore.loadAgentsFromDirectory(agentsDir, storyArtifactService);
232
+ await this.roomStore.loadRoomsFromDirectory(roomsDir);
233
+ room = await this.roomStore.getRoom(story.roomId);
234
+ if (room) {
235
+ room.setOnStateChange(() => {
236
+ this.emitStoryStateUpdate(storyId);
237
+ });
238
+ room.setOnError((error) => {
239
+ this.handleRoomError(storyId, error);
240
+ });
241
+ room.setOnSituationUpdate((situation) => {
242
+ this.updateStorySituation(storyId, situation);
243
+ });
244
+ if (story.situation) {
245
+ room.setSituation(story.situation);
246
+ }
247
+ }
248
+ return story;
249
+ }
250
+ async getStoryInfo(storyId) {
251
+ return this.storyStore.getStory(storyId);
252
+ }
253
+ async createStory(name, idea, userCharacterDesc, otherCharactersDesc, storyModel, isImport = false, imageModelName) {
254
+ if (!name || name.trim().length === 0) {
255
+ throw new Error('Story name is required');
256
+ }
257
+ const storyInfo = this.storyStore.createStory(name);
258
+ storyInfo.turnNumber = 0;
259
+ try {
260
+ this.progressService.createProgressEmitter(storyInfo.id);
261
+ this.progressService.emitProgress(storyInfo.id, 'start', 'Starting story creation...');
262
+ const { agentsDir: storyAgentsDir, roomsDir: storyRoomsDir } = this.getStoryStorageDirs(storyInfo.id);
263
+ const storyArtifactService = this.getStoryArtifactService(storyInfo.id);
264
+ let aiServiceName;
265
+ let aiModelName;
266
+ if (!storyModel || storyModel.trim().length === 0)
267
+ storyModel = process.env.DEFAULT_STORY_MODEL;
268
+ const modelConfig = this.getStoryModelConfig(storyModel);
269
+ if (modelConfig) {
270
+ aiServiceName = modelConfig.service;
271
+ aiModelName = modelConfig.model;
272
+ }
273
+ if (!aiServiceName || !aiModelName)
274
+ throw new Error(`Failed to find model config for "${storyModel}"`);
275
+ let moderator = this.agentFactory.createAgent(process.env.MODERATOR_AI_SERVICE || aiServiceName, 'Moderator', '', 'Story moderator responsible for message routing and conversation flow', 'story_moderator', process.env.MODERATOR_AI_MODEL || aiModelName, storyAgentsDir, storyArtifactService);
276
+ moderator.maxHistoryMessages = 16;
277
+ moderator.reasoningEffort = 'low';
278
+ moderator.promptCacheTTL = 60;
279
+ moderator.ownerRoomId = storyInfo.id;
280
+ moderator.markupRate = 0;
281
+ moderator.save();
282
+ console.log(`Created moderator agent: ${moderator.agentName}`);
283
+ const artist = this.createArtistAgent(storyInfo.id, storyAgentsDir, storyArtifactService, imageModelName);
284
+ let illustrator = null;
285
+ if (artist) {
286
+ illustrator = this.agentFactory.createAgent(process.env.MODERATOR_AI_SERVICE || aiServiceName, 'Illustrator', '', 'Visual artist for generating scene illustrations', 'illustrator', process.env.MODERATOR_AI_MODEL || aiModelName, storyAgentsDir, storyArtifactService);
287
+ illustrator.maxHistoryMessages = 10;
288
+ illustrator.promptCacheTTL = 60;
289
+ illustrator.ownerRoomId = storyInfo.id;
290
+ illustrator.save();
291
+ console.log(`Created illustrator agent: ${illustrator.agentName}`);
292
+ }
293
+ let narrator = this.agentFactory.createAgent(aiServiceName, 'Narrator', '', 'Story narrator. Should receive all messages where a character wants to perform an action or PASS or INTRODUCE a new character. Responds to all dialog with characters not listed in Available Agents.', 'narrator', aiModelName, storyAgentsDir, storyArtifactService);
294
+ narrator.reasoningEffort = 'low';
295
+ narrator.allowSearch = true;
296
+ narrator.promptCacheTTL = 60;
297
+ narrator.ownerRoomId = storyInfo.id;
298
+ narrator.save();
299
+ console.log(`Created narrator agent: ${narrator.agentName}`);
300
+ narrator.disableMarkup = true;
301
+ narrator.disableBalanceCheck = true;
302
+ narrator.save();
303
+ this.progressService.emitProgress(storyInfo.id, 'opening-scene', 'Generating opening scene...');
304
+ const storyFrameworkPromptName = isImport ? 'import_story' : 'create_story';
305
+ const storyFrameworkResponse = await narrator.preparedPrompt(storyFrameworkPromptName, {
306
+ name,
307
+ idea,
308
+ userCharacterDesc,
309
+ otherCharactersDesc,
310
+ randomNumber: Math.floor(Math.random() * 100),
311
+ randomWord: this.getRandomWord(),
312
+ }, false);
313
+ const scenario = storyFrameworkResponse.scenario;
314
+ const openingScene = storyFrameworkResponse.openingScene;
315
+ const userCharacterInfo = storyFrameworkResponse.userCharacter;
316
+ const userCharacterBackstory = userCharacterInfo.backstory;
317
+ const otherCharactersInfo = storyFrameworkResponse.otherCharacters || [];
318
+ let importedStoryText = '';
319
+ if (isImport) {
320
+ importedStoryText = idea;
321
+ }
322
+ console.log(`Story framework extracted: ${otherCharactersInfo.length} other characters`);
323
+ const characters = [
324
+ {
325
+ name: userCharacterInfo.name,
326
+ sex: userCharacterInfo.sex,
327
+ description: userCharacterInfo.description,
328
+ isControlledByHuman: true,
329
+ },
330
+ ...otherCharactersInfo.map((char) => ({
331
+ name: char.name,
332
+ sex: char.sex,
333
+ description: char.description,
334
+ isControlledByHuman: false,
335
+ })),
336
+ ];
337
+ storyInfo.scenario = scenario;
338
+ storyInfo.characters = characters;
339
+ storyInfo.aiService = aiServiceName;
340
+ storyInfo.aiModel = aiModelName;
341
+ storyInfo.isImport = isImport;
342
+ this.storyStore.updateStoryMetadata(storyInfo.id, storyInfo);
343
+ this.storyStore.saveStoryCreationParameters(storyInfo.id, idea, userCharacterDesc, otherCharactersDesc);
344
+ const userCharacterName = userCharacterInfo.name || 'Player';
345
+ const userNickname = userCharacterName.trim().split(/\s+/)[0];
346
+ let userAgent = null;
347
+ try {
348
+ userAgent = this.agentFactory.createAgent(aiServiceName, `${name} - ${userNickname}`, userNickname, userCharacterInfo.description || userCharacterDesc, 'character', aiModelName, storyAgentsDir, storyArtifactService);
349
+ userAgent.isControlledByHuman = true;
350
+ userAgent.ownerRoomId = storyInfo.id;
351
+ userAgent.save();
352
+ console.log(`Created human-controlled character agent: ${userCharacterName}`);
353
+ userAgent.disableMarkup = true;
354
+ userAgent.disableBalanceCheck = true;
355
+ userAgent.save();
356
+ }
357
+ catch (error) {
358
+ console.error('Error creating user character:', error);
359
+ throw error;
360
+ }
361
+ const characterAgents = [];
362
+ for (let i = 0; i < otherCharactersInfo.length; i++) {
363
+ const charInfo = otherCharactersInfo[i];
364
+ const characterNickname = charInfo.name.trim().split(/\s+/)[0];
365
+ try {
366
+ const agent = this.agentFactory.createAgent(aiServiceName, `${name} - ${characterNickname}`, characterNickname, charInfo.description, 'character', aiModelName, storyAgentsDir, storyArtifactService);
367
+ agent.promptCacheTTL = 60;
368
+ agent.ownerRoomId = storyInfo.id;
369
+ agent.save();
370
+ console.log(`Created character agent: ${charInfo.name}`);
371
+ agent.disableMarkup = true;
372
+ agent.disableBalanceCheck = true;
373
+ agent.save();
374
+ characterAgents.push(agent);
375
+ }
376
+ catch (error) {
377
+ console.error(`Error creating character ${charInfo.name}:`, error);
378
+ }
379
+ }
380
+ console.log(`Created ${characterAgents.length + (userAgent ? 1 : 0)} character agents`);
381
+ const room = this.roomFactory.createRoom(`Story: ${name}`, scenario, '', storyRoomsDir);
382
+ room.arrive(moderator);
383
+ room.arrive(narrator);
384
+ if (userAgent) {
385
+ room.arrive(userAgent);
386
+ }
387
+ for (const characterAgent of characterAgents) {
388
+ room.arrive(characterAgent);
389
+ }
390
+ room.setRoomLeader(narrator.agentNickname);
391
+ room.setCurrentSpeaker(narrator.agentNickname);
392
+ room.setSituation(scenario || 'Story beginning');
393
+ const roomId = room.saveMetadata();
394
+ room.addRoomMessages([
395
+ new message_1.RoomMessage(`${userCharacterName}'s Backstory`, app_types_1.MessageAction.SYSTEM, userCharacterBackstory),
396
+ ]);
397
+ this.populateStoryHistory(room, openingScene);
398
+ const totalCharacters = (userAgent ? 1 : 0) + characterAgents.length;
399
+ console.log(`Created story room: ${roomId} with moderator, narrator, and ${totalCharacters} character agents`);
400
+ if (userAgent) {
401
+ room.setCurrentSpeaker(userAgent.agentNickname);
402
+ }
403
+ room.setOnStateChange(() => {
404
+ this.emitStoryStateUpdate(storyInfo.id);
405
+ });
406
+ room.setOnError((error) => {
407
+ this.handleRoomError(storyInfo.id, error);
408
+ });
409
+ room.setOnSituationUpdate((situation) => {
410
+ this.updateStorySituation(storyInfo.id, situation);
411
+ });
412
+ storyInfo.roomId = roomId;
413
+ storyInfo.moderatorAgentId = moderator.id;
414
+ storyInfo.illustratorAgentId = illustrator?.id;
415
+ storyInfo.artistAgentId = artist?.id;
416
+ storyInfo.imageModelName = imageModelName;
417
+ if (userAgent) {
418
+ storyInfo.userAgentId = userAgent.id;
419
+ }
420
+ this.storyStore.updateStoryMetadata(storyInfo.id, storyInfo);
421
+ await this.updateStoryCost(storyInfo.id);
422
+ room.ready();
423
+ setImmediate(() => {
424
+ this.createStoryAsync(storyInfo.id, name, importedStoryText, isImport).catch((error) => {
425
+ console.error('Error in async story creation:', error);
426
+ this.progressService.emitProgress(storyInfo.id, 'error', `Error: ${error.message}`);
427
+ this.progressService.cleanup(storyInfo.id);
428
+ this.deleteStory(storyInfo.id).catch((cleanupError) => {
429
+ console.error('Error cleaning up story after async failure:', cleanupError);
430
+ });
431
+ });
432
+ });
433
+ return storyInfo;
434
+ }
435
+ catch (error) {
436
+ console.error('Error creating story:', error);
437
+ this.progressService.emitProgress(storyInfo.id, 'error', `Error: ${error.message}`);
438
+ this.progressService.cleanup(storyInfo.id);
439
+ await this.deleteStory(storyInfo.id);
440
+ throw error;
441
+ }
442
+ }
443
+ async createStoryAsync(storyId, name, importedStoryText, isImport) {
444
+ try {
445
+ const room = await this.getStoryRoom(storyId);
446
+ const storyInfo = this.storyStore.getStory(storyId);
447
+ const plotPromptName = isImport ? 'import_plot' : 'create_plot';
448
+ const userCharPromptName = isImport ? 'import_user_character' : 'create_user_character';
449
+ const characterPromptName = isImport ? 'import_character' : 'create_character';
450
+ this.progressService.emitProgress(storyInfo.id, 'profiles', 'Generating detailed profiles and plot...');
451
+ const narrator = room.getAgents().find((a) => a.agentNickname === 'Narrator');
452
+ const userAgent = room.getAgents().find((a) => a.isControlledByHuman === true);
453
+ const userCharacter = storyInfo.characters.find((c) => c.isControlledByHuman === true);
454
+ const otherCharacters = storyInfo.characters
455
+ .filter((c) => c.isControlledByHuman === false)
456
+ .map((c) => `${c.name}: ${c.description}.`)
457
+ .join('\n');
458
+ let plotPlan = '';
459
+ const phase1Results = await Promise.all([
460
+ narrator
461
+ .preparedPrompt(plotPromptName, {
462
+ name,
463
+ importedStoryText,
464
+ scenario: storyInfo.scenario,
465
+ characters: storyInfo.characters,
466
+ }, false)
467
+ .then((response) => {
468
+ if (response) {
469
+ const cleanedPlotPlan = this.extractMarkdownContent(response);
470
+ plotPlan = cleanedPlotPlan;
471
+ room.publishArtifact('Plot Plan', narrator.agentNickname, cleanedPlotPlan, [
472
+ narrator.agentNickname,
473
+ ]);
474
+ console.log(`Published plot plan artifact to narrator`);
475
+ this.progressService.emitProgress(storyInfo.id, 'profiles', 'Finished creating detailed plot plan.');
476
+ }
477
+ return { type: 'plot', success: !!response };
478
+ })
479
+ .catch((error) => {
480
+ console.error('Error generating/publishing plot plan:', error);
481
+ return { type: 'plot', success: false, error };
482
+ }),
483
+ ]);
484
+ const phase2Promises = [];
485
+ if (userAgent) {
486
+ phase2Promises.push(userAgent
487
+ .preparedPrompt(userCharPromptName, {
488
+ name,
489
+ importedStoryText,
490
+ scenario: storyInfo.scenario,
491
+ characterName: userCharacter.name,
492
+ characterObservableDesc: userCharacter.description,
493
+ otherCharacters,
494
+ }, false)
495
+ .then((response) => {
496
+ if (response.character?.character_profile) {
497
+ room.publishArtifact(`Character Profile - ${userAgent.agentNickname}`, userAgent.agentNickname, response.character.character_profile, [narrator.agentNickname, userAgent.agentNickname]);
498
+ console.log(`Published character profile for ${userCharacter.name} (human-controlled)`);
499
+ this.progressService.emitProgress(storyInfo.id, 'profiles', `Finished creating character profile for ${userCharacter.name}`);
500
+ }
501
+ else {
502
+ throw new Error('No character profile returned from API');
503
+ }
504
+ return { type: 'userCharacter', success: true };
505
+ })
506
+ .catch((error) => {
507
+ console.error(`Error generating/publishing user character profile:`, error);
508
+ return { type: 'userCharacter', success: false, error };
509
+ }));
510
+ }
511
+ for (let i = 0; i < storyInfo.characters.length; i++) {
512
+ const charInfo = storyInfo.characters[i];
513
+ if (charInfo.isControlledByHuman)
514
+ continue;
515
+ const agent = room.getAgents().find((a) => a.agentNickname === charInfo.name);
516
+ const aiCharOtherCharacters = storyInfo.characters
517
+ .filter((c) => c.isControlledByHuman === false)
518
+ .map((c) => `${c.name}: ${c.description}.`)
519
+ .join('\n');
520
+ phase2Promises.push(agent
521
+ .preparedPrompt(characterPromptName, {
522
+ name,
523
+ importedStoryText,
524
+ scenario: storyInfo.scenario,
525
+ characterName: charInfo.name,
526
+ characterObservableDesc: charInfo.description,
527
+ userCharacter,
528
+ otherCharacters: aiCharOtherCharacters,
529
+ plotPlan,
530
+ }, false)
531
+ .then((response) => {
532
+ if (response.character?.character_profile) {
533
+ room.publishArtifact(`Character Profile - ${agent.agentNickname}`, agent.agentNickname, response.character.character_profile, [agent.agentNickname]);
534
+ console.log(`Published character profile for ${charInfo.name}`);
535
+ this.progressService.emitProgress(storyInfo.id, 'profiles', `Finished creating character profile for ${charInfo.name}`);
536
+ }
537
+ else {
538
+ throw new Error(`No character profile returned for ${charInfo.name}`);
539
+ }
540
+ return { type: 'character', name: charInfo.name, success: true };
541
+ })
542
+ .catch((error) => {
543
+ console.error(`Error generating/publishing profile for ${charInfo.name}:`, error);
544
+ return {
545
+ type: 'character',
546
+ name: charInfo.name,
547
+ success: false,
548
+ error,
549
+ };
550
+ }));
551
+ }
552
+ const phase2Results = await Promise.all(phase2Promises);
553
+ const openingSceneResult = await this.generateOpeningSceneImage(storyInfo, room);
554
+ const profileResults = [...phase1Results, ...phase2Results, openingSceneResult];
555
+ const failedProfiles = profileResults.filter((r) => !r.success);
556
+ if (failedProfiles.length > 0) {
557
+ console.warn(`${failedProfiles.length} profile(s) failed to generate`);
558
+ }
559
+ narrator.allowSearch = false;
560
+ narrator.save();
561
+ const allAgents = room.getAgents();
562
+ for (const agent of allAgents) {
563
+ if (agent.disableMarkup || agent.disableBalanceCheck) {
564
+ agent.disableMarkup = false;
565
+ agent.disableBalanceCheck = false;
566
+ agent.save();
567
+ console.log(`Re-enabled markup and balance checks for ${agent.agentName}`);
568
+ }
569
+ }
570
+ console.log(`Generated and published ${profileResults.length} profiles in parallel (each agent created its own profile)`);
571
+ room.saveMetadata();
572
+ this.progressService.emitProgress(storyInfo.id, 'complete', 'Story plot creation complete');
573
+ }
574
+ catch (error) {
575
+ console.error('Error creating story:', error);
576
+ this.progressService.emitProgress(storyId, 'error', `Error: ${error.message}`);
577
+ }
578
+ finally {
579
+ try {
580
+ const room = await this.getStoryRoom(storyId);
581
+ if (room) {
582
+ const allAgents = room.getAgents();
583
+ this.enableStoryAgentFlags(allAgents, 'story creation');
584
+ }
585
+ }
586
+ catch (finallyError) {
587
+ console.error('Error in finally block disabling flags:', finallyError);
588
+ }
589
+ }
590
+ }
591
+ generateCharacterPortraits(storyInfo, room) {
592
+ if (!storyInfo.artistAgentId) {
593
+ console.log('Skipping character portrait generation: no artist agent');
594
+ return [];
595
+ }
596
+ this.progressService.emitProgress(storyInfo.id, 'portraits', 'Generating character portraits...');
597
+ const characterAgents = room
598
+ .getAgents()
599
+ .filter((agent) => agent.promptFolder === 'character');
600
+ return characterAgents.map(async (characterAgent) => {
601
+ try {
602
+ return this.generateCharacterPortrait(room, characterAgent, storyInfo.id).then((artifactId) => {
603
+ if (artifactId) {
604
+ this.progressService.emitProgress(storyInfo.id, 'portraits', `Generated portrait for ${characterAgent.agentNickname}`);
605
+ }
606
+ });
607
+ }
608
+ catch (error) {
609
+ console.error(`Portrait error for ${characterAgent.agentNickname}:`, error);
610
+ }
611
+ });
612
+ }
613
+ generateOpeningSceneImage(storyInfo, room) {
614
+ return Promise.all(this.generateCharacterPortraits(storyInfo, room))
615
+ .then(() => {
616
+ return this.generateSceneIllustration(storyInfo.id, 'Opening Scene');
617
+ })
618
+ .then(() => {
619
+ this.progressService.emitProgress(storyInfo.id, 'opening-scene', 'Generating opening scene image...');
620
+ return { type: 'opening-scene', success: true };
621
+ })
622
+ .catch((_error) => {
623
+ return Promise.resolve({ type: 'opening-scene', success: false });
624
+ });
625
+ }
626
+ async validateImportStructure(importDir) {
627
+ const errors = [];
628
+ const metadataPath = path.join(importDir, 'metadata.json');
629
+ if (!fs.existsSync(metadataPath)) {
630
+ errors.push('metadata.json not found at root level');
631
+ return { valid: false, errors };
632
+ }
633
+ let metadata;
634
+ try {
635
+ const metadataContent = fs.readFileSync(metadataPath, 'utf-8');
636
+ metadata = JSON.parse(metadataContent);
637
+ if (!metadata.id || typeof metadata.id !== 'string') {
638
+ errors.push("metadata.json missing or invalid 'id' field");
639
+ }
640
+ if (!metadata.name ||
641
+ typeof metadata.name !== 'string' ||
642
+ metadata.name.trim() === '') {
643
+ errors.push("metadata.json missing or invalid 'name' field");
644
+ }
645
+ if (!metadata.roomId || typeof metadata.roomId !== 'string') {
646
+ errors.push("metadata.json missing or invalid 'roomId' field");
647
+ }
648
+ if (!metadata.moderatorAgentId || typeof metadata.moderatorAgentId !== 'string') {
649
+ errors.push("metadata.json missing or invalid 'moderatorAgentId' field");
650
+ }
651
+ if (!Array.isArray(metadata.characters)) {
652
+ errors.push("metadata.json missing or invalid 'characters' field");
653
+ }
654
+ }
655
+ catch (error) {
656
+ errors.push(`Failed to parse metadata.json: ${error.message}`);
657
+ return { valid: false, errors };
658
+ }
659
+ const agentsDir = path.join(importDir, 'agents');
660
+ if (!fs.existsSync(agentsDir)) {
661
+ errors.push('agents/ folder not found');
662
+ }
663
+ else {
664
+ const referencedAgentIds = new Set();
665
+ if (metadata.moderatorAgentId)
666
+ referencedAgentIds.add(metadata.moderatorAgentId);
667
+ if (metadata.illustratorAgentId)
668
+ referencedAgentIds.add(metadata.illustratorAgentId);
669
+ if (metadata.artistAgentId)
670
+ referencedAgentIds.add(metadata.artistAgentId);
671
+ if (metadata.userAgentId)
672
+ referencedAgentIds.add(metadata.userAgentId);
673
+ for (const agentId of referencedAgentIds) {
674
+ const agentFile = path.join(agentsDir, `${agentId}.json`);
675
+ if (!fs.existsSync(agentFile)) {
676
+ errors.push(`Agent file missing: agents/${agentId}.json`);
677
+ }
678
+ }
679
+ }
680
+ const roomsDir = path.join(importDir, 'rooms');
681
+ if (!fs.existsSync(roomsDir)) {
682
+ errors.push('rooms/ folder not found');
683
+ }
684
+ else {
685
+ const roomFolders = fs
686
+ .readdirSync(roomsDir)
687
+ .filter((f) => fs.statSync(path.join(roomsDir, f)).isDirectory());
688
+ if (roomFolders.length !== 1) {
689
+ errors.push(`Expected exactly 1 room folder, found ${roomFolders.length}`);
690
+ }
691
+ else {
692
+ const roomFolderName = roomFolders[0];
693
+ if (roomFolderName !== metadata.roomId) {
694
+ errors.push(`Room folder name '${roomFolderName}' doesn't match roomId '${metadata.roomId}' in metadata`);
695
+ }
696
+ const roomMetadataPath = path.join(roomsDir, roomFolderName, 'metadata.json');
697
+ if (!fs.existsSync(roomMetadataPath)) {
698
+ errors.push(`Room metadata.json not found at rooms/${roomFolderName}/metadata.json`);
699
+ }
700
+ }
701
+ }
702
+ const storyCreationPath = path.join(importDir, 'story_creation.json');
703
+ if (!fs.existsSync(storyCreationPath)) {
704
+ console.warn('story_creation.json not found (non-fatal)');
705
+ }
706
+ return {
707
+ valid: errors.length === 0,
708
+ errors,
709
+ metadata: errors.length === 0 ? metadata : undefined,
710
+ };
711
+ }
712
+ async extractZip(zipBuffer, targetDir) {
713
+ return new Promise((resolve, reject) => {
714
+ let totalSize = 0;
715
+ const maxSize = 100 * 1024 * 1024;
716
+ yauzl.fromBuffer(zipBuffer, { lazyEntries: true }, (err, zipfile) => {
717
+ if (err) {
718
+ return reject(new Error(`Failed to read zip file: ${err.message}`));
719
+ }
720
+ zipfile.readEntry();
721
+ zipfile.on('entry', (entry) => {
722
+ const entryPath = entry.fileName;
723
+ if (entryPath.includes('..') || path.isAbsolute(entryPath)) {
724
+ zipfile.close();
725
+ return reject(new Error(`Security: Invalid path in zip: ${entryPath}`));
726
+ }
727
+ const fullPath = path.join(targetDir, entryPath);
728
+ if (/\/$/.test(entryPath)) {
729
+ fs.mkdirSync(fullPath, { recursive: true });
730
+ zipfile.readEntry();
731
+ }
732
+ else {
733
+ zipfile.openReadStream(entry, (err, readStream) => {
734
+ if (err) {
735
+ zipfile.close();
736
+ return reject(new Error(`Failed to read entry ${entryPath}: ${err.message}`));
737
+ }
738
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
739
+ const writeStream = fs.createWriteStream(fullPath);
740
+ readStream.on('data', (chunk) => {
741
+ totalSize += chunk.length;
742
+ if (totalSize > maxSize) {
743
+ zipfile.close();
744
+ writeStream.close();
745
+ reject(new Error(`Zip file exceeds maximum size of ${maxSize} bytes`));
746
+ }
747
+ });
748
+ readStream.pipe(writeStream);
749
+ writeStream.on('finish', () => {
750
+ zipfile.readEntry();
751
+ });
752
+ writeStream.on('error', (err) => {
753
+ zipfile.close();
754
+ reject(new Error(`Failed to write file ${entryPath}: ${err.message}`));
755
+ });
756
+ });
757
+ }
758
+ });
759
+ zipfile.on('end', () => {
760
+ resolve();
761
+ });
762
+ zipfile.on('error', (err) => {
763
+ reject(new Error(`Zip extraction error: ${err.message}`));
764
+ });
765
+ });
766
+ });
767
+ }
768
+ async importStoryFromZip(zipBuffer) {
769
+ const storiesDir = path.join(this.configService.getUserDataDir(), 'stories');
770
+ const importDir = path.join(storiesDir, 'import');
771
+ try {
772
+ if (fs.existsSync(importDir)) {
773
+ fs.rmSync(importDir, { recursive: true, force: true });
774
+ }
775
+ fs.mkdirSync(importDir, { recursive: true });
776
+ await this.extractZip(zipBuffer, importDir);
777
+ const validationResult = await this.validateImportStructure(importDir);
778
+ if (!validationResult.valid) {
779
+ throw new Error(`Invalid story structure:\n${validationResult.errors.join('\n')}`);
780
+ }
781
+ const metadata = validationResult.metadata;
782
+ const finalStoryPath = path.join(storiesDir, metadata.id);
783
+ if (fs.existsSync(finalStoryPath)) {
784
+ throw new Error(`Story with ID ${metadata.id} already exists (name: '${metadata.name}')`);
785
+ }
786
+ fs.renameSync(importDir, finalStoryPath);
787
+ console.log(`Successfully imported story: ${metadata.name} (${metadata.id})`);
788
+ return metadata;
789
+ }
790
+ catch (error) {
791
+ if (fs.existsSync(importDir)) {
792
+ fs.rmSync(importDir, { recursive: true, force: true });
793
+ }
794
+ throw error;
795
+ }
796
+ }
797
+ populateStoryHistory(room, storyText) {
798
+ try {
799
+ const storyMessage = {
800
+ role: 'assistant',
801
+ content: storyText,
802
+ };
803
+ room.getAgents().forEach((agent) => {
804
+ agent.addToConversationHistory(storyMessage);
805
+ agent.save();
806
+ });
807
+ room.addRoomMessages([
808
+ new message_1.RoomMessage(`Opening Scene`, app_types_1.MessageAction.SYSTEM, storyText),
809
+ ]);
810
+ }
811
+ catch (error) {
812
+ console.error('Error populating imported story history:', error);
813
+ throw error;
814
+ }
815
+ }
816
+ async getStoryState(storyId) {
817
+ const story = await this.ensureStoryLoaded(storyId);
818
+ if (!story) {
819
+ throw new Error('Story not found');
820
+ }
821
+ const room = await this.roomStore.getRoom(story.roomId);
822
+ if (!room) {
823
+ throw new Error('Story room not found');
824
+ }
825
+ const humanAgent = room.getAgents().find((agent) => agent.isControlledByHuman);
826
+ if (!humanAgent) {
827
+ throw new Error('No human-controlled agent found in story');
828
+ }
829
+ const roomMessages = room.getLatestRoomMessages(0, true);
830
+ const latestMessageIndex = roomMessages.length > 0 ? roomMessages[roomMessages.length - 1].index : -1;
831
+ let latestRoomMessage = null;
832
+ if (latestMessageIndex >= 0)
833
+ latestRoomMessage = roomMessages[latestMessageIndex];
834
+ const currentSpeaker = room.getCurrentSpeaker();
835
+ const humanPrompt = this.getHumanPrompt(room);
836
+ let storyState = {
837
+ storyId: storyId,
838
+ userAgentName: humanAgent.agentNickname,
839
+ latestRoomMessage: latestRoomMessage,
840
+ humanPrompt: humanPrompt,
841
+ currentSpeaker: currentSpeaker,
842
+ totalCost: story.totalCost || 0,
843
+ totalInputTokens: story.totalInputTokens || 0,
844
+ totalOutputTokens: story.totalOutputTokens || 0,
845
+ };
846
+ return storyState;
847
+ }
848
+ async listCharacters(storyId) {
849
+ try {
850
+ const room = await this.getStoryRoom(storyId);
851
+ const characters = room
852
+ .getAgents()
853
+ .filter((agent) => agent.promptFolder === 'character');
854
+ return characters.map((agent) => ({
855
+ name: agent.agentNickname,
856
+ description: agent.description,
857
+ isControlledByHuman: agent.isControlledByHuman,
858
+ }));
859
+ }
860
+ catch (error) {
861
+ console.error('Error listing characters:', error);
862
+ return [];
863
+ }
864
+ }
865
+ async getCharacter(storyId, characterName) {
866
+ try {
867
+ const room = await this.getStoryRoom(storyId);
868
+ const artifactName = `Character Profile - ${characterName}`;
869
+ const artifacts = room.getArtifacts();
870
+ const profileArtifact = artifacts.find((a) => a.name === artifactName);
871
+ if (!profileArtifact) {
872
+ return null;
873
+ }
874
+ let content = profileArtifact.body;
875
+ const portraitName = `Portrait - ${characterName}`;
876
+ const storyArtifactService = this.getStoryArtifactService(storyId);
877
+ const allArtifacts = storyArtifactService.listArtifacts();
878
+ const portraitArtifact = allArtifacts.find((a) => a.name === portraitName);
879
+ if (portraitArtifact) {
880
+ const imgUrl = `/api/stories/${storyId}/artifacts/${portraitArtifact.artifactId}`;
881
+ const imageMarkdown = `![Portrait of ${characterName}](${imgUrl})\n\n`;
882
+ content = imageMarkdown + content;
883
+ }
884
+ return content;
885
+ }
886
+ catch (error) {
887
+ console.error('Error getting character:', error);
888
+ throw new Error(`Error getting character: ${error.message}`);
889
+ }
890
+ }
891
+ saveCharacter(storyId, characterName, content) {
892
+ const artifactName = `Character Profile - ${characterName}`;
893
+ this.publishArtifact(storyId, artifactName, characterName, content, []);
894
+ }
895
+ async getPlotPlan(storyId) {
896
+ const room = await this.getStoryRoom(storyId);
897
+ const artifacts = room.getArtifacts();
898
+ const artifact = artifacts.find((a) => a.name === 'Plot Plan');
899
+ if (!artifact) {
900
+ return null;
901
+ }
902
+ return artifact.body;
903
+ }
904
+ async getAgentHistory(storyId, agentId) {
905
+ const room = await this.getStoryRoom(storyId);
906
+ const agent = room.getAgents().find((a) => a.id === agentId);
907
+ if (!agent) {
908
+ throw new Error(`Agent not found: ${agentId}`);
909
+ }
910
+ return JSON.stringify(agent.history || []);
911
+ }
912
+ async savePlotPlan(storyId, content) {
913
+ const room = await this.getStoryRoom(storyId);
914
+ room.publishArtifact('Plot Plan', 'Narrator', content, []);
915
+ }
916
+ async publishArtifact(storyId, name, creator, body, viewers) {
917
+ const room = await this.getStoryRoom(storyId);
918
+ room.publishArtifact(name, creator, body, viewers);
919
+ }
920
+ async respondToStory(storyId, content) {
921
+ const room = await this.getStoryRoom(storyId);
922
+ const trimmedContent = content?.trim();
923
+ const isPassing = trimmedContent?.toUpperCase() === 'PASS';
924
+ if (!trimmedContent && !isPassing) {
925
+ throw new Error('No message content provided');
926
+ }
927
+ const story = this.storyStore.getStory(storyId);
928
+ if (story) {
929
+ story.turnNumber = (story.turnNumber || 0) + 1;
930
+ this.storyStore.updateStoryMetadata(storyId, story);
931
+ }
932
+ const humanAgent = room.getAgents().find((agent) => agent.isControlledByHuman);
933
+ if (!humanAgent) {
934
+ throw new Error('No human-controlled agent found in story');
935
+ }
936
+ const responseMessage = new message_1.RoomMessage(humanAgent.agentNickname, app_types_1.MessageAction.MODERATE, content, [], null);
937
+ room.addPendingMessage(responseMessage);
938
+ }
939
+ async introduceCharacter(storyId, characterName, characterDescription, storyModel, fromNarratorSuggestion) {
940
+ const room = await this.getStoryRoom(storyId);
941
+ if (!characterName)
942
+ throw new Error('No character name provided');
943
+ if (characterName === 'Narrator' || characterName === 'Moderator') {
944
+ throw new Error('Cannot introduce a character named Narrator or Moderator');
945
+ }
946
+ const existingAgent = room.getAgents().find((agent) => {
947
+ const agentFirstNickname = agent.agentNickname.split(/\s+/)[0];
948
+ return agent.agentNickname === characterName || agentFirstNickname === characterName;
949
+ });
950
+ if (existingAgent) {
951
+ throw new Error(`A character named ${characterName} already exists in this story`);
952
+ }
953
+ let aiServiceName;
954
+ let aiModelName;
955
+ if (!storyModel || storyModel.trim().length === 0)
956
+ storyModel = process.env.DEFAULT_STORY_MODEL;
957
+ const modelConfig = this.getStoryModelConfig(storyModel);
958
+ if (modelConfig) {
959
+ aiServiceName = modelConfig.service;
960
+ aiModelName = modelConfig.model;
961
+ }
962
+ if (!aiServiceName || !aiModelName) {
963
+ throw new Error('Invalid story model provided');
964
+ }
965
+ room.setCurrentSpeaker(null);
966
+ const { agentsDir: storyAgentsDir } = this.getStoryStorageDirs(storyId);
967
+ const storyArtifactService = this.getStoryArtifactService(storyId);
968
+ const story = this.storyStore.getStory(storyId);
969
+ const storyTitle = story.name;
970
+ const characterNickname = characterName.trim().split(/\s+/)[0];
971
+ const characterAgent = this.agentFactory.createAgent(aiServiceName, `${storyTitle} - ${characterNickname}`, characterNickname, characterDescription, 'character', aiModelName, storyAgentsDir, storyArtifactService);
972
+ characterAgent.promptCacheTTL = 60;
973
+ characterAgent.save();
974
+ room.arrive(characterAgent);
975
+ const introducedCharArtifacts = room.getArtifacts();
976
+ const introducedCharPlotPlanArtifact = introducedCharArtifacts.find((a) => a.name === 'Plot Plan');
977
+ const introducedCharPlotPlan = introducedCharPlotPlanArtifact?.body || '';
978
+ await this.updateCharacterProfiles(room, [characterAgent], introducedCharPlotPlan);
979
+ try {
980
+ const artifactId = await this.generateCharacterPortrait(room, characterAgent, storyId);
981
+ if (artifactId) {
982
+ console.log(`Generated portrait for newly introduced character: ${characterName}`);
983
+ }
984
+ }
985
+ catch (error) {
986
+ console.error(`Error generating portrait for introduced character ${characterName}:`, error);
987
+ }
988
+ if (!fromNarratorSuggestion) {
989
+ room.addPendingMessage(new message_1.RoomMessage('system', app_types_1.MessageAction.MODERATE, `INTRODUCE ${characterName}`));
990
+ }
991
+ else {
992
+ console.log(`Skipping INTRODUCE message for ${characterName} (already introduced by narrator)`);
993
+ }
994
+ }
995
+ async declineCharacter(storyId, characterName) {
996
+ const story = this.storyStore.getStory(storyId);
997
+ if (!story) {
998
+ throw new Error('Story not found');
999
+ }
1000
+ if (!story.declinedCharacters) {
1001
+ story.declinedCharacters = [];
1002
+ }
1003
+ if (!story.declinedCharacters.includes(characterName)) {
1004
+ story.declinedCharacters.push(characterName);
1005
+ this.storyStore.updateStoryMetadata(storyId, story);
1006
+ console.log(`Recorded declined character: ${characterName} for story ${storyId}`);
1007
+ }
1008
+ }
1009
+ async deleteCharacter(storyId, characterName) {
1010
+ let room;
1011
+ try {
1012
+ room = await this.getStoryRoom(storyId);
1013
+ }
1014
+ catch (_error) {
1015
+ throw new errors_1.NotFoundError(`Story not found: ${storyId}`);
1016
+ }
1017
+ if (!room) {
1018
+ throw new errors_1.NotFoundError(`Story not found: ${storyId}`);
1019
+ }
1020
+ const agent = room.getAgents().find((a) => a.agentNickname === characterName);
1021
+ if (!agent) {
1022
+ throw new errors_1.NotFoundError(`Character agent not found: ${characterName}`);
1023
+ }
1024
+ if (characterName === 'Narrator' ||
1025
+ characterName === 'Moderator' ||
1026
+ agent.isControlledByHuman) {
1027
+ throw new errors_1.OperationFailedError(`Cannot delete ${characterName} - system agents and human-controlled characters cannot be removed`);
1028
+ }
1029
+ const agents = room.getAgents();
1030
+ const filteredAgents = agents.filter((a) => a.agentNickname !== characterName);
1031
+ room.setAgents(filteredAgents);
1032
+ room.saveMetadata();
1033
+ this.agentStore.removeAgent(agent.id);
1034
+ }
1035
+ async deleteStory(storyId) {
1036
+ console.log(`Deleting story ${storyId}...`);
1037
+ const story = this.storyStore.getStory(storyId);
1038
+ if (story?.roomId) {
1039
+ try {
1040
+ const room = await this.roomStore.getRoom(story.roomId);
1041
+ if (room) {
1042
+ const agents = room.getAgents();
1043
+ await Promise.all(agents.map(async (agent) => {
1044
+ try {
1045
+ await agent.deleteAgent();
1046
+ }
1047
+ catch (error) {
1048
+ console.warn(`Error deleting agent ${agent.id}:`, error);
1049
+ }
1050
+ }));
1051
+ room.deleteRoom();
1052
+ console.log(`Deleted room ${story.roomId} for story ${storyId}`);
1053
+ }
1054
+ else {
1055
+ console.warn(`Room ${story.roomId} not found for story ${storyId}`);
1056
+ }
1057
+ }
1058
+ catch (error) {
1059
+ console.warn(`Error cleaning up room for story ${storyId}:`, error);
1060
+ }
1061
+ }
1062
+ else {
1063
+ console.warn(`Story ${storyId} has no roomId, skipping room cleanup`);
1064
+ }
1065
+ if (story?.artistAgentId) {
1066
+ try {
1067
+ this.agentStore.removeAgent(story.artistAgentId);
1068
+ console.log(`Deleted artist agent ${story.artistAgentId}`);
1069
+ }
1070
+ catch (error) {
1071
+ console.warn(`Error deleting artist agent ${story.artistAgentId}:`, error);
1072
+ }
1073
+ }
1074
+ if (story?.illustratorAgentId) {
1075
+ try {
1076
+ this.agentStore.removeAgent(story.illustratorAgentId);
1077
+ console.log(`Deleted illustrator agent ${story.illustratorAgentId}`);
1078
+ }
1079
+ catch (error) {
1080
+ console.warn(`Error deleting illustrator agent ${story.illustratorAgentId}:`, error);
1081
+ }
1082
+ }
1083
+ try {
1084
+ this.cleanupProgressEmitter(storyId);
1085
+ this.cleanupMessageEmitter(storyId);
1086
+ }
1087
+ catch (error) {
1088
+ console.warn(`Error cleaning up emitters for story ${storyId}:`, error);
1089
+ }
1090
+ try {
1091
+ this.storyStore.removeStory(storyId);
1092
+ console.log(`Deleted story ${storyId} from store`);
1093
+ }
1094
+ catch (error) {
1095
+ console.warn(`Error removing story ${storyId} from store:`, error);
1096
+ }
1097
+ console.log(`Story ${storyId} deletion complete`);
1098
+ }
1099
+ disableStoryAgentFlags(agents, reason = 'operation') {
1100
+ for (const agent of agents) {
1101
+ if (agent && !agent.disableMarkup && !agent.disableBalanceCheck) {
1102
+ agent.disableMarkup = true;
1103
+ agent.disableBalanceCheck = true;
1104
+ agent.save();
1105
+ console.log(`Disabled markup/balance checks for ${agent.agentName} (${reason})`);
1106
+ }
1107
+ }
1108
+ }
1109
+ enableStoryAgentFlags(agents, reason = 'operation') {
1110
+ for (const agent of agents) {
1111
+ if (agent && (agent.disableMarkup || agent.disableBalanceCheck)) {
1112
+ agent.disableMarkup = false;
1113
+ agent.disableBalanceCheck = false;
1114
+ agent.save();
1115
+ console.log(`Re-enabled markup/balance checks for ${agent.agentName} (${reason})`);
1116
+ }
1117
+ }
1118
+ }
1119
+ async compactStory(storyId) {
1120
+ let agents = [];
1121
+ try {
1122
+ const room = await this.getStoryRoom(storyId);
1123
+ agents = room.getAgents();
1124
+ if (agents.length === 0) {
1125
+ throw new Error('No agents in story room');
1126
+ }
1127
+ console.log(`Compacting ${agents.length} agents in parallel`);
1128
+ const agentsToCompact = agents.filter(agent => agent !== room.getModeratorAgent());
1129
+ this.disableStoryAgentFlags(agentsToCompact, 'compaction');
1130
+ const compactionPromises = agents.map(async (agent) => {
1131
+ if (agent === room.getModeratorAgent()) {
1132
+ agent.history = [];
1133
+ agent.save();
1134
+ return;
1135
+ }
1136
+ try {
1137
+ await this.compactAgentHistory(agent);
1138
+ }
1139
+ catch (error) {
1140
+ console.error(`Error compacting ${agent.agentName}:`, error);
1141
+ }
1142
+ });
1143
+ await Promise.all(compactionPromises);
1144
+ console.log(`Finished compacting ${agents.length} agents in parallel`);
1145
+ return { success: true };
1146
+ }
1147
+ catch (error) {
1148
+ console.error('Error compacting story:', error);
1149
+ return { success: false, message: error.message };
1150
+ }
1151
+ finally {
1152
+ if (agents.length > 0) {
1153
+ this.enableStoryAgentFlags(agents, 'compaction');
1154
+ }
1155
+ }
1156
+ }
1157
+ async progressStoryToNextChapter(storyId) {
1158
+ const story = await this.ensureStoryLoaded(storyId);
1159
+ if (!story) {
1160
+ throw new Error('Story not found');
1161
+ }
1162
+ const existingEmitter = this.progressService.getProgressEmitter(storyId);
1163
+ if (!existingEmitter) {
1164
+ this.progressService.createProgressEmitter(storyId);
1165
+ }
1166
+ const room = await this.getStoryRoom(storyId);
1167
+ room.setCurrentSpeaker('system');
1168
+ this.progressService.emitProgress(storyId, 'opening-scene', 'Generating opening scene of chapter...');
1169
+ const agents = room.getAgents();
1170
+ const narrator = agents.find((agent) => agent.promptFolder === 'narrator');
1171
+ const { openingScene, chapterTitle } = await this.generateOpeningScene(room, narrator);
1172
+ this.progressService.emitProgress(storyId, 'chapter-backup', `Saving previous chapter: "${chapterTitle}"...`);
1173
+ const chapterIndex = this.storyStore.getNextChapterIndex(storyId);
1174
+ const backupSuccess = this.storyStore.createChapterBackup(storyId, chapterIndex, chapterTitle);
1175
+ if (!backupSuccess) {
1176
+ throw new Error('Failed to backup chapter');
1177
+ }
1178
+ room.clearRoomMessages();
1179
+ this.populateStoryHistory(room, openingScene);
1180
+ const humanAgent = room.getAgents().find((a) => a.isControlledByHuman);
1181
+ if (humanAgent) {
1182
+ room.setCurrentSpeaker(humanAgent.agentNickname);
1183
+ }
1184
+ this.progressService.emitProgress(storyId, 'ready', 'Chapter opening is ready! Continuing chapter progression in the background...');
1185
+ setImmediate(() => {
1186
+ this.progressStoryToNextChapterAsync(storyId).catch((error) => {
1187
+ console.error('Error in async chapter progression:', error);
1188
+ this.progressService.emitProgress(storyId, 'error', `Error: ${error.message}`);
1189
+ });
1190
+ });
1191
+ return { chapterIndex };
1192
+ }
1193
+ async progressStoryToNextChapterAsync(storyId) {
1194
+ let room = null;
1195
+ let agents = [];
1196
+ let narrator = null;
1197
+ let characterAgents = [];
1198
+ try {
1199
+ room = await this.getStoryRoom(storyId);
1200
+ agents = room.getAgents();
1201
+ narrator = agents.find((agent) => agent.promptFolder === 'narrator');
1202
+ characterAgents = agents.filter((agent) => agent.promptFolder === 'character');
1203
+ if (narrator) {
1204
+ narrator.disableMarkup = true;
1205
+ narrator.disableBalanceCheck = true;
1206
+ narrator.allowSearch = false;
1207
+ narrator.save();
1208
+ }
1209
+ for (const agent of characterAgents) {
1210
+ agent.disableMarkup = true;
1211
+ agent.disableBalanceCheck = true;
1212
+ agent.save();
1213
+ }
1214
+ this.progressService.emitProgress(storyId, 'profiles-compact', 'Updating plot plan and character profiles...');
1215
+ const updatedPlotPlan = await this.updatePlotPlan(room, narrator);
1216
+ await this.updateCharacterProfiles(room, characterAgents, updatedPlotPlan);
1217
+ await this.updateStoryCost(storyId);
1218
+ this.progressService.emitProgress(storyId, 'complete', 'Chapter progression complete!');
1219
+ }
1220
+ catch (error) {
1221
+ console.error('Error in async chapter progression:', error);
1222
+ throw error;
1223
+ }
1224
+ finally {
1225
+ if (room) {
1226
+ const agentsToReEnable = narrator ? [narrator, ...characterAgents] : characterAgents;
1227
+ this.enableStoryAgentFlags(agentsToReEnable, 'chapter progression');
1228
+ }
1229
+ }
1230
+ }
1231
+ async generateOpeningScene(room, narrator) {
1232
+ const artifacts = room.getArtifacts();
1233
+ const plotPlanArtifact = artifacts.find((a) => a.name === 'Plot Plan');
1234
+ const currentPlotPlan = plotPlanArtifact?.body || 'No plot plan found.';
1235
+ const formattedHistory = narrator.getRawMessages();
1236
+ const aiResponse = await narrator.preparedPrompt('create_chapter', {
1237
+ currentPlotPlan: currentPlotPlan,
1238
+ formattedHistory: formattedHistory || 'No recent events...',
1239
+ }, false);
1240
+ const lines = aiResponse.split('\n');
1241
+ let chapterTitle = 'Untitled Chapter';
1242
+ let openingScene = aiResponse;
1243
+ if (lines.length > 0 && lines[0].trim().startsWith('#')) {
1244
+ chapterTitle = lines[0].trim().substring(1).trim();
1245
+ openingScene = lines.slice(1).join('\n').trim();
1246
+ }
1247
+ return {
1248
+ openingScene,
1249
+ chapterTitle,
1250
+ };
1251
+ }
1252
+ async compactAgentHistories(agents, threshold) {
1253
+ await Promise.all(agents.map(async (agent) => {
1254
+ let numMessageChars = agent.history?.map((m) => m.content?.length).reduce((a, b) => a + b, 0);
1255
+ if (numMessageChars > threshold) {
1256
+ await this.compactAgentHistory(agent);
1257
+ }
1258
+ else {
1259
+ return Promise.resolve();
1260
+ }
1261
+ }));
1262
+ }
1263
+ async compactAgentHistory(agent) {
1264
+ const originalHistory = [...agent.history];
1265
+ const originalLength = originalHistory.length;
1266
+ if (originalHistory.length == 0) {
1267
+ return {
1268
+ success: true,
1269
+ originalLength: originalLength,
1270
+ newLength: originalLength,
1271
+ message: 'No conversation history to compact',
1272
+ };
1273
+ }
1274
+ const formattedHistory = agent.getFormattedMessages(0);
1275
+ try {
1276
+ agent.history = [];
1277
+ const summaryResponse = await agent.preparedPrompt('compact_story', {
1278
+ agentName: agent.agentNickname,
1279
+ formattedHistory: formattedHistory,
1280
+ }, false);
1281
+ const summary = summaryResponse?.summary || summaryResponse;
1282
+ agent.addToConversationHistory(`[CONVERSATION HISTORY SUMMARY]\n\n${summary}`, true);
1283
+ const newLength = agent.history.length;
1284
+ console.log(`Compacted ${agent.agentName}: ${originalLength} messages`);
1285
+ agent.save();
1286
+ return {
1287
+ success: true,
1288
+ originalLength: originalLength,
1289
+ newLength: newLength,
1290
+ message: `${originalLength} messages -> ${newLength} messages`,
1291
+ summary: summary,
1292
+ };
1293
+ }
1294
+ catch (error) {
1295
+ agent.history = originalHistory;
1296
+ console.error(`Error compacting ${agent.agentName}:`, error);
1297
+ throw error;
1298
+ }
1299
+ }
1300
+ extractMarkdownContent(response) {
1301
+ const fenceMatch = response.match(/```(?:markdown)?\s*\n([\s\S]*?)```/);
1302
+ if (fenceMatch) {
1303
+ return fenceMatch[1].trim();
1304
+ }
1305
+ return response.trim();
1306
+ }
1307
+ async updatePlotPlan(room, narrator) {
1308
+ const artifacts = room.getArtifacts();
1309
+ const plotPlanArtifact = artifacts.find((a) => a.name === 'Plot Plan');
1310
+ const currentPlotPlan = plotPlanArtifact ? plotPlanArtifact.body : 'No plot plan found.';
1311
+ const formattedHistory = narrator.getRawMessages();
1312
+ try {
1313
+ const progressPlotResponse = await narrator.preparedPrompt('progress_plot', {
1314
+ currentPlotPlan: currentPlotPlan,
1315
+ formattedHistory: formattedHistory,
1316
+ }, false);
1317
+ if (progressPlotResponse) {
1318
+ const cleanedPlotPlan = this.extractMarkdownContent(progressPlotResponse);
1319
+ room.publishArtifact('Plot Plan', narrator.agentNickname, cleanedPlotPlan, [
1320
+ narrator.agentNickname,
1321
+ ]);
1322
+ console.log(`Updated plot plan`);
1323
+ return cleanedPlotPlan;
1324
+ }
1325
+ }
1326
+ catch (error) {
1327
+ console.error(`Error updating plot plan:`, error);
1328
+ }
1329
+ return '';
1330
+ }
1331
+ async updateCharacterProfiles(room, characterAgents, plotPlan = '') {
1332
+ const artifacts = room.getArtifacts();
1333
+ const updatePromises = characterAgents.map(async (character) => {
1334
+ try {
1335
+ const profileArtifact = artifacts.find((a) => a.name === `Character Profile - ${character.agentNickname}`);
1336
+ let currentProfile = profileArtifact ? profileArtifact.body : null;
1337
+ let formattedHistory = character.getFormattedMessages(0);
1338
+ if (!currentProfile) {
1339
+ currentProfile = `There is not yet a character profile for ${character.agentNickname}. Use the updated plot plan and recent story messages to create a character profile.`;
1340
+ if (!formattedHistory || formattedHistory.length === 0) {
1341
+ formattedHistory = room
1342
+ .getLatestRoomMessages(0, true)
1343
+ .map((m) => `${m.sender}: ${m.content}\n`);
1344
+ }
1345
+ }
1346
+ const progressCharacterResponse = await character.preparedPrompt('progress_character', {
1347
+ agentName: character.agentNickname,
1348
+ currentProfile: currentProfile,
1349
+ formattedHistory: formattedHistory,
1350
+ plotPlan,
1351
+ }, false);
1352
+ if (progressCharacterResponse.description) {
1353
+ character.description = progressCharacterResponse.description;
1354
+ character.save();
1355
+ }
1356
+ room.publishArtifact(`Character Profile - ${character.agentNickname}`, character.agentNickname, progressCharacterResponse.character_profile, [character.agentNickname]);
1357
+ }
1358
+ catch (error) {
1359
+ console.error(`Error updating character profile for ${character.agentNickname}:`, error);
1360
+ }
1361
+ });
1362
+ await Promise.all(updatePromises);
1363
+ console.log(`Updated ${characterAgents.length} character profiles in parallel`);
1364
+ const portraitPromises = characterAgents.map(async (characterAgent) => {
1365
+ try {
1366
+ const pathParts = room.getStorageDir().split(path.sep);
1367
+ const storiesIndex = pathParts.findIndex((p) => p === 'stories');
1368
+ const storyId = storiesIndex >= 0 ? pathParts[storiesIndex + 1] : null;
1369
+ if (!storyId) {
1370
+ console.error('Could not extract story ID from room path');
1371
+ return { character: characterAgent.agentNickname, success: false };
1372
+ }
1373
+ const storyArtifactService = this.getStoryArtifactService(storyId);
1374
+ const oldPortraitName = `Portrait - ${characterAgent.agentNickname}`;
1375
+ const oldArtifacts = storyArtifactService.listArtifacts();
1376
+ const oldPortrait = oldArtifacts.find((a) => a.name === oldPortraitName);
1377
+ if (oldPortrait) {
1378
+ storyArtifactService.deleteArtifact(oldPortrait.artifactId);
1379
+ console.log(`Deleted old portrait for ${characterAgent.agentName}`);
1380
+ }
1381
+ const artifactId = await this.generateCharacterPortrait(room, characterAgent, storyId);
1382
+ return {
1383
+ character: characterAgent.agentNickname,
1384
+ success: !!artifactId,
1385
+ artifactId,
1386
+ };
1387
+ }
1388
+ catch (error) {
1389
+ console.error(`Error regenerating portrait for ${characterAgent.agentName}:`, error);
1390
+ return { character: characterAgent.agentNickname, success: false, error };
1391
+ }
1392
+ });
1393
+ await Promise.all(portraitPromises);
1394
+ console.log(`Regenerated portraits for ${characterAgents.length} characters`);
1395
+ }
1396
+ getImageModelConfig(modelName) {
1397
+ try {
1398
+ if (!modelName) {
1399
+ return null;
1400
+ }
1401
+ const imageModelsPath = path.join(this.configService.getCommonConfigDir(), 'image_models.json');
1402
+ const imageModels = JSON.parse(fs.readFileSync(imageModelsPath, 'utf8'));
1403
+ const modelConfig = imageModels.find((m) => m.name === modelName);
1404
+ if (!modelConfig) {
1405
+ console.warn(`Image model not found: ${modelName}`);
1406
+ return null;
1407
+ }
1408
+ if (!modelConfig.service || !modelConfig.model) {
1409
+ console.log(`Images disabled: selected "${modelName}"`);
1410
+ return null;
1411
+ }
1412
+ return { service: modelConfig.service, model: modelConfig.model };
1413
+ }
1414
+ catch (error) {
1415
+ console.error('Error loading image model config:', error);
1416
+ return null;
1417
+ }
1418
+ }
1419
+ createArtistAgent(storyId, storyAgentsDir, storyArtifactService, imageModelName) {
1420
+ const imageConfig = this.getImageModelConfig(imageModelName);
1421
+ if (!imageConfig) {
1422
+ console.log('Artist agent creation skipped: images disabled');
1423
+ return null;
1424
+ }
1425
+ const artistAgent = this.agentFactory.createAgent(imageConfig.service, 'Artist', '', 'AI artist for generating character portraits and scene illustrations', 'default', imageConfig.model, storyAgentsDir, storyArtifactService);
1426
+ artistAgent.maxHistoryMessages = 10;
1427
+ artistAgent.promptCacheTTL = 0;
1428
+ artistAgent.save();
1429
+ console.log(`Created artist agent: ${artistAgent.agentName} (${imageConfig.service}/${imageConfig.model})`);
1430
+ return artistAgent;
1431
+ }
1432
+ async generateCharacterPortrait(room, characterAgent, storyId) {
1433
+ try {
1434
+ const artifacts = room.getArtifacts();
1435
+ const profileArtifact = artifacts.find((a) => a.name === `Character Profile - ${characterAgent.agentNickname}`);
1436
+ const storyInfo = this.storyStore.getStory(storyId);
1437
+ const scenario = storyInfo?.scenario || '';
1438
+ const character = storyInfo.characters.find((c) => c.name === characterAgent.agentNickname);
1439
+ let characterDescription = profileArtifact?.body || character?.description || '';
1440
+ if (!characterDescription) {
1441
+ console.warn(`No profile for ${characterAgent.agentNickname}, skipping portrait`);
1442
+ return null;
1443
+ }
1444
+ const artistAgent = await this.agentStore.getAgent(storyInfo.artistAgentId);
1445
+ if (!artistAgent) {
1446
+ console.warn(`Artist agent not found: ${storyInfo.artistAgentId}`);
1447
+ return null;
1448
+ }
1449
+ const visualDescription = await characterAgent.preparedPrompt('describe_character', {
1450
+ characterName: characterAgent.agentNickname,
1451
+ characterProfile: characterDescription,
1452
+ scenario: scenario,
1453
+ }, false);
1454
+ if (!visualDescription || typeof visualDescription !== 'string') {
1455
+ console.warn(`Failed to generate visual description for ${characterAgent.agentNickname}`);
1456
+ return null;
1457
+ }
1458
+ const imageResult = await artistAgent.generateImage(visualDescription, 1024, 1536, 'high');
1459
+ if (imageResult.error) {
1460
+ return null;
1461
+ }
1462
+ artistAgent.save();
1463
+ const artifactId = imageResult.artifactId;
1464
+ let storyArtifactService = this.getStoryArtifactService(storyId);
1465
+ storyArtifactService.renameArtifact(artifactId, `Portrait - ${characterAgent.agentNickname}`);
1466
+ storyArtifactService.updateArtifactDescription(artifactId, visualDescription);
1467
+ console.log(`Generated portrait for ${characterAgent.agentNickname}: ${artifactId}`);
1468
+ return artifactId;
1469
+ }
1470
+ catch (error) {
1471
+ console.error(`Error generating portrait for ${characterAgent.agentNickname}:`, error);
1472
+ return null;
1473
+ }
1474
+ }
1475
+ async generateSceneIllustration(storyId, situation) {
1476
+ try {
1477
+ const story = this.storyStore.getStory(storyId);
1478
+ if (!story?.illustratorAgentId) {
1479
+ console.log('No illustrator configured');
1480
+ return;
1481
+ }
1482
+ const illustrator = await this.agentStore.getAgent(story.illustratorAgentId);
1483
+ const room = await this.roomStore.getRoom(story.roomId);
1484
+ if (!illustrator || !room)
1485
+ return;
1486
+ const allMessages = room.getLatestRoomMessages(0, true);
1487
+ const latestMessage = allMessages[allMessages.length - 1];
1488
+ if (!latestMessage) {
1489
+ console.warn('No messages in room');
1490
+ return;
1491
+ }
1492
+ illustrator.addToConversationHistory(latestMessage.content, false);
1493
+ const storyArtifactService = this.getStoryArtifactService(storyId);
1494
+ const allArtifacts = storyArtifactService.listArtifacts();
1495
+ const existingScenes = allArtifacts
1496
+ .filter((a) => a.name.startsWith('Scene - '))
1497
+ .map((a) => ({
1498
+ name: a.name.replace('Scene - ', ''),
1499
+ description: a.description || '',
1500
+ }));
1501
+ let existingScenesString = existingScenes
1502
+ .map((s) => `- ${s.name}: ${s.description}`)
1503
+ .join('\n');
1504
+ if (!existingScenesString)
1505
+ existingScenesString =
1506
+ 'No scene reference images have been created yet. (set isReference: true)';
1507
+ let prompt = `**Current Situation**:\n ${story.situation}\n\n**Existing Scenes**:\n ${existingScenesString}`;
1508
+ const sceneAnalysis = await illustrator.instructedPrompt(prompt, 'describe_scene', {
1509
+ characters: story.characters,
1510
+ }, true, true);
1511
+ illustrator.save();
1512
+ if (!sceneAnalysis || !sceneAnalysis.createImage) {
1513
+ console.log('Illustrator decided not to create an image for this situation');
1514
+ return;
1515
+ }
1516
+ if (sceneAnalysis.isReference) {
1517
+ await this.generateSceneReference(storyId, sceneAnalysis.sceneName, sceneAnalysis.sceneDescription);
1518
+ await this.generateSceneIllustration(storyId, situation);
1519
+ }
1520
+ else {
1521
+ await this.generateStoryImage(storyId, story.turnNumber, sceneAnalysis.imageCaption, sceneAnalysis.sceneName, sceneAnalysis.sceneDescription, sceneAnalysis.characterNames);
1522
+ }
1523
+ }
1524
+ catch (error) {
1525
+ console.error('Scene illustration error:', error);
1526
+ }
1527
+ }
1528
+ async generateSceneReference(storyId, sceneName, sceneDescription) {
1529
+ try {
1530
+ console.log(`Generating scene reference: ${sceneName}`);
1531
+ const storyInfo = this.storyStore.getStory(storyId);
1532
+ if (!storyInfo || !storyInfo.artistAgentId) {
1533
+ console.error(`Cannot generate scene reference: story ${storyId} has no artist agent`);
1534
+ return;
1535
+ }
1536
+ const artistAgent = await this.agentStore.getAgent(storyInfo.artistAgentId);
1537
+ if (!artistAgent) {
1538
+ console.error(`Artist agent not found: ${storyInfo.artistAgentId}`);
1539
+ return;
1540
+ }
1541
+ let storyArtifactService = this.getStoryArtifactService(storyId);
1542
+ if (!storyArtifactService) {
1543
+ console.error(`Story artifact service not found: ${storyId}`);
1544
+ return;
1545
+ }
1546
+ const imageResult = await artistAgent.generateImage(sceneDescription, 1024, 1024, 'auto');
1547
+ if (imageResult.error) {
1548
+ return;
1549
+ }
1550
+ artistAgent.save();
1551
+ const artifactId = imageResult.artifactId;
1552
+ storyArtifactService.renameArtifact(artifactId, `Scene - ${sceneName}`);
1553
+ storyArtifactService.updateArtifactDescription(artifactId, sceneDescription);
1554
+ console.log(`Generated scene reference: ${sceneName} (${artifactId})`);
1555
+ }
1556
+ catch (error) {
1557
+ console.error('Scene reference generation error:', error);
1558
+ }
1559
+ }
1560
+ async generateStoryImage(storyId, turnNumber, imageCaption, sceneName, sceneDescription, characterNames) {
1561
+ try {
1562
+ console.log(`Generating story image for turn ${turnNumber}`);
1563
+ const storyArtifactService = this.getStoryArtifactService(storyId);
1564
+ const allArtifacts = storyArtifactService.listArtifacts();
1565
+ const sceneArtifact = allArtifacts.find((a) => a.name === `Scene - ${sceneName}`);
1566
+ if (!sceneArtifact) {
1567
+ console.warn(`Scene not found: ${sceneName}`);
1568
+ return;
1569
+ }
1570
+ const characterPortraitIds = [];
1571
+ for (const charName of characterNames) {
1572
+ const portrait = allArtifacts.find((a) => a.name === `Portrait - ${charName}`);
1573
+ if (portrait) {
1574
+ characterPortraitIds.push(portrait.artifactId);
1575
+ }
1576
+ else {
1577
+ console.warn(`Portrait not found: ${charName}`);
1578
+ }
1579
+ }
1580
+ const referenceImageIds = [sceneArtifact.artifactId, ...characterPortraitIds];
1581
+ const storyInfo = this.storyStore.getStory(storyId);
1582
+ if (!storyInfo || !storyInfo.artistAgentId) {
1583
+ console.error(`Cannot generate story image: story ${storyId} has no artist agent`);
1584
+ return;
1585
+ }
1586
+ const artistAgent = await this.agentStore.getAgent(storyInfo.artistAgentId);
1587
+ if (!artistAgent) {
1588
+ console.error(`Artist agent not found: ${storyInfo.artistAgentId}`);
1589
+ return;
1590
+ }
1591
+ let quality = 'high';
1592
+ let width = 1536;
1593
+ const imageResult = await artistAgent.generateImage(sceneDescription, width, 1024, quality, referenceImageIds);
1594
+ if (imageResult.error) {
1595
+ return;
1596
+ }
1597
+ artistAgent.save();
1598
+ const artifactId = imageResult.artifactId;
1599
+ storyArtifactService.renameArtifact(artifactId, `Story image - ${turnNumber}`);
1600
+ storyArtifactService.updateArtifactDescription(artifactId, imageCaption);
1601
+ console.log(`Generated story image: ${imageCaption} (${artifactId})`);
1602
+ try {
1603
+ const room = await this.getStoryRoom(storyId);
1604
+ const imgUrl = `/api/stories/${storyId}/artifacts/${artifactId}`;
1605
+ const imageMarkdown = `![${imageCaption}](${imgUrl})`;
1606
+ const imageMessage = new message_1.RoomMessage(imageCaption, app_types_1.MessageAction.SYSTEM, imageMarkdown);
1607
+ room.addRoomMessage(imageMessage);
1608
+ console.log(`Added story image message to room`);
1609
+ }
1610
+ catch (error) {
1611
+ console.error('Error adding image message to room:', error);
1612
+ }
1613
+ }
1614
+ catch (error) {
1615
+ console.error('Story image generation error:', error);
1616
+ }
1617
+ }
1618
+ async updateStorySituation(storyId, situation) {
1619
+ const story = this.storyStore.getStory(storyId);
1620
+ if (!story)
1621
+ return;
1622
+ const room = await this.getStoryRoom(storyId);
1623
+ let progressChapter = situation.startsWith('PROGRESS');
1624
+ if (progressChapter) {
1625
+ if (story) {
1626
+ story.declinedCharacters = [];
1627
+ this.storyStore.updateStoryMetadata(storyId, story);
1628
+ }
1629
+ this.messageService.emitUpdate(storyId, {
1630
+ type: 'suggestion',
1631
+ suggestion: {
1632
+ type: 'progress_chapter',
1633
+ timestamp: Date.now()
1634
+ }
1635
+ });
1636
+ return;
1637
+ }
1638
+ let agentCompactionThreshold = Number(process.env.AGENT_COMPACTION_THRESHOLD) || 150000;
1639
+ await this.compactAgentHistories(room.getAgents(), agentCompactionThreshold);
1640
+ let introduce = situation.startsWith('INTRODUCE:');
1641
+ if (introduce) {
1642
+ let newCharacterName = situation.substring(11).trim();
1643
+ if (newCharacterName) {
1644
+ const declinedCharacters = story?.declinedCharacters || [];
1645
+ if (declinedCharacters.includes(newCharacterName)) {
1646
+ console.log(`Character ${newCharacterName} was declined, skipping prompt`);
1647
+ return;
1648
+ }
1649
+ this.messageService.emitUpdate(storyId, {
1650
+ type: 'suggestion',
1651
+ suggestion: {
1652
+ type: 'introduce_character',
1653
+ characterName: newCharacterName,
1654
+ timestamp: Date.now()
1655
+ }
1656
+ });
1657
+ }
1658
+ return;
1659
+ }
1660
+ story.situation = situation;
1661
+ this.storyStore.updateStoryMetadata(storyId, story);
1662
+ console.log(`Updated story ${storyId} situation: ${situation}`);
1663
+ this.generateSceneIllustration(storyId, situation).catch((error) => {
1664
+ console.error('Illustration generation error:', error);
1665
+ });
1666
+ }
1667
+ async generateStoryMarkdown(storyId) {
1668
+ const story = this.storyStore.getStory(storyId);
1669
+ if (!story) {
1670
+ throw new Error('Story not found');
1671
+ }
1672
+ let markdown = `# ${story.name}\n\n`;
1673
+ markdown += `**Scenario**: ${story.scenario}\n\n`;
1674
+ markdown += `**Characters**:\n`;
1675
+ for (const char of story.characters) {
1676
+ const type = char.isControlledByHuman ? 'Human' : 'AI';
1677
+ markdown += `- ${char.name} (${type}): ${char.description}\n`;
1678
+ }
1679
+ markdown += `\n---\n\n`;
1680
+ const chapters = this.storyStore.listChapters(storyId);
1681
+ for (const chapter of chapters) {
1682
+ markdown += `## Chapter ${chapter.chapterNum}: ${chapter.chapterTitle}\n\n`;
1683
+ const messages = await this.storyStore.getChapterContent(storyId, chapter.chapterNum);
1684
+ markdown += this.formatMessagesToMarkdown(messages);
1685
+ markdown += `\n---\n\n`;
1686
+ }
1687
+ const room = await this.getStoryRoom(storyId);
1688
+ if (room) {
1689
+ markdown += `## Current Chapter\n\n`;
1690
+ markdown += this.formatMessagesToMarkdown(room.getLatestRoomMessages(0, true));
1691
+ }
1692
+ markdown = this.processImageMarkdown(markdown, 600);
1693
+ return markdown;
1694
+ }
1695
+ async exportStoryData(storyId) {
1696
+ const story = this.storyStore.getStory(storyId);
1697
+ if (!story) {
1698
+ throw new Error('Story not found');
1699
+ }
1700
+ const userStoriesDir = path.join(this.configService.getUserDataDir(), 'stories');
1701
+ const storyFolderPath = path.join(userStoriesDir, storyId);
1702
+ if (!fs.existsSync(storyFolderPath)) {
1703
+ throw new Error('Story folder not found on disk');
1704
+ }
1705
+ const archive = (0, archiver_1.default)('zip', {
1706
+ zlib: { level: 9 },
1707
+ });
1708
+ archive.directory(storyFolderPath, false);
1709
+ archive.finalize();
1710
+ const sanitizedName = story.name.replace(/[^a-z0-9]/gi, '_');
1711
+ const filename = `${sanitizedName}.zip`;
1712
+ return {
1713
+ stream: archive,
1714
+ filename: filename,
1715
+ };
1716
+ }
1717
+ formatMessagesToMarkdown(messages) {
1718
+ let text = '';
1719
+ for (const msg of messages) {
1720
+ if (msg.situation) {
1721
+ text += `### ${msg.situation}\n\n`;
1722
+ }
1723
+ text += `**${msg.sender}**: ${msg.content}\n\n`;
1724
+ }
1725
+ return text;
1726
+ }
1727
+ processImageMarkdown(markdown, maxWidth = 600) {
1728
+ markdown = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (match, alt, url) => {
1729
+ return `<img src="${url}" alt="${alt}" style="max-width: ${maxWidth}px; width: 100%; height: auto; display: block; margin: 1rem auto;" />`;
1730
+ });
1731
+ return markdown;
1732
+ }
1733
+ async updateStoryCost(storyId) {
1734
+ try {
1735
+ const storyInfo = this.storyStore.getStory(storyId);
1736
+ if (!storyInfo || !storyInfo.roomId) {
1737
+ console.warn(`Cannot update story cost: story ${storyId} not found or has no room`);
1738
+ return;
1739
+ }
1740
+ const room = await this.roomStore.getRoom(storyInfo.roomId);
1741
+ if (!room) {
1742
+ console.warn(`Cannot update story cost: room ${storyInfo.roomId} not found`);
1743
+ return;
1744
+ }
1745
+ let totalCost = 0;
1746
+ let totalInputTokens = 0;
1747
+ let totalOutputTokens = 0;
1748
+ const agents = room.getAgents();
1749
+ for (const agent of agents) {
1750
+ totalCost += agent.totalCost || 0;
1751
+ totalInputTokens += agent.totalInputTokens || 0;
1752
+ totalOutputTokens += agent.totalOutputTokens || 0;
1753
+ }
1754
+ if (storyInfo.illustratorAgentId) {
1755
+ const illustratorAgent = await this.agentStore.getAgent(storyInfo.illustratorAgentId);
1756
+ if (illustratorAgent) {
1757
+ totalCost += illustratorAgent.totalCost || 0;
1758
+ totalInputTokens += illustratorAgent.totalInputTokens || 0;
1759
+ totalOutputTokens += illustratorAgent.totalOutputTokens || 0;
1760
+ }
1761
+ else {
1762
+ console.warn(`Illustrator agent not found: ${storyInfo.illustratorAgentId}`);
1763
+ }
1764
+ }
1765
+ if (storyInfo.artistAgentId) {
1766
+ const artistAgent = await this.agentStore.getAgent(storyInfo.artistAgentId);
1767
+ if (artistAgent) {
1768
+ totalCost += artistAgent.totalCost || 0;
1769
+ totalInputTokens += artistAgent.totalInputTokens || 0;
1770
+ totalOutputTokens += artistAgent.totalOutputTokens || 0;
1771
+ }
1772
+ else {
1773
+ console.warn(`Artist agent not found: ${storyInfo.artistAgentId}`);
1774
+ }
1775
+ }
1776
+ storyInfo.totalCost = totalCost;
1777
+ storyInfo.totalInputTokens = totalInputTokens;
1778
+ storyInfo.totalOutputTokens = totalOutputTokens;
1779
+ this.storyStore.updateStoryMetadata(storyId, storyInfo);
1780
+ }
1781
+ catch (error) {
1782
+ console.error(`Error updating story cost for ${storyId}:`, error);
1783
+ }
1784
+ }
1785
+ };
1786
+ exports.StoryService = StoryService;
1787
+ exports.StoryService = StoryService = __decorate([
1788
+ (0, common_1.Injectable)(),
1789
+ __metadata("design:paramtypes", [story_store_service_1.StoryStoreService,
1790
+ agent_store_service_1.AgentStoreService,
1791
+ room_store_service_1.RoomStoreService,
1792
+ story_progress_service_1.StoryProgressService,
1793
+ story_message_service_1.StoryMessageService,
1794
+ configuration_service_1.ConfigurationService,
1795
+ agent_factory_1.AgentFactory,
1796
+ room_factory_1.RoomFactory])
1797
+ ], StoryService);