@seaverse/conversation-sdk 0.2.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.
Files changed (150) hide show
  1. package/README.md +284 -0
  2. package/dist/aggregated/apps-with-conversations.d.ts +47 -0
  3. package/dist/aggregated/apps-with-conversations.d.ts.map +1 -0
  4. package/dist/aggregated/apps-with-conversations.js +90 -0
  5. package/dist/aggregated/apps-with-conversations.js.map +1 -0
  6. package/dist/aggregated/index.d.ts +3 -0
  7. package/dist/aggregated/index.d.ts.map +1 -0
  8. package/dist/aggregated/index.js +2 -0
  9. package/dist/aggregated/index.js.map +1 -0
  10. package/dist/client/ConversationClient.d.ts +24 -0
  11. package/dist/client/ConversationClient.d.ts.map +1 -0
  12. package/dist/client/ConversationClient.js +56 -0
  13. package/dist/client/ConversationClient.js.map +1 -0
  14. package/dist/client/ConversationsClient.d.ts +31 -0
  15. package/dist/client/ConversationsClient.d.ts.map +1 -0
  16. package/dist/client/ConversationsClient.js +50 -0
  17. package/dist/client/ConversationsClient.js.map +1 -0
  18. package/dist/client/EnvironmentConfig.d.ts +12 -0
  19. package/dist/client/EnvironmentConfig.d.ts.map +1 -0
  20. package/dist/client/EnvironmentConfig.js +21 -0
  21. package/dist/client/EnvironmentConfig.js.map +1 -0
  22. package/dist/client/MessagesClient.d.ts +31 -0
  23. package/dist/client/MessagesClient.d.ts.map +1 -0
  24. package/dist/client/MessagesClient.js +57 -0
  25. package/dist/client/MessagesClient.js.map +1 -0
  26. package/dist/client/index.d.ts +3 -0
  27. package/dist/client/index.d.ts.map +1 -0
  28. package/dist/client/index.js +3 -0
  29. package/dist/client/index.js.map +1 -0
  30. package/dist/data/DbClient.d.ts +76 -0
  31. package/dist/data/DbClient.d.ts.map +1 -0
  32. package/dist/data/DbClient.js +107 -0
  33. package/dist/data/DbClient.js.map +1 -0
  34. package/dist/data/index.d.ts +2 -0
  35. package/dist/data/index.d.ts.map +1 -0
  36. package/dist/data/index.js +2 -0
  37. package/dist/data/index.js.map +1 -0
  38. package/dist/data/postgrest-headers.d.ts +10 -0
  39. package/dist/data/postgrest-headers.d.ts.map +1 -0
  40. package/dist/data/postgrest-headers.js +58 -0
  41. package/dist/data/postgrest-headers.js.map +1 -0
  42. package/dist/data/query.types.d.ts +62 -0
  43. package/dist/data/query.types.d.ts.map +1 -0
  44. package/dist/data/query.types.js +2 -0
  45. package/dist/data/query.types.js.map +1 -0
  46. package/dist/errors/AuthError.d.ts +8 -0
  47. package/dist/errors/AuthError.d.ts.map +1 -0
  48. package/dist/errors/AuthError.js +10 -0
  49. package/dist/errors/AuthError.js.map +1 -0
  50. package/dist/errors/BaseError.d.ts +17 -0
  51. package/dist/errors/BaseError.d.ts.map +1 -0
  52. package/dist/errors/BaseError.js +26 -0
  53. package/dist/errors/BaseError.js.map +1 -0
  54. package/dist/errors/NetworkError.d.ts +8 -0
  55. package/dist/errors/NetworkError.d.ts.map +1 -0
  56. package/dist/errors/NetworkError.js +10 -0
  57. package/dist/errors/NetworkError.js.map +1 -0
  58. package/dist/errors/ProtocolError.d.ts +8 -0
  59. package/dist/errors/ProtocolError.d.ts.map +1 -0
  60. package/dist/errors/ProtocolError.js +10 -0
  61. package/dist/errors/ProtocolError.js.map +1 -0
  62. package/dist/errors/TimeoutError.d.ts +8 -0
  63. package/dist/errors/TimeoutError.d.ts.map +1 -0
  64. package/dist/errors/TimeoutError.js +10 -0
  65. package/dist/errors/TimeoutError.js.map +1 -0
  66. package/dist/errors/index.d.ts +6 -0
  67. package/dist/errors/index.d.ts.map +1 -0
  68. package/dist/errors/index.js +6 -0
  69. package/dist/errors/index.js.map +1 -0
  70. package/dist/functional-api.d.ts +24 -0
  71. package/dist/functional-api.d.ts.map +1 -0
  72. package/dist/functional-api.js +59 -0
  73. package/dist/functional-api.js.map +1 -0
  74. package/dist/index.d.ts +5 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +9 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/resources/AppsResource.d.ts +37 -0
  79. package/dist/resources/AppsResource.d.ts.map +1 -0
  80. package/dist/resources/AppsResource.js +51 -0
  81. package/dist/resources/AppsResource.js.map +1 -0
  82. package/dist/resources/ConversationsResource.d.ts +81 -0
  83. package/dist/resources/ConversationsResource.d.ts.map +1 -0
  84. package/dist/resources/ConversationsResource.js +103 -0
  85. package/dist/resources/ConversationsResource.js.map +1 -0
  86. package/dist/resources/MessagesResource.d.ts +56 -0
  87. package/dist/resources/MessagesResource.d.ts.map +1 -0
  88. package/dist/resources/MessagesResource.js +115 -0
  89. package/dist/resources/MessagesResource.js.map +1 -0
  90. package/dist/session/session-token.d.ts +38 -0
  91. package/dist/session/session-token.d.ts.map +1 -0
  92. package/dist/session/session-token.js +74 -0
  93. package/dist/session/session-token.js.map +1 -0
  94. package/dist/transforms/app.transform.d.ts +6 -0
  95. package/dist/transforms/app.transform.d.ts.map +1 -0
  96. package/dist/transforms/app.transform.js +39 -0
  97. package/dist/transforms/app.transform.js.map +1 -0
  98. package/dist/transforms/conversation.transform.d.ts +10 -0
  99. package/dist/transforms/conversation.transform.d.ts.map +1 -0
  100. package/dist/transforms/conversation.transform.js +45 -0
  101. package/dist/transforms/conversation.transform.js.map +1 -0
  102. package/dist/transforms/message.transform.d.ts +12 -0
  103. package/dist/transforms/message.transform.d.ts.map +1 -0
  104. package/dist/transforms/message.transform.js +119 -0
  105. package/dist/transforms/message.transform.js.map +1 -0
  106. package/dist/transport/HttpClient.d.ts +34 -0
  107. package/dist/transport/HttpClient.d.ts.map +1 -0
  108. package/dist/transport/HttpClient.js +158 -0
  109. package/dist/transport/HttpClient.js.map +1 -0
  110. package/dist/transport/config.types.d.ts +40 -0
  111. package/dist/transport/config.types.d.ts.map +1 -0
  112. package/dist/transport/config.types.js +2 -0
  113. package/dist/transport/config.types.js.map +1 -0
  114. package/dist/transport/index.d.ts +10 -0
  115. package/dist/transport/index.d.ts.map +1 -0
  116. package/dist/transport/index.js +11 -0
  117. package/dist/transport/index.js.map +1 -0
  118. package/dist/transport/timeout.d.ts +12 -0
  119. package/dist/transport/timeout.d.ts.map +1 -0
  120. package/dist/transport/timeout.js +29 -0
  121. package/dist/transport/timeout.js.map +1 -0
  122. package/dist/types/common.types.d.ts +24 -0
  123. package/dist/types/common.types.d.ts.map +1 -0
  124. package/dist/types/common.types.js +5 -0
  125. package/dist/types/common.types.js.map +1 -0
  126. package/dist/types/config.types.d.ts +28 -0
  127. package/dist/types/config.types.d.ts.map +1 -0
  128. package/dist/types/config.types.js +2 -0
  129. package/dist/types/config.types.js.map +1 -0
  130. package/dist/types/http.types.d.ts +47 -0
  131. package/dist/types/http.types.d.ts.map +1 -0
  132. package/dist/types/http.types.js +2 -0
  133. package/dist/types/http.types.js.map +1 -0
  134. package/dist/types/index.d.ts +7 -0
  135. package/dist/types/index.d.ts.map +1 -0
  136. package/dist/types/index.js +2 -0
  137. package/dist/types/index.js.map +1 -0
  138. package/dist/types/models.types.d.ts +118 -0
  139. package/dist/types/models.types.d.ts.map +1 -0
  140. package/dist/types/models.types.js +5 -0
  141. package/dist/types/models.types.js.map +1 -0
  142. package/dist/types/pagination.types.d.ts +69 -0
  143. package/dist/types/pagination.types.d.ts.map +1 -0
  144. package/dist/types/pagination.types.js +24 -0
  145. package/dist/types/pagination.types.js.map +1 -0
  146. package/dist/types/token.types.d.ts +6 -0
  147. package/dist/types/token.types.d.ts.map +1 -0
  148. package/dist/types/token.types.js +2 -0
  149. package/dist/types/token.types.js.map +1 -0
  150. package/package.json +38 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TimeoutError.js","sourceRoot":"","sources":["../../src/errors/TimeoutError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,SAAS;IACzC,YAAY,UAAkB,iBAAiB,EAAE,SAAkB;QACjE,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ export { BaseError } from './BaseError.js';
2
+ export { NetworkError } from './NetworkError.js';
3
+ export { AuthError } from './AuthError.js';
4
+ export { TimeoutError } from './TimeoutError.js';
5
+ export { ProtocolError } from './ProtocolError.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { BaseError } from './BaseError.js';
2
+ export { NetworkError } from './NetworkError.js';
3
+ export { AuthError } from './AuthError.js';
4
+ export { TimeoutError } from './TimeoutError.js';
5
+ export { ProtocolError } from './ProtocolError.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * 函数式 API
3
+ * 提供简洁的函数式调用方式
4
+ */
5
+ import type { ConversationClientConfig } from './types/config.types.js';
6
+ import type { ListAppsWithConversationsResult, Message } from './types/index.js';
7
+ /**
8
+ * 初始化 Conversation SDK
9
+ */
10
+ export declare function initConversationSdk(config: ConversationClientConfig): {
11
+ getAppsWithConversationsList: (options?: {
12
+ appId?: string;
13
+ page?: number;
14
+ pageSize?: number;
15
+ }) => Promise<ListAppsWithConversationsResult>;
16
+ getMessagesList: (conversationId: string, options?: {
17
+ page?: number;
18
+ pageSize?: number;
19
+ }) => Promise<{
20
+ messages: Message[];
21
+ hasMore: boolean;
22
+ }>;
23
+ };
24
+ //# sourceMappingURL=functional-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functional-api.d.ts","sourceRoot":"","sources":["../src/functional-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAGxE,OAAO,KAAK,EAAE,+BAA+B,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGjF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,wBAAwB;6CA4BZ;QACpD,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,KAAG,OAAO,CAAC,+BAA+B,CAAC;sCAW1B,MAAM,YACZ;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,KACA,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;EActD"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * 函数式 API
3
+ * 提供简洁的函数式调用方式
4
+ */
5
+ import { createHttpClient } from './transport/index.js';
6
+ import { DbClient } from './data/DbClient.js';
7
+ import { getEnvironmentConfig } from './client/EnvironmentConfig.js';
8
+ import { listAppsWithConversations } from './aggregated/apps-with-conversations.js';
9
+ import { MessagesResource } from './resources/MessagesResource.js';
10
+ /**
11
+ * 初始化 Conversation SDK
12
+ */
13
+ export function initConversationSdk(config) {
14
+ // 环境配置解析
15
+ const envConfig = getEnvironmentConfig(config.environment);
16
+ const fullConfig = {
17
+ environment: config.environment,
18
+ token: config.token,
19
+ getToken: config.getToken || (() => config.token),
20
+ fetch: config.fetch || globalThis.fetch,
21
+ timeout: config.timeout || 30000,
22
+ urls: envConfig,
23
+ };
24
+ // 创建底层客户端
25
+ const http = createHttpClient({
26
+ baseUrl: fullConfig.urls.postgrest,
27
+ fetch: fullConfig.fetch,
28
+ getAuthToken: fullConfig.getToken,
29
+ timeoutMs: fullConfig.timeout,
30
+ });
31
+ const db = new DbClient(http);
32
+ const messagesResource = new MessagesResource(db);
33
+ /**
34
+ * 获取 Apps 及其会话列表
35
+ * 每个 app 只返回消息最多的那一个会话
36
+ */
37
+ async function getAppsWithConversationsList(options) {
38
+ return listAppsWithConversations({
39
+ ...options,
40
+ db,
41
+ });
42
+ }
43
+ /**
44
+ * 获取会话的消息列表(旧 API 格式)
45
+ */
46
+ async function getMessagesList(conversationId, options) {
47
+ const result = await messagesResource.list(conversationId, options);
48
+ // 转换为旧 API 格式:{messages: [...], hasMore: boolean}
49
+ return {
50
+ messages: result.data,
51
+ hasMore: result.pagination.hasNextPage,
52
+ };
53
+ }
54
+ return {
55
+ getAppsWithConversationsList,
56
+ getMessagesList,
57
+ };
58
+ }
59
+ //# sourceMappingURL=functional-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functional-api.js","sourceRoot":"","sources":["../src/functional-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AAEpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAgC;IAClE,SAAS;IACT,MAAM,SAAS,GAAG,oBAAoB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAE3D,MAAM,UAAU,GAAG;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;QACjD,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK;QACvC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;QAChC,IAAI,EAAE,SAAS;KAChB,CAAC;IAEF,UAAU;IACV,MAAM,IAAI,GAAG,gBAAgB,CAAC;QAC5B,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS;QAClC,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,YAAY,EAAE,UAAU,CAAC,QAAQ;QACjC,SAAS,EAAE,UAAU,CAAC,OAAO;KAC9B,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAElD;;;OAGG;IACH,KAAK,UAAU,4BAA4B,CAAC,OAI3C;QACC,OAAO,yBAAyB,CAAC;YAC/B,GAAG,OAAO;YACV,EAAE;SACH,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,UAAU,eAAe,CAC5B,cAAsB,EACtB,OAGC;QAED,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QAEpE,kDAAkD;QAClD,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,IAAI;YACrB,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,WAAW;SACvC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,4BAA4B;QAC5B,eAAe;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { initConversationSdk } from './functional-api.js';
2
+ export type { ConversationClientConfig } from './types/config.types.js';
3
+ export type { Conversation, Message, ToolCall, } from './types/index.js';
4
+ export { BaseError, NetworkError, AuthError, TimeoutError, ProtocolError, } from './errors/index.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAKxE,YAAY,EAEV,YAAY,EAEZ,OAAO,EACP,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,aAAa,GACd,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // ═══════════════════════════════════════
2
+ // 主 API
3
+ // ═══════════════════════════════════════
4
+ export { initConversationSdk } from './functional-api.js';
5
+ // ═══════════════════════════════════════
6
+ // 错误类型(供错误处理使用)
7
+ // ═══════════════════════════════════════
8
+ export { BaseError, NetworkError, AuthError, TimeoutError, ProtocolError, } from './errors/index.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,QAAQ;AACR,0CAA0C;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAc1D,0CAA0C;AAC1C,gBAAgB;AAChB,0CAA0C;AAC1C,OAAO,EACL,SAAS,EACT,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,aAAa,GACd,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { DbClient } from '../data/DbClient.js';
2
+ import type { App } from '../types/models.types.js';
3
+ import type { PaginationOptions, PaginatedResult } from '../types/pagination.types.js';
4
+ /**
5
+ * 应用列表查询选项
6
+ */
7
+ export interface ListAppsOptions extends PaginationOptions {
8
+ /**
9
+ * 按用户 ID 过滤
10
+ */
11
+ userId?: string;
12
+ /**
13
+ * 按状态过滤
14
+ */
15
+ status?: 'draft' | 'published' | 'archived';
16
+ /**
17
+ * 排序方向
18
+ * @default 'desc'
19
+ */
20
+ order?: 'asc' | 'desc';
21
+ }
22
+ /**
23
+ * 应用资源类
24
+ */
25
+ export declare class AppsResource {
26
+ private readonly db;
27
+ constructor(db: DbClient);
28
+ /**
29
+ * 列出应用(带分页)
30
+ */
31
+ list(options?: ListAppsOptions): Promise<PaginatedResult<App>>;
32
+ /**
33
+ * 获取单个应用
34
+ */
35
+ get(id: string): Promise<App | null>;
36
+ }
37
+ //# sourceMappingURL=AppsResource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppsResource.d.ts","sourceRoot":"","sources":["../../src/resources/AppsResource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,GAAG,EAAY,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIvF;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,CAAC;IAE5C;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAEzC;;OAEG;IACG,IAAI,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IA6BxE;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;CAS3C"}
@@ -0,0 +1,51 @@
1
+ import { calculatePaginationMeta, pageToOffset } from '../types/pagination.types.js';
2
+ import { transformApp } from '../transforms/app.transform.js';
3
+ /**
4
+ * 应用资源类
5
+ */
6
+ export class AppsResource {
7
+ constructor(db) {
8
+ this.db = db;
9
+ }
10
+ /**
11
+ * 列出应用(带分页)
12
+ */
13
+ async list(options = {}) {
14
+ // 分页参数
15
+ const page = options.page || 1;
16
+ const pageSize = options.pageSize || 20;
17
+ const { limit, offset } = pageToOffset(page, pageSize);
18
+ // 构建过滤条件
19
+ const filter = {};
20
+ if (options.userId)
21
+ filter.user_id = `eq.${options.userId}`;
22
+ if (options.status)
23
+ filter.status = `eq.${options.status}`;
24
+ const dbApps = await this.db.get('apps', {
25
+ filter,
26
+ order: `created_at.${options.order || 'desc'}`,
27
+ limit,
28
+ offset,
29
+ count: 'exact',
30
+ });
31
+ // 获取总数(从响应头)
32
+ const total = dbApps.count || 0;
33
+ const pagination = calculatePaginationMeta(total, page, pageSize);
34
+ return {
35
+ data: dbApps.data.map(transformApp),
36
+ pagination,
37
+ };
38
+ }
39
+ /**
40
+ * 获取单个应用
41
+ */
42
+ async get(id) {
43
+ const dbApp = await this.db.getOne('apps', {
44
+ filter: { app_id: `eq.${id}` },
45
+ });
46
+ if (!dbApp)
47
+ return null;
48
+ return transformApp(dbApp);
49
+ }
50
+ }
51
+ //# sourceMappingURL=AppsResource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppsResource.js","sourceRoot":"","sources":["../../src/resources/AppsResource.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAuB9D;;GAEG;AACH,MAAM,OAAO,YAAY;IACvB,YAA6B,EAAY;QAAZ,OAAE,GAAF,EAAE,CAAU;IAAG,CAAC;IAE7C;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,UAA2B,EAAE;QACtC,OAAO;QACP,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;QACxC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAEvD,SAAS;QACT,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM,CAAC,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;QAC5D,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM,CAAC,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;QAE3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAe,MAAM,EAAE;YACrD,MAAM;YACN,KAAK,EAAE,cAAc,OAAO,CAAC,KAAK,IAAI,MAAM,EAAE;YAC9C,KAAK;YACL,MAAM;YACN,KAAK,EAAE,OAAO;SACf,CAAC,CAAC;QAEH,aAAa;QACb,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;QAChC,MAAM,UAAU,GAAG,uBAAuB,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAElE,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;YACnC,UAAU;SACX,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAe,MAAM,EAAE;YACvD,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;SAC/B,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAExB,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,81 @@
1
+ import type { DbClient } from '../data/DbClient.js';
2
+ import type { Conversation, ListAppsWithConversationsResult } from '../types/models.types.js';
3
+ import type { PaginationOptions, PaginatedResult } from '../types/pagination.types.js';
4
+ /**
5
+ * 会话列表查询选项
6
+ */
7
+ export interface ListConversationsOptions extends PaginationOptions {
8
+ /**
9
+ * 按应用 ID 过滤
10
+ */
11
+ appId?: string;
12
+ /**
13
+ * 按用户 ID 过滤
14
+ */
15
+ userId?: string;
16
+ /**
17
+ * 排序字段
18
+ * @default 'createdAt'
19
+ */
20
+ orderBy?: 'createdAt' | 'updatedAt' | 'lastActiveAt';
21
+ /**
22
+ * 排序方向
23
+ * @default 'desc'
24
+ */
25
+ order?: 'asc' | 'desc';
26
+ }
27
+ /**
28
+ * 创建会话数据
29
+ */
30
+ export interface CreateConversationData {
31
+ title: string;
32
+ appId?: string | null;
33
+ userId: string;
34
+ }
35
+ /**
36
+ * 更新会话数据
37
+ */
38
+ export interface UpdateConversationData {
39
+ title?: string;
40
+ }
41
+ /**
42
+ * 会话资源类
43
+ */
44
+ export declare class ConversationsResource {
45
+ private readonly db;
46
+ constructor(db: DbClient);
47
+ /**
48
+ * 列出会话(带分页)
49
+ */
50
+ list(options?: ListConversationsOptions): Promise<PaginatedResult<Conversation>>;
51
+ /**
52
+ * 获取单个会话
53
+ */
54
+ get(id: string): Promise<Conversation | null>;
55
+ /**
56
+ * 创建会话
57
+ */
58
+ create(data: CreateConversationData): Promise<Conversation>;
59
+ /**
60
+ * 更新会话
61
+ */
62
+ update(id: string, data: UpdateConversationData): Promise<Conversation>;
63
+ /**
64
+ * 删除会话
65
+ */
66
+ delete(id: string): Promise<void>;
67
+ /**
68
+ * 聚合查询:获取应用及其会话列表
69
+ * 每个 app 只返回 message_count 最大的会话
70
+ *
71
+ * 替代 builder-sdk 的 GET /api/apps/with-conversations
72
+ * 直接从 PostgREST 并行获取数据
73
+ */
74
+ listAppsWithConversations(options?: {
75
+ appId?: string;
76
+ userId?: string;
77
+ page?: number;
78
+ pageSize?: number;
79
+ }): Promise<ListAppsWithConversationsResult>;
80
+ }
81
+ //# sourceMappingURL=ConversationsResource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConversationsResource.d.ts","sourceRoot":"","sources":["../../src/resources/ConversationsResource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EACV,YAAY,EAEZ,+BAA+B,EAEhC,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMvF;;GAEG;AACH,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IACjE;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,cAAc,CAAC;IAErD;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAG/B;;OAEG;IACG,IAAI,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAoC1F;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAUnD;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC;IAgBjE;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC;IAa7E;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;;;;;OAMG;IACG,yBAAyB,CAAC,OAAO,CAAC,EAAE;QACxC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,+BAA+B,CAAC;CAW7C"}
@@ -0,0 +1,103 @@
1
+ import { calculatePaginationMeta, pageToOffset } from '../types/pagination.types.js';
2
+ import { transformConversation, toDbConversation } from '../transforms/conversation.transform.js';
3
+ import { listAppsWithConversations as listAppsWithConversationsAggregated } from '../aggregated/apps-with-conversations.js';
4
+ /**
5
+ * 会话资源类
6
+ */
7
+ export class ConversationsResource {
8
+ constructor(db) {
9
+ this.db = db;
10
+ }
11
+ /**
12
+ * 列出会话(带分页)
13
+ */
14
+ async list(options = {}) {
15
+ // 分页参数
16
+ const page = options.page || 1;
17
+ const pageSize = options.pageSize || 20;
18
+ const { limit, offset } = pageToOffset(page, pageSize);
19
+ // 构建过滤条件
20
+ const filter = {};
21
+ if (options.appId)
22
+ filter.app_id = `eq.${options.appId}`;
23
+ if (options.userId)
24
+ filter.user_id = `eq.${options.userId}`;
25
+ // 构建排序
26
+ const orderField = options.orderBy === 'lastActiveAt' ? 'last_message_created_at' :
27
+ options.orderBy === 'updatedAt' ? 'updated_at' :
28
+ 'created_at';
29
+ const order = `${orderField}.${options.order || 'desc'}`;
30
+ const dbConversations = await this.db.get('conversations', {
31
+ filter,
32
+ order,
33
+ limit,
34
+ offset,
35
+ count: 'exact',
36
+ });
37
+ // 获取总数(从响应头)
38
+ const total = dbConversations.count || 0;
39
+ const pagination = calculatePaginationMeta(total, page, pageSize);
40
+ return {
41
+ data: dbConversations.data.map(conv => transformConversation(conv)),
42
+ pagination,
43
+ };
44
+ }
45
+ /**
46
+ * 获取单个会话
47
+ */
48
+ async get(id) {
49
+ const dbConv = await this.db.getOne('conversations', {
50
+ filter: { id: `eq.${id}` },
51
+ });
52
+ if (!dbConv)
53
+ return null;
54
+ return transformConversation(dbConv);
55
+ }
56
+ /**
57
+ * 创建会话
58
+ */
59
+ async create(data) {
60
+ const dbData = toDbConversation({
61
+ title: data.title,
62
+ appId: data.appId,
63
+ userId: data.userId,
64
+ });
65
+ const results = await this.db.post('conversations', dbData, {
66
+ returning: 'representation',
67
+ });
68
+ const dbConv = results[0];
69
+ return transformConversation(dbConv);
70
+ }
71
+ /**
72
+ * 更新会话
73
+ */
74
+ async update(id, data) {
75
+ const dbData = toDbConversation(data);
76
+ const results = await this.db.patch('conversations', { id: `eq.${id}` }, dbData, { returning: 'representation' });
77
+ return transformConversation(results[0]);
78
+ }
79
+ /**
80
+ * 删除会话
81
+ */
82
+ async delete(id) {
83
+ await this.db.delete('conversations', { id: `eq.${id}` });
84
+ }
85
+ /**
86
+ * 聚合查询:获取应用及其会话列表
87
+ * 每个 app 只返回 message_count 最大的会话
88
+ *
89
+ * 替代 builder-sdk 的 GET /api/apps/with-conversations
90
+ * 直接从 PostgREST 并行获取数据
91
+ */
92
+ async listAppsWithConversations(options) {
93
+ // 注意:这里暂时忽略 userId 过滤,因为聚合函数还不支持
94
+ // TODO: 在 apps-with-conversations.ts 中添加 userId 过滤支持
95
+ return await listAppsWithConversationsAggregated({
96
+ appId: options?.appId,
97
+ page: options?.page,
98
+ pageSize: options?.pageSize,
99
+ db: this.db,
100
+ });
101
+ }
102
+ }
103
+ //# sourceMappingURL=ConversationsResource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConversationsResource.js","sourceRoot":"","sources":["../../src/resources/ConversationsResource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import type { DbClient } from '../data/DbClient.js';
2
+ import type { Message } from '../types/models.types.js';
3
+ import type { PaginationOptions, PaginatedResult } from '../types/pagination.types.js';
4
+ /**
5
+ * 消息列表查询选项
6
+ */
7
+ export interface ListMessagesOptions extends PaginationOptions {
8
+ }
9
+ /**
10
+ * 创建消息数据
11
+ */
12
+ export interface CreateMessageData {
13
+ role: 'user' | 'assistant' | 'system';
14
+ content: string;
15
+ metadata?: Record<string, unknown>;
16
+ }
17
+ /**
18
+ * 消息资源类
19
+ */
20
+ export declare class MessagesResource {
21
+ private readonly db;
22
+ constructor(db: DbClient);
23
+ /**
24
+ * 列出会话的消息(带分页和去重)
25
+ */
26
+ list(conversationId: string, options?: ListMessagesOptions): Promise<PaginatedResult<Message>>;
27
+ /**
28
+ * 获取单条消息
29
+ */
30
+ get(messageId: string): Promise<Message | null>;
31
+ /**
32
+ * 添加消息
33
+ */
34
+ create(conversationId: string, data: CreateMessageData): Promise<Message>;
35
+ /**
36
+ * 更新消息
37
+ */
38
+ update(messageId: string, data: Partial<CreateMessageData>): Promise<Message>;
39
+ /**
40
+ * 删除消息
41
+ */
42
+ delete(messageId: string): Promise<void>;
43
+ /**
44
+ * 去重媒体消息
45
+ * 如果两条消息具有相同的 role、content、timestamp 和 media 内容,只保留第一条
46
+ *
47
+ * 参考 runtime-plugins/conversations/src/handlers/messages.ts
48
+ */
49
+ private deduplicateMediaMessages;
50
+ /**
51
+ * 创建媒体去重键
52
+ * 对数组进行排序以确保 ["a", "b"] 和 ["b", "a"] 被视为相同
53
+ */
54
+ private createMediaKey;
55
+ }
56
+ //# sourceMappingURL=MessagesResource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagesResource.d.ts","sourceRoot":"","sources":["../../src/resources/MessagesResource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIvF;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;CAE7D;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAEzC;;OAEG;IACG,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IA8BxG;;OAEG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAUrD;;OAEG;IACG,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAa/E;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAanF;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB;IAgChC;;;OAGG;IACH,OAAO,CAAC,cAAc;CAiBvB"}
@@ -0,0 +1,115 @@
1
+ import { calculatePaginationMeta, pageToOffset } from '../types/pagination.types.js';
2
+ import { transformMessage, toDbMessage } from '../transforms/message.transform.js';
3
+ /**
4
+ * 消息资源类
5
+ */
6
+ export class MessagesResource {
7
+ constructor(db) {
8
+ this.db = db;
9
+ }
10
+ /**
11
+ * 列出会话的消息(带分页和去重)
12
+ */
13
+ async list(conversationId, options = {}) {
14
+ // 分页参数
15
+ const page = options.page || 1;
16
+ const pageSize = options.pageSize || 100;
17
+ const { limit, offset } = pageToOffset(page, pageSize);
18
+ const dbMessages = await this.db.get('messages', {
19
+ filter: { conversation_id: `eq.${conversationId}` },
20
+ order: 'created_at.desc', // 默认倒序,最新的消息在前
21
+ limit,
22
+ offset,
23
+ count: 'exact',
24
+ });
25
+ // 转换消息
26
+ const messages = dbMessages.data.map(transformMessage);
27
+ // 去重(移除重复的媒体消息)
28
+ const dedupedMessages = this.deduplicateMediaMessages(messages);
29
+ // 获取总数(从响应头)
30
+ const total = dbMessages.count || 0;
31
+ const pagination = calculatePaginationMeta(total, page, pageSize);
32
+ return {
33
+ data: dedupedMessages,
34
+ pagination,
35
+ };
36
+ }
37
+ /**
38
+ * 获取单条消息
39
+ */
40
+ async get(messageId) {
41
+ const dbMsg = await this.db.getOne('messages', {
42
+ filter: { id: `eq.${messageId}` },
43
+ });
44
+ if (!dbMsg)
45
+ return null;
46
+ return transformMessage(dbMsg);
47
+ }
48
+ /**
49
+ * 添加消息
50
+ */
51
+ async create(conversationId, data) {
52
+ const dbData = {
53
+ conversation_id: conversationId,
54
+ ...toDbMessage(data),
55
+ };
56
+ const results = await this.db.post('messages', dbData, {
57
+ returning: 'representation',
58
+ });
59
+ return transformMessage(results[0]);
60
+ }
61
+ /**
62
+ * 更新消息
63
+ */
64
+ async update(messageId, data) {
65
+ const dbData = toDbMessage(data);
66
+ const results = await this.db.patch('messages', { id: `eq.${messageId}` }, dbData, { returning: 'representation' });
67
+ return transformMessage(results[0]);
68
+ }
69
+ /**
70
+ * 删除消息
71
+ */
72
+ async delete(messageId) {
73
+ await this.db.delete('messages', { id: `eq.${messageId}` });
74
+ }
75
+ /**
76
+ * 去重媒体消息
77
+ * 如果两条消息具有相同的 role、content、timestamp 和 media 内容,只保留第一条
78
+ *
79
+ * 参考 runtime-plugins/conversations/src/handlers/messages.ts
80
+ */
81
+ deduplicateMediaMessages(messages) {
82
+ const result = [];
83
+ const seenMedia = new Set();
84
+ for (const msg of messages) {
85
+ // 检查消息的 metadata 中是否包含 media 字段(需要通过 any 类型访问)
86
+ const metadata = msg.metadata;
87
+ const hasMedia = metadata?.type === 'media' && metadata?.media;
88
+ if (hasMedia) {
89
+ // 创建去重键(基于 content、role、timestamp 和 media)
90
+ const mediaKey = this.createMediaKey(msg.content || '', msg.role || 'unknown', msg.timestamp, metadata.media);
91
+ // 如果已经见过这个媒体内容,跳过
92
+ if (seenMedia.has(mediaKey)) {
93
+ continue;
94
+ }
95
+ seenMedia.add(mediaKey);
96
+ }
97
+ result.push(msg);
98
+ }
99
+ return result;
100
+ }
101
+ /**
102
+ * 创建媒体去重键
103
+ * 对数组进行排序以确保 ["a", "b"] 和 ["b", "a"] 被视为相同
104
+ */
105
+ createMediaKey(content, role, timestamp, media) {
106
+ // 排序图片
107
+ const images = (media.images || []).slice().sort();
108
+ // 排序音频
109
+ const audios = (media.audios || []).slice().sort();
110
+ // 排序视频
111
+ const videos = (media.videos || []).slice().sort();
112
+ return `content:${content}|role:${role}|ts:${timestamp}|images:${JSON.stringify(images)}|audios:${JSON.stringify(audios)}|videos:${JSON.stringify(videos)}`;
113
+ }
114
+ }
115
+ //# sourceMappingURL=MessagesResource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagesResource.js","sourceRoot":"","sources":["../../src/resources/MessagesResource.ts"],"names":[],"mappings":"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"}