mirror of
https://gh-proxy.org/https://github.com/klinsmaya/workdsh.git
synced 2026-11-09 01:47:06 +08:00
81 lines
6.0 KiB
JavaScript
81 lines
6.0 KiB
JavaScript
import { execFile } from 'node:child_process';
|
|
import { access, copyFile, mkdir, readFile, realpath } from 'node:fs/promises';
|
|
import { createHash } from 'node:crypto';
|
|
import { createRequire } from 'node:module';
|
|
import { dirname, join, resolve } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { promisify } from 'node:util';
|
|
|
|
const root = fileURLToPath(new URL('..', import.meta.url));
|
|
const rootManifest = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
|
|
const baseVersion = rootManifest.pnpm?.overrides?.['@deepseek-ai/dsh-base'];
|
|
const webAppVersion = rootManifest.pnpm?.overrides?.['@deepseek-ai/dsh-web-app'];
|
|
if (typeof baseVersion !== 'string') throw new Error('Missing pinned @deepseek-ai/dsh-base version in package.json pnpm.overrides.');
|
|
if (typeof webAppVersion !== 'string') throw new Error('Missing pinned @deepseek-ai/dsh-web-app version in package.json pnpm.overrides.');
|
|
const baseSpec = `@deepseek-ai/dsh-base@${baseVersion}`;
|
|
const webAppSpec = `@deepseek-ai/dsh-web-app@${webAppVersion}`;
|
|
const home = resolve(process.env.WORKDSH_PREVIEW_HOME ?? join(root, '.test-runtime/preview'));
|
|
const artifacts = join(root, '.artifacts');
|
|
const env = { ...process.env, DSH_HOME: home, PATH: `${join(root, 'node_modules/.bin')}:${dirname(process.execPath)}:${process.env.PATH}` };
|
|
const exec = promisify(execFile);
|
|
const run = async (tool, args) => {
|
|
await exec(process.execPath, [join(root, 'node_modules', tool), ...args], { cwd: root, env, timeout: 60_000, maxBuffer: 8 * 1024 * 1024 });
|
|
};
|
|
await mkdir(home, { recursive: true }); await mkdir(artifacts, { recursive: true });
|
|
const tarballs = [];
|
|
const packages = [];
|
|
for (const directory of ['packages/providers/identity-local', 'packages/plugins/audit', 'packages/plugins/access', 'packages/plugins/skills', 'packages/plugins/experts', 'packages/plugins/connectors', 'packages/plugins/office', 'packages/plugins/library', 'packages/plugins/projects', 'packages/plugins/activity', 'packages/bundle']) {
|
|
const manifest = JSON.parse(await readFile(join(root, directory, 'package.json'), 'utf8'));
|
|
await access(join(root, directory, manifest.exports['.'].default));
|
|
await run('pnpm/bin/pnpm.cjs', ['--filter', manifest.name, 'pack', '--pack-destination', artifacts]);
|
|
const packed = join(artifacts, `${manifest.name}-${manifest.version}.tgz`);
|
|
// Preview candidates can change before their next release. A stable file:
|
|
// address lets the package manager reuse an older archive, even after pack.
|
|
// Keep official CLI installation, but address each archive by its content.
|
|
const digest = createHash('sha256').update(await readFile(packed)).digest('hex');
|
|
const destination = join(artifacts, 'preview', digest);
|
|
await mkdir(destination, { recursive: true });
|
|
const immutableArchive = join(destination, `${manifest.name}-${manifest.version}.tgz`);
|
|
await copyFile(packed, immutableArchive);
|
|
tarballs.push(immutableArchive);
|
|
packages.push({ directory, manifest });
|
|
}
|
|
let initialized = false;
|
|
try { await access(join(home, 'profiles/preview/package.json')); initialized = true; }
|
|
catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
if (!initialized) await run('@deepseek-ai/dsh/lib/bin.js', ['--profile', 'preview', '--from-default-profile', 'web', '--dump-config']);
|
|
// Reinstall the pinned official Web bundle as well as the WorkDSH layers. An
|
|
// existing preview Profile may have been created by an older DSH release; its
|
|
// bundle list alone does not upgrade the packages that provide newly added Web
|
|
// surfaces such as Terminal and archived-session recovery.
|
|
await run('@deepseek-ai/dsh/lib/bin.js', ['plugin', '--profile', 'preview', 'add', baseSpec, webAppSpec, ...tarballs]);
|
|
const installedBase = JSON.parse(await readFile(join(home, 'profiles/preview/node_modules/@deepseek-ai/dsh-base/package.json'), 'utf8'));
|
|
if (installedBase.version !== baseVersion) throw new Error(`Installed @deepseek-ai/dsh-base ${installedBase.version} does not match pinned ${baseVersion}.`);
|
|
const installedWebApp = JSON.parse(await readFile(join(home, 'profiles/preview/node_modules/@deepseek-ai/dsh-web-app/package.json'), 'utf8'));
|
|
if (installedWebApp.version !== webAppVersion) throw new Error(`Installed @deepseek-ai/dsh-web-app ${installedWebApp.version} does not match pinned ${webAppVersion}.`);
|
|
// DSH 0.1.6 scopes are module-instance local. Installing only the Web bundle
|
|
// beside a CLI-provided Base bundle can load two physical dsh-scope copies: the
|
|
// Agent Loop tags one copy while Agent Presets reads the other, so every new
|
|
// session fails as an "unscoped context". Resolve both consumers from the
|
|
// Profile and fail installation unless they share the exact same module file.
|
|
const profileRequire = createRequire(join(home, 'profiles/preview/package.json'));
|
|
const resolveProfileDependency = async (consumer, dependency) => {
|
|
const consumerManifest = profileRequire.resolve(`${consumer}/package.json`);
|
|
const consumerRequire = createRequire(consumerManifest);
|
|
return realpath(consumerRequire.resolve(`${dependency}/package.json`));
|
|
};
|
|
const loopScope = await resolveProfileDependency('@deepseek-ai/dsh-agent-loop', '@deepseek-ai/dsh-scope');
|
|
const presetScope = await resolveProfileDependency('@deepseek-ai/dsh-agent-presets', '@deepseek-ai/dsh-scope');
|
|
if (loopScope !== presetScope) throw new Error(`Preview loaded split @deepseek-ai/dsh-scope instances: agent-loop=${loopScope}; agent-presets=${presetScope}.`);
|
|
for (const { directory, manifest } of packages) {
|
|
for (const face of ['.', './client']) {
|
|
const entry = manifest.exports[face]?.default;
|
|
if (!entry) continue;
|
|
const expected = await readFile(join(root, directory, entry));
|
|
const installed = await readFile(join(home, 'profiles/preview/node_modules', manifest.name, entry));
|
|
if (!expected.equals(installed)) throw new Error(`Installed ${manifest.name} ${face} differs from the current build; refusing to report a successful preview update.`);
|
|
}
|
|
}
|
|
console.log('Installed Skill, Expert, Connector, Office, Library, Projects and WorkDSH presentation as separate official Profile layers.');
|
|
console.log('Start the stopped preview with: corepack pnpm preview');
|