@things-factory/ai-assistant 10.1.123 → 10.1.127
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 +145 -95
- package/client/components/chat-echo-dedup.ts +2 -1
- package/client/components/reply-message.test.ts +15 -0
- package/client/components/reply-message.ts +11 -0
- package/client/components/roster-identity.test.ts +18 -0
- package/client/components/roster-identity.ts +10 -0
- package/client/utils/assistant-navigation.test.ts +22 -0
- package/dist-client/components/assistant-chat.d.ts +7 -0
- package/dist-client/components/assistant-chat.js +148 -94
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/components/chat-echo-dedup.d.ts +1 -0
- package/dist-client/components/chat-echo-dedup.js +1 -0
- package/dist-client/components/chat-echo-dedup.js.map +1 -1
- package/dist-client/components/reply-message.d.ts +5 -0
- package/dist-client/components/reply-message.js +14 -0
- package/dist-client/components/reply-message.js.map +1 -0
- package/dist-client/components/reply-message.test.d.ts +1 -0
- package/dist-client/components/reply-message.test.js +16 -0
- package/dist-client/components/reply-message.test.js.map +1 -0
- package/dist-client/components/roster-identity.d.ts +11 -0
- package/dist-client/components/roster-identity.js +11 -0
- package/dist-client/components/roster-identity.js.map +1 -0
- package/dist-client/components/roster-identity.test.d.ts +1 -0
- package/dist-client/components/roster-identity.test.js +20 -0
- package/dist-client/components/roster-identity.test.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/assistant-navigation.test.js +20 -0
- package/dist-client/utils/assistant-navigation.test.js.map +1 -1
- package/dist-server/service/chat-session-participant/read-roster.d.ts +9 -0
- package/dist-server/service/chat-session-participant/read-roster.js +15 -0
- package/dist-server/service/chat-session-participant/read-roster.js.map +1 -0
- package/dist-server/service/chat-session-resolver.d.ts +1 -1
- package/dist-server/service/chat-session-resolver.js +15 -11
- package/dist-server/service/chat-session-resolver.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/server/service/chat-session-participant/read-roster.test.ts +18 -0
- package/server/service/chat-session-participant/read-roster.ts +14 -0
- package/server/service/chat-session-resolver.ts +11 -8
- package/test/assistant-request-context.test.ts +3 -1
- package/translations/en.json +9 -1
- package/translations/ko.json +9 -1
|
@@ -34,4 +34,24 @@ describe('navigation wiring', () => {
|
|
|
34
34
|
expect(dock).toContain("errorCode: 'conversation-screen-changed'");
|
|
35
35
|
});
|
|
36
36
|
});
|
|
37
|
+
describe('a carried draft survives opening a new conversation', () => {
|
|
38
|
+
test('automatic review starts after cleanup and is sent once per request', () => {
|
|
39
|
+
const source = readFileSync(join(__dirname, '../components/assistant-chat.ts'), 'utf8');
|
|
40
|
+
const update = source.slice(source.indexOf(' updated(changed:'), source.indexOf(' disconnectedCallback()', source.indexOf(' updated(changed:')));
|
|
41
|
+
const placement = update.indexOf('if (this.autoAsk &&');
|
|
42
|
+
expect(placement).toBeGreaterThan(update.indexOf("if (changed.has('sessionId')"));
|
|
43
|
+
expect(update.slice(placement)).not.toContain("this.input = ''");
|
|
44
|
+
expect(update.slice(placement)).toContain('!== this._autoAsked');
|
|
45
|
+
expect(update.slice(placement)).toContain('void this.send()');
|
|
46
|
+
});
|
|
47
|
+
test('draft placement follows subject, mode and session cleanup', () => {
|
|
48
|
+
const source = readFileSync(join(__dirname, '../components/assistant-chat.ts'), 'utf8');
|
|
49
|
+
const update = source.slice(source.indexOf(' updated(changed:'), source.indexOf(' disconnectedCallback()', source.indexOf(' updated(changed:')));
|
|
50
|
+
const placement = update.indexOf('const draft = assistantDraftDecision(');
|
|
51
|
+
expect(placement).toBeGreaterThan(update.indexOf("if (changed.has('subject'))"));
|
|
52
|
+
expect(placement).toBeGreaterThan(update.indexOf("if (changed.has('mode')"));
|
|
53
|
+
expect(placement).toBeGreaterThan(update.indexOf("if (changed.has('sessionId')"));
|
|
54
|
+
expect(update.slice(placement)).not.toContain("this.input = ''");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
37
57
|
//# sourceMappingURL=assistant-navigation.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-navigation.test.js","sourceRoot":"","sources":["../../client/utils/assistant-navigation.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,QAAQ,CAAC,oEAAoE,EAAE,GAAG,EAAE;IAClF,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,iDAAiD,EAAE,MAAM,CAAC,EAAE;QACnF,KAAK,MAAM,WAAW,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,iBAAiB,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzF,CAAC;IACH,CAAC,CAAC,CAAA;IACF,IAAI,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,iBAAiB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACzG,CAAC,CAAC,CAAA;IACF,IAAI,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC/E,MAAM,CAAC,iBAAiB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACvG,CAAC,CAAC,CAAA;IACF,IAAI,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,iBAAiB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACxG,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iCAAiC,CAAC,EAAE,MAAM,CAAC,CAAA;IACrF,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC5E,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAA;QACxD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAA;IACnE,CAAC,CAAC,CAAA;IACF,IAAI,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAA;QACrD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAA;QACjD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;IACF,IAAI,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACtF,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAA;QAC9D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QACvE,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,0CAA0C,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import { surfaceTransition } from './assistant-navigation.js'\nimport { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\ndescribe('a screen offers context without taking over an active conversation', () => {\n test.each([false, true])('a different identity resets even when active=%s', active => {\n for (const sameSubject of [false, true]) {\n expect(surfaceTransition({ identityChanged: true, sameSubject, active })).toBe('reset')\n }\n })\n test('an empty conversation follows the screen', () => {\n expect(surfaceTransition({ identityChanged: false, sameSubject: false, active: false })).toBe('follow')\n })\n test('an existing conversation, draft or ongoing response offers a switch', () => {\n expect(surfaceTransition({ identityChanged: false, sameSubject: false, active: true })).toBe('offer')\n })\n test('returning to the same subject refreshes without reopening', () => {\n expect(surfaceTransition({ identityChanged: false, sameSubject: true, active: true })).toBe('refresh')\n })\n})\n\ndescribe('navigation wiring', () => {\n const dock = readFileSync(join(__dirname, '../components/assistant-dock.ts'), 'utf8')\n test('history hides rather than unmounts the chat and its unsent input', () => {\n expect(dock).toContain('?hidden=${this.showingHistory}')\n expect(dock).toContain('ready && !this.loading && !this.failure')\n })\n test('identity changes clear a carried ask and reread capability', () => {\n expect(dock).toContain(\"if (transition === 'reset')\")\n expect(dock).toContain('this.asking = undefined')\n expect(dock).toContain(\"this.capability = 'unknown'\")\n })\n test('all direct board actions check the current screen, not the retained editor', () => {\n expect(dock).toContain('if (!this.mayApplyOnScreen()) return')\n expect(dock.match(/if \\(this.mayApplyOnScreen\\(\\)\\)/g)).toHaveLength(2)\n expect(dock).toContain(\"errorCode: 'conversation-screen-changed'\")\n })\n})\n"]}
|
|
1
|
+
{"version":3,"file":"assistant-navigation.test.js","sourceRoot":"","sources":["../../client/utils/assistant-navigation.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { surfaceTransition } from './assistant-navigation.js'\nimport { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\ndescribe('a screen offers context without taking over an active conversation', () => {\n test.each([false, true])('a different identity resets even when active=%s', active => {\n for (const sameSubject of [false, true]) {\n expect(surfaceTransition({ identityChanged: true, sameSubject, active })).toBe('reset')\n }\n })\n test('an empty conversation follows the screen', () => {\n expect(surfaceTransition({ identityChanged: false, sameSubject: false, active: false })).toBe('follow')\n })\n test('an existing conversation, draft or ongoing response offers a switch', () => {\n expect(surfaceTransition({ identityChanged: false, sameSubject: false, active: true })).toBe('offer')\n })\n test('returning to the same subject refreshes without reopening', () => {\n expect(surfaceTransition({ identityChanged: false, sameSubject: true, active: true })).toBe('refresh')\n })\n})\n\ndescribe('navigation wiring', () => {\n const dock = readFileSync(join(__dirname, '../components/assistant-dock.ts'), 'utf8')\n test('history hides rather than unmounts the chat and its unsent input', () => {\n expect(dock).toContain('?hidden=${this.showingHistory}')\n expect(dock).toContain('ready && !this.loading && !this.failure')\n })\n test('identity changes clear a carried ask and reread capability', () => {\n expect(dock).toContain(\"if (transition === 'reset')\")\n expect(dock).toContain('this.asking = undefined')\n expect(dock).toContain(\"this.capability = 'unknown'\")\n })\n test('all direct board actions check the current screen, not the retained editor', () => {\n expect(dock).toContain('if (!this.mayApplyOnScreen()) return')\n expect(dock.match(/if \\(this.mayApplyOnScreen\\(\\)\\)/g)).toHaveLength(2)\n expect(dock).toContain(\"errorCode: 'conversation-screen-changed'\")\n })\n})\n\n\ndescribe('a carried draft survives opening a new conversation', () => {\n test('automatic review starts after cleanup and is sent once per request', () => {\n const source = readFileSync(join(__dirname, '../components/assistant-chat.ts'), 'utf8')\n const update = source.slice(source.indexOf(' updated(changed:'), source.indexOf(' disconnectedCallback()', source.indexOf(' updated(changed:')))\n const placement = update.indexOf('if (this.autoAsk &&')\n expect(placement).toBeGreaterThan(update.indexOf(\"if (changed.has('sessionId')\"))\n expect(update.slice(placement)).not.toContain(\"this.input = ''\")\n expect(update.slice(placement)).toContain('!== this._autoAsked')\n expect(update.slice(placement)).toContain('void this.send()')\n })\n test('draft placement follows subject, mode and session cleanup', () => {\n const source = readFileSync(join(__dirname, '../components/assistant-chat.ts'), 'utf8')\n const update = source.slice(source.indexOf(' updated(changed:'), source.indexOf(' disconnectedCallback()', source.indexOf(' updated(changed:')))\n const placement = update.indexOf('const draft = assistantDraftDecision(')\n expect(placement).toBeGreaterThan(update.indexOf(\"if (changed.has('subject'))\"))\n expect(placement).toBeGreaterThan(update.indexOf(\"if (changed.has('mode')\"))\n expect(placement).toBeGreaterThan(update.indexOf(\"if (changed.has('sessionId')\"))\n expect(update.slice(placement)).not.toContain(\"this.input = ''\")\n })\n})\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Read the room roster with user identities hydrated, after applying the room's visibility gate. */
|
|
2
|
+
export declare function readRoster<T>(room: {
|
|
3
|
+
id: string;
|
|
4
|
+
domainId: string;
|
|
5
|
+
visibility?: string;
|
|
6
|
+
}, port: {
|
|
7
|
+
isParticipant(): Promise<boolean>;
|
|
8
|
+
find(options: any): Promise<T[]>;
|
|
9
|
+
}): Promise<T[]>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readRoster = readRoster;
|
|
4
|
+
const session_visibility_js_1 = require("../chat-session/session-visibility.js");
|
|
5
|
+
/** Read the room roster with user identities hydrated, after applying the room's visibility gate. */
|
|
6
|
+
async function readRoster(room, port) {
|
|
7
|
+
if (!(0, session_visibility_js_1.mayReadSession)(room.visibility, room.visibility === 'private' ? await port.isParticipant() : false))
|
|
8
|
+
return [];
|
|
9
|
+
return port.find({
|
|
10
|
+
where: { session: { id: room.id }, domain: { id: room.domainId } },
|
|
11
|
+
relations: ['user'],
|
|
12
|
+
order: { createdAt: 'ASC' }
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=read-roster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-roster.js","sourceRoot":"","sources":["../../../server/service/chat-session-participant/read-roster.ts"],"names":[],"mappings":";;AAGA,gCAUC;AAbD,iFAAsE;AAEtE,qGAAqG;AAC9F,KAAK,UAAU,UAAU,CAC9B,IAA2D,EAC3D,IAA6E;IAE7E,IAAI,CAAC,IAAA,sCAAc,EAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACnH,OAAO,IAAI,CAAC,IAAI,CAAC;QACf,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE;QAClE,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;KAC5B,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { mayReadSession } from '../chat-session/session-visibility.js'\n\n/** Read the room roster with user identities hydrated, after applying the room's visibility gate. */\nexport async function readRoster<T>(\n room: { id: string; domainId: string; visibility?: string },\n port: { isParticipant(): Promise<boolean>; find(options: any): Promise<T[]> }\n): Promise<T[]> {\n if (!mayReadSession(room.visibility, room.visibility === 'private' ? await port.isParticipant() : false)) return []\n return port.find({\n where: { session: { id: room.id }, domain: { id: room.domainId } },\n relations: ['user'],\n order: { createdAt: 'ASC' }\n })\n}\n"]}
|
|
@@ -116,7 +116,7 @@ export declare class ChatSessionResolver {
|
|
|
116
116
|
* attachment policy. The size is known only once stored, so a file over the limit is removed and refused.
|
|
117
117
|
*/
|
|
118
118
|
attachToConversation(sessionId: string, files: FileUpload[], context: ResolverContext, kind?: string): Promise<ChatAttachmentInfo[]>;
|
|
119
|
-
sayToRoom(sessionId: string, content: string, context: ResolverContext): Promise<string | null>;
|
|
119
|
+
sayToRoom(sessionId: string, content: string, replyToId: string | undefined, context: ResolverContext): Promise<string | null>;
|
|
120
120
|
appendSessionNote(sessionId: string, content: string, context: ResolverContext): Promise<boolean>;
|
|
121
121
|
appendSessionTurns(sessionId: string, turns: {
|
|
122
122
|
role?: string;
|
|
@@ -23,6 +23,7 @@ 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 read_roster_js_1 = require("./chat-session-participant/read-roster.js");
|
|
26
27
|
const participant_lookup_js_1 = require("./chat-session-participant/participant-lookup.js");
|
|
27
28
|
const session_write_gate_js_1 = require("./chat-session/session-write-gate.js");
|
|
28
29
|
/**
|
|
@@ -447,16 +448,16 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
447
448
|
return await qb.getMany();
|
|
448
449
|
}
|
|
449
450
|
async chatSessionParticipants(sessionId, context) {
|
|
450
|
-
const { domain } = context.state;
|
|
451
|
+
const { domain, user } = context.state;
|
|
451
452
|
const session = await (0, shell_1.getRepository)(chat_session_js_1.ChatSession).findOneBy({
|
|
452
453
|
id: sessionId,
|
|
453
454
|
domain: { id: domain.id }
|
|
454
455
|
});
|
|
455
456
|
if (!session)
|
|
456
457
|
return [];
|
|
457
|
-
return
|
|
458
|
-
|
|
459
|
-
|
|
458
|
+
return (0, read_roster_js_1.readRoster)({ id: sessionId, domainId: domain.id, visibility: session.visibility }, {
|
|
459
|
+
isParticipant: () => (0, participant_lookup_js_1.isSessionParticipant)(domain.id, sessionId, user?.id),
|
|
460
|
+
find: options => (0, shell_1.getRepository)(chat_session_participant_js_1.ChatSessionParticipant).find(options)
|
|
460
461
|
});
|
|
461
462
|
}
|
|
462
463
|
async touchPresence(sessionId, context) {
|
|
@@ -650,7 +651,7 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
650
651
|
}
|
|
651
652
|
return saved;
|
|
652
653
|
}
|
|
653
|
-
async sayToRoom(sessionId, content, context) {
|
|
654
|
+
async sayToRoom(sessionId, content, replyToId, context) {
|
|
654
655
|
const { domain, user, tx } = context.state;
|
|
655
656
|
const session = await (0, shell_1.getRepository)(chat_session_js_1.ChatSession, tx).findOneBy({ id: sessionId, domain: { id: domain.id } });
|
|
656
657
|
if (!session)
|
|
@@ -659,10 +660,12 @@ let ChatSessionResolver = class ChatSessionResolver {
|
|
|
659
660
|
const body = (0, room_message_js_1.roomMessageBody)(content);
|
|
660
661
|
if (!body)
|
|
661
662
|
return null;
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
663
|
+
const messages = (0, shell_1.getRepository)(chat_message_js_1.ChatMessage, tx);
|
|
664
|
+
const previousLast = replyToId
|
|
665
|
+
? await messages.findOneBy({ id: replyToId, session: { id: session.id } })
|
|
666
|
+
: await messages.findOne({ where: { session: { id: session.id } }, order: { createdAt: 'DESC' } });
|
|
667
|
+
if (replyToId && !previousLast)
|
|
668
|
+
throw new Error('The message to reply to is not in this conversation');
|
|
666
669
|
const saved = await (0, shell_1.getRepository)(chat_message_js_1.ChatMessage, tx).save({
|
|
667
670
|
session: { id: session.id },
|
|
668
671
|
role: 'user',
|
|
@@ -1099,9 +1102,10 @@ tslib_1.__decorate([
|
|
|
1099
1102
|
(0, type_graphql_1.Directive)('@privilege(category: "ai-assistant", privilege: "mutation", domainOwnerGranted: true)'),
|
|
1100
1103
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('sessionId')),
|
|
1101
1104
|
tslib_1.__param(1, (0, type_graphql_1.Arg)('content')),
|
|
1102
|
-
tslib_1.__param(2, (0, type_graphql_1.
|
|
1105
|
+
tslib_1.__param(2, (0, type_graphql_1.Arg)('replyToId', { nullable: true })),
|
|
1106
|
+
tslib_1.__param(3, (0, type_graphql_1.Ctx)()),
|
|
1103
1107
|
tslib_1.__metadata("design:type", Function),
|
|
1104
|
-
tslib_1.__metadata("design:paramtypes", [String, String, Object]),
|
|
1108
|
+
tslib_1.__metadata("design:paramtypes", [String, String, String, Object]),
|
|
1105
1109
|
tslib_1.__metadata("design:returntype", Promise)
|
|
1106
1110
|
], ChatSessionResolver.prototype, "sayToRoom", null);
|
|
1107
1111
|
tslib_1.__decorate([
|