@openclaw/feishu 2026.5.2 → 2026.5.3-beta.2
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/dist/accounts-Ba3-WP1z.js +423 -0
- package/dist/api.js +2280 -0
- package/dist/app-registration-B8qc1MCM.js +184 -0
- package/dist/audio-preflight.runtime-BPlzkO3l.js +7 -0
- package/dist/card-interaction-BfRLgvw_.js +96 -0
- package/dist/channel-CSD_Jt8I.js +1668 -0
- package/dist/channel-entry.js +22 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-DYsXcD36.js +700 -0
- package/dist/client-DBVoQL5w.js +157 -0
- package/dist/contract-api.js +9 -0
- package/dist/conversation-id-DWS3Ep2A.js +139 -0
- package/dist/directory.static-f3EeoRJd.js +44 -0
- package/dist/drive-C5eJLJr7.js +883 -0
- package/dist/index.js +68 -0
- package/dist/monitor-CT189QfR.js +60 -0
- package/dist/monitor.account-dJV2jO8C.js +4990 -0
- package/dist/monitor.state-DYM02ipp.js +100 -0
- package/dist/policy-D6c-wMPl.js +118 -0
- package/dist/probe-BNzzU_uR.js +149 -0
- package/dist/rolldown-runtime-DUslC3ob.js +14 -0
- package/dist/runtime-CG0DuRCy.js +8 -0
- package/dist/runtime-api.js +14 -0
- package/dist/secret-contract-Dm4Z_zQN.js +119 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/security-audit-DqJdocrN.js +11 -0
- package/dist/security-audit-shared-ByuMx9cJ.js +38 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/send-DowxxbpH.js +1218 -0
- package/dist/session-conversation-B4nrW-vo.js +27 -0
- package/dist/session-key-api.js +2 -0
- package/dist/setup-api.js +2 -0
- package/dist/setup-entry.js +15 -0
- package/dist/subagent-hooks-C3UhPVLV.js +227 -0
- package/dist/subagent-hooks-api.js +23 -0
- package/dist/targets-JMFJRKSe.js +48 -0
- package/dist/thread-bindings-BmS6TLes.js +222 -0
- package/package.json +15 -6
- package/api.ts +0 -31
- package/channel-entry.ts +0 -20
- package/channel-plugin-api.ts +0 -1
- package/contract-api.ts +0 -16
- package/index.ts +0 -82
- package/runtime-api.ts +0 -55
- package/secret-contract-api.ts +0 -5
- package/security-contract-api.ts +0 -1
- package/session-key-api.ts +0 -1
- package/setup-api.ts +0 -3
- package/setup-entry.test.ts +0 -14
- package/setup-entry.ts +0 -13
- package/src/accounts.test.ts +0 -459
- package/src/accounts.ts +0 -326
- package/src/app-registration.ts +0 -331
- package/src/approval-auth.test.ts +0 -24
- package/src/approval-auth.ts +0 -25
- package/src/async.test.ts +0 -35
- package/src/async.ts +0 -104
- package/src/audio-preflight.runtime.ts +0 -9
- package/src/bitable.test.ts +0 -131
- package/src/bitable.ts +0 -762
- package/src/bot-content.ts +0 -474
- package/src/bot-group-name.test.ts +0 -108
- package/src/bot-runtime-api.ts +0 -12
- package/src/bot-sender-name.ts +0 -125
- package/src/bot.broadcast.test.ts +0 -463
- package/src/bot.card-action.test.ts +0 -577
- package/src/bot.checkBotMentioned.test.ts +0 -265
- package/src/bot.helpers.test.ts +0 -118
- package/src/bot.stripBotMention.test.ts +0 -126
- package/src/bot.test.ts +0 -3040
- package/src/bot.ts +0 -1559
- package/src/card-action.ts +0 -447
- package/src/card-interaction.test.ts +0 -129
- package/src/card-interaction.ts +0 -159
- package/src/card-test-helpers.ts +0 -47
- package/src/card-ux-approval.ts +0 -65
- package/src/card-ux-launcher.test.ts +0 -99
- package/src/card-ux-launcher.ts +0 -121
- package/src/card-ux-shared.ts +0 -33
- package/src/channel-runtime-api.ts +0 -16
- package/src/channel.runtime.ts +0 -47
- package/src/channel.test.ts +0 -959
- package/src/channel.ts +0 -1313
- package/src/chat-schema.ts +0 -25
- package/src/chat.test.ts +0 -196
- package/src/chat.ts +0 -188
- package/src/client.test.ts +0 -433
- package/src/client.ts +0 -290
- package/src/comment-dispatcher-runtime-api.ts +0 -6
- package/src/comment-dispatcher.test.ts +0 -169
- package/src/comment-dispatcher.ts +0 -107
- package/src/comment-handler-runtime-api.ts +0 -3
- package/src/comment-handler.test.ts +0 -486
- package/src/comment-handler.ts +0 -309
- package/src/comment-reaction.test.ts +0 -166
- package/src/comment-reaction.ts +0 -259
- package/src/comment-shared.test.ts +0 -182
- package/src/comment-shared.ts +0 -406
- package/src/comment-target.ts +0 -44
- package/src/config-schema.test.ts +0 -309
- package/src/config-schema.ts +0 -333
- package/src/conversation-id.test.ts +0 -18
- package/src/conversation-id.ts +0 -199
- package/src/dedup-runtime-api.ts +0 -1
- package/src/dedup.ts +0 -141
- package/src/directory.static.ts +0 -61
- package/src/directory.test.ts +0 -136
- package/src/directory.ts +0 -124
- package/src/doc-schema.ts +0 -182
- package/src/docx-batch-insert.test.ts +0 -91
- package/src/docx-batch-insert.ts +0 -223
- package/src/docx-color-text.ts +0 -154
- package/src/docx-table-ops.test.ts +0 -53
- package/src/docx-table-ops.ts +0 -316
- package/src/docx-types.ts +0 -38
- package/src/docx.account-selection.test.ts +0 -79
- package/src/docx.test.ts +0 -685
- package/src/docx.ts +0 -1616
- package/src/drive-schema.ts +0 -92
- package/src/drive.test.ts +0 -1219
- package/src/drive.ts +0 -829
- package/src/dynamic-agent.ts +0 -137
- package/src/event-types.ts +0 -45
- package/src/external-keys.test.ts +0 -20
- package/src/external-keys.ts +0 -19
- package/src/lifecycle.test-support.ts +0 -220
- package/src/media.test.ts +0 -900
- package/src/media.ts +0 -861
- package/src/mention-target.types.ts +0 -5
- package/src/mention.ts +0 -114
- package/src/message-action-contract.ts +0 -13
- package/src/monitor-state-runtime-api.ts +0 -7
- package/src/monitor-transport-runtime-api.ts +0 -7
- package/src/monitor.account.ts +0 -468
- package/src/monitor.acp-init-failure.lifecycle.test-support.ts +0 -219
- package/src/monitor.bot-identity.ts +0 -86
- package/src/monitor.bot-menu-handler.ts +0 -165
- package/src/monitor.bot-menu.lifecycle.test-support.ts +0 -224
- package/src/monitor.bot-menu.test.ts +0 -178
- package/src/monitor.broadcast.reply-once.lifecycle.test-support.ts +0 -264
- package/src/monitor.card-action.lifecycle.test-support.ts +0 -373
- package/src/monitor.cleanup.test.ts +0 -376
- package/src/monitor.comment-notice-handler.ts +0 -105
- package/src/monitor.comment.test.ts +0 -937
- package/src/monitor.comment.ts +0 -1386
- package/src/monitor.lifecycle.test.ts +0 -4
- package/src/monitor.message-handler.ts +0 -339
- package/src/monitor.reaction.lifecycle.test-support.ts +0 -68
- package/src/monitor.reaction.test.ts +0 -713
- package/src/monitor.startup.test.ts +0 -192
- package/src/monitor.startup.ts +0 -74
- package/src/monitor.state.defaults.test.ts +0 -46
- package/src/monitor.state.ts +0 -170
- package/src/monitor.synthetic-error.ts +0 -18
- package/src/monitor.test-mocks.ts +0 -45
- package/src/monitor.transport.ts +0 -424
- package/src/monitor.ts +0 -100
- package/src/monitor.webhook-e2e.test.ts +0 -272
- package/src/monitor.webhook-security.test.ts +0 -264
- package/src/monitor.webhook.test-helpers.ts +0 -116
- package/src/outbound-runtime-api.ts +0 -1
- package/src/outbound.test.ts +0 -935
- package/src/outbound.ts +0 -718
- package/src/perm-schema.ts +0 -52
- package/src/perm.ts +0 -170
- package/src/pins.ts +0 -108
- package/src/policy.test.ts +0 -334
- package/src/policy.ts +0 -236
- package/src/post.test.ts +0 -105
- package/src/post.ts +0 -275
- package/src/probe.test.ts +0 -275
- package/src/probe.ts +0 -166
- package/src/processing-claims.ts +0 -59
- package/src/qr-terminal.ts +0 -1
- package/src/reactions.ts +0 -123
- package/src/reasoning-preview.test.ts +0 -59
- package/src/reasoning-preview.ts +0 -20
- package/src/reply-dispatcher-runtime-api.ts +0 -7
- package/src/reply-dispatcher.test.ts +0 -1144
- package/src/reply-dispatcher.ts +0 -650
- package/src/runtime.ts +0 -9
- package/src/secret-contract.ts +0 -145
- package/src/secret-input.ts +0 -1
- package/src/security-audit-shared.ts +0 -69
- package/src/security-audit.test.ts +0 -61
- package/src/security-audit.ts +0 -1
- package/src/send-result.ts +0 -29
- package/src/send-target.test.ts +0 -80
- package/src/send-target.ts +0 -35
- package/src/send.reply-fallback.test.ts +0 -292
- package/src/send.test.ts +0 -550
- package/src/send.ts +0 -800
- package/src/sequential-key.test.ts +0 -72
- package/src/sequential-key.ts +0 -28
- package/src/sequential-queue.test.ts +0 -92
- package/src/sequential-queue.ts +0 -16
- package/src/session-conversation.ts +0 -42
- package/src/session-route.ts +0 -48
- package/src/setup-core.ts +0 -51
- package/src/setup-surface.test.ts +0 -174
- package/src/setup-surface.ts +0 -581
- package/src/streaming-card.test.ts +0 -190
- package/src/streaming-card.ts +0 -490
- package/src/subagent-hooks.test.ts +0 -603
- package/src/subagent-hooks.ts +0 -397
- package/src/targets.ts +0 -97
- package/src/test-support/lifecycle-test-support.ts +0 -453
- package/src/thread-bindings.test.ts +0 -143
- package/src/thread-bindings.ts +0 -330
- package/src/tool-account-routing.test.ts +0 -187
- package/src/tool-account.test.ts +0 -44
- package/src/tool-account.ts +0 -93
- package/src/tool-factory-test-harness.ts +0 -79
- package/src/tool-result.test.ts +0 -32
- package/src/tool-result.ts +0 -16
- package/src/tools-config.test.ts +0 -21
- package/src/tools-config.ts +0 -22
- package/src/types.ts +0 -104
- package/src/typing.test.ts +0 -144
- package/src/typing.ts +0 -214
- package/src/wiki-schema.ts +0 -55
- package/src/wiki.ts +0 -227
- package/subagent-hooks-api.ts +0 -31
- package/tsconfig.json +0 -16
package/src/card-interaction.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { isRecord } from "./comment-shared.js";
|
|
2
|
-
|
|
3
|
-
export const FEISHU_CARD_INTERACTION_VERSION = "ocf1";
|
|
4
|
-
|
|
5
|
-
type FeishuCardInteractionKind = "button" | "quick" | "meta";
|
|
6
|
-
type FeishuCardInteractionReason = "malformed" | "stale" | "wrong_user" | "wrong_conversation";
|
|
7
|
-
|
|
8
|
-
type FeishuCardInteractionMetadata = Record<string, string | number | boolean | null | undefined>;
|
|
9
|
-
|
|
10
|
-
export type FeishuCardInteractionEnvelope = {
|
|
11
|
-
oc: typeof FEISHU_CARD_INTERACTION_VERSION;
|
|
12
|
-
k: FeishuCardInteractionKind;
|
|
13
|
-
a: string;
|
|
14
|
-
q?: string;
|
|
15
|
-
m?: FeishuCardInteractionMetadata;
|
|
16
|
-
c?: {
|
|
17
|
-
u?: string;
|
|
18
|
-
h?: string;
|
|
19
|
-
s?: string;
|
|
20
|
-
e?: number;
|
|
21
|
-
t?: "p2p" | "group";
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
type FeishuCardActionEventLike = {
|
|
26
|
-
operator: {
|
|
27
|
-
open_id?: string;
|
|
28
|
-
};
|
|
29
|
-
action: {
|
|
30
|
-
value: unknown;
|
|
31
|
-
};
|
|
32
|
-
context: {
|
|
33
|
-
chat_id?: string;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
type DecodedFeishuCardAction =
|
|
38
|
-
| {
|
|
39
|
-
kind: "structured";
|
|
40
|
-
envelope: FeishuCardInteractionEnvelope;
|
|
41
|
-
}
|
|
42
|
-
| {
|
|
43
|
-
kind: "legacy";
|
|
44
|
-
text: string;
|
|
45
|
-
}
|
|
46
|
-
| {
|
|
47
|
-
kind: "invalid";
|
|
48
|
-
reason: FeishuCardInteractionReason;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
function isInteractionKind(value: unknown): value is FeishuCardInteractionKind {
|
|
52
|
-
return value === "button" || value === "quick" || value === "meta";
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function isMetadataValue(value: unknown): value is string | number | boolean | null | undefined {
|
|
56
|
-
return (
|
|
57
|
-
value === null ||
|
|
58
|
-
value === undefined ||
|
|
59
|
-
typeof value === "string" ||
|
|
60
|
-
typeof value === "number" ||
|
|
61
|
-
typeof value === "boolean"
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function createFeishuCardInteractionEnvelope(
|
|
66
|
-
envelope: Omit<FeishuCardInteractionEnvelope, "oc">,
|
|
67
|
-
): FeishuCardInteractionEnvelope {
|
|
68
|
-
return {
|
|
69
|
-
oc: FEISHU_CARD_INTERACTION_VERSION,
|
|
70
|
-
...envelope,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function buildFeishuCardActionTextFallback(event: FeishuCardActionEventLike): string {
|
|
75
|
-
const actionValue = event.action.value;
|
|
76
|
-
if (isRecord(actionValue)) {
|
|
77
|
-
if (typeof actionValue.text === "string") {
|
|
78
|
-
return actionValue.text;
|
|
79
|
-
}
|
|
80
|
-
if (typeof actionValue.command === "string") {
|
|
81
|
-
return actionValue.command;
|
|
82
|
-
}
|
|
83
|
-
return JSON.stringify(actionValue);
|
|
84
|
-
}
|
|
85
|
-
return String(actionValue);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function decodeFeishuCardAction(params: {
|
|
89
|
-
event: FeishuCardActionEventLike;
|
|
90
|
-
now?: number;
|
|
91
|
-
}): DecodedFeishuCardAction {
|
|
92
|
-
const { event, now = Date.now() } = params;
|
|
93
|
-
const actionValue = event.action.value;
|
|
94
|
-
if (!isRecord(actionValue) || actionValue.oc !== FEISHU_CARD_INTERACTION_VERSION) {
|
|
95
|
-
return {
|
|
96
|
-
kind: "legacy",
|
|
97
|
-
text: buildFeishuCardActionTextFallback(event),
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (!isInteractionKind(actionValue.k) || typeof actionValue.a !== "string" || !actionValue.a) {
|
|
102
|
-
return { kind: "invalid", reason: "malformed" };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (actionValue.q !== undefined && typeof actionValue.q !== "string") {
|
|
106
|
-
return { kind: "invalid", reason: "malformed" };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (actionValue.m !== undefined) {
|
|
110
|
-
if (!isRecord(actionValue.m)) {
|
|
111
|
-
return { kind: "invalid", reason: "malformed" };
|
|
112
|
-
}
|
|
113
|
-
for (const value of Object.values(actionValue.m)) {
|
|
114
|
-
if (!isMetadataValue(value)) {
|
|
115
|
-
return { kind: "invalid", reason: "malformed" };
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (actionValue.c !== undefined) {
|
|
121
|
-
if (!isRecord(actionValue.c)) {
|
|
122
|
-
return { kind: "invalid", reason: "malformed" };
|
|
123
|
-
}
|
|
124
|
-
if (actionValue.c.u !== undefined && typeof actionValue.c.u !== "string") {
|
|
125
|
-
return { kind: "invalid", reason: "malformed" };
|
|
126
|
-
}
|
|
127
|
-
if (actionValue.c.h !== undefined && typeof actionValue.c.h !== "string") {
|
|
128
|
-
return { kind: "invalid", reason: "malformed" };
|
|
129
|
-
}
|
|
130
|
-
if (actionValue.c.s !== undefined && typeof actionValue.c.s !== "string") {
|
|
131
|
-
return { kind: "invalid", reason: "malformed" };
|
|
132
|
-
}
|
|
133
|
-
if (actionValue.c.e !== undefined && !Number.isFinite(actionValue.c.e)) {
|
|
134
|
-
return { kind: "invalid", reason: "malformed" };
|
|
135
|
-
}
|
|
136
|
-
if (actionValue.c.t !== undefined && actionValue.c.t !== "p2p" && actionValue.c.t !== "group") {
|
|
137
|
-
return { kind: "invalid", reason: "malformed" };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (typeof actionValue.c.e === "number" && actionValue.c.e < now) {
|
|
141
|
-
return { kind: "invalid", reason: "stale" };
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const expectedUser = actionValue.c.u?.trim();
|
|
145
|
-
if (expectedUser && expectedUser !== (event.operator.open_id ?? "").trim()) {
|
|
146
|
-
return { kind: "invalid", reason: "wrong_user" };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const expectedChat = actionValue.c.h?.trim();
|
|
150
|
-
if (expectedChat && expectedChat !== (event.context.chat_id ?? "").trim()) {
|
|
151
|
-
return { kind: "invalid", reason: "wrong_conversation" };
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
kind: "structured",
|
|
157
|
-
envelope: actionValue as FeishuCardInteractionEnvelope,
|
|
158
|
-
};
|
|
159
|
-
}
|
package/src/card-test-helpers.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { expect } from "vitest";
|
|
2
|
-
|
|
3
|
-
export function expectFirstSentCardUsesFillWidthOnly(sendCardMock: {
|
|
4
|
-
mock: { calls: unknown[][] };
|
|
5
|
-
}) {
|
|
6
|
-
const firstSendArg = sendCardMock.mock.calls.at(0)?.[0] as
|
|
7
|
-
| {
|
|
8
|
-
card?: {
|
|
9
|
-
config?: {
|
|
10
|
-
width_mode?: string;
|
|
11
|
-
wide_screen_mode?: boolean;
|
|
12
|
-
enable_forward?: boolean;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
| undefined;
|
|
17
|
-
const sentCard = firstSendArg?.card;
|
|
18
|
-
expect(sentCard).toBeDefined();
|
|
19
|
-
expect(sentCard?.config?.width_mode).toBe("fill");
|
|
20
|
-
expect(sentCard?.config?.wide_screen_mode).toBeUndefined();
|
|
21
|
-
expect(sentCard?.config?.enable_forward).toBeUndefined();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function expectSentCardHasP2pAction(sendCardMock: unknown) {
|
|
25
|
-
expect(sendCardMock).toHaveBeenCalledWith(
|
|
26
|
-
expect.objectContaining({
|
|
27
|
-
card: expect.objectContaining({
|
|
28
|
-
body: expect.objectContaining({
|
|
29
|
-
elements: expect.arrayContaining([
|
|
30
|
-
expect.objectContaining({
|
|
31
|
-
tag: "action",
|
|
32
|
-
actions: expect.arrayContaining([
|
|
33
|
-
expect.objectContaining({
|
|
34
|
-
value: expect.objectContaining({
|
|
35
|
-
c: expect.objectContaining({
|
|
36
|
-
t: "p2p",
|
|
37
|
-
}),
|
|
38
|
-
}),
|
|
39
|
-
}),
|
|
40
|
-
]),
|
|
41
|
-
}),
|
|
42
|
-
]),
|
|
43
|
-
}),
|
|
44
|
-
}),
|
|
45
|
-
}),
|
|
46
|
-
);
|
|
47
|
-
}
|
package/src/card-ux-approval.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { createFeishuCardInteractionEnvelope } from "./card-interaction.js";
|
|
2
|
-
import { buildFeishuCardButton, buildFeishuCardInteractionContext } from "./card-ux-shared.js";
|
|
3
|
-
|
|
4
|
-
export const FEISHU_APPROVAL_REQUEST_ACTION = "feishu.quick_actions.request_approval";
|
|
5
|
-
export const FEISHU_APPROVAL_CONFIRM_ACTION = "feishu.approval.confirm";
|
|
6
|
-
export const FEISHU_APPROVAL_CANCEL_ACTION = "feishu.approval.cancel";
|
|
7
|
-
|
|
8
|
-
export function createApprovalCard(params: {
|
|
9
|
-
operatorOpenId: string;
|
|
10
|
-
chatId?: string;
|
|
11
|
-
command: string;
|
|
12
|
-
prompt: string;
|
|
13
|
-
expiresAt: number;
|
|
14
|
-
chatType?: "p2p" | "group";
|
|
15
|
-
sessionKey?: string;
|
|
16
|
-
confirmLabel?: string;
|
|
17
|
-
cancelLabel?: string;
|
|
18
|
-
}): Record<string, unknown> {
|
|
19
|
-
const context = buildFeishuCardInteractionContext(params);
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
schema: "2.0",
|
|
23
|
-
config: {
|
|
24
|
-
width_mode: "fill",
|
|
25
|
-
},
|
|
26
|
-
header: {
|
|
27
|
-
title: {
|
|
28
|
-
tag: "plain_text",
|
|
29
|
-
content: "Confirm action",
|
|
30
|
-
},
|
|
31
|
-
template: "orange",
|
|
32
|
-
},
|
|
33
|
-
body: {
|
|
34
|
-
elements: [
|
|
35
|
-
{
|
|
36
|
-
tag: "markdown",
|
|
37
|
-
content: params.prompt,
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
tag: "action",
|
|
41
|
-
actions: [
|
|
42
|
-
buildFeishuCardButton({
|
|
43
|
-
label: params.confirmLabel ?? "Confirm",
|
|
44
|
-
type: "primary",
|
|
45
|
-
value: createFeishuCardInteractionEnvelope({
|
|
46
|
-
k: "quick",
|
|
47
|
-
a: FEISHU_APPROVAL_CONFIRM_ACTION,
|
|
48
|
-
q: params.command,
|
|
49
|
-
c: context,
|
|
50
|
-
}),
|
|
51
|
-
}),
|
|
52
|
-
buildFeishuCardButton({
|
|
53
|
-
label: params.cancelLabel ?? "Cancel",
|
|
54
|
-
value: createFeishuCardInteractionEnvelope({
|
|
55
|
-
k: "button",
|
|
56
|
-
a: FEISHU_APPROVAL_CANCEL_ACTION,
|
|
57
|
-
c: context,
|
|
58
|
-
}),
|
|
59
|
-
}),
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { createRuntimeEnv } from "openclaw/plugin-sdk/plugin-test-runtime";
|
|
2
|
-
import { describe, expect, it, vi, beforeEach } from "vitest";
|
|
3
|
-
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
|
|
4
|
-
import {
|
|
5
|
-
expectFirstSentCardUsesFillWidthOnly,
|
|
6
|
-
expectSentCardHasP2pAction,
|
|
7
|
-
} from "./card-test-helpers.js";
|
|
8
|
-
import {
|
|
9
|
-
createQuickActionLauncherCard,
|
|
10
|
-
isFeishuQuickActionMenuEventKey,
|
|
11
|
-
maybeHandleFeishuQuickActionMenu,
|
|
12
|
-
} from "./card-ux-launcher.js";
|
|
13
|
-
|
|
14
|
-
const sendCardFeishuMock = vi.hoisted(() => vi.fn());
|
|
15
|
-
|
|
16
|
-
vi.mock("./send.js", () => ({
|
|
17
|
-
sendCardFeishu: sendCardFeishuMock,
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
describe("feishu quick-action launcher", () => {
|
|
21
|
-
const cfg: ClawdbotConfig = {};
|
|
22
|
-
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
vi.clearAllMocks();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("recognizes the quick-actions bot menu key", () => {
|
|
28
|
-
expect(isFeishuQuickActionMenuEventKey("quick-actions")).toBe(true);
|
|
29
|
-
expect(isFeishuQuickActionMenuEventKey("other")).toBe(false);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("builds a launcher card with interactive actions", () => {
|
|
33
|
-
const card = createQuickActionLauncherCard({
|
|
34
|
-
operatorOpenId: "u123",
|
|
35
|
-
chatId: "chat1",
|
|
36
|
-
expiresAt: 123,
|
|
37
|
-
sessionKey: "agent:codex:feishu:chat:chat1",
|
|
38
|
-
}) as {
|
|
39
|
-
config: {
|
|
40
|
-
width_mode?: string;
|
|
41
|
-
enable_forward?: boolean;
|
|
42
|
-
wide_screen_mode?: boolean;
|
|
43
|
-
};
|
|
44
|
-
body: {
|
|
45
|
-
elements: Array<{
|
|
46
|
-
tag: string;
|
|
47
|
-
actions?: Array<{ value?: { oc?: string; c?: { s?: string; t?: string } } }>;
|
|
48
|
-
}>;
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
expect(card.config.width_mode).toBe("fill");
|
|
53
|
-
expect(card.config.enable_forward).toBeUndefined();
|
|
54
|
-
expect(card.config.wide_screen_mode).toBeUndefined();
|
|
55
|
-
const actionBlock = card.body.elements.find((entry) => entry.tag === "action");
|
|
56
|
-
expect(actionBlock?.actions).toHaveLength(3);
|
|
57
|
-
expect(actionBlock?.actions?.[0]?.value?.oc).toBe("ocf1");
|
|
58
|
-
expect(actionBlock?.actions?.[0]?.value?.c?.s).toBe("agent:codex:feishu:chat:chat1");
|
|
59
|
-
expect(actionBlock?.actions?.[0]?.value?.c?.t).toBeUndefined();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("opens the launcher from a supported bot menu event", async () => {
|
|
63
|
-
sendCardFeishuMock.mockResolvedValue({ messageId: "m1", chatId: "c1" });
|
|
64
|
-
|
|
65
|
-
const handled = await maybeHandleFeishuQuickActionMenu({
|
|
66
|
-
cfg,
|
|
67
|
-
eventKey: "quick-actions",
|
|
68
|
-
operatorOpenId: "u123",
|
|
69
|
-
accountId: "main",
|
|
70
|
-
now: 100,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
expect(handled).toBe(true);
|
|
74
|
-
expect(sendCardFeishuMock).toHaveBeenCalledWith(
|
|
75
|
-
expect.objectContaining({
|
|
76
|
-
to: "user:u123",
|
|
77
|
-
accountId: "main",
|
|
78
|
-
}),
|
|
79
|
-
);
|
|
80
|
-
expectSentCardHasP2pAction(sendCardFeishuMock);
|
|
81
|
-
expectFirstSentCardUsesFillWidthOnly(sendCardFeishuMock);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("falls back to legacy menu handling when launcher send fails", async () => {
|
|
85
|
-
sendCardFeishuMock.mockRejectedValueOnce(new Error("network"));
|
|
86
|
-
const runtime: RuntimeEnv = createRuntimeEnv();
|
|
87
|
-
|
|
88
|
-
const handled = await maybeHandleFeishuQuickActionMenu({
|
|
89
|
-
cfg,
|
|
90
|
-
eventKey: "quick-actions",
|
|
91
|
-
operatorOpenId: "u123",
|
|
92
|
-
accountId: "main",
|
|
93
|
-
runtime,
|
|
94
|
-
now: 100,
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
expect(handled).toBe(false);
|
|
98
|
-
});
|
|
99
|
-
});
|
package/src/card-ux-launcher.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
|
2
|
-
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
|
|
3
|
-
import { createFeishuCardInteractionEnvelope } from "./card-interaction.js";
|
|
4
|
-
import { FEISHU_APPROVAL_REQUEST_ACTION } from "./card-ux-approval.js";
|
|
5
|
-
import { buildFeishuCardButton, buildFeishuCardInteractionContext } from "./card-ux-shared.js";
|
|
6
|
-
import { sendCardFeishu } from "./send.js";
|
|
7
|
-
|
|
8
|
-
const FEISHU_QUICK_ACTION_CARD_TTL_MS = 10 * 60_000;
|
|
9
|
-
|
|
10
|
-
const QUICK_ACTION_MENU_KEYS = new Set(["quick-actions", "quick_actions", "launcher"]);
|
|
11
|
-
|
|
12
|
-
export function isFeishuQuickActionMenuEventKey(eventKey: string): boolean {
|
|
13
|
-
return QUICK_ACTION_MENU_KEYS.has(normalizeOptionalLowercaseString(eventKey) ?? "");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function createQuickActionLauncherCard(params: {
|
|
17
|
-
operatorOpenId: string;
|
|
18
|
-
chatId?: string;
|
|
19
|
-
expiresAt: number;
|
|
20
|
-
chatType?: "p2p" | "group";
|
|
21
|
-
sessionKey?: string;
|
|
22
|
-
}): Record<string, unknown> {
|
|
23
|
-
const context = buildFeishuCardInteractionContext(params);
|
|
24
|
-
return {
|
|
25
|
-
schema: "2.0",
|
|
26
|
-
config: {
|
|
27
|
-
width_mode: "fill",
|
|
28
|
-
},
|
|
29
|
-
header: {
|
|
30
|
-
title: {
|
|
31
|
-
tag: "plain_text",
|
|
32
|
-
content: "Quick actions",
|
|
33
|
-
},
|
|
34
|
-
template: "indigo",
|
|
35
|
-
},
|
|
36
|
-
body: {
|
|
37
|
-
elements: [
|
|
38
|
-
{
|
|
39
|
-
tag: "markdown",
|
|
40
|
-
content: "Run common actions without typing raw commands.",
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
tag: "action",
|
|
44
|
-
actions: [
|
|
45
|
-
buildFeishuCardButton({
|
|
46
|
-
label: "Help",
|
|
47
|
-
value: createFeishuCardInteractionEnvelope({
|
|
48
|
-
k: "quick",
|
|
49
|
-
a: "feishu.quick_actions.help",
|
|
50
|
-
q: "/help",
|
|
51
|
-
c: context,
|
|
52
|
-
}),
|
|
53
|
-
}),
|
|
54
|
-
buildFeishuCardButton({
|
|
55
|
-
label: "New session",
|
|
56
|
-
type: "primary",
|
|
57
|
-
value: createFeishuCardInteractionEnvelope({
|
|
58
|
-
k: "meta",
|
|
59
|
-
a: FEISHU_APPROVAL_REQUEST_ACTION,
|
|
60
|
-
m: {
|
|
61
|
-
command: "/new",
|
|
62
|
-
prompt: "Start a fresh session? This will reset the current chat context.",
|
|
63
|
-
},
|
|
64
|
-
c: context,
|
|
65
|
-
}),
|
|
66
|
-
}),
|
|
67
|
-
buildFeishuCardButton({
|
|
68
|
-
label: "Reset",
|
|
69
|
-
type: "danger",
|
|
70
|
-
value: createFeishuCardInteractionEnvelope({
|
|
71
|
-
k: "meta",
|
|
72
|
-
a: FEISHU_APPROVAL_REQUEST_ACTION,
|
|
73
|
-
m: {
|
|
74
|
-
command: "/reset",
|
|
75
|
-
prompt: "Reset this session now? Any active conversation state will be cleared.",
|
|
76
|
-
},
|
|
77
|
-
c: context,
|
|
78
|
-
}),
|
|
79
|
-
}),
|
|
80
|
-
],
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export async function maybeHandleFeishuQuickActionMenu(params: {
|
|
88
|
-
cfg: ClawdbotConfig;
|
|
89
|
-
eventKey: string;
|
|
90
|
-
operatorOpenId: string;
|
|
91
|
-
runtime?: RuntimeEnv;
|
|
92
|
-
accountId?: string;
|
|
93
|
-
now?: number;
|
|
94
|
-
}): Promise<boolean> {
|
|
95
|
-
if (!isFeishuQuickActionMenuEventKey(params.eventKey)) {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const expiresAt = (params.now ?? Date.now()) + FEISHU_QUICK_ACTION_CARD_TTL_MS;
|
|
100
|
-
try {
|
|
101
|
-
await sendCardFeishu({
|
|
102
|
-
cfg: params.cfg,
|
|
103
|
-
to: `user:${params.operatorOpenId}`,
|
|
104
|
-
card: createQuickActionLauncherCard({
|
|
105
|
-
operatorOpenId: params.operatorOpenId,
|
|
106
|
-
expiresAt,
|
|
107
|
-
chatType: "p2p",
|
|
108
|
-
}),
|
|
109
|
-
accountId: params.accountId,
|
|
110
|
-
});
|
|
111
|
-
} catch (err) {
|
|
112
|
-
params.runtime?.log?.(
|
|
113
|
-
`feishu[${params.accountId ?? "default"}]: failed to open quick-action launcher for ${params.operatorOpenId}: ${String(err)}`,
|
|
114
|
-
);
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
params.runtime?.log?.(
|
|
118
|
-
`feishu[${params.accountId ?? "default"}]: opened quick-action launcher for ${params.operatorOpenId}`,
|
|
119
|
-
);
|
|
120
|
-
return true;
|
|
121
|
-
}
|
package/src/card-ux-shared.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { FeishuCardInteractionEnvelope } from "./card-interaction.js";
|
|
2
|
-
|
|
3
|
-
export function buildFeishuCardButton(params: {
|
|
4
|
-
label: string;
|
|
5
|
-
value: FeishuCardInteractionEnvelope;
|
|
6
|
-
type?: "default" | "primary" | "danger";
|
|
7
|
-
}) {
|
|
8
|
-
return {
|
|
9
|
-
tag: "button",
|
|
10
|
-
text: {
|
|
11
|
-
tag: "plain_text",
|
|
12
|
-
content: params.label,
|
|
13
|
-
},
|
|
14
|
-
type: params.type ?? "default",
|
|
15
|
-
value: params.value,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function buildFeishuCardInteractionContext(params: {
|
|
20
|
-
operatorOpenId: string;
|
|
21
|
-
chatId?: string;
|
|
22
|
-
expiresAt: number;
|
|
23
|
-
chatType?: "p2p" | "group";
|
|
24
|
-
sessionKey?: string;
|
|
25
|
-
}) {
|
|
26
|
-
return {
|
|
27
|
-
u: params.operatorOpenId,
|
|
28
|
-
...(params.chatId ? { h: params.chatId } : {}),
|
|
29
|
-
...(params.sessionKey ? { s: params.sessionKey } : {}),
|
|
30
|
-
e: params.expiresAt,
|
|
31
|
-
...(params.chatType ? { t: params.chatType } : {}),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
ChannelMessageActionName,
|
|
3
|
-
ChannelMeta,
|
|
4
|
-
ChannelPlugin,
|
|
5
|
-
ClawdbotConfig,
|
|
6
|
-
} from "../runtime-api.js";
|
|
7
|
-
|
|
8
|
-
export { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-resolution";
|
|
9
|
-
export { createActionGate } from "openclaw/plugin-sdk/channel-actions";
|
|
10
|
-
export { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-primitives";
|
|
11
|
-
export {
|
|
12
|
-
buildProbeChannelStatusSummary,
|
|
13
|
-
createDefaultChannelRuntimeState,
|
|
14
|
-
} from "openclaw/plugin-sdk/status-helpers";
|
|
15
|
-
export { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
|
|
16
|
-
export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
package/src/channel.runtime.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getChatInfo as getChatInfoImpl,
|
|
3
|
-
getChatMembers as getChatMembersImpl,
|
|
4
|
-
getFeishuMemberInfo as getFeishuMemberInfoImpl,
|
|
5
|
-
} from "./chat.js";
|
|
6
|
-
import {
|
|
7
|
-
listFeishuDirectoryGroupsLive as listFeishuDirectoryGroupsLiveImpl,
|
|
8
|
-
listFeishuDirectoryPeersLive as listFeishuDirectoryPeersLiveImpl,
|
|
9
|
-
} from "./directory.js";
|
|
10
|
-
import { feishuOutbound as feishuOutboundImpl } from "./outbound.js";
|
|
11
|
-
import {
|
|
12
|
-
createPinFeishu as createPinFeishuImpl,
|
|
13
|
-
listPinsFeishu as listPinsFeishuImpl,
|
|
14
|
-
removePinFeishu as removePinFeishuImpl,
|
|
15
|
-
} from "./pins.js";
|
|
16
|
-
import { probeFeishu as probeFeishuImpl } from "./probe.js";
|
|
17
|
-
import {
|
|
18
|
-
addReactionFeishu as addReactionFeishuImpl,
|
|
19
|
-
listReactionsFeishu as listReactionsFeishuImpl,
|
|
20
|
-
removeReactionFeishu as removeReactionFeishuImpl,
|
|
21
|
-
} from "./reactions.js";
|
|
22
|
-
import {
|
|
23
|
-
editMessageFeishu as editMessageFeishuImpl,
|
|
24
|
-
getMessageFeishu as getMessageFeishuImpl,
|
|
25
|
-
sendCardFeishu as sendCardFeishuImpl,
|
|
26
|
-
sendMessageFeishu as sendMessageFeishuImpl,
|
|
27
|
-
} from "./send.js";
|
|
28
|
-
|
|
29
|
-
export const feishuChannelRuntime = {
|
|
30
|
-
listFeishuDirectoryGroupsLive: listFeishuDirectoryGroupsLiveImpl,
|
|
31
|
-
listFeishuDirectoryPeersLive: listFeishuDirectoryPeersLiveImpl,
|
|
32
|
-
feishuOutbound: { ...feishuOutboundImpl },
|
|
33
|
-
createPinFeishu: createPinFeishuImpl,
|
|
34
|
-
listPinsFeishu: listPinsFeishuImpl,
|
|
35
|
-
removePinFeishu: removePinFeishuImpl,
|
|
36
|
-
probeFeishu: probeFeishuImpl,
|
|
37
|
-
addReactionFeishu: addReactionFeishuImpl,
|
|
38
|
-
listReactionsFeishu: listReactionsFeishuImpl,
|
|
39
|
-
removeReactionFeishu: removeReactionFeishuImpl,
|
|
40
|
-
getChatInfo: getChatInfoImpl,
|
|
41
|
-
getChatMembers: getChatMembersImpl,
|
|
42
|
-
getFeishuMemberInfo: getFeishuMemberInfoImpl,
|
|
43
|
-
editMessageFeishu: editMessageFeishuImpl,
|
|
44
|
-
getMessageFeishu: getMessageFeishuImpl,
|
|
45
|
-
sendCardFeishu: sendCardFeishuImpl,
|
|
46
|
-
sendMessageFeishu: sendMessageFeishuImpl,
|
|
47
|
-
};
|