@aalis/plugin-message-archive 0.1.0

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/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # @aalis/plugin-message-archive
2
+
3
+ 运行时插件
4
+
5
+ ## 角色
6
+
7
+ 运行时插件
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ pnpm add @aalis/plugin-message-archive
13
+ ```
14
+
15
+ ## 使用
16
+
17
+ 参考 [docs/architecture.md](../../docs/architecture.md) 与 [docs/guide/third-party-plugin.md](../../docs/guide/third-party-plugin.md)。
18
+
19
+ ## 许可
20
+
21
+ 见仓库根目录 LICENSE。
@@ -0,0 +1,17 @@
1
+ import type { ConfigSchema, Context } from '@aalis/core';
2
+ export type { ArchiveIncomingResult, ArchiveNoticeOptions, MessageArchiveCapability, MessageArchiveCapabilityRegistry, MessageArchiveService, } from '@aalis/plugin-message-archive-api';
3
+ export { MessageArchiveCapabilities } from '@aalis/plugin-message-archive-api';
4
+ export declare const name = "@aalis/plugin-message-archive";
5
+ export declare const displayName = "\u6D88\u606F\u5F52\u6863";
6
+ export declare const subsystem = "message";
7
+ export declare const inject: {
8
+ required: string[];
9
+ optional: string[];
10
+ };
11
+ export declare const provides: string[];
12
+ export declare const configSchema: ConfigSchema;
13
+ export declare const defaultConfig: {
14
+ debugLogs: boolean;
15
+ };
16
+ export declare function apply(ctx: Context, config: Record<string, unknown>): void;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AASzD,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,gCAAgC,EAChC,qBAAqB,GACtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE/E,eAAO,MAAM,IAAI,kCAAkC,CAAC;AACpD,eAAO,MAAM,WAAW,6BAAS,CAAC;AAClC,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,eAAO,MAAM,MAAM;;;CAGlB,CAAC;AACF,eAAO,MAAM,QAAQ,UAAsB,CAAC;AAE5C,eAAO,MAAM,YAAY,EAAE,YAO1B,CAAC;AAEF,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAiDF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAgKzE"}
package/dist/index.js ADDED
@@ -0,0 +1,220 @@
1
+ import { getMessageName, getSenderLabel, prefixSender, WellKnownKinds } from '@aalis/plugin-message-api';
2
+ import { MessageArchiveCapabilities } from '@aalis/plugin-message-archive-api';
3
+ export { MessageArchiveCapabilities } from '@aalis/plugin-message-archive-api';
4
+ export const name = '@aalis/plugin-message-archive';
5
+ export const displayName = '消息归档';
6
+ export const subsystem = 'message';
7
+ export const inject = {
8
+ required: ['memory'],
9
+ optional: ['media'],
10
+ };
11
+ export const provides = ['message-archive'];
12
+ export const configSchema = {
13
+ debugLogs: {
14
+ type: 'boolean',
15
+ label: '归档调试日志',
16
+ default: true,
17
+ description: '记录图片解释完成和消息写入记忆等调试日志。',
18
+ },
19
+ };
20
+ export const defaultConfig = {
21
+ debugLogs: true,
22
+ };
23
+ /** 从消息文本中抽取 @提及的用户 ID 列表(平台无关:依赖各 adapter 输出统一的 <at id="X"> 标签) */
24
+ function extractMentions(text) {
25
+ if (!text)
26
+ return [];
27
+ const ids = new Set();
28
+ const re = /<at(?:\s+self)?\s+id="([^"]+)">/g;
29
+ let m = re.exec(text);
30
+ while (m !== null) {
31
+ const id = m[1];
32
+ if (id && id !== 'all')
33
+ ids.add(id);
34
+ m = re.exec(text);
35
+ }
36
+ return [...ids];
37
+ }
38
+ /** 单用户平台:无需发送者前缀(不存在多人说话歧义) */
39
+ const SINGLE_USER_PLATFORMS = new Set(['webui', 'cli']);
40
+ function buildIncomingContent(incoming) {
41
+ const useSenderPrefix = !SINGLE_USER_PLATFORMS.has(incoming.platform);
42
+ let content = useSenderPrefix ? prefixSender(incoming.content, incoming.nickname, incoming.userId) : incoming.content;
43
+ // 引用回复:把被引用消息的标签 + 内容拼到末尾,作为不可分割的上下文
44
+ // 与图片描述、forward 摘要相同处理逻辑——把"非当前指令"的素材烘焙进归档文本,
45
+ // 这样下一轮从 memory 拉历史时仍能看到引用关系。
46
+ if (incoming.replyTo?.content) {
47
+ const replyLabel = getSenderLabel(incoming.replyTo.nickname, incoming.replyTo.userId) ?? '?';
48
+ content += `\n[引用 ${replyLabel} 的消息: ${incoming.replyTo.content}]`;
49
+ }
50
+ // 把 plugin-media 写入的 _attachmentDescriptions 按 attachments 顺序追加。
51
+ // 这里是图片/语音/视频描述合入对话文本的**唯一**入口——preprocessor 只负责写 descs,不改 content。
52
+ const attDescs = incoming._attachmentDescriptions;
53
+ if (attDescs && attDescs.length > 0) {
54
+ const lines = attDescs.filter((d) => Boolean(d?.trim()));
55
+ if (lines.length > 0) {
56
+ const attachText = lines.join('\n');
57
+ content = content ? `${content}\n${attachText}` : attachText;
58
+ }
59
+ }
60
+ return content;
61
+ }
62
+ export function apply(ctx, config) {
63
+ const cfg = {
64
+ debugLogs: config.debugLogs !== false,
65
+ };
66
+ // 必须懒查:ServiceRegistry.get 返回裸引用,apply 时缓存会在 memory provider 重载后失效。
67
+ // 表面上多一次查表调用,实际开销可忽,换取 provider 切换/bounce 时本插件不被级联 dispose。
68
+ function getMemory() {
69
+ const m = ctx.getService('memory');
70
+ if (!m)
71
+ throw new Error('message-archive 需要 memory 服务');
72
+ return m;
73
+ }
74
+ const service = {
75
+ async saveMessage(sessionId, message, options) {
76
+ await getMemory().saveMessage(sessionId, message);
77
+ if (cfg.debugLogs && options?.debugLabel) {
78
+ ctx.logger.debug(options.debugLabel);
79
+ }
80
+ },
81
+ async archiveIncoming(incoming) {
82
+ const working = {
83
+ ...incoming,
84
+ attachments: incoming.attachments ? incoming.attachments.map(a => ({ ...a })) : incoming.attachments,
85
+ _attachmentDescriptions: incoming._attachmentDescriptions
86
+ ? [...incoming._attachmentDescriptions]
87
+ : incoming._attachmentDescriptions,
88
+ };
89
+ // 调用 plugin-media 一站式处理(识别 attachments 并写回 _attachmentDescriptions)
90
+ // 仅在 preprocessor 尚未运行(_attachmentDescriptions 未预设)时才调用,避免重复识别。
91
+ if (working.attachments && working.attachments.length > 0 && !working._attachmentDescriptions) {
92
+ const mediaSvc = ctx.getService('media');
93
+ if (mediaSvc?.processMessage) {
94
+ const report = await mediaSvc.processMessage(working);
95
+ if (cfg.debugLogs && report.total > 0) {
96
+ ctx.logger.debug(`附件识别完成: ${report.successCount}/${report.total} 个成功 | ${working.content}`);
97
+ }
98
+ }
99
+ }
100
+ const content = buildIncomingContent(working);
101
+ // 把会话身份信息存入 metadata,供向量检索/上下文渲染等场景使用
102
+ const meta = {};
103
+ if (working.userId)
104
+ meta.userId = working.userId;
105
+ if (working.nickname)
106
+ meta.nickname = working.nickname;
107
+ if (working.platform)
108
+ meta.platform = working.platform;
109
+ if (working.groupId)
110
+ meta.groupId = working.groupId;
111
+ if (working.groupName)
112
+ meta.groupName = working.groupName;
113
+ if (working.sessionType)
114
+ meta.sessionType = working.sessionType;
115
+ // 平台侧消息 ID(如 OneBot message_id),用于"引用回复"反查归档原文
116
+ if (working.messageId)
117
+ meta.messageId = working.messageId;
118
+ // 文件附件名称列表:供前端历史加载时重建文件标签,避免 content 里的 inline 文件内容
119
+ // 污染对话气泡显示。此时 plugin-file-reader 已将 att.data 替换为 aalis-file://ID,
120
+ // 但 att.name 仍保留原始文件名。
121
+ const fileAttachments = working.attachments?.filter(a => a.kind === 'file') ?? [];
122
+ if (fileAttachments.length > 0) {
123
+ meta.fileNames = fileAttachments.map(a => a.name ?? '未知文件').filter(Boolean);
124
+ }
125
+ // 触发与来源溯源:用于区分真实用户消息 vs proactive 委派/调度等系统注入,
126
+ // 也方便事后审计"agent 在 X 群做过什么"
127
+ if (working.triggerType)
128
+ meta.triggerType = working.triggerType;
129
+ if (working.source)
130
+ meta.source = working.source;
131
+ const mentions = extractMentions(content);
132
+ if (mentions.length > 0)
133
+ meta.mentions = mentions;
134
+ // proactive 跨会话委派消息:作为 notice 角色 + kind='cross-session-delegation' 落盘,
135
+ // 与 plugin-agent 的 buildMessages 保持一致,避免 B 下次回看历史时
136
+ // 把派发任务误读为「曾经有用户说过这个」。
137
+ const isProactive = working.triggerType === 'proactive';
138
+ const message = {
139
+ role: isProactive ? 'notice' : 'user',
140
+ kind: isProactive ? WellKnownKinds.CrossSessionDelegation : undefined,
141
+ content,
142
+ name: isProactive ? undefined : getMessageName(working.userId),
143
+ timestamp: Date.now(),
144
+ metadata: Object.keys(meta).length > 0 ? meta : undefined,
145
+ };
146
+ await getMemory().saveMessage(working.sessionId, message);
147
+ if (cfg.debugLogs && working.attachments?.length) {
148
+ ctx.logger.debug(`附件消息已写入记忆: session=${working.sessionId}, attachments=${working.attachments.length} | ${content}`);
149
+ }
150
+ // 通知监听者:入站消息已落库(用于触发用户档案事实提取等后台任务)
151
+ // 与 agent 是否回复无关,所有走 archiveIncoming 的消息都会发出
152
+ ctx
153
+ .emit('inbound:message:archived', {
154
+ sessionId: working.sessionId,
155
+ incoming: working,
156
+ archivedMessage: message,
157
+ })
158
+ .catch(err => ctx.logger.debug(`inbound:message:archived 事件分发失败: ${err}`));
159
+ return {
160
+ message,
161
+ content,
162
+ };
163
+ },
164
+ async archiveNotice(opts) {
165
+ const text = (opts.content ?? '').trim();
166
+ if (!text)
167
+ return null;
168
+ const metadata = {};
169
+ if (opts.subType)
170
+ metadata.subType = opts.subType;
171
+ if (opts.platform)
172
+ metadata.platform = opts.platform;
173
+ if (opts.userId)
174
+ metadata.userId = opts.userId;
175
+ if (opts.targetId)
176
+ metadata.targetId = opts.targetId;
177
+ if (opts.groupId)
178
+ metadata.groupId = opts.groupId;
179
+ if (opts.operatorId)
180
+ metadata.operatorId = opts.operatorId;
181
+ if (opts.data)
182
+ Object.assign(metadata, opts.data);
183
+ const message = {
184
+ role: 'notice',
185
+ kind: opts.noticeType,
186
+ content: text,
187
+ timestamp: opts.timestamp ?? Date.now(),
188
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
189
+ };
190
+ await getMemory().saveMessage(opts.sessionId, message);
191
+ if (cfg.debugLogs) {
192
+ ctx.logger.debug(`[notice 入档] session=${opts.sessionId} type=${opts.noticeType}${opts.subType ? `/${opts.subType}` : ''} | ${text}`);
193
+ }
194
+ return message;
195
+ },
196
+ async findByMessageId(sessionId, messageId, scanLimit) {
197
+ if (!messageId)
198
+ return null;
199
+ const limit = Math.max(1, Math.min(500, Math.floor(scanLimit ?? 100)));
200
+ const history = await getMemory().getHistory(sessionId, limit);
201
+ // 从最新往旧找:引用通常指向最近发的消息
202
+ for (let i = history.length - 1; i >= 0; i -= 1) {
203
+ const m = history[i];
204
+ const mid = m.metadata?.messageId;
205
+ if (mid != null && String(mid) === messageId)
206
+ return m;
207
+ }
208
+ return null;
209
+ },
210
+ };
211
+ ctx.provide('message-archive', service, {
212
+ capabilities: [
213
+ MessageArchiveCapabilities.Incoming,
214
+ MessageArchiveCapabilities.Generic,
215
+ MessageArchiveCapabilities.Notice,
216
+ MessageArchiveCapabilities.Lookup,
217
+ ],
218
+ });
219
+ }
220
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { IncomingMessage, Message } from '@aalis/plugin-message-api';
2
+ export interface ArchiveIncomingResult {
3
+ message: Message;
4
+ content: string;
5
+ imageRecognitionInfo?: IncomingMessage['_imageRecognitionInfo'];
6
+ }
7
+ /** 平台通知/事件归档参数(参考 OneBot v11/v12 notice 规范) */
8
+ export interface ArchiveNoticeOptions {
9
+ /** 归档目标会话 ID(与正常消息共用同一会话) */
10
+ sessionId: string;
11
+ /** 通知类型:onebot 中的 notice_type / detail_type,例如 group_ban、group_recall、group_increase 等 */
12
+ noticeType: string;
13
+ /** 通知子类型(如 v11 group_ban 的 ban / lift_ban) */
14
+ subType?: string;
15
+ /** 人类可读的描述文本,将作为 system 消息内容写入记忆 */
16
+ content: string;
17
+ /** 平台标识(如 onebot) */
18
+ platform?: string;
19
+ /** 触发者用户 ID */
20
+ userId?: string;
21
+ /** 被操作者用户 ID(如禁言对象、撤回消息发送者) */
22
+ targetId?: string;
23
+ /** 群 ID(群聊场景) */
24
+ groupId?: string;
25
+ /** 操作者用户 ID(如管理员) */
26
+ operatorId?: string;
27
+ /** 事件时间戳(毫秒),缺省使用当前时间 */
28
+ timestamp?: number;
29
+ /** 任意附加数据(持续时长、消息 ID 等),透传至 metadata */
30
+ data?: Record<string, unknown>;
31
+ }
32
+ export interface MessageArchiveService {
33
+ saveMessage(sessionId: string, message: Message, options?: {
34
+ debugLabel?: string;
35
+ }): Promise<void>;
36
+ archiveIncoming(message: IncomingMessage): Promise<ArchiveIncomingResult>;
37
+ /** 平台 notice/事件入档(系统级条目,不会触发 agent 响应) */
38
+ archiveNotice?(options: ArchiveNoticeOptions): Promise<Message | null>;
39
+ }
40
+ export interface MessageArchiveCapabilityRegistry {
41
+ /** 支持入站消息归档(archiveIncoming,含图片预识别) */
42
+ Incoming: 'incoming';
43
+ /** 支持通用消息保存(saveMessage) */
44
+ Generic: 'generic';
45
+ /** 支持平台 notice 事件入档(archiveNotice) */
46
+ Notice: 'notice';
47
+ }
48
+ export type MessageArchiveCapability = MessageArchiveCapabilityRegistry[keyof MessageArchiveCapabilityRegistry];
49
+ export declare const MessageArchiveCapabilities: {
50
+ readonly Incoming: "incoming";
51
+ readonly Generic: "generic";
52
+ readonly Notice: "notice";
53
+ };
54
+ declare module '@aalis/core' {
55
+ interface ServiceCapabilityMap {
56
+ 'message-archive': MessageArchiveCapability;
57
+ }
58
+ }
59
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAC1E,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,eAAe,CAAC,uBAAuB,CAAC,CAAC;CACjE;AAED,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,0FAA0F;IAC1F,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnG,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC1E,0CAA0C;IAC1C,aAAa,CAAC,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CACxE;AAID,MAAM,WAAW,gCAAgC;IAC/C,uCAAuC;IACvC,QAAQ,EAAE,UAAU,CAAC;IACrB,4BAA4B;IAC5B,OAAO,EAAE,SAAS,CAAC;IACnB,sCAAsC;IACtC,MAAM,EAAE,QAAQ,CAAC;CAClB;AAED,MAAM,MAAM,wBAAwB,GAAG,gCAAgC,CAAC,MAAM,gCAAgC,CAAC,CAAC;AAEhH,eAAO,MAAM,0BAA0B;;;;CAIc,CAAC;AAEtD,OAAO,QAAQ,aAAa,CAAC;IAC3B,UAAU,oBAAoB;QAC5B,iBAAiB,EAAE,wBAAwB,CAAC;KAC7C;CACF"}
package/dist/types.js ADDED
@@ -0,0 +1,16 @@
1
+ import { registerCapabilityProbe } from '@aalis/core';
2
+ export const MessageArchiveCapabilities = {
3
+ Incoming: 'incoming',
4
+ Generic: 'generic',
5
+ Notice: 'notice',
6
+ };
7
+ registerCapabilityProbe('message-archive', MessageArchiveCapabilities.Incoming, inst => typeof inst.archiveIncoming === 'function'
8
+ ? true
9
+ : 'MessageArchiveService.archiveIncoming() is required for capability "incoming"');
10
+ registerCapabilityProbe('message-archive', MessageArchiveCapabilities.Generic, inst => typeof inst.saveMessage === 'function'
11
+ ? true
12
+ : 'MessageArchiveService.saveMessage() is required for capability "generic"');
13
+ registerCapabilityProbe('message-archive', MessageArchiveCapabilities.Notice, inst => typeof inst.archiveNotice === 'function'
14
+ ? true
15
+ : 'MessageArchiveService.archiveNotice() is required for capability "notice"');
16
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAsDtD,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;CACmC,CAAC;AAQtD,uBAAuB,CAAC,iBAAiB,EAAE,0BAA0B,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CACrF,OAAQ,IAAsC,CAAC,eAAe,KAAK,UAAU;IAC3E,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,+EAA+E,CACpF,CAAC;AAEF,uBAAuB,CAAC,iBAAiB,EAAE,0BAA0B,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CACpF,OAAQ,IAAkC,CAAC,WAAW,KAAK,UAAU;IACnE,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,0EAA0E,CAC/E,CAAC;AAEF,uBAAuB,CAAC,iBAAiB,EAAE,0BAA0B,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CACnF,OAAQ,IAAoC,CAAC,aAAa,KAAK,UAAU;IACvE,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,2EAA2E,CAChF,CAAC"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@aalis/plugin-message-archive",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "keywords": [
6
+ "aalis-plugin"
7
+ ],
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "dependencies": {
14
+ "@aalis/plugin-message-api": "^0.1.0",
15
+ "@aalis/plugin-message-archive-api": "^0.1.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^22.0.0",
19
+ "typescript": "^5.7.0",
20
+ "@aalis/plugin-media-api": "0.1.0",
21
+ "@aalis/core": "0.1.0",
22
+ "@aalis/plugin-memory-api": "0.1.0"
23
+ },
24
+ "peerDependencies": {
25
+ "@aalis/core": "^0.1.0"
26
+ },
27
+ "aalis": {
28
+ "service": {
29
+ "required": [
30
+ "memory"
31
+ ],
32
+ "optional": [
33
+ "media"
34
+ ],
35
+ "provides": [
36
+ "message-archive"
37
+ ]
38
+ }
39
+ },
40
+ "scripts": {
41
+ "build": "tsc",
42
+ "dev": "tsc --watch"
43
+ }
44
+ }