chore(runtime): upgrade DSH and bundled plugins for runtime-7.11
This commit is contained in:
@@ -1,5 +1,13 @@
|
|||||||
# DSH Runtime Release
|
# DSH Runtime Release
|
||||||
|
|
||||||
|
## runtime-7.11:DSH rc.5 与内置插件更新(待运行验收)
|
||||||
|
|
||||||
|
DSH 从 `0.2.1-rc.3` 更新为 `0.2.1-rc.5`(查询时 npm `latest` 和 `next` 均为此版本,不切换 alpha 渠道)。free-search 从 `0.9.15` 更新为 `0.9.21`,Chat Manager 从 `1.5.18-dsh-mgr.1` 更新为 `1.5.20-dsh-mgr.1`。mobile `3.2.1` 已是最新;自有 workspace `1.0.0`、preview-download `1.0.1` 及运行布局 7 不变。
|
||||||
|
|
||||||
|
同步安装归档 SHA-512、新 profile、已有内置归档迁移目标及精确宿主版本门禁,保留自定义来源、启用选择和备份机制。真实发布包的 Chat Manager 客户端补丁、原生设置接口及 Office converter 导入检查通过。48 项单元测试通过,新增 runtime-7.10 插件引用迁移、备份和幂等回归。完整镜像与运行验收结果另行记录;未提交、推送或修改线上实例。
|
||||||
|
|
||||||
|
AMD64 镜像 `dsh-web:runtime-7.11-amd64` 已成功构建;新版本真实依赖、插件 SHA-512 和安装期兼容性检查全部通过。禁网 UID 1000 新 profile 离线安装、重复执行启动入口(`--version`)及锁文件 SHA-256 不变通过;默认 Web 服务启动后,3080/8080 未认证请求均为 HTTP 401。测试容器已清理,未挂载现有工作区。尚未验收浏览器交互、真实搜索、设置保存、Office 实际转换、终端原生模块及 ARM64;本机没有 runtime-7.10 镜像,旧镜像锁文件迁移集成测试未执行(配置迁移单元回归已通过)。
|
||||||
|
|
||||||
## runtime-7.10:DSH rc.3 与内置插件更新(待运行验收)
|
## runtime-7.10:DSH rc.3 与内置插件更新(待运行验收)
|
||||||
|
|
||||||
沿用此前的 npm `next` 渠道,DSH 精确固定为 `0.2.1-rc.3`;查询时 `latest` 为 `0.2.1-rc.2`。mobile 更新为 `3.2.1`,free-search 为 `0.9.15`,Chat Manager 为 `1.5.18-dsh-mgr.1`(基于上游 `1.5.18`)。workspace `1.0.0`、preview-download `1.0.1` 和运行布局 7 保持不变。三个上游插件归档的 SHA-512 已核对并更新。
|
沿用此前的 npm `next` 渠道,DSH 精确固定为 `0.2.1-rc.3`;查询时 `latest` 为 `0.2.1-rc.2`。mobile 更新为 `3.2.1`,free-search 为 `0.9.15`,Chat Manager 为 `1.5.18-dsh-mgr.1`(基于上游 `1.5.18`)。workspace `1.0.0`、preview-download `1.0.1` 和运行布局 7 保持不变。三个上游插件归档的 SHA-512 已核对并更新。
|
||||||
@@ -106,7 +114,7 @@ Runtime 镜像包含 Debian Bookworm 的 Python 3、pip、venv(`python` 指向
|
|||||||
|
|
||||||
## 发布清单
|
## 发布清单
|
||||||
|
|
||||||
`release.json` 是发布入口:`schema_version` 为清单格式版本,`release_id` 标识一次发布,`version` 为精确 DSH 版本,`deployment_schema` 为运行布局版本,`platforms` 为支持的平台。当前待验收配置为 `runtime-7.10`、DSH `0.2.1-rc.3`、布局 7、`linux/amd64` 和 `linux/arm64`(aarch64,不含 32 位 ARM)。
|
`release.json` 是发布入口:`schema_version` 为清单格式版本,`release_id` 标识一次发布,`version` 为精确 DSH 版本,`deployment_schema` 为运行布局版本,`platforms` 为支持的平台。当前待验收配置为 `runtime-7.11`、DSH `0.2.1-rc.5`、布局 7、`linux/amd64` 和 `linux/arm64`(aarch64,不含 32 位 ARM)。
|
||||||
|
|
||||||
ARM64 验收状态:已确认 Node/Caddy 基础镜像提供 ARM64 版本,但尚未完成 ARM64 runtime 构建及运行验收。清单声明会开放面板的对应平台构建入口,不等于兼容性证明;验收完成前不要推送发布。
|
ARM64 验收状态:已确认 Node/Caddy 基础镜像提供 ARM64 版本,但尚未完成 ARM64 runtime 构建及运行验收。清单声明会开放面板的对应平台构建入口,不等于兼容性证明;验收完成前不要推送发布。
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export function initProfile(home, options) {
|
|||||||
pnpm: { overrides: BUILTIN_OVERRIDES },
|
pnpm: { overrides: BUILTIN_OVERRIDES },
|
||||||
dsh: { profile: { bundles: ['@deepseek-ai/dsh-base', '@deepseek-ai/dsh-web-app', 'dsh-web-mobile', 'dsh-free-search', 'dsh-mgr-workspace', 'dsh-chat-manager', 'dsh-preview-download'] } },
|
dsh: { profile: { bundles: ['@deepseek-ai/dsh-base', '@deepseek-ai/dsh-web-app', 'dsh-web-mobile', 'dsh-free-search', 'dsh-mgr-workspace', 'dsh-chat-manager', 'dsh-preview-download'] } },
|
||||||
}, null, 2), { flag: 'wx', mode: 0o600 });
|
}, null, 2), { flag: 'wx', mode: 0o600 });
|
||||||
console.log('dsh-mgr: new web profile includes [email protected] and [email protected]5 and [email protected].18-dsh-mgr.1');
|
console.log('dsh-mgr: new web profile includes [email protected] and [email protected].21 and [email protected].20-dsh-mgr.1');
|
||||||
}
|
}
|
||||||
const migration = reconcileProfile(profile, options);
|
const migration = reconcileProfile(profile, options);
|
||||||
console.log(migration.changed
|
console.log(migration.changed
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ test('new profile enables bundle once and preserves existing configuration', ()
|
|||||||
assert.equal(JSON.parse(original).dependencies['dsh-preview-download'], 'file:/usr/local/lib/dsh-mgr/dsh-preview-download-1.0.1.tgz');
|
assert.equal(JSON.parse(original).dependencies['dsh-preview-download'], 'file:/usr/local/lib/dsh-mgr/dsh-preview-download-1.0.1.tgz');
|
||||||
assert.equal(JSON.parse(original).dsh.profile.bundles.filter(name => name === 'dsh-preview-download').length, 1);
|
assert.equal(JSON.parse(original).dsh.profile.bundles.filter(name => name === 'dsh-preview-download').length, 1);
|
||||||
assert.ok(JSON.parse(original).dsh.profile.bundles.includes('dsh-chat-manager'));
|
assert.ok(JSON.parse(original).dsh.profile.bundles.includes('dsh-chat-manager'));
|
||||||
assert.equal(JSON.parse(original).dependencies['dsh-chat-manager'], 'file:/usr/local/lib/dsh-mgr/dsh-chat-manager-1.5.18-dsh-mgr.1.tgz');
|
assert.equal(JSON.parse(original).dependencies['dsh-chat-manager'], 'file:/usr/local/lib/dsh-mgr/dsh-chat-manager-1.5.20-dsh-mgr.1.tgz');
|
||||||
assert.equal(JSON.parse(original).pnpm.overrides['dsh-chat-manager>clsx'], 'file:/usr/local/lib/dsh-mgr/clsx-2.1.1.tgz');
|
assert.equal(JSON.parse(original).pnpm.overrides['dsh-chat-manager>clsx'], 'file:/usr/local/lib/dsh-mgr/clsx-2.1.1.tgz');
|
||||||
assert.ok(JSON.parse(original).dsh.profile.bundles.includes('dsh-web-mobile'));
|
assert.ok(JSON.parse(original).dsh.profile.bundles.includes('dsh-web-mobile'));
|
||||||
assert.ok(JSON.parse(original).dsh.profile.bundles.includes('dsh-free-search'));
|
assert.ok(JSON.parse(original).dsh.profile.bundles.includes('dsh-free-search'));
|
||||||
assert.ok(JSON.parse(original).dsh.profile.bundles.includes('dsh-mgr-workspace'));
|
assert.ok(JSON.parse(original).dsh.profile.bundles.includes('dsh-mgr-workspace'));
|
||||||
assert.equal(JSON.parse(original).dependencies['dsh-mgr-workspace'], 'file:/usr/local/lib/dsh-mgr/dsh-mgr-workspace-1.0.0.tgz');
|
assert.equal(JSON.parse(original).dependencies['dsh-mgr-workspace'], 'file:/usr/local/lib/dsh-mgr/dsh-mgr-workspace-1.0.0.tgz');
|
||||||
assert.equal(JSON.parse(original).dependencies['dsh-free-search'], 'file:/usr/local/lib/dsh-mgr/dsh-free-search-0.9.15.tgz');
|
assert.equal(JSON.parse(original).dependencies['dsh-free-search'], 'file:/usr/local/lib/dsh-mgr/dsh-free-search-0.9.21.tgz');
|
||||||
assert.equal(JSON.parse(original).pnpm.overrides['dsh-free-search>@deepseek-ai/schemastery'], 'file:/usr/local/lib/dsh-mgr/schemastery-3.18.4.tgz');
|
assert.equal(JSON.parse(original).pnpm.overrides['dsh-free-search>@deepseek-ai/schemastery'], 'file:/usr/local/lib/dsh-mgr/schemastery-3.18.4.tgz');
|
||||||
assert.equal(JSON.parse(original).dependencies['dsh-web-mobile'], 'file:/usr/local/lib/dsh-mgr/dsh-web-mobile-3.2.1.tgz');
|
assert.equal(JSON.parse(original).dependencies['dsh-web-mobile'], 'file:/usr/local/lib/dsh-mgr/dsh-web-mobile-3.2.1.tgz');
|
||||||
const workspace = join(home, 'profiles/web/pnpm-workspace.yaml');
|
const workspace = join(home, 'profiles/web/pnpm-workspace.yaml');
|
||||||
@@ -67,7 +67,7 @@ test('chat-manager-only restored profile gets overrides and offline peer setting
|
|||||||
try {
|
try {
|
||||||
const profile = join(home, 'profiles/web');
|
const profile = join(home, 'profiles/web');
|
||||||
mkdirSync(profile, { recursive: true });
|
mkdirSync(profile, { recursive: true });
|
||||||
const manifest = JSON.stringify({ dependencies: { 'dsh-chat-manager': 'file:/usr/local/lib/dsh-mgr/dsh-chat-manager-1.5.18-dsh-mgr.1.tgz' } });
|
const manifest = JSON.stringify({ dependencies: { 'dsh-chat-manager': 'file:/usr/local/lib/dsh-mgr/dsh-chat-manager-1.5.20-dsh-mgr.1.tgz' } });
|
||||||
writeFileSync(join(profile, 'package.json'), manifest);
|
writeFileSync(join(profile, 'package.json'), manifest);
|
||||||
initProfile(home, archives(home));
|
initProfile(home, archives(home));
|
||||||
assert.deepEqual(JSON.parse(readFileSync(join(profile, 'package.json'))), { ...JSON.parse(manifest), pnpm: { overrides: { 'dsh-chat-manager>clsx': BUILTIN_OVERRIDES['dsh-chat-manager>clsx'] } } });
|
assert.deepEqual(JSON.parse(readFileSync(join(profile, 'package.json'))), { ...JSON.parse(manifest), pnpm: { overrides: { 'dsh-chat-manager>clsx': BUILTIN_OVERRIDES['dsh-chat-manager>clsx'] } } });
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import { createRequire } from 'node:module';
|
|||||||
import { patchClient } from './patch-chat-manager.mjs';
|
import { patchClient } from './patch-chat-manager.mjs';
|
||||||
|
|
||||||
const root = '/usr/local/lib/dsh-mgr';
|
const root = '/usr/local/lib/dsh-mgr';
|
||||||
const version = '1.5.18';
|
const version = '1.5.20';
|
||||||
const patchedVersion = '1.5.18-dsh-mgr.1';
|
const patchedVersion = '1.5.20-dsh-mgr.1';
|
||||||
const hostManifest = '/usr/local/lib/node_modules/@deepseek-ai/dsh/package.json';
|
const hostManifest = '/usr/local/lib/node_modules/@deepseek-ai/dsh/package.json';
|
||||||
const destination = '/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/dsh-chat-manager';
|
const destination = '/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/dsh-chat-manager';
|
||||||
const packages = [
|
const packages = [
|
||||||
['dsh-chat-manager', version, 'https://registry.npmjs.org/dsh-chat-manager/-/dsh-chat-manager-1.5.18.tgz', 'kkGog/h162duGKjeSx5NgN/KRzsniIPXeUTTcAMyTM9ci0eA/KdORUpR8v/AqWPBNH/CAg3F1+OgXUpbI4vkLQ=='],
|
['dsh-chat-manager', version, 'https://registry.npmjs.org/dsh-chat-manager/-/dsh-chat-manager-1.5.20.tgz', 'V/7N48lJioxBr2h+hmVnNoZB5jjoT/EGC6Pk8pSbNJveQoHye+zBj3tUX1Xf520YyopVk5fSVpt+aeCkBBVxdA=='],
|
||||||
['clsx', '2.1.1', 'https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz', 'eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=='],
|
['clsx', '2.1.1', 'https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz', 'eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=='],
|
||||||
];
|
];
|
||||||
mkdirSync(root, { recursive: true });
|
mkdirSync(root, { recursive: true });
|
||||||
@@ -30,7 +30,7 @@ const require = createRequire(hostManifest);
|
|||||||
const host = JSON.parse(readFileSync(hostManifest));
|
const host = JSON.parse(readFileSync(hostManifest));
|
||||||
const semver = createRequire('/usr/local/lib/node_modules/npm/package.json')('semver');
|
const semver = createRequire('/usr/local/lib/node_modules/npm/package.json')('semver');
|
||||||
for (const [name, range] of Object.entries(pkg.peerDependencies || {})) {
|
for (const [name, range] of Object.entries(pkg.peerDependencies || {})) {
|
||||||
// 1.5.18 retains this optional legacy peer but its runtime no longer imports it.
|
// 1.5.20 retains this optional legacy peer but its runtime no longer imports it.
|
||||||
if (name === '@deepseek-ai/dsh-invariants' && pkg.peerDependenciesMeta?.[name]?.optional) {
|
if (name === '@deepseek-ai/dsh-invariants' && pkg.peerDependenciesMeta?.[name]?.optional) {
|
||||||
for (const file of ['src/index.js', 'src/host/archive-manager.mjs', 'src/host/delete-session.mjs', 'lib/client.js']) {
|
for (const file of ['src/index.js', 'src/host/archive-manager.mjs', 'src/host/delete-session.mjs', 'lib/client.js']) {
|
||||||
if (readFileSync(destination + '/' + file, 'utf8').includes(name)) throw new Error('legacy invariants peer is used again');
|
if (readFileSync(destination + '/' + file, 'utf8').includes(name)) throw new Error('legacy invariants peer is used again');
|
||||||
@@ -38,11 +38,11 @@ for (const [name, range] of Object.entries(pkg.peerDependencies || {})) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (name === 'react') {
|
if (name === 'react') {
|
||||||
if (host.version !== '0.2.1-rc.3') throw new Error('unverified browser React host: ' + host.version);
|
if (host.version !== '0.2.1-rc.5') throw new Error('unverified browser React host: ' + host.version);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// New web hosts bundle this pure UI module in the browser bootstrap.
|
// New web hosts bundle this pure UI module in the browser bootstrap.
|
||||||
if (['@deepseek-ai/dsh-client-ui-primitives', '@deepseek-ai/dsh-client-ui-slots'].includes(name) && host.version === '0.2.1-rc.3') {
|
if (['@deepseek-ai/dsh-client-ui-primitives', '@deepseek-ai/dsh-client-ui-slots'].includes(name) && host.version === '0.2.1-rc.5') {
|
||||||
const frontend = require.resolve('@deepseek-ai/dsh-web-frontend/package.json');
|
const frontend = require.resolve('@deepseek-ai/dsh-web-frontend/package.json');
|
||||||
const assets = frontend.slice(0, -'package.json'.length) + 'dist/assets';
|
const assets = frontend.slice(0, -'package.json'.length) + 'dist/assets';
|
||||||
const frontendVersion = JSON.parse(readFileSync(frontend)).version;
|
const frontendVersion = JSON.parse(readFileSync(frontend)).version;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { execFileSync } from 'node:child_process';
|
|||||||
import { createRequire } from 'node:module';
|
import { createRequire } from 'node:module';
|
||||||
const root = '/usr/local/lib/dsh-mgr';
|
const root = '/usr/local/lib/dsh-mgr';
|
||||||
const packages = [
|
const packages = [
|
||||||
['dsh-free-search', '0.9.15', 'https://registry.npmjs.org/dsh-free-search/-/dsh-free-search-0.9.15.tgz', 'T6YxSR4NOK3c7ivdqDxrOdgdORGYBFmGbM7oZNpFUVZg2KIbU0f4TSOO99wjG0NnSrwqjdc1i/yK8pviZHtVhA=='],
|
['dsh-free-search', '0.9.21', 'https://registry.npmjs.org/dsh-free-search/-/dsh-free-search-0.9.21.tgz', '3RtN+hphVn5WcqjbwPBkG+QGgz7YO6KtkAKQFmWmsVl3lmDEhLENuno95JheKahllt0IXCLFCTHsI2HSzttg4g=='],
|
||||||
['@deepseek-ai/schemastery', '3.18.4', 'https://registry.npmjs.org/@deepseek-ai/schemastery/-/schemastery-3.18.4.tgz', 'SSXO6tYuyrIqKVbmOnIq0s+riUywYzouFMcnBluHF9n4KMo2G8HvEzhCYj6pj2617/glOjbJuVInJ9hfONsjkg=='],
|
['@deepseek-ai/schemastery', '3.18.4', 'https://registry.npmjs.org/@deepseek-ai/schemastery/-/schemastery-3.18.4.tgz', 'SSXO6tYuyrIqKVbmOnIq0s+riUywYzouFMcnBluHF9n4KMo2G8HvEzhCYj6pj2617/glOjbJuVInJ9hfONsjkg=='],
|
||||||
['@deepseek-ai/cosmokit', '1.8.5', 'https://registry.npmjs.org/@deepseek-ai/cosmokit/-/cosmokit-1.8.5.tgz', 'LXsrlem9z8dq4sLflj2yuCuYX7KqhdzF5hZly3eZyuTo8d6oDSOXuEgC5DbQWKW+lksm6zmOutQLsP/ma6wR6A=='],
|
['@deepseek-ai/cosmokit', '1.8.5', 'https://registry.npmjs.org/@deepseek-ai/cosmokit/-/cosmokit-1.8.5.tgz', 'LXsrlem9z8dq4sLflj2yuCuYX7KqhdzF5hZly3eZyuTo8d6oDSOXuEgC5DbQWKW+lksm6zmOutQLsP/ma6wR6A=='],
|
||||||
['@standard-schema/spec', '1.1.0', 'https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz', 'l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=='],
|
['@standard-schema/spec', '1.1.0', 'https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz', 'l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=='],
|
||||||
@@ -20,21 +20,21 @@ for (const [name, version, url, integrity] of packages) {
|
|||||||
const hostManifest = '/usr/local/lib/node_modules/@deepseek-ai/dsh/package.json';
|
const hostManifest = '/usr/local/lib/node_modules/@deepseek-ai/dsh/package.json';
|
||||||
const destination = '/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/dsh-free-search';
|
const destination = '/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/dsh-free-search';
|
||||||
mkdirSync(destination, { recursive: true });
|
mkdirSync(destination, { recursive: true });
|
||||||
execFileSync('tar', ['-xzf', `${root}/dsh-free-search-0.9.15.tgz`, '--strip-components=1', '--no-same-owner', '-C', destination]);
|
execFileSync('tar', ['-xzf', `${root}/dsh-free-search-0.9.21.tgz`, '--strip-components=1', '--no-same-owner', '-C', destination]);
|
||||||
execFileSync('chmod', ['-R', 'a+rX', destination]);
|
execFileSync('chmod', ['-R', 'a+rX', destination]);
|
||||||
const pkg = JSON.parse(readFileSync(destination + '/package.json'));
|
const pkg = JSON.parse(readFileSync(destination + '/package.json'));
|
||||||
if (pkg.name !== 'dsh-free-search' || pkg.version !== '0.9.15' || JSON.stringify(pkg.dependencies) !== JSON.stringify({ '@deepseek-ai/schemastery': '^3.18.4' })) throw new Error('unexpected free-search metadata');
|
if (pkg.name !== 'dsh-free-search' || pkg.version !== '0.9.21' || JSON.stringify(pkg.dependencies) !== JSON.stringify({ '@deepseek-ai/schemastery': '^3.18.4' })) throw new Error('unexpected free-search metadata');
|
||||||
const require = createRequire(hostManifest);
|
const require = createRequire(hostManifest);
|
||||||
const semver = createRequire('/usr/local/lib/node_modules/npm/package.json')('semver');
|
const semver = createRequire('/usr/local/lib/node_modules/npm/package.json')('semver');
|
||||||
for (const [name, range] of Object.entries({ ...pkg.peerDependencies, ...pkg.dependencies })) {
|
for (const [name, range] of Object.entries({ ...pkg.peerDependencies, ...pkg.dependencies })) {
|
||||||
if (name === 'react') {
|
if (name === 'react') {
|
||||||
if (require('./package.json').version !== '0.2.1-rc.3') throw new Error('unverified browser React host');
|
if (require('./package.json').version !== '0.2.1-rc.5') throw new Error('unverified browser React host');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const peer = require(name + '/package.json');
|
const peer = require(name + '/package.json');
|
||||||
if (!(semver.satisfies(peer.version, range) || (peer.version === "0.2.1-rc.3" && name.startsWith("@deepseek-ai/dsh-") && semver.satisfies(peer.version, range, { includePrerelease: true })))) throw new Error('incompatible free-search host dependency: ' + name);
|
if (!(semver.satisfies(peer.version, range) || (peer.version === "0.2.1-rc.5" && name.startsWith("@deepseek-ai/dsh-") && semver.satisfies(peer.version, range, { includePrerelease: true })))) throw new Error('incompatible free-search host dependency: ' + name);
|
||||||
}
|
}
|
||||||
const host = JSON.parse(readFileSync(hostManifest));
|
const host = JSON.parse(readFileSync(hostManifest));
|
||||||
host.dependencies = { ...host.dependencies, 'dsh-free-search': '0.9.15' };
|
host.dependencies = { ...host.dependencies, 'dsh-free-search': '0.9.21' };
|
||||||
writeFileSync(hostManifest, JSON.stringify(host, null, 2));
|
writeFileSync(hostManifest, JSON.stringify(host, null, 2));
|
||||||
console.log('Installed [email protected]5 and pinned offline dependency archives (SHA-512 verified; no lifecycle scripts)');
|
console.log('Installed [email protected].21 and pinned offline dependency archives (SHA-512 verified; no lifecycle scripts)');
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const replacement = 'const persistence = "host"; /* dsh-mgr: authenticated remot
|
|||||||
// Fail closed on upstream changes instead of silently shipping a broken UI.
|
// Fail closed on upstream changes instead of silently shipping a broken UI.
|
||||||
export function patchSettings(source, version) {
|
export function patchSettings(source, version) {
|
||||||
// Native host settings supersede the old persistence patch.
|
// Native host settings supersede the old persistence patch.
|
||||||
if (version === "0.2.1-rc.3") {
|
if (version === "0.2.1-rc.5") {
|
||||||
if (source.includes(target) || !source.includes("this.ctx.remote.settings.describe()") || !source.includes("this.ctx.remote.settings.mutate(")) throw new Error("expected native host settings API");
|
if (source.includes(target) || !source.includes("this.ctx.remote.settings.describe()") || !source.includes("this.ctx.remote.settings.mutate(")) throw new Error("expected native host settings API");
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import { patchSettings, target } from './install-host-settings.mjs';
|
|||||||
|
|
||||||
test("next host settings API remains unchanged", () => {
|
test("next host settings API remains unchanged", () => {
|
||||||
const source = "this.ctx.remote.settings.describe(); this.ctx.remote.settings.mutate(namespace, ops, revision);";
|
const source = "this.ctx.remote.settings.describe(); this.ctx.remote.settings.mutate(namespace, ops, revision);";
|
||||||
assert.equal(patchSettings(source, "0.2.1-rc.3"), source);
|
assert.equal(patchSettings(source, "0.2.1-rc.5"), source);
|
||||||
assert.throws(() => patchSettings(target, "0.2.1-rc.3"), /native host settings/);
|
assert.throws(() => patchSettings(target, "0.2.1-rc.5"), /native host settings/);
|
||||||
assert.throws(() => patchSettings("", "0.2.1-rc.3"), /native host settings/);
|
assert.throws(() => patchSettings("", "0.2.1-rc.5"), /native host settings/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('settings use host persistence on domains without changing loopback facts', () => {
|
test('settings use host persistence on domains without changing loopback facts', () => {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ for (const [name, range] of Object.entries(pkg.peerDependencies || {})) {
|
|||||||
// Limit that exception to the upstream-declared, tested RC hosts.
|
// Limit that exception to the upstream-declared, tested RC hosts.
|
||||||
if (name === 'react') {
|
if (name === 'react') {
|
||||||
const host = require('./package.json').version;
|
const host = require('./package.json').version;
|
||||||
if (host !== '0.2.1-rc.3') throw new Error('unverified browser React host: ' + host);
|
if (host !== '0.2.1-rc.5') throw new Error('unverified browser React host: ' + host);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let peer;
|
let peer;
|
||||||
@@ -33,7 +33,7 @@ for (const [name, range] of Object.entries(pkg.peerDependencies || {})) {
|
|||||||
if (pkg.peerDependenciesMeta?.[name]?.optional) continue;
|
if (pkg.peerDependenciesMeta?.[name]?.optional) continue;
|
||||||
throw new Error('missing required mobile peer: ' + name);
|
throw new Error('missing required mobile peer: ' + name);
|
||||||
}
|
}
|
||||||
if (!(semver.satisfies(peer.version, range) || (peer.version === "0.2.1-rc.3" && name.startsWith("@deepseek-ai/dsh-") && semver.satisfies(peer.version, range, { includePrerelease: true })))) throw new Error('incompatible mobile peer: ' + name + '@' + peer.version);
|
if (!(semver.satisfies(peer.version, range) || (peer.version === "0.2.1-rc.5" && name.startsWith("@deepseek-ai/dsh-") && semver.satisfies(peer.version, range, { includePrerelease: true })))) throw new Error('incompatible mobile peer: ' + name + '@' + peer.version);
|
||||||
}
|
}
|
||||||
// DSH runtime resolution traverses the installation manifest, not arbitrary
|
// DSH runtime resolution traverses the installation manifest, not arbitrary
|
||||||
// directories in node_modules. Declare the baked package in that graph.
|
// directories in node_modules. Declare the baked package in that graph.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { pathToFileURL } from 'node:url';
|
|||||||
|
|
||||||
export const target = 'import { createConverter } from "@deepseek-ai/libreoffice-kit";';
|
export const target = 'import { createConverter } from "@deepseek-ai/libreoffice-kit";';
|
||||||
export function patchOffice(source, hostVersion, packageVersion) {
|
export function patchOffice(source, hostVersion, packageVersion) {
|
||||||
if (hostVersion !== '0.2.1-rc.3' || packageVersion !== '0.2.1-rc.3') throw new Error('unsupported Office preview version');
|
if (hostVersion !== '0.2.1-rc.5' || packageVersion !== '0.2.1-rc.5') throw new Error('unsupported Office preview version');
|
||||||
if (source.split(target).length !== 2) throw new Error('expected exactly one original converter import');
|
if (source.split(target).length !== 2) throw new Error('expected exactly one original converter import');
|
||||||
return source.replace(target, 'import { createConverter } from "./dsh-native-office.mjs";');
|
return source.replace(target, 'import { createConverter } from "./dsh-native-office.mjs";');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { cpSync, mkdirSync, readFileSync } from 'node:fs';
|
|||||||
import { execFileSync } from 'node:child_process';
|
import { execFileSync } from 'node:child_process';
|
||||||
const root = '/usr/local/lib/dsh-mgr';
|
const root = '/usr/local/lib/dsh-mgr';
|
||||||
const host = JSON.parse(readFileSync('/usr/local/lib/node_modules/@deepseek-ai/dsh/package.json'));
|
const host = JSON.parse(readFileSync('/usr/local/lib/node_modules/@deepseek-ai/dsh/package.json'));
|
||||||
if (host.version !== '0.2.1-rc.3') throw new Error('Unverified preview download host');
|
if (host.version !== '0.2.1-rc.5') throw new Error('Unverified preview download host');
|
||||||
mkdirSync(root + '/preview-download-package', { recursive: true });
|
mkdirSync(root + '/preview-download-package', { recursive: true });
|
||||||
cpSync(new URL('./preview-download', import.meta.url), root + '/preview-download-package/package', { recursive: true });
|
cpSync(new URL('./preview-download', import.meta.url), root + '/preview-download-package/package', { recursive: true });
|
||||||
execFileSync('tar', ['-czf', root + '/dsh-preview-download-1.0.1.tgz', '-C', root + '/preview-download-package', 'package']);
|
execFileSync('tar', ['-czf', root + '/dsh-preview-download-1.0.1.tgz', '-C', root + '/preview-download-package', 'package']);
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import assert from 'node:assert/strict';
|
|||||||
import { execFileSync } from 'node:child_process';
|
import { execFileSync } from 'node:child_process';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import { randomUUID } from 'node:crypto';
|
import { randomUUID } from 'node:crypto';
|
||||||
const oldImage = process.env.DSH_OLD_IMAGE || 'dsh-web:runtime-7.9-amd64';
|
const oldImage = process.env.DSH_OLD_IMAGE || 'dsh-web:runtime-7.10-amd64';
|
||||||
const newImage = process.env.DSH_NEW_IMAGE || 'dsh-web:runtime-7.10-amd64';
|
const newImage = process.env.DSH_NEW_IMAGE || 'dsh-web:runtime-7.11-amd64';
|
||||||
const volume = `dsh-lockfile-smoke-${randomUUID()}`;
|
const volume = `dsh-lockfile-smoke-${randomUUID()}`;
|
||||||
const docker = args => execFileSync('docker', args, { encoding: 'utf8', timeout: 180000, maxBuffer: 8 * 1024 * 1024 });
|
const docker = args => execFileSync('docker', args, { encoding: 'utf8', timeout: 180000, maxBuffer: 8 * 1024 * 1024 });
|
||||||
const run = (image, args, mounts = []) => docker(['run', '--rm', '--network', 'none', '-v', `${volume}:/workspace`, ...mounts, '--entrypoint', 'bash', image, '-ec', args]);
|
const run = (image, args, mounts = []) => docker(['run', '--rm', '--network', 'none', '-v', `${volume}:/workspace`, ...mounts, '--entrypoint', 'bash', image, '-ec', args]);
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import { createConverter, runProcess } from './native-office.mjs';
|
|||||||
import { patchOffice, target } from './install-office-preview.mjs';
|
import { patchOffice, target } from './install-office-preview.mjs';
|
||||||
|
|
||||||
test('patch is exact, version gated and refuses repeat application', () => {
|
test('patch is exact, version gated and refuses repeat application', () => {
|
||||||
const patched = patchOffice(target, '0.2.1-rc.3', '0.2.1-rc.3');
|
const patched = patchOffice(target, '0.2.1-rc.5', '0.2.1-rc.5');
|
||||||
assert.match(patched, /dsh-native-office/);
|
assert.match(patched, /dsh-native-office/);
|
||||||
for (const source of ['', target + target, patched]) assert.throws(() => patchOffice(source, '0.2.1-rc.3', '0.2.1-rc.3'));
|
for (const source of ['', target + target, patched]) assert.throws(() => patchOffice(source, '0.2.1-rc.5', '0.2.1-rc.5'));
|
||||||
assert.throws(() => patchOffice(target, 'next', '0.2.1-rc.3'));
|
assert.throws(() => patchOffice(target, 'next', '0.2.1-rc.5'));
|
||||||
assert.throws(() => patchOffice(target, '0.2.1-rc.3', 'next'));
|
assert.throws(() => patchOffice(target, '0.2.1-rc.5', 'next'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('process cancellation, missing binary and failure are classified', async () => {
|
test('process cancellation, missing binary and failure are classified', async () => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ async function dshChatJson(response) {
|
|||||||
export const clientHelpers = dshChatFetch.toString() + String.fromCharCode(10) + dshChatJson.toString() + String.fromCharCode(10);
|
export const clientHelpers = dshChatFetch.toString() + String.fromCharCode(10) + dshChatJson.toString() + String.fromCharCode(10);
|
||||||
|
|
||||||
export function patchClient(source, version) {
|
export function patchClient(source, version) {
|
||||||
if (version !== '1.5.18') throw new Error('unsupported chat-manager version');
|
if (version !== '1.5.20') throw new Error('unsupported chat-manager version');
|
||||||
if (source.includes('dshChatFetch') || source.split('await fetch(').length !== 4
|
if (source.includes('dshChatFetch') || source.split('await fetch(').length !== 4
|
||||||
|| source.split('await response.json()').length !== 4
|
|| source.split('await response.json()').length !== 4
|
||||||
|| source.split('/plugins/dsh-session-delete/').length !== 4) {
|
|| source.split('/plugins/dsh-session-delete/').length !== 4) {
|
||||||
|
|||||||
@@ -30,15 +30,15 @@ test('patch rejects unsupported or changed clients and double patching', () => {
|
|||||||
'await fetch(`/plugins/dsh-session-delete/${action}`, options); await response.json()',
|
'await fetch(`/plugins/dsh-session-delete/${action}`, options); await response.json()',
|
||||||
"await fetch('/plugins/dsh-session-delete/archive-search', options); await response.json()",
|
"await fetch('/plugins/dsh-session-delete/archive-search', options); await response.json()",
|
||||||
].join(';');
|
].join(';');
|
||||||
const patched = patchClient(source, '1.5.18');
|
const patched = patchClient(source, '1.5.20');
|
||||||
assert.equal(patched.split('await dshChatFetch(').length, 4);
|
assert.equal(patched.split('await dshChatFetch(').length, 4);
|
||||||
assert.equal(patched.slice(clientHelpers.length).replaceAll('await dshChatFetch(', 'await fetch(')
|
assert.equal(patched.slice(clientHelpers.length).replaceAll('await dshChatFetch(', 'await fetch(')
|
||||||
.replaceAll('await dshChatJson(response)', 'await response.json()'), source);
|
.replaceAll('await dshChatJson(response)', 'await response.json()'), source);
|
||||||
assert.throws(() => patchClient(source, '1.5.16'), /unsupported/);
|
assert.throws(() => patchClient(source, '1.5.16'), /unsupported/);
|
||||||
assert.throws(() => patchClient(source, '1.5.13'), /unsupported/);
|
assert.throws(() => patchClient(source, '1.5.13'), /unsupported/);
|
||||||
assert.throws(() => patchClient('', '1.5.18'), /unexpected/);
|
assert.throws(() => patchClient('', '1.5.20'), /unexpected/);
|
||||||
assert.throws(() => patchClient(source.replace('await fetch(', 'fetch('), '1.5.18'), /unexpected/);
|
assert.throws(() => patchClient(source.replace('await fetch(', 'fetch('), '1.5.20'), /unexpected/);
|
||||||
assert.throws(() => patchClient(source.replace('await response.json()', 'response.json()'), '1.5.18'), /unexpected/);
|
assert.throws(() => patchClient(source.replace('await response.json()', 'response.json()'), '1.5.20'), /unexpected/);
|
||||||
assert.throws(() => patchClient(source.replace('/plugins/dsh-session-delete/', '/plugins/changed/'), '1.5.18'), /unexpected/);
|
assert.throws(() => patchClient(source.replace('/plugins/dsh-session-delete/', '/plugins/changed/'), '1.5.20'), /unexpected/);
|
||||||
assert.throws(() => patchClient(patched, '1.5.18'), /unexpected/);
|
assert.throws(() => patchClient(patched, '1.5.20'), /unexpected/);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { randomUUID } from 'node:crypto';
|
|||||||
|
|
||||||
export const BUILTIN_DEPENDENCIES = Object.freeze({
|
export const BUILTIN_DEPENDENCIES = Object.freeze({
|
||||||
'dsh-preview-download': 'file:/usr/local/lib/dsh-mgr/dsh-preview-download-1.0.1.tgz',
|
'dsh-preview-download': 'file:/usr/local/lib/dsh-mgr/dsh-preview-download-1.0.1.tgz',
|
||||||
'dsh-chat-manager': 'file:/usr/local/lib/dsh-mgr/dsh-chat-manager-1.5.18-dsh-mgr.1.tgz',
|
'dsh-chat-manager': 'file:/usr/local/lib/dsh-mgr/dsh-chat-manager-1.5.20-dsh-mgr.1.tgz',
|
||||||
'dsh-mgr-workspace': 'file:/usr/local/lib/dsh-mgr/dsh-mgr-workspace-1.0.0.tgz',
|
'dsh-mgr-workspace': 'file:/usr/local/lib/dsh-mgr/dsh-mgr-workspace-1.0.0.tgz',
|
||||||
'dsh-web-mobile': 'file:/usr/local/lib/dsh-mgr/dsh-web-mobile-3.2.1.tgz',
|
'dsh-web-mobile': 'file:/usr/local/lib/dsh-mgr/dsh-web-mobile-3.2.1.tgz',
|
||||||
'dsh-free-search': 'file:/usr/local/lib/dsh-mgr/dsh-free-search-0.9.15.tgz',
|
'dsh-free-search': 'file:/usr/local/lib/dsh-mgr/dsh-free-search-0.9.21.tgz',
|
||||||
});
|
});
|
||||||
export const BUILTIN_OVERRIDES = Object.freeze({
|
export const BUILTIN_OVERRIDES = Object.freeze({
|
||||||
'dsh-chat-manager>clsx': 'file:/usr/local/lib/dsh-mgr/clsx-2.1.1.tgz',
|
'dsh-chat-manager>clsx': 'file:/usr/local/lib/dsh-mgr/clsx-2.1.1.tgz',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { BUILTIN_DEPENDENCIES, BUILTIN_OVERRIDES, reconcileManifest, reconcilePr
|
|||||||
import { initProfile } from './init-profile.mjs';
|
import { initProfile } from './init-profile.mjs';
|
||||||
|
|
||||||
const old = name => 'file:/usr/local/lib/dsh-mgr/' + name + '-0.0.1-rc.1+build.2.tgz';
|
const old = name => 'file:/usr/local/lib/dsh-mgr/' + name + '-0.0.1-rc.1+build.2.tgz';
|
||||||
test('runtime-7.9 plugin references migrate to runtime-7.10 without changing bundle choices', t => {
|
test('runtime-7.9 plugin references migrate to runtime-7.11 without changing bundle choices', t => {
|
||||||
const bundles = ['dsh-web-mobile', 'dsh-chat-manager'];
|
const bundles = ['dsh-web-mobile', 'dsh-chat-manager'];
|
||||||
const f = fixture(t, {
|
const f = fixture(t, {
|
||||||
dependencies: {
|
dependencies: {
|
||||||
@@ -26,6 +26,24 @@ test('runtime-7.9 plugin references migrate to runtime-7.10 without changing bun
|
|||||||
assert.deepEqual(current.dsh.profile.bundles, bundles);
|
assert.deepEqual(current.dsh.profile.bundles, bundles);
|
||||||
assert.deepEqual(f.run(), { changed: false });
|
assert.deepEqual(f.run(), { changed: false });
|
||||||
});
|
});
|
||||||
|
test('runtime-7.10 plugin references migrate to runtime-7.11 without changing bundle choices', t => {
|
||||||
|
const bundles = ['dsh-web-mobile', 'dsh-chat-manager'];
|
||||||
|
const f = fixture(t, {
|
||||||
|
dependencies: {
|
||||||
|
'dsh-web-mobile': 'file:/usr/local/lib/dsh-mgr/dsh-web-mobile-3.2.1.tgz',
|
||||||
|
'dsh-free-search': 'file:/usr/local/lib/dsh-mgr/dsh-free-search-0.9.15.tgz',
|
||||||
|
'dsh-chat-manager': 'file:/usr/local/lib/dsh-mgr/dsh-chat-manager-1.5.18-dsh-mgr.1.tgz',
|
||||||
|
},
|
||||||
|
dsh: { profile: { bundles } },
|
||||||
|
});
|
||||||
|
const result = f.run();
|
||||||
|
assert.equal(result.changed, true);
|
||||||
|
assert.equal(readFileSync(result.backupPath, 'utf8'), f.original);
|
||||||
|
const current = JSON.parse(readFileSync(f.path));
|
||||||
|
for (const name of Object.keys(current.dependencies)) assert.equal(current.dependencies[name], BUILTIN_DEPENDENCIES[name]);
|
||||||
|
assert.deepEqual(current.dsh.profile.bundles, bundles);
|
||||||
|
assert.deepEqual(f.run(), { changed: false });
|
||||||
|
});
|
||||||
function fixture(t, manifest) {
|
function fixture(t, manifest) {
|
||||||
const root = mkdtempSync(join(tmpdir(), 'dsh-reconcile-'));
|
const root = mkdtempSync(join(tmpdir(), 'dsh-reconcile-'));
|
||||||
t.after(() => rmSync(root, { recursive: true, force: true }));
|
t.after(() => rmSync(root, { recursive: true, force: true }));
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schema_version": 1,
|
"schema_version": 1,
|
||||||
"release_id": "runtime-7.10",
|
"release_id": "runtime-7.11",
|
||||||
"version": "0.2.1-rc.3",
|
"version": "0.2.1-rc.5",
|
||||||
"deployment_schema": 7,
|
"deployment_schema": 7,
|
||||||
"platforms": ["linux/amd64", "linux/arm64"]
|
"platforms": ["linux/amd64", "linux/arm64"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user