@things-factory/ai-assistant 10.1.39 → 10.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/client/components/assistant-chat.ts +30 -1
  2. package/client/utils/assistant-request-context.ts +32 -0
  3. package/dist-client/components/assistant-chat.d.ts +12 -0
  4. package/dist-client/components/assistant-chat.js +24 -1
  5. package/dist-client/components/assistant-chat.js.map +1 -1
  6. package/dist-client/tsconfig.tsbuildinfo +1 -1
  7. package/dist-client/utils/assistant-request-context.d.ts +23 -0
  8. package/dist-client/utils/assistant-request-context.js +25 -0
  9. package/dist-client/utils/assistant-request-context.js.map +1 -1
  10. package/dist-server/service/assistant-capability-resolver.js +1 -1
  11. package/dist-server/service/assistant-capability-resolver.js.map +1 -1
  12. package/dist-server/service/assistant-chat-resolver.js +1 -1
  13. package/dist-server/service/assistant-chat-resolver.js.map +1 -1
  14. package/dist-server/service/assistant-mode/assistant-mode-resolver.js +2 -2
  15. package/dist-server/service/assistant-mode/assistant-mode-resolver.js.map +1 -1
  16. package/dist-server/service/chat-session/chat-session.js +1 -1
  17. package/dist-server/service/chat-session/chat-session.js.map +1 -1
  18. package/dist-server/service/chat-session/session-anchor.d.ts +5 -1
  19. package/dist-server/service/chat-session/session-anchor.js +23 -1
  20. package/dist-server/service/chat-session/session-anchor.js.map +1 -1
  21. package/dist-server/service/chat-session-resolver.js +21 -21
  22. package/dist-server/service/chat-session-resolver.js.map +1 -1
  23. package/dist-server/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +4 -4
  25. package/server/service/assistant-capability-resolver.ts +1 -1
  26. package/server/service/assistant-chat-resolver.ts +1 -1
  27. package/server/service/assistant-mode/assistant-mode-resolver.ts +2 -2
  28. package/server/service/chat-session/chat-session.ts +1 -1
  29. package/server/service/chat-session/session-anchor.ts +26 -1
  30. package/server/service/chat-session/session-visibility.test.ts +47 -0
  31. package/server/service/chat-session-resolver.ts +21 -21
  32. package/server/service/session-anchor.test.ts +55 -1
  33. package/test/assistant-request-context.test.ts +41 -1
  34. package/test/open-doors.test.ts +16 -0
@@ -696,7 +696,7 @@ let ChatSessionResolver = class ChatSessionResolver {
696
696
  exports.ChatSessionResolver = ChatSessionResolver;
697
697
  tslib_1.__decorate([
698
698
  (0, type_graphql_1.Query)(() => chat_session_js_1.ChatSession, { nullable: true, description: 'Get AI chat session by id.' }),
699
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query")'),
699
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query", domainOwnerGranted: true)'),
700
700
  tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
701
701
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
702
702
  tslib_1.__metadata("design:type", Function),
@@ -707,7 +707,7 @@ tslib_1.__decorate([
707
707
  (0, type_graphql_1.Query)(() => [chat_session_js_1.ChatSession], {
708
708
  description: 'List AI chat sessions anchored to a target (oldest first). Anchor decides the nature and the history boundary of the conversation: board = authoring, space = the site and the twins running there. Board anchor also matches legacy rows that only have boardId.'
709
709
  }),
710
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query")'),
710
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query", domainOwnerGranted: true)'),
711
711
  tslib_1.__param(0, (0, type_graphql_1.Arg)('anchorType')),
712
712
  tslib_1.__param(1, (0, type_graphql_1.Arg)('anchorId')),
713
713
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -719,7 +719,7 @@ tslib_1.__decorate([
719
719
  (0, type_graphql_1.Query)(() => [ChatSessionInboxEntry], {
720
720
  description: "List sessions anchored to a target with this viewer's unread state, most recent activity first. Supports free-text search over name and last preview, a mine-only filter, hidden inclusion, and paging. Uses the denormalized last-activity timestamp compared against the viewer's read point — no per-session aggregation."
721
721
  }),
722
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query")'),
722
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query", domainOwnerGranted: true)'),
723
723
  tslib_1.__param(0, (0, type_graphql_1.Arg)('anchorType')),
724
724
  tslib_1.__param(1, (0, type_graphql_1.Arg)('anchorId')),
725
725
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -736,7 +736,7 @@ tslib_1.__decorate([
736
736
  (0, type_graphql_1.Query)(() => type_graphql_1.Int, {
737
737
  description: 'Total number of sessions matching the same filters as chatSessionInbox (before paging). Request it alongside the list so the UI can tell "end of page" from "end of data".'
738
738
  }),
739
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query")'),
739
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query", domainOwnerGranted: true)'),
740
740
  tslib_1.__param(0, (0, type_graphql_1.Arg)('anchorType')),
741
741
  tslib_1.__param(1, (0, type_graphql_1.Arg)('anchorId')),
742
742
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -751,7 +751,7 @@ tslib_1.__decorate([
751
751
  (0, type_graphql_1.Query)(() => type_graphql_1.Int, {
752
752
  description: "Number of sessions on this anchor that the caller has hidden and that have had no activity since. Meant to be requested alongside chatSessionInbox in the same operation so the filter can say how many are folded away."
753
753
  }),
754
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query")'),
754
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query", domainOwnerGranted: true)'),
755
755
  tslib_1.__param(0, (0, type_graphql_1.Arg)('anchorType')),
756
756
  tslib_1.__param(1, (0, type_graphql_1.Arg)('anchorId')),
757
757
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -763,7 +763,7 @@ tslib_1.__decorate([
763
763
  (0, type_graphql_1.Mutation)(() => Boolean, {
764
764
  description: 'Delete a chat session — creator only, since a shared deliberation cannot be un-deleted from the UI. Participants who are not the creator can hide it from their own list instead (hideAISession). Soft delete; broadcast as meta activity so every list drops it.'
765
765
  }),
766
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
766
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
767
767
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
768
768
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
769
769
  tslib_1.__metadata("design:type", Function),
@@ -774,7 +774,7 @@ tslib_1.__decorate([
774
774
  (0, type_graphql_1.Mutation)(() => Boolean, {
775
775
  description: 'Hide (or unhide) a session from the calling user\'s own list. Per-user and reversible — the session and other participants are unaffected. Activity newer than the hide makes it reappear; the inbox filter (showHidden) reveals hidden ones.'
776
776
  }),
777
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
777
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
778
778
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
779
779
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
780
780
  tslib_1.__param(2, (0, type_graphql_1.Arg)('hidden', { nullable: true })),
@@ -786,7 +786,7 @@ tslib_1.__decorate([
786
786
  (0, type_graphql_1.Mutation)(() => Boolean, {
787
787
  description: "Open this conversation to everyone in the domain, or close it to its participants. Only the owner may change it. Opening exposes what is already written — the screen says so before asking. Door checks on assistant answers are unaffected (ADR-0073)."
788
788
  }),
789
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
789
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
790
790
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
791
791
  tslib_1.__param(1, (0, type_graphql_1.Arg)('visibility')),
792
792
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -798,7 +798,7 @@ tslib_1.__decorate([
798
798
  (0, type_graphql_1.Mutation)(() => Boolean, {
799
799
  description: 'Rename a chat session. Any participant may rename it — the name is the topic label of a shared deliberation and the change is reversible. Broadcast as meta activity so every participant sees it without raising unread badges.'
800
800
  }),
801
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
801
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
802
802
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
803
803
  tslib_1.__param(1, (0, type_graphql_1.Arg)('name')),
804
804
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -810,7 +810,7 @@ tslib_1.__decorate([
810
810
  (0, type_graphql_1.Mutation)(() => Boolean, {
811
811
  description: "Mark a session as read up to now for the current user. Idempotent. Distinct from presence (lastSeenAt) — a window can be open without being read."
812
812
  }),
813
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
813
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
814
814
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
815
815
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
816
816
  tslib_1.__metadata("design:type", Function),
@@ -821,7 +821,7 @@ tslib_1.__decorate([
821
821
  (0, type_graphql_1.Query)(() => [auth_base_1.User], {
822
822
  description: 'List users in the current domain for the `@` mention popup. Anyone with the chat privilege may search here; this is separate from the admin-only users().'
823
823
  }),
824
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query")'),
824
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query", domainOwnerGranted: true)'),
825
825
  tslib_1.__param(0, (0, type_graphql_1.Arg)('query', { nullable: true, description: 'Substring to match against name/email (case-insensitive). Empty → all.' })),
826
826
  tslib_1.__param(1, (0, type_graphql_1.Arg)('limit', () => type_graphql_1.Int, { nullable: true, defaultValue: 50 })),
827
827
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -833,7 +833,7 @@ tslib_1.__decorate([
833
833
  (0, type_graphql_1.Query)(() => [chat_session_participant_js_1.ChatSessionParticipant], {
834
834
  description: 'List participants of a ChatSession (members / owner).'
835
835
  }),
836
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query")'),
836
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query", domainOwnerGranted: true)'),
837
837
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
838
838
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
839
839
  tslib_1.__metadata("design:type", Function),
@@ -844,7 +844,7 @@ tslib_1.__decorate([
844
844
  (0, type_graphql_1.Mutation)(() => Boolean, {
845
845
  description: 'Presence heartbeat — bump current user\'s lastSeenAt in the session (online indicator).'
846
846
  }),
847
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
847
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
848
848
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
849
849
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
850
850
  tslib_1.__metadata("design:type", Function),
@@ -853,7 +853,7 @@ tslib_1.__decorate([
853
853
  ], ChatSessionResolver.prototype, "touchPresence", null);
854
854
  tslib_1.__decorate([
855
855
  (0, type_graphql_1.Query)(() => [chat_message_js_1.ChatMessage], { description: 'List chat messages of a session, oldest first.' }),
856
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query")'),
856
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "query", domainOwnerGranted: true)'),
857
857
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
858
858
  tslib_1.__param(1, (0, type_graphql_1.Arg)('limit', () => type_graphql_1.Int, { nullable: true, defaultValue: 100 })),
859
859
  tslib_1.__param(2, (0, type_graphql_1.Arg)('offset', () => type_graphql_1.Int, { nullable: true, defaultValue: 0 })),
@@ -867,7 +867,7 @@ tslib_1.__decorate([
867
867
  (0, type_graphql_1.Mutation)(() => chat_session_js_1.ChatSession, {
868
868
  description: 'Start (or get existing) AI chat session anchored to a target. Idempotent — returns first existing or creates one. Use anchorType board for board authoring, space for a site (its co-located twins).'
869
869
  }),
870
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
870
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
871
871
  tslib_1.__param(0, (0, type_graphql_1.Arg)('anchorType')),
872
872
  tslib_1.__param(1, (0, type_graphql_1.Arg)('anchorId')),
873
873
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -880,7 +880,7 @@ tslib_1.__decorate([
880
880
  (0, type_graphql_1.Mutation)(() => chat_session_js_1.ChatSession, {
881
881
  description: 'Always create a new AI chat session anchored to a target (no idempotent reuse). For multi-session UX — opening another tab.'
882
882
  }),
883
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
883
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
884
884
  tslib_1.__param(0, (0, type_graphql_1.Arg)('anchorType')),
885
885
  tslib_1.__param(1, (0, type_graphql_1.Arg)('anchorId')),
886
886
  tslib_1.__param(2, (0, type_graphql_1.Arg)('name', { nullable: true, description: 'Optional name. Defaults to a generated one, numbered within the anchor.' })),
@@ -894,7 +894,7 @@ tslib_1.__decorate([
894
894
  (0, type_graphql_1.Mutation)(() => Boolean, {
895
895
  description: 'Rename a ChatSession (tab label).'
896
896
  }),
897
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
897
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
898
898
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
899
899
  tslib_1.__param(1, (0, type_graphql_1.Arg)('name')),
900
900
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -907,7 +907,7 @@ tslib_1.__decorate([
907
907
  (0, type_graphql_1.Mutation)(() => Boolean, {
908
908
  description: "What the host did with a proposal the assistant made. The host calls this once per card it was asked to run; the server records it as a system row, so the panel shows it, a refreshed panel still shows it, and the model reads on its next turn that its proposal was refused instead of assuming it landed (ADR-0070)."
909
909
  }),
910
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
910
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
911
911
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
912
912
  tslib_1.__param(1, (0, type_graphql_1.Arg)('proposalKey')),
913
913
  tslib_1.__param(2, (0, type_graphql_1.Arg)('outcome', () => graphql_scalars_1.GraphQLJSON)),
@@ -922,7 +922,7 @@ tslib_1.__decorate([
922
922
  nullable: true,
923
923
  description: "Say something to the people in this session. The turn is stored as the speaker's, addressed to the room, and the assistant is not called — it reads the line as context the next time someone asks it something. Returns the stored message id, or null when there was nothing to say (ADR-0070)."
924
924
  }),
925
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
925
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
926
926
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
927
927
  tslib_1.__param(1, (0, type_graphql_1.Arg)('content')),
928
928
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -935,7 +935,7 @@ tslib_1.__decorate([
935
935
  (0, type_graphql_1.Mutation)(() => Boolean, {
936
936
  description: 'Append a system note to a session — context that did not come from a participant typing (e.g. a conversation carried over from another surface, an external state change). The AI sees it as part of the shared history.'
937
937
  }),
938
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
938
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
939
939
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
940
940
  tslib_1.__param(1, (0, type_graphql_1.Arg)('content')),
941
941
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -948,7 +948,7 @@ tslib_1.__decorate([
948
948
  (0, type_graphql_1.Mutation)(() => Boolean, {
949
949
  description: "Carry a conversation from another surface into this session as its own turns, preserving order. A person's turns are stored as theirs, addressed to the room. An assistant turn is stored as the assistant's only when it names its original (sourceSessionId, sourceMessageId) and the server can read it; otherwise it is kept as a quotation on a system row — roles are the server's to write (ADR-0070)."
950
950
  }),
951
- (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation")'),
951
+ (0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
952
952
  tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
953
953
  tslib_1.__param(1, (0, type_graphql_1.Arg)('turns', () => graphql_scalars_1.GraphQLJSON)),
954
954
  tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-resolver.js","sourceRoot":"","sources":["../../server/service/chat-session-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatSession lifecycle resolver — start/get/recordDirectPatch/revertPatch + 메시지·패치 페이징 query.\n *\n * 핵심: `recordDirectPatch` — 사용자가 모델러에서 직접 편집 시 클라이언트가 호출.\n * 이게 PatchEntry(source:'user-direct') + system 메시지 자동 추가 → AI 가 모든 변경을 인지.\n */\nimport { Resolver, Query, Mutation, Arg, Ctx, Directive, Int, ObjectType, Field, ID } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\nimport { User } from '@things-factory/auth-base'\nimport { buildDomainUsersQueryBuilder } from '@things-factory/auth-base/dist-server/utils/get-domain-users.js'\n\nimport { getRepository } from '@things-factory/shell'\nimport { In } from 'typeorm'\n\nimport { ChatSession } from './chat-session/chat-session.js'\nimport { anchorColumns, anchorWhere } from './chat-session/session-anchor.js'\nimport { buildInbox, applyHidden, activityPatch, searchInbox, INBOX_SCAN_CAP } from './chat-session/session-inbox.js'\nimport { carriedOriginalWhere, planCarriedTurns, quoteCarriedAnswer } from './chat-message/carried-turns.js'\nimport { roomMessageBody } from './chat-message/room-message.js'\nimport { readerGate } from './chat-message/reader-gate.js'\nimport { initialVisibility, mayReadSession, SESSION_VISIBILITIES } from './chat-session/session-visibility.js'\nimport { inviteMentionedUsers } from './chat-session-participant/mention-invite.js'\nimport { buildInviteNotification } from './chat-session-participant/invite-notification.js'\n\n/**\n * 초대 알림 — 발송은 호스트의 기전을 그대로 쓴다(중복 구현 금지).\n *\n * 알림이 안 가도 초대 자체는 이미 일어났다. 그래서 실패를 삼키되, 초대를 되돌리지는 않는다 —\n * 참여자 목록이 정본이고 알림은 그것을 알리는 편지다.\n */\nasync function notifyInvited(context: any, invited: string[], inviter: any): Promise<void> {\n if (invited.length === 0) return\n const payload = buildInviteNotification(invited, undefined, inviter)\n if (!payload) return\n try {\n await context.state?.notify?.(payload)\n } catch {\n /* 편지가 못 갔다고 방에 들어온 사실이 취소되지는 않는다. */\n }\n}\nimport { formatProposalOutcomeLine, PROPOSAL_VERDICTS, type ProposalOutcome } from './chat-message/proposal-outcome.js'\nimport { publishSessionActivity } from './chat-session/session-activity-publish.js'\nimport { ChatMessage } from './chat-message/chat-message.js'\nimport { ChatSessionParticipant } from './chat-session-participant/chat-session-participant.js'\nimport { publishChatMessage } from './chat-message/chat-message-publish.js'\n\n@ObjectType({\n description:\n 'Session list entry for the inbox — a session plus this viewer\\'s unread state. Ordered by recent activity so a user can find where to go back to.'\n})\nclass ChatSessionInboxEntry {\n @Field(type => ID, { nullable: true, description: 'Session id.' })\n id?: string\n\n @Field({ nullable: true, description: 'User-given session name (tab label).' })\n name?: string\n\n /** 어느 대화인가 — 목록에서 고른 것이 지금 열린 대화와 다르면 화면이 그 대화로 따라간다. */\n @Field({ nullable: true, description: 'Which conversation this session is — the registered mode kind.' })\n kind?: string\n\n @Field({ nullable: true, description: \"What the session is anchored to: 'board' | 'space' | 'instance' | 'none'.\" })\n anchorType?: string\n\n @Field({ nullable: true, description: 'Id of the anchored target.' })\n anchorId?: string\n\n @Field({ nullable: true, description: 'Connected board id (board-anchored sessions).' })\n boardId?: string\n\n @Field({ nullable: true, description: 'Timestamp of the last message (list ordering / unread comparison).' })\n lastMessageAt?: Date\n\n @Field({ nullable: true, description: 'Short preview of the last message.' })\n lastMessagePreview?: string\n\n /** 미리보기가 이 사람에게 가려져 나갔는가 — 목록도 대화와 같은 관문을 지난다(ADR-0073 판정 1). */\n @Field({ nullable: true, description: 'True when the preview was replaced because this reader does not pass the doors of the message it came from.' })\n previewRedacted?: boolean\n\n @Field({ nullable: true, description: 'Session creation timestamp.' })\n createdAt?: Date\n\n @Field({ description: 'Whether this viewer has unread activity in the session.' })\n unread!: boolean\n\n @Field({ description: 'Whether this viewer is a participant of the session (non-participants get no unread state).' })\n participant!: boolean\n\n /* 삭제는 되돌릴 수 없으므로 **만든 사람**만 한다 — 클라이언트가 버튼을 보일지 판단하는 근거.\n * (권한 판정은 서버가 다시 한다. 이 값은 UI 힌트일 뿐이다.) */\n @Field({ description: 'Whether this viewer created the session — only the creator may delete it.' })\n mine!: boolean\n\n /* 숨김은 나에게만 적용되고 되돌릴 수 있다 — 필터를 켠 사용자가 무엇이 숨겨진 것인지 알아야 한다. */\n @Field({ nullable: true, description: 'Whether this viewer hid the session from their own list (only returned when showHidden is on).' })\n hidden?: boolean\n}\n\n@Resolver()\nexport class ChatSessionResolver {\n @Query(() => ChatSession, { nullable: true, description: 'Get AI chat session by id.' })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\")')\n async chatSession(\n @Arg('id') id: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession | null> {\n const { domain } = context.state\n return (await getRepository(ChatSession).findOneBy({ id, domain: { id: domain.id } })) ?? null\n }\n\n @Query(() => [ChatSession], {\n description:\n 'List AI chat sessions anchored to a target (oldest first). Anchor decides the nature and the history boundary of the conversation: board = authoring, space = the site and the twins running there. Board anchor also matches legacy rows that only have boardId.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\")')\n async chatSessionsByAnchor(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession[]> {\n const { domain } = context.state\n return await getRepository(ChatSession).find({\n where: anchorWhere(domain.id, anchorType, anchorId),\n order: { createdAt: 'ASC' }\n })\n }\n\n /**\n * 받은편지함 — 앵커의 세션 목록 + 내 안 읽음 상태. 최근 활동순.\n * 집계 쿼리를 쓰지 않는다: 세션의 비정규화된 lastMessageAt 과 내 참여자 lastReadAt 을 **값 비교**한다\n * (5개 DB 드라이버 지원 때문에 group by/MAX 를 목록 경로에 두지 않는다).\n */\n @Query(() => [ChatSessionInboxEntry], {\n description:\n \"List sessions anchored to a target with this viewer's unread state, most recent activity first. Supports free-text search over name and last preview, a mine-only filter, hidden inclusion, and paging. Uses the denormalized last-activity timestamp compared against the viewer's read point — no per-session aggregation.\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\")')\n async chatSessionInbox(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext,\n /* 숨긴 대화 보기 — 숨김이 한 번 넣으면 못 꺼내는 함정이 되지 않도록 필터를 준다. */\n @Arg('showHidden', { nullable: true }) showHidden?: boolean,\n /* 대량 목록 대응 — 검색·소유 필터·페이지. 목록 UI 는 처음부터 이걸 갖고 있어야 한다. */\n @Arg('search', { nullable: true }) search?: string,\n @Arg('mineOnly', { nullable: true }) mineOnly?: boolean,\n @Arg('limit', () => Int, { nullable: true }) limit?: number,\n @Arg('offset', () => Int, { nullable: true }) offset?: number\n ): Promise<ChatSessionInboxEntry[]> {\n const filtered = await this._inboxFiltered(anchorType, anchorId, context, { showHidden, search, mineOnly })\n const from = Math.max(0, offset ?? 0)\n const size = Math.min(Math.max(1, limit ?? 50), 200)\n return filtered.slice(from, from + size) as any\n }\n\n /**\n * 필터를 통과한 **전체 개수** — \"더 보기\" 가 남았는지, 검색 결과가 몇 건인지.\n *\n * 목록과 같은 요청에 담아 가져가므로 왕복은 늘지 않는다. 개수를 모르면 사용자는 목록의 끝이\n * 페이지의 끝인지 자료의 끝인지 구별할 수 없다.\n */\n @Query(() => Int, {\n description:\n 'Total number of sessions matching the same filters as chatSessionInbox (before paging). Request it alongside the list so the UI can tell \"end of page\" from \"end of data\".'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\")')\n async chatSessionInboxTotal(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext,\n @Arg('showHidden', { nullable: true }) showHidden?: boolean,\n @Arg('search', { nullable: true }) search?: string,\n @Arg('mineOnly', { nullable: true }) mineOnly?: boolean\n ): Promise<number> {\n return (await this._inboxFiltered(anchorType, anchorId, context, { showHidden, search, mineOnly })).length\n }\n\n /** 필터 적용(페이지 전) — 목록·개수가 **같은 규칙**을 쓰도록 한 곳에 둔다(어긋나면 \"더 보기\" 가 거짓말이 된다). */\n private async _inboxFiltered(\n anchorType: string,\n anchorId: string,\n context: ResolverContext,\n opts: { showHidden?: boolean; search?: string; mineOnly?: boolean }\n ): Promise<ChatSessionInboxEntry[]> {\n const all = await this._inboxEntries(anchorType, anchorId, context)\n let entries = opts.showHidden ? all : all.filter(e => !e.hidden)\n if (opts.mineOnly) entries = entries.filter(e => (e as any).mine)\n return searchInbox(entries as any, opts.search) as any\n }\n\n /**\n * 내가 숨긴 대화 수 — 필터에 \"몇 개가 접혀 있는지\" 를 보여주기 위한 값.\n *\n * 숨긴 것이 몇 개인지 모르면 필터를 눌러 볼 이유가 생기지 않는다(숨긴 사실 자체를 잊는다).\n * 목록 조회와 **같은 요청**에 담아 가져갈 수 있으므로 왕복은 늘지 않는다.\n */\n @Query(() => Int, {\n description:\n \"Number of sessions on this anchor that the caller has hidden and that have had no activity since. Meant to be requested alongside chatSessionInbox in the same operation so the filter can say how many are folded away.\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\")')\n async hiddenSessionCount(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext\n ): Promise<number> {\n const all = await this._inboxEntries(anchorType, anchorId, context)\n return all.filter(e => e.hidden).length\n }\n\n /** 목록 조립 — 숨김 표시까지 붙인 **전체**. 목록·개수 두 진입점이 같은 규칙을 쓰도록 한 곳에 둔다. */\n private async _inboxEntries(\n anchorType: string,\n anchorId: string,\n context: ResolverContext\n ): Promise<ChatSessionInboxEntry[]> {\n const { domain, user } = context.state\n /* 조회 상한 — 한 앵커의 대화가 아무리 늘어도 한 번에 이만큼만 훑는다. 최근 활동순으로 자른다\n * (오래된 대화가 잘리는 것이 최근 대화가 잘리는 것보다 낫다). 정렬·검색·페이지는 순수 로직이 한다. */\n const sessions = await getRepository(ChatSession).find({\n where: anchorWhere(domain.id, anchorType, anchorId),\n order: { lastMessageAt: 'DESC' },\n take: INBOX_SCAN_CAP\n })\n if (sessions.length === 0) return []\n const rows = await getRepository(ChatSessionParticipant).find({\n where: { domain: { id: domain.id } as any, user: { id: user.id } as any, session: { id: In(sessions.map(s => s.id!)) } as any }\n })\n /* 'viewer' 는 대화에 낀 사람이 아니다 — 숨김을 기록하려고 만든 행이므로 읽음·안 읽음 판정에서 뺀다.\n * (참여자가 아닌 사람에게 남의 협의 배지를 띄우지 않는다.) */\n const participations = rows.filter(r => r.role !== 'viewer')\n const hiddenAt = new Map(rows.map(r => [(r as any).sessionId as string, r.hiddenAt]))\n /* 내가 만든 대화인지 표시 — 삭제 버튼을 보일지 결정하는 UI 힌트(권한은 서버가 다시 판정한다). */\n const createdByMe = new Set(sessions.filter(s => (s as any).creatorId === user?.id).map(s => s.id))\n const entries = buildInbox(sessions as any, participations as any).map(entry => ({\n ...entry,\n mine: createdByMe.has(entry.id)\n }))\n /* showHidden=true 로 불러 **전체**를 얻는다 — 숨김 여부 판정을 두 곳에 복제하지 않기 위함. */\n const shown = applyHidden(entries as any, hiddenAt, true) as any[]\n\n /*\n * 목록도 같은 관문을 지난다 — ADR-0073 판정 1. 미리보기는 그 답을 **다시 읽는 두 번째 길**이고,\n * 한 길만 막으면 같은 문장이 다른 길로 그대로 나간다. 미리보기 자리를 `content` 로 바꿔 넣고\n * 가려진 것만 되돌려 담는다.\n */\n const gate = readerGate(context)\n const judged = await gate(\n shown.map(entry => ({ doors: entry.lastMessageDoors, content: entry.lastMessagePreview ?? '' }))\n )\n return shown.map((entry, index) => ({\n ...entry,\n lastMessagePreview: judged[index].content,\n previewRedacted: (judged[index] as any).redacted === true\n })) as any\n }\n\n /**\n * 세션 삭제 — **만든 사람만.**\n *\n * 협의는 여럿의 기록이고 삭제는 화면에서 되돌릴 수 없다. 그래서 권한을 좁힌다(이름 변경은 되돌릴 수\n * 있어서 누구나 할 수 있는 것과 대비). 권한이 없는 사람에게는 `hideAISession`(내 목록에서만 숨김)이\n * 있다 — 남의 기록을 지우지 않고 자기 목록을 정리하는 길.\n *\n * 소프트 삭제(deletedAt)다 — 메시지·패치는 세션을 통해서만 도달하므로 함께 사라지고, 잘못 지운 경우\n * 데이터로는 남아 있다. 다른 참여자 목록에서도 사라져야 하므로 meta 활동으로 방송한다.\n */\n @Mutation(() => Boolean, {\n description:\n 'Delete a chat session — creator only, since a shared deliberation cannot be un-deleted from the UI. Participants who are not the creator can hide it from their own list instead (hideAISession). Soft delete; broadcast as meta activity so every list drops it.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async deleteAISession(@Arg('sessionId') sessionId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, user } = context.state\n const repo = getRepository(ChatSession)\n const session = await repo.findOneBy({ id: sessionId, domain: { id: domain.id } as any })\n if (!session) return false\n if (!user?.id || (session as any).creatorId !== user.id) {\n /* 조용한 무동작이 아니라 명시 실패 — 지워진 줄 알고 넘어가면 안 된다. */\n throw new Error('Only the user who created this session may delete it. Hide it from your own list instead.')\n }\n await repo.softDelete(sessionId)\n publishSessionActivity({\n domainId: domain.id,\n sessionId,\n kind: 'meta',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n actorId: user?.id\n })\n return true\n }\n\n /**\n * 내 목록에서 숨기기·되돌리기 — **나에게만** 적용된다(대화·다른 참여자 목록은 그대로).\n *\n * 참여자가 아니어도 숨길 수 있어야 한다 — 목록에는 같은 공간의 남의 협의도 보이고, 그것을 정리하는\n * 것은 남에게 아무 영향이 없다. 그 경우 'viewer' 역할로 기록만 남긴다(참여자 명부·배지에는 들지 않는다).\n */\n @Mutation(() => Boolean, {\n description:\n 'Hide (or unhide) a session from the calling user\\'s own list. Per-user and reversible — the session and other participants are unaffected. Activity newer than the hide makes it reappear; the inbox filter (showHidden) reveals hidden ones.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async hideAISession(\n @Arg('sessionId') sessionId: string,\n @Ctx() context: ResolverContext,\n @Arg('hidden', { nullable: true }) hidden?: boolean\n ): Promise<boolean> {\n const { domain, user } = context.state\n if (!user?.id) return false\n const session = await getRepository(ChatSession).findOneBy({ id: sessionId, domain: { id: domain.id } as any })\n if (!session) return false\n const repo = getRepository(ChatSessionParticipant)\n const existing = await repo.findOne({\n where: { domain: { id: domain.id } as any, session: { id: sessionId } as any, user: { id: user.id } as any }\n })\n const hiddenAt = hidden === false ? null : new Date()\n if (existing) {\n await repo.update(existing.id!, { hiddenAt, updater: user } as any)\n } else {\n if (hidden === false) return true // 숨긴 적이 없으면 되돌릴 것도 없다\n await repo.save({\n domain: { id: domain.id } as any,\n session: { id: sessionId } as any,\n user: { id: user.id } as any,\n role: 'viewer', // 대화에 낀 것이 아니라 숨김만 기록한다\n hiddenAt,\n creator: user,\n updater: user\n } as any)\n }\n return true\n }\n\n /**\n * 세션 이름 변경 — **참여자 누구나** 할 수 있다.\n *\n * 왜 소유자 전용이 아닌가: 이름은 대화의 주제표이고 협의는 여럿이 한다. 논의가 흘러 주제가 달라졌는데\n * 만든 사람만 고칠 수 있으면 그 사람이 없을 때 목록이 계속 어긋난다. 되돌릴 수 있는 변경이고 대화\n * 내용에 영향이 없으므로 권한을 좁힐 이유가 없다(되돌릴 수 없는 것만 좁힌다).\n *\n * 변경은 **meta 활동**으로 방송한다 — 모든 참여자 목록에 즉시 반영되지만 안 읽음 배지는 올리지 않는다\n * (이름 변경을 \"새 소식\" 으로 알리면 소음이다).\n */\n /**\n * 이 대화를 도메인 안 누구나 읽게 할 것인가 — ADR-0073 판정 2.\n *\n * owner 만 바꾼다. 이름 바꾸기는 어느 참여자나 하지만(되돌릴 수 있고 값을 드러내지 않는다), 공개로\n * 바꾸는 일은 이미 쓰인 글을 도메인 전체에 여는 일이다 — 되돌려도 읽힌 것은 읽힌 것이다.\n *\n * 화면은 공개로 바꾸기 전에 한 줄을 먼저 보인다(문구는 클라이언트가 가진다). 그 한 줄은 이 문이\n * 강제하지 않는다 — 문이 막을 수 있는 것은 누가 바꾸느냐까지다.\n */\n @Mutation(() => Boolean, {\n description:\n \"Open this conversation to everyone in the domain, or close it to its participants. Only the owner may change it. Opening exposes what is already written — the screen says so before asking. Door checks on assistant answers are unaffected (ADR-0073).\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async setSessionVisibility(\n @Arg('sessionId') sessionId: string,\n @Arg('visibility') visibility: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user } = context.state\n if (!SESSION_VISIBILITIES.includes(visibility as any)) {\n throw new Error(`unknown visibility '${visibility}' — use ${SESSION_VISIBILITIES.join(' or ')}`)\n }\n\n const session = await getRepository(ChatSession).findOneBy({ id: sessionId, domain: { id: domain.id } as any })\n if (!session) return false\n\n const mine = await getRepository(ChatSessionParticipant).findOne({\n where: { domain: { id: domain.id } as any, session: { id: sessionId } as any, user: { id: user.id } as any }\n })\n if (mine?.role !== 'owner') return false\n\n if ((session as any).visibility === visibility) return true\n\n await getRepository(ChatSession).update(sessionId, { visibility, updater: user } as any)\n publishSessionActivity({\n domainId: domain.id,\n sessionId,\n kind: 'meta',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n actorId: user?.id\n } as any)\n return true\n }\n\n @Mutation(() => Boolean, {\n description:\n 'Rename a chat session. Any participant may rename it — the name is the topic label of a shared deliberation and the change is reversible. Broadcast as meta activity so every participant sees it without raising unread badges.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async renameAISession(\n @Arg('sessionId') sessionId: string,\n @Arg('name') name: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user } = context.state\n const trimmed = (name ?? '').trim().slice(0, 200)\n if (!trimmed) return false // 빈 이름으로 지우지 않는다 — 지우려면 별도 의도가 필요하다\n const participant = await getRepository(ChatSessionParticipant).findOne({\n where: { domain: { id: domain.id } as any, session: { id: sessionId } as any, user: { id: user.id } as any }\n })\n if (!participant) return false // 참여자가 아니면 남의 대화 제목을 바꿀 수 없다\n const session = await getRepository(ChatSession).findOneBy({ id: sessionId, domain: { id: domain.id } as any })\n if (!session) return false\n await getRepository(ChatSession).update(sessionId, { name: trimmed, updater: user } as any)\n publishSessionActivity({\n domainId: domain.id,\n sessionId,\n kind: 'meta',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n actorId: user?.id\n })\n return true\n }\n\n /**\n * 읽은 지점 갱신 — 이 세션을 여기까지 읽었다. 멱등(여러 번 호출해도 최신 시각으로만 이동).\n * 접속 표시(lastSeenAt)와 분리한다 — 창을 열어 두고 화면을 안 볼 수 있다.\n */\n @Mutation(() => Boolean, {\n description:\n \"Mark a session as read up to now for the current user. Idempotent. Distinct from presence (lastSeenAt) — a window can be open without being read.\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async markSessionRead(\n @Arg('sessionId') sessionId: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user } = context.state\n const repo = getRepository(ChatSessionParticipant)\n const mine = await repo.findOne({\n where: { domain: { id: domain.id } as any, session: { id: sessionId } as any, user: { id: user.id } as any }\n })\n /* 참여자가 아니면 읽음 상태를 만들지 않는다 — 참여하지 않은 대화에 내 읽음 지점을 남기지 않는다. */\n if (!mine) return false\n await repo.update(mine.id!, { lastReadAt: new Date(), updater: user } as any)\n return true\n }\n\n @Query(() => [User], {\n description:\n 'List users in the current domain for the `@` mention popup. Anyone with the chat privilege may search here; this is separate from the admin-only users().'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\")')\n async domainUsersForMention(\n @Arg('query', { nullable: true, description: 'Substring to match against name/email (case-insensitive). Empty → all.' }) query: string | undefined,\n @Arg('limit', () => Int, { nullable: true, defaultValue: 50 }) limit: number,\n @Ctx() context: ResolverContext\n ): Promise<User[]> {\n const { domain } = context.state\n const qb = buildDomainUsersQueryBuilder(domain.id, 'USER')\n if (query?.trim()) {\n const q = `%${query.trim().toLowerCase()}%`\n qb.andWhere('(LOWER(USER.name) LIKE :q OR LOWER(USER.email) LIKE :q)', { q })\n }\n qb.orderBy('USER.name', 'ASC').limit(limit)\n return await qb.getMany()\n }\n\n @Query(() => [ChatSessionParticipant], {\n description: 'List participants of a ChatSession (members / owner).'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\")')\n async chatSessionParticipants(\n @Arg('sessionId') sessionId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSessionParticipant[]> {\n const { domain } = context.state\n const session = await getRepository(ChatSession).findOneBy({\n id: sessionId,\n domain: { id: domain.id }\n })\n if (!session) return []\n return await getRepository(ChatSessionParticipant).find({\n where: { session: { id: sessionId } as any, domain: { id: domain.id } },\n order: { createdAt: 'ASC' }\n })\n }\n\n @Mutation(() => Boolean, {\n description: 'Presence heartbeat — bump current user\\'s lastSeenAt in the session (online indicator).'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async touchPresence(@Arg('sessionId') sessionId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, user } = context.state\n const repo = getRepository(ChatSessionParticipant)\n const part = await repo.findOne({\n where: { session: { id: sessionId } as any, user: { id: user.id } as any, domain: { id: domain.id } as any }\n })\n if (!part) return false // 참여자가 아니면 heartbeat 무시 (초대 전)\n await repo.update(part.id!, { lastSeenAt: new Date(), updater: user } as any)\n return true\n }\n\n @Query(() => [ChatMessage], { description: 'List chat messages of a session, oldest first.' })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\")')\n async chatMessages(\n @Arg('sessionId') sessionId: string,\n @Arg('limit', () => Int, { nullable: true, defaultValue: 100 }) limit: number,\n @Arg('offset', () => Int, { nullable: true, defaultValue: 0 }) offset: number,\n @Ctx() context: ResolverContext\n ): Promise<ChatMessage[]> {\n const { domain, user } = context.state\n const session = await getRepository(ChatSession).findOneBy({\n id: sessionId,\n domain: { id: domain.id }\n })\n if (!session) return []\n\n /*\n * 공개 대화는 도메인 안이면 누구나 읽는다 — 초대 절차가 없다(ADR-0073 판정 2). 비공개 대화는\n * 참여자만. 여기서 막히는 것은 **방**이고, 방에 들어온 뒤 값을 읽는 일은 아래 문 판정이 따로 본다.\n */\n if ((session as any).visibility === 'private') {\n const part = await getRepository(ChatSessionParticipant).findOne({\n where: { session: { id: sessionId } as any, user: { id: user.id } as any, domain: { id: domain.id } as any }\n })\n if (!mayReadSession((session as any).visibility, !!part)) return []\n }\n\n const rows = await getRepository(ChatMessage).find({\n where: { session: { id: sessionId } as any },\n // creator: 그룹챗 발신자 표시(name) + 자기 여부 판정(email). 내부 관리키(id)에 의존하지 않는다.\n relations: { creator: true },\n order: { createdAt: 'ASC' },\n take: limit,\n skip: offset\n })\n\n /*\n * 어시스턴트의 답은 도구 결과를 평문으로 옮겨 적은 것이다. 읽는 사람이 그 도구가 지난 문을 못 지나면\n * 본문 대신 한 줄이 나간다 — 행이 있다는 사실은 보이고 값만 안 보인다(ADR-0073 판정 1).\n */\n return await readerGate(context)(rows)\n }\n\n @Directive('@transaction')\n @Mutation(() => ChatSession, {\n description:\n 'Start (or get existing) AI chat session anchored to a target. Idempotent — returns first existing or creates one. Use anchorType board for board authoring, space for a site (its co-located twins).'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async startAISession(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n\n const existing = await repo.findOneBy(anchorWhere(domain.id, anchorType, anchorId))\n if (existing) return existing\n\n const session = await repo.save({\n domain,\n ...anchorColumns(anchorType, anchorId),\n /* 앵커가 있는 대화는 공개로 태어난다 — ADR-0073 판정 2. */\n visibility: initialVisibility({ anchorType }),\n creator: user,\n updater: user\n } as any)\n // creator 를 owner participant 로 자동 등록 — 다자간 채팅 기반.\n await getRepository(ChatSessionParticipant, tx).save({\n domain,\n session: { id: session.id } as any,\n user,\n role: 'owner',\n creator: user,\n updater: user\n } as any)\n return session\n }\n\n @Directive('@transaction')\n @Mutation(() => ChatSession, {\n description:\n 'Always create a new AI chat session anchored to a target (no idempotent reuse). For multi-session UX — opening another tab.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async createAISession(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Arg('name', { nullable: true, description: 'Optional name. Defaults to a generated one, numbered within the anchor.' }) name: string | undefined,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n\n // 이름 미지정 시 자동 생성 — **같은 앵커**의 기존 세션 수 + 1.\n let finalName = name?.trim()\n if (!finalName) {\n const count = await repo.count({ where: anchorWhere(domain.id, anchorType, anchorId) })\n /* The name is stored, so it is written in the language of whoever created it (context.t), and read back as is. */\n finalName = context.t('ai-assistant.session.default-name', { n: count + 1, defaultValue: 'conversation {n}' })\n }\n\n const session = await repo.save({\n domain,\n ...anchorColumns(anchorType, anchorId),\n visibility: initialVisibility({ anchorType }),\n creator: user,\n updater: user,\n name: finalName\n } as any)\n // creator 를 owner participant 로 자동 등록.\n await getRepository(ChatSessionParticipant, tx).save({\n domain,\n session: { id: session.id } as any,\n user,\n role: 'owner',\n creator: user,\n updater: user\n } as any)\n return session\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description: 'Rename a ChatSession (tab label).'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async renameChatSession(\n @Arg('sessionId') sessionId: string,\n @Arg('name') name: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n const session = await repo.findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n await repo.update(sessionId, { name: name.trim() || null, updater: user } as any)\n return true\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description:\n \"What the host did with a proposal the assistant made. The host calls this once per card it was asked to run; the server records it as a system row, so the panel shows it, a refreshed panel still shows it, and the model reads on its next turn that its proposal was refused instead of assuming it landed (ADR-0070).\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async reportProposalOutcome(\n @Arg('sessionId') sessionId: string,\n @Arg('proposalKey') proposalKey: string,\n @Arg('outcome', () => GraphQLJSON) outcome: ProposalOutcome,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n\n const key = (proposalKey ?? '').trim()\n if (!key) return false\n\n /*\n * 낱말은 ADR-0042 의 것에 `declined` 하나다. 모르는 낱말을 받으면 그대로 적지 않는다 — 카드가\n * 읽지 못하는 상태가 되고, 그때 화면은 아무 말도 못 한다.\n */\n if (!PROPOSAL_VERDICTS.includes(outcome?.verdict as any)) {\n throw new Error(\n `[ai-assistant] '${outcome?.verdict}' is not a proposal verdict. Use one of ${PROPOSAL_VERDICTS.join(', ')}.`\n )\n }\n\n const body = formatProposalOutcomeLine(key, outcome)\n\n const previousLast = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const sysMsg = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: 'system',\n content: body,\n creator: user,\n updater: user,\n parentMessage: previousLast ? ({ id: previousLast.id } as any) : undefined\n } as any)\n\n /* 목록의 미리보기는 사람의 말로 두는 편이 낫다 — 이 줄은 기계의 기록이다. 방송만 한다. */\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message: sysMsg })\n return true\n }\n\n @Directive('@transaction')\n @Mutation(() => String, {\n nullable: true,\n description:\n \"Say something to the people in this session. The turn is stored as the speaker's, addressed to the room, and the assistant is not called — it reads the line as context the next time someone asks it something. Returns the stored message id, or null when there was nothing to say (ADR-0070).\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async sayToRoom(\n @Arg('sessionId') sessionId: string,\n @Arg('content') content: string,\n @Ctx() context: ResolverContext\n ): Promise<string | null> {\n const { domain, user, tx } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n\n const body = roomMessageBody(content)\n if (!body) return null\n\n const previousLast = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const saved = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: 'user',\n content: body,\n /* 대상은 문이 정한다 — 이 문은 사람들에게 하는 말이다(ADR-0070 A15 결정 ①). */\n addressee: 'room',\n creator: user,\n updater: user,\n parentMessage: previousLast ? ({ id: previousLast.id } as any) : undefined\n } as any)\n\n /*\n * 멘션은 사람을 불러들인다 — **사람의 말을 저장하는 문**만 이것을 한다(ADR-0071 결정 1 ①).\n * 초대는 방에 있는 사람(owner · member)만 할 수 있고, 거절되면 그 사실이 화면으로 돌아간다.\n */\n const invite = await inviteMentionedUsers({\n content: body,\n sessionId: session.id!,\n domainId: domain.id,\n inviter: user,\n participants: getRepository(ChatSessionParticipant, tx),\n /* 비공개 대화에서는 이름만 닿는다 — ADR-0073 판정 2. */\n visibility: (session as any).visibility\n })\n await notifyInvited(context, invite.invited, user)\n\n /* 사람의 말이다 — 목록의 최근 활동과 다른 참여자의 안 읽음이 이것으로 움직인다. */\n try {\n await getRepository(ChatSession, tx).update(session.id!, activityPatch(body) as any)\n } catch {\n /* 목록이 한 박자 늦는 것이 말을 못 하게 할 이유는 아니다. */\n }\n publishSessionActivity({\n domainId: domain.id,\n sessionId: session.id!,\n kind: 'message',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n preview: body,\n actorId: user?.id\n })\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message: saved })\n\n return saved.id ?? null\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description:\n 'Append a system note to a session — context that did not come from a participant typing (e.g. a conversation carried over from another surface, an external state change). The AI sees it as part of the shared history.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async appendSessionNote(\n @Arg('sessionId') sessionId: string,\n @Arg('content') content: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n /* 프롬프트가 한 기록으로 폭증하지 않도록 자른다 — 맥락 전달이 목적이고 전문 보존이 아니다. */\n const body = (content ?? '').trim().slice(0, 4000)\n if (!body) return false\n\n const previousLast = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const sysMsg = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: 'system',\n content: body,\n creator: user,\n updater: user,\n parentMessage: previousLast ? ({ id: previousLast.id } as any) : undefined\n } as any)\n\n /* 활동 갱신 + 방송 — 다른 참여자 목록·안 읽음과 열려 있는 화면의 transcript 일관성. best-effort. */\n try {\n await getRepository(ChatSession, tx).update(session.id!, activityPatch(body) as any)\n } catch {\n /* 기록 자체를 막지 않는다 */\n }\n publishSessionActivity({\n domainId: domain.id,\n sessionId: session.id!,\n kind: 'message',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n preview: body,\n actorId: user?.id\n })\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message: sysMsg })\n return true\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description:\n \"Carry a conversation from another surface into this session as its own turns, preserving order. A person's turns are stored as theirs, addressed to the room. An assistant turn is stored as the assistant's only when it names its original (sourceSessionId, sourceMessageId) and the server can read it; otherwise it is kept as a quotation on a system row — roles are the server's to write (ADR-0070).\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\")')\n async appendSessionTurns(\n @Arg('sessionId') sessionId: string,\n @Arg('turns', () => GraphQLJSON) turns: { role?: string; content?: string }[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n\n /* 옮겨온 대화는 **그 대화의 발언 그대로** 들어간다 — 한 덩어리 기록으로 뭉치면 사람이 읽을 수 없고\n * (화면 하나를 잡아먹는 이탤릭 덩어리), 마크다운도 죽는다. 대신 개수·길이는 제한한다: 맥락 전달이\n * 목적이고 전문 보존이 아니다. */\n /* **역할은 서버가 쓴다**(ADR-0070 A15 결정 ③). 어시스턴트의 답은 원본을 읽어 복사하고, 원본이 없으면\n * 인용문으로 `system` 행에 남긴다 — 클라이언트가 보낸 글자를 어시스턴트의 말로 저장하지 않는다. */\n const planned = planCarriedTurns(turns as any)\n const rows: { role: string; content: string; addressee?: string; doors?: string[] }[] = []\n /* 옮겨 적힌 원문이 소급해서 공개되지 않게, 받는 대화는 이 순간부터 비공개다 — ADR-0073 판정 2. */\n let carried = false\n for (const row of planned) {\n if (!row.copyOf) {\n rows.push({ role: row.role, content: row.content, addressee: row.addressee })\n continue\n }\n /* 원본은 이 테넌트 안에서만 찾는다 — 남의 도메인 메시지를 옮겨 오는 길이 되지 않게. */\n const original = await getRepository(ChatMessage, tx).findOne({\n where: carriedOriginalWhere(domain.id, row.copyOf),\n relations: ['session']\n })\n carried = true\n if (original && original.role === 'assistant') {\n /*\n * 답과 함께 **그 답이 지나온 문**을 옮긴다 — ADR-0073 판정 1. 문을 두고 글만 옮기면, 문 하나를\n * 지나 얻은 값이 문 없는 행이 되어 아무나 읽는다. 옮겨 적기가 권한을 씻는 길이 된다.\n */\n rows.push({ role: 'assistant', content: original.content, doors: (original as any).doors ?? [] })\n } else {\n /* 인용문에도 원문의 문을 실어 둔다 — 인용이라고 값이 달라지지 않는다. */\n rows.push({ role: 'system', content: quoteCarriedAnswer(row.content), doors: (original as any)?.doors ?? [] })\n }\n }\n if (!rows.length) return false\n\n let previous = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const saved: ChatMessage[] = []\n for (const row of rows) {\n previous = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: row.role,\n content: row.content,\n /* 사람의 말은 방을 향한 것이다 — 이 문은 어시스턴트를 부르는 문이 아니다. */\n addressee: row.addressee,\n doors: row.doors,\n creator: user,\n updater: user,\n parentMessage: previous ? ({ id: previous.id } as any) : undefined\n } as any)\n saved.push(previous!)\n }\n\n if (carried && (session as any).visibility !== 'private') {\n await getRepository(ChatSession, tx).update(session.id!, { visibility: 'private', updater: user } as any)\n }\n\n /* 활동은 마지막 발언 기준 한 번만 — 옮긴 줄마다 목록을 흔들 이유가 없다. */\n const last = rows[rows.length - 1]\n try {\n await getRepository(ChatSession, tx).update(session.id!, activityPatch(last.content) as any)\n } catch {\n /* best-effort — 옮기기 자체를 막지 않는다 */\n }\n publishSessionActivity({\n domainId: domain.id,\n sessionId: session.id!,\n kind: 'message',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n preview: last.content,\n actorId: user?.id\n })\n for (const message of saved) {\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message })\n }\n return true\n }\n\n}\n"]}
1
+ {"version":3,"file":"chat-session-resolver.js","sourceRoot":"","sources":["../../server/service/chat-session-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatSession lifecycle resolver — start/get/recordDirectPatch/revertPatch + 메시지·패치 페이징 query.\n *\n * 핵심: `recordDirectPatch` — 사용자가 모델러에서 직접 편집 시 클라이언트가 호출.\n * 이게 PatchEntry(source:'user-direct') + system 메시지 자동 추가 → AI 가 모든 변경을 인지.\n */\nimport { Resolver, Query, Mutation, Arg, Ctx, Directive, Int, ObjectType, Field, ID } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\nimport { User } from '@things-factory/auth-base'\nimport { buildDomainUsersQueryBuilder } from '@things-factory/auth-base/dist-server/utils/get-domain-users.js'\n\nimport { getRepository } from '@things-factory/shell'\nimport { In } from 'typeorm'\n\nimport { ChatSession } from './chat-session/chat-session.js'\nimport { anchorColumns, anchorWhere } from './chat-session/session-anchor.js'\nimport { buildInbox, applyHidden, activityPatch, searchInbox, INBOX_SCAN_CAP } from './chat-session/session-inbox.js'\nimport { carriedOriginalWhere, planCarriedTurns, quoteCarriedAnswer } from './chat-message/carried-turns.js'\nimport { roomMessageBody } from './chat-message/room-message.js'\nimport { readerGate } from './chat-message/reader-gate.js'\nimport { initialVisibility, mayReadSession, SESSION_VISIBILITIES } from './chat-session/session-visibility.js'\nimport { inviteMentionedUsers } from './chat-session-participant/mention-invite.js'\nimport { buildInviteNotification } from './chat-session-participant/invite-notification.js'\n\n/**\n * 초대 알림 — 발송은 호스트의 기전을 그대로 쓴다(중복 구현 금지).\n *\n * 알림이 안 가도 초대 자체는 이미 일어났다. 그래서 실패를 삼키되, 초대를 되돌리지는 않는다 —\n * 참여자 목록이 정본이고 알림은 그것을 알리는 편지다.\n */\nasync function notifyInvited(context: any, invited: string[], inviter: any): Promise<void> {\n if (invited.length === 0) return\n const payload = buildInviteNotification(invited, undefined, inviter)\n if (!payload) return\n try {\n await context.state?.notify?.(payload)\n } catch {\n /* 편지가 못 갔다고 방에 들어온 사실이 취소되지는 않는다. */\n }\n}\nimport { formatProposalOutcomeLine, PROPOSAL_VERDICTS, type ProposalOutcome } from './chat-message/proposal-outcome.js'\nimport { publishSessionActivity } from './chat-session/session-activity-publish.js'\nimport { ChatMessage } from './chat-message/chat-message.js'\nimport { ChatSessionParticipant } from './chat-session-participant/chat-session-participant.js'\nimport { publishChatMessage } from './chat-message/chat-message-publish.js'\n\n@ObjectType({\n description:\n 'Session list entry for the inbox — a session plus this viewer\\'s unread state. Ordered by recent activity so a user can find where to go back to.'\n})\nclass ChatSessionInboxEntry {\n @Field(type => ID, { nullable: true, description: 'Session id.' })\n id?: string\n\n @Field({ nullable: true, description: 'User-given session name (tab label).' })\n name?: string\n\n /** 어느 대화인가 — 목록에서 고른 것이 지금 열린 대화와 다르면 화면이 그 대화로 따라간다. */\n @Field({ nullable: true, description: 'Which conversation this session is — the registered mode kind.' })\n kind?: string\n\n @Field({ nullable: true, description: \"What the session is anchored to: 'board' | 'space' | 'instance' | 'none'.\" })\n anchorType?: string\n\n @Field({ nullable: true, description: 'Id of the anchored target.' })\n anchorId?: string\n\n @Field({ nullable: true, description: 'Connected board id (board-anchored sessions).' })\n boardId?: string\n\n @Field({ nullable: true, description: 'Timestamp of the last message (list ordering / unread comparison).' })\n lastMessageAt?: Date\n\n @Field({ nullable: true, description: 'Short preview of the last message.' })\n lastMessagePreview?: string\n\n /** 미리보기가 이 사람에게 가려져 나갔는가 — 목록도 대화와 같은 관문을 지난다(ADR-0073 판정 1). */\n @Field({ nullable: true, description: 'True when the preview was replaced because this reader does not pass the doors of the message it came from.' })\n previewRedacted?: boolean\n\n @Field({ nullable: true, description: 'Session creation timestamp.' })\n createdAt?: Date\n\n @Field({ description: 'Whether this viewer has unread activity in the session.' })\n unread!: boolean\n\n @Field({ description: 'Whether this viewer is a participant of the session (non-participants get no unread state).' })\n participant!: boolean\n\n /* 삭제는 되돌릴 수 없으므로 **만든 사람**만 한다 — 클라이언트가 버튼을 보일지 판단하는 근거.\n * (권한 판정은 서버가 다시 한다. 이 값은 UI 힌트일 뿐이다.) */\n @Field({ description: 'Whether this viewer created the session — only the creator may delete it.' })\n mine!: boolean\n\n /* 숨김은 나에게만 적용되고 되돌릴 수 있다 — 필터를 켠 사용자가 무엇이 숨겨진 것인지 알아야 한다. */\n @Field({ nullable: true, description: 'Whether this viewer hid the session from their own list (only returned when showHidden is on).' })\n hidden?: boolean\n}\n\n@Resolver()\nexport class ChatSessionResolver {\n @Query(() => ChatSession, { nullable: true, description: 'Get AI chat session by id.' })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\", domainOwnerGranted: true)')\n async chatSession(\n @Arg('id') id: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession | null> {\n const { domain } = context.state\n return (await getRepository(ChatSession).findOneBy({ id, domain: { id: domain.id } })) ?? null\n }\n\n @Query(() => [ChatSession], {\n description:\n 'List AI chat sessions anchored to a target (oldest first). Anchor decides the nature and the history boundary of the conversation: board = authoring, space = the site and the twins running there. Board anchor also matches legacy rows that only have boardId.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\", domainOwnerGranted: true)')\n async chatSessionsByAnchor(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession[]> {\n const { domain } = context.state\n return await getRepository(ChatSession).find({\n where: anchorWhere(domain.id, anchorType, anchorId),\n order: { createdAt: 'ASC' }\n })\n }\n\n /**\n * 받은편지함 — 앵커의 세션 목록 + 내 안 읽음 상태. 최근 활동순.\n * 집계 쿼리를 쓰지 않는다: 세션의 비정규화된 lastMessageAt 과 내 참여자 lastReadAt 을 **값 비교**한다\n * (5개 DB 드라이버 지원 때문에 group by/MAX 를 목록 경로에 두지 않는다).\n */\n @Query(() => [ChatSessionInboxEntry], {\n description:\n \"List sessions anchored to a target with this viewer's unread state, most recent activity first. Supports free-text search over name and last preview, a mine-only filter, hidden inclusion, and paging. Uses the denormalized last-activity timestamp compared against the viewer's read point — no per-session aggregation.\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\", domainOwnerGranted: true)')\n async chatSessionInbox(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext,\n /* 숨긴 대화 보기 — 숨김이 한 번 넣으면 못 꺼내는 함정이 되지 않도록 필터를 준다. */\n @Arg('showHidden', { nullable: true }) showHidden?: boolean,\n /* 대량 목록 대응 — 검색·소유 필터·페이지. 목록 UI 는 처음부터 이걸 갖고 있어야 한다. */\n @Arg('search', { nullable: true }) search?: string,\n @Arg('mineOnly', { nullable: true }) mineOnly?: boolean,\n @Arg('limit', () => Int, { nullable: true }) limit?: number,\n @Arg('offset', () => Int, { nullable: true }) offset?: number\n ): Promise<ChatSessionInboxEntry[]> {\n const filtered = await this._inboxFiltered(anchorType, anchorId, context, { showHidden, search, mineOnly })\n const from = Math.max(0, offset ?? 0)\n const size = Math.min(Math.max(1, limit ?? 50), 200)\n return filtered.slice(from, from + size) as any\n }\n\n /**\n * 필터를 통과한 **전체 개수** — \"더 보기\" 가 남았는지, 검색 결과가 몇 건인지.\n *\n * 목록과 같은 요청에 담아 가져가므로 왕복은 늘지 않는다. 개수를 모르면 사용자는 목록의 끝이\n * 페이지의 끝인지 자료의 끝인지 구별할 수 없다.\n */\n @Query(() => Int, {\n description:\n 'Total number of sessions matching the same filters as chatSessionInbox (before paging). Request it alongside the list so the UI can tell \"end of page\" from \"end of data\".'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\", domainOwnerGranted: true)')\n async chatSessionInboxTotal(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext,\n @Arg('showHidden', { nullable: true }) showHidden?: boolean,\n @Arg('search', { nullable: true }) search?: string,\n @Arg('mineOnly', { nullable: true }) mineOnly?: boolean\n ): Promise<number> {\n return (await this._inboxFiltered(anchorType, anchorId, context, { showHidden, search, mineOnly })).length\n }\n\n /** 필터 적용(페이지 전) — 목록·개수가 **같은 규칙**을 쓰도록 한 곳에 둔다(어긋나면 \"더 보기\" 가 거짓말이 된다). */\n private async _inboxFiltered(\n anchorType: string,\n anchorId: string,\n context: ResolverContext,\n opts: { showHidden?: boolean; search?: string; mineOnly?: boolean }\n ): Promise<ChatSessionInboxEntry[]> {\n const all = await this._inboxEntries(anchorType, anchorId, context)\n let entries = opts.showHidden ? all : all.filter(e => !e.hidden)\n if (opts.mineOnly) entries = entries.filter(e => (e as any).mine)\n return searchInbox(entries as any, opts.search) as any\n }\n\n /**\n * 내가 숨긴 대화 수 — 필터에 \"몇 개가 접혀 있는지\" 를 보여주기 위한 값.\n *\n * 숨긴 것이 몇 개인지 모르면 필터를 눌러 볼 이유가 생기지 않는다(숨긴 사실 자체를 잊는다).\n * 목록 조회와 **같은 요청**에 담아 가져갈 수 있으므로 왕복은 늘지 않는다.\n */\n @Query(() => Int, {\n description:\n \"Number of sessions on this anchor that the caller has hidden and that have had no activity since. Meant to be requested alongside chatSessionInbox in the same operation so the filter can say how many are folded away.\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\", domainOwnerGranted: true)')\n async hiddenSessionCount(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext\n ): Promise<number> {\n const all = await this._inboxEntries(anchorType, anchorId, context)\n return all.filter(e => e.hidden).length\n }\n\n /** 목록 조립 — 숨김 표시까지 붙인 **전체**. 목록·개수 두 진입점이 같은 규칙을 쓰도록 한 곳에 둔다. */\n private async _inboxEntries(\n anchorType: string,\n anchorId: string,\n context: ResolverContext\n ): Promise<ChatSessionInboxEntry[]> {\n const { domain, user } = context.state\n /* 조회 상한 — 한 앵커의 대화가 아무리 늘어도 한 번에 이만큼만 훑는다. 최근 활동순으로 자른다\n * (오래된 대화가 잘리는 것이 최근 대화가 잘리는 것보다 낫다). 정렬·검색·페이지는 순수 로직이 한다. */\n const sessions = await getRepository(ChatSession).find({\n where: anchorWhere(domain.id, anchorType, anchorId),\n order: { lastMessageAt: 'DESC' },\n take: INBOX_SCAN_CAP\n })\n if (sessions.length === 0) return []\n const rows = await getRepository(ChatSessionParticipant).find({\n where: { domain: { id: domain.id } as any, user: { id: user.id } as any, session: { id: In(sessions.map(s => s.id!)) } as any }\n })\n /* 'viewer' 는 대화에 낀 사람이 아니다 — 숨김을 기록하려고 만든 행이므로 읽음·안 읽음 판정에서 뺀다.\n * (참여자가 아닌 사람에게 남의 협의 배지를 띄우지 않는다.) */\n const participations = rows.filter(r => r.role !== 'viewer')\n const hiddenAt = new Map(rows.map(r => [(r as any).sessionId as string, r.hiddenAt]))\n /* 내가 만든 대화인지 표시 — 삭제 버튼을 보일지 결정하는 UI 힌트(권한은 서버가 다시 판정한다). */\n const createdByMe = new Set(sessions.filter(s => (s as any).creatorId === user?.id).map(s => s.id))\n const entries = buildInbox(sessions as any, participations as any).map(entry => ({\n ...entry,\n mine: createdByMe.has(entry.id)\n }))\n /* showHidden=true 로 불러 **전체**를 얻는다 — 숨김 여부 판정을 두 곳에 복제하지 않기 위함. */\n const shown = applyHidden(entries as any, hiddenAt, true) as any[]\n\n /*\n * 목록도 같은 관문을 지난다 — ADR-0073 판정 1. 미리보기는 그 답을 **다시 읽는 두 번째 길**이고,\n * 한 길만 막으면 같은 문장이 다른 길로 그대로 나간다. 미리보기 자리를 `content` 로 바꿔 넣고\n * 가려진 것만 되돌려 담는다.\n */\n const gate = readerGate(context)\n const judged = await gate(\n shown.map(entry => ({ doors: entry.lastMessageDoors, content: entry.lastMessagePreview ?? '' }))\n )\n return shown.map((entry, index) => ({\n ...entry,\n lastMessagePreview: judged[index].content,\n previewRedacted: (judged[index] as any).redacted === true\n })) as any\n }\n\n /**\n * 세션 삭제 — **만든 사람만.**\n *\n * 협의는 여럿의 기록이고 삭제는 화면에서 되돌릴 수 없다. 그래서 권한을 좁힌다(이름 변경은 되돌릴 수\n * 있어서 누구나 할 수 있는 것과 대비). 권한이 없는 사람에게는 `hideAISession`(내 목록에서만 숨김)이\n * 있다 — 남의 기록을 지우지 않고 자기 목록을 정리하는 길.\n *\n * 소프트 삭제(deletedAt)다 — 메시지·패치는 세션을 통해서만 도달하므로 함께 사라지고, 잘못 지운 경우\n * 데이터로는 남아 있다. 다른 참여자 목록에서도 사라져야 하므로 meta 활동으로 방송한다.\n */\n @Mutation(() => Boolean, {\n description:\n 'Delete a chat session — creator only, since a shared deliberation cannot be un-deleted from the UI. Participants who are not the creator can hide it from their own list instead (hideAISession). Soft delete; broadcast as meta activity so every list drops it.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async deleteAISession(@Arg('sessionId') sessionId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, user } = context.state\n const repo = getRepository(ChatSession)\n const session = await repo.findOneBy({ id: sessionId, domain: { id: domain.id } as any })\n if (!session) return false\n if (!user?.id || (session as any).creatorId !== user.id) {\n /* 조용한 무동작이 아니라 명시 실패 — 지워진 줄 알고 넘어가면 안 된다. */\n throw new Error('Only the user who created this session may delete it. Hide it from your own list instead.')\n }\n await repo.softDelete(sessionId)\n publishSessionActivity({\n domainId: domain.id,\n sessionId,\n kind: 'meta',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n actorId: user?.id\n })\n return true\n }\n\n /**\n * 내 목록에서 숨기기·되돌리기 — **나에게만** 적용된다(대화·다른 참여자 목록은 그대로).\n *\n * 참여자가 아니어도 숨길 수 있어야 한다 — 목록에는 같은 공간의 남의 협의도 보이고, 그것을 정리하는\n * 것은 남에게 아무 영향이 없다. 그 경우 'viewer' 역할로 기록만 남긴다(참여자 명부·배지에는 들지 않는다).\n */\n @Mutation(() => Boolean, {\n description:\n 'Hide (or unhide) a session from the calling user\\'s own list. Per-user and reversible — the session and other participants are unaffected. Activity newer than the hide makes it reappear; the inbox filter (showHidden) reveals hidden ones.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async hideAISession(\n @Arg('sessionId') sessionId: string,\n @Ctx() context: ResolverContext,\n @Arg('hidden', { nullable: true }) hidden?: boolean\n ): Promise<boolean> {\n const { domain, user } = context.state\n if (!user?.id) return false\n const session = await getRepository(ChatSession).findOneBy({ id: sessionId, domain: { id: domain.id } as any })\n if (!session) return false\n const repo = getRepository(ChatSessionParticipant)\n const existing = await repo.findOne({\n where: { domain: { id: domain.id } as any, session: { id: sessionId } as any, user: { id: user.id } as any }\n })\n const hiddenAt = hidden === false ? null : new Date()\n if (existing) {\n await repo.update(existing.id!, { hiddenAt, updater: user } as any)\n } else {\n if (hidden === false) return true // 숨긴 적이 없으면 되돌릴 것도 없다\n await repo.save({\n domain: { id: domain.id } as any,\n session: { id: sessionId } as any,\n user: { id: user.id } as any,\n role: 'viewer', // 대화에 낀 것이 아니라 숨김만 기록한다\n hiddenAt,\n creator: user,\n updater: user\n } as any)\n }\n return true\n }\n\n /**\n * 세션 이름 변경 — **참여자 누구나** 할 수 있다.\n *\n * 왜 소유자 전용이 아닌가: 이름은 대화의 주제표이고 협의는 여럿이 한다. 논의가 흘러 주제가 달라졌는데\n * 만든 사람만 고칠 수 있으면 그 사람이 없을 때 목록이 계속 어긋난다. 되돌릴 수 있는 변경이고 대화\n * 내용에 영향이 없으므로 권한을 좁힐 이유가 없다(되돌릴 수 없는 것만 좁힌다).\n *\n * 변경은 **meta 활동**으로 방송한다 — 모든 참여자 목록에 즉시 반영되지만 안 읽음 배지는 올리지 않는다\n * (이름 변경을 \"새 소식\" 으로 알리면 소음이다).\n */\n /**\n * 이 대화를 도메인 안 누구나 읽게 할 것인가 — ADR-0073 판정 2.\n *\n * owner 만 바꾼다. 이름 바꾸기는 어느 참여자나 하지만(되돌릴 수 있고 값을 드러내지 않는다), 공개로\n * 바꾸는 일은 이미 쓰인 글을 도메인 전체에 여는 일이다 — 되돌려도 읽힌 것은 읽힌 것이다.\n *\n * 화면은 공개로 바꾸기 전에 한 줄을 먼저 보인다(문구는 클라이언트가 가진다). 그 한 줄은 이 문이\n * 강제하지 않는다 — 문이 막을 수 있는 것은 누가 바꾸느냐까지다.\n */\n @Mutation(() => Boolean, {\n description:\n \"Open this conversation to everyone in the domain, or close it to its participants. Only the owner may change it. Opening exposes what is already written — the screen says so before asking. Door checks on assistant answers are unaffected (ADR-0073).\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async setSessionVisibility(\n @Arg('sessionId') sessionId: string,\n @Arg('visibility') visibility: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user } = context.state\n if (!SESSION_VISIBILITIES.includes(visibility as any)) {\n throw new Error(`unknown visibility '${visibility}' — use ${SESSION_VISIBILITIES.join(' or ')}`)\n }\n\n const session = await getRepository(ChatSession).findOneBy({ id: sessionId, domain: { id: domain.id } as any })\n if (!session) return false\n\n const mine = await getRepository(ChatSessionParticipant).findOne({\n where: { domain: { id: domain.id } as any, session: { id: sessionId } as any, user: { id: user.id } as any }\n })\n if (mine?.role !== 'owner') return false\n\n if ((session as any).visibility === visibility) return true\n\n await getRepository(ChatSession).update(sessionId, { visibility, updater: user } as any)\n publishSessionActivity({\n domainId: domain.id,\n sessionId,\n kind: 'meta',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n actorId: user?.id\n } as any)\n return true\n }\n\n @Mutation(() => Boolean, {\n description:\n 'Rename a chat session. Any participant may rename it — the name is the topic label of a shared deliberation and the change is reversible. Broadcast as meta activity so every participant sees it without raising unread badges.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async renameAISession(\n @Arg('sessionId') sessionId: string,\n @Arg('name') name: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user } = context.state\n const trimmed = (name ?? '').trim().slice(0, 200)\n if (!trimmed) return false // 빈 이름으로 지우지 않는다 — 지우려면 별도 의도가 필요하다\n const participant = await getRepository(ChatSessionParticipant).findOne({\n where: { domain: { id: domain.id } as any, session: { id: sessionId } as any, user: { id: user.id } as any }\n })\n if (!participant) return false // 참여자가 아니면 남의 대화 제목을 바꿀 수 없다\n const session = await getRepository(ChatSession).findOneBy({ id: sessionId, domain: { id: domain.id } as any })\n if (!session) return false\n await getRepository(ChatSession).update(sessionId, { name: trimmed, updater: user } as any)\n publishSessionActivity({\n domainId: domain.id,\n sessionId,\n kind: 'meta',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n actorId: user?.id\n })\n return true\n }\n\n /**\n * 읽은 지점 갱신 — 이 세션을 여기까지 읽었다. 멱등(여러 번 호출해도 최신 시각으로만 이동).\n * 접속 표시(lastSeenAt)와 분리한다 — 창을 열어 두고 화면을 안 볼 수 있다.\n */\n @Mutation(() => Boolean, {\n description:\n \"Mark a session as read up to now for the current user. Idempotent. Distinct from presence (lastSeenAt) — a window can be open without being read.\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async markSessionRead(\n @Arg('sessionId') sessionId: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user } = context.state\n const repo = getRepository(ChatSessionParticipant)\n const mine = await repo.findOne({\n where: { domain: { id: domain.id } as any, session: { id: sessionId } as any, user: { id: user.id } as any }\n })\n /* 참여자가 아니면 읽음 상태를 만들지 않는다 — 참여하지 않은 대화에 내 읽음 지점을 남기지 않는다. */\n if (!mine) return false\n await repo.update(mine.id!, { lastReadAt: new Date(), updater: user } as any)\n return true\n }\n\n @Query(() => [User], {\n description:\n 'List users in the current domain for the `@` mention popup. Anyone with the chat privilege may search here; this is separate from the admin-only users().'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\", domainOwnerGranted: true)')\n async domainUsersForMention(\n @Arg('query', { nullable: true, description: 'Substring to match against name/email (case-insensitive). Empty → all.' }) query: string | undefined,\n @Arg('limit', () => Int, { nullable: true, defaultValue: 50 }) limit: number,\n @Ctx() context: ResolverContext\n ): Promise<User[]> {\n const { domain } = context.state\n const qb = buildDomainUsersQueryBuilder(domain.id, 'USER')\n if (query?.trim()) {\n const q = `%${query.trim().toLowerCase()}%`\n qb.andWhere('(LOWER(USER.name) LIKE :q OR LOWER(USER.email) LIKE :q)', { q })\n }\n qb.orderBy('USER.name', 'ASC').limit(limit)\n return await qb.getMany()\n }\n\n @Query(() => [ChatSessionParticipant], {\n description: 'List participants of a ChatSession (members / owner).'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\", domainOwnerGranted: true)')\n async chatSessionParticipants(\n @Arg('sessionId') sessionId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSessionParticipant[]> {\n const { domain } = context.state\n const session = await getRepository(ChatSession).findOneBy({\n id: sessionId,\n domain: { id: domain.id }\n })\n if (!session) return []\n return await getRepository(ChatSessionParticipant).find({\n where: { session: { id: sessionId } as any, domain: { id: domain.id } },\n order: { createdAt: 'ASC' }\n })\n }\n\n @Mutation(() => Boolean, {\n description: 'Presence heartbeat — bump current user\\'s lastSeenAt in the session (online indicator).'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async touchPresence(@Arg('sessionId') sessionId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, user } = context.state\n const repo = getRepository(ChatSessionParticipant)\n const part = await repo.findOne({\n where: { session: { id: sessionId } as any, user: { id: user.id } as any, domain: { id: domain.id } as any }\n })\n if (!part) return false // 참여자가 아니면 heartbeat 무시 (초대 전)\n await repo.update(part.id!, { lastSeenAt: new Date(), updater: user } as any)\n return true\n }\n\n @Query(() => [ChatMessage], { description: 'List chat messages of a session, oldest first.' })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"query\", domainOwnerGranted: true)')\n async chatMessages(\n @Arg('sessionId') sessionId: string,\n @Arg('limit', () => Int, { nullable: true, defaultValue: 100 }) limit: number,\n @Arg('offset', () => Int, { nullable: true, defaultValue: 0 }) offset: number,\n @Ctx() context: ResolverContext\n ): Promise<ChatMessage[]> {\n const { domain, user } = context.state\n const session = await getRepository(ChatSession).findOneBy({\n id: sessionId,\n domain: { id: domain.id }\n })\n if (!session) return []\n\n /*\n * 공개 대화는 도메인 안이면 누구나 읽는다 — 초대 절차가 없다(ADR-0073 판정 2). 비공개 대화는\n * 참여자만. 여기서 막히는 것은 **방**이고, 방에 들어온 뒤 값을 읽는 일은 아래 문 판정이 따로 본다.\n */\n if ((session as any).visibility === 'private') {\n const part = await getRepository(ChatSessionParticipant).findOne({\n where: { session: { id: sessionId } as any, user: { id: user.id } as any, domain: { id: domain.id } as any }\n })\n if (!mayReadSession((session as any).visibility, !!part)) return []\n }\n\n const rows = await getRepository(ChatMessage).find({\n where: { session: { id: sessionId } as any },\n // creator: 그룹챗 발신자 표시(name) + 자기 여부 판정(email). 내부 관리키(id)에 의존하지 않는다.\n relations: { creator: true },\n order: { createdAt: 'ASC' },\n take: limit,\n skip: offset\n })\n\n /*\n * 어시스턴트의 답은 도구 결과를 평문으로 옮겨 적은 것이다. 읽는 사람이 그 도구가 지난 문을 못 지나면\n * 본문 대신 한 줄이 나간다 — 행이 있다는 사실은 보이고 값만 안 보인다(ADR-0073 판정 1).\n */\n return await readerGate(context)(rows)\n }\n\n @Directive('@transaction')\n @Mutation(() => ChatSession, {\n description:\n 'Start (or get existing) AI chat session anchored to a target. Idempotent — returns first existing or creates one. Use anchorType board for board authoring, space for a site (its co-located twins).'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async startAISession(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n\n const existing = await repo.findOneBy(anchorWhere(domain.id, anchorType, anchorId))\n if (existing) return existing\n\n const session = await repo.save({\n domain,\n ...anchorColumns(anchorType, anchorId),\n /* 앵커가 있는 대화는 공개로 태어난다 — ADR-0073 판정 2. */\n visibility: initialVisibility({ anchorType }),\n creator: user,\n updater: user\n } as any)\n // creator 를 owner participant 로 자동 등록 — 다자간 채팅 기반.\n await getRepository(ChatSessionParticipant, tx).save({\n domain,\n session: { id: session.id } as any,\n user,\n role: 'owner',\n creator: user,\n updater: user\n } as any)\n return session\n }\n\n @Directive('@transaction')\n @Mutation(() => ChatSession, {\n description:\n 'Always create a new AI chat session anchored to a target (no idempotent reuse). For multi-session UX — opening another tab.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async createAISession(\n @Arg('anchorType') anchorType: string,\n @Arg('anchorId') anchorId: string,\n @Arg('name', { nullable: true, description: 'Optional name. Defaults to a generated one, numbered within the anchor.' }) name: string | undefined,\n @Ctx() context: ResolverContext\n ): Promise<ChatSession> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n\n // 이름 미지정 시 자동 생성 — **같은 앵커**의 기존 세션 수 + 1.\n let finalName = name?.trim()\n if (!finalName) {\n const count = await repo.count({ where: anchorWhere(domain.id, anchorType, anchorId) })\n /* The name is stored, so it is written in the language of whoever created it (context.t), and read back as is. */\n finalName = context.t('ai-assistant.session.default-name', { n: count + 1, defaultValue: 'conversation {n}' })\n }\n\n const session = await repo.save({\n domain,\n ...anchorColumns(anchorType, anchorId),\n visibility: initialVisibility({ anchorType }),\n creator: user,\n updater: user,\n name: finalName\n } as any)\n // creator 를 owner participant 로 자동 등록.\n await getRepository(ChatSessionParticipant, tx).save({\n domain,\n session: { id: session.id } as any,\n user,\n role: 'owner',\n creator: user,\n updater: user\n } as any)\n return session\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description: 'Rename a ChatSession (tab label).'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async renameChatSession(\n @Arg('sessionId') sessionId: string,\n @Arg('name') name: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const repo = getRepository(ChatSession, tx)\n const session = await repo.findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n await repo.update(sessionId, { name: name.trim() || null, updater: user } as any)\n return true\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description:\n \"What the host did with a proposal the assistant made. The host calls this once per card it was asked to run; the server records it as a system row, so the panel shows it, a refreshed panel still shows it, and the model reads on its next turn that its proposal was refused instead of assuming it landed (ADR-0070).\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async reportProposalOutcome(\n @Arg('sessionId') sessionId: string,\n @Arg('proposalKey') proposalKey: string,\n @Arg('outcome', () => GraphQLJSON) outcome: ProposalOutcome,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n\n const key = (proposalKey ?? '').trim()\n if (!key) return false\n\n /*\n * 낱말은 ADR-0042 의 것에 `declined` 하나다. 모르는 낱말을 받으면 그대로 적지 않는다 — 카드가\n * 읽지 못하는 상태가 되고, 그때 화면은 아무 말도 못 한다.\n */\n if (!PROPOSAL_VERDICTS.includes(outcome?.verdict as any)) {\n throw new Error(\n `[ai-assistant] '${outcome?.verdict}' is not a proposal verdict. Use one of ${PROPOSAL_VERDICTS.join(', ')}.`\n )\n }\n\n const body = formatProposalOutcomeLine(key, outcome)\n\n const previousLast = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const sysMsg = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: 'system',\n content: body,\n creator: user,\n updater: user,\n parentMessage: previousLast ? ({ id: previousLast.id } as any) : undefined\n } as any)\n\n /* 목록의 미리보기는 사람의 말로 두는 편이 낫다 — 이 줄은 기계의 기록이다. 방송만 한다. */\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message: sysMsg })\n return true\n }\n\n @Directive('@transaction')\n @Mutation(() => String, {\n nullable: true,\n description:\n \"Say something to the people in this session. The turn is stored as the speaker's, addressed to the room, and the assistant is not called — it reads the line as context the next time someone asks it something. Returns the stored message id, or null when there was nothing to say (ADR-0070).\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async sayToRoom(\n @Arg('sessionId') sessionId: string,\n @Arg('content') content: string,\n @Ctx() context: ResolverContext\n ): Promise<string | null> {\n const { domain, user, tx } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n\n const body = roomMessageBody(content)\n if (!body) return null\n\n const previousLast = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const saved = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: 'user',\n content: body,\n /* 대상은 문이 정한다 — 이 문은 사람들에게 하는 말이다(ADR-0070 A15 결정 ①). */\n addressee: 'room',\n creator: user,\n updater: user,\n parentMessage: previousLast ? ({ id: previousLast.id } as any) : undefined\n } as any)\n\n /*\n * 멘션은 사람을 불러들인다 — **사람의 말을 저장하는 문**만 이것을 한다(ADR-0071 결정 1 ①).\n * 초대는 방에 있는 사람(owner · member)만 할 수 있고, 거절되면 그 사실이 화면으로 돌아간다.\n */\n const invite = await inviteMentionedUsers({\n content: body,\n sessionId: session.id!,\n domainId: domain.id,\n inviter: user,\n participants: getRepository(ChatSessionParticipant, tx),\n /* 비공개 대화에서는 이름만 닿는다 — ADR-0073 판정 2. */\n visibility: (session as any).visibility\n })\n await notifyInvited(context, invite.invited, user)\n\n /* 사람의 말이다 — 목록의 최근 활동과 다른 참여자의 안 읽음이 이것으로 움직인다. */\n try {\n await getRepository(ChatSession, tx).update(session.id!, activityPatch(body) as any)\n } catch {\n /* 목록이 한 박자 늦는 것이 말을 못 하게 할 이유는 아니다. */\n }\n publishSessionActivity({\n domainId: domain.id,\n sessionId: session.id!,\n kind: 'message',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n preview: body,\n actorId: user?.id\n })\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message: saved })\n\n return saved.id ?? null\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description:\n 'Append a system note to a session — context that did not come from a participant typing (e.g. a conversation carried over from another surface, an external state change). The AI sees it as part of the shared history.'\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async appendSessionNote(\n @Arg('sessionId') sessionId: string,\n @Arg('content') content: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n /* 프롬프트가 한 기록으로 폭증하지 않도록 자른다 — 맥락 전달이 목적이고 전문 보존이 아니다. */\n const body = (content ?? '').trim().slice(0, 4000)\n if (!body) return false\n\n const previousLast = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const sysMsg = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: 'system',\n content: body,\n creator: user,\n updater: user,\n parentMessage: previousLast ? ({ id: previousLast.id } as any) : undefined\n } as any)\n\n /* 활동 갱신 + 방송 — 다른 참여자 목록·안 읽음과 열려 있는 화면의 transcript 일관성. best-effort. */\n try {\n await getRepository(ChatSession, tx).update(session.id!, activityPatch(body) as any)\n } catch {\n /* 기록 자체를 막지 않는다 */\n }\n publishSessionActivity({\n domainId: domain.id,\n sessionId: session.id!,\n kind: 'message',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n preview: body,\n actorId: user?.id\n })\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message: sysMsg })\n return true\n }\n\n @Directive('@transaction')\n @Mutation(() => Boolean, {\n description:\n \"Carry a conversation from another surface into this session as its own turns, preserving order. A person's turns are stored as theirs, addressed to the room. An assistant turn is stored as the assistant's only when it names its original (sourceSessionId, sourceMessageId) and the server can read it; otherwise it is kept as a quotation on a system row — roles are the server's to write (ADR-0070).\"\n })\n @Directive('@privilege(category: \"ai-assistant\", privilege: \"mutation\", domainOwnerGranted: true)')\n async appendSessionTurns(\n @Arg('sessionId') sessionId: string,\n @Arg('turns', () => GraphQLJSON) turns: { role?: string; content?: string }[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n const session = await getRepository(ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } })\n if (!session) throw new Error(`ChatSession ${sessionId} not found`)\n\n /* 옮겨온 대화는 **그 대화의 발언 그대로** 들어간다 — 한 덩어리 기록으로 뭉치면 사람이 읽을 수 없고\n * (화면 하나를 잡아먹는 이탤릭 덩어리), 마크다운도 죽는다. 대신 개수·길이는 제한한다: 맥락 전달이\n * 목적이고 전문 보존이 아니다. */\n /* **역할은 서버가 쓴다**(ADR-0070 A15 결정 ③). 어시스턴트의 답은 원본을 읽어 복사하고, 원본이 없으면\n * 인용문으로 `system` 행에 남긴다 — 클라이언트가 보낸 글자를 어시스턴트의 말로 저장하지 않는다. */\n const planned = planCarriedTurns(turns as any)\n const rows: { role: string; content: string; addressee?: string; doors?: string[] }[] = []\n /* 옮겨 적힌 원문이 소급해서 공개되지 않게, 받는 대화는 이 순간부터 비공개다 — ADR-0073 판정 2. */\n let carried = false\n for (const row of planned) {\n if (!row.copyOf) {\n rows.push({ role: row.role, content: row.content, addressee: row.addressee })\n continue\n }\n /* 원본은 이 테넌트 안에서만 찾는다 — 남의 도메인 메시지를 옮겨 오는 길이 되지 않게. */\n const original = await getRepository(ChatMessage, tx).findOne({\n where: carriedOriginalWhere(domain.id, row.copyOf),\n relations: ['session']\n })\n carried = true\n if (original && original.role === 'assistant') {\n /*\n * 답과 함께 **그 답이 지나온 문**을 옮긴다 — ADR-0073 판정 1. 문을 두고 글만 옮기면, 문 하나를\n * 지나 얻은 값이 문 없는 행이 되어 아무나 읽는다. 옮겨 적기가 권한을 씻는 길이 된다.\n */\n rows.push({ role: 'assistant', content: original.content, doors: (original as any).doors ?? [] })\n } else {\n /* 인용문에도 원문의 문을 실어 둔다 — 인용이라고 값이 달라지지 않는다. */\n rows.push({ role: 'system', content: quoteCarriedAnswer(row.content), doors: (original as any)?.doors ?? [] })\n }\n }\n if (!rows.length) return false\n\n let previous = await getRepository(ChatMessage, tx).findOne({\n where: { session: { id: session.id } as any },\n order: { createdAt: 'DESC' }\n })\n const saved: ChatMessage[] = []\n for (const row of rows) {\n previous = await getRepository(ChatMessage, tx).save({\n session: { id: session.id } as any,\n role: row.role,\n content: row.content,\n /* 사람의 말은 방을 향한 것이다 — 이 문은 어시스턴트를 부르는 문이 아니다. */\n addressee: row.addressee,\n doors: row.doors,\n creator: user,\n updater: user,\n parentMessage: previous ? ({ id: previous.id } as any) : undefined\n } as any)\n saved.push(previous!)\n }\n\n if (carried && (session as any).visibility !== 'private') {\n await getRepository(ChatSession, tx).update(session.id!, { visibility: 'private', updater: user } as any)\n }\n\n /* 활동은 마지막 발언 기준 한 번만 — 옮긴 줄마다 목록을 흔들 이유가 없다. */\n const last = rows[rows.length - 1]\n try {\n await getRepository(ChatSession, tx).update(session.id!, activityPatch(last.content) as any)\n } catch {\n /* best-effort — 옮기기 자체를 막지 않는다 */\n }\n publishSessionActivity({\n domainId: domain.id,\n sessionId: session.id!,\n kind: 'message',\n anchorType: (session as any).anchorType,\n anchorId: (session as any).anchorId,\n preview: last.content,\n actorId: user?.id\n })\n for (const message of saved) {\n publishChatMessage({ domainId: domain.id, sessionId: session.id, message })\n }\n return true\n }\n\n}\n"]}