oasis_test_v2 2.2.115 → 2.2.117

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.
@@ -51,15 +51,17 @@ feishu_reply_blocked() {
51
51
  feishu_blocked() {
52
52
  # $1 = 规则要求的模块(逗号分隔,空 = 不属于任何模块);$2 = 给人看的命令写法(已过滤成安全字符)。
53
53
  local mods="$1" shown="$2" need="" m entry label
54
- local reconnect="请让配置人在 Oasis 里这个 agent 的飞书连接器详情点「重新连接」"
54
+ # 只勾模块、保存即可让机器人身份可用,不需要用户授权;用户身份才要本人另行授权。
55
+ local pick="请让配置人在 Oasis 里这个 agent 的飞书连接器详情「接入功能」"
56
+ local bot_ok="保存后机器人身份即可调用(不需要用户授权,应用须已开通对应权限);只有需要以用户身份调用时,才需本人在同一处「去授权 / 重新授权」"
55
57
  case "${OASIS_FEISHU_POLICY:-}" in
56
58
  ok) ;;
57
59
  none)
58
60
  feishu_reply_blocked "本 agent 的飞书连接器还没有保存过可用模块的选择,Oasis 按「一个模块都没开放」处理,${shown} 已被拦下(机器人与用户身份都不可用)。" \
59
- "${reconnect},勾选需要的模块后完成授权。" ;;
61
+ "${pick}勾选需要的模块并保存;${bot_ok}。" ;;
60
62
  invalid)
61
63
  feishu_reply_blocked "本 agent 的飞书连接器保存的模块选择无法识别,Oasis 按「一个模块都没开放」处理,${shown} 已被拦下(机器人与用户身份都不可用)。" \
62
- "${reconnect},重新勾选模块后完成授权。" ;;
64
+ "${pick}重新勾选模块并保存;${bot_ok}。" ;;
63
65
  *)
64
66
  feishu_reply_blocked "本次运行没有拿到飞书模块放行表,Oasis 不放行 ${shown}(机器人与用户身份都不可用)。" \
65
67
  "请重新发起任务;仍出现请联系 Oasis 管理员检查飞书连接器。" ;;
@@ -73,7 +75,7 @@ feishu_blocked() {
73
75
  need="${need:+${need}」或「}${label}"
74
76
  done
75
77
  feishu_reply_blocked "本 agent 的飞书连接器没有开放「${need}」模块,${shown} 已被 Oasis 拦下(机器人与用户身份都不可用)。当前开放的模块:${OASIS_FEISHU_MODULES:-无}。" \
76
- "如需使用,${reconnect},勾选「${need}」后完成授权。"
78
+ "如需使用,${pick}点「调整接入功能」勾选「${need}」并保存;${bot_ok}。"
77
79
  fi
78
80
  feishu_reply_blocked "${shown} 不属于任何可勾选的飞书功能模块;本 agent 的飞书调用已按模块限制,Oasis 不放行它。当前开放的模块:${OASIS_FEISHU_MODULES:-无}。" \
79
81
  "请改用已开放模块对应的 lark-cli 命令;共用的 drive 子命令须紧跟在 drive 之后写。确需此能力请联系 Oasis 管理员。"
package/dist/index.js CHANGED
@@ -20789,6 +20789,9 @@ ${input.link}` : `${head}
20789
20789
  function feishuPendingApprovalNotice(modules) {
20790
20790
  return `${moduleNames(modules)}\u542B\u9700\u98DE\u4E66\u7BA1\u7406\u5458\u5BA1\u6279\u7684\u6743\u9650\uFF0C\u5DF2\u63D0\u4EA4\u5BA1\u6279\u3002\u6279\u51C6\u540E\u4F1A\u5728\u98DE\u4E66\u79C1\u4FE1\u901A\u77E5\u4F60\uFF0C\u70B9\u4E00\u4E0B\u5373\u53EF\u8865\u4E0A\u8FD9\u90E8\u5206\u6743\u9650\uFF1B\u5DF2\u6709\u7684\u98DE\u4E66\u80FD\u529B\u4E0D\u53D7\u5F71\u54CD\u3002`;
20791
20791
  }
20792
+ function feishuPendingApprovalKeptNotice(modules) {
20793
+ return `${moduleNames(modules)}\u542B\u9700\u98DE\u4E66\u7BA1\u7406\u5458\u5BA1\u6279\u7684\u6743\u9650\uFF0C\u5DF2\u63D0\u4EA4\u5BA1\u6279\u3002\u98DE\u4E66\u8FD9\u4E00\u8F6E\u7ED9\u7684\u6388\u6743\u4E0D\u5305\u542B\u4F60\u73B0\u6709\u6388\u6743\u7684\u5168\u90E8\u6743\u9650\uFF0C\u4E3A\u4E0D\u5F71\u54CD\u5DF2\u6709\u7684\u98DE\u4E66\u80FD\u529B\uFF0C\u539F\u6388\u6743\u4FDD\u6301\u4E0D\u53D8\u3001\u8FD9\u4E00\u8F6E\u7684\u6388\u6743\u6CA1\u6709\u4FDD\u5B58\u3002\u6279\u51C6\u540E\u4F1A\u5728\u98DE\u4E66\u79C1\u4FE1\u901A\u77E5\u4F60\uFF0C\u70B9\u4E00\u4E0B\u5373\u53EF\u4E00\u5E76\u8865\u4E0A\u3002`;
20794
+ }
20792
20795
  function feishuApprovalUnconfirmedNotice(modules, expired) {
20793
20796
  return `${expired ? "\u6388\u6743\u9875\u5DF2\u8D85\u65F6\uFF0C" : ""}\u98DE\u4E66\u8FD9\u4E00\u8F6E\u6CA1\u6709\u7ED9\u51FA\u6388\u6743\uFF0COasis \u65E0\u6CD5\u786E\u8BA4\u4F60\u662F\u5426\u5728\u6388\u6743\u9875\u5BF9${moduleNames(modules)}\u7684\u6743\u9650\u70B9\u4E86\u300C\u7533\u8BF7\u300D\u3002\u5982\u679C\u70B9\u4E86\uFF0C\u8BF7\u9009\u300C\u6211\u70B9\u4E86\u7533\u8BF7\u300D\uFF0C\u6279\u51C6\u540E\u4F1A\u5728\u98DE\u4E66\u79C1\u4FE1\u901A\u77E5\u4F60\u8865\u6388\u6743\uFF1B\u6CA1\u70B9\uFF08\u6216\u70B9\u7684\u662F\u62D2\u7EDD\uFF09\u7684\u8BDD\u91CD\u65B0\u53D1\u8D77\u6388\u6743\u5373\u53EF\u3002\u5DF2\u6709\u7684\u98DE\u4E66\u80FD\u529B\u4E0D\u53D7\u5F71\u54CD\u3002`;
20794
20797
  }
@@ -24751,6 +24754,74 @@ var init_src3 = __esm({
24751
24754
  }
24752
24755
  });
24753
24756
 
24757
+ // ../server/src/feishu-pending-approval.ts
24758
+ async function recordFeishuPendingApproval(input) {
24759
+ const pendingScopes = input.pendingScopes ?? await pendingApprovalScopes(input);
24760
+ if (pendingScopes.length === 0) {
24761
+ if (input.granted) {
24762
+ await withConnectorCredentialLock("feishu", input.actorId, () => clearFeishuPendingApproval(input.store, input.actorId));
24763
+ }
24764
+ return null;
24765
+ }
24766
+ const record10 = {
24767
+ at: new Date(input.now).toISOString(),
24768
+ appId: input.appId,
24769
+ ...input.applicant ? { applicant: input.applicant } : {},
24770
+ modules: input.selection.modules,
24771
+ sendAsUser: input.selection.sendAsUser,
24772
+ sendAsUserRequested: input.sendAsUserRequested,
24773
+ pendingScopes
24774
+ };
24775
+ await withConnectorCredentialLock("feishu", input.actorId, () => writeFeishuPendingApproval(input.store, input.actorId, record10));
24776
+ const modules = feishuPendingApprovalModules(record10);
24777
+ return { modules, scopes: pendingScopes, notice: input.keptExisting ? feishuPendingApprovalKeptNotice(modules) : feishuPendingApprovalNotice(modules) };
24778
+ }
24779
+ function feishuStillPendingScopes(input) {
24780
+ return pendingApprovalScopes(input);
24781
+ }
24782
+ async function pendingApprovalScopes(input) {
24783
+ const requested = scopesForSelection(input.selection, input.sendAsUserRequested);
24784
+ let appScopes = null;
24785
+ try {
24786
+ appScopes = await (input.fetchScopes ?? fetchFeishuAppScopes)(input.appId, input.appSecret);
24787
+ } catch (e) {
24788
+ (input.warn ?? ((m2) => console.warn(`[feishu-oauth] ${m2}`)))(`\u5E94\u7528\u6743\u9650\u5217\u8868\u67E5\u8BE2\u5931\u8D25\uFF0C\u5F85\u5BA1\u6279\u6309\u514D\u5BA1\u96C6\u5408\u4F30\u7B97: ${String(e)}`);
24789
+ }
24790
+ return feishuPendingApprovalScopes({ requested, granted: input.granted, appScopes });
24791
+ }
24792
+ async function assessFeishuApprovalUnconfirmed(input) {
24793
+ const scopes = await pendingApprovalScopes(input);
24794
+ if (scopes.length === 0) return null;
24795
+ const modules = feishuPendingApprovalModules({ modules: input.selection.modules, pendingScopes: scopes });
24796
+ return { modules, scopes, notice: feishuApprovalUnconfirmedNotice(modules, input.expired) };
24797
+ }
24798
+ async function feishuExistingGrantAtRisk(input) {
24799
+ const { store, actorId } = input;
24800
+ const read3 = (key2) => store.revealVariable(key2, actorId).catch(() => null);
24801
+ if (await read3(FEISHU_USER_AUTH_INVALID_VAR)) return { keep: false };
24802
+ if (await store.revealResolvedVariable("FEISHU_APP_ID", actorId).catch(() => null) !== input.appId) return { keep: false };
24803
+ const alive2 = (token2, expiresAt2) => !!token2 && (!expiresAt2 || !Number.isFinite(Number(expiresAt2)) || Number(expiresAt2) > input.now);
24804
+ const usable = alive2(await read3("FEISHU_REFRESH_TOKEN"), await read3("FEISHU_REFRESH_TOKEN_EXPIRES_AT")) || !!await read3("FEISHU_USER_TOKEN_EXPIRES_AT") && alive2(await read3("FEISHU_USER_ACCESS_TOKEN"), await read3("FEISHU_USER_TOKEN_EXPIRES_AT"));
24805
+ if (!usable) return { keep: false };
24806
+ let oldGranted = null;
24807
+ try {
24808
+ const rec2 = JSON.parse(await read3(FEISHU_AUTH_SELECTION_VAR) ?? "null");
24809
+ if (Array.isArray(rec2?.grantedScopes)) oldGranted = rec2.grantedScopes.filter((s2) => typeof s2 === "string");
24810
+ } catch {
24811
+ }
24812
+ if (!input.newGranted) return { keep: true, missing: null };
24813
+ if (!oldGranted) return { keep: true, missing: null };
24814
+ const granted = new Set(input.newGranted);
24815
+ const missing = oldGranted.filter((s2) => s2 !== "offline_access" && !granted.has(s2));
24816
+ return missing.length > 0 ? { keep: true, missing } : { keep: false };
24817
+ }
24818
+ var init_feishu_pending_approval = __esm({
24819
+ "../server/src/feishu-pending-approval.ts"() {
24820
+ "use strict";
24821
+ init_src3();
24822
+ }
24823
+ });
24824
+
24754
24825
  // ../server/src/feishu-reauth.ts
24755
24826
  async function supplementSelection(store, actorId) {
24756
24827
  const pending = await readFeishuPendingApproval(store, actorId);
@@ -24787,7 +24858,7 @@ function createFeishuReauth(deps) {
24787
24858
  const appSecret = await store.revealResolvedVariable("FEISHU_APP_SECRET", actorId);
24788
24859
  return appId && appSecret ? { appId, appSecret } : null;
24789
24860
  };
24790
- const settle = async (claims, store, data, sel, sendAsUserRequested) => {
24861
+ const settle = async (claims, store, data, sel, sendAsUserRequested, appId) => {
24791
24862
  const who = await (deps.identity ?? fetchFeishuUserIdentity)(String(data["access_token"] ?? ""));
24792
24863
  if (!who.openId) {
24793
24864
  return { state: "error", message: "\u6388\u6743\u5B8C\u6210\u4E86\uFF0C\u4F46\u6CA1\u80FD\u5411\u98DE\u4E66\u786E\u8BA4\u6388\u6743\u4EBA\u662F\u8C01\uFF0C\u672C\u6B21\u6388\u6743\u672A\u4FDD\u5B58\u3002\u8BF7\u7A0D\u540E\u91CD\u65B0\u70B9\u94FE\u63A5\u518D\u8BD5\u3002" };
@@ -24801,59 +24872,61 @@ function createFeishuReauth(deps) {
24801
24872
  }
24802
24873
  const supplement = await withConnectorCredentialLock("feishu", claims.actorId, async () => {
24803
24874
  const pending2 = claims.purpose === "supplement" ? await readFeishuPendingApproval(store, claims.actorId) : null;
24804
- await persistFeishuUserAuthorization(store, claims.actorId, data, now(), {
24805
- openId: who.openId,
24806
- ...who.name ? { userName: who.name } : {},
24807
- ...pending2?.applicant ? { authorizedBy: pending2.applicant } : {}
24808
- });
24809
24875
  const record10 = feishuAuthSelectionRecord(sel, sendAsUserRequested, data);
24810
- await store.putVariable({
24811
- key: FEISHU_AUTH_SELECTION_VAR,
24812
- value: JSON.stringify(record10),
24813
- ...claims.actorId ? { scope: "personal", actorId: claims.actorId } : { scope: "global" },
24814
- connectorId: "feishu",
24815
- encrypted: false
24816
- });
24817
- if (claims.purpose !== "supplement") return null;
24818
- if (!record10.grantedScopes) return "unknown";
24819
- if (!pending2) {
24820
- const granted2 = new Set(record10.grantedScopes);
24821
- const wanted = scopesForSelection(sel, sendAsUserRequested).filter((x2) => x2 !== "offline_access");
24822
- return wanted.every((x2) => granted2.has(x2)) ? "complete" : "short";
24823
- }
24824
- const granted = new Set(record10.grantedScopes);
24825
- const still = pending2.pendingScopes.filter((x2) => !granted.has(x2));
24826
- if (still.length === 0) {
24827
- await clearFeishuPendingApproval(store, claims.actorId);
24828
- return "complete";
24829
- }
24830
- const next = { ...pending2, pendingScopes: still };
24831
- delete next.approvedAt;
24832
- delete next.notice;
24833
- await writeFeishuPendingApproval(store, claims.actorId, next);
24834
- return "partial";
24876
+ let outcome = null;
24877
+ let still = [];
24878
+ if (claims.purpose === "supplement") {
24879
+ if (!record10.grantedScopes) {
24880
+ outcome = "unknown";
24881
+ } else if (!pending2) {
24882
+ const granted = new Set(record10.grantedScopes);
24883
+ const wanted = scopesForSelection(sel, sendAsUserRequested).filter((x2) => x2 !== "offline_access");
24884
+ outcome = wanted.every((x2) => granted.has(x2)) ? "complete" : "short";
24885
+ } else {
24886
+ const granted = new Set(record10.grantedScopes);
24887
+ still = pending2.pendingScopes.filter((x2) => !granted.has(x2));
24888
+ outcome = still.length === 0 ? "complete" : "partial";
24889
+ }
24890
+ }
24891
+ const kept = outcome !== null && outcome !== "complete" && (await feishuExistingGrantAtRisk({
24892
+ store,
24893
+ actorId: claims.actorId,
24894
+ appId,
24895
+ ...record10.grantedScopes ? { newGranted: record10.grantedScopes } : {},
24896
+ now: now()
24897
+ })).keep;
24898
+ if (!kept) {
24899
+ await persistFeishuUserAuthorization(store, claims.actorId, data, now(), {
24900
+ openId: who.openId,
24901
+ ...who.name ? { userName: who.name } : {},
24902
+ ...pending2?.applicant ? { authorizedBy: pending2.applicant } : {}
24903
+ });
24904
+ await store.putVariable({
24905
+ key: FEISHU_AUTH_SELECTION_VAR,
24906
+ value: JSON.stringify(record10),
24907
+ ...claims.actorId ? { scope: "personal", actorId: claims.actorId } : { scope: "global" },
24908
+ connectorId: "feishu",
24909
+ encrypted: false
24910
+ });
24911
+ }
24912
+ if (outcome === "complete" && pending2) await clearFeishuPendingApproval(store, claims.actorId);
24913
+ if (outcome === "partial" && pending2) {
24914
+ const next = { ...pending2, pendingScopes: still };
24915
+ delete next.approvedAt;
24916
+ delete next.notice;
24917
+ await writeFeishuPendingApproval(store, claims.actorId, next);
24918
+ }
24919
+ return outcome === null ? null : { outcome, kept };
24835
24920
  });
24836
24921
  const userName = who.name ? { userName: who.name } : {};
24837
- if (supplement === "partial") {
24838
- return {
24839
- state: "incomplete",
24840
- ...userName,
24841
- message: "\u6388\u6743\u5DF2\u4FDD\u5B58\uFF0C\u4F46\u98DE\u4E66\u8FD9\u6B21\u6CA1\u6709\u7ED9\u9F50\u7BA1\u7406\u5458\u6279\u51C6\u7684\u6743\u9650\uFF0C\u8FD8\u5DEE\u7684\u90E8\u5206\u7EE7\u7EED\u7B49\u5F85\u5BA1\u6279\uFF1B\u6279\u51C6\u540E\u4F1A\u518D\u79C1\u4FE1\u901A\u77E5\u4F60\u3002\u5DF2\u6709\u7684\u98DE\u4E66\u80FD\u529B\u4E0D\u53D7\u5F71\u54CD\u3002"
24842
- };
24843
- }
24844
- if (supplement === "short") {
24845
- return {
24846
- state: "incomplete",
24847
- ...userName,
24848
- message: "\u6388\u6743\u5DF2\u4FDD\u5B58\uFF0C\u4F46\u98DE\u4E66\u8FD9\u6B21\u6CA1\u6709\u7ED9\u9F50\u6240\u7533\u8BF7\u7684\u6743\u9650\u3002\u53EF\u5728 Oasis \u8FDE\u63A5\u5668\u8BE6\u60C5\u67E5\u770B\u5DF2\u5F00\u901A\u7684\u529F\u80FD\uFF0C\u9700\u8981\u65F6\u91CD\u65B0\u8FDE\u63A5\u98DE\u4E66\u3002"
24849
- };
24850
- }
24851
- if (supplement === "unknown") {
24852
- return {
24853
- state: "incomplete",
24854
- ...userName,
24855
- message: "\u6388\u6743\u5DF2\u4FDD\u5B58\uFF0C\u4F46\u98DE\u4E66\u6CA1\u6709\u56DE\u62A5\u8FD9\u6B21\u6388\u4E88\u4E86\u54EA\u4E9B\u6743\u9650\uFF0C\u65E0\u6CD5\u786E\u8BA4\u7BA1\u7406\u5458\u6279\u51C6\u7684\u6743\u9650\u662F\u5426\u5DF2\u8865\u4E0A\u3002\u53EF\u5728 Oasis \u8FDE\u63A5\u5668\u8BE6\u60C5\u67E5\u770B\uFF1B\u4ECD\u663E\u793A\u5F85\u8865\u6388\u6743\u7684\u8BDD\uFF0C\u518D\u70B9\u4E00\u6B21\u94FE\u63A5\u5373\u53EF\u3002"
24856
- };
24922
+ if (supplement && supplement.outcome !== "complete") {
24923
+ const saved = supplement.kept ? "\u4E3A\u4E0D\u5F71\u54CD\u5DF2\u6709\u7684\u98DE\u4E66\u80FD\u529B\uFF0C\u539F\u6388\u6743\u4FDD\u6301\u4E0D\u53D8\u3001\u8FD9\u6B21\u6388\u6743\u6CA1\u6709\u4FDD\u5B58\uFF08\u98DE\u4E66\u8FD9\u6B21\u7ED9\u7684\u6388\u6743\u4E0D\u5305\u542B\u4F60\u73B0\u6709\u6388\u6743\u7684\u5168\u90E8\u6743\u9650\uFF09\u3002" : "\u6388\u6743\u5DF2\u4FDD\u5B58\u3002";
24924
+ const message = {
24925
+ partial: `\u98DE\u4E66\u8FD9\u6B21\u6CA1\u6709\u7ED9\u9F50\u7BA1\u7406\u5458\u6279\u51C6\u7684\u6743\u9650\uFF0C\u8FD8\u5DEE\u7684\u90E8\u5206\u7EE7\u7EED\u7B49\u5F85\u5BA1\u6279\uFF0C\u6279\u51C6\u540E\u4F1A\u518D\u79C1\u4FE1\u901A\u77E5\u4F60\u3002${saved}`,
24926
+ short: `\u98DE\u4E66\u8FD9\u6B21\u6CA1\u6709\u7ED9\u9F50\u6240\u7533\u8BF7\u7684\u6743\u9650\u3002${saved}\u53EF\u5728 Oasis \u8FDE\u63A5\u5668\u8BE6\u60C5\u67E5\u770B\u5DF2\u5F00\u901A\u7684\u529F\u80FD\uFF0C\u9700\u8981\u65F6\u91CD\u65B0\u8FDE\u63A5\u98DE\u4E66\u3002`,
24927
+ unknown: `\u98DE\u4E66\u6CA1\u6709\u56DE\u62A5\u8FD9\u6B21\u6388\u4E88\u4E86\u54EA\u4E9B\u6743\u9650\uFF0C\u65E0\u6CD5\u786E\u8BA4\u7BA1\u7406\u5458\u6279\u51C6\u7684\u6743\u9650\u662F\u5426\u5DF2\u8865\u4E0A\u3002${saved}\u53EF\u5728 Oasis \u8FDE\u63A5\u5668\u8BE6\u60C5\u67E5\u770B\uFF1B\u4ECD\u663E\u793A\u5F85\u8865\u6388\u6743\u7684\u8BDD\uFF0C\u518D\u70B9\u4E00\u6B21\u94FE\u63A5\u5373\u53EF\u3002`
24928
+ }[supplement.outcome];
24929
+ return { state: "incomplete", ...userName, message };
24857
24930
  }
24858
24931
  await deps.onRestored?.(claims, { openId: who.openId, ...userName }).catch((e) => warn(`onRestored: ${String(e)}`));
24859
24932
  return { state: "restored", ...who.name ? { userName: who.name } : {} };
@@ -24864,7 +24937,7 @@ function createFeishuReauth(deps) {
24864
24937
  try {
24865
24938
  const r = await (deps.poll ?? pollFeishuDeviceToken)({ appId: ctx.appId, appSecret: ctx.appSecret, deviceCode });
24866
24939
  if (r.status === "pending") continue;
24867
- entry.result = await settle(entry.claims, ctx.store, r.data, ctx.sel, ctx.sendAsUser);
24940
+ entry.result = await settle(entry.claims, ctx.store, r.data, ctx.sel, ctx.sendAsUser, ctx.appId);
24868
24941
  return;
24869
24942
  } catch (e) {
24870
24943
  entry.result = { state: "error", message: `\u98DE\u4E66\u6CA1\u6709\u5B8C\u6210\u6388\u6743\uFF1A${String(e?.message ?? e).slice(0, 200)}\u3002\u53EF\u4EE5\u91CD\u65B0\u70B9\u94FE\u63A5\u518D\u8BD5\u3002` };
@@ -24959,6 +25032,7 @@ var init_feishu_reauth = __esm({
24959
25032
  "../server/src/feishu-reauth.ts"() {
24960
25033
  "use strict";
24961
25034
  init_src3();
25035
+ init_feishu_pending_approval();
24962
25036
  DEFAULT_DEVICE_CODE_TTL_SEC = 240;
24963
25037
  DEFAULT_POLL_INTERVAL_SEC = 5;
24964
25038
  escapeHtml = (s2) => s2.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
@@ -212364,51 +212438,6 @@ var init_feishu_module_access = __esm({
212364
212438
  }
212365
212439
  });
212366
212440
 
212367
- // ../server/src/feishu-pending-approval.ts
212368
- async function recordFeishuPendingApproval(input) {
212369
- const pendingScopes = await pendingApprovalScopes(input);
212370
- if (pendingScopes.length === 0) {
212371
- if (input.granted) {
212372
- await withConnectorCredentialLock("feishu", input.actorId, () => clearFeishuPendingApproval(input.store, input.actorId));
212373
- }
212374
- return null;
212375
- }
212376
- const record10 = {
212377
- at: new Date(input.now).toISOString(),
212378
- appId: input.appId,
212379
- ...input.applicant ? { applicant: input.applicant } : {},
212380
- modules: input.selection.modules,
212381
- sendAsUser: input.selection.sendAsUser,
212382
- sendAsUserRequested: input.sendAsUserRequested,
212383
- pendingScopes
212384
- };
212385
- await withConnectorCredentialLock("feishu", input.actorId, () => writeFeishuPendingApproval(input.store, input.actorId, record10));
212386
- const modules = feishuPendingApprovalModules(record10);
212387
- return { modules, scopes: pendingScopes, notice: feishuPendingApprovalNotice(modules) };
212388
- }
212389
- async function pendingApprovalScopes(input) {
212390
- const requested = scopesForSelection(input.selection, input.sendAsUserRequested);
212391
- let appScopes = null;
212392
- try {
212393
- appScopes = await (input.fetchScopes ?? fetchFeishuAppScopes)(input.appId, input.appSecret);
212394
- } catch (e) {
212395
- (input.warn ?? ((m2) => console.warn(`[feishu-oauth] ${m2}`)))(`\u5E94\u7528\u6743\u9650\u5217\u8868\u67E5\u8BE2\u5931\u8D25\uFF0C\u5F85\u5BA1\u6279\u6309\u514D\u5BA1\u96C6\u5408\u4F30\u7B97: ${String(e)}`);
212396
- }
212397
- return feishuPendingApprovalScopes({ requested, granted: input.granted, appScopes });
212398
- }
212399
- async function assessFeishuApprovalUnconfirmed(input) {
212400
- const scopes = await pendingApprovalScopes(input);
212401
- if (scopes.length === 0) return null;
212402
- const modules = feishuPendingApprovalModules({ modules: input.selection.modules, pendingScopes: scopes });
212403
- return { modules, scopes, notice: feishuApprovalUnconfirmedNotice(modules, input.expired) };
212404
- }
212405
- var init_feishu_pending_approval = __esm({
212406
- "../server/src/feishu-pending-approval.ts"() {
212407
- "use strict";
212408
- init_src3();
212409
- }
212410
- });
212411
-
212412
212441
  // ../server/src/github-app-inventory.ts
212413
212442
  async function collectOasisGithubApps(svc) {
212414
212443
  const rows = (await svc.listVariables()).filter((r) => r.scope === "global" || r.scope === "personal");
@@ -218811,6 +218840,44 @@ ${composed}`;
218811
218840
  const data = polled.data;
218812
218841
  let pendingApproval = null;
218813
218842
  const svc = await connectorActorsService();
218843
+ const grantedNow = feishuAuthSelectionRecord(startedSelection.selection, startedSelection.sendAsUserRequested, data).grantedScopes;
218844
+ let stillPending;
218845
+ if (svc) {
218846
+ stillPending = await feishuStillPendingScopes({
218847
+ appId,
218848
+ appSecret,
218849
+ selection: startedSelection.selection,
218850
+ sendAsUserRequested: startedSelection.sendAsUserRequested,
218851
+ ...grantedNow ? { granted: grantedNow } : {}
218852
+ });
218853
+ const risk = stillPending.length > 0 ? await feishuExistingGrantAtRisk({ store: svc, actorId, appId, ...grantedNow ? { newGranted: grantedNow } : {}, now: Date.now() }) : { keep: false };
218854
+ if (risk.keep) {
218855
+ console.error(`[feishu-oauth] \u65B0 token \u672A\u8BC1\u5B9E\u5305\u542B\u5DF2\u6709\u6388\u6743\uFF08\u7F3A ${risk.missing?.join(" ") ?? "\u672A\u56DE\u62A5 scope"}\uFF09\uFF0C\u4FDD\u7559\u539F\u6388\u6743\u3001\u4E0D\u843D\u65B0 token`);
218856
+ const kept = grantedNow ? await recordFeishuPendingApproval({
218857
+ store: svc,
218858
+ actorId,
218859
+ appId,
218860
+ appSecret,
218861
+ selection: startedSelection.selection,
218862
+ sendAsUserRequested: startedSelection.sendAsUserRequested,
218863
+ ...isHumanActorId(actor) ? { applicant: actor } : {},
218864
+ granted: grantedNow,
218865
+ pendingScopes: stillPending,
218866
+ keptExisting: true,
218867
+ now: Date.now()
218868
+ }).catch((e) => {
218869
+ console.error(`[feishu-oauth] \u5F85\u5BA1\u6279\u8BB0\u5F55\u5199\u5165\u5931\u8D25: ${String(e)}`);
218870
+ return null;
218871
+ }) : null;
218872
+ res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify(kept ? { ok: false, final: true, keptExisting: true, pendingApproval: { modules: kept.modules, scopes: kept.scopes }, notice: kept.notice } : {
218873
+ ok: false,
218874
+ final: true,
218875
+ keptExisting: true,
218876
+ error: grantedNow ? "\u98DE\u4E66\u8FD9\u4E00\u8F6E\u7ED9\u7684\u6388\u6743\u4E0D\u5305\u542B\u4F60\u73B0\u6709\u6388\u6743\u7684\u5168\u90E8\u6743\u9650\uFF0C\u4E3A\u4E0D\u5F71\u54CD\u5DF2\u6709\u7684\u98DE\u4E66\u80FD\u529B\uFF0C\u539F\u6388\u6743\u4FDD\u6301\u4E0D\u53D8\u3001\u8FD9\u4E00\u8F6E\u7684\u6388\u6743\u6CA1\u6709\u4FDD\u5B58\u3002" : "\u98DE\u4E66\u6CA1\u6709\u56DE\u62A5\u8FD9\u4E00\u8F6E\u6388\u4E88\u4E86\u54EA\u4E9B\u6743\u9650\uFF0C\u65E0\u6CD5\u786E\u8BA4\u662F\u5426\u5305\u542B\u4F60\u73B0\u6709\u6388\u6743\u7684\u5168\u90E8\u6743\u9650\u3002\u4E3A\u4E0D\u5F71\u54CD\u5DF2\u6709\u7684\u98DE\u4E66\u80FD\u529B\uFF0C\u539F\u6388\u6743\u4FDD\u6301\u4E0D\u53D8\u3001\u8FD9\u4E00\u8F6E\u7684\u6388\u6743\u6CA1\u6709\u4FDD\u5B58\u3002"
218877
+ }));
218878
+ return;
218879
+ }
218880
+ }
218814
218881
  if (svc) {
218815
218882
  if (actorId) {
218816
218883
  await svc.putVariable({ key: "FEISHU_APP_ID", value: appId, scope: "personal", actorId, connectorId: "feishu", encrypted: true });
@@ -218845,6 +218912,7 @@ ${composed}`;
218845
218912
  sendAsUserRequested: startedSelection.sendAsUserRequested,
218846
218913
  ...isHumanActorId(actor) ? { applicant: actor } : {},
218847
218914
  granted: record10.grantedScopes,
218915
+ ...stillPending ? { pendingScopes: stillPending } : {},
218848
218916
  now: Date.now()
218849
218917
  });
218850
218918
  } catch (e) {
@@ -301535,7 +301603,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
301535
301603
  }
301536
301604
  }
301537
301605
  }
301538
- var CLI_VERSION = "2.2.115" ? "2.2.115" : "dev";
301606
+ var CLI_VERSION = "2.2.117" ? "2.2.117" : "dev";
301539
301607
  function apiHeaders(token2, company) {
301540
301608
  const headers = {
301541
301609
  authorization: `Bearer ${token2}`,
@@ -305706,7 +305774,7 @@ function shimScript() {
305706
305774
  }
305707
305775
 
305708
305776
  // src/index.ts
305709
- var PKG_VERSION = true ? "2.2.115" : "dev";
305777
+ var PKG_VERSION = true ? "2.2.117" : "dev";
305710
305778
  var LOCAL_BIN = localBin();
305711
305779
  var NPM_PREFIX = npmPrefix();
305712
305780
  var INSTANCE = DEFAULT_INSTANCE;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oasis_test_v2",
3
- "version": "2.2.115",
3
+ "version": "2.2.117",
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": "9c025c6edd39870a4e40a29026007109bbec04cf"
29
+ "sourceHead": "5abfe31a5f1f2ad0ffa56221ddd536173a1c8f62"
30
30
  }
31
31
  }