oasis_test_v2 2.2.107 → 2.2.109
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/index.js +382 -11
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -206747,6 +206747,35 @@ var init_host_isolation = __esm({
|
|
|
206747
206747
|
});
|
|
206748
206748
|
|
|
206749
206749
|
// ../connectors/src/feishu/index.ts
|
|
206750
|
+
async function fetchFeishuTenantAccessToken(appId, appSecret) {
|
|
206751
|
+
try {
|
|
206752
|
+
const resp = await fetch(FEISHU_TENANT_TOKEN_URL, {
|
|
206753
|
+
method: "POST",
|
|
206754
|
+
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
206755
|
+
body: JSON.stringify({ app_id: appId, app_secret: appSecret }),
|
|
206756
|
+
signal: AbortSignal.timeout(TENANT_TOKEN_TIMEOUT_MS)
|
|
206757
|
+
});
|
|
206758
|
+
const data = await resp.json();
|
|
206759
|
+
if (!resp.ok || data.code !== 0 || typeof data.tenant_access_token !== "string" || !data.tenant_access_token) {
|
|
206760
|
+
log("[feishu]", `\u6362\u4F01\u4E1A token \u5931\u8D25\uFF08\u672C\u8F6E bot \u8EAB\u4EFD\u4E0D\u53EF\u7528\uFF09: HTTP ${resp.status} code=${String(data.code)} ${String(data.msg ?? "")}`.trim());
|
|
206761
|
+
return null;
|
|
206762
|
+
}
|
|
206763
|
+
return data.tenant_access_token;
|
|
206764
|
+
} catch (err) {
|
|
206765
|
+
log("[feishu]", `\u6362\u4F01\u4E1A token \u5931\u8D25\uFF08\u672C\u8F6E bot \u8EAB\u4EFD\u4E0D\u53EF\u7528\uFF09: ${String(err?.message ?? err).slice(0, 200)}`);
|
|
206766
|
+
return null;
|
|
206767
|
+
}
|
|
206768
|
+
}
|
|
206769
|
+
function previousTenantToken(credsFile, appId) {
|
|
206770
|
+
if (!credsFile) return null;
|
|
206771
|
+
try {
|
|
206772
|
+
const prev = readSessionCredsFile(credsFile);
|
|
206773
|
+
if (prev["LARKSUITE_CLI_APP_ID"] !== appId) return null;
|
|
206774
|
+
return prev["LARKSUITE_CLI_TENANT_ACCESS_TOKEN"] || null;
|
|
206775
|
+
} catch {
|
|
206776
|
+
return null;
|
|
206777
|
+
}
|
|
206778
|
+
}
|
|
206750
206779
|
function parseFeishuTokenResponse(data, nowMs) {
|
|
206751
206780
|
const accessToken = String(data["access_token"] ?? "");
|
|
206752
206781
|
const refreshToken = String(data["refresh_token"] ?? "");
|
|
@@ -206765,7 +206794,7 @@ function parseFeishuTokenResponse(data, nowMs) {
|
|
|
206765
206794
|
expiresAt: new Date(expiresAtMs)
|
|
206766
206795
|
};
|
|
206767
206796
|
}
|
|
206768
|
-
var import_node_child_process14, import_node_util4, import_node_path16, import_node_url3, import_promises9, execFileAsync2, __dirname2, FEISHU_WELL_KNOWN_SKILLS_BASE, FEISHU_TOKEN_URL, FeishuConnector;
|
|
206797
|
+
var import_node_child_process14, import_node_util4, import_node_path16, import_node_url3, import_promises9, execFileAsync2, __dirname2, FEISHU_WELL_KNOWN_SKILLS_BASE, FEISHU_TOKEN_URL, FEISHU_TENANT_TOKEN_URL, TENANT_TOKEN_TIMEOUT_MS, FeishuConnector;
|
|
206769
206798
|
var init_feishu = __esm({
|
|
206770
206799
|
"../connectors/src/feishu/index.ts"() {
|
|
206771
206800
|
"use strict";
|
|
@@ -206775,10 +206804,13 @@ var init_feishu = __esm({
|
|
|
206775
206804
|
import_node_url3 = require("node:url");
|
|
206776
206805
|
import_promises9 = require("node:fs/promises");
|
|
206777
206806
|
init_base();
|
|
206807
|
+
init_logger();
|
|
206778
206808
|
execFileAsync2 = (0, import_node_util4.promisify)(import_node_child_process14.execFile);
|
|
206779
206809
|
__dirname2 = (0, import_node_path16.dirname)((0, import_node_url3.fileURLToPath)(__esm_import_meta_url));
|
|
206780
206810
|
FEISHU_WELL_KNOWN_SKILLS_BASE = "https://open.feishu.cn/.well-known/skills";
|
|
206781
206811
|
FEISHU_TOKEN_URL = "https://open.feishu.cn/open-apis/authen/v2/oauth/token";
|
|
206812
|
+
FEISHU_TENANT_TOKEN_URL = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal";
|
|
206813
|
+
TENANT_TOKEN_TIMEOUT_MS = 5e3;
|
|
206782
206814
|
FeishuConnector = class extends CliConnector {
|
|
206783
206815
|
config = {
|
|
206784
206816
|
slug: "feishu",
|
|
@@ -206876,9 +206908,12 @@ var init_feishu = __esm({
|
|
|
206876
206908
|
/** 厂商技能包源——平台自动拉取飞书官方技能包时用。 */
|
|
206877
206909
|
wellKnownSkillsBase = FEISHU_WELL_KNOWN_SKILLS_BASE;
|
|
206878
206910
|
larkBin;
|
|
206879
|
-
|
|
206911
|
+
fetchTenantToken;
|
|
206912
|
+
/** `fetchTenantToken` 只给测试替换(不打真飞书);生产一律用 {@link fetchFeishuTenantAccessToken}。 */
|
|
206913
|
+
constructor(larkBin, opts = {}) {
|
|
206880
206914
|
super(__dirname2);
|
|
206881
206915
|
this.larkBin = larkBin ?? this.resolveLarkBin();
|
|
206916
|
+
this.fetchTenantToken = opts.fetchTenantToken ?? fetchFeishuTenantAccessToken;
|
|
206882
206917
|
}
|
|
206883
206918
|
/**
|
|
206884
206919
|
* 解析 user_info 的 JSON。lark-cli 的 `ok:false` 也是**退出码 0** 的正常输出,
|
|
@@ -206909,6 +206944,7 @@ var init_feishu = __esm({
|
|
|
206909
206944
|
/**
|
|
206910
206945
|
* Agent run 开始:把凭据作为 lark-cli「外部凭据」写进凭据文件(不进 agent env)。
|
|
206911
206946
|
* credentials 接受:app_id, app_secret, user_access_token?(及其 FEISHU_* 别名)。
|
|
206947
|
+
* 企业 token 不随 job 下发,由这里用 app_id/app_secret 现换(换不到只是本轮没有 bot 身份,不抛)。
|
|
206912
206948
|
*
|
|
206913
206949
|
* 注入的 sessionEnv 键(全部非敏感):
|
|
206914
206950
|
* FEISHU_CREDS_FILE — 凭据文件路径,wrapper source 它
|
|
@@ -206921,9 +206957,11 @@ var init_feishu = __esm({
|
|
|
206921
206957
|
if (!appId) throw new Error("feishu inject: missing app_id");
|
|
206922
206958
|
if (!appSecret) throw new Error("feishu inject: missing app_secret");
|
|
206923
206959
|
const userAccessToken = credentials2["user_access_token"] ?? credentials2["FEISHU_USER_ACCESS_TOKEN"];
|
|
206960
|
+
const tenantAccessToken = this.isSimulated() ? null : await this.fetchTenantToken(appId, appSecret) ?? previousTenantToken(sessionEnv.get("FEISHU_CREDS_FILE"), appId);
|
|
206924
206961
|
const creds = await writeSessionCredsFile(this.config.slug, {
|
|
206925
206962
|
LARKSUITE_CLI_APP_ID: appId,
|
|
206926
206963
|
LARKSUITE_CLI_APP_SECRET: appSecret,
|
|
206964
|
+
...tenantAccessToken ? { LARKSUITE_CLI_TENANT_ACCESS_TOKEN: tenantAccessToken } : {},
|
|
206927
206965
|
...userAccessToken ? { LARKSUITE_CLI_USER_ACCESS_TOKEN: userAccessToken } : {}
|
|
206928
206966
|
}, sessionEnv.get("FEISHU_RUN_TMPDIR"));
|
|
206929
206967
|
const configDir = (0, import_node_path16.join)(creds.dir, "lark-config");
|
|
@@ -206993,7 +207031,65 @@ var init_feishu = __esm({
|
|
|
206993
207031
|
});
|
|
206994
207032
|
|
|
206995
207033
|
// ../connectors/src/feishu/scopes.ts
|
|
206996
|
-
|
|
207034
|
+
function scopesForDomains(domains) {
|
|
207035
|
+
const set = /* @__PURE__ */ new Set(["offline_access"]);
|
|
207036
|
+
for (const d of domains) {
|
|
207037
|
+
const g2 = FEISHU_DOMAIN_SCOPES[d];
|
|
207038
|
+
if (g2) for (const s2 of g2.scopes) set.add(s2);
|
|
207039
|
+
}
|
|
207040
|
+
return [...set];
|
|
207041
|
+
}
|
|
207042
|
+
function feishuModuleNeedsApproval(module2) {
|
|
207043
|
+
const g2 = FEISHU_DOMAIN_SCOPES[module2];
|
|
207044
|
+
return !!g2 && g2.scopes.some((s2) => !AUTO_APPROVED.has(s2));
|
|
207045
|
+
}
|
|
207046
|
+
function normalizeFeishuAuthSelection(body2) {
|
|
207047
|
+
const all2 = Object.keys(FEISHU_DOMAIN_SCOPES);
|
|
207048
|
+
let raw = body2.modules;
|
|
207049
|
+
if (raw === void 0) {
|
|
207050
|
+
if (body2.scopeLevel === "full") raw = all2;
|
|
207051
|
+
else if (body2.scopeLevel === "basic") raw = all2.filter((m2) => !feishuModuleNeedsApproval(m2));
|
|
207052
|
+
else raw = body2.domains;
|
|
207053
|
+
}
|
|
207054
|
+
const picked = new Set(Array.isArray(raw) ? raw.filter((m2) => typeof m2 === "string") : []);
|
|
207055
|
+
const modules = all2.filter((m2) => picked.has(m2));
|
|
207056
|
+
if (modules.length === 0) return null;
|
|
207057
|
+
return { modules, sendAsUser: body2.sendAsUser === true };
|
|
207058
|
+
}
|
|
207059
|
+
function scopesForSelection(sel, includeSendAsUser) {
|
|
207060
|
+
const scopes = scopesForDomains(sel.modules);
|
|
207061
|
+
if (includeSendAsUser) scopes.push(FEISHU_SEND_AS_USER_SCOPE);
|
|
207062
|
+
return scopes;
|
|
207063
|
+
}
|
|
207064
|
+
async function appHasScope(appId, appSecret, scope2, fetchImpl = fetch) {
|
|
207065
|
+
const tokenResp = await fetchImpl("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", {
|
|
207066
|
+
method: "POST",
|
|
207067
|
+
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
207068
|
+
body: JSON.stringify({ app_id: appId, app_secret: appSecret })
|
|
207069
|
+
});
|
|
207070
|
+
const tokenBody = await tokenResp.json();
|
|
207071
|
+
if (tokenBody.code !== 0 || !tokenBody.tenant_access_token) {
|
|
207072
|
+
throw new Error(`tenant_access_token failed: code=${tokenBody.code} msg=${tokenBody.msg ?? ""}`);
|
|
207073
|
+
}
|
|
207074
|
+
const resp = await fetchImpl("https://open.feishu.cn/open-apis/application/v6/scopes", {
|
|
207075
|
+
headers: { authorization: `Bearer ${tokenBody.tenant_access_token}` }
|
|
207076
|
+
});
|
|
207077
|
+
const body2 = await resp.json();
|
|
207078
|
+
if (body2.code !== 0) throw new Error(`application/v6/scopes failed: code=${body2.code} msg=${body2.msg ?? ""}`);
|
|
207079
|
+
return (body2.data?.scopes ?? []).some(
|
|
207080
|
+
(s2) => s2.scope_name === scope2 && (!s2.scope_type || s2.scope_type === "user")
|
|
207081
|
+
);
|
|
207082
|
+
}
|
|
207083
|
+
function feishuAuthSelectionRecord(sel, sendAsUserRequested, tokenResponse) {
|
|
207084
|
+
const granted = typeof tokenResponse["scope"] === "string" ? tokenResponse["scope"].split(/\s+/).filter(Boolean) : void 0;
|
|
207085
|
+
return {
|
|
207086
|
+
modules: sel.modules,
|
|
207087
|
+
sendAsUser: sel.sendAsUser,
|
|
207088
|
+
sendAsUserRequested,
|
|
207089
|
+
...granted ? { grantedScopes: granted } : {}
|
|
207090
|
+
};
|
|
207091
|
+
}
|
|
207092
|
+
var FEISHU_BASIC_SCOPES, FEISHU_DOMAIN_SCOPES, FEISHU_USER_SCOPES, FEISHU_USER_SCOPE_STRING, FEISHU_SEND_AS_USER_SCOPE, FEISHU_AUTH_SELECTION_VAR, AUTO_APPROVED;
|
|
206997
207093
|
var init_scopes = __esm({
|
|
206998
207094
|
"../connectors/src/feishu/scopes.ts"() {
|
|
206999
207095
|
"use strict";
|
|
@@ -207136,6 +207232,231 @@ var init_scopes = __esm({
|
|
|
207136
207232
|
"offline_access"
|
|
207137
207233
|
// refresh_token(--recommend 不含,但 token 刷新必须)
|
|
207138
207234
|
];
|
|
207235
|
+
FEISHU_DOMAIN_SCOPES = {
|
|
207236
|
+
im: {
|
|
207237
|
+
label: "\u5373\u65F6\u6D88\u606F\uFF08\u53D1\u6D88\u606F\u3001\u7FA4\u804A\u3001\u53CD\u5E94\uFF09",
|
|
207238
|
+
scopes: [
|
|
207239
|
+
"im:chat.members:read",
|
|
207240
|
+
"im:chat.members:write_only",
|
|
207241
|
+
"im:chat:read",
|
|
207242
|
+
"im:chat:update",
|
|
207243
|
+
"im:feed.flag:read",
|
|
207244
|
+
"im:feed.flag:write",
|
|
207245
|
+
"im:message",
|
|
207246
|
+
"im:message.group_msg:get_as_user",
|
|
207247
|
+
"im:message.p2p_msg:get_as_user",
|
|
207248
|
+
"im:message.pins:read",
|
|
207249
|
+
"im:message.pins:write_only",
|
|
207250
|
+
"im:message.reactions:read",
|
|
207251
|
+
"im:message.reactions:write_only",
|
|
207252
|
+
"im:message:readonly"
|
|
207253
|
+
]
|
|
207254
|
+
},
|
|
207255
|
+
calendar: {
|
|
207256
|
+
label: "\u65E5\u5386\uFF08\u65E5\u7A0B\u8BFB\u5199\uFF09",
|
|
207257
|
+
scopes: [
|
|
207258
|
+
"calendar:calendar:read",
|
|
207259
|
+
"calendar:calendar:create",
|
|
207260
|
+
"calendar:calendar:update",
|
|
207261
|
+
"calendar:calendar:delete",
|
|
207262
|
+
"calendar:calendar.event:read",
|
|
207263
|
+
"calendar:calendar.event:create",
|
|
207264
|
+
"calendar:calendar.event:update",
|
|
207265
|
+
"calendar:calendar.event:delete",
|
|
207266
|
+
"calendar:calendar.free_busy:read"
|
|
207267
|
+
]
|
|
207268
|
+
},
|
|
207269
|
+
docs: {
|
|
207270
|
+
label: "\u4E91\u6587\u6863\uFF08\u6587\u6863\u3001\u6743\u9650\u3001\u8BC4\u8BBA\uFF09",
|
|
207271
|
+
scopes: [
|
|
207272
|
+
"docs:document.content:read",
|
|
207273
|
+
"docs:document:copy",
|
|
207274
|
+
"docs:document:export",
|
|
207275
|
+
"docs:document:import",
|
|
207276
|
+
"docs:document.comment:read",
|
|
207277
|
+
"docs:document.comment:create",
|
|
207278
|
+
"docs:document.comment:update",
|
|
207279
|
+
"docs:document.comment:delete",
|
|
207280
|
+
"docs:document.comment:write_only",
|
|
207281
|
+
"docs:document.media:download",
|
|
207282
|
+
"docs:document.media:upload",
|
|
207283
|
+
"docs:event:subscribe",
|
|
207284
|
+
"docs:permission.member:apply",
|
|
207285
|
+
"docs:permission.member:auth",
|
|
207286
|
+
"docs:permission.member:create",
|
|
207287
|
+
"docs:permission.member:transfer",
|
|
207288
|
+
"docs:permission.setting:read",
|
|
207289
|
+
"docs:permission.setting:write_only",
|
|
207290
|
+
"docs:secure_label:write_only",
|
|
207291
|
+
"docx:document:create",
|
|
207292
|
+
"docx:document:readonly",
|
|
207293
|
+
"docx:document:write_only",
|
|
207294
|
+
"space:document:delete",
|
|
207295
|
+
"space:document:move",
|
|
207296
|
+
"space:document:shortcut",
|
|
207297
|
+
"space:folder:create"
|
|
207298
|
+
]
|
|
207299
|
+
},
|
|
207300
|
+
drive: {
|
|
207301
|
+
label: "\u4E91\u76D8\uFF08\u6587\u4EF6\u4E0A\u4F20\u4E0B\u8F7D\uFF09",
|
|
207302
|
+
scopes: [
|
|
207303
|
+
"drive:drive.metadata:readonly",
|
|
207304
|
+
"drive:file:download",
|
|
207305
|
+
"drive:file:upload",
|
|
207306
|
+
"drive:file:view_record:readonly",
|
|
207307
|
+
"drive:quota_detail:read_one"
|
|
207308
|
+
]
|
|
207309
|
+
},
|
|
207310
|
+
sheets: {
|
|
207311
|
+
label: "\u7535\u5B50\u8868\u683C",
|
|
207312
|
+
scopes: [
|
|
207313
|
+
"sheets:spreadsheet:create",
|
|
207314
|
+
"sheets:spreadsheet:read",
|
|
207315
|
+
"sheets:spreadsheet:write_only",
|
|
207316
|
+
"sheets:spreadsheet.meta:read",
|
|
207317
|
+
"sheets:spreadsheet.meta:write_only"
|
|
207318
|
+
]
|
|
207319
|
+
},
|
|
207320
|
+
base: {
|
|
207321
|
+
label: "\u591A\u7EF4\u8868\u683C\uFF08Base\uFF09",
|
|
207322
|
+
scopes: [
|
|
207323
|
+
"base:app:copy",
|
|
207324
|
+
"base:app:create",
|
|
207325
|
+
"base:app:read",
|
|
207326
|
+
"base:app:update",
|
|
207327
|
+
"base:dashboard:create",
|
|
207328
|
+
"base:dashboard:delete",
|
|
207329
|
+
"base:dashboard:read",
|
|
207330
|
+
"base:dashboard:update",
|
|
207331
|
+
"base:field:create",
|
|
207332
|
+
"base:field:delete",
|
|
207333
|
+
"base:field:read",
|
|
207334
|
+
"base:field:update",
|
|
207335
|
+
"base:form:create",
|
|
207336
|
+
"base:form:delete",
|
|
207337
|
+
"base:form:read",
|
|
207338
|
+
"base:form:update",
|
|
207339
|
+
"base:history:read",
|
|
207340
|
+
"base:record:create",
|
|
207341
|
+
"base:record:delete",
|
|
207342
|
+
"base:record:read",
|
|
207343
|
+
"base:record:update",
|
|
207344
|
+
"base:role:create",
|
|
207345
|
+
"base:role:delete",
|
|
207346
|
+
"base:role:read",
|
|
207347
|
+
"base:role:update",
|
|
207348
|
+
"base:table:create",
|
|
207349
|
+
"base:table:delete",
|
|
207350
|
+
"base:table:read",
|
|
207351
|
+
"base:table:update",
|
|
207352
|
+
"base:view:read",
|
|
207353
|
+
"base:view:write_only",
|
|
207354
|
+
"base:workflow:create",
|
|
207355
|
+
"base:workflow:read",
|
|
207356
|
+
"base:workflow:update"
|
|
207357
|
+
]
|
|
207358
|
+
},
|
|
207359
|
+
wiki: {
|
|
207360
|
+
label: "\u77E5\u8BC6\u5E93",
|
|
207361
|
+
scopes: [
|
|
207362
|
+
"wiki:member:create",
|
|
207363
|
+
"wiki:member:retrieve",
|
|
207364
|
+
"wiki:member:update",
|
|
207365
|
+
"wiki:node:copy",
|
|
207366
|
+
"wiki:node:create",
|
|
207367
|
+
"wiki:node:move",
|
|
207368
|
+
"wiki:node:read",
|
|
207369
|
+
"wiki:node:retrieve",
|
|
207370
|
+
"wiki:space:read",
|
|
207371
|
+
"wiki:space:retrieve",
|
|
207372
|
+
"wiki:space:write_only"
|
|
207373
|
+
]
|
|
207374
|
+
},
|
|
207375
|
+
slides: {
|
|
207376
|
+
label: "\u5E7B\u706F\u7247",
|
|
207377
|
+
scopes: [
|
|
207378
|
+
"slides:presentation:create",
|
|
207379
|
+
"slides:presentation:read",
|
|
207380
|
+
"slides:presentation:update",
|
|
207381
|
+
"slides:presentation:write_only"
|
|
207382
|
+
]
|
|
207383
|
+
},
|
|
207384
|
+
task: {
|
|
207385
|
+
label: "\u4EFB\u52A1",
|
|
207386
|
+
scopes: [
|
|
207387
|
+
"task:attachment:write",
|
|
207388
|
+
"task:comment:write",
|
|
207389
|
+
"task:custom_field:read",
|
|
207390
|
+
"task:custom_field:write",
|
|
207391
|
+
"task:section:read",
|
|
207392
|
+
"task:section:write",
|
|
207393
|
+
"task:task:read",
|
|
207394
|
+
"task:task:write",
|
|
207395
|
+
"task:tasklist:read",
|
|
207396
|
+
"task:tasklist:write"
|
|
207397
|
+
]
|
|
207398
|
+
},
|
|
207399
|
+
approval: {
|
|
207400
|
+
label: "\u5BA1\u6279",
|
|
207401
|
+
scopes: [
|
|
207402
|
+
"approval:instance:read",
|
|
207403
|
+
"approval:instance:write",
|
|
207404
|
+
"approval:task:read",
|
|
207405
|
+
"approval:task:write"
|
|
207406
|
+
]
|
|
207407
|
+
},
|
|
207408
|
+
mail: {
|
|
207409
|
+
label: "\u90AE\u4EF6",
|
|
207410
|
+
scopes: [
|
|
207411
|
+
"mail:user_mailbox:readonly",
|
|
207412
|
+
"mail:user_mailbox.message:modify",
|
|
207413
|
+
"mail:user_mailbox.message.address:read",
|
|
207414
|
+
"mail:user_mailbox.message.body:read",
|
|
207415
|
+
"mail:user_mailbox.message.subject:read",
|
|
207416
|
+
"mail:user_mailbox.message:readonly",
|
|
207417
|
+
"mail:user_mailbox.mail_contact:read",
|
|
207418
|
+
"mail:user_mailbox.mail_contact:write",
|
|
207419
|
+
"mail:event"
|
|
207420
|
+
]
|
|
207421
|
+
},
|
|
207422
|
+
minutes: {
|
|
207423
|
+
label: "\u5999\u8BB0\uFF08\u4F1A\u8BAE\u5F55\u97F3\uFF09",
|
|
207424
|
+
scopes: ["minutes:minutes.search:read", "minutes:minutes.upload:write"]
|
|
207425
|
+
},
|
|
207426
|
+
vc: {
|
|
207427
|
+
label: "\u89C6\u9891\u4F1A\u8BAE",
|
|
207428
|
+
scopes: [
|
|
207429
|
+
"vc:meeting.meetingevent:read",
|
|
207430
|
+
"vc:meeting.search:read",
|
|
207431
|
+
"vc:note:read",
|
|
207432
|
+
"vc:record:readonly"
|
|
207433
|
+
]
|
|
207434
|
+
},
|
|
207435
|
+
contact: {
|
|
207436
|
+
label: "\u901A\u8BAF\u5F55",
|
|
207437
|
+
scopes: [
|
|
207438
|
+
"contact:user.base:readonly",
|
|
207439
|
+
"contact:user:search",
|
|
207440
|
+
"contact:user.basic_profile:readonly"
|
|
207441
|
+
]
|
|
207442
|
+
},
|
|
207443
|
+
okr: {
|
|
207444
|
+
label: "OKR",
|
|
207445
|
+
scopes: ["okr:okr:read"]
|
|
207446
|
+
},
|
|
207447
|
+
attendance: {
|
|
207448
|
+
label: "\u8003\u52E4",
|
|
207449
|
+
scopes: ["attendance:record:read"]
|
|
207450
|
+
},
|
|
207451
|
+
board: {
|
|
207452
|
+
label: "\u767D\u677F",
|
|
207453
|
+
scopes: ["board:whiteboard:node:create", "board:whiteboard:node:read"]
|
|
207454
|
+
},
|
|
207455
|
+
spark: {
|
|
207456
|
+
label: "\u5E94\u7528\uFF08Spark\uFF09",
|
|
207457
|
+
scopes: ["spark:app:read", "spark:app:write"]
|
|
207458
|
+
}
|
|
207459
|
+
};
|
|
207139
207460
|
FEISHU_USER_SCOPES = [
|
|
207140
207461
|
// ── 自动审批权限(与 FEISHU_BASIC_SCOPES 完全相同)────────────────────
|
|
207141
207462
|
...FEISHU_BASIC_SCOPES,
|
|
@@ -207168,6 +207489,9 @@ var init_scopes = __esm({
|
|
|
207168
207489
|
"space:document:retrieve"
|
|
207169
207490
|
];
|
|
207170
207491
|
FEISHU_USER_SCOPE_STRING = FEISHU_USER_SCOPES.join(" ");
|
|
207492
|
+
FEISHU_SEND_AS_USER_SCOPE = "im:message.send_as_user";
|
|
207493
|
+
FEISHU_AUTH_SELECTION_VAR = "FEISHU_AUTH_SELECTION";
|
|
207494
|
+
AUTO_APPROVED = new Set(FEISHU_BASIC_SCOPES);
|
|
207171
207495
|
}
|
|
207172
207496
|
});
|
|
207173
207497
|
|
|
@@ -210646,7 +210970,7 @@ async function prepareConnectorsForJob(job, deps) {
|
|
|
210646
210970
|
await connector.inject(credentials2, sessionEnv);
|
|
210647
210971
|
for (const [k2, v2] of sessionEnv) envOverrides[k2] = v2;
|
|
210648
210972
|
cleanups.push(() => connector.cleanup(sessionEnv));
|
|
210649
|
-
injected.set(slug5, { connector, sessionEnv, credsFingerprint: credentialsFingerprint(credentials2) });
|
|
210973
|
+
injected.set(slug5, { connector, sessionEnv, credentials: credentials2, credsFingerprint: credentialsFingerprint(credentials2) });
|
|
210650
210974
|
status.credsReady = true;
|
|
210651
210975
|
} catch (err) {
|
|
210652
210976
|
status.error = String(err);
|
|
@@ -210772,7 +211096,12 @@ async function renewInjectedCredentials(injected, fetchCredentials) {
|
|
|
210772
211096
|
try {
|
|
210773
211097
|
fresh = await fetchCredentials();
|
|
210774
211098
|
} catch (err) {
|
|
210775
|
-
for (const slug5 of injected
|
|
211099
|
+
for (const [slug5, target] of injected) {
|
|
211100
|
+
outcome.failed.push({ slug: slug5, error: String(err) });
|
|
211101
|
+
await target.connector.inject(target.credentials, target.sessionEnv).catch((reErr) => {
|
|
211102
|
+
log("[node-connectors]", `\u26A0 \u7EED\u671F\uFF1A${slug5} \u6309\u65E7\u51ED\u636E\u91CD\u6CE8\u5931\u8D25: ${String(reErr)}`);
|
|
211103
|
+
});
|
|
211104
|
+
}
|
|
210776
211105
|
log("[node-connectors]", `\u7EED\u671F\uFF1A\u5411 server \u53D6\u51ED\u636E\u5931\u8D25\uFF0C\u672C\u8F6E\u6CBF\u7528\u65E7\u51ED\u636E: ${String(err)}`);
|
|
210777
211106
|
return outcome;
|
|
210778
211107
|
}
|
|
@@ -210781,6 +211110,7 @@ async function renewInjectedCredentials(injected, fetchCredentials) {
|
|
|
210781
211110
|
if (!target) continue;
|
|
210782
211111
|
try {
|
|
210783
211112
|
await target.connector.inject(credentials2, target.sessionEnv);
|
|
211113
|
+
target.credentials = credentials2;
|
|
210784
211114
|
const fingerprint2 = credentialsFingerprint(credentials2);
|
|
210785
211115
|
if (fingerprint2 !== target.credsFingerprint) {
|
|
210786
211116
|
target.credsFingerprint = fingerprint2;
|
|
@@ -217139,15 +217469,34 @@ ${composed}`;
|
|
|
217139
217469
|
return;
|
|
217140
217470
|
}
|
|
217141
217471
|
if (url.pathname === "/api/connectors/feishu/login/start" && req.method === "POST") {
|
|
217142
|
-
const
|
|
217472
|
+
const startBody = JSON.parse(rawBody);
|
|
217473
|
+
const { appId, actorId } = startBody;
|
|
217143
217474
|
if (!appId) {
|
|
217144
217475
|
res.writeHead(400).end(JSON.stringify({ error: "appId required" }));
|
|
217145
217476
|
return;
|
|
217146
217477
|
}
|
|
217478
|
+
const selection = normalizeFeishuAuthSelection(startBody);
|
|
217479
|
+
if (!selection) {
|
|
217480
|
+
res.writeHead(400).end(JSON.stringify({ error: "\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u529F\u80FD\u6A21\u5757" }));
|
|
217481
|
+
return;
|
|
217482
|
+
}
|
|
217147
217483
|
try {
|
|
217148
217484
|
const startSvc = await connectorActorsService();
|
|
217149
217485
|
const appSecret = startSvc ? await startSvc.revealResolvedVariable("FEISHU_APP_SECRET", actorId) : null;
|
|
217150
217486
|
if (!appSecret) throw new Error("FEISHU_APP_SECRET not found \u2014 please complete app setup first");
|
|
217487
|
+
let sendAsUserRequested = false;
|
|
217488
|
+
let notice;
|
|
217489
|
+
if (selection.sendAsUser) {
|
|
217490
|
+
try {
|
|
217491
|
+
sendAsUserRequested = await appHasScope(appId, appSecret, FEISHU_SEND_AS_USER_SCOPE);
|
|
217492
|
+
if (!sendAsUserRequested) {
|
|
217493
|
+
notice = "\u8BE5\u98DE\u4E66\u5E94\u7528\u5C1A\u672A\u5F00\u901A\u300C\u4EE5\u7528\u6237\u8EAB\u4EFD\u53D1\u6D88\u606F\u300D\u6743\u9650\uFF08im:message.send_as_user\uFF09\uFF0C\u672C\u6B21\u6388\u6743\u5DF2\u8DF3\u8FC7\u8FD9\u4E00\u9879\uFF0C\u5176\u4F59\u6743\u9650\u7167\u5E38\u7533\u8BF7\u3002\u5728\u98DE\u4E66\u5F00\u653E\u5E73\u53F0\u4E3A\u5E94\u7528\u5F00\u901A\u540E\u91CD\u65B0\u8FDE\u63A5\u5373\u53EF\u3002";
|
|
217494
|
+
}
|
|
217495
|
+
} catch (e) {
|
|
217496
|
+
console.error(`[feishu-oauth] app scopes check failed: ${String(e)}`);
|
|
217497
|
+
notice = "\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8BE5\u98DE\u4E66\u5E94\u7528\u662F\u5426\u5F00\u901A\u4E86\u300C\u4EE5\u7528\u6237\u8EAB\u4EFD\u53D1\u6D88\u606F\u300D\u6743\u9650\uFF0C\u672C\u6B21\u6388\u6743\u5DF2\u8DF3\u8FC7\u8FD9\u4E00\u9879\uFF0C\u5176\u4F59\u6743\u9650\u7167\u5E38\u7533\u8BF7\u3002\u7A0D\u540E\u53EF\u91CD\u65B0\u8FDE\u63A5\u518D\u8BD5\u3002";
|
|
217498
|
+
}
|
|
217499
|
+
}
|
|
217151
217500
|
const basicAuth = Buffer.from(`${appId}:${appSecret}`).toString("base64");
|
|
217152
217501
|
const resp = await fetch("https://accounts.feishu.cn/oauth/v1/device_authorization", {
|
|
217153
217502
|
method: "POST",
|
|
@@ -217155,7 +217504,10 @@ ${composed}`;
|
|
|
217155
217504
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
217156
217505
|
"Authorization": `Basic ${basicAuth}`
|
|
217157
217506
|
},
|
|
217158
|
-
body: new URLSearchParams({
|
|
217507
|
+
body: new URLSearchParams({
|
|
217508
|
+
client_id: appId,
|
|
217509
|
+
scope: scopesForSelection(selection, sendAsUserRequested).join(" ")
|
|
217510
|
+
}).toString()
|
|
217159
217511
|
});
|
|
217160
217512
|
const data = await resp.json();
|
|
217161
217513
|
if (!resp.ok || data["error"]) {
|
|
@@ -217163,14 +217515,22 @@ ${composed}`;
|
|
|
217163
217515
|
}
|
|
217164
217516
|
const verificationUrl = String(data["verification_uri_complete"] ?? data["verification_uri"] ?? "");
|
|
217165
217517
|
if (!verificationUrl) throw new Error("no verification_uri in response");
|
|
217166
|
-
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
|
|
217518
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
|
|
217519
|
+
verificationUrl,
|
|
217520
|
+
deviceCode: data["device_code"],
|
|
217521
|
+
modules: selection.modules,
|
|
217522
|
+
sendAsUser: selection.sendAsUser,
|
|
217523
|
+
sendAsUserRequested,
|
|
217524
|
+
...notice ? { notice } : {}
|
|
217525
|
+
}));
|
|
217167
217526
|
} catch (e) {
|
|
217168
217527
|
res.writeHead(500).end(JSON.stringify({ error: String(e) }));
|
|
217169
217528
|
}
|
|
217170
217529
|
return;
|
|
217171
217530
|
}
|
|
217172
217531
|
if (url.pathname === "/api/connectors/feishu/login/poll" && req.method === "POST") {
|
|
217173
|
-
const
|
|
217532
|
+
const pollBody = JSON.parse(rawBody);
|
|
217533
|
+
const { appId, deviceCode, actorId } = pollBody;
|
|
217174
217534
|
if (!appId || !deviceCode) {
|
|
217175
217535
|
res.writeHead(400).end(JSON.stringify({ error: "appId and deviceCode required" }));
|
|
217176
217536
|
return;
|
|
@@ -217210,6 +217570,17 @@ ${composed}`;
|
|
|
217210
217570
|
}
|
|
217211
217571
|
await persistFeishuUserTokens(svc, actorId, data, Date.now());
|
|
217212
217572
|
const nameScope = actorId ? { scope: "personal", actorId } : { scope: "global" };
|
|
217573
|
+
const pollSelection = pollBody.modules === void 0 ? null : normalizeFeishuAuthSelection(pollBody);
|
|
217574
|
+
if (pollSelection) {
|
|
217575
|
+
const record10 = feishuAuthSelectionRecord(pollSelection, pollBody.sendAsUserRequested === true, data);
|
|
217576
|
+
await svc.putVariable({
|
|
217577
|
+
key: FEISHU_AUTH_SELECTION_VAR,
|
|
217578
|
+
value: JSON.stringify(record10),
|
|
217579
|
+
...nameScope,
|
|
217580
|
+
connectorId: "feishu",
|
|
217581
|
+
encrypted: false
|
|
217582
|
+
});
|
|
217583
|
+
}
|
|
217213
217584
|
try {
|
|
217214
217585
|
const uiResp = await fetch("https://open.feishu.cn/open-apis/authen/v1/user_info", {
|
|
217215
217586
|
headers: { authorization: `Bearer ${String(data["access_token"])}` }
|
|
@@ -299347,7 +299718,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
299347
299718
|
}
|
|
299348
299719
|
}
|
|
299349
299720
|
}
|
|
299350
|
-
var CLI_VERSION = "2.2.
|
|
299721
|
+
var CLI_VERSION = "2.2.109" ? "2.2.109" : "dev";
|
|
299351
299722
|
function apiHeaders(token2, company) {
|
|
299352
299723
|
const headers = {
|
|
299353
299724
|
authorization: `Bearer ${token2}`,
|
|
@@ -303518,7 +303889,7 @@ function shimScript() {
|
|
|
303518
303889
|
}
|
|
303519
303890
|
|
|
303520
303891
|
// src/index.ts
|
|
303521
|
-
var PKG_VERSION = true ? "2.2.
|
|
303892
|
+
var PKG_VERSION = true ? "2.2.109" : "dev";
|
|
303522
303893
|
var LOCAL_BIN = localBin();
|
|
303523
303894
|
var NPM_PREFIX = npmPrefix();
|
|
303524
303895
|
var INSTANCE = DEFAULT_INSTANCE;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oasis_test_v2",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.109",
|
|
4
4
|
"description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"oasis": "./dist/index.js"
|
|
@@ -26,6 +26,6 @@
|
|
|
26
26
|
"node": ">=20"
|
|
27
27
|
},
|
|
28
28
|
"oasisRelease": {
|
|
29
|
-
"sourceHead": "
|
|
29
|
+
"sourceHead": "ed886e183f5c2444ee63e480a04b46976ddcf303"
|
|
30
30
|
}
|
|
31
31
|
}
|