msdevflow 0.7.4 → 0.7.6
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/README.md +39 -40
- package/lib/bootstrap.js +485 -103
- package/package.json +2 -2
- package/skill/{msdevflow → msd}/README.md +54 -39
- package/skill/{msdevflow → msd}/SKILL.md +26 -35
- package/skill/{msdevflow → msd}/references/ci-and-review.md +2 -2
- package/skill/{msdevflow → msd}/references/command-capabilities.md +1 -1
- package/skill/{msdevflow → msd}/references/create-issue.md +1 -1
- package/skill/{msdevflow → msd}/references/design-and-development.md +1 -1
- package/skill/{msdevflow → msd}/references/openlibing-ci.md +9 -2
- package/skill/{msdevflow → msd}/references/pr-and-ci.md +2 -2
- package/skill/{msdevflow → msd}/references/recovery.md +1 -1
- package/skill/{msdevflow → msd}/references/review-and-merge.md +2 -2
- package/skill/{msdevflow → msd}/references/setup-and-issue.md +2 -2
- package/skill/{msdevflow → msd}/references/state-and-safety.md +1 -1
- package/skill/{msdevflow → msd}/scripts/openlibing_ci.py +62 -21
- package/skill/msd-ci/SKILL.md +15 -0
- package/skill/msd-code-review/SKILL.md +15 -0
- package/skill/msd-create-issue/SKILL.md +15 -0
- package/skill/msd-develop/SKILL.md +15 -0
- package/skill/msd-discover/SKILL.md +15 -0
- package/skill/msd-feedback/SKILL.md +15 -0
- package/skill/msd-issue/SKILL.md +15 -0
- package/skill/msd-merge/SKILL.md +15 -0
- package/skill/msd-openlibing-auth/SKILL.md +15 -0
- package/skill/msd-pr/SKILL.md +15 -0
- /package/skill/{msdevflow → msd}/references/code-review.md +0 -0
- /package/skill/{msdevflow → msd}/scripts/requirements.txt +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msdevflow",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
4
4
|
"description": "Install the msdevflow GitCode skill and its runtime dependencies",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"bin/",
|
|
11
11
|
"lib/",
|
|
12
12
|
"skill/",
|
|
13
|
-
"!skill
|
|
13
|
+
"!skill/**/scripts/test_openlibing_ci.py",
|
|
14
14
|
"!skill/**/__pycache__/**",
|
|
15
15
|
"!skill/**/*.pyc"
|
|
16
16
|
],
|
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
#
|
|
1
|
+
# msd
|
|
2
2
|
|
|
3
|
-
通用 GitCode Issue 到 PR 合入 workflow
|
|
3
|
+
通用 GitCode Issue 到 PR 合入 workflow Skill 套件。业务规则只存在于核心 `msd`;十个 `msd-<action>` 薄路由 Skill 让 Claude Code、Codex 和 OpenCode 在输入阶段展示并补全可用 action。
|
|
4
4
|
|
|
5
5
|
## 1. Action 模型
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
输入 `/msd-`(Claude Code/OpenCode)或 `$msd-`(Codex)即可筛选:
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
msd-discover
|
|
11
|
+
msd-create-issue
|
|
12
|
+
msd-issue
|
|
13
|
+
msd-develop
|
|
14
|
+
msd-pr
|
|
15
|
+
msd-ci
|
|
16
|
+
msd-openlibing-auth
|
|
17
|
+
msd-feedback
|
|
18
|
+
msd-code-review
|
|
19
|
+
msd-merge
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
每个薄路由只固定唯一 action、保留调用正文,并从相对路径 `../msd/SKILL.md` 加载同一 skills 根目录中的核心,不复制业务规则;核心 references 继续以 `../msd/` 为基准。直接调用核心 `msd` 会运行完整作者 E2E,不会在提交后弹出 Question 菜单;`/msd action=<name>`、`$msd action=<name>` 仍作为兼容调用,但参数本身没有跨客户端枚举下拉。
|
|
20
23
|
|
|
21
24
|
支持:
|
|
22
25
|
|
|
@@ -42,7 +45,7 @@ Claude Code 使用 `AskUserQuestion`,Codex 使用 `request_user_input`,OpenC
|
|
|
42
45
|
|
|
43
46
|
## 2. 完整作者 E2E
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
直接调用核心 `msd` 且不提供 `action=` 时,从环境、CLI 能力和仓库画像开始运行完整流程:
|
|
46
49
|
|
|
47
50
|
```text
|
|
48
51
|
discover -> issue -> develop -> pr -> ci
|
|
@@ -69,12 +72,12 @@ discover -> issue -> develop -> pr -> ci
|
|
|
69
72
|
|
|
70
73
|
## 4. 调用示例
|
|
71
74
|
|
|
72
|
-
以下示例使用 Claude Code 的 `/
|
|
75
|
+
以下示例使用 Claude Code 的 `/msd` 形式。Codex 使用 `$msd`,OpenCode 可从 `/skills` 选择 `msd`;OpenCode 的 `@` 不用于 Skill。单项能力优先使用各客户端输入补全中的 `msd-<action>`,正文中的任务参数保持不变。
|
|
73
76
|
|
|
74
|
-
###
|
|
77
|
+
### 运行完整 E2E
|
|
75
78
|
|
|
76
79
|
```text
|
|
77
|
-
/
|
|
80
|
+
/msd
|
|
78
81
|
处理 https://gitcode.com/Ascend/example/issues/123。
|
|
79
82
|
本地仓库:D:\work\example
|
|
80
83
|
canonical:Ascend/example
|
|
@@ -85,7 +88,7 @@ Fork:myname/example
|
|
|
85
88
|
### 只发现候选 Issue
|
|
86
89
|
|
|
87
90
|
```text
|
|
88
|
-
/
|
|
91
|
+
/msd-discover
|
|
89
92
|
查询 Ascend/example 中分配给当前账号的开放 Issue,列出仍需处理的候选。
|
|
90
93
|
```
|
|
91
94
|
|
|
@@ -94,7 +97,7 @@ Fork:myname/example
|
|
|
94
97
|
### 只创建 Issue
|
|
95
98
|
|
|
96
99
|
```text
|
|
97
|
-
/
|
|
100
|
+
/msd-create-issue
|
|
98
101
|
在 Ascend/example 提一个 bug:升级后首次启动失败,错误信息和环境如下……
|
|
99
102
|
使用 guided 模式,先给我完整预览,确认后再创建。
|
|
100
103
|
```
|
|
@@ -106,7 +109,7 @@ Fork:myname/example
|
|
|
106
109
|
### 只接取和核验 Issue
|
|
107
110
|
|
|
108
111
|
```text
|
|
109
|
-
/
|
|
112
|
+
/msd-issue
|
|
110
113
|
处理 https://gitcode.com/Ascend/example/issues/123。
|
|
111
114
|
本地仓库:D:\work\example
|
|
112
115
|
```
|
|
@@ -116,7 +119,7 @@ Fork:myname/example
|
|
|
116
119
|
### 只开发和本地验证
|
|
117
120
|
|
|
118
121
|
```text
|
|
119
|
-
/
|
|
122
|
+
/msd-develop
|
|
120
123
|
Issue:https://gitcode.com/Ascend/example/issues/123
|
|
121
124
|
本地仓库:D:\work\example
|
|
122
125
|
```
|
|
@@ -126,7 +129,7 @@ Issue:https://gitcode.com/Ascend/example/issues/123
|
|
|
126
129
|
### 只创建 PR
|
|
127
130
|
|
|
128
131
|
```text
|
|
129
|
-
/
|
|
132
|
+
/msd-pr
|
|
130
133
|
Issue:https://gitcode.com/Ascend/example/issues/123
|
|
131
134
|
本地仓库:D:\work\example
|
|
132
135
|
canonical:Ascend/example
|
|
@@ -138,28 +141,28 @@ source:myname/example
|
|
|
138
141
|
### 只处理 CI
|
|
139
142
|
|
|
140
143
|
```text
|
|
141
|
-
/
|
|
144
|
+
/msd-ci
|
|
142
145
|
PR:https://gitcode.com/Ascend/example/pulls/456
|
|
143
146
|
本地仓库:D:\work\example
|
|
144
147
|
```
|
|
145
148
|
|
|
146
|
-
CI 通过后立即停止,不处理 feedback 或 merge。识别为 openLiBing 且只读 API 返回 401/403
|
|
149
|
+
CI 通过后立即停止,不处理 feedback 或 merge。识别为 openLiBing 且只读 API 返回 401/403 时,使用 setup 创建的受管 Python 运行时和其中的 Playwright 打开已有的系统 Chrome/Edge 或 Playwright Chromium,认证成功后继续本 action;运行时不可用时停止并要求运行 `npx msdevflow@latest setup`,不会在 action 内调用 pip,也不会自动下载浏览器。浏览器不可用时输出可复制的 OAuth 链接并停止为 `blocked: browser-required`。可用 `autonomous-ci` 只授权同一 PR 上根因明确的最小 CI 修复循环。
|
|
147
150
|
|
|
148
151
|
### 只验证 openLiBing OAuth
|
|
149
152
|
|
|
150
153
|
```text
|
|
151
|
-
/
|
|
154
|
+
/msd-openlibing-auth
|
|
152
155
|
本地仓库:D:\work\example
|
|
153
156
|
```
|
|
154
157
|
|
|
155
|
-
本 action 从当前工作区唯一识别 canonical,只在该仓库内按“当前分支关联 PR → 最近开放 PR → 最近合入 PR”的顺序选择一个包含 openLiBing run 的验证目标,不要求用户提供 PR
|
|
158
|
+
本 action 从当前工作区唯一识别 canonical,只在该仓库内按“当前分支关联 PR → 最近开放 PR → 最近合入 PR”的顺序选择一个包含 openLiBing run 的验证目标,不要求用户提供 PR。它使用 setup 创建的受管 Python 运行时和其中的 Playwright,并使用已有的系统 Chrome/Edge 或 Playwright Chromium 打开可见窗口;运行时不可用时要求运行 `npx msdevflow@latest setup`,不会在 action 内调用 pip,也不会自动下载浏览器。用户亲自完成 GitCode 登录和授权。浏览器不可用时输出可复制的 OAuth 链接并停止为 `blocked: browser-required`;人工浏览器登录不等于验证完成。只有 OAuth 后对固定 run 的真实只读请求成功才完成,随后立即停止,不进入 `ci`。
|
|
156
159
|
|
|
157
160
|
它不读取或输出 GitCode Token。openLiBing Token 只驻留当前 Python 进程,固定显示为 `redacted`;持久化的只有受管专用 profile 中的 GitCode 浏览器登录态。
|
|
158
161
|
|
|
159
162
|
### 只处理自己 PR 的意见
|
|
160
163
|
|
|
161
164
|
```text
|
|
162
|
-
/
|
|
165
|
+
/msd-feedback
|
|
163
166
|
PR:https://gitcode.com/Ascend/example/pulls/456
|
|
164
167
|
本地仓库:D:\work\example
|
|
165
168
|
```
|
|
@@ -169,7 +172,7 @@ PR:https://gitcode.com/Ascend/example/pulls/456
|
|
|
169
172
|
### 检视他人的 PR
|
|
170
173
|
|
|
171
174
|
```text
|
|
172
|
-
/
|
|
175
|
+
/msd-code-review
|
|
173
176
|
PR:https://gitcode.com/Ascend/example/pulls/789
|
|
174
177
|
```
|
|
175
178
|
|
|
@@ -180,7 +183,7 @@ PR:https://gitcode.com/Ascend/example/pulls/789
|
|
|
180
183
|
### 只核验并合入
|
|
181
184
|
|
|
182
185
|
```text
|
|
183
|
-
/
|
|
186
|
+
/msd-merge
|
|
184
187
|
PR:https://gitcode.com/Ascend/example/pulls/456
|
|
185
188
|
```
|
|
186
189
|
|
|
@@ -224,7 +227,7 @@ GitCode CLI 会打开官方页面让用户创建 Token,再在 CLI 自己的终
|
|
|
224
227
|
|
|
225
228
|
## 6. 安装
|
|
226
229
|
|
|
227
|
-
npm
|
|
230
|
+
npm 包 `msdevflow` 同时携带 `msd` Skill 套件和 setup 程序。首次安装:
|
|
228
231
|
|
|
229
232
|
```bash
|
|
230
233
|
npx msdevflow setup
|
|
@@ -238,26 +241,38 @@ npx msdevflow@latest setup
|
|
|
238
241
|
|
|
239
242
|
`setup` 是幂等的:内容一致时保持 `current`,内容不同时原子更新。
|
|
240
243
|
|
|
241
|
-
`setup` 默认检测 PATH 中的 Claude Code、Codex 和 OpenCode,先展示客户端、物理 skill 目标、安装或更新状态、GitCode CLI 归属、registry
|
|
244
|
+
`setup` 默认检测 PATH 中的 Claude Code、Codex 和 OpenCode,先展示客户端、物理 skill 目标、安装或更新状态、GitCode CLI 归属、registry、安装模式、受管 Python 运行时、依赖命令和认证方式;用户确认后,在同一次运行中:
|
|
242
245
|
|
|
243
|
-
1.
|
|
244
|
-
2.
|
|
245
|
-
3.
|
|
246
|
+
1. 创建、修复或复用 msdevflow 受管 Python venv;
|
|
247
|
+
2. 用受管 Python 安装内置 `scripts/requirements.txt` 中的 Playwright 包;
|
|
248
|
+
3. 安装或升级官方 GitCode npm CLI;
|
|
246
249
|
4. 验收 workflow 所需 schema/API;
|
|
247
|
-
5. CLI 未认证时运行选定命令的 `auth login --web
|
|
250
|
+
5. CLI 未认证时运行选定命令的 `auth login --web`;
|
|
251
|
+
6. 从 npm 包内的 `skill/msd` 核心和十个 `skill/msd-<action>` 路由器原子安装或更新整套入口。
|
|
252
|
+
|
|
253
|
+
受管运行时默认位于:
|
|
254
|
+
|
|
255
|
+
```text
|
|
256
|
+
Windows: %LOCALAPPDATA%\msdevflow\python
|
|
257
|
+
macOS/Linux: ${XDG_DATA_HOME:-$HOME/.local/share}/msdevflow/python
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
可用 `MSDEVFLOW_PYTHON_DIR` 覆盖,值必须是绝对路径或以 `~` 开头;setup 与后续 action 必须使用同一配置。`venv` 属于 CPython 标准库,但精简发行版可能缺失;Debian/Ubuntu 通常需要用户自行安装 `python3-venv`。setup 不执行 sudo,不回退到全局 pip,也不使用 `--break-system-packages`。来源不明或 marker 损坏的运行时目录不会被接管。
|
|
248
261
|
|
|
249
262
|
客户端到物理目录的映射:
|
|
250
263
|
|
|
251
264
|
```text
|
|
252
|
-
Claude Code -> ~/.claude/skills/
|
|
253
|
-
Codex -> ~/.agents/skills/
|
|
254
|
-
仅 OpenCode -> ~/.agents/skills/
|
|
265
|
+
Claude Code -> ~/.claude/skills/{msd,msd-*}
|
|
266
|
+
Codex -> ~/.agents/skills/{msd,msd-*}
|
|
267
|
+
仅 OpenCode -> ~/.agents/skills/{msd,msd-*}
|
|
255
268
|
OpenCode + Claude Code -> 复用 Claude 目标
|
|
256
269
|
OpenCode + Codex -> 复用 Agent Skills 目标
|
|
257
|
-
Claude Code + Codex ->
|
|
258
|
-
三者同时安装 ->
|
|
270
|
+
Claude Code + Codex -> 两套受管副本
|
|
271
|
+
三者同时安装 -> 两套受管副本,并提示 OpenCode 双路径发现
|
|
259
272
|
```
|
|
260
273
|
|
|
274
|
+
每个物理目标都包含一个 `msd` 核心和十个 `msd-<action>` 路由器;业务规则仍只有一份。
|
|
275
|
+
|
|
261
276
|
显式选择客户端、只读预检或自定义目录:
|
|
262
277
|
|
|
263
278
|
```bash
|
|
@@ -277,7 +292,7 @@ npm 包尚未发布时,可从当前源码/发布目录运行等价入口:
|
|
|
277
292
|
node ./msdevflow/bin/msdevflow.js setup
|
|
278
293
|
```
|
|
279
294
|
|
|
280
|
-
`setup` 不下载或启动 Chromium。GitCode Token 只由 GitCode CLI 自己的终端提示接收并验证;setup 父进程不读取、输出或转存 Token,也不要求用户把 Token 传给 Agent。每个已有
|
|
295
|
+
`setup` 不下载或启动 Chromium。GitCode Token 只由 GitCode CLI 自己的终端提示接收并验证;setup 父进程不读取、输出或转存 Token,也不要求用户把 Token 传给 Agent。每个已有 `msd` 或 `msd-<action>` entry 的 manifest 都必须精确匹配自身名称才允许更新;来源不明的目录、文件或符号链接会阻断整套安装。旧 `msdevflow` 目录只有在 manifest 精确证明由本包管理时,才会在新套件全部切换并验证后安全迁移;失败时回滚整套变更。安装后重启或重新加载对应客户端。
|
|
281
296
|
|
|
282
297
|
## 7. 仓库画像和 PR 模板
|
|
283
298
|
|
|
@@ -1,52 +1,43 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: msd
|
|
3
3
|
description: >
|
|
4
|
-
通用 GitCode Issue 到 PR
|
|
4
|
+
通用 GitCode Issue 到 PR 合入工作流核心。直接调用 msd 时运行完整作者端到端流程;也接受 action=discover、create-issue、issue、develop、pr、ci、openlibing-auth、feedback、code-review 或 merge 兼容参数。推荐通过独立的 msd-<action> Skill 在输入时发现并选择单项能力。适用于发现、新建或接取 GitCode Issue、开发并创建 PR、处理 CI、验证 openLiBing OAuth、处理自己 PR 的检视意见、检视他人 PR,以及在独立审批和显式确认后合入。仅适用于已授权的 GitCode 仓库。
|
|
5
5
|
compatibility: Requires Git, Node.js >=18, Python >=3.10, GitCode access, and the setup-installed GitCode CLI. Supports Claude Code, Codex, and OpenCode.
|
|
6
6
|
metadata:
|
|
7
|
-
version:
|
|
7
|
+
version: 3.0.0
|
|
8
8
|
source: msdevflow
|
|
9
|
+
role: core
|
|
9
10
|
---
|
|
10
11
|
|
|
11
|
-
#
|
|
12
|
+
# msd:GitCode Issue 到 PR 合入
|
|
12
13
|
|
|
13
|
-
把 GitCode
|
|
14
|
+
把 GitCode 工作拆成可独立发现和调用的 action,不硬编码组织、默认分支、CI、分支命名、合并方式或机器人协议。安装套件同时提供核心 `msd` 和十个薄路由 Skill:Claude Code 与 OpenCode 输入 `/msd-`、Codex 输入 `$msd-`,即可在客户端的 Skill 补全中查看 action。
|
|
14
15
|
|
|
15
16
|
## Action 路由
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
推荐入口为 `msd-<action>`。薄路由 Skill 只固定一个 action、保留调用正文并加载本核心,不复制业务规则。核心也兼容字面量参数 `action=<name>`;显式 action 直接路由,未知 action 停止并列出有效值,不做远端写入。
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
直接调用核心 `msd` 且没有 `action=` 时,运行完整作者 E2E,不显示运行时 Question 菜单,也不根据自然语言改成某个独立 action。完整 E2E 内部按权威证据定位当前阶段并渐进加载规则。
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
若薄路由 Skill 固定的 action 与调用正文中的 `action=` 冲突,停止为 `blocked: action-conflict`,不得猜测或执行远端写入。
|
|
23
|
+
|
|
24
|
+
可发现入口:
|
|
22
25
|
|
|
23
26
|
```text
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
│ └─ PR 后续
|
|
36
|
-
│ ├─ feedback
|
|
37
|
-
│ └─ merge
|
|
38
|
-
└─ 独立工具
|
|
39
|
-
├─ openlibing-auth
|
|
40
|
-
└─ code-review
|
|
27
|
+
msd
|
|
28
|
+
msd-discover
|
|
29
|
+
msd-create-issue
|
|
30
|
+
msd-issue
|
|
31
|
+
msd-develop
|
|
32
|
+
msd-pr
|
|
33
|
+
msd-ci
|
|
34
|
+
msd-openlibing-auth
|
|
35
|
+
msd-feedback
|
|
36
|
+
msd-code-review
|
|
37
|
+
msd-merge
|
|
41
38
|
```
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
1. 顶层“完整端到端流程”不是 action;选中后按“完整作者 E2E”执行,并在内部将本次路由记为 `full-e2e`。
|
|
46
|
-
2. 每级原生菜单都把推荐项放在首位,并按宿主约定标明推荐:顶层推荐“完整端到端流程”;作者工作流分类推荐“Issue 管理”;各叶子层分别推荐 `discover`、`develop`、`feedback` 和 `openlibing-auth`。不得为了改变推荐项而提前探测仓库或远端。
|
|
47
|
-
3. 选中叶子 action 后,等同于用户显式提供了对应 `action=<name>`,严格遵守显式 action 契约;保留调用正文中已经给出的 URL、路径、仓库和模式等参数。
|
|
48
|
-
4. 宿主没有可用选择工具、选择工具在当前模式被禁用,或处于非交互运行时,只输出当前层的编号文本选项并停止等待用户回复;不得自行选择默认项,也不得把多层菜单一次性展开。
|
|
49
|
-
5. 只要调用中没有字面量 `action=<name>`,即使自然语言看似指向某个流程,也必须从顶层菜单开始;不得根据意图猜测跳过菜单。菜单选择属于当前 skill 调用,选定后立即继续,不要求用户重新输入 `/msdevflow`。
|
|
40
|
+
薄路由选定后,等同于向本核心显式提供对应 `action=<name>`,并严格遵守显式 action 契约。
|
|
50
41
|
|
|
51
42
|
| action | 目标 | 主要输入 | 完成后立即停止于 | 必读文件 |
|
|
52
43
|
|---|---|---|---|---|
|
|
@@ -61,7 +52,7 @@ metadata:
|
|
|
61
52
|
| `code-review` | 检视他人的 PR,发布 finding 或 `/lgtm` | 他人 PR | `review-findings`、`review-passed`、`review-incomplete`、`waiting` 或 `blocked` | [references/code-review.md](references/code-review.md) |
|
|
62
53
|
| `merge` | 核验门禁并在最终确认后合入 | canonical PR | `merged`、`waiting` 或 `blocked` | [references/review-and-merge.md](references/review-and-merge.md) |
|
|
63
54
|
|
|
64
|
-
`code-review`
|
|
55
|
+
`code-review` 只能通过 `msd-code-review` 或兼容参数 `action=code-review` 独立调用,永不进入作者 E2E,不得检视或批准当前账号自己的 PR。它固定当前 head,完整检视权威 diff、必要上下文和既有 discussions:有高置信度问题时发布经确认且逐字回读的 finding,不发送 `/lgtm`;没有问题、没有有效未解决意见且覆盖完整时,在针对当前 PR/head 明确确认后先发布带尾签摘要,再原样发送 `/lgtm`。它不发送 `/approve`、`/merge`,不修改作者代码。
|
|
65
56
|
|
|
66
57
|
## 显式 action 契约
|
|
67
58
|
|
|
@@ -75,7 +66,7 @@ metadata:
|
|
|
75
66
|
|
|
76
67
|
## 完整作者 E2E
|
|
77
68
|
|
|
78
|
-
|
|
69
|
+
直接调用核心 `msd` 且未提供 `action=` 时,从 Phase 0 环境、CLI 能力和仓库画像开始运行完整流程;调用正文可以提供完整 E2E 所需的 URL、路径、仓库和模式。“从头开始”只表示重新读取事实,不表示重复创建资源或重复评论。按证据幂等跳过已完成步骤:
|
|
79
70
|
|
|
80
71
|
```text
|
|
81
72
|
discover -> issue -> develop -> pr -> ci
|
|
@@ -97,7 +88,7 @@ discover -> issue -> develop -> pr -> ci
|
|
|
97
88
|
1. 固定 `gitcode_command`:无 Python 同名工具时为 `gitcode`;有 Python `gitcode` 时保留它并使用 `gitcode-npm`。来源不明时停止,不覆盖。
|
|
98
89
|
2. 检查当前目录;若不是 Git 仓库,自动探测直接子目录中的 Git 仓库及 remotes。
|
|
99
90
|
3. 确认 canonical repository、source repository、operation target、当前账号和授权范围。
|
|
100
|
-
4. 除纯只读 `discover` 外,显式 action 先从 [references/setup-and-issue.md](references/setup-and-issue.md) 只读取公共环境、仓库上下文和最小充分仓库画像,不执行其中的 Issue 接取业务;随后只加载该 action 对应 reference 及实际触发的深层规则。`create-issue` 的模板选择和写入只按 [references/create-issue.md](references/create-issue.md),不执行候选发现或既有 Issue 核验。`code-review` 只使用公共只读画像和 [references/code-review.md](references/code-review.md),不加载作者 feedback/merge
|
|
91
|
+
4. 除纯只读 `discover` 外,显式 action 先从 [references/setup-and-issue.md](references/setup-and-issue.md) 只读取公共环境、仓库上下文和最小充分仓库画像,不执行其中的 Issue 接取业务;随后只加载该 action 对应 reference 及实际触发的深层规则。`create-issue` 的模板选择和写入只按 [references/create-issue.md](references/create-issue.md),不执行候选发现或既有 Issue 核验。`code-review` 只使用公共只读画像和 [references/code-review.md](references/code-review.md),不加载作者 feedback/merge 规则。完整作者 E2E 也只按当前位置渐进加载。
|
|
101
92
|
5. CLI 缺失、命令不兼容或版本不足时读 [references/command-capabilities.md](references/command-capabilities.md),停止当前 action 并提示用户运行独立 setup;setup 成功后恢复原 action。
|
|
102
93
|
6. 进入 autonomous、远端写、危险动作或恢复时读 [references/state-and-safety.md](references/state-and-safety.md)。
|
|
103
94
|
7. 中断恢复、写结果不确定或最终报告时读 [references/recovery.md](references/recovery.md)。
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
不要把一个仓库的 `compile`、label 或机器人协议迁移到另一个仓库。
|
|
13
13
|
|
|
14
|
-
若评论/文档明确为 openLiBing,按需加载 [openlibing-ci.md](openlibing-ci.md);先用 GitCode 评论定位 run/job,再尝试只读 detail/log API。401/403 时,显式 `action=ci` 和完整 E2E 都直接进入安全 OAuth
|
|
14
|
+
若评论/文档明确为 openLiBing,按需加载 [openlibing-ci.md](openlibing-ci.md);先用 GitCode 评论定位 run/job,再尝试只读 detail/log API。401/403 时,显式 `action=ci` 和完整 E2E 都直接进入安全 OAuth 子流程,使用 setup 创建的受管 Python 运行时和其中的 Playwright,并打开已有的系统 Chrome/Edge 或 Playwright Chromium;action 内不调用 pip,也不自动下载浏览器。受管运行时不可用时要求运行 `npx msdevflow@latest setup`;成功后恢复原 CI 诊断,浏览器不可用时输出 OAuth 链接并停止为 `blocked: browser-required`。不得把 GitCode Actions 当作 openLiBing。
|
|
15
15
|
|
|
16
16
|
记录适配器:
|
|
17
17
|
|
|
@@ -107,7 +107,7 @@ commit/head SHA
|
|
|
107
107
|
- 不采纳:spec/代码/测试依据;
|
|
108
108
|
6. 统一换行为 `\n` 后逐字比较完整远端回复与预期正文,并验证末尾恰好存在一次尾签;发现 `?`、乱码、截断、尾签缺失、重复或其他不一致时先原地修复,未修复前不得 resolve;
|
|
109
109
|
7. 正文回读通过后,仓库规则允许且权限具备时 resolve,再回读确认 `resolved=true`;
|
|
110
|
-
8. 产生新 head 时,显式 `action=feedback` 停止并建议 `action=ci
|
|
110
|
+
8. 产生新 head 时,显式 `action=feedback` 停止并建议 `action=ci`;核心 `msd` 启动的完整作者 E2E 由编排器随后路由到 `ci`。
|
|
111
111
|
|
|
112
112
|
不要只发一条总体总结替代逐条回复。汇总应在逐条闭环后发布。
|
|
113
113
|
|
|
@@ -42,7 +42,7 @@ CLI 缺失、版本低于推荐下限或所需 schema 不存在时,当前 acti
|
|
|
42
42
|
npx msdevflow setup
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
独立 setup 会在同一次确认后安装或更新 npm 包内置的 `
|
|
45
|
+
独立 setup 会在同一次确认后安装或更新 npm 包内置的 `msd` Skill 套件,安装或升级官方 npm 包 `@gitcode-cli/cli@latest`,保留已有 Python `gitcode`,创建或修复 msdevflow 受管 Python venv,在其中安装 `scripts/requirements.txt` 的 Playwright,并验收 workflow 所需 schema/API。它不修改系统 Python、不使用 `--break-system-packages`、不回退到全局 pip,也不下载 Playwright Chromium。若 Python 发行版缺少 `venv`,setup 明确阻断;Debian/Ubuntu 通常需要用户自行安装 `python3-venv`。若 CLI 未认证,setup 会启动 `<gitcode-command> auth login --web` 的官方浏览器流程;凭证由 GitCode CLI 自己接收和保存,setup 不读取、打印或转存 Token,也不要求用户把 Token 传给 Agent。workflow 不在 action 内隐式安装依赖。setup 成功后重新探测环境并恢复原 action;不要 fallback 到可能安装旧实现的 PyPI `gitcode-cli`。
|
|
46
46
|
|
|
47
47
|
## 能力降级顺序
|
|
48
48
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `create-issue`
|
|
2
2
|
|
|
3
|
-
显式 `action=create-issue` 用于在一个已授权的 canonical repository 中创建一个 GitCode Issue。它是独立 action:创建并回读确认后立即停止,不执行 `discover`、`issue`、接取、查重、代码核验、开发或 PR
|
|
3
|
+
显式 `action=create-issue` 用于在一个已授权的 canonical repository 中创建一个 GitCode Issue。它是独立 action:创建并回读确认后立即停止,不执行 `discover`、`issue`、接取、查重、代码核验、开发或 PR 流程,也不进入核心 `msd` 启动的完整作者 E2E。
|
|
4
4
|
|
|
5
5
|
## 输入和边界
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `develop`:分析、设计与开发
|
|
2
2
|
|
|
3
|
-
只在显式 `action=develop
|
|
3
|
+
只在显式 `action=develop`,或核心 `msd` 启动的完整作者 E2E 已达到 `verified` 时读取。显式 action 启动时先只读确认 Issue 已核验且没有重复实现;前置不足时返回 `blocked` 并建议 `action=issue`,不得自动接取或补跑核验。
|
|
4
4
|
|
|
5
5
|
## Phase 3:需求分析与设计决策树
|
|
6
6
|
|
|
@@ -20,7 +20,14 @@
|
|
|
20
20
|
|
|
21
21
|
### 执行和完成证据
|
|
22
22
|
|
|
23
|
-
setup
|
|
23
|
+
setup 在所有平台创建或修复一个 msdevflow 受管 Python venv,并在其中安装 `scripts/requirements.txt` 的 Playwright;脚本进入 OAuth 流程时自动重启到该受管解释器。受管运行时或 Playwright 不可用时要求运行 `npx msdevflow@latest setup`,脚本自身不调用 pip,不修改系统 Python,也不下载 Playwright Chromium。脚本优先使用系统 Chrome/Edge,其次使用受管 Playwright 环境中已经存在的 Chromium。然后运行:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
Windows: %LOCALAPPDATA%\msdevflow\python
|
|
27
|
+
macOS/Linux: ${XDG_DATA_HOME:-$HOME/.local/share}/msdevflow/python
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
可用 `MSDEVFLOW_PYTHON_DIR` 覆盖,值必须是绝对路径或以 `~` 开头;setup 与运行 action 时必须保持一致。
|
|
24
31
|
|
|
25
32
|
```bash
|
|
26
33
|
python <skill-dir>/scripts/openlibing_ci.py login-check \
|
|
@@ -85,7 +92,7 @@ python <skill-dir>/scripts/openlibing_ci.py diagnose \
|
|
|
85
92
|
python <skill-dir>/scripts/openlibing_ci.py diagnose ... --oauth
|
|
86
93
|
```
|
|
87
94
|
|
|
88
|
-
`--oauth` 需要 Python Playwright,以及已有的系统 Chrome/Edge
|
|
95
|
+
`--oauth` 需要 setup 已准备好的受管 Python 运行时及其中的 Playwright,以及已有的系统 Chrome/Edge 或受管 Playwright 环境中已经存在的 Chromium。脚本不调用 pip,也不会执行 `playwright install chromium`;受管运行时或依赖缺失时停止并要求运行 `npx msdevflow@latest setup`。浏览器可用时打开本机可见窗口让用户自己完成 GitCode 登录/授权,浏览器不可用时只输出可复制的 OAuth 链接并停止为 `blocked: browser-required`。捕获的 openLiBing token 只驻留当前 Python 进程内,不打印、不落盘。
|
|
89
96
|
|
|
90
97
|
默认使用专用持久浏览器 profile:
|
|
91
98
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `pr` 与 `ci`
|
|
2
2
|
|
|
3
|
-
只在显式 `action=pr`、`action=ci
|
|
3
|
+
只在显式 `action=pr`、`action=ci`,或核心 `msd` 启动的完整作者 E2E 路由到对应位置时读取。任何远端写前同时读取 [state-and-safety.md](state-and-safety.md)。CI 触发或失败时再读取 [ci-and-review.md](ci-and-review.md),不要提前加载。
|
|
4
4
|
|
|
5
5
|
## Action `pr`:Commit、Push、普通 PR
|
|
6
6
|
|
|
@@ -90,7 +90,7 @@ Suggested next action: ci
|
|
|
90
90
|
4. 分类当前改动、连带失败、canonical 基线、基础设施、权限或证据不足;
|
|
91
91
|
5. guided 模式确认修复;`autonomous-ci` 只在已授权最小范围内自动修改、验证、新 commit、push 和重触发;
|
|
92
92
|
6. 新 push 后获取新 head,旧 head 结果失效;
|
|
93
|
-
7. openLiBing detail/log 返回 401/403 时,按 [openlibing-ci.md](openlibing-ci.md)
|
|
93
|
+
7. openLiBing detail/log 返回 401/403 时,按 [openlibing-ci.md](openlibing-ci.md) 使用 setup 创建的受管 Python 运行时和其中的 Playwright,并用已有的系统 Chrome/Edge 或 Playwright Chromium 打开可见浏览器;action 内不调用 pip,也不自动下载浏览器。受管运行时不可用时要求运行 `npx msdevflow@latest setup`;用户完成 GitCode 登录/授权且固定 run 验证成功后恢复当前 CI 诊断,浏览器不可用时输出 OAuth 链接并停止为 `blocked: browser-required`;
|
|
94
94
|
8. 循环至当前 head 全绿或形成证据充分的 blocker。
|
|
95
95
|
|
|
96
96
|
重试不能代替根因分析。CI 修复不得扩大 Issue 范围;发现产品实现缺失或方案错误时返回 `blocked` 并建议 `action=develop`,不得把 CI action 变成补开发流程。
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
4. 根据 action 完成条件识别最后一个有证据的状态;不能只信先前摘要或旧 run 产物。
|
|
15
15
|
5. 验证本地分支与远端 source head 是否一致。
|
|
16
16
|
6. 显式 action 只判断自身前置和完成条件:前置缺失时 `blocked`,不得运行上游;已完成时报告证据并立即停止。
|
|
17
|
-
7.
|
|
17
|
+
7. 核心 `msd` 启动的完整作者 E2E 从 Phase 0 重建仓库画像,再路由到下一未完成作者 action;不重复已完成的写操作。
|
|
18
18
|
8. `create-issue` 不执行产品查重;仅在本次创建结果不确定时按目标仓库、当前账号、启动时间、标题和完整正文做有界恢复,无法唯一证明时停止。`openlibing-auth` 的历史 profile 或旧认证摘要不证明当前授权有效;必须用本次固定 run 做真实只读请求。
|
|
19
19
|
9. `code-review` 不参与作者 E2E,也不从作者 feedback 状态恢复。恢复时重新确认 reviewer、author、PR 状态和当前 head;旧 `review_head_sha` 的分析、摘要、finding 或 `/lgtm` 不证明当前 head 已检视。
|
|
20
20
|
10. 当前 head 等于旧 `review_head_sha` 时,回读结构化 comments/discussions,并按 reviewer、head、path/position 和完整正文恢复已发布 finding;检视通过必须同时回读到绑定当前 head 的带尾签摘要和同一 reviewer 的精确 `/lgtm`。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `feedback` 与 `merge`
|
|
2
2
|
|
|
3
|
-
只在显式 `action=feedback`、`action=merge
|
|
3
|
+
只在显式 `action=feedback`、`action=merge`,或核心 `msd` 启动的完整作者 E2E 路由到对应位置时读取。开始时同时读取 [state-and-safety.md](state-and-safety.md);处理结构化 discussion 或 CI 时按需读取 [ci-and-review.md](ci-and-review.md)。本文件不定义 `action=code-review`。
|
|
4
4
|
|
|
5
5
|
## Action `feedback`:处理自己 PR 的检视意见
|
|
6
6
|
|
|
@@ -31,7 +31,7 @@ PR 不存在时返回 `blocked` 并建议 `action=pr`;source branch 不可写
|
|
|
31
31
|
6. 创建新 commit 并 push,不 amend、不 force push;
|
|
32
32
|
7. 每条 discussion 在线程内回复:已修复引用 commit;部分采纳、不采纳或延期说明依据;每条回复按 [state-and-safety.md](state-and-safety.md) 使用 UTF-8 安全通道并附加唯一尾签,逐字回读完整正文;
|
|
33
33
|
8. 只有回复正文和尾签回读一致后,仓库规则和权限允许时才 resolve;乱码、`?`、截断或不一致时先原地修复;
|
|
34
|
-
9. 产生新 head 时记录旧 CI 结果已失效,停止后建议 `action=ci`;不得在显式 `feedback` 内触发或监控远端 CI
|
|
34
|
+
9. 产生新 head 时记录旧 CI 结果已失效,停止后建议 `action=ci`;不得在显式 `feedback` 内触发或监控远端 CI。核心 `msd` 启动的完整作者 E2E 由编排器随后路由到 `ci`。
|
|
35
35
|
|
|
36
36
|
不要以一条总体评论替代逐条回复。处理完成后不请求重新检视、不触发检视机器人;外部 reviewer 是否重新检视由仓库和人员流程决定。
|
|
37
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `discover` 与 `issue`
|
|
2
2
|
|
|
3
|
-
在显式 `action=discover`、`action=issue
|
|
3
|
+
在显式 `action=discover`、`action=issue`,或核心 `msd` 启动的完整作者 E2E 启动时读取;显式 `action=create-issue` 只读取本文件的公共环境、仓库上下文和最小充分画像,模板和写入业务转到 [create-issue.md](create-issue.md),不得执行本文件的发现、接取或重复实现核验。`discover` 全程只读并在候选报告后立即停止;`issue` 只接取和核验指定 Issue,达到 `verified` 后立即停止,不进入开发。
|
|
4
4
|
|
|
5
5
|
显式 `action=issue` 必须提供 Issue URL 或编号。缺少目标时只做确认输入缺失所需的只读核验,随后返回 `blocked` 并建议先运行 `action=discover`;不得在本 action 内查询候选、让用户选择 Issue 或执行 `discover` 的业务。
|
|
6
6
|
|
|
@@ -98,7 +98,7 @@ pr_number(如已有)
|
|
|
98
98
|
|
|
99
99
|
## Phase 1:发现与接取
|
|
100
100
|
|
|
101
|
-
显式 `action=issue` 直接读取输入中的 Issue URL/编号;缺少目标时按本文件入口规则返回 `blocked`。显式 `action=discover`
|
|
101
|
+
显式 `action=issue` 直接读取输入中的 Issue URL/编号;缺少目标时按本文件入口规则返回 `blocked`。显式 `action=discover` 或核心 `msd` 启动的完整作者 E2E 尚无目标时,才对“无目标发现”确认出的每个 canonical 查询当前用户负责的开放 Issue:
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
104
|
<gitcode-command> issue list -R <canonical> --state open --assignee <username> --json
|
|
@@ -100,7 +100,7 @@ Agent 创建或修改的 Issue/PR 正文,以及发布的 Issue 评论、PR 普
|
|
|
100
100
|
|
|
101
101
|
`autonomous-ci` 只授权在同一 PR 的 CI 修复循环中:修改与根因直接相关的代码、运行门禁、创建新 commit、push 同一 source branch、重触发 CI。它不授权扩大需求、force push、降低测试、处理 feedback、review、approve 或 merge。
|
|
102
102
|
|
|
103
|
-
显式 `openlibing-auth`、显式 `ci` 和完整 E2E 均授权在需要 openLiBing OAuth
|
|
103
|
+
显式 `openlibing-auth`、显式 `ci` 和完整 E2E 均授权在需要 openLiBing OAuth 时使用 setup 创建的受管 Python 运行时和其中的 Playwright 打开可见浏览器,但不授权在 action 内调用 pip,也不授权下载 Playwright Chromium。受管运行时不可用时要求用户运行 `npx msdevflow@latest setup`。优先使用系统 Chrome/Edge,其次使用已存在的 Playwright Chromium;均不可用或 Playwright 无法启动时输出可复制的 OAuth 链接并停止为 `blocked: browser-required`。该链接只供人工浏览器访问,不能证明当前进程已认证或固定 run 已验证。该授权不允许 Agent 代替用户填写 GitCode 凭证、点击授权同意、读取浏览器 Cookie 值或导出任何 Token。
|
|
104
104
|
|
|
105
105
|
## Guided 检查点
|
|
106
106
|
|
|
@@ -8,7 +8,6 @@ import os
|
|
|
8
8
|
import re
|
|
9
9
|
import shutil
|
|
10
10
|
import stat
|
|
11
|
-
import subprocess
|
|
12
11
|
import sys
|
|
13
12
|
import time
|
|
14
13
|
import urllib.error
|
|
@@ -79,6 +78,59 @@ LEGACY_PROFILE_MARKERS = {
|
|
|
79
78
|
},
|
|
80
79
|
}
|
|
81
80
|
PROFILE_METADATA = "session.json"
|
|
81
|
+
PYTHON_RUNTIME_MARKER = ".msdevflow-python-runtime"
|
|
82
|
+
PYTHON_RUNTIME_MARKER_CONTENT = "managed-by=msdevflow\n"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def configured_directory(value: str, variable: str) -> Path:
|
|
86
|
+
selected = Path(value).expanduser()
|
|
87
|
+
if not selected.is_absolute():
|
|
88
|
+
raise OpenLibingAuthRequired(
|
|
89
|
+
f"{variable} 必须是绝对路径或以 ~ 开头。请运行 npx msdevflow@latest setup。"
|
|
90
|
+
)
|
|
91
|
+
return selected
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def default_python_runtime_dir() -> Path:
|
|
95
|
+
configured = os.getenv("MSDEVFLOW_PYTHON_DIR")
|
|
96
|
+
if configured:
|
|
97
|
+
return configured_directory(configured, "MSDEVFLOW_PYTHON_DIR")
|
|
98
|
+
if os.name == "nt":
|
|
99
|
+
local_app_data = os.getenv("LOCALAPPDATA")
|
|
100
|
+
root = (
|
|
101
|
+
configured_directory(local_app_data, "LOCALAPPDATA")
|
|
102
|
+
if local_app_data
|
|
103
|
+
else Path.home() / "AppData" / "Local"
|
|
104
|
+
)
|
|
105
|
+
return root / "msdevflow" / "python"
|
|
106
|
+
data_home = os.getenv("XDG_DATA_HOME")
|
|
107
|
+
root = (
|
|
108
|
+
configured_directory(data_home, "XDG_DATA_HOME")
|
|
109
|
+
if data_home
|
|
110
|
+
else Path.home() / ".local" / "share"
|
|
111
|
+
)
|
|
112
|
+
return root / "msdevflow" / "python"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def managed_python_executable(runtime_dir: Path | None = None) -> Path:
|
|
116
|
+
selected = (runtime_dir or default_python_runtime_dir()).expanduser()
|
|
117
|
+
executable = selected / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
|
|
118
|
+
marker = selected / PYTHON_RUNTIME_MARKER
|
|
119
|
+
try:
|
|
120
|
+
owned = (
|
|
121
|
+
selected.is_dir()
|
|
122
|
+
and not selected.is_symlink()
|
|
123
|
+
and marker.is_file()
|
|
124
|
+
and not marker.is_symlink()
|
|
125
|
+
and marker.read_text(encoding="utf-8") == PYTHON_RUNTIME_MARKER_CONTENT
|
|
126
|
+
)
|
|
127
|
+
except OSError:
|
|
128
|
+
owned = False
|
|
129
|
+
if not owned or not executable.is_file():
|
|
130
|
+
raise OpenLibingAuthRequired(
|
|
131
|
+
f"msdevflow 受管 Python 运行时不可用:{selected}。请运行 npx msdevflow@latest setup。"
|
|
132
|
+
)
|
|
133
|
+
return executable
|
|
82
134
|
|
|
83
135
|
|
|
84
136
|
def profile_marker(profile_dir: Path) -> Path:
|
|
@@ -181,29 +233,18 @@ def clear_openlibing_storage(context: Any, page: Any, base_url: str) -> None:
|
|
|
181
233
|
raise OpenLibingAuthRequired("无法从持久 profile 清除 openLiBing Cookie,已拒绝保存会话。")
|
|
182
234
|
|
|
183
235
|
|
|
184
|
-
def oauth_requirements_file() -> Path:
|
|
185
|
-
return Path(__file__).with_name("requirements.txt")
|
|
186
|
-
|
|
187
|
-
|
|
188
236
|
def ensure_playwright() -> None:
|
|
237
|
+
executable = managed_python_executable()
|
|
238
|
+
active_prefix = os.path.normcase(str(Path(sys.prefix).resolve()))
|
|
239
|
+
managed_prefix = os.path.normcase(str(default_python_runtime_dir().resolve()))
|
|
240
|
+
if active_prefix != managed_prefix:
|
|
241
|
+
os.execv(str(executable), [str(executable), str(Path(__file__).resolve()), *sys.argv[1:]])
|
|
189
242
|
try:
|
|
190
243
|
importlib.import_module("playwright.sync_api")
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
raise OpenLibingAuthRequired("缺少 openLiBing OAuth 依赖清单,无法自动安装 Playwright。")
|
|
196
|
-
result = subprocess.run(
|
|
197
|
-
[sys.executable, "-m", "pip", "install", "-r", str(requirements)],
|
|
198
|
-
check=False,
|
|
199
|
-
)
|
|
200
|
-
if result.returncode != 0:
|
|
201
|
-
raise OpenLibingAuthRequired("自动安装 Playwright 失败。")
|
|
202
|
-
importlib.invalidate_caches()
|
|
203
|
-
try:
|
|
204
|
-
importlib.import_module("playwright.sync_api")
|
|
205
|
-
except ImportError as error:
|
|
206
|
-
raise OpenLibingAuthRequired("Playwright 安装完成但当前 Python 无法导入。") from error
|
|
244
|
+
except ImportError as error:
|
|
245
|
+
raise OpenLibingAuthRequired(
|
|
246
|
+
"受管 Python 运行时缺少 Playwright。请运行 npx msdevflow@latest setup。"
|
|
247
|
+
) from error
|
|
207
248
|
|
|
208
249
|
|
|
209
250
|
def playwright_chromium_path() -> Path:
|