dsh-design-studio 0.8.0 → 0.9.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/README.en.md +1 -1
- package/README.md +1 -1
- package/cordis.patch.yml +6 -4
- package/lib/browser.js +34 -0
- package/lib/client.js +334 -46
- package/lib/core.js +4 -3
- package/lib/handoff.js +7 -0
- package/lib/index.js +1 -1
- package/lib/look.js +19 -4
- package/lib/picker.js +407 -34
- package/package.json +1 -1
- package/skills/ui-design/SKILL.md +4 -3
- package/skills/ui-design/references/app.md +1 -1
- package/skills/ui-design/references/desktop.md +24 -0
- package/skills/ui-design/references/miniprogram.md +36 -0
package/README.en.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
**Design Studio** is a DeepSeek Harness (DSH) plugin. Say what you want to make, and the model's web pages, app screens, mini programs, posters and slides appear one by one on a canvas in the right sidebar, inside phone or
|
|
18
|
+
**Design Studio** is a DeepSeek Harness (DSH) plugin. Say what you want to make, and the model's web pages, app screens, mini programs, desktop apps, posters and slides appear one by one on a canvas in the right sidebar, inside phone, browser or app-window frames. Click the direction you like, or click whatever looks off and add a sentence, and the model edits it.
|
|
19
19
|
|
|
20
20
|

|
|
21
21
|
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
**设计工作台**是 DeepSeek Harness(DSH)的插件:说一句要做什么,模型做的网页、App
|
|
18
|
+
**设计工作台**是 DeepSeek Harness(DSH)的插件:说一句要做什么,模型做的网页、App 界面、小程序、桌面软件、海报、幻灯片在右边画布上一屏屏长出来,套着手机、浏览器或软件窗口外框。看中哪个方向点一下,哪里不对点一下说一句,模型就照着改。
|
|
19
19
|
|
|
20
20
|

|
|
21
21
|
|
package/cordis.patch.yml
CHANGED
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
name: dsh-design-studio/tool
|
|
13
13
|
- id: dsh-design-studio-skill
|
|
14
14
|
name: dsh-design-studio/skill
|
|
15
|
-
# 设计模式:照抄 DSH
|
|
16
|
-
# 人设换成做设计的,再挂上预览工具和设计技能。DSH
|
|
15
|
+
# 设计模式:照抄 DSH 标准模式(web-app 的 presets/standard.patch.yml)的全套插件,
|
|
16
|
+
# 人设换成做设计的,再挂上预览工具和设计技能。DSH 标准模式有变动时跟着改;
|
|
17
|
+
# 只写 0.2.1 和 0.2.2 都有的插件——清单里有一个装不上,整个设计模式就不出来
|
|
17
18
|
- id: preset-design
|
|
18
19
|
name: dsh-design-studio/preset
|
|
19
20
|
config:
|
|
@@ -104,14 +105,15 @@
|
|
|
104
105
|
config:
|
|
105
106
|
- id: tool-subagent-control
|
|
106
107
|
name: '@deepseek-ai/dsh-tool-subagent-control'
|
|
107
|
-
- id: tool-subagent-list-agents
|
|
108
|
-
name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
|
|
109
108
|
- id: tool-subagent
|
|
110
109
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
111
110
|
config:
|
|
112
111
|
provider: spawn
|
|
113
112
|
toolName: subagent
|
|
113
|
+
# 0.2.1 叫 modelSelectionSettings,0.2.2 拆成下面两个;多写的键旧版新版都不管
|
|
114
114
|
modelSelectionSettings: true
|
|
115
|
+
modelSelection: true
|
|
116
|
+
modelDiscovery: true
|
|
115
117
|
- id: tool-subagent-fork
|
|
116
118
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
117
119
|
config:
|
package/lib/browser.js
CHANGED
|
@@ -15,6 +15,7 @@ const IDLE_MS = 90000 // 闲置多久关掉
|
|
|
15
15
|
const CALL_MS = 30000 // 一条指令最多等多久
|
|
16
16
|
const LOAD_MS = 15000 // 页面载入最多等多久(到点照样往下走:有个图一直载不完也能量)
|
|
17
17
|
const MAX_PAGES = 3 // 同时开几个页面
|
|
18
|
+
const MAX_PSEUDO = 1500 // 伪元素最多问几个宿主的框(多了只问靠后的:底栏一般写在最后)
|
|
18
19
|
|
|
19
20
|
/** 这台电脑上的 Chromium 系浏览器;DSH_DESIGN_BROWSER / CHROME_BIN 可以指定 */
|
|
20
21
|
export function findBrowser({ env = process.env, platform = process.platform, exists = fs.existsSync, home = os.homedir() } = {}) {
|
|
@@ -204,6 +205,7 @@ export function createBrowser({ bin = findBrowser(), log = () => {}, idleMs = ID
|
|
|
204
205
|
/**
|
|
205
206
|
* 开一个 w×h 的页面载入 url,fn(page) 里量 / 截图,完了关掉。
|
|
206
207
|
* page.eval(表达式):在页面里算(Promise 会等),返回 JSON 值
|
|
208
|
+
* page.pseudo():把伪元素的真实框挂到宿主元素上,体检时用(页面里量不到伪元素)
|
|
207
209
|
* page.shot({ clip, format }):截视口;clip({ x, y, width, height },CSS 像素,按整页坐标 = 视口位置 + 滚动距离)只截那一块 → JPEG Buffer(format: 'png' 无损)
|
|
208
210
|
* allow(网址):给了就只让它说行的页面载入(主页面、iframe,连跳转、脚本改地址都算),别的拦下,记在 page.blocked
|
|
209
211
|
*/
|
|
@@ -249,6 +251,38 @@ export function createBrowser({ bin = findBrowser(), log = () => {}, idleMs = ID
|
|
|
249
251
|
const r = await c('Page.captureScreenshot', { format, ...(format === 'jpeg' ? { quality } : {}), ...(clip ? { clip: { ...clip, scale: 1 } } : {}) })
|
|
250
252
|
return Buffer.from(r.data, 'base64')
|
|
251
253
|
},
|
|
254
|
+
// 伪元素(::before / ::after)的真实框:页面里的脚本量不到,问浏览器要,挂到宿主元素上(__dshPseudo),
|
|
255
|
+
// 连同当时的滚动位置(__dshPseudoAt);体检在同一滚动位置时直接用,不再按样式推。返回挂了几个宿主
|
|
256
|
+
pseudo: async () => {
|
|
257
|
+
const { root } = await c('DOM.getDocument', { depth: -1 })
|
|
258
|
+
const hosts = []
|
|
259
|
+
const walk = (n) => {
|
|
260
|
+
const ps = (n.pseudoElements || []).filter((p) => p.pseudoType === 'before' || p.pseudoType === 'after')
|
|
261
|
+
if (ps.length) hosts.push({ id: n.nodeId, ps })
|
|
262
|
+
for (const k of n.children || []) walk(k)
|
|
263
|
+
}
|
|
264
|
+
walk(root)
|
|
265
|
+
const at = await page.eval('scrollX + "," + scrollY')
|
|
266
|
+
const tagged = await Promise.all(hosts.slice(-MAX_PSEUDO).map(async (h) => {
|
|
267
|
+
const boxes = {}
|
|
268
|
+
for (const p of h.ps) {
|
|
269
|
+
try {
|
|
270
|
+
const q = (await c('DOM.getBoxModel', { nodeId: p.nodeId })).model.border
|
|
271
|
+
const xs = [q[0], q[2], q[4], q[6]], ys = [q[1], q[3], q[5], q[7]]
|
|
272
|
+
boxes['::' + p.pseudoType] = { l: Math.min(...xs), t: Math.min(...ys), r: Math.max(...xs), b: Math.max(...ys) }
|
|
273
|
+
} catch { /* 没有框(没排出来) */ }
|
|
274
|
+
}
|
|
275
|
+
try {
|
|
276
|
+
const { object } = await c('DOM.resolveNode', { nodeId: h.id })
|
|
277
|
+
await c('Runtime.callFunctionOn', { objectId: object.objectId, functionDeclaration: 'function (b) { this.__dshPseudo = b }', arguments: [{ value: { ...boxes, at } }] })
|
|
278
|
+
c('Runtime.releaseObject', { objectId: object.objectId }).catch(() => {})
|
|
279
|
+
return 1
|
|
280
|
+
} catch { return 0 }
|
|
281
|
+
}))
|
|
282
|
+
// __dshPseudoAll:全问到了,没挂框的宿主就是伪元素没排出来;没问全时没挂的按样式推
|
|
283
|
+
await page.eval(`window.__dshPseudoAt = ${JSON.stringify(at)}; window.__dshPseudoAll = ${hosts.length <= MAX_PSEUDO}`)
|
|
284
|
+
return tagged.reduce((m, x) => m + x, 0)
|
|
285
|
+
},
|
|
252
286
|
blocked,
|
|
253
287
|
}
|
|
254
288
|
return await fn(page)
|