@things-factory/board-ai 10.0.0-beta.108

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/PLAN-styling-tools.md +1253 -0
  2. package/client/components/board-ai-chat.test.ts +149 -0
  3. package/client/components/board-ai-chat.ts +2574 -0
  4. package/client/components/chat-echo-dedup.test.ts +116 -0
  5. package/client/components/chat-echo-dedup.ts +89 -0
  6. package/client/components/chat-input-builder.ts +47 -0
  7. package/client/components/default-catalog-entries.test.ts +59 -0
  8. package/client/components/default-catalog-entries.ts +100 -0
  9. package/client/components/default-slash-templates.test.ts +55 -0
  10. package/client/components/default-slash-templates.ts +129 -0
  11. package/client/components/markdown.test.ts +518 -0
  12. package/client/components/markdown.ts +508 -0
  13. package/client/components/mention-popup-helpers.ts +433 -0
  14. package/client/components/mention-popup.test.ts +588 -0
  15. package/client/components/mention-popup.ts +238 -0
  16. package/client/index.ts +11 -0
  17. package/client/tsconfig.json +13 -0
  18. package/client/utils/board-edit-patch.ts +374 -0
  19. package/config/config.development.js +43 -0
  20. package/config/config.production.js +15 -0
  21. package/dist-client/client/components/board-ai-chat.d.ts +277 -0
  22. package/dist-client/client/components/board-ai-chat.js +2444 -0
  23. package/dist-client/client/components/board-ai-chat.js.map +1 -0
  24. package/dist-client/client/components/board-ai-chat.test.d.ts +1 -0
  25. package/dist-client/client/components/board-ai-chat.test.js +138 -0
  26. package/dist-client/client/components/board-ai-chat.test.js.map +1 -0
  27. package/dist-client/client/components/chat-echo-dedup.d.ts +45 -0
  28. package/dist-client/client/components/chat-echo-dedup.js +58 -0
  29. package/dist-client/client/components/chat-echo-dedup.js.map +1 -0
  30. package/dist-client/client/components/chat-echo-dedup.test.d.ts +1 -0
  31. package/dist-client/client/components/chat-echo-dedup.test.js +101 -0
  32. package/dist-client/client/components/chat-echo-dedup.test.js.map +1 -0
  33. package/dist-client/client/components/chat-input-builder.d.ts +39 -0
  34. package/dist-client/client/components/chat-input-builder.js +26 -0
  35. package/dist-client/client/components/chat-input-builder.js.map +1 -0
  36. package/dist-client/client/components/default-catalog-entries.d.ts +15 -0
  37. package/dist-client/client/components/default-catalog-entries.js +86 -0
  38. package/dist-client/client/components/default-catalog-entries.js.map +1 -0
  39. package/dist-client/client/components/default-catalog-entries.test.d.ts +1 -0
  40. package/dist-client/client/components/default-catalog-entries.test.js +52 -0
  41. package/dist-client/client/components/default-catalog-entries.test.js.map +1 -0
  42. package/dist-client/client/components/default-slash-templates.d.ts +17 -0
  43. package/dist-client/client/components/default-slash-templates.js +113 -0
  44. package/dist-client/client/components/default-slash-templates.js.map +1 -0
  45. package/dist-client/client/components/default-slash-templates.test.d.ts +1 -0
  46. package/dist-client/client/components/default-slash-templates.test.js +51 -0
  47. package/dist-client/client/components/default-slash-templates.test.js.map +1 -0
  48. package/dist-client/client/components/markdown.d.ts +60 -0
  49. package/dist-client/client/components/markdown.js +422 -0
  50. package/dist-client/client/components/markdown.js.map +1 -0
  51. package/dist-client/client/components/markdown.test.d.ts +1 -0
  52. package/dist-client/client/components/markdown.test.js +418 -0
  53. package/dist-client/client/components/markdown.test.js.map +1 -0
  54. package/dist-client/client/components/mention-popup-helpers.d.ts +165 -0
  55. package/dist-client/client/components/mention-popup-helpers.js +330 -0
  56. package/dist-client/client/components/mention-popup-helpers.js.map +1 -0
  57. package/dist-client/client/components/mention-popup.d.ts +35 -0
  58. package/dist-client/client/components/mention-popup.js +223 -0
  59. package/dist-client/client/components/mention-popup.js.map +1 -0
  60. package/dist-client/client/components/mention-popup.test.d.ts +1 -0
  61. package/dist-client/client/components/mention-popup.test.js +474 -0
  62. package/dist-client/client/components/mention-popup.test.js.map +1 -0
  63. package/dist-client/client/index.d.ts +11 -0
  64. package/dist-client/client/index.js +12 -0
  65. package/dist-client/client/index.js.map +1 -0
  66. package/dist-client/client/utils/board-edit-patch.d.ts +157 -0
  67. package/dist-client/client/utils/board-edit-patch.js +284 -0
  68. package/dist-client/client/utils/board-edit-patch.js.map +1 -0
  69. package/dist-client/server/service/agentic-loop.d.ts +87 -0
  70. package/dist-client/server/service/agentic-loop.js +276 -0
  71. package/dist-client/server/service/agentic-loop.js.map +1 -0
  72. package/dist-client/server/service/assistant.d.ts +84 -0
  73. package/dist-client/server/service/assistant.js +2220 -0
  74. package/dist-client/server/service/assistant.js.map +1 -0
  75. package/dist-client/server/service/catalog-resolver.d.ts +18 -0
  76. package/dist-client/server/service/catalog-resolver.js +93 -0
  77. package/dist-client/server/service/catalog-resolver.js.map +1 -0
  78. package/dist-client/server/service/component-tree.d.ts +68 -0
  79. package/dist-client/server/service/component-tree.js +68 -0
  80. package/dist-client/server/service/component-tree.js.map +1 -0
  81. package/dist-client/server/service/mention-resolver.d.ts +96 -0
  82. package/dist-client/server/service/mention-resolver.js +172 -0
  83. package/dist-client/server/service/mention-resolver.js.map +1 -0
  84. package/dist-client/server/service/prefab-registry.d.ts +73 -0
  85. package/dist-client/server/service/prefab-registry.js +252 -0
  86. package/dist-client/server/service/prefab-registry.js.map +1 -0
  87. package/dist-client/server/service/styling/clear-tools.d.ts +15 -0
  88. package/dist-client/server/service/styling/clear-tools.js +50 -0
  89. package/dist-client/server/service/styling/clear-tools.js.map +1 -0
  90. package/dist-client/server/service/styling/color-utils.d.ts +43 -0
  91. package/dist-client/server/service/styling/color-utils.js +205 -0
  92. package/dist-client/server/service/styling/color-utils.js.map +1 -0
  93. package/dist-client/server/service/styling/copy-tools.d.ts +27 -0
  94. package/dist-client/server/service/styling/copy-tools.js +78 -0
  95. package/dist-client/server/service/styling/copy-tools.js.map +1 -0
  96. package/dist-client/server/service/styling/effect-tools.d.ts +45 -0
  97. package/dist-client/server/service/styling/effect-tools.js +85 -0
  98. package/dist-client/server/service/styling/effect-tools.js.map +1 -0
  99. package/dist-client/server/service/styling/fill-tools.d.ts +60 -0
  100. package/dist-client/server/service/styling/fill-tools.js +226 -0
  101. package/dist-client/server/service/styling/fill-tools.js.map +1 -0
  102. package/dist-client/server/service/styling/material-tools.d.ts +32 -0
  103. package/dist-client/server/service/styling/material-tools.js +88 -0
  104. package/dist-client/server/service/styling/material-tools.js.map +1 -0
  105. package/dist-client/server/service/styling/read-tools.d.ts +34 -0
  106. package/dist-client/server/service/styling/read-tools.js +42 -0
  107. package/dist-client/server/service/styling/read-tools.js.map +1 -0
  108. package/dist-client/server/service/styling/registry.d.ts +91 -0
  109. package/dist-client/server/service/styling/registry.js +345 -0
  110. package/dist-client/server/service/styling/registry.js.map +1 -0
  111. package/dist-client/server/service/styling/stroke-tools.d.ts +35 -0
  112. package/dist-client/server/service/styling/stroke-tools.js +94 -0
  113. package/dist-client/server/service/styling/stroke-tools.js.map +1 -0
  114. package/dist-client/server/service/styling/text-tools.d.ts +32 -0
  115. package/dist-client/server/service/styling/text-tools.js +101 -0
  116. package/dist-client/server/service/styling/text-tools.js.map +1 -0
  117. package/dist-client/server/service/types.d.ts +265 -0
  118. package/dist-client/server/service/types.js +2 -0
  119. package/dist-client/server/service/types.js.map +1 -0
  120. package/dist-client/server/service/validation/board-model-schema.d.ts +8311 -0
  121. package/dist-client/server/service/validation/board-model-schema.js +402 -0
  122. package/dist-client/server/service/validation/board-model-schema.js.map +1 -0
  123. package/dist-client/server/service/validation/tool-validation.d.ts +31 -0
  124. package/dist-client/server/service/validation/tool-validation.js +193 -0
  125. package/dist-client/server/service/validation/tool-validation.js.map +1 -0
  126. package/dist-client/tsconfig.tsbuildinfo +1 -0
  127. package/dist-server/index.d.ts +23 -0
  128. package/dist-server/index.js +27 -0
  129. package/dist-server/index.js.map +1 -0
  130. package/dist-server/service/agentic-loop.d.ts +87 -0
  131. package/dist-server/service/agentic-loop.js +280 -0
  132. package/dist-server/service/agentic-loop.js.map +1 -0
  133. package/dist-server/service/apply-patch.d.ts +47 -0
  134. package/dist-server/service/apply-patch.js +369 -0
  135. package/dist-server/service/apply-patch.js.map +1 -0
  136. package/dist-server/service/assistant.d.ts +84 -0
  137. package/dist-server/service/assistant.js +2237 -0
  138. package/dist-server/service/assistant.js.map +1 -0
  139. package/dist-server/service/board-ai-resolver.d.ts +54 -0
  140. package/dist-server/service/board-ai-resolver.js +409 -0
  141. package/dist-server/service/board-ai-resolver.js.map +1 -0
  142. package/dist-server/service/catalog-resolver.d.ts +18 -0
  143. package/dist-server/service/catalog-resolver.js +98 -0
  144. package/dist-server/service/catalog-resolver.js.map +1 -0
  145. package/dist-server/service/chat-message/chat-message-broadcast.d.ts +13 -0
  146. package/dist-server/service/chat-message/chat-message-broadcast.js +13 -0
  147. package/dist-server/service/chat-message/chat-message-broadcast.js.map +1 -0
  148. package/dist-server/service/chat-message/chat-message-publish.d.ts +6 -0
  149. package/dist-server/service/chat-message/chat-message-publish.js +27 -0
  150. package/dist-server/service/chat-message/chat-message-publish.js.map +1 -0
  151. package/dist-server/service/chat-message/chat-message-subscription.d.ts +8 -0
  152. package/dist-server/service/chat-message/chat-message-subscription.js +53 -0
  153. package/dist-server/service/chat-message/chat-message-subscription.js.map +1 -0
  154. package/dist-server/service/chat-message/chat-message.d.ts +56 -0
  155. package/dist-server/service/chat-message/chat-message.js +149 -0
  156. package/dist-server/service/chat-message/chat-message.js.map +1 -0
  157. package/dist-server/service/chat-message/index.d.ts +5 -0
  158. package/dist-server/service/chat-message/index.js +12 -0
  159. package/dist-server/service/chat-message/index.js.map +1 -0
  160. package/dist-server/service/chat-session/chat-session.d.ts +31 -0
  161. package/dist-server/service/chat-session/chat-session.js +131 -0
  162. package/dist-server/service/chat-session/chat-session.js.map +1 -0
  163. package/dist-server/service/chat-session/index.d.ts +3 -0
  164. package/dist-server/service/chat-session/index.js +7 -0
  165. package/dist-server/service/chat-session/index.js.map +1 -0
  166. package/dist-server/service/chat-session-participant/chat-session-participant.d.ts +30 -0
  167. package/dist-server/service/chat-session-participant/chat-session-participant.js +112 -0
  168. package/dist-server/service/chat-session-participant/chat-session-participant.js.map +1 -0
  169. package/dist-server/service/chat-session-participant/index.d.ts +4 -0
  170. package/dist-server/service/chat-session-participant/index.js +10 -0
  171. package/dist-server/service/chat-session-participant/index.js.map +1 -0
  172. package/dist-server/service/chat-session-participant/invite-notification.d.ts +27 -0
  173. package/dist-server/service/chat-session-participant/invite-notification.js +30 -0
  174. package/dist-server/service/chat-session-participant/invite-notification.js.map +1 -0
  175. package/dist-server/service/chat-session-participant/presence.d.ts +4 -0
  176. package/dist-server/service/chat-session-participant/presence.js +22 -0
  177. package/dist-server/service/chat-session-participant/presence.js.map +1 -0
  178. package/dist-server/service/chat-session-resolver.d.ts +20 -0
  179. package/dist-server/service/chat-session-resolver.js +356 -0
  180. package/dist-server/service/chat-session-resolver.js.map +1 -0
  181. package/dist-server/service/component-tree.d.ts +68 -0
  182. package/dist-server/service/component-tree.js +73 -0
  183. package/dist-server/service/component-tree.js.map +1 -0
  184. package/dist-server/service/index.d.ts +20 -0
  185. package/dist-server/service/index.js +34 -0
  186. package/dist-server/service/index.js.map +1 -0
  187. package/dist-server/service/mention-marker.d.ts +78 -0
  188. package/dist-server/service/mention-marker.js +162 -0
  189. package/dist-server/service/mention-marker.js.map +1 -0
  190. package/dist-server/service/mention-resolver.d.ts +96 -0
  191. package/dist-server/service/mention-resolver.js +177 -0
  192. package/dist-server/service/mention-resolver.js.map +1 -0
  193. package/dist-server/service/patch-entry/board-patch-broadcast.d.ts +13 -0
  194. package/dist-server/service/patch-entry/board-patch-broadcast.js +13 -0
  195. package/dist-server/service/patch-entry/board-patch-broadcast.js.map +1 -0
  196. package/dist-server/service/patch-entry/board-patch-subscription.d.ts +12 -0
  197. package/dist-server/service/patch-entry/board-patch-subscription.js +63 -0
  198. package/dist-server/service/patch-entry/board-patch-subscription.js.map +1 -0
  199. package/dist-server/service/patch-entry/index.d.ts +4 -0
  200. package/dist-server/service/patch-entry/index.js +12 -0
  201. package/dist-server/service/patch-entry/index.js.map +1 -0
  202. package/dist-server/service/patch-entry/patch-entry.d.ts +16 -0
  203. package/dist-server/service/patch-entry/patch-entry.js +96 -0
  204. package/dist-server/service/patch-entry/patch-entry.js.map +1 -0
  205. package/dist-server/service/prefab-registry.d.ts +73 -0
  206. package/dist-server/service/prefab-registry.js +258 -0
  207. package/dist-server/service/prefab-registry.js.map +1 -0
  208. package/dist-server/service/styling/clear-tools.d.ts +15 -0
  209. package/dist-server/service/styling/clear-tools.js +53 -0
  210. package/dist-server/service/styling/clear-tools.js.map +1 -0
  211. package/dist-server/service/styling/color-utils.d.ts +43 -0
  212. package/dist-server/service/styling/color-utils.js +210 -0
  213. package/dist-server/service/styling/color-utils.js.map +1 -0
  214. package/dist-server/service/styling/copy-tools.d.ts +27 -0
  215. package/dist-server/service/styling/copy-tools.js +81 -0
  216. package/dist-server/service/styling/copy-tools.js.map +1 -0
  217. package/dist-server/service/styling/effect-tools.d.ts +45 -0
  218. package/dist-server/service/styling/effect-tools.js +90 -0
  219. package/dist-server/service/styling/effect-tools.js.map +1 -0
  220. package/dist-server/service/styling/fill-tools.d.ts +60 -0
  221. package/dist-server/service/styling/fill-tools.js +229 -0
  222. package/dist-server/service/styling/fill-tools.js.map +1 -0
  223. package/dist-server/service/styling/material-tools.d.ts +32 -0
  224. package/dist-server/service/styling/material-tools.js +92 -0
  225. package/dist-server/service/styling/material-tools.js.map +1 -0
  226. package/dist-server/service/styling/read-tools.d.ts +34 -0
  227. package/dist-server/service/styling/read-tools.js +45 -0
  228. package/dist-server/service/styling/read-tools.js.map +1 -0
  229. package/dist-server/service/styling/registry.d.ts +91 -0
  230. package/dist-server/service/styling/registry.js +352 -0
  231. package/dist-server/service/styling/registry.js.map +1 -0
  232. package/dist-server/service/styling/stroke-tools.d.ts +35 -0
  233. package/dist-server/service/styling/stroke-tools.js +97 -0
  234. package/dist-server/service/styling/stroke-tools.js.map +1 -0
  235. package/dist-server/service/styling/text-tools.d.ts +32 -0
  236. package/dist-server/service/styling/text-tools.js +105 -0
  237. package/dist-server/service/styling/text-tools.js.map +1 -0
  238. package/dist-server/service/subscribe-auth.d.ts +14 -0
  239. package/dist-server/service/subscribe-auth.js +33 -0
  240. package/dist-server/service/subscribe-auth.js.map +1 -0
  241. package/dist-server/service/types.d.ts +265 -0
  242. package/dist-server/service/types.js +3 -0
  243. package/dist-server/service/types.js.map +1 -0
  244. package/dist-server/service/validation/board-model-schema.d.ts +8311 -0
  245. package/dist-server/service/validation/board-model-schema.js +409 -0
  246. package/dist-server/service/validation/board-model-schema.js.map +1 -0
  247. package/dist-server/service/validation/tool-validation.d.ts +31 -0
  248. package/dist-server/service/validation/tool-validation.js +196 -0
  249. package/dist-server/service/validation/tool-validation.js.map +1 -0
  250. package/dist-server/tsconfig.tsbuildinfo +1 -0
  251. package/package.json +48 -0
  252. package/server/index.ts +23 -0
  253. package/server/service/agentic-loop.test.ts +705 -0
  254. package/server/service/agentic-loop.ts +431 -0
  255. package/server/service/apply-patch-drift.test.ts +829 -0
  256. package/server/service/apply-patch.test.ts +757 -0
  257. package/server/service/apply-patch.ts +411 -0
  258. package/server/service/assistant-integration.test.ts +922 -0
  259. package/server/service/assistant-llm-smoke.test.ts +296 -0
  260. package/server/service/assistant.test.ts +2034 -0
  261. package/server/service/assistant.ts +2378 -0
  262. package/server/service/board-ai-resolver.ts +407 -0
  263. package/server/service/catalog-resolver.test.ts +137 -0
  264. package/server/service/catalog-resolver.ts +102 -0
  265. package/server/service/chat-message/chat-message-broadcast.integration.test.ts +73 -0
  266. package/server/service/chat-message/chat-message-broadcast.test.ts +40 -0
  267. package/server/service/chat-message/chat-message-broadcast.ts +27 -0
  268. package/server/service/chat-message/chat-message-publish.ts +22 -0
  269. package/server/service/chat-message/chat-message-subscription.ts +41 -0
  270. package/server/service/chat-message/chat-message.ts +169 -0
  271. package/server/service/chat-message/index.ts +12 -0
  272. package/server/service/chat-session/chat-session.ts +130 -0
  273. package/server/service/chat-session/index.ts +5 -0
  274. package/server/service/chat-session-participant/chat-session-participant.ts +110 -0
  275. package/server/service/chat-session-participant/index.ts +6 -0
  276. package/server/service/chat-session-participant/invite-notification.test.ts +30 -0
  277. package/server/service/chat-session-participant/invite-notification.ts +48 -0
  278. package/server/service/chat-session-participant/presence.test.ts +39 -0
  279. package/server/service/chat-session-participant/presence.ts +21 -0
  280. package/server/service/chat-session-resolver.ts +312 -0
  281. package/server/service/component-tree.test.ts +248 -0
  282. package/server/service/component-tree.ts +135 -0
  283. package/server/service/index.ts +32 -0
  284. package/server/service/mention-marker.extract.test.ts +61 -0
  285. package/server/service/mention-marker.test.ts +228 -0
  286. package/server/service/mention-marker.ts +184 -0
  287. package/server/service/mention-resolver.test.ts +273 -0
  288. package/server/service/mention-resolver.ts +264 -0
  289. package/server/service/patch-entry/board-patch-broadcast.ts +24 -0
  290. package/server/service/patch-entry/board-patch-subscription.test.ts +40 -0
  291. package/server/service/patch-entry/board-patch-subscription.ts +50 -0
  292. package/server/service/patch-entry/index.ts +12 -0
  293. package/server/service/patch-entry/patch-entry.ts +89 -0
  294. package/server/service/prefab-registry.test.ts +172 -0
  295. package/server/service/prefab-registry.ts +332 -0
  296. package/server/service/styling/clear-tools.test.ts +164 -0
  297. package/server/service/styling/clear-tools.ts +69 -0
  298. package/server/service/styling/color-utils.test.ts +130 -0
  299. package/server/service/styling/color-utils.ts +226 -0
  300. package/server/service/styling/copy-tools.test.ts +152 -0
  301. package/server/service/styling/copy-tools.ts +115 -0
  302. package/server/service/styling/effect-tools.test.ts +277 -0
  303. package/server/service/styling/effect-tools.ts +124 -0
  304. package/server/service/styling/fill-tools.test.ts +331 -0
  305. package/server/service/styling/fill-tools.ts +293 -0
  306. package/server/service/styling/material-tools.test.ts +294 -0
  307. package/server/service/styling/material-tools.ts +114 -0
  308. package/server/service/styling/read-tools.test.ts +78 -0
  309. package/server/service/styling/read-tools.ts +67 -0
  310. package/server/service/styling/registry.test.ts +203 -0
  311. package/server/service/styling/registry.ts +423 -0
  312. package/server/service/styling/stroke-tools.test.ts +245 -0
  313. package/server/service/styling/stroke-tools.ts +145 -0
  314. package/server/service/styling/text-tools.test.ts +253 -0
  315. package/server/service/styling/text-tools.ts +131 -0
  316. package/server/service/styling/tier1-tools.test.ts +300 -0
  317. package/server/service/subscribe-auth.test.ts +57 -0
  318. package/server/service/subscribe-auth.ts +34 -0
  319. package/server/service/types.ts +235 -0
  320. package/server/service/validation/board-model-schema.test.ts +778 -0
  321. package/server/service/validation/board-model-schema.ts +446 -0
  322. package/server/service/validation/tool-validation.ts +228 -0
  323. package/things-factory.config.js +1 -0
  324. package/translations/en.json +49 -0
  325. package/translations/ja.json +48 -0
  326. package/translations/ko.json +49 -0
  327. package/translations/ms.json +48 -0
  328. package/translations/zh.json +48 -0
  329. package/tsconfig.json +9 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-session-resolver.js","sourceRoot":"","sources":["../../server/service/chat-session-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatSession lifecycle resolver — start/get/recordDirectPatch/revertPatch + 메시지·패치 페이징 query.\n *\n * 핵심: `recordDirectPatch` — 사용자가 모델러에서 직접 편집 시 클라이언트가 호출.\n * 이게 PatchEntry(source:'user-direct') + system 메시지 자동 추가 → AI 가 모든 변경을 인지.\n */\nimport { Resolver, Query, Mutation, Arg, Ctx, Directive, Int } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\nimport { User } from '@things-factory/auth-base'\nimport { buildDomainUsersQueryBuilder } from '@things-factory/auth-base/dist-server/utils/get-domain-users.js'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { ChatSession } from './chat-session/chat-session.js'\nimport { ChatMessage } from './chat-message/chat-message.js'\nimport { ChatSessionParticipant } from './chat-session-participant/chat-session-participant.js'\nimport { PatchEntry } from './patch-entry/patch-entry.js'\nimport { publishBoardPatch } from './patch-entry/board-patch-subscription.js'\nimport { publishChatMessage } from './chat-message/chat-message-publish.js'\n\n@Resolver()\nexport class ChatSessionResolver {\n @Query(() => ChatSession, { nullable: true, description: 'Get AI chat session by id.' })\n @Directive('@privilege(category: \"board-ai\", privilege: \"query\")')\n async chatSession(\n @Arg('id') id: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession | null> {\n const { domain } = context.state\n return (await getRepository(ChatSession).findOneBy({ id, domain: { id: domain.id } })) ?? null\n }\n\n @Query(() => ChatSession, { nullable: true, description: 'Get AI chat session by board id (returns first match — backward compat single-session lookup).' })\n @Directive('@privilege(category: \"board-ai\", privilege: \"query\")')\n async chatSessionByBoard(\n @Arg('boardId') boardId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession | null> {\n const { domain } = context.state\n return (\n (await getRepository(ChatSession).findOneBy({ boardId, domain: { id: domain.id } })) ?? null\n )\n }\n\n @Query(() => [ChatSession], {\n description: 'List all AI chat sessions for a board (oldest first). Multi-session support — UI 탭으로 표시.'\n })\n @Directive('@privilege(category: \"board-ai\", privilege: \"query\")')\n async chatSessionsByBoard(\n @Arg('boardId') boardId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession[]> {\n const { domain } = context.state\n return await getRepository(ChatSession).find({\n where: { boardId, domain: { id: domain.id } },\n order: { createdAt: 'ASC' }\n })\n }\n\n @Query(() => [User], {\n description:\n 'List users in the current domain for `@` mention popup. board-ai 권한이면 누구나 멘션용 검색 가능 (관리자 전용 users() 와 별도).'\n })\n @Directive('@privilege(category: \"board-ai\", privilege: \"query\")')\n async domainUsersForMention(\n @Arg('query', { nullable: true, description: 'Substring to match against name/email (case-insensitive). Empty → all.' }) query: string | undefined,\n @Arg('limit', () => Int, { nullable: true, defaultValue: 50 }) limit: number,\n @Ctx() context: ResolverContext\n ): Promise<User[]> {\n const { domain } = context.state\n const qb = buildDomainUsersQueryBuilder(domain.id, 'USER')\n if (query?.trim()) {\n const q = `%${query.trim().toLowerCase()}%`\n qb.andWhere('(LOWER(USER.name) LIKE :q OR LOWER(USER.email) LIKE :q)', { q })\n }\n qb.orderBy('USER.name', 'ASC').limit(limit)\n return await qb.getMany()\n }\n\n @Query(() => [ChatSessionParticipant], {\n description: 'List participants of a ChatSession (members / owner).'\n })\n @Directive('@privilege(category: \"board-ai\", privilege: \"query\")')\n async chatSessionParticipants(\n @Arg('sessionId') sessionId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSessionParticipant[]> {\n const { domain } = context.state\n const session = await getRepository(ChatSession).findOneBy({\n id: sessionId,\n domain: { id: domain.id }\n })\n if (!session) return []\n return await getRepository(ChatSessionParticipant).find({\n where: { session: { id: sessionId } as any, domain: { id: domain.id } },\n order: { createdAt: 'ASC' }\n })\n }\n\n @Mutation(() => Boolean, {\n description: 'Presence heartbeat — bump current user\\'s lastSeenAt in the session (online indicator).'\n })\n @Directive('@privilege(category: \"board-ai\", privilege: \"mutation\")')\n async touchPresence(@Arg('sessionId') sessionId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, user } = context.state\n const repo = getRepository(ChatSessionParticipant)\n const part = await repo.findOne({\n where: { session: { id: sessionId } as any, user: { id: user.id } as any, domain: { id: domain.id } as any }\n })\n if (!part) return false // 참여자가 아니면 heartbeat 무시 (초대 전)\n await repo.update(part.id!, { lastSeenAt: new Date(), updater: user } as any)\n return true\n }\n\n @Query(() => [ChatMessage], { description: 'List chat messages of a session, oldest first.' })\n @Directive('@privilege(category: \"board-ai\", privilege: \"query\")')\n async chatMessages(\n @Arg('sessionId') sessionId: string,\n @Arg('limit', () => Int, { nullable: true, defaultValue: 100 }) limit: number,\n @Arg('offset', () => Int, { nullable: true, defaultValue: 0 }) offset: number,\n @Ctx() context: ResolverContext\n ): Promise<ChatMessage[]> {\n const { domain } = context.state\n const session = await getRepository(ChatSession).findOneBy({\n id: sessionId,\n domain: { id: domain.id }\n })\n if (!session) return []\n return await getRepository(ChatMessage).find({\n where: { session: { id: sessionId } as any },\n // creator: 그룹챗 발신자 표시용 (id/name). 다른 참여자 메시지에 보낸이를 보여준다.\n relations: { creator: true },\n order: { createdAt: 'ASC' },\n take: limit,\n skip: offset\n })\n }\n\n @Query(() => [PatchEntry], { description: 'List patch entries of a session, newest first.' })\n @Directive('@privilege(category: \"board-ai\", privilege: \"query\")')\n async chatPatches(\n @Arg('sessionId') sessionId: string,\n @Arg('limit', () => Int, { nullable: true, defaultValue: 100 }) limit: number,\n @Ctx() context: ResolverContext\n ): Promise<PatchEntry[]> {\n const { domain } = context.state\n const session = await getRepository(ChatSession).findOneBy({\n id: sessionId,\n domain: { id: domain.id }\n })\n if (!session) return []\n return await getRepository(PatchEntry).find({\n where: { session: { id: sessionId } as any },\n order: { createdAt: 'DESC' },\n take: limit\n })\n }\n\n @Directive('@transaction')\n @Mutation(() => ChatSession, {\n description: 'Start (or get existing) AI chat session for a board. Idempotent — returns first existing or creates one.'\n })\n @Directive('@privilege(category: \"board-ai\", privilege: \"mutation\")')\n async startBoardAISession(\n @Arg('boardId') boardId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n\n const existing = await repo.findOneBy({ boardId, domain: { id: domain.id } })\n if (existing) return existing\n\n const session = await repo.save({\n domain,\n boardId,\n creator: user,\n updater: user\n } as any)\n // creator 를 owner participant 로 자동 등록 — 다자간 채팅 기반.\n await getRepository(ChatSessionParticipant, tx).save({\n domain,\n session: { id: session.id } as any,\n user,\n role: 'owner',\n creator: user,\n updater: user\n } as any)\n return session\n }\n\n @Directive('@transaction')\n @Mutation(() => ChatSession, {\n description: 'Always create a new AI chat session for a board (no idempotent reuse). For multi-session UX — 새 탭 열기.'\n })\n @Directive('@privilege(category: \"board-ai\", privilege: \"mutation\")')\n async createChatSession(\n @Arg('boardId') boardId: string,\n @Arg('name', { nullable: true, description: 'Optional name (defaults to auto-generated `세션 N`).' }) name: string | undefined,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n\n // 이름 미지정 시 자동 생성 — 보드의 기존 세션 수 + 1.\n let finalName = name?.trim()\n if (!finalName) {\n const count = await repo.count({\n where: { boardId, domain: { id: domain.id } }\n })\n finalName = `세션 ${count + 1}`\n }\n\n const session = await repo.save({\n domain,\n boardId,\n creator: user,\n updater: user,\n name: finalName\n } as any)\n // creator 를 owner participant 로 자동 등록.\n await getRepository(ChatSessionParticipant, tx).save({\n domain,\n session: { id: session.id } as any,\n user,\n role: 'owner',\n creator: user,\n updater: user\n } as any)\n return session\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description: 'Rename a ChatSession (tab label).'\n })\n @Directive('@privilege(category: \"board-ai\", privilege: \"mutation\")')\n async renameChatSession(\n @Arg('sessionId') sessionId: string,\n @Arg('name') name: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n const session = await repo.findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n await repo.update(sessionId, { name: name.trim() || null, updater: user } as any)\n return true\n }\n\n @Directive('@transaction')\n @Mutation(() => PatchEntry, {\n description: 'Record a patch from user direct edit. Adds a system message so AI sees the change next turn.'\n })\n @Directive('@privilege(category: \"board-ai\", privilege: \"mutation\")')\n async recordDirectPatch(\n @Arg('sessionId') sessionId: string,\n @Arg('ops', () => GraphQLJSON) ops: any[],\n @Arg('summary', { nullable: true }) summary: string | undefined,\n @Ctx() context: ResolverContext\n ): Promise<PatchEntry> {\n const { domain, tx, user } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({\n id: sessionId,\n domain: { id: domain.id }\n })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n\n const entry = await getRepository(PatchEntry, tx).save({\n session: { id: session.id } as any,\n source: 'user-direct',\n ops: JSON.stringify(ops || []),\n summary,\n reverted: false\n } as any)\n\n // AI 컨텍스트 흐름 — system 메시지 자동 추가. creator = 직접 편집한 사용자.\n // parentMessage = 직전 in-session 메시지 (timeline 연속성 유지 — system 도 chain 에 합류).\n const previousLast = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const sysMsg = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: 'system',\n content: `User directly edited the board: ${summary ?? `${(ops || []).length} op(s)`}`,\n relatedPatchId: entry.id,\n creator: user,\n updater: user,\n parentMessage: previousLast ? ({ id: previousLast.id } as any) : undefined\n } as any)\n\n // C1: user-direct 편집도 같은 board 구독자에게 방송 (AI·타참여자 실시간 반영). best-effort.\n publishBoardPatch({ domainId: domain.id, boardId: session.boardId, patch: entry })\n // C4: 직접편집 system 메시지를 같은 세션 구독자에게 방송 (transcript 실시간 일관성). best-effort.\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message: sysMsg })\n\n return entry\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, { description: 'Mark a patch as reverted (does not undo, only flags).' })\n @Directive('@privilege(category: \"board-ai\", privilege: \"mutation\")')\n async revertPatch(\n @Arg('patchId') patchId: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { tx } = context.state\n await getRepository(PatchEntry, tx).update(patchId, { reverted: true })\n return true\n }\n}\n"]}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * 보드의 컴포넌트 트리 walk helper.
3
+ *
4
+ * things-scene 의 보드 모델은 group / container 같은 부모 컴포넌트가 자기
5
+ * `components` 배열로 자식을 갖는 *재귀 구조*. AI / styling tool 의 입장에선
6
+ * "어떤 컴포넌트가 어디에 있든" 동일하게 다뤄야 함 — depth 와 parent 정보만
7
+ * 메타로 첨부해 *평면 list* 로 펼쳐 노출.
8
+ *
9
+ * 본 모듈은 *순수* 함수만 — board model 입력만으로 결과 결정. mutation 없음.
10
+ */
11
+ import type { BoardComponent, BoardModel } from '@things-factory/board-import';
12
+ /**
13
+ * 평면화된 컴포넌트 — 원본 컴포넌트 + 메타 (parent, depth, path).
14
+ *
15
+ * 메타는 원본을 mutate 하지 않고 별도로 노출 — LLM 이 "어느 group 안인지" 알
16
+ * 수 있되 영속 데이터엔 영향 없음.
17
+ */
18
+ export interface FlatComponent {
19
+ /** 원본 컴포넌트 (참조 — 변경 시 보드에 반영). */
20
+ component: BoardComponent;
21
+ /** 컴포넌트의 refid (없으면 undefined). 타깃팅 용도. */
22
+ refid: number | undefined;
23
+ /** 부모 컴포넌트의 refid (root 직속이면 undefined). */
24
+ parentRefid: number | undefined;
25
+ /** 0=root 직속, 1=group 안, 2=group 안 group 안, ... */
26
+ depth: number;
27
+ /** 부모-자식 chain 의 refid 시퀀스 (root 부터). 본 컴포넌트의 refid 도 끝에 포함. */
28
+ path: number[];
29
+ }
30
+ /**
31
+ * 보드의 모든 컴포넌트를 재귀 walk 해 평면 list 로 반환.
32
+ *
33
+ * 순서: depth-first pre-order — 부모 먼저, 그 다음 자식. 사용자/AI 가 보드를
34
+ * 좌상단부터 시각적으로 읽는 순서와 일치.
35
+ *
36
+ * 재귀 깊이 안전 — 일반적인 보드 (depth < 10) 에서 stack overflow 없음.
37
+ * 비정상적으로 깊은 (cycle 가능성?) 케이스는 maxDepth 로 cap.
38
+ */
39
+ export declare function collectAllComponents(board: BoardModel | null | undefined, options?: {
40
+ maxDepth?: number;
41
+ }): FlatComponent[];
42
+ /**
43
+ * 보드 트리 안에서 refid 로 컴포넌트 찾기 — 깊은 search.
44
+ *
45
+ * apply-patch 의 modify / remove 가 자식 refid 도 매칭하도록 해주는 핵심 helper.
46
+ * top-level 만 보던 기존 동작과 달리 group 안 자식도 찾는다.
47
+ *
48
+ * 반환: 찾은 컴포넌트 + 그 컴포넌트가 들어있는 array (parent 또는 board.components)
49
+ * + array 내 index. parent 정보로 in-place mutation 가능.
50
+ */
51
+ export interface FoundComponent {
52
+ component: BoardComponent;
53
+ /** 본 컴포넌트가 속한 array (부모의 components 또는 board.components). 직접 mutation 가능. */
54
+ parentArray: BoardComponent[];
55
+ /** parentArray 내에서의 index. */
56
+ index: number;
57
+ }
58
+ export declare function findComponentByRefid(board: BoardModel | null | undefined, refid: number): FoundComponent | undefined;
59
+ /**
60
+ * collectAllComponents 결과를 LLM 표시용으로 가볍게 요약 — 메타만.
61
+ * 본 컴포넌트 데이터는 별도 summarize 단계에서 처리.
62
+ */
63
+ export declare function describeComponentMeta(flat: FlatComponent): {
64
+ refid: number | undefined;
65
+ type: string;
66
+ parentRefid: number | undefined;
67
+ depth: number;
68
+ };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectAllComponents = collectAllComponents;
4
+ exports.findComponentByRefid = findComponentByRefid;
5
+ exports.describeComponentMeta = describeComponentMeta;
6
+ /**
7
+ * 보드의 모든 컴포넌트를 재귀 walk 해 평면 list 로 반환.
8
+ *
9
+ * 순서: depth-first pre-order — 부모 먼저, 그 다음 자식. 사용자/AI 가 보드를
10
+ * 좌상단부터 시각적으로 읽는 순서와 일치.
11
+ *
12
+ * 재귀 깊이 안전 — 일반적인 보드 (depth < 10) 에서 stack overflow 없음.
13
+ * 비정상적으로 깊은 (cycle 가능성?) 케이스는 maxDepth 로 cap.
14
+ */
15
+ function collectAllComponents(board, options = {}) {
16
+ if (!board || !Array.isArray(board.components))
17
+ return [];
18
+ const maxDepth = options.maxDepth ?? 32;
19
+ const out = [];
20
+ walk(board.components, undefined, 0, [], maxDepth, out);
21
+ return out;
22
+ }
23
+ function walk(components, parentRefid, depth, parentPath, maxDepth, out) {
24
+ if (depth > maxDepth)
25
+ return;
26
+ for (const c of components) {
27
+ if (!c || typeof c !== 'object')
28
+ continue;
29
+ const refid = typeof c.refid === 'number' ? c.refid : undefined;
30
+ const path = refid !== undefined ? [...parentPath, refid] : parentPath;
31
+ out.push({ component: c, refid, parentRefid, depth, path });
32
+ // 자식 컴포넌트 — group / container 의 components 배열
33
+ const children = c.components;
34
+ if (Array.isArray(children) && children.length > 0) {
35
+ walk(children, refid, depth + 1, path, maxDepth, out);
36
+ }
37
+ }
38
+ }
39
+ function findComponentByRefid(board, refid) {
40
+ if (!board || !Array.isArray(board.components))
41
+ return undefined;
42
+ return findInArray(board.components, refid);
43
+ }
44
+ function findInArray(arr, refid) {
45
+ for (let i = 0; i < arr.length; i++) {
46
+ const c = arr[i];
47
+ if (!c || typeof c !== 'object')
48
+ continue;
49
+ if (c.refid === refid) {
50
+ return { component: c, parentArray: arr, index: i };
51
+ }
52
+ const children = c.components;
53
+ if (Array.isArray(children) && children.length > 0) {
54
+ const sub = findInArray(children, refid);
55
+ if (sub)
56
+ return sub;
57
+ }
58
+ }
59
+ return undefined;
60
+ }
61
+ /**
62
+ * collectAllComponents 결과를 LLM 표시용으로 가볍게 요약 — 메타만.
63
+ * 본 컴포넌트 데이터는 별도 summarize 단계에서 처리.
64
+ */
65
+ function describeComponentMeta(flat) {
66
+ return {
67
+ refid: flat.refid,
68
+ type: typeof flat.component.type === 'string' ? flat.component.type : 'unknown',
69
+ parentRefid: flat.parentRefid,
70
+ depth: flat.depth
71
+ };
72
+ }
73
+ //# sourceMappingURL=component-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-tree.js","sourceRoot":"","sources":["../../server/service/component-tree.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 보드의 컴포넌트 트리 walk helper.\n *\n * things-scene 의 보드 모델은 group / container 같은 부모 컴포넌트가 자기\n * `components` 배열로 자식을 갖는 *재귀 구조*. AI / styling tool 의 입장에선\n * \"어떤 컴포넌트가 어디에 있든\" 동일하게 다뤄야 함 — depth 와 parent 정보만\n * 메타로 첨부해 *평면 list* 로 펼쳐 노출.\n *\n * 본 모듈은 *순수* 함수만 — board model 입력만으로 결과 결정. mutation 없음.\n */\nimport type { BoardComponent, BoardModel } from '@things-factory/board-import'\n\n/**\n * 평면화된 컴포넌트 — 원본 컴포넌트 + 메타 (parent, depth, path).\n *\n * 메타는 원본을 mutate 하지 않고 별도로 노출 — LLM 이 \"어느 group 안인지\" 알\n * 수 있되 영속 데이터엔 영향 없음.\n */\nexport interface FlatComponent {\n /** 원본 컴포넌트 (참조 — 변경 시 보드에 반영). */\n component: BoardComponent\n /** 컴포넌트의 refid (없으면 undefined). 타깃팅 용도. */\n refid: number | undefined\n /** 부모 컴포넌트의 refid (root 직속이면 undefined). */\n parentRefid: number | undefined\n /** 0=root 직속, 1=group 안, 2=group 안 group 안, ... */\n depth: number\n /** 부모-자식 chain 의 refid 시퀀스 (root 부터). 본 컴포넌트의 refid 도 끝에 포함. */\n path: number[]\n}\n\n/**\n * 보드의 모든 컴포넌트를 재귀 walk 해 평면 list 로 반환.\n *\n * 순서: depth-first pre-order — 부모 먼저, 그 다음 자식. 사용자/AI 가 보드를\n * 좌상단부터 시각적으로 읽는 순서와 일치.\n *\n * 재귀 깊이 안전 — 일반적인 보드 (depth < 10) 에서 stack overflow 없음.\n * 비정상적으로 깊은 (cycle 가능성?) 케이스는 maxDepth 로 cap.\n */\nexport function collectAllComponents(\n board: BoardModel | null | undefined,\n options: { maxDepth?: number } = {}\n): FlatComponent[] {\n if (!board || !Array.isArray(board.components)) return []\n const maxDepth = options.maxDepth ?? 32\n const out: FlatComponent[] = []\n walk(board.components, undefined, 0, [], maxDepth, out)\n return out\n}\n\nfunction walk(\n components: BoardComponent[],\n parentRefid: number | undefined,\n depth: number,\n parentPath: number[],\n maxDepth: number,\n out: FlatComponent[]\n): void {\n if (depth > maxDepth) return\n for (const c of components) {\n if (!c || typeof c !== 'object') continue\n const refid = typeof (c as any).refid === 'number' ? (c as any).refid : undefined\n const path = refid !== undefined ? [...parentPath, refid] : parentPath\n out.push({ component: c, refid, parentRefid, depth, path })\n\n // 자식 컴포넌트 — group / container 의 components 배열\n const children = (c as any).components\n if (Array.isArray(children) && children.length > 0) {\n walk(children, refid, depth + 1, path, maxDepth, out)\n }\n }\n}\n\n/**\n * 보드 트리 안에서 refid 로 컴포넌트 찾기 — 깊은 search.\n *\n * apply-patch 의 modify / remove 가 자식 refid 도 매칭하도록 해주는 핵심 helper.\n * top-level 만 보던 기존 동작과 달리 group 안 자식도 찾는다.\n *\n * 반환: 찾은 컴포넌트 + 그 컴포넌트가 들어있는 array (parent 또는 board.components)\n * + array 내 index. parent 정보로 in-place mutation 가능.\n */\nexport interface FoundComponent {\n component: BoardComponent\n /** 본 컴포넌트가 속한 array (부모의 components 또는 board.components). 직접 mutation 가능. */\n parentArray: BoardComponent[]\n /** parentArray 내에서의 index. */\n index: number\n}\n\nexport function findComponentByRefid(\n board: BoardModel | null | undefined,\n refid: number\n): FoundComponent | undefined {\n if (!board || !Array.isArray(board.components)) return undefined\n return findInArray(board.components, refid)\n}\n\nfunction findInArray(\n arr: BoardComponent[],\n refid: number\n): FoundComponent | undefined {\n for (let i = 0; i < arr.length; i++) {\n const c = arr[i]\n if (!c || typeof c !== 'object') continue\n if ((c as any).refid === refid) {\n return { component: c, parentArray: arr, index: i }\n }\n const children = (c as any).components\n if (Array.isArray(children) && children.length > 0) {\n const sub = findInArray(children, refid)\n if (sub) return sub\n }\n }\n return undefined\n}\n\n/**\n * collectAllComponents 결과를 LLM 표시용으로 가볍게 요약 — 메타만.\n * 본 컴포넌트 데이터는 별도 summarize 단계에서 처리.\n */\nexport function describeComponentMeta(flat: FlatComponent): {\n refid: number | undefined\n type: string\n parentRefid: number | undefined\n depth: number\n} {\n return {\n refid: flat.refid,\n type: typeof flat.component.type === 'string' ? flat.component.type : 'unknown',\n parentRefid: flat.parentRefid,\n depth: flat.depth\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import { BoardAIChatResolver } from './board-ai-resolver.js';
2
+ import { ChatSessionResolver } from './chat-session-resolver.js';
3
+ import { BoardPatchSubscription } from './patch-entry/board-patch-subscription.js';
4
+ import { BoardChatMessageSubscription } from './chat-message/chat-message-subscription.js';
5
+ export * from './types.js';
6
+ export * from './assistant.js';
7
+ export * from './apply-patch.js';
8
+ export * from './prefab-registry.js';
9
+ export * from './mention-resolver.js';
10
+ export * from './catalog-resolver.js';
11
+ export * from './board-ai-resolver.js';
12
+ export * from './chat-session-resolver.js';
13
+ export * from './chat-session/index.js';
14
+ export * from './chat-message/index.js';
15
+ export * from './chat-session-participant/index.js';
16
+ export * from './patch-entry/index.js';
17
+ export declare const entities: (typeof import("./chat-message/chat-message.js").ChatMessage | typeof import("./chat-session/chat-session.js").ChatSession | typeof import("./patch-entry/patch-entry.js").PatchEntry | typeof import("./chat-session-participant/chat-session-participant.js").ChatSessionParticipant)[];
18
+ export declare const schema: {
19
+ resolverClasses: (typeof BoardPatchSubscription | typeof BoardAIChatResolver | typeof ChatSessionResolver | typeof BoardChatMessageSubscription)[];
20
+ };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.schema = exports.entities = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const board_ai_resolver_js_1 = require("./board-ai-resolver.js");
6
+ const chat_session_resolver_js_1 = require("./chat-session-resolver.js");
7
+ const board_patch_subscription_js_1 = require("./patch-entry/board-patch-subscription.js");
8
+ const chat_message_subscription_js_1 = require("./chat-message/chat-message-subscription.js");
9
+ const index_js_1 = require("./chat-session/index.js");
10
+ const index_js_2 = require("./chat-message/index.js");
11
+ const index_js_3 = require("./chat-session-participant/index.js");
12
+ const index_js_4 = require("./patch-entry/index.js");
13
+ tslib_1.__exportStar(require("./types.js"), exports);
14
+ tslib_1.__exportStar(require("./assistant.js"), exports);
15
+ tslib_1.__exportStar(require("./apply-patch.js"), exports);
16
+ tslib_1.__exportStar(require("./prefab-registry.js"), exports);
17
+ tslib_1.__exportStar(require("./mention-resolver.js"), exports);
18
+ tslib_1.__exportStar(require("./catalog-resolver.js"), exports);
19
+ tslib_1.__exportStar(require("./board-ai-resolver.js"), exports);
20
+ tslib_1.__exportStar(require("./chat-session-resolver.js"), exports);
21
+ tslib_1.__exportStar(require("./chat-session/index.js"), exports);
22
+ tslib_1.__exportStar(require("./chat-message/index.js"), exports);
23
+ tslib_1.__exportStar(require("./chat-session-participant/index.js"), exports);
24
+ tslib_1.__exportStar(require("./patch-entry/index.js"), exports);
25
+ exports.entities = [
26
+ ...index_js_1.entities,
27
+ ...index_js_2.entities,
28
+ ...index_js_3.entities,
29
+ ...index_js_4.entities
30
+ ];
31
+ exports.schema = {
32
+ resolverClasses: [board_ai_resolver_js_1.BoardAIChatResolver, chat_session_resolver_js_1.ChatSessionResolver, board_patch_subscription_js_1.BoardPatchSubscription, chat_message_subscription_js_1.BoardChatMessageSubscription]
33
+ };
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,iEAA4D;AAC5D,yEAAgE;AAChE,2FAAkF;AAClF,8FAA0F;AAC1F,sDAAyE;AACzE,sDAAyE;AACzE,kEAAgG;AAChG,qDAAuE;AAEvE,qDAA0B;AAC1B,yDAA8B;AAC9B,2DAAgC;AAChC,+DAAoC;AACpC,gEAAqC;AACrC,gEAAqC;AACrC,iEAAsC;AACtC,qEAA0C;AAC1C,kEAAuC;AACvC,kEAAuC;AACvC,8EAAmD;AACnD,iEAAsC;AAEzB,QAAA,QAAQ,GAAG;IACtB,GAAG,mBAAmB;IACtB,GAAG,mBAAmB;IACtB,GAAG,mBAA8B;IACjC,GAAG,mBAAkB;CACtB,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE,CAAC,0CAAmB,EAAE,8CAAmB,EAAE,oDAAsB,EAAE,2DAA4B,CAAC;CAClH,CAAA","sourcesContent":["import { BoardAIChatResolver } from './board-ai-resolver.js'\nimport { ChatSessionResolver } from './chat-session-resolver.js'\nimport { BoardPatchSubscription } from './patch-entry/board-patch-subscription.js'\nimport { BoardChatMessageSubscription } from './chat-message/chat-message-subscription.js'\nimport { entities as ChatSessionEntities } from './chat-session/index.js'\nimport { entities as ChatMessageEntities } from './chat-message/index.js'\nimport { entities as ChatSessionParticipantEntities } from './chat-session-participant/index.js'\nimport { entities as PatchEntryEntities } from './patch-entry/index.js'\n\nexport * from './types.js'\nexport * from './assistant.js'\nexport * from './apply-patch.js'\nexport * from './prefab-registry.js'\nexport * from './mention-resolver.js'\nexport * from './catalog-resolver.js'\nexport * from './board-ai-resolver.js'\nexport * from './chat-session-resolver.js'\nexport * from './chat-session/index.js'\nexport * from './chat-message/index.js'\nexport * from './chat-session-participant/index.js'\nexport * from './patch-entry/index.js'\n\nexport const entities = [\n ...ChatSessionEntities,\n ...ChatMessageEntities,\n ...ChatSessionParticipantEntities,\n ...PatchEntryEntities\n]\n\nexport const schema = {\n resolverClasses: [BoardAIChatResolver, ChatSessionResolver, BoardPatchSubscription, BoardChatMessageSubscription]\n}\n"]}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * `#token{refid:N}` inline marker — 채팅 메시지의 단일 source-of-truth.
3
+ *
4
+ * 설계 원칙:
5
+ * - 메시지 영속은 `ChatMessage.content` 한 컬럼에 통합. token-refid 매핑은 본문 안에
6
+ * `#motor1{refid:35}` 형태로 inline 마킹.
7
+ * - 별도 컬럼이 없으니 두 데이터 사이 consistency 깨질 일 자체가 없음.
8
+ * - LLM 한테는 `stripMentionRefids` 로 마커 제거 후 보냄 — 토큰 낭비 / 주의 분산 차단.
9
+ * - 클라이언트 렌더는 `#token{refid:N}` 패턴을 추출해 `<span data-refid="N">#token</span>`
10
+ * 으로 변환 → 클릭 시 deterministic 한 컴포넌트 점프.
11
+ *
12
+ * 마커 형식:
13
+ * - `#token{refid:N}` (N 은 정수)
14
+ * - token 과 `{` 사이 공백 없음
15
+ * - `{refid:N}` 자체는 사람도 디버그 시 읽기 쉬움 (zero-width 문자나 prefix 약어
16
+ * 보다 우선) — 렌더링 깨졌을 때 로그 / DB 직접 보고 파악 가능
17
+ */
18
+ import type { BoardModel } from '@things-factory/board-import';
19
+ import { type MentionPick } from './mention-resolver';
20
+ /**
21
+ * 인라인 마커 정규식 — `{key:value}` 형태. 현재 사용:
22
+ * - `{refid:N}` — `#component` 멘션 (things-scene refid)
23
+ * - `{userId:UUID}` — `@user` 멘션 (도메인 사용자)
24
+ * 향후 새 종류 (agentId / threadId / 외부 시스템 id 등) 도 동일 형식으로 추가 가능.
25
+ */
26
+ export declare const MENTION_MARKER_RE: RegExp;
27
+ /**
28
+ * 멘션된 userId 중 *아직 참여자가 아닌* + *자기 자신이 아닌* 신규만 (C4 초대 — 차집합).
29
+ * 순수 — 누구를 새로 참여자 등록할지 판정. (resolver 가 repo 작업과 분리해 테스트 가능.)
30
+ */
31
+ export declare function newParticipantUserIds(mentioned: ReadonlyArray<string>, existing: ReadonlyArray<string>, selfUserId?: string | null): string[];
32
+ /**
33
+ * 본문에서 `@user{userId:UUID}` 마커의 *userId 집합* 추출 (C4 — 초대 트리거).
34
+ * 같은 user 중복 제거, 순서 보존(첫 등장순). 마커 없으면 빈 배열.
35
+ * 순수 — content 만으로 "이 메시지가 누구를 멘션했나" 판정.
36
+ */
37
+ export declare function extractMentionUserIds(text: string | null | undefined): string[];
38
+ /**
39
+ * 본문에서 모든 `{key:value}` 인라인 마커 제거. LLM 입력 / textarea 편집 / 평문 표출 등.
40
+ * 토큰 자체 (#component, @user) 는 그대로 유지.
41
+ */
42
+ export declare function stripMentionRefids(text: string | null | undefined): string;
43
+ /**
44
+ * 일반화된 inline marker 주입 — trigger 와 markerKey 별로 picks 를 본문에 박음.
45
+ *
46
+ * injectInlineMarkers(text, '#', 'refid', [{ token, value: 35 }])
47
+ * injectInlineMarkers(text, '@', 'userId', [{ token, value: 'uuid' }])
48
+ *
49
+ * 룰:
50
+ * - 정확 token 일치 (popup 명시 선택된 것만 — 자유 입력 토큰은 안 건드림)
51
+ * - 동일 token 여러 번 등장하면 모두 marker 적용
52
+ * - 이미 같은 markerKey 의 marker 가 붙어있으면 그대로 유지 (덮어쓰기 X)
53
+ */
54
+ export declare function injectInlineMarkers(text: string, trigger: string, markerKey: string, picks: ReadonlyArray<{
55
+ token: string;
56
+ value: string | number;
57
+ }> | null | undefined): string;
58
+ /**
59
+ * `#component` 멘션 picks 를 `{refid:N}` 마커로 주입 (호환 유지).
60
+ */
61
+ export declare function injectMentionRefids(text: string, picks: ReadonlyArray<MentionPick> | null | undefined): string;
62
+ /**
63
+ * `@user` 멘션 picks 를 `{userId:UUID}` 마커로 주입.
64
+ * picks: [{token: 사용자_표시명, value: 사용자_id}]
65
+ */
66
+ export declare function injectMentionUserIds(text: string, picks: ReadonlyArray<{
67
+ token: string;
68
+ userId: string;
69
+ }> | null | undefined): string;
70
+ /**
71
+ * AI 응답 텍스트의 `#token` 들을 currentBoard 에 대해 resolve 해 inline marker 로 주입.
72
+ *
73
+ * - 매칭 룰: `findMentions` (= name/id/type/tag/class/text OR). 다중 일치 시 첫 결과.
74
+ * - 매칭 안 되면 marker 없이 통과 (예: AI 가 patch 로 새로 만든 컴포넌트는 input.currentBoard
75
+ * 에 없으므로 marker 못 박음 — 클라이언트 클릭 시 runtime fallback 으로 해석 가능).
76
+ * - 이미 marker 있으면 그대로.
77
+ */
78
+ export declare function injectAiMentionRefids(text: string, currentBoard: BoardModel | null | undefined): string;
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * `#token{refid:N}` inline marker — 채팅 메시지의 단일 source-of-truth.
4
+ *
5
+ * 설계 원칙:
6
+ * - 메시지 영속은 `ChatMessage.content` 한 컬럼에 통합. token-refid 매핑은 본문 안에
7
+ * `#motor1{refid:35}` 형태로 inline 마킹.
8
+ * - 별도 컬럼이 없으니 두 데이터 사이 consistency 깨질 일 자체가 없음.
9
+ * - LLM 한테는 `stripMentionRefids` 로 마커 제거 후 보냄 — 토큰 낭비 / 주의 분산 차단.
10
+ * - 클라이언트 렌더는 `#token{refid:N}` 패턴을 추출해 `<span data-refid="N">#token</span>`
11
+ * 으로 변환 → 클릭 시 deterministic 한 컴포넌트 점프.
12
+ *
13
+ * 마커 형식:
14
+ * - `#token{refid:N}` (N 은 정수)
15
+ * - token 과 `{` 사이 공백 없음
16
+ * - `{refid:N}` 자체는 사람도 디버그 시 읽기 쉬움 (zero-width 문자나 prefix 약어
17
+ * 보다 우선) — 렌더링 깨졌을 때 로그 / DB 직접 보고 파악 가능
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.MENTION_MARKER_RE = void 0;
21
+ exports.newParticipantUserIds = newParticipantUserIds;
22
+ exports.extractMentionUserIds = extractMentionUserIds;
23
+ exports.stripMentionRefids = stripMentionRefids;
24
+ exports.injectInlineMarkers = injectInlineMarkers;
25
+ exports.injectMentionRefids = injectMentionRefids;
26
+ exports.injectMentionUserIds = injectMentionUserIds;
27
+ exports.injectAiMentionRefids = injectAiMentionRefids;
28
+ const mention_resolver_1 = require("./mention-resolver");
29
+ /**
30
+ * 인라인 마커 정규식 — `{key:value}` 형태. 현재 사용:
31
+ * - `{refid:N}` — `#component` 멘션 (things-scene refid)
32
+ * - `{userId:UUID}` — `@user` 멘션 (도메인 사용자)
33
+ * 향후 새 종류 (agentId / threadId / 외부 시스템 id 등) 도 동일 형식으로 추가 가능.
34
+ */
35
+ exports.MENTION_MARKER_RE = /\{[a-zA-Z][a-zA-Z0-9]*:[^}\s]+\}/g;
36
+ /**
37
+ * 멘션된 userId 중 *아직 참여자가 아닌* + *자기 자신이 아닌* 신규만 (C4 초대 — 차집합).
38
+ * 순수 — 누구를 새로 참여자 등록할지 판정. (resolver 가 repo 작업과 분리해 테스트 가능.)
39
+ */
40
+ function newParticipantUserIds(mentioned, existing, selfUserId) {
41
+ const have = new Set(existing);
42
+ if (selfUserId)
43
+ have.add(selfUserId);
44
+ const out = [];
45
+ const seen = new Set();
46
+ for (const id of mentioned) {
47
+ if (!id || have.has(id) || seen.has(id))
48
+ continue;
49
+ seen.add(id);
50
+ out.push(id);
51
+ }
52
+ return out;
53
+ }
54
+ /**
55
+ * 본문에서 `@user{userId:UUID}` 마커의 *userId 집합* 추출 (C4 — 초대 트리거).
56
+ * 같은 user 중복 제거, 순서 보존(첫 등장순). 마커 없으면 빈 배열.
57
+ * 순수 — content 만으로 "이 메시지가 누구를 멘션했나" 판정.
58
+ */
59
+ function extractMentionUserIds(text) {
60
+ if (!text)
61
+ return [];
62
+ const re = /\{userId:([^}\s]+)\}/g;
63
+ const seen = new Set();
64
+ const out = [];
65
+ let m;
66
+ while ((m = re.exec(text)) !== null) {
67
+ const id = m[1];
68
+ if (!seen.has(id)) {
69
+ seen.add(id);
70
+ out.push(id);
71
+ }
72
+ }
73
+ return out;
74
+ }
75
+ /**
76
+ * 본문에서 모든 `{key:value}` 인라인 마커 제거. LLM 입력 / textarea 편집 / 평문 표출 등.
77
+ * 토큰 자체 (#component, @user) 는 그대로 유지.
78
+ */
79
+ function stripMentionRefids(text) {
80
+ if (!text)
81
+ return '';
82
+ return text.replace(exports.MENTION_MARKER_RE, '');
83
+ }
84
+ /** 토큰 매칭 정규식 빌더 — trigger 별로 build. */
85
+ function buildTokenRegex(trigger, markerKey) {
86
+ const word = '\\w\\p{Script=Hangul}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Han}';
87
+ // (앞경계)(트리거)(토큰)(이미 같은 markerKey 의 마커가 붙어있는지 — skip 판정용)
88
+ return new RegExp(`(^|[^${word}])(${escapeRegex(trigger)})([${word}-]+)(\\{${markerKey}:[^}\\s]+\\})?`, 'gu');
89
+ }
90
+ function escapeRegex(s) {
91
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
92
+ }
93
+ /**
94
+ * 일반화된 inline marker 주입 — trigger 와 markerKey 별로 picks 를 본문에 박음.
95
+ *
96
+ * injectInlineMarkers(text, '#', 'refid', [{ token, value: 35 }])
97
+ * injectInlineMarkers(text, '@', 'userId', [{ token, value: 'uuid' }])
98
+ *
99
+ * 룰:
100
+ * - 정확 token 일치 (popup 명시 선택된 것만 — 자유 입력 토큰은 안 건드림)
101
+ * - 동일 token 여러 번 등장하면 모두 marker 적용
102
+ * - 이미 같은 markerKey 의 marker 가 붙어있으면 그대로 유지 (덮어쓰기 X)
103
+ */
104
+ function injectInlineMarkers(text, trigger, markerKey, picks) {
105
+ if (!text || !picks || picks.length === 0)
106
+ return text ?? '';
107
+ const map = new Map();
108
+ for (const p of picks)
109
+ map.set(p.token, p.value);
110
+ const re = buildTokenRegex(trigger, markerKey);
111
+ return text.replace(re, (match, leading, trig, token, existingMarker) => {
112
+ if (existingMarker)
113
+ return match;
114
+ const value = map.get(token);
115
+ if (value === undefined)
116
+ return match;
117
+ return `${leading}${trig}${token}{${markerKey}:${value}}`;
118
+ });
119
+ }
120
+ /**
121
+ * `#component` 멘션 picks 를 `{refid:N}` 마커로 주입 (호환 유지).
122
+ */
123
+ function injectMentionRefids(text, picks) {
124
+ return injectInlineMarkers(text, '#', 'refid', picks?.map(p => ({ token: p.token, value: p.refid })));
125
+ }
126
+ /**
127
+ * `@user` 멘션 picks 를 `{userId:UUID}` 마커로 주입.
128
+ * picks: [{token: 사용자_표시명, value: 사용자_id}]
129
+ */
130
+ function injectMentionUserIds(text, picks) {
131
+ return injectInlineMarkers(text, '@', 'userId', picks?.map(p => ({ token: p.token, value: p.userId })));
132
+ }
133
+ /**
134
+ * AI 응답 텍스트의 `#token` 들을 currentBoard 에 대해 resolve 해 inline marker 로 주입.
135
+ *
136
+ * - 매칭 룰: `findMentions` (= name/id/type/tag/class/text OR). 다중 일치 시 첫 결과.
137
+ * - 매칭 안 되면 marker 없이 통과 (예: AI 가 patch 로 새로 만든 컴포넌트는 input.currentBoard
138
+ * 에 없으므로 marker 못 박음 — 클라이언트 클릭 시 runtime fallback 으로 해석 가능).
139
+ * - 이미 marker 있으면 그대로.
140
+ */
141
+ function injectAiMentionRefids(text, currentBoard) {
142
+ if (!text)
143
+ return '';
144
+ const matches = (0, mention_resolver_1.findMentions)(text, currentBoard ?? null);
145
+ if (matches.length === 0)
146
+ return text;
147
+ // token → 첫 매칭 refid 맵
148
+ const tokenToRefid = new Map();
149
+ for (const m of matches) {
150
+ if (tokenToRefid.has(m.token))
151
+ continue;
152
+ if (m.matched.length === 0)
153
+ continue;
154
+ tokenToRefid.set(m.token, m.matched[0].refid);
155
+ }
156
+ if (tokenToRefid.size === 0)
157
+ return text;
158
+ // 사용자 picks 와 동일한 injection 룰로 주입.
159
+ const picks = Array.from(tokenToRefid.entries()).map(([token, refid]) => ({ token, refid }));
160
+ return injectMentionRefids(text, picks);
161
+ }
162
+ //# sourceMappingURL=mention-marker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mention-marker.js","sourceRoot":"","sources":["../../server/service/mention-marker.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `#token{refid:N}` inline marker — 채팅 메시지의 단일 source-of-truth.\n *\n * 설계 원칙:\n * - 메시지 영속은 `ChatMessage.content` 한 컬럼에 통합. token-refid 매핑은 본문 안에\n * `#motor1{refid:35}` 형태로 inline 마킹.\n * - 별도 컬럼이 없으니 두 데이터 사이 consistency 깨질 일 자체가 없음.\n * - LLM 한테는 `stripMentionRefids` 로 마커 제거 후 보냄 — 토큰 낭비 / 주의 분산 차단.\n * - 클라이언트 렌더는 `#token{refid:N}` 패턴을 추출해 `<span data-refid=\"N\">#token</span>`\n * 으로 변환 → 클릭 시 deterministic 한 컴포넌트 점프.\n *\n * 마커 형식:\n * - `#token{refid:N}` (N 은 정수)\n * - token 과 `{` 사이 공백 없음\n * - `{refid:N}` 자체는 사람도 디버그 시 읽기 쉬움 (zero-width 문자나 prefix 약어\n * 보다 우선) — 렌더링 깨졌을 때 로그 / DB 직접 보고 파악 가능\n */\n\nimport type { BoardModel } from '@things-factory/board-import'\nimport { findMentions, type MentionPick } from './mention-resolver'\n\n/**\n * 인라인 마커 정규식 — `{key:value}` 형태. 현재 사용:\n * - `{refid:N}` — `#component` 멘션 (things-scene refid)\n * - `{userId:UUID}` — `@user` 멘션 (도메인 사용자)\n * 향후 새 종류 (agentId / threadId / 외부 시스템 id 등) 도 동일 형식으로 추가 가능.\n */\nexport const MENTION_MARKER_RE = /\\{[a-zA-Z][a-zA-Z0-9]*:[^}\\s]+\\}/g\n\n/**\n * 멘션된 userId 중 *아직 참여자가 아닌* + *자기 자신이 아닌* 신규만 (C4 초대 — 차집합).\n * 순수 — 누구를 새로 참여자 등록할지 판정. (resolver 가 repo 작업과 분리해 테스트 가능.)\n */\nexport function newParticipantUserIds(\n mentioned: ReadonlyArray<string>,\n existing: ReadonlyArray<string>,\n selfUserId?: string | null\n): string[] {\n const have = new Set(existing)\n if (selfUserId) have.add(selfUserId)\n const out: string[] = []\n const seen = new Set<string>()\n for (const id of mentioned) {\n if (!id || have.has(id) || seen.has(id)) continue\n seen.add(id)\n out.push(id)\n }\n return out\n}\n\n/**\n * 본문에서 `@user{userId:UUID}` 마커의 *userId 집합* 추출 (C4 — 초대 트리거).\n * 같은 user 중복 제거, 순서 보존(첫 등장순). 마커 없으면 빈 배열.\n * 순수 — content 만으로 \"이 메시지가 누구를 멘션했나\" 판정.\n */\nexport function extractMentionUserIds(text: string | null | undefined): string[] {\n if (!text) return []\n const re = /\\{userId:([^}\\s]+)\\}/g\n const seen = new Set<string>()\n const out: string[] = []\n let m: RegExpExecArray | null\n while ((m = re.exec(text)) !== null) {\n const id = m[1]\n if (!seen.has(id)) {\n seen.add(id)\n out.push(id)\n }\n }\n return out\n}\n\n/**\n * 본문에서 모든 `{key:value}` 인라인 마커 제거. LLM 입력 / textarea 편집 / 평문 표출 등.\n * 토큰 자체 (#component, @user) 는 그대로 유지.\n */\nexport function stripMentionRefids(text: string | null | undefined): string {\n if (!text) return ''\n return text.replace(MENTION_MARKER_RE, '')\n}\n\n/** 토큰 매칭 정규식 빌더 — trigger 별로 build. */\nfunction buildTokenRegex(trigger: string, markerKey: string): RegExp {\n const word =\n '\\\\w\\\\p{Script=Hangul}\\\\p{Script=Hiragana}\\\\p{Script=Katakana}\\\\p{Script=Han}'\n // (앞경계)(트리거)(토큰)(이미 같은 markerKey 의 마커가 붙어있는지 — skip 판정용)\n return new RegExp(\n `(^|[^${word}])(${escapeRegex(trigger)})([${word}-]+)(\\\\{${markerKey}:[^}\\\\s]+\\\\})?`,\n 'gu'\n )\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * 일반화된 inline marker 주입 — trigger 와 markerKey 별로 picks 를 본문에 박음.\n *\n * injectInlineMarkers(text, '#', 'refid', [{ token, value: 35 }])\n * injectInlineMarkers(text, '@', 'userId', [{ token, value: 'uuid' }])\n *\n * 룰:\n * - 정확 token 일치 (popup 명시 선택된 것만 — 자유 입력 토큰은 안 건드림)\n * - 동일 token 여러 번 등장하면 모두 marker 적용\n * - 이미 같은 markerKey 의 marker 가 붙어있으면 그대로 유지 (덮어쓰기 X)\n */\nexport function injectInlineMarkers(\n text: string,\n trigger: string,\n markerKey: string,\n picks: ReadonlyArray<{ token: string; value: string | number }> | null | undefined\n): string {\n if (!text || !picks || picks.length === 0) return text ?? ''\n const map = new Map<string, string | number>()\n for (const p of picks) map.set(p.token, p.value)\n const re = buildTokenRegex(trigger, markerKey)\n return text.replace(re, (match, leading, trig, token, existingMarker) => {\n if (existingMarker) return match\n const value = map.get(token)\n if (value === undefined) return match\n return `${leading}${trig}${token}{${markerKey}:${value}}`\n })\n}\n\n/**\n * `#component` 멘션 picks 를 `{refid:N}` 마커로 주입 (호환 유지).\n */\nexport function injectMentionRefids(\n text: string,\n picks: ReadonlyArray<MentionPick> | null | undefined\n): string {\n return injectInlineMarkers(\n text,\n '#',\n 'refid',\n picks?.map(p => ({ token: p.token, value: p.refid }))\n )\n}\n\n/**\n * `@user` 멘션 picks 를 `{userId:UUID}` 마커로 주입.\n * picks: [{token: 사용자_표시명, value: 사용자_id}]\n */\nexport function injectMentionUserIds(\n text: string,\n picks: ReadonlyArray<{ token: string; userId: string }> | null | undefined\n): string {\n return injectInlineMarkers(\n text,\n '@',\n 'userId',\n picks?.map(p => ({ token: p.token, value: p.userId }))\n )\n}\n\n/**\n * AI 응답 텍스트의 `#token` 들을 currentBoard 에 대해 resolve 해 inline marker 로 주입.\n *\n * - 매칭 룰: `findMentions` (= name/id/type/tag/class/text OR). 다중 일치 시 첫 결과.\n * - 매칭 안 되면 marker 없이 통과 (예: AI 가 patch 로 새로 만든 컴포넌트는 input.currentBoard\n * 에 없으므로 marker 못 박음 — 클라이언트 클릭 시 runtime fallback 으로 해석 가능).\n * - 이미 marker 있으면 그대로.\n */\nexport function injectAiMentionRefids(\n text: string,\n currentBoard: BoardModel | null | undefined\n): string {\n if (!text) return ''\n const matches = findMentions(text, currentBoard ?? null)\n if (matches.length === 0) return text\n\n // token → 첫 매칭 refid 맵\n const tokenToRefid = new Map<string, number>()\n for (const m of matches) {\n if (tokenToRefid.has(m.token)) continue\n if (m.matched.length === 0) continue\n tokenToRefid.set(m.token, m.matched[0].refid)\n }\n if (tokenToRefid.size === 0) return text\n\n // 사용자 picks 와 동일한 injection 룰로 주입.\n const picks = Array.from(tokenToRefid.entries()).map(([token, refid]) => ({ token, refid }))\n return injectMentionRefids(text, picks)\n}\n"]}