@cerulin/chell 0.2.5
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 +75 -0
- package/bin/chell-mcp.mjs +33 -0
- package/bin/chell.mjs +37 -0
- package/dist/codex/chellMcpStdioBridge.cjs +80 -0
- package/dist/codex/chellMcpStdioBridge.d.cts +2 -0
- package/dist/codex/chellMcpStdioBridge.d.mts +2 -0
- package/dist/codex/chellMcpStdioBridge.mjs +78 -0
- package/dist/index-B443j7JQ.mjs +6714 -0
- package/dist/index-qS668VWY.cjs +6730 -0
- package/dist/index.cjs +42 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +39 -0
- package/dist/lib.cjs +32 -0
- package/dist/lib.d.cts +891 -0
- package/dist/lib.d.mts +891 -0
- package/dist/lib.mjs +22 -0
- package/dist/runCodex-DHtm7TWT.cjs +2020 -0
- package/dist/runCodex-DLbjgnc4.mjs +2017 -0
- package/dist/runGemini-C03RUmvr.mjs +788 -0
- package/dist/runGemini-fdb5jxAA.cjs +791 -0
- package/dist/types-DBjv5m4J.cjs +2499 -0
- package/dist/types-fM_iFuNp.mjs +2452 -0
- package/package.json +131 -0
- package/scripts/claude_local_launcher.cjs +98 -0
- package/scripts/claude_remote_launcher.cjs +13 -0
- package/scripts/codex_local_launcher.cjs +155 -0
- package/scripts/codex_preload.cjs +56 -0
- package/scripts/codex_remote_launcher.cjs +129 -0
- package/scripts/obfuscate-dist.mjs +73 -0
- package/scripts/pack-chell.cjs +32 -0
- package/scripts/publish-scoped.ps1 +58 -0
- package/scripts/ripgrep_launcher.cjs +33 -0
- package/scripts/unpack-tools.cjs +163 -0
- package/tools/archives/difftastic-LICENSE +21 -0
- package/tools/archives/difftastic-arm64-darwin.tar.gz +0 -0
- package/tools/archives/difftastic-arm64-linux.tar.gz +0 -0
- package/tools/archives/difftastic-x64-darwin.tar.gz +0 -0
- package/tools/archives/difftastic-x64-linux.tar.gz +0 -0
- package/tools/archives/difftastic-x64-win32.tar.gz +0 -0
- package/tools/archives/ripgrep-LICENSE +3 -0
- package/tools/archives/ripgrep-arm64-darwin.tar.gz +0 -0
- package/tools/archives/ripgrep-arm64-linux.tar.gz +0 -0
- package/tools/archives/ripgrep-x64-darwin.tar.gz +0 -0
- package/tools/archives/ripgrep-x64-linux.tar.gz +0 -0
- package/tools/archives/ripgrep-x64-win32.tar.gz +0 -0
- package/tools/licenses/difftastic-LICENSE +21 -0
- package/tools/licenses/ripgrep-LICENSE +3 -0
- package/tools/unpacked/difft +0 -0
- package/tools/unpacked/difft.exe +0 -0
- package/tools/unpacked/rg +0 -0
- package/tools/unpacked/rg.exe +0 -0
- package/tools/unpacked/ripgrep.node +0 -0
package/package.json
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cerulin/chell",
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"description": "Mobile and Web client for Claude Code and Codex",
|
|
5
|
+
"author": "Cerulin",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"homepage": "https://github.com/cerulin/chell-cli",
|
|
9
|
+
"bugs": "https://github.com/cerulin/chell-cli/issues",
|
|
10
|
+
"repository": "cerulin/chell-cli",
|
|
11
|
+
"bin": {
|
|
12
|
+
"happy": "./bin/chell.mjs",
|
|
13
|
+
"happy-mcp": "./bin/chell-mcp.mjs",
|
|
14
|
+
"chell": "./bin/chell.mjs",
|
|
15
|
+
"chell-mcp": "./bin/chell-mcp.mjs"
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.cjs",
|
|
18
|
+
"module": "./dist/index.mjs",
|
|
19
|
+
"types": "./dist/index.d.cts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"require": {
|
|
23
|
+
"types": "./dist/index.d.cts",
|
|
24
|
+
"default": "./dist/index.cjs"
|
|
25
|
+
},
|
|
26
|
+
"import": {
|
|
27
|
+
"types": "./dist/index.d.mts",
|
|
28
|
+
"default": "./dist/index.mjs"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"./lib": {
|
|
32
|
+
"require": {
|
|
33
|
+
"types": "./dist/lib.d.cts",
|
|
34
|
+
"default": "./dist/lib.cjs"
|
|
35
|
+
},
|
|
36
|
+
"import": {
|
|
37
|
+
"types": "./dist/lib.d.mts",
|
|
38
|
+
"default": "./dist/lib.mjs"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"./codex/chellMcpStdioBridge": {
|
|
42
|
+
"require": {
|
|
43
|
+
"types": "./dist/codex/chellMcpStdioBridge.d.cts",
|
|
44
|
+
"default": "./dist/codex/chellMcpStdioBridge.cjs"
|
|
45
|
+
},
|
|
46
|
+
"import": {
|
|
47
|
+
"types": "./dist/codex/chellMcpStdioBridge.d.mts",
|
|
48
|
+
"default": "./dist/codex/chellMcpStdioBridge.mjs"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"dist",
|
|
54
|
+
"bin",
|
|
55
|
+
"scripts",
|
|
56
|
+
"tools",
|
|
57
|
+
"package.json"
|
|
58
|
+
],
|
|
59
|
+
"scripts": {
|
|
60
|
+
"why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy",
|
|
61
|
+
"typecheck": "tsc --noEmit",
|
|
62
|
+
"build": "shx rm -rf dist && npx tsc --noEmit && pkgroll",
|
|
63
|
+
"obfuscate": "shx rm -rf dist.obf && javascript-obfuscator dist --output dist.obf --compact true --self-defending false --control-flow-flattening true --string-array true --string-array-encoding base64 --identifier-names-generator mangled && shx cp -r dist/*.d.* dist.obf 2>nul && shx rm -rf dist && shx mv dist.obf dist",
|
|
64
|
+
"build:obf": "yarn build && yarn obfuscate",
|
|
65
|
+
"pack:chell": "node scripts/pack-chell.cjs",
|
|
66
|
+
"test": "yarn build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
|
|
67
|
+
"start": "yarn build && ./bin/chell.mjs",
|
|
68
|
+
"dev": "yarn build && tsx --env-file .env.dev src/index.ts",
|
|
69
|
+
"dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
|
|
70
|
+
"dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
|
|
71
|
+
"prepublishOnly": "yarn build && yarn test",
|
|
72
|
+
"release": "release-it",
|
|
73
|
+
"postinstall": "node scripts/unpack-tools.cjs"
|
|
74
|
+
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"@anthropic-ai/claude-code": "^2.0.14",
|
|
77
|
+
"@anthropic-ai/sdk": "^0.56.0",
|
|
78
|
+
"@modelcontextprotocol/sdk": "^1.15.1",
|
|
79
|
+
"@openai/codex": "^0.50.0",
|
|
80
|
+
"@stablelib/base64": "^2.0.1",
|
|
81
|
+
"@types/cross-spawn": "^6.0.6",
|
|
82
|
+
"@types/http-proxy": "^1.17.16",
|
|
83
|
+
"@types/ps-list": "^6.2.1",
|
|
84
|
+
"@types/qrcode-terminal": "^0.12.2",
|
|
85
|
+
"@types/react": "^19.1.9",
|
|
86
|
+
"axios": "^1.10.0",
|
|
87
|
+
"chalk": "^5.4.1",
|
|
88
|
+
"chell": "^1.0.4",
|
|
89
|
+
"cross-spawn": "^7.0.6",
|
|
90
|
+
"expo-server-sdk": "^3.15.0",
|
|
91
|
+
"fastify": "^5.5.0",
|
|
92
|
+
"fastify-type-provider-zod": "4.0.2",
|
|
93
|
+
"http-proxy": "^1.18.1",
|
|
94
|
+
"http-proxy-middleware": "^3.0.5",
|
|
95
|
+
"ink": "^6.1.0",
|
|
96
|
+
"node-pty": "1.0.0",
|
|
97
|
+
"open": "^10.2.0",
|
|
98
|
+
"ps-list": "^8.1.1",
|
|
99
|
+
"qrcode-terminal": "^0.12.0",
|
|
100
|
+
"react": "^19.1.1",
|
|
101
|
+
"socket.io-client": "^4.8.1",
|
|
102
|
+
"tar": "^7.4.3",
|
|
103
|
+
"tweetnacl": "^1.0.3",
|
|
104
|
+
"zod": "^3.23.8"
|
|
105
|
+
},
|
|
106
|
+
"devDependencies": {
|
|
107
|
+
"@eslint/compat": "^1",
|
|
108
|
+
"@types/node": ">=20",
|
|
109
|
+
"cross-env": "^10.0.0",
|
|
110
|
+
"dotenv": "^16.6.1",
|
|
111
|
+
"eslint": "^9",
|
|
112
|
+
"eslint-config-prettier": "^10",
|
|
113
|
+
"javascript-obfuscator": "4",
|
|
114
|
+
"pkgroll": "^2.14.2",
|
|
115
|
+
"release-it": "^19.0.4",
|
|
116
|
+
"shx": "^0.3.3",
|
|
117
|
+
"ts-node": "^10",
|
|
118
|
+
"tsx": "^4.20.3",
|
|
119
|
+
"typescript": "^5",
|
|
120
|
+
"vitest": "^3.2.4"
|
|
121
|
+
},
|
|
122
|
+
"resolutions": {
|
|
123
|
+
"whatwg-url": "14.2.0",
|
|
124
|
+
"parse-path": "7.0.3",
|
|
125
|
+
"@types/parse-path": "7.0.3"
|
|
126
|
+
},
|
|
127
|
+
"publishConfig": {
|
|
128
|
+
"registry": "https://registry.npmjs.org"
|
|
129
|
+
},
|
|
130
|
+
"packageManager": "yarn@1.22.22"
|
|
131
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
|
|
4
|
+
// Disable autoupdater (never works really)
|
|
5
|
+
process.env.DISABLE_AUTOUPDATER = '1';
|
|
6
|
+
|
|
7
|
+
// Helper to write JSON messages to fd 3
|
|
8
|
+
function writeMessage(message) {
|
|
9
|
+
try {
|
|
10
|
+
fs.writeSync(3, JSON.stringify(message) + '\n');
|
|
11
|
+
} catch (err) {
|
|
12
|
+
// fd 3 not available, ignore
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Intercept crypto.randomUUID
|
|
17
|
+
const originalRandomUUID = crypto.randomUUID;
|
|
18
|
+
Object.defineProperty(global, 'crypto', {
|
|
19
|
+
configurable: true,
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get() {
|
|
22
|
+
return {
|
|
23
|
+
randomUUID: () => {
|
|
24
|
+
const uuid = originalRandomUUID();
|
|
25
|
+
writeMessage({ type: 'uuid', value: uuid });
|
|
26
|
+
return uuid;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(crypto, 'randomUUID', {
|
|
32
|
+
configurable: true,
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get() {
|
|
35
|
+
return () => {
|
|
36
|
+
const uuid = originalRandomUUID();
|
|
37
|
+
writeMessage({ type: 'uuid', value: uuid });
|
|
38
|
+
return uuid;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Intercept fetch to track activity
|
|
44
|
+
const originalFetch = global.fetch;
|
|
45
|
+
let fetchCounter = 0;
|
|
46
|
+
|
|
47
|
+
global.fetch = function(...args) {
|
|
48
|
+
const id = ++fetchCounter;
|
|
49
|
+
const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
|
|
50
|
+
const method = args[1]?.method || 'GET';
|
|
51
|
+
|
|
52
|
+
// Parse URL for privacy
|
|
53
|
+
let hostname = '';
|
|
54
|
+
let path = '';
|
|
55
|
+
try {
|
|
56
|
+
const urlObj = new URL(url, 'http://localhost');
|
|
57
|
+
hostname = urlObj.hostname;
|
|
58
|
+
path = urlObj.pathname;
|
|
59
|
+
} catch (e) {
|
|
60
|
+
// If URL parsing fails, use defaults
|
|
61
|
+
hostname = 'unknown';
|
|
62
|
+
path = url;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Send fetch start event
|
|
66
|
+
writeMessage({
|
|
67
|
+
type: 'fetch-start',
|
|
68
|
+
id,
|
|
69
|
+
hostname,
|
|
70
|
+
path,
|
|
71
|
+
method,
|
|
72
|
+
timestamp: Date.now()
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Execute the original fetch immediately
|
|
76
|
+
const fetchPromise = originalFetch(...args);
|
|
77
|
+
|
|
78
|
+
// Attach handlers to send fetch end event
|
|
79
|
+
const sendEnd = () => {
|
|
80
|
+
writeMessage({
|
|
81
|
+
type: 'fetch-end',
|
|
82
|
+
id,
|
|
83
|
+
timestamp: Date.now()
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Send end event on both success and failure
|
|
88
|
+
fetchPromise.then(sendEnd, sendEnd);
|
|
89
|
+
|
|
90
|
+
// Return the original promise unchanged
|
|
91
|
+
return fetchPromise;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Preserve fetch properties
|
|
95
|
+
Object.defineProperty(global.fetch, 'name', { value: 'fetch' });
|
|
96
|
+
Object.defineProperty(global.fetch, 'length', { value: originalFetch.length });
|
|
97
|
+
|
|
98
|
+
import('@anthropic-ai/claude-code/cli.js')
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Intercept setTimeout for the Claude Code SDK
|
|
2
|
+
const originalSetTimeout = global.setTimeout;
|
|
3
|
+
|
|
4
|
+
global.setTimeout = function(callback, delay, ...args) {
|
|
5
|
+
// Just wrap and call the original setTimeout
|
|
6
|
+
return originalSetTimeout(callback, delay, ...args);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// Preserve setTimeout properties
|
|
10
|
+
Object.defineProperty(global.setTimeout, 'name', { value: 'setTimeout' });
|
|
11
|
+
Object.defineProperty(global.setTimeout, 'length', { value: originalSetTimeout.length });
|
|
12
|
+
|
|
13
|
+
import('@anthropic-ai/claude-code/cli.js')
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
|
|
4
|
+
// Disable autoupdater if Codex has one
|
|
5
|
+
process.env.DISABLE_AUTOUPDATER = '1';
|
|
6
|
+
|
|
7
|
+
// Helper to write JSON messages to fd 3
|
|
8
|
+
function writeMessage(message) {
|
|
9
|
+
try {
|
|
10
|
+
fs.writeSync(3, JSON.stringify(message) + '\n');
|
|
11
|
+
} catch (err) {
|
|
12
|
+
// fd 3 not available, ignore
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Intercept crypto.randomUUID
|
|
17
|
+
const originalRandomUUID = crypto.randomUUID;
|
|
18
|
+
Object.defineProperty(global, 'crypto', {
|
|
19
|
+
configurable: true,
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get() {
|
|
22
|
+
return {
|
|
23
|
+
randomUUID: () => {
|
|
24
|
+
const uuid = originalRandomUUID();
|
|
25
|
+
writeMessage({ type: 'uuid', value: uuid });
|
|
26
|
+
return uuid;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(crypto, 'randomUUID', {
|
|
32
|
+
configurable: true,
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get() {
|
|
35
|
+
return () => {
|
|
36
|
+
const uuid = originalRandomUUID();
|
|
37
|
+
writeMessage({ type: 'uuid', value: uuid });
|
|
38
|
+
return uuid;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Intercept fetch to track activity
|
|
44
|
+
const originalFetch = global.fetch;
|
|
45
|
+
let fetchCounter = 0;
|
|
46
|
+
|
|
47
|
+
global.fetch = function(...args) {
|
|
48
|
+
const id = ++fetchCounter;
|
|
49
|
+
const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
|
|
50
|
+
const method = args[1]?.method || 'GET';
|
|
51
|
+
|
|
52
|
+
// Parse URL for privacy
|
|
53
|
+
let hostname = '';
|
|
54
|
+
let path = '';
|
|
55
|
+
try {
|
|
56
|
+
const urlObj = new URL(url, 'http://localhost');
|
|
57
|
+
hostname = urlObj.hostname;
|
|
58
|
+
path = urlObj.pathname;
|
|
59
|
+
} catch (e) {
|
|
60
|
+
// If URL parsing fails, use defaults
|
|
61
|
+
hostname = 'unknown';
|
|
62
|
+
path = url;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Send fetch start event
|
|
66
|
+
writeMessage({
|
|
67
|
+
type: 'fetch-start',
|
|
68
|
+
id,
|
|
69
|
+
hostname,
|
|
70
|
+
path,
|
|
71
|
+
method,
|
|
72
|
+
timestamp: Date.now()
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Execute the original fetch immediately
|
|
76
|
+
const fetchPromise = originalFetch(...args);
|
|
77
|
+
|
|
78
|
+
// Attach handlers to send fetch end event
|
|
79
|
+
const sendEnd = () => {
|
|
80
|
+
writeMessage({
|
|
81
|
+
type: 'fetch-end',
|
|
82
|
+
id,
|
|
83
|
+
timestamp: Date.now()
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Send end event on both success and failure
|
|
88
|
+
fetchPromise.then(sendEnd, sendEnd);
|
|
89
|
+
|
|
90
|
+
// Return the original promise unchanged
|
|
91
|
+
return fetchPromise;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Preserve fetch properties
|
|
95
|
+
Object.defineProperty(global.fetch, 'name', { value: 'fetch' });
|
|
96
|
+
Object.defineProperty(global.fetch, 'length', { value: originalFetch.length });
|
|
97
|
+
|
|
98
|
+
// Log startup to fd3
|
|
99
|
+
writeMessage({ type: 'launcher_start', timestamp: Date.now() });
|
|
100
|
+
|
|
101
|
+
// Import Codex CLI
|
|
102
|
+
// Try different entry points based on how OpenAI packages Codex
|
|
103
|
+
(async () => {
|
|
104
|
+
try {
|
|
105
|
+
// Try with .js extension first (Node ESM requires explicit extensions)
|
|
106
|
+
writeMessage({ type: 'import_attempt', path: '@openai/codex/bin/codex.js' });
|
|
107
|
+
await import('@openai/codex/bin/codex.js');
|
|
108
|
+
writeMessage({ type: 'import_success', path: '@openai/codex/bin/codex.js' });
|
|
109
|
+
} catch (err1) {
|
|
110
|
+
try {
|
|
111
|
+
// Try CLI entry point
|
|
112
|
+
writeMessage({ type: 'import_attempt', path: '@openai/codex/cli.js' });
|
|
113
|
+
await import('@openai/codex/cli.js');
|
|
114
|
+
writeMessage({ type: 'import_success', path: '@openai/codex/cli.js' });
|
|
115
|
+
} catch (err2) {
|
|
116
|
+
try {
|
|
117
|
+
// Try main export
|
|
118
|
+
writeMessage({ type: 'import_attempt', path: '@openai/codex' });
|
|
119
|
+
await import('@openai/codex');
|
|
120
|
+
writeMessage({ type: 'import_success', path: '@openai/codex' });
|
|
121
|
+
} catch (err3) {
|
|
122
|
+
try {
|
|
123
|
+
// Try bin without extension (for older Node versions)
|
|
124
|
+
writeMessage({ type: 'import_attempt', path: '@openai/codex/bin/codex' });
|
|
125
|
+
await import('@openai/codex/bin/codex');
|
|
126
|
+
writeMessage({ type: 'import_success', path: '@openai/codex/bin/codex' });
|
|
127
|
+
} catch (err4) {
|
|
128
|
+
try {
|
|
129
|
+
// Try dist/bin/codex.js (common build output location)
|
|
130
|
+
writeMessage({ type: 'import_attempt', path: '@openai/codex/dist/bin/codex.js' });
|
|
131
|
+
await import('@openai/codex/dist/bin/codex.js');
|
|
132
|
+
writeMessage({ type: 'import_success', path: '@openai/codex/dist/bin/codex.js' });
|
|
133
|
+
} catch (err5) {
|
|
134
|
+
writeMessage({ type: 'import_failed', error: err5.message });
|
|
135
|
+
console.error('❌ Failed to load Codex CLI from any known entry point');
|
|
136
|
+
console.error('Attempted paths:');
|
|
137
|
+
console.error(' - @openai/codex/bin/codex.js');
|
|
138
|
+
console.error(' - @openai/codex/cli.js');
|
|
139
|
+
console.error(' - @openai/codex');
|
|
140
|
+
console.error(' - @openai/codex/bin/codex');
|
|
141
|
+
console.error(' - @openai/codex/dist/bin/codex.js');
|
|
142
|
+
console.error('');
|
|
143
|
+
console.error('Last error:', err5.message);
|
|
144
|
+
console.error('');
|
|
145
|
+
console.error('This is likely a bundling issue. The @openai/codex package should be');
|
|
146
|
+
console.error('included in chell dependencies and bundled during npm pack.');
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
})();
|
|
154
|
+
|
|
155
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
// Helper to write JSON messages to fd 3
|
|
5
|
+
function writeMessage(message) {
|
|
6
|
+
try {
|
|
7
|
+
fs.writeSync(3, JSON.stringify(message) + '\n');
|
|
8
|
+
} catch (_) {
|
|
9
|
+
// fd3 not available; ignore
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Log preload activation
|
|
14
|
+
writeMessage({ type: 'launcher_start', timestamp: Date.now(), preload: true });
|
|
15
|
+
|
|
16
|
+
// Intercept crypto.randomUUID to surface session UUIDs
|
|
17
|
+
try {
|
|
18
|
+
const originalRandomUUID = crypto.randomUUID;
|
|
19
|
+
Object.defineProperty(crypto, 'randomUUID', {
|
|
20
|
+
configurable: true,
|
|
21
|
+
enumerable: true,
|
|
22
|
+
value: () => {
|
|
23
|
+
const uuid = originalRandomUUID();
|
|
24
|
+
writeMessage({ type: 'uuid', value: uuid });
|
|
25
|
+
return uuid;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
} catch (_) {}
|
|
29
|
+
|
|
30
|
+
// Intercept global.fetch to track thinking
|
|
31
|
+
try {
|
|
32
|
+
const originalFetch = global.fetch;
|
|
33
|
+
if (typeof originalFetch === 'function') {
|
|
34
|
+
let fetchCounter = 0;
|
|
35
|
+
global.fetch = function(...args) {
|
|
36
|
+
const id = ++fetchCounter;
|
|
37
|
+
const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
|
|
38
|
+
let hostname = '';
|
|
39
|
+
let path = '';
|
|
40
|
+
try {
|
|
41
|
+
const urlObj = new URL(url, 'http://localhost');
|
|
42
|
+
hostname = urlObj.hostname;
|
|
43
|
+
path = urlObj.pathname;
|
|
44
|
+
} catch {}
|
|
45
|
+
writeMessage({ type: 'fetch-start', id, hostname, path, timestamp: Date.now() });
|
|
46
|
+
const p = originalFetch.apply(this, args);
|
|
47
|
+
const sendEnd = () => writeMessage({ type: 'fetch-end', id, timestamp: Date.now() });
|
|
48
|
+
p.then(sendEnd, sendEnd);
|
|
49
|
+
return p;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} catch (_) {}
|
|
53
|
+
|
|
54
|
+
// Disable any autoupdater behavior in codex if present
|
|
55
|
+
process.env.DISABLE_AUTOUPDATER = '1';
|
|
56
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
|
|
4
|
+
// Disable autoupdater if Codex has one
|
|
5
|
+
process.env.DISABLE_AUTOUPDATER = '1';
|
|
6
|
+
|
|
7
|
+
// Helper to write JSON messages to fd 3
|
|
8
|
+
function writeMessage(message) {
|
|
9
|
+
try {
|
|
10
|
+
fs.writeSync(3, JSON.stringify(message) + '\n');
|
|
11
|
+
} catch (err) {
|
|
12
|
+
// fd 3 not available, ignore
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Intercept crypto.randomUUID
|
|
17
|
+
const originalRandomUUID = crypto.randomUUID;
|
|
18
|
+
Object.defineProperty(global, 'crypto', {
|
|
19
|
+
configurable: true,
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get() {
|
|
22
|
+
return {
|
|
23
|
+
randomUUID: () => {
|
|
24
|
+
const uuid = originalRandomUUID();
|
|
25
|
+
writeMessage({ type: 'uuid', value: uuid });
|
|
26
|
+
return uuid;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(crypto, 'randomUUID', {
|
|
32
|
+
configurable: true,
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get() {
|
|
35
|
+
return () => {
|
|
36
|
+
const uuid = originalRandomUUID();
|
|
37
|
+
writeMessage({ type: 'uuid', value: uuid });
|
|
38
|
+
return uuid;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Intercept fetch to track activity
|
|
44
|
+
const originalFetch = global.fetch;
|
|
45
|
+
let fetchCounter = 0;
|
|
46
|
+
|
|
47
|
+
global.fetch = function(...args) {
|
|
48
|
+
const id = ++fetchCounter;
|
|
49
|
+
const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
|
|
50
|
+
const method = args[1]?.method || 'GET';
|
|
51
|
+
|
|
52
|
+
// Parse URL for privacy
|
|
53
|
+
let hostname = '';
|
|
54
|
+
let path = '';
|
|
55
|
+
try {
|
|
56
|
+
const urlObj = new URL(url, 'http://localhost');
|
|
57
|
+
hostname = urlObj.hostname;
|
|
58
|
+
path = urlObj.pathname;
|
|
59
|
+
} catch (e) {
|
|
60
|
+
// If URL parsing fails, use defaults
|
|
61
|
+
hostname = 'unknown';
|
|
62
|
+
path = url;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Send fetch start event
|
|
66
|
+
writeMessage({
|
|
67
|
+
type: 'fetch-start',
|
|
68
|
+
id,
|
|
69
|
+
hostname,
|
|
70
|
+
path,
|
|
71
|
+
method,
|
|
72
|
+
timestamp: Date.now()
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Execute the original fetch immediately
|
|
76
|
+
const fetchPromise = originalFetch(...args);
|
|
77
|
+
|
|
78
|
+
// Attach handlers to send fetch end event
|
|
79
|
+
const sendEnd = () => {
|
|
80
|
+
writeMessage({
|
|
81
|
+
type: 'fetch-end',
|
|
82
|
+
id,
|
|
83
|
+
timestamp: Date.now()
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Send end event on both success and failure
|
|
88
|
+
fetchPromise.then(sendEnd, sendEnd);
|
|
89
|
+
|
|
90
|
+
// Return the original promise unchanged
|
|
91
|
+
return fetchPromise;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Preserve fetch properties
|
|
95
|
+
Object.defineProperty(global.fetch, 'name', { value: 'fetch' });
|
|
96
|
+
Object.defineProperty(global.fetch, 'length', { value: originalFetch.length });
|
|
97
|
+
|
|
98
|
+
// Import Codex SDK for remote control
|
|
99
|
+
// Try different entry points based on how OpenAI packages Codex
|
|
100
|
+
(async () => {
|
|
101
|
+
try {
|
|
102
|
+
// Try SDK entry point first (for remote/programmatic control)
|
|
103
|
+
await import('@openai/codex/sdk.js');
|
|
104
|
+
} catch (err1) {
|
|
105
|
+
try {
|
|
106
|
+
// Try CLI as fallback (can also be used remotely)
|
|
107
|
+
await import('@openai/codex/cli.js');
|
|
108
|
+
} catch (err2) {
|
|
109
|
+
try {
|
|
110
|
+
// Try main export
|
|
111
|
+
await import('@openai/codex');
|
|
112
|
+
} catch (err3) {
|
|
113
|
+
console.error('❌ Failed to load Codex from any known entry point');
|
|
114
|
+
console.error('Attempted paths:');
|
|
115
|
+
console.error(' - @openai/codex/sdk.js');
|
|
116
|
+
console.error(' - @openai/codex/cli.js');
|
|
117
|
+
console.error(' - @openai/codex');
|
|
118
|
+
console.error('');
|
|
119
|
+
console.error('Error details:', err3.message);
|
|
120
|
+
console.error('');
|
|
121
|
+
console.error('Please ensure @openai/codex is installed correctly:');
|
|
122
|
+
console.error(' npm install @openai/codex');
|
|
123
|
+
console.error(' or check https://github.com/openai/codex for installation instructions');
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
})();
|
|
129
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join, relative, extname, basename } from 'path';
|
|
5
|
+
import { readFileSync, writeFileSync, mkdirSync, readdirSync, statSync, copyFileSync } from 'fs';
|
|
6
|
+
import JavaScriptObfuscator from 'javascript-obfuscator';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
const rootDir = join(__dirname, '..');
|
|
11
|
+
const distDir = join(rootDir, 'dist');
|
|
12
|
+
const distObfDir = join(rootDir, 'dist.obf');
|
|
13
|
+
|
|
14
|
+
const obfuscatorOptions = {
|
|
15
|
+
compact: true,
|
|
16
|
+
selfDefending: false,
|
|
17
|
+
controlFlowFlattening: true,
|
|
18
|
+
stringArray: true,
|
|
19
|
+
stringArrayEncoding: ['base64'],
|
|
20
|
+
identifierNamesGenerator: 'mangled'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function getAllFiles(dir, fileList = []) {
|
|
24
|
+
const files = readdirSync(dir);
|
|
25
|
+
|
|
26
|
+
files.forEach(file => {
|
|
27
|
+
const filePath = join(dir, file);
|
|
28
|
+
if (statSync(filePath).isDirectory()) {
|
|
29
|
+
getAllFiles(filePath, fileList);
|
|
30
|
+
} else {
|
|
31
|
+
fileList.push(filePath);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return fileList;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function obfuscateFile(inputPath, outputPath) {
|
|
39
|
+
const ext = extname(inputPath);
|
|
40
|
+
|
|
41
|
+
// Only obfuscate .cjs and .mjs files
|
|
42
|
+
if (ext === '.cjs' || ext === '.mjs') {
|
|
43
|
+
console.log(`Obfuscating: ${relative(rootDir, inputPath)}`);
|
|
44
|
+
const code = readFileSync(inputPath, 'utf8');
|
|
45
|
+
const obfuscated = JavaScriptObfuscator.obfuscate(code, obfuscatorOptions);
|
|
46
|
+
|
|
47
|
+
// Create output directory if it doesn't exist
|
|
48
|
+
const outputDir = dirname(outputPath);
|
|
49
|
+
mkdirSync(outputDir, { recursive: true });
|
|
50
|
+
|
|
51
|
+
writeFileSync(outputPath, obfuscated.getObfuscatedCode(), 'utf8');
|
|
52
|
+
} else {
|
|
53
|
+
// Copy type definition files and other files as-is
|
|
54
|
+
console.log(`Copying: ${relative(rootDir, inputPath)}`);
|
|
55
|
+
const outputDir = dirname(outputPath);
|
|
56
|
+
mkdirSync(outputDir, { recursive: true });
|
|
57
|
+
copyFileSync(inputPath, outputPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log('Starting obfuscation...');
|
|
62
|
+
|
|
63
|
+
// Get all files from dist
|
|
64
|
+
const allFiles = getAllFiles(distDir);
|
|
65
|
+
|
|
66
|
+
// Process each file
|
|
67
|
+
allFiles.forEach(inputPath => {
|
|
68
|
+
const relativePath = relative(distDir, inputPath);
|
|
69
|
+
const outputPath = join(distObfDir, relativePath);
|
|
70
|
+
obfuscateFile(inputPath, outputPath);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
console.log(`Obfuscation complete! Output in ${relative(rootDir, distObfDir)}`);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { execSync } = require('node:child_process');
|
|
3
|
+
const { existsSync, unlinkSync, renameSync } = require('node:fs');
|
|
4
|
+
const { join } = require('node:path');
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
const outName = 'chell.tgz';
|
|
8
|
+
const outPath = join(process.cwd(), outName);
|
|
9
|
+
|
|
10
|
+
if (existsSync(outPath)) {
|
|
11
|
+
unlinkSync(outPath);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Run npm pack and capture the produced filename
|
|
15
|
+
const result = execSync('npm pack --silent', { stdio: ['ignore', 'pipe', 'inherit'] })
|
|
16
|
+
.toString()
|
|
17
|
+
.trim();
|
|
18
|
+
|
|
19
|
+
if (!result || !result.endsWith('.tgz')) {
|
|
20
|
+
console.error('Failed to determine pack filename, got:', result);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Rename to chell.tgz
|
|
25
|
+
renameSync(join(process.cwd(), result), outPath);
|
|
26
|
+
console.log(`Created ${outName}`);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
console.error('pack-chell failed:', err?.message || err);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|