@larksuite/openclaw-lark 2026.7.9 → 2026.7.16-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/channel/event-handlers.js +136 -3
- package/src/channel/interactive-dispatch.js +7 -1
- package/src/core/config-schema.d.ts +471 -4
- package/src/messaging/inbound/gate.d.ts +7 -0
- package/src/messaging/inbound/gate.js +2 -2
- package/src/messaging/inbound/handler-registry.d.ts +4 -0
- package/src/messaging/inbound/handler.d.ts +6 -0
- package/src/messaging/inbound/handler.js +15 -4
- package/src/messaging/inbound/synthetic-message.d.ts +5 -0
- package/src/messaging/inbound/synthetic-message.js +2 -1
- package/src/tools/ask-user-question.js +10 -2
- package/tsdown.config.d.ts +1 -1
- package/vitest.config.d.ts +1 -1
package/package.json
CHANGED
|
@@ -9,6 +9,39 @@
|
|
|
9
9
|
* function size. Each handler receives a MonitorContext with all
|
|
10
10
|
* dependencies needed to process the event.
|
|
11
11
|
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
12
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
46
|
exports.handleMessageEvent = handleMessageEvent;
|
|
14
47
|
exports.handleReactionEvent = handleReactionEvent;
|
|
@@ -16,6 +49,7 @@ exports.handleBotMembershipEvent = handleBotMembershipEvent;
|
|
|
16
49
|
exports.handleVcMeetingInvitedEvent = handleVcMeetingInvitedEvent;
|
|
17
50
|
exports.handleCommentEvent = handleCommentEvent;
|
|
18
51
|
exports.handleCardActionEvent = handleCardActionEvent;
|
|
52
|
+
const crypto = __importStar(require("node:crypto"));
|
|
19
53
|
const handler_1 = require("../messaging/inbound/handler.js");
|
|
20
54
|
const reaction_handler_1 = require("../messaging/inbound/reaction-handler.js");
|
|
21
55
|
const comment_handler_1 = require("../messaging/inbound/comment-handler.js");
|
|
@@ -27,6 +61,9 @@ const lark_ticket_1 = require("../core/lark-ticket.js");
|
|
|
27
61
|
const lark_logger_1 = require("../core/lark-logger.js");
|
|
28
62
|
const auto_auth_1 = require("../tools/auto-auth.js");
|
|
29
63
|
const ask_user_question_1 = require("../tools/ask-user-question.js");
|
|
64
|
+
const synthetic_message_1 = require("../messaging/inbound/synthetic-message.js");
|
|
65
|
+
const chat_info_cache_1 = require("../core/chat-info-cache.js");
|
|
66
|
+
const message_lookup_1 = require("../messaging/shared/message-lookup.js");
|
|
30
67
|
const chat_queue_1 = require("./chat-queue.js");
|
|
31
68
|
const abort_detect_1 = require("./abort-detect.js");
|
|
32
69
|
const interactive_dispatch_1 = require("./interactive-dispatch.js");
|
|
@@ -358,11 +395,107 @@ async function handleCommentEvent(ctx, data) {
|
|
|
358
395
|
error(`feishu[${accountId}]: error handling comment event: ${String(err)}`);
|
|
359
396
|
}
|
|
360
397
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
398
|
+
/**
|
|
399
|
+
* Generic "button click = inject a user message" mechanism.
|
|
400
|
+
*
|
|
401
|
+
* When a card button's `value` is `{ action: "inject_prompt", prompt: "<text>" }`,
|
|
402
|
+
* clicking it dispatches `<text>` as a synthetic user message (via the standard
|
|
403
|
+
* inbound pipeline, `replyToMessageId` set to the card's own message so the agent
|
|
404
|
+
* replies in the same conversation) and returns a toast receipt. This lets any
|
|
405
|
+
* card offer functional buttons — click a button, the corresponding request runs,
|
|
406
|
+
* no typing needed — without registering a business plugin handler.
|
|
407
|
+
*
|
|
408
|
+
* Returns the toast receipt when the event is an inject_prompt action, or
|
|
409
|
+
* `undefined` so the caller falls through to the other card handlers.
|
|
410
|
+
*
|
|
411
|
+
* Security / correctness (mirrors reaction-handler, which faces the same
|
|
412
|
+
* "card-ish event carries no chat_type/thread_id" problem):
|
|
413
|
+
* - Chat type is resolved from the cached chat-info helper and the dispatch
|
|
414
|
+
* fails closed if it can't be determined, so a group card is never
|
|
415
|
+
* mis-routed as a p2p direct session.
|
|
416
|
+
* - The synthetic message goes through the real access-control gate
|
|
417
|
+
* (`cardActionGate`): the click satisfies the mention requirement, but
|
|
418
|
+
* group/DM admission and sender allowlists are still enforced.
|
|
419
|
+
* - The synthetic message id is unique per click (event_id / token / uuid), so
|
|
420
|
+
* inbound MessageSid dedup does not silently drop a second button click.
|
|
421
|
+
* - Only a real `operator.open_id` is used as the sender identity; a Schema-2
|
|
422
|
+
* `user_id` is never smuggled into an `open_id` field (fail closed instead).
|
|
423
|
+
*
|
|
424
|
+
* Note: `card.action.trigger` is a synchronous request/response — the handler
|
|
425
|
+
* MUST return a card receipt (here a toast). Returning `undefined` makes the SDK
|
|
426
|
+
* fall back to a card update it cannot resolve, which Feishu rejects with
|
|
427
|
+
* `99992354 Invalid ids:[card]`. So we dispatch the synthetic message
|
|
428
|
+
* asynchronously (`setImmediate`) and return the toast synchronously.
|
|
429
|
+
*/
|
|
430
|
+
function handleInjectPromptAction(ctx, data) {
|
|
431
|
+
const ev = data;
|
|
432
|
+
const val = ev.action?.value;
|
|
433
|
+
if (!val || val.action !== 'inject_prompt' || typeof val.prompt !== 'string' || !val.prompt.trim()) {
|
|
434
|
+
return undefined;
|
|
435
|
+
}
|
|
436
|
+
// Use only a real open_id as the sender identity. A Schema-2 callback may carry
|
|
437
|
+
// only operator.user_id; that is a different namespace and must not be written
|
|
438
|
+
// into an open_id field (would corrupt session routing, sender allowlists,
|
|
439
|
+
// user-token lookup, and owner checks). Fail closed until user_id→open_id
|
|
440
|
+
// conversion is supported.
|
|
441
|
+
const senderOpenId = ev.operator?.open_id?.trim();
|
|
442
|
+
const chatId = ev.open_chat_id ?? ev.context?.open_chat_id;
|
|
443
|
+
const cardMsgId = ev.open_message_id ?? ev.context?.open_message_id;
|
|
444
|
+
if (!senderOpenId || !chatId) {
|
|
445
|
+
elog.warn('inject_prompt: missing operator open_id or chatId, ignoring');
|
|
446
|
+
return { toast: { type: 'error', content: '无法处理该操作' } };
|
|
447
|
+
}
|
|
448
|
+
const prompt = val.prompt;
|
|
449
|
+
// Unique per click so inbound dedup (by MessageSid, ~20min) does not drop a
|
|
450
|
+
// second click on a different button of the same card. Prefer the callback's
|
|
451
|
+
// unique event_id; fall back to token, then a random uuid.
|
|
452
|
+
const syntheticMessageId = ev.event_id?.trim() || ev.token?.trim() || crypto.randomUUID();
|
|
453
|
+
// Dispatch asynchronously so the synchronous toast receipt is not blocked.
|
|
454
|
+
// The card trigger carries no chat_type or thread_id, so resolve both here.
|
|
455
|
+
setImmediate(async () => {
|
|
456
|
+
try {
|
|
457
|
+
// Resolve the real chat type; fail closed if it can't be determined
|
|
458
|
+
// (do NOT assume p2p — that would mis-route a group card).
|
|
459
|
+
const info = await (0, chat_info_cache_1.getChatInfo)({ cfg: ctx.cfg, chatId, accountId: ctx.accountId });
|
|
460
|
+
if (!info) {
|
|
461
|
+
elog.warn(`inject_prompt: could not resolve chat type for ${chatId}, skipping dispatch`);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
const chatType = info.chatMode === 'group' || info.chatMode === 'topic' ? 'group' : 'p2p';
|
|
465
|
+
// Recover the thread id from the card's own message (the trigger has none)
|
|
466
|
+
// so thread session isolation is preserved.
|
|
467
|
+
let threadId;
|
|
468
|
+
if (cardMsgId) {
|
|
469
|
+
const msg = await (0, message_lookup_1.getMessageFeishu)({ cfg: ctx.cfg, messageId: cardMsgId, accountId: ctx.accountId }).catch(() => null);
|
|
470
|
+
threadId = msg?.threadId;
|
|
471
|
+
}
|
|
472
|
+
await (0, synthetic_message_1.dispatchSyntheticTextMessage)({
|
|
473
|
+
cfg: ctx.cfg,
|
|
474
|
+
accountId: ctx.accountId,
|
|
475
|
+
chatId,
|
|
476
|
+
senderOpenId,
|
|
477
|
+
text: prompt,
|
|
478
|
+
syntheticMessageId,
|
|
479
|
+
replyToMessageId: cardMsgId ?? '',
|
|
480
|
+
chatType,
|
|
481
|
+
threadId,
|
|
482
|
+
forceMention: false,
|
|
483
|
+
cardActionGate: true,
|
|
484
|
+
runtime: ctx.runtime,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
catch (e) {
|
|
488
|
+
elog.warn(`inject_prompt dispatch failed: ${e}`);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
return { toast: { type: 'info', content: '收到,正在为你处理…' } };
|
|
492
|
+
}
|
|
364
493
|
async function handleCardActionEvent(ctx, data) {
|
|
365
494
|
try {
|
|
495
|
+
// inject_prompt:通用「按钮点击 = 注入一条用户消息」机制(渠道内建,优先拦截)。
|
|
496
|
+
const injectResult = handleInjectPromptAction(ctx, data);
|
|
497
|
+
if (injectResult !== undefined)
|
|
498
|
+
return injectResult;
|
|
366
499
|
// AskUserQuestion:表单卡片交互(宿主内建能力优先)
|
|
367
500
|
const askResult = (0, ask_user_question_1.handleAskUserAction)(data, ctx.cfg, ctx.accountId);
|
|
368
501
|
if (askResult !== undefined)
|
|
@@ -23,7 +23,7 @@ const log = (0, lark_logger_1.larkLogger)('channel/interactive-dispatch');
|
|
|
23
23
|
function extractBasics(data) {
|
|
24
24
|
try {
|
|
25
25
|
const ev = data;
|
|
26
|
-
const action = ev.action?.value?.action ?? ev.action?.name;
|
|
26
|
+
const action = ev.action?.value?.action ?? ev.action?.name ?? formSubmitActionName(ev);
|
|
27
27
|
if (!action || typeof action !== 'string')
|
|
28
28
|
return null;
|
|
29
29
|
const openChatId = ev.open_chat_id ?? ev.context?.open_chat_id;
|
|
@@ -39,6 +39,12 @@ function extractBasics(data) {
|
|
|
39
39
|
return null;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
function formSubmitActionName(ev) {
|
|
43
|
+
const tag = ev.action?.tag;
|
|
44
|
+
if (tag !== 'form_submit')
|
|
45
|
+
return undefined;
|
|
46
|
+
return ev.action?.form_name;
|
|
47
|
+
}
|
|
42
48
|
function buildMarkdownCard(text) {
|
|
43
49
|
return {
|
|
44
50
|
schema: '2.0',
|
|
@@ -9,10 +9,477 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
export { z };
|
|
12
|
-
export declare const UATConfigSchema:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
export declare const UATConfigSchema: z.ZodOptional<z.ZodObject<{
|
|
13
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
14
|
+
allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
15
|
+
blockedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
16
|
+
}, z.core.$strip>>;
|
|
17
|
+
export declare const FeishuGroupSchema: z.ZodObject<{
|
|
18
|
+
groupPolicy: z.ZodOptional<z.ZodEnum<{
|
|
19
|
+
open: "open";
|
|
20
|
+
allowlist: "allowlist";
|
|
21
|
+
disabled: "disabled";
|
|
22
|
+
}>>;
|
|
23
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
24
|
+
respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
|
|
25
|
+
tools: z.ZodOptional<z.ZodObject<{
|
|
26
|
+
allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
27
|
+
deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
28
|
+
}, z.core.$strip>>;
|
|
29
|
+
skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
30
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
31
|
+
allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
32
|
+
systemPrompt: z.ZodOptional<z.ZodString>;
|
|
33
|
+
allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
|
|
34
|
+
replyInThread: z.ZodOptional<z.ZodBoolean>;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
export declare const FeishuAccountConfigSchema: z.ZodObject<{
|
|
37
|
+
appId: z.ZodOptional<z.ZodString>;
|
|
38
|
+
appSecret: z.ZodOptional<z.ZodString>;
|
|
39
|
+
encryptKey: z.ZodOptional<z.ZodString>;
|
|
40
|
+
verificationToken: z.ZodOptional<z.ZodString>;
|
|
41
|
+
name: z.ZodOptional<z.ZodString>;
|
|
42
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
43
|
+
domain: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"feishu">, z.ZodLiteral<"lark">, z.ZodString]>>;
|
|
44
|
+
connectionMode: z.ZodOptional<z.ZodEnum<{
|
|
45
|
+
websocket: "websocket";
|
|
46
|
+
webhook: "webhook";
|
|
47
|
+
}>>;
|
|
48
|
+
webhookPath: z.ZodOptional<z.ZodString>;
|
|
49
|
+
webhookPort: z.ZodOptional<z.ZodNumber>;
|
|
50
|
+
dmPolicy: z.ZodOptional<z.ZodEnum<{
|
|
51
|
+
open: "open";
|
|
52
|
+
pairing: "pairing";
|
|
53
|
+
allowlist: "allowlist";
|
|
54
|
+
disabled: "disabled";
|
|
55
|
+
}>>;
|
|
56
|
+
allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
57
|
+
groupPolicy: z.ZodOptional<z.ZodEnum<{
|
|
58
|
+
open: "open";
|
|
59
|
+
allowlist: "allowlist";
|
|
60
|
+
disabled: "disabled";
|
|
61
|
+
}>>;
|
|
62
|
+
groupAllowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
63
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
64
|
+
respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
|
|
65
|
+
groups: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
66
|
+
groupPolicy: z.ZodOptional<z.ZodEnum<{
|
|
67
|
+
open: "open";
|
|
68
|
+
allowlist: "allowlist";
|
|
69
|
+
disabled: "disabled";
|
|
70
|
+
}>>;
|
|
71
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
72
|
+
respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
|
|
73
|
+
tools: z.ZodOptional<z.ZodObject<{
|
|
74
|
+
allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
75
|
+
deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
76
|
+
}, z.core.$strip>>;
|
|
77
|
+
skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
78
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
79
|
+
allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
80
|
+
systemPrompt: z.ZodOptional<z.ZodString>;
|
|
81
|
+
allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
|
|
82
|
+
replyInThread: z.ZodOptional<z.ZodBoolean>;
|
|
83
|
+
}, z.core.$strip>>>;
|
|
84
|
+
historyLimit: z.ZodOptional<z.ZodNumber>;
|
|
85
|
+
dmHistoryLimit: z.ZodOptional<z.ZodNumber>;
|
|
86
|
+
dms: z.ZodOptional<z.ZodObject<{
|
|
87
|
+
historyLimit: z.ZodOptional<z.ZodNumber>;
|
|
88
|
+
}, z.core.$strip>>;
|
|
89
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
chunkMode: z.ZodOptional<z.ZodEnum<{
|
|
91
|
+
newline: "newline";
|
|
92
|
+
paragraph: "paragraph";
|
|
93
|
+
none: "none";
|
|
94
|
+
}>>;
|
|
95
|
+
blockStreamingCoalesce: z.ZodOptional<z.ZodObject<{
|
|
96
|
+
minChars: z.ZodOptional<z.ZodNumber>;
|
|
97
|
+
maxChars: z.ZodOptional<z.ZodNumber>;
|
|
98
|
+
idleMs: z.ZodOptional<z.ZodNumber>;
|
|
99
|
+
}, z.core.$strip>>;
|
|
100
|
+
mediaMaxMb: z.ZodOptional<z.ZodNumber>;
|
|
101
|
+
heartbeat: z.ZodOptional<z.ZodObject<{
|
|
102
|
+
every: z.ZodOptional<z.ZodString>;
|
|
103
|
+
activeHours: z.ZodOptional<z.ZodObject<{
|
|
104
|
+
start: z.ZodOptional<z.ZodString>;
|
|
105
|
+
end: z.ZodOptional<z.ZodString>;
|
|
106
|
+
timezone: z.ZodOptional<z.ZodString>;
|
|
107
|
+
}, z.core.$strip>>;
|
|
108
|
+
target: z.ZodOptional<z.ZodString>;
|
|
109
|
+
to: z.ZodOptional<z.ZodString>;
|
|
110
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
111
|
+
accountId: z.ZodOptional<z.ZodString>;
|
|
112
|
+
}, z.core.$strip>>;
|
|
113
|
+
replyMode: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
114
|
+
auto: "auto";
|
|
115
|
+
static: "static";
|
|
116
|
+
streaming: "streaming";
|
|
117
|
+
}>, z.ZodObject<{
|
|
118
|
+
default: z.ZodOptional<z.ZodEnum<{
|
|
119
|
+
auto: "auto";
|
|
120
|
+
static: "static";
|
|
121
|
+
streaming: "streaming";
|
|
122
|
+
}>>;
|
|
123
|
+
group: z.ZodOptional<z.ZodEnum<{
|
|
124
|
+
auto: "auto";
|
|
125
|
+
static: "static";
|
|
126
|
+
streaming: "streaming";
|
|
127
|
+
}>>;
|
|
128
|
+
direct: z.ZodOptional<z.ZodEnum<{
|
|
129
|
+
auto: "auto";
|
|
130
|
+
static: "static";
|
|
131
|
+
streaming: "streaming";
|
|
132
|
+
}>>;
|
|
133
|
+
}, z.core.$strip>]>>;
|
|
134
|
+
streaming: z.ZodOptional<z.ZodBoolean>;
|
|
135
|
+
blockStreaming: z.ZodOptional<z.ZodBoolean>;
|
|
136
|
+
toolUseDisplay: z.ZodOptional<z.ZodObject<{
|
|
137
|
+
showFullPaths: z.ZodOptional<z.ZodBoolean>;
|
|
138
|
+
}, z.core.$strip>>;
|
|
139
|
+
tools: z.ZodOptional<z.ZodObject<{
|
|
140
|
+
doc: z.ZodOptional<z.ZodBoolean>;
|
|
141
|
+
wiki: z.ZodOptional<z.ZodBoolean>;
|
|
142
|
+
drive: z.ZodOptional<z.ZodBoolean>;
|
|
143
|
+
perm: z.ZodOptional<z.ZodBoolean>;
|
|
144
|
+
scopes: z.ZodOptional<z.ZodBoolean>;
|
|
145
|
+
}, z.core.$strip>>;
|
|
146
|
+
footer: z.ZodOptional<z.ZodObject<{
|
|
147
|
+
status: z.ZodOptional<z.ZodBoolean>;
|
|
148
|
+
elapsed: z.ZodOptional<z.ZodBoolean>;
|
|
149
|
+
tokens: z.ZodOptional<z.ZodBoolean>;
|
|
150
|
+
cache: z.ZodOptional<z.ZodBoolean>;
|
|
151
|
+
context: z.ZodOptional<z.ZodBoolean>;
|
|
152
|
+
model: z.ZodOptional<z.ZodBoolean>;
|
|
153
|
+
}, z.core.$strip>>;
|
|
154
|
+
markdown: z.ZodOptional<z.ZodObject<{
|
|
155
|
+
tables: z.ZodOptional<z.ZodEnum<{
|
|
156
|
+
off: "off";
|
|
157
|
+
bullets: "bullets";
|
|
158
|
+
code: "code";
|
|
159
|
+
}>>;
|
|
160
|
+
}, z.core.$strip>>;
|
|
161
|
+
configWrites: z.ZodOptional<z.ZodBoolean>;
|
|
162
|
+
capabilities: z.ZodOptional<z.ZodObject<{
|
|
163
|
+
image: z.ZodOptional<z.ZodBoolean>;
|
|
164
|
+
audio: z.ZodOptional<z.ZodBoolean>;
|
|
165
|
+
video: z.ZodOptional<z.ZodBoolean>;
|
|
166
|
+
}, z.core.$strip>>;
|
|
167
|
+
dedup: z.ZodOptional<z.ZodObject<{
|
|
168
|
+
ttlMs: z.ZodOptional<z.ZodNumber>;
|
|
169
|
+
maxEntries: z.ZodOptional<z.ZodNumber>;
|
|
170
|
+
}, z.core.$strip>>;
|
|
171
|
+
reactionNotifications: z.ZodOptional<z.ZodEnum<{
|
|
172
|
+
off: "off";
|
|
173
|
+
own: "own";
|
|
174
|
+
all: "all";
|
|
175
|
+
}>>;
|
|
176
|
+
threadSession: z.ZodOptional<z.ZodBoolean>;
|
|
177
|
+
allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
|
|
178
|
+
replyInThread: z.ZodOptional<z.ZodBoolean>;
|
|
179
|
+
uat: z.ZodOptional<z.ZodObject<{
|
|
180
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
181
|
+
allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
182
|
+
blockedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
183
|
+
}, z.core.$strip>>;
|
|
184
|
+
}, z.core.$strip>;
|
|
185
|
+
export declare const FeishuConfigSchema: z.ZodObject<{
|
|
186
|
+
appId: z.ZodOptional<z.ZodString>;
|
|
187
|
+
appSecret: z.ZodOptional<z.ZodString>;
|
|
188
|
+
encryptKey: z.ZodOptional<z.ZodString>;
|
|
189
|
+
verificationToken: z.ZodOptional<z.ZodString>;
|
|
190
|
+
name: z.ZodOptional<z.ZodString>;
|
|
191
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
192
|
+
domain: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"feishu">, z.ZodLiteral<"lark">, z.ZodString]>>;
|
|
193
|
+
connectionMode: z.ZodOptional<z.ZodEnum<{
|
|
194
|
+
websocket: "websocket";
|
|
195
|
+
webhook: "webhook";
|
|
196
|
+
}>>;
|
|
197
|
+
webhookPath: z.ZodOptional<z.ZodString>;
|
|
198
|
+
webhookPort: z.ZodOptional<z.ZodNumber>;
|
|
199
|
+
dmPolicy: z.ZodOptional<z.ZodEnum<{
|
|
200
|
+
open: "open";
|
|
201
|
+
pairing: "pairing";
|
|
202
|
+
allowlist: "allowlist";
|
|
203
|
+
disabled: "disabled";
|
|
204
|
+
}>>;
|
|
205
|
+
allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
206
|
+
groupPolicy: z.ZodOptional<z.ZodEnum<{
|
|
207
|
+
open: "open";
|
|
208
|
+
allowlist: "allowlist";
|
|
209
|
+
disabled: "disabled";
|
|
210
|
+
}>>;
|
|
211
|
+
groupAllowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
212
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
213
|
+
respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
|
|
214
|
+
groups: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
215
|
+
groupPolicy: z.ZodOptional<z.ZodEnum<{
|
|
216
|
+
open: "open";
|
|
217
|
+
allowlist: "allowlist";
|
|
218
|
+
disabled: "disabled";
|
|
219
|
+
}>>;
|
|
220
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
221
|
+
respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
|
|
222
|
+
tools: z.ZodOptional<z.ZodObject<{
|
|
223
|
+
allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
224
|
+
deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
225
|
+
}, z.core.$strip>>;
|
|
226
|
+
skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
227
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
228
|
+
allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
229
|
+
systemPrompt: z.ZodOptional<z.ZodString>;
|
|
230
|
+
allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
|
|
231
|
+
replyInThread: z.ZodOptional<z.ZodBoolean>;
|
|
232
|
+
}, z.core.$strip>>>;
|
|
233
|
+
historyLimit: z.ZodOptional<z.ZodNumber>;
|
|
234
|
+
dmHistoryLimit: z.ZodOptional<z.ZodNumber>;
|
|
235
|
+
dms: z.ZodOptional<z.ZodObject<{
|
|
236
|
+
historyLimit: z.ZodOptional<z.ZodNumber>;
|
|
237
|
+
}, z.core.$strip>>;
|
|
238
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
239
|
+
chunkMode: z.ZodOptional<z.ZodEnum<{
|
|
240
|
+
newline: "newline";
|
|
241
|
+
paragraph: "paragraph";
|
|
242
|
+
none: "none";
|
|
243
|
+
}>>;
|
|
244
|
+
blockStreamingCoalesce: z.ZodOptional<z.ZodObject<{
|
|
245
|
+
minChars: z.ZodOptional<z.ZodNumber>;
|
|
246
|
+
maxChars: z.ZodOptional<z.ZodNumber>;
|
|
247
|
+
idleMs: z.ZodOptional<z.ZodNumber>;
|
|
248
|
+
}, z.core.$strip>>;
|
|
249
|
+
mediaMaxMb: z.ZodOptional<z.ZodNumber>;
|
|
250
|
+
heartbeat: z.ZodOptional<z.ZodObject<{
|
|
251
|
+
every: z.ZodOptional<z.ZodString>;
|
|
252
|
+
activeHours: z.ZodOptional<z.ZodObject<{
|
|
253
|
+
start: z.ZodOptional<z.ZodString>;
|
|
254
|
+
end: z.ZodOptional<z.ZodString>;
|
|
255
|
+
timezone: z.ZodOptional<z.ZodString>;
|
|
256
|
+
}, z.core.$strip>>;
|
|
257
|
+
target: z.ZodOptional<z.ZodString>;
|
|
258
|
+
to: z.ZodOptional<z.ZodString>;
|
|
259
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
260
|
+
accountId: z.ZodOptional<z.ZodString>;
|
|
261
|
+
}, z.core.$strip>>;
|
|
262
|
+
replyMode: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
263
|
+
auto: "auto";
|
|
264
|
+
static: "static";
|
|
265
|
+
streaming: "streaming";
|
|
266
|
+
}>, z.ZodObject<{
|
|
267
|
+
default: z.ZodOptional<z.ZodEnum<{
|
|
268
|
+
auto: "auto";
|
|
269
|
+
static: "static";
|
|
270
|
+
streaming: "streaming";
|
|
271
|
+
}>>;
|
|
272
|
+
group: z.ZodOptional<z.ZodEnum<{
|
|
273
|
+
auto: "auto";
|
|
274
|
+
static: "static";
|
|
275
|
+
streaming: "streaming";
|
|
276
|
+
}>>;
|
|
277
|
+
direct: z.ZodOptional<z.ZodEnum<{
|
|
278
|
+
auto: "auto";
|
|
279
|
+
static: "static";
|
|
280
|
+
streaming: "streaming";
|
|
281
|
+
}>>;
|
|
282
|
+
}, z.core.$strip>]>>;
|
|
283
|
+
streaming: z.ZodOptional<z.ZodBoolean>;
|
|
284
|
+
blockStreaming: z.ZodOptional<z.ZodBoolean>;
|
|
285
|
+
toolUseDisplay: z.ZodOptional<z.ZodObject<{
|
|
286
|
+
showFullPaths: z.ZodOptional<z.ZodBoolean>;
|
|
287
|
+
}, z.core.$strip>>;
|
|
288
|
+
tools: z.ZodOptional<z.ZodObject<{
|
|
289
|
+
doc: z.ZodOptional<z.ZodBoolean>;
|
|
290
|
+
wiki: z.ZodOptional<z.ZodBoolean>;
|
|
291
|
+
drive: z.ZodOptional<z.ZodBoolean>;
|
|
292
|
+
perm: z.ZodOptional<z.ZodBoolean>;
|
|
293
|
+
scopes: z.ZodOptional<z.ZodBoolean>;
|
|
294
|
+
}, z.core.$strip>>;
|
|
295
|
+
footer: z.ZodOptional<z.ZodObject<{
|
|
296
|
+
status: z.ZodOptional<z.ZodBoolean>;
|
|
297
|
+
elapsed: z.ZodOptional<z.ZodBoolean>;
|
|
298
|
+
tokens: z.ZodOptional<z.ZodBoolean>;
|
|
299
|
+
cache: z.ZodOptional<z.ZodBoolean>;
|
|
300
|
+
context: z.ZodOptional<z.ZodBoolean>;
|
|
301
|
+
model: z.ZodOptional<z.ZodBoolean>;
|
|
302
|
+
}, z.core.$strip>>;
|
|
303
|
+
markdown: z.ZodOptional<z.ZodObject<{
|
|
304
|
+
tables: z.ZodOptional<z.ZodEnum<{
|
|
305
|
+
off: "off";
|
|
306
|
+
bullets: "bullets";
|
|
307
|
+
code: "code";
|
|
308
|
+
}>>;
|
|
309
|
+
}, z.core.$strip>>;
|
|
310
|
+
configWrites: z.ZodOptional<z.ZodBoolean>;
|
|
311
|
+
capabilities: z.ZodOptional<z.ZodObject<{
|
|
312
|
+
image: z.ZodOptional<z.ZodBoolean>;
|
|
313
|
+
audio: z.ZodOptional<z.ZodBoolean>;
|
|
314
|
+
video: z.ZodOptional<z.ZodBoolean>;
|
|
315
|
+
}, z.core.$strip>>;
|
|
316
|
+
dedup: z.ZodOptional<z.ZodObject<{
|
|
317
|
+
ttlMs: z.ZodOptional<z.ZodNumber>;
|
|
318
|
+
maxEntries: z.ZodOptional<z.ZodNumber>;
|
|
319
|
+
}, z.core.$strip>>;
|
|
320
|
+
reactionNotifications: z.ZodOptional<z.ZodEnum<{
|
|
321
|
+
off: "off";
|
|
322
|
+
own: "own";
|
|
323
|
+
all: "all";
|
|
324
|
+
}>>;
|
|
325
|
+
threadSession: z.ZodOptional<z.ZodBoolean>;
|
|
326
|
+
allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
|
|
327
|
+
replyInThread: z.ZodOptional<z.ZodBoolean>;
|
|
328
|
+
uat: z.ZodOptional<z.ZodObject<{
|
|
329
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
330
|
+
allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
331
|
+
blockedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
332
|
+
}, z.core.$strip>>;
|
|
333
|
+
accounts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
334
|
+
appId: z.ZodOptional<z.ZodString>;
|
|
335
|
+
appSecret: z.ZodOptional<z.ZodString>;
|
|
336
|
+
encryptKey: z.ZodOptional<z.ZodString>;
|
|
337
|
+
verificationToken: z.ZodOptional<z.ZodString>;
|
|
338
|
+
name: z.ZodOptional<z.ZodString>;
|
|
339
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
340
|
+
domain: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"feishu">, z.ZodLiteral<"lark">, z.ZodString]>>;
|
|
341
|
+
connectionMode: z.ZodOptional<z.ZodEnum<{
|
|
342
|
+
websocket: "websocket";
|
|
343
|
+
webhook: "webhook";
|
|
344
|
+
}>>;
|
|
345
|
+
webhookPath: z.ZodOptional<z.ZodString>;
|
|
346
|
+
webhookPort: z.ZodOptional<z.ZodNumber>;
|
|
347
|
+
dmPolicy: z.ZodOptional<z.ZodEnum<{
|
|
348
|
+
open: "open";
|
|
349
|
+
pairing: "pairing";
|
|
350
|
+
allowlist: "allowlist";
|
|
351
|
+
disabled: "disabled";
|
|
352
|
+
}>>;
|
|
353
|
+
allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
354
|
+
groupPolicy: z.ZodOptional<z.ZodEnum<{
|
|
355
|
+
open: "open";
|
|
356
|
+
allowlist: "allowlist";
|
|
357
|
+
disabled: "disabled";
|
|
358
|
+
}>>;
|
|
359
|
+
groupAllowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
360
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
361
|
+
respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
|
|
362
|
+
groups: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
363
|
+
groupPolicy: z.ZodOptional<z.ZodEnum<{
|
|
364
|
+
open: "open";
|
|
365
|
+
allowlist: "allowlist";
|
|
366
|
+
disabled: "disabled";
|
|
367
|
+
}>>;
|
|
368
|
+
requireMention: z.ZodOptional<z.ZodBoolean>;
|
|
369
|
+
respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
|
|
370
|
+
tools: z.ZodOptional<z.ZodObject<{
|
|
371
|
+
allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
372
|
+
deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
373
|
+
}, z.core.$strip>>;
|
|
374
|
+
skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
375
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
376
|
+
allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
|
|
377
|
+
systemPrompt: z.ZodOptional<z.ZodString>;
|
|
378
|
+
allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
|
|
379
|
+
replyInThread: z.ZodOptional<z.ZodBoolean>;
|
|
380
|
+
}, z.core.$strip>>>;
|
|
381
|
+
historyLimit: z.ZodOptional<z.ZodNumber>;
|
|
382
|
+
dmHistoryLimit: z.ZodOptional<z.ZodNumber>;
|
|
383
|
+
dms: z.ZodOptional<z.ZodObject<{
|
|
384
|
+
historyLimit: z.ZodOptional<z.ZodNumber>;
|
|
385
|
+
}, z.core.$strip>>;
|
|
386
|
+
textChunkLimit: z.ZodOptional<z.ZodNumber>;
|
|
387
|
+
chunkMode: z.ZodOptional<z.ZodEnum<{
|
|
388
|
+
newline: "newline";
|
|
389
|
+
paragraph: "paragraph";
|
|
390
|
+
none: "none";
|
|
391
|
+
}>>;
|
|
392
|
+
blockStreamingCoalesce: z.ZodOptional<z.ZodObject<{
|
|
393
|
+
minChars: z.ZodOptional<z.ZodNumber>;
|
|
394
|
+
maxChars: z.ZodOptional<z.ZodNumber>;
|
|
395
|
+
idleMs: z.ZodOptional<z.ZodNumber>;
|
|
396
|
+
}, z.core.$strip>>;
|
|
397
|
+
mediaMaxMb: z.ZodOptional<z.ZodNumber>;
|
|
398
|
+
heartbeat: z.ZodOptional<z.ZodObject<{
|
|
399
|
+
every: z.ZodOptional<z.ZodString>;
|
|
400
|
+
activeHours: z.ZodOptional<z.ZodObject<{
|
|
401
|
+
start: z.ZodOptional<z.ZodString>;
|
|
402
|
+
end: z.ZodOptional<z.ZodString>;
|
|
403
|
+
timezone: z.ZodOptional<z.ZodString>;
|
|
404
|
+
}, z.core.$strip>>;
|
|
405
|
+
target: z.ZodOptional<z.ZodString>;
|
|
406
|
+
to: z.ZodOptional<z.ZodString>;
|
|
407
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
408
|
+
accountId: z.ZodOptional<z.ZodString>;
|
|
409
|
+
}, z.core.$strip>>;
|
|
410
|
+
replyMode: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
411
|
+
auto: "auto";
|
|
412
|
+
static: "static";
|
|
413
|
+
streaming: "streaming";
|
|
414
|
+
}>, z.ZodObject<{
|
|
415
|
+
default: z.ZodOptional<z.ZodEnum<{
|
|
416
|
+
auto: "auto";
|
|
417
|
+
static: "static";
|
|
418
|
+
streaming: "streaming";
|
|
419
|
+
}>>;
|
|
420
|
+
group: z.ZodOptional<z.ZodEnum<{
|
|
421
|
+
auto: "auto";
|
|
422
|
+
static: "static";
|
|
423
|
+
streaming: "streaming";
|
|
424
|
+
}>>;
|
|
425
|
+
direct: z.ZodOptional<z.ZodEnum<{
|
|
426
|
+
auto: "auto";
|
|
427
|
+
static: "static";
|
|
428
|
+
streaming: "streaming";
|
|
429
|
+
}>>;
|
|
430
|
+
}, z.core.$strip>]>>;
|
|
431
|
+
streaming: z.ZodOptional<z.ZodBoolean>;
|
|
432
|
+
blockStreaming: z.ZodOptional<z.ZodBoolean>;
|
|
433
|
+
toolUseDisplay: z.ZodOptional<z.ZodObject<{
|
|
434
|
+
showFullPaths: z.ZodOptional<z.ZodBoolean>;
|
|
435
|
+
}, z.core.$strip>>;
|
|
436
|
+
tools: z.ZodOptional<z.ZodObject<{
|
|
437
|
+
doc: z.ZodOptional<z.ZodBoolean>;
|
|
438
|
+
wiki: z.ZodOptional<z.ZodBoolean>;
|
|
439
|
+
drive: z.ZodOptional<z.ZodBoolean>;
|
|
440
|
+
perm: z.ZodOptional<z.ZodBoolean>;
|
|
441
|
+
scopes: z.ZodOptional<z.ZodBoolean>;
|
|
442
|
+
}, z.core.$strip>>;
|
|
443
|
+
footer: z.ZodOptional<z.ZodObject<{
|
|
444
|
+
status: z.ZodOptional<z.ZodBoolean>;
|
|
445
|
+
elapsed: z.ZodOptional<z.ZodBoolean>;
|
|
446
|
+
tokens: z.ZodOptional<z.ZodBoolean>;
|
|
447
|
+
cache: z.ZodOptional<z.ZodBoolean>;
|
|
448
|
+
context: z.ZodOptional<z.ZodBoolean>;
|
|
449
|
+
model: z.ZodOptional<z.ZodBoolean>;
|
|
450
|
+
}, z.core.$strip>>;
|
|
451
|
+
markdown: z.ZodOptional<z.ZodObject<{
|
|
452
|
+
tables: z.ZodOptional<z.ZodEnum<{
|
|
453
|
+
off: "off";
|
|
454
|
+
bullets: "bullets";
|
|
455
|
+
code: "code";
|
|
456
|
+
}>>;
|
|
457
|
+
}, z.core.$strip>>;
|
|
458
|
+
configWrites: z.ZodOptional<z.ZodBoolean>;
|
|
459
|
+
capabilities: z.ZodOptional<z.ZodObject<{
|
|
460
|
+
image: z.ZodOptional<z.ZodBoolean>;
|
|
461
|
+
audio: z.ZodOptional<z.ZodBoolean>;
|
|
462
|
+
video: z.ZodOptional<z.ZodBoolean>;
|
|
463
|
+
}, z.core.$strip>>;
|
|
464
|
+
dedup: z.ZodOptional<z.ZodObject<{
|
|
465
|
+
ttlMs: z.ZodOptional<z.ZodNumber>;
|
|
466
|
+
maxEntries: z.ZodOptional<z.ZodNumber>;
|
|
467
|
+
}, z.core.$strip>>;
|
|
468
|
+
reactionNotifications: z.ZodOptional<z.ZodEnum<{
|
|
469
|
+
off: "off";
|
|
470
|
+
own: "own";
|
|
471
|
+
all: "all";
|
|
472
|
+
}>>;
|
|
473
|
+
threadSession: z.ZodOptional<z.ZodBoolean>;
|
|
474
|
+
allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
|
|
475
|
+
replyInThread: z.ZodOptional<z.ZodBoolean>;
|
|
476
|
+
uat: z.ZodOptional<z.ZodObject<{
|
|
477
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
478
|
+
allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
479
|
+
blockedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
480
|
+
}, z.core.$strip>>;
|
|
481
|
+
}, z.core.$strip>>>;
|
|
482
|
+
}, z.core.$strip>;
|
|
16
483
|
/**
|
|
17
484
|
* JSON Schema derived from FeishuConfigSchema.
|
|
18
485
|
*
|
|
@@ -88,4 +88,11 @@ export declare function checkMessageGate(params: {
|
|
|
88
88
|
/** account 级别的 ClawdbotConfig(channels.feishu 已替换为 per-account 合并后的配置) */
|
|
89
89
|
accountScopedCfg?: ClawdbotConfig;
|
|
90
90
|
log: (...args: unknown[]) => void;
|
|
91
|
+
/**
|
|
92
|
+
* When true, treat the mention requirement as already satisfied (e.g. a card
|
|
93
|
+
* click is itself an explicit user action targeting the bot). Group/DM
|
|
94
|
+
* admission and sender-allowlist checks still run — this only bypasses the
|
|
95
|
+
* "must @-mention the bot" requirement, not access control.
|
|
96
|
+
*/
|
|
97
|
+
mentionSatisfied?: boolean;
|
|
91
98
|
}): Promise<GateResult>;
|
|
@@ -216,7 +216,7 @@ function checkBotSenderGate(params) {
|
|
|
216
216
|
// Internal: group gate
|
|
217
217
|
// ---------------------------------------------------------------------------
|
|
218
218
|
function checkGroupGate(params) {
|
|
219
|
-
const { ctx, accountFeishuCfg, account, accountScopedCfg, log } = params;
|
|
219
|
+
const { ctx, accountFeishuCfg, account, accountScopedCfg, log, mentionSatisfied } = params;
|
|
220
220
|
const core = lark_client_1.LarkClient.runtime;
|
|
221
221
|
// ---- Layer 1: Group-level admission (shared with bot path) ----
|
|
222
222
|
const access = resolveFeishuGroupAccess(params);
|
|
@@ -259,7 +259,7 @@ function checkGroupGate(params) {
|
|
|
259
259
|
groupIdCaseInsensitive: true,
|
|
260
260
|
requireMentionOverride: accountFeishuCfg?.requireMention,
|
|
261
261
|
});
|
|
262
|
-
if (requireMention && !(0, mention_1.mentionedBot)(ctx)) {
|
|
262
|
+
if (requireMention && !(0, mention_1.mentionedBot)(ctx) && !mentionSatisfied) {
|
|
263
263
|
// Check if @all mention should bypass the mention requirement
|
|
264
264
|
if (ctx.mentionAll) {
|
|
265
265
|
const respondToAll = resolveRespondToMentionAll({
|
|
@@ -17,6 +17,10 @@ export interface InboundHandlerParams {
|
|
|
17
17
|
accountId?: string;
|
|
18
18
|
replyToMessageId?: string;
|
|
19
19
|
forceMention?: boolean;
|
|
20
|
+
/** Run the real access-control gate but treat the mention requirement as
|
|
21
|
+
* satisfied (card-action synthetic messages). Takes precedence over
|
|
22
|
+
* forceMention. See handleFeishuMessage. */
|
|
23
|
+
cardActionGate?: boolean;
|
|
20
24
|
skipTyping?: boolean;
|
|
21
25
|
}
|
|
22
26
|
type InboundHandler = (params: InboundHandlerParams) => Promise<void>;
|
|
@@ -32,6 +32,12 @@ export declare function handleFeishuMessage(params: {
|
|
|
32
32
|
/** When true, skip the policy gate (mention requirement, allowlist).
|
|
33
33
|
* Used for synthetic messages that are not real user messages. */
|
|
34
34
|
forceMention?: boolean;
|
|
35
|
+
/** When true, run the real access-control gate but treat the mention
|
|
36
|
+
* requirement as already satisfied. Used for card-action synthetic messages:
|
|
37
|
+
* the click is an explicit user action targeting the bot (implicit mention),
|
|
38
|
+
* but group/DM admission and sender allowlists must still be enforced.
|
|
39
|
+
* Takes precedence over forceMention. */
|
|
40
|
+
cardActionGate?: boolean;
|
|
35
41
|
/** When true, skip the typing indicator for this dispatch (e.g. reactions). */
|
|
36
42
|
skipTyping?: boolean;
|
|
37
43
|
}): Promise<void>;
|
|
@@ -40,7 +40,7 @@ const logger = (0, lark_logger_1.larkLogger)('inbound/handler');
|
|
|
40
40
|
// Public: handle inbound message
|
|
41
41
|
// ---------------------------------------------------------------------------
|
|
42
42
|
async function handleFeishuMessage(params) {
|
|
43
|
-
const { cfg, event, botOpenId, runtime, chatHistories, accountId, replyToMessageId, forceMention, skipTyping } = params;
|
|
43
|
+
const { cfg, event, botOpenId, runtime, chatHistories, accountId, replyToMessageId, forceMention, cardActionGate, skipTyping, } = params;
|
|
44
44
|
// 1. Account resolution
|
|
45
45
|
const account = (0, accounts_1.getLarkAccount)(cfg, accountId);
|
|
46
46
|
const accountFeishuCfg = account.config;
|
|
@@ -116,10 +116,21 @@ async function handleFeishuMessage(params) {
|
|
|
116
116
|
log(`feishu[${account.accountId}]: received message from ${ctx.senderId} in ${ctx.chatId} (${ctx.chatType})`);
|
|
117
117
|
logger.info(`received from ${ctx.senderId} in ${ctx.chatId} (${ctx.chatType})`);
|
|
118
118
|
const historyLimit = Math.max(0, accountFeishuCfg?.historyLimit ?? accountScopedCfg.messages?.groupChat?.historyLimit ?? reply_history_1.DEFAULT_GROUP_HISTORY_LIMIT);
|
|
119
|
-
// 5. Gate: policy / access-control checks (skipped for synthetic messages)
|
|
120
|
-
|
|
119
|
+
// 5. Gate: policy / access-control checks (skipped for synthetic messages).
|
|
120
|
+
// cardActionGate runs the real gate with the mention requirement treated as
|
|
121
|
+
// satisfied (the click is an implicit mention) — it takes precedence over
|
|
122
|
+
// forceMention so card actions are still subject to group/DM admission and
|
|
123
|
+
// sender allowlists.
|
|
124
|
+
const gate = forceMention && !cardActionGate
|
|
121
125
|
? { allowed: true }
|
|
122
|
-
: await (0, gate_1.checkMessageGate)({
|
|
126
|
+
: await (0, gate_1.checkMessageGate)({
|
|
127
|
+
ctx,
|
|
128
|
+
accountFeishuCfg,
|
|
129
|
+
account,
|
|
130
|
+
accountScopedCfg,
|
|
131
|
+
log,
|
|
132
|
+
mentionSatisfied: cardActionGate,
|
|
133
|
+
});
|
|
123
134
|
if (!gate.allowed) {
|
|
124
135
|
if (gate.reason === 'no_mention') {
|
|
125
136
|
logger.info(`rejected: no bot mention in group ${ctx.chatId}`);
|
|
@@ -23,4 +23,9 @@ export declare function dispatchSyntheticTextMessage(params: {
|
|
|
23
23
|
error?: (msg: string) => void;
|
|
24
24
|
};
|
|
25
25
|
forceMention?: boolean;
|
|
26
|
+
/** When true, run the real access-control gate with the mention requirement
|
|
27
|
+
* treated as satisfied (see handleFeishuMessage.cardActionGate). Use for
|
|
28
|
+
* card-action synthetic messages so group/DM admission + sender allowlists
|
|
29
|
+
* are still enforced. Takes precedence over forceMention. */
|
|
30
|
+
cardActionGate?: boolean;
|
|
26
31
|
}): Promise<string>;
|
|
@@ -15,7 +15,7 @@ const lark_ticket_1 = require("../../core/lark-ticket.js");
|
|
|
15
15
|
const handler_registry_1 = require("./handler-registry.js");
|
|
16
16
|
async function dispatchSyntheticTextMessage(params) {
|
|
17
17
|
const handleFeishuMessage = (0, handler_registry_1.getInboundHandler)();
|
|
18
|
-
const { cfg, accountId, chatId, senderOpenId, text, syntheticMessageId, replyToMessageId, chatType, threadId, runtime, forceMention = true, } = params;
|
|
18
|
+
const { cfg, accountId, chatId, senderOpenId, text, syntheticMessageId, replyToMessageId, chatType, threadId, runtime, forceMention = true, cardActionGate, } = params;
|
|
19
19
|
const syntheticEvent = {
|
|
20
20
|
sender: {
|
|
21
21
|
sender_id: { open_id: senderOpenId },
|
|
@@ -48,6 +48,7 @@ async function dispatchSyntheticTextMessage(params) {
|
|
|
48
48
|
event: syntheticEvent,
|
|
49
49
|
accountId,
|
|
50
50
|
forceMention,
|
|
51
|
+
cardActionGate,
|
|
51
52
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
53
|
runtime: runtime,
|
|
53
54
|
replyToMessageId,
|
|
@@ -173,13 +173,15 @@ function handleAskUserAction(data, _cfg, accountId) {
|
|
|
173
173
|
openChatId = event.open_chat_id ?? event.context?.open_chat_id;
|
|
174
174
|
const actionTag = event.action?.tag;
|
|
175
175
|
const actionName = event.action?.name;
|
|
176
|
+
const formName = event.action?.form_name;
|
|
176
177
|
formValue = event.action?.form_value;
|
|
177
178
|
log.info(`card action received: tag=${actionTag}, name=${actionName}, chat=${openChatId}, ` +
|
|
178
179
|
`sender=${senderOpenId}, hasFormValue=${!!formValue}, hasValue=${!!event.action?.value}`);
|
|
179
180
|
// Extract action/operationId from button value (may not propagate for form submit)
|
|
180
181
|
const val = event.action?.value;
|
|
181
182
|
if (val && typeof val === 'object') {
|
|
182
|
-
|
|
183
|
+
const valueAction = val.action;
|
|
184
|
+
action = valueAction === ACTION_SUBMIT ? ACTION_SUBMIT : undefined;
|
|
183
185
|
operationId = val.operation_id;
|
|
184
186
|
}
|
|
185
187
|
// Detect form submit by button name
|
|
@@ -196,7 +198,13 @@ function handleAskUserAction(data, _cfg, accountId) {
|
|
|
196
198
|
action = ACTION_SUBMIT;
|
|
197
199
|
}
|
|
198
200
|
// Some SDK versions emit tag='form_submit' without button value/name.
|
|
199
|
-
|
|
201
|
+
// Business plugins also use form_submit; a form_name means it belongs to
|
|
202
|
+
// the named business form, while absent form_name keeps the old AskUser
|
|
203
|
+
// chat-scoped fallback for legacy callbacks.
|
|
204
|
+
if (!action &&
|
|
205
|
+
actionTag === 'form_submit' &&
|
|
206
|
+
!formName &&
|
|
207
|
+
(!actionName || actionName.startsWith(SUBMIT_BUTTON_PREFIX))) {
|
|
200
208
|
action = ACTION_SUBMIT;
|
|
201
209
|
if (!formValue && event.action) {
|
|
202
210
|
formValue = event.action;
|
package/tsdown.config.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default:
|
|
1
|
+
declare const _default: import("tsdown/types-D2Jnze_i").d;
|
|
2
2
|
export default _default;
|
package/vitest.config.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default:
|
|
1
|
+
declare const _default: UserConfig;
|
|
2
2
|
export default _default;
|