@petercjl/codex-own 0.4.1 → 0.5.1
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/README.md +20 -0
- package/bin/codex-own.mjs +13 -3
- package/capabilities.json +26 -1
- package/lib/app-update.mjs +2 -0
- package/lib/manager.mjs +10 -4
- package/lib/npm-assets.mjs +1 -1
- package/lib/tool-env.cjs +45 -0
- package/lib/tool-runtime.mjs +82 -0
- package/package.json +158 -69
- package/release.json +157 -68
- package/skills/codex-own/SKILL.md +14 -0
package/README.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
独立桌面应用的 npm 安装与更新工具。支持 Mac ARM64 和 Windows x64。管理工具和桌面资源均从 npm 下载。
|
|
4
4
|
|
|
5
|
+
## 独立 Node、npm 和 Python
|
|
6
|
+
|
|
7
|
+
从 0.5.0 起,安装或更新桌面程序会同时安装其固定版本的独立工具。第一版为 Node 24.22.0、npm 11.19.1、Python 3.12.15,保留发行包自带许可证。资源通过 npm 内容包分发,接收端无需连接 GitHub 或 Node/Python 下载站。工具版本独立于桌面版本;后续桌面更新复用相同工具和已校验分片。
|
|
8
|
+
|
|
9
|
+
Mac 工具位于 `~/Library/Application Support/codex-own-independent/runtimes`,Windows 位于 `%LOCALAPPDATA%\codex-own-independent\runtimes`。版本目录、npm 全局包与缓存、pip 缓存和 Python 字节码均归 codex-own 所有。应用启动后只为自己的进程及工作子进程设置 PATH;用户/系统 PATH、shell 配置和原版 Codex 缓存保持不变。项目的 `node_modules` 和 Python `.venv` 继续保存在项目中。Python 包安装使用项目虚拟环境,pip 默认要求虚拟环境,保证工具版本目录稳定。
|
|
10
|
+
|
|
11
|
+
Mac 任务使用运行时目录内的私有 zsh 启动文件和 Bash `BASH_ENV`,保证登录 shell 仍优先选择独立工具。这些配置只在 codex-own 进程中生效,用户原有 shell 文件保持不变。
|
|
12
|
+
|
|
13
|
+
可直接发给 Agent:
|
|
14
|
+
|
|
15
|
+
> 请检查 codex-own 的独立 Node、npm 和 Python 运行时,并验证实际执行路径。
|
|
16
|
+
|
|
17
|
+
> 请通过 @petercjl/codex-own 更新 codex-own 及其独立运行时,保留配置和对话。
|
|
18
|
+
|
|
19
|
+
开发者和终端测试入口:`codex-own runtime doctor` 查看工具版本和实际路径;`codex-own runtime run -- node --version`、`codex-own runtime run -- npm --version`、`codex-own runtime run -- python --version` 可在应用外使用同一套工具。`runtime env` 只返回工具环境合同,不输出 API Key 或继承的账户信息。独立更新使用 `runtime update --yes`,回到上个工具版本使用 `runtime rollback --yes`;已运行的应用在重启后采用新版本。安装失败保持原有活动版本,保留可恢复的版本记录。
|
|
20
|
+
|
|
21
|
+
首次通过 npm 安装管理工具仍需要机器已有 Node.js 22+ 和 npm;这只是引导安装的前提。安装完成后,桌面任务和应用内更新使用 codex-own 自己的工具。此工具集包含 Node、npm、Python、pip、venv;原版完整办公依赖集合、Git、编译器和额外项目库按实际任务另行安装。
|
|
22
|
+
|
|
23
|
+
从 0.4.x 的应用内更新按钮升级时,新应用首次打开会显示“正在准备 codex-own 工作环境”,自动从 npm 补齐工具并验证后再进入桌面。下载失败或取消后可重新打开重试,已验证分片会保留。
|
|
24
|
+
|
|
5
25
|
## 应用内更新
|
|
6
26
|
|
|
7
27
|
带有 npm 更新组件的桌面版本会在启动 15 秒后、以及运行期间每 6 小时检查稳定版。也可以打开菜单“更新 → 检查 codex-own 更新…”。发现新版后点击“下载更新”,下载期间可以继续使用 App。下载完成后结束正在运行的任务,点击“重启并安装”;更新进程会等待 App 退出,备份程序及独立数据,再安装并重新打开。
|
package/bin/codex-own.mjs
CHANGED
|
@@ -3,15 +3,25 @@ import fs from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import {pkg,packageRoot,read,fail,paths,doctor,latest,state,install,launch,rollback,hash,rejectLinks,configure} from '../lib/manager.mjs';
|
|
6
|
+
import {manifestFor} from '../lib/manager.mjs';
|
|
7
|
+
import {installRuntime,runtimeDoctor,rollbackRuntime,runRuntime,toolEnv} from '../lib/tool-runtime.mjs';
|
|
6
8
|
const args=process.argv.slice(2),[command,sub]=args;
|
|
7
9
|
const flag=n=>args.includes('--'+n),value=n=>{const i=args.indexOf('--'+n);return i<0?undefined:args[i+1];};
|
|
8
10
|
const yes=()=>{if(!flag('yes'))fail('CONFIRMATION_REQUIRED','Mutating commands require --yes');};
|
|
9
11
|
async function skill(){const source=path.join(packageRoot,'skills','codex-own');if(sub==='source')return {ok:true,source,version:pkg.version};const agent=value('agent')||'codex';if(!['codex','sealseek'].includes(agent))fail('UNSUPPORTED_AGENT',agent);const base=value('target-root')||(agent==='codex'?path.join(os.homedir(),'.codex','skills'):null);if(!base)fail('TARGET_REQUIRED','Provide the configured Agent skill root with --target-root');const dest=path.join(base,'codex-own'),marker=path.join(dest,'.codex-own-managed.json');rejectLinks(base);rejectLinks(dest);const exists=fs.existsSync(dest);const owned=exists&&fs.existsSync(marker)&&read(marker).package===pkg.name;const srcHash=hash(fs.readFileSync(path.join(source,'SKILL.md')));if(sub==='status')return {ok:true,source,destination:dest,installed:exists,managed:owned,current:owned&&hash(fs.readFileSync(path.join(dest,'SKILL.md')))===srcHash};if(!['install','update'].includes(sub))fail('INVALID_COMMAND','skill source/status/install/update');yes();if(exists&&!owned)fail('UNMANAGED_TARGET','Existing skill is not managed');let backup=null;if(exists){backup=dest+'.backup-'+Date.now();fs.cpSync(dest,backup,{recursive:true,force:false,errorOnExist:true});}fs.mkdirSync(dest,{recursive:true});const ui=path.join(dest,'agents','openai.yaml'),customUI=fs.existsSync(ui)?fs.readFileSync(ui):null;fs.cpSync(source,dest,{recursive:true});if(customUI)fs.writeFileSync(ui,customUI);fs.writeFileSync(marker,JSON.stringify({package:pkg.name,version:pkg.version,hash:srcHash}));if(hash(fs.readFileSync(path.join(dest,'SKILL.md')))!==srcHash)fail('VERIFY_FAILED','Skill copy mismatch');return {ok:true,source,destination:dest,backup,version:pkg.version};}
|
|
10
12
|
async function main(){
|
|
11
|
-
if(!command||command==='help'||command==='--help')return {commands:['version','capabilities','doctor','install --yes [--adopt]','configure --api-key-file <file> --yes','update check','update install --yes','launch','rollback --restore-data --yes','skill source|status|install|update'],note:'Application data
|
|
13
|
+
if(!command||command==='help'||command==='--help')return {commands:['version','capabilities','doctor','install --yes [--adopt]','configure --api-key-file <file> --yes','update check','update install --yes','runtime install|update|doctor|env|run|rollback','launch','rollback --restore-data --yes','skill source|status|install|update'],note:'Application data and private tools remain outside npm manager packages. Quit the app before desktop updates. Manager, desktop and tool runtime versions are reported separately.'};
|
|
12
14
|
if(command==='version'||command==='--version')return {manager:pkg.version,desktop:state()?.version||null};
|
|
13
15
|
if(command==='capabilities')return read(path.join(packageRoot,'capabilities.json'));
|
|
14
|
-
if(command==='doctor')return doctor();
|
|
16
|
+
if(command==='doctor')return {...doctor(),runtime:runtimeDoctor()};
|
|
17
|
+
if(command==='runtime'){
|
|
18
|
+
if(sub==='doctor')return runtimeDoctor();
|
|
19
|
+
if(sub==='env'){const env=toolEnv.environment();if(!env)fail('RUNTIME_NOT_INSTALLED','Install private tools first');return {ok:true,contract:1,root:toolEnv.runtimeRoot(),environment:Object.fromEntries(Object.entries(env).filter(([k])=>['PATH','ZDOTDIR','BASH_ENV','CODEX_OWN_NODE','CODEX_OWN_PYTHON','CODEX_OWN_RUNTIME_VERSION','AGENT_WORKBENCH_NPM_CLI'].includes(k)||/^(NPM_CONFIG_|PYTHON|PIP_)/.test(k)))};}
|
|
20
|
+
if(sub==='run'){const i=args.indexOf('--');process.exitCode=runRuntime(i<0?args.slice(2):args.slice(i+1));return;}
|
|
21
|
+
if(sub==='install'||sub==='update'){yes();const m=await manifestFor(value('version')||await latest());return installRuntime(m.runtimes);}
|
|
22
|
+
if(sub==='rollback'){yes();return rollbackRuntime();}
|
|
23
|
+
return {commands:['runtime install --yes','runtime update --yes','runtime doctor','runtime env','runtime run -- <node|npm|npx|python|python3|pip> [args]','runtime rollback --yes']};
|
|
24
|
+
}
|
|
15
25
|
if(command==='launch')return launch();
|
|
16
26
|
if(command==='skill')return skill();
|
|
17
27
|
if(command==='configure'){yes();return configure(value('api-key-file'));}
|
|
@@ -20,4 +30,4 @@ async function main(){
|
|
|
20
30
|
if(command==='rollback'){yes();return rollback({restoreData:flag('restore-data')});}
|
|
21
31
|
fail('INVALID_COMMAND','See codex-own help');
|
|
22
32
|
}
|
|
23
|
-
try{const result=await main();console.log(JSON.stringify(result,null,2));if(result.ok===false)process.exitCode=1;}catch(e){console.error(JSON.stringify({ok:false,code:e.code||'OPERATION_FAILED',message:e.message}));process.exitCode=1;}
|
|
33
|
+
try{const result=await main();if(result!==undefined){console.log(JSON.stringify(result,null,2));if(result.ok===false)process.exitCode=1;}}catch(e){console.error(JSON.stringify({ok:false,code:e.code||'OPERATION_FAILED',message:e.message}));process.exitCode=1;}
|
package/capabilities.json
CHANGED
|
@@ -12,7 +12,13 @@
|
|
|
12
12
|
"skill source",
|
|
13
13
|
"skill status",
|
|
14
14
|
"skill install",
|
|
15
|
-
"skill update"
|
|
15
|
+
"skill update",
|
|
16
|
+
"runtime install",
|
|
17
|
+
"runtime update",
|
|
18
|
+
"runtime doctor",
|
|
19
|
+
"runtime env",
|
|
20
|
+
"runtime run",
|
|
21
|
+
"runtime rollback"
|
|
16
22
|
],
|
|
17
23
|
"platforms": {
|
|
18
24
|
"darwin-arm64": "implemented",
|
|
@@ -55,5 +61,24 @@
|
|
|
55
61
|
"runtime": "bundled standalone Node; no global npm upgrade required",
|
|
56
62
|
"menu": "更新 → 检查 codex-own 更新…",
|
|
57
63
|
"offline": "current installation remains usable; manual retry; verified prepared update survives restart"
|
|
64
|
+
},
|
|
65
|
+
"toolRuntime": {
|
|
66
|
+
"contract": 1,
|
|
67
|
+
"platforms": [
|
|
68
|
+
"darwin-arm64",
|
|
69
|
+
"win32-x64"
|
|
70
|
+
],
|
|
71
|
+
"versions": {
|
|
72
|
+
"node": "24.22.0",
|
|
73
|
+
"npm": "11.19.1",
|
|
74
|
+
"python": "3.12.15"
|
|
75
|
+
},
|
|
76
|
+
"source": "release manifest pinned npm content payloads",
|
|
77
|
+
"state": "independent root/runtimes/active.json",
|
|
78
|
+
"pathPolicy": "app and child processes only; user and system PATH preserved",
|
|
79
|
+
"pythonPackages": "project venv; pip requires virtualenv",
|
|
80
|
+
"npmGlobalPackages": "private runtimes/npm-global prefix",
|
|
81
|
+
"rollback": "verify predecessor and switch receipt; no conversation data restore",
|
|
82
|
+
"firstBootstrap": "existing Node >=22 and npm required"
|
|
58
83
|
}
|
|
59
84
|
}
|
package/lib/app-update.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import {latest,manifestFor,validateManifest,paths,state,locked,rejectLinks,exclusive,digestFile,tarExecutable,install,fail,running,launch} from './manager.mjs';
|
|
4
4
|
import {assembleNpmAsset} from './npm-assets.mjs';
|
|
5
5
|
import {reuseInstalledBlocks} from './content-blocks.mjs';
|
|
6
|
+
import {ensureRuntime} from './tool-runtime.mjs';
|
|
6
7
|
|
|
7
8
|
// Desktop release versions use the stable npm channel, independently of upstream's app version.
|
|
8
9
|
export function isNewer(candidate,current) {
|
|
@@ -31,6 +32,7 @@ export async function prepareUpdate(current,{p=paths(),resolve=latest,manifest=m
|
|
|
31
32
|
// The app may stay open: only read program resources, never user data.
|
|
32
33
|
if(p.target){rejectLinks(p.target);await reuseInstalledBlocks(asset,p.target,cache,{report,signal});}
|
|
33
34
|
const transfer=await assemble(asset,archive,cache,tarExecutable(),{report,signal});
|
|
35
|
+
if(m.runtimes)await ensureRuntime(m.runtimes,{p,report,signal});
|
|
34
36
|
// Verify even when a download adapter is supplied.
|
|
35
37
|
if(fs.statSync(archive).size!==asset.size||await digestFile(archive)!==asset.sha256)fail('CHECKSUM_MISMATCH','Prepared update checksum mismatch');
|
|
36
38
|
const receipt=path.join(dir,'receipt.json');
|
package/lib/manager.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import {execFileSync, spawn} from 'node:child_process';
|
|
|
7
7
|
import {networkFetch, verifiedDownload, progress} from './network.mjs';
|
|
8
8
|
import {validateParts, assembleNpmAsset} from './npm-assets.mjs';
|
|
9
9
|
import {reuseInstalledBlocks} from './content-blocks.mjs';
|
|
10
|
+
import {ensureRuntime,validateRuntime} from './tool-runtime.mjs';
|
|
10
11
|
|
|
11
12
|
export const packageRoot = path.resolve(import.meta.dirname, '..');
|
|
12
13
|
export const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot,'package.json'),'utf8'));
|
|
@@ -24,6 +25,7 @@ export function rejectLinks(p) {
|
|
|
24
25
|
}
|
|
25
26
|
export function validateManifest(m, platform) {
|
|
26
27
|
if(![1,2].includes(m.schema)||m.repository!=='petercjl/codex-own'||!/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(m.version))fail('INVALID_MANIFEST','Invalid release identity');
|
|
28
|
+
if(m.runtimes)validateRuntime(m.runtimes,platform);
|
|
27
29
|
const a=m.platforms?.[platform];if(!a)fail('PLATFORM_UNAVAILABLE',`No verified build for ${platform} in ${m.version}`);
|
|
28
30
|
if(!/^[a-f0-9]{64}$/.test(a.sha256)||!Number.isSafeInteger(a.size)||a.size<=0)fail('INVALID_MANIFEST','Invalid archive checksum/size');
|
|
29
31
|
if(m.schema===2){validateParts(a);if(a.entry!==(platform==='darwin-arm64'?'codex-own.app':'app'))fail('INVALID_MANIFEST','Unexpected archive entry');return a;}
|
|
@@ -46,8 +48,11 @@ export function tarExecutable(platform=process.platform,env=process.env,exists=f
|
|
|
46
48
|
return executable;
|
|
47
49
|
}
|
|
48
50
|
export function unpack(archive,dest) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
// Older Windows tar builds convert absolute argv paths through the ANSI code
|
|
52
|
+
// page. CreateProcessW's cwd supports Unicode; sibling relative args avoid it.
|
|
53
|
+
const cwd=path.dirname(path.resolve(archive)),source=path.basename(archive),target=path.relative(cwd,path.resolve(dest));
|
|
54
|
+
const names=execFileSync(tarExecutable(),['-tf',source],{cwd,encoding:'utf8',maxBuffer:30*1024*1024}).split('\n').filter(Boolean);checkEntries(names);
|
|
55
|
+
fs.mkdirSync(dest);execFileSync(tarExecutable(),['-xf',source,'-C',target],{cwd,stdio:'pipe'});
|
|
51
56
|
// Bundled framework links may be relative but must stay within the extracted tree.
|
|
52
57
|
function walk(p){for(const x of fs.readdirSync(p,{withFileTypes:true})){const f=path.join(p,x.name);if(x.isSymbolicLink()){const resolved=path.resolve(path.dirname(f),fs.readlinkSync(f));if(!resolved.startsWith(dest+path.sep))fail('UNSAFE_ARCHIVE','Escaping symlink');}else if(x.isDirectory())walk(f);}}
|
|
53
58
|
walk(dest);
|
|
@@ -93,7 +98,7 @@ export function switchApp({p,source,version,adopt=false,identity=appIdentity,isR
|
|
|
93
98
|
}
|
|
94
99
|
export async function locked(p,fn){rejectLinks(p.root);fs.mkdirSync(p.manager,{recursive:true,mode:0o700});const lock=path.join(p.manager,'operation.lock');let fd;try{fd=fs.openSync(lock,'wx',0o600);}catch{fail('BUSY','Another operation or interrupted lock exists; inspect doctor before recovery');}try{fs.writeSync(fd,JSON.stringify({pid:process.pid,time:new Date().toISOString()}));return await fn();}finally{fs.closeSync(fd);fs.unlinkSync(lock);}}
|
|
95
100
|
export async function latest() {const r=await networkFetch('https://registry.npmjs.org/@petercjl%2fcodex-own/latest',{signal:AbortSignal.timeout(30000)});if(!r.ok)fail('REGISTRY_UNAVAILABLE',`Registry HTTP ${r.status}`);const p=await r.json();if(p.name!==pkg.name)fail('INVALID_MANIFEST','Registry package mismatch');return p.version;}
|
|
96
|
-
export async function manifestFor(v){if(v===pkg.version)
|
|
101
|
+
export async function manifestFor(v){if(v===pkg.version){const local=read(path.join(packageRoot,'release.json'));if(local.version===v)return local;}if(!/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(v))fail('INVALID_VERSION','Invalid version');const r=await networkFetch(`https://registry.npmjs.org/@petercjl%2fcodex-own/${v}`,{signal:AbortSignal.timeout(30000)});if(!r.ok)fail('MANIFEST_UNAVAILABLE',`npm HTTP ${r.status}`);const p=await r.json(),m=p.ownDesktopManifest;if(p.name!==pkg.name||p.version!==v||m?.version!==v||m?.schema!==2)fail('MANIFEST_UNAVAILABLE','This version has no npm desktop manifest; update the npm manager to latest.');return m;}
|
|
97
102
|
export async function configure(keyFile){if(!keyFile)fail('KEY_FILE_REQUIRED','Provide --api-key-file');const key=fs.readFileSync(keyFile,'utf8').trim();if(!/^sk-[A-Za-z0-9_-]{10,}$/.test(key))fail('INVALID_KEY_FILE','Expected a single API key');const p=paths();return locked(p,async()=>{if(running(p).length)fail('APP_RUNNING','Quit codex-own first');rejectLinks(p.core);fs.mkdirSync(p.core,{recursive:true,mode:0o700});fs.chmodSync(p.core,0o700);
|
|
98
103
|
if(process.platform==='win32'){const sid=execFileSync('powershell.exe',['-NoProfile','-Command','[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value'],{encoding:'utf8'}).trim();execFileSync('icacls.exe',[p.core,'/inheritance:r','/grant:r',`*${sid}:(OI)(CI)F`],{stdio:'pipe'});}
|
|
99
104
|
const auth=path.join(p.core,'auth.json');rejectLinks(auth);let backup=null;if(fs.existsSync(auth)){backup=auth+'.backup-'+crypto.randomUUID();fs.copyFileSync(auth,backup,fs.constants.COPYFILE_EXCL);fs.chmodSync(backup,0o600);}const tmp=auth+'.new-'+crypto.randomUUID();exclusive(tmp,{auth_mode:'apikey',OPENAI_API_KEY:key});fs.renameSync(tmp,auth);
|
|
@@ -104,7 +109,7 @@ export async function install({version,adopt=false,archive,manifest,expectedCurr
|
|
|
104
109
|
progress('准备安装:检查版本、平台与独立目录');
|
|
105
110
|
return locked(p,async()=>{const m=manifest||await manifestFor(version||pkg.version);const a=validateManifest(m,p.platform);
|
|
106
111
|
if(expectedCurrent!==undefined&&state(p)?.version!==expectedCurrent)fail('INSTALLATION_CHANGED','Installation changed after the update was prepared; check again');
|
|
107
|
-
if(state(p)?.version===m.version&&!archive)return {ok:true,unchanged:true,version:m.version};
|
|
112
|
+
if(state(p)?.version===m.version&&!archive){if(m.runtimes)await ensureRuntime(m.runtimes,{p,report:progress});return {ok:true,unchanged:true,version:m.version};}
|
|
108
113
|
if(running(p).length)fail('APP_RUNNING','Quit codex-own before install/update');
|
|
109
114
|
const stage=fs.mkdtempSync(path.join(p.manager,'stage-'));let f=archive,transfer;
|
|
110
115
|
if(f){if(fs.statSync(f).size!==a.size||await digestFile(f)!==a.sha256)fail('CHECKSUM_MISMATCH','Local archive checksum mismatch');}
|
|
@@ -116,6 +121,7 @@ export async function install({version,adopt=false,archive,manifest,expectedCurr
|
|
|
116
121
|
progress('校验通过,正在解压桌面程序');
|
|
117
122
|
const content=path.join(stage,'unpacked');unpack(f,content);const source=path.join(content,a.entry);
|
|
118
123
|
if(process.platform==='darwin')execFileSync('codesign',['--verify','--deep','--strict',source],{stdio:'pipe'});
|
|
124
|
+
if(m.runtimes)await ensureRuntime(m.runtimes,{p,report:progress});
|
|
119
125
|
progress('正在安装到独立目录');
|
|
120
126
|
const result=switchApp({p,source,version:m.version,adopt});
|
|
121
127
|
if(process.platform==='darwin')execFileSync('/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister',['-f',p.target],{stdio:'pipe'});
|
package/lib/npm-assets.mjs
CHANGED
|
@@ -58,7 +58,7 @@ export async function assembleNpmAsset(asset, dest, cache, tar, {download = veri
|
|
|
58
58
|
const archive = path.join(scratch, 'package.tgz');
|
|
59
59
|
await download(part.url, archive, {size:part.archiveSize, sha256:part.archiveSha256}, {signal:controller.signal, report:message=>report(`[${i+1}/${asset.parts.length}] ${message}`)});
|
|
60
60
|
// Extract only the fixed payload entry, never arbitrary paths from a package tarball.
|
|
61
|
-
execFileSync(tar, ['-xf', archive, '-C',
|
|
61
|
+
execFileSync(tar, ['-xf', path.basename(archive), '-C', '.', 'package/payload.bin'], {cwd:scratch,stdio:'pipe'});
|
|
62
62
|
const payload = path.join(scratch, 'package', 'payload.bin');
|
|
63
63
|
safeCache(payload);
|
|
64
64
|
if (fs.statSync(payload).size !== part.size || await fileHash(payload) !== part.sha256)
|
package/lib/tool-env.cjs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Public environment contract v1. Only the caller's environment is changed.
|
|
3
|
+
const fs=require('node:fs'),path=require('node:path'),os=require('node:os');
|
|
4
|
+
function runtimeRoot(platform=process.platform,home=os.homedir(),env=process.env){
|
|
5
|
+
return path.join(platform==='darwin'?path.join(home,'Library','Application Support'):(env.LOCALAPPDATA||path.join(home,'AppData','Local')),'codex-own-independent','runtimes');
|
|
6
|
+
}
|
|
7
|
+
function inside(base,file){return path.resolve(file).startsWith(path.resolve(base)+path.sep);}
|
|
8
|
+
function pathEntries(r,platform=process.platform){const win=platform==='win32';return [r.shims,r.bin,win?path.join(r.directory,'python'):path.join(r.directory,'python','bin'),...(win?[path.join(r.directory,'python','Scripts')]:[]),path.join(r.root,'npm-global',...(win?[]:['bin']))];}
|
|
9
|
+
function active(base=runtimeRoot(),platform=process.platform,version){
|
|
10
|
+
const file=path.join(base,'active.json');if(!version&&!fs.existsSync(file))return null;
|
|
11
|
+
const r=version?{schema:1,version,platform:`${platform}-${process.arch}`} : JSON.parse(fs.readFileSync(file,'utf8'));
|
|
12
|
+
if(r.schema!==1||!/^node[0-9.]+-python[0-9.]+-r\d+$/.test(r.version)||r.platform!==`${platform}-${process.arch}`)throw Error('Invalid codex-own runtime receipt');
|
|
13
|
+
const dir=path.join(base,'versions',r.version),bin=platform==='win32'?path.join(dir,'node'):path.join(dir,'node','bin');
|
|
14
|
+
const python=platform==='win32'?path.join(dir,'python','python.exe'):path.join(dir,'python','bin','python3');
|
|
15
|
+
const node=path.join(bin,platform==='win32'?'node.exe':'node');
|
|
16
|
+
const npm=path.join(dir,'node',platform==='win32'?'node_modules':'lib/node_modules','npm','bin','npm-cli.js');
|
|
17
|
+
if(!inside(base,dir)||!inside(fs.realpathSync(base),fs.realpathSync(dir)))throw Error('Runtime path escapes private directory');
|
|
18
|
+
for(const f of [node,python,npm]){if(!inside(dir,f)||!inside(fs.realpathSync(dir),fs.realpathSync(f)))throw Error('Runtime executable escapes immutable version directory');}
|
|
19
|
+
return {...r,root:base,directory:dir,node,python,npm,bin,shims:path.join(dir,'shims')};
|
|
20
|
+
}
|
|
21
|
+
function environment(base=runtimeRoot(),inherited=process.env,platform=process.platform,version){
|
|
22
|
+
const r=active(base,platform,version);if(!r)return null;
|
|
23
|
+
const win=platform==='win32',separator=win?';':':',env={...inherited};
|
|
24
|
+
const key=Object.keys(env).find(k=>k.toUpperCase()==='PATH')||'PATH';
|
|
25
|
+
const tail=(env[key]||'').split(separator).filter(p=>p&&!p.includes('codex-runtimes')&&!p.startsWith(path.join(base,'versions')));
|
|
26
|
+
for(const k of Object.keys(env))if(/^(PATH|NODE_PATH|NODE_OPTIONS|PYTHONHOME|PYTHONPATH|PYTHONUSERBASE|NPM_CONFIG_.+|PIP_CONFIG_FILE)$/i.test(k))delete env[k];
|
|
27
|
+
const bins=pathEntries(r,platform);
|
|
28
|
+
Object.assign(env,{PATH:[...bins,...tail].join(separator),CODEX_OWN_RUNTIME_ROOT:base,CODEX_OWN_RUNTIME_VERSION:r.version,CODEX_OWN_NODE:r.node,CODEX_OWN_PYTHON:r.python,AGENT_WORKBENCH_NPM_CLI:r.npm,
|
|
29
|
+
NPM_CONFIG_PREFIX:path.join(base,'npm-global'),NPM_CONFIG_CACHE:path.join(base,'npm-cache'),NPM_CONFIG_USERCONFIG:path.join(base,'npmrc'),NPM_CONFIG_GLOBALCONFIG:path.join(base,'global-npmrc'),
|
|
30
|
+
PYTHONUTF8:'1',PYTHONIOENCODING:'utf-8',PYTHONPYCACHEPREFIX:path.join(base,'python-bytecode',r.version),PYTHONNOUSERSITE:'1',PYTHONUSERBASE:path.join(base,'python-user'),PIP_CACHE_DIR:path.join(base,'pip-cache'),PIP_CONFIG_FILE:win?'NUL':'/dev/null',PIP_REQUIRE_VIRTUALENV:'true'});
|
|
31
|
+
if(!win)Object.assign(env,{ZDOTDIR:path.join(r.directory,'shell'),BASH_ENV:path.join(r.directory,'shell','bash-env.sh')});
|
|
32
|
+
return env;
|
|
33
|
+
}
|
|
34
|
+
function shellFiles(base,version){
|
|
35
|
+
const r=active(base,process.platform,version),env=environment(base,{PATH:''},process.platform,version),quote=s=>"'"+s.replaceAll("'","'\"'\"'")+"'";
|
|
36
|
+
const settings=Object.entries(env).filter(([k])=>k!=='PATH').map(([k,v])=>`export ${k}=${quote(v)}`).join('\n');
|
|
37
|
+
const body='# codex-own private task shell; system and user profiles are unchanged.\n'+settings+'\nexport CODEX_HOME='+quote(path.join(base,'..','core'))+'\nexport PATH='+quote(pathEntries(r).join(':'))+':"$PATH"\nunset NODE_OPTIONS NODE_PATH PYTHONHOME PYTHONPATH OPENAI_API_KEY OPENAI_BASE_URL CHATGPT_TOKEN\nunalias node npm npx python python3 pip pip3 2>/dev/null || true\nfor own_tool in node npm npx python python3 pip pip3; do unset -f "$own_tool" 2>/dev/null || true; done\nunset own_tool\n';
|
|
38
|
+
const include='. '+quote(path.join(r.directory,'shell','bash-env.sh'))+'\n';
|
|
39
|
+
return {'bash-env.sh':body,'.zshenv':include,'.zprofile':include,'.zshrc':include,'.zlogin':include};
|
|
40
|
+
}
|
|
41
|
+
function apply(base=runtimeRoot(),env=process.env,platform=process.platform){
|
|
42
|
+
const next=environment(base,env,platform);if(!next)return false;
|
|
43
|
+
for(const k of Object.keys(env))if(!(k in next))delete env[k];Object.assign(env,next);return true;
|
|
44
|
+
}
|
|
45
|
+
module.exports={runtimeRoot,active,environment,apply,shellFiles};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import crypto from 'node:crypto';
|
|
4
|
+
import {execFileSync,spawnSync} from 'node:child_process';
|
|
5
|
+
import {createRequire} from 'node:module';
|
|
6
|
+
import {assembleNpmAsset,validateParts} from './npm-assets.mjs';
|
|
7
|
+
import {paths,locked,rejectLinks,exclusive,unpack,fail,tarExecutable,digestFile} from './manager.mjs';
|
|
8
|
+
const require=createRequire(import.meta.url);
|
|
9
|
+
export const toolEnv=require('./tool-env.cjs');
|
|
10
|
+
export function validateRuntime(m,platform){
|
|
11
|
+
if(m?.schema!==1||!/^node\d+\.\d+\.\d+-python\d+\.\d+\.\d+-r\d+$/.test(m.version))fail('INVALID_RUNTIME_MANIFEST','Invalid runtime identity');
|
|
12
|
+
const a=m.platforms?.[platform];if(!a)fail('RUNTIME_UNAVAILABLE',platform);
|
|
13
|
+
for(const name of ['node','python']){const s=a[name];if(!s||!/^[a-f0-9]{64}$/.test(s.sha256)||!Number.isSafeInteger(s.size)||s.size<1||s.size>128*1048576||!['zip','tar.gz'].includes(s.format)||!(/^[a-zA-Z0-9.+_-]+$/).test(s.entry))fail('INVALID_RUNTIME_MANIFEST','Invalid runtime asset');validateParts(s);}
|
|
14
|
+
return a;
|
|
15
|
+
}
|
|
16
|
+
function writeActive(base,r){
|
|
17
|
+
const f=path.join(base,'active.json');rejectLinks(f);
|
|
18
|
+
if(fs.existsSync(f))fs.copyFileSync(f,f+'.backup-'+crypto.randomUUID(),fs.constants.COPYFILE_EXCL);
|
|
19
|
+
const tmp=f+'.new-'+crypto.randomUUID();exclusive(tmp,r);fs.renameSync(tmp,f);
|
|
20
|
+
}
|
|
21
|
+
export function runtimeDoctor(base=toolEnv.runtimeRoot(),{version}={}){
|
|
22
|
+
try{const r=toolEnv.active(base,process.platform,version);if(!r)return {ok:false,code:'RUNTIME_NOT_INSTALLED',root:base};
|
|
23
|
+
const env=toolEnv.environment(base,process.env,process.platform,version),run=(file,args)=>execFileSync(file,args,{encoding:'utf8',env,windowsHide:true,timeout:30000}).trim();
|
|
24
|
+
return {ok:true,contract:1,version:r.version,root:base,node:{path:r.node,version:run(r.node,['--version'])},npm:{path:r.npm,version:run(r.node,[r.npm,'--version'])},python:{path:r.python,version:run(r.python,['--version']),pip:run(r.python,['-m','pip','--version'])}};
|
|
25
|
+
}catch(e){return {ok:false,code:'RUNTIME_INVALID',root:base,message:e.message};}
|
|
26
|
+
}
|
|
27
|
+
// Lock is shared with app installation. Updates keep immutable versions, so an
|
|
28
|
+
// already running app continues using its old tools until it restarts.
|
|
29
|
+
export async function ensureRuntime(m,{p=paths(),assemble=assembleNpmAsset,report=()=>{},localAssets,signal}={}){
|
|
30
|
+
const assets=validateRuntime(m,p.platform),base=path.join(p.root,'runtimes');rejectLinks(base);fs.mkdirSync(base,{recursive:true,mode:0o700});
|
|
31
|
+
const previous=toolEnv.active(base),target=path.join(base,'versions',m.version);rejectLinks(target);
|
|
32
|
+
if(previous?.version===m.version){const d=runtimeDoctor(base);if(!d.ok)fail(d.code,d.message||'Invalid private runtime');return {...d,unchanged:true};}
|
|
33
|
+
if(fs.existsSync(target))fail('RUNTIME_VERSION_EXISTS','Existing runtime version preserved; inspect runtime doctor and receipt before recovery');
|
|
34
|
+
fs.mkdirSync(path.dirname(target),{recursive:true,mode:0o700});
|
|
35
|
+
const stage=fs.mkdtempSync(path.join(base,'stage-')),candidate=path.join(stage,'candidate');fs.mkdirSync(candidate);let created=false,committed=false;
|
|
36
|
+
try{
|
|
37
|
+
for(const name of ['node','python']){
|
|
38
|
+
const a=assets[name],archive=path.join(stage,name+'.'+a.format);report(`安装独立 ${name} 运行时`);
|
|
39
|
+
if(localAssets?.[name]){if(fs.statSync(localAssets[name]).size!==a.size||await digestFile(localAssets[name])!==a.sha256)fail('CHECKSUM_MISMATCH','Local runtime checksum mismatch');fs.copyFileSync(localAssets[name],archive,fs.constants.COPYFILE_EXCL);}
|
|
40
|
+
else await assemble(a,archive,path.join(base,'npm-assets'),tarExecutable(),{report,signal});
|
|
41
|
+
const extracted=path.join(stage,name+'-unpacked');unpack(archive,extracted);
|
|
42
|
+
if(fs.readdirSync(extracted).some(n=>n!==a.entry))fail('UNSAFE_ARCHIVE','Unexpected runtime archive root');
|
|
43
|
+
fs.renameSync(path.join(extracted,a.entry),path.join(candidate,name));
|
|
44
|
+
}
|
|
45
|
+
const shims=path.join(candidate,'shims');fs.mkdirSync(shims);
|
|
46
|
+
if(process.platform==='win32'){
|
|
47
|
+
for(const name of ['python','python3','pip','pip3'])fs.writeFileSync(path.join(shims,name+'.cmd'),`@echo off\r\n"%~dp0..\\python\\python.exe" ${name.startsWith('pip')?'-m pip ':''}%*\r\n`,{flag:'wx'});
|
|
48
|
+
for(const name of ['npm','npx'])fs.writeFileSync(path.join(shims,name+'.cmd'),`@echo off\r\n"%~dp0..\\node\\node.exe" "%~dp0..\\node\\node_modules\\npm\\bin\\${name}-cli.js" %*\r\n`,{flag:'wx'});
|
|
49
|
+
}else{
|
|
50
|
+
fs.symlinkSync('../python/bin/python3',path.join(shims,'python'));fs.symlinkSync('../python/bin/python3',path.join(shims,'python3'));
|
|
51
|
+
for(const name of ['pip','pip3'])fs.writeFileSync(path.join(shims,name),'#!/bin/sh\nexec "$(dirname "$0")/../python/bin/python3" -m pip "$@"\n',{flag:'wx',mode:0o755});
|
|
52
|
+
}
|
|
53
|
+
for(const name of ['npmrc','global-npmrc']){const f=path.join(base,name);rejectLinks(f);if(!fs.existsSync(f))fs.writeFileSync(f,'# codex-own isolated npm configuration\n',{flag:'wx',mode:0o600});}
|
|
54
|
+
for(const name of ['npm-global','npm-cache','pip-cache','python-user']){rejectLinks(path.join(base,name));fs.mkdirSync(path.join(base,name),{recursive:true,mode:0o700});}
|
|
55
|
+
// Windows scanners may hold executables after execution. Never rename an
|
|
56
|
+
// executed tool directory: copy to a fresh immutable final path, probe there,
|
|
57
|
+
// and only then atomically switch the small active receipt.
|
|
58
|
+
fs.mkdirSync(target);created=true;fs.cpSync(candidate,target,{recursive:true,force:false,errorOnExist:true,verbatimSymlinks:true});
|
|
59
|
+
if(process.platform==='darwin'){const shell=path.join(target,'shell');fs.mkdirSync(shell);for(const [name,body]of Object.entries(toolEnv.shellFiles(base,m.version)))fs.writeFileSync(path.join(shell,name),body,{flag:'wx',mode:0o600});}
|
|
60
|
+
const tested=runtimeDoctor(base,{version:m.version});if(!tested.ok)fail('RUNTIME_PROBE_FAILED',tested.message||'Tool verification failed');
|
|
61
|
+
const expected=m.version.match(/^node([0-9.]+)-python([0-9.]+)-/);
|
|
62
|
+
if(tested.node.version!=='v'+expected[1]||tested.python.version!=='Python '+expected[2])fail('RUNTIME_VERSION_MISMATCH','Runtime executable versions do not match manifest');
|
|
63
|
+
if(signal?.aborted)fail('CANCELLED','Runtime installation cancelled');
|
|
64
|
+
exclusive(path.join(target,'codex-own-runtime.json'),{schema:1,version:m.version,platform:p.platform,assets:{node:assets.node.sha256,python:assets.python.sha256},verified:tested});
|
|
65
|
+
writeActive(base,{schema:1,version:m.version,platform:p.platform,previous:previous?.version||null,installedAt:new Date().toISOString()});
|
|
66
|
+
committed=true;
|
|
67
|
+
return runtimeDoctor(base);
|
|
68
|
+
}finally{for(const f of [stage,...(created&&!committed?[target]:[])])try{fs.rmSync(f,{recursive:true,force:true,maxRetries:10,retryDelay:200});}catch{report(`临时目录被系统占用,已保留:${f}`);}}
|
|
69
|
+
}
|
|
70
|
+
export async function installRuntime(m,options={}){const p=options.p||paths();return locked(p,()=>ensureRuntime(m,{...options,p}));}
|
|
71
|
+
export async function rollbackRuntime({p=paths()}={}){return locked(p,async()=>{
|
|
72
|
+
const base=path.join(p.root,'runtimes'),r=toolEnv.active(base);if(!r?.previous)fail('NO_RUNTIME_ROLLBACK','No previous runtime');
|
|
73
|
+
const f=path.join(base,'versions',r.previous,'codex-own-runtime.json');rejectLinks(f);const old=JSON.parse(fs.readFileSync(f));
|
|
74
|
+
if(old.version!==r.previous||old.platform!==p.platform)fail('INVALID_RUNTIME_RECEIPT','Previous runtime does not match');
|
|
75
|
+
const checked=runtimeDoctor(base,{version:r.previous});if(!checked.ok)fail('RUNTIME_INVALID','Previous runtime verification failed; active tools preserved');
|
|
76
|
+
writeActive(base,{schema:1,version:r.previous,platform:p.platform,previous:r.version,installedAt:new Date().toISOString()});return runtimeDoctor(base);
|
|
77
|
+
});}
|
|
78
|
+
export function runRuntime(args){if(!args.length)fail('COMMAND_REQUIRED','runtime run -- <node|npm|npx|python|python3|pip> [args]');const base=toolEnv.runtimeRoot(),r=toolEnv.active(base);if(!r)fail('RUNTIME_NOT_INSTALLED','Install codex-own runtime first');
|
|
79
|
+
const [name,...rest]=args;const command=name==='node'?{file:r.node,args:rest}:['npm','npx'].includes(name)?{file:r.node,args:[name==='npm'?r.npm:path.join(path.dirname(r.npm),'npx-cli.js'),...rest]}:['python','python3','pip'].includes(name)?{file:r.python,args:[...(name==='pip'?['-m','pip']:[]),...rest]}:null;
|
|
80
|
+
if(!command)fail('INVALID_COMMAND','Supported tools: node, npm, npx, python, python3, pip');
|
|
81
|
+
const out=spawnSync(command.file,command.args,{env:toolEnv.environment(base),stdio:'inherit',windowsHide:true});if(out.error)throw out.error;return out.status??1;
|
|
82
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@petercjl/codex-own",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Independent codex-own desktop installation and update manager",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -44,13 +44,13 @@
|
|
|
44
44
|
"ownDesktopManifest": {
|
|
45
45
|
"schema": 2,
|
|
46
46
|
"repository": "petercjl/codex-own",
|
|
47
|
-
"version": "0.
|
|
47
|
+
"version": "0.5.1",
|
|
48
48
|
"platforms": {
|
|
49
49
|
"darwin-arm64": {
|
|
50
50
|
"entry": "codex-own.app",
|
|
51
51
|
"transport": "canonical-tar-cdc-v1",
|
|
52
|
-
"size":
|
|
53
|
-
"sha256": "
|
|
52
|
+
"size": 2045519872,
|
|
53
|
+
"sha256": "6ceef71b166b31dfe8295258c336bb2dddd01cbf7cbd6355de5c16178cd2749d",
|
|
54
54
|
"parts": [
|
|
55
55
|
{
|
|
56
56
|
"sha256": "f7950fe492a347a0e74528f4f73472052fc43d5155f32f92481fc96c3cc6ce95",
|
|
@@ -88,11 +88,11 @@
|
|
|
88
88
|
"archiveSha256": "1697a11a56260838efd2bb2f0d95767540c7154ad85c274f86b23a1baddf8d7c"
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
|
-
"sha256": "
|
|
91
|
+
"sha256": "61f22cc033b97a745f8afd40e750591cf00df08a9454c54ca924e89061eef41f",
|
|
92
92
|
"size": 46558388,
|
|
93
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
94
|
-
"archiveSize":
|
|
95
|
-
"archiveSha256": "
|
|
93
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h61f22cc033b97a745f8afd40e750591cf00df08a9454c54ca924e89061eef41f.tgz",
|
|
94
|
+
"archiveSize": 13975144,
|
|
95
|
+
"archiveSha256": "acf70e99c7cea6c10007035aa7d8509457b7cc73d9378f5f5dc7ae42152726d0"
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
"sha256": "e09427abf6b00a3719b916121a734361209e637eefe8dff4ee5736dde2ac8751",
|
|
@@ -116,18 +116,18 @@
|
|
|
116
116
|
"archiveSha256": "25db0027db503c12230d346ec500d01ba53880069164eeb0020da829dcff6c8f"
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
|
-
"sha256": "
|
|
119
|
+
"sha256": "d30e0f5e5bdd6a27a5f8d12a3272a94aaa47dccae8b58036dc3b162dac4b7e61",
|
|
120
120
|
"size": 26327040,
|
|
121
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
122
|
-
"archiveSize":
|
|
123
|
-
"archiveSha256": "
|
|
121
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hd30e0f5e5bdd6a27a5f8d12a3272a94aaa47dccae8b58036dc3b162dac4b7e61.tgz",
|
|
122
|
+
"archiveSize": 8466868,
|
|
123
|
+
"archiveSha256": "5e19777e583abc273553db5c8c9808b098085cc2ec319ae5cd8def73bd923f24"
|
|
124
124
|
},
|
|
125
125
|
{
|
|
126
|
-
"sha256": "
|
|
127
|
-
"size":
|
|
128
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
129
|
-
"archiveSize":
|
|
130
|
-
"archiveSha256": "
|
|
126
|
+
"sha256": "9b44de3ecc70850eccbb992540cfd1b9b14ab2bfa042bbee072bcbebbe7a1338",
|
|
127
|
+
"size": 20033661,
|
|
128
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h9b44de3ecc70850eccbb992540cfd1b9b14ab2bfa042bbee072bcbebbe7a1338.tgz",
|
|
129
|
+
"archiveSize": 5138668,
|
|
130
|
+
"archiveSha256": "9149d9c8394d1cb9770861460b52815481409a9cd39c935cbf3497171b858128"
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
"sha256": "432172d98e9f5fb2d7a7e41036c0d36f3c405203e2e612c0706ec2440bd50044",
|
|
@@ -207,11 +207,11 @@
|
|
|
207
207
|
"archiveSha256": "4193df135e7180f6fc32a0fd9fa1cef6b1ee90e3bfd437cf9d7a7c2c82a23310"
|
|
208
208
|
},
|
|
209
209
|
{
|
|
210
|
-
"sha256": "
|
|
211
|
-
"size":
|
|
212
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
213
|
-
"archiveSize":
|
|
214
|
-
"archiveSha256": "
|
|
210
|
+
"sha256": "ff1233b968d63b1329b76402e82b689f0d0a46f1f6127107a1a05b181163118e",
|
|
211
|
+
"size": 5769319,
|
|
212
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hff1233b968d63b1329b76402e82b689f0d0a46f1f6127107a1a05b181163118e.tgz",
|
|
213
|
+
"archiveSize": 4533434,
|
|
214
|
+
"archiveSha256": "6be6ad10c5bc084261686bb6f498abbd0fa637180d933b9a5a8c3af5a66a2b8d"
|
|
215
215
|
},
|
|
216
216
|
{
|
|
217
217
|
"sha256": "2c7b16b63b93ce10c381c512543fadd21e65ec8b5b499e68cf7e6b9905e4ef09",
|
|
@@ -382,11 +382,11 @@
|
|
|
382
382
|
"archiveSha256": "7cdf4ba6de25f51905fac22b7079c52464a4c06b4a9bb39af20121f29e1261a2"
|
|
383
383
|
},
|
|
384
384
|
{
|
|
385
|
-
"sha256": "
|
|
386
|
-
"size":
|
|
387
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
388
|
-
"archiveSize":
|
|
389
|
-
"archiveSha256": "
|
|
385
|
+
"sha256": "bf0ecb90c4a398ce1bf67b04c2cd43a1b21e8c995f0ebf6b2790187b9c9a7edd",
|
|
386
|
+
"size": 59472896,
|
|
387
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hbf0ecb90c4a398ce1bf67b04c2cd43a1b21e8c995f0ebf6b2790187b9c9a7edd.tgz",
|
|
388
|
+
"archiveSize": 26339649,
|
|
389
|
+
"archiveSha256": "281d76c73c4e3326535729045ad0198905d92ef38c7e2b2b984c7b7350af6b6e"
|
|
390
390
|
},
|
|
391
391
|
{
|
|
392
392
|
"sha256": "7160a34ddbb6db8a2296686a530bb99f78cb8803027cbb32fb76aa9ed2222355",
|
|
@@ -403,11 +403,11 @@
|
|
|
403
403
|
"archiveSha256": "783256484f3f6dfc99561fe6680100f457b5acf0e845a8824a9b8a94c6518b1e"
|
|
404
404
|
},
|
|
405
405
|
{
|
|
406
|
-
"sha256": "
|
|
407
|
-
"size":
|
|
408
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
409
|
-
"archiveSize":
|
|
410
|
-
"archiveSha256": "
|
|
406
|
+
"sha256": "3ab3b4e037c73a5c8372185f95e53cfa3d896b0e0ad83f22e0ba03930a6c6a12",
|
|
407
|
+
"size": 35849613,
|
|
408
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h3ab3b4e037c73a5c8372185f95e53cfa3d896b0e0ad83f22e0ba03930a6c6a12.tgz",
|
|
409
|
+
"archiveSize": 29376983,
|
|
410
|
+
"archiveSha256": "238a4fa5b80e3a066b6e4ad279e7345e6e5f2b6b8fa9f9b479b01285a3405bad"
|
|
411
411
|
},
|
|
412
412
|
{
|
|
413
413
|
"sha256": "20604d70f3b62c4f011cc6fcf2215c5b21005cf31ff27e7e8c0a31af21c46c37",
|
|
@@ -431,19 +431,19 @@
|
|
|
431
431
|
"archiveSha256": "988c7e1746e5237643195824ef5f1193e03998135de90a5ae0c33e105b450f5f"
|
|
432
432
|
},
|
|
433
433
|
{
|
|
434
|
-
"sha256": "
|
|
435
|
-
"size":
|
|
436
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
437
|
-
"archiveSize":
|
|
438
|
-
"archiveSha256": "
|
|
434
|
+
"sha256": "2cb194bbeda7df041b482386d4c61d512994b84dc4baa76df73985942cff7366",
|
|
435
|
+
"size": 1766400,
|
|
436
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h2cb194bbeda7df041b482386d4c61d512994b84dc4baa76df73985942cff7366.tgz",
|
|
437
|
+
"archiveSize": 355805,
|
|
438
|
+
"archiveSha256": "9b5d0900872c202813608df4e3558a82b14eafa28bde964fdf488cea8d7539b7"
|
|
439
439
|
}
|
|
440
440
|
]
|
|
441
441
|
},
|
|
442
442
|
"win32-x64": {
|
|
443
443
|
"entry": "app",
|
|
444
444
|
"transport": "canonical-tar-cdc-v1",
|
|
445
|
-
"size":
|
|
446
|
-
"sha256": "
|
|
445
|
+
"size": 2424552960,
|
|
446
|
+
"sha256": "eaef194c566bdf33238cc85fcca3ac88924efac107d85acbed92cb7c28625f65",
|
|
447
447
|
"parts": [
|
|
448
448
|
{
|
|
449
449
|
"sha256": "75e7eeb9ec280f24305ca34c3a22539c26616b4fb74cb89ac5436ed62390d31d",
|
|
@@ -516,11 +516,11 @@
|
|
|
516
516
|
"archiveSha256": "00624b63deb580eaa1f50528d963c34871c5d650bc704fed498dbedb44a832a4"
|
|
517
517
|
},
|
|
518
518
|
{
|
|
519
|
-
"sha256": "
|
|
519
|
+
"sha256": "94c67bc06de1d41fc2ef15a8f13084070637c48afa45b88f65d5338e3a4733ed",
|
|
520
520
|
"size": 23890432,
|
|
521
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
522
|
-
"archiveSize":
|
|
523
|
-
"archiveSha256": "
|
|
521
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h94c67bc06de1d41fc2ef15a8f13084070637c48afa45b88f65d5338e3a4733ed.tgz",
|
|
522
|
+
"archiveSize": 11339437,
|
|
523
|
+
"archiveSha256": "5306b9fa30dde73a6a6c376da4d62b42c4586798d18d3a51103b981c0098b77d"
|
|
524
524
|
},
|
|
525
525
|
{
|
|
526
526
|
"sha256": "723a5e60c1066bd5ba6e387fae972124a6f8f1726d7ba1bdb273aa620b62726f",
|
|
@@ -551,11 +551,11 @@
|
|
|
551
551
|
"archiveSha256": "893d020e3aa46399d3f91f0212b66a47c42e7a03bc1072b76dbe22224d00b9f7"
|
|
552
552
|
},
|
|
553
553
|
{
|
|
554
|
-
"sha256": "
|
|
555
|
-
"size":
|
|
556
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
557
|
-
"archiveSize":
|
|
558
|
-
"archiveSha256": "
|
|
554
|
+
"sha256": "007c6c48ecb83a528c06de0e5686f9e406fb78c714c6e513cbc19184df6bf825",
|
|
555
|
+
"size": 24784186,
|
|
556
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h007c6c48ecb83a528c06de0e5686f9e406fb78c714c6e513cbc19184df6bf825.tgz",
|
|
557
|
+
"archiveSize": 6289351,
|
|
558
|
+
"archiveSha256": "10d50695aad87cff4305ab9e0455b726e2467a662d3f50b3f362c7d372f95c1f"
|
|
559
559
|
},
|
|
560
560
|
{
|
|
561
561
|
"sha256": "8209fa7ff4208fabdc6143ddce15132d60abdfe5123505704b70c2bcb9be6394",
|
|
@@ -635,11 +635,11 @@
|
|
|
635
635
|
"archiveSha256": "08144618dc5dafba20b37e708ff2b11950486eb02666b31bbf7c28398855edf6"
|
|
636
636
|
},
|
|
637
637
|
{
|
|
638
|
-
"sha256": "
|
|
639
|
-
"size":
|
|
640
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
641
|
-
"archiveSize":
|
|
642
|
-
"archiveSha256": "
|
|
638
|
+
"sha256": "d47efa1bc6aed426cb5cca7d0c5395843d9ebe99597d9382135f8afbfe5e554a",
|
|
639
|
+
"size": 5769008,
|
|
640
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hd47efa1bc6aed426cb5cca7d0c5395843d9ebe99597d9382135f8afbfe5e554a.tgz",
|
|
641
|
+
"archiveSize": 4533424,
|
|
642
|
+
"archiveSha256": "62b5013f5b29776fe699f6e0cf6465cadbae965ec03a702b8481bc719a983f90"
|
|
643
643
|
},
|
|
644
644
|
{
|
|
645
645
|
"sha256": "641ba77a852ed34cc497714672d9d26250796f736f4df1a6b5ca196c6d7c9bfa",
|
|
@@ -859,11 +859,11 @@
|
|
|
859
859
|
"archiveSha256": "eb3f18bd55a152598f8d6b8325f21c3e2e6f82f937c5e8f29d2b7d5c758f075a"
|
|
860
860
|
},
|
|
861
861
|
{
|
|
862
|
-
"sha256": "
|
|
863
|
-
"size":
|
|
864
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
865
|
-
"archiveSize":
|
|
866
|
-
"archiveSha256": "
|
|
862
|
+
"sha256": "b2593d5d8c1e3fdb53ef446121af11f261cdc4cf8605868a9ae348e34df4bcef",
|
|
863
|
+
"size": 5942272,
|
|
864
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hb2593d5d8c1e3fdb53ef446121af11f261cdc4cf8605868a9ae348e34df4bcef.tgz",
|
|
865
|
+
"archiveSize": 2001323,
|
|
866
|
+
"archiveSha256": "b11a13e8cb1bba05f78908f9026247a83c623c422672a4153ab91decbcd6d0b6"
|
|
867
867
|
},
|
|
868
868
|
{
|
|
869
869
|
"sha256": "6d72766b19ebd5e4aae33b6d57b22f07b10cb83bc080f7596bfdd834675dfbc6",
|
|
@@ -887,11 +887,11 @@
|
|
|
887
887
|
"archiveSha256": "39f25e55411d144f5cea0f7b1842f48eabc3de2983ce26bd8d2e19175abbd312"
|
|
888
888
|
},
|
|
889
889
|
{
|
|
890
|
-
"sha256": "
|
|
891
|
-
"size":
|
|
892
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
893
|
-
"archiveSize":
|
|
894
|
-
"archiveSha256": "
|
|
890
|
+
"sha256": "40de87acec8f30d6a282b5d7d90f7c9afa8314fe936e456340eb21372d700510",
|
|
891
|
+
"size": 34148749,
|
|
892
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h40de87acec8f30d6a282b5d7d90f7c9afa8314fe936e456340eb21372d700510.tgz",
|
|
893
|
+
"archiveSize": 27842671,
|
|
894
|
+
"archiveSha256": "c89125ab38d07a4857e544bbdaf051cae32eab0126c1185b47d5c8aabdae5e37"
|
|
895
895
|
},
|
|
896
896
|
{
|
|
897
897
|
"sha256": "e80bff562bb79507e555d21bac0d844f17994b47b5bad12409a0046df9de72cd",
|
|
@@ -934,17 +934,106 @@
|
|
|
934
934
|
"provenance": {
|
|
935
935
|
"darwin-arm64": {
|
|
936
936
|
"kind": "verified-own-overlay-upgrade",
|
|
937
|
-
"sourceVersion": "0.
|
|
937
|
+
"sourceVersion": "0.5.0",
|
|
938
938
|
"upgradeNpmUpdater": true,
|
|
939
|
-
"
|
|
940
|
-
"windowsIcon": "windows-blue-w"
|
|
939
|
+
"firstToolBootstrap": "automatic-relaunch"
|
|
941
940
|
},
|
|
942
941
|
"win32-x64": {
|
|
943
942
|
"kind": "verified-own-overlay-upgrade",
|
|
944
|
-
"sourceVersion": "0.
|
|
943
|
+
"sourceVersion": "0.5.0",
|
|
945
944
|
"upgradeNpmUpdater": true,
|
|
946
|
-
"
|
|
947
|
-
|
|
945
|
+
"firstToolBootstrap": "automatic-relaunch"
|
|
946
|
+
}
|
|
947
|
+
},
|
|
948
|
+
"runtimes": {
|
|
949
|
+
"schema": 1,
|
|
950
|
+
"version": "node24.22.0-python3.12.15-r1",
|
|
951
|
+
"platforms": {
|
|
952
|
+
"darwin-arm64": {
|
|
953
|
+
"node": {
|
|
954
|
+
"entry": "node-v24.22.0-darwin-arm64",
|
|
955
|
+
"format": "tar.gz",
|
|
956
|
+
"size": 53049576,
|
|
957
|
+
"sha256": "6a9724d9b50a5f22b4816cded441b5a8d9ddae546191a5e5b7efa5a5e2ee26d5",
|
|
958
|
+
"parts": [
|
|
959
|
+
{
|
|
960
|
+
"sha256": "949aea7a152b116e84670a7b771614bcea487f587a581e0d1a120928e9ab0221",
|
|
961
|
+
"size": 33554432,
|
|
962
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h949aea7a152b116e84670a7b771614bcea487f587a581e0d1a120928e9ab0221.tgz",
|
|
963
|
+
"archiveSize": 33512749,
|
|
964
|
+
"archiveSha256": "5f3bbf063aa3d82e32ba0499e46123822d7148542101aee2d019929190c196c2"
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
"sha256": "4cac86c2c3bad12d3402c7cd52ce002dcf222ebb3db964d1cbc5042b433aab59",
|
|
968
|
+
"size": 19495144,
|
|
969
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h4cac86c2c3bad12d3402c7cd52ce002dcf222ebb3db964d1cbc5042b433aab59.tgz",
|
|
970
|
+
"archiveSize": 19133414,
|
|
971
|
+
"archiveSha256": "643fb96788aef65d2a7adb81e1df6e55d963364b34837e152167282843818172"
|
|
972
|
+
}
|
|
973
|
+
]
|
|
974
|
+
},
|
|
975
|
+
"python": {
|
|
976
|
+
"entry": "python",
|
|
977
|
+
"format": "tar.gz",
|
|
978
|
+
"size": 25180390,
|
|
979
|
+
"sha256": "ba32036ad8f4c434d97a1ee7feef8b7edc0fac16777639b97e39c74a108e4440",
|
|
980
|
+
"parts": [
|
|
981
|
+
{
|
|
982
|
+
"sha256": "ba32036ad8f4c434d97a1ee7feef8b7edc0fac16777639b97e39c74a108e4440",
|
|
983
|
+
"size": 25180390,
|
|
984
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hba32036ad8f4c434d97a1ee7feef8b7edc0fac16777639b97e39c74a108e4440.tgz",
|
|
985
|
+
"archiveSize": 25107923,
|
|
986
|
+
"archiveSha256": "503f5667f2d6fa6950438764f0ac29e413e3080bfcfe83b295b6c74c2c15163e"
|
|
987
|
+
}
|
|
988
|
+
]
|
|
989
|
+
}
|
|
990
|
+
},
|
|
991
|
+
"win32-x64": {
|
|
992
|
+
"node": {
|
|
993
|
+
"entry": "node-v24.22.0-win-x64",
|
|
994
|
+
"format": "zip",
|
|
995
|
+
"size": 37733703,
|
|
996
|
+
"sha256": "f9683a19877e12a9b167305c8db71040d812876359de21f0d2e97c3f321f80c3",
|
|
997
|
+
"parts": [
|
|
998
|
+
{
|
|
999
|
+
"sha256": "94c14ce1eeda03b3b96bd4ea01346bf43b21e70efbc5b25adaba94fda2b85906",
|
|
1000
|
+
"size": 33554432,
|
|
1001
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h94c14ce1eeda03b3b96bd4ea01346bf43b21e70efbc5b25adaba94fda2b85906.tgz",
|
|
1002
|
+
"archiveSize": 33182230,
|
|
1003
|
+
"archiveSha256": "72c783c0db418be6745f13f1c824b00314eec2d534c9b1913cc58b6c0524a9ce"
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
"sha256": "84cf2122a4133990d5f24187fecab4e1c8137bc71b37e6289cbf3aa68118839d",
|
|
1007
|
+
"size": 4179271,
|
|
1008
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h84cf2122a4133990d5f24187fecab4e1c8137bc71b37e6289cbf3aa68118839d.tgz",
|
|
1009
|
+
"archiveSize": 3550650,
|
|
1010
|
+
"archiveSha256": "93768d0020e6ab5be47b5c841bcba0e4d3feebbcc5b07e2378309239d1a3e186"
|
|
1011
|
+
}
|
|
1012
|
+
]
|
|
1013
|
+
},
|
|
1014
|
+
"python": {
|
|
1015
|
+
"entry": "python",
|
|
1016
|
+
"format": "tar.gz",
|
|
1017
|
+
"size": 46390009,
|
|
1018
|
+
"sha256": "bbc902d4d187ac4914915bf538196a064b49109a33a104965b5164ced5b80a1e",
|
|
1019
|
+
"parts": [
|
|
1020
|
+
{
|
|
1021
|
+
"sha256": "69b8bc6e8da423ec63f0b80af3c43a1c10efad679fa3a6c875bf33f0373ab201",
|
|
1022
|
+
"size": 33554432,
|
|
1023
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h69b8bc6e8da423ec63f0b80af3c43a1c10efad679fa3a6c875bf33f0373ab201.tgz",
|
|
1024
|
+
"archiveSize": 33403996,
|
|
1025
|
+
"archiveSha256": "2b124ed954113cd681b37e442539c6cc8daee7e2a96724c76e94b86418da7e4d"
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
"sha256": "94972a77f8080d4b9e5094d5ac42a1e3d7cfce1c7b2dcd804b43e02f4133d885",
|
|
1029
|
+
"size": 12835577,
|
|
1030
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h94972a77f8080d4b9e5094d5ac42a1e3d7cfce1c7b2dcd804b43e02f4133d885.tgz",
|
|
1031
|
+
"archiveSize": 12811675,
|
|
1032
|
+
"archiveSha256": "38cffc9d4a50f51d0dc333aca4e7065f12721a200bfc20f5e01ac24e44ae9e2d"
|
|
1033
|
+
}
|
|
1034
|
+
]
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
948
1037
|
}
|
|
949
1038
|
}
|
|
950
1039
|
}
|
package/release.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 2,
|
|
3
3
|
"repository": "petercjl/codex-own",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"platforms": {
|
|
6
6
|
"darwin-arm64": {
|
|
7
7
|
"entry": "codex-own.app",
|
|
8
8
|
"transport": "canonical-tar-cdc-v1",
|
|
9
|
-
"size":
|
|
10
|
-
"sha256": "
|
|
9
|
+
"size": 2045519872,
|
|
10
|
+
"sha256": "6ceef71b166b31dfe8295258c336bb2dddd01cbf7cbd6355de5c16178cd2749d",
|
|
11
11
|
"parts": [
|
|
12
12
|
{
|
|
13
13
|
"sha256": "f7950fe492a347a0e74528f4f73472052fc43d5155f32f92481fc96c3cc6ce95",
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
"archiveSha256": "1697a11a56260838efd2bb2f0d95767540c7154ad85c274f86b23a1baddf8d7c"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
|
-
"sha256": "
|
|
48
|
+
"sha256": "61f22cc033b97a745f8afd40e750591cf00df08a9454c54ca924e89061eef41f",
|
|
49
49
|
"size": 46558388,
|
|
50
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
51
|
-
"archiveSize":
|
|
52
|
-
"archiveSha256": "
|
|
50
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h61f22cc033b97a745f8afd40e750591cf00df08a9454c54ca924e89061eef41f.tgz",
|
|
51
|
+
"archiveSize": 13975144,
|
|
52
|
+
"archiveSha256": "acf70e99c7cea6c10007035aa7d8509457b7cc73d9378f5f5dc7ae42152726d0"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"sha256": "e09427abf6b00a3719b916121a734361209e637eefe8dff4ee5736dde2ac8751",
|
|
@@ -73,18 +73,18 @@
|
|
|
73
73
|
"archiveSha256": "25db0027db503c12230d346ec500d01ba53880069164eeb0020da829dcff6c8f"
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
|
-
"sha256": "
|
|
76
|
+
"sha256": "d30e0f5e5bdd6a27a5f8d12a3272a94aaa47dccae8b58036dc3b162dac4b7e61",
|
|
77
77
|
"size": 26327040,
|
|
78
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
79
|
-
"archiveSize":
|
|
80
|
-
"archiveSha256": "
|
|
78
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hd30e0f5e5bdd6a27a5f8d12a3272a94aaa47dccae8b58036dc3b162dac4b7e61.tgz",
|
|
79
|
+
"archiveSize": 8466868,
|
|
80
|
+
"archiveSha256": "5e19777e583abc273553db5c8c9808b098085cc2ec319ae5cd8def73bd923f24"
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
|
-
"sha256": "
|
|
84
|
-
"size":
|
|
85
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
86
|
-
"archiveSize":
|
|
87
|
-
"archiveSha256": "
|
|
83
|
+
"sha256": "9b44de3ecc70850eccbb992540cfd1b9b14ab2bfa042bbee072bcbebbe7a1338",
|
|
84
|
+
"size": 20033661,
|
|
85
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h9b44de3ecc70850eccbb992540cfd1b9b14ab2bfa042bbee072bcbebbe7a1338.tgz",
|
|
86
|
+
"archiveSize": 5138668,
|
|
87
|
+
"archiveSha256": "9149d9c8394d1cb9770861460b52815481409a9cd39c935cbf3497171b858128"
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
"sha256": "432172d98e9f5fb2d7a7e41036c0d36f3c405203e2e612c0706ec2440bd50044",
|
|
@@ -164,11 +164,11 @@
|
|
|
164
164
|
"archiveSha256": "4193df135e7180f6fc32a0fd9fa1cef6b1ee90e3bfd437cf9d7a7c2c82a23310"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
|
-
"sha256": "
|
|
168
|
-
"size":
|
|
169
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
170
|
-
"archiveSize":
|
|
171
|
-
"archiveSha256": "
|
|
167
|
+
"sha256": "ff1233b968d63b1329b76402e82b689f0d0a46f1f6127107a1a05b181163118e",
|
|
168
|
+
"size": 5769319,
|
|
169
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hff1233b968d63b1329b76402e82b689f0d0a46f1f6127107a1a05b181163118e.tgz",
|
|
170
|
+
"archiveSize": 4533434,
|
|
171
|
+
"archiveSha256": "6be6ad10c5bc084261686bb6f498abbd0fa637180d933b9a5a8c3af5a66a2b8d"
|
|
172
172
|
},
|
|
173
173
|
{
|
|
174
174
|
"sha256": "2c7b16b63b93ce10c381c512543fadd21e65ec8b5b499e68cf7e6b9905e4ef09",
|
|
@@ -339,11 +339,11 @@
|
|
|
339
339
|
"archiveSha256": "7cdf4ba6de25f51905fac22b7079c52464a4c06b4a9bb39af20121f29e1261a2"
|
|
340
340
|
},
|
|
341
341
|
{
|
|
342
|
-
"sha256": "
|
|
343
|
-
"size":
|
|
344
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
345
|
-
"archiveSize":
|
|
346
|
-
"archiveSha256": "
|
|
342
|
+
"sha256": "bf0ecb90c4a398ce1bf67b04c2cd43a1b21e8c995f0ebf6b2790187b9c9a7edd",
|
|
343
|
+
"size": 59472896,
|
|
344
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hbf0ecb90c4a398ce1bf67b04c2cd43a1b21e8c995f0ebf6b2790187b9c9a7edd.tgz",
|
|
345
|
+
"archiveSize": 26339649,
|
|
346
|
+
"archiveSha256": "281d76c73c4e3326535729045ad0198905d92ef38c7e2b2b984c7b7350af6b6e"
|
|
347
347
|
},
|
|
348
348
|
{
|
|
349
349
|
"sha256": "7160a34ddbb6db8a2296686a530bb99f78cb8803027cbb32fb76aa9ed2222355",
|
|
@@ -360,11 +360,11 @@
|
|
|
360
360
|
"archiveSha256": "783256484f3f6dfc99561fe6680100f457b5acf0e845a8824a9b8a94c6518b1e"
|
|
361
361
|
},
|
|
362
362
|
{
|
|
363
|
-
"sha256": "
|
|
364
|
-
"size":
|
|
365
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
366
|
-
"archiveSize":
|
|
367
|
-
"archiveSha256": "
|
|
363
|
+
"sha256": "3ab3b4e037c73a5c8372185f95e53cfa3d896b0e0ad83f22e0ba03930a6c6a12",
|
|
364
|
+
"size": 35849613,
|
|
365
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h3ab3b4e037c73a5c8372185f95e53cfa3d896b0e0ad83f22e0ba03930a6c6a12.tgz",
|
|
366
|
+
"archiveSize": 29376983,
|
|
367
|
+
"archiveSha256": "238a4fa5b80e3a066b6e4ad279e7345e6e5f2b6b8fa9f9b479b01285a3405bad"
|
|
368
368
|
},
|
|
369
369
|
{
|
|
370
370
|
"sha256": "20604d70f3b62c4f011cc6fcf2215c5b21005cf31ff27e7e8c0a31af21c46c37",
|
|
@@ -388,19 +388,19 @@
|
|
|
388
388
|
"archiveSha256": "988c7e1746e5237643195824ef5f1193e03998135de90a5ae0c33e105b450f5f"
|
|
389
389
|
},
|
|
390
390
|
{
|
|
391
|
-
"sha256": "
|
|
392
|
-
"size":
|
|
393
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
394
|
-
"archiveSize":
|
|
395
|
-
"archiveSha256": "
|
|
391
|
+
"sha256": "2cb194bbeda7df041b482386d4c61d512994b84dc4baa76df73985942cff7366",
|
|
392
|
+
"size": 1766400,
|
|
393
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h2cb194bbeda7df041b482386d4c61d512994b84dc4baa76df73985942cff7366.tgz",
|
|
394
|
+
"archiveSize": 355805,
|
|
395
|
+
"archiveSha256": "9b5d0900872c202813608df4e3558a82b14eafa28bde964fdf488cea8d7539b7"
|
|
396
396
|
}
|
|
397
397
|
]
|
|
398
398
|
},
|
|
399
399
|
"win32-x64": {
|
|
400
400
|
"entry": "app",
|
|
401
401
|
"transport": "canonical-tar-cdc-v1",
|
|
402
|
-
"size":
|
|
403
|
-
"sha256": "
|
|
402
|
+
"size": 2424552960,
|
|
403
|
+
"sha256": "eaef194c566bdf33238cc85fcca3ac88924efac107d85acbed92cb7c28625f65",
|
|
404
404
|
"parts": [
|
|
405
405
|
{
|
|
406
406
|
"sha256": "75e7eeb9ec280f24305ca34c3a22539c26616b4fb74cb89ac5436ed62390d31d",
|
|
@@ -473,11 +473,11 @@
|
|
|
473
473
|
"archiveSha256": "00624b63deb580eaa1f50528d963c34871c5d650bc704fed498dbedb44a832a4"
|
|
474
474
|
},
|
|
475
475
|
{
|
|
476
|
-
"sha256": "
|
|
476
|
+
"sha256": "94c67bc06de1d41fc2ef15a8f13084070637c48afa45b88f65d5338e3a4733ed",
|
|
477
477
|
"size": 23890432,
|
|
478
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
479
|
-
"archiveSize":
|
|
480
|
-
"archiveSha256": "
|
|
478
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h94c67bc06de1d41fc2ef15a8f13084070637c48afa45b88f65d5338e3a4733ed.tgz",
|
|
479
|
+
"archiveSize": 11339437,
|
|
480
|
+
"archiveSha256": "5306b9fa30dde73a6a6c376da4d62b42c4586798d18d3a51103b981c0098b77d"
|
|
481
481
|
},
|
|
482
482
|
{
|
|
483
483
|
"sha256": "723a5e60c1066bd5ba6e387fae972124a6f8f1726d7ba1bdb273aa620b62726f",
|
|
@@ -508,11 +508,11 @@
|
|
|
508
508
|
"archiveSha256": "893d020e3aa46399d3f91f0212b66a47c42e7a03bc1072b76dbe22224d00b9f7"
|
|
509
509
|
},
|
|
510
510
|
{
|
|
511
|
-
"sha256": "
|
|
512
|
-
"size":
|
|
513
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
514
|
-
"archiveSize":
|
|
515
|
-
"archiveSha256": "
|
|
511
|
+
"sha256": "007c6c48ecb83a528c06de0e5686f9e406fb78c714c6e513cbc19184df6bf825",
|
|
512
|
+
"size": 24784186,
|
|
513
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h007c6c48ecb83a528c06de0e5686f9e406fb78c714c6e513cbc19184df6bf825.tgz",
|
|
514
|
+
"archiveSize": 6289351,
|
|
515
|
+
"archiveSha256": "10d50695aad87cff4305ab9e0455b726e2467a662d3f50b3f362c7d372f95c1f"
|
|
516
516
|
},
|
|
517
517
|
{
|
|
518
518
|
"sha256": "8209fa7ff4208fabdc6143ddce15132d60abdfe5123505704b70c2bcb9be6394",
|
|
@@ -592,11 +592,11 @@
|
|
|
592
592
|
"archiveSha256": "08144618dc5dafba20b37e708ff2b11950486eb02666b31bbf7c28398855edf6"
|
|
593
593
|
},
|
|
594
594
|
{
|
|
595
|
-
"sha256": "
|
|
596
|
-
"size":
|
|
597
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
598
|
-
"archiveSize":
|
|
599
|
-
"archiveSha256": "
|
|
595
|
+
"sha256": "d47efa1bc6aed426cb5cca7d0c5395843d9ebe99597d9382135f8afbfe5e554a",
|
|
596
|
+
"size": 5769008,
|
|
597
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hd47efa1bc6aed426cb5cca7d0c5395843d9ebe99597d9382135f8afbfe5e554a.tgz",
|
|
598
|
+
"archiveSize": 4533424,
|
|
599
|
+
"archiveSha256": "62b5013f5b29776fe699f6e0cf6465cadbae965ec03a702b8481bc719a983f90"
|
|
600
600
|
},
|
|
601
601
|
{
|
|
602
602
|
"sha256": "641ba77a852ed34cc497714672d9d26250796f736f4df1a6b5ca196c6d7c9bfa",
|
|
@@ -816,11 +816,11 @@
|
|
|
816
816
|
"archiveSha256": "eb3f18bd55a152598f8d6b8325f21c3e2e6f82f937c5e8f29d2b7d5c758f075a"
|
|
817
817
|
},
|
|
818
818
|
{
|
|
819
|
-
"sha256": "
|
|
820
|
-
"size":
|
|
821
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
822
|
-
"archiveSize":
|
|
823
|
-
"archiveSha256": "
|
|
819
|
+
"sha256": "b2593d5d8c1e3fdb53ef446121af11f261cdc4cf8605868a9ae348e34df4bcef",
|
|
820
|
+
"size": 5942272,
|
|
821
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hb2593d5d8c1e3fdb53ef446121af11f261cdc4cf8605868a9ae348e34df4bcef.tgz",
|
|
822
|
+
"archiveSize": 2001323,
|
|
823
|
+
"archiveSha256": "b11a13e8cb1bba05f78908f9026247a83c623c422672a4153ab91decbcd6d0b6"
|
|
824
824
|
},
|
|
825
825
|
{
|
|
826
826
|
"sha256": "6d72766b19ebd5e4aae33b6d57b22f07b10cb83bc080f7596bfdd834675dfbc6",
|
|
@@ -844,11 +844,11 @@
|
|
|
844
844
|
"archiveSha256": "39f25e55411d144f5cea0f7b1842f48eabc3de2983ce26bd8d2e19175abbd312"
|
|
845
845
|
},
|
|
846
846
|
{
|
|
847
|
-
"sha256": "
|
|
848
|
-
"size":
|
|
849
|
-
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.
|
|
850
|
-
"archiveSize":
|
|
851
|
-
"archiveSha256": "
|
|
847
|
+
"sha256": "40de87acec8f30d6a282b5d7d90f7c9afa8314fe936e456340eb21372d700510",
|
|
848
|
+
"size": 34148749,
|
|
849
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h40de87acec8f30d6a282b5d7d90f7c9afa8314fe936e456340eb21372d700510.tgz",
|
|
850
|
+
"archiveSize": 27842671,
|
|
851
|
+
"archiveSha256": "c89125ab38d07a4857e544bbdaf051cae32eab0126c1185b47d5c8aabdae5e37"
|
|
852
852
|
},
|
|
853
853
|
{
|
|
854
854
|
"sha256": "e80bff562bb79507e555d21bac0d844f17994b47b5bad12409a0046df9de72cd",
|
|
@@ -891,17 +891,106 @@
|
|
|
891
891
|
"provenance": {
|
|
892
892
|
"darwin-arm64": {
|
|
893
893
|
"kind": "verified-own-overlay-upgrade",
|
|
894
|
-
"sourceVersion": "0.
|
|
894
|
+
"sourceVersion": "0.5.0",
|
|
895
895
|
"upgradeNpmUpdater": true,
|
|
896
|
-
"
|
|
897
|
-
"windowsIcon": "windows-blue-w"
|
|
896
|
+
"firstToolBootstrap": "automatic-relaunch"
|
|
898
897
|
},
|
|
899
898
|
"win32-x64": {
|
|
900
899
|
"kind": "verified-own-overlay-upgrade",
|
|
901
|
-
"sourceVersion": "0.
|
|
900
|
+
"sourceVersion": "0.5.0",
|
|
902
901
|
"upgradeNpmUpdater": true,
|
|
903
|
-
"
|
|
904
|
-
|
|
902
|
+
"firstToolBootstrap": "automatic-relaunch"
|
|
903
|
+
}
|
|
904
|
+
},
|
|
905
|
+
"runtimes": {
|
|
906
|
+
"schema": 1,
|
|
907
|
+
"version": "node24.22.0-python3.12.15-r1",
|
|
908
|
+
"platforms": {
|
|
909
|
+
"darwin-arm64": {
|
|
910
|
+
"node": {
|
|
911
|
+
"entry": "node-v24.22.0-darwin-arm64",
|
|
912
|
+
"format": "tar.gz",
|
|
913
|
+
"size": 53049576,
|
|
914
|
+
"sha256": "6a9724d9b50a5f22b4816cded441b5a8d9ddae546191a5e5b7efa5a5e2ee26d5",
|
|
915
|
+
"parts": [
|
|
916
|
+
{
|
|
917
|
+
"sha256": "949aea7a152b116e84670a7b771614bcea487f587a581e0d1a120928e9ab0221",
|
|
918
|
+
"size": 33554432,
|
|
919
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h949aea7a152b116e84670a7b771614bcea487f587a581e0d1a120928e9ab0221.tgz",
|
|
920
|
+
"archiveSize": 33512749,
|
|
921
|
+
"archiveSha256": "5f3bbf063aa3d82e32ba0499e46123822d7148542101aee2d019929190c196c2"
|
|
922
|
+
},
|
|
923
|
+
{
|
|
924
|
+
"sha256": "4cac86c2c3bad12d3402c7cd52ce002dcf222ebb3db964d1cbc5042b433aab59",
|
|
925
|
+
"size": 19495144,
|
|
926
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h4cac86c2c3bad12d3402c7cd52ce002dcf222ebb3db964d1cbc5042b433aab59.tgz",
|
|
927
|
+
"archiveSize": 19133414,
|
|
928
|
+
"archiveSha256": "643fb96788aef65d2a7adb81e1df6e55d963364b34837e152167282843818172"
|
|
929
|
+
}
|
|
930
|
+
]
|
|
931
|
+
},
|
|
932
|
+
"python": {
|
|
933
|
+
"entry": "python",
|
|
934
|
+
"format": "tar.gz",
|
|
935
|
+
"size": 25180390,
|
|
936
|
+
"sha256": "ba32036ad8f4c434d97a1ee7feef8b7edc0fac16777639b97e39c74a108e4440",
|
|
937
|
+
"parts": [
|
|
938
|
+
{
|
|
939
|
+
"sha256": "ba32036ad8f4c434d97a1ee7feef8b7edc0fac16777639b97e39c74a108e4440",
|
|
940
|
+
"size": 25180390,
|
|
941
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.hba32036ad8f4c434d97a1ee7feef8b7edc0fac16777639b97e39c74a108e4440.tgz",
|
|
942
|
+
"archiveSize": 25107923,
|
|
943
|
+
"archiveSha256": "503f5667f2d6fa6950438764f0ac29e413e3080bfcfe83b295b6c74c2c15163e"
|
|
944
|
+
}
|
|
945
|
+
]
|
|
946
|
+
}
|
|
947
|
+
},
|
|
948
|
+
"win32-x64": {
|
|
949
|
+
"node": {
|
|
950
|
+
"entry": "node-v24.22.0-win-x64",
|
|
951
|
+
"format": "zip",
|
|
952
|
+
"size": 37733703,
|
|
953
|
+
"sha256": "f9683a19877e12a9b167305c8db71040d812876359de21f0d2e97c3f321f80c3",
|
|
954
|
+
"parts": [
|
|
955
|
+
{
|
|
956
|
+
"sha256": "94c14ce1eeda03b3b96bd4ea01346bf43b21e70efbc5b25adaba94fda2b85906",
|
|
957
|
+
"size": 33554432,
|
|
958
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h94c14ce1eeda03b3b96bd4ea01346bf43b21e70efbc5b25adaba94fda2b85906.tgz",
|
|
959
|
+
"archiveSize": 33182230,
|
|
960
|
+
"archiveSha256": "72c783c0db418be6745f13f1c824b00314eec2d534c9b1913cc58b6c0524a9ce"
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
"sha256": "84cf2122a4133990d5f24187fecab4e1c8137bc71b37e6289cbf3aa68118839d",
|
|
964
|
+
"size": 4179271,
|
|
965
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h84cf2122a4133990d5f24187fecab4e1c8137bc71b37e6289cbf3aa68118839d.tgz",
|
|
966
|
+
"archiveSize": 3550650,
|
|
967
|
+
"archiveSha256": "93768d0020e6ab5be47b5c841bcba0e4d3feebbcc5b07e2378309239d1a3e186"
|
|
968
|
+
}
|
|
969
|
+
]
|
|
970
|
+
},
|
|
971
|
+
"python": {
|
|
972
|
+
"entry": "python",
|
|
973
|
+
"format": "tar.gz",
|
|
974
|
+
"size": 46390009,
|
|
975
|
+
"sha256": "bbc902d4d187ac4914915bf538196a064b49109a33a104965b5164ced5b80a1e",
|
|
976
|
+
"parts": [
|
|
977
|
+
{
|
|
978
|
+
"sha256": "69b8bc6e8da423ec63f0b80af3c43a1c10efad679fa3a6c875bf33f0373ab201",
|
|
979
|
+
"size": 33554432,
|
|
980
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h69b8bc6e8da423ec63f0b80af3c43a1c10efad679fa3a6c875bf33f0373ab201.tgz",
|
|
981
|
+
"archiveSize": 33403996,
|
|
982
|
+
"archiveSha256": "2b124ed954113cd681b37e442539c6cc8daee7e2a96724c76e94b86418da7e4d"
|
|
983
|
+
},
|
|
984
|
+
{
|
|
985
|
+
"sha256": "94972a77f8080d4b9e5094d5ac42a1e3d7cfce1c7b2dcd804b43e02f4133d885",
|
|
986
|
+
"size": 12835577,
|
|
987
|
+
"url": "https://registry.npmjs.org/@petercjl/codex-own/-/codex-own-0.0.0-payload.h94972a77f8080d4b9e5094d5ac42a1e3d7cfce1c7b2dcd804b43e02f4133d885.tgz",
|
|
988
|
+
"archiveSize": 12811675,
|
|
989
|
+
"archiveSha256": "38cffc9d4a50f51d0dc333aca4e7065f12721a200bfc20f5e01ac24e44ae9e2d"
|
|
990
|
+
}
|
|
991
|
+
]
|
|
992
|
+
}
|
|
993
|
+
}
|
|
905
994
|
}
|
|
906
995
|
}
|
|
907
996
|
}
|
|
@@ -20,6 +20,20 @@ For installation-only acceptance, verify doctor, version, target and shortcut wi
|
|
|
20
20
|
|
|
21
21
|
Desktop builds with the bundled npm updater check stable latest 15 seconds after startup and every six hours. The user-facing menu is 更新 → 检查 codex-own 更新…. Download runs while the app remains usable; 重启并安装 asks the user to end active tasks, then an independent helper waits for exit, backs up and replaces the app. The helper uses bundled Node and npm payloads, so daily in-app updates do not require updating global npm tooling. Inspect the installed app's own updater version separately from the global CLI version. Retain CLI step 3 for older builds and recovery. Prepared, verified downloads survive restarts; offline checks preserve the current installation. Install logs and unique result records live under the independent manager directory; never delete locks to bypass a failed update.
|
|
22
22
|
|
|
23
|
+
## Private tool runtime (contract 1)
|
|
24
|
+
|
|
25
|
+
Desktop installations from 0.5.0 include a separately versioned Node/npm/Python toolchain. The manager's release manifest pins verified npm payloads for macOS ARM64 and Windows x64. Install/update ensures these tools before switching the app. Runtime bytes retain upstream licenses and contain no user configuration. The initial npm manager bootstrap still requires existing Node.js 22+; ordinary app updates use the bundled updater.
|
|
26
|
+
|
|
27
|
+
When migrating through a 0.4.x in-app updater, the new desktop's async startup gate downloads and verifies its pinned tools from npm before loading the desktop backend. A progress window supports cancellation and retry; no system Node/npm/Python is required for this migration. Inspect unique `logs/runtime-bootstrap-*.log` files if preparation fails. An installed valid runtime allows offline startup without a registry check.
|
|
28
|
+
|
|
29
|
+
Use `codex-own runtime doctor` to discover the actual version and executable paths. Use `runtime env` for a sanitized JSON environment contract; it returns only tool settings, never inherited credentials. `runtime run -- node|npm|npx|python|python3|pip [args]` executes the selected private tool and propagates its exit status. Do not infer availability from system PATH, Windows App Execution Aliases or Start-menu Python groups. The app reapplies its private environment after importing the login shell.
|
|
30
|
+
|
|
31
|
+
On macOS, the runtime owns its task-only `ZDOTDIR` and `BASH_ENV` startup files. Login shells retain private tool precedence without editing the user's profiles. Verify paths through the backend's actual command execution, including login zsh/Bash, rather than checking only the parent process PATH. Project activation inside a task can explicitly select its own venv or toolchain.
|
|
32
|
+
|
|
33
|
+
For authorized installation or update, use `runtime install --yes` or `runtime update --yes`. Immutable versions are stored below the independent data root's `runtimes/versions`, with `active.json` recording the active version and predecessor. Updates keep the old version; already running processes keep their prior paths until restart. `runtime rollback --yes` verifies and reactivates the predecessor without restoring conversation data. BUSY and interrupted staging require inspecting the lock/process and receipts, not deleting state blindly. RUNTIME_VERSION_EXISTS preserves an unexpected existing target for diagnosis. Failed verification leaves the old active receipt unchanged.
|
|
34
|
+
|
|
35
|
+
Tools own their npm prefix/cache and pip cache; no user/system PATH, shell profile or original Codex runtime is modified. Project npm dependencies belong in project `node_modules`; Python dependencies belong in the project's `.venv`, created with the private Python. pip requires a virtual environment, so use its Python executable with `-m pip` after creating the venv. A project explicitly selecting another interpreter remains an explicit caller choice. Additional Git, compilers and office/media libraries are separate dependencies, not guaranteed by this toolchain. Never copy the original Codex cached runtime or account files to fill a missing dependency.
|
|
36
|
+
|
|
23
37
|
## Recovery and boundaries
|
|
24
38
|
|
|
25
39
|
- APP_RUNNING: request or perform authorized graceful exit, then return to step 3.
|