@michengai/dsh-codex-suite-installer 0.1.18 → 0.1.20

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 (2) hide show
  1. package/installer.mjs +33 -12
  2. package/package.json +7 -7
package/installer.mjs CHANGED
@@ -9,7 +9,7 @@ export const WEB_BUNDLE = '@deepseek-ai/dsh-web-app'
9
9
 
10
10
  const suiteManifest = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8'))
11
11
 
12
- /** Keep the same layer order as the legacy aggregate patch. */
12
+ /** 保持与旧聚合补丁一致的成员加载顺序。 */
13
13
  export const MEMBER_PACKAGES = [
14
14
  '@michengai/dsh-archive-manager',
15
15
  '@michengai/dsh-codex-ui',
@@ -72,9 +72,23 @@ export function profileDirectory(profile, env = process.env, home = homedir()) {
72
72
  }
73
73
 
74
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]
75
+ const unique = bundles.filter((name, index) => typeof name === 'string' && bundles.indexOf(name) === index)
76
+ const baseIndex = unique.indexOf(BASE_BUNDLE)
77
+ const webIndex = unique.indexOf(WEB_BUNDLE)
78
+ if (baseIndex === -1) throw new Error(`目标 profile 缺少 ${BASE_BUNDLE} bundle,已中止迁移。`)
79
+ if (webIndex === -1) throw new Error(`目标 profile 缺少 ${WEB_BUNDLE} bundle,已中止迁移。`)
80
+ if (baseIndex > webIndex) throw new Error(`${BASE_BUNDLE} 必须位于 ${WEB_BUNDLE} 之前;安装器不会自动修改既有加载顺序。`)
81
+
82
+ const managed = new Set([SUITE_PACKAGE, ...MEMBER_PACKAGES])
83
+ const suiteIndex = unique.indexOf(SUITE_PACKAGE)
84
+ const firstMemberIndex = unique.findIndex(name => MEMBER_PACKAGES.includes(name))
85
+ const anchorIndex = suiteIndex === -1 ? firstMemberIndex : suiteIndex
86
+ const retained = unique.filter(name => !managed.has(name))
87
+ const minimumInsertionIndex = retained.indexOf(WEB_BUNDLE) + 1
88
+ const insertionIndex = anchorIndex === -1
89
+ ? retained.length
90
+ : Math.max(minimumInsertionIndex, unique.slice(0, anchorIndex).filter(name => !managed.has(name)).length)
91
+ return [...retained.slice(0, insertionIndex), ...MEMBER_PACKAGES, ...retained.slice(insertionIndex)]
78
92
  }
79
93
 
80
94
  export function allowRequiredBuilds(source) {
@@ -84,8 +98,10 @@ export function allowRequiredBuilds(source) {
84
98
  if (start === -1) return `${source}${source === '' || source.endsWith('\n') ? '' : eol}allowBuilds:${eol} protobufjs: false${eol} koffi: false${eol}`
85
99
  let end = start + 1
86
100
  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)
101
+ const existing = lines.slice(start + 1, end)
102
+ const indentation = existing.map(line => /^(\s+)\S/.exec(line)?.[1]).find(value => value !== undefined) ?? ' '
103
+ const body = existing.filter(line => !/^\s+(?:protobufjs|koffi):/.test(line))
104
+ lines.splice(start + 1, end - start - 1, `${indentation}protobufjs: false`, `${indentation}koffi: false`, ...body)
89
105
  return lines.join(eol)
90
106
  }
91
107
 
@@ -110,8 +126,8 @@ export function validateWindowsDshCommand(command) {
110
126
  throw new Error('DSH_BIN must be a command name or an absolute local Windows path.')
111
127
  }
112
128
 
113
- function quoteWindowsCommandArgument(argument) {
114
- if (/["\r\n]/u.test(argument)) throw new Error('dsh argument contains unsupported shell characters.')
129
+ export function quoteWindowsCommandArgument(argument) {
130
+ if (/["%^!\r\n]/u.test(argument)) throw new Error('dsh argument contains unsupported shell characters.')
115
131
  return `"${argument}"`
116
132
  }
117
133
 
@@ -143,11 +159,11 @@ function legacyDirectPackages(manifest) {
143
159
  ]
144
160
  }
145
161
 
146
- function writeNormalizedManifest(path) {
162
+ function writeNormalizedManifest(path, bundles) {
147
163
  const manifest = readProfileManifest(path)
148
164
  manifest.dsh ??= {}
149
165
  manifest.dsh.profile ??= {}
150
- manifest.dsh.profile.bundles = normalizeBundles(manifest.dsh.profile.bundles)
166
+ manifest.dsh.profile.bundles = bundles
151
167
  writeFileSync(path, `${JSON.stringify(manifest, undefined, 2)}\n`, 'utf8')
152
168
  }
153
169
 
@@ -160,7 +176,11 @@ export function installSuite(argv = process.argv.slice(2)) {
160
176
  const profilePath = profileDirectory(options.profile)
161
177
  const manifestPath = resolve(profilePath, 'package.json')
162
178
  const workspacePath = resolve(profilePath, 'pnpm-workspace.yaml')
163
- if (!existsSync(manifestPath)) runDsh(['plugin', '--profile', options.profile, 'install', '--lockfile-only', '--ignore-scripts'], options)
179
+ const manifestExists = existsSync(manifestPath)
180
+ if (!manifestExists) runDsh(['plugin', '--profile', options.profile, 'install', '--lockfile-only', '--ignore-scripts'], options)
181
+ const normalizedBundles = manifestExists || !options.dryRun
182
+ ? normalizeBundles(readProfileManifest(manifestPath).dsh?.profile?.bundles)
183
+ : undefined
164
184
  if (options.dryRun) {
165
185
  process.stdout.write(`> ensure protobufjs build scripts stay explicitly disabled in ${workspacePath}\n`)
166
186
  } else {
@@ -174,10 +194,11 @@ export function installSuite(argv = process.argv.slice(2)) {
174
194
  process.stdout.write(`> remove legacy ${SUITE_PACKAGE} and redundant direct ${WEB_BUNDLE} dependencies when present\n`)
175
195
  return
176
196
  }
197
+ if (normalizedBundles === undefined) throw new Error('无法读取目标 profile 的 bundle 配置。')
177
198
  const installedManifest = readProfileManifest(manifestPath)
178
199
  const legacyPackages = legacyDirectPackages(installedManifest)
179
200
  if (legacyPackages.length > 0) runDsh(['plugin', '--profile', options.profile, 'remove', ...legacyPackages], options)
180
- writeNormalizedManifest(manifestPath)
201
+ writeNormalizedManifest(manifestPath, normalizedBundles)
181
202
  runDsh(['--profile', options.profile, '--dump-config'], options)
182
203
  process.stdout.write(`\nCodex Suite members are direct plugins in profile ${options.profile}. Restart DSH and hard-refresh the browser.\n`)
183
204
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-suite-installer",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "轻量 DSH Codex Suite 安装器:将六个成员装为同一 profile 的直接插件",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -26,12 +26,12 @@
26
26
  },
27
27
  "dshCodexSuite": {
28
28
  "members": {
29
- "@michengai/dsh-archive-manager": "0.1.23",
30
- "@michengai/dsh-codex-ui": "0.2.101",
31
- "@michengai/dsh-skills-manager": "0.1.32",
32
- "@michengai/dsh-agency-agents": "0.1.25",
33
- "@michengai/dsh-im-connect": "0.1.30",
34
- "@michengai/dsh-automation": "0.1.22"
29
+ "@michengai/dsh-archive-manager": "0.1.30",
30
+ "@michengai/dsh-codex-ui": "0.2.103",
31
+ "@michengai/dsh-skills-manager": "0.1.38",
32
+ "@michengai/dsh-agency-agents": "0.1.30",
33
+ "@michengai/dsh-im-connect": "0.1.34",
34
+ "@michengai/dsh-automation": "0.1.29"
35
35
  }
36
36
  }
37
37
  }