@oooooooooo/ch0de 1.9.55 → 1.9.56
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.
- package/install.cjs +2 -2
- package/package.json +3 -1
package/install.cjs
CHANGED
|
@@ -4,10 +4,10 @@ const fs=require('fs'),os=require('os'),path=require('path'),crypto=require('cry
|
|
|
4
4
|
const REPOSITORY='https://github.com/fogennnnn/chode.git';
|
|
5
5
|
function execute(command,args,options={}){const r=spawnSync(command,args,{encoding:'utf8',windowsHide:true,timeout:180000,maxBuffer:4*1024*1024,...options});if(r.error||r.status!==0)throw Error(String(r.stderr||r.stdout||r.error||'Command failed').trim().slice(-2000));return r.stdout.trim();}
|
|
6
6
|
function npmRunner(){const directories=[path.dirname(process.execPath),...String(process.env.PATH||'').split(path.delimiter)];const candidates=[process.env.npm_execpath,path.join(path.dirname(process.execPath),'..','lib','node_modules','npm','bin','npm-cli.js'),'/usr/share/nodejs/npm/bin/npm-cli.js'];for(const directory of directories){candidates.push(path.join(directory,'node_modules','npm','bin','npm-cli.js'));try{candidates.push(fs.realpathSync(path.join(directory,'npm')));}catch(_){}}const cli=candidates.find(p=>p&&/npm-cli\.js$/i.test(p)&&fs.existsSync(p));if(!cli)throw Error('npm was not found. Install Node.js 18+ with npm, then retry.');return args=>execute(process.execPath,[cli,...args]);}
|
|
7
|
-
async function install(options={}){if(Number(process.versions.node.split('.')[0])<18)throw Error('Node.js 18+ is required.');const release=await fetchRelease();execute('git',['--version']);const npm=npmRunner(),temporaryRoot=fs.realpathSync(os.tmpdir()),staging=fs.mkdtempSync(path.join(temporaryRoot,'chode-install-'));const prefix=options.prefix?['--prefix',path.resolve(options.prefix)]:[];try{const checkout=path.join(staging,'source');console.log('Downloading the latest Chode from master…');execute('git',['clone','--depth','1','--single-branch','--no-tags','--branch','master',REPOSITORY,checkout]);const project=path.join(checkout,'chode'),manifest=JSON.parse(fs.readFileSync(path.join(project,'package.json'),'utf8'));if(manifest.name!=='chode'||!fs.existsSync(path.join(project,'chode.js')))throw Error('Downloaded source is not the expected Chode project.');verifyRelease(project,release);const commit=execute('git',['-C',checkout,'rev-parse','HEAD']);const packed=JSON.parse(npm(['pack',project,'--ignore-scripts','--json','--pack-destination',staging]));if(!Array.isArray(packed)||packed.length!==1||path.basename(packed[0].filename)!==packed[0].filename)throw Error('Unexpected package archive.');const archive=path.join(staging,packed[0].filename);console.log('Installing Chode '+manifest.version+'…');npm(['install','--global','--ignore-scripts','--no-audit','--no-fund',...prefix,archive]);const modules=npm(['root','--global',...prefix]),
|
|
7
|
+
async function install(options={}){if(Number(process.versions.node.split('.')[0])<18)throw Error('Node.js 18+ is required.');const release=await fetchRelease();execute('git',['--version']);const npm=npmRunner(),temporaryRoot=fs.realpathSync(os.tmpdir()),staging=fs.mkdtempSync(path.join(temporaryRoot,'chode-install-'));const prefix=options.prefix?['--prefix',path.resolve(options.prefix)]:[];try{const checkout=path.join(staging,'source');console.log('Downloading the latest Chode from master…');execute('git',['clone','--depth','1','--single-branch','--no-tags','--branch','master',REPOSITORY,checkout]);const project=path.join(checkout,'chode'),manifest=JSON.parse(fs.readFileSync(path.join(project,'package.json'),'utf8'));if((manifest.name!=='chode'&&manifest.name!=='@oooooooooo/ch0de')||!fs.existsSync(path.join(project,'chode.js')))throw Error('Downloaded source is not the expected Chode project.');verifyRelease(project,release);const commit=execute('git',['-C',checkout,'rev-parse','HEAD']);const packed=JSON.parse(npm(['pack',project,'--ignore-scripts','--json','--pack-destination',staging]));if(!Array.isArray(packed)||packed.length!==1||path.basename(packed[0].filename)!==packed[0].filename)throw Error('Unexpected package archive.');const archive=path.join(staging,packed[0].filename);console.log('Installing Chode '+manifest.version+'…');npm(['install','--global','--force','--ignore-scripts','--no-audit','--no-fund',...prefix,archive]);const modules=npm(['root','--global',...prefix]),pkgRoot=manifest.name.startsWith('@')?path.join(modules,manifest.name.split('/')[0],manifest.name.split('/')[1]):path.join(modules,manifest.name),installed=path.join(pkgRoot,'chode.js');verifyRelease(path.dirname(installed),release);const version=execute(process.execPath,[installed,'--version']);if(version!==manifest.version)throw Error('Installed version mismatch: expected '+manifest.version+', received '+version);console.log('Installed Chode '+version+' · '+commit.slice(0,12));console.log('Verified executable: '+installed);warnShadowed(modules);console.log('Start coding: chode');if(options.prefix)console.log('Command directory: '+(process.platform==='win32'?path.resolve(options.prefix):path.join(path.resolve(options.prefix),'bin')));console.log(options.prefix?'If chode is not found, add the command directory above to PATH and reopen your terminal.':'If chode is not found, add npm\'s global command directory to PATH and reopen your terminal.');return {version,commit,installed};}finally{const resolved=path.resolve(staging);if(path.dirname(resolved)!==temporaryRoot||!path.basename(resolved).startsWith('chode-install-'))throw Error('Refusing cleanup outside the installer staging directory.');fs.rmSync(resolved,{recursive:true,force:true});}}
|
|
8
8
|
if(require.main===module){try{const args=process.argv.slice(2);if(args.length&&!(args.length===2&&args[0]==='--prefix'))throw Error('Usage: node install.cjs [--prefix directory]');install({prefix:args[1]||process.env.CHODE_INSTALL_PREFIX}).catch(error=>{console.error('Chode installation failed: '+error.message);process.exitCode=1;});}catch(error){console.error('Chode installation failed: '+error.message);process.exitCode=1;}}
|
|
9
9
|
function digestFile(root,file){let content=fs.readFileSync(path.join(root,file),'utf8').replace(/\r\n/g,'\n');if(file==='package.json'){const p=JSON.parse(content);content=JSON.stringify({name:p.name,version:p.version,main:p.main,bin:p.bin,engines:p.engines,files:p.files,dependencies:p.dependencies||{}});}return crypto.createHash('sha256').update(content).digest('hex');}
|
|
10
|
-
function verifyRelease(root,release){if(!release||release.channel!=='master'||!/^\d+\.\d+\.\d+$/.test(release.version)||!release.files)throw Error('Verified release metadata is invalid.');const parts=release.version.split('.').map(Number);if(parts[0]<1||parts[0]===1&&(parts[1]<7||parts[1]===7&&parts[2]<2))throw Error('Release is below the supported security floor.');const p=JSON.parse(fs.readFileSync(path.join(root,'package.json'),'utf8'));if(p.version!==release.version)throw Error('Downloaded version does not match the verified release. No stale version will be installed; retry after publication completes.');if(p.name!=='chode'||p.bin
|
|
10
|
+
function verifyRelease(root,release){if(!release||release.channel!=='master'||!/^\d+\.\d+\.\d+$/.test(release.version)||!release.files)throw Error('Verified release metadata is invalid.');const parts=release.version.split('.').map(Number);if(parts[0]<1||parts[0]===1&&(parts[1]<7||parts[1]===7&&parts[2]<2))throw Error('Release is below the supported security floor.');const p=JSON.parse(fs.readFileSync(path.join(root,'package.json'),'utf8'));if(p.version!==release.version)throw Error('Downloaded version does not match the verified release. No stale version will be installed; retry after publication completes.');if((p.name!=='chode'&&p.name!=='@oooooooooo/ch0de')||p.bin&&!(p.bin.chode==='chode.js'||p.bin.ch0de==='chode.js'))throw Error('Unexpected package identity.');for(const required of ['package.json','chode.js','provider-policy.js'])if(!release.files[required])throw Error('Release integrity list is incomplete.');for(const file of Object.keys(release.files)){if(path.isAbsolute(file)||file.split(/[\\/]/).includes('..')||!/^[a-zA-Z0-9_./-]+$/.test(file))throw Error('Unsafe release file path.');if(digestFile(root,file)!==release.files[file])throw Error('Release integrity mismatch: '+file);}for(const file of p.files||[]){if(/\.(?:js|cjs)$/.test(file)){if(!release.files[file])throw Error('Unverified runtime file: '+file);const content=fs.readFileSync(path.join(root,file),'utf8');if(new RegExp('poll'+'inat','i').test(content))throw Error('Forbidden retired fallback detected in '+file);}}return true;}
|
|
11
11
|
async function fetchRelease(options={}){
|
|
12
12
|
const request=options.fetch||fetch,pause=options.sleep||(ms=>new Promise(resolve=>setTimeout(resolve,ms)));let last;
|
|
13
13
|
for(let attempt=0;attempt<3;attempt++){
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oooooooooo/ch0de",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.56",
|
|
4
4
|
"description": "The self-healing AI coding harness. Free tiers. HEMO auto-provisioning. Zero lock-in. Canonical brand: ch0de.",
|
|
5
5
|
"main": "chode.js",
|
|
6
6
|
"bin": {
|
|
7
|
+
"chode": "chode.js",
|
|
7
8
|
"ch0de": "chode.js",
|
|
8
9
|
"chode-council": "expert-panel.cjs"
|
|
9
10
|
},
|
|
@@ -150,6 +151,7 @@
|
|
|
150
151
|
},
|
|
151
152
|
"dependencies": {
|
|
152
153
|
"@modelcontextprotocol/sdk": "1.32.2",
|
|
154
|
+
"@oooooooooo/ch0de": "^1.9.55",
|
|
153
155
|
"lean": "^0.1.1"
|
|
154
156
|
},
|
|
155
157
|
"devDependencies": {
|