@tnnevol/dsh-midscene 0.2.0-rc.2.4 → 0.2.0-rc.2.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/LICENSE +202 -0
- package/README.md +1 -1
- package/compatibility.json +1 -0
- package/lib/client.js +8 -8
- package/lib/index.js +34 -4
- package/package.json +39 -38
- package/skills/SOURCE.md +3 -1
- package/skills/dsh-midscene/SKILL.md +78 -0
- package/skills/vitest-midscene-e2e/scripts/clone-boilerplate.sh +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
CHANGED
package/compatibility.json
CHANGED
package/lib/client.js
CHANGED
|
@@ -42662,7 +42662,7 @@ onKeyDown: (e) => this.foundation._handleKeyDown(e) });
|
|
|
42662
42662
|
sectionTitle: "Midscene 接入设置",
|
|
42663
42663
|
sectionHint: "Midscene 通过本地桥接服务使用 DSH 已配置的模型,无需任何模型 API 密钥。",
|
|
42664
42664
|
apiKeyLabel: "接入密钥",
|
|
42665
|
-
apiKeyHint: "
|
|
42665
|
+
apiKeyHint: "桥接服务的接入密钥,不是模型密钥。重新生成后需要同步更新下面的接入配置(命令行 .env 与浏览器扩展两处)。",
|
|
42666
42666
|
regenerate: "随机重新生成",
|
|
42667
42667
|
regenerating: "生成中…",
|
|
42668
42668
|
customKey: "自定义密钥",
|
|
@@ -42682,9 +42682,9 @@ onKeyDown: (e) => this.foundation._handleKeyDown(e) });
|
|
|
42682
42682
|
modelsUnavailable: "DSH 当前没有可用于 Midscene 的识图模型。请先在 DSH 中安装并登录一个提供方(模型需具备图片输入能力),然后回到本页重新加载。",
|
|
42683
42683
|
addModel: "添加模型",
|
|
42684
42684
|
removeModel: "移除",
|
|
42685
|
-
envLabel: "
|
|
42686
|
-
envHint: "
|
|
42687
|
-
envCopy: "
|
|
42685
|
+
envLabel: "接入配置(命令行 .env 或 Midscene 浏览器扩展)",
|
|
42686
|
+
envHint: "两条路都用这四行:跑命令行时保存为工作目录的 .env;用 Chrome 里的 Midscene 扩展时,打开它的侧边栏设置把这段粘进去。模型跟随当前 DSH 会话,不需要任何第三方模型密钥。",
|
|
42687
|
+
envCopy: "复制接入配置",
|
|
42688
42688
|
loading: "正在读取当前设置…",
|
|
42689
42689
|
loadFailed: "读取设置失败",
|
|
42690
42690
|
saveFailed: "保存失败",
|
|
@@ -42695,7 +42695,7 @@ onKeyDown: (e) => this.foundation._handleKeyDown(e) });
|
|
|
42695
42695
|
sectionTitle: "Midscene bridge settings",
|
|
42696
42696
|
sectionHint: "Midscene drives DSH-configured models through the local bridge — no model API key needed.",
|
|
42697
42697
|
apiKeyLabel: "Bridge access key",
|
|
42698
|
-
apiKeyHint: "Access key for the bridge, not a model key. Regenerating requires updating the
|
|
42698
|
+
apiKeyHint: "Access key for the bridge, not a model key. Regenerating requires updating the access config below (both the CLI .env and the browser extension).",
|
|
42699
42699
|
regenerate: "Regenerate",
|
|
42700
42700
|
regenerating: "Generating…",
|
|
42701
42701
|
customKey: "Custom key",
|
|
@@ -42715,9 +42715,9 @@ onKeyDown: (e) => this.foundation._handleKeyDown(e) });
|
|
|
42715
42715
|
modelsUnavailable: "DSH has no vision-capable model available for Midscene. Install and sign in to a provider in DSH first (the model needs image input), then reload this page.",
|
|
42716
42716
|
addModel: "Add model",
|
|
42717
42717
|
removeModel: "Remove",
|
|
42718
|
-
envLabel: "
|
|
42719
|
-
envHint: "
|
|
42720
|
-
envCopy: "Copy
|
|
42718
|
+
envLabel: "Access config (CLI .env or Midscene browser extension)",
|
|
42719
|
+
envHint: "Both paths use these four lines: save them as .env in the directory where you run the CLI, or open the Midscene browser extension sidebar settings and paste them there. The model follows the current DSH session — no third-party model key is needed.",
|
|
42720
|
+
envCopy: "Copy access config",
|
|
42721
42721
|
loading: "Reading current settings…",
|
|
42722
42722
|
loadFailed: "Failed to read settings",
|
|
42723
42723
|
saveFailed: "Failed to save",
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
1
|
+
import { randomBytes, randomUUID } from "node:crypto";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { createServer } from "node:http";
|
|
4
|
+
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
4
5
|
import { existsSync } from "node:fs";
|
|
5
6
|
import { readFile, readdir, stat } from "node:fs/promises";
|
|
6
7
|
import { basename, join } from "node:path";
|
|
@@ -1296,6 +1297,18 @@ var BridgeServer = class {
|
|
|
1296
1297
|
#server;
|
|
1297
1298
|
/** 实际监听端口;启动成功前为 undefined。 */
|
|
1298
1299
|
#port;
|
|
1300
|
+
/**
|
|
1301
|
+
* 桥自身的会话标识,随每次请求下发给模型层。
|
|
1302
|
+
*
|
|
1303
|
+
* 部分提供方要求「按会话路由」的请求头(如 opencode 的 `x-opencode-session`),
|
|
1304
|
+
* 而 DSH 正是从 `GenerateOptions.sessionId` 生成该头。桥原先不传这个字段,
|
|
1305
|
+
* 于是**只要会话模型属于这类提供方,桥就整体不可用**(502 `MissingSessionID`)——
|
|
1306
|
+
* 与「DSH 会话能正常请求的模型,桥也应该能正常发送」直接冲突。
|
|
1307
|
+
*
|
|
1308
|
+
* 取值稳定(每个桥实例一个):既满足按会话路由的要求,也让支持提示缓存的
|
|
1309
|
+
* 提供方拿到稳定的缓存键;不支持的提供方会忽略它,因此对所有提供方都安全。
|
|
1310
|
+
*/
|
|
1311
|
+
#sessionId = SessionId(randomUUID());
|
|
1299
1312
|
catalog;
|
|
1300
1313
|
/**
|
|
1301
1314
|
* @param deps - 运行依赖。
|
|
@@ -1594,6 +1607,7 @@ var BridgeServer = class {
|
|
|
1594
1607
|
const timer = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : void 0;
|
|
1595
1608
|
const stream = this.deps.llm.stream({
|
|
1596
1609
|
...options,
|
|
1610
|
+
sessionId: this.#sessionId,
|
|
1597
1611
|
signal: controller.signal
|
|
1598
1612
|
});
|
|
1599
1613
|
try {
|
|
@@ -1690,9 +1704,20 @@ var BridgeServer = class {
|
|
|
1690
1704
|
* Midscene 技能,无需另行执行技能安装命令。注册随 Cordis 效果注销:插件卸载
|
|
1691
1705
|
* 或 HMR 时技能同步消失(AC-03)。
|
|
1692
1706
|
*
|
|
1693
|
-
*
|
|
1694
|
-
*
|
|
1695
|
-
*
|
|
1707
|
+
* **不写入用户技能目录**(需求行为约束):技能只在注册表里存在,由宿主自己的
|
|
1708
|
+
* 发现优先级负责共存,插件不往用户目录里写文件、也不重复提示。
|
|
1709
|
+
*
|
|
1710
|
+
* **同名冲突时插件保持最高优先级**(AC-04):插件分发的是**本环境的权威版本**
|
|
1711
|
+
* ——包内技能带环境说明(模型由桥提供、不索要密钥),而用户目录里的同名副本
|
|
1712
|
+
* 通常是没有这段说明的上游原文。一旦被后者遮蔽,agent 就会不知道插件的作用,
|
|
1713
|
+
* 转而向用户索要模型密钥(实测事故:会话里 agent 翻了 9 步环境、最后仍让用户
|
|
1714
|
+
* 提供 `MIDSCENE_MODEL_API_KEY`)。因此候选统一用 `rank: 0`(数值最小者胜)。
|
|
1715
|
+
*
|
|
1716
|
+
* ⚠️ **层序优先于 rank**:宿主按 `[global, ...作用域链]` 逐层合并同名技能,
|
|
1717
|
+
* **后面的层直接覆盖前面的层**,rank 只在同一层内决定胜负。插件在 profile 启动时
|
|
1718
|
+
* 注册(global 层),而 `~/.agents/skills` 落在作用域链里(更靠后)——**这种情况
|
|
1719
|
+
* 下 rank 再小也赢不了**。所以另有一条兜底:插件自有的入口技能 `dsh-midscene`
|
|
1720
|
+
* 用**独占名字**,不参与任何同名冲突。
|
|
1696
1721
|
*/
|
|
1697
1722
|
/** SkillProvider 在注册表里的名字。 */
|
|
1698
1723
|
const SKILL_PROVIDER_NAME = "dsh-midscene";
|
|
@@ -1717,6 +1742,11 @@ const BRIDGE_PRELUDE = `> **本环境说明(由 DSH Midscene 插件注入,
|
|
|
1717
1742
|
> - **不要向用户索要模型 API key,也不要引导用户去申请第三方模型。** 本文档中出现的服务商、
|
|
1718
1743
|
> 模型与 key 示例仅作背景知识;实际使用哪个模型由桥决定。
|
|
1719
1744
|
> - 需要浏览器桥接模式时同样走桥:Midscene 侧的模型配置始终是上面这四行。
|
|
1745
|
+
> - **浏览器交互用用户的主 Chrome**:走扩展桥接(\`--bridge\` / \`AgentOverChromeBridge\`),
|
|
1746
|
+
> 复用用户真实浏览器的登录态,而不是另起一个干净 profile。用户只需**一次性**把上面四行
|
|
1747
|
+
> 粘进 **Midscene 扩展的侧边栏设置**(扩展的 Playground 靠它接上 DSH 的模型)。
|
|
1748
|
+
> **要主动把这一步讲给用户** —— 少了它扩展用不上 DSH 的模型,用户就会被引向申请第三方
|
|
1749
|
+
> key,而那正是本插件要消除的成本。不要反过来让用户「先配好模型再来」。
|
|
1720
1750
|
>
|
|
1721
1751
|
> **静默操作(不打断用户)**:用 Bridge 模式驱动用户浏览器时,连接标签页应传
|
|
1722
1752
|
> \`activate: false\`,否则会把用户正在看的页面切走、让浏览器变成测试画布。JS SDK 路径:
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@tnnevol/dsh-midscene",
|
|
3
3
|
"displayName": "Midscene Bridge",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.2.0-rc.2.
|
|
5
|
+
"version": "0.2.0-rc.2.6",
|
|
6
6
|
"description": "Hosts a loopback OpenAI-compatible bridge that exposes every model configured in DSH (official routes, plugin routes, and user-declared providers) so Midscene browser automation can drive pages with natural language without holding any credential itself.",
|
|
7
7
|
"author": "tnnevol",
|
|
8
8
|
"license": "Apache-2.0",
|
|
@@ -44,17 +44,6 @@
|
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": "^22.19.0 || >=24.0.0"
|
|
46
46
|
},
|
|
47
|
-
"scripts": {
|
|
48
|
-
"build": "tsdown",
|
|
49
|
-
"dev": "tsdown --watch",
|
|
50
|
-
"typecheck": "tsc -p tsconfig.json",
|
|
51
|
-
"check": "pnpm run typecheck && pnpm run test",
|
|
52
|
-
"prepublishOnly": "pnpm run check",
|
|
53
|
-
"publish:next": "pnpm publish --tag next --access public",
|
|
54
|
-
"test": "vitest run --config vitest.config.ts",
|
|
55
|
-
"test:e2e": "midscene-test --config tests/e2e/midscene.config.ts",
|
|
56
|
-
"test:bridge": "node --experimental-strip-types scripts/bridge-smoke.ts"
|
|
57
|
-
},
|
|
58
47
|
"dsh": {
|
|
59
48
|
"bundle": {
|
|
60
49
|
"patch": "./cordis.patch.yml"
|
|
@@ -70,7 +59,7 @@
|
|
|
70
59
|
}
|
|
71
60
|
},
|
|
72
61
|
"peerDependencies": {
|
|
73
|
-
"@deepseek-ai/cordis": "
|
|
62
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
74
63
|
"@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
|
|
75
64
|
"@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
|
|
76
65
|
"@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.0-rc.2",
|
|
@@ -79,33 +68,45 @@
|
|
|
79
68
|
"@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
|
|
80
69
|
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
|
|
81
70
|
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
|
|
82
72
|
"@deepseek-ai/dsh-settings": "0.2.0-rc.2",
|
|
83
73
|
"@deepseek-ai/dsh-skill": "0.2.0-rc.2",
|
|
84
|
-
"@deepseek-ai/schemastery": "
|
|
85
|
-
"react": "
|
|
74
|
+
"@deepseek-ai/schemastery": "3.18.4",
|
|
75
|
+
"react": "^18.3.1"
|
|
86
76
|
},
|
|
87
77
|
"devDependencies": {
|
|
88
|
-
"@deepseek-ai/cordis": "
|
|
89
|
-
"@deepseek-ai/dsh-attachment": "
|
|
90
|
-
"@deepseek-ai/dsh-client-locale": "
|
|
91
|
-
"@deepseek-ai/dsh-client-ui-plugin-manager": "
|
|
92
|
-
"@deepseek-ai/dsh-client-ui-renderer": "
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-settings": "
|
|
94
|
-
"@deepseek-ai/dsh-client-ui-slots": "
|
|
95
|
-
"@deepseek-ai/dsh-host-webserver": "
|
|
96
|
-
"@deepseek-ai/dsh-llm": "
|
|
97
|
-
"@deepseek-ai/dsh-
|
|
98
|
-
"@deepseek-ai/dsh-
|
|
99
|
-
"@deepseek-ai/
|
|
100
|
-
"@
|
|
101
|
-
"@midscene/
|
|
102
|
-
"@
|
|
103
|
-
"@
|
|
104
|
-
"@types/
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
78
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
79
|
+
"@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
|
|
80
|
+
"@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.0-rc.2",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
|
|
83
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
|
|
84
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
|
|
85
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
|
|
86
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
|
|
87
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
|
|
88
|
+
"@deepseek-ai/dsh-settings": "0.2.0-rc.2",
|
|
89
|
+
"@deepseek-ai/dsh-skill": "0.2.0-rc.2",
|
|
90
|
+
"@deepseek-ai/schemastery": "3.18.4",
|
|
91
|
+
"@midscene/test": "1.15.1",
|
|
92
|
+
"@midscene/web": "1.15.1",
|
|
93
|
+
"@types/node": "^22.20.0",
|
|
94
|
+
"@types/react": "^18.3.31",
|
|
95
|
+
"react": "^18.3.1",
|
|
96
|
+
"tsdown": "^0.22.2",
|
|
97
|
+
"typescript": "^5.9.3",
|
|
98
|
+
"vitest": "^4.1.8",
|
|
99
|
+
"@tnnevol/dsh-e2e-kit": "5.7.7",
|
|
100
|
+
"@tnnevol/dsh-semi-ui": "5.7.7"
|
|
101
|
+
},
|
|
102
|
+
"scripts": {
|
|
103
|
+
"build": "tsdown",
|
|
104
|
+
"dev": "tsdown --watch",
|
|
105
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
106
|
+
"check": "pnpm run typecheck && pnpm run test",
|
|
107
|
+
"publish:next": "pnpm publish --tag next --access public",
|
|
108
|
+
"test": "vitest run --config vitest.config.ts",
|
|
109
|
+
"test:e2e": "midscene-test --config tests/e2e/midscene.config.ts",
|
|
110
|
+
"test:bridge": "node --experimental-strip-types scripts/bridge-smoke.ts"
|
|
110
111
|
}
|
|
111
|
-
}
|
|
112
|
+
}
|
package/skills/SOURCE.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# 内置技能来源
|
|
2
2
|
|
|
3
|
-
本目录内置 **7
|
|
3
|
+
本目录内置 **8 个技能**:**7 个来自上游**(与上游逐字节一致,不含任何本地补丁),
|
|
4
|
+
外加 **1 个插件自有技能** `dsh-midscene`(**不是**上游内容,不参与上游同步)。
|
|
4
5
|
|
|
5
6
|
| 技能 | 上游 | 定位 |
|
|
6
7
|
| --- | --- | --- |
|
|
8
|
+
| **`dsh-midscene`** | **插件自有** | **本环境入口**:模型由插件的桥提供、不索要密钥、优先用用户自己的 Chrome |
|
|
7
9
|
| `browser-automation` | [`web-infra-dev/midscene-skills`](https://github.com/web-infra-dev/midscene-skills) | 浏览器自动化(Puppeteer / CDP / Bridge 三种模式) |
|
|
8
10
|
| `computer-automation` | 同上 | 桌面控制(macOS / Windows / Linux,本地模式会接管真实鼠标键盘) |
|
|
9
11
|
| `android-automation` | 同上 | Android 设备控制(ADB) |
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dsh-midscene
|
|
3
|
+
description: |
|
|
4
|
+
DSH 环境里做 Midscene 浏览器/设备自动化时的**入口技能**:模型由 DSH 的
|
|
5
|
+
dsh-midscene 插件经本地桥提供,**不需要任何第三方模型密钥**。
|
|
6
|
+
|
|
7
|
+
只要任务涉及以下任一项,**先加载本技能**再动手:
|
|
8
|
+
- Midscene、@midscene/web、@midscene/test、MIDSCENE_MODEL_*、GUI Agent、视觉驱动 UI 自动化
|
|
9
|
+
- 用**真实 Chrome** 做端到端测试、点击/输入/断言、浏览器取证、截图
|
|
10
|
+
- Bridge 模式、Chrome 扩展、连接**用户自己的浏览器**
|
|
11
|
+
- Playwright / Puppeteer 集成、Midscene Test、midscene.config.ts
|
|
12
|
+
- 用户说「用 midscene 插件」「连上 chrome 测试」「浏览器自动化」「帮我点一下页面」
|
|
13
|
+
|
|
14
|
+
本技能是**本环境的权威入口**:与上游 Midscene 文档冲突时,以本技能为准。
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# DSH Midscene 插件(本环境的唯一入口)
|
|
18
|
+
|
|
19
|
+
## 一句话
|
|
20
|
+
|
|
21
|
+
**模型由 DSH 提供,不要向用户索要任何模型密钥。**
|
|
22
|
+
|
|
23
|
+
DSH 装了 `@tnnevol/dsh-midscene` 插件,它在本地起一个 OpenAI 兼容的桥,把 Midscene 的
|
|
24
|
+
模型请求转发给**当前 DSH 会话正在用的模型**(凭据留在 DSH 的提供方插件里,桥不接触)。
|
|
25
|
+
所以在本环境里:
|
|
26
|
+
|
|
27
|
+
- ✅ 配置是**固定四行**,一条命令就能拿到,**开箱可用**
|
|
28
|
+
- ❌ **不要**让用户提供 `MIDSCENE_MODEL_API_KEY`、模型名或服务商
|
|
29
|
+
- ❌ **不要**让用户写 `.env`,也不要自己去翻 `~/.zshrc`、`~/.midscene`、npx 缓存找配置
|
|
30
|
+
- ❌ **不要**建议用户「先配好模型再来」——那正是本插件要消除的成本
|
|
31
|
+
|
|
32
|
+
## 第一步:取配置(一条命令)
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
curl -s "http://127.0.0.1:<端口>/v1/midscene-env"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
端口以 `GET /v1/health` 的 `port` 字段为准(默认 `8787`,被占用会跳号)。
|
|
39
|
+
返回 JSON 的 `content` 字段就是那四行,**直接可用**:
|
|
40
|
+
|
|
41
|
+
| 去处 | 怎么用 |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| 跑命令行 | 存成**运行目录**的 `.env`(Midscene 只加载当前目录的 `.env`) |
|
|
44
|
+
| Midscene 浏览器扩展 | 打开扩展的**侧边栏设置**粘进去(扩展的 Playground 靠它接上 DSH 的模型) |
|
|
45
|
+
|
|
46
|
+
同一份配置,两个去处,内容完全相同。
|
|
47
|
+
|
|
48
|
+
## 第二步:优先用用户自己的 Chrome(Bridge 模式)
|
|
49
|
+
|
|
50
|
+
用户要的是**他自己的浏览器**——真实登录态、已装扩展、可见窗口,**不是**另起的 headless 实例:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
npx -y @midscene/web@1 --bridge connect --url "<目标地址>"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- 需要用户已安装 **Midscene 浏览器扩展**;首次连接时在扩展弹窗点 **Allow**
|
|
57
|
+
- **静默操作**:连接标签页传 `activate: false`,否则会把用户正在看的页面切走
|
|
58
|
+
- 只有用户明确要「无头跑」「隔离环境」时才用 CDP / Puppeteer 路径
|
|
59
|
+
|
|
60
|
+
## 第三步:按需操作并给出证据
|
|
61
|
+
|
|
62
|
+
需要「看」→ `take_screenshot`;需要「动手」→ `act` / `assert`(或测试框架里的 `aiAct` / `aiAssert`)。
|
|
63
|
+
报告结果时**附证据**(截图路径、断言输出、接口返回),不要只说「已完成」。
|
|
64
|
+
|
|
65
|
+
## 常见弯路(都不要走)
|
|
66
|
+
|
|
67
|
+
| 弯路 | 为什么错 |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| 向用户索要模型 key | 桥已经提供;模型就是当前 DSH 会话的模型 |
|
|
70
|
+
| 翻 `~/.zshrc` / `~/.midscene` / npx 缓存找配置 | 那里不该有配置,翻也翻不到 |
|
|
71
|
+
| 自己起 Puppeteer/Chrome 实例 | 用户要的是**他本人的**浏览器与登录态 |
|
|
72
|
+
| 引用上游文档断言「插件不提供 env」 | 上游文档不知道本插件的桥存在,**以本技能为准** |
|
|
73
|
+
| 先花十几步探索环境再动手 | 第一步就是上面那条 `curl`,配置立刻到手 |
|
|
74
|
+
|
|
75
|
+
## 端口与多实例
|
|
76
|
+
|
|
77
|
+
同一台机器可能有多个 DSH 实例,各自一个桥、端口不同(`8787`、`8788`…)。
|
|
78
|
+
**以当前会话所属实例的桥为准**:从该实例的设置页或 `/v1/health` 确认端口,不要默认套用别的实例。
|
|
File without changes
|