@yanhaidao/wecom 2.3.13 → 2.3.14

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.
@@ -0,0 +1,408 @@
1
+
2
+ export interface DocMemberEntry {
3
+ userid?: string;
4
+ partyid?: string;
5
+ tagid?: string;
6
+ /**
7
+ * 权限位:1-查看,2-编辑,7-管理
8
+ */
9
+ auth?: number;
10
+ type?: number; // 1:用户, 2:部门
11
+ tmp_external_userid?: string;
12
+ }
13
+
14
+ export interface Node {
15
+ begin: number;
16
+ end: number;
17
+ property: Property;
18
+ type: NodeType;
19
+ children: Node[];
20
+ text?: string;
21
+ }
22
+
23
+ export enum NodeType {
24
+ Document = "Document",
25
+ MainStory = "MainStory",
26
+ Section = "Section",
27
+ Paragraph = "Paragraph",
28
+ Table = "Table",
29
+ TableRow = "TableRow",
30
+ TableCell = "TableCell",
31
+ Text = "Text",
32
+ Drawing = "Drawing"
33
+ }
34
+
35
+ export interface Property {
36
+ section_property?: SectionProperty;
37
+ paragraph_property?: ParagraphProperty;
38
+ run_property?: RunProperty;
39
+ table_property?: TableProperty;
40
+ table_row_property?: TableRowProperty;
41
+ table_cell_property?: TableCellProperty;
42
+ drawing_property?: DrawingProperty;
43
+ }
44
+
45
+ export interface SectionProperty {
46
+ page_size?: PageSize;
47
+ page_margins?: PageMargins;
48
+ }
49
+
50
+ export interface PageSize {
51
+ width: number;
52
+ height: number;
53
+ orientation?: PageOrientation;
54
+ }
55
+
56
+ export interface PageOrientation {
57
+ orientation: "PAGE_ORIENTATION_PORTRAIT" | "PAGE_ORIENTATION_LANDSCAPE" | "PAGE_ORIENTATION_UNSPECIFIED";
58
+ }
59
+
60
+ export interface PageMargins {
61
+ top: number;
62
+ right: number;
63
+ bottom: number;
64
+ left: number;
65
+ }
66
+
67
+ export interface ParagraphProperty {
68
+ number_property?: NumberProperty;
69
+ spacing?: Spacing;
70
+ indent?: Indent;
71
+ alignment_type?: AlignmentType;
72
+ text_direction?: TextDirection;
73
+ }
74
+
75
+ export interface NumberProperty {
76
+ nesting_level: number;
77
+ number_id: string;
78
+ }
79
+
80
+ export interface Spacing {
81
+ before?: number;
82
+ after?: number;
83
+ line?: number;
84
+ line_rule?: LineSpacingRule;
85
+ }
86
+
87
+ export enum LineSpacingRule {
88
+ AUTO = "LINE_SPACING_RULE_AUTO",
89
+ EXACT = "LINE_SPACING_RULE_EXACT",
90
+ AT_LEAST = "LINE_SPACING_RULE_AT_LEAST",
91
+ UNSPECIFIED = "PAGE_ORIENTATION_UNSPECIFIED" // Note: User text had a copy-paste error here, listing PAGE_ORIENTATION_UNSPECIFIED
92
+ }
93
+
94
+ export interface Indent {
95
+ left?: number;
96
+ left_chars?: number;
97
+ right?: number;
98
+ right_chars?: number;
99
+ hanging?: number;
100
+ hanging_chars?: number;
101
+ first_line?: number;
102
+ first_line_chars?: number;
103
+ }
104
+
105
+ export enum AlignmentType {
106
+ UNSPECIFIED = "ALIGNMENT_TYPE_UNSPECIFIED",
107
+ CENTER = "ALIGNMENT_TYPE_CENTER",
108
+ BOTH = "ALIGNMENT_TYPE_BOTH", // Justified
109
+ DISTRIBUTE = "ALIGNMENT_TYPE_DISTRIBUTE",
110
+ LEFT = "ALIGNMENT_TYPE_LEFT",
111
+ RIGHT = "ALIGNMENT_TYPE_RIGHT"
112
+ }
113
+
114
+ export enum TextDirection {
115
+ UNSPECIFIED = "TEXT_DIRECTION_UNSPECIFIED",
116
+ RTL = "TEXT_DIRECTION_RIGHT_TO_LEFT",
117
+ LTR = "TEXT_DIRECTION_LEFT_TO_RIGHT"
118
+ }
119
+
120
+ export interface RunProperty {
121
+ font?: string;
122
+ bold?: boolean;
123
+ italics?: boolean;
124
+ underline?: boolean;
125
+ strike?: boolean;
126
+ color?: string; // RRGGBB
127
+ spacing?: number;
128
+ size?: number; // half-points
129
+ shading?: Shading;
130
+ vertical_align?: TextVerticalAlign;
131
+ is_placeholder?: boolean;
132
+ }
133
+
134
+ export interface Shading {
135
+ foreground_color: string; // RRGGBB
136
+ background_color: string; // RRGGBB
137
+ }
138
+
139
+ export enum TextVerticalAlign {
140
+ UNSPECIFIED = "RUN_VERTICAL_ALIGN_UNSPECIFIED",
141
+ BASELINE = "RUN_VERTICAL_ALIGN_BASELINE",
142
+ SUPER_SCRIPT = "RUN_VERTICAL_ALIGN_SUPER_SCRIPT",
143
+ SUB_SCRIPT = "RUN_VERTICAL_ALIGN_SUB_SCRIPT"
144
+ }
145
+
146
+ export interface TableProperty {
147
+ table_width?: TableWidth;
148
+ horizontal_alignment_type?: TableHorizontalAlignmentType;
149
+ table_layout?: TableLayoutType;
150
+ }
151
+
152
+ export interface TableWidth {
153
+ width: number;
154
+ type: TableWidthType;
155
+ }
156
+
157
+ export enum TableHorizontalAlignmentType {
158
+ UNSPECIFIED = "TABLE_HORIZONTAL_ALIGNMENT_TYPE_UNSPECIFIED",
159
+ CENTER = "TABLE_HORIZONTAL_ALIGNMENT_TYPE_CENTER",
160
+ LEFT = "TABLE_HORIZONTAL_ALIGNMENT_TYPE_LEFT",
161
+ START = "TABLE_HORIZONTAL_ALIGNMENT_TYPE_START"
162
+ }
163
+
164
+ export enum TableLayoutType {
165
+ UNSPECIFIED = "TABLE_LAYOUT_TYPE_UNSPECIFIED",
166
+ FIXED = "TABLE_LAYOUT_TYPE_FIXED",
167
+ AUTO_FIT = "TABLE_LAYOUT_TYPE_AUTO_FIT"
168
+ }
169
+
170
+ export enum TableWidthType {
171
+ UNSPECIFIED = "TABLE_LAYOUT_TYPE_UNSPECIFIED",
172
+ FIXED = "TABLE_LAYOUT_TYPE_FIXED",
173
+ AUTO_FIT = "TABLE_LAYOUT_TYPE_AUTO_FIT"
174
+ }
175
+
176
+ export interface TableRowProperty {
177
+ is_header?: boolean;
178
+ }
179
+
180
+ export interface TableCellProperty {
181
+ table_cell_borders?: Borders;
182
+ vertical_alignment?: VerticalAlignment;
183
+ }
184
+
185
+ export interface Borders {
186
+ top?: BorderProperty;
187
+ left?: BorderProperty;
188
+ bottom?: BorderProperty;
189
+ right?: BorderProperty;
190
+ }
191
+
192
+ export interface BorderProperty {
193
+ color: string; // RRGGBB
194
+ width: number;
195
+ }
196
+
197
+ export enum VerticalAlignment {
198
+ UNSPECIFIED = "VERTICAL_ALIGNMENT__UNSPECIFIED",
199
+ TOP = "VERTICAL_ALIGNMENT_TOP",
200
+ CENTER = "VERTICAL_ALIGNMENT_CENTER",
201
+ BOTH = "VERTICAL_ALIGNMENT_BOTH",
202
+ BOTTOM = "VERTICAL_ALIGNMENT_BOTTOM"
203
+ }
204
+
205
+ export interface DrawingProperty {
206
+ inline_keyword?: Inline;
207
+ anchor?: Anchor;
208
+ is_placeholder?: boolean;
209
+ }
210
+
211
+ export interface Inline {
212
+ picture?: InlinePicture;
213
+ addon?: InlineAddon;
214
+ }
215
+
216
+ export interface InlinePicture {
217
+ uri: string;
218
+ relative_rect?: RelativeRect;
219
+ shape?: ShapeProperties;
220
+ }
221
+
222
+ export interface RelativeRect {
223
+ left: number;
224
+ top: number;
225
+ right: number;
226
+ bottom: number;
227
+ }
228
+
229
+ export interface ShapeProperties {
230
+ transform?: Transform2D;
231
+ }
232
+
233
+ export interface Transform2D {
234
+ extent?: PositiveSize2D;
235
+ rotation?: number;
236
+ }
237
+
238
+ export interface PositiveSize2D {
239
+ cx: number;
240
+ cy: number;
241
+ }
242
+
243
+ export interface InlineAddon {
244
+ addon_id: string;
245
+ addon_source: AddonSourceType;
246
+ }
247
+
248
+ export enum AddonSourceType {
249
+ UNSPECIFIED = "ADDON_SOURCE_TYPE_UNSPECIFIED",
250
+ NONE = "ADDON_SOURCE_TYPE_NONE",
251
+ LATEX = "ADDON_SOURCE_TYPE_LATEX",
252
+ SIGN = "ADDON_SOURCE_TYPE_SIGN",
253
+ SIGN_BAR = "ADDON_SOURCE_TYPE_SIGN_BAR"
254
+ }
255
+
256
+ export interface Anchor {
257
+ picture?: AnchorPicture;
258
+ }
259
+
260
+ export interface AnchorPicture {
261
+ uri: string;
262
+ relative_rect?: RelativeRect;
263
+ shape?: ShapeProperties;
264
+ position_horizontal?: PositionHorizontal;
265
+ position_vertical?: PositionVertical;
266
+ wrap_none?: boolean;
267
+ wrap_square?: WrapSquare;
268
+ wrap_top_and_bottom?: boolean;
269
+ behind_doc?: boolean;
270
+ allow_overlap?: boolean;
271
+ }
272
+
273
+ export interface PositionHorizontal {
274
+ pos_offset: number;
275
+ relative_from: RelativeFromHorizontal;
276
+ }
277
+
278
+ export enum RelativeFromHorizontal {
279
+ UNSPECIFIED = "RELATIVE_FROM_HORIZONTAL_UNSPECIFIED",
280
+ MARGIN = "RELATIVE_FROM_HORIZONTAL_MARGIN",
281
+ PAGE = "RELATIVE_FROM_HORIZONTAL_PAGE",
282
+ COLUMN = "RELATIVE_FROM_HORIZONTAL_COLUMN",
283
+ CHARACTER = "RELATIVE_FROM_HORIZONTAL_CHARACTER",
284
+ LEFT_MARGIN = "RELATIVE_FROM_HORIZONTAL_LEFT_MARGIN",
285
+ RIGHT_MARGIN = "RELATIVE_FROM_HORIZONTAL_RIGHT_MARGIN",
286
+ INSIDE_MARGIN = "RELATIVE_FROM_HORIZONTAL_INSIDE_MARGIN",
287
+ OUTSIDE_MARGIN = "RELATIVE_FROM_HORIZONTAL_OUTSIDE_MARGIN"
288
+ }
289
+
290
+ export interface PositionVertical {
291
+ pos_offset: number;
292
+ relative_from: RelativeFromVertical;
293
+ }
294
+
295
+ export enum RelativeFromVertical {
296
+ UNSPECIFIED = "RELATIVE_FROM_VERTICAL_UNSPECIFIED",
297
+ MARGIN = "RELATIVE_FROM_VERTICAL_MARGIN",
298
+ PAGE = "RELATIVE_FROM_VERTICAL_PAGE",
299
+ PARAGRAPH = "RELATIVE_FROM_VERTICAL_PARAGRAPH",
300
+ LINE = "RELATIVE_FROM_VERTICAL_LINE",
301
+ TOP_MARGIN = "RELATIVE_FROM_VERTICAL_TOP_MARGIN",
302
+ BOTTOM_MARGIN = "RELATIVE_FROM_VERTICAL_BOTTOM_MARGIN",
303
+ INSIDE_MARGIN = "RELATIVE_FROM_VERTICAL_INSIDE_MARGIN",
304
+ OUTSIDE_MARGIN = "RELATIVE_FROM_VERTICAL_OUTSIDE_MARGIN"
305
+ }
306
+
307
+ export interface WrapSquare {
308
+ wrap_text: WrapText;
309
+ }
310
+
311
+ export enum WrapText {
312
+ UNSPECIFIED = "WRAP_TEXT_BOTH_UNSPECIFIED",
313
+ BOTH_SIDES = "WRAP_TEXT_BOTH_SIDES",
314
+ LEFT = "WRAP_TEXT_LEFT",
315
+ RIGHT = "WRAP_TEXT_RIGHT",
316
+ LARGEST = "WRAP_TEXT_LARGEST"
317
+ }
318
+
319
+
320
+ // --- Update Requests ---
321
+
322
+ export interface Location {
323
+ index: number;
324
+ }
325
+
326
+ export interface Range {
327
+ start_index: number;
328
+ length: number;
329
+ }
330
+
331
+ export interface ReplaceTextRequest {
332
+ text: string;
333
+ ranges: Range[];
334
+ }
335
+
336
+ export interface InsertTextRequest {
337
+ text: string;
338
+ location: Location;
339
+ }
340
+
341
+ export interface DeleteContentRequest {
342
+ range: Range;
343
+ }
344
+
345
+ export interface InsertImageRequest {
346
+ image_id: string;
347
+ location: Location;
348
+ width?: number;
349
+ height?: number;
350
+ }
351
+
352
+ export interface InsertPageBreakRequest {
353
+ location: Location;
354
+ }
355
+
356
+ export interface InsertTableRequest {
357
+ rows: number;
358
+ cols: number;
359
+ location: Location;
360
+ }
361
+
362
+ export interface InsertParagraphRequest {
363
+ location: Location;
364
+ }
365
+
366
+ export interface TextProperty {
367
+ bold?: boolean;
368
+ italics?: boolean; // User text says "italics", Schema says "italic". User text for RunProperty says "italics", UpdateTextProperty example says "bold" but doesn't list italics explicitly in example, but RunProperty does. Standard WeCom API is "italics"? My schema says "italic". I will use "italics" as per user provided text for RunProperty, but UpdateTextProperty might differ.
369
+ // User text for TextProperty example: bold, color, background_color.
370
+ // RunProperty has "italics".
371
+ // I will check the user provided TextProperty definition again.
372
+ // "blod" (typo in user text), color, background_color.
373
+ // It doesn't list italics in TextProperty section, but RunProperty does.
374
+ // I will support what is likely correct.
375
+ underline?: boolean;
376
+ strikethrough?: boolean;
377
+ color?: string;
378
+ background_color?: string;
379
+ font_size?: number;
380
+ }
381
+
382
+ export interface UpdateTextPropertyRequest {
383
+ text_property: TextProperty;
384
+ ranges: Range[];
385
+ }
386
+
387
+ export interface UpdateRequest {
388
+ replace_text?: ReplaceTextRequest;
389
+ insert_text?: InsertTextRequest;
390
+ delete_content?: DeleteContentRequest;
391
+ insert_image?: InsertImageRequest;
392
+ insert_page_break?: InsertPageBreakRequest;
393
+ insert_table?: InsertTableRequest;
394
+ insert_paragraph?: InsertParagraphRequest;
395
+ update_text_property?: UpdateTextPropertyRequest;
396
+ }
397
+
398
+ export interface BatchUpdateDocResponse {
399
+ errcode: number;
400
+ errmsg: string;
401
+ }
402
+
403
+ export interface GetDocContentResponse {
404
+ errcode: number;
405
+ errmsg: string;
406
+ version: number;
407
+ document: Node;
408
+ }
package/src/channel.ts CHANGED
@@ -65,7 +65,7 @@ export const wecomPlugin: ChannelPlugin<ResolvedWecomAccount> = {
65
65
  threads: false,
66
66
  polls: false,
67
67
  nativeCommands: false,
68
- blockStreaming: true,
68
+ blockStreaming: false,
69
69
  },
70
70
  reload: { configPrefixes: ["channels.wecom"] },
71
71
  // NOTE: We intentionally avoid Zod -> JSON Schema conversion at plugin-load time.
package/src/outbound.ts CHANGED
@@ -49,7 +49,7 @@ function resolveAgentConfigOrThrow(params: {
49
49
  );
50
50
  }
51
51
  // 注意:不要在日志里输出 corpSecret 等敏感信息
52
- console.log(`[wecom-outbound] Using agent config: accountId=${account.accountId}, corpId=${account.corpId}, agentId=${account.agentId}`);
52
+ getAccountRuntime(account.accountId)?.log.info?.(`[wecom-outbound] Using agent config: accountId=${account.accountId}, corpId=${account.corpId}, agentId=${account.agentId}`);
53
53
  return account;
54
54
  }
55
55
 
@@ -158,7 +158,7 @@ export const wecomOutbound: ChannelOutboundAdapter = {
158
158
 
159
159
  if (looksLikeNewSessionAck) {
160
160
  if (!isAgentSessionTarget) {
161
- console.log(`[wecom-outbound] Suppressed command ack to avoid Bot/Agent double-reply (len=${trimmed.length})`);
161
+ getAccountRuntime(agent.accountId)?.log.info?.(`[wecom-outbound] Suppressed command ack to avoid Bot/Agent double-reply (len=${trimmed.length})`);
162
162
  return { channel: "wecom", messageId: `suppressed-${Date.now()}`, timestamp: Date.now() };
163
163
  }
164
164
 
@@ -167,11 +167,11 @@ export const wecomOutbound: ChannelOutboundAdapter = {
167
167
  return m?.[1]?.trim();
168
168
  })();
169
169
  const rewritten = modelLabel ? `✅ 已开启新会话(模型:${modelLabel})` : "✅ 已开启新会话。";
170
- console.log(`[wecom-outbound] Rewrote command ack for agent session (len=${rewritten.length})`);
170
+ getAccountRuntime(agent.accountId)?.log.info?.(`[wecom-outbound] Rewrote command ack for agent session (len=${rewritten.length})`);
171
171
  outgoingText = rewritten;
172
172
  }
173
173
 
174
- console.log(`[wecom-outbound] Sending text to target=${String(to ?? "")} (len=${outgoingText.length})`);
174
+ getAccountRuntime(agent.accountId)?.log.info?.(`[wecom-outbound] Sending text to target=${String(to ?? "")} (len=${outgoingText.length})`);
175
175
 
176
176
  let sentViaBotWs = false;
177
177
  try {
@@ -191,7 +191,7 @@ export const wecomOutbound: ChannelOutboundAdapter = {
191
191
  console.log(`[wecom-outbound] Successfully sent Agent text to ${String(to ?? "")}`);
192
192
  }
193
193
  } catch (err) {
194
- console.error(`[wecom-outbound] Failed to send text to ${String(to ?? "")}:`, err);
194
+ getAccountRuntime(agent.accountId)?.log.error?.(`[wecom-outbound] Failed to send text to ${String(to ?? "")}: ${err instanceof Error ? err.message : String(err)}`);
195
195
  throw err;
196
196
  }
197
197
 
@@ -46,8 +46,8 @@ export async function prepareInboundSession(params: {
46
46
  From:
47
47
  event.conversation.peerKind === "group"
48
48
  ? `wecom:group:${event.conversation.peerId}`
49
- : `wecom:${event.conversation.senderId}`,
50
- To: `wecom:${event.conversation.peerId}`,
49
+ : `wecom:user:${event.conversation.senderId}`,
50
+ To: event.conversation.peerKind === "group" ? `wecom:group:${event.conversation.peerId}` : `wecom:user:${event.conversation.peerId}`,
51
51
  SessionKey: route.sessionKey,
52
52
  AccountId: route.accountId,
53
53
  ChatType: event.conversation.peerKind,
@@ -57,7 +57,7 @@ export async function prepareInboundSession(params: {
57
57
  Provider: "wecom",
58
58
  Surface: "wecom",
59
59
  OriginatingChannel: "wecom",
60
- OriginatingTo: `wecom:${event.conversation.peerId}`,
60
+ OriginatingTo: event.conversation.peerKind === "group" ? `wecom:group:${event.conversation.peerId}` : `wecom:user:${event.conversation.peerId}`,
61
61
  MessageSid: event.messageId,
62
62
  CommandAuthorized: true,
63
63
  MediaPath: mediaPath,
@@ -69,7 +69,7 @@ export async function prepareInboundSession(params: {
69
69
  storePath,
70
70
  sessionKey: ctx.SessionKey ?? route.sessionKey,
71
71
  ctx,
72
- onRecordError: () => {},
72
+ onRecordError: () => { },
73
73
  });
74
74
 
75
75
  return { route, ctx, storePath };
package/src/target.ts CHANGED
@@ -85,6 +85,9 @@ export function resolveWecomTarget(raw: string | undefined, options?: { preferUs
85
85
  }
86
86
 
87
87
  // Default to User (默认为用户)
88
+ // 注意:纯数字通常可能是 UserID (内部成员 ID),也可能是 PartyID。
89
+ // 为了兼容性,如果没有前缀且不匹配群聊规则,我们将其视为 UserID。
90
+ // 如果需要明确发送给部门,请使用 "party:1" 前缀。
88
91
  return { touser: clean };
89
92
  }
90
93
 
@@ -15,7 +15,10 @@ export async function useActiveReplyOnce(
15
15
  streamId: string,
16
16
  fn: (params: { responseUrl: string; proxyUrl?: string }) => Promise<void>,
17
17
  ): Promise<void> {
18
- return activeReplyStore.use(streamId, fn);
18
+ return activeReplyStore.use(streamId, async (params) => {
19
+ await new Promise((resolve) => setTimeout(resolve, 1000));
20
+ await fn(params);
21
+ });
19
22
  }
20
23
 
21
24
  export async function sendActiveMessage(streamId: string, content: string): Promise<void> {
@@ -90,9 +90,9 @@ export function mapBotWsFrameToInboundEvent(params: {
90
90
  },
91
91
  },
92
92
  attachments: body.msgtype === "image"
93
- ? [{ name: "image", remoteUrl: body.image?.url, aesKey: body.image?.aeskey }]
93
+ ? [{ name: "image", remoteUrl: (body as any).image?.url, aesKey: (body as any).image?.aeskey }]
94
94
  : body.msgtype === "file"
95
- ? [{ name: "file", remoteUrl: body.file?.url, aesKey: body.file?.aeskey }]
95
+ ? [{ name: "file", remoteUrl: (body as any).file?.url, aesKey: (body as any).file?.aeskey }]
96
96
  : undefined,
97
97
  };
98
98
  }