@things-factory/ai-assistant 10.1.47 → 10.1.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/components/assistant-chat.ts +97 -19
- package/client/components/assistant-dock.ts +617 -0
- package/client/components/assistant-mode.ts +2 -0
- package/client/components/assistant-session-manager.ts +607 -0
- package/client/components/chat-echo-dedup.ts +4 -0
- package/client/components/chat-input-builder.ts +4 -1
- package/client/components/panel-aria.test.ts +13 -8
- package/client/index.ts +8 -0
- package/client/setup-assistant-dock.ts +118 -0
- package/client/utils/assistant-activity.ts +122 -0
- package/client/utils/assistant-ask.ts +44 -0
- package/client/utils/assistant-proposals.ts +50 -0
- package/client/utils/assistant-session-actions.ts +18 -0
- package/client/utils/assistant-session-admin.ts +167 -0
- package/client/utils/assistant-session-controller.ts +2 -0
- package/client/utils/assistant-session-transport.ts +6 -2
- package/client/utils/assistant-surface.ts +157 -0
- package/client/utils/attachment-policy.ts +71 -0
- package/dist-client/components/assistant-chat.d.ts +6 -0
- package/dist-client/components/assistant-chat.js +98 -20
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/components/assistant-dock.d.ts +74 -0
- package/dist-client/components/assistant-dock.js +641 -0
- package/dist-client/components/assistant-dock.js.map +1 -0
- package/dist-client/components/assistant-mode.d.ts +6 -0
- package/dist-client/components/assistant-mode.js.map +1 -1
- package/dist-client/components/assistant-session-manager.d.ts +77 -0
- package/dist-client/components/assistant-session-manager.js +652 -0
- package/dist-client/components/assistant-session-manager.js.map +1 -0
- package/dist-client/components/chat-echo-dedup.js +4 -0
- package/dist-client/components/chat-echo-dedup.js.map +1 -1
- package/dist-client/components/chat-input-builder.d.ts +2 -0
- package/dist-client/components/chat-input-builder.js +2 -1
- package/dist-client/components/chat-input-builder.js.map +1 -1
- package/dist-client/components/panel-aria.test.js +12 -8
- package/dist-client/components/panel-aria.test.js.map +1 -1
- package/dist-client/index.d.ts +8 -0
- package/dist-client/index.js +8 -0
- package/dist-client/index.js.map +1 -1
- package/dist-client/setup-assistant-dock.d.ts +15 -0
- package/dist-client/setup-assistant-dock.js +119 -0
- package/dist-client/setup-assistant-dock.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/assistant-activity.d.ts +22 -0
- package/dist-client/utils/assistant-activity.js +104 -0
- package/dist-client/utils/assistant-activity.js.map +1 -0
- package/dist-client/utils/assistant-ask.d.ts +23 -0
- package/dist-client/utils/assistant-ask.js +18 -0
- package/dist-client/utils/assistant-ask.js.map +1 -0
- package/dist-client/utils/assistant-proposals.d.ts +29 -0
- package/dist-client/utils/assistant-proposals.js +22 -0
- package/dist-client/utils/assistant-proposals.js.map +1 -0
- package/dist-client/utils/assistant-session-actions.d.ts +12 -0
- package/dist-client/utils/assistant-session-actions.js +19 -0
- package/dist-client/utils/assistant-session-actions.js.map +1 -0
- package/dist-client/utils/assistant-session-admin.d.ts +72 -0
- package/dist-client/utils/assistant-session-admin.js +81 -0
- package/dist-client/utils/assistant-session-admin.js.map +1 -0
- package/dist-client/utils/assistant-session-controller.d.ts +2 -0
- package/dist-client/utils/assistant-session-controller.js.map +1 -1
- package/dist-client/utils/assistant-session-transport.js +6 -2
- package/dist-client/utils/assistant-session-transport.js.map +1 -1
- package/dist-client/utils/assistant-surface.d.ts +72 -0
- package/dist-client/utils/assistant-surface.js +99 -0
- package/dist-client/utils/assistant-surface.js.map +1 -0
- package/dist-client/utils/attachment-policy.d.ts +35 -0
- package/dist-client/utils/attachment-policy.js +56 -0
- package/dist-client/utils/attachment-policy.js.map +1 -0
- package/dist-server/service/assistant-chat-resolver.d.ts +1 -0
- package/dist-server/service/assistant-chat-resolver.js +71 -3
- package/dist-server/service/assistant-chat-resolver.js.map +1 -1
- package/dist-server/service/assistant-mode/assistant-mode-resolver.d.ts +1 -0
- package/dist-server/service/assistant-mode/assistant-mode-resolver.js +7 -0
- package/dist-server/service/assistant-mode/assistant-mode-resolver.js.map +1 -1
- package/dist-server/service/assistant-mode/resolve.d.ts +3 -0
- package/dist-server/service/assistant-mode/resolve.js +6 -2
- package/dist-server/service/assistant-mode/resolve.js.map +1 -1
- package/dist-server/service/assistant-mode/types.d.ts +6 -0
- package/dist-server/service/assistant-mode/types.js +0 -9
- package/dist-server/service/assistant-mode/types.js.map +1 -1
- package/dist-server/service/chat-message/chat-message.d.ts +6 -0
- package/dist-server/service/chat-message/chat-message.js +19 -0
- package/dist-server/service/chat-message/chat-message.js.map +1 -1
- package/dist-server/service/chat-session/attachment-policy.d.ts +44 -0
- package/dist-server/service/chat-session/attachment-policy.js +56 -0
- package/dist-server/service/chat-session/attachment-policy.js.map +1 -0
- package/dist-server/service/chat-session/attachment-route.d.ts +3 -0
- package/dist-server/service/chat-session/attachment-route.js +44 -0
- package/dist-server/service/chat-session/attachment-route.js.map +1 -0
- package/dist-server/service/chat-session/attachment-tools.d.ts +3 -0
- package/dist-server/service/chat-session/attachment-tools.js +59 -0
- package/dist-server/service/chat-session/attachment-tools.js.map +1 -0
- package/dist-server/service/chat-session/session-attachments.d.ts +36 -0
- package/dist-server/service/chat-session/session-attachments.js +84 -0
- package/dist-server/service/chat-session/session-attachments.js.map +1 -0
- package/dist-server/service/chat-session/session-inbox.d.ts +29 -0
- package/dist-server/service/chat-session/session-inbox.js +32 -8
- package/dist-server/service/chat-session/session-inbox.js.map +1 -1
- package/dist-server/service/chat-session/session-purge.d.ts +14 -0
- package/dist-server/service/chat-session/session-purge.js +77 -0
- package/dist-server/service/chat-session/session-purge.js.map +1 -0
- package/dist-server/service/chat-session/session-retention.d.ts +6 -0
- package/dist-server/service/chat-session/session-retention.js +20 -0
- package/dist-server/service/chat-session/session-retention.js.map +1 -0
- package/dist-server/service/chat-session/session-visibility.d.ts +8 -0
- package/dist-server/service/chat-session/session-visibility.js +11 -0
- package/dist-server/service/chat-session/session-visibility.js.map +1 -1
- package/dist-server/service/chat-session/session-write-gate.d.ts +11 -0
- package/dist-server/service/chat-session/session-write-gate.js +24 -0
- package/dist-server/service/chat-session/session-write-gate.js.map +1 -0
- package/dist-server/service/chat-session-participant/invite-notification.d.ts +1 -1
- package/dist-server/service/chat-session-participant/invite-notification.js +21 -6
- package/dist-server/service/chat-session-participant/invite-notification.js.map +1 -1
- package/dist-server/service/chat-session-participant/participant-lookup-roles.d.ts +3 -0
- package/dist-server/service/chat-session-participant/participant-lookup-roles.js +10 -0
- package/dist-server/service/chat-session-participant/participant-lookup-roles.js.map +1 -0
- package/dist-server/service/chat-session-participant/participant-lookup.d.ts +2 -0
- package/dist-server/service/chat-session-participant/participant-lookup.js +26 -0
- package/dist-server/service/chat-session-participant/participant-lookup.js.map +1 -0
- package/dist-server/service/chat-session-resolver.d.ts +17 -2
- package/dist-server/service/chat-session-resolver.js +135 -15
- package/dist-server/service/chat-session-resolver.js.map +1 -1
- package/dist-server/service/index.d.ts +5 -0
- package/dist-server/service/index.js +5 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -2
- package/server/service/assistant-chat-resolver.ts +71 -4
- package/server/service/assistant-mode/assistant-mode-resolver.ts +6 -0
- package/server/service/assistant-mode/resolve.ts +9 -2
- package/server/service/assistant-mode/types.ts +6 -0
- package/server/service/chat-message/chat-message.ts +17 -0
- package/server/service/chat-session/attachment-policy.test.ts +42 -0
- package/server/service/chat-session/attachment-policy.ts +68 -0
- package/server/service/chat-session/attachment-route.ts +45 -0
- package/server/service/chat-session/attachment-tools.ts +63 -0
- package/server/service/chat-session/session-attachments.ts +89 -0
- package/server/service/chat-session/session-inbox.test.ts +71 -1
- package/server/service/chat-session/session-inbox.ts +61 -11
- package/server/service/chat-session/session-purge.test.ts +24 -0
- package/server/service/chat-session/session-purge.ts +81 -0
- package/server/service/chat-session/session-retention.ts +17 -0
- package/server/service/chat-session/session-visibility.ts +11 -0
- package/server/service/chat-session/session-write-gate.test.ts +53 -0
- package/server/service/chat-session/session-write-gate.ts +31 -0
- package/server/service/chat-session-participant/invite-notification.test.ts +15 -0
- package/server/service/chat-session-participant/invite-notification.ts +24 -6
- package/server/service/chat-session-participant/participant-lookup-roles.ts +6 -0
- package/server/service/chat-session-participant/participant-lookup.ts +22 -0
- package/server/service/chat-session-resolver.ts +130 -13
- package/server/service/index.ts +5 -0
- package/test/assistant-dock.test.ts +124 -0
- package/test/assistant-session-manager.test.ts +126 -0
- package/test/attachment-policy-agree.test.ts +32 -0
- package/test/open-doors.test.ts +5 -2
- package/translations/en.json +61 -1
- package/translations/ja.json +61 -1
- package/translations/ko.json +61 -1
- package/translations/ms.json +61 -1
- package/translations/zh.json +61 -1
|
@@ -12,18 +12,33 @@ exports.buildInviteNotification = buildInviteNotification;
|
|
|
12
12
|
* 초대된 사용자들에게 보낼 협업 초대 알림 payload 를 만든다.
|
|
13
13
|
* 받는 사람이 없으면 null (= 보낼 것 없음).
|
|
14
14
|
*/
|
|
15
|
-
function buildInviteNotification(userIds, boardId, inviter) {
|
|
15
|
+
function buildInviteNotification(userIds, boardId, inviter, sessionName) {
|
|
16
16
|
if (!Array.isArray(userIds) || userIds.length === 0)
|
|
17
17
|
return null;
|
|
18
18
|
const who = inviter?.name || inviter?.email || 'someone';
|
|
19
|
+
/* A board conversation keeps its board wording and the link to the modeller. */
|
|
20
|
+
if (boardId) {
|
|
21
|
+
return {
|
|
22
|
+
receivers: userIds,
|
|
23
|
+
type: 'board-collab-invite',
|
|
24
|
+
subject: 'info',
|
|
25
|
+
title: 'Board collaboration invite',
|
|
26
|
+
body: `${who} invited you to collaborate on a board.`,
|
|
27
|
+
url: `board-modeller/${boardId}`,
|
|
28
|
+
mode: 'background'
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/*
|
|
32
|
+
* Every other conversation is not about a board. Both chat doors called this without one and every
|
|
33
|
+
* invite read "Board collaboration invite" - in operato-ecs, in plant, anywhere (2026-09-24).
|
|
34
|
+
*/
|
|
35
|
+
const name = sessionName?.trim();
|
|
19
36
|
return {
|
|
20
37
|
receivers: userIds,
|
|
21
|
-
type: '
|
|
38
|
+
type: 'chat-invite',
|
|
22
39
|
subject: 'info',
|
|
23
|
-
title: '
|
|
24
|
-
body: `${who}
|
|
25
|
-
// board 가 연결돼 있으면 모델러로 바로 가는 링크. 없으면 링크 생략.
|
|
26
|
-
url: boardId ? `board-modeller/${boardId}` : undefined,
|
|
40
|
+
title: 'Conversation invite',
|
|
41
|
+
body: name ? `${who} brought you into the conversation "${name}".` : `${who} brought you into a conversation.`,
|
|
27
42
|
mode: 'background'
|
|
28
43
|
};
|
|
29
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invite-notification.js","sourceRoot":"","sources":["../../../server/service/chat-session-participant/invite-notification.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAuBH,
|
|
1
|
+
{"version":3,"file":"invite-notification.js","sourceRoot":"","sources":["../../../server/service/chat-session-participant/invite-notification.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAuBH,0DAoCC;AAxCD;;;GAGG;AACH,SAAgB,uBAAuB,CACrC,OAAiB,EACjB,OAA2B,EAC3B,OAAmC,EACnC,WAA2B;IAE3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAEhE,MAAM,GAAG,GAAG,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,KAAK,IAAI,SAAS,CAAA;IAExD,gFAAgF;IAChF,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO;YACL,SAAS,EAAE,OAAO;YAClB,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,4BAA4B;YACnC,IAAI,EAAE,GAAG,GAAG,yCAAyC;YACrD,GAAG,EAAE,kBAAkB,OAAO,EAAE;YAChC,IAAI,EAAE,YAAY;SACnB,CAAA;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,IAAI,GAAG,WAAW,EAAE,IAAI,EAAE,CAAA;IAChC,OAAO;QACL,SAAS,EAAE,OAAO;QAClB,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,uCAAuC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,mCAAmC;QAC9G,IAAI,EAAE,YAAY;KACnB,CAAA;AACH,CAAC","sourcesContent":["/**\n * 협업 초대 알림 — 순수 payload 빌더.\n *\n * 부수효과(실제 발송)는 resolver 의 thin caller 가 `context.state.notify` 로 수행.\n * 여기엔 \"무엇을 보낼지\"(payload) 결정 로직만 둔다 — DB·pubsub·notify 의존 없이 테스트 가능.\n * (patch spine 의 board-patch-broadcast.ts 와 동일한 순수/부수효과 분리 컨벤션.)\n */\n\n/** notification-middleware 의 notifier 가 받는 인자 형태 (필요한 키만). */\nexport interface InviteNotification {\n receivers: string[]\n type: string\n subject: string\n title: string\n body: string\n url?: string\n mode: 'background' | 'foreground'\n}\n\n/** 초대자 식별용 — User 엔티티에서 쓰는 필드만 (duck-typed). */\nexport interface Inviter {\n name?: string | null\n email?: string | null\n}\n\n/**\n * 초대된 사용자들에게 보낼 협업 초대 알림 payload 를 만든다.\n * 받는 사람이 없으면 null (= 보낼 것 없음).\n */\nexport function buildInviteNotification(\n userIds: string[],\n boardId: string | undefined,\n inviter: Inviter | undefined | null,\n sessionName?: string | null\n): InviteNotification | null {\n if (!Array.isArray(userIds) || userIds.length === 0) return null\n\n const who = inviter?.name || inviter?.email || 'someone'\n\n /* A board conversation keeps its board wording and the link to the modeller. */\n if (boardId) {\n return {\n receivers: userIds,\n type: 'board-collab-invite',\n subject: 'info',\n title: 'Board collaboration invite',\n body: `${who} invited you to collaborate on a board.`,\n url: `board-modeller/${boardId}`,\n mode: 'background'\n }\n }\n\n /*\n * Every other conversation is not about a board. Both chat doors called this without one and every\n * invite read \"Board collaboration invite\" - in operato-ecs, in plant, anywhere (2026-09-24).\n */\n const name = sessionName?.trim()\n return {\n receivers: userIds,\n type: 'chat-invite',\n subject: 'info',\n title: 'Conversation invite',\n body: name ? `${who} brought you into the conversation \"${name}\".` : `${who} brought you into a conversation.`,\n mode: 'background'\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ROOM_ROLES = void 0;
|
|
4
|
+
exports.isRoomRole = isRoomRole;
|
|
5
|
+
/** Being in the room - owner or member. A `viewer` row only remembers a hide. Pure, so it is tested alone. */
|
|
6
|
+
exports.ROOM_ROLES = ['owner', 'member'];
|
|
7
|
+
function isRoomRole(role) {
|
|
8
|
+
return exports.ROOM_ROLES.includes(role ?? '');
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=participant-lookup-roles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"participant-lookup-roles.js","sourceRoot":"","sources":["../../../server/service/chat-session-participant/participant-lookup-roles.ts"],"names":[],"mappings":";;;AAGA,gCAEC;AALD,8GAA8G;AACjG,QAAA,UAAU,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAU,CAAA;AAEtD,SAAgB,UAAU,CAAC,IAA+B;IACxD,OAAQ,kBAAgC,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;AAC/D,CAAC","sourcesContent":["/** Being in the room - owner or member. A `viewer` row only remembers a hide. Pure, so it is tested alone. */\nexport const ROOM_ROLES = ['owner', 'member'] as const\n\nexport function isRoomRole(role: string | null | undefined): boolean {\n return (ROOM_ROLES as readonly string[]).includes(role ?? '')\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isRoomRole = exports.ROOM_ROLES = void 0;
|
|
4
|
+
exports.isSessionParticipant = isSessionParticipant;
|
|
5
|
+
/*
|
|
6
|
+
* Is this user in the room - owner or member?
|
|
7
|
+
*
|
|
8
|
+
* A `viewer` row is not being in the room: `hideAISession` writes one to remember a hide for someone who
|
|
9
|
+
* never took part. Counting it let a person who hid a private conversation by its id read it afterwards -
|
|
10
|
+
* the hide became the key. Every gate that asks "is this a participant" asks here.
|
|
11
|
+
*/
|
|
12
|
+
const shell_1 = require("@things-factory/shell");
|
|
13
|
+
const chat_session_participant_js_1 = require("./chat-session-participant.js");
|
|
14
|
+
const participant_lookup_roles_js_1 = require("./participant-lookup-roles.js");
|
|
15
|
+
var participant_lookup_roles_js_2 = require("./participant-lookup-roles.js");
|
|
16
|
+
Object.defineProperty(exports, "ROOM_ROLES", { enumerable: true, get: function () { return participant_lookup_roles_js_2.ROOM_ROLES; } });
|
|
17
|
+
Object.defineProperty(exports, "isRoomRole", { enumerable: true, get: function () { return participant_lookup_roles_js_2.isRoomRole; } });
|
|
18
|
+
async function isSessionParticipant(domainId, sessionId, userId, tx) {
|
|
19
|
+
if (!userId)
|
|
20
|
+
return false;
|
|
21
|
+
const row = await (0, shell_1.getRepository)(chat_session_participant_js_1.ChatSessionParticipant, tx).findOne({
|
|
22
|
+
where: { domain: { id: domainId }, session: { id: sessionId }, user: { id: userId } }
|
|
23
|
+
});
|
|
24
|
+
return (0, participant_lookup_roles_js_1.isRoomRole)(row?.role);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=participant-lookup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"participant-lookup.js","sourceRoot":"","sources":["../../../server/service/chat-session-participant/participant-lookup.ts"],"names":[],"mappings":";;;AAeA,oDAMC;AArBD;;;;;;GAMG;AACH,iDAAqD;AAErD,+EAAsE;AAEtE,+EAA0D;AAE1D,6EAAsE;AAA7D,yHAAA,UAAU,OAAA;AAAE,yHAAA,UAAU,OAAA;AAExB,KAAK,UAAU,oBAAoB,CAAC,QAAgB,EAAE,SAAiB,EAAE,MAA0B,EAAE,EAAQ;IAClH,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACzB,MAAM,GAAG,GAAG,MAAM,IAAA,qBAAa,EAAC,oDAAsB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC;QAClE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,SAAS,EAAS,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAS,EAAE;KAC3G,CAAC,CAAA;IACF,OAAO,IAAA,wCAAU,EAAC,GAAG,EAAE,IAAI,CAAC,CAAA;AAC9B,CAAC","sourcesContent":["/*\n * Is this user in the room - owner or member?\n *\n * A `viewer` row is not being in the room: `hideAISession` writes one to remember a hide for someone who\n * never took part. Counting it let a person who hid a private conversation by its id read it afterwards -\n * the hide became the key. Every gate that asks \"is this a participant\" asks here.\n */\nimport { getRepository } from '@things-factory/shell'\n\nimport { ChatSessionParticipant } from './chat-session-participant.js'\n\nimport { isRoomRole } from './participant-lookup-roles.js'\n\nexport { ROOM_ROLES, isRoomRole } from './participant-lookup-roles.js'\n\nexport async function isSessionParticipant(domainId: string, sessionId: string, userId: string | undefined, tx?: any): Promise<boolean> {\n if (!userId) return false\n const row = await getRepository(ChatSessionParticipant, tx).findOne({\n where: { domain: { id: domainId } as any, session: { id: sessionId } as any, user: { id: userId } as any }\n })\n return isRoomRole(row?.role)\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import { ChatSession } from './chat-session/chat-session.js';
|
|
|
3
3
|
import { type ProposalOutcome } from './chat-message/proposal-outcome.js';
|
|
4
4
|
import { ChatMessage } from './chat-message/chat-message.js';
|
|
5
5
|
import { ChatSessionParticipant } from './chat-session-participant/chat-session-participant.js';
|
|
6
|
+
import type { FileUpload } from 'graphql-upload/GraphQLUpload.js';
|
|
6
7
|
declare class ChatSessionInboxEntry {
|
|
7
8
|
id?: string;
|
|
8
9
|
name?: string;
|
|
@@ -20,6 +21,14 @@ declare class ChatSessionInboxEntry {
|
|
|
20
21
|
participant: boolean;
|
|
21
22
|
mine: boolean;
|
|
22
23
|
hidden?: boolean;
|
|
24
|
+
visibility: string;
|
|
25
|
+
owner: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare class ChatAttachmentInfo {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
mimetype: string;
|
|
31
|
+
size: number;
|
|
23
32
|
}
|
|
24
33
|
export declare class ChatSessionResolver {
|
|
25
34
|
chatSession(id: string, context: ResolverContext): Promise<ChatSession | null>;
|
|
@@ -29,14 +38,14 @@ export declare class ChatSessionResolver {
|
|
|
29
38
|
* 집계 쿼리를 쓰지 않는다: 세션의 비정규화된 lastMessageAt 과 내 참여자 lastReadAt 을 **값 비교**한다
|
|
30
39
|
* (5개 DB 드라이버 지원 때문에 group by/MAX 를 목록 경로에 두지 않는다).
|
|
31
40
|
*/
|
|
32
|
-
chatSessionInbox(anchorType: string, anchorId: string, context: ResolverContext, showHidden?: boolean, search?: string, mineOnly?: boolean, limit?: number, offset?: number): Promise<ChatSessionInboxEntry[]>;
|
|
41
|
+
chatSessionInbox(anchorType: string, anchorId: string, context: ResolverContext, showHidden?: boolean, search?: string, mineOnly?: boolean, limit?: number, offset?: number, kind?: string, participantOnly?: boolean, visibility?: string, unreadOnly?: boolean): Promise<ChatSessionInboxEntry[]>;
|
|
33
42
|
/**
|
|
34
43
|
* 필터를 통과한 **전체 개수** — "더 보기" 가 남았는지, 검색 결과가 몇 건인지.
|
|
35
44
|
*
|
|
36
45
|
* 목록과 같은 요청에 담아 가져가므로 왕복은 늘지 않는다. 개수를 모르면 사용자는 목록의 끝이
|
|
37
46
|
* 페이지의 끝인지 자료의 끝인지 구별할 수 없다.
|
|
38
47
|
*/
|
|
39
|
-
chatSessionInboxTotal(anchorType: string, anchorId: string, context: ResolverContext, showHidden?: boolean, search?: string, mineOnly?: boolean): Promise<number>;
|
|
48
|
+
chatSessionInboxTotal(anchorType: string, anchorId: string, context: ResolverContext, showHidden?: boolean, search?: string, mineOnly?: boolean, kind?: string, participantOnly?: boolean, visibility?: string, unreadOnly?: boolean): Promise<number>;
|
|
40
49
|
/** 필터 적용(페이지 전) — 목록·개수가 **같은 규칙**을 쓰도록 한 곳에 둔다(어긋나면 "더 보기" 가 거짓말이 된다). */
|
|
41
50
|
private _inboxFiltered;
|
|
42
51
|
/**
|
|
@@ -100,6 +109,12 @@ export declare class ChatSessionResolver {
|
|
|
100
109
|
createAISession(anchorType: string, anchorId: string, name: string | undefined, context: ResolverContext): Promise<ChatSession>;
|
|
101
110
|
renameChatSession(sessionId: string, name: string, context: ResolverContext): Promise<boolean>;
|
|
102
111
|
reportProposalOutcome(sessionId: string, proposalKey: string, outcome: ProposalOutcome, context: ResolverContext): Promise<boolean>;
|
|
112
|
+
/**
|
|
113
|
+
* Stores files with a conversation before the turn that carries them (design/ai/shared-dock.md §9).
|
|
114
|
+
* Passes the write gate - a private conversation takes files from its people only - and the mode's
|
|
115
|
+
* attachment policy. The size is known only once stored, so a file over the limit is removed and refused.
|
|
116
|
+
*/
|
|
117
|
+
attachToConversation(sessionId: string, files: FileUpload[], context: ResolverContext, kind?: string): Promise<ChatAttachmentInfo[]>;
|
|
103
118
|
sayToRoom(sessionId: string, content: string, context: ResolverContext): Promise<string | null>;
|
|
104
119
|
appendSessionNote(sessionId: string, content: string, context: ResolverContext): Promise<boolean>;
|
|
105
120
|
appendSessionTurns(sessionId: string, turns: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ChatSessionResolver = void 0;
|
|
3
|
+
exports.ChatSessionResolver = exports.ChatAttachmentInfo = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
/**
|
|
6
6
|
* ChatSession lifecycle resolver — start/get/recordDirectPatch/revertPatch + 메시지·패치 페이징 query.
|
|
@@ -23,16 +23,18 @@ const reader_gate_js_1 = require("./chat-message/reader-gate.js");
|
|
|
23
23
|
const session_visibility_js_1 = require("./chat-session/session-visibility.js");
|
|
24
24
|
const mention_invite_js_1 = require("./chat-session-participant/mention-invite.js");
|
|
25
25
|
const invite_notification_js_1 = require("./chat-session-participant/invite-notification.js");
|
|
26
|
+
const participant_lookup_js_1 = require("./chat-session-participant/participant-lookup.js");
|
|
27
|
+
const session_write_gate_js_1 = require("./chat-session/session-write-gate.js");
|
|
26
28
|
/**
|
|
27
29
|
* 초대 알림 — 발송은 호스트의 기전을 그대로 쓴다(중복 구현 금지).
|
|
28
30
|
*
|
|
29
31
|
* 알림이 안 가도 초대 자체는 이미 일어났다. 그래서 실패를 삼키되, 초대를 되돌리지는 않는다 —
|
|
30
32
|
* 참여자 목록이 정본이고 알림은 그것을 알리는 편지다.
|
|
31
33
|
*/
|
|
32
|
-
async function notifyInvited(context, invited, inviter) {
|
|
34
|
+
async function notifyInvited(context, invited, inviter, sessionName) {
|
|
33
35
|
if (invited.length === 0)
|
|
34
36
|
return;
|
|
35
|
-
const payload = (0, invite_notification_js_1.buildInviteNotification)(invited, undefined, inviter);
|
|
37
|
+
const payload = (0, invite_notification_js_1.buildInviteNotification)(invited, undefined, inviter, sessionName);
|
|
36
38
|
if (!payload)
|
|
37
39
|
return;
|
|
38
40
|
try {
|
|
@@ -42,11 +44,25 @@ async function notifyInvited(context, invited, inviter) {
|
|
|
42
44
|
/* 편지가 못 갔다고 방에 들어온 사실이 취소되지는 않는다. */
|
|
43
45
|
}
|
|
44
46
|
}
|
|
47
|
+
/** Every door that writes into a conversation passes this first (`session-write-gate.ts`). */
|
|
48
|
+
async function writeGate(session, context, tx) {
|
|
49
|
+
const { domain, user } = context.state;
|
|
50
|
+
await (0, session_write_gate_js_1.assertMayWriteSession)({
|
|
51
|
+
session,
|
|
52
|
+
userId: user?.id,
|
|
53
|
+
isParticipant: () => (0, participant_lookup_js_1.isSessionParticipant)(domain.id, session.id, user?.id, tx),
|
|
54
|
+
t: (key, options) => (context.t ? context.t(key, options) : String(options?.defaultValue ?? key))
|
|
55
|
+
});
|
|
56
|
+
}
|
|
45
57
|
const proposal_outcome_js_1 = require("./chat-message/proposal-outcome.js");
|
|
46
58
|
const session_activity_publish_js_1 = require("./chat-session/session-activity-publish.js");
|
|
47
59
|
const chat_message_js_1 = require("./chat-message/chat-message.js");
|
|
48
60
|
const chat_session_participant_js_1 = require("./chat-session-participant/chat-session-participant.js");
|
|
49
61
|
const chat_message_publish_js_1 = require("./chat-message/chat-message-publish.js");
|
|
62
|
+
const GraphQLUpload_js_1 = tslib_1.__importDefault(require("graphql-upload/GraphQLUpload.js"));
|
|
63
|
+
const registry_js_1 = require("./assistant-mode/registry.js");
|
|
64
|
+
const attachment_policy_js_1 = require("./chat-session/attachment-policy.js");
|
|
65
|
+
const session_attachments_js_1 = require("./chat-session/session-attachments.js");
|
|
50
66
|
let ChatSessionInboxEntry = class ChatSessionInboxEntry {
|
|
51
67
|
};
|
|
52
68
|
tslib_1.__decorate([
|
|
@@ -105,11 +121,63 @@ tslib_1.__decorate([
|
|
|
105
121
|
(0, type_graphql_1.Field)({ nullable: true, description: 'Whether this viewer hid the session from their own list (only returned when showHidden is on).' }),
|
|
106
122
|
tslib_1.__metadata("design:type", Boolean)
|
|
107
123
|
], ChatSessionInboxEntry.prototype, "hidden", void 0);
|
|
124
|
+
tslib_1.__decorate([
|
|
125
|
+
(0, type_graphql_1.Field)({ description: "Who may read the session: 'open' (everyone in the domain) or 'private' (participants only)." }),
|
|
126
|
+
tslib_1.__metadata("design:type", String)
|
|
127
|
+
], ChatSessionInboxEntry.prototype, "visibility", void 0);
|
|
128
|
+
tslib_1.__decorate([
|
|
129
|
+
(0, type_graphql_1.Field)({ description: 'Whether this viewer is the owner of the session - only the owner may change its visibility.' }),
|
|
130
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
131
|
+
], ChatSessionInboxEntry.prototype, "owner", void 0);
|
|
108
132
|
ChatSessionInboxEntry = tslib_1.__decorate([
|
|
109
133
|
(0, type_graphql_1.ObjectType)({
|
|
110
134
|
description: '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.'
|
|
111
135
|
})
|
|
112
136
|
], ChatSessionInboxEntry);
|
|
137
|
+
let ChatAttachmentInfo = class ChatAttachmentInfo {
|
|
138
|
+
};
|
|
139
|
+
exports.ChatAttachmentInfo = ChatAttachmentInfo;
|
|
140
|
+
tslib_1.__decorate([
|
|
141
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.ID, { description: 'Attachment id.' }),
|
|
142
|
+
tslib_1.__metadata("design:type", String)
|
|
143
|
+
], ChatAttachmentInfo.prototype, "id", void 0);
|
|
144
|
+
tslib_1.__decorate([
|
|
145
|
+
(0, type_graphql_1.Field)({ description: 'File name.' }),
|
|
146
|
+
tslib_1.__metadata("design:type", String)
|
|
147
|
+
], ChatAttachmentInfo.prototype, "name", void 0);
|
|
148
|
+
tslib_1.__decorate([
|
|
149
|
+
(0, type_graphql_1.Field)({ description: 'MIME type.' }),
|
|
150
|
+
tslib_1.__metadata("design:type", String)
|
|
151
|
+
], ChatAttachmentInfo.prototype, "mimetype", void 0);
|
|
152
|
+
tslib_1.__decorate([
|
|
153
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Size in bytes.' }),
|
|
154
|
+
tslib_1.__metadata("design:type", Number)
|
|
155
|
+
], ChatAttachmentInfo.prototype, "size", void 0);
|
|
156
|
+
exports.ChatAttachmentInfo = ChatAttachmentInfo = tslib_1.__decorate([
|
|
157
|
+
(0, type_graphql_1.ObjectType)({ description: 'A file stored with a conversation - opened only through the conversation.' })
|
|
158
|
+
], ChatAttachmentInfo);
|
|
159
|
+
/** A refusal said in the reader's words - code first, the sentence from it (ADR-0054). */
|
|
160
|
+
function attachmentRefusalMessage(refusal, context) {
|
|
161
|
+
const t = (key, options) => (context.t ? context.t(key, options) : String(options?.defaultValue ?? key));
|
|
162
|
+
switch (refusal.code) {
|
|
163
|
+
case 'attachments-not-accepted':
|
|
164
|
+
return t('ai-assistant.text.attachments-not-accepted', { defaultValue: 'this conversation does not take attachments.' });
|
|
165
|
+
case 'attachment-kind-not-accepted':
|
|
166
|
+
return t('ai-assistant.text.attachment-kind-not-accepted', {
|
|
167
|
+
name: refusal.name,
|
|
168
|
+
kinds: refusal.kinds.join(', '),
|
|
169
|
+
defaultValue: '{name} cannot be attached here - this conversation takes {kinds}.'
|
|
170
|
+
});
|
|
171
|
+
case 'attachment-too-large':
|
|
172
|
+
return t('ai-assistant.text.attachment-too-large', {
|
|
173
|
+
name: refusal.name,
|
|
174
|
+
max: Math.round(refusal.maxBytes / 1024 / 1024),
|
|
175
|
+
defaultValue: '{name} is larger than {max} MB.'
|
|
176
|
+
});
|
|
177
|
+
case 'too-many-attachments':
|
|
178
|
+
return t('ai-assistant.text.too-many-attachments', { max: refusal.maxFiles, defaultValue: 'at most {max} files can be sent at once.' });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
113
181
|
let ChatSessionResolver = class ChatSessionResolver {
|
|
114
182
|
async chatSession(id, context) {
|
|
115
183
|
const { domain } = context.state;
|
|
@@ -127,8 +195,10 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
127
195
|
* 집계 쿼리를 쓰지 않는다: 세션의 비정규화된 lastMessageAt 과 내 참여자 lastReadAt 을 **값 비교**한다
|
|
128
196
|
* (5개 DB 드라이버 지원 때문에 group by/MAX 를 목록 경로에 두지 않는다).
|
|
129
197
|
*/
|
|
130
|
-
async chatSessionInbox(anchorType, anchorId, context, showHidden, search, mineOnly, limit, offset) {
|
|
131
|
-
const filtered = await this._inboxFiltered(anchorType, anchorId, context, {
|
|
198
|
+
async chatSessionInbox(anchorType, anchorId, context, showHidden, search, mineOnly, limit, offset, kind, participantOnly, visibility, unreadOnly) {
|
|
199
|
+
const filtered = await this._inboxFiltered(anchorType, anchorId, context, {
|
|
200
|
+
showHidden, search, mineOnly, kind, participantOnly, visibility, unreadOnly
|
|
201
|
+
});
|
|
132
202
|
const from = Math.max(0, offset ?? 0);
|
|
133
203
|
const size = Math.min(Math.max(1, limit ?? 50), 200);
|
|
134
204
|
return filtered.slice(from, from + size);
|
|
@@ -139,15 +209,14 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
139
209
|
* 목록과 같은 요청에 담아 가져가므로 왕복은 늘지 않는다. 개수를 모르면 사용자는 목록의 끝이
|
|
140
210
|
* 페이지의 끝인지 자료의 끝인지 구별할 수 없다.
|
|
141
211
|
*/
|
|
142
|
-
async chatSessionInboxTotal(anchorType, anchorId, context, showHidden, search, mineOnly) {
|
|
143
|
-
return (await this._inboxFiltered(anchorType, anchorId, context, { showHidden, search, mineOnly })).length;
|
|
212
|
+
async chatSessionInboxTotal(anchorType, anchorId, context, showHidden, search, mineOnly, kind, participantOnly, visibility, unreadOnly) {
|
|
213
|
+
return (await this._inboxFiltered(anchorType, anchorId, context, { showHidden, search, mineOnly, kind, participantOnly, visibility, unreadOnly })).length;
|
|
144
214
|
}
|
|
145
215
|
/** 필터 적용(페이지 전) — 목록·개수가 **같은 규칙**을 쓰도록 한 곳에 둔다(어긋나면 "더 보기" 가 거짓말이 된다). */
|
|
146
216
|
async _inboxFiltered(anchorType, anchorId, context, opts) {
|
|
147
217
|
const all = await this._inboxEntries(anchorType, anchorId, context);
|
|
148
218
|
let entries = opts.showHidden ? all : all.filter(e => !e.hidden);
|
|
149
|
-
|
|
150
|
-
entries = entries.filter(e => e.mine);
|
|
219
|
+
entries = (0, session_inbox_js_1.filterInbox)(entries, opts);
|
|
151
220
|
return (0, session_inbox_js_1.searchInbox)(entries, opts.search);
|
|
152
221
|
}
|
|
153
222
|
/**
|
|
@@ -399,10 +468,9 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
399
468
|
* 참여자만. 여기서 막히는 것은 **방**이고, 방에 들어온 뒤 값을 읽는 일은 아래 문 판정이 따로 본다.
|
|
400
469
|
*/
|
|
401
470
|
if (session.visibility === 'private') {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if (!(0, session_visibility_js_1.mayReadSession)(session.visibility, !!part))
|
|
471
|
+
/* A hide-only `viewer` row is not being in the room - it must not open a private conversation. */
|
|
472
|
+
const part = await (0, participant_lookup_js_1.isSessionParticipant)(domain.id, sessionId, user?.id);
|
|
473
|
+
if (!(0, session_visibility_js_1.mayReadSession)(session.visibility, part))
|
|
406
474
|
return [];
|
|
407
475
|
}
|
|
408
476
|
const rows = await (0, shell_1.getRepository)(chat_message_js_1.ChatMessage).find({
|
|
@@ -479,6 +547,8 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
479
547
|
const session = await repo.findOneBy({ id: sessionId, domain: { id: domain.id } });
|
|
480
548
|
if (!session)
|
|
481
549
|
throw new Error(`ChatSession ${sessionId} not found`);
|
|
550
|
+
/* The board-era rename door had no gate at all - a private conversation's name was anyone's to change. */
|
|
551
|
+
await writeGate(session, context, tx);
|
|
482
552
|
await repo.update(sessionId, { name: name.trim() || null, updater: user });
|
|
483
553
|
return true;
|
|
484
554
|
}
|
|
@@ -487,6 +557,7 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
487
557
|
const session = await (0, shell_1.getRepository)(chat_session_js_1.ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } });
|
|
488
558
|
if (!session)
|
|
489
559
|
throw new Error(`ChatSession ${sessionId} not found`);
|
|
560
|
+
await writeGate(session, context, tx);
|
|
490
561
|
const key = (proposalKey ?? '').trim();
|
|
491
562
|
if (!key)
|
|
492
563
|
return false;
|
|
@@ -514,11 +585,36 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
514
585
|
(0, chat_message_publish_js_1.publishChatMessage)({ domainId: domain.id, sessionId: session.id, message: sysMsg });
|
|
515
586
|
return true;
|
|
516
587
|
}
|
|
588
|
+
/**
|
|
589
|
+
* Stores files with a conversation before the turn that carries them (design/ai/shared-dock.md §9).
|
|
590
|
+
* Passes the write gate - a private conversation takes files from its people only - and the mode's
|
|
591
|
+
* attachment policy. The size is known only once stored, so a file over the limit is removed and refused.
|
|
592
|
+
*/
|
|
593
|
+
async attachToConversation(sessionId, files, context, kind) {
|
|
594
|
+
const { domain, tx } = context.state;
|
|
595
|
+
const session = await (0, shell_1.getRepository)(chat_session_js_1.ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } });
|
|
596
|
+
if (!session)
|
|
597
|
+
throw new Error(`ChatSession ${sessionId} not found`);
|
|
598
|
+
await writeGate(session, context, tx);
|
|
599
|
+
const policy = (0, registry_js_1.getAssistantMode)(session.kind || kind || '')?.attachments;
|
|
600
|
+
const uploads = await Promise.all(files);
|
|
601
|
+
const before = (0, attachment_policy_js_1.refuseAttachments)(policy, uploads.map(upload => ({ name: upload.filename, type: upload.mimetype })));
|
|
602
|
+
if (before)
|
|
603
|
+
throw new Error(attachmentRefusalMessage(before, context));
|
|
604
|
+
const saved = await (0, session_attachments_js_1.saveChatAttachments)(session.id, uploads, context);
|
|
605
|
+
const after = (0, attachment_policy_js_1.refuseAttachments)(policy, saved.map(file => ({ name: file.name, type: file.mimetype, size: file.size })));
|
|
606
|
+
if (after) {
|
|
607
|
+
await (0, session_attachments_js_1.removeAttachmentRows)(saved.map(file => file.id));
|
|
608
|
+
throw new Error(attachmentRefusalMessage(after, context));
|
|
609
|
+
}
|
|
610
|
+
return saved;
|
|
611
|
+
}
|
|
517
612
|
async sayToRoom(sessionId, content, context) {
|
|
518
613
|
const { domain, user, tx } = context.state;
|
|
519
614
|
const session = await (0, shell_1.getRepository)(chat_session_js_1.ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } });
|
|
520
615
|
if (!session)
|
|
521
616
|
throw new Error(`ChatSession ${sessionId} not found`);
|
|
617
|
+
await writeGate(session, context, tx);
|
|
522
618
|
const body = (0, room_message_js_1.roomMessageBody)(content);
|
|
523
619
|
if (!body)
|
|
524
620
|
return null;
|
|
@@ -574,6 +670,7 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
574
670
|
const session = await (0, shell_1.getRepository)(chat_session_js_1.ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } });
|
|
575
671
|
if (!session)
|
|
576
672
|
throw new Error(`ChatSession ${sessionId} not found`);
|
|
673
|
+
await writeGate(session, context, tx);
|
|
577
674
|
/* 프롬프트가 한 기록으로 폭증하지 않도록 자른다 — 맥락 전달이 목적이고 전문 보존이 아니다. */
|
|
578
675
|
const body = (content ?? '').trim().slice(0, 4000);
|
|
579
676
|
if (!body)
|
|
@@ -614,6 +711,7 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
614
711
|
const session = await (0, shell_1.getRepository)(chat_session_js_1.ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } });
|
|
615
712
|
if (!session)
|
|
616
713
|
throw new Error(`ChatSession ${sessionId} not found`);
|
|
714
|
+
await writeGate(session, context, tx);
|
|
617
715
|
/* 옮겨온 대화는 **그 대화의 발언 그대로** 들어간다 — 한 덩어리 기록으로 뭉치면 사람이 읽을 수 없고
|
|
618
716
|
* (화면 하나를 잡아먹는 이탤릭 덩어리), 마크다운도 죽는다. 대신 개수·길이는 제한한다: 맥락 전달이
|
|
619
717
|
* 목적이고 전문 보존이 아니다. */
|
|
@@ -728,8 +826,12 @@ tslib_1.__decorate([
|
|
|
728
826
|
tslib_1.__param(5, (0, type_graphql_1.Arg)('mineOnly', { nullable: true })),
|
|
729
827
|
tslib_1.__param(6, (0, type_graphql_1.Arg)('limit', () => type_graphql_1.Int, { nullable: true })),
|
|
730
828
|
tslib_1.__param(7, (0, type_graphql_1.Arg)('offset', () => type_graphql_1.Int, { nullable: true })),
|
|
829
|
+
tslib_1.__param(8, (0, type_graphql_1.Arg)('kind', { nullable: true, description: 'Only this conversation kind (mode).' })),
|
|
830
|
+
tslib_1.__param(9, (0, type_graphql_1.Arg)('participantOnly', { nullable: true, description: 'Only conversations the caller is in.' })),
|
|
831
|
+
tslib_1.__param(10, (0, type_graphql_1.Arg)('visibility', { nullable: true, description: "Only 'open' or only 'private'." })),
|
|
832
|
+
tslib_1.__param(11, (0, type_graphql_1.Arg)('unreadOnly', { nullable: true, description: 'Only conversations with unread activity.' })),
|
|
731
833
|
tslib_1.__metadata("design:type", Function),
|
|
732
|
-
tslib_1.__metadata("design:paramtypes", [String, String, Object, Boolean, String, Boolean, Number, Number]),
|
|
834
|
+
tslib_1.__metadata("design:paramtypes", [String, String, Object, Boolean, String, Boolean, Number, Number, String, Boolean, String, Boolean]),
|
|
733
835
|
tslib_1.__metadata("design:returntype", Promise)
|
|
734
836
|
], ChatSessionResolver.prototype, "chatSessionInbox", null);
|
|
735
837
|
tslib_1.__decorate([
|
|
@@ -743,8 +845,12 @@ tslib_1.__decorate([
|
|
|
743
845
|
tslib_1.__param(3, (0, type_graphql_1.Arg)('showHidden', { nullable: true })),
|
|
744
846
|
tslib_1.__param(4, (0, type_graphql_1.Arg)('search', { nullable: true })),
|
|
745
847
|
tslib_1.__param(5, (0, type_graphql_1.Arg)('mineOnly', { nullable: true })),
|
|
848
|
+
tslib_1.__param(6, (0, type_graphql_1.Arg)('kind', { nullable: true, description: 'Only this conversation kind (mode).' })),
|
|
849
|
+
tslib_1.__param(7, (0, type_graphql_1.Arg)('participantOnly', { nullable: true, description: 'Only conversations the caller is in.' })),
|
|
850
|
+
tslib_1.__param(8, (0, type_graphql_1.Arg)('visibility', { nullable: true, description: "Only 'open' or only 'private'." })),
|
|
851
|
+
tslib_1.__param(9, (0, type_graphql_1.Arg)('unreadOnly', { nullable: true, description: 'Only conversations with unread activity.' })),
|
|
746
852
|
tslib_1.__metadata("design:type", Function),
|
|
747
|
-
tslib_1.__metadata("design:paramtypes", [String, String, Object, Boolean, String, Boolean]),
|
|
853
|
+
tslib_1.__metadata("design:paramtypes", [String, String, Object, Boolean, String, Boolean, String, Boolean, String, Boolean]),
|
|
748
854
|
tslib_1.__metadata("design:returntype", Promise)
|
|
749
855
|
], ChatSessionResolver.prototype, "chatSessionInboxTotal", null);
|
|
750
856
|
tslib_1.__decorate([
|
|
@@ -916,6 +1022,20 @@ tslib_1.__decorate([
|
|
|
916
1022
|
tslib_1.__metadata("design:paramtypes", [String, String, Object, Object]),
|
|
917
1023
|
tslib_1.__metadata("design:returntype", Promise)
|
|
918
1024
|
], ChatSessionResolver.prototype, "reportProposalOutcome", null);
|
|
1025
|
+
tslib_1.__decorate([
|
|
1026
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
1027
|
+
(0, type_graphql_1.Mutation)(() => [ChatAttachmentInfo], {
|
|
1028
|
+
description: "Store files with a conversation, to be sent with the next turn (assistantChat attachmentIds). Private conversations take files from their participants only; what is accepted is the conversation mode's attachment policy."
|
|
1029
|
+
}),
|
|
1030
|
+
(0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
|
|
1031
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
|
|
1032
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('files', () => [GraphQLUpload_js_1.default])),
|
|
1033
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
1034
|
+
tslib_1.__param(3, (0, type_graphql_1.Arg)('kind', { nullable: true, description: 'The conversation kind, for a session not stamped with one yet.' })),
|
|
1035
|
+
tslib_1.__metadata("design:type", Function),
|
|
1036
|
+
tslib_1.__metadata("design:paramtypes", [String, Array, Object, String]),
|
|
1037
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
1038
|
+
], ChatSessionResolver.prototype, "attachToConversation", null);
|
|
919
1039
|
tslib_1.__decorate([
|
|
920
1040
|
(0, type_graphql_1.Directive)('@transaction'),
|
|
921
1041
|
(0, type_graphql_1.Mutation)(() => String, {
|