@xopcai/xopc 0.0.14 → 0.0.16

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 (161) hide show
  1. package/dist/extensions/feishu/src/adapters/onboard-cli.d.ts +7 -0
  2. package/dist/extensions/feishu/src/adapters/onboard-cli.js +432 -0
  3. package/dist/extensions/feishu/src/adapters/onboard-cli.js.map +1 -0
  4. package/dist/extensions/feishu/src/auth/pairing.d.ts +7 -0
  5. package/dist/extensions/feishu/src/auth/pairing.js +45 -0
  6. package/dist/extensions/feishu/src/auth/pairing.js.map +1 -0
  7. package/dist/extensions/feishu/src/auth/paths.d.ts +2 -0
  8. package/dist/extensions/feishu/src/auth/paths.js +18 -0
  9. package/dist/extensions/feishu/src/auth/paths.js.map +1 -0
  10. package/dist/extensions/feishu/src/directory/directory-adapter.d.ts +2 -0
  11. package/dist/extensions/feishu/src/directory/directory-adapter.js +27 -0
  12. package/dist/extensions/feishu/src/directory/directory-adapter.js.map +1 -0
  13. package/dist/extensions/feishu/src/format.d.ts +21 -0
  14. package/dist/extensions/feishu/src/format.js +99 -0
  15. package/dist/extensions/feishu/src/format.js.map +1 -0
  16. package/dist/extensions/feishu/src/index.d.ts +5 -0
  17. package/dist/extensions/feishu/src/index.js +3 -0
  18. package/dist/extensions/feishu/src/outbound/actions.d.ts +51 -0
  19. package/dist/extensions/feishu/src/outbound/actions.js +62 -0
  20. package/dist/extensions/feishu/src/outbound/actions.js.map +1 -0
  21. package/dist/extensions/feishu/src/outbound/media-load.d.ts +12 -0
  22. package/dist/extensions/feishu/src/outbound/media-load.js +125 -0
  23. package/dist/extensions/feishu/src/outbound/media-load.js.map +1 -0
  24. package/dist/extensions/feishu/src/outbound/outbound-adapter.d.ts +2 -0
  25. package/dist/extensions/feishu/src/outbound/outbound-adapter.js +201 -0
  26. package/dist/extensions/feishu/src/outbound/outbound-adapter.js.map +1 -0
  27. package/dist/extensions/feishu/src/plugin.d.ts +70 -0
  28. package/dist/extensions/feishu/src/plugin.js +313 -0
  29. package/dist/extensions/feishu/src/plugin.js.map +1 -0
  30. package/dist/extensions/feishu/src/schema/config-schema.d.ts +215 -0
  31. package/dist/extensions/feishu/src/schema/config-schema.js +198 -0
  32. package/dist/extensions/feishu/src/schema/config-schema.js.map +1 -0
  33. package/dist/extensions/feishu/src/state/accounts.d.ts +38 -0
  34. package/dist/extensions/feishu/src/state/accounts.js +96 -0
  35. package/dist/extensions/feishu/src/state/accounts.js.map +1 -0
  36. package/dist/extensions/feishu/src/state/message-bindings.d.ts +11 -0
  37. package/dist/extensions/feishu/src/state/message-bindings.js +41 -0
  38. package/dist/extensions/feishu/src/state/message-bindings.js.map +1 -0
  39. package/dist/extensions/feishu/src/state/thread-bindings.js +46 -0
  40. package/dist/extensions/feishu/src/state/thread-bindings.js.map +1 -0
  41. package/dist/extensions/feishu/src/status/doctor.d.ts +2 -0
  42. package/dist/extensions/feishu/src/status/doctor.js +38 -0
  43. package/dist/extensions/feishu/src/status/doctor.js.map +1 -0
  44. package/dist/extensions/feishu/src/status/status-adapter.d.ts +3 -0
  45. package/dist/extensions/feishu/src/status/status-adapter.js +45 -0
  46. package/dist/extensions/feishu/src/status/status-adapter.js.map +1 -0
  47. package/dist/extensions/feishu/src/streaming/streaming-adapter.d.ts +3 -0
  48. package/dist/extensions/feishu/src/streaming/streaming-adapter.js +242 -0
  49. package/dist/extensions/feishu/src/streaming/streaming-adapter.js.map +1 -0
  50. package/dist/extensions/feishu/src/subagent-hooks.js +52 -0
  51. package/dist/extensions/feishu/src/subagent-hooks.js.map +1 -0
  52. package/dist/extensions/feishu/src/tools/docx/docx-batch-insert.js +95 -0
  53. package/dist/extensions/feishu/src/tools/docx/docx-batch-insert.js.map +1 -0
  54. package/dist/extensions/feishu/src/tools/docx/docx-color-text.js +75 -0
  55. package/dist/extensions/feishu/src/tools/docx/docx-color-text.js.map +1 -0
  56. package/dist/extensions/feishu/src/tools/docx/docx-table-ops.js +173 -0
  57. package/dist/extensions/feishu/src/tools/docx/docx-table-ops.js.map +1 -0
  58. package/dist/extensions/feishu/src/tools/docx/docx-types.js +1 -0
  59. package/dist/extensions/feishu/src/tools/tools.d.ts +5 -0
  60. package/dist/extensions/feishu/src/tools/tools.js +46 -0
  61. package/dist/extensions/feishu/src/tools/tools.js.map +1 -0
  62. package/dist/extensions/feishu/src/transport/client/client.d.ts +6 -0
  63. package/dist/extensions/feishu/src/transport/client/client.js +41 -0
  64. package/dist/extensions/feishu/src/transport/client/client.js.map +1 -0
  65. package/dist/extensions/feishu/src/transport/client/lark-sdk-logger.d.ts +13 -0
  66. package/dist/extensions/feishu/src/transport/client/lark-sdk-logger.js +104 -0
  67. package/dist/extensions/feishu/src/transport/client/lark-sdk-logger.js.map +1 -0
  68. package/dist/extensions/feishu/src/transport/reliability/dedupe.d.ts +7 -0
  69. package/dist/extensions/feishu/src/transport/reliability/dedupe.js +30 -0
  70. package/dist/extensions/feishu/src/transport/reliability/dedupe.js.map +1 -0
  71. package/dist/extensions/feishu/src/transport/socket-mode/monitor.d.ts +19 -0
  72. package/dist/extensions/feishu/src/transport/socket-mode/monitor.js +326 -0
  73. package/dist/extensions/feishu/src/transport/socket-mode/monitor.js.map +1 -0
  74. package/dist/extensions/feishu/src/transport/socket-mode/retry.d.ts +1 -0
  75. package/dist/extensions/feishu/src/transport/socket-mode/retry.js +10 -0
  76. package/dist/extensions/feishu/src/transport/socket-mode/retry.js.map +1 -0
  77. package/dist/extensions/feishu/src/transport/text/mentions.d.ts +1 -0
  78. package/dist/extensions/feishu/src/transport/text/mentions.js +9 -0
  79. package/dist/extensions/feishu/src/transport/text/mentions.js.map +1 -0
  80. package/dist/extensions/feishu/src/transport/webhook/monitor.d.ts +19 -0
  81. package/dist/extensions/feishu/src/transport/webhook/monitor.js +271 -0
  82. package/dist/extensions/feishu/src/transport/webhook/monitor.js.map +1 -0
  83. package/dist/extensions/feishu/src/ui/config-surface.d.ts +2 -0
  84. package/dist/extensions/feishu/src/ui/config-surface.js +6 -0
  85. package/dist/extensions/feishu/src/ui/config-surface.js.map +1 -0
  86. package/dist/extensions/feishu/xopc.extension.json +18 -0
  87. package/dist/extensions/telegram/xopc.extension.json +20 -0
  88. package/dist/extensions/weixin/xopc.extension.json +17 -0
  89. package/dist/gateway/static/root/assets/{agents-C2blSFQk.js → agents-Dy5cGVVQ.js} +2 -2
  90. package/dist/gateway/static/root/assets/{agents-C2blSFQk.js.map → agents-Dy5cGVVQ.js.map} +1 -1
  91. package/dist/gateway/static/root/assets/{apps-page-Dg7InQ41.js → apps-page-BOpDR0Lz.js} +2 -2
  92. package/dist/gateway/static/root/assets/{apps-page-Dg7InQ41.js.map → apps-page-BOpDR0Lz.js.map} +1 -1
  93. package/dist/gateway/static/root/assets/channels-settings-CrCesccB.js +9 -0
  94. package/dist/gateway/static/root/assets/channels-settings-CrCesccB.js.map +1 -0
  95. package/dist/gateway/static/root/assets/{cron-page-B-7O4_QQ.js → cron-page-B_XY0gPt.js} +2 -2
  96. package/dist/gateway/static/root/assets/{cron-page-B-7O4_QQ.js.map → cron-page-B_XY0gPt.js.map} +1 -1
  97. package/dist/gateway/static/root/assets/{cron-utils-DvRPM814.js → cron-utils-BYdnLwhl.js} +2 -2
  98. package/dist/gateway/static/root/assets/{cron-utils-DvRPM814.js.map → cron-utils-BYdnLwhl.js.map} +1 -1
  99. package/dist/gateway/static/root/assets/{dist-DYzyRkRh.js → dist-DvaA5uNp.js} +2 -2
  100. package/dist/gateway/static/root/assets/{dist-DYzyRkRh.js.map → dist-DvaA5uNp.js.map} +1 -1
  101. package/dist/gateway/static/root/assets/{extension-debug-page-DV-NwlaY.js → extension-debug-page-CPSk7gFW.js} +2 -2
  102. package/dist/gateway/static/root/assets/{extension-debug-page-DV-NwlaY.js.map → extension-debug-page-CPSk7gFW.js.map} +1 -1
  103. package/dist/gateway/static/root/assets/{extension-page-UUKLJwpo.js → extension-page-COdbk9I6.js} +2 -2
  104. package/dist/gateway/static/root/assets/{extension-page-UUKLJwpo.js.map → extension-page-COdbk9I6.js.map} +1 -1
  105. package/dist/gateway/static/root/assets/{extension-settings-page-R4VlbZOj.js → extension-settings-page-BlEz2Ily.js} +2 -2
  106. package/dist/gateway/static/root/assets/{extension-settings-page-R4VlbZOj.js.map → extension-settings-page-BlEz2Ily.js.map} +1 -1
  107. package/dist/gateway/static/root/assets/index-BQNdJlkw.css +1 -0
  108. package/dist/gateway/static/root/assets/index-tm9ZY35l.js +144 -0
  109. package/dist/gateway/static/root/assets/{index-BCVqNi5T.js.map → index-tm9ZY35l.js.map} +1 -1
  110. package/dist/gateway/static/root/assets/{logs-page-BgUDjMge.js → logs-page-LSa0jmLO.js} +2 -2
  111. package/dist/gateway/static/root/assets/{logs-page-BgUDjMge.js.map → logs-page-LSa0jmLO.js.map} +1 -1
  112. package/dist/gateway/static/root/assets/sessions-page-cn2fi_V3.js +2 -0
  113. package/dist/gateway/static/root/assets/sessions-page-cn2fi_V3.js.map +1 -0
  114. package/dist/gateway/static/root/assets/{settings-page-Doa_lzdW.js → settings-page-CyHd5szQ.js} +2 -2
  115. package/dist/gateway/static/root/assets/{settings-page-Doa_lzdW.js.map → settings-page-CyHd5szQ.js.map} +1 -1
  116. package/dist/gateway/static/root/assets/{skills-page-BdNqg2NG.js → skills-page-irjxwW9u.js} +2 -2
  117. package/dist/gateway/static/root/assets/{skills-page-BdNqg2NG.js.map → skills-page-irjxwW9u.js.map} +1 -1
  118. package/dist/gateway/static/root/channel-icons/feishu.svg +12 -0
  119. package/dist/gateway/static/root/channel-icons/lark.svg +12 -0
  120. package/dist/gateway/static/root/channel-icons/telegram.svg +1 -0
  121. package/dist/gateway/static/root/channel-icons/wechat.svg +1 -0
  122. package/dist/gateway/static/root/channel-icons/weixin.svg +1 -0
  123. package/dist/gateway/static/root/index.html +2 -2
  124. package/dist/package.js +1 -1
  125. package/dist/src/agent/agent-manager.d.ts +1 -0
  126. package/dist/src/agent/agent-manager.js +1 -0
  127. package/dist/src/agent/agent-manager.js.map +1 -1
  128. package/dist/src/agent/service.js +3 -0
  129. package/dist/src/agent/service.js.map +1 -1
  130. package/dist/src/agent/tools/delegate-tool.d.ts +8 -0
  131. package/dist/src/agent/tools/delegate-tool.js +60 -2
  132. package/dist/src/agent/tools/delegate-tool.js.map +1 -1
  133. package/dist/src/agent/tools/factory.d.ts +1 -0
  134. package/dist/src/agent/tools/factory.js +2 -0
  135. package/dist/src/agent/tools/factory.js.map +1 -1
  136. package/dist/src/channels/envelope-timestamp.d.ts +5 -0
  137. package/dist/src/channels/envelope-timestamp.js +10 -1
  138. package/dist/src/channels/envelope-timestamp.js.map +1 -1
  139. package/dist/src/channels/feishu/index.d.ts +5 -0
  140. package/dist/src/channels/feishu/index.js +4 -0
  141. package/dist/src/chat-commands/types.d.ts +1 -1
  142. package/dist/src/extensions/types/hooks.d.ts +46 -1
  143. package/dist/src/extensions/types/hooks.js +3 -0
  144. package/dist/src/extensions/types/hooks.js.map +1 -1
  145. package/dist/src/gateway/service.js +1 -1
  146. package/dist/src/generated/bundled-channel-plugins.d.ts +2 -1
  147. package/dist/src/generated/bundled-channel-plugins.js +8 -2
  148. package/dist/src/generated/bundled-channel-plugins.js.map +1 -1
  149. package/dist/src/providers/env-keys.js +1 -0
  150. package/dist/src/providers/env-keys.js.map +1 -1
  151. package/dist/src/providers/index.js +5 -0
  152. package/dist/src/providers/index.js.map +1 -1
  153. package/dist/src/session/session-title.js +2 -1
  154. package/dist/src/session/session-title.js.map +1 -1
  155. package/package.json +2 -2
  156. package/dist/gateway/static/root/assets/channels-settings-CHOL7G_P.js +0 -9
  157. package/dist/gateway/static/root/assets/channels-settings-CHOL7G_P.js.map +0 -1
  158. package/dist/gateway/static/root/assets/index-BCVqNi5T.js +0 -144
  159. package/dist/gateway/static/root/assets/index-XbYityMf.css +0 -1
  160. package/dist/gateway/static/root/assets/sessions-page-L2VUocA4.js +0 -2
  161. package/dist/gateway/static/root/assets/sessions-page-L2VUocA4.js.map +0 -1
@@ -0,0 +1,173 @@
1
+ //#region extensions/feishu/src/tools/docx/docx-table-ops.ts
2
+ const MIN_COLUMN_WIDTH = 50;
3
+ const MAX_COLUMN_WIDTH = 400;
4
+ const DEFAULT_TABLE_WIDTH = 730;
5
+ function normalizeChildBlockIds(children) {
6
+ if (Array.isArray(children)) return children;
7
+ return typeof children === "string" ? [children] : [];
8
+ }
9
+ function omitParentId(block) {
10
+ const cleanBlock = { ...block };
11
+ delete cleanBlock.parent_id;
12
+ return cleanBlock;
13
+ }
14
+ function createDescendantTable(table, adaptiveWidths) {
15
+ const { row_size, column_size } = table.property || {};
16
+ return { property: {
17
+ row_size,
18
+ column_size,
19
+ ...adaptiveWidths?.length ? { column_width: adaptiveWidths } : {}
20
+ } };
21
+ }
22
+ function calculateAdaptiveColumnWidths(blocks, tableBlockId) {
23
+ const tableBlock = blocks.find((b) => b.block_id === tableBlockId && b.block_type === 31);
24
+ if (!tableBlock?.table?.property) return [];
25
+ const { row_size, column_size, column_width: originalWidths } = tableBlock.table.property;
26
+ if (!row_size || !column_size) return [];
27
+ const totalWidth = originalWidths && originalWidths.length > 0 ? originalWidths.reduce((a, b) => a + b, 0) : DEFAULT_TABLE_WIDTH;
28
+ const cellIds = normalizeChildBlockIds(tableBlock.children);
29
+ const blockMap = /* @__PURE__ */ new Map();
30
+ for (const block of blocks) if (block.block_id) blockMap.set(block.block_id, block);
31
+ function getCellText(cellId) {
32
+ const cell = blockMap.get(cellId);
33
+ let text = "";
34
+ const childIds = normalizeChildBlockIds(cell?.children);
35
+ for (const childId of childIds) {
36
+ const child = blockMap.get(childId);
37
+ if (child?.text?.elements) {
38
+ for (const elem of child.text.elements) if (elem.text_run?.content) text += elem.text_run.content;
39
+ }
40
+ }
41
+ return text;
42
+ }
43
+ function getWeightedLength(text) {
44
+ return Array.from(text).reduce((sum, char) => sum + (char.charCodeAt(0) > 255 ? 2 : 1), 0);
45
+ }
46
+ const maxLengths = Array.from({ length: column_size }, () => 0);
47
+ for (let row = 0; row < row_size; row++) for (let col = 0; col < column_size; col++) {
48
+ const cellId = cellIds[row * column_size + col];
49
+ if (!cellId) continue;
50
+ const length = getWeightedLength(getCellText(cellId));
51
+ maxLengths[col] = Math.max(maxLengths[col], length);
52
+ }
53
+ const totalLength = maxLengths.reduce((a, b) => a + b, 0);
54
+ if (totalLength === 0) {
55
+ const equalWidth = Math.max(MIN_COLUMN_WIDTH, Math.min(MAX_COLUMN_WIDTH, Math.floor(totalWidth / column_size)));
56
+ return Array.from({ length: column_size }, () => equalWidth);
57
+ }
58
+ let widths = maxLengths.map((len) => Math.round(len / totalLength * totalWidth));
59
+ widths = widths.map((w) => Math.max(MIN_COLUMN_WIDTH, Math.min(MAX_COLUMN_WIDTH, w)));
60
+ let remaining = totalWidth - widths.reduce((a, b) => a + b, 0);
61
+ while (remaining > 0) {
62
+ const growable = widths.map((w, i) => w < MAX_COLUMN_WIDTH ? i : -1).filter((i) => i >= 0);
63
+ if (growable.length === 0) break;
64
+ const perColumn = Math.floor(remaining / growable.length);
65
+ if (perColumn === 0) break;
66
+ for (const i of growable) {
67
+ const add = Math.min(perColumn, MAX_COLUMN_WIDTH - widths[i]);
68
+ widths[i] += add;
69
+ remaining -= add;
70
+ }
71
+ }
72
+ return widths;
73
+ }
74
+ function cleanBlocksForDescendant(blocks) {
75
+ const tableWidths = /* @__PURE__ */ new Map();
76
+ for (const block of blocks) if (block.block_type === 31 && block.block_id) tableWidths.set(block.block_id, calculateAdaptiveColumnWidths(blocks, block.block_id));
77
+ return blocks.map((block) => {
78
+ const cleanBlock = omitParentId(block);
79
+ if (cleanBlock.block_type === 32 && typeof cleanBlock.children === "string") cleanBlock.children = [cleanBlock.children];
80
+ if (cleanBlock.block_type === 31 && cleanBlock.table) {
81
+ const adaptive = block.block_id ? tableWidths.get(block.block_id) : void 0;
82
+ cleanBlock.table = createDescendantTable(cleanBlock.table, adaptive);
83
+ }
84
+ return cleanBlock;
85
+ });
86
+ }
87
+ async function insertTableRow(client, docToken, blockId, rowIndex = -1) {
88
+ const res = await client.docx.documentBlock.patch({
89
+ path: {
90
+ document_id: docToken,
91
+ block_id: blockId
92
+ },
93
+ data: { insert_table_row: { row_index: rowIndex } }
94
+ });
95
+ if (res.code !== 0) throw new Error(res.msg);
96
+ return {
97
+ success: true,
98
+ block: res.data?.block
99
+ };
100
+ }
101
+ async function insertTableColumn(client, docToken, blockId, columnIndex = -1) {
102
+ const res = await client.docx.documentBlock.patch({
103
+ path: {
104
+ document_id: docToken,
105
+ block_id: blockId
106
+ },
107
+ data: { insert_table_column: { column_index: columnIndex } }
108
+ });
109
+ if (res.code !== 0) throw new Error(res.msg);
110
+ return {
111
+ success: true,
112
+ block: res.data?.block
113
+ };
114
+ }
115
+ async function deleteTableRows(client, docToken, blockId, rowStart, rowCount = 1) {
116
+ const res = await client.docx.documentBlock.patch({
117
+ path: {
118
+ document_id: docToken,
119
+ block_id: blockId
120
+ },
121
+ data: { delete_table_rows: {
122
+ row_start_index: rowStart,
123
+ row_end_index: rowStart + rowCount
124
+ } }
125
+ });
126
+ if (res.code !== 0) throw new Error(res.msg);
127
+ return {
128
+ success: true,
129
+ rows_deleted: rowCount,
130
+ block: res.data?.block
131
+ };
132
+ }
133
+ async function deleteTableColumns(client, docToken, blockId, columnStart, columnCount = 1) {
134
+ const res = await client.docx.documentBlock.patch({
135
+ path: {
136
+ document_id: docToken,
137
+ block_id: blockId
138
+ },
139
+ data: { delete_table_columns: {
140
+ column_start_index: columnStart,
141
+ column_end_index: columnStart + columnCount
142
+ } }
143
+ });
144
+ if (res.code !== 0) throw new Error(res.msg);
145
+ return {
146
+ success: true,
147
+ columns_deleted: columnCount,
148
+ block: res.data?.block
149
+ };
150
+ }
151
+ async function mergeTableCells(client, docToken, blockId, rowStart, rowEnd, columnStart, columnEnd) {
152
+ const res = await client.docx.documentBlock.patch({
153
+ path: {
154
+ document_id: docToken,
155
+ block_id: blockId
156
+ },
157
+ data: { merge_table_cells: {
158
+ row_start_index: rowStart,
159
+ row_end_index: rowEnd,
160
+ column_start_index: columnStart,
161
+ column_end_index: columnEnd
162
+ } }
163
+ });
164
+ if (res.code !== 0) throw new Error(res.msg);
165
+ return {
166
+ success: true,
167
+ block: res.data?.block
168
+ };
169
+ }
170
+ //#endregion
171
+ export { calculateAdaptiveColumnWidths, cleanBlocksForDescendant, deleteTableColumns, deleteTableRows, insertTableColumn, insertTableRow, mergeTableCells };
172
+
173
+ //# sourceMappingURL=docx-table-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docx-table-ops.js","names":[],"sources":["../../../../../../extensions/feishu/src/tools/docx/docx-table-ops.ts"],"sourcesContent":["import type * as Lark from '@larksuiteoapi/node-sdk';\n\nimport type { FeishuBlockTable, FeishuDocxBlock } from './docx-types.js';\n\nconst MIN_COLUMN_WIDTH = 50;\nconst MAX_COLUMN_WIDTH = 400;\nconst DEFAULT_TABLE_WIDTH = 730;\n\nfunction normalizeChildBlockIds(children: string[] | string | undefined): string[] {\n if (Array.isArray(children)) return children;\n return typeof children === 'string' ? [children] : [];\n}\n\nfunction omitParentId(block: FeishuDocxBlock): FeishuDocxBlock {\n const cleanBlock = { ...block };\n delete cleanBlock.parent_id;\n return cleanBlock;\n}\n\nfunction createDescendantTable(table: FeishuBlockTable, adaptiveWidths: number[] | undefined): FeishuBlockTable {\n const { row_size, column_size } = table.property || {};\n return {\n property: {\n row_size,\n column_size,\n ...(adaptiveWidths?.length ? { column_width: adaptiveWidths } : {}),\n },\n };\n}\n\nexport function calculateAdaptiveColumnWidths(blocks: FeishuDocxBlock[], tableBlockId: string): number[] {\n const tableBlock = blocks.find((b) => b.block_id === tableBlockId && b.block_type === 31);\n if (!tableBlock?.table?.property) return [];\n\n const { row_size, column_size, column_width: originalWidths } = tableBlock.table.property;\n if (!row_size || !column_size) return [];\n\n const totalWidth =\n originalWidths && originalWidths.length > 0\n ? originalWidths.reduce((a: number, b: number) => a + b, 0)\n : DEFAULT_TABLE_WIDTH;\n\n const cellIds = normalizeChildBlockIds(tableBlock.children);\n const blockMap = new Map<string, FeishuDocxBlock>();\n for (const block of blocks) {\n if (block.block_id) blockMap.set(block.block_id, block);\n }\n\n function getCellText(cellId: string): string {\n const cell = blockMap.get(cellId);\n let text = '';\n const childIds = normalizeChildBlockIds(cell?.children as any);\n for (const childId of childIds) {\n const child = blockMap.get(childId);\n if (child?.text?.elements) {\n for (const elem of child.text.elements) {\n if (elem.text_run?.content) {\n text += elem.text_run.content;\n }\n }\n }\n }\n return text;\n }\n\n function getWeightedLength(text: string): number {\n return Array.from(text).reduce((sum, char) => sum + (char.charCodeAt(0) > 255 ? 2 : 1), 0);\n }\n\n const maxLengths = Array.from({ length: column_size }, () => 0);\n for (let row = 0; row < row_size; row++) {\n for (let col = 0; col < column_size; col++) {\n const cellIndex = row * column_size + col;\n const cellId = cellIds[cellIndex];\n if (!cellId) continue;\n const content = getCellText(cellId);\n const length = getWeightedLength(content);\n maxLengths[col] = Math.max(maxLengths[col], length);\n }\n }\n\n const totalLength = maxLengths.reduce((a, b) => a + b, 0);\n if (totalLength === 0) {\n const equalWidth = Math.max(\n MIN_COLUMN_WIDTH,\n Math.min(MAX_COLUMN_WIDTH, Math.floor(totalWidth / column_size)),\n );\n return Array.from({ length: column_size }, () => equalWidth);\n }\n\n let widths = maxLengths.map((len) => Math.round((len / totalLength) * totalWidth));\n widths = widths.map((w) => Math.max(MIN_COLUMN_WIDTH, Math.min(MAX_COLUMN_WIDTH, w)));\n\n let remaining = totalWidth - widths.reduce((a, b) => a + b, 0);\n while (remaining > 0) {\n const growable = widths.map((w, i) => (w < MAX_COLUMN_WIDTH ? i : -1)).filter((i) => i >= 0);\n if (growable.length === 0) break;\n const perColumn = Math.floor(remaining / growable.length);\n if (perColumn === 0) break;\n for (const i of growable) {\n const add = Math.min(perColumn, MAX_COLUMN_WIDTH - widths[i]!);\n widths[i]! += add;\n remaining -= add;\n }\n }\n\n return widths;\n}\n\nexport function cleanBlocksForDescendant(blocks: FeishuDocxBlock[]): FeishuDocxBlock[] {\n const tableWidths = new Map<string, number[]>();\n for (const block of blocks) {\n if (block.block_type === 31 && block.block_id) {\n tableWidths.set(block.block_id, calculateAdaptiveColumnWidths(blocks, block.block_id));\n }\n }\n\n return blocks.map((block) => {\n const cleanBlock = omitParentId(block);\n if (cleanBlock.block_type === 32 && typeof cleanBlock.children === 'string') {\n cleanBlock.children = [cleanBlock.children];\n }\n if (cleanBlock.block_type === 31 && cleanBlock.table) {\n const adaptive = block.block_id ? tableWidths.get(block.block_id) : undefined;\n cleanBlock.table = createDescendantTable(cleanBlock.table, adaptive);\n }\n return cleanBlock;\n });\n}\n\nexport async function insertTableRow(client: Lark.Client, docToken: string, blockId: string, rowIndex: number = -1) {\n const res = await client.docx.documentBlock.patch({\n path: { document_id: docToken, block_id: blockId },\n data: { insert_table_row: { row_index: rowIndex } },\n });\n if (res.code !== 0) throw new Error(res.msg);\n return { success: true, block: res.data?.block };\n}\n\nexport async function insertTableColumn(\n client: Lark.Client,\n docToken: string,\n blockId: string,\n columnIndex: number = -1,\n) {\n const res = await client.docx.documentBlock.patch({\n path: { document_id: docToken, block_id: blockId },\n data: { insert_table_column: { column_index: columnIndex } },\n });\n if (res.code !== 0) throw new Error(res.msg);\n return { success: true, block: res.data?.block };\n}\n\nexport async function deleteTableRows(\n client: Lark.Client,\n docToken: string,\n blockId: string,\n rowStart: number,\n rowCount: number = 1,\n) {\n const res = await client.docx.documentBlock.patch({\n path: { document_id: docToken, block_id: blockId },\n data: { delete_table_rows: { row_start_index: rowStart, row_end_index: rowStart + rowCount } },\n });\n if (res.code !== 0) throw new Error(res.msg);\n return { success: true, rows_deleted: rowCount, block: res.data?.block };\n}\n\nexport async function deleteTableColumns(\n client: Lark.Client,\n docToken: string,\n blockId: string,\n columnStart: number,\n columnCount: number = 1,\n) {\n const res = await client.docx.documentBlock.patch({\n path: { document_id: docToken, block_id: blockId },\n data: { delete_table_columns: { column_start_index: columnStart, column_end_index: columnStart + columnCount } },\n });\n if (res.code !== 0) throw new Error(res.msg);\n return { success: true, columns_deleted: columnCount, block: res.data?.block };\n}\n\nexport async function mergeTableCells(\n client: Lark.Client,\n docToken: string,\n blockId: string,\n rowStart: number,\n rowEnd: number,\n columnStart: number,\n columnEnd: number,\n) {\n const res = await client.docx.documentBlock.patch({\n path: { document_id: docToken, block_id: blockId },\n data: {\n merge_table_cells: {\n row_start_index: rowStart,\n row_end_index: rowEnd,\n column_start_index: columnStart,\n column_end_index: columnEnd,\n },\n },\n });\n if (res.code !== 0) throw new Error(res.msg);\n return { success: true, block: res.data?.block };\n}\n\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Config } from '@xopcai/xopc/config/schema.js';
2
+ export declare function feishuWhoAmI(params: {
3
+ cfg: Config;
4
+ accountId?: string;
5
+ }): Promise<any>;
@@ -0,0 +1,46 @@
1
+ import { resolveFeishuAccount } from "../state/accounts.js";
2
+ import { createFeishuClient } from "../transport/client/client.js";
3
+ //#region extensions/feishu/src/tools/tools.ts
4
+ async function feishuWhoAmI(params) {
5
+ const account = resolveFeishuAccount(params.cfg, params.accountId ?? "default");
6
+ if (!account.configured) throw new Error("Feishu account not configured");
7
+ const { api } = createFeishuClient(account);
8
+ const res = await api.auth.tenantAccessToken.internal({ data: {
9
+ app_id: account.appId,
10
+ app_secret: account.appSecret
11
+ } });
12
+ const token = res?.tenant_access_token || res?.data?.tenant_access_token || "";
13
+ const probes = {};
14
+ const tryProbe = async (name, fn) => {
15
+ try {
16
+ await fn();
17
+ probes[name] = { ok: true };
18
+ } catch (err) {
19
+ probes[name] = {
20
+ ok: false,
21
+ error: err instanceof Error ? err.message : String(err)
22
+ };
23
+ }
24
+ };
25
+ await tryProbe("im.message.read", async () => {
26
+ await api.im.v1.chat.list({ params: { page_size: 1 } });
27
+ });
28
+ await tryProbe("drive.files.list", async () => {
29
+ await api.drive.v1.file.list({ params: { page_size: 1 } });
30
+ });
31
+ await tryProbe("wiki.spaces.list", async () => {
32
+ await api.wiki.v2.space.list({ params: { page_size: 1 } });
33
+ });
34
+ await tryProbe("bitable.apps.list", async () => {
35
+ await api.bitable.v1.app.list({ params: { page_size: 1 } });
36
+ });
37
+ return {
38
+ ok: true,
39
+ tenantAccessToken: Boolean(token),
40
+ probes
41
+ };
42
+ }
43
+ //#endregion
44
+ export { feishuWhoAmI };
45
+
46
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","names":[],"sources":["../../../../../extensions/feishu/src/tools/tools.ts"],"sourcesContent":["import type { Config } from '@xopcai/xopc/config/schema.js';\n\nimport { resolveFeishuAccount } from '../state/accounts.js';\nimport { createFeishuClient } from '../transport/client/client.js';\n\nexport async function feishuWhoAmI(params: { cfg: Config; accountId?: string }): Promise<any> {\n const account = resolveFeishuAccount(params.cfg, params.accountId ?? 'default');\n if (!account.configured) {\n throw new Error('Feishu account not configured');\n }\n const { api } = createFeishuClient(account);\n const res = await (api as any).auth.tenantAccessToken.internal({\n data: {\n app_id: account.appId,\n app_secret: account.appSecret,\n },\n });\n const token = res?.tenant_access_token || res?.data?.tenant_access_token || '';\n\n // Probe a few representative APIs to surface which permission buckets are working.\n // Keep it cheap: one lightweight call per area, each isolated so partial failures still return signal.\n const probes: Record<string, { ok: boolean; error?: string }> = {};\n\n const tryProbe = async (name: string, fn: () => Promise<void>) => {\n try {\n await fn();\n probes[name] = { ok: true };\n } catch (err) {\n probes[name] = { ok: false, error: err instanceof Error ? err.message : String(err) };\n }\n };\n\n await tryProbe('im.message.read', async () => {\n // A harmless endpoint that validates the token; will still fail if permissions missing.\n await (api as any).im.v1.chat.list({ params: { page_size: 1 } });\n });\n\n await tryProbe('drive.files.list', async () => {\n await (api as any).drive.v1.file.list({ params: { page_size: 1 } });\n });\n\n await tryProbe('wiki.spaces.list', async () => {\n await (api as any).wiki.v2.space.list({ params: { page_size: 1 } });\n });\n\n await tryProbe('bitable.apps.list', async () => {\n await (api as any).bitable.v1.app.list({ params: { page_size: 1 } });\n });\n\n return {\n ok: true,\n tenantAccessToken: Boolean(token),\n probes,\n };\n}\n\n"],"mappings":";;;AAKA,eAAsB,aAAa,QAA2D;CAC5F,MAAM,UAAU,qBAAqB,OAAO,KAAK,OAAO,aAAa,UAAU;AAC/E,KAAI,CAAC,QAAQ,WACX,OAAM,IAAI,MAAM,gCAAgC;CAElD,MAAM,EAAE,QAAQ,mBAAmB,QAAQ;CAC3C,MAAM,MAAM,MAAO,IAAY,KAAK,kBAAkB,SAAS,EAC7D,MAAM;EACJ,QAAQ,QAAQ;EAChB,YAAY,QAAQ;EACrB,EACF,CAAC;CACF,MAAM,QAAQ,KAAK,uBAAuB,KAAK,MAAM,uBAAuB;CAI5E,MAAM,SAA0D,EAAE;CAElE,MAAM,WAAW,OAAO,MAAc,OAA4B;AAChE,MAAI;AACF,SAAM,IAAI;AACV,UAAO,QAAQ,EAAE,IAAI,MAAM;WACpB,KAAK;AACZ,UAAO,QAAQ;IAAE,IAAI;IAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IAAE;;;AAIzF,OAAM,SAAS,mBAAmB,YAAY;AAE5C,QAAO,IAAY,GAAG,GAAG,KAAK,KAAK,EAAE,QAAQ,EAAE,WAAW,GAAG,EAAE,CAAC;GAChE;AAEF,OAAM,SAAS,oBAAoB,YAAY;AAC7C,QAAO,IAAY,MAAM,GAAG,KAAK,KAAK,EAAE,QAAQ,EAAE,WAAW,GAAG,EAAE,CAAC;GACnE;AAEF,OAAM,SAAS,oBAAoB,YAAY;AAC7C,QAAO,IAAY,KAAK,GAAG,MAAM,KAAK,EAAE,QAAQ,EAAE,WAAW,GAAG,EAAE,CAAC;GACnE;AAEF,OAAM,SAAS,qBAAqB,YAAY;AAC9C,QAAO,IAAY,QAAQ,GAAG,IAAI,KAAK,EAAE,QAAQ,EAAE,WAAW,GAAG,EAAE,CAAC;GACpE;AAEF,QAAO;EACL,IAAI;EACJ,mBAAmB,QAAQ,MAAM;EACjC;EACD"}
@@ -0,0 +1,6 @@
1
+ import type { ResolvedFeishuAccount } from '../../state/accounts.js';
2
+ export declare function createFeishuClient(account: ResolvedFeishuAccount): {
3
+ wsClient: any;
4
+ dispatcher: any;
5
+ api: any;
6
+ };
@@ -0,0 +1,41 @@
1
+ import { createFeishuLarkSdkPinoLogger } from "./lark-sdk-logger.js";
2
+ import lark from "@larksuiteoapi/node-sdk";
3
+ //#region extensions/feishu/src/transport/client/client.ts
4
+ function createFeishuClient(account) {
5
+ const l = lark;
6
+ const sdkLogger = createFeishuLarkSdkPinoLogger(account.accountId);
7
+ const apiBaseUrl = resolveFeishuBaseUrl(account.domain);
8
+ const api = new l.Client({
9
+ appId: account.appId,
10
+ appSecret: account.appSecret,
11
+ logger: sdkLogger,
12
+ loggerLevel: l.LoggerLevel.info,
13
+ ...apiBaseUrl ? { baseURL: apiBaseUrl } : {}
14
+ });
15
+ const dispatcher = new l.EventDispatcher({
16
+ verifyChallenge: false,
17
+ logger: sdkLogger,
18
+ loggerLevel: l.LoggerLevel.info
19
+ });
20
+ return {
21
+ wsClient: new l.WSClient({
22
+ appId: account.appId,
23
+ appSecret: account.appSecret,
24
+ eventDispatcher: dispatcher,
25
+ logger: sdkLogger,
26
+ loggerLevel: l.LoggerLevel.info,
27
+ ...apiBaseUrl ? { baseURL: apiBaseUrl } : {}
28
+ }),
29
+ dispatcher,
30
+ api
31
+ };
32
+ }
33
+ function resolveFeishuBaseUrl(domain) {
34
+ if (domain === "feishu") return "https://open.feishu.cn";
35
+ if (domain === "lark") return "https://open.larksuite.com";
36
+ if (domain && domain.startsWith("https://")) return domain;
37
+ }
38
+ //#endregion
39
+ export { createFeishuClient };
40
+
41
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":[],"sources":["../../../../../../extensions/feishu/src/transport/client/client.ts"],"sourcesContent":["import lark from '@larksuiteoapi/node-sdk';\n\nimport type { ResolvedFeishuAccount } from '../../state/accounts.js';\nimport { createFeishuLarkSdkPinoLogger } from './lark-sdk-logger.js';\n\nexport function createFeishuClient(account: ResolvedFeishuAccount): {\n wsClient: any;\n dispatcher: any;\n api: any;\n} {\n const l = lark as any;\n const sdkLogger = createFeishuLarkSdkPinoLogger(account.accountId);\n\n const apiBaseUrl = resolveFeishuBaseUrl(account.domain);\n\n const api = new l.Client({\n appId: account.appId,\n appSecret: account.appSecret,\n logger: sdkLogger,\n loggerLevel: l.LoggerLevel.info,\n ...(apiBaseUrl ? { baseURL: apiBaseUrl } : {}),\n });\n\n const dispatcher = new l.EventDispatcher({ verifyChallenge: false, logger: sdkLogger, loggerLevel: l.LoggerLevel.info } as any);\n const wsClient = new l.WSClient({\n appId: account.appId,\n appSecret: account.appSecret,\n eventDispatcher: dispatcher,\n logger: sdkLogger,\n loggerLevel: l.LoggerLevel.info,\n ...(apiBaseUrl ? { baseURL: apiBaseUrl } : {}),\n });\n\n return { wsClient, dispatcher, api };\n}\n\nfunction resolveFeishuBaseUrl(domain: string): string | undefined {\n if (domain === 'feishu') {\n return 'https://open.feishu.cn';\n }\n if (domain === 'lark') {\n return 'https://open.larksuite.com';\n }\n if (domain && domain.startsWith('https://')) {\n return domain;\n }\n return undefined;\n}\n\n"],"mappings":";;;AAKA,SAAgB,mBAAmB,SAIjC;CACA,MAAM,IAAI;CACV,MAAM,YAAY,8BAA8B,QAAQ,UAAU;CAElE,MAAM,aAAa,qBAAqB,QAAQ,OAAO;CAEvD,MAAM,MAAM,IAAI,EAAE,OAAO;EACvB,OAAO,QAAQ;EACf,WAAW,QAAQ;EACnB,QAAQ;EACR,aAAa,EAAE,YAAY;EAC3B,GAAI,aAAa,EAAE,SAAS,YAAY,GAAG,EAAE;EAC9C,CAAC;CAEF,MAAM,aAAa,IAAI,EAAE,gBAAgB;EAAE,iBAAiB;EAAO,QAAQ;EAAW,aAAa,EAAE,YAAY;EAAM,CAAQ;AAU/H,QAAO;EAAE,UAAA,IATY,EAAE,SAAS;GAC9B,OAAO,QAAQ;GACf,WAAW,QAAQ;GACnB,iBAAiB;GACjB,QAAQ;GACR,aAAa,EAAE,YAAY;GAC3B,GAAI,aAAa,EAAE,SAAS,YAAY,GAAG,EAAE;GAC9C,CAEgB;EAAE;EAAY;EAAK;;AAGtC,SAAS,qBAAqB,QAAoC;AAChE,KAAI,WAAW,SACb,QAAO;AAET,KAAI,WAAW,OACb,QAAO;AAET,KAAI,UAAU,OAAO,WAAW,WAAW,CACzC,QAAO"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Adapts `@larksuiteoapi/node-sdk`'s `Logger` interface to xopc's pino-based logger.
3
+ *
4
+ * The SDK wraps calls like `this.logger.info('a', 'b')` into `LoggerProxy.info` which forwards a *single* array
5
+ * argument to the underlying logger — which is why the default output looks like: `[info]: [ 'a', 'b' ]`.
6
+ */
7
+ export declare function createFeishuLarkSdkPinoLogger(accountId: string): {
8
+ error: (...msg: any[]) => void;
9
+ warn: (...msg: any[]) => void;
10
+ info: (...msg: any[]) => void;
11
+ debug: (...msg: any[]) => void;
12
+ trace: (...msg: any[]) => void;
13
+ };
@@ -0,0 +1,104 @@
1
+ import { createLogger } from "../../../../../src/utils/logger/index.js";
2
+ import { init_logger } from "../../../../../src/utils/logger.js";
3
+ //#region extensions/feishu/src/transport/client/lark-sdk-logger.ts
4
+ init_logger();
5
+ function normalizeLarkLogArgs(args) {
6
+ const raw = args.length === 1 ? args[0] : args;
7
+ if (Array.isArray(raw)) {
8
+ const errIdx = raw.findIndex((x) => x instanceof Error);
9
+ if (errIdx >= 0) {
10
+ const err = raw[errIdx];
11
+ return {
12
+ parts: raw.filter((_, i) => i !== errIdx),
13
+ err
14
+ };
15
+ }
16
+ return { parts: raw };
17
+ }
18
+ return { parts: [raw] };
19
+ }
20
+ function stringifyParts(parts) {
21
+ const text = parts.map((p) => {
22
+ if (typeof p === "string") return p;
23
+ if (p instanceof Error) return p.message;
24
+ if (p === null || p === void 0) return "";
25
+ try {
26
+ return JSON.stringify(p);
27
+ } catch {
28
+ return String(p);
29
+ }
30
+ }).join(" ").replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
31
+ return {
32
+ text,
33
+ hasLongLines: text.includes("\n") || text.length > 240
34
+ };
35
+ }
36
+ function linePreview(text, max = 240) {
37
+ const oneLine = text.replace(/\s+/g, " ").trim();
38
+ if (oneLine.length <= max) return oneLine;
39
+ return oneLine.slice(0, max - 1) + "…";
40
+ }
41
+ /**
42
+ * Adapts `@larksuiteoapi/node-sdk`'s `Logger` interface to xopc's pino-based logger.
43
+ *
44
+ * The SDK wraps calls like `this.logger.info('a', 'b')` into `LoggerProxy.info` which forwards a *single* array
45
+ * argument to the underlying logger — which is why the default output looks like: `[info]: [ 'a', 'b' ]`.
46
+ */
47
+ function createFeishuLarkSdkPinoLogger(accountId) {
48
+ const log = createLogger("FeishuLarkSDK");
49
+ const write = (level, args) => {
50
+ const { parts, err } = normalizeLarkLogArgs(args);
51
+ const { text, hasLongLines } = stringifyParts(parts);
52
+ if (!text && !err) return;
53
+ if (err) {
54
+ log[level]({
55
+ err,
56
+ accountId,
57
+ linePreview: text ? linePreview(text) : void 0,
58
+ component: "lark-sdk"
59
+ }, text || err.message);
60
+ return;
61
+ }
62
+ if (level === "info" && (text === "client ready" || /^\[ws\]\s*ws client ready$/.test(text))) {
63
+ log.info({
64
+ accountId,
65
+ component: "lark-sdk",
66
+ lark: "api+ws"
67
+ }, "Lark SDK is ready (HTTP client + websocket)");
68
+ return;
69
+ }
70
+ if (level === "info" && text === "event-dispatch is ready") {
71
+ log.info({
72
+ accountId,
73
+ component: "lark-sdk",
74
+ lark: "event-dispatch"
75
+ }, "Lark event dispatcher is ready");
76
+ return;
77
+ }
78
+ if (level === "info" && hasLongLines) {
79
+ log.info({
80
+ accountId,
81
+ component: "lark-sdk",
82
+ lark: "event-subscription",
83
+ linePreview: linePreview(text)
84
+ }, "Lark subscription guidance: enable persistent connection mode in Developer Console (self-build + Feishu app)");
85
+ return;
86
+ }
87
+ log[level]({
88
+ accountId,
89
+ component: "lark-sdk",
90
+ linePreview: linePreview(text)
91
+ }, text);
92
+ };
93
+ return {
94
+ error: (...args) => write("error", args),
95
+ warn: (...args) => write("warn", args),
96
+ info: (...args) => write("info", args),
97
+ debug: (...args) => write("debug", args),
98
+ trace: (...args) => write("trace", args)
99
+ };
100
+ }
101
+ //#endregion
102
+ export { createFeishuLarkSdkPinoLogger };
103
+
104
+ //# sourceMappingURL=lark-sdk-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lark-sdk-logger.js","names":[],"sources":["../../../../../../extensions/feishu/src/transport/client/lark-sdk-logger.ts"],"sourcesContent":["import { createLogger } from '@xopcai/xopc/utils/logger.js';\nimport type { Logger } from 'pino';\n\nfunction normalizeLarkLogArgs(args: any[]): { parts: any[]; err?: Error } {\n const raw: any = args.length === 1 ? args[0] : args;\n if (Array.isArray(raw)) {\n const errIdx = raw.findIndex((x) => x instanceof Error);\n if (errIdx >= 0) {\n const err = raw[errIdx] as Error;\n const parts = raw.filter((_, i) => i !== errIdx);\n return { parts, err };\n }\n return { parts: raw };\n }\n return { parts: [raw] };\n}\n\nfunction stringifyParts(parts: any[]): { text: string; hasLongLines: boolean } {\n const mapped = parts.map((p) => {\n if (typeof p === 'string') return p;\n if (p instanceof Error) return p.message;\n if (p === null || p === undefined) return '';\n try {\n return JSON.stringify(p);\n } catch {\n return String(p);\n }\n });\n const text = mapped.join(' ').replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n').trim();\n const hasLongLines = text.includes('\\n') || text.length > 240;\n return { text, hasLongLines };\n}\n\nfunction linePreview(text: string, max = 240): string {\n const oneLine = text.replace(/\\s+/g, ' ').trim();\n if (oneLine.length <= max) return oneLine;\n return oneLine.slice(0, max - 1) + '…';\n}\n\n/**\n * Adapts `@larksuiteoapi/node-sdk`'s `Logger` interface to xopc's pino-based logger.\n *\n * The SDK wraps calls like `this.logger.info('a', 'b')` into `LoggerProxy.info` which forwards a *single* array\n * argument to the underlying logger — which is why the default output looks like: `[info]: [ 'a', 'b' ]`.\n */\nexport function createFeishuLarkSdkPinoLogger(accountId: string): {\n error: (...msg: any[]) => void;\n warn: (...msg: any[]) => void;\n info: (...msg: any[]) => void;\n debug: (...msg: any[]) => void;\n trace: (...msg: any[]) => void;\n} {\n const log: Logger = createLogger('FeishuLarkSDK') as unknown as Logger;\n\n const write = (level: 'error' | 'warn' | 'info' | 'debug' | 'trace', args: any[]) => {\n const { parts, err } = normalizeLarkLogArgs(args);\n const { text, hasLongLines } = stringifyParts(parts);\n if (!text && !err) return;\n\n if (err) {\n (log as any)[level](\n { err, accountId, linePreview: text ? linePreview(text) : undefined, component: 'lark-sdk' },\n text || err.message,\n );\n return;\n }\n\n if (level === 'info' && (text === 'client ready' || /^\\[ws\\]\\s*ws client ready$/.test(text))) {\n // `Client` logs \"client ready\" and WSClient logs \"[ws] ws client ready\" — both mean the client stack is up.\n log.info({ accountId, component: 'lark-sdk', lark: 'api+ws' }, 'Lark SDK is ready (HTTP client + websocket)');\n return;\n }\n if (level === 'info' && text === 'event-dispatch is ready') {\n log.info({ accountId, component: 'lark-sdk', lark: 'event-dispatch' }, 'Lark event dispatcher is ready');\n return;\n }\n if (level === 'info' && hasLongLines) {\n log.info(\n { accountId, component: 'lark-sdk', lark: 'event-subscription', linePreview: linePreview(text) },\n 'Lark subscription guidance: enable persistent connection mode in Developer Console (self-build + Feishu app)',\n );\n return;\n }\n\n (log as any)[level]({ accountId, component: 'lark-sdk', linePreview: linePreview(text) }, text);\n };\n\n return {\n error: (...args) => write('error', args),\n warn: (...args) => write('warn', args),\n info: (...args) => write('info', args),\n debug: (...args) => write('debug', args),\n trace: (...args) => write('trace', args),\n };\n}\n"],"mappings":";;;aAA4D;AAG5D,SAAS,qBAAqB,MAA4C;CACxE,MAAM,MAAW,KAAK,WAAW,IAAI,KAAK,KAAK;AAC/C,KAAI,MAAM,QAAQ,IAAI,EAAE;EACtB,MAAM,SAAS,IAAI,WAAW,MAAM,aAAa,MAAM;AACvD,MAAI,UAAU,GAAG;GACf,MAAM,MAAM,IAAI;AAEhB,UAAO;IAAE,OADK,IAAI,QAAQ,GAAG,MAAM,MAAM,OAC3B;IAAE;IAAK;;AAEvB,SAAO,EAAE,OAAO,KAAK;;AAEvB,QAAO,EAAE,OAAO,CAAC,IAAI,EAAE;;AAGzB,SAAS,eAAe,OAAuD;CAW7E,MAAM,OAVS,MAAM,KAAK,MAAM;AAC9B,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,MAAI,aAAa,MAAO,QAAO,EAAE;AACjC,MAAI,MAAM,QAAQ,MAAM,KAAA,EAAW,QAAO;AAC1C,MAAI;AACF,UAAO,KAAK,UAAU,EAAE;UAClB;AACN,UAAO,OAAO,EAAE;;GAGD,CAAC,KAAK,IAAI,CAAC,QAAQ,SAAS,KAAK,CAAC,QAAQ,OAAO,KAAK,CAAC,MAAM;AAEhF,QAAO;EAAE;EAAM,cADM,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS;EAC7B;;AAG/B,SAAS,YAAY,MAAc,MAAM,KAAa;CACpD,MAAM,UAAU,KAAK,QAAQ,QAAQ,IAAI,CAAC,MAAM;AAChD,KAAI,QAAQ,UAAU,IAAK,QAAO;AAClC,QAAO,QAAQ,MAAM,GAAG,MAAM,EAAE,GAAG;;;;;;;;AASrC,SAAgB,8BAA8B,WAM5C;CACA,MAAM,MAAc,aAAa,gBAAgB;CAEjD,MAAM,SAAS,OAAsD,SAAgB;EACnF,MAAM,EAAE,OAAO,QAAQ,qBAAqB,KAAK;EACjD,MAAM,EAAE,MAAM,iBAAiB,eAAe,MAAM;AACpD,MAAI,CAAC,QAAQ,CAAC,IAAK;AAEnB,MAAI,KAAK;AACN,OAAY,OACX;IAAE;IAAK;IAAW,aAAa,OAAO,YAAY,KAAK,GAAG,KAAA;IAAW,WAAW;IAAY,EAC5F,QAAQ,IAAI,QACb;AACD;;AAGF,MAAI,UAAU,WAAW,SAAS,kBAAkB,6BAA6B,KAAK,KAAK,GAAG;AAE5F,OAAI,KAAK;IAAE;IAAW,WAAW;IAAY,MAAM;IAAU,EAAE,8CAA8C;AAC7G;;AAEF,MAAI,UAAU,UAAU,SAAS,2BAA2B;AAC1D,OAAI,KAAK;IAAE;IAAW,WAAW;IAAY,MAAM;IAAkB,EAAE,iCAAiC;AACxG;;AAEF,MAAI,UAAU,UAAU,cAAc;AACpC,OAAI,KACF;IAAE;IAAW,WAAW;IAAY,MAAM;IAAsB,aAAa,YAAY,KAAK;IAAE,EAChG,+GACD;AACD;;AAGD,MAAY,OAAO;GAAE;GAAW,WAAW;GAAY,aAAa,YAAY,KAAK;GAAE,EAAE,KAAK;;AAGjG,QAAO;EACL,QAAQ,GAAG,SAAS,MAAM,SAAS,KAAK;EACxC,OAAO,GAAG,SAAS,MAAM,QAAQ,KAAK;EACtC,OAAO,GAAG,SAAS,MAAM,QAAQ,KAAK;EACtC,QAAQ,GAAG,SAAS,MAAM,SAAS,KAAK;EACxC,QAAQ,GAAG,SAAS,MAAM,SAAS,KAAK;EACzC"}
@@ -0,0 +1,7 @@
1
+ export interface FeishuDedupe {
2
+ claim(id: string): boolean;
3
+ }
4
+ export declare function createFeishuDedupe(options?: {
5
+ max?: number;
6
+ ttlMs?: number;
7
+ }): FeishuDedupe;
@@ -0,0 +1,30 @@
1
+ //#region extensions/feishu/src/transport/reliability/dedupe.ts
2
+ function createFeishuDedupe(options) {
3
+ const max = options?.max ?? 1e4;
4
+ const ttlMs = options?.ttlMs ?? 10 * 6e4;
5
+ const seen = /* @__PURE__ */ new Map();
6
+ function prune(now) {
7
+ for (const [k, t] of seen) if (now - t > ttlMs) seen.delete(k);
8
+ if (seen.size <= max) return;
9
+ const extra = seen.size - max;
10
+ let i = 0;
11
+ for (const k of seen.keys()) {
12
+ seen.delete(k);
13
+ i++;
14
+ if (i >= extra) break;
15
+ }
16
+ }
17
+ return { claim(id) {
18
+ const key = id.trim();
19
+ if (!key) return false;
20
+ const now = Date.now();
21
+ prune(now);
22
+ if (seen.has(key)) return false;
23
+ seen.set(key, now);
24
+ return true;
25
+ } };
26
+ }
27
+ //#endregion
28
+ export { createFeishuDedupe };
29
+
30
+ //# sourceMappingURL=dedupe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedupe.js","names":[],"sources":["../../../../../../extensions/feishu/src/transport/reliability/dedupe.ts"],"sourcesContent":["export interface FeishuDedupe {\n claim(id: string): boolean;\n}\n\nexport function createFeishuDedupe(options?: { max?: number; ttlMs?: number }): FeishuDedupe {\n const max = options?.max ?? 10_000;\n const ttlMs = options?.ttlMs ?? 10 * 60_000;\n const seen = new Map<string, number>();\n\n function prune(now: number) {\n for (const [k, t] of seen) {\n if (now - t > ttlMs) {\n seen.delete(k);\n }\n }\n if (seen.size <= max) return;\n const extra = seen.size - max;\n let i = 0;\n for (const k of seen.keys()) {\n seen.delete(k);\n i++;\n if (i >= extra) break;\n }\n }\n\n return {\n claim(id: string): boolean {\n const key = id.trim();\n if (!key) return false;\n const now = Date.now();\n prune(now);\n if (seen.has(key)) return false;\n seen.set(key, now);\n return true;\n },\n };\n}\n\n"],"mappings":";AAIA,SAAgB,mBAAmB,SAA0D;CAC3F,MAAM,MAAM,SAAS,OAAO;CAC5B,MAAM,QAAQ,SAAS,SAAS,KAAK;CACrC,MAAM,uBAAO,IAAI,KAAqB;CAEtC,SAAS,MAAM,KAAa;AAC1B,OAAK,MAAM,CAAC,GAAG,MAAM,KACnB,KAAI,MAAM,IAAI,MACZ,MAAK,OAAO,EAAE;AAGlB,MAAI,KAAK,QAAQ,IAAK;EACtB,MAAM,QAAQ,KAAK,OAAO;EAC1B,IAAI,IAAI;AACR,OAAK,MAAM,KAAK,KAAK,MAAM,EAAE;AAC3B,QAAK,OAAO,EAAE;AACd;AACA,OAAI,KAAK,MAAO;;;AAIpB,QAAO,EACL,MAAM,IAAqB;EACzB,MAAM,MAAM,GAAG,MAAM;AACrB,MAAI,CAAC,IAAK,QAAO;EACjB,MAAM,MAAM,KAAK,KAAK;AACtB,QAAM,IAAI;AACV,MAAI,KAAK,IAAI,IAAI,CAAE,QAAO;AAC1B,OAAK,IAAI,KAAK,IAAI;AAClB,SAAO;IAEV"}
@@ -0,0 +1,19 @@
1
+ import type { MessageBus } from '@xopcai/xopc/infra/bus/index.js';
2
+ import type { Config } from '@xopcai/xopc/config/schema.js';
3
+ import type { ChannelSecurityContext } from '@xopcai/xopc/channels/plugin-types.js';
4
+ import type { ResolvedFeishuAccount } from '../../state/accounts.js';
5
+ export interface FeishuSocketModeMonitorDeps {
6
+ account: ResolvedFeishuAccount;
7
+ config: Config;
8
+ bus: MessageBus;
9
+ abortSignal: AbortSignal;
10
+ security: {
11
+ checkAccess: (ctx: ChannelSecurityContext) => {
12
+ allowed: boolean;
13
+ reason?: string;
14
+ } | undefined;
15
+ };
16
+ }
17
+ export declare function createFeishuSocketModeMonitor(deps: FeishuSocketModeMonitorDeps): {
18
+ run: () => Promise<void>;
19
+ };