@workclaw/openclaw-workclaw 1.0.342 → 1.0.343

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/{anthropic-BX4T2YIB.js → anthropic-C1jzp_Rc.js} +1 -1
  2. package/dist/api.js +379 -0
  3. package/dist/{azure-openai-responses-CRtsnQnD.js → azure-openai-responses-zym2wxMB.js} +2 -2
  4. package/dist/{index-ZWLWkJXc.js → channel-CWeiUgV5.js} +2162 -5548
  5. package/dist/channel-bootstrap.runtime-B0t3vnup-S_ZINco5.js +5 -0
  6. package/dist/channel-entry-api.d.ts +3 -0
  7. package/dist/channel-entry-api.d.ts.map +1 -0
  8. package/dist/channel-entry-api.js +719 -0
  9. package/dist/channel-entry-contract-BDMmGZzs-4ZlSsA7g.js +252 -0
  10. package/dist/channel-plugin-api.d.ts +2 -0
  11. package/dist/channel-plugin-api.d.ts.map +1 -0
  12. package/dist/channel-plugin-api.js +4 -0
  13. package/dist/{cleanup-i9QIMqva-CYcFSfZC.js → cleanup-i9QIMqva-DceifGSO.js} +2 -2
  14. package/dist/config-QB0JLJHX.js +94 -0
  15. package/dist/{cron-tasks-handler-BIpSoLIG.js → cron-tasks-handler-CIhnDbA3.js} +1 -1
  16. package/dist/{google-BhYq3yh7.js → google-DqQHu2NY.js} +2 -2
  17. package/dist/{google-shared-sAeUdThk.js → google-shared-BeRWP6yE.js} +1 -1
  18. package/dist/{google-vertex-CFbea9mm.js → google-vertex-Cs1hEe_j.js} +2 -2
  19. package/dist/{host-hook-cleanup-BNlJQu7G-DZh9GtcC.js → host-hook-cleanup-BNlJQu7G-NNZIzDgg.js} +3 -2
  20. package/dist/index-DLeHpawu.js +1351 -0
  21. package/dist/index-DvlDhBhd.js +524 -0
  22. package/dist/{index-CXEk4j12.js → index-mQv9vOMk.js} +1 -1
  23. package/dist/index.d.ts +1 -10
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +42 -11
  26. package/dist/{legacy-config-issues-Czu0_ffE-BUj03gnH.js → legacy-config-issues-Czu0_ffE-C-SKoHc6.js} +4 -2
  27. package/dist/{message-oTt1u1XX-BHxJ4z66.js → message-oTt1u1XX-NFsrpDss.js} +5 -4
  28. package/dist/message.config.runtime-DmvQNASl.js +4 -0
  29. package/dist/{message.gateway.runtime-Ch5zdrYr.js → message.gateway.runtime-BIIf6teh.js} +3 -2
  30. package/dist/{mistral-DgMDMo1J.js → mistral-B0v4IfAz.js} +1 -1
  31. package/dist/models-config.runtime-cY4XGOI0.js +4 -0
  32. package/dist/{openai-codex-responses-D6j-616z.js → openai-codex-responses-tC0hde6o.js} +2 -2
  33. package/dist/{openai-completions-BtT6C5eC.js → openai-completions-w3FtI3rd.js} +1 -1
  34. package/dist/{openai-responses-Dtuy4M7B.js → openai-responses-rRjf4OAK.js} +2 -2
  35. package/dist/{openai-responses-shared-DZBSlU2d.js → openai-responses-shared-ZlolmuqL.js} +1 -1
  36. package/dist/{openrouter-DbsgRqzU.js → openrouter-CXWxTM8p.js} +1 -1
  37. package/dist/{photon_rs-CbOi7Vp0.js → photon_rs-CGHeuAJ1.js} +1 -1
  38. package/dist/{plugin-load-profile-DOnG9jJ5-zOQuKNoi.js → plugin-load-profile-DOnG9jJ5-B0ymqOTX.js} +9936 -9990
  39. package/dist/plugins-C54ejDC8-qGQvFNWW.js +8 -0
  40. package/dist/provider-discovery.runtime-ZgcVwu5_.js +4 -0
  41. package/dist/runtime-api-DU-e2Pen.js +391 -0
  42. package/dist/runtime-api.d.ts +2 -0
  43. package/dist/runtime-api.d.ts.map +1 -0
  44. package/dist/runtime-api.js +4 -0
  45. package/dist/{session-archive.runtime-BAljnZWW.js → session-archive.runtime-SvY1eJq4.js} +2 -2
  46. package/dist/setup-entry.js +2 -194
  47. package/dist/src/runtime.js +37 -0
  48. package/dist/src/secret-contract-api.js +7 -0
  49. package/dist/string-coerce-DyL154ka-BEV0SzzS.js +61 -0
  50. package/dist/subsystem-W8wAQXn1-BIMucqMi.js +4 -0
  51. package/dist/tools-api.d.ts +2 -0
  52. package/dist/tools-api.d.ts.map +1 -0
  53. package/dist/tools-api.js +4 -0
  54. package/dist/transcript.runtime-Dchg_w3u.js +5 -0
  55. package/dist/workclaw-client-CMjcFjJx.js +538 -0
  56. package/package.json +9 -5
  57. package/dist/channel-bootstrap.runtime-B0t3vnup-vflkdVI8.js +0 -5
  58. package/dist/config-Cw8JPyMQ.js +0 -94
  59. package/dist/message.config.runtime-DuzEAWuz.js +0 -4
  60. package/dist/models-config.runtime-DLspRp8e.js +0 -4
  61. package/dist/plugins-C54ejDC8-Df48OaX-.js +0 -8
  62. package/dist/provider-discovery.runtime-Dps3xmj0.js +0 -4
  63. package/dist/subsystem-W8wAQXn1-Dh_4L9-w.js +0 -4
  64. package/dist/transcript.runtime-B6llle92.js +0 -5
@@ -0,0 +1,7 @@
1
+ const channelSecrets = {
2
+ specifier: "./runtime.js",
3
+ exportName: "getWorkclawSecrets"
4
+ };
5
+ export {
6
+ channelSecrets
7
+ };
@@ -0,0 +1,61 @@
1
+ function readStringValue(value) {
2
+ return typeof value === "string" ? value : void 0;
3
+ }
4
+ function normalizeNullableString(value) {
5
+ if (typeof value !== "string") return null;
6
+ const trimmed = value.trim();
7
+ return trimmed ? trimmed : null;
8
+ }
9
+ function normalizeOptionalString(value) {
10
+ return normalizeNullableString(value) ?? void 0;
11
+ }
12
+ function normalizeStringifiedOptionalString(value) {
13
+ if (typeof value === "string") return normalizeOptionalString(value);
14
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return normalizeOptionalString(String(value));
15
+ }
16
+ function normalizeOptionalLowercaseString(value) {
17
+ return normalizeOptionalString(value)?.toLowerCase();
18
+ }
19
+ function normalizeLowercaseStringOrEmpty(value) {
20
+ return normalizeOptionalLowercaseString(value) ?? "";
21
+ }
22
+ function normalizeFastMode(raw) {
23
+ if (typeof raw === "boolean") return raw;
24
+ if (!raw) return;
25
+ const key = normalizeLowercaseStringOrEmpty(raw);
26
+ if ([
27
+ "off",
28
+ "false",
29
+ "no",
30
+ "0",
31
+ "disable",
32
+ "disabled",
33
+ "normal"
34
+ ].includes(key)) return false;
35
+ if ([
36
+ "on",
37
+ "true",
38
+ "yes",
39
+ "1",
40
+ "enable",
41
+ "enabled",
42
+ "fast"
43
+ ].includes(key)) return true;
44
+ }
45
+ function normalizeOptionalThreadValue(value) {
46
+ if (typeof value === "number") return Number.isFinite(value) ? Math.trunc(value) : void 0;
47
+ return normalizeOptionalString(value);
48
+ }
49
+ function hasNonEmptyString(value) {
50
+ return normalizeOptionalString(value) !== void 0;
51
+ }
52
+ export {
53
+ normalizeOptionalLowercaseString as a,
54
+ normalizeOptionalString as b,
55
+ normalizeStringifiedOptionalString as c,
56
+ normalizeFastMode as d,
57
+ normalizeOptionalThreadValue as e,
58
+ hasNonEmptyString as h,
59
+ normalizeLowercaseStringOrEmpty as n,
60
+ readStringValue as r
61
+ };
@@ -0,0 +1,4 @@
1
+ import { as as createSubsystemLogger } from "./channel-CWeiUgV5.js";
2
+ export {
3
+ createSubsystemLogger
4
+ };
@@ -0,0 +1,2 @@
1
+ export { registerAllOpenclawWorkclawCronTools as registerWorkclawTools } from './src/tools/openclaw-workclaw-cron/index.js';
2
+ //# sourceMappingURL=tools-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools-api.d.ts","sourceRoot":"","sources":["../tools-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oCAAoC,IAAI,qBAAqB,EAAE,MAAM,6CAA6C,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { r } from "./index-DLeHpawu.js";
2
+ export {
3
+ r as registerWorkclawTools
4
+ };
@@ -0,0 +1,5 @@
1
+ import { ao, ap } from "./channel-CWeiUgV5.js";
2
+ export {
3
+ ao as appendAssistantMessageToSessionTranscript,
4
+ ap as appendExactAssistantMessageToSessionTranscript
5
+ };
@@ -0,0 +1,538 @@
1
+ import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-DyL154ka-BEV0SzzS.js";
2
+ import { g as getWorkclawConnectionConfig, l as logger } from "./runtime-api-DU-e2Pen.js";
3
+ import { Agent, fetch } from "undici";
4
+ const BLOCKED_OBJECT_KEYS = /* @__PURE__ */ new Set([
5
+ "__proto__",
6
+ "prototype",
7
+ "constructor"
8
+ ]);
9
+ function isBlockedObjectKey(key) {
10
+ return BLOCKED_OBJECT_KEYS.has(key);
11
+ }
12
+ const DEFAULT_ACCOUNT_ID = "default";
13
+ const VALID_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
14
+ const INVALID_CHARS_RE = /[^a-z0-9_-]+/g;
15
+ const LEADING_DASH_RE = /^-+/;
16
+ const TRAILING_DASH_RE = /-+$/;
17
+ const ACCOUNT_ID_CACHE_MAX = 512;
18
+ const normalizeAccountIdCache = /* @__PURE__ */ new Map();
19
+ const normalizeOptionalAccountIdCache = /* @__PURE__ */ new Map();
20
+ function canonicalizeAccountId(value) {
21
+ const normalized = normalizeLowercaseStringOrEmpty(value);
22
+ if (VALID_ID_RE.test(value)) return normalized;
23
+ return normalized.replace(INVALID_CHARS_RE, "-").replace(LEADING_DASH_RE, "").replace(TRAILING_DASH_RE, "").slice(0, 64);
24
+ }
25
+ function normalizeCanonicalAccountId(value) {
26
+ const canonical = canonicalizeAccountId(value);
27
+ if (!canonical || isBlockedObjectKey(canonical)) return;
28
+ return canonical;
29
+ }
30
+ function normalizeAccountId$1(value) {
31
+ const trimmed = (value ?? "").trim();
32
+ if (!trimmed) return DEFAULT_ACCOUNT_ID;
33
+ const cached = normalizeAccountIdCache.get(trimmed);
34
+ if (cached) return cached;
35
+ const normalized = normalizeCanonicalAccountId(trimmed) || "default";
36
+ setNormalizeCache(normalizeAccountIdCache, trimmed, normalized);
37
+ return normalized;
38
+ }
39
+ function normalizeOptionalAccountId(value) {
40
+ const trimmed = (value ?? "").trim();
41
+ if (!trimmed) return;
42
+ if (normalizeOptionalAccountIdCache.has(trimmed)) return normalizeOptionalAccountIdCache.get(trimmed);
43
+ const normalized = normalizeCanonicalAccountId(trimmed) || void 0;
44
+ setNormalizeCache(normalizeOptionalAccountIdCache, trimmed, normalized);
45
+ return normalized;
46
+ }
47
+ function setNormalizeCache(cache, key, value) {
48
+ cache.set(key, value);
49
+ if (cache.size <= ACCOUNT_ID_CACHE_MAX) return;
50
+ const oldest = cache.keys().next();
51
+ if (!oldest.done) cache.delete(oldest.value);
52
+ }
53
+ function normalizeAccountId(accountId) {
54
+ return String(accountId ?? "").trim();
55
+ }
56
+ function makeLookupKey(userId, agentId) {
57
+ return `${userId}|${agentId}`;
58
+ }
59
+ const lookupCache = /* @__PURE__ */ new Map();
60
+ const accountIndex = /* @__PURE__ */ new Map();
61
+ let nextWorkspaceNum = 1;
62
+ function buildAccountMap(cfg) {
63
+ lookupCache.clear();
64
+ accountIndex.clear();
65
+ nextWorkspaceNum = 1;
66
+ const _WorkclawConfig = cfg.channels?.["openclaw-workclaw"] || {};
67
+ const accounts = _WorkclawConfig?.accounts;
68
+ if (!accounts || typeof accounts !== "object")
69
+ return;
70
+ for (const [accountId, accountCfg] of Object.entries(accounts)) {
71
+ if (!accountCfg)
72
+ continue;
73
+ const cfg2 = accountCfg;
74
+ const userId = cfg2.userId || _WorkclawConfig.userId;
75
+ const agentId = cfg2.agentId;
76
+ if (!agentId)
77
+ continue;
78
+ if (userId) {
79
+ const key = makeLookupKey(String(userId), String(agentId));
80
+ lookupCache.set(key, accountId);
81
+ }
82
+ accountIndex.set(accountId, { userId: String(userId ?? ""), agentId: String(agentId) });
83
+ if (accountId.startsWith("workspace-")) {
84
+ const num = Number.parseInt(accountId.slice(accountId.lastIndexOf("-") + 1), 10);
85
+ if (!Number.isNaN(num) && num >= nextWorkspaceNum) {
86
+ nextWorkspaceNum = num + 1;
87
+ }
88
+ }
89
+ }
90
+ if (!accountIndex.has(DEFAULT_ACCOUNT_ID) && _WorkclawConfig.userId && _WorkclawConfig.agentId) {
91
+ const userId = String(_WorkclawConfig.userId);
92
+ const agentId = String(_WorkclawConfig.agentId);
93
+ const key = makeLookupKey(userId, agentId);
94
+ lookupCache.set(key, DEFAULT_ACCOUNT_ID);
95
+ accountIndex.set(DEFAULT_ACCOUNT_ID, { userId, agentId });
96
+ }
97
+ logger.info(`【智小途-账户】已构建账户映射表,共 ${lookupCache.size} 条记录,下一个工作区编号=${nextWorkspaceNum}`);
98
+ }
99
+ function resolveAccountByUserIdAndAgentId(cfg, userId, agentId) {
100
+ const key = makeLookupKey(userId, agentId);
101
+ if (lookupCache.has(key)) {
102
+ return lookupCache.get(key);
103
+ }
104
+ const _WorkclawConfig = cfg.channels?.["openclaw-workclaw"] || {};
105
+ const accounts = _WorkclawConfig?.accounts;
106
+ if (accounts && typeof accounts === "object") {
107
+ for (const [accountId, accountCfg] of Object.entries(accounts)) {
108
+ if (!accountCfg)
109
+ continue;
110
+ const cfg2 = accountCfg;
111
+ const accountUserId = cfg2.userId || _WorkclawConfig.userId;
112
+ if (String(accountUserId) === userId && String(cfg2.agentId) === agentId) {
113
+ lookupCache.set(key, accountId);
114
+ accountIndex.set(accountId, { userId, agentId });
115
+ return accountId;
116
+ }
117
+ }
118
+ }
119
+ if (String(_WorkclawConfig.userId ?? "") === userId && String(_WorkclawConfig.agentId ?? "") === agentId) {
120
+ lookupCache.set(key, DEFAULT_ACCOUNT_ID);
121
+ accountIndex.set(DEFAULT_ACCOUNT_ID, { userId, agentId });
122
+ return DEFAULT_ACCOUNT_ID;
123
+ }
124
+ return null;
125
+ }
126
+ function allocateWorkerAccountId(_cfg, userId, agentId) {
127
+ const accountId = `workspace-${nextWorkspaceNum}`;
128
+ nextWorkspaceNum++;
129
+ const key = makeLookupKey(userId, agentId);
130
+ lookupCache.set(key, accountId);
131
+ accountIndex.set(accountId, { userId, agentId });
132
+ logger.info(`【智小途-账户】已分配账户ID=${accountId} 用于 userId=${userId} agentId=${agentId}`);
133
+ return accountId;
134
+ }
135
+ function refreshAccountCache(cfg) {
136
+ buildAccountMap(cfg);
137
+ }
138
+ function listConfiguredAccountIds(cfg) {
139
+ const accounts = cfg.channels?.["openclaw-workclaw"]?.accounts;
140
+ if (!accounts || typeof accounts !== "object") {
141
+ return [];
142
+ }
143
+ return Object.keys(accounts).filter(Boolean);
144
+ }
145
+ function hasPluginLevelWorkClawConfig(cfg) {
146
+ const workclawCfg = cfg.channels?.["openclaw-workclaw"];
147
+ const key = typeof workclawCfg?.appKey === "string" ? workclawCfg.appKey.trim() : "";
148
+ const secret = typeof workclawCfg?.appSecret === "string" ? workclawCfg.appSecret.trim() : "";
149
+ return Boolean(key && secret);
150
+ }
151
+ function listWorkclawAccountIds(cfg) {
152
+ const ids = listConfiguredAccountIds(cfg);
153
+ if (ids.length === 0) {
154
+ if (hasPluginLevelWorkClawConfig(cfg)) {
155
+ return [DEFAULT_ACCOUNT_ID];
156
+ }
157
+ return [DEFAULT_ACCOUNT_ID];
158
+ }
159
+ return [...ids].toSorted((a, b) => a.localeCompare(b));
160
+ }
161
+ function resolveDefaultWorkclawAccountId(cfg) {
162
+ const ids = listWorkclawAccountIds(cfg);
163
+ if (ids.includes(DEFAULT_ACCOUNT_ID)) {
164
+ return DEFAULT_ACCOUNT_ID;
165
+ }
166
+ return ids[0] ?? DEFAULT_ACCOUNT_ID;
167
+ }
168
+ function resolveAccountConfig(cfg, accountId) {
169
+ const accounts = cfg.channels?.["openclaw-workclaw"]?.accounts;
170
+ if (!accounts || typeof accounts !== "object") {
171
+ return void 0;
172
+ }
173
+ return accounts[accountId];
174
+ }
175
+ function hasWorkClawConfig(config) {
176
+ const key = typeof config.appKey === "string" ? config.appKey.trim() : "";
177
+ const secret = typeof config.appSecret === "string" ? config.appSecret.trim() : "";
178
+ return Boolean(key && secret);
179
+ }
180
+ function isWorkclawAccountConfigured(config) {
181
+ return hasWorkClawConfig(config);
182
+ }
183
+ function mergeWorkclawAccountConfig(cfg, accountId) {
184
+ const workclawCfg = cfg.channels?.["openclaw-workclaw"];
185
+ const { accounts: _ignored, ...base } = workclawCfg ?? {};
186
+ const account = resolveAccountConfig(cfg, accountId) ?? {};
187
+ return { ...base, ...account };
188
+ }
189
+ function resolveWorkclawAccount(params) {
190
+ const accountId = normalizeAccountId(params.accountId);
191
+ const workclawCfg = params.cfg.channels?.["openclaw-workclaw"];
192
+ const baseEnabled = workclawCfg?.enabled !== false;
193
+ const merged = mergeWorkclawAccountConfig(params.cfg, accountId);
194
+ const accountEnabled = merged.enabled !== false;
195
+ const enabled = baseEnabled && accountEnabled;
196
+ return {
197
+ accountId,
198
+ enabled,
199
+ configured: isWorkclawAccountConfigured(merged),
200
+ name: merged.name?.trim() || void 0,
201
+ config: merged
202
+ };
203
+ }
204
+ function resolveWorkclawAccountWithCache(params) {
205
+ const account = resolveWorkclawAccount(params);
206
+ const cachedConfig = getWorkclawConnectionConfig(account.accountId);
207
+ if (cachedConfig) {
208
+ account.config.appKey = cachedConfig.appKey || account.config.appKey;
209
+ account.config.appSecret = cachedConfig.appSecret || account.config.appSecret;
210
+ if (cachedConfig.baseUrl)
211
+ account.config.baseUrl = cachedConfig.baseUrl;
212
+ if (cachedConfig.websocketUrl !== void 0)
213
+ account.config.websocketUrl = cachedConfig.websocketUrl;
214
+ if (cachedConfig.localIp !== void 0)
215
+ account.config.localIp = cachedConfig.localIp;
216
+ if (cachedConfig.allowInsecureTls !== void 0)
217
+ account.config.allowInsecureTls = cachedConfig.allowInsecureTls;
218
+ if (cachedConfig.requestTimeout !== void 0)
219
+ account.config.requestTimeout = cachedConfig.requestTimeout;
220
+ }
221
+ return account;
222
+ }
223
+ function inspectWorkclawCredentials(workclawCfg) {
224
+ const appKey = typeof workclawCfg?.appKey === "string" ? workclawCfg.appKey.trim() : "";
225
+ const appSecret = typeof workclawCfg?.appSecret === "string" ? workclawCfg.appSecret.trim() : "";
226
+ if (!appKey || !appSecret) {
227
+ return null;
228
+ }
229
+ return async () => {
230
+ try {
231
+ return { ok: true };
232
+ } catch {
233
+ return { ok: false };
234
+ }
235
+ };
236
+ }
237
+ const tokenCache = /* @__PURE__ */ new Map();
238
+ function clearWorkclawTokenCache(cacheKey) {
239
+ tokenCache.delete(cacheKey);
240
+ }
241
+ function normalizeBaseUrl(value) {
242
+ const raw = (value || "https://workbrain.cn/backend-api").trim();
243
+ return raw.endsWith("/") ? raw.slice(0, -1) : raw;
244
+ }
245
+ function createWsEndpoint(baseUrl) {
246
+ const wsBase = baseUrl.replace(/^https?:\/\//i, (match) => match.toLowerCase() === "https://" ? "wss://" : "ws://");
247
+ return `${wsBase}/v1/ws/connect`;
248
+ }
249
+ async function doFetchJson(url, init, allowInsecureTls, requestTimeout) {
250
+ const dispatcher = allowInsecureTls ? new Agent({ connect: { rejectUnauthorized: false } }) : void 0;
251
+ const fetcher = allowInsecureTls ? fetch : globalThis.fetch;
252
+ const controller = new AbortController();
253
+ const timeoutMs = typeof requestTimeout === "number" && requestTimeout > 0 ? requestTimeout : 3e4;
254
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
255
+ logger.info(`【智小途-HTTP】请求 method=${init.method || "GET"} url=${url}`);
256
+ logger.info(`【智小途-HTTP】请求头: ${JSON.stringify(init.headers || {})}`);
257
+ if (init.body) {
258
+ logger.info(`【智小途-HTTP】请求体: ${String(init.body)}`);
259
+ }
260
+ let response;
261
+ let text = "";
262
+ try {
263
+ response = await fetcher(url, {
264
+ ...init,
265
+ signal: controller.signal,
266
+ ...dispatcher ? { dispatcher } : {}
267
+ });
268
+ text = await response.text().catch(() => "");
269
+ } finally {
270
+ clearTimeout(timeoutId);
271
+ }
272
+ logger.info(`【智小途-HTTP】响应 status=${response?.status} url=${url}`);
273
+ logger.info(`【智小途-HTTP】响应体: ${text}`);
274
+ let data = {};
275
+ if (text) {
276
+ try {
277
+ data = JSON.parse(text);
278
+ } catch {
279
+ data = {};
280
+ }
281
+ }
282
+ if (!response.ok) {
283
+ const message = data?.message || text || `HTTP ${response.status}`;
284
+ throw new Error(message);
285
+ }
286
+ return data;
287
+ }
288
+ async function fetchAccessTokenFromServer(requestUrl, config) {
289
+ logger.info(
290
+ `【智小途-连接】正在请求访问令牌 url=${requestUrl} appKey前缀=${String(config.appKey)}... appSecret长度=${String(config.appSecret)}`
291
+ );
292
+ const data = await doFetchJson(
293
+ requestUrl,
294
+ {
295
+ method: "POST",
296
+ headers: { "Content-Type": "application/json" },
297
+ body: JSON.stringify({
298
+ app_key: config.appKey,
299
+ app_secret: config.appSecret
300
+ })
301
+ },
302
+ config.allowInsecureTls,
303
+ config.requestTimeout
304
+ );
305
+ logger.info(
306
+ `【智小途-连接】访问令牌响应 code=${String(data?.code ?? "")} errCode=${String(data?.errCode ?? "")} errMsg=${String(data?.errMsg ?? data?.message ?? "")}`
307
+ );
308
+ if (data?.code !== 200 || !data?.data?.accessToken) {
309
+ throw new Error(
310
+ String(data?.message || data?.errMsg || "Failed to acquire access token")
311
+ );
312
+ }
313
+ const token = String(data.data.accessToken);
314
+ const expiresIn = Number(data.data.expiresIn || 0);
315
+ const expiresAt = Date.now() + (expiresIn > 0 ? expiresIn * 1e3 : 0);
316
+ logger.info(
317
+ `【智小途-连接】访问令牌获取成功 token长度=${token.length} 有效期秒=${expiresIn} 过期时间=${new Date(expiresAt).toISOString()}`
318
+ );
319
+ return { token, expiresAt };
320
+ }
321
+ async function getWorkclawAccessToken(cacheKey, config) {
322
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
323
+ const requestUrl = `${baseUrl}/authen/v1/access_token/internal`;
324
+ typeof config.requestTimeout === "number" && config.requestTimeout > 0 ? config.requestTimeout : 3e4;
325
+ try {
326
+ const cached = tokenCache.get(cacheKey);
327
+ if (cached && cached.token) {
328
+ const now = Date.now();
329
+ const refreshAt = cached.expiresAt - 5 * 60 * 1e3;
330
+ if (now < refreshAt) {
331
+ return cached.token;
332
+ }
333
+ logger.info(`【智小途-令牌】需要刷新缓存 cacheKey=${cacheKey}`);
334
+ }
335
+ if (!config.appKey || !config.appSecret) {
336
+ logger.error(`【智小途-令牌】缺少 appKey/appSecret`);
337
+ throw new Error("Missing appKey/appSecret");
338
+ }
339
+ const result = await fetchAccessTokenFromServer(requestUrl, config);
340
+ tokenCache.set(cacheKey, { token: result.token, expiresAt: result.expiresAt });
341
+ logger.info(`【智小途-令牌】已刷新缓存 cacheKey=${cacheKey}`);
342
+ return result.token;
343
+ } catch (error) {
344
+ logger.error(`【智小途-令牌】获取令牌失败 cacheKey=${cacheKey} 错误=${String(error)}`);
345
+ throw error;
346
+ }
347
+ }
348
+ async function openWorkclawConnection(cacheKey, config) {
349
+ const startedAt = Date.now();
350
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
351
+ const requestUrl = `${baseUrl}/open-apis/v1/connections/open`;
352
+ const timeoutMs = typeof config.requestTimeout === "number" && config.requestTimeout > 0 ? config.requestTimeout : 3e4;
353
+ const appKeyRaw = String(config.appKey ?? "");
354
+ const appSecretRaw = String(config.appSecret ?? "");
355
+ logger.info(
356
+ `【智小途-连接】打开Workclaw连接开始 cacheKey=${cacheKey} baseUrl=${baseUrl} requestUrl=${requestUrl} allowInsecureTls=${Boolean(config.allowInsecureTls)} timeoutMs=${timeoutMs} localIp=${String(config.localIp ?? "")} websocketUrl=${String(config.websocketUrl ?? "")} appKey前缀=${appKeyRaw ? `${appKeyRaw.slice(0, 8)}...` : "缺失"} appSecret长度=${appSecretRaw.length}`
357
+ );
358
+ const tokenStartedAt = Date.now();
359
+ const token = await getWorkclawAccessToken(cacheKey, config);
360
+ logger.info(
361
+ `【智小途-连接】打开Workclaw连接获取访问令牌 cacheKey=${cacheKey} token长度=${token.length} 耗时=${Date.now() - tokenStartedAt}ms`
362
+ );
363
+ const payload = {
364
+ appKey: config.appKey,
365
+ appSecret: config.appSecret,
366
+ subscriptions: [
367
+ { type: "CALLBACK", topic: "AGENT_MESSAGE" },
368
+ { type: "EVENT", topic: "*" },
369
+ { type: "SYSTEM", topic: "*" }
370
+ ],
371
+ ...config.localIp ? { localIp: config.localIp } : {}
372
+ };
373
+ logger.info(
374
+ `【智小途-连接】正在打开连接 url=${requestUrl} cacheKey=${cacheKey} 订阅数量=${payload.subscriptions.length}`
375
+ );
376
+ const data = await doFetchJson(
377
+ requestUrl,
378
+ {
379
+ method: "POST",
380
+ headers: {
381
+ "Content-Type": "application/json",
382
+ "Authorization": `Bearer ${token}`
383
+ },
384
+ body: JSON.stringify(payload)
385
+ },
386
+ config.allowInsecureTls,
387
+ config.requestTimeout
388
+ );
389
+ logger.info(
390
+ `【智小途-连接】打开连接响应 code=${String(data?.code ?? "")} errCode=${String(data?.errCode ?? "")} errMsg=${String(data?.errMsg ?? data?.message ?? "")} 有ticket=${Boolean(data?.data?.ticket)} 有endpoint=${Boolean(data?.data?.endpoint)}`
391
+ );
392
+ if (data?.code !== 200 || !data?.data?.ticket) {
393
+ throw new Error(String(data?.message || data?.errMsg || "Failed to open connection"));
394
+ }
395
+ const ticket = String(data.data.ticket);
396
+ let endpointSource = "derived";
397
+ const endpoint = config.websocketUrl ? (endpointSource = "config", String(config.websocketUrl)) : data?.data?.endpoint ? (endpointSource = "api", String(data.data.endpoint)) : (endpointSource = "derived", createWsEndpoint(baseUrl));
398
+ logger.info(
399
+ `【智小途-连接】打开Workclaw连接成功 cacheKey=${cacheKey} endpoint=${endpoint} endpoint来源=${endpointSource} ticket长度=${ticket.length} 总耗时=${Date.now() - startedAt}ms`
400
+ );
401
+ return { endpoint, ticket };
402
+ }
403
+ async function sendWorkclawMessage(params) {
404
+ const baseUrl = normalizeBaseUrl(params.config.baseUrl);
405
+ const token = await getWorkclawAccessToken(params.cacheKey, params.config);
406
+ const payload = {
407
+ agentId: params.agentId,
408
+ receiveId: params.receiveId,
409
+ msgType: params.msgType,
410
+ content: params.content
411
+ };
412
+ if (params.last === true) {
413
+ payload.is_last = true;
414
+ }
415
+ if (params.openConversationId) {
416
+ payload.conversationId = params.openConversationId;
417
+ }
418
+ const endpoint = params.endpoint || "/open-apis/im/v1/messages";
419
+ logger.info(`【智小途-API】正在发送主动消息到 ${baseUrl}${endpoint}`);
420
+ logger.info(`【智小途-API】请求参数: ${JSON.stringify(payload, null, 2)}`);
421
+ const data = await doFetchJson(
422
+ `${baseUrl}${endpoint}`,
423
+ {
424
+ method: "POST",
425
+ headers: {
426
+ "Content-Type": "application/json",
427
+ "Authorization": `Bearer ${token}`
428
+ },
429
+ body: JSON.stringify(payload)
430
+ },
431
+ params.config.allowInsecureTls,
432
+ params.config.requestTimeout
433
+ );
434
+ logger.info(`【智小途-API】发送消息响应: ${JSON.stringify(data, null, 2)}`);
435
+ if (data?.code !== 200 || !data?.data?.msgId) {
436
+ throw new Error(data?.message || "Failed to send message");
437
+ }
438
+ return String(data.data.msgId);
439
+ }
440
+ async function sendWorkclawReplyMessage(params) {
441
+ const baseUrl = normalizeBaseUrl(params.config.baseUrl);
442
+ const token = await getWorkclawAccessToken(params.cacheKey, params.config);
443
+ const payload = {
444
+ agentId: params.agentId,
445
+ receiveId: params.receiveId,
446
+ msgType: params.msgType,
447
+ content: params.content
448
+ };
449
+ if (params.last === true) {
450
+ payload.is_last = true;
451
+ }
452
+ if (params.openConversationId) {
453
+ payload.conversationId = params.openConversationId;
454
+ }
455
+ const endpoint = params.endpoint || `/open-apis/im/v1/messages/${params.messageId}/reply`;
456
+ logger.info(`【智小途-发送】来源=${params.source || "?"} last=${params.last} 会话=${params.openConversationId || "(无)"} msgId=${params.messageId}`);
457
+ const data = await doFetchJson(
458
+ `${baseUrl}${endpoint}`,
459
+ {
460
+ method: "POST",
461
+ headers: {
462
+ "Content-Type": "application/json",
463
+ "Authorization": `Bearer ${token}`
464
+ },
465
+ body: JSON.stringify(payload)
466
+ },
467
+ params.config.allowInsecureTls,
468
+ params.config.requestTimeout
469
+ );
470
+ logger.info(`【智小途-发送】完成 msgId=${data?.data?.msgId} code=${data?.code}`);
471
+ if (data?.code !== 200 || !data?.data?.msgId) {
472
+ throw new Error(data?.message || "Failed to send reply");
473
+ }
474
+ return String(data.data.msgId);
475
+ }
476
+ function resolveWorkclawMessage(text, mediaUrl) {
477
+ if (!mediaUrl || text.trim()) {
478
+ return { msgType: "text", content: text };
479
+ }
480
+ const url = mediaUrl.trim();
481
+ const lower = url.toLowerCase();
482
+ const isAudio = lower.endsWith(".mp3") || lower.endsWith(".wav") || lower.endsWith(".aac") || lower.endsWith(".m4a") || lower.endsWith(".ogg");
483
+ const payload = JSON.stringify({ url });
484
+ return { msgType: isAudio ? "audio" : "image", content: payload };
485
+ }
486
+ async function getWorkclawModelConfigByAppKey(cacheKey, config) {
487
+ const baseUrl = normalizeBaseUrl(config.baseUrl);
488
+ const token = await getWorkclawAccessToken(cacheKey, config);
489
+ const appKey = config.appKey;
490
+ if (!appKey) {
491
+ throw new Error("Missing appKey for getModelKeyByAppKey");
492
+ }
493
+ const requestUrl = `${baseUrl}/open-apis/instance/apiKey/${appKey}`;
494
+ logger.info(`【智小途-API】正在获取模型配置 ${requestUrl}`);
495
+ const data = await doFetchJson(
496
+ requestUrl,
497
+ {
498
+ method: "GET",
499
+ headers: {
500
+ "Content-Type": "x-www-form-urlencoded",
501
+ "Authorization": `Bearer ${token}`
502
+ }
503
+ },
504
+ config.allowInsecureTls,
505
+ config.requestTimeout
506
+ );
507
+ logger.info(`【智小途-API】模型配置响应: ${JSON.stringify(data, null, 2)}`);
508
+ if (data?.code !== 200 || !data?.data) {
509
+ throw new Error(data?.message || data?.msg || "Failed to get model key");
510
+ }
511
+ return data.data;
512
+ }
513
+ export {
514
+ DEFAULT_ACCOUNT_ID as D,
515
+ resolveWorkclawMessage as a,
516
+ sendWorkclawMessage as b,
517
+ resolveWorkclawAccountWithCache as c,
518
+ doFetchJson as d,
519
+ resolveAccountByUserIdAndAgentId as e,
520
+ isBlockedObjectKey as f,
521
+ normalizeBaseUrl as g,
522
+ getWorkclawAccessToken as h,
523
+ inspectWorkclawCredentials as i,
524
+ normalizeOptionalAccountId as j,
525
+ normalizeAccountId$1 as k,
526
+ refreshAccountCache as l,
527
+ allocateWorkerAccountId as m,
528
+ normalizeAccountId as n,
529
+ getWorkclawModelConfigByAppKey as o,
530
+ clearWorkclawTokenCache as p,
531
+ openWorkclawConnection as q,
532
+ resolveDefaultWorkclawAccountId as r,
533
+ sendWorkclawReplyMessage as s,
534
+ buildAccountMap as t,
535
+ isWorkclawAccountConfigured as u,
536
+ resolveWorkclawAccount as v,
537
+ listWorkclawAccountIds as w
538
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@workclaw/openclaw-workclaw",
3
3
  "type": "module",
4
- "version": "1.0.342",
4
+ "version": "1.0.343",
5
5
  "description": "智小途企业通讯平台 OpenClaw 渠道插件",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -22,6 +22,10 @@
22
22
  "./setup": {
23
23
  "types": "./dist/setup-entry.d.ts",
24
24
  "import": "./dist/setup-entry.js"
25
+ },
26
+ "./tools-api": {
27
+ "types": "./dist/tools-api.d.ts",
28
+ "import": "./dist/tools-api.js"
25
29
  }
26
30
  },
27
31
  "main": "./dist/index.js",
@@ -51,12 +55,12 @@
51
55
  ],
52
56
  "setupEntry": "./dist/setup-entry.js",
53
57
  "compat": {
54
- "pluginApi": "2026.5.22",
55
- "minGatewayVersion": "2026.5.22"
58
+ "pluginApi": ">=2026.6.2",
59
+ "minGatewayVersion": "2026.6.2"
56
60
  },
57
61
  "build": {
58
- "openclawVersion": "2026.5.22",
59
- "pluginSdkVersion": "2026.5.22"
62
+ "openclawVersion": "2026.6.2",
63
+ "pluginSdkVersion": "2026.6.2"
60
64
  },
61
65
  "install": {
62
66
  "npmSpec": "@workclaw/openclaw-workclaw",
@@ -1,5 +0,0 @@
1
- import { ap, aq } from "./index-ZWLWkJXc.js";
2
- export {
3
- ap as bootstrapOutboundChannelPlugin,
4
- aq as resetOutboundChannelBootstrapStateForTests
5
- };