@cnwenf/occ 2.1.269 → 2.1.271
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 +5 -5
- package/README.zh-CN.md +3 -3
- package/bin/occ.cjs +203 -107
- package/dist/cli.js +35890 -35649
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@cnwenf/occ)
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
[](https://bun.sh/)
|
|
8
|
-
[](https://docs.anthropic.com/en/docs/claude-code)
|
|
9
9
|
|
|
10
10
|
[简体中文](./README.zh-CN.md) · **English**
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
## What is OCC
|
|
15
15
|
|
|
16
|
-
**Open C Code (OCC)** is an open-source coding agent. Its capabilities are aligned with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (currently tracking `2.1.
|
|
16
|
+
**Open C Code (OCC)** is an open-source coding agent. Its capabilities are aligned with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (currently tracking `2.1.211`). The code is fully open, auditable, backdoor-free, and your data stays under your control.
|
|
17
17
|
|
|
18
18
|
If you worry that a closed-source CLI might hide backdoors, or that your code and credentials are uploaded to unauditable services, OCC is for you: all source is open and unobfuscated, the build is reproducible from source, and API credentials are sent only to endpoints you configure.
|
|
19
19
|
|
|
@@ -62,7 +62,7 @@ Requires a valid Anthropic API Key (or AWS Bedrock / Google Vertex / Azure Found
|
|
|
62
62
|
| **Auditability** | Line-by-line reviewable | No |
|
|
63
63
|
| **Telemetry** | Minimal (analytics stubbed) | Standard |
|
|
64
64
|
| **Data sovereignty** | Credentials stay on your machine; requests only to endpoints you configure | Anthropic endpoints |
|
|
65
|
-
| **Capability parity** | Tracks CC `2.1.
|
|
65
|
+
| **Capability parity** | Tracks CC `2.1.211` | Reference implementation |
|
|
66
66
|
| **Providers** | Anthropic Direct, Bedrock, Vertex, Azure | Anthropic, Bedrock, Vertex |
|
|
67
67
|
| **Cost** | Free & open-source (MIT) | Subscription |
|
|
68
68
|
| **Build** | Reproducible from source | N/A |
|
|
@@ -143,7 +143,7 @@ Requires [Bun](https://bun.sh/) >= 1.3.11 (use `bun upgrade` — older Bun cause
|
|
|
143
143
|
|
|
144
144
|
```bash
|
|
145
145
|
bun install
|
|
146
|
-
bun run dev # run from source; version prints 2.1.
|
|
146
|
+
bun run dev # run from source; version prints 2.1.270 (dev polyfill; build overrides with pkg.version) when working
|
|
147
147
|
bun run build # output: dist/cli.js (~26 MB, single-file bundle)
|
|
148
148
|
bun test # test suite (Bun test runner)
|
|
149
149
|
bun run lint # Biome lint (formatter disabled to avoid large diffs)
|
|
@@ -157,7 +157,7 @@ For architecture, entry/bootstrap, tool system, UI layer, and module-status deta
|
|
|
157
157
|
|
|
158
158
|
## Status
|
|
159
159
|
|
|
160
|
-
- Tracks Claude Code **`2.1.
|
|
160
|
+
- Tracks Claude Code **`2.1.211`**.
|
|
161
161
|
- Published to npm as [`@cnwenf/occ`](https://www.npmjs.com/package/@cnwenf/occ).
|
|
162
162
|
- Many modules are intentionally stubbed or feature-flagged off — see "Disabled / stubbed" above.
|
|
163
163
|
|
package/README.zh-CN.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## 这是什么
|
|
10
10
|
|
|
11
|
-
**Open C Code(OCC)** 是一个开源的编码智能体。能力与 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 对齐(当前跟踪 `2.1.
|
|
11
|
+
**Open C Code(OCC)** 是一个开源的编码智能体。能力与 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 对齐(当前跟踪 `2.1.211`)。代码全开放、可审计、无暗门,数据由你掌控。
|
|
12
12
|
|
|
13
13
|
如果你担心闭源 CLI 可能植入后门、担心代码与凭据被上传到不可审计的服务,OCC 就是为你准备的:全部源码开放、无混淆,构建产物可由源码复现,API 凭据只发往你自己配置的端点。
|
|
14
14
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
## 现状
|
|
23
23
|
|
|
24
|
-
- 跟踪 Claude Code **`2.1.
|
|
24
|
+
- 跟踪 Claude Code **`2.1.211`**。
|
|
25
25
|
- 代码库有约 1300 个不阻塞的 `tsc` 类型错误(大量松散的 `unknown`/`never`/`{}` 类型),**不影响 Bun 运行时执行**。门槛是 Biome lint,不是 `tsc`。
|
|
26
26
|
- 所有内部 feature flag(`feature(...)`)已被 polyfill 为 `false` —— 内部功能(COORDINATOR_MODE、KAIROS、PROACTIVE 等)全部关闭。
|
|
27
27
|
- 已发布到 npm:[`@cnwenf/occ`](https://www.npmjs.com/package/@cnwenf/occ)。
|
|
@@ -80,7 +80,7 @@ Glob、Grep(默认启用);TaskCreate/Get/Update/List(Todo v2)、EnterW
|
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
82
|
bun install
|
|
83
|
-
bun run dev # 从源码运行;版本号显示 2.1.
|
|
83
|
+
bun run dev # 从源码运行;版本号显示 2.1.270(dev polyfill;build 用 pkg.version 覆盖)即正常
|
|
84
84
|
bun run build # 产物:dist/cli.js(~26MB,5300+ 模块,单文件 bundle)
|
|
85
85
|
bun test # 测试套件
|
|
86
86
|
bun run lint # Biome lint(禁用格式化以避免大 diff)
|
package/bin/occ.cjs
CHANGED
|
@@ -15,25 +15,47 @@
|
|
|
15
15
|
* `bun <package>/dist/cli.js <args…>`. If no Bun is available it prints
|
|
16
16
|
* a clear install instruction instead of a cryptic env error.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
18
|
+
* WHY PROBE-RUN + LIBC DETECTION
|
|
19
|
+
* `bun` is an OCC *optional* dependency. npm does NOT link an optional
|
|
20
|
+
* dependency's `bin` into the global bin dir, so `bun` is NOT on PATH
|
|
21
|
+
* after `npm i -g @cnwenf/occ` — the shim must rely on the bundled
|
|
22
|
+
* `@oven/bun-*` platform binaries (and the `bun` meta-package's
|
|
23
|
+
* postinstall-selected `bin/bun.exe`).
|
|
24
|
+
*
|
|
25
|
+
* The `bun` meta-package ships platform binaries for BOTH glibc and musl
|
|
26
|
+
* variants without an `os.libc` filter, so npm installs ALL of them on
|
|
27
|
+
* every Linux host. A musl ELF's interpreter is `/lib/ld-musl-x86_64.so.1`,
|
|
28
|
+
* which does NOT exist on a glibc host — spawning it fails with ENOENT.
|
|
29
|
+
* Older versions of this shim picked the first `existsSync`-true candidate
|
|
30
|
+
* in a fixed order (glibc, musl, …); when the glibc tarball's `bin/bun`
|
|
31
|
+
* was absent (the `bun` postinstall moves it) the musl binary was picked
|
|
32
|
+
* next, `existsSync`'d true, then ENOENT'd at spawn — `occ` died with
|
|
33
|
+
* `failed to launch bun`.
|
|
34
|
+
*
|
|
35
|
+
* The fix mirrors the official `@anthropic-ai/claude-code` cli-wrapper:
|
|
36
|
+
* detect the host's libc (`process.report` glibcVersionRuntime), restrict
|
|
37
|
+
* candidates to the MATCHING libc only, and PROBE-RUN each candidate
|
|
38
|
+
* (`<bin> --version`) before committing — a present-but-unrunnable binary
|
|
39
|
+
* is skipped, not fatal.
|
|
40
|
+
*
|
|
41
|
+
* BUN RESOLUTION ORDER (each existing candidate is probe-run; first success wins)
|
|
19
42
|
* 1. `$BUN_PATH` env (power-user override)
|
|
20
|
-
* 2. `bun` on PATH (
|
|
21
|
-
* whose postinstall puts the real binary on PATH)
|
|
43
|
+
* 2. `bun` on PATH (explicit PATH walk — npm does not link it for optional deps)
|
|
22
44
|
* 3. `~/.bun/bin/bun` (user installed Bun via bun.sh installer)
|
|
23
|
-
* 4. The
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
45
|
+
* 4. The `bun` meta-package's `bin/bun.exe` — the meta postinstall already
|
|
46
|
+
* detected the host and placed the correct (arch + libc) binary here.
|
|
47
|
+
* 5. The `@oven/bun-<platform>-<arch>[-musl][-baseline]` platform binary
|
|
48
|
+
* matching the host's libc, non-baseline (AVX2) before baseline. This
|
|
49
|
+
* path works EVEN WHEN npm was run with `--ignore-scripts` (so the
|
|
50
|
+
* `bun` postinstall never ran and #4 is absent), because the `@oven-*`
|
|
51
|
+
* tarballs ship the real ELF/Mach-O/PE binary — no postinstall needed.
|
|
30
52
|
*
|
|
31
|
-
* If none
|
|
53
|
+
* If none probe-run successfully, print install instructions and exit 1.
|
|
32
54
|
*/
|
|
33
55
|
'use strict'
|
|
34
56
|
|
|
35
57
|
const { existsSync } = require('node:fs')
|
|
36
|
-
const { spawn } = require('node:child_process')
|
|
58
|
+
const { spawn, spawnSync } = require('node:child_process')
|
|
37
59
|
const path = require('node:path')
|
|
38
60
|
const os = require('node:os')
|
|
39
61
|
|
|
@@ -51,41 +73,105 @@ if (!existsSync(cliJs)) {
|
|
|
51
73
|
}
|
|
52
74
|
|
|
53
75
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* on
|
|
58
|
-
|
|
76
|
+
* Detect a musl-libc Linux host the same way the official
|
|
77
|
+
* `@anthropic-ai/claude-code` cli-wrapper does: Node's runtime report sets
|
|
78
|
+
* `header.glibcVersionRuntime` only when running against glibc. Its absence
|
|
79
|
+
* (on Alpine/musl, or when the report is unavailable) means musl.
|
|
80
|
+
*/
|
|
81
|
+
function detectMusl() {
|
|
82
|
+
if (process.platform !== 'linux') return false
|
|
83
|
+
try {
|
|
84
|
+
const report =
|
|
85
|
+
typeof process.report?.getReport === 'function'
|
|
86
|
+
? process.report.getReport()
|
|
87
|
+
: null
|
|
88
|
+
if (!report) return false
|
|
89
|
+
return report.header?.glibcVersionRuntime === undefined
|
|
90
|
+
} catch (_) {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The @oven/bun-<platform>-<arch> packages that match the CURRENT process,
|
|
97
|
+
* restricted to the host's libc (glibc OR musl, never both) and ordered
|
|
98
|
+
* non-baseline (AVX2, faster) before baseline (compatible fallback). Each
|
|
99
|
+
* ships the real Bun binary at `bin/bun` (or `bin/bun.exe` on Windows).
|
|
100
|
+
* List gleaned from the `bun` npm meta-package's optionalDependencies
|
|
101
|
+
* (@oven 1.3.14).
|
|
102
|
+
*
|
|
103
|
+
* Restricting to one libc is the whole point: a glibc host must never
|
|
104
|
+
* consider a musl ELF (its `/lib/ld-musl-x86_64.so.1` interpreter is absent
|
|
105
|
+
* → ENOENT at spawn), and vice versa.
|
|
59
106
|
*/
|
|
60
107
|
function platformPackages() {
|
|
61
108
|
const p = process.platform
|
|
62
109
|
const a = process.arch
|
|
110
|
+
const musl = detectMusl()
|
|
63
111
|
if (p === 'darwin' && a === 'x64') return ['@oven/bun-darwin-x64']
|
|
64
112
|
if (p === 'darwin' && a === 'arm64') return ['@oven/bun-darwin-aarch64']
|
|
65
|
-
if (p === 'linux' && a === 'x64')
|
|
66
|
-
|
|
67
|
-
'@oven/bun-linux-x64',
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
]
|
|
72
|
-
|
|
73
|
-
|
|
113
|
+
if (p === 'linux' && a === 'x64') {
|
|
114
|
+
if (musl)
|
|
115
|
+
return ['@oven/bun-linux-x64-musl', '@oven/bun-linux-x64-musl-baseline']
|
|
116
|
+
return ['@oven/bun-linux-x64', '@oven/bun-linux-x64-baseline']
|
|
117
|
+
}
|
|
118
|
+
if (p === 'linux' && a === 'arm64') {
|
|
119
|
+
if (musl) return ['@oven/bun-linux-aarch64-musl']
|
|
120
|
+
return ['@oven/bun-linux-aarch64']
|
|
121
|
+
}
|
|
74
122
|
if (p === 'win32' && a === 'x64') return ['@oven/bun-windows-x64']
|
|
75
123
|
if (p === 'win32' && a === 'arm64') return ['@oven/bun-windows-aarch64']
|
|
76
124
|
return []
|
|
77
125
|
}
|
|
78
126
|
|
|
79
|
-
/**
|
|
80
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Resolve a dependency PACKAGE DIRECTORY via its package.json (always
|
|
129
|
+
* resolvable — `package.json` is exempt from `exports` restrictions), then
|
|
130
|
+
* join the in-package relative path. This is the reliable way to locate a
|
|
131
|
+
* bundled binary: `require.resolve('pkg/bin/bun')` fails when the binary
|
|
132
|
+
* file is absent (postinstall hasn't created/moved it yet) or when the
|
|
133
|
+
* package restricts subpath access — both false negatives that broke the
|
|
134
|
+
* old shim. Returns null if the package or file is not present.
|
|
135
|
+
*/
|
|
136
|
+
function resolveDepFile(spec, relPath) {
|
|
81
137
|
try {
|
|
82
|
-
|
|
138
|
+
// Resolve the package DIRECTORY via its package.json (always resolvable
|
|
139
|
+
// — `package.json` is exempt from `exports` restrictions). Resolving the
|
|
140
|
+
// bare package name would fail for packages with no `main`/`exports`
|
|
141
|
+
// (e.g. the `bun` meta-package and the `@oven/bun-*` binaries).
|
|
142
|
+
const pkgJson = require.resolve(spec + '/package.json')
|
|
143
|
+
const file = path.join(path.dirname(pkgJson), relPath)
|
|
144
|
+
return existsSync(file) ? file : null
|
|
83
145
|
} catch (_) {
|
|
84
146
|
return null
|
|
85
147
|
}
|
|
86
148
|
}
|
|
87
149
|
|
|
88
|
-
/**
|
|
150
|
+
/**
|
|
151
|
+
* Walk PATH for an executable named `name` (with Windows PATHEXT extensions
|
|
152
|
+
* on win32). Returns the absolute path if found, else null.
|
|
153
|
+
*/
|
|
154
|
+
function findOnPath(name) {
|
|
155
|
+
const pathVar = process.env.PATH || process.env.Path
|
|
156
|
+
if (!pathVar) return null
|
|
157
|
+
const sep = isWin ? ';' : ':'
|
|
158
|
+
const exts = isWin
|
|
159
|
+
? (process.env.PATHEXT ? process.env.PATHEXT.split(';') : ['.exe', '.cmd', '.bat', ''])
|
|
160
|
+
: ['']
|
|
161
|
+
for (const dir of pathVar.split(sep)) {
|
|
162
|
+
if (!dir) continue
|
|
163
|
+
for (const ext of exts) {
|
|
164
|
+
const candidate = path.join(dir, name + ext)
|
|
165
|
+
if (existsSync(candidate)) return candidate
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return null
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Ordered candidate Bun binaries. Each entry is an absolute path. Existence
|
|
173
|
+
* is checked at build time; runnability is probe-verified later in selectBun().
|
|
174
|
+
*/
|
|
89
175
|
function bunCandidates() {
|
|
90
176
|
const cands = []
|
|
91
177
|
|
|
@@ -94,111 +180,121 @@ function bunCandidates() {
|
|
|
94
180
|
cands.push(process.env.BUN_PATH)
|
|
95
181
|
}
|
|
96
182
|
|
|
97
|
-
// 2. `bun` on PATH — verified
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
|
|
183
|
+
// 2. `bun` on PATH — verified via an explicit PATH walk (npm does not
|
|
184
|
+
// link an optional dependency's bin globally, so this only matches when
|
|
185
|
+
// the user installed Bun separately).
|
|
186
|
+
const pathBun = findOnPath(bunExeName)
|
|
187
|
+
if (pathBun) cands.push(pathBun)
|
|
101
188
|
|
|
102
189
|
// 3. ~/.bun/bin/bun (bun.sh installer default location).
|
|
103
190
|
const homeBun = path.join(os.homedir(), '.bun', 'bin', bunExeName)
|
|
104
191
|
if (existsSync(homeBun)) cands.push(homeBun)
|
|
105
192
|
|
|
106
|
-
// 4.
|
|
193
|
+
// 4. `bun` meta-package bin — postinstall-selected for this host. The
|
|
194
|
+
// meta package always names it `bin/bun.exe` regardless of platform.
|
|
195
|
+
const metaBin = resolveDepFile('bun', path.posix.join('bin', 'bun.exe'))
|
|
196
|
+
if (metaBin) cands.push(metaBin)
|
|
197
|
+
|
|
198
|
+
// 5. Optional-dep platform binary (robust under --ignore-scripts); one
|
|
199
|
+
// libc only, non-baseline before baseline.
|
|
107
200
|
for (const pkg of platformPackages()) {
|
|
108
|
-
const resolved = resolveDepFile(path.posix.join(
|
|
109
|
-
if (resolved
|
|
201
|
+
const resolved = resolveDepFile(pkg, path.posix.join('bin', bunExeName))
|
|
202
|
+
if (resolved) cands.push(resolved)
|
|
110
203
|
}
|
|
111
204
|
|
|
112
|
-
// 5. `bun` meta-package bin (real only if its postinstall ran).
|
|
113
|
-
const metaBin = resolveDepFile('bun/bin/bun.exe')
|
|
114
|
-
if (metaBin && existsSync(metaBin)) cands.push(metaBin)
|
|
115
|
-
|
|
116
205
|
return cands
|
|
117
206
|
}
|
|
118
207
|
|
|
119
208
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
209
|
+
* Probe-run a candidate Bun binary: `spawnSync(<bin>, ['--version'])` with a
|
|
210
|
+
* short timeout. Returns true only if the binary actually launched AND
|
|
211
|
+
* exited 0 — i.e. it is executable on THIS host. This is the signal that
|
|
212
|
+
* `existsSync` cannot give: a present musl ELF on a glibc host `existsSync`'s
|
|
213
|
+
* true but ENOENTs at spawn (missing `/lib/ld-musl-x86_64.so.1`); a
|
|
214
|
+
* non-baseline binary needing a newer glibc ditto. Probing lets the shim
|
|
215
|
+
* fall through to the next candidate instead of dying.
|
|
125
216
|
*/
|
|
126
|
-
function
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
217
|
+
function probeRuns(bin) {
|
|
218
|
+
try {
|
|
219
|
+
const r = spawnSync(bin, ['--version'], {
|
|
220
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
221
|
+
timeout: 5000,
|
|
222
|
+
windowsHide: true,
|
|
223
|
+
shell: false,
|
|
224
|
+
})
|
|
225
|
+
if (r.error) return false
|
|
226
|
+
return r.status === 0
|
|
227
|
+
} catch (_) {
|
|
228
|
+
return false
|
|
139
229
|
}
|
|
140
|
-
return null
|
|
141
230
|
}
|
|
142
231
|
|
|
143
|
-
function
|
|
232
|
+
function selectBun() {
|
|
144
233
|
const tried = []
|
|
145
234
|
for (const c of bunCandidates()) {
|
|
146
235
|
if (!c) continue
|
|
147
236
|
tried.push(c)
|
|
148
|
-
|
|
149
|
-
// #3/#4/#5 fallbacks get a chance when it isn't — otherwise we'd return
|
|
150
|
-
// a phantom 'bun' that ENOENTs at spawn, defeating the shim's purpose.
|
|
151
|
-
if (c === 'bun') {
|
|
152
|
-
if (findOnPath(bunExeName)) return { bin: c, viaShell: isWin, tried }
|
|
153
|
-
continue
|
|
154
|
-
}
|
|
155
|
-
if (existsSync(c)) return { bin: c, viaShell: false, tried }
|
|
237
|
+
if (probeRuns(c)) return { bin: c, viaShell: false, tried }
|
|
156
238
|
}
|
|
157
239
|
return { bin: null, viaShell: false, tried }
|
|
158
240
|
}
|
|
159
241
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
console.error('Tried: ' + tried.join(', '))
|
|
172
|
-
process.exit(1)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const child = spawn(bunBin, [cliJs, ...process.argv.slice(2)], {
|
|
176
|
-
stdio: 'inherit',
|
|
177
|
-
env: process.env,
|
|
178
|
-
shell: viaShell,
|
|
179
|
-
windowsHide: false,
|
|
180
|
-
})
|
|
242
|
+
/**
|
|
243
|
+
* Locate a working Bun binary and spawn `bun dist/cli.js <args…>`, inheriting
|
|
244
|
+
* stdio so the child REPL/pipe owns the terminal. Exits the process with the
|
|
245
|
+
* child's code/signal, or 1 on a launch error / no-binary-found.
|
|
246
|
+
*
|
|
247
|
+
* Hoisted into a function (and only invoked when this file is the entry point)
|
|
248
|
+
* so the pure helpers above can be unit-tested via `require('./bin/occ.cjs')`
|
|
249
|
+
* without the shim auto-spawning a child on import.
|
|
250
|
+
*/
|
|
251
|
+
function launch() {
|
|
252
|
+
const { bin: bunBin, viaShell, tried } = selectBun()
|
|
181
253
|
|
|
182
|
-
|
|
183
|
-
|
|
254
|
+
if (!bunBin) {
|
|
255
|
+
console.error('')
|
|
256
|
+
console.error('occ: Bun runtime not found.')
|
|
184
257
|
console.error('')
|
|
185
|
-
console.error('
|
|
258
|
+
console.error('OCC requires Bun (>= 1.3.11) to run. Install it with one of:')
|
|
186
259
|
console.error(' npm i -g bun')
|
|
187
260
|
console.error(' curl -fsSL https://bun.sh/install | bash')
|
|
261
|
+
console.error('Then run `occ` again.')
|
|
262
|
+
console.error('')
|
|
263
|
+
console.error('Tried: ' + (tried.length ? tried.join(', ') : '(no bundled bun found)'))
|
|
188
264
|
process.exit(1)
|
|
189
265
|
}
|
|
190
|
-
|
|
191
|
-
process.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
266
|
+
|
|
267
|
+
const child = spawn(bunBin, [cliJs, ...process.argv.slice(2)], {
|
|
268
|
+
stdio: 'inherit',
|
|
269
|
+
env: process.env,
|
|
270
|
+
shell: viaShell,
|
|
271
|
+
windowsHide: false,
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
child.on('error', (err) => {
|
|
275
|
+
console.error('occ: failed to launch bun:', err ? err.message : 'unknown error')
|
|
276
|
+
console.error(' binary: ' + bunBin)
|
|
277
|
+
process.exit(1)
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
child.on('exit', (code, signal) => {
|
|
281
|
+
if (signal) {
|
|
282
|
+
try {
|
|
283
|
+
process.kill(process.pid, signal)
|
|
284
|
+
} catch (_) {
|
|
285
|
+
process.exit(1)
|
|
286
|
+
}
|
|
287
|
+
return
|
|
200
288
|
}
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
289
|
+
process.exit(code ?? 0)
|
|
290
|
+
})
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Pure helpers exported for unit tests (see test/launcher.test.ts). When this
|
|
294
|
+
// file is the entry point (`occ` invoked on the CLI), run the launcher; when
|
|
295
|
+
// it is merely required, do nothing — no spawn side effect on import.
|
|
296
|
+
module.exports = { detectMusl, platformPackages, resolveDepFile, findOnPath, bunCandidates, probeRuns, selectBun }
|
|
297
|
+
|
|
298
|
+
if (require.main === module) {
|
|
299
|
+
launch()
|
|
300
|
+
}
|