@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.
- package/PLAN-styling-tools.md +1253 -0
- package/client/components/board-ai-chat.test.ts +149 -0
- package/client/components/board-ai-chat.ts +2574 -0
- package/client/components/chat-echo-dedup.test.ts +116 -0
- package/client/components/chat-echo-dedup.ts +89 -0
- package/client/components/chat-input-builder.ts +47 -0
- package/client/components/default-catalog-entries.test.ts +59 -0
- package/client/components/default-catalog-entries.ts +100 -0
- package/client/components/default-slash-templates.test.ts +55 -0
- package/client/components/default-slash-templates.ts +129 -0
- package/client/components/markdown.test.ts +518 -0
- package/client/components/markdown.ts +508 -0
- package/client/components/mention-popup-helpers.ts +433 -0
- package/client/components/mention-popup.test.ts +588 -0
- package/client/components/mention-popup.ts +238 -0
- package/client/index.ts +11 -0
- package/client/tsconfig.json +13 -0
- package/client/utils/board-edit-patch.ts +374 -0
- package/config/config.development.js +43 -0
- package/config/config.production.js +15 -0
- package/dist-client/client/components/board-ai-chat.d.ts +277 -0
- package/dist-client/client/components/board-ai-chat.js +2444 -0
- package/dist-client/client/components/board-ai-chat.js.map +1 -0
- package/dist-client/client/components/board-ai-chat.test.d.ts +1 -0
- package/dist-client/client/components/board-ai-chat.test.js +138 -0
- package/dist-client/client/components/board-ai-chat.test.js.map +1 -0
- package/dist-client/client/components/chat-echo-dedup.d.ts +45 -0
- package/dist-client/client/components/chat-echo-dedup.js +58 -0
- package/dist-client/client/components/chat-echo-dedup.js.map +1 -0
- package/dist-client/client/components/chat-echo-dedup.test.d.ts +1 -0
- package/dist-client/client/components/chat-echo-dedup.test.js +101 -0
- package/dist-client/client/components/chat-echo-dedup.test.js.map +1 -0
- package/dist-client/client/components/chat-input-builder.d.ts +39 -0
- package/dist-client/client/components/chat-input-builder.js +26 -0
- package/dist-client/client/components/chat-input-builder.js.map +1 -0
- package/dist-client/client/components/default-catalog-entries.d.ts +15 -0
- package/dist-client/client/components/default-catalog-entries.js +86 -0
- package/dist-client/client/components/default-catalog-entries.js.map +1 -0
- package/dist-client/client/components/default-catalog-entries.test.d.ts +1 -0
- package/dist-client/client/components/default-catalog-entries.test.js +52 -0
- package/dist-client/client/components/default-catalog-entries.test.js.map +1 -0
- package/dist-client/client/components/default-slash-templates.d.ts +17 -0
- package/dist-client/client/components/default-slash-templates.js +113 -0
- package/dist-client/client/components/default-slash-templates.js.map +1 -0
- package/dist-client/client/components/default-slash-templates.test.d.ts +1 -0
- package/dist-client/client/components/default-slash-templates.test.js +51 -0
- package/dist-client/client/components/default-slash-templates.test.js.map +1 -0
- package/dist-client/client/components/markdown.d.ts +60 -0
- package/dist-client/client/components/markdown.js +422 -0
- package/dist-client/client/components/markdown.js.map +1 -0
- package/dist-client/client/components/markdown.test.d.ts +1 -0
- package/dist-client/client/components/markdown.test.js +418 -0
- package/dist-client/client/components/markdown.test.js.map +1 -0
- package/dist-client/client/components/mention-popup-helpers.d.ts +165 -0
- package/dist-client/client/components/mention-popup-helpers.js +330 -0
- package/dist-client/client/components/mention-popup-helpers.js.map +1 -0
- package/dist-client/client/components/mention-popup.d.ts +35 -0
- package/dist-client/client/components/mention-popup.js +223 -0
- package/dist-client/client/components/mention-popup.js.map +1 -0
- package/dist-client/client/components/mention-popup.test.d.ts +1 -0
- package/dist-client/client/components/mention-popup.test.js +474 -0
- package/dist-client/client/components/mention-popup.test.js.map +1 -0
- package/dist-client/client/index.d.ts +11 -0
- package/dist-client/client/index.js +12 -0
- package/dist-client/client/index.js.map +1 -0
- package/dist-client/client/utils/board-edit-patch.d.ts +157 -0
- package/dist-client/client/utils/board-edit-patch.js +284 -0
- package/dist-client/client/utils/board-edit-patch.js.map +1 -0
- package/dist-client/server/service/agentic-loop.d.ts +87 -0
- package/dist-client/server/service/agentic-loop.js +276 -0
- package/dist-client/server/service/agentic-loop.js.map +1 -0
- package/dist-client/server/service/assistant.d.ts +84 -0
- package/dist-client/server/service/assistant.js +2220 -0
- package/dist-client/server/service/assistant.js.map +1 -0
- package/dist-client/server/service/catalog-resolver.d.ts +18 -0
- package/dist-client/server/service/catalog-resolver.js +93 -0
- package/dist-client/server/service/catalog-resolver.js.map +1 -0
- package/dist-client/server/service/component-tree.d.ts +68 -0
- package/dist-client/server/service/component-tree.js +68 -0
- package/dist-client/server/service/component-tree.js.map +1 -0
- package/dist-client/server/service/mention-resolver.d.ts +96 -0
- package/dist-client/server/service/mention-resolver.js +172 -0
- package/dist-client/server/service/mention-resolver.js.map +1 -0
- package/dist-client/server/service/prefab-registry.d.ts +73 -0
- package/dist-client/server/service/prefab-registry.js +252 -0
- package/dist-client/server/service/prefab-registry.js.map +1 -0
- package/dist-client/server/service/styling/clear-tools.d.ts +15 -0
- package/dist-client/server/service/styling/clear-tools.js +50 -0
- package/dist-client/server/service/styling/clear-tools.js.map +1 -0
- package/dist-client/server/service/styling/color-utils.d.ts +43 -0
- package/dist-client/server/service/styling/color-utils.js +205 -0
- package/dist-client/server/service/styling/color-utils.js.map +1 -0
- package/dist-client/server/service/styling/copy-tools.d.ts +27 -0
- package/dist-client/server/service/styling/copy-tools.js +78 -0
- package/dist-client/server/service/styling/copy-tools.js.map +1 -0
- package/dist-client/server/service/styling/effect-tools.d.ts +45 -0
- package/dist-client/server/service/styling/effect-tools.js +85 -0
- package/dist-client/server/service/styling/effect-tools.js.map +1 -0
- package/dist-client/server/service/styling/fill-tools.d.ts +60 -0
- package/dist-client/server/service/styling/fill-tools.js +226 -0
- package/dist-client/server/service/styling/fill-tools.js.map +1 -0
- package/dist-client/server/service/styling/material-tools.d.ts +32 -0
- package/dist-client/server/service/styling/material-tools.js +88 -0
- package/dist-client/server/service/styling/material-tools.js.map +1 -0
- package/dist-client/server/service/styling/read-tools.d.ts +34 -0
- package/dist-client/server/service/styling/read-tools.js +42 -0
- package/dist-client/server/service/styling/read-tools.js.map +1 -0
- package/dist-client/server/service/styling/registry.d.ts +91 -0
- package/dist-client/server/service/styling/registry.js +345 -0
- package/dist-client/server/service/styling/registry.js.map +1 -0
- package/dist-client/server/service/styling/stroke-tools.d.ts +35 -0
- package/dist-client/server/service/styling/stroke-tools.js +94 -0
- package/dist-client/server/service/styling/stroke-tools.js.map +1 -0
- package/dist-client/server/service/styling/text-tools.d.ts +32 -0
- package/dist-client/server/service/styling/text-tools.js +101 -0
- package/dist-client/server/service/styling/text-tools.js.map +1 -0
- package/dist-client/server/service/types.d.ts +265 -0
- package/dist-client/server/service/types.js +2 -0
- package/dist-client/server/service/types.js.map +1 -0
- package/dist-client/server/service/validation/board-model-schema.d.ts +8311 -0
- package/dist-client/server/service/validation/board-model-schema.js +402 -0
- package/dist-client/server/service/validation/board-model-schema.js.map +1 -0
- package/dist-client/server/service/validation/tool-validation.d.ts +31 -0
- package/dist-client/server/service/validation/tool-validation.js +193 -0
- package/dist-client/server/service/validation/tool-validation.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-server/index.d.ts +23 -0
- package/dist-server/index.js +27 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/service/agentic-loop.d.ts +87 -0
- package/dist-server/service/agentic-loop.js +280 -0
- package/dist-server/service/agentic-loop.js.map +1 -0
- package/dist-server/service/apply-patch.d.ts +47 -0
- package/dist-server/service/apply-patch.js +369 -0
- package/dist-server/service/apply-patch.js.map +1 -0
- package/dist-server/service/assistant.d.ts +84 -0
- package/dist-server/service/assistant.js +2237 -0
- package/dist-server/service/assistant.js.map +1 -0
- package/dist-server/service/board-ai-resolver.d.ts +54 -0
- package/dist-server/service/board-ai-resolver.js +409 -0
- package/dist-server/service/board-ai-resolver.js.map +1 -0
- package/dist-server/service/catalog-resolver.d.ts +18 -0
- package/dist-server/service/catalog-resolver.js +98 -0
- package/dist-server/service/catalog-resolver.js.map +1 -0
- package/dist-server/service/chat-message/chat-message-broadcast.d.ts +13 -0
- package/dist-server/service/chat-message/chat-message-broadcast.js +13 -0
- package/dist-server/service/chat-message/chat-message-broadcast.js.map +1 -0
- package/dist-server/service/chat-message/chat-message-publish.d.ts +6 -0
- package/dist-server/service/chat-message/chat-message-publish.js +27 -0
- package/dist-server/service/chat-message/chat-message-publish.js.map +1 -0
- package/dist-server/service/chat-message/chat-message-subscription.d.ts +8 -0
- package/dist-server/service/chat-message/chat-message-subscription.js +53 -0
- package/dist-server/service/chat-message/chat-message-subscription.js.map +1 -0
- package/dist-server/service/chat-message/chat-message.d.ts +56 -0
- package/dist-server/service/chat-message/chat-message.js +149 -0
- package/dist-server/service/chat-message/chat-message.js.map +1 -0
- package/dist-server/service/chat-message/index.d.ts +5 -0
- package/dist-server/service/chat-message/index.js +12 -0
- package/dist-server/service/chat-message/index.js.map +1 -0
- package/dist-server/service/chat-session/chat-session.d.ts +31 -0
- package/dist-server/service/chat-session/chat-session.js +131 -0
- package/dist-server/service/chat-session/chat-session.js.map +1 -0
- package/dist-server/service/chat-session/index.d.ts +3 -0
- package/dist-server/service/chat-session/index.js +7 -0
- package/dist-server/service/chat-session/index.js.map +1 -0
- package/dist-server/service/chat-session-participant/chat-session-participant.d.ts +30 -0
- package/dist-server/service/chat-session-participant/chat-session-participant.js +112 -0
- package/dist-server/service/chat-session-participant/chat-session-participant.js.map +1 -0
- package/dist-server/service/chat-session-participant/index.d.ts +4 -0
- package/dist-server/service/chat-session-participant/index.js +10 -0
- package/dist-server/service/chat-session-participant/index.js.map +1 -0
- package/dist-server/service/chat-session-participant/invite-notification.d.ts +27 -0
- package/dist-server/service/chat-session-participant/invite-notification.js +30 -0
- package/dist-server/service/chat-session-participant/invite-notification.js.map +1 -0
- package/dist-server/service/chat-session-participant/presence.d.ts +4 -0
- package/dist-server/service/chat-session-participant/presence.js +22 -0
- package/dist-server/service/chat-session-participant/presence.js.map +1 -0
- package/dist-server/service/chat-session-resolver.d.ts +20 -0
- package/dist-server/service/chat-session-resolver.js +356 -0
- package/dist-server/service/chat-session-resolver.js.map +1 -0
- package/dist-server/service/component-tree.d.ts +68 -0
- package/dist-server/service/component-tree.js +73 -0
- package/dist-server/service/component-tree.js.map +1 -0
- package/dist-server/service/index.d.ts +20 -0
- package/dist-server/service/index.js +34 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/mention-marker.d.ts +78 -0
- package/dist-server/service/mention-marker.js +162 -0
- package/dist-server/service/mention-marker.js.map +1 -0
- package/dist-server/service/mention-resolver.d.ts +96 -0
- package/dist-server/service/mention-resolver.js +177 -0
- package/dist-server/service/mention-resolver.js.map +1 -0
- package/dist-server/service/patch-entry/board-patch-broadcast.d.ts +13 -0
- package/dist-server/service/patch-entry/board-patch-broadcast.js +13 -0
- package/dist-server/service/patch-entry/board-patch-broadcast.js.map +1 -0
- package/dist-server/service/patch-entry/board-patch-subscription.d.ts +12 -0
- package/dist-server/service/patch-entry/board-patch-subscription.js +63 -0
- package/dist-server/service/patch-entry/board-patch-subscription.js.map +1 -0
- package/dist-server/service/patch-entry/index.d.ts +4 -0
- package/dist-server/service/patch-entry/index.js +12 -0
- package/dist-server/service/patch-entry/index.js.map +1 -0
- package/dist-server/service/patch-entry/patch-entry.d.ts +16 -0
- package/dist-server/service/patch-entry/patch-entry.js +96 -0
- package/dist-server/service/patch-entry/patch-entry.js.map +1 -0
- package/dist-server/service/prefab-registry.d.ts +73 -0
- package/dist-server/service/prefab-registry.js +258 -0
- package/dist-server/service/prefab-registry.js.map +1 -0
- package/dist-server/service/styling/clear-tools.d.ts +15 -0
- package/dist-server/service/styling/clear-tools.js +53 -0
- package/dist-server/service/styling/clear-tools.js.map +1 -0
- package/dist-server/service/styling/color-utils.d.ts +43 -0
- package/dist-server/service/styling/color-utils.js +210 -0
- package/dist-server/service/styling/color-utils.js.map +1 -0
- package/dist-server/service/styling/copy-tools.d.ts +27 -0
- package/dist-server/service/styling/copy-tools.js +81 -0
- package/dist-server/service/styling/copy-tools.js.map +1 -0
- package/dist-server/service/styling/effect-tools.d.ts +45 -0
- package/dist-server/service/styling/effect-tools.js +90 -0
- package/dist-server/service/styling/effect-tools.js.map +1 -0
- package/dist-server/service/styling/fill-tools.d.ts +60 -0
- package/dist-server/service/styling/fill-tools.js +229 -0
- package/dist-server/service/styling/fill-tools.js.map +1 -0
- package/dist-server/service/styling/material-tools.d.ts +32 -0
- package/dist-server/service/styling/material-tools.js +92 -0
- package/dist-server/service/styling/material-tools.js.map +1 -0
- package/dist-server/service/styling/read-tools.d.ts +34 -0
- package/dist-server/service/styling/read-tools.js +45 -0
- package/dist-server/service/styling/read-tools.js.map +1 -0
- package/dist-server/service/styling/registry.d.ts +91 -0
- package/dist-server/service/styling/registry.js +352 -0
- package/dist-server/service/styling/registry.js.map +1 -0
- package/dist-server/service/styling/stroke-tools.d.ts +35 -0
- package/dist-server/service/styling/stroke-tools.js +97 -0
- package/dist-server/service/styling/stroke-tools.js.map +1 -0
- package/dist-server/service/styling/text-tools.d.ts +32 -0
- package/dist-server/service/styling/text-tools.js +105 -0
- package/dist-server/service/styling/text-tools.js.map +1 -0
- package/dist-server/service/subscribe-auth.d.ts +14 -0
- package/dist-server/service/subscribe-auth.js +33 -0
- package/dist-server/service/subscribe-auth.js.map +1 -0
- package/dist-server/service/types.d.ts +265 -0
- package/dist-server/service/types.js +3 -0
- package/dist-server/service/types.js.map +1 -0
- package/dist-server/service/validation/board-model-schema.d.ts +8311 -0
- package/dist-server/service/validation/board-model-schema.js +409 -0
- package/dist-server/service/validation/board-model-schema.js.map +1 -0
- package/dist-server/service/validation/tool-validation.d.ts +31 -0
- package/dist-server/service/validation/tool-validation.js +196 -0
- package/dist-server/service/validation/tool-validation.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/package.json +48 -0
- package/server/index.ts +23 -0
- package/server/service/agentic-loop.test.ts +705 -0
- package/server/service/agentic-loop.ts +431 -0
- package/server/service/apply-patch-drift.test.ts +829 -0
- package/server/service/apply-patch.test.ts +757 -0
- package/server/service/apply-patch.ts +411 -0
- package/server/service/assistant-integration.test.ts +922 -0
- package/server/service/assistant-llm-smoke.test.ts +296 -0
- package/server/service/assistant.test.ts +2034 -0
- package/server/service/assistant.ts +2378 -0
- package/server/service/board-ai-resolver.ts +407 -0
- package/server/service/catalog-resolver.test.ts +137 -0
- package/server/service/catalog-resolver.ts +102 -0
- package/server/service/chat-message/chat-message-broadcast.integration.test.ts +73 -0
- package/server/service/chat-message/chat-message-broadcast.test.ts +40 -0
- package/server/service/chat-message/chat-message-broadcast.ts +27 -0
- package/server/service/chat-message/chat-message-publish.ts +22 -0
- package/server/service/chat-message/chat-message-subscription.ts +41 -0
- package/server/service/chat-message/chat-message.ts +169 -0
- package/server/service/chat-message/index.ts +12 -0
- package/server/service/chat-session/chat-session.ts +130 -0
- package/server/service/chat-session/index.ts +5 -0
- package/server/service/chat-session-participant/chat-session-participant.ts +110 -0
- package/server/service/chat-session-participant/index.ts +6 -0
- package/server/service/chat-session-participant/invite-notification.test.ts +30 -0
- package/server/service/chat-session-participant/invite-notification.ts +48 -0
- package/server/service/chat-session-participant/presence.test.ts +39 -0
- package/server/service/chat-session-participant/presence.ts +21 -0
- package/server/service/chat-session-resolver.ts +312 -0
- package/server/service/component-tree.test.ts +248 -0
- package/server/service/component-tree.ts +135 -0
- package/server/service/index.ts +32 -0
- package/server/service/mention-marker.extract.test.ts +61 -0
- package/server/service/mention-marker.test.ts +228 -0
- package/server/service/mention-marker.ts +184 -0
- package/server/service/mention-resolver.test.ts +273 -0
- package/server/service/mention-resolver.ts +264 -0
- package/server/service/patch-entry/board-patch-broadcast.ts +24 -0
- package/server/service/patch-entry/board-patch-subscription.test.ts +40 -0
- package/server/service/patch-entry/board-patch-subscription.ts +50 -0
- package/server/service/patch-entry/index.ts +12 -0
- package/server/service/patch-entry/patch-entry.ts +89 -0
- package/server/service/prefab-registry.test.ts +172 -0
- package/server/service/prefab-registry.ts +332 -0
- package/server/service/styling/clear-tools.test.ts +164 -0
- package/server/service/styling/clear-tools.ts +69 -0
- package/server/service/styling/color-utils.test.ts +130 -0
- package/server/service/styling/color-utils.ts +226 -0
- package/server/service/styling/copy-tools.test.ts +152 -0
- package/server/service/styling/copy-tools.ts +115 -0
- package/server/service/styling/effect-tools.test.ts +277 -0
- package/server/service/styling/effect-tools.ts +124 -0
- package/server/service/styling/fill-tools.test.ts +331 -0
- package/server/service/styling/fill-tools.ts +293 -0
- package/server/service/styling/material-tools.test.ts +294 -0
- package/server/service/styling/material-tools.ts +114 -0
- package/server/service/styling/read-tools.test.ts +78 -0
- package/server/service/styling/read-tools.ts +67 -0
- package/server/service/styling/registry.test.ts +203 -0
- package/server/service/styling/registry.ts +423 -0
- package/server/service/styling/stroke-tools.test.ts +245 -0
- package/server/service/styling/stroke-tools.ts +145 -0
- package/server/service/styling/text-tools.test.ts +253 -0
- package/server/service/styling/text-tools.ts +131 -0
- package/server/service/styling/tier1-tools.test.ts +300 -0
- package/server/service/subscribe-auth.test.ts +57 -0
- package/server/service/subscribe-auth.ts +34 -0
- package/server/service/types.ts +235 -0
- package/server/service/validation/board-model-schema.test.ts +778 -0
- package/server/service/validation/board-model-schema.ts +446 -0
- package/server/service/validation/tool-validation.ts +228 -0
- package/things-factory.config.js +1 -0
- package/translations/en.json +49 -0
- package/translations/ja.json +48 -0
- package/translations/ko.json +49 -0
- package/translations/ms.json +48 -0
- package/translations/zh.json +48 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.publishChatMessage = publishChatMessage;
|
|
4
|
+
/*
|
|
5
|
+
* chat-message 방송 publisher — pubsub 의존, 데코레이터 없음.
|
|
6
|
+
*
|
|
7
|
+
* 데코레이터 resolver(chat-message-subscription.ts)와 분리한 이유: babel-jest 가 파라미터
|
|
8
|
+
* 데코레이터(@Root/@Arg)를 파싱 못 해 그 파일을 테스트에서 import 할 수 없다. 이 모듈은
|
|
9
|
+
* 데코레이터가 없어 통합 테스트가 실제 publish→방송 경로를 직접 구동할 수 있다.
|
|
10
|
+
*/
|
|
11
|
+
const shell_1 = require("@things-factory/shell");
|
|
12
|
+
const chat_message_broadcast_js_1 = require("./chat-message-broadcast.js");
|
|
13
|
+
/**
|
|
14
|
+
* ChatMessage 영속 직후 호출 — 같은 세션 구독자에게 방송.
|
|
15
|
+
* sessionId 없으면 skip. pubsub 미가용/실패해도 본 흐름(영속 완료)을 막지 않는다.
|
|
16
|
+
*/
|
|
17
|
+
function publishChatMessage(payload) {
|
|
18
|
+
if (!payload.sessionId)
|
|
19
|
+
return;
|
|
20
|
+
try {
|
|
21
|
+
shell_1.pubsub.publish(chat_message_broadcast_js_1.CHAT_MESSAGE_TOPIC, payload);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
/* 방송 생략 — 영속은 이미 끝남 */
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=chat-message-publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-message-publish.js","sourceRoot":"","sources":["../../../server/service/chat-message/chat-message-publish.ts"],"names":[],"mappings":";;AAcA,gDAOC;AArBD;;;;;;GAMG;AACH,iDAA8C;AAC9C,2EAAyF;AAEzF;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,OAA2B;IAC5D,IAAI,CAAC,OAAO,CAAC,SAAS;QAAE,OAAM;IAC9B,IAAI,CAAC;QACH,cAAM,CAAC,OAAO,CAAC,8CAAkB,EAAE,OAAO,CAAC,CAAA;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;AACH,CAAC","sourcesContent":["/*\n * chat-message 방송 publisher — pubsub 의존, 데코레이터 없음.\n *\n * 데코레이터 resolver(chat-message-subscription.ts)와 분리한 이유: babel-jest 가 파라미터\n * 데코레이터(@Root/@Arg)를 파싱 못 해 그 파일을 테스트에서 import 할 수 없다. 이 모듈은\n * 데코레이터가 없어 통합 테스트가 실제 publish→방송 경로를 직접 구동할 수 있다.\n */\nimport { pubsub } from '@things-factory/shell'\nimport { CHAT_MESSAGE_TOPIC, type ChatMessagePayload } from './chat-message-broadcast.js'\n\n/**\n * ChatMessage 영속 직후 호출 — 같은 세션 구독자에게 방송.\n * sessionId 없으면 skip. pubsub 미가용/실패해도 본 흐름(영속 완료)을 막지 않는다.\n */\nexport function publishChatMessage(payload: ChatMessagePayload): void {\n if (!payload.sessionId) return\n try {\n pubsub.publish(CHAT_MESSAGE_TOPIC, payload)\n } catch {\n /* 방송 생략 — 영속은 이미 끝남 */\n }\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ChatMessage } from './chat-message.js';
|
|
2
|
+
import { type ChatMessagePayload } from './chat-message-broadcast.js';
|
|
3
|
+
export { publishChatMessage } from './chat-message-publish.js';
|
|
4
|
+
export { CHAT_MESSAGE_TOPIC, chatMessageFilter } from './chat-message-broadcast.js';
|
|
5
|
+
export type { ChatMessagePayload } from './chat-message-broadcast.js';
|
|
6
|
+
export declare class BoardChatMessageSubscription {
|
|
7
|
+
chatMessageActivity(payload: ChatMessagePayload, sessionId: string): ChatMessage;
|
|
8
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BoardChatMessageSubscription = exports.chatMessageFilter = exports.CHAT_MESSAGE_TOPIC = exports.publishChatMessage = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
/*
|
|
6
|
+
* BoardChatMessageSubscription (Phase Board-AI C4 — 그룹챗 메시지 실시간 방송).
|
|
7
|
+
*
|
|
8
|
+
* ChatMessage(사용자 / AI / system) 가 영속될 때마다 같은 세션 구독자에게 방송 →
|
|
9
|
+
* 그룹챗의 척추. 클라이언트(board-ai-chat)가 구독해 원격 메시지를 transcript 에 append.
|
|
10
|
+
* 자기 발신 에코는 클라이언트가 message.id 로 dedup (mutation 응답으로 이미 렌더).
|
|
11
|
+
*
|
|
12
|
+
* patch spine(board-patch-subscription.ts)과 동일 패턴 — PubSub + graphql-ws, domain 격리.
|
|
13
|
+
* 차이: 필터 키가 board 가 아닌 sessionId (채팅은 ChatSession 단위).
|
|
14
|
+
* 순수 로직(토픽/필터)은 chat-message-broadcast.ts (테스트 가능). 여기엔 pubsub 의존만.
|
|
15
|
+
*/
|
|
16
|
+
const type_graphql_1 = require("type-graphql");
|
|
17
|
+
const graphql_yoga_1 = require("graphql-yoga");
|
|
18
|
+
const shell_1 = require("@things-factory/shell");
|
|
19
|
+
const chat_message_js_1 = require("./chat-message.js");
|
|
20
|
+
const chat_message_broadcast_js_1 = require("./chat-message-broadcast.js");
|
|
21
|
+
const subscribe_auth_js_1 = require("../subscribe-auth.js");
|
|
22
|
+
// publishChatMessage 는 데코레이터 없는 chat-message-publish.ts 에 분리 (테스트 import 가능).
|
|
23
|
+
var chat_message_publish_js_1 = require("./chat-message-publish.js");
|
|
24
|
+
Object.defineProperty(exports, "publishChatMessage", { enumerable: true, get: function () { return chat_message_publish_js_1.publishChatMessage; } });
|
|
25
|
+
var chat_message_broadcast_js_2 = require("./chat-message-broadcast.js");
|
|
26
|
+
Object.defineProperty(exports, "CHAT_MESSAGE_TOPIC", { enumerable: true, get: function () { return chat_message_broadcast_js_2.CHAT_MESSAGE_TOPIC; } });
|
|
27
|
+
Object.defineProperty(exports, "chatMessageFilter", { enumerable: true, get: function () { return chat_message_broadcast_js_2.chatMessageFilter; } });
|
|
28
|
+
let BoardChatMessageSubscription = class BoardChatMessageSubscription {
|
|
29
|
+
chatMessageActivity(payload, sessionId) {
|
|
30
|
+
return payload.message;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
exports.BoardChatMessageSubscription = BoardChatMessageSubscription;
|
|
34
|
+
tslib_1.__decorate([
|
|
35
|
+
(0, type_graphql_1.Subscription)({
|
|
36
|
+
description: 'Subscribes to chat messages (user / assistant / system) of a session for real-time group chat.',
|
|
37
|
+
subscribe: async ({ args, context }) => {
|
|
38
|
+
const { domain, user } = context.state;
|
|
39
|
+
const { sessionId } = args;
|
|
40
|
+
await (0, subscribe_auth_js_1.assertDomainSubscribeAllowed)(domain, user, (d, u) => process.superUserGranted(d, u));
|
|
41
|
+
return (0, graphql_yoga_1.pipe)(shell_1.pubsub.subscribe(chat_message_broadcast_js_1.CHAT_MESSAGE_TOPIC), (0, graphql_yoga_1.filter)((0, chat_message_broadcast_js_1.chatMessageFilter)(domain.id, sessionId)));
|
|
42
|
+
}
|
|
43
|
+
}),
|
|
44
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
45
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('sessionId')),
|
|
46
|
+
tslib_1.__metadata("design:type", Function),
|
|
47
|
+
tslib_1.__metadata("design:paramtypes", [Object, String]),
|
|
48
|
+
tslib_1.__metadata("design:returntype", chat_message_js_1.ChatMessage)
|
|
49
|
+
], BoardChatMessageSubscription.prototype, "chatMessageActivity", null);
|
|
50
|
+
exports.BoardChatMessageSubscription = BoardChatMessageSubscription = tslib_1.__decorate([
|
|
51
|
+
(0, type_graphql_1.Resolver)(chat_message_js_1.ChatMessage)
|
|
52
|
+
], BoardChatMessageSubscription);
|
|
53
|
+
//# sourceMappingURL=chat-message-subscription.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-message-subscription.js","sourceRoot":"","sources":["../../../server/service/chat-message/chat-message-subscription.ts"],"names":[],"mappings":";;;;AAAA;;;;;;;;;;GAUG;AACH,+CAAgE;AAChE,+CAA2C;AAC3C,iDAA8C;AAC9C,uDAA+C;AAC/C,2EAA4G;AAC5G,4DAAmE;AAEnE,8EAA8E;AAC9E,qEAA8D;AAArD,6HAAA,kBAAkB,OAAA;AAC3B,yEAAmF;AAA1E,+HAAA,kBAAkB,OAAA;AAAE,8HAAA,iBAAiB,OAAA;AAIvC,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IAavC,mBAAmB,CAAS,OAA2B,EAAoB,SAAiB;QAC1F,OAAO,OAAO,CAAC,OAAO,CAAA;IACxB,CAAC;CACF,CAAA;AAhBY,oEAA4B;AAavC;IAZC,IAAA,2BAAY,EAAC;QACZ,WAAW,EACT,gGAAgG;QAClG,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;YACrC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;YACtC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAA;YAE1B,MAAM,IAAA,gDAA4B,EAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YAE1F,OAAO,IAAA,mBAAI,EAAC,cAAM,CAAC,SAAS,CAAC,8CAAkB,CAAC,EAAE,IAAA,qBAAM,EAAC,IAAA,6CAAiB,EAAC,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;QACpG,CAAC;KACF,CAAC;IACmB,mBAAA,IAAA,mBAAI,GAAE,CAAA;IAA+B,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;;;4CAAqB,6BAAW;uEAEzG;uCAfU,4BAA4B;IADxC,IAAA,uBAAQ,EAAC,6BAAW,CAAC;GACT,4BAA4B,CAgBxC","sourcesContent":["/*\n * BoardChatMessageSubscription (Phase Board-AI C4 — 그룹챗 메시지 실시간 방송).\n *\n * ChatMessage(사용자 / AI / system) 가 영속될 때마다 같은 세션 구독자에게 방송 →\n * 그룹챗의 척추. 클라이언트(board-ai-chat)가 구독해 원격 메시지를 transcript 에 append.\n * 자기 발신 에코는 클라이언트가 message.id 로 dedup (mutation 응답으로 이미 렌더).\n *\n * patch spine(board-patch-subscription.ts)과 동일 패턴 — PubSub + graphql-ws, domain 격리.\n * 차이: 필터 키가 board 가 아닌 sessionId (채팅은 ChatSession 단위).\n * 순수 로직(토픽/필터)은 chat-message-broadcast.ts (테스트 가능). 여기엔 pubsub 의존만.\n */\nimport { Resolver, Subscription, Root, Arg } from 'type-graphql'\nimport { filter, pipe } from 'graphql-yoga'\nimport { pubsub } from '@things-factory/shell'\nimport { ChatMessage } from './chat-message.js'\nimport { CHAT_MESSAGE_TOPIC, chatMessageFilter, type ChatMessagePayload } from './chat-message-broadcast.js'\nimport { assertDomainSubscribeAllowed } from '../subscribe-auth.js'\n\n// publishChatMessage 는 데코레이터 없는 chat-message-publish.ts 에 분리 (테스트 import 가능).\nexport { publishChatMessage } from './chat-message-publish.js'\nexport { CHAT_MESSAGE_TOPIC, chatMessageFilter } from './chat-message-broadcast.js'\nexport type { ChatMessagePayload } from './chat-message-broadcast.js'\n\n@Resolver(ChatMessage)\nexport class BoardChatMessageSubscription {\n @Subscription({\n description:\n 'Subscribes to chat messages (user / assistant / system) of a session for real-time group chat.',\n subscribe: async ({ args, context }) => {\n const { domain, user } = context.state\n const { sessionId } = args\n\n await assertDomainSubscribeAllowed(domain, user, (d, u) => process.superUserGranted(d, u))\n\n return pipe(pubsub.subscribe(CHAT_MESSAGE_TOPIC), filter(chatMessageFilter(domain.id, sessionId)))\n }\n })\n chatMessageActivity(@Root() payload: ChatMessagePayload, @Arg('sessionId') sessionId: string): ChatMessage {\n return payload.message\n }\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { User } from '@things-factory/auth-base';
|
|
2
|
+
import { ChatSession } from '../chat-session/chat-session.js';
|
|
3
|
+
export declare class ChatMessage {
|
|
4
|
+
readonly id?: string;
|
|
5
|
+
session?: ChatSession;
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
role: string;
|
|
8
|
+
content: string;
|
|
9
|
+
relatedPatchId?: string;
|
|
10
|
+
relatedImportSessionId?: string;
|
|
11
|
+
/**
|
|
12
|
+
* AI 가 응답을 만드는 동안 호출한 도구 trace — JSON-stringified.
|
|
13
|
+
*
|
|
14
|
+
* 컬럼은 string (PatchEntry.ops 와 동일 패턴), GraphQL 노출은 toolUsagesJson getter
|
|
15
|
+
* 로 parse 된 객체. UI 의 fold-able 박스 ("AI 가 이런 도구를 사용했습니다") 가
|
|
16
|
+
* 페이지 reload / loadHistory 후에도 살아있도록 영속.
|
|
17
|
+
*
|
|
18
|
+
* 형태: ToolUsage[] (assistant.ts 의 시간순 trace, summarizeToolResult 로 압축).
|
|
19
|
+
* null 이면 도구 호출 없었던 메시지 (text-only 응답).
|
|
20
|
+
*/
|
|
21
|
+
toolUsages?: string;
|
|
22
|
+
/** GraphQL 노출용 — JSON 배열로 parse. */
|
|
23
|
+
get toolUsagesJson(): any;
|
|
24
|
+
/**
|
|
25
|
+
* 메시지를 일으킨 사용자.
|
|
26
|
+
* - role='user' → 보낸 사용자
|
|
27
|
+
* - role='assistant' → 그 응답을 트리거한 사용자 (직전 user 메시지의 작성자)
|
|
28
|
+
* - role='system' → 시스템 액션을 일으킨 사용자 (예: 직접 편집한 사용자)
|
|
29
|
+
*
|
|
30
|
+
* nullable — legacy 메시지 (이 필드 추가 이전에 작성) 는 null. 또한 ad-hoc 모드 / 시스템
|
|
31
|
+
* 자동 메시지 중 사용자 컨텍스트가 없는 경우도 null 가능.
|
|
32
|
+
*/
|
|
33
|
+
creator?: User;
|
|
34
|
+
creatorId?: string;
|
|
35
|
+
updater?: User;
|
|
36
|
+
updaterId?: string;
|
|
37
|
+
/**
|
|
38
|
+
* 부모 메시지 — 이 메시지가 "응답하는 대상" / "이어가는 메시지" 의 id.
|
|
39
|
+
*
|
|
40
|
+
* 의미 (role 별):
|
|
41
|
+
* - 'user' → 직전 in-session 메시지 (보통 assistant 또는 system). 첫 turn 은 null.
|
|
42
|
+
* - 'assistant' → 이 응답이 답하는 user 메시지. (regenerate 로 같은 user 메시지를 부모로
|
|
43
|
+
* 하는 형제 assistant 메시지가 생기면 자연스럽게 branching tree 가 됨)
|
|
44
|
+
* - 'system' → 직전 in-session 메시지 (timeline 연속성 유지).
|
|
45
|
+
*
|
|
46
|
+
* 이 한 컬럼으로 향후 어떤 흐름이든 표현 가능 — linear chain / branching (regenerate) /
|
|
47
|
+
* tree (replies-to-specific-message) 등. UI/쿼리는 점진 도입.
|
|
48
|
+
*
|
|
49
|
+
* onDelete: 'SET NULL' — 부모 메시지가 삭제돼도 child 는 남되 dangling 마킹.
|
|
50
|
+
*/
|
|
51
|
+
parentMessage?: ChatMessage;
|
|
52
|
+
parentMessageId?: string;
|
|
53
|
+
createdAt?: Date;
|
|
54
|
+
updatedAt?: Date;
|
|
55
|
+
deletedAt?: Date;
|
|
56
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChatMessage = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
/**
|
|
6
|
+
* ChatMessage — ChatSession 의 한 메시지.
|
|
7
|
+
*
|
|
8
|
+
* role: 'user' | 'assistant' | 'system'
|
|
9
|
+
* 'system' 은 사용자 직접 편집/import 진행 등 시스템이 자동 생성하는 컨텍스트 메시지.
|
|
10
|
+
*
|
|
11
|
+
* relatedPatchId / relatedImportSessionId 로 메시지가 트리거한 패치·임포트와 연결.
|
|
12
|
+
*/
|
|
13
|
+
const typeorm_1 = require("typeorm");
|
|
14
|
+
const type_graphql_1 = require("type-graphql");
|
|
15
|
+
const graphql_scalars_1 = require("graphql-scalars");
|
|
16
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
17
|
+
const env_1 = require("@things-factory/env");
|
|
18
|
+
const chat_session_js_1 = require("../chat-session/chat-session.js");
|
|
19
|
+
const ORMCONFIG = env_1.config.get('ormconfig', {});
|
|
20
|
+
const DATABASE_TYPE = ORMCONFIG.type;
|
|
21
|
+
let ChatMessage = class ChatMessage {
|
|
22
|
+
/** GraphQL 노출용 — JSON 배열로 parse. */
|
|
23
|
+
get toolUsagesJson() {
|
|
24
|
+
if (!this.toolUsages)
|
|
25
|
+
return null;
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(this.toolUsages);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.ChatMessage = ChatMessage;
|
|
35
|
+
tslib_1.__decorate([
|
|
36
|
+
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
37
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.ID, { nullable: true }),
|
|
38
|
+
tslib_1.__metadata("design:type", String)
|
|
39
|
+
], ChatMessage.prototype, "id", void 0);
|
|
40
|
+
tslib_1.__decorate([
|
|
41
|
+
(0, typeorm_1.ManyToOne)(type => chat_session_js_1.ChatSession, session => session.messages, { onDelete: 'CASCADE' }),
|
|
42
|
+
tslib_1.__metadata("design:type", chat_session_js_1.ChatSession)
|
|
43
|
+
], ChatMessage.prototype, "session", void 0);
|
|
44
|
+
tslib_1.__decorate([
|
|
45
|
+
(0, typeorm_1.RelationId)((message) => message.session),
|
|
46
|
+
tslib_1.__metadata("design:type", String)
|
|
47
|
+
], ChatMessage.prototype, "sessionId", void 0);
|
|
48
|
+
tslib_1.__decorate([
|
|
49
|
+
(0, typeorm_1.Column)({ type: 'varchar', length: 16 }),
|
|
50
|
+
(0, type_graphql_1.Field)({ description: "'user' | 'assistant' | 'system'" }),
|
|
51
|
+
tslib_1.__metadata("design:type", String)
|
|
52
|
+
], ChatMessage.prototype, "role", void 0);
|
|
53
|
+
tslib_1.__decorate([
|
|
54
|
+
(0, typeorm_1.Column)({
|
|
55
|
+
type: DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
|
|
56
|
+
? 'longtext'
|
|
57
|
+
: DATABASE_TYPE == 'oracle'
|
|
58
|
+
? 'clob'
|
|
59
|
+
: DATABASE_TYPE == 'mssql'
|
|
60
|
+
? 'nvarchar'
|
|
61
|
+
: 'text',
|
|
62
|
+
length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined
|
|
63
|
+
}),
|
|
64
|
+
(0, type_graphql_1.Field)({ description: 'Message content' }),
|
|
65
|
+
tslib_1.__metadata("design:type", String)
|
|
66
|
+
], ChatMessage.prototype, "content", void 0);
|
|
67
|
+
tslib_1.__decorate([
|
|
68
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
69
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'PatchEntry.id this message triggered (if any).' }),
|
|
70
|
+
tslib_1.__metadata("design:type", String)
|
|
71
|
+
], ChatMessage.prototype, "relatedPatchId", void 0);
|
|
72
|
+
tslib_1.__decorate([
|
|
73
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
74
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'ImportSession.id this message triggered (if any).' }),
|
|
75
|
+
tslib_1.__metadata("design:type", String)
|
|
76
|
+
], ChatMessage.prototype, "relatedImportSessionId", void 0);
|
|
77
|
+
tslib_1.__decorate([
|
|
78
|
+
(0, typeorm_1.Column)({
|
|
79
|
+
type: DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
|
|
80
|
+
? 'longtext'
|
|
81
|
+
: DATABASE_TYPE == 'oracle'
|
|
82
|
+
? 'clob'
|
|
83
|
+
: DATABASE_TYPE == 'mssql'
|
|
84
|
+
? 'nvarchar'
|
|
85
|
+
: 'text',
|
|
86
|
+
length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined,
|
|
87
|
+
nullable: true
|
|
88
|
+
}),
|
|
89
|
+
tslib_1.__metadata("design:type", String)
|
|
90
|
+
], ChatMessage.prototype, "toolUsages", void 0);
|
|
91
|
+
tslib_1.__decorate([
|
|
92
|
+
(0, type_graphql_1.Field)(() => graphql_scalars_1.GraphQLJSON, {
|
|
93
|
+
nullable: true,
|
|
94
|
+
description: 'Tool usage trace — array of {name, arguments, result, kind}. Only on assistant messages.'
|
|
95
|
+
}),
|
|
96
|
+
tslib_1.__metadata("design:type", Object),
|
|
97
|
+
tslib_1.__metadata("design:paramtypes", [])
|
|
98
|
+
], ChatMessage.prototype, "toolUsagesJson", null);
|
|
99
|
+
tslib_1.__decorate([
|
|
100
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
101
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'User who triggered this message.' }),
|
|
102
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
103
|
+
], ChatMessage.prototype, "creator", void 0);
|
|
104
|
+
tslib_1.__decorate([
|
|
105
|
+
(0, typeorm_1.RelationId)((message) => message.creator),
|
|
106
|
+
tslib_1.__metadata("design:type", String)
|
|
107
|
+
], ChatMessage.prototype, "creatorId", void 0);
|
|
108
|
+
tslib_1.__decorate([
|
|
109
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
110
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Last user to update this message (for future edit support).' }),
|
|
111
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
112
|
+
], ChatMessage.prototype, "updater", void 0);
|
|
113
|
+
tslib_1.__decorate([
|
|
114
|
+
(0, typeorm_1.RelationId)((message) => message.updater),
|
|
115
|
+
tslib_1.__metadata("design:type", String)
|
|
116
|
+
], ChatMessage.prototype, "updaterId", void 0);
|
|
117
|
+
tslib_1.__decorate([
|
|
118
|
+
(0, typeorm_1.ManyToOne)(type => ChatMessage, { nullable: true, onDelete: 'SET NULL' }),
|
|
119
|
+
tslib_1.__metadata("design:type", ChatMessage)
|
|
120
|
+
], ChatMessage.prototype, "parentMessage", void 0);
|
|
121
|
+
tslib_1.__decorate([
|
|
122
|
+
(0, typeorm_1.RelationId)((message) => message.parentMessage),
|
|
123
|
+
(0, type_graphql_1.Field)({
|
|
124
|
+
nullable: true,
|
|
125
|
+
description: 'Id of the message this one is in-response-to / continues. Enables linear / branching / tree structures.'
|
|
126
|
+
}),
|
|
127
|
+
tslib_1.__metadata("design:type", String)
|
|
128
|
+
], ChatMessage.prototype, "parentMessageId", void 0);
|
|
129
|
+
tslib_1.__decorate([
|
|
130
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
131
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Creation timestamp.' }),
|
|
132
|
+
tslib_1.__metadata("design:type", Date)
|
|
133
|
+
], ChatMessage.prototype, "createdAt", void 0);
|
|
134
|
+
tslib_1.__decorate([
|
|
135
|
+
(0, typeorm_1.UpdateDateColumn)(),
|
|
136
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Last update timestamp (relevant once message editing is supported).' }),
|
|
137
|
+
tslib_1.__metadata("design:type", Date)
|
|
138
|
+
], ChatMessage.prototype, "updatedAt", void 0);
|
|
139
|
+
tslib_1.__decorate([
|
|
140
|
+
(0, typeorm_1.DeleteDateColumn)(),
|
|
141
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Soft delete timestamp.' }),
|
|
142
|
+
tslib_1.__metadata("design:type", Date)
|
|
143
|
+
], ChatMessage.prototype, "deletedAt", void 0);
|
|
144
|
+
exports.ChatMessage = ChatMessage = tslib_1.__decorate([
|
|
145
|
+
(0, typeorm_1.Entity)(),
|
|
146
|
+
(0, typeorm_1.Index)('ix_chat_message_1', (message) => [message.session, message.createdAt]),
|
|
147
|
+
(0, type_graphql_1.ObjectType)({ description: 'A single chat message in a ChatSession.' })
|
|
148
|
+
], ChatMessage);
|
|
149
|
+
//# sourceMappingURL=chat-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-message.js","sourceRoot":"","sources":["../../../server/service/chat-message/chat-message.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatMessage — ChatSession 의 한 메시지.\n *\n * role: 'user' | 'assistant' | 'system'\n * 'system' 은 사용자 직접 편집/import 진행 등 시스템이 자동 생성하는 컨텍스트 메시지.\n *\n * relatedPatchId / relatedImportSessionId 로 메시지가 트리거한 패치·임포트와 연결.\n */\nimport {\n Column,\n CreateDateColumn,\n DeleteDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, ID, ObjectType } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\n\nimport { User } from '@things-factory/auth-base'\nimport { config } from '@things-factory/env'\n\nimport { ChatSession } from '../chat-session/chat-session.js'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\n@Entity()\n@Index('ix_chat_message_1', (message: ChatMessage) => [message.session, message.createdAt])\n@ObjectType({ description: 'A single chat message in a ChatSession.' })\nexport class ChatMessage {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { nullable: true })\n readonly id?: string\n\n @ManyToOne(type => ChatSession, session => session.messages, { onDelete: 'CASCADE' })\n session?: ChatSession\n\n @RelationId((message: ChatMessage) => message.session)\n sessionId?: string\n\n @Column({ type: 'varchar', length: 16 })\n @Field({ description: \"'user' | 'assistant' | 'system'\" })\n role!: string\n\n @Column({\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'text',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined\n })\n @Field({ description: 'Message content' })\n content!: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'PatchEntry.id this message triggered (if any).' })\n relatedPatchId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'ImportSession.id this message triggered (if any).' })\n relatedImportSessionId?: string\n\n /**\n * AI 가 응답을 만드는 동안 호출한 도구 trace — JSON-stringified.\n *\n * 컬럼은 string (PatchEntry.ops 와 동일 패턴), GraphQL 노출은 toolUsagesJson getter\n * 로 parse 된 객체. UI 의 fold-able 박스 (\"AI 가 이런 도구를 사용했습니다\") 가\n * 페이지 reload / loadHistory 후에도 살아있도록 영속.\n *\n * 형태: ToolUsage[] (assistant.ts 의 시간순 trace, summarizeToolResult 로 압축).\n * null 이면 도구 호출 없었던 메시지 (text-only 응답).\n */\n @Column({\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'text',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined,\n nullable: true\n })\n toolUsages?: string\n\n /** GraphQL 노출용 — JSON 배열로 parse. */\n @Field(() => GraphQLJSON, {\n nullable: true,\n description:\n 'Tool usage trace — array of {name, arguments, result, kind}. Only on assistant messages.'\n })\n get toolUsagesJson(): any {\n if (!this.toolUsages) return null\n try {\n return JSON.parse(this.toolUsages)\n } catch {\n return null\n }\n }\n\n /**\n * 메시지를 일으킨 사용자.\n * - role='user' → 보낸 사용자\n * - role='assistant' → 그 응답을 트리거한 사용자 (직전 user 메시지의 작성자)\n * - role='system' → 시스템 액션을 일으킨 사용자 (예: 직접 편집한 사용자)\n *\n * nullable — legacy 메시지 (이 필드 추가 이전에 작성) 는 null. 또한 ad-hoc 모드 / 시스템\n * 자동 메시지 중 사용자 컨텍스트가 없는 경우도 null 가능.\n */\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'User who triggered this message.' })\n creator?: User\n\n @RelationId((message: ChatMessage) => message.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Last user to update this message (for future edit support).' })\n updater?: User\n\n @RelationId((message: ChatMessage) => message.updater)\n updaterId?: string\n\n /**\n * 부모 메시지 — 이 메시지가 \"응답하는 대상\" / \"이어가는 메시지\" 의 id.\n *\n * 의미 (role 별):\n * - 'user' → 직전 in-session 메시지 (보통 assistant 또는 system). 첫 turn 은 null.\n * - 'assistant' → 이 응답이 답하는 user 메시지. (regenerate 로 같은 user 메시지를 부모로\n * 하는 형제 assistant 메시지가 생기면 자연스럽게 branching tree 가 됨)\n * - 'system' → 직전 in-session 메시지 (timeline 연속성 유지).\n *\n * 이 한 컬럼으로 향후 어떤 흐름이든 표현 가능 — linear chain / branching (regenerate) /\n * tree (replies-to-specific-message) 등. UI/쿼리는 점진 도입.\n *\n * onDelete: 'SET NULL' — 부모 메시지가 삭제돼도 child 는 남되 dangling 마킹.\n */\n @ManyToOne(type => ChatMessage, { nullable: true, onDelete: 'SET NULL' })\n parentMessage?: ChatMessage\n\n @RelationId((message: ChatMessage) => message.parentMessage)\n @Field({\n nullable: true,\n description:\n 'Id of the message this one is in-response-to / continues. Enables linear / branching / tree structures.'\n })\n parentMessageId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp (relevant once message editing is supported).' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft delete timestamp.' })\n deletedAt?: Date\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ChatMessage } from './chat-message.js';
|
|
2
|
+
export { ChatMessage };
|
|
3
|
+
export { BoardChatMessageSubscription, publishChatMessage, CHAT_MESSAGE_TOPIC, chatMessageFilter } from './chat-message-subscription.js';
|
|
4
|
+
export type { ChatMessagePayload } from './chat-message-subscription.js';
|
|
5
|
+
export declare const entities: (typeof ChatMessage)[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.entities = exports.chatMessageFilter = exports.CHAT_MESSAGE_TOPIC = exports.publishChatMessage = exports.BoardChatMessageSubscription = exports.ChatMessage = void 0;
|
|
4
|
+
const chat_message_js_1 = require("./chat-message.js");
|
|
5
|
+
Object.defineProperty(exports, "ChatMessage", { enumerable: true, get: function () { return chat_message_js_1.ChatMessage; } });
|
|
6
|
+
var chat_message_subscription_js_1 = require("./chat-message-subscription.js");
|
|
7
|
+
Object.defineProperty(exports, "BoardChatMessageSubscription", { enumerable: true, get: function () { return chat_message_subscription_js_1.BoardChatMessageSubscription; } });
|
|
8
|
+
Object.defineProperty(exports, "publishChatMessage", { enumerable: true, get: function () { return chat_message_subscription_js_1.publishChatMessage; } });
|
|
9
|
+
Object.defineProperty(exports, "CHAT_MESSAGE_TOPIC", { enumerable: true, get: function () { return chat_message_subscription_js_1.CHAT_MESSAGE_TOPIC; } });
|
|
10
|
+
Object.defineProperty(exports, "chatMessageFilter", { enumerable: true, get: function () { return chat_message_subscription_js_1.chatMessageFilter; } });
|
|
11
|
+
exports.entities = [chat_message_js_1.ChatMessage];
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/chat-message/index.ts"],"names":[],"mappings":";;;AAAA,uDAA+C;AAEtC,4FAFA,6BAAW,OAEA;AACpB,+EAKuC;AAJrC,4IAAA,4BAA4B,OAAA;AAC5B,kIAAA,kBAAkB,OAAA;AAClB,kIAAA,kBAAkB,OAAA;AAClB,iIAAA,iBAAiB,OAAA;AAIN,QAAA,QAAQ,GAAG,CAAC,6BAAW,CAAC,CAAA","sourcesContent":["import { ChatMessage } from './chat-message.js'\n\nexport { ChatMessage }\nexport {\n BoardChatMessageSubscription,\n publishChatMessage,\n CHAT_MESSAGE_TOPIC,\n chatMessageFilter\n} from './chat-message-subscription.js'\nexport type { ChatMessagePayload } from './chat-message-subscription.js'\n\nexport const entities = [ChatMessage]\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Domain } from '@things-factory/shell';
|
|
2
|
+
import { User } from '@things-factory/auth-base';
|
|
3
|
+
import { ChatMessage } from '../chat-message/chat-message.js';
|
|
4
|
+
import { PatchEntry } from '../patch-entry/patch-entry.js';
|
|
5
|
+
export declare class ChatSession {
|
|
6
|
+
readonly id?: string;
|
|
7
|
+
domain?: Domain;
|
|
8
|
+
domainId?: string;
|
|
9
|
+
/** Board.id 와 연결. Board 가 owning side 가 될 예정. 1:N — 한 보드에 여러 세션 가능. */
|
|
10
|
+
boardId?: string;
|
|
11
|
+
/**
|
|
12
|
+
* 세션의 사용자 정의 이름 (탭 레이블 / 세션 식별 표시용).
|
|
13
|
+
*
|
|
14
|
+
* nullable — 미설정 시 UI 가 fallback 라벨 ("세션 N" 또는 createdAt 기반) 사용. 사용자가
|
|
15
|
+
* 다중 세션 운영 시 의미 부여 (예: "초기 설계", "운영 시뮬레이션", "사용자A 의 사적 세션").
|
|
16
|
+
*/
|
|
17
|
+
name?: string;
|
|
18
|
+
creator?: User;
|
|
19
|
+
creatorId?: string;
|
|
20
|
+
updater?: User;
|
|
21
|
+
updaterId?: string;
|
|
22
|
+
/** 토큰 절감용 — 오래된 메시지를 LLM 으로 압축한 요약. Phase 2 에서 작성. */
|
|
23
|
+
lastSummary?: string;
|
|
24
|
+
/** 사용 모델 식별 — 'anthropic:claude-sonnet-4-6' 등 */
|
|
25
|
+
aiClientId?: string;
|
|
26
|
+
createdAt?: Date;
|
|
27
|
+
updatedAt?: Date;
|
|
28
|
+
deletedAt?: Date;
|
|
29
|
+
messages?: ChatMessage[];
|
|
30
|
+
patches?: PatchEntry[];
|
|
31
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChatSession = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
/**
|
|
6
|
+
* ChatSession — Board 와 결합되는 AI 협력 세션.
|
|
7
|
+
*
|
|
8
|
+
* 한 보드에 여러 세션 가능 — DB 레벨 unique 제약 없음.
|
|
9
|
+
*
|
|
10
|
+
* 향후 폭증할 세션 분화 차원 (예: thread / 사용자별 / 컨텍스트별 design vs ops /
|
|
11
|
+
* archived / forked from clone / agent별) 을 미리 차단하지 않기 위해 구조 자체는 1:N
|
|
12
|
+
* 으로 열어둠. 단일 세션 정책 (현재 UX) 은 app 레벨 idempotent 로직 — `startBoardAISession`
|
|
13
|
+
* 이 boardId 매칭 시 기존 세션 반환, `chatSessionByBoard` 가 첫 매칭 반환.
|
|
14
|
+
*
|
|
15
|
+
* 미래에 다중 세션 활성화 시 discriminator 컬럼 (kind / name / threadId / creatorId 등)
|
|
16
|
+
* 을 그때 추가. 마이그레이션 부담 최소화 — 현재는 unique 만 풀어 자리 마련.
|
|
17
|
+
*
|
|
18
|
+
* board-service 의 Board 가 owning side 가 될 예정 (ChatSession FK).
|
|
19
|
+
*/
|
|
20
|
+
const typeorm_1 = require("typeorm");
|
|
21
|
+
const type_graphql_1 = require("type-graphql");
|
|
22
|
+
const shell_1 = require("@things-factory/shell");
|
|
23
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
24
|
+
const env_1 = require("@things-factory/env");
|
|
25
|
+
const chat_message_js_1 = require("../chat-message/chat-message.js");
|
|
26
|
+
const patch_entry_js_1 = require("../patch-entry/patch-entry.js");
|
|
27
|
+
const ORMCONFIG = env_1.config.get('ormconfig', {});
|
|
28
|
+
const DATABASE_TYPE = ORMCONFIG.type;
|
|
29
|
+
let ChatSession = class ChatSession {
|
|
30
|
+
};
|
|
31
|
+
exports.ChatSession = ChatSession;
|
|
32
|
+
tslib_1.__decorate([
|
|
33
|
+
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
34
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.ID, { nullable: true }),
|
|
35
|
+
tslib_1.__metadata("design:type", String)
|
|
36
|
+
], ChatSession.prototype, "id", void 0);
|
|
37
|
+
tslib_1.__decorate([
|
|
38
|
+
(0, typeorm_1.ManyToOne)(type => shell_1.Domain),
|
|
39
|
+
(0, type_graphql_1.Field)(type => shell_1.Domain, { nullable: true }),
|
|
40
|
+
tslib_1.__metadata("design:type", shell_1.Domain)
|
|
41
|
+
], ChatSession.prototype, "domain", void 0);
|
|
42
|
+
tslib_1.__decorate([
|
|
43
|
+
(0, typeorm_1.RelationId)((session) => session.domain),
|
|
44
|
+
tslib_1.__metadata("design:type", String)
|
|
45
|
+
], ChatSession.prototype, "domainId", void 0);
|
|
46
|
+
tslib_1.__decorate([
|
|
47
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
48
|
+
(0, type_graphql_1.Field)({
|
|
49
|
+
nullable: true,
|
|
50
|
+
description: 'Connected Board id. Multiple sessions per board allowed (future: threads / per-user / contexts).'
|
|
51
|
+
}),
|
|
52
|
+
tslib_1.__metadata("design:type", String)
|
|
53
|
+
], ChatSession.prototype, "boardId", void 0);
|
|
54
|
+
tslib_1.__decorate([
|
|
55
|
+
(0, typeorm_1.Column)({ nullable: true, length: 200 }),
|
|
56
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'User-given name of this session (tab label / identification).' }),
|
|
57
|
+
tslib_1.__metadata("design:type", String)
|
|
58
|
+
], ChatSession.prototype, "name", void 0);
|
|
59
|
+
tslib_1.__decorate([
|
|
60
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User),
|
|
61
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'User who created this session.' }),
|
|
62
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
63
|
+
], ChatSession.prototype, "creator", void 0);
|
|
64
|
+
tslib_1.__decorate([
|
|
65
|
+
(0, typeorm_1.RelationId)((session) => session.creator),
|
|
66
|
+
tslib_1.__metadata("design:type", String)
|
|
67
|
+
], ChatSession.prototype, "creatorId", void 0);
|
|
68
|
+
tslib_1.__decorate([
|
|
69
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User),
|
|
70
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'User who last updated this session.' }),
|
|
71
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
72
|
+
], ChatSession.prototype, "updater", void 0);
|
|
73
|
+
tslib_1.__decorate([
|
|
74
|
+
(0, typeorm_1.RelationId)((session) => session.updater),
|
|
75
|
+
tslib_1.__metadata("design:type", String)
|
|
76
|
+
], ChatSession.prototype, "updaterId", void 0);
|
|
77
|
+
tslib_1.__decorate([
|
|
78
|
+
(0, typeorm_1.Column)({
|
|
79
|
+
nullable: true,
|
|
80
|
+
type: DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
|
|
81
|
+
? 'longtext'
|
|
82
|
+
: DATABASE_TYPE == 'oracle'
|
|
83
|
+
? 'clob'
|
|
84
|
+
: DATABASE_TYPE == 'mssql'
|
|
85
|
+
? 'nvarchar'
|
|
86
|
+
: 'text',
|
|
87
|
+
length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined
|
|
88
|
+
}),
|
|
89
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Compressed summary of older messages (for token saving).' }),
|
|
90
|
+
tslib_1.__metadata("design:type", String)
|
|
91
|
+
], ChatSession.prototype, "lastSummary", void 0);
|
|
92
|
+
tslib_1.__decorate([
|
|
93
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
94
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
95
|
+
tslib_1.__metadata("design:type", String)
|
|
96
|
+
], ChatSession.prototype, "aiClientId", void 0);
|
|
97
|
+
tslib_1.__decorate([
|
|
98
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
99
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
100
|
+
tslib_1.__metadata("design:type", Date)
|
|
101
|
+
], ChatSession.prototype, "createdAt", void 0);
|
|
102
|
+
tslib_1.__decorate([
|
|
103
|
+
(0, typeorm_1.UpdateDateColumn)(),
|
|
104
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
105
|
+
tslib_1.__metadata("design:type", Date)
|
|
106
|
+
], ChatSession.prototype, "updatedAt", void 0);
|
|
107
|
+
tslib_1.__decorate([
|
|
108
|
+
(0, typeorm_1.DeleteDateColumn)(),
|
|
109
|
+
tslib_1.__metadata("design:type", Date
|
|
110
|
+
// ── 관계 (TypeORM 만, GraphQL 노출은 별도 query 통해 페이징) ──
|
|
111
|
+
)
|
|
112
|
+
], ChatSession.prototype, "deletedAt", void 0);
|
|
113
|
+
tslib_1.__decorate([
|
|
114
|
+
(0, typeorm_1.OneToMany)(type => chat_message_js_1.ChatMessage, message => message.session),
|
|
115
|
+
tslib_1.__metadata("design:type", Array)
|
|
116
|
+
], ChatSession.prototype, "messages", void 0);
|
|
117
|
+
tslib_1.__decorate([
|
|
118
|
+
(0, typeorm_1.OneToMany)(type => patch_entry_js_1.PatchEntry, patch => patch.session),
|
|
119
|
+
tslib_1.__metadata("design:type", Array)
|
|
120
|
+
], ChatSession.prototype, "patches", void 0);
|
|
121
|
+
exports.ChatSession = ChatSession = tslib_1.__decorate([
|
|
122
|
+
(0, typeorm_1.Entity)()
|
|
123
|
+
// 인덱스는 조회 성능용으로 유지 (chatSessionByBoard 가 [domain, boardId] 로 자주 쿼리).
|
|
124
|
+
// unique 제약은 의도적으로 제거 — 한 보드에 여러 세션을 미래에 허용하기 위함.
|
|
125
|
+
,
|
|
126
|
+
(0, typeorm_1.Index)('ix_chat_session_1', (session) => [session.domain, session.boardId]),
|
|
127
|
+
(0, type_graphql_1.ObjectType)({
|
|
128
|
+
description: 'AI 협력 세션 — Board 와 결합. 한 보드에 여러 세션 가능 (thread / 사용자별 / 컨텍스트별 등 미래 확장).'
|
|
129
|
+
})
|
|
130
|
+
], ChatSession);
|
|
131
|
+
//# sourceMappingURL=chat-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-session.js","sourceRoot":"","sources":["../../../server/service/chat-session/chat-session.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatSession — Board 와 결합되는 AI 협력 세션.\n *\n * 한 보드에 여러 세션 가능 — DB 레벨 unique 제약 없음.\n *\n * 향후 폭증할 세션 분화 차원 (예: thread / 사용자별 / 컨텍스트별 design vs ops /\n * archived / forked from clone / agent별) 을 미리 차단하지 않기 위해 구조 자체는 1:N\n * 으로 열어둠. 단일 세션 정책 (현재 UX) 은 app 레벨 idempotent 로직 — `startBoardAISession`\n * 이 boardId 매칭 시 기존 세션 반환, `chatSessionByBoard` 가 첫 매칭 반환.\n *\n * 미래에 다중 세션 활성화 시 discriminator 컬럼 (kind / name / threadId / creatorId 등)\n * 을 그때 추가. 마이그레이션 부담 최소화 — 현재는 unique 만 풀어 자리 마련.\n *\n * board-service 의 Board 가 owning side 가 될 예정 (ChatSession FK).\n */\nimport {\n Column,\n CreateDateColumn,\n DeleteDateColumn,\n Entity,\n Index,\n ManyToOne,\n OneToMany,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, ID, ObjectType } from 'type-graphql'\n\nimport { Domain } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { config } from '@things-factory/env'\n\nimport { ChatMessage } from '../chat-message/chat-message.js'\nimport { PatchEntry } from '../patch-entry/patch-entry.js'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\n@Entity()\n// 인덱스는 조회 성능용으로 유지 (chatSessionByBoard 가 [domain, boardId] 로 자주 쿼리).\n// unique 제약은 의도적으로 제거 — 한 보드에 여러 세션을 미래에 허용하기 위함.\n@Index('ix_chat_session_1', (session: ChatSession) => [session.domain, session.boardId])\n@ObjectType({\n description: 'AI 협력 세션 — Board 와 결합. 한 보드에 여러 세션 가능 (thread / 사용자별 / 컨텍스트별 등 미래 확장).'\n})\nexport class ChatSession {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { nullable: true })\n readonly id?: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true })\n domain?: Domain\n\n @RelationId((session: ChatSession) => session.domain)\n domainId?: string\n\n /** Board.id 와 연결. Board 가 owning side 가 될 예정. 1:N — 한 보드에 여러 세션 가능. */\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description:\n 'Connected Board id. Multiple sessions per board allowed (future: threads / per-user / contexts).'\n })\n boardId?: string\n\n /**\n * 세션의 사용자 정의 이름 (탭 레이블 / 세션 식별 표시용).\n *\n * nullable — 미설정 시 UI 가 fallback 라벨 (\"세션 N\" 또는 createdAt 기반) 사용. 사용자가\n * 다중 세션 운영 시 의미 부여 (예: \"초기 설계\", \"운영 시뮬레이션\", \"사용자A 의 사적 세션\").\n */\n @Column({ nullable: true, length: 200 })\n @Field({ nullable: true, description: 'User-given name of this session (tab label / identification).' })\n name?: string\n\n @ManyToOne(type => User)\n @Field(type => User, { nullable: true, description: 'User who created this session.' })\n creator?: User\n\n @RelationId((session: ChatSession) => session.creator)\n creatorId?: string\n\n @ManyToOne(type => User)\n @Field(type => User, { nullable: true, description: 'User who last updated this session.' })\n updater?: User\n\n @RelationId((session: ChatSession) => session.updater)\n updaterId?: string\n\n /** 토큰 절감용 — 오래된 메시지를 LLM 으로 압축한 요약. Phase 2 에서 작성. */\n @Column({\n nullable: true,\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'text',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined\n })\n @Field({ nullable: true, description: 'Compressed summary of older messages (for token saving).' })\n lastSummary?: string\n\n /** 사용 모델 식별 — 'anthropic:claude-sonnet-4-6' 등 */\n @Column({ nullable: true })\n @Field({ nullable: true })\n aiClientId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true })\n updatedAt?: Date\n\n @DeleteDateColumn()\n deletedAt?: Date\n\n // ── 관계 (TypeORM 만, GraphQL 노출은 별도 query 통해 페이징) ──\n @OneToMany(type => ChatMessage, message => message.session)\n messages?: ChatMessage[]\n\n @OneToMany(type => PatchEntry, patch => patch.session)\n patches?: PatchEntry[]\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.entities = exports.ChatSession = void 0;
|
|
4
|
+
const chat_session_js_1 = require("./chat-session.js");
|
|
5
|
+
Object.defineProperty(exports, "ChatSession", { enumerable: true, get: function () { return chat_session_js_1.ChatSession; } });
|
|
6
|
+
exports.entities = [chat_session_js_1.ChatSession];
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/chat-session/index.ts"],"names":[],"mappings":";;;AAAA,uDAA+C;AAEtC,4FAFA,6BAAW,OAEA;AAEP,QAAA,QAAQ,GAAG,CAAC,6BAAW,CAAC,CAAA","sourcesContent":["import { ChatSession } from './chat-session.js'\n\nexport { ChatSession }\n\nexport const entities = [ChatSession]\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Domain } from '@things-factory/shell';
|
|
2
|
+
import { User } from '@things-factory/auth-base';
|
|
3
|
+
import { ChatSession } from '../chat-session/chat-session.js';
|
|
4
|
+
export declare class ChatSessionParticipant {
|
|
5
|
+
readonly id?: string;
|
|
6
|
+
domain?: Domain;
|
|
7
|
+
domainId?: string;
|
|
8
|
+
session?: ChatSession;
|
|
9
|
+
sessionId?: string;
|
|
10
|
+
user?: User;
|
|
11
|
+
userId?: string;
|
|
12
|
+
/**
|
|
13
|
+
* 참여자의 역할.
|
|
14
|
+
* - 'owner': 세션 만든 사람. rename / delete 권한.
|
|
15
|
+
* - 'member': 일반 참여자. 메시지 송수신.
|
|
16
|
+
* - 'viewer': 읽기 전용 (미래 권한 정책 활성화 시).
|
|
17
|
+
*
|
|
18
|
+
* 시작은 'owner' / 'member' 둘로 충분. 더 세분화 필요해지면 enum 확장.
|
|
19
|
+
*/
|
|
20
|
+
role: string;
|
|
21
|
+
/** 마지막 활동 시각 — presence indicator. nullable. */
|
|
22
|
+
lastSeenAt?: Date;
|
|
23
|
+
creator?: User;
|
|
24
|
+
creatorId?: string;
|
|
25
|
+
updater?: User;
|
|
26
|
+
updaterId?: string;
|
|
27
|
+
createdAt?: Date;
|
|
28
|
+
updatedAt?: Date;
|
|
29
|
+
deletedAt?: Date;
|
|
30
|
+
}
|