@wps365/openclaw-wpsxiezuo 1.11.0 → 1.11.2-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/bin/cli.mjs +48 -94
- package/dist/core/config.d.ts +6 -0
- package/dist/core/delegated-scope-refresh.d.ts +24 -0
- package/dist/core/errors.d.ts +2 -0
- package/dist/core/index.d.ts +6 -2
- package/dist/core/scope-checker.d.ts +36 -0
- package/dist/core/scope-persist.d.ts +15 -0
- package/dist/core/tool-scopes.d.ts +11 -0
- package/dist/core/user-token-store.d.ts +8 -0
- package/dist/index.js +24 -23
- package/dist/messaging/synthetic-message.d.ts +20 -0
- package/dist/tools/oapi/auth-card-cooldown.d.ts +17 -4
- package/dist/tools/oapi/delegated-auth.d.ts +9 -3
- package/dist/tools/oauth/index.d.ts +4 -0
- package/package.json +2 -1
- package/scripts/lib/openclaw-cleanup.mjs +129 -0
- package/scripts/lib/openclaw-config-core.mjs +186 -0
package/bin/cli.mjs
CHANGED
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
* 设计目标:
|
|
11
11
|
* 1. 纯 Node.js(无外部依赖),全平台可用(macOS / Linux / Windows)。
|
|
12
12
|
* 2. 复用项目原 install.sh 的策略:清理历史残留 → 注册插件 → 写入 channel/
|
|
13
|
+
*
|
|
14
|
+
* 配置操作的核心逻辑已提取到 scripts/lib/openclaw-config-core.mjs,
|
|
15
|
+
* 本文件及 scripts/install.js, scripts/uninstall.js, tests/ 共享同一份实现。
|
|
13
16
|
* plugins/bindings → 校验 openclaw.json。
|
|
14
17
|
*/
|
|
15
18
|
|
|
@@ -27,6 +30,16 @@ import path from "node:path";
|
|
|
27
30
|
import readline from "node:readline/promises";
|
|
28
31
|
import { createRequire } from "node:module";
|
|
29
32
|
import { fileURLToPath } from "node:url";
|
|
33
|
+
import {
|
|
34
|
+
CHANNEL_ID as _CH_ID,
|
|
35
|
+
LEGACY_CHANNEL_IDS as _LEGACY_IDS,
|
|
36
|
+
ALL_IDS as _ALL_IDS,
|
|
37
|
+
DEFAULT_BASE_URL as _DEFAULT_BASE_URL,
|
|
38
|
+
pruneOpenclawJson as corePrune,
|
|
39
|
+
mergeChannelConfig as coreMergeChannel,
|
|
40
|
+
ensurePluginsAndBindings as coreEnsurePlugins,
|
|
41
|
+
pruneSessionsData as corePruneSessions,
|
|
42
|
+
} from "../scripts/lib/openclaw-config-core.mjs";
|
|
30
43
|
|
|
31
44
|
// 通过 createRequire + 拼接字符串加载子进程模块
|
|
32
45
|
// 对静态 import 的启发式匹配。本 CLI 必须调用系统的 `openclaw`
|
|
@@ -42,14 +55,14 @@ function env(name) {
|
|
|
42
55
|
return p && p["env"] ? p["env"][name] : undefined;
|
|
43
56
|
}
|
|
44
57
|
|
|
45
|
-
// ──
|
|
58
|
+
// ── 常量(核心常量来自 shared core,本地仅补充 CLI 专用常量)──────────────
|
|
46
59
|
|
|
47
|
-
const CHANNEL_ID =
|
|
48
|
-
const LEGACY_CHANNEL_IDS =
|
|
49
|
-
const ALL_IDS =
|
|
60
|
+
const CHANNEL_ID = _CH_ID;
|
|
61
|
+
const LEGACY_CHANNEL_IDS = _LEGACY_IDS;
|
|
62
|
+
const ALL_IDS = _ALL_IDS;
|
|
50
63
|
const UNINSTALL_IDS = [CHANNEL_ID];
|
|
51
|
-
const DEFAULT_BASE_URL =
|
|
52
|
-
const DEFAULT_AGENT_ID = "
|
|
64
|
+
const DEFAULT_BASE_URL = _DEFAULT_BASE_URL;
|
|
65
|
+
const DEFAULT_AGENT_ID = "main";
|
|
53
66
|
const OPENCLAW_HOME = path.join(os.homedir(), ".openclaw");
|
|
54
67
|
const OPENCLAW_JSON = path.join(OPENCLAW_HOME, "openclaw.json");
|
|
55
68
|
const OPENCLAW_EXTENSIONS_DIR = path.join(OPENCLAW_HOME, "extensions");
|
|
@@ -170,19 +183,6 @@ function writeJson(filePath, data) {
|
|
|
170
183
|
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
171
184
|
}
|
|
172
185
|
|
|
173
|
-
/** 从 map 上按 id 列表删除 key,返回是否有改动。 */
|
|
174
|
-
function pruneMapByIds(map, ids) {
|
|
175
|
-
if (!map || typeof map !== "object") return false;
|
|
176
|
-
let changed = false;
|
|
177
|
-
for (const id of ids) {
|
|
178
|
-
if (id in map) {
|
|
179
|
-
delete map[id];
|
|
180
|
-
changed = true;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return changed;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
186
|
function which(cmd) {
|
|
187
187
|
const exts = process.platform === "win32" ? (env("PATHEXT") || ".EXE;.CMD;.BAT").split(";") : [""];
|
|
188
188
|
const dirs = (env("PATH") || "").split(path.delimiter);
|
|
@@ -376,47 +376,21 @@ function readSecret(rl) {
|
|
|
376
376
|
|
|
377
377
|
// ── 核心:清理旧配置 ────────────────────────────────────────────────────────
|
|
378
378
|
|
|
379
|
-
function pruneOpenclawJson() {
|
|
379
|
+
function pruneOpenclawJson({ includeCurrent = false } = {}) {
|
|
380
380
|
const cfg = readJsonSafe(OPENCLAW_JSON);
|
|
381
381
|
if (!cfg) return;
|
|
382
|
-
|
|
383
|
-
let dirty = false;
|
|
384
|
-
dirty = pruneMapByIds(cfg.channels, ALL_IDS) || dirty;
|
|
385
|
-
dirty = pruneMapByIds(cfg.plugins?.entries, ALL_IDS) || dirty;
|
|
386
|
-
dirty = pruneMapByIds(cfg.plugins?.installs, ALL_IDS) || dirty;
|
|
387
|
-
|
|
388
|
-
if (Array.isArray(cfg.plugins?.allow)) {
|
|
389
|
-
const before = cfg.plugins.allow.length;
|
|
390
|
-
cfg.plugins.allow = cfg.plugins.allow.filter((x) => !ALL_IDS.includes(String(x)));
|
|
391
|
-
if (cfg.plugins.allow.length !== before) dirty = true;
|
|
392
|
-
}
|
|
393
|
-
|
|
382
|
+
const dirty = corePrune(cfg, { mode: includeCurrent ? "all" : "legacy" });
|
|
394
383
|
if (dirty) {
|
|
395
384
|
writeJson(OPENCLAW_JSON, cfg);
|
|
396
|
-
log.info(
|
|
385
|
+
log.info(includeCurrent
|
|
386
|
+
? "已清理 openclaw.json 中的所有 wps-xiezuo 配置"
|
|
387
|
+
: "已清理 openclaw.json 中的历史残留项(保留当前 wps-xiezuo 配置)");
|
|
397
388
|
}
|
|
398
389
|
}
|
|
399
390
|
|
|
400
391
|
function pruneOpenclawSessions() {
|
|
401
392
|
const data = readJsonSafe(SESSIONS_JSON);
|
|
402
|
-
|
|
403
|
-
const next = {};
|
|
404
|
-
let removed = 0;
|
|
405
|
-
for (const [key, value] of Object.entries(data)) {
|
|
406
|
-
const record = value && typeof value === "object" ? value : {};
|
|
407
|
-
const origin = record.origin && typeof record.origin === "object" ? record.origin : {};
|
|
408
|
-
const delivery = record.deliveryContext && typeof record.deliveryContext === "object" ? record.deliveryContext : {};
|
|
409
|
-
const hitByKey = /:wps-xiezuo:|:wps:/i.test(String(key));
|
|
410
|
-
const hitByProvider = String(origin.provider || "").toLowerCase() === CHANNEL_ID;
|
|
411
|
-
const hitByChannel =
|
|
412
|
-
String(record.lastChannel || "").toLowerCase() === CHANNEL_ID ||
|
|
413
|
-
String(delivery.channel || "").toLowerCase() === CHANNEL_ID;
|
|
414
|
-
if (hitByKey || hitByProvider || hitByChannel) {
|
|
415
|
-
removed++;
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
next[key] = value;
|
|
419
|
-
}
|
|
393
|
+
const { next, removed } = corePruneSessions(data);
|
|
420
394
|
if (removed > 0) {
|
|
421
395
|
writeJson(SESSIONS_JSON, next);
|
|
422
396
|
log.info(`已清理 sessions.json 中 ${removed} 条 wps/wps-xiezuo 残留会话`);
|
|
@@ -425,52 +399,32 @@ function pruneOpenclawSessions() {
|
|
|
425
399
|
|
|
426
400
|
// ── 核心:写入 channel / plugins / bindings ─────────────────────────────────
|
|
427
401
|
|
|
402
|
+
const CLI_MCP_DEFAULTS = {
|
|
403
|
+
enabled: true,
|
|
404
|
+
mode: "app",
|
|
405
|
+
toolAllowlist: [
|
|
406
|
+
"wps_message_send",
|
|
407
|
+
"wps_user_search",
|
|
408
|
+
"wps_user_get",
|
|
409
|
+
"wps_chat_list",
|
|
410
|
+
"wps_chat_create",
|
|
411
|
+
"wps_calendar_create",
|
|
412
|
+
"wps_calendar_list_events",
|
|
413
|
+
],
|
|
414
|
+
};
|
|
415
|
+
|
|
428
416
|
function writeChannelConfig({ appId, appSecret, baseUrl }) {
|
|
429
417
|
const cfg = readJsonSafe(OPENCLAW_JSON) ?? {};
|
|
430
418
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
baseUrl: baseUrl || DEFAULT_BASE_URL,
|
|
437
|
-
sdk: { enabled: true, logLevel: "info" },
|
|
438
|
-
mcp: {
|
|
439
|
-
enabled: true,
|
|
440
|
-
mode: "app",
|
|
441
|
-
toolAllowlist: [
|
|
442
|
-
"wps_message_send",
|
|
443
|
-
"wps_user_search",
|
|
444
|
-
"wps_user_get",
|
|
445
|
-
"wps_chat_list",
|
|
446
|
-
"wps_chat_create",
|
|
447
|
-
"wps_calendar_create",
|
|
448
|
-
"wps_calendar_list_events",
|
|
449
|
-
],
|
|
450
|
-
},
|
|
451
|
-
dmPolicy: "open",
|
|
452
|
-
groupPolicy: "open",
|
|
453
|
-
instantAck: { enabled: true, text: "内容处理中,请稍候..." },
|
|
454
|
-
};
|
|
455
|
-
|
|
456
|
-
if (!cfg.plugins || typeof cfg.plugins !== "object") cfg.plugins = {};
|
|
457
|
-
if (!cfg.plugins.entries || typeof cfg.plugins.entries !== "object") cfg.plugins.entries = {};
|
|
458
|
-
cfg.plugins.entries[CHANNEL_ID] = { enabled: true };
|
|
459
|
-
|
|
460
|
-
if (!Array.isArray(cfg.plugins.allow)) cfg.plugins.allow = [];
|
|
461
|
-
if (!cfg.plugins.allow.includes(CHANNEL_ID)) cfg.plugins.allow.push(CHANNEL_ID);
|
|
462
|
-
|
|
463
|
-
if (!Array.isArray(cfg.bindings)) cfg.bindings = [];
|
|
464
|
-
const hasBinding = cfg.bindings.some(
|
|
465
|
-
(b) => b && b.match && b.match.channel === CHANNEL_ID,
|
|
466
|
-
);
|
|
467
|
-
if (!hasBinding) {
|
|
468
|
-
cfg.bindings.push({
|
|
469
|
-
agentId: DEFAULT_AGENT_ID,
|
|
470
|
-
match: { channel: CHANNEL_ID, accountId: "default" },
|
|
471
|
-
});
|
|
419
|
+
const result = coreMergeChannel(cfg, { appId, appSecret, baseUrl }, { mcp: CLI_MCP_DEFAULTS });
|
|
420
|
+
if (result === "merged") {
|
|
421
|
+
log.info(`已合并更新 channels.${CHANNEL_ID}(保留用户自定义配置)`);
|
|
422
|
+
} else {
|
|
423
|
+
log.info(`已创建 channels.${CHANNEL_ID}(首次安装)`);
|
|
472
424
|
}
|
|
473
425
|
|
|
426
|
+
coreEnsurePlugins(cfg, { agentId: DEFAULT_AGENT_ID });
|
|
427
|
+
|
|
474
428
|
if (!cfg.commands) {
|
|
475
429
|
cfg.commands = { text: true };
|
|
476
430
|
log.info("commands.text=true 已启用(支持 /status /new 等内置命令)");
|
|
@@ -735,9 +689,9 @@ async function cmdUninstall(flags) {
|
|
|
735
689
|
}
|
|
736
690
|
}
|
|
737
691
|
|
|
738
|
-
// 步骤三:清理 openclaw.json 中的 channels / plugins / bindings
|
|
692
|
+
// 步骤三:清理 openclaw.json 中的 channels / plugins / bindings(卸载时清理全部)
|
|
739
693
|
log.step("清理 openclaw.json 配置残留");
|
|
740
|
-
pruneOpenclawJson();
|
|
694
|
+
pruneOpenclawJson({ includeCurrent: true });
|
|
741
695
|
|
|
742
696
|
// 步骤四:清理 sessions.json 中的 WPS 会话记录
|
|
743
697
|
log.step("清理 sessions 残留");
|
package/dist/core/config.d.ts
CHANGED
|
@@ -258,6 +258,12 @@ export type WebhookConfig = z.infer<typeof WebhookConfigSchema>;
|
|
|
258
258
|
/** 始终返回插件内置用户 OAuth 回调地址(忽略 channel 配置)。 */
|
|
259
259
|
export declare function resolveUserOAuthRedirectUri(_wpsCfg?: WpsConfig | null): string;
|
|
260
260
|
export declare function resolveDefaultWpsAccountId(cfg?: WpsChannelConfig): string;
|
|
261
|
+
/**
|
|
262
|
+
* 解析多账号配置。继承-覆盖模型:
|
|
263
|
+
* - 外层字段 = base config(公共默认值 + default 账号配置)
|
|
264
|
+
* - accounts 中各条目继承 base,用自身字段覆盖
|
|
265
|
+
* - accounts.default 作为迁移兼容:其字段合并到 base,然后被忽略
|
|
266
|
+
*/
|
|
261
267
|
export declare function resolveWpsAccounts(cfg?: WpsChannelConfig): Record<string, WpsConfig>;
|
|
262
268
|
export declare function resolveAppCredentials(cfg?: WpsConfig): AppCredentials | null;
|
|
263
269
|
export declare function resolveMcpCredentials(cfg?: WpsConfig): AppCredentials | null;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegated scopes 按需 TTL 缓存(对标飞书 30s 策略)。
|
|
3
|
+
*
|
|
4
|
+
* 只在工具调用时按需获取 App scopes,30 秒 TTL 缓存。
|
|
5
|
+
* 空闲时不产生任何 API 调用。
|
|
6
|
+
*
|
|
7
|
+
* 403 兜底路径可通过 invalidateDelegatedScopeCache 强制清除缓存,
|
|
8
|
+
* 下次调用立即重新获取。
|
|
9
|
+
*/
|
|
10
|
+
export declare function invalidateDelegatedScopeCache(accountId: string): void;
|
|
11
|
+
/** 标记缓存为新鲜(启动拉取后调用,避免 30s 内重复拉取) */
|
|
12
|
+
export declare function markDelegatedScopeCacheFresh(accountId: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* 确保 delegated scopes 在 TTL 内,过期则重新获取。
|
|
15
|
+
* 并发调用共享同一个 inflight promise,不重复请求。
|
|
16
|
+
*/
|
|
17
|
+
export declare function ensureDelegatedScopesFresh(accountId: string): Promise<void>;
|
|
18
|
+
/** @deprecated No longer needed — scopes are refreshed on demand */
|
|
19
|
+
export declare function startDelegatedScopeRefresh(_accountId: string): void;
|
|
20
|
+
/** @deprecated No longer needed — no background timer to stop */
|
|
21
|
+
export declare function stopDelegatedScopeRefresh(_accountId: string): void;
|
|
22
|
+
/** @deprecated No longer needed */
|
|
23
|
+
export declare function stopAllDelegatedScopeRefresh(): void;
|
|
24
|
+
//# sourceMappingURL=delegated-scope-refresh.d.ts.map
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -29,6 +29,8 @@ export declare class WpsTokenError extends Error {
|
|
|
29
29
|
readonly name = "WpsTokenError";
|
|
30
30
|
constructor(message: string, cause?: unknown | undefined);
|
|
31
31
|
}
|
|
32
|
+
export declare function isScopeRelatedError(err: unknown): boolean;
|
|
33
|
+
export declare function isTokenInvalidError(err: unknown): boolean;
|
|
32
34
|
export declare function httpStatusHint(status: number): {
|
|
33
35
|
hint: string;
|
|
34
36
|
retriable: boolean;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
* core/ 公共导出。
|
|
3
3
|
* 上层模块统一从 `@/core/index.js` 或具体文件导入。
|
|
4
4
|
*/
|
|
5
|
-
export { WpsRequestError, WpsTokenError, httpStatusHint } from "./errors.js";
|
|
5
|
+
export { WpsRequestError, WpsTokenError, httpStatusHint, isScopeRelatedError, isTokenInvalidError } from "./errors.js";
|
|
6
6
|
export type { WpsErrorStage, WpsErrorDetail } from "./errors.js";
|
|
7
|
+
export { checkScopes } from "./scope-checker.js";
|
|
8
|
+
export type { ScopeCheckResult } from "./scope-checker.js";
|
|
7
9
|
export { AppTokenStore, getAppTokenStore, clearAllTokenStores } from "./token-store.js";
|
|
8
10
|
export type { TokenEntry, AppCredentials } from "./token-store.js";
|
|
9
|
-
export { exchangeCodeForToken, putUserToken, getUserToken, takeUserToken, hasUserToken, setRefreshContext, restoreRefreshTimers } from "./user-token-store.js";
|
|
11
|
+
export { exchangeCodeForToken, putUserToken, getUserToken, getUserTokenEntry, clearGrantedScopes, deleteUserToken, takeUserToken, hasUserToken, setRefreshContext, restoreRefreshTimers } from "./user-token-store.js";
|
|
10
12
|
export type { UserTokenEntry, OAuthCodeExchangeParams } from "./user-token-store.js";
|
|
11
13
|
export { WpsClient, AppAuthProvider, UserAuthProvider, createWpsClient, createUserWpsClient } from "./wps-client.js";
|
|
12
14
|
export type { AuthProvider, WpsRequestOptions } from "./wps-client.js";
|
|
13
15
|
export { resolveDownloadUrl, resolveDownloadUrlOrThrow } from "./media-utils.js";
|
|
16
|
+
export { getModuleScopes, MODULE_SCOPES } from "./tool-scopes.js";
|
|
17
|
+
export type { ToolModule } from "./tool-scopes.js";
|
|
14
18
|
export { addThinkingReaction, removeThinkingReaction, REACTION_TYPE } from "./reaction.js";
|
|
15
19
|
export type { ThinkingIndicatorState } from "./reaction.js";
|
|
16
20
|
export { WpsConfigSchema, WpsChannelConfigSchema, DmPolicySchema, GroupConfigSchema, McpConfigSchema, InstantAckSchema, SdkConfigSchema, WebhookConfigSchema, resolveAppCredentials, resolveMcpCredentials, resolveDefaultWpsAccountId, resolveWpsAccounts, resolveUserOAuthRedirectUri, DEFAULT_USER_OAUTH_REDIRECT_URI, WPS_CHANNEL_ID, WPS_PLUGIN_ID, DEFAULT_ACCOUNT_ID, } from "./config.js";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 三层前置 scope 检查统一入口。
|
|
3
|
+
*
|
|
4
|
+
* 第 1 层:App scope(delegated scopes 列表)— 纯本地,无 API 调用
|
|
5
|
+
* 第 2 层:User token 有无
|
|
6
|
+
* 第 3 层:User scope diff(grantedScopes vs requiredScopes)
|
|
7
|
+
*
|
|
8
|
+
* appScopeVerified 降级机制:delegated 列表为空时,第 1、3 层均跳过,信任服务端。
|
|
9
|
+
* 当 appScopeVerified=false 时,调用方不应自动发送授权卡片(对标飞书保守策略)。
|
|
10
|
+
*/
|
|
11
|
+
export type ScopeCheckResult = {
|
|
12
|
+
ok: true;
|
|
13
|
+
appScopeVerified: boolean;
|
|
14
|
+
} | {
|
|
15
|
+
ok: false;
|
|
16
|
+
reason: "app_scope_missing";
|
|
17
|
+
missingScopes: string[];
|
|
18
|
+
message: string;
|
|
19
|
+
} | {
|
|
20
|
+
ok: false;
|
|
21
|
+
reason: "no_token";
|
|
22
|
+
appScopeVerified: boolean;
|
|
23
|
+
message: string;
|
|
24
|
+
} | {
|
|
25
|
+
ok: false;
|
|
26
|
+
reason: "user_scope_insufficient";
|
|
27
|
+
appScopeVerified: boolean;
|
|
28
|
+
missingScopes: string[];
|
|
29
|
+
message: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function checkScopes(opts: {
|
|
32
|
+
requiredScopes: string[];
|
|
33
|
+
accountId: string;
|
|
34
|
+
wpsUserId: string;
|
|
35
|
+
}): ScopeCheckResult;
|
|
36
|
+
//# sourceMappingURL=scope-checker.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegated scopes 持久化 — 跨重启对比 scope 变更。
|
|
3
|
+
*
|
|
4
|
+
* 存储路径与 token-persist 同目录,使用明文 JSON(scope 不含敏感信息)。
|
|
5
|
+
*/
|
|
6
|
+
type PersistedScopes = Record<string, string[]>;
|
|
7
|
+
export declare function loadPersistedScopes(): PersistedScopes;
|
|
8
|
+
export declare function savePersistedScopes(scopes: PersistedScopes): void;
|
|
9
|
+
export type ScopeChangeLog = {
|
|
10
|
+
added: string[];
|
|
11
|
+
removed: string[];
|
|
12
|
+
};
|
|
13
|
+
export declare function detectScopeChanges(accountId: string, currentNames: string[]): ScopeChangeLog;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=scope-persist.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块级 scope 映射表 — 声明每个 delegated 工具模块所需的 WPS 开放平台权限点。
|
|
3
|
+
*
|
|
4
|
+
* scope 名称来自各工具文件的 description 注释,与 GET /v7/developer/apps 返回的
|
|
5
|
+
* delegated scope name 一致。不使用 delegated auth 的模块(messaging / user / chat /
|
|
6
|
+
* media / meeting-room)不在此映射中,它们使用 app token。
|
|
7
|
+
*/
|
|
8
|
+
export type ToolModule = "calendar" | "todo" | "cloud-doc" | "airsheet" | "dbsheet" | "airpage";
|
|
9
|
+
export declare const MODULE_SCOPES: Record<ToolModule, string[]>;
|
|
10
|
+
export declare function getModuleScopes(module: ToolModule): string[];
|
|
11
|
+
//# sourceMappingURL=tool-scopes.d.ts.map
|
|
@@ -13,6 +13,8 @@ export type UserTokenEntry = {
|
|
|
13
13
|
refreshToken: string;
|
|
14
14
|
expiresAt: number;
|
|
15
15
|
openid: string;
|
|
16
|
+
/** 用户已授权的 scope 列表。undefined = 未知(旧 token),[] = 明确无 scope */
|
|
17
|
+
grantedScopes?: string[];
|
|
16
18
|
};
|
|
17
19
|
export type OAuthCodeExchangeParams = {
|
|
18
20
|
appId: string;
|
|
@@ -29,6 +31,12 @@ export type RefreshContext = {
|
|
|
29
31
|
export declare function setRefreshContext(accountId: string, ctx: RefreshContext): void;
|
|
30
32
|
export declare function putUserToken(accountId: string, wpsUserId: string, entry: UserTokenEntry): void;
|
|
31
33
|
export declare function getUserToken(accountId: string, wpsUserId: string): string | null;
|
|
34
|
+
/** 返回完整 UserTokenEntry(含 grantedScopes),不删除。过期返回 null。 */
|
|
35
|
+
export declare function getUserTokenEntry(accountId: string, wpsUserId: string): UserTokenEntry | null;
|
|
36
|
+
/** 清除 grantedScopes 但保留 token 本身。403 兜底使用。 */
|
|
37
|
+
export declare function clearGrantedScopes(accountId: string, wpsUserId: string): void;
|
|
38
|
+
/** 删除用户 token(含 grantedScopes)。401 兜底使用。 */
|
|
39
|
+
export declare function deleteUserToken(accountId: string, wpsUserId: string): void;
|
|
32
40
|
/** 兼容旧调用方 — 行为改为不删除 */
|
|
33
41
|
export declare function takeUserToken(accountId: string, wpsUserId: string): string | null;
|
|
34
42
|
export declare function hasUserToken(accountId: string, wpsUserId: string): boolean;
|