| 1 | // Source-focused Node host/fake Core acceptance. Rust admission/selection is separate. |
| 2 | import {test} from 'node:test' |
| 3 | import assert from 'node:assert/strict' |
| 4 | import {createHash} from 'node:crypto' |
| 5 | import {mkdtempSync,mkdirSync,writeFileSync,readFileSync,rmSync} from 'node:fs' |
| 6 | import {join,dirname} from 'node:path' |
| 7 | import {tmpdir} from 'node:os' |
| 8 | import {fileURLToPath} from 'node:url' |
| 9 | import {reviewAgentPresets,containedPackageModule} from '../dist/agent-presets.mjs' |
| 10 | import {spawnSync} from 'node:child_process' |
| 11 | import {activate,startHost} from './harness.mjs' |
| 12 | const hash=s=>createHash('sha256').update(s).digest('hex') |
| 13 | function request(config,contents,extraDirs=[]) { |
| 14 | const layer=JSON.stringify([{insert:[{id:'raw-roster',name:'@deepseek-ai/dsh-agent-presets',config}]}]) |
| 15 | const directories=new Set(extraDirs) |
| 16 | for(const path of Object.keys(contents)) { let dir=dirname(path);while(dir!=='.'){directories.add(dir);dir=dirname(dir)} } |
| 17 | const files=Object.fromEntries(Object.entries(contents).map(([path,text])=>[path,hash(text)])) |
| 18 | return {kind:'agent-presets',composition:{version:1,layers:[{path:'bundle.json',sha256:hash(layer),source:layer}],modules:[],files},directories:[...directories],documents:Object.entries(contents).filter(([path])=>/\/(?:package\.json|preset\.yml|agent\.cordis\.yml)$/.test(path)).map(([path,source])=>({path,source,sha256:hash(source)}))} |
| 19 | } |
| 20 | const cfg={includeShippedRoot:false,includeUserRoot:false,roots:[{path:'presets',trust:'user'}],default:'a'} |
| 21 | const empty='[]\n' |
| 22 | |
| 23 | test('raw discovery preserves first-root-wins, metadata order, broken rows and ignored metadata trust',async()=>{ |
| 24 | const input=request({...cfg,roots:[{path:'system',trust:'system'},{path:'user',trust:'user'}],default:'a'},{ |
| 25 | 'system/a/agent.cordis.yml':empty,'system/a/preset.yml':'name: Alpha\norder: 2\nid: spoof\ntrust: admin\n', |
| 26 | 'system/b/agent.cordis.yml':empty,'system/b/preset.yml':'name: Beta\norder: 1\n', |
| 27 | 'user/a/agent.cordis.yml':empty,'user/a/preset.yml':'name: Shadowed\n', |
| 28 | 'user/c/agent.cordis.yml':empty,'user/c/preset.yml':'[malformed\n', |
| 29 | },['user/missing','user/INVALID']) |
| 30 | const review=await reviewAgentPresets(input) |
| 31 | assert.deepEqual(review.catalog.presets.map(p=>p.id),['b','a','c','missing']) |
| 32 | assert.equal(review.catalog.presets[1].name,'Alpha');assert.equal(review.catalog.presets[1].trust,'system') |
| 33 | assert.equal(review.catalog.presets[2].name,undefined);assert.match(review.catalog.presets[3].broken,/missing/) |
| 34 | assert.deepEqual(review.presets.map(p=>p.metadata.id),['b','a','c']) |
| 35 | }) |
| 36 | |
| 37 | test('confined bare lookup honors exact ESM export and refuses ambient/escape/require-only exports',async()=>{ |
| 38 | const manifests=new Map([['node_modules/@test/profile/package.json',JSON.stringify({name:'@test/profile',type:'module',exports:{'.':{require:'./bad.cjs',import:'./main.mjs'},'./review':'./review.mjs'}})]]) |
| 39 | const files={'node_modules/@test/profile/main.mjs':hash('main'),'node_modules/@test/profile/review.mjs':hash('review')} |
| 40 | assert.equal(containedPackageModule('@test/profile',manifests,files).path,'node_modules/@test/profile/main.mjs') |
| 41 | assert.equal(containedPackageModule('@test/profile/review',manifests,files).path,'node_modules/@test/profile/review.mjs') |
| 42 | for(const name of ['js-yaml','@test/profile/../../outside','file:///outside']) assert.equal(containedPackageModule(name,manifests,files),undefined) |
| 43 | const blocked=new Map([['node_modules/@test/profile/package.json',JSON.stringify({name:'@test/profile',type:'module',exports:{node:null,import:'./main.mjs'}})]]) |
| 44 | assert.equal(containedPackageModule('@test/profile',blocked,files),undefined,'a blocked matched condition never falls through') |
| 45 | const input=request(cfg,{'presets/a/agent.cordis.yml':'- name: "@test/profile"\n','node_modules/@test/profile/package.json':manifests.get('node_modules/@test/profile/package.json'),'node_modules/@test/profile/main.mjs':'export function apply(){}'}) |
| 46 | const review=await reviewAgentPresets(input) |
| 47 | assert.equal(review.presets[0].composition.modules[0].path,'node_modules/@test/profile/main.mjs') |
| 48 | }) |
| 49 | |
| 50 | test('raw roots and bytes stay admitted; disabled groups and conditional missing rows are not guessed',async()=>{ |
| 51 | const input=request(cfg,{'presets/a/agent.cordis.yml':"- name: cordis:group\n group: true\n disabled: true\n config:\n - name: absent\n- name: absent-conditional\n disabled: !!js 'true'\n"}) |
| 52 | const review=await reviewAgentPresets(input) |
| 53 | assert.equal(review.presets.length,1);assert.equal(review.presets[0].composition.modules.length,0) |
| 54 | const changed=structuredClone(input);changed.documents[0].source+=' # tampered' |
| 55 | await assert.rejects(reviewAgentPresets(changed),/document changed/) |
| 56 | for(const config of [{...cfg,roots:[{path:'../outside',trust:'user'}]},{...cfg,includeUserRoot:true},{...cfg,includeShippedRoot:true}]) { |
| 57 | await assert.rejects(reviewAgentPresets(request(config,{'presets/a/agent.cordis.yml':empty})),/admitted|inside/) |
| 58 | } |
| 59 | }) |
| 60 | |
| 61 | test('cyclic/oversized preset rows remain broken and cannot recurse discovery or replace Core prompt',async()=>{ |
| 62 | const input=request(cfg,{'presets/a/agent.cordis.yml':empty, |
| 63 | 'presets/cycle/agent.cordis.yml':'&rows\n- name: cordis:group\n group: true\n config: *rows\n', |
| 64 | 'presets/minimal/agent.cordis.yml':'- name: "@deepseek-ai/dsh-persona"\n config: {complete: true}\n', |
| 65 | 'node_modules/@deepseek-ai/dsh-persona/package.json':JSON.stringify({name:'@deepseek-ai/dsh-persona',type:'module',exports:'./index.mjs'}), |
| 66 | 'node_modules/@deepseek-ai/dsh-persona/index.mjs':'export function apply(){}', |
| 67 | }) |
| 68 | const review=await reviewAgentPresets(input) |
| 69 | assert.deepEqual(review.presets.map(p=>p.metadata.id),['a']) |
| 70 | assert.match(review.catalog.presets.find(p=>p.id==='cycle').broken,/cannot be read/) |
| 71 | assert.match(review.catalog.presets.find(p=>p.id==='minimal').broken,/Core prompt/) |
| 72 | const additive=request(cfg,{'presets/a/agent.cordis.yml':empty,'presets/persona/agent.cordis.yml':'- name: "@deepseek-ai/dsh-persona"\n config: {prefix: additive}\n','node_modules/@deepseek-ai/dsh-persona/package.json':JSON.stringify({name:'@deepseek-ai/dsh-persona',type:'module',exports:'./index.mjs'}),'node_modules/@deepseek-ai/dsh-persona/index.mjs':'export function apply(){}'}) |
| 73 | const bounded=await reviewAgentPresets(additive) |
| 74 | assert.equal(bounded.catalog.presets.find(p=>p.id==='persona').broken,undefined) |
| 75 | assert.deepEqual(bounded.presets.map(p=>p.metadata.id),['a','persona']) |
| 76 | await assert.rejects(reviewAgentPresets({...input,composition:{...input.composition,layers:input.composition.layers.map(l=>{const source=l.source.replace('"default":"a"','"default":"minimal"');return {...l,source,sha256:hash(source)}})}}),/default preset is missing or broken/) |
| 77 | }) |
| 78 | |
| 79 | function authoredRow(value) { |
| 80 | return `export const inject=['tools','commands','prompt','skills','agentPresets']; |
| 81 | export function apply(ctx){ |
| 82 | const value=${JSON.stringify(value)}+':'+ctx.agentPresets.composedPreset(); |
| 83 | ctx.tools.register({name:'preset_echo',description:'exact selected preset',parameters:{type:'object',properties:{}},execute:()=>value}); |
| 84 | ctx.commands.register({name:'preset-echo',description:'exact selected preset',handler:()=>value}); |
| 85 | ctx.prompt.registerSection({id:'selected',text:value}); |
| 86 | ctx.skills.registerRoot({path:'source/skills/${value}'}); |
| 87 | ctx.on('tools/pre-execute',()=>({kind:'annotate',text:value})); |
| 88 | }` |
| 89 | } |
| 90 | function installedEntries(t,review,contents) { |
| 91 | const root=mkdtempSync(join(tmpdir(),'cw-raw-presets-'));t.after(()=>rmSync(root,{recursive:true,force:true})) |
| 92 | for(const [path,source] of Object.entries(contents)){const target=join(root,'source',path);mkdirSync(dirname(target),{recursive:true});writeFileSync(target,source)} |
| 93 | mkdirSync(join(root,'native/presets'),{recursive:true}) |
| 94 | return review.presets.map(selected=>{ |
| 95 | const id=selected.metadata.id |
| 96 | const entry=join(root,'native/presets',`${id}.mjs`) |
| 97 | writeFileSync(join(root,'native/presets',`${id}.json`),JSON.stringify({catalog:review.catalog,selected,composition:review.top})) |
| 98 | const source=`import {mountReviewedPreset} from '@codewhale/dsh-composition';import data from './${id}.json' with {type:'json'};export async function apply(ctx){await mountReviewedPreset(ctx,new URL('../../source/',import.meta.url).href,data.composition,data.catalog,data.selected)}` |
| 99 | writeFileSync(entry,source);return {path:entry,sha256:hash(source)} |
| 100 | }) |
| 101 | } |
| 102 | |
| 103 | test('real raw roster mounts all five registries under one exact selected entry and tears down only that sibling',async t=>{ |
| 104 | const host=await startHost();t.after(()=>host.stop()) |
| 105 | const contents={ |
| 106 | 'presets/a/agent.cordis.yml':'- name: ./row.mjs\n','presets/a/row.mjs':authoredRow('A'), |
| 107 | 'presets/b/agent.cordis.yml':'- name: "@demo/preset-row"\n', |
| 108 | 'node_modules/@demo/preset-row/package.json':JSON.stringify({name:'@demo/preset-row',type:'module',exports:'./index.mjs'}), |
| 109 | 'node_modules/@demo/preset-row/index.mjs':authoredRow('B'), |
| 110 | } |
| 111 | const input=request(cfg,contents),review=await reviewAgentPresets(input);review.top=input.composition |
| 112 | const [a,b]=installedEntries(t,review,contents) |
| 113 | const first=await activate(host,'raw-presets',a.path,{scope:a}) |
| 114 | assert.equal(first.result.status,'ok',first.result.diagnostic+' '+JSON.stringify(host.logs)+' '+host.stderr) |
| 115 | const second=await host.call('ext/activate',{owner:first.ref,plugin_name:'raw-presets',entry:b,scope:b,config:{}}) |
| 116 | assert.equal(second.status,'ok',second.diagnostic) |
| 117 | const registrations=host.registry.filter(r=>r.op==='register') |
| 118 | for(const scope of [a,b])assert.deepEqual(new Set(registrations.filter(r=>r.scope.path===scope.path).map(r=>r.kind)),new Set(['tool','command','hook','prompt_section','skill_root'])) |
| 119 | const handle=(scope,kind)=>registrations.find(r=>r.scope.path===scope.path && r.kind===kind).handle |
| 120 | const call=scope=>host.call('tool/call',{handle:handle(scope,'tool'),input:{},call_id:scope.path,deadline_ms:5000}) |
| 121 | assert.match(JSON.stringify(await call(a)),/A:a/);assert.match(JSON.stringify(await call(b)),/B:b/) |
| 122 | assert.deepEqual(await host.call('command/run',{handle:handle(b,'command'),command_id:'preset-command',raw_input:'',deadline_ms:5000}),{kind:'success',text:'B:b'}) |
| 123 | assert.deepEqual(await host.call('hook/evaluate',{handle:handle(b,'hook'),event:'tools/pre-execute',deadline_ms:5000,payload:{name:'read',call_id:'preset-hook',input:{},mode:'Agent',workspace:'/workspace',model:'fixture'}}),{kind:'annotate',text:'B:b'}) |
| 124 | assert.deepEqual(await host.call('ext/deactivate',{owner:first.ref,entry:a}),{disposed:true,leaked:[]}) |
| 125 | await assert.rejects(call(a),/not live/);assert.match(JSON.stringify(await call(b)),/B:b/) |
| 126 | for(const row of registrations.filter(r=>r.scope.path===a.path)) assert.ok(host.registry.some(r=>r.op==='unregister' && r.handle===row.handle)) |
| 127 | for(const row of registrations.filter(r=>r.scope.path===b.path)) assert.ok(!host.registry.some(r=>r.op==='unregister' && r.handle===row.handle)) |
| 128 | assert.deepEqual(await host.call('ext/deactivate',{owner:first.ref}),{disposed:true,leaked:[]}) |
| 129 | }) |
| 130 | |
| 131 | |
| 132 | test('absent raw default stays visible and requires explicit selection before real host mount',async t=>{ |
| 133 | const noDefault={...cfg};delete noDefault.default |
| 134 | const contents={'presets/a/agent.cordis.yml':'- name: ./row.mjs\n','presets/a/row.mjs':authoredRow('A'),'presets/b/agent.cordis.yml':empty} |
| 135 | const input=request(noDefault,contents),review=await reviewAgentPresets(input);review.top=input.composition |
| 136 | assert.equal(review.catalog.default,undefined) |
| 137 | assert.ok(review.catalog.presets.every(row=>row.is_default===false)) |
| 138 | const [a]=installedEntries(t,review,contents) |
| 139 | // Core stages a whole reviewed bundle before importing any of its entries. |
| 140 | // Creating a sibling after an import also hits Bun's directory resolver cache. |
| 141 | const root=dirname(a.path),bad=join(root,'unselected.mjs') |
| 142 | const source="import {mountReviewedPreset} from '@codewhale/dsh-composition';import data from './a.json' with {type:'json'};export async function apply(ctx){await mountReviewedPreset(ctx,new URL('../../source/',import.meta.url).href,data.composition,data.catalog,undefined)}" |
| 143 | writeFileSync(bad,source) |
| 144 | const host=await startHost();t.after(()=>host.stop()) |
| 145 | const first=await activate(host,'absent-default',a.path,{scope:a}) |
| 146 | assert.equal(first.result.status,'ok',first.result.diagnostic+' '+host.stderr) |
| 147 | const tool=host.registry.find(row=>row.op==='register' && row.kind==='tool') |
| 148 | assert.match(JSON.stringify(await host.call('tool/call',{handle:tool.handle,input:{},call_id:'explicit',deadline_ms:5000})),/A:a/) |
| 149 | // Unselected generated mount is an error, never a first-healthy fallback. |
| 150 | const refused=await activate(host,'missing-selected',bad,{scope:{path:bad,sha256:hash(source)}}) |
| 151 | assert.equal(refused.result.status,'failed') |
| 152 | assert.match(refused.result.diagnostic,/explicit selection is required/) |
| 153 | }) |
| 154 | |
| 155 | |
| 156 | test('actual installed source counterparts mount default and explicitly selected no-default entries',async t=>{ |
| 157 | const host=await startHost();t.after(()=>host.stop()) |
| 158 | for(const suffix of ['', '-no-default']) { |
| 159 | const root=new URL(`../../tests/fixtures/extension_host/raw-agent-presets${suffix}/`,import.meta.url) |
| 160 | const catalog=JSON.parse(readFileSync(new URL('native/presets.json',root),'utf8')) |
| 161 | assert.equal(catalog.default,suffix?undefined:'a') |
| 162 | const row=catalog.presets.find(p=>p.id==='b'),entry=fileURLToPath(new URL(row.entry.path,root)) |
| 163 | assert.equal(hash(readFileSync(entry)),row.entry.sha256) |
| 164 | const admitted=await activate(host,'counterpart'+suffix,entry,{scope:{path:entry,sha256:row.entry.sha256}}) |
| 165 | assert.equal(admitted.result.status,'ok',admitted.result.diagnostic+' '+host.stderr) |
| 166 | const tool=host.registry.findLast(r=>r.op==='register' && r.kind==='tool') |
| 167 | assert.match(JSON.stringify(await host.call('tool/call',{handle:tool.handle,input:{},call_id:'fixed'+suffix,deadline_ms:5000})),/B:b/) |
| 168 | assert.deepEqual(await host.call('ext/deactivate',{owner:admitted.ref}),{disposed:true,leaked:[]}) |
| 169 | } |
| 170 | }) |
| 171 | |
| 172 | |
| 173 | test('the existing upstream patch authority retains exact skipped operation identities and anonymous groups',()=>{ |
| 174 | const first='- insert:\n - {id: group, group: true, config: []}\n - {id: docs-entry, name: portable}\n' |
| 175 | const second='- {id: missing-group, insert: []}\n- {disabled: true}\n- {id: missing-row, disabled: true}\n- {id: docs-entry, name: wrong-package, disabled: true}\n- id: group\n insert:\n - {id: child, name: ./row.mjs}\n' |
| 176 | const spec={version:1,layers:[{path:'first.yml',source:first,sha256:hash(first)},{path:'overlay.yml',source:second,sha256:hash(second)}],modules:[],files:{}} |
| 177 | const result=spawnSync(process.execPath,[fileURLToPath(new URL('../dist/dsh-composition-review.mjs',import.meta.url))],{input:JSON.stringify(spec),encoding:'utf8',timeout:5000}) |
| 178 | assert.equal(result.status,0,result.stderr) |
| 179 | const reviewed=JSON.parse(result.stdout) |
| 180 | assert.deepEqual(reviewed.skipped.map(row=>[row.row??null,row.layer,row.patch]),[['missing-group','overlay.yml',1],[null,'overlay.yml',2],['missing-row','overlay.yml',3],['docs-entry','overlay.yml',4]]) |
| 181 | assert.equal(reviewed.entries[1].disabled,undefined) |
| 182 | assert.equal(reviewed.entries[0].name,undefined,'raw patch comparison keeps its original anonymous identity') |
| 183 | assert.equal(reviewed.entries[0].config[0].name,'./row.mjs') |
| 184 | }) |
| 185 | |
| 186 | test('roster inventory uses real selected fiber facts and unmounted conditional rows without another graph',async t=>{ |
| 187 | const host=await startHost();t.after(()=>host.stop()) |
| 188 | const source=`export const inject=['tools','agentPresets'];export function apply(ctx){ctx.tools.register({name:'preset_inspect',description:'readonly roster',parameters:{type:'object',properties:{}},execute:async()=>({roster:await ctx.agentPresets.remoteExportList(),inventory:await ctx.agentPresets.compositionInventory(),selected:ctx.agentPresets.composedPreset()})})}` |
| 189 | const contents={'presets/a/agent.cordis.yml':'- name: ./row.mjs\n','presets/a/row.mjs':source,'presets/b/agent.cordis.yml':"- name: missing-conditional\n disabled: !!js 'true'\n"} |
| 190 | const input=request(cfg,contents) |
| 191 | const top=JSON.stringify([{insert:[{id:'anonymous',group:true,config:JSON.parse(input.composition.layers[0].source)[0].insert}]}]) |
| 192 | input.composition.layers[0]={path:'bundle.json',source:top,sha256:hash(top)} |
| 193 | const review=await reviewAgentPresets(input);review.top=input.composition |
| 194 | const [a]=installedEntries(t,review,contents) |
| 195 | const mounted=await activate(host,'inventory-roster',a.path,{scope:a}) |
| 196 | assert.equal(mounted.result.status,'ok',mounted.result.diagnostic+' '+host.stderr+' '+JSON.stringify(host.logs)) |
| 197 | const tool=host.registry.find(r=>r.op==='register' && r.kind==='tool') |
| 198 | const result=await host.call('tool/call',{handle:tool.handle,input:{},call_id:'inventory',deadline_ms:5000}) |
| 199 | assert.equal(result.structured.selected,'a') |
| 200 | assert.equal(result.structured.roster.authorable,false) |
| 201 | assert.equal(result.structured.roster.defaultId,'a') |
| 202 | assert.equal(result.structured.inventory[0].isDefault,true) |
| 203 | assert.equal(result.structured.inventory[0].rows[0].enabled,true) |
| 204 | assert.ok(Object.hasOwn(result.structured.inventory[0].rows[0],'fiberState')) |
| 205 | assert.equal(result.structured.inventory[1].rows[0].enabled,'conditional') |
| 206 | assert.equal(Object.hasOwn(result.structured.inventory[1].rows[0],'fiberState'),false) |
| 207 | assert.deepEqual(await host.call('ext/deactivate',{owner:mounted.ref}),{disposed:true,leaked:[]}) |
| 208 | }) |
| 209 | |
| 210 | |
| 211 | test('real raw persona rows admit stock additive templates under exact sibling scopes', async t => { |
| 212 | const contents = { |
| 213 | 'presets/a/agent.cordis.yml': '- name: "@deepseek-ai/dsh-persona"\n config: {prefix: "You are {{model}}.", suffix: "Work in {{cwd}}."}\n', |
| 214 | 'presets/b/agent.cordis.yml': '- name: "@deepseek-ai/dsh-persona"\n config: {prefix: "B {{model}}", suffix: "{{cwd}}"}\n', |
| 215 | 'presets/replacement/agent.cordis.yml': '- name: "@deepseek-ai/dsh-persona"\n config: {prefix: replace, complete: true}\n', |
| 216 | 'presets/suppression/agent.cordis.yml': '- name: "@deepseek-ai/dsh-persona"\n config: {prefix: suppress, includeRuntimeContext: false}\n', |
| 217 | 'presets/unknown/agent.cordis.yml': '- name: "@deepseek-ai/dsh-persona"\n config: {prefix: "{{env}}"}\n', |
| 218 | } |
| 219 | const input = request(cfg, contents), review = await reviewAgentPresets(input); review.top = input.composition |
| 220 | assert.deepEqual(review.presets.map(row=>row.metadata.id), ['a','b']) |
| 221 | assert.match(review.catalog.presets.find(row=>row.id==='replacement').broken,/Core prompt/) |
| 222 | assert.match(review.catalog.presets.find(row=>row.id==='suppression').broken,/Core prompt/) |
| 223 | assert.match(review.catalog.presets.find(row=>row.id==='unknown').broken,/unknown Core prompt variable/) |
| 224 | assert.ok(review.presets.every(row=>row.composition.modules.length===0),'fixed bridge requires no ambient persona package') |
| 225 | const [a,b] = installedEntries(t, review, contents) |
| 226 | const host = await startHost(); t.after(()=>host.stop()) |
| 227 | const first = await activate(host,'raw-personas',a.path,{scope:a}) |
| 228 | assert.equal(first.result.status,'ok',first.result.diagnostic+' '+host.stderr) |
| 229 | const second = await host.call('ext/activate',{owner:first.ref,plugin_name:'raw-personas',entry:b,scope:b,config:{}}) |
| 230 | assert.equal(second.status,'ok',second.diagnostic) |
| 231 | const rows = host.registry.filter(row=>row.op==='register' && row.kind==='prompt_template') |
| 232 | assert.equal(rows.length,4) |
| 233 | for (const scope of [a,b]) assert.deepEqual(rows.filter(row=>row.scope.path===scope.path).map(row=>row.spec.name),['persona-prefix','persona-suffix']) |
| 234 | assert.ok(rows.every(row=>row.spec.description.includes('{{')),'only Core may expand actual turn facts') |
| 235 | assert.deepEqual(await host.call('ext/deactivate',{owner:first.ref,entry:a}),{disposed:true,leaked:[]}) |
| 236 | for (const row of rows) assert.equal(host.registry.some(event=>event.op==='unregister' && event.handle===row.handle),row.scope.path===a.path) |
| 237 | assert.deepEqual(await host.call('ext/deactivate',{owner:first.ref}),{disposed:true,leaked:[]}) |
| 238 | }) |
| 239 |