oasis_test_v2 2.2.111 → 2.2.113
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/feishu/wrapper.sh +162 -0
- package/dist/index.js +752 -444
- package/package.json +2 -2
package/dist/feishu/wrapper.sh
CHANGED
|
@@ -10,8 +10,16 @@
|
|
|
10
10
|
# 环境变量:
|
|
11
11
|
# LARK_BIN — 真实 lark-cli 绝对路径(避免递归调用自身)
|
|
12
12
|
# FEISHU_CREDS_FILE — 凭据文件路径(内含 export LARKSUITE_CLI_* 行)
|
|
13
|
+
#
|
|
14
|
+
# 按 Agent 限制可用模块(产品反馈「飞书连接器·按 Agent 的权限模型」):只放行所选模块的
|
|
15
|
+
# `lark-cli <domain> …` 与 `lark-cli api <METHOD> /open-apis/<service>/…`,机器人与用户身份一样拦
|
|
16
|
+
# (bot 的企业 token 能调应用开通的全集,飞书侧分不开)。放行表由 inject() 按 FEISHU_AUTH_SELECTION
|
|
17
|
+
# 算好写入凭据文件(feishuModulePolicyEnv),这里不认识任何模块,只按规则表(OASIS_FEISHU_RULES)查。
|
|
18
|
+
# 共用的 drive 命令/接口按子命令、路径细分。**没有放行表、没有有效选择都按一个模块都没开放拦**,不会退成不限制。
|
|
19
|
+
# 被拦时照 lark-cli 的错误形状往 stderr 打一段 JSON、退出码 3(与 lark-cli 自己的鉴权失败同码)。
|
|
13
20
|
|
|
14
21
|
set -euo pipefail
|
|
22
|
+
shopt -s extglob # 放行规则用 +([!/]) / ?(/*) 表示「一段」「零到多段」
|
|
15
23
|
|
|
16
24
|
OASIS_BIN_VAR="LARK_BIN"
|
|
17
25
|
OASIS_CMD_NAME="lark-cli"
|
|
@@ -21,10 +29,164 @@ source "$(dirname "$(realpath "$0")")/../_base/wrapper-base.sh"
|
|
|
21
29
|
oasis_resolve_bin
|
|
22
30
|
oasis_check_available
|
|
23
31
|
|
|
32
|
+
# 放行表只认凭据文件里的:先清掉 agent 环境里可能带进来的同名变量。
|
|
33
|
+
unset OASIS_FEISHU_POLICY OASIS_FEISHU_ALLOW OASIS_FEISHU_RULES OASIS_FEISHU_LABELS OASIS_FEISHU_MODULES
|
|
34
|
+
|
|
24
35
|
# Load feishu credentials into THIS process only (not visible to the agent).
|
|
25
36
|
if [ -n "${FEISHU_CREDS_FILE:-}" ] && [ -f "${FEISHU_CREDS_FILE}" ]; then
|
|
26
37
|
# shellcheck disable=SC1090
|
|
27
38
|
source "${FEISHU_CREDS_FILE}"
|
|
28
39
|
fi
|
|
29
40
|
|
|
41
|
+
# 任何模块都放行的命令(帮助、查参数、内置技能、自检);与 scopes.ts FEISHU_NEUTRAL_COMMANDS 同一份。
|
|
42
|
+
FEISHU_NEUTRAL_COMMANDS=" help schema skills whoami doctor completion auth config profile update "
|
|
43
|
+
# 任何模块都放行的接口 service;与 scopes.ts FEISHU_NEUTRAL_API_SERVICES 同一份。
|
|
44
|
+
FEISHU_NEUTRAL_API=" authen auth "
|
|
45
|
+
|
|
46
|
+
feishu_reply_blocked() {
|
|
47
|
+
printf '{\n "ok": false,\n "error": {\n "type": "oasis_module_blocked",\n "message": "%s",\n "hint": "%s"\n }\n}\n' "$1" "$2" >&2
|
|
48
|
+
exit 3
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
feishu_blocked() {
|
|
52
|
+
# $1 = 规则要求的模块(逗号分隔,空 = 不属于任何模块);$2 = 给人看的命令写法(已过滤成安全字符)。
|
|
53
|
+
local mods="$1" shown="$2" need="" m entry label
|
|
54
|
+
local reconnect="请让配置人在 Oasis 里这个 agent 的飞书连接器详情点「重新连接」"
|
|
55
|
+
case "${OASIS_FEISHU_POLICY:-}" in
|
|
56
|
+
ok) ;;
|
|
57
|
+
none)
|
|
58
|
+
feishu_reply_blocked "本 agent 的飞书连接器还没有保存过可用模块的选择,Oasis 按「一个模块都没开放」处理,${shown} 已被拦下(机器人与用户身份都不可用)。" \
|
|
59
|
+
"${reconnect},勾选需要的模块后完成授权。" ;;
|
|
60
|
+
invalid)
|
|
61
|
+
feishu_reply_blocked "本 agent 的飞书连接器保存的模块选择无法识别,Oasis 按「一个模块都没开放」处理,${shown} 已被拦下(机器人与用户身份都不可用)。" \
|
|
62
|
+
"${reconnect},重新勾选模块后完成授权。" ;;
|
|
63
|
+
*)
|
|
64
|
+
feishu_reply_blocked "本次运行没有拿到飞书模块放行表,Oasis 不放行 ${shown}(机器人与用户身份都不可用)。" \
|
|
65
|
+
"请重新发起任务;仍出现请联系 Oasis 管理员检查飞书连接器。" ;;
|
|
66
|
+
esac
|
|
67
|
+
if [ -n "$mods" ]; then
|
|
68
|
+
for m in ${mods//,/ }; do
|
|
69
|
+
label="$m"
|
|
70
|
+
for entry in ${OASIS_FEISHU_LABELS:-}; do
|
|
71
|
+
if [ "${entry%%=*}" = "$m" ]; then label="${entry#*=}"; break; fi
|
|
72
|
+
done
|
|
73
|
+
need="${need:+${need}」或「}${label}"
|
|
74
|
+
done
|
|
75
|
+
feishu_reply_blocked "本 agent 的飞书连接器没有开放「${need}」模块,${shown} 已被 Oasis 拦下(机器人与用户身份都不可用)。当前开放的模块:${OASIS_FEISHU_MODULES:-无}。" \
|
|
76
|
+
"如需使用,${reconnect},勾选「${need}」后完成授权。"
|
|
77
|
+
fi
|
|
78
|
+
feishu_reply_blocked "${shown} 不属于任何可勾选的飞书功能模块;本 agent 的飞书调用已按模块限制,Oasis 不放行它。当前开放的模块:${OASIS_FEISHU_MODULES:-无}。" \
|
|
79
|
+
"请改用已开放模块对应的 lark-cli 命令;共用的 drive 子命令须紧跟在 drive 之后写。确需此能力请联系 Oasis 管理员。"
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# 只把「看起来像命令名 / service 名」的字符串回显出来,其余一律写成占位——它要进 JSON。
|
|
83
|
+
feishu_safe() {
|
|
84
|
+
case "$1" in
|
|
85
|
+
''|*[!A-Za-z0-9_.+-]*) printf '%s' "该命令" ;;
|
|
86
|
+
*) printf '%s' "$1" ;;
|
|
87
|
+
esac
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# 按规则表判 $1(cmd/<domain>/… 或 api/<METHOD>/<service>/…):命中且所需模块里有一个已放行 → 放行;
|
|
91
|
+
# 命中但都没放行 → 拦并说缺哪个;一条都没命中 → 拦(不属于任何模块)。
|
|
92
|
+
feishu_check_key() {
|
|
93
|
+
local key="$1" shown="$2" entry pat mods m
|
|
94
|
+
set -f
|
|
95
|
+
for entry in ${OASIS_FEISHU_RULES:-}; do
|
|
96
|
+
pat="${entry%=*}"; mods="${entry##*=}"
|
|
97
|
+
# shellcheck disable=SC2254
|
|
98
|
+
case "$key" in
|
|
99
|
+
$pat)
|
|
100
|
+
set +f
|
|
101
|
+
if [ "${OASIS_FEISHU_POLICY:-}" = "ok" ]; then
|
|
102
|
+
for m in ${mods//,/ }; do
|
|
103
|
+
case "${OASIS_FEISHU_ALLOW:-}" in *" $m "*) return 0 ;; esac
|
|
104
|
+
done
|
|
105
|
+
fi
|
|
106
|
+
feishu_blocked "$mods" "$shown" ;;
|
|
107
|
+
esac
|
|
108
|
+
done
|
|
109
|
+
set +f
|
|
110
|
+
feishu_blocked "" "$shown"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# 命令行里的一个词能不能原样进规则 key:只允许命令名字符,其余写成 ?(不会命中任何规则)。
|
|
114
|
+
feishu_seg() {
|
|
115
|
+
case "$1" in
|
|
116
|
+
''|*[!A-Za-z0-9_.+-]*) printf '?' ;;
|
|
117
|
+
*) printf '%s' "$1" ;;
|
|
118
|
+
esac
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
feishu_enforce_modules() {
|
|
122
|
+
local args=("$@") i=0 n=$# cmd=""
|
|
123
|
+
# 跳过命令前的全局参数(--profile X、-h/--help、-v/--version)。
|
|
124
|
+
while [ "$i" -lt "$n" ]; do
|
|
125
|
+
case "${args[$i]}" in
|
|
126
|
+
--profile) i=$((i + 2)) ;;
|
|
127
|
+
-*) i=$((i + 1)) ;;
|
|
128
|
+
*) cmd="${args[$i]}"; break ;;
|
|
129
|
+
esac
|
|
130
|
+
done
|
|
131
|
+
[ -n "$cmd" ] || return 0 # 只有 --help / --version 之类
|
|
132
|
+
case "$FEISHU_NEUTRAL_COMMANDS" in *" $cmd "*) return 0 ;; esac
|
|
133
|
+
|
|
134
|
+
if [ "$cmd" = "api" ]; then
|
|
135
|
+
# lark-cli api <METHOD> <path> [flags]:api 之后第一、二个位置参数为 method、path(跳过带值的参数)。
|
|
136
|
+
local pos=0 method="" path="" a
|
|
137
|
+
i=$((i + 1))
|
|
138
|
+
while [ "$i" -lt "$n" ]; do
|
|
139
|
+
a="${args[$i]}"
|
|
140
|
+
case "$a" in
|
|
141
|
+
--as|--data|--file|--format|--jq|-q|--output|-o|--page-delay|--page-limit|--page-size|--params|--profile) i=$((i + 2)); continue ;;
|
|
142
|
+
-*) i=$((i + 1)); continue ;;
|
|
143
|
+
esac
|
|
144
|
+
pos=$((pos + 1))
|
|
145
|
+
if [ "$pos" -eq 1 ]; then method="$a"; fi
|
|
146
|
+
if [ "$pos" -eq 2 ]; then path="$a"; break; fi
|
|
147
|
+
i=$((i + 1))
|
|
148
|
+
done
|
|
149
|
+
[ -n "$path" ] || return 0 # 没给 path:lark-cli 自己报用法错,不会发请求
|
|
150
|
+
# 归一成 <service>/…:lark-cli 接受完整 URL、/open-apis/ 前缀可省、前导斜杠可省;连续斜杠并成一个。
|
|
151
|
+
local p="$path"
|
|
152
|
+
p="${p#http://}"; p="${p#https://}"
|
|
153
|
+
case "$path" in http://*|https://*) p="${p#*/}" ;; esac
|
|
154
|
+
while [ "${p#/}" != "$p" ]; do p="${p#/}"; done
|
|
155
|
+
p="${p#open-apis/}"
|
|
156
|
+
while [ "${p#/}" != "$p" ]; do p="${p#/}"; done
|
|
157
|
+
p="${p%%[?#]*}"
|
|
158
|
+
while [ "${p//\/\//\/}" != "$p" ]; do p="${p//\/\//\/}"; done
|
|
159
|
+
# 路径里带 ..、. 段或百分号编码的,不去猜它最后落到哪个接口——直接拒。
|
|
160
|
+
case "/$p/" in *..*|*%*|*\\*|*/./*) feishu_blocked "" "lark-cli api(路径含 .. 或编码字符)" ;; esac
|
|
161
|
+
local svc="${p%%/*}"
|
|
162
|
+
case "$FEISHU_NEUTRAL_API" in *" $svc "*) return 0 ;; esac
|
|
163
|
+
case "$p" in *[!A-Za-z0-9_./:-]*) feishu_blocked "" "lark-cli api(路径含非法字符)" ;; esac
|
|
164
|
+
# 方法名转大写(macOS 自带 bash 3.2 没有 ${x^^})。
|
|
165
|
+
method="$(feishu_seg "$method" | tr '[:lower:]' '[:upper:]')"
|
|
166
|
+
feishu_check_key "api/$method/$p" "lark-cli api …/open-apis/$(feishu_safe "$svc")/…"
|
|
167
|
+
return 0
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
# lark-cli <domain> [子命令] [方法]:只取紧跟在 domain 后面的词(drive 这类共用 domain 按子命令分模块);
|
|
171
|
+
# domain 后面先出现参数的,key 里记成「-」,共用 domain 的细分规则一条都不会命中。
|
|
172
|
+
local key="cmd/$(feishu_seg "$cmd")" depth=0 j=$((i + 1)) only_help=1 w
|
|
173
|
+
while [ "$j" -lt "$n" ]; do
|
|
174
|
+
case "${args[$j]}" in -h|--help) ;; *) only_help=0 ;; esac
|
|
175
|
+
j=$((j + 1))
|
|
176
|
+
done
|
|
177
|
+
[ "$only_help" -eq 1 ] && [ $((i + 1)) -lt "$n" ] && return 0 # lark-cli <domain> --help
|
|
178
|
+
j=$((i + 1))
|
|
179
|
+
while [ "$j" -lt "$n" ] && [ "$depth" -lt 2 ]; do
|
|
180
|
+
w="${args[$j]}"
|
|
181
|
+
case "$w" in -*) key="$key/-"; break ;; esac
|
|
182
|
+
key="$key/$(feishu_seg "$w")"
|
|
183
|
+
depth=$((depth + 1)); j=$((j + 1))
|
|
184
|
+
done
|
|
185
|
+
local shown="lark-cli $(feishu_safe "$cmd")"
|
|
186
|
+
[ "$depth" -ge 1 ] && shown="$shown $(feishu_safe "${args[$((i + 1))]}")"
|
|
187
|
+
feishu_check_key "$key" "$shown"
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
feishu_enforce_modules "$@"
|
|
191
|
+
|
|
30
192
|
exec "$LARK_BIN" "$@"
|