Initial commit: DSH Web Manager

This commit is contained in:
2026-10-13 09:34:47 +08:00
commit 85332bbc56
135 changed files with 19712 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
import {execFileSync, spawnSync} from 'node:child_process';
import assert from 'node:assert/strict';
const image=process.argv[2]||'dsh-web:0.2.0-rc.2-6';
const docker=(args)=>execFileSync('docker',args,{encoding:'utf8',stdio:['ignore','pipe','pipe']}).trim();
const id=docker(['run','-d','--network','none','--read-only','--cap-drop','ALL','--security-opt','no-new-privileges','--tmpfs','/tmp:rw,exec,nosuid,nodev,size=256m','--tmpfs','/data/dsh-home:rw,uid=1000,gid=1000,size=256m','--tmpfs','/workspace:rw,uid=1000,gid=1000,size=64m',image]);
try {
let ready=false;
for(let n=0;n<60;n++){
assert.equal(docker(['inspect','--format','{{.State.Running}}',id]),'true','runtime exited');
try {docker(['exec',id,'node','-e',"fetch('http://127.0.0.1:8080/').then(r=>process.exit(r.status<500?0:1)).catch(()=>process.exit(1))"]);ready=true;break;}catch{}
await new Promise(r=>setTimeout(r,1000));
}
assert.ok(ready,'offline startup readiness');
const startup = spawnSync('docker', ['logs', id], {encoding:'utf8'});
const token = (startup.stdout + startup.stderr).match(/[?&]token=([^\s\x1b]+)/)?.[1];
assert.ok(token, 'startup token available');
const rpc = (method, args = {}) => {
const source = "const {token,method,args}=JSON.parse(require('node:fs').readFileSync(0,'utf8')); (async()=>{const auth=await fetch('http://127.0.0.1:3080/?token='+encodeURIComponent(token),{redirect:'manual'});const cookie=auth.headers.getSetCookie().map(v=>v.split(';')[0]).join('; ');const r=await fetch('http://127.0.0.1:3080/api/'+method,{method:'POST',headers:{'content-type':'application/json',cookie},body:JSON.stringify({type:'client-request',rpcId:'workspace-test',method,payload:{args}})});console.log(JSON.stringify((await r.json()).result));})().catch(()=>process.exit(1));";
const result = spawnSync('docker',['exec','-i',id,'node','-e',source],{encoding:'utf8',input:JSON.stringify({token,method,args})});
assert.equal(result.status,0,'authenticated RPC failed');
return JSON.parse(result.stdout);
};
const initial = rpc('workspace/initializeDefault');
assert.equal(initial.ok, true, JSON.stringify(initial));
assert.equal(initial.value.workspace.path, '/workspace');
assert.deepEqual(initial.value.workspace.sessionIds, []);
const again = rpc('workspace/initializeDefault');
assert.deepEqual(again, initial);
const registered = rpc('workspace/create', {request:{path:'/workspace'}});
assert.equal(registered.ok,true);
assert.equal(registered.value.created,false);
assert.equal(registered.value.workspace.workspaceId, initial.value.workspace.workspaceId);
console.log('PASS real offline fresh registry: canonical /workspace, no sessions, durable default reused by controller and create');
const manifest=JSON.parse(docker(['exec',id,'cat','/data/dsh-home/profiles/web/package.json']));
assert.ok(manifest.dsh.profile.bundles.includes('dsh-web-mobile'));
assert.equal(manifest.dependencies['dsh-web-mobile'], 'file:/usr/local/lib/dsh-mgr/dsh-web-mobile-3.0.5.tgz');
const inventory = (home = '/data/dsh-home') => JSON.parse(docker(['exec', id, 'node', '--input-type=module', '-e', "import {readProfilePlugins} from '/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-app-boot/lib/index.js'; console.log(JSON.stringify(readProfilePlugins({binName:'dsh',profileDir:" + JSON.stringify(home + '/profiles/web') + ",installAnchor:'/usr/local/lib/node_modules/@deepseek-ai/dsh/package.json'}).dependencies))"]));
assert.deepEqual(inventory().sort((a,b)=>a.name.localeCompare(b.name)), [{name:'dsh-free-search',version:'0.8.5',bundle:true,enabled:true},{name:'dsh-mgr-workspace',version:'1.0.0',bundle:true,enabled:true},{name:'dsh-web-mobile',version:'3.0.5',bundle:true,enabled:true}]);
const bundles = JSON.parse(docker(['exec',id,'node','--input-type=module','-e', "import {PluginManager} from '/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-plugin-manager/lib/index.js'; const manager=Object.create(PluginManager.prototype); Object.defineProperties(manager,{profile:{value:{dir:'/data/dsh-home/profiles/web',installAnchor:'/usr/local/lib/node_modules/@deepseek-ai/dsh/package.json'}},ctx:{value:{loader:{entries:()=>[]},get:()=>undefined}},managementBundles:{value:new Set()},ownerEntryId:{value:'include:plugin-manager'}}); console.log(JSON.stringify((await manager.listBundles()).filter(b=>['dsh-web-mobile','dsh-free-search'].includes(b.name))));"]));
assert.equal(bundles.length,2);
for (const bundle of bundles) {
assert.equal(bundle.installed,true);
assert.equal(bundle.enabled,true);
assert.equal(bundle.removable,false);
assert.equal(bundle.error,undefined);
assert.equal(bundle.readOnlyReason,undefined);
}
console.log('PASS upstream listBundles: mobile and free-search installed/enabled, no error/readOnlyReason; baked host bundle not removable');
docker(['exec',id,'node','--input-type=module','-e', "import {readdirSync,lstatSync,readlinkSync} from 'node:fs'; import {join,isAbsolute} from 'node:path'; import assert from 'node:assert/strict'; const root='/data/dsh-home/profiles/web/node_modules'; assert.deepEqual(readdirSync(root).filter(n=>!n.startsWith('.')),['@deepseek-ai','@standard-schema','dsh-free-search','dsh-mgr-workspace','dsh-web-mobile']); assert.deepEqual(readdirSync(join(root,'@deepseek-ai')).sort(),['cosmokit','schemastery']); assert.deepEqual(readdirSync(join(root,'@standard-schema')),['spec']); function scan(dir){for(const n of readdirSync(dir)){const p=join(dir,n);const s=lstatSync(p);if(s.isSymbolicLink())assert.equal(isAbsolute(readlinkSync(p)),false,p);else if(s.isDirectory())scan(p);}}scan(root);"]);
const dump=docker(['exec',id,'dsh','--profile','web','--dump-config']);
assert.match(dump,/name: ['"]?dsh-web-mobile/);
const logResult=spawnSync('docker',['logs',id],{encoding:'utf8'});
assert.equal(logResult.status,0);
assert.ok(!/failed to import|entry did not activate|entries did not activate/.test(logResult.stdout+logResult.stderr),'runtime activation failure (logs withheld to protect startup token)');
docker(['exec',id,'node','--input-type=module','-e', "const {apply}=await import('/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/dsh-free-search/lib/index.js'); const {default:assert}=await import('node:assert/strict'); for(const selected of [undefined,'deepseek-official','custom']){const web={searchProviderId:selected,fetchProviderId:'custom-fetch',registerSearchProvider(){},registerFetchProvider(){}}; apply({web,logger:{info(){},warn(){}},inject(){},get(){}},{}); assert.equal(web.searchProviderId,selected==='custom'?'custom':'ddg'); assert.equal(web.fetchProviderId,'custom-fetch');}"]);
const settings = JSON.parse(docker(['exec',id,'node','-e', "fetch('http://127.0.0.1:3080/api/dsh-free-search-settings/describe',{method:'POST'}).then(async r=>{if(r.status!==200)throw new Error('status '+r.status);console.log(JSON.stringify(await r.json()))})"]));
assert.equal(settings.ok,true);
assert.equal(settings.value.namespaces.find(n=>n.ns==='web-search-free').value.provider,'bing');
console.log('PASS live free-search activation, official provider takeover and settings describe route');
console.log('PASS offline nonroot startup, readProfilePlugins inventory, no duplicate peers or absolute symlinks');
// Restore only the portable profile manifest/patch/lockfile, without workspace or node_modules.
docker(['exec',id,'bash','-ec', 'mkdir -p /tmp/mobile-restore/profiles/web; cp /data/dsh-home/profiles/web/package.json /data/dsh-home/profiles/web/pnpm-lock.yaml /tmp/mobile-restore/profiles/web/; if test -f /data/dsh-home/profiles/web/cordis.patch.yml; then cp /data/dsh-home/profiles/web/cordis.patch.yml /tmp/mobile-restore/profiles/web/; fi']);
docker(['exec',id,'node','-e', "const fs=require('node:fs'); const p='/tmp/mobile-restore/profiles/web/package.json'; const m=JSON.parse(fs.readFileSync(p)); m.dsh.profile.bundles=m.dsh.profile.bundles.filter(n=>n!=='dsh-web-mobile');fs.writeFileSync(p,JSON.stringify(m));"]);
docker(['exec', '-e', 'DSH_HOME=/tmp/mobile-restore', '-e', 'HOME=/tmp/mobile-restore', '-e', 'XDG_DATA_HOME=/tmp/mobile-restore/.local/share', '-e', 'npm_config_ignore_scripts=true', id, 'bash', '-ec', 'node /usr/local/lib/dsh-mgr/init-profile.mjs; dsh plugin --profile web install --ignore-scripts']);
assert.deepEqual(inventory('/tmp/mobile-restore').sort((a,b)=>a.name.localeCompare(b.name)), [{name:'dsh-free-search',version:'0.8.5',bundle:true,enabled:true},{name:'dsh-mgr-workspace',version:'1.0.0',bundle:true,enabled:true},{name:'dsh-web-mobile',version:'3.0.5',bundle:true,enabled:false}]);
const workspace = docker(['exec',id,'cat','/tmp/mobile-restore/profiles/web/pnpm-workspace.yaml']);
assert.match(workspace,/autoInstallPeers: false/);
assert.match(workspace,/nodeLinker: hoisted/);
console.log('PASS offline backup restore without workspace/store/node_modules; disabled bundle preserved');
docker(['exec',id,'node','-e', "const fs=require('node:fs'); const dir='/tmp/mobile-legacy/profiles/web'; fs.mkdirSync(dir,{recursive:true}); fs.writeFileSync(dir+'/package.json',JSON.stringify({name:'dsh-profile-web',private:true,dependencies:{'dsh-web-mobile':'file:/usr/local/lib/dsh-mgr/dsh-web-mobile-3.0.5.tgz'},dsh:{profile:{bundles:['@deepseek-ai/dsh-base','@deepseek-ai/dsh-web-app','dsh-web-mobile']}}}));"]);
docker(['exec','-e','DSH_HOME=/tmp/mobile-legacy','-e','HOME=/tmp/mobile-legacy','-e','XDG_DATA_HOME=/tmp/mobile-legacy/.local/share','-e','npm_config_ignore_scripts=true',id,'bash','-ec','node /usr/local/lib/dsh-mgr/init-profile.mjs; dsh plugin --profile web install --ignore-scripts']);
assert.deepEqual(inventory('/tmp/mobile-legacy'),[{name:'dsh-web-mobile',version:'3.0.5',bundle:true,enabled:true}]);
console.log('PASS recipe4 mobile-only manifest restore; no free-search injection');
docker(['exec', id, 'node', '-e', "require('node:fs').writeFileSync('/workspace/normal','preserved')"]);
assert.equal(rpc('workspace/delete', {request:{workspaceId:initial.value.workspace.workspaceId}}).ok, true);
assert.equal(rpc('workspace/initializeDefault').value, undefined);
assert.equal(docker(['exec', id, 'cat', '/workspace/normal']), 'preserved');
assert.equal(rpc('workspace/create', {request:{path:'/workspace'}}).value.created, true);
assert.equal(rpc('workspace/initializeDefault').value, undefined);
console.log('PASS deleted default stays deleted; files preserved; explicit registration remains available');
} finally {docker(['rm','-f',id]);console.log('Removed dedicated smoke container (tmpfs data only)');}