@sokeai/cli 1.2.1 → 1.3.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/package.json
CHANGED
|
@@ -15,6 +15,32 @@ NC='\033[0m' # No Color
|
|
|
15
15
|
VERSION=$(node -p "require('./package.json').version")
|
|
16
16
|
echo -e "${GREEN}开始编译 soke-cli v${VERSION}${NC}"
|
|
17
17
|
|
|
18
|
+
# task 11.2 — OAuth 凭证通过 env 注入(替代原 sed 改 Go 源的方式)。
|
|
19
|
+
#
|
|
20
|
+
# 重要:vendor.yaml 的 ${SOKE_CLIENT_ID} / ${SOKE_CLIENT_SECRET} 由
|
|
21
|
+
# sokeai/provider.go 在 init() 阶段 Interpolate,**取的是产物运行时的 env**,
|
|
22
|
+
# 而不是 build 期。因此:
|
|
23
|
+
#
|
|
24
|
+
# * 本地开发:用户在 shell 里 export SOKE_CLIENT_ID / SOKE_CLIENT_SECRET,
|
|
25
|
+
# 然后 go run / 已 build 的 ./bin/soke-cli 启动时 init() 取到。
|
|
26
|
+
# * Release 二进制:client_id / client_secret 不在 build 阶段嵌入产物。
|
|
27
|
+
# 发版 CI 应当在制作 NPM 包时附带一个 wrapper(scripts/run.js)在启动
|
|
28
|
+
# soke-cli 前 setenv 注入(具体方式由 release-lead 在发版 CI 里定),
|
|
29
|
+
# 或要求最终用户自己 export(仅适用于内部分发场景)。
|
|
30
|
+
#
|
|
31
|
+
# 本脚本只做 sanity check + 把当前 shell env 透传到 go build(用于自动化
|
|
32
|
+
# 测试场景中,build 后立即跑 ./bin/soke-cli auth login 走流程)。
|
|
33
|
+
if [ -z "${SOKE_CLIENT_ID:-}" ] || [ -z "${SOKE_CLIENT_SECRET:-}" ]; then
|
|
34
|
+
if [ "${SOKE_CLI_RELEASE:-}" = "1" ]; then
|
|
35
|
+
echo -e "${RED}[FATAL] release 模式必须设置 SOKE_CLIENT_ID / SOKE_CLIENT_SECRET${NC}"
|
|
36
|
+
echo -e "${RED} 二进制本身不嵌入凭证,run.js wrapper 也需要相应的注入逻辑${NC}"
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
echo -e "${YELLOW}[警告] SOKE_CLIENT_ID / SOKE_CLIENT_SECRET 未设置;${NC}"
|
|
40
|
+
echo -e "${YELLOW} 本地 build 后直接 ./bin/soke-cli auth login 会 fail-fast。${NC}"
|
|
41
|
+
fi
|
|
42
|
+
export SOKE_CLIENT_ID SOKE_CLIENT_SECRET
|
|
43
|
+
|
|
18
44
|
# 编译参数
|
|
19
45
|
LDFLAGS="-s -w -X main.Version=${VERSION}"
|
|
20
46
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# task 9.1 — 拦截误引入的 dws-cli upstream 旧常量。
|
|
3
|
+
#
|
|
4
|
+
# 故意提一个引入旧常量的 bad PR 时,CI 该步骤应当失败。
|
|
5
|
+
# 允许出现在 openspec/ 历史 doc 与 docs/dead-code-audit-*.md。
|
|
6
|
+
#
|
|
7
|
+
# 用法:bash scripts/ci/check-legacy-constants.sh
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
PATTERN='OpenDevURL\|AuthorizeURL\|DefaultMCPBaseURL\|DefaultClientID\|DefaultClientSecret\|<YOUR_CLIENT_'
|
|
12
|
+
|
|
13
|
+
# 只扫源码目录;openspec/docs/scripts 历史档案允许出现。
|
|
14
|
+
hits=$(grep -rn -E "$PATTERN" cmd/ internal/ extension/ 2>/dev/null \
|
|
15
|
+
| grep -v vendorplugin/ \
|
|
16
|
+
| grep -v "_test.go" \
|
|
17
|
+
|| true)
|
|
18
|
+
|
|
19
|
+
if [ -n "$hits" ]; then
|
|
20
|
+
echo "[FAIL] 检测到 dws-cli 旧常量残留:"
|
|
21
|
+
echo "$hits"
|
|
22
|
+
echo
|
|
23
|
+
echo "请改用 vendor.Active().Endpoints() / OAuth() 读取(见 cmd/user_auth/vendor.go)。"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
echo "[OK] 无 dws-cli 旧常量残留。"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# task 9.2 — 校验 extension/vendorplugin/builtin/**/vendor.yaml 内 ${VAR}
|
|
3
|
+
# 占位符全部符合白名单(^SOKE_[A-Z0-9_]+$)。
|
|
4
|
+
#
|
|
5
|
+
# 故意写一个 ${HOME} 进 vendor.yaml 时,本步骤应当 FAIL。
|
|
6
|
+
#
|
|
7
|
+
# 用法:bash scripts/ci/check-yaml-env-whitelist.sh
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
WHITELIST_RE='^SOKE_[A-Z0-9_]+$'
|
|
12
|
+
fail=0
|
|
13
|
+
|
|
14
|
+
for yaml in $(find extension/vendorplugin/builtin -name vendor.yaml 2>/dev/null); do
|
|
15
|
+
# 抽出所有 ${...} 占位符内层内容(去掉默认值部分)
|
|
16
|
+
vars=$(grep -oE '\$\{[^{}]+\}' "$yaml" \
|
|
17
|
+
| sed -E 's/^\$\{([^:}]+)(:-[^}]*)?\}$/\1/' \
|
|
18
|
+
| sort -u)
|
|
19
|
+
for v in $vars; do
|
|
20
|
+
if ! echo "$v" | grep -qE "$WHITELIST_RE"; then
|
|
21
|
+
echo "[FAIL] $yaml 引用了非白名单 env: $v"
|
|
22
|
+
fail=1
|
|
23
|
+
fi
|
|
24
|
+
done
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
if [ "$fail" -ne 0 ]; then
|
|
28
|
+
echo
|
|
29
|
+
echo "白名单规则:^SOKE_[A-Z0-9_]+\$(见 extension/vendorplugin/env_whitelist.go)"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
echo "[OK] 所有 vendor.yaml 内 \${VAR} 占位符均符合 SOKE_* 白名单。"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# mcp-stdout-scan.sh — openspec change make-soke-cli-mcp-first §10.3
|
|
3
|
+
#
|
|
4
|
+
# 静态扫描 internal/mcp/ / extension/vendor/builtin/ / internal/courseimport/ 三个
|
|
5
|
+
# 与 mcp stdio 帧纯净性相关的代码树,拦下任何会污染 stdout JSON-RPC 帧的调用:
|
|
6
|
+
# - fmt.Println / fmt.Printf / fmt.Print
|
|
7
|
+
# - fmt.Fprintln / Fprintf / Fprint to os.Stdout
|
|
8
|
+
# - os.Stdout.Write*
|
|
9
|
+
# - 顶层 print( / println( 内建函数
|
|
10
|
+
#
|
|
11
|
+
# 排除 _test.go (测试代码允许写 stdout);
|
|
12
|
+
# 通过 sed 把 `// ...` 注释剥掉再 grep,避免文档/注释里提到 fmt.Println 触发 false positive。
|
|
13
|
+
#
|
|
14
|
+
# 用法: bash scripts/mcp-stdout-scan.sh
|
|
15
|
+
# 退出码: 0 = 干净;1 = 有命中(并打到 stderr)。
|
|
16
|
+
|
|
17
|
+
set -e
|
|
18
|
+
|
|
19
|
+
ROOTS="internal/mcp extension/vendor/builtin internal/courseimport"
|
|
20
|
+
PATTERN='fmt\.(Println|Printf|Print\()|fmt\.(Fprintln|Fprintf|Fprint)\(os\.Stdout|os\.Stdout\.Write|^[[:space:]]*(print|println)\('
|
|
21
|
+
|
|
22
|
+
have_hits=0
|
|
23
|
+
for d in $ROOTS; do
|
|
24
|
+
if [ ! -d "$d" ]; then
|
|
25
|
+
echo "skip 不存在的目录 $d"
|
|
26
|
+
continue
|
|
27
|
+
fi
|
|
28
|
+
files=$(find "$d" -name '*.go' ! -name '*_test.go' 2>/dev/null)
|
|
29
|
+
for f in $files; do
|
|
30
|
+
# 把行号前缀附在文件内容上, 再用 sed 剥 // 注释 (单行注释一律剥), 再 grep
|
|
31
|
+
hits=$(awk '{ printf "%s:%d:%s\n", FILENAME, NR, $0 }' "$f" \
|
|
32
|
+
| sed 's_//.*$__' \
|
|
33
|
+
| grep -E "$PATTERN" \
|
|
34
|
+
|| true)
|
|
35
|
+
if [ -n "$hits" ]; then
|
|
36
|
+
echo "❌ $f 检测到 stdout-write 调用 (会破坏 mcp stdio JSON-RPC 帧):" >&2
|
|
37
|
+
echo "$hits" >&2
|
|
38
|
+
have_hits=1
|
|
39
|
+
fi
|
|
40
|
+
done
|
|
41
|
+
done
|
|
42
|
+
|
|
43
|
+
if [ "$have_hits" -eq 1 ]; then
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
echo "✓ stdout 纯净性扫描通过"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# 回归 auth 命令体感 — task 8.1
|
|
3
|
+
#
|
|
4
|
+
# 串行跑:
|
|
5
|
+
# 1. auth status --json (预期未登录)
|
|
6
|
+
# 2. auth login (人工:浏览器跳转 + 真账号授权)
|
|
7
|
+
# 3. auth status --json (预期已登录)
|
|
8
|
+
# 4. auth logout
|
|
9
|
+
# 5. auth status --json (预期未登录)
|
|
10
|
+
#
|
|
11
|
+
# 用法:
|
|
12
|
+
# SOKE_CLIENT_ID=... SOKE_CLIENT_SECRET=... bash scripts/regress-auth.sh
|
|
13
|
+
# 首次运行前 build:make install 或 go build -o bin/soke-cli main.go
|
|
14
|
+
#
|
|
15
|
+
# 输出建议用 tee 保存,事后人工对比 baseline:
|
|
16
|
+
# bash scripts/regress-auth.sh 2>&1 | tee /tmp/regress-after.txt
|
|
17
|
+
# diff /tmp/regress-before.txt /tmp/regress-after.txt
|
|
18
|
+
|
|
19
|
+
set -u
|
|
20
|
+
|
|
21
|
+
BIN="${SOKE_CLI_BIN:-./bin/soke-cli}"
|
|
22
|
+
if [ ! -x "$BIN" ]; then
|
|
23
|
+
BIN="$(command -v soke-cli 2>/dev/null || echo "$BIN")"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if [ ! -x "$BIN" ]; then
|
|
27
|
+
echo "[FATAL] 找不到 soke-cli 二进制(尝试 SOKE_CLI_BIN env 指定路径)" >&2
|
|
28
|
+
exit 2
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
run_step() {
|
|
32
|
+
local label="$1"; shift
|
|
33
|
+
echo
|
|
34
|
+
echo "==== [$label] $* ===="
|
|
35
|
+
"$@"
|
|
36
|
+
local rc=$?
|
|
37
|
+
echo "==== [$label] exit=$rc ===="
|
|
38
|
+
return $rc
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# baseline 时间戳 mask:让 diff 忽略 expires_at / iat / nbf / exp 等时间字段。
|
|
42
|
+
mask_timestamps() {
|
|
43
|
+
sed -E 's/("(expires_at|iat|nbf|exp|access_token|refresh_token)":\s*)"[^"]*"/\1"<masked>"/g'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
run_step "1.before-status" "$BIN" auth status --json | mask_timestamps
|
|
47
|
+
echo
|
|
48
|
+
echo "请在浏览器完成授权后按回车继续…"
|
|
49
|
+
run_step "2.login" "$BIN" auth login
|
|
50
|
+
read -r _
|
|
51
|
+
run_step "3.after-login-status" "$BIN" auth status --json | mask_timestamps
|
|
52
|
+
run_step "4.logout" "$BIN" auth logout
|
|
53
|
+
run_step "5.final-status" "$BIN" auth status --json | mask_timestamps
|
|
54
|
+
|
|
55
|
+
echo
|
|
56
|
+
echo "[done] 完成。请人工对比 baseline diff(/tmp/regress-before.txt)。"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# auth 回归 baseline 流程(task 8.2)
|
|
2
|
+
|
|
3
|
+
> 配套脚本:`scripts/regress-auth.sh`
|
|
4
|
+
> 用途:在本 change 引入前后两次跑同一脚本,diff 验证零回归。
|
|
5
|
+
|
|
6
|
+
## 1. baseline 采样(本 change 引入**前**)
|
|
7
|
+
|
|
8
|
+
在 master 或上一个 release tag 下:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git checkout <last-release-tag>
|
|
12
|
+
make install # 或:go build -o bin/soke-cli main.go
|
|
13
|
+
SOKE_CLIENT_ID=... SOKE_CLIENT_SECRET=... \
|
|
14
|
+
bash scripts/regress-auth.sh 2>&1 | tee /tmp/regress-before.txt
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`/tmp/regress-before.txt` 即 baseline,包含:
|
|
18
|
+
- 各步 stdout/stderr
|
|
19
|
+
- 各步 exit code(脚本内 `==== [label] exit=N ====` 行)
|
|
20
|
+
- timestamps 已 mask,仅保留结构性差异
|
|
21
|
+
|
|
22
|
+
## 2. 引入后采样
|
|
23
|
+
|
|
24
|
+
切到本 change 分支,重新 build 跑一次:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git checkout worktree-generalize-vendor-plugin
|
|
28
|
+
make install
|
|
29
|
+
SOKE_CLIENT_ID=... SOKE_CLIENT_SECRET=... \
|
|
30
|
+
bash scripts/regress-auth.sh 2>&1 | tee /tmp/regress-after.txt
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 3. diff
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
diff /tmp/regress-before.txt /tmp/regress-after.txt
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
期望:**无差异**(允许时间戳 mask 后的剩余 token 字段差异,因每次实际签发的
|
|
40
|
+
token bytes 不同 —— 但 mask 应已覆盖)。
|
|
41
|
+
|
|
42
|
+
若 diff 显示行为变化,本 change 视为引入回归,**禁止 merge**,
|
|
43
|
+
回到代码层检查 ClientID() / Endpoints() / CallbackPath 取值路径。
|
|
44
|
+
|
|
45
|
+
## 4. keychain 字段验证(任选其一,平台相关)
|
|
46
|
+
|
|
47
|
+
macOS:
|
|
48
|
+
```bash
|
|
49
|
+
security find-generic-password -s "soke-cli" -g 2>&1 | grep -E "acct|cdat"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Linux(libsecret):
|
|
53
|
+
```bash
|
|
54
|
+
secret-tool search service soke-cli
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
字段名(`access_token` / `refresh_token` 等)与 baseline 完全一致。
|
|
58
|
+
|
|
59
|
+
## 5. 三平台 matrix(task 8.3)
|
|
60
|
+
|
|
61
|
+
本 change 不接入 GH Actions yml(避免 PR 卡在未跑通的 CI 任务),由 ①
|
|
62
|
+
`make-soke-cli-mcp-first` 在 same release 时一并引入。matrix 草案:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
# .github/workflows/regress-auth.yml(草案,在 ① 同 release 一起合)
|
|
66
|
+
strategy:
|
|
67
|
+
matrix:
|
|
68
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
69
|
+
jobs:
|
|
70
|
+
regress:
|
|
71
|
+
runs-on: ${{ matrix.os }}
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
- uses: actions/setup-go@v5
|
|
75
|
+
with: { go-version: '1.25' }
|
|
76
|
+
- run: |
|
|
77
|
+
go build -o bin/soke-cli main.go
|
|
78
|
+
# auth login 需要真账号,CI 内只跑 status / logout 路径
|
|
79
|
+
./bin/soke-cli auth status --json
|
|
80
|
+
./bin/soke-cli auth logout
|
|
81
|
+
./bin/soke-cli auth status --json
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
跑出 CI matrix 三个 job 全绿,本 change 才视为通过 task 8.3 AC。
|