@things-factory/ai-assistant 10.1.26 โ 10.1.28
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/client/components/assistant-chat.ts +653 -59
- package/client/components/assistant-mode.test.ts +86 -55
- package/client/components/assistant-mode.ts +124 -82
- package/client/components/chat-echo-dedup.test.ts +23 -0
- package/client/components/chat-echo-dedup.ts +29 -3
- package/client/components/chat-input-builder.test.ts +20 -20
- package/client/components/chat-input-builder.ts +16 -14
- package/client/components/chat-proposal-survival.test.ts +73 -0
- package/client/components/mention-popup.ts +31 -8
- package/client/components/panel-aria.test.ts +34 -0
- package/client/components/proposal-outcome-line.ts +33 -0
- package/client/utils/assistant-session-controller.test.ts +75 -0
- package/client/utils/assistant-session-controller.ts +23 -0
- package/client/utils/assistant-session-transport.ts +11 -3
- package/dist-client/components/assistant-chat.d.ts +128 -13
- package/dist-client/components/assistant-chat.js +613 -67
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/components/assistant-mode.d.ts +80 -68
- package/dist-client/components/assistant-mode.js +63 -19
- package/dist-client/components/assistant-mode.js.map +1 -1
- package/dist-client/components/assistant-mode.test.js +74 -53
- package/dist-client/components/assistant-mode.test.js.map +1 -1
- package/dist-client/components/chat-echo-dedup.d.ts +2 -0
- package/dist-client/components/chat-echo-dedup.js +27 -4
- package/dist-client/components/chat-echo-dedup.js.map +1 -1
- package/dist-client/components/chat-echo-dedup.test.js +20 -0
- package/dist-client/components/chat-echo-dedup.test.js.map +1 -1
- package/dist-client/components/chat-input-builder.d.ts +12 -7
- package/dist-client/components/chat-input-builder.js +8 -10
- package/dist-client/components/chat-input-builder.js.map +1 -1
- package/dist-client/components/chat-input-builder.test.js +17 -18
- package/dist-client/components/chat-input-builder.test.js.map +1 -1
- package/dist-client/components/chat-proposal-survival.test.d.ts +1 -0
- package/dist-client/components/chat-proposal-survival.test.js +61 -0
- package/dist-client/components/chat-proposal-survival.test.js.map +1 -0
- package/dist-client/components/mention-popup.js +28 -8
- package/dist-client/components/mention-popup.js.map +1 -1
- package/dist-client/components/panel-aria.test.d.ts +1 -0
- package/dist-client/components/panel-aria.test.js +31 -0
- package/dist-client/components/panel-aria.test.js.map +1 -0
- package/dist-client/components/proposal-outcome-line.d.ts +9 -0
- package/dist-client/components/proposal-outcome-line.js +15 -0
- package/dist-client/components/proposal-outcome-line.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/assistant-session-controller.d.ts +10 -0
- package/dist-client/utils/assistant-session-controller.js +16 -0
- package/dist-client/utils/assistant-session-controller.js.map +1 -1
- package/dist-client/utils/assistant-session-controller.test.d.ts +1 -0
- package/dist-client/utils/assistant-session-controller.test.js +56 -0
- package/dist-client/utils/assistant-session-controller.test.js.map +1 -0
- package/dist-client/utils/assistant-session-transport.js +11 -3
- package/dist-client/utils/assistant-session-transport.js.map +1 -1
- package/dist-server/service/assistant-capability-resolver.d.ts +17 -0
- package/dist-server/service/assistant-capability-resolver.js +88 -0
- package/dist-server/service/assistant-capability-resolver.js.map +1 -0
- package/dist-server/service/assistant-chat-resolver.d.ts +6 -6
- package/dist-server/service/assistant-chat-resolver.js +166 -44
- package/dist-server/service/assistant-chat-resolver.js.map +1 -1
- package/dist-server/service/assistant-mode/assistant-mode-resolver.d.ts +25 -0
- package/dist-server/service/assistant-mode/assistant-mode-resolver.js +140 -0
- package/dist-server/service/assistant-mode/assistant-mode-resolver.js.map +1 -0
- package/dist-server/service/assistant-mode/index.d.ts +9 -0
- package/dist-server/service/assistant-mode/index.js +19 -0
- package/dist-server/service/assistant-mode/index.js.map +1 -0
- package/dist-server/service/assistant-mode/registry.d.ts +18 -0
- package/dist-server/service/assistant-mode/registry.js +136 -0
- package/dist-server/service/assistant-mode/registry.js.map +1 -0
- package/dist-server/service/assistant-mode/resolve.d.ts +33 -0
- package/dist-server/service/assistant-mode/resolve.js +60 -0
- package/dist-server/service/assistant-mode/resolve.js.map +1 -0
- package/dist-server/service/assistant-mode/types.d.ts +99 -0
- package/dist-server/service/assistant-mode/types.js +12 -0
- package/dist-server/service/assistant-mode/types.js.map +1 -0
- package/dist-server/service/chat-message/carried-turns.d.ts +48 -0
- package/dist-server/service/chat-message/carried-turns.js +80 -0
- package/dist-server/service/chat-message/carried-turns.js.map +1 -0
- package/dist-server/service/chat-message/chat-message-subscription.d.ts +1 -1
- package/dist-server/service/chat-message/chat-message-subscription.js +24 -6
- package/dist-server/service/chat-message/chat-message-subscription.js.map +1 -1
- package/dist-server/service/chat-message/chat-message.d.ts +32 -0
- package/dist-server/service/chat-message/chat-message.js +17 -0
- package/dist-server/service/chat-message/chat-message.js.map +1 -1
- package/dist-server/service/chat-message/door-access.d.ts +15 -0
- package/dist-server/service/chat-message/door-access.js +26 -0
- package/dist-server/service/chat-message/door-access.js.map +1 -0
- package/dist-server/service/chat-message/fold-session-history.d.ts +30 -0
- package/dist-server/service/chat-message/fold-session-history.js +133 -0
- package/dist-server/service/chat-message/fold-session-history.js.map +1 -0
- package/dist-server/service/chat-message/llm-history.d.ts +7 -0
- package/dist-server/service/chat-message/llm-history.js +23 -11
- package/dist-server/service/chat-message/llm-history.js.map +1 -1
- package/dist-server/service/chat-message/message-doors.d.ts +29 -0
- package/dist-server/service/chat-message/message-doors.js +107 -0
- package/dist-server/service/chat-message/message-doors.js.map +1 -0
- package/dist-server/service/chat-message/proposal-outcome.d.ts +18 -0
- package/dist-server/service/chat-message/proposal-outcome.js +31 -0
- package/dist-server/service/chat-message/proposal-outcome.js.map +1 -0
- package/dist-server/service/chat-message/reader-gate.d.ts +3 -0
- package/dist-server/service/chat-message/reader-gate.js +37 -0
- package/dist-server/service/chat-message/reader-gate.js.map +1 -0
- package/dist-server/service/chat-message/room-message.d.ts +4 -0
- package/dist-server/service/chat-message/room-message.js +25 -0
- package/dist-server/service/chat-message/room-message.js.map +1 -0
- package/dist-server/service/chat-session/chat-session.d.ts +24 -0
- package/dist-server/service/chat-session/chat-session.js +26 -2
- package/dist-server/service/chat-session/chat-session.js.map +1 -1
- package/dist-server/service/chat-session/session-inbox.d.ts +4 -1
- package/dist-server/service/chat-session/session-inbox.js +3 -2
- package/dist-server/service/chat-session/session-inbox.js.map +1 -1
- package/dist-server/service/chat-session/session-visibility.d.ts +15 -0
- package/dist-server/service/chat-session/session-visibility.js +28 -0
- package/dist-server/service/chat-session/session-visibility.js.map +1 -0
- package/dist-server/service/chat-session/station-session-guard.d.ts +1 -5
- package/dist-server/service/chat-session/station-session-guard.js +7 -2
- package/dist-server/service/chat-session/station-session-guard.js.map +1 -1
- package/dist-server/service/chat-session-participant/mention-invite.d.ts +29 -0
- package/dist-server/service/chat-session-participant/mention-invite.js +103 -0
- package/dist-server/service/chat-session-participant/mention-invite.js.map +1 -0
- package/dist-server/service/chat-session-resolver.d.ts +15 -0
- package/dist-server/service/chat-session-resolver.js +267 -15
- package/dist-server/service/chat-session-resolver.js.map +1 -1
- package/dist-server/service/grounding-sources.d.ts +14 -0
- package/dist-server/service/grounding-sources.js +26 -0
- package/dist-server/service/grounding-sources.js.map +1 -0
- package/dist-server/service/index.d.ts +8 -1
- package/dist-server/service/index.js +19 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/request-translator.d.ts +2 -0
- package/dist-server/service/request-translator.js +20 -0
- package/dist-server/service/request-translator.js.map +1 -0
- package/dist-server/service/testing/conversation-script.d.ts +123 -0
- package/dist-server/service/testing/conversation-script.js +202 -0
- package/dist-server/service/testing/conversation-script.js.map +1 -0
- package/dist-server/service/testing/mode-conformance.d.ts +40 -0
- package/dist-server/service/testing/mode-conformance.js +90 -0
- package/dist-server/service/testing/mode-conformance.js.map +1 -0
- package/dist-server/tool-registry-boot-report.d.ts +3 -0
- package/dist-server/tool-registry-boot-report.js +25 -2
- package/dist-server/tool-registry-boot-report.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/explicit-graphql-types.test.ts +56 -0
- package/server/service/assistant-capability-resolver.ts +66 -0
- package/server/service/assistant-chat-resolver.ts +184 -42
- package/server/service/assistant-mode/assistant-mode-resolver.ts +102 -0
- package/server/service/assistant-mode/index.ts +16 -0
- package/server/service/assistant-mode/registry.test.ts +105 -0
- package/server/service/assistant-mode/registry.ts +147 -0
- package/server/service/assistant-mode/resolve.test.ts +78 -0
- package/server/service/assistant-mode/resolve.ts +96 -0
- package/server/service/assistant-mode/subject-defaults.test.ts +86 -0
- package/server/service/assistant-mode/types.ts +103 -0
- package/server/service/chat-message/carried-turns.test.ts +69 -0
- package/server/service/chat-message/carried-turns.ts +99 -0
- package/server/service/chat-message/chat-message-subscription.ts +20 -4
- package/server/service/chat-message/chat-message.ts +44 -0
- package/server/service/chat-message/door-access.ts +45 -0
- package/server/service/chat-message/fold-session-history.test.ts +98 -0
- package/server/service/chat-message/fold-session-history.ts +115 -0
- package/server/service/chat-message/llm-history.test.ts +58 -7
- package/server/service/chat-message/llm-history.ts +30 -11
- package/server/service/chat-message/message-doors.test.ts +87 -0
- package/server/service/chat-message/message-doors.ts +117 -0
- package/server/service/chat-message/proposal-outcome.test.ts +48 -0
- package/server/service/chat-message/proposal-outcome.ts +42 -0
- package/server/service/chat-message/reader-gate.ts +42 -0
- package/server/service/chat-message/room-message.test.ts +21 -0
- package/server/service/chat-message/room-message.ts +22 -0
- package/server/service/chat-session/chat-session.ts +31 -1
- package/server/service/chat-session/session-inbox.test.ts +18 -0
- package/server/service/chat-session/session-inbox.ts +9 -2
- package/server/service/chat-session/session-visibility.test.ts +36 -0
- package/server/service/chat-session/session-visibility.ts +26 -0
- package/server/service/chat-session/station-session-guard.ts +10 -2
- package/server/service/chat-session-participant/mention-invite.test.ts +125 -0
- package/server/service/chat-session-participant/mention-invite.ts +121 -0
- package/server/service/chat-session-resolver.ts +272 -15
- package/server/service/grounding-sources.test.ts +55 -0
- package/server/service/grounding-sources.ts +46 -0
- package/server/service/index.ts +19 -0
- package/server/service/request-translator.test.ts +45 -0
- package/server/service/request-translator.ts +33 -0
- package/server/service/station-session-guard.test.ts +12 -5
- package/server/service/testing/conversation-scenario.test.ts +163 -0
- package/server/service/testing/conversation-script.test.ts +131 -0
- package/server/service/testing/conversation-script.ts +288 -0
- package/server/service/testing/mode-conformance.ts +107 -0
- package/server/tool-registry-boot-report.ts +25 -2
- package/test/assistant-chat-call-sites.test.ts +82 -0
- package/translations/en.json +44 -2
- package/translations/ja.json +44 -2
- package/translations/ko.json +44 -2
- package/translations/ms.json +44 -2
- package/translations/zh.json +44 -2
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ์ด ๋ต์ด ์ง๋ ๋ฌธ๋ค โ ๋ถ๋ฅธ ๋๊ตฌ๋ค์ ๋ฌธ์ ํฉ์น๋ค(์ค๋ณต ์์ด, ์ ๋ ฌ).
|
|
3
|
+
*
|
|
4
|
+
* ๋ฑ๋ก๊ธฐ์ ์๋ ๋๊ตฌ๊ฐ ๋ต์ ๋ผ๋ฉด ๊ทธ ๋๊ตฌ๊ฐ ๋ฌด์์ ์ฝ์๋์ง ์ ๊ธธ์ด ์๋ค. ๊ทธ๋ `[]`(๋๊ตฌ๋ ์ฝ๋ ๋ต)๋ก
|
|
5
|
+
* ์ ์ผ๋ฉด ๋ชจ๋ฅด๋ ๊ฐ์ด ๊ณต๊ฐ๋๋ค. ์๋ฌด๋ ๋ชป ์ง๋๋ ์ด๋ฆ์ ์ ์ด **๊ฐ๋ ค์ง๋ ์ชฝ**์ผ๋ก ๋์ด๋จ๋ฆฌ๊ณ , ์ด๋ฆ์
|
|
6
|
+
* ์์ธ์ ์ค์ด ๋๋ค.
|
|
7
|
+
*/
|
|
8
|
+
export declare function doorsForAnswer(toolNames: readonly string[], doorsOf: (name: string) => string[] | undefined): string[];
|
|
9
|
+
/**
|
|
10
|
+
* ํ ์์ฒญ ์์์ (์ฌ๋, ๋ฌธ) ๋ณ๋ก ํ ๋ฒ๋ง ๋ฌป๋ ๊ด๋ฌธ.
|
|
11
|
+
*
|
|
12
|
+
* ํ ํ๋ฉด์ด ๋ฐฑ ์ค์ ์ฝ๊ณ ๊ทธ ์ค๋ค์ด ๊ฐ์ ๋ฌธ ์๋์ ๊ฐ๋ฆฌํจ๋ค. ์ค๋ง๋ค ๋ฌผ์ผ๋ฉด ๊ถํ ์กฐํ๊ฐ ๋ฐฑ ๋ฒ ๊ฐ๋ค.
|
|
13
|
+
* ๊ฐ์ ์์ฒญ ์์์ ๋ต์ด ๋ฐ๋ ์ผ์ ์์ผ๋ฏ๋ก ๋ฌธ ํ๋์ ํ ๋ฒ ๋ฌป๊ณ ๊ทธ ๋ต์ ์ด๋ค. ๊ด๋ฌธ์ ์์ฒญ๋ง๋ค ์๋ก
|
|
14
|
+
* ๋ง๋ ๋ค โ ํ๋ก์ธ์ค๊ฐ ๋ค๊ณ ์์ผ๋ฉด ๊ถํ์ด ๋ฐ๋์ด๋ ๋ก์ ๋ต์ ์ค๋ค.
|
|
15
|
+
*/
|
|
16
|
+
export declare function doorGate(check: (door: string) => Promise<boolean>): (door: string) => Promise<boolean>;
|
|
17
|
+
/** ์ด ์ฌ๋์ด ์ด ํ์ ์ด ์ ์๋ โ ์ ํ ๋ฌธ์ **์ ๋ถ** ์ง๋์ผ ํ๋ค(AND). */
|
|
18
|
+
export declare function passesRow(doors: readonly string[] | null | undefined, gate: (door: string) => Promise<boolean>): Promise<boolean>;
|
|
19
|
+
/** ๋ฌธ ํ์ ์ ํ์ํ ๋งํผ๋ง โ ์ํฐํฐ๋ฅผ ์ด ์๋ฆฌ๋ก ๋๊ณ ์ค์ง ์๋๋ค. */
|
|
20
|
+
export interface DoorReadableRow {
|
|
21
|
+
doors?: string[] | null;
|
|
22
|
+
content?: string | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* ๋ชป ์ง๋๋ ํ์ ๊ฐ์ ๊ฐ๋ฆฐ๋ค โ ํ์ ๋จ๊ธฐ๊ณ ๋ณธ๋ฌธ์ ํ ์ค๋ก ๋ฐ๊พผ๋ค.
|
|
26
|
+
*
|
|
27
|
+
* `notice` ๋ ๋ถ๋ฅด๋ ์ชฝ์ด ๋ฒ์ญํด ๋๊ธด๋ค(์๋ฒ ๋ฒ์ญ, ํ๋ฉด ๋ง์ ์๋ฒ๊ฐ ๋ง๋ ๋ค โ ADR-0061 ๊ฒฐ์ 7).
|
|
28
|
+
*/
|
|
29
|
+
export declare function redactByDoors<T extends DoorReadableRow>(rows: readonly T[], gate: (door: string) => Promise<boolean>, notice: (doors: string[]) => string): Promise<T[]>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* ๋ต์ ์ค๋ฆฐ ๋ฌธ โ ADR-0073 ํ์ 1.
|
|
4
|
+
*
|
|
5
|
+
* โโ ๋ฌด์์ ๋ง๋๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
6
|
+
* ๋ํ๋ฐฉ์ ๋๋ฉ์ธ ์์์ ๊ณต๊ฐ๋ค(ADR-0073 ํ์ 2). ๊ทธ๋ฐ๋ฐ ๋ํ ์์๋ ์ด์์คํดํธ๊ฐ ๋๊ตฌ ๊ฒฐ๊ณผ๋ก ๊ทผ๊ฑฐ๋ฅผ
|
|
7
|
+
* ๋๊ณ ์ด ๋ต์ด ๋ค์ด ์๊ณ , ๊ทธ ๊ทผ๊ฑฐ๋ **๋ถ๋ฅธ ์ฌ๋์ ๋ฌธ**์ ์ง๋ ์ป์ ๊ฐ์ด๋ค. ๋๊ตฌ๋ ๋ฌธ์ ์ง์ผฐ๋๋ฐ
|
|
8
|
+
* ์ด์์คํดํธ์ ๋ฌธ์ฅ์ด ๊ทธ ๊ฐ์ ์ด๋ฏธ ํ๋ฌธ์ผ๋ก ์ ์ด ๋์๋ค. ๋์ค์ ์ฝ๋ ์ฌ๋์ ์๊ธฐ๊ฐ ๋ชป ์ฌ๋ ๋ฌธ ๋๋จธ์
|
|
9
|
+
* ๊ฐ์ ์ด์์คํดํธ์ ๋ง๋ก ์ฝ๋๋ค โ ๋๊ตฌ ๊ถํ์ ๋ค ์ง์ผ๋ **๊ธ๋ก ์๋ ๊ธธ**์ด๋ค.
|
|
10
|
+
*
|
|
11
|
+
* ๊ทธ๋์ ๋ต ํ์ ๊ทธ ๋ต์ ๋ง๋ ๋๊ตฌ๋ค์ด ์ง๋ ๋ฌธ ๋ชฉ๋ก์ ์ ์ด ๋๊ณ (์ฌ๋์ ๋ง์ `[]`), ์ฝ๋ ์ฌ๋์ด ๊ทธ ๋ฌธ์
|
|
12
|
+
* ์ ๋ถ ์ง๋๋์ง ๋ณผ ๋๋ง๋ค ํ์ธํ๋ค. ๋ชป ์ง๋๋ฉด ๋ณธ๋ฌธ ๋์ ํ ์ค์ด ๋๊ฐ๋ค โ **ํ์ด ์๋ค๋ ์ฌ์ค์ ๋ณด์ด๊ณ
|
|
13
|
+
* ๊ฐ๋ง ์ ๋ณด์ธ๋ค.** ๋ฐฉ์ ๋ฌด์จ ์ผ์ด ์์๋์ง๋ ์ ์ ์๊ณ , ๊ฐ์ ์๊ธฐ ๊ถํ๋งํผ๋ง ์ฝ๋๋ค.
|
|
14
|
+
*
|
|
15
|
+
* โโ ์์ ์ ๋ป์ด ์๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
16
|
+
* ์ธ์ ๋ค์ด์๋์ง๋ก ๊ฐ๋ฅด์ง ์๋๋ค. ์ค์ ์ ์์๋ ๋ฐฉ๊ธ ๋ค์ด์๋ , ๋ณผ ์ ์๋ ๊ฒ์ ๋ณธ๋ค. ๊ถํ์ด ๋์ค์
|
|
17
|
+
* ๋ถ์ผ๋ฉด ๊ทธ๋๋ถํฐ ๋ณด์ด๊ณ , ๋จ์ด์ง๋ฉด ๊ทธ๋๋ถํฐ ์ ๋ณด์ธ๋ค. ์ ์ฅ๋ ํ์ ๊ทธ๋๋ก ์๊ณ **๋ณด๋ ์ผ๋ง** ๋ฌ๋ผ์ง๋ค.
|
|
18
|
+
*
|
|
19
|
+
* โโ ๋ชจ๋ธ์ด ์ฝ๋ ์ด๋ ฅ๋ ๊ฐ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
20
|
+
* ๋ถ๋ฅธ ์ฌ๋์ด ๋ชป ์ฌ๋ ๋ฌธ์ ๋ต์ ๋ชจ๋ธ์๊ฒ๋ ๊ฐ๋ฆฌ๊ณ ๋ณด๋ธ๋ค. ๊ฐ๋ฆฌ์ง ์์ผ๋ฉด ๋ชจ๋ธ์ด ๊ทธ ๊ฐ์ ๋ค์ ๋ต์ ์ฎ๊ฒจ
|
|
21
|
+
* ์ ์ด์, ๋ฌธ์ ํ ๋ฒ๋ ์ ์ง๋ ์ฌ๋์ด ๊ฐ์ ๊ฐ๊ฒ ๋๋ค. ๊ฐ๋ฆฐ ์๋ฆฌ๋ฅผ ์ง์ฐ์ง ์๊ณ ํ ์ค๋ก ๋จ๊ธฐ๋ ์ด์ ๋
|
|
22
|
+
* ๊ฐ๋ค โ ๋ชจ๋ธ์ด "๊ทธ๋ฐ ๋ง ํ ์ ์๋ค"๊ณ ๋ตํ๋ฉด ๊ทธ๊ฒ์ ๊ฑฐ์ง๋ง์ด๋ค.
|
|
23
|
+
*
|
|
24
|
+
* ์ด ํ์ผ์ ์ ์ฅ์ยท์ํฐํฐ๋ฅผ ๋ชจ๋ฅด๋ ์์ ํ์ ์ด๋ค.
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.doorsForAnswer = doorsForAnswer;
|
|
28
|
+
exports.doorGate = doorGate;
|
|
29
|
+
exports.passesRow = passesRow;
|
|
30
|
+
exports.redactByDoors = redactByDoors;
|
|
31
|
+
/** ๋ฌธ ์ด๋ฆ์ผ๋ก ๋ณด์ด์ง ์๋ ๊ฐ โ ๋ฑ๋ก๋์ง ์์ ๋๊ตฌ๊ฐ ๋ต์ ๋ผ์์ ๋. */
|
|
32
|
+
const UNRESOLVED = 'unresolved:';
|
|
33
|
+
/**
|
|
34
|
+
* ์ด ๋ต์ด ์ง๋ ๋ฌธ๋ค โ ๋ถ๋ฅธ ๋๊ตฌ๋ค์ ๋ฌธ์ ํฉ์น๋ค(์ค๋ณต ์์ด, ์ ๋ ฌ).
|
|
35
|
+
*
|
|
36
|
+
* ๋ฑ๋ก๊ธฐ์ ์๋ ๋๊ตฌ๊ฐ ๋ต์ ๋ผ๋ฉด ๊ทธ ๋๊ตฌ๊ฐ ๋ฌด์์ ์ฝ์๋์ง ์ ๊ธธ์ด ์๋ค. ๊ทธ๋ `[]`(๋๊ตฌ๋ ์ฝ๋ ๋ต)๋ก
|
|
37
|
+
* ์ ์ผ๋ฉด ๋ชจ๋ฅด๋ ๊ฐ์ด ๊ณต๊ฐ๋๋ค. ์๋ฌด๋ ๋ชป ์ง๋๋ ์ด๋ฆ์ ์ ์ด **๊ฐ๋ ค์ง๋ ์ชฝ**์ผ๋ก ๋์ด๋จ๋ฆฌ๊ณ , ์ด๋ฆ์
|
|
38
|
+
* ์์ธ์ ์ค์ด ๋๋ค.
|
|
39
|
+
*/
|
|
40
|
+
function doorsForAnswer(toolNames, doorsOf) {
|
|
41
|
+
const doors = new Set();
|
|
42
|
+
for (const name of toolNames) {
|
|
43
|
+
const declared = doorsOf(name);
|
|
44
|
+
if (declared === undefined)
|
|
45
|
+
doors.add(`${UNRESOLVED}${name}`);
|
|
46
|
+
else
|
|
47
|
+
for (const door of declared)
|
|
48
|
+
doors.add(door);
|
|
49
|
+
}
|
|
50
|
+
return [...doors].sort();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* ํ ์์ฒญ ์์์ (์ฌ๋, ๋ฌธ) ๋ณ๋ก ํ ๋ฒ๋ง ๋ฌป๋ ๊ด๋ฌธ.
|
|
54
|
+
*
|
|
55
|
+
* ํ ํ๋ฉด์ด ๋ฐฑ ์ค์ ์ฝ๊ณ ๊ทธ ์ค๋ค์ด ๊ฐ์ ๋ฌธ ์๋์ ๊ฐ๋ฆฌํจ๋ค. ์ค๋ง๋ค ๋ฌผ์ผ๋ฉด ๊ถํ ์กฐํ๊ฐ ๋ฐฑ ๋ฒ ๊ฐ๋ค.
|
|
56
|
+
* ๊ฐ์ ์์ฒญ ์์์ ๋ต์ด ๋ฐ๋ ์ผ์ ์์ผ๋ฏ๋ก ๋ฌธ ํ๋์ ํ ๋ฒ ๋ฌป๊ณ ๊ทธ ๋ต์ ์ด๋ค. ๊ด๋ฌธ์ ์์ฒญ๋ง๋ค ์๋ก
|
|
57
|
+
* ๋ง๋ ๋ค โ ํ๋ก์ธ์ค๊ฐ ๋ค๊ณ ์์ผ๋ฉด ๊ถํ์ด ๋ฐ๋์ด๋ ๋ก์ ๋ต์ ์ค๋ค.
|
|
58
|
+
*/
|
|
59
|
+
function doorGate(check) {
|
|
60
|
+
const asked = new Map();
|
|
61
|
+
return (door) => {
|
|
62
|
+
/* ๋ฑ๋ก๋์ง ์์ ๋๊ตฌ์ ์๋ฆฌ๋ ๋ฌผ์ ๊ฒ๋ ์๋ค โ ์ง๋๋ ์ฌ๋์ด ์๋ค. */
|
|
63
|
+
if (door.startsWith(UNRESOLVED))
|
|
64
|
+
return Promise.resolve(false);
|
|
65
|
+
let answer = asked.get(door);
|
|
66
|
+
if (!answer) {
|
|
67
|
+
answer = check(door);
|
|
68
|
+
asked.set(door, answer);
|
|
69
|
+
}
|
|
70
|
+
return answer;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** ์ด ์ฌ๋์ด ์ด ํ์ ์ด ์ ์๋ โ ์ ํ ๋ฌธ์ **์ ๋ถ** ์ง๋์ผ ํ๋ค(AND). */
|
|
74
|
+
async function passesRow(doors, gate) {
|
|
75
|
+
for (const door of doors ?? []) {
|
|
76
|
+
if (!(await gate(door)))
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
/** ๊ฐ๋ฆฐ ํ์์ ๊ฐ์ด ์ค๋ ค ์๋ ์นธ๋ค โ ๋ณธ๋ฌธ๋ง ์ง์ฐ๊ณ ๋๋ฉด ๊ทธ๋ฆฌ๋ก ์์ด ๋๊ฐ๋ค. */
|
|
82
|
+
const VALUE_CARRYING = ['extra', 'proposals', 'grounding', 'patchEntryId', 'importSessionId'];
|
|
83
|
+
/**
|
|
84
|
+
* ๋ชป ์ง๋๋ ํ์ ๊ฐ์ ๊ฐ๋ฆฐ๋ค โ ํ์ ๋จ๊ธฐ๊ณ ๋ณธ๋ฌธ์ ํ ์ค๋ก ๋ฐ๊พผ๋ค.
|
|
85
|
+
*
|
|
86
|
+
* `notice` ๋ ๋ถ๋ฅด๋ ์ชฝ์ด ๋ฒ์ญํด ๋๊ธด๋ค(์๋ฒ ๋ฒ์ญ, ํ๋ฉด ๋ง์ ์๋ฒ๊ฐ ๋ง๋ ๋ค โ ADR-0061 ๊ฒฐ์ 7).
|
|
87
|
+
*/
|
|
88
|
+
async function redactByDoors(rows, gate, notice) {
|
|
89
|
+
const out = [];
|
|
90
|
+
for (const row of rows) {
|
|
91
|
+
const doors = row.doors ?? [];
|
|
92
|
+
if (doors.length === 0 || (await passesRow(doors, gate))) {
|
|
93
|
+
out.push(row);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const hidden = { ...row, content: notice(doors) };
|
|
97
|
+
for (const field of VALUE_CARRYING) {
|
|
98
|
+
if (field in hidden)
|
|
99
|
+
hidden[field] = null;
|
|
100
|
+
}
|
|
101
|
+
/* ๊ฐ๋ ค์ก๋ค๋ ๊ฒ ์์ฒด๋ ์ฌ์ค์ด๋ค. ํ๋ฉด์ด ์๋ฌผ์ ๋ฅผ ๊ทธ๋ฆด ์ ์๊ฒ ๋จ๊ธด๋ค. */
|
|
102
|
+
hidden.redacted = true;
|
|
103
|
+
out.push(hidden);
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=message-doors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-doors.js","sourceRoot":"","sources":["../../../server/service/chat-message/message-doors.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;AAYH,wCAUC;AASD,4BAcC;AAGD,8BAKC;AAgBD,sCAwBC;AA3FD,8CAA8C;AAC9C,MAAM,UAAU,GAAG,aAAa,CAAA;AAEhC;;;;;;GAMG;AACH,SAAgB,cAAc,CAAC,SAA4B,EAAE,OAA+C;IAC1G,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAA;IAE/B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QAC9B,IAAI,QAAQ,KAAK,SAAS;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,GAAG,IAAI,EAAE,CAAC,CAAA;;YACxD,KAAK,MAAM,IAAI,IAAI,QAAQ;gBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnD,CAAC;IAED,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAA;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,QAAQ,CAAC,KAAyC;IAChE,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAA;IAEjD,OAAO,CAAC,IAAY,EAAE,EAAE;QACtB,4CAA4C;QAC5C,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAE9D,IAAI,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;YACpB,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;AACH,CAAC;AAED,oDAAoD;AAC7C,KAAK,UAAU,SAAS,CAAC,KAA2C,EAAE,IAAwC;IACnH,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAC/B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO,KAAK,CAAA;IACvC,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAQD,kDAAkD;AAClD,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,CAAU,CAAA;AAEtG;;;;GAIG;AACI,KAAK,UAAU,aAAa,CACjC,IAAkB,EAClB,IAAwC,EACxC,MAAmC;IAEnC,MAAM,GAAG,GAAQ,EAAE,CAAA;IAEnB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAA;QAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YACzD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACb,SAAQ;QACV,CAAC;QAED,MAAM,MAAM,GAAQ,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAA;QACtD,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,IAAI,KAAK,IAAI,MAAM;gBAAE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;QAC3C,CAAC;QACD,6CAA6C;QAC7C,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAA;QACtB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAClB,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC","sourcesContent":["/*\n * ๋ต์ ์ค๋ฆฐ ๋ฌธ โ ADR-0073 ํ์ 1.\n *\n * โโ ๋ฌด์์ ๋ง๋๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ํ๋ฐฉ์ ๋๋ฉ์ธ ์์์ ๊ณต๊ฐ๋ค(ADR-0073 ํ์ 2). ๊ทธ๋ฐ๋ฐ ๋ํ ์์๋ ์ด์์คํดํธ๊ฐ ๋๊ตฌ ๊ฒฐ๊ณผ๋ก ๊ทผ๊ฑฐ๋ฅผ\n * ๋๊ณ ์ด ๋ต์ด ๋ค์ด ์๊ณ , ๊ทธ ๊ทผ๊ฑฐ๋ **๋ถ๋ฅธ ์ฌ๋์ ๋ฌธ**์ ์ง๋ ์ป์ ๊ฐ์ด๋ค. ๋๊ตฌ๋ ๋ฌธ์ ์ง์ผฐ๋๋ฐ\n * ์ด์์คํดํธ์ ๋ฌธ์ฅ์ด ๊ทธ ๊ฐ์ ์ด๋ฏธ ํ๋ฌธ์ผ๋ก ์ ์ด ๋์๋ค. ๋์ค์ ์ฝ๋ ์ฌ๋์ ์๊ธฐ๊ฐ ๋ชป ์ฌ๋ ๋ฌธ ๋๋จธ์\n * ๊ฐ์ ์ด์์คํดํธ์ ๋ง๋ก ์ฝ๋๋ค โ ๋๊ตฌ ๊ถํ์ ๋ค ์ง์ผ๋ **๊ธ๋ก ์๋ ๊ธธ**์ด๋ค.\n *\n * ๊ทธ๋์ ๋ต ํ์ ๊ทธ ๋ต์ ๋ง๋ ๋๊ตฌ๋ค์ด ์ง๋ ๋ฌธ ๋ชฉ๋ก์ ์ ์ด ๋๊ณ (์ฌ๋์ ๋ง์ `[]`), ์ฝ๋ ์ฌ๋์ด ๊ทธ ๋ฌธ์\n * ์ ๋ถ ์ง๋๋์ง ๋ณผ ๋๋ง๋ค ํ์ธํ๋ค. ๋ชป ์ง๋๋ฉด ๋ณธ๋ฌธ ๋์ ํ ์ค์ด ๋๊ฐ๋ค โ **ํ์ด ์๋ค๋ ์ฌ์ค์ ๋ณด์ด๊ณ \n * ๊ฐ๋ง ์ ๋ณด์ธ๋ค.** ๋ฐฉ์ ๋ฌด์จ ์ผ์ด ์์๋์ง๋ ์ ์ ์๊ณ , ๊ฐ์ ์๊ธฐ ๊ถํ๋งํผ๋ง ์ฝ๋๋ค.\n *\n * โโ ์์ ์ ๋ป์ด ์๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ธ์ ๋ค์ด์๋์ง๋ก ๊ฐ๋ฅด์ง ์๋๋ค. ์ค์ ์ ์์๋ ๋ฐฉ๊ธ ๋ค์ด์๋ , ๋ณผ ์ ์๋ ๊ฒ์ ๋ณธ๋ค. ๊ถํ์ด ๋์ค์\n * ๋ถ์ผ๋ฉด ๊ทธ๋๋ถํฐ ๋ณด์ด๊ณ , ๋จ์ด์ง๋ฉด ๊ทธ๋๋ถํฐ ์ ๋ณด์ธ๋ค. ์ ์ฅ๋ ํ์ ๊ทธ๋๋ก ์๊ณ **๋ณด๋ ์ผ๋ง** ๋ฌ๋ผ์ง๋ค.\n *\n * โโ ๋ชจ๋ธ์ด ์ฝ๋ ์ด๋ ฅ๋ ๊ฐ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ถ๋ฅธ ์ฌ๋์ด ๋ชป ์ฌ๋ ๋ฌธ์ ๋ต์ ๋ชจ๋ธ์๊ฒ๋ ๊ฐ๋ฆฌ๊ณ ๋ณด๋ธ๋ค. ๊ฐ๋ฆฌ์ง ์์ผ๋ฉด ๋ชจ๋ธ์ด ๊ทธ ๊ฐ์ ๋ค์ ๋ต์ ์ฎ๊ฒจ\n * ์ ์ด์, ๋ฌธ์ ํ ๋ฒ๋ ์ ์ง๋ ์ฌ๋์ด ๊ฐ์ ๊ฐ๊ฒ ๋๋ค. ๊ฐ๋ฆฐ ์๋ฆฌ๋ฅผ ์ง์ฐ์ง ์๊ณ ํ ์ค๋ก ๋จ๊ธฐ๋ ์ด์ ๋\n * ๊ฐ๋ค โ ๋ชจ๋ธ์ด \"๊ทธ๋ฐ ๋ง ํ ์ ์๋ค\"๊ณ ๋ตํ๋ฉด ๊ทธ๊ฒ์ ๊ฑฐ์ง๋ง์ด๋ค.\n *\n * ์ด ํ์ผ์ ์ ์ฅ์ยท์ํฐํฐ๋ฅผ ๋ชจ๋ฅด๋ ์์ ํ์ ์ด๋ค.\n */\n\n/** ๋ฌธ ์ด๋ฆ์ผ๋ก ๋ณด์ด์ง ์๋ ๊ฐ โ ๋ฑ๋ก๋์ง ์์ ๋๊ตฌ๊ฐ ๋ต์ ๋ผ์์ ๋. */\nconst UNRESOLVED = 'unresolved:'\n\n/**\n * ์ด ๋ต์ด ์ง๋ ๋ฌธ๋ค โ ๋ถ๋ฅธ ๋๊ตฌ๋ค์ ๋ฌธ์ ํฉ์น๋ค(์ค๋ณต ์์ด, ์ ๋ ฌ).\n *\n * ๋ฑ๋ก๊ธฐ์ ์๋ ๋๊ตฌ๊ฐ ๋ต์ ๋ผ๋ฉด ๊ทธ ๋๊ตฌ๊ฐ ๋ฌด์์ ์ฝ์๋์ง ์ ๊ธธ์ด ์๋ค. ๊ทธ๋ `[]`(๋๊ตฌ๋ ์ฝ๋ ๋ต)๋ก\n * ์ ์ผ๋ฉด ๋ชจ๋ฅด๋ ๊ฐ์ด ๊ณต๊ฐ๋๋ค. ์๋ฌด๋ ๋ชป ์ง๋๋ ์ด๋ฆ์ ์ ์ด **๊ฐ๋ ค์ง๋ ์ชฝ**์ผ๋ก ๋์ด๋จ๋ฆฌ๊ณ , ์ด๋ฆ์\n * ์์ธ์ ์ค์ด ๋๋ค.\n */\nexport function doorsForAnswer(toolNames: readonly string[], doorsOf: (name: string) => string[] | undefined): string[] {\n const doors = new Set<string>()\n\n for (const name of toolNames) {\n const declared = doorsOf(name)\n if (declared === undefined) doors.add(`${UNRESOLVED}${name}`)\n else for (const door of declared) doors.add(door)\n }\n\n return [...doors].sort()\n}\n\n/**\n * ํ ์์ฒญ ์์์ (์ฌ๋, ๋ฌธ) ๋ณ๋ก ํ ๋ฒ๋ง ๋ฌป๋ ๊ด๋ฌธ.\n *\n * ํ ํ๋ฉด์ด ๋ฐฑ ์ค์ ์ฝ๊ณ ๊ทธ ์ค๋ค์ด ๊ฐ์ ๋ฌธ ์๋์ ๊ฐ๋ฆฌํจ๋ค. ์ค๋ง๋ค ๋ฌผ์ผ๋ฉด ๊ถํ ์กฐํ๊ฐ ๋ฐฑ ๋ฒ ๊ฐ๋ค.\n * ๊ฐ์ ์์ฒญ ์์์ ๋ต์ด ๋ฐ๋ ์ผ์ ์์ผ๋ฏ๋ก ๋ฌธ ํ๋์ ํ ๋ฒ ๋ฌป๊ณ ๊ทธ ๋ต์ ์ด๋ค. ๊ด๋ฌธ์ ์์ฒญ๋ง๋ค ์๋ก\n * ๋ง๋ ๋ค โ ํ๋ก์ธ์ค๊ฐ ๋ค๊ณ ์์ผ๋ฉด ๊ถํ์ด ๋ฐ๋์ด๋ ๋ก์ ๋ต์ ์ค๋ค.\n */\nexport function doorGate(check: (door: string) => Promise<boolean>): (door: string) => Promise<boolean> {\n const asked = new Map<string, Promise<boolean>>()\n\n return (door: string) => {\n /* ๋ฑ๋ก๋์ง ์์ ๋๊ตฌ์ ์๋ฆฌ๋ ๋ฌผ์ ๊ฒ๋ ์๋ค โ ์ง๋๋ ์ฌ๋์ด ์๋ค. */\n if (door.startsWith(UNRESOLVED)) return Promise.resolve(false)\n\n let answer = asked.get(door)\n if (!answer) {\n answer = check(door)\n asked.set(door, answer)\n }\n return answer\n }\n}\n\n/** ์ด ์ฌ๋์ด ์ด ํ์ ์ด ์ ์๋ โ ์ ํ ๋ฌธ์ **์ ๋ถ** ์ง๋์ผ ํ๋ค(AND). */\nexport async function passesRow(doors: readonly string[] | null | undefined, gate: (door: string) => Promise<boolean>): Promise<boolean> {\n for (const door of doors ?? []) {\n if (!(await gate(door))) return false\n }\n return true\n}\n\n/** ๋ฌธ ํ์ ์ ํ์ํ ๋งํผ๋ง โ ์ํฐํฐ๋ฅผ ์ด ์๋ฆฌ๋ก ๋๊ณ ์ค์ง ์๋๋ค. */\nexport interface DoorReadableRow {\n doors?: string[] | null\n content?: string | null\n}\n\n/** ๊ฐ๋ฆฐ ํ์์ ๊ฐ์ด ์ค๋ ค ์๋ ์นธ๋ค โ ๋ณธ๋ฌธ๋ง ์ง์ฐ๊ณ ๋๋ฉด ๊ทธ๋ฆฌ๋ก ์์ด ๋๊ฐ๋ค. */\nconst VALUE_CARRYING = ['extra', 'proposals', 'grounding', 'patchEntryId', 'importSessionId'] as const\n\n/**\n * ๋ชป ์ง๋๋ ํ์ ๊ฐ์ ๊ฐ๋ฆฐ๋ค โ ํ์ ๋จ๊ธฐ๊ณ ๋ณธ๋ฌธ์ ํ ์ค๋ก ๋ฐ๊พผ๋ค.\n *\n * `notice` ๋ ๋ถ๋ฅด๋ ์ชฝ์ด ๋ฒ์ญํด ๋๊ธด๋ค(์๋ฒ ๋ฒ์ญ, ํ๋ฉด ๋ง์ ์๋ฒ๊ฐ ๋ง๋ ๋ค โ ADR-0061 ๊ฒฐ์ 7).\n */\nexport async function redactByDoors<T extends DoorReadableRow>(\n rows: readonly T[],\n gate: (door: string) => Promise<boolean>,\n notice: (doors: string[]) => string\n): Promise<T[]> {\n const out: T[] = []\n\n for (const row of rows) {\n const doors = row.doors ?? []\n if (doors.length === 0 || (await passesRow(doors, gate))) {\n out.push(row)\n continue\n }\n\n const hidden: any = { ...row, content: notice(doors) }\n for (const field of VALUE_CARRYING) {\n if (field in hidden) hidden[field] = null\n }\n /* ๊ฐ๋ ค์ก๋ค๋ ๊ฒ ์์ฒด๋ ์ฌ์ค์ด๋ค. ํ๋ฉด์ด ์๋ฌผ์ ๋ฅผ ๊ทธ๋ฆด ์ ์๊ฒ ๋จ๊ธด๋ค. */\n hidden.redacted = true\n out.push(hidden)\n }\n\n return out\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** ADR-0042's verdicts, plus the one for a person who backed out at the confirm step. */
|
|
2
|
+
export type ProposalVerdict = 'accepted' | 'refused' | 'unavailable' | 'declined';
|
|
3
|
+
export interface ProposalOutcome {
|
|
4
|
+
verdict: ProposalVerdict;
|
|
5
|
+
/** The host's own reason code, carried through untouched โ no mapping table (ADR-0042). */
|
|
6
|
+
errorCode?: string;
|
|
7
|
+
/** For a proposal made of several edits: how many went in, and how many did not. */
|
|
8
|
+
applied?: number;
|
|
9
|
+
missed?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const PROPOSAL_OUTCOME_PREFIX = "proposal ";
|
|
12
|
+
export declare const PROPOSAL_VERDICTS: ProposalVerdict[];
|
|
13
|
+
/**
|
|
14
|
+
* `proposal <key>: <verdict> (<errorCode>) 2/3`
|
|
15
|
+
*
|
|
16
|
+
* English, like the other lines the model reads. The panel turns it into the reader's language.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatProposalOutcomeLine(key: string, outcome: ProposalOutcome): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* What the host did with a proposal, written into the conversation (ADR-0070 A12-a).
|
|
4
|
+
*
|
|
5
|
+
* The card used to change to "executed" the moment it was pressed, which is the one thing it knew
|
|
6
|
+
* and the one thing that is not the answer. The host's answer comes back through a server door and
|
|
7
|
+
* is stored as a `system` row, so three readers get it from the same place: the card that is open,
|
|
8
|
+
* the card after a refresh, and the model on its next turn โ a model that is not told its proposal
|
|
9
|
+
* was refused goes on as though it had been applied.
|
|
10
|
+
*
|
|
11
|
+
* The line is the row's content. It is parsed back by the panel, so the shape is fixed here and the
|
|
12
|
+
* panel's parser is tested against this formatter.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PROPOSAL_VERDICTS = exports.PROPOSAL_OUTCOME_PREFIX = void 0;
|
|
16
|
+
exports.formatProposalOutcomeLine = formatProposalOutcomeLine;
|
|
17
|
+
exports.PROPOSAL_OUTCOME_PREFIX = 'proposal ';
|
|
18
|
+
exports.PROPOSAL_VERDICTS = ['accepted', 'refused', 'unavailable', 'declined'];
|
|
19
|
+
/**
|
|
20
|
+
* `proposal <key>: <verdict> (<errorCode>) 2/3`
|
|
21
|
+
*
|
|
22
|
+
* English, like the other lines the model reads. The panel turns it into the reader's language.
|
|
23
|
+
*/
|
|
24
|
+
function formatProposalOutcomeLine(key, outcome) {
|
|
25
|
+
const reason = outcome.errorCode ? ` (${outcome.errorCode})` : '';
|
|
26
|
+
const counted = typeof outcome.applied === 'number' || typeof outcome.missed === 'number'
|
|
27
|
+
? ` ${outcome.applied ?? 0}/${(outcome.applied ?? 0) + (outcome.missed ?? 0)}`
|
|
28
|
+
: '';
|
|
29
|
+
return `${exports.PROPOSAL_OUTCOME_PREFIX}${key}: ${outcome.verdict}${reason}${counted}`;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=proposal-outcome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-outcome.js","sourceRoot":"","sources":["../../../server/service/chat-message/proposal-outcome.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAuBH,8DAOC;AAhBY,QAAA,uBAAuB,GAAG,WAAW,CAAA;AAErC,QAAA,iBAAiB,GAAsB,CAAC,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,CAAC,CAAA;AAEtG;;;;GAIG;AACH,SAAgB,yBAAyB,CAAC,GAAW,EAAE,OAAwB;IAC7E,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IACjE,MAAM,OAAO,GACX,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;QACvE,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE;QAC9E,CAAC,CAAC,EAAE,CAAA;IACR,OAAO,GAAG,+BAAuB,GAAG,GAAG,KAAK,OAAO,CAAC,OAAO,GAAG,MAAM,GAAG,OAAO,EAAE,CAAA;AAClF,CAAC","sourcesContent":["/*\n * What the host did with a proposal, written into the conversation (ADR-0070 A12-a).\n *\n * The card used to change to \"executed\" the moment it was pressed, which is the one thing it knew\n * and the one thing that is not the answer. The host's answer comes back through a server door and\n * is stored as a `system` row, so three readers get it from the same place: the card that is open,\n * the card after a refresh, and the model on its next turn โ a model that is not told its proposal\n * was refused goes on as though it had been applied.\n *\n * The line is the row's content. It is parsed back by the panel, so the shape is fixed here and the\n * panel's parser is tested against this formatter.\n */\n\n/** ADR-0042's verdicts, plus the one for a person who backed out at the confirm step. */\nexport type ProposalVerdict = 'accepted' | 'refused' | 'unavailable' | 'declined'\n\nexport interface ProposalOutcome {\n verdict: ProposalVerdict\n /** The host's own reason code, carried through untouched โ no mapping table (ADR-0042). */\n errorCode?: string\n /** For a proposal made of several edits: how many went in, and how many did not. */\n applied?: number\n missed?: number\n}\n\nexport const PROPOSAL_OUTCOME_PREFIX = 'proposal '\n\nexport const PROPOSAL_VERDICTS: ProposalVerdict[] = ['accepted', 'refused', 'unavailable', 'declined']\n\n/**\n * `proposal <key>: <verdict> (<errorCode>) 2/3`\n *\n * English, like the other lines the model reads. The panel turns it into the reader's language.\n */\nexport function formatProposalOutcomeLine(key: string, outcome: ProposalOutcome): string {\n const reason = outcome.errorCode ? ` (${outcome.errorCode})` : ''\n const counted =\n typeof outcome.applied === 'number' || typeof outcome.missed === 'number'\n ? ` ${outcome.applied ?? 0}/${(outcome.applied ?? 0) + (outcome.missed ?? 0)}`\n : ''\n return `${PROPOSAL_OUTCOME_PREFIX}${key}: ${outcome.verdict}${reason}${counted}`\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readerGate = readerGate;
|
|
4
|
+
/*
|
|
5
|
+
* ์ฝ๋ ์ฌ๋์ ๊ด๋ฌธ โ ADR-0073 ํ์ 1ยท2 ๋ฅผ ์์ฒญ ํ๋์ ์ธ์ด๋ค.
|
|
6
|
+
*
|
|
7
|
+
* ๋ฆฌ์กธ๋ฒ๋ ์ด๊ฒ์ ํ ๋ฒ ๋ง๋ค๊ณ ํ ๋ชฉ๋ก์ ํต๊ณผ์ํจ๋ค. ๋ฌธ ํ์ ์ (์ฌ๋, ๋ฌธ) ๋ณ๋ก ํ ๋ฒ๋ง ์ผ์ด๋๊ณ ,
|
|
8
|
+
* ์ธ์
์ด private ์ธ์ง๋ ์ฌ๊ธฐ์ ํจ๊ป ๋ตํ๋ค. ๋ฆฌ์กธ๋ฒ๋ง๋ค ๊ฐ์ ํ์ ์ ๋ค์ ์ ์ผ๋ฉด ํ ๊ณณ์ด ๋น ์ง ๋
|
|
9
|
+
* ๊ทธ ๋ฌธ์ผ๋ก ์๋ค.
|
|
10
|
+
*/
|
|
11
|
+
const ai_client_base_1 = require("@things-factory/ai-client-base");
|
|
12
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
13
|
+
const door_access_js_1 = require("./door-access.js");
|
|
14
|
+
const message_doors_js_1 = require("./message-doors.js");
|
|
15
|
+
const request_translator_js_1 = require("../request-translator.js");
|
|
16
|
+
/** ์ด ์์ฒญ์์ ํ์ ๊ฐ๋ ค ๋ด๋ณด๋ด๋ ํจ์. ๊ฐ์ ์์ฒญ ์์์ ๊ณ์ ์ด๋ค. */
|
|
17
|
+
function readerGate(context) {
|
|
18
|
+
const { domain, user } = context.state;
|
|
19
|
+
const t = (0, request_translator_js_1.requestTranslator)(context);
|
|
20
|
+
const gate = (0, message_doors_js_1.doorGate)((0, door_access_js_1.doorCheck)({
|
|
21
|
+
specs: (0, ai_client_base_1.getAllToolSpecs)(),
|
|
22
|
+
hasPrivilege: privilege => auth_base_1.User.hasPrivilege(privilege.privilege, privilege.category, domain, user)
|
|
23
|
+
}));
|
|
24
|
+
/*
|
|
25
|
+
* ๋ฌธ ์ด๋ฆ(`Query.productionReports`)์ ์ด ๋ฌธ์ฅ์ ๋ฃ์ง ์๋๋ค.
|
|
26
|
+
*
|
|
27
|
+
* ํ์ฅ์์ ์ฝ๋ ์ฌ๋์๊ฒ GraphQL ์ด๋ฆ์ ์๋ฌด ๋ง๋ ์๋๋ค. ๋ฌธ ์ด๋ฆ์ ์ฌ๋์ ๋ง๋ก ๋ฐ๊ฟ ํ๋ AUTH ์
|
|
28
|
+
* ํ๋โ๊ถํ ํ์ ๊ฐ์ ์๋ฆฌ์์ ๋์์ผ ํ๊ณ , ๊ทธ๊ฒ์ ์์ง ์๋ค(ADR-0072 ๊ฒฐ์ 2 (b)). ์๋ ํ๋ฅผ ํ๋ด
|
|
29
|
+
* ๋ด๋๋ ๋ฌธ์ฅ์ ์ฌ์ค๋ง ๋งํ๊ณ , ๋ชฉ๋ก์ `ChatMessage.doors` ๋ก ๋ฐ๋ก ๋๊ฐ๋ค โ ๊ด๋ฆฌ์์๊ฒ ๋ฌด์์
|
|
30
|
+
* ์ฒญํ ์ง ์์์ผ ํ๋ ํ๋ฉด์ ๊ฑฐ๊ธฐ์ ์ฝ๋๋ค. ๋ฌธ๊ตฌ๋ UX ๋ ์ธ์ด ์ ํ๋ค.
|
|
31
|
+
*/
|
|
32
|
+
return rows => (0, message_doors_js_1.redactByDoors)(rows, gate, () => t('ai-assistant.text.answer-needs-permission', {
|
|
33
|
+
/* ๊ตฌ๋
์๋ ์์ฒญ ๋ฒ์ญ๊ธฐ๊ฐ ์๋ค โ `request-translator.ts` ์ฐธ์กฐ. */
|
|
34
|
+
defaultValue: 'you do not have permission to see this answer. ask an administrator for access.'
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=reader-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader-gate.js","sourceRoot":"","sources":["../../../server/service/chat-message/reader-gate.ts"],"names":[],"mappings":";;AAeA,gCA0BC;AAzCD;;;;;;GAMG;AACH,mEAAgE;AAChE,yDAAgD;AAEhD,qDAA4C;AAC5C,yDAAkF;AAClF,oEAA4D;AAE5D,6CAA6C;AAC7C,SAAgB,UAAU,CAAC,OAAY;IACrC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IACtC,MAAM,CAAC,GAAG,IAAA,yCAAiB,EAAC,OAAO,CAAC,CAAA;IAEpC,MAAM,IAAI,GAAG,IAAA,2BAAQ,EACnB,IAAA,0BAAS,EAAC;QACR,KAAK,EAAE,IAAA,gCAAe,GAAE;QACxB,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC,gBAAI,CAAC,YAAY,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC;KACpG,CAAC,CACH,CAAA;IAED;;;;;;;OAOG;IACH,OAAO,IAAI,CAAC,EAAE,CACZ,IAAA,gCAAa,EAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAC7B,CAAC,CAAC,2CAA2C,EAAE;QAC7C,mDAAmD;QACnD,YAAY,EAAE,iFAAiF;KAChG,CAAC,CACH,CAAA;AACL,CAAC","sourcesContent":["/*\n * ์ฝ๋ ์ฌ๋์ ๊ด๋ฌธ โ ADR-0073 ํ์ 1ยท2 ๋ฅผ ์์ฒญ ํ๋์ ์ธ์ด๋ค.\n *\n * ๋ฆฌ์กธ๋ฒ๋ ์ด๊ฒ์ ํ ๋ฒ ๋ง๋ค๊ณ ํ ๋ชฉ๋ก์ ํต๊ณผ์ํจ๋ค. ๋ฌธ ํ์ ์ (์ฌ๋, ๋ฌธ) ๋ณ๋ก ํ ๋ฒ๋ง ์ผ์ด๋๊ณ ,\n * ์ธ์
์ด private ์ธ์ง๋ ์ฌ๊ธฐ์ ํจ๊ป ๋ตํ๋ค. ๋ฆฌ์กธ๋ฒ๋ง๋ค ๊ฐ์ ํ์ ์ ๋ค์ ์ ์ผ๋ฉด ํ ๊ณณ์ด ๋น ์ง ๋ \n * ๊ทธ ๋ฌธ์ผ๋ก ์๋ค.\n */\nimport { getAllToolSpecs } from '@things-factory/ai-client-base'\nimport { User } from '@things-factory/auth-base'\n\nimport { doorCheck } from './door-access.js'\nimport { doorGate, redactByDoors, type DoorReadableRow } from './message-doors.js'\nimport { requestTranslator } from '../request-translator.js'\n\n/** ์ด ์์ฒญ์์ ํ์ ๊ฐ๋ ค ๋ด๋ณด๋ด๋ ํจ์. ๊ฐ์ ์์ฒญ ์์์ ๊ณ์ ์ด๋ค. */\nexport function readerGate(context: any): <T extends DoorReadableRow>(rows: readonly T[]) => Promise<T[]> {\n const { domain, user } = context.state\n const t = requestTranslator(context)\n\n const gate = doorGate(\n doorCheck({\n specs: getAllToolSpecs(),\n hasPrivilege: privilege => User.hasPrivilege(privilege.privilege, privilege.category, domain, user)\n })\n )\n\n /*\n * ๋ฌธ ์ด๋ฆ(`Query.productionReports`)์ ์ด ๋ฌธ์ฅ์ ๋ฃ์ง ์๋๋ค.\n *\n * ํ์ฅ์์ ์ฝ๋ ์ฌ๋์๊ฒ GraphQL ์ด๋ฆ์ ์๋ฌด ๋ง๋ ์๋๋ค. ๋ฌธ ์ด๋ฆ์ ์ฌ๋์ ๋ง๋ก ๋ฐ๊ฟ ํ๋ AUTH ์\n * ํ๋โ๊ถํ ํ์ ๊ฐ์ ์๋ฆฌ์์ ๋์์ผ ํ๊ณ , ๊ทธ๊ฒ์ ์์ง ์๋ค(ADR-0072 ๊ฒฐ์ 2 (b)). ์๋ ํ๋ฅผ ํ๋ด\n * ๋ด๋๋ ๋ฌธ์ฅ์ ์ฌ์ค๋ง ๋งํ๊ณ , ๋ชฉ๋ก์ `ChatMessage.doors` ๋ก ๋ฐ๋ก ๋๊ฐ๋ค โ ๊ด๋ฆฌ์์๊ฒ ๋ฌด์์\n * ์ฒญํ ์ง ์์์ผ ํ๋ ํ๋ฉด์ ๊ฑฐ๊ธฐ์ ์ฝ๋๋ค. ๋ฌธ๊ตฌ๋ UX ๋ ์ธ์ด ์ ํ๋ค.\n */\n return rows =>\n redactByDoors(rows, gate, () =>\n t('ai-assistant.text.answer-needs-permission', {\n /* ๊ตฌ๋
์๋ ์์ฒญ ๋ฒ์ญ๊ธฐ๊ฐ ์๋ค โ `request-translator.ts` ์ฐธ์กฐ. */\n defaultValue: 'you do not have permission to see this answer. ask an administrator for access.'\n })\n )\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** How much of one turn is kept โ the same cap the carried turns use. */
|
|
2
|
+
export declare const ROOM_MESSAGE_LIMIT = 4000;
|
|
3
|
+
/** Trimmed and capped, or nothing when there is no message. */
|
|
4
|
+
export declare function roomMessageBody(content: string | undefined | null): string | undefined;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* A person saying something to the room (ADR-0070 A15).
|
|
4
|
+
*
|
|
5
|
+
* The addressee column has two values and, until this door, a screen could only produce one of
|
|
6
|
+
* them: every turn a person typed went through `assistantChat`, which means every turn was for the
|
|
7
|
+
* assistant. `room` existed only on turns carried in from somewhere else. So the half of the design
|
|
8
|
+
* that says "people also talk to each other here, and the assistant reads it as context" had no way
|
|
9
|
+
* to happen.
|
|
10
|
+
*
|
|
11
|
+
* The rule the door follows is the same one: the addressee comes from **which door was called**,
|
|
12
|
+
* never from an argument. This one is the people's door โ it stores the turn and does not call the
|
|
13
|
+
* model. Nobody is answered, and that silence is the point (A15 decision โฆ).
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.ROOM_MESSAGE_LIMIT = void 0;
|
|
17
|
+
exports.roomMessageBody = roomMessageBody;
|
|
18
|
+
/** How much of one turn is kept โ the same cap the carried turns use. */
|
|
19
|
+
exports.ROOM_MESSAGE_LIMIT = 4000;
|
|
20
|
+
/** Trimmed and capped, or nothing when there is no message. */
|
|
21
|
+
function roomMessageBody(content) {
|
|
22
|
+
const body = (content ?? '').trim().slice(0, exports.ROOM_MESSAGE_LIMIT);
|
|
23
|
+
return body || undefined;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=room-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-message.js","sourceRoot":"","sources":["../../../server/service/chat-message/room-message.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAMH,0CAGC;AAPD,yEAAyE;AAC5D,QAAA,kBAAkB,GAAG,IAAI,CAAA;AAEtC,+DAA+D;AAC/D,SAAgB,eAAe,CAAC,OAAkC;IAChE,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,0BAAkB,CAAC,CAAA;IAChE,OAAO,IAAI,IAAI,SAAS,CAAA;AAC1B,CAAC","sourcesContent":["/*\n * A person saying something to the room (ADR-0070 A15).\n *\n * The addressee column has two values and, until this door, a screen could only produce one of\n * them: every turn a person typed went through `assistantChat`, which means every turn was for the\n * assistant. `room` existed only on turns carried in from somewhere else. So the half of the design\n * that says \"people also talk to each other here, and the assistant reads it as context\" had no way\n * to happen.\n *\n * The rule the door follows is the same one: the addressee comes from **which door was called**,\n * never from an argument. This one is the people's door โ it stores the turn and does not call the\n * model. Nobody is answered, and that silence is the point (A15 decision โฆ).\n */\n\n/** How much of one turn is kept โ the same cap the carried turns use. */\nexport const ROOM_MESSAGE_LIMIT = 4000\n\n/** Trimmed and capped, or nothing when there is no message. */\nexport function roomMessageBody(content: string | undefined | null): string | undefined {\n const body = (content ?? '').trim().slice(0, ROOM_MESSAGE_LIMIT)\n return body || undefined\n}\n"]}
|
|
@@ -40,8 +40,32 @@ export declare class ChatSession {
|
|
|
40
40
|
* ๋๋ผ์ด๋ฒ ์ฐจ์ด๊ฐ ์๋ค. ๋ฉ์์ง๋ฅผ ์ ์ฅํ ๋ ํจ๊ป ๊ฐฑ์ ํ๋ค(activityPatch).
|
|
41
41
|
*/
|
|
42
42
|
lastMessageAt?: Date;
|
|
43
|
+
/**
|
|
44
|
+
* ์ด ๋ํ๋ฅผ ๋๋ฉ์ธ ์ ๋๊ตฌ๋ ์ฝ๋๊ฐ โ ADR-0073 ํ์ 2.
|
|
45
|
+
*
|
|
46
|
+
* `open` ๋๋ฉ์ธ ์์ด๋ฉด ๋๊ตฌ๋ ๋ค์ด์ ์ฝ๊ณ ๋งํ๋ค. ์ด๋ ์ ์ฐจ๋ ์๋ค.
|
|
47
|
+
* `private` ์ฐธ์ฌ์๋ง ์ฝ๋๋ค.
|
|
48
|
+
*
|
|
49
|
+
* ์ต์ปค๊ฐ ์๋ ์ธ์
(space ยท board ยท station)์ ๊ณต์ ๋ ๋ฌด์์ ๋๊ณ ํ๋ ์ด์ผ๊ธฐ์ด๋ฏ๋ก `open` ์ผ๋ก
|
|
50
|
+
* ์์ํ๋ค. ์ต์ปค๊ฐ ์๋ ์ธ์
๊ณผ **์ฎ๊ฒจ ์ ์ด ๋ง๋ ์ธ์
**์ `private` ์ผ๋ก ์์ํ๋ค โ ๊ฐ๋ฒผ์ด ์ง๋ฌธ์
|
|
51
|
+
* ์น๊ฒฉํ๋ฉด์ ์์ ๋ํ๊ฐ ์ ์ธ์
์ ์ฎ๊ฒจ ์ ํ๋๋ฐ(`appendSessionTurns`), ๊ทธ๊ฒ์ด ๊ณต๊ฐ๋ก ํ์ด๋๋ฉด
|
|
52
|
+
* ์ฌ์ ์ผ๋ก ์ค๊ฐ ์๋ฌธ์ด ์๊ธํด์ ๊ณต๊ฐ๋๋ค.
|
|
53
|
+
*
|
|
54
|
+
* owner ๊ฐ ์๋ฐฉํฅ์ผ๋ก ๋ฐ๊ฟ ์ ์๋ค. ๊ณต๊ฐ๋ก ๋ฐ๊พธ๊ธฐ ์ ์ ํ๋ฉด์ด ํ ์ค์ ๋จผ์ ๋ณด์ธ๋ค.
|
|
55
|
+
*
|
|
56
|
+
* open ์ด์ด๋ ๋ต ํ์ ๋ฌธ ํ์ (ADR-0073 ํ์ 1)์ ๊ทธ๋๋ก๋ค โ ๋ฐฉ์ ๋ค์ด์จ ๊ฒ๊ณผ ๊ฐ์ ์ฝ๋ ๊ฒ์ ๋ค๋ฅด๋ค.
|
|
57
|
+
*/
|
|
58
|
+
visibility: string;
|
|
43
59
|
/** ๋ชฉ๋ก์ ๋ณด์ฌ์ค ๋ง์ง๋ง ๋ฉ์์ง ๋ฏธ๋ฆฌ๋ณด๊ธฐ โ ๋ชฉ๋ก์์ ๋ฉ์์ง ํ
์ด๋ธ์ ๋ค์ ์ฝ์ง ์๊ธฐ ์ํด ์งง๊ฒ ์ ์ฅ. */
|
|
44
60
|
lastMessagePreview?: string;
|
|
61
|
+
/**
|
|
62
|
+
* ๊ทธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ง๋์จ ๋ฌธ โ ADR-0073 ํ์ 1.
|
|
63
|
+
*
|
|
64
|
+
* ๋ชฉ๋ก์ ๋ต์ **๋ค์ ์ฝ๋ ๋ ๋ฒ์งธ ๊ธธ**์ด๋ค. ๋ฉ์์ง ํ๋ฉด์์๋ง ๊ฐ๋ฆฌ๋ฉด ๊ฐ์ ๋ฌธ์ฅ์ด ๋ชฉ๋ก์ ๊ทธ๋๋ก ๋ฌ๋ค.
|
|
65
|
+
* ๋ฌธ์ด ๋์ด๊ณ ํ์ชฝ์ด ๋์จํ๋ฉด ๋์จํ ์ชฝ์ด ์ด๊ธด๋ค(ADR-0061 ๊ฒฐ์ 1). ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์ ์ฅํ ๋ ๊ทธ ํ์ ๋ฌธ์
|
|
66
|
+
* ํจ๊ป ์ฎ๊ฒจ ์ ๊ณ , ๋ชฉ๋ก๋ ๊ฐ์ ๊ด๋ฌธ์ ์ง๋๋ค.
|
|
67
|
+
*/
|
|
68
|
+
lastMessageDoors?: string[];
|
|
45
69
|
lastSummary?: string;
|
|
46
70
|
/**
|
|
47
71
|
* `lastSummary` ๊ฐ **์ด๋๊น์ง ๋ฎ๋์ง** โ ์ด ๋ฉ์์ง๊น์ง ์์ฝ์ ๋ฐ์๋๋ค.
|
|
@@ -90,14 +90,38 @@ tslib_1.__decorate([
|
|
|
90
90
|
(0, typeorm_1.Column)({ nullable: true }),
|
|
91
91
|
(0, type_graphql_1.Field)({ nullable: true, description: 'Timestamp of the last message in this session (denormalized for list ordering and unread comparison โ avoids per-session aggregation across the supported DB drivers).' }),
|
|
92
92
|
tslib_1.__metadata("design:type", Date
|
|
93
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* ์ด ๋ํ๋ฅผ ๋๋ฉ์ธ ์ ๋๊ตฌ๋ ์ฝ๋๊ฐ โ ADR-0073 ํ์ 2.
|
|
95
|
+
*
|
|
96
|
+
* `open` ๋๋ฉ์ธ ์์ด๋ฉด ๋๊ตฌ๋ ๋ค์ด์ ์ฝ๊ณ ๋งํ๋ค. ์ด๋ ์ ์ฐจ๋ ์๋ค.
|
|
97
|
+
* `private` ์ฐธ์ฌ์๋ง ์ฝ๋๋ค.
|
|
98
|
+
*
|
|
99
|
+
* ์ต์ปค๊ฐ ์๋ ์ธ์
(space ยท board ยท station)์ ๊ณต์ ๋ ๋ฌด์์ ๋๊ณ ํ๋ ์ด์ผ๊ธฐ์ด๋ฏ๋ก `open` ์ผ๋ก
|
|
100
|
+
* ์์ํ๋ค. ์ต์ปค๊ฐ ์๋ ์ธ์
๊ณผ **์ฎ๊ฒจ ์ ์ด ๋ง๋ ์ธ์
**์ `private` ์ผ๋ก ์์ํ๋ค โ ๊ฐ๋ฒผ์ด ์ง๋ฌธ์
|
|
101
|
+
* ์น๊ฒฉํ๋ฉด์ ์์ ๋ํ๊ฐ ์ ์ธ์
์ ์ฎ๊ฒจ ์ ํ๋๋ฐ(`appendSessionTurns`), ๊ทธ๊ฒ์ด ๊ณต๊ฐ๋ก ํ์ด๋๋ฉด
|
|
102
|
+
* ์ฌ์ ์ผ๋ก ์ค๊ฐ ์๋ฌธ์ด ์๊ธํด์ ๊ณต๊ฐ๋๋ค.
|
|
103
|
+
*
|
|
104
|
+
* owner ๊ฐ ์๋ฐฉํฅ์ผ๋ก ๋ฐ๊ฟ ์ ์๋ค. ๊ณต๊ฐ๋ก ๋ฐ๊พธ๊ธฐ ์ ์ ํ๋ฉด์ด ํ ์ค์ ๋จผ์ ๋ณด์ธ๋ค.
|
|
105
|
+
*
|
|
106
|
+
* open ์ด์ด๋ ๋ต ํ์ ๋ฌธ ํ์ (ADR-0073 ํ์ 1)์ ๊ทธ๋๋ก๋ค โ ๋ฐฉ์ ๋ค์ด์จ ๊ฒ๊ณผ ๊ฐ์ ์ฝ๋ ๊ฒ์ ๋ค๋ฅด๋ค.
|
|
107
|
+
*/
|
|
94
108
|
)
|
|
95
109
|
], ChatSession.prototype, "lastMessageAt", void 0);
|
|
110
|
+
tslib_1.__decorate([
|
|
111
|
+
(0, typeorm_1.Column)({ type: 'varchar', length: 16, default: 'open' }),
|
|
112
|
+
(0, type_graphql_1.Field)({ description: "Who may read this conversation: 'open' (anyone in the domain) or 'private' (participants only)." }),
|
|
113
|
+
tslib_1.__metadata("design:type", String)
|
|
114
|
+
], ChatSession.prototype, "visibility", void 0);
|
|
96
115
|
tslib_1.__decorate([
|
|
97
116
|
(0, typeorm_1.Column)({ nullable: true, length: 200 }),
|
|
98
117
|
(0, type_graphql_1.Field)({ nullable: true, description: 'Short preview of the last message, stored so the session list does not need to query messages.' }),
|
|
99
118
|
tslib_1.__metadata("design:type", String)
|
|
100
119
|
], ChatSession.prototype, "lastMessagePreview", void 0);
|
|
120
|
+
tslib_1.__decorate([
|
|
121
|
+
(0, typeorm_1.Column)({ type: 'simple-array', nullable: true }),
|
|
122
|
+
(0, type_graphql_1.Field)(() => [String], { nullable: true, description: 'Doors of the message the preview came from โ the session list passes the same gate as the conversation.' }),
|
|
123
|
+
tslib_1.__metadata("design:type", Array)
|
|
124
|
+
], ChatSession.prototype, "lastMessageDoors", void 0);
|
|
101
125
|
tslib_1.__decorate([
|
|
102
126
|
(0, typeorm_1.Column)({
|
|
103
127
|
nullable: true,
|
|
@@ -153,7 +177,7 @@ exports.ChatSession = ChatSession = tslib_1.__decorate([
|
|
|
153
177
|
,
|
|
154
178
|
(0, typeorm_1.Index)('ix_chat_session_2', (session) => [session.domain, session.anchorType, session.anchorId]),
|
|
155
179
|
(0, type_graphql_1.ObjectType)({
|
|
156
|
-
description: 'AI
|
|
180
|
+
description: 'One AI conversation, anchored to what it is about. An anchor may have several โ threads, one per person, one per context.'
|
|
157
181
|
})
|
|
158
182
|
], ChatSession);
|
|
159
183
|
//# sourceMappingURL=chat-session.js.map
|
|
@@ -1 +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'\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// ์ต์ปค ์กฐํ์ฉ โ chatSessionsByAnchor ๊ฐ [domain, anchorType, anchorId] ๋ก ์ง์.\n@Index('ix_chat_session_2', (session: ChatSession) => [session.domain, session.anchorType, session.anchorId])\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 *\n * **์ต์ปค ์ผ๋ฐํ ์ดํ์๋ ์ ์ง๋๋ ํ์ํธํ ์ปฌ๋ผ**์ด๋ค(์ ๊ฑฐํ์ง ๋ง ๊ฒ). ์ต์ปค๊ฐ board ์ธ ์ธ์
์\n * anchorId ์ ํจ๊ป ์ด ์ปฌ๋ผ์๋ ๊ฐ์ ๊ฐ์ ์ด๋ค(dual-write) โ ๊ธฐ์กด ์กฐํ/์ธ๋ฑ์ค/์๋น์๊ฐ ๊ทธ๋๋ก ๋์ํ๋ค. */\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). Kept for backward compatibility โ board-anchored sessions dual-write this alongside anchorId.'\n })\n boardId?: string\n\n /**\n * ๋ํ๊ฐ ๋งค๋ฌ๋ฆฐ ๋์์ **์ข
๋ฅ**. ์ธ์
์ ๋ณด๋์๋ง ๋งค๋ฌ๋ฆฌ์ง ์๋๋ค โ\n * ์ ์ ๋ํ๋ ๋ณด๋์, ์ด์ ๋ํ๋ ๊ณต๊ฐ(์ฌ์ดํธ)์ ๋งค๋ฌ๋ฆฐ๋ค. ์ต์ปค๊ฐ ๋ํ์ ์ฑ๊ฒฉ๊ณผ ์ด๋ ฅ ๊ฒฝ๊ณ๋ฅผ ์ ํ๋ค.\n *\n * 'board' | 'space' | 'instance' | 'none'. ๋ฏธ์ค์ (๊ธฐ์กด ๋ฐ์ดํฐ)์ boardId ๊ฐ ์์ผ๋ฉด board ๋ก ์ฝ๋๋ค โ\n * ๋ฐฑํ ๋ง์ด๊ทธ๋ ์ด์
์์ด lazy ํ์ํธํ(์ปฌ๋ผ ์ถ๊ฐ๋ง).\n */\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description:\n \"What this conversation is anchored to: 'board' | 'figure' (authoring a Figure) | 'space' | 'instance' | 'domain' | 'none'. Absent on legacy rows โ treated as 'board' when boardId is present.\"\n })\n anchorType?: string\n\n /** ์ต์ปค ๋์์ id(๋ณด๋ id ยท ๊ณต๊ฐ id ยท ์ธ์คํด์ค id). anchorType ๊ณผ ํจ๊ป ์๋ฏธ๋ฅผ ๊ฐ๋๋ค. */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Id of the anchored target (board id / space id / instance id).' })\n anchorId?: 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 /**\n * ๋ง์ง๋ง ๋ฉ์์ง ์๊ฐ โ **๋น์ ๊ทํ**. ๋ชฉ๋ก ์ ๋ ฌ(์ต๊ทผ ํ๋์)๊ณผ ์ ์ฝ์ ํ์ ์ ๊ธฐ์ค.\n *\n * ์ ๋น์ ๊ทํ์ธ๊ฐ: ์ธ์
๋ง๋ค ๋ฉ์์ง๋ฅผ ์ง๊ณํ๋ฉด(MAX/COUNT + group by) ๋ชฉ๋ก ํ ๋ฒ์ ์ง๊ณ ์ฟผ๋ฆฌ๊ฐ ๋ถ๊ณ ,\n * ์ด ํ๋ ์์ํฌ๋ 5๊ฐ DB ๋๋ผ์ด๋ฒ๋ฅผ ์ง์ํด์ผ ํ๋ค. ์ธ์
์ปฌ๋ผ ํ๋๋ก ๋๋ฉด ์ ๋ ฌยท๋น๊ต๊ฐ ๊ฐ์ธ๊ฒ ๋๋๊ณ \n * ๋๋ผ์ด๋ฒ ์ฐจ์ด๊ฐ ์๋ค. ๋ฉ์์ง๋ฅผ ์ ์ฅํ ๋ ํจ๊ป ๊ฐฑ์ ํ๋ค(activityPatch).\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Timestamp of the last message in this session (denormalized for list ordering and unread comparison โ avoids per-session aggregation across the supported DB drivers).' })\n lastMessageAt?: Date\n\n /** ๋ชฉ๋ก์ ๋ณด์ฌ์ค ๋ง์ง๋ง ๋ฉ์์ง ๋ฏธ๋ฆฌ๋ณด๊ธฐ โ ๋ชฉ๋ก์์ ๋ฉ์์ง ํ
์ด๋ธ์ ๋ค์ ์ฝ์ง ์๊ธฐ ์ํด ์งง๊ฒ ์ ์ฅ. */\n @Column({ nullable: true, length: 200 })\n @Field({ nullable: true, description: 'Short preview of the last message, stored so the session list does not need to query messages.' })\n lastMessagePreview?: string\n\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 /**\n * `lastSummary` ๊ฐ **์ด๋๊น์ง ๋ฎ๋์ง** โ ์ด ๋ฉ์์ง๊น์ง ์์ฝ์ ๋ฐ์๋๋ค.\n *\n * ์ด๊ฒ ์์ผ๋ฉด ๋์ ์์ฝ์ ํ ์ ์๋ค: ๋งค ํด ์ ์ฒด๋ฅผ ๋ค์ ์์ฝํ๊ฑฐ๋(๋น์ฉ) ์ด๋ฏธ ์์ฝํ ๊ตฌ๊ฐ์\n * ๋ ์ด์ด ๋ถ์ธ๋ค(์ค๋ณต). ์ด๋ ฅ์์ ์ด id ๋ฅผ ๋ชป ์ฐพ์ผ๋ฉด(์ญ์ ยทํธ์ง) ๋ฎ์ ๋ฒ์๋ฅผ ์ ์ ์์ผ๋ฏ๋ก\n * ์ ๋ถ ๋ฏธ๋ฐ์์ผ๋ก ๋ณด๊ณ ๋ค์ ์์ฝํ๋ค โ ๋น ๋จ๋ฆฌ๋ ์ชฝ๋ณด๋ค ์์ ํ๋ค.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Id of the last message folded into lastSummary โ enables incremental summarization instead of re-reading the whole history.' })\n summaryUpToMessageId?: 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 /*\n * โโ ๋ณด๋ ํจ์น ๊ด๊ณ๋ฅผ ๋์๋ค (2026-09-10) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฌ๊ธฐ `@OneToMany(PatchEntry)` ๊ฐ ์์๋ค. ๊ทธ๋์ **๋ํ ์ธ์
์ด ๋ณด๋ ํธ์ง๊ธฐ๋ฅผ ์์์ผ** ํ๊ณ ,\n * ์ธ์
๊ณ์ด์ ์ค๋ฆฝ ํจํค์ง๋ก ์ฎ๊ธฐ๋ ค๋ ์๊ฐ `ai-assistant โ board-ai โ ai-assistant` ์ํ์ด\n * ๋๋ค.\n *\n * ๋์ด๋ ์๋ ๊ฒ์ด ์๋ค โ ์ด ๊ด๊ณ๋ฅผ **์๋ฃ๋ก ์ฝ๋ ์๋ฆฌ๊ฐ ํ๋๋ ์์๋ค**(์ ์ ์ฅ์์์\n * `session.patches` ๋ฅผ ์ฝ๋ ์ฝ๋ 0 ๊ฑด). ์ ์ผํ ์ฐ์์ด `PatchEntry` ์ชฝ์ ์ญ๋ฐฉํฅ ์ ์ธ ํ ์ค์ด์๊ณ ,\n * TypeORM ์ ์ญ๋ฐฉํฅ ์์ด๋ `@ManyToOne` ์ ๋ง๋ ๋ค. ํจ์น๋ `sessionId` ๋ก ์ฐพ๋๋ค\n * (`chatPatches` ๊ฐ ์ด๋ฏธ ๊ทธ๋ ๊ฒ ํ๋ค).\n *\n * ๋ฐฉํฅ์ ๋จ๋๋ค: **๋ณด๋ ํจ์น๊ฐ ์ธ์
์ ์๋ค. ์ธ์
์ ๋ณด๋ ํจ์น๋ฅผ ๋ชจ๋ฅธ๋ค.** ์ข
์์ด ํ์ชฝ์ด๋ฉด\n * ์ค๋ฆฝ ์ชฝ์ด ์ฎ๊ฒจ์ง ์ ์๋ค.\n */\n}\n"]}
|
|
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'\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// ์ต์ปค ์กฐํ์ฉ โ chatSessionsByAnchor ๊ฐ [domain, anchorType, anchorId] ๋ก ์ง์.\n@Index('ix_chat_session_2', (session: ChatSession) => [session.domain, session.anchorType, session.anchorId])\n@ObjectType({\n description: 'One AI conversation, anchored to what it is about. An anchor may have several โ threads, one per person, one per context.'\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 *\n * **์ต์ปค ์ผ๋ฐํ ์ดํ์๋ ์ ์ง๋๋ ํ์ํธํ ์ปฌ๋ผ**์ด๋ค(์ ๊ฑฐํ์ง ๋ง ๊ฒ). ์ต์ปค๊ฐ board ์ธ ์ธ์
์\n * anchorId ์ ํจ๊ป ์ด ์ปฌ๋ผ์๋ ๊ฐ์ ๊ฐ์ ์ด๋ค(dual-write) โ ๊ธฐ์กด ์กฐํ/์ธ๋ฑ์ค/์๋น์๊ฐ ๊ทธ๋๋ก ๋์ํ๋ค. */\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). Kept for backward compatibility โ board-anchored sessions dual-write this alongside anchorId.'\n })\n boardId?: string\n\n /**\n * ๋ํ๊ฐ ๋งค๋ฌ๋ฆฐ ๋์์ **์ข
๋ฅ**. ์ธ์
์ ๋ณด๋์๋ง ๋งค๋ฌ๋ฆฌ์ง ์๋๋ค โ\n * ์ ์ ๋ํ๋ ๋ณด๋์, ์ด์ ๋ํ๋ ๊ณต๊ฐ(์ฌ์ดํธ)์ ๋งค๋ฌ๋ฆฐ๋ค. ์ต์ปค๊ฐ ๋ํ์ ์ฑ๊ฒฉ๊ณผ ์ด๋ ฅ ๊ฒฝ๊ณ๋ฅผ ์ ํ๋ค.\n *\n * 'board' | 'space' | 'instance' | 'none'. ๋ฏธ์ค์ (๊ธฐ์กด ๋ฐ์ดํฐ)์ boardId ๊ฐ ์์ผ๋ฉด board ๋ก ์ฝ๋๋ค โ\n * ๋ฐฑํ ๋ง์ด๊ทธ๋ ์ด์
์์ด lazy ํ์ํธํ(์ปฌ๋ผ ์ถ๊ฐ๋ง).\n */\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description:\n \"What this conversation is anchored to: 'board' | 'figure' (authoring a Figure) | 'space' | 'instance' | 'domain' | 'none'. Absent on legacy rows โ treated as 'board' when boardId is present.\"\n })\n anchorType?: string\n\n /** ์ต์ปค ๋์์ id(๋ณด๋ id ยท ๊ณต๊ฐ id ยท ์ธ์คํด์ค id). anchorType ๊ณผ ํจ๊ป ์๋ฏธ๋ฅผ ๊ฐ๋๋ค. */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Id of the anchored target (board id / space id / instance id).' })\n anchorId?: 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 /**\n * ๋ง์ง๋ง ๋ฉ์์ง ์๊ฐ โ **๋น์ ๊ทํ**. ๋ชฉ๋ก ์ ๋ ฌ(์ต๊ทผ ํ๋์)๊ณผ ์ ์ฝ์ ํ์ ์ ๊ธฐ์ค.\n *\n * ์ ๋น์ ๊ทํ์ธ๊ฐ: ์ธ์
๋ง๋ค ๋ฉ์์ง๋ฅผ ์ง๊ณํ๋ฉด(MAX/COUNT + group by) ๋ชฉ๋ก ํ ๋ฒ์ ์ง๊ณ ์ฟผ๋ฆฌ๊ฐ ๋ถ๊ณ ,\n * ์ด ํ๋ ์์ํฌ๋ 5๊ฐ DB ๋๋ผ์ด๋ฒ๋ฅผ ์ง์ํด์ผ ํ๋ค. ์ธ์
์ปฌ๋ผ ํ๋๋ก ๋๋ฉด ์ ๋ ฌยท๋น๊ต๊ฐ ๊ฐ์ธ๊ฒ ๋๋๊ณ \n * ๋๋ผ์ด๋ฒ ์ฐจ์ด๊ฐ ์๋ค. ๋ฉ์์ง๋ฅผ ์ ์ฅํ ๋ ํจ๊ป ๊ฐฑ์ ํ๋ค(activityPatch).\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Timestamp of the last message in this session (denormalized for list ordering and unread comparison โ avoids per-session aggregation across the supported DB drivers).' })\n lastMessageAt?: Date\n\n /**\n * ์ด ๋ํ๋ฅผ ๋๋ฉ์ธ ์ ๋๊ตฌ๋ ์ฝ๋๊ฐ โ ADR-0073 ํ์ 2.\n *\n * `open` ๋๋ฉ์ธ ์์ด๋ฉด ๋๊ตฌ๋ ๋ค์ด์ ์ฝ๊ณ ๋งํ๋ค. ์ด๋ ์ ์ฐจ๋ ์๋ค.\n * `private` ์ฐธ์ฌ์๋ง ์ฝ๋๋ค.\n *\n * ์ต์ปค๊ฐ ์๋ ์ธ์
(space ยท board ยท station)์ ๊ณต์ ๋ ๋ฌด์์ ๋๊ณ ํ๋ ์ด์ผ๊ธฐ์ด๋ฏ๋ก `open` ์ผ๋ก\n * ์์ํ๋ค. ์ต์ปค๊ฐ ์๋ ์ธ์
๊ณผ **์ฎ๊ฒจ ์ ์ด ๋ง๋ ์ธ์
**์ `private` ์ผ๋ก ์์ํ๋ค โ ๊ฐ๋ฒผ์ด ์ง๋ฌธ์\n * ์น๊ฒฉํ๋ฉด์ ์์ ๋ํ๊ฐ ์ ์ธ์
์ ์ฎ๊ฒจ ์ ํ๋๋ฐ(`appendSessionTurns`), ๊ทธ๊ฒ์ด ๊ณต๊ฐ๋ก ํ์ด๋๋ฉด\n * ์ฌ์ ์ผ๋ก ์ค๊ฐ ์๋ฌธ์ด ์๊ธํด์ ๊ณต๊ฐ๋๋ค.\n *\n * owner ๊ฐ ์๋ฐฉํฅ์ผ๋ก ๋ฐ๊ฟ ์ ์๋ค. ๊ณต๊ฐ๋ก ๋ฐ๊พธ๊ธฐ ์ ์ ํ๋ฉด์ด ํ ์ค์ ๋จผ์ ๋ณด์ธ๋ค.\n *\n * open ์ด์ด๋ ๋ต ํ์ ๋ฌธ ํ์ (ADR-0073 ํ์ 1)์ ๊ทธ๋๋ก๋ค โ ๋ฐฉ์ ๋ค์ด์จ ๊ฒ๊ณผ ๊ฐ์ ์ฝ๋ ๊ฒ์ ๋ค๋ฅด๋ค.\n */\n @Column({ type: 'varchar', length: 16, default: 'open' })\n @Field({ description: \"Who may read this conversation: 'open' (anyone in the domain) or 'private' (participants only).\" })\n visibility!: string\n\n /** ๋ชฉ๋ก์ ๋ณด์ฌ์ค ๋ง์ง๋ง ๋ฉ์์ง ๋ฏธ๋ฆฌ๋ณด๊ธฐ โ ๋ชฉ๋ก์์ ๋ฉ์์ง ํ
์ด๋ธ์ ๋ค์ ์ฝ์ง ์๊ธฐ ์ํด ์งง๊ฒ ์ ์ฅ. */\n @Column({ nullable: true, length: 200 })\n @Field({ nullable: true, description: 'Short preview of the last message, stored so the session list does not need to query messages.' })\n lastMessagePreview?: string\n\n /**\n * ๊ทธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ง๋์จ ๋ฌธ โ ADR-0073 ํ์ 1.\n *\n * ๋ชฉ๋ก์ ๋ต์ **๋ค์ ์ฝ๋ ๋ ๋ฒ์งธ ๊ธธ**์ด๋ค. ๋ฉ์์ง ํ๋ฉด์์๋ง ๊ฐ๋ฆฌ๋ฉด ๊ฐ์ ๋ฌธ์ฅ์ด ๋ชฉ๋ก์ ๊ทธ๋๋ก ๋ฌ๋ค.\n * ๋ฌธ์ด ๋์ด๊ณ ํ์ชฝ์ด ๋์จํ๋ฉด ๋์จํ ์ชฝ์ด ์ด๊ธด๋ค(ADR-0061 ๊ฒฐ์ 1). ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์ ์ฅํ ๋ ๊ทธ ํ์ ๋ฌธ์\n * ํจ๊ป ์ฎ๊ฒจ ์ ๊ณ , ๋ชฉ๋ก๋ ๊ฐ์ ๊ด๋ฌธ์ ์ง๋๋ค.\n */\n @Column({ type: 'simple-array', nullable: true })\n @Field(() => [String], { nullable: true, description: 'Doors of the message the preview came from โ the session list passes the same gate as the conversation.' })\n lastMessageDoors?: string[]\n\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 /**\n * `lastSummary` ๊ฐ **์ด๋๊น์ง ๋ฎ๋์ง** โ ์ด ๋ฉ์์ง๊น์ง ์์ฝ์ ๋ฐ์๋๋ค.\n *\n * ์ด๊ฒ ์์ผ๋ฉด ๋์ ์์ฝ์ ํ ์ ์๋ค: ๋งค ํด ์ ์ฒด๋ฅผ ๋ค์ ์์ฝํ๊ฑฐ๋(๋น์ฉ) ์ด๋ฏธ ์์ฝํ ๊ตฌ๊ฐ์\n * ๋ ์ด์ด ๋ถ์ธ๋ค(์ค๋ณต). ์ด๋ ฅ์์ ์ด id ๋ฅผ ๋ชป ์ฐพ์ผ๋ฉด(์ญ์ ยทํธ์ง) ๋ฎ์ ๋ฒ์๋ฅผ ์ ์ ์์ผ๋ฏ๋ก\n * ์ ๋ถ ๋ฏธ๋ฐ์์ผ๋ก ๋ณด๊ณ ๋ค์ ์์ฝํ๋ค โ ๋น ๋จ๋ฆฌ๋ ์ชฝ๋ณด๋ค ์์ ํ๋ค.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Id of the last message folded into lastSummary โ enables incremental summarization instead of re-reading the whole history.' })\n summaryUpToMessageId?: 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 /*\n * โโ ๋ณด๋ ํจ์น ๊ด๊ณ๋ฅผ ๋์๋ค (2026-09-10) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฌ๊ธฐ `@OneToMany(PatchEntry)` ๊ฐ ์์๋ค. ๊ทธ๋์ **๋ํ ์ธ์
์ด ๋ณด๋ ํธ์ง๊ธฐ๋ฅผ ์์์ผ** ํ๊ณ ,\n * ์ธ์
๊ณ์ด์ ์ค๋ฆฝ ํจํค์ง๋ก ์ฎ๊ธฐ๋ ค๋ ์๊ฐ `ai-assistant โ board-ai โ ai-assistant` ์ํ์ด\n * ๋๋ค.\n *\n * ๋์ด๋ ์๋ ๊ฒ์ด ์๋ค โ ์ด ๊ด๊ณ๋ฅผ **์๋ฃ๋ก ์ฝ๋ ์๋ฆฌ๊ฐ ํ๋๋ ์์๋ค**(์ ์ ์ฅ์์์\n * `session.patches` ๋ฅผ ์ฝ๋ ์ฝ๋ 0 ๊ฑด). ์ ์ผํ ์ฐ์์ด `PatchEntry` ์ชฝ์ ์ญ๋ฐฉํฅ ์ ์ธ ํ ์ค์ด์๊ณ ,\n * TypeORM ์ ์ญ๋ฐฉํฅ ์์ด๋ `@ManyToOne` ์ ๋ง๋ ๋ค. ํจ์น๋ `sessionId` ๋ก ์ฐพ๋๋ค\n * (`chatPatches` ๊ฐ ์ด๋ฏธ ๊ทธ๋ ๊ฒ ํ๋ค).\n *\n * ๋ฐฉํฅ์ ๋จ๋๋ค: **๋ณด๋ ํจ์น๊ฐ ์ธ์
์ ์๋ค. ์ธ์
์ ๋ณด๋ ํจ์น๋ฅผ ๋ชจ๋ฅธ๋ค.** ์ข
์์ด ํ์ชฝ์ด๋ฉด\n * ์ค๋ฆฝ ์ชฝ์ด ์ฎ๊ฒจ์ง ์ ์๋ค.\n */\n}\n"]}
|
|
@@ -7,6 +7,8 @@ export interface InboxSessionRow {
|
|
|
7
7
|
boardId?: string;
|
|
8
8
|
lastMessageAt?: Date | string | null;
|
|
9
9
|
lastMessagePreview?: string | null;
|
|
10
|
+
/** ๊ทธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ง๋์จ ๋ฌธ โ ๋ชฉ๋ก๋ ๊ฐ์ ๊ด๋ฌธ์ ์ง๋๋ค. */
|
|
11
|
+
lastMessageDoors?: string[] | null;
|
|
10
12
|
createdAt?: Date | string | null;
|
|
11
13
|
}
|
|
12
14
|
/** ๋ด ์ฐธ์ฌ ๊ธฐ๋ก(์ฝ์ ์ง์ ). */
|
|
@@ -64,9 +66,10 @@ export declare function countUnreadSessions(entries: InboxEntry[]): number;
|
|
|
64
66
|
* ๋ฉ์์ง ์ ์ฅ ์ ์ธ์
์ ๋ฐ์ํ ํ๋ ๊ฐ. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ ์งง๊ฒ ์๋ฅด๊ณ ๊ฐํ์ ์์ค๋ค
|
|
65
67
|
* (๋ชฉ๋ก ํ ์ค์ ๋ค์ด๊ฐ์ผ ํ๊ณ , ์ปฌ๋ผ ๊ธธ์ด ์ ํ์ด ์๋ค).
|
|
66
68
|
*/
|
|
67
|
-
export declare function activityPatch(content: string, at?: Date): {
|
|
69
|
+
export declare function activityPatch(content: string, at?: Date, doors?: string[]): {
|
|
68
70
|
lastMessageAt: Date;
|
|
69
71
|
lastMessagePreview: string;
|
|
72
|
+
lastMessageDoors: string[];
|
|
70
73
|
};
|
|
71
74
|
/**
|
|
72
75
|
* ์ฒซ ๋ฐํ๋ก ์ธ์
์ด๋ฆ์ ๋ง๋ ๋ค.
|
|
@@ -108,9 +108,10 @@ function countUnreadSessions(entries) {
|
|
|
108
108
|
* ๋ฉ์์ง ์ ์ฅ ์ ์ธ์
์ ๋ฐ์ํ ํ๋ ๊ฐ. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ ์งง๊ฒ ์๋ฅด๊ณ ๊ฐํ์ ์์ค๋ค
|
|
109
109
|
* (๋ชฉ๋ก ํ ์ค์ ๋ค์ด๊ฐ์ผ ํ๊ณ , ์ปฌ๋ผ ๊ธธ์ด ์ ํ์ด ์๋ค).
|
|
110
110
|
*/
|
|
111
|
-
function activityPatch(content, at = new Date()) {
|
|
111
|
+
function activityPatch(content, at = new Date(), doors = []) {
|
|
112
112
|
const flat = (content ?? '').replace(/\s+/g, ' ').trim();
|
|
113
|
-
|
|
113
|
+
/* ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ด๋ ๋ฌธ์ ์ง๋์จ ๊ฐ์ธ์ง ํจ๊ป ์ ๋๋ค โ ๋ชฉ๋ก๋ ๊ฐ์ ๊ด๋ฌธ์ ์ง๋๋ค(ADR-0073 ํ์ 1). */
|
|
114
|
+
return { lastMessageAt: at, lastMessagePreview: flat.slice(0, 200), lastMessageDoors: doors };
|
|
114
115
|
}
|
|
115
116
|
/**
|
|
116
117
|
* ์ฒซ ๋ฐํ๋ก ์ธ์
์ด๋ฆ์ ๋ง๋ ๋ค.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-inbox.js","sourceRoot":"","sources":["../../../server/service/chat-session/session-inbox.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;
|
|
1
|
+
{"version":3,"file":"session-inbox.js","sourceRoot":"","sources":["../../../server/service/chat-session/session-inbox.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * ์ธ์
๋ชฉ๋ก(๋ฐ์ํธ์งํจ) ์์ ๋ก์ง โ ๋ฆฌ์กธ๋ฒ์ ๋ถ๋ฆฌํด ๋จ์ ํ
์คํธ ๊ฐ๋ฅ.\n *\n * โโ ์ ํ์ํ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ํ๊ฐ ๋๋ฉด(๊ฐ๋ฒผ์ด ์ง๋ฌธ์ ์น๊ฒฉํ ๋๋ง๋ค ์ ์ธ์
) \"์ด๋๋ก ๊ฐ์ง\"๋ฅผ ๋ชฉ๋ก์์ ๊ณจ๋ผ์ผ ํ๊ณ , ๋ค๋ฅธ ์ฐธ์ฌ์๊ฐ\n * ๋จ๊ธด ์ ๋ฉ์์ง๋ฅผ ์์์ผ ํ๋ค. ์ธ์
๋ชฉ๋ก์ **์ต๊ทผ ํ๋์**์ด์ด์ผ ํ๊ณ **์ ์ฝ์**์ด ๋ณด์ฌ์ผ ํ๋ค.\n *\n * โโ ์ง๊ณ ์ฟผ๋ฆฌ๋ฅผ ์ฐ์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ธ์
๋ง๋ค ๋ฉ์์ง๋ฅผ ์ง๊ณํ๋ฉด(MAX/COUNT + group by) ๋ชฉ๋ก ํ ๋ฒ์ ์ง๊ณ๊ฐ ๋ถ๊ณ , ์ด ํ๋ ์์ํฌ๋ 5๊ฐ DB\n * ๋๋ผ์ด๋ฒ๋ฅผ ์ง์ํด์ผ ํ๋ค. ๋์ `ChatSession.lastMessageAt` ์ ๋น์ ๊ทํํด ๋๊ณ (๋ฉ์์ง ์ ์ฅ ์ ๊ฐฑ์ ),\n * ์ฐธ์ฌ์์ `lastReadAt` ๊ณผ **๊ฐ ๋น๊ต**๋ก ์ ์ฝ์์ ํ์ ํ๋ค โ ์กฐํ ๋ ๋ฒ(์ธ์
ยท๋ด ์ฐธ์ฌ์)์ผ๋ก ๋๋๋ค.\n *\n * โโ v1 ์ ๊ฐ์๊ฐ ์๋๋ผ \"์ ์ฝ์ ์ฌ๋ถ\" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ํํ ๋ฏธ์ฝ์ **๊ฐ์**๋ ์ธ์
๋ณ count ๊ฐ ํ์ํ๋ค(๋ชฉ๋ก N๊ฐ๋ฉด N๋ฒ). ๋ชฉ๋ก์์๋ ์ ํ๋๋ก ์ถฉ๋ถํ๊ณ ,\n * ์ซ์๊ฐ ํ์ํด์ง๋ฉด ํ๋ฉด์ ๋ณด์ด๋ ์ธ์
์ ํํด ๋ฐ๋ก ์ธ๋ฉด ๋๋ค. ์ฒ์๋ถํฐ N๋ฒ ์ธ์ง ์๋๋ค.\n */\n\n/** ๋ชฉ๋ก์ ํ์ํ ์ธ์
ํ๋(์ํฐํฐยทtypeorm ๋น์์กด). */\nexport interface InboxSessionRow {\n id?: string\n name?: string\n anchorType?: string\n anchorId?: string\n boardId?: string\n lastMessageAt?: Date | string | null\n lastMessagePreview?: string | null\n /** ๊ทธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ง๋์จ ๋ฌธ โ ๋ชฉ๋ก๋ ๊ฐ์ ๊ด๋ฌธ์ ์ง๋๋ค. */\n lastMessageDoors?: string[] | null\n createdAt?: Date | string | null\n}\n\n/** ๋ด ์ฐธ์ฌ ๊ธฐ๋ก(์ฝ์ ์ง์ ). */\nexport interface MyParticipation {\n sessionId?: string\n lastReadAt?: Date | string | null\n /** ๋ด ๋ชฉ๋ก์์ ์จ๊ธด ์๊ฐ โ ์ดํ ์ ํ๋์ด ์๊ธฐ๋ฉด ๋ค์ ๋ณด์ธ๋ค. */\n hiddenAt?: Date | string | null\n}\n\nexport interface InboxEntry extends InboxSessionRow {\n /** ์ ์ฝ์ ํ๋์ด ์๋๊ฐ โ ๋ชฉ๋ก์ ์ ํ์. */\n unread: boolean\n /** ๋ด๊ฐ ์ฐธ์ฌ์์ธ๊ฐ โ ์๋๋ฉด ์ด์ด๋ณผ ์๋ ์์ด๋ ์ฝ์ ์ํ๋ฅผ ๊ฐ์ง ์๋๋ค. */\n participant: boolean\n /** ๋ด๊ฐ ์จ๊ธด ๋ํ์ธ๊ฐ โ ๋ชฉ๋ก์์ ๋น ์ง์ง๋ง ํํฐ๋ก ๋ณผ ์ ์๋ค(๋๋๋ฆฌ๊ธฐ ๊ฐ๋ฅ). */\n hidden?: boolean\n}\n\nfunction time(v: Date | string | null | undefined): number {\n if (!v) return 0\n const t = v instanceof Date ? v.getTime() : Date.parse(v)\n return Number.isFinite(t) ? t : 0\n}\n\n/**\n * ์ธ์
+ ๋ด ์ฐธ์ฌ ๊ธฐ๋ก โ ๋ชฉ๋ก ํญ๋ชฉ. **์ต๊ทผ ํ๋์**(ํ๋ ์์ผ๋ฉด ์์ฑ์) ๋ด๋ฆผ์ฐจ์.\n *\n * ์ ์ฝ์ ํ์ : ์ธ์
์ ๋ง์ง๋ง ํ๋์ด ๋ด๊ฐ ์ฝ์ ์ง์ ๋ณด๋ค **๋ค**๋ฉด ์ ์ฝ์.\n * ยท ์ฐธ์ฌ์๊ฐ ์๋๋ฉด ์ ์ฝ์์ผ๋ก ํ์ํ์ง ์๋๋ค(๋ด ๊ฒ์ด ์๋ ๋ํ์ ๋ฐฐ์ง๋ฅผ ๋์ฐ์ง ์๋๋ค).\n * ยท ์ฐธ์ฌ์์ธ๋ฐ ํ ๋ฒ๋ ์ฝ์ง ์์๊ณ (lastReadAt ์์) ํ๋์ด ์์ผ๋ฉด ์ ์ฝ์์ด๋ค.\n * ยท ํ๋์ด ์๋ ์ธ์
(๋น ๋ํ)์ ์ ์ฝ์์ด ์๋๋ค.\n *\n * ๊ฐ์ ์๊ฐ ๋น๊ต๋ **์๊ฒฉ ์ด๊ณผ**๋ง ์ ์ฝ์์ผ๋ก ๋ณธ๋ค โ ์ฝ์ ์งํ ๊ฐ์ ๋ฐ๋ฆฌ์ด์ ์ ์ฅ๋ ํ๋์ ์ ์ฝ์์ผ๋ก\n * ์ก์ผ๋ฉด ๋ฐฉ๊ธ ์ฝ์ ํ๋ฉด์ ๋ฐฐ์ง๊ฐ ๋จ๋๋ค.\n */\nexport function buildInbox(sessions: InboxSessionRow[], mine: MyParticipation[]): InboxEntry[] {\n const readBy = new Map<string, number>()\n const isParticipant = new Set<string>()\n for (const p of mine) {\n if (!p.sessionId) continue\n isParticipant.add(p.sessionId)\n readBy.set(p.sessionId, time(p.lastReadAt))\n }\n\n const entries = sessions.map(session => {\n const id = session.id ?? ''\n const activity = time(session.lastMessageAt)\n const participant = isParticipant.has(id)\n const read = readBy.get(id) ?? 0\n return {\n ...session,\n participant,\n unread: participant && activity > 0 && activity > read\n }\n })\n\n return entries.sort(\n (a, b) => (time(b.lastMessageAt) || time(b.createdAt)) - (time(a.lastMessageAt) || time(a.createdAt))\n )\n}\n\n/**\n * ์จ๊น ํ์ยทํํฐ.\n *\n * ์จ๊น์ **๋์๊ฒ๋ง** ์ ์ฉ๋๊ณ ๋๋๋ฆด ์ ์๋ค. ์จ๊ธด **๋ค์ ์ ํ๋์ด ์๊ธฐ๋ฉด ๋ค์ ๋ณด์ธ๋ค** โ\n * ์์ง ์ฐธ์ฌ ์ค์ธ ๋ํ์์ ์กฐ์ฉํ ์๋ ค ๋๊ฐ๋ ๊ฒ์ด ๋ชฉ๋ก ํ ์ค๋ณด๋ค ๋์๋ค.\n *\n * `showHidden` ์ด๋ฉด ์จ๊ธด ๊ฒ๋ ํจ๊ป ๋๋ ค์ฃผ๋ ํ์(hidden)๋ฅผ ๋จ๊ธด๋ค โ ํํฐ๋ฅผ ์ผ ์ฌ์ฉ์๊ฐ ๋ฌด์์ด\n * ์จ๊ฒจ์ง ๊ฒ์ธ์ง ์์์ผ ๋๋๋ฆด ์ ์๋ค.\n */\nexport function applyHidden(entries: InboxEntry[], hiddenAt: Map<string, Date | string | null | undefined>, showHidden = false): InboxEntry[] {\n const out: InboxEntry[] = []\n for (const entry of entries) {\n const at = hiddenAt.get(entry.id ?? '')\n /* ์จ๊ธด ์๊ฐ๋ณด๋ค **๋ค์** ํ๋์ด ์์ผ๋ฉด ์จ๊น์ ํ๋ฆฐ ๊ฒ์ผ๋ก ๋ณธ๋ค. */\n const hidden = !!at && time(entry.lastMessageAt) <= time(at)\n if (hidden && !showHidden) continue\n out.push(hidden ? { ...entry, hidden: true } : entry)\n }\n return out\n}\n\n/**\n * ๊ฒ์ โ ์ด๋ฆ๊ณผ ๋ง์ง๋ง ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ ๋ํ ๋์๋ฌธ์ ๋ฌด์ ๋ถ๋ถ์ผ์น.\n *\n * **์ ๋ฉ๋ชจ๋ฆฌ์์ ํ๋๊ฐ**: ์ด ํ๋ ์์ํฌ๋ 5๊ฐ DB ๋๋ผ์ด๋ฒ๋ฅผ ์ง์ํ๋ค. ๋์๋ฌธ์ ๋ฌด์ ๊ฒ์์\n * ๋๋ผ์ด๋ฒ๋ง๋ค ํ๊ธฐ๊ฐ ๊ฐ๋ฆฌ๊ณ (ILIKE=pg ์ ์ฉ, LOWER()+LIKE ๋ ๋์ง๋ง ์ ๋ ฌยทNULL ์ทจ๊ธ์ด ๋ ๊ฐ๋ฆฐ๋ค),\n * ๋ชฉ๋ก ๊ฒฝ๋ก์ ๋๋ผ์ด๋ฒ๋ณ SQL ์ ๋๋ ๊ฒ์ ์ด ํ๋ก์ ํธ์ ๊ท์จ์ ๋ฐํ๋ค. ๊ทธ๋์ ์กฐํ๋ ์ต์ปค๋ก\n * **์ํ์ ๋๊ณ ** ๊ฐ์ ธ์ค๊ณ (์๋ INBOX_SCAN_CAP) ๊ฑธ๋ฌ๋ด๊ธฐยท์ ๋ ฌยทํ์ด์ง๋ ์ฌ๊ธฐ์ ํ๋ค.\n * ์ํ์ ๋์ผ๋ฉด ์๋ ธ๋ค๋ ์ฌ์ค์ ๊ทธ๋๋ก ์๋ฆฐ๋ค(์กฐ์ฉํ ์ผ๋ถ๋ง ๋ณด์ฌ์ฃผ์ง ์๋๋ค).\n */\nexport function searchInbox(entries: InboxEntry[], search?: string): InboxEntry[] {\n const q = (search ?? '').trim().toLowerCase()\n if (!q) return entries\n return entries.filter(e =>\n `${e.name ?? ''}\\n${e.lastMessagePreview ?? ''}`.toLowerCase().includes(q)\n )\n}\n\n/** ํ ๋ฒ์ ํ๋ ์ธ์
์ํ โ ์ด๋ณด๋ค ๋ง์ผ๋ฉด ์๋ ธ๋ค๊ณ ์๋ฆฐ๋ค(์ ์ง). */\nexport const INBOX_SCAN_CAP = 500\n\n/** ์ ์ฝ์ ์ธ์
์ โ ๋ํฌ ๋ฒํผ ๋ฐฐ์ง(๊ฐ์๊ฐ ์๋๋ผ **์ธ์
์**). */\nexport function countUnreadSessions(entries: InboxEntry[]): number {\n return entries.filter(e => e.unread).length\n}\n\n/**\n * ๋ฉ์์ง ์ ์ฅ ์ ์ธ์
์ ๋ฐ์ํ ํ๋ ๊ฐ. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ ์งง๊ฒ ์๋ฅด๊ณ ๊ฐํ์ ์์ค๋ค\n * (๋ชฉ๋ก ํ ์ค์ ๋ค์ด๊ฐ์ผ ํ๊ณ , ์ปฌ๋ผ ๊ธธ์ด ์ ํ์ด ์๋ค).\n */\nexport function activityPatch(\n content: string,\n at: Date = new Date(),\n doors: string[] = []\n): { lastMessageAt: Date; lastMessagePreview: string; lastMessageDoors: string[] } {\n const flat = (content ?? '').replace(/\\s+/g, ' ').trim()\n /* ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ด๋ ๋ฌธ์ ์ง๋์จ ๊ฐ์ธ์ง ํจ๊ป ์ ๋๋ค โ ๋ชฉ๋ก๋ ๊ฐ์ ๊ด๋ฌธ์ ์ง๋๋ค(ADR-0073 ํ์ 1). */\n return { lastMessageAt: at, lastMessagePreview: flat.slice(0, 200), lastMessageDoors: doors }\n}\n\n/**\n * ์ฒซ ๋ฐํ๋ก ์ธ์
์ด๋ฆ์ ๋ง๋ ๋ค.\n *\n * `์ธ์
2` ๊ฐ์ ์๋ฒ์ ๋ชฉ๋ก์์ ์๋ฌด๊ฒ๋ ์๋ ค์ฃผ์ง ์๋๋ค โ \"A-DC ํฌํ ์์ธ\" ์ด์ด์ผ ๋์๊ฐ ๋ํ๋ฅผ ์ฐพ๋๋ค.\n * ์ฌ์ฉ์๊ฐ ์ง์ ์ง์ ์ด๋ฆ์ ์ด ํจ์๋ก ๋ฎ์ง ์๋๋ค(ํธ์ถ๋ถ๊ฐ ์ด๋ฆ ์์ ๋๋ง ๋ถ๋ฅธ๋ค).\n *\n * ๊ท์น: ํ ์ค๋ก ๋๋ฌ ์ฒซ ๋ฌธ์ฅ ๊ฒฝ๊ณ(., ?, !, ๊ฐํ)๊น์ง, ์ต๋ 40์. ๋ฌธ์ฅ ๋ถํธ๋ก ๋๋๋ฉด ๋ผ์ด ๋ธ๋ค\n * (๋ชฉ๋ก ์ ๋ชฉ์ ๋ฌผ์ํ๊ฐ ๋ถ์ผ๋ฉด ๊ธธ์ด๋ง ๋จน๋๋ค).\n */\nexport function autoSessionName(content: string, max = 40): string {\n const flat = (content ?? '').replace(/\\s+/g, ' ').trim()\n if (!flat) return ''\n const cut = flat.search(/[.?!\\n]/)\n const head = (cut > 0 ? flat.slice(0, cut) : flat).trim()\n const name = head.length > max ? head.slice(0, max).trim() + 'โฆ' : head\n return name\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type SessionVisibility = 'open' | 'private';
|
|
2
|
+
export declare const SESSION_VISIBILITIES: readonly SessionVisibility[];
|
|
3
|
+
/**
|
|
4
|
+
* ์ด๋ ๊ฒ ๋ง๋ค์ด์ง ์ธ์
์ ๋ฌด์์ผ๋ก ์์ํ๋.
|
|
5
|
+
*
|
|
6
|
+
* ์ต์ปค๊ฐ ์์ผ๋ฉด ๊ณต์ ๋ ๋์์ ๋๊ณ ํ๋ ์ด์ผ๊ธฐ๋ค โ ๊ณต๊ฐ. ์ต์ปค๊ฐ ์๊ฑฐ๋ ์์ ๋ํ๋ฅผ ์ฎ๊ฒจ ์ ์ด ๋ง๋
|
|
7
|
+
* ๊ฒ์ด๋ฉด ๋น๊ณต๊ฐ. `copyOf` ๊ฐ ์๋ค๋ ๊ฒ์ ๋ค๋ฅธ ๋ํ์ ์๋ฌธ์ด ์ด ์์ ๋ค์ด์๋ค๋ ๋ป์ด๊ณ , ๊ทธ ์๋ฌธ์
|
|
8
|
+
* ์๊ธฐ๊ฐ ์๋ ์๋ฆฌ์ ๊ท์น์ผ๋ก ์ฐ์๋ค.
|
|
9
|
+
*/
|
|
10
|
+
export declare function initialVisibility(session: {
|
|
11
|
+
anchorType?: string | null;
|
|
12
|
+
copyOf?: string | null;
|
|
13
|
+
}): SessionVisibility;
|
|
14
|
+
/** ์ด ์ฌ๋์ด ์ด ๋ํ๋ฅผ ์ฝ์ ์ ์๋. open ์ด๋ฉด ๋๋ฉ์ธ ์ ๋๊ตฌ๋, private ์ด๋ฉด ์ฐธ์ฌ์๋ง. */
|
|
15
|
+
export declare function mayReadSession(visibility: string | null | undefined, isParticipant: boolean): boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* ์ ๋ํ๊ฐ ๊ณต๊ฐ๋ก ํ์ด๋๋๊ฐ โ ADR-0073 ํ์ 2.
|
|
4
|
+
*
|
|
5
|
+
* ํ์ ์ ์ธ์
์ ๋ง๋๋ ์๋ฆฌ๋ง๋ค ์ ์ผ๋ฉด ํ ๊ณณ์ด ๋น ์ง ๋ ๊ทธ ์ธ์
๋ง ๋ค๋ฅธ ๊ท์น์ผ๋ก ์ฐ๋ค. ํ ์ค๋ก ๋ชจ์๋ค.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.SESSION_VISIBILITIES = void 0;
|
|
9
|
+
exports.initialVisibility = initialVisibility;
|
|
10
|
+
exports.mayReadSession = mayReadSession;
|
|
11
|
+
exports.SESSION_VISIBILITIES = ['open', 'private'];
|
|
12
|
+
/**
|
|
13
|
+
* ์ด๋ ๊ฒ ๋ง๋ค์ด์ง ์ธ์
์ ๋ฌด์์ผ๋ก ์์ํ๋.
|
|
14
|
+
*
|
|
15
|
+
* ์ต์ปค๊ฐ ์์ผ๋ฉด ๊ณต์ ๋ ๋์์ ๋๊ณ ํ๋ ์ด์ผ๊ธฐ๋ค โ ๊ณต๊ฐ. ์ต์ปค๊ฐ ์๊ฑฐ๋ ์์ ๋ํ๋ฅผ ์ฎ๊ฒจ ์ ์ด ๋ง๋
|
|
16
|
+
* ๊ฒ์ด๋ฉด ๋น๊ณต๊ฐ. `copyOf` ๊ฐ ์๋ค๋ ๊ฒ์ ๋ค๋ฅธ ๋ํ์ ์๋ฌธ์ด ์ด ์์ ๋ค์ด์๋ค๋ ๋ป์ด๊ณ , ๊ทธ ์๋ฌธ์
|
|
17
|
+
* ์๊ธฐ๊ฐ ์๋ ์๋ฆฌ์ ๊ท์น์ผ๋ก ์ฐ์๋ค.
|
|
18
|
+
*/
|
|
19
|
+
function initialVisibility(session) {
|
|
20
|
+
if (session.copyOf)
|
|
21
|
+
return 'private';
|
|
22
|
+
return session.anchorType ? 'open' : 'private';
|
|
23
|
+
}
|
|
24
|
+
/** ์ด ์ฌ๋์ด ์ด ๋ํ๋ฅผ ์ฝ์ ์ ์๋. open ์ด๋ฉด ๋๋ฉ์ธ ์ ๋๊ตฌ๋, private ์ด๋ฉด ์ฐธ์ฌ์๋ง. */
|
|
25
|
+
function mayReadSession(visibility, isParticipant) {
|
|
26
|
+
return (visibility ?? 'open') === 'open' || isParticipant;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=session-visibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-visibility.js","sourceRoot":"","sources":["../../../server/service/chat-session/session-visibility.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAaH,8CAGC;AAGD,wCAEC;AAjBY,QAAA,oBAAoB,GAAiC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAErF;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAAC,OAA+D;IAC/F,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IACpC,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;AAChD,CAAC;AAED,+DAA+D;AAC/D,SAAgB,cAAc,CAAC,UAAqC,EAAE,aAAsB;IAC1F,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,KAAK,MAAM,IAAI,aAAa,CAAA;AAC3D,CAAC","sourcesContent":["/*\n * ์ ๋ํ๊ฐ ๊ณต๊ฐ๋ก ํ์ด๋๋๊ฐ โ ADR-0073 ํ์ 2.\n *\n * ํ์ ์ ์ธ์
์ ๋ง๋๋ ์๋ฆฌ๋ง๋ค ์ ์ผ๋ฉด ํ ๊ณณ์ด ๋น ์ง ๋ ๊ทธ ์ธ์
๋ง ๋ค๋ฅธ ๊ท์น์ผ๋ก ์ฐ๋ค. ํ ์ค๋ก ๋ชจ์๋ค.\n */\n\nexport type SessionVisibility = 'open' | 'private'\n\nexport const SESSION_VISIBILITIES: readonly SessionVisibility[] = ['open', 'private']\n\n/**\n * ์ด๋ ๊ฒ ๋ง๋ค์ด์ง ์ธ์
์ ๋ฌด์์ผ๋ก ์์ํ๋.\n *\n * ์ต์ปค๊ฐ ์์ผ๋ฉด ๊ณต์ ๋ ๋์์ ๋๊ณ ํ๋ ์ด์ผ๊ธฐ๋ค โ ๊ณต๊ฐ. ์ต์ปค๊ฐ ์๊ฑฐ๋ ์์ ๋ํ๋ฅผ ์ฎ๊ฒจ ์ ์ด ๋ง๋ \n * ๊ฒ์ด๋ฉด ๋น๊ณต๊ฐ. `copyOf` ๊ฐ ์๋ค๋ ๊ฒ์ ๋ค๋ฅธ ๋ํ์ ์๋ฌธ์ด ์ด ์์ ๋ค์ด์๋ค๋ ๋ป์ด๊ณ , ๊ทธ ์๋ฌธ์\n * ์๊ธฐ๊ฐ ์๋ ์๋ฆฌ์ ๊ท์น์ผ๋ก ์ฐ์๋ค.\n */\nexport function initialVisibility(session: { anchorType?: string | null; copyOf?: string | null }): SessionVisibility {\n if (session.copyOf) return 'private'\n return session.anchorType ? 'open' : 'private'\n}\n\n/** ์ด ์ฌ๋์ด ์ด ๋ํ๋ฅผ ์ฝ์ ์ ์๋. open ์ด๋ฉด ๋๋ฉ์ธ ์ ๋๊ตฌ๋, private ์ด๋ฉด ์ฐธ์ฌ์๋ง. */\nexport function mayReadSession(visibility: string | null | undefined, isParticipant: boolean): boolean {\n return (visibility ?? 'open') === 'open' || isParticipant\n}\n"]}
|