@vobs/cli 1.7.4 → 1.7.7

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.
Files changed (64) hide show
  1. package/dist/cli.cjs +551 -5
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.js +551 -5
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/dsh.cjs +677 -0
  6. package/dist/commands/dsh.cjs.map +1 -0
  7. package/dist/commands/dsh.d.cts +43 -0
  8. package/dist/commands/dsh.d.ts +43 -0
  9. package/dist/commands/dsh.js +638 -0
  10. package/dist/commands/dsh.js.map +1 -0
  11. package/dist/commands/generate.cjs.map +1 -1
  12. package/dist/commands/generate.js.map +1 -1
  13. package/dist/commands/index.cjs +543 -5
  14. package/dist/commands/index.cjs.map +1 -1
  15. package/dist/commands/index.d.cts +2 -0
  16. package/dist/commands/index.d.ts +2 -0
  17. package/dist/commands/index.js +540 -5
  18. package/dist/commands/index.js.map +1 -1
  19. package/dist/commands/init.cjs +5 -2
  20. package/dist/commands/init.cjs.map +1 -1
  21. package/dist/commands/init.js +5 -2
  22. package/dist/commands/init.js.map +1 -1
  23. package/dist/index.cjs +553 -7
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +551 -5
  26. package/dist/index.js.map +1 -1
  27. package/dist/repl.cjs +5 -2
  28. package/dist/repl.cjs.map +1 -1
  29. package/dist/repl.js +5 -2
  30. package/dist/repl.js.map +1 -1
  31. package/dist/start.cjs +553 -7
  32. package/dist/start.cjs.map +1 -1
  33. package/dist/start.js +551 -5
  34. package/dist/start.js.map +1 -1
  35. package/dist/templates/dsh-plugin/README.md.hbs +54 -0
  36. package/dist/templates/dsh-plugin/cordis.patch.yml.hbs +7 -0
  37. package/dist/templates/dsh-plugin/package.json.hbs +40 -0
  38. package/dist/templates/dsh-plugin/src/client/index.tsx.hbs +24 -0
  39. package/dist/templates/dsh-plugin/src/client/panel.tsx.hbs +45 -0
  40. package/dist/templates/dsh-plugin/src/client/styles.ts.hbs +65 -0
  41. package/dist/templates/dsh-plugin/src/host/index.ts.hbs +20 -0
  42. package/dist/templates/dsh-plugin/tsconfig.json.hbs +19 -0
  43. package/dist/templates/dsh-plugin/vite.config.ts.hbs +13 -0
  44. package/dist/utils/file.cjs +5 -2
  45. package/dist/utils/file.cjs.map +1 -1
  46. package/dist/utils/file.d.cts +2 -2
  47. package/dist/utils/file.d.ts +2 -2
  48. package/dist/utils/file.js +5 -2
  49. package/dist/utils/file.js.map +1 -1
  50. package/package.json +1 -1
  51. package/src/cli.ts +28 -0
  52. package/src/commands/dsh.test.ts +279 -0
  53. package/src/commands/dsh.ts +673 -0
  54. package/src/commands/index.ts +2 -1
  55. package/src/templates/dsh-plugin/README.md.hbs +54 -0
  56. package/src/templates/dsh-plugin/cordis.patch.yml.hbs +7 -0
  57. package/src/templates/dsh-plugin/package.json.hbs +40 -0
  58. package/src/templates/dsh-plugin/src/client/index.tsx.hbs +24 -0
  59. package/src/templates/dsh-plugin/src/client/panel.tsx.hbs +45 -0
  60. package/src/templates/dsh-plugin/src/client/styles.ts.hbs +65 -0
  61. package/src/templates/dsh-plugin/src/host/index.ts.hbs +20 -0
  62. package/src/templates/dsh-plugin/tsconfig.json.hbs +19 -0
  63. package/src/templates/dsh-plugin/vite.config.ts.hbs +13 -0
  64. package/src/utils/file.ts +7 -3
@@ -0,0 +1,54 @@
1
+ # {{displayName}}
2
+
3
+ 用 [vobs](https://github.com/vobsjs/vobs) 渲染的 DeepSeek Harness 插件。
4
+
5
+ ## 开发
6
+
7
+ ```bash
8
+ pnpm install
9
+ pnpm dev # 本地预览:不用装进 DSH,浏览器里就能看到面板
10
+ pnpm build # 产出 lib/{index,client}.js
11
+ pnpm check # 装前一致性校验
12
+ ```
13
+
14
+ ## 安装进 DSH
15
+
16
+ 产物**必须提交进 Git** —— DSH 安装时不会构建你的包。
17
+
18
+ ```bash
19
+ git add -A && git commit -m "feat: {{displayName}}" && git tag v0.1.0 && git push --tags
20
+ ```
21
+
22
+ 然后在 DSH 侧边栏「插件」页填:
23
+
24
+ ```text
25
+ github:<owner>/<repo>#v0.1.0&path:/<本包在仓库中的路径>
26
+ ```
27
+
28
+ `&path:` 是 pnpm 的 Git 仓库子目录语法。**Windows 上用命令行时要注意**:
29
+ `dsh.cmd` 是 batch 包装,`&` 会被 `cmd.exe` 吃掉而静默装错包,PowerShell 里要写
30
+ `dsh --% plugin --profile desktop add "…"`。
31
+
32
+ 装完完全退出 DSH 再打开。
33
+
34
+ ## 结构
35
+
36
+ ```
37
+ src/
38
+ ├── host/index.ts Host 侧 cordis 插件(只负责「被挂载」)
39
+ └── client/
40
+ ├── index.tsx defineDshOverlay:挂到哪个 slot、渲染什么
41
+ ├── panel.tsx 面板主体(vobs 组件,只执行一次)
42
+ └── styles.ts 注入 shadow root 的样式
43
+ cordis.patch.yml 把自己的行插进 profile 的 cordis 树
44
+ lib/ 构建产物(提交进 Git)
45
+ ```
46
+
47
+ ## 换一种挂法
48
+
49
+ `src/client/index.tsx` 里的 `defineDshOverlay` 可以换成:
50
+
51
+ - `defineDshPanel({ key, label, sidebarEntry })` —— 占满主区域的整页 + 左侧栏入口
52
+ - `defineDshPlugin({ setup(ctx) { … } })` —— 自己写 apply,挂到适配层还没封装的 slot
53
+
54
+ 可用的 slot 与字段见 [`@vobs/dsh` 的 README](https://github.com/vobsjs/vobs/tree/main/packages/dsh)。
@@ -0,0 +1,7 @@
1
+ # DSH 组合包补丁层:只追加自己的插件行,不覆盖任何官方条目。
2
+ #
3
+ # 条目 id 是你在 DSH「插件」页里做开关时用的名字;
4
+ # name 必须等于 package.json 的 name(去掉 scope 的裸包名亦可)。
5
+ - insert:
6
+ - id: {{rowId}}
7
+ name: {{packageName}}
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "{{packageName}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "{{displayName}} —— 用 vobs 渲染的 DSH 插件",
6
+ "type": "module",
7
+ "main": "./lib/index.js",
8
+ "exports": {
9
+ ".": "./lib/index.js",
10
+ "./client": "./lib/client.js",
11
+ "./cordis.patch.yml": "./cordis.patch.yml",
12
+ "./package.json": "./package.json"
13
+ },
14
+ "files": [
15
+ "lib",
16
+ "cordis.patch.yml",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "dev": "vobs dsh dev",
21
+ "build": "vobs dsh build",
22
+ "check": "vobs dsh check"
23
+ },
24
+ "dsh": {
25
+ "manifestVersion": 1,
26
+ "bundle": {
27
+ "patch": "./cordis.patch.yml"
28
+ },
29
+ "client": {
30
+ "platform": "web"
31
+ }
32
+ },
33
+ "devDependencies": {
34
+ "@vobs/cli": "^{{vobsVersion}}",
35
+ "@vobs/dsh": "^{{vobsVersion}}",
36
+ "@vobs/vite-plugin": "^{{vobsVersion}}",
37
+ "@vobs/vobs": "^{{vobsVersion}}",
38
+ "vite": "^7.3.6"
39
+ }
40
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Client 半侧入口。会被 dshBundle() 构建成 lib/client.js:
3
+ *
4
+ * window.__ModuleLoader__.load({ id: '{{packageName}}', factory: function (require) { … } })
5
+ *
6
+ * 适配层(@vobs/dsh)负责 React 绑定、shadow root 宿主、slot 注册、配色跟随与清理,
7
+ * 这里只剩「挂到哪个 slot」和「渲染什么」两件事。
8
+ */
9
+ import { defineDshOverlay } from '@vobs/dsh'
10
+ import { Panel } from './panel'
11
+ import { PANEL_CSS } from './styles'
12
+
13
+ /**
14
+ * shell.overlay 是 @deepseek-ai/dsh-client-ui-layout 声明的 list slot(scope: root),
15
+ * DSH 自家的配额提示、插件管理器 toast 都挂在这里。
16
+ */
17
+ export default defineDshOverlay(
18
+ {
19
+ id: '{{rowId}}',
20
+ order: 120,
21
+ styles: PANEL_CSS
22
+ },
23
+ () => <Panel />
24
+ )
@@ -0,0 +1,45 @@
1
+ import { state } from '@vobs/vobs'
2
+
3
+ /**
4
+ * 面板主体。整个函数**只执行一次** —— 下面每个 `{…}` 都会被编译成独立的
5
+ * DOM binding effect,更新只触碰变化的那个文本节点,不会有组件重渲染。
6
+ */
7
+ export function Panel() {
8
+ const count = state(0)
9
+
10
+ return (
11
+ <div class="panel">
12
+ <header class="panel__head">
13
+ <span class="panel__brand">{{displayName}}</span>
14
+ <span class="panel__tag">vobs 渲染</span>
15
+ </header>
16
+
17
+ <div class="panel__body">
18
+ <p class="panel__hint">
19
+ 改 <code>src/client/panel.tsx</code> 就能看到界面变化;
20
+ <code>vobs dsh dev</code> 可以在不装进 DSH 的情况下预览。
21
+ </p>
22
+
23
+ <div class="panel__row">
24
+ <button
25
+ class="panel__btn"
26
+ onClick={() => {
27
+ count.value -= 1
28
+ }}
29
+ >
30
+ −1
31
+ </button>
32
+ <span class="panel__count">{count.value}</span>
33
+ <button
34
+ class="panel__btn panel__btn--primary"
35
+ onClick={() => {
36
+ count.value += 1
37
+ }}
38
+ >
39
+ +1
40
+ </button>
41
+ </div>
42
+ </div>
43
+ </div>
44
+ )
45
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * 面板样式。由 @vobs/dsh 注入 shadow root:DSH 的全局 CSS 进不来,这里也漏不出去。
3
+ *
4
+ * 配色优先读 DSH 的 design token(会继承进 shadow root),读不到就按
5
+ * `data-scheme` 回退 —— 所以脱离 DSH 预览时同样好看。
6
+ */
7
+ export const PANEL_CSS = `
8
+ :where(*, *::before, *::after) { box-sizing: border-box; }
9
+
10
+ .vobs-dsh-root {
11
+ --p-bg: rgba(26, 27, 33, 0.94);
12
+ --p-fg: #e9eaf0;
13
+ --p-fg-muted: #9aa1ae;
14
+ --p-line: rgba(255, 255, 255, 0.14);
15
+ --p-accent: #8f80ff;
16
+ --p-shadow: 0 18px 48px rgba(0, 0, 0, 0.46);
17
+ }
18
+ .vobs-dsh-root[data-scheme='light'] {
19
+ --p-bg: rgba(255, 255, 255, 0.96);
20
+ --p-fg: #1b1c22;
21
+ --p-fg-muted: #6b7280;
22
+ --p-line: rgba(15, 18, 32, 0.12);
23
+ --p-accent: #5b47e0;
24
+ --p-shadow: 0 18px 48px rgba(15, 18, 32, 0.22);
25
+ }
26
+
27
+ .panel {
28
+ width: 300px;
29
+ border: 1px solid var(--p-line);
30
+ border-radius: 14px;
31
+ background: var(--p-bg);
32
+ box-shadow: var(--p-shadow);
33
+ backdrop-filter: blur(14px);
34
+ color: var(--p-fg);
35
+ font: 13px/1.55 ui-sans-serif, system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif;
36
+ }
37
+
38
+ .panel__head {
39
+ display: flex; align-items: center; gap: 8px;
40
+ padding: 10px 12px; border-bottom: 1px solid var(--p-line);
41
+ }
42
+ .panel__brand { font-weight: 650; }
43
+ .panel__tag {
44
+ padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 600;
45
+ background: color-mix(in srgb, var(--p-accent) 18%, transparent);
46
+ color: var(--p-accent);
47
+ }
48
+ .panel__body { padding: 12px; display: grid; gap: 12px; }
49
+ .panel__hint { margin: 0; color: var(--p-fg-muted); font-size: 12px; }
50
+ .panel__hint code {
51
+ font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11.5px;
52
+ padding: 1px 5px; border-radius: 5px;
53
+ background: color-mix(in srgb, var(--p-fg) 8%, transparent);
54
+ }
55
+ .panel__row { display: flex; align-items: center; gap: 10px; }
56
+ .panel__count { font-size: 18px; font-weight: 650; font-variant-numeric: tabular-nums; min-width: 32px; text-align: center; }
57
+ .panel__btn {
58
+ padding: 5px 12px; border: 1px solid var(--p-line); border-radius: 8px;
59
+ background: transparent; color: inherit; font: inherit; font-size: 12px; cursor: pointer;
60
+ }
61
+ .panel__btn:hover { background: color-mix(in srgb, var(--p-fg) 8%, transparent); }
62
+ .panel__btn--primary {
63
+ border-color: transparent; background: var(--p-accent); color: #fff; font-weight: 600;
64
+ }
65
+ `
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Host 半侧。
3
+ *
4
+ * DSH 的组合包在该 profile 的 cordis 树里插入一行,这一行指向本模块。
5
+ * 客户端模块系统扫描**已启用的 Loader 条目**,读取本包的 `dsh.client` 声明,
6
+ * 把 `exports['./client']`(lib/client.js)作为浏览器 bundle 提供给页面。
7
+ *
8
+ * 也就是说:Host 侧只负责「被挂载」,从而让客户端 bundle 进入启动图。
9
+ * 要给 Agent 加工具、订阅 session/event、注册服务,才需要在这里写。
10
+ */
11
+
12
+ /** cordis 插件名,用于调试命名空间;与 npm 包名无关。 */
13
+ export const name = '{{rowId}}'
14
+
15
+ /** 需要先就绪的 Host 服务名。 */
16
+ export const inject: readonly string[] = []
17
+
18
+ export function apply(_ctx: unknown): void {
19
+ // 有意留空:默认插件的可观察行为全部发生在浏览器半侧。
20
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "strict": true,
8
+ "noUnusedLocals": true,
9
+ "noUnusedParameters": true,
10
+ "noImplicitReturns": true,
11
+ "jsx": "preserve",
12
+ "jsxImportSource": "@vobs/vobs",
13
+ "noEmit": true,
14
+ "skipLibCheck": true,
15
+ "isolatedModules": true,
16
+ "types": []
17
+ },
18
+ "include": ["src", "vite.config.ts"]
19
+ }
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from 'vite'
2
+ import { vobsPlugin } from '@vobs/vite-plugin'
3
+ import { dshBundle } from '@vobs/dsh/vite'
4
+
5
+ export default defineConfig({
6
+ plugins: [
7
+ // 把 TSX 编译成细粒度 DOM 绑定
8
+ vobsPlugin(),
9
+ // 把产物包成 DSH 的 window.__ModuleLoader__ factory,
10
+ // 并在这里挡住「拆了 chunk / 出了独立 asset / 格式不是 cjs」三类错误。
11
+ dshBundle({ entry: 'src/client/index.tsx' })
12
+ ]
13
+ })
package/src/utils/file.ts CHANGED
@@ -66,12 +66,16 @@ async function copyDirRecursive(srcDir: string, destDir: string, context: Record
66
66
  }
67
67
  }
68
68
 
69
- /** Scaffold a project from the basic template */
69
+ /** Scaffold a project from a named template under `src/templates`. */
70
70
  export async function scaffoldProject(
71
71
  targetDir: string,
72
- context: Record<string, unknown>
72
+ context: Record<string, unknown>,
73
+ template = 'basic'
73
74
  ): Promise<void> {
74
- const templateDir = resolve(TEMPLATES_ROOT, 'basic')
75
+ const templateDir = resolve(TEMPLATES_ROOT, template)
76
+ if (!existsSync(templateDir)) {
77
+ throw new Error(`模板不存在: ${template}(可用模板见 ${TEMPLATES_ROOT})`)
78
+ }
75
79
  ensureDir(targetDir)
76
80
  await copyDirRecursive(templateDir, targetDir, context)
77
81
  }