@michengai/dsh-codex-suite 0.1.14 → 0.1.15

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # DSH Codex Suite
2
2
 
3
- `@michengai/dsh-codex-suite` is a one-click installer that adds Codex UI, expert management, skill management, archive management, IM Assistant, and scheduled tasks to one profile as six **direct dependencies**.
3
+ `@michengai/dsh-codex-suite` remains the compatibility aggregate for profiles installed with the old `dsh plugin add` command. For new installs and migration, use the lightweight `@michengai/dsh-codex-suite-installer`; it adds the six members as **direct dependencies**.
4
4
 
5
5
  ## Plugin combo
6
6
 
@@ -13,7 +13,7 @@
13
13
  | IM Assistant | `@michengai/dsh-im-connect` |
14
14
  | Scheduled tasks | `@michengai/dsh-automation` |
15
15
 
16
- Each Suite release pins one exact, verified member set. Making the members direct dependencies lets **Settings About** detect, install, and update them independently. `dshmarket` remains optional.
16
+ Each Suite release pins one exact, verified member set. The separate installer has no member runtime dependency tree of its own, so `npx` can start immediately and let DSH install the members directly. `dshmarket` remains optional.
17
17
 
18
18
  ## One-click installation
19
19
 
@@ -22,7 +22,7 @@ Node.js 22+ is required, and the current DSH `dsh` command must be on PATH. Run
22
22
  ```powershell
23
23
  [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
24
24
  $OutputEncoding = [System.Text.Encoding]::UTF8
25
- npx --yes @michengai/dsh-codex-suite@latest --profile web
25
+ npx --yes @michengai/dsh-codex-suite-installer@latest --profile web
26
26
  ```
27
27
 
28
28
  The installer:
@@ -39,7 +39,7 @@ Restart DSH Web and hard-refresh the browser afterwards. Set `DSH_BIN` when `dsh
39
39
  Keep the same `DSH_HOME` and choose another profile name:
40
40
 
41
41
  ```powershell
42
- npx --yes @michengai/dsh-codex-suite@latest --profile codex
42
+ npx --yes @michengai/dsh-codex-suite-installer@latest --profile codex
43
43
  ```
44
44
 
45
45
  DSH supplies `@deepseek-ai/dsh-base` when it creates a custom profile. The installer places DSH's built-in `@deepseek-ai/dsh-web-app` before the six member bundles without creating a separate Home or reinstalling the official Web package from npm.
package/README.zh-CN.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # DSH Codex Suite
2
2
 
3
- `@michengai/dsh-codex-suite` 是一键安装器:把 Codex UI、专家、技能、归档、IM 助理和定时任务作为目标 profile 的六个**直接依赖**安装。
3
+ `@michengai/dsh-codex-suite` 保留为兼容旧版 `dsh plugin add` 的聚合包。新安装和旧版迁移请使用轻量的 `@michengai/dsh-codex-suite-installer`,它会把六个成员写成目标 profile 的**直接依赖**。
4
4
 
5
5
  ## 插件组合
6
6
 
@@ -13,7 +13,7 @@
13
13
  | IM 助理 | `@michengai/dsh-im-connect` |
14
14
  | 定时任务 | `@michengai/dsh-automation` |
15
15
 
16
- 每个 Suite 版本锁定一组经过验证的成员精确版本。成员成为直接依赖后,「设置 关于」可以分别检测、安装和升级它们。`dshmarket` 不在套件内,需要时单独安装。
16
+ 每个 Suite 版本锁定一组经过验证的成员精确版本。独立安装器自身不携带成员运行时依赖树,因此 `npx` 可以立即启动,再交给 DSH 直接安装成员。`dshmarket` 不在套件内,需要时单独安装。
17
17
 
18
18
  ## 一键安装
19
19
 
@@ -22,7 +22,7 @@
22
22
  ```powershell
23
23
  [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
24
24
  $OutputEncoding = [System.Text.Encoding]::UTF8
25
- npx --yes @michengai/dsh-codex-suite@latest --profile web
25
+ npx --yes @michengai/dsh-codex-suite-installer@latest --profile web
26
26
  ```
27
27
 
28
28
  安装器会:
@@ -39,7 +39,7 @@ npx --yes @michengai/dsh-codex-suite@latest --profile web
39
39
  保持同一个 `DSH_HOME`,只需换一个 profile 名:
40
40
 
41
41
  ```powershell
42
- npx --yes @michengai/dsh-codex-suite@latest --profile codex
42
+ npx --yes @michengai/dsh-codex-suite-installer@latest --profile codex
43
43
  ```
44
44
 
45
45
  DSH 创建自定义 profile 时会提供 `@deepseek-ai/dsh-base`。安装器会再把 DSH 自带的 `@deepseek-ai/dsh-web-app` 放到六个成员 bundle 之前,不会创建独立 Home,也不会通过 npm 重装官方 Web 包。
package/package.json CHANGED
@@ -1,22 +1,14 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-suite",
3
- "version": "0.1.14",
4
- "description": "DSH Codex UI 一键安装器:将侧栏、专家、技能、归档、IM 助理和定时任务装为直接插件",
3
+ "version": "0.1.15",
4
+ "description": "DSH Codex UI 兼容聚合包:保留旧版 dsh plugin add 安装方式",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
- "engines": {
8
- "node": ">=22"
9
- },
10
7
  "files": [
11
- "bin.mjs",
12
- "installer.mjs",
13
8
  "cordis.patch.yml",
14
9
  "README.md",
15
10
  "README.zh-CN.md"
16
11
  ],
17
- "bin": {
18
- "dsh-codex-suite": "./bin.mjs"
19
- },
20
12
  "dsh": {
21
13
  "bundle": {
22
14
  "patch": "./cordis.patch.yml"
@@ -32,6 +24,6 @@
32
24
  "@michengai/dsh-automation": "0.1.14",
33
25
  "@michengai/dsh-im-connect": "0.1.23",
34
26
  "@michengai/dsh-skills-manager": "0.1.24",
35
- "@michengai/dsh-codex-ui": "0.2.82"
27
+ "@michengai/dsh-codex-ui": "0.2.83"
36
28
  }
37
29
  }
package/bin.mjs DELETED
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { installSuite } from './installer.mjs'
4
-
5
- try {
6
- installSuite()
7
- } catch (error) {
8
- process.stderr.write(`dsh-codex-suite: ${error instanceof Error ? error.message : String(error)}\n`)
9
- process.exitCode = 1
10
- }
package/installer.mjs DELETED
@@ -1,169 +0,0 @@
1
- import { spawnSync } from 'node:child_process'
2
- import { existsSync, readFileSync, writeFileSync } from 'node:fs'
3
- import { homedir } from 'node:os'
4
- import { resolve } from 'node:path'
5
-
6
- export const SUITE_PACKAGE = '@michengai/dsh-codex-suite'
7
- export const BASE_BUNDLE = '@deepseek-ai/dsh-base'
8
- export const WEB_BUNDLE = '@deepseek-ai/dsh-web-app'
9
-
10
- const suiteManifest = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8'))
11
-
12
- /** Keep the same layer order as the legacy aggregate patch. */
13
- export const MEMBER_PACKAGES = [
14
- '@michengai/dsh-archive-manager',
15
- '@michengai/dsh-codex-ui',
16
- '@michengai/dsh-skills-manager',
17
- '@michengai/dsh-agency-agents',
18
- '@michengai/dsh-im-connect',
19
- '@michengai/dsh-automation',
20
- ]
21
-
22
- export function memberSpecs(manifest = suiteManifest) {
23
- return MEMBER_PACKAGES.map((packageName) => {
24
- let version = manifest.dependencies?.[packageName]
25
- if (version?.startsWith('workspace:') === true && packageName === '@michengai/dsh-codex-ui') {
26
- version = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')).version
27
- }
28
- if (typeof version !== 'string' || version === '' || version.startsWith('workspace:')) {
29
- throw new Error(`Suite manifest does not contain a published version for ${packageName}.`)
30
- }
31
- return `${packageName}@${version}`
32
- })
33
- }
34
-
35
- export function parseArgs(argv) {
36
- const options = {
37
- profile: 'web',
38
- registry: 'https://registry.npmjs.org/',
39
- dryRun: false,
40
- help: false,
41
- }
42
- for (let index = 0; index < argv.length; index += 1) {
43
- const argument = argv[index]
44
- if (argument === '--help' || argument === '-h') options.help = true
45
- else if (argument === '--dry-run') options.dryRun = true
46
- else if (argument === '--profile') options.profile = argv[++index]
47
- else if (argument.startsWith('--profile=')) options.profile = argument.slice('--profile='.length)
48
- else if (argument === '--registry') options.registry = argv[++index]
49
- else if (argument.startsWith('--registry=')) options.registry = argument.slice('--registry='.length)
50
- else throw new Error(`Unknown argument: ${argument}`)
51
- }
52
- if (typeof options.profile !== 'string' || !/^[0-9A-Za-z][0-9A-Za-z._-]*$/.test(options.profile) || options.profile === 'node_modules') {
53
- throw new Error(`Invalid DSH profile name: ${JSON.stringify(options.profile)}`)
54
- }
55
- let registry
56
- try {
57
- registry = new URL(options.registry)
58
- } catch {
59
- throw new Error(`Invalid npm registry URL: ${JSON.stringify(options.registry)}`)
60
- }
61
- if (registry.protocol !== 'https:' && registry.protocol !== 'http:') throw new Error('npm registry must use HTTP or HTTPS.')
62
- if (registry.username !== '' || registry.password !== '' || registry.search !== '' || registry.hash !== '' || !/^[0-9A-Za-z._~/-]*$/.test(registry.pathname)) {
63
- throw new Error('npm registry URL contains unsupported characters.')
64
- }
65
- options.registry = registry.href
66
- return options
67
- }
68
-
69
- export function profileDirectory(profile, env = process.env, home = homedir()) {
70
- const dshHome = env.DSH_HOME === undefined || env.DSH_HOME === '' ? resolve(home, '.dsh') : resolve(env.DSH_HOME)
71
- return resolve(dshHome, 'profiles', profile)
72
- }
73
-
74
- export function normalizeBundles(bundles = []) {
75
- const managed = new Set([BASE_BUNDLE, WEB_BUNDLE, SUITE_PACKAGE, ...MEMBER_PACKAGES])
76
- const unrelated = bundles.filter((name, index) => typeof name === 'string' && !managed.has(name) && bundles.indexOf(name) === index)
77
- return [BASE_BUNDLE, WEB_BUNDLE, ...unrelated, ...MEMBER_PACKAGES]
78
- }
79
-
80
- export function allowRequiredBuilds(source) {
81
- const eol = source.includes('\r\n') ? '\r\n' : '\n'
82
- const lines = source.split(/\r?\n/)
83
- const start = lines.findIndex(line => line === 'allowBuilds:')
84
- if (start === -1) return `${source}${source === '' || source.endsWith('\n') ? '' : eol}allowBuilds:${eol} protobufjs: false${eol} koffi: false${eol}`
85
- let end = start + 1
86
- while (end < lines.length && (lines[end] === '' || /^\s/.test(lines[end]))) end += 1
87
- const body = lines.slice(start + 1, end).filter(line => !/^\s{2}(?:protobufjs|koffi):/.test(line))
88
- lines.splice(start + 1, end - start - 1, ' protobufjs: false', ' koffi: false', ...body)
89
- return lines.join(eol)
90
- }
91
-
92
- export function directInstallArgs(profile, registry, manifest = suiteManifest) {
93
- return ['plugin', '--profile', profile, 'add', ...memberSpecs(manifest), '--save-exact', `--registry=${registry}`]
94
- }
95
-
96
- export function helpText() {
97
- return `Usage: dsh-codex-suite [options]\n\nInstall every Codex Suite member as a direct dependency of one DSH profile.\n\nOptions:\n --profile <name> target profile (default: web)\n --registry <url> npm registry (default: https://registry.npmjs.org/)\n --dry-run print commands without changing the profile\n -h, --help show this help\n`
98
- }
99
-
100
- function quote(argument) {
101
- return /[\s"']/u.test(argument) ? JSON.stringify(argument) : argument
102
- }
103
-
104
- function runDsh(args, { dryRun = false, command = process.env.DSH_BIN || 'dsh' } = {}) {
105
- process.stdout.write(`> dsh ${args.map(quote).join(' ')}\n`)
106
- if (dryRun) return
107
- const result = process.platform === 'win32'
108
- ? spawnSync(process.env.ComSpec || 'cmd.exe', ['/d', '/s', '/c', `call ${/\s/.test(command) ? `"${command.replaceAll('"', '""')}"` : command} ${args.join(' ')}`], { encoding: 'utf8', stdio: 'inherit', windowsHide: true })
109
- : spawnSync(command, args, { encoding: 'utf8', stdio: 'inherit' })
110
- if (result.error !== undefined) throw new Error(`Unable to run dsh: ${result.error.message}`)
111
- if (result.status !== 0) throw new Error(`dsh exited with code ${result.status ?? 1}.`)
112
- }
113
-
114
- function readProfileManifest(path) {
115
- return JSON.parse(readFileSync(path, 'utf8'))
116
- }
117
-
118
- function suiteDeclared(manifest) {
119
- return manifest.dependencies?.[SUITE_PACKAGE] !== undefined
120
- || manifest.devDependencies?.[SUITE_PACKAGE] !== undefined
121
- || manifest.dsh?.profile?.bundles?.includes(SUITE_PACKAGE) === true
122
- }
123
-
124
- function legacyDirectPackages(manifest) {
125
- const declared = { ...manifest.devDependencies, ...manifest.dependencies }
126
- return [
127
- ...(suiteDeclared(manifest) ? [SUITE_PACKAGE] : []),
128
- ...(declared[WEB_BUNDLE] !== undefined ? [WEB_BUNDLE] : []),
129
- ]
130
- }
131
-
132
- function writeNormalizedManifest(path) {
133
- const manifest = readProfileManifest(path)
134
- manifest.dsh ??= {}
135
- manifest.dsh.profile ??= {}
136
- manifest.dsh.profile.bundles = normalizeBundles(manifest.dsh.profile.bundles)
137
- writeFileSync(path, `${JSON.stringify(manifest, undefined, 2)}\n`, 'utf8')
138
- }
139
-
140
- export function installSuite(argv = process.argv.slice(2)) {
141
- const options = parseArgs(argv)
142
- if (options.help) {
143
- process.stdout.write(helpText())
144
- return
145
- }
146
- const profilePath = profileDirectory(options.profile)
147
- const manifestPath = resolve(profilePath, 'package.json')
148
- const workspacePath = resolve(profilePath, 'pnpm-workspace.yaml')
149
- if (!existsSync(manifestPath)) runDsh(['plugin', '--profile', options.profile, 'install', '--lockfile-only', '--ignore-scripts'], options)
150
- if (options.dryRun) {
151
- process.stdout.write(`> ensure protobufjs build scripts stay explicitly disabled in ${workspacePath}\n`)
152
- } else {
153
- const workspace = existsSync(workspacePath) ? readFileSync(workspacePath, 'utf8') : ''
154
- const nextWorkspace = allowRequiredBuilds(workspace)
155
- if (nextWorkspace !== workspace) writeFileSync(workspacePath, nextWorkspace, 'utf8')
156
- }
157
- runDsh(directInstallArgs(options.profile, options.registry), options)
158
- if (options.dryRun) {
159
- process.stdout.write(`> ensure ${WEB_BUNDLE} precedes the six member bundles in ${manifestPath}\n`)
160
- process.stdout.write(`> remove legacy ${SUITE_PACKAGE} and redundant direct ${WEB_BUNDLE} dependencies when present\n`)
161
- return
162
- }
163
- const installedManifest = readProfileManifest(manifestPath)
164
- const legacyPackages = legacyDirectPackages(installedManifest)
165
- if (legacyPackages.length > 0) runDsh(['plugin', '--profile', options.profile, 'remove', ...legacyPackages], options)
166
- writeNormalizedManifest(manifestPath)
167
- runDsh(['--profile', options.profile, '--dump-config'], options)
168
- process.stdout.write(`\nCodex Suite members are direct plugins in profile ${options.profile}. Restart DSH and hard-refresh the browser.\n`)
169
- }