@larksuite/openclaw-lark 2026.5.12 → 2026.5.13-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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@larksuite/openclaw-lark",
3
- "version": "2026.5.12",
3
+ "version": "2026.5.13-beta.0",
4
4
  "description": "OpenClaw Lark/Feishu channel plugin",
5
5
  "exports": {
6
6
  ".": {
@@ -30,7 +30,7 @@
30
30
  "zod": "^4.3.6"
31
31
  },
32
32
  "peerDependencies": {
33
- "openclaw": ">=2026.3.22"
33
+ "openclaw": ">=2026.5.4"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "openclaw": {
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ *
5
+ * Feishu channel secret-contract registration. Declares which fields are
6
+ * SecretRef-shaped so OpenClaw's runtime resolves them at startup.
7
+ */
8
+ import type { ResolverContext, SecretDefaults, SecretTargetRegistryEntry } from 'openclaw/plugin-sdk/channel-secret-basic-runtime';
9
+ import type { OpenClawConfig } from 'openclaw/plugin-sdk';
10
+ export declare const secretTargetRegistryEntries: readonly SecretTargetRegistryEntry[];
11
+ export declare function collectRuntimeConfigAssignments(params: {
12
+ config: OpenClawConfig;
13
+ defaults: SecretDefaults | undefined;
14
+ context: ResolverContext;
15
+ }): void;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Feishu channel secret-contract registration. Declares which fields are
7
+ * SecretRef-shaped so OpenClaw's runtime resolves them at startup.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.secretTargetRegistryEntries = void 0;
11
+ exports.collectRuntimeConfigAssignments = collectRuntimeConfigAssignments;
12
+ const channel_secret_basic_runtime_1 = require("openclaw/plugin-sdk/channel-secret-basic-runtime");
13
+ const SECRET_FIELDS = ['appSecret', 'encryptKey', 'verificationToken'];
14
+ /** Fields the Lark SDK only consumes when an account is in webhook mode. */
15
+ const WEBHOOK_ONLY_FIELDS = ['encryptKey', 'verificationToken'];
16
+ exports.secretTargetRegistryEntries = SECRET_FIELDS.flatMap((field) => {
17
+ const acctPath = `channels.feishu.accounts.*.${field}`;
18
+ const topPath = `channels.feishu.${field}`;
19
+ return [
20
+ {
21
+ id: acctPath,
22
+ targetType: acctPath,
23
+ configFile: 'openclaw.json',
24
+ pathPattern: acctPath,
25
+ secretShape: 'secret_input',
26
+ expectedResolvedValue: 'string',
27
+ includeInPlan: true,
28
+ includeInConfigure: true,
29
+ includeInAudit: true,
30
+ },
31
+ {
32
+ id: topPath,
33
+ targetType: topPath,
34
+ configFile: 'openclaw.json',
35
+ pathPattern: topPath,
36
+ secretShape: 'secret_input',
37
+ expectedResolvedValue: 'string',
38
+ includeInPlan: true,
39
+ includeInConfigure: true,
40
+ includeInAudit: true,
41
+ },
42
+ ];
43
+ });
44
+ function collectRuntimeConfigAssignments(params) {
45
+ const resolved = (0, channel_secret_basic_runtime_1.getChannelSurface)(params.config, 'feishu');
46
+ if (!resolved)
47
+ return;
48
+ const { channel, surface } = resolved;
49
+ (0, channel_secret_basic_runtime_1.collectSimpleChannelFieldAssignments)({
50
+ channelKey: 'feishu',
51
+ field: 'appSecret',
52
+ channel,
53
+ surface,
54
+ defaults: params.defaults,
55
+ context: params.context,
56
+ topInactiveReason: 'no enabled Feishu account inherits this top-level appSecret.',
57
+ accountInactiveReason: 'Feishu account is disabled.',
58
+ });
59
+ const baseConnectionMode = (0, channel_secret_basic_runtime_1.normalizeSecretStringValue)(channel.connectionMode) === 'webhook' ? 'webhook' : 'websocket';
60
+ const resolveAccountMode = (account) => (0, channel_secret_basic_runtime_1.hasOwnProperty)(account, 'connectionMode')
61
+ ? (0, channel_secret_basic_runtime_1.normalizeSecretStringValue)(account.connectionMode)
62
+ : baseConnectionMode;
63
+ for (const field of WEBHOOK_ONLY_FIELDS) {
64
+ (0, channel_secret_basic_runtime_1.collectConditionalChannelFieldAssignments)({
65
+ channelKey: 'feishu',
66
+ field,
67
+ channel,
68
+ surface,
69
+ defaults: params.defaults,
70
+ context: params.context,
71
+ topLevelActiveWithoutAccounts: baseConnectionMode === 'webhook',
72
+ topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !(0, channel_secret_basic_runtime_1.hasOwnProperty)(account, field) && resolveAccountMode(account) === 'webhook',
73
+ accountActive: ({ account, enabled }) => enabled && resolveAccountMode(account) === 'webhook',
74
+ topInactiveReason: `no enabled Feishu webhook-mode surface inherits this top-level ${field}.`,
75
+ accountInactiveReason: 'Feishu account is disabled or not running in webhook mode.',
76
+ });
77
+ }
78
+ }
@@ -121,6 +121,7 @@ export interface FooterSessionMetrics {
121
121
  }
122
122
  export interface StreamingCardDeps {
123
123
  cfg: ClawdbotConfig;
124
+ agentId: string;
124
125
  sessionKey: string;
125
126
  accountId: string | undefined;
126
127
  chatId: string;
@@ -78,6 +78,7 @@ function createFeishuReplyDispatcher(params) {
78
78
  const controller = useStreamingCards
79
79
  ? new streaming_card_controller_1.StreamingCardController({
80
80
  cfg,
81
+ agentId,
81
82
  sessionKey,
82
83
  accountId,
83
84
  chatId,
@@ -107,7 +107,7 @@ class StreamingCardController {
107
107
  const candidateKeys = fallbackKey !== key ? [key, fallbackKey] : [key];
108
108
  const sessionApi = runtime.agent?.session;
109
109
  if (sessionApi?.resolveStorePath && sessionApi?.loadSessionStore) {
110
- const storePath = sessionApi.resolveStorePath(sessionStorePath);
110
+ const storePath = sessionApi.resolveStorePath(sessionStorePath, { agentId: this.deps.agentId });
111
111
  const store = sessionApi.loadSessionStore(storePath);
112
112
  let entry;
113
113
  let matchedKey;
@@ -150,7 +150,7 @@ class StreamingCardController {
150
150
  if (!channelSession?.resolveStorePath) {
151
151
  return undefined;
152
152
  }
153
- const storePath = channelSession.resolveStorePath(sessionStorePath);
153
+ const storePath = channelSession.resolveStorePath(sessionStorePath, { agentId: this.deps.agentId });
154
154
  const raw = await (0, promises_1.readFile)(storePath, 'utf8');
155
155
  const parsed = JSON.parse(raw);
156
156
  const store = parsed && typeof parsed === 'object' && !Array.isArray(parsed)
@@ -85,7 +85,7 @@ function buildSyntheticContext(event) {
85
85
  // reply language is still governed by the agent/session prompt stack.
86
86
  // If we later need locale-aware synthetic prompts, this is the single place
87
87
  // to introduce a template or config-based language switch.
88
- const syntheticText = `Join the meeting with meeting number ${event.meetingNo}.`;
88
+ const syntheticText = `Use the available tool to join the meeting with meeting number ${event.meetingNo} immediately. Do not ask for confirmation.`;
89
89
  const syntheticMessageId = event.eventId
90
90
  ? `vc-invited:event:${event.eventId}`
91
91
  : `vc-invited:${event.meetingNo}:${event.inviteTime ?? crypto.randomUUID()}`;
package/tsdown.config.js CHANGED
@@ -2,7 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tsdown_1 = require("tsdown");
4
4
  exports.default = (0, tsdown_1.defineConfig)({
5
- entry: { index: 'index.ts' },
5
+ entry: {
6
+ index: 'index.ts',
7
+ 'secret-contract-api': 'secret-contract-api.ts',
8
+ },
6
9
  format: 'esm',
7
10
  target: 'node22',
8
11
  platform: 'node',