@auroraflow/code 0.0.6 → 0.0.8
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 +67 -189
- package/bin/aurora-claude.js +4 -0
- package/bin/aurora-codex.js +4 -0
- package/bin/aurora-postinstall.js +24 -0
- package/bin/aurora-sidecar.js +4 -0
- package/bin/aurora.js +2 -382
- package/lib/aurora-api.js +100 -0
- package/lib/commands.js +27 -0
- package/lib/launcher.js +9 -0
- package/lib/pickers.js +137 -0
- package/lib/prompt.js +136 -0
- package/lib/sidecar-client.js +10 -0
- package/lib/sidecar.js +1 -0
- package/lib/state.js +1 -0
- package/package.json +20 -24
- package/packages/cli/package.json +9 -0
- package/packages/cli/src/index.js +135 -0
- package/packages/clients/package.json +9 -0
- package/packages/clients/src/index.js +299 -0
- package/packages/protocol/package.json +9 -0
- package/packages/protocol/src/index.js +170 -0
- package/packages/protocol/src/index.test.js +180 -0
- package/packages/sidecar/package.json +9 -0
- package/packages/sidecar/src/index.js +177 -0
- package/packages/state/package.json +9 -0
- package/packages/state/src/index.js +57 -0
- package/scripts/install_posix_launcher.js +0 -106
package/README.md
CHANGED
|
@@ -1,189 +1,67 @@
|
|
|
1
|
-
# Aurora
|
|
2
|
-
|
|
3
|
-
Aurora
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
##
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- 避免在核心代码里做大范围品牌替换。
|
|
69
|
-
- Aurora 专属逻辑放到清晰命名的 adapter / integration 模块。
|
|
70
|
-
- 保持 Aurora patch 小、集中、可 review,便于上游更新后重新合并。
|
|
71
|
-
- 模型目录和 key 选择使用结构化字段,不把 Aurora 元数据塞进展示文本再解析。
|
|
72
|
-
|
|
73
|
-
## 长期二开边界
|
|
74
|
-
|
|
75
|
-
本项目的长期维护基线是:
|
|
76
|
-
|
|
77
|
-
> Codex core + Aurora identity/model/key/runtime adapter + Aurora distribution。
|
|
78
|
-
|
|
79
|
-
也就是说,本仓库不是“全仓改名版 Codex”,而是在尽量保留 Codex 核心结构的前提下,把 Aurora 必须拥有的产品接入面替换掉。
|
|
80
|
-
|
|
81
|
-
### 必须二开的范围
|
|
82
|
-
|
|
83
|
-
以下范围属于 Aurora 产品边界,应由本项目长期维护。
|
|
84
|
-
|
|
85
|
-
1. 品牌与分发层
|
|
86
|
-
|
|
87
|
-
- CLI 命令名:`aurora`。
|
|
88
|
-
- npm / Python / 其他发布包名。
|
|
89
|
-
- 安装脚本、平台二进制包、release artifact 命名。
|
|
90
|
-
- 面向用户的 Aurora 产品文案。
|
|
91
|
-
|
|
92
|
-
2. 登录与身份体系
|
|
93
|
-
|
|
94
|
-
- Aurora 账号登录。
|
|
95
|
-
- Aurora session / token 存储。
|
|
96
|
-
- Aurora API key reveal / create / select。
|
|
97
|
-
- 移除默认 Codex/OpenAI 登录入口;除非明确设定兼容期,不保留旧登录路径并行支持。
|
|
98
|
-
|
|
99
|
-
3. Aurora Key 选择
|
|
100
|
-
|
|
101
|
-
- 先选择 key 类型:`personal`、`platform`、`org`、`market`。
|
|
102
|
-
- 再选择或创建具体 key。
|
|
103
|
-
- 持久化运行时请求所需的 key 元数据。
|
|
104
|
-
- 客户端只做交互所需判断,资源池和权限判定以 Aurora 后端为准。
|
|
105
|
-
|
|
106
|
-
4. Aurora 模型目录与模型选择器
|
|
107
|
-
|
|
108
|
-
- 使用 Aurora 模型目录接口。
|
|
109
|
-
- 模型选择器采用 provider -> model 两级选择。
|
|
110
|
-
- 运行时请求发送 Aurora 后端要求的 alias / model id。
|
|
111
|
-
- 模型元数据必须是结构化字段,不通过解析展示文本获得业务字段。
|
|
112
|
-
|
|
113
|
-
5. Aurora runtime 接入
|
|
114
|
-
|
|
115
|
-
- 运行时请求走 Aurora endpoint。
|
|
116
|
-
- 长期优先使用 `POST /v1/responses` 作为标准请求入口。
|
|
117
|
-
- 鉴权使用已选 Aurora key。
|
|
118
|
-
- Codex core 产生的请求语义应通过 Aurora adapter 转换,不在 core 里散落 Aurora 特例。
|
|
119
|
-
|
|
120
|
-
### 尽量不动的范围
|
|
121
|
-
|
|
122
|
-
以下范围主要承接上游 Codex 能力,应尽量保持接近 upstream,只有 Aurora 接入必须触及时才改。
|
|
123
|
-
|
|
124
|
-
1. Agent 核心循环
|
|
125
|
-
|
|
126
|
-
- session / turn orchestration
|
|
127
|
-
- context 构建与压缩
|
|
128
|
-
- tool call 生命周期
|
|
129
|
-
- rollout / resume / history 机制
|
|
130
|
-
|
|
131
|
-
2. 通用工具与执行能力
|
|
132
|
-
|
|
133
|
-
- shell / exec / sandbox
|
|
134
|
-
- apply_patch
|
|
135
|
-
- MCP server / MCP client
|
|
136
|
-
- skills / plugins
|
|
137
|
-
- file search / file watcher
|
|
138
|
-
|
|
139
|
-
3. 通用协议模型
|
|
140
|
-
|
|
141
|
-
- Codex 内部 protocol 基础类型。
|
|
142
|
-
- OpenAI Responses / ChatGPT 相关结构在仍被上游 core 使用时不做无意义改名。
|
|
143
|
-
- 只在 Aurora 后端契约确实不同的时候新增 adapter 或结构化扩展。
|
|
144
|
-
|
|
145
|
-
4. TUI 通用交互
|
|
146
|
-
|
|
147
|
-
- 聊天主界面。
|
|
148
|
-
- 底部输入框。
|
|
149
|
-
- 历史、diff、审批、工具展示。
|
|
150
|
-
- 只替换登录、模型选择、key 选择等 Aurora 产品面。
|
|
151
|
-
|
|
152
|
-
5. 上游测试、CI 和构建基础设施
|
|
153
|
-
|
|
154
|
-
- 除发布包名、安装路径、artifact 命名外,不主动重写 CI 结构。
|
|
155
|
-
- 继续使用上游测试习惯和格式化规则。
|
|
156
|
-
|
|
157
|
-
### 每次改动的边界判断
|
|
158
|
-
|
|
159
|
-
每个 PR 或开发任务开始前,先判断改动属于哪一类:
|
|
160
|
-
|
|
161
|
-
- 属于 Aurora 账号、模型、key、runtime endpoint、包分发:可以进入 Aurora patch。
|
|
162
|
-
- 属于 agent 推理循环、通用工具、MCP、sandbox、TUI 通用能力:优先保持 upstream;必须修改时先收敛为小 adapter。
|
|
163
|
-
- 属于纯品牌替换但会扩大 diff:默认不做。
|
|
164
|
-
- 属于上游 bug 或通用能力改进:优先评估是否应该以 upstream-compatible 的方式实现,避免 Aurora 私有分叉扩大。
|
|
165
|
-
|
|
166
|
-
长期目标是让 Aurora patch 面积稳定、可解释、可重放。每次合并上游 Codex 时,应优先解决这些明确边界内的冲突,避免把临时兼容逻辑扩散到 core。
|
|
167
|
-
|
|
168
|
-
## Aurora 接入面
|
|
169
|
-
|
|
170
|
-
预期依赖的 Aurora 后端接口:
|
|
171
|
-
|
|
172
|
-
- `POST /api/v1/auth/login`
|
|
173
|
-
- `GET /api/v1/aurora-cli/api-keys`
|
|
174
|
-
- `POST /api/v1/aurora-cli/api-keys`
|
|
175
|
-
- `POST /api/v1/aurora-cli/api-keys/{id}/reveal`
|
|
176
|
-
- `GET /v1/aurora-cli/models`
|
|
177
|
-
|
|
178
|
-
模型目录接口应返回结构化的 `provider`、`model_id`、`alias` 等字段,客户端不应通过解析展示文本获取业务字段。
|
|
179
|
-
|
|
180
|
-
## 非目标
|
|
181
|
-
|
|
182
|
-
- 不重写 Codex 核心 agent 行为。
|
|
183
|
-
- Aurora auth 接入后,不保留旧 Codex/OpenAI 登录流程的兼容分支,除非明确需要兼容期。
|
|
184
|
-
- 不为了品牌统一而全仓重命名内部符号,如果这会显著增加上游合并成本。
|
|
185
|
-
- 不在客户端重复实现 Aurora 后端 domain 规则;客户端只保留交互所需的最小判断。
|
|
186
|
-
|
|
187
|
-
## 当前状态
|
|
188
|
-
|
|
189
|
-
当前仓库已经导入最新 Codex `main` 作为基线。下一步是在不扩大 core diff 的前提下,依次叠加 Aurora 命令入口、身份、模型选择和 key 选择适配层。
|
|
1
|
+
# Aurora Code
|
|
2
|
+
|
|
3
|
+
Unified Aurora launcher for official Claude Code and Codex clients.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
packages/cli command entrypoints and init flow
|
|
9
|
+
packages/clients official Claude/Codex launch adapters
|
|
10
|
+
packages/sidecar local HTTP proxy for runtime traffic
|
|
11
|
+
packages/protocol shared rewrite/projection helpers
|
|
12
|
+
packages/state ~/.aurora state paths and JSON state
|
|
13
|
+
bin/ npm bin shims
|
|
14
|
+
lib/ current MVP support modules
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
Installing `@auroraflow/code` as a global npm package attempts to install/update the
|
|
20
|
+
official Claude Code and Codex global commands:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g @auroraflow/code
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Aurora does not export `claude` or `codex` bins. The standalone `claude` and
|
|
27
|
+
`codex` commands remain the official clients and keep their official behavior.
|
|
28
|
+
Aurora only wraps them through `aurora-claude` and `aurora-codex`.
|
|
29
|
+
|
|
30
|
+
To install or update the official clients explicitly:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
aurora install-clients
|
|
34
|
+
aurora update-clients
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Commands
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm run check
|
|
41
|
+
scripts/release_npm.sh 0.0.7
|
|
42
|
+
node bin/aurora.js
|
|
43
|
+
node bin/aurora.js init
|
|
44
|
+
node bin/aurora.js claude
|
|
45
|
+
node bin/aurora.js codex
|
|
46
|
+
node bin/aurora.js install-clients
|
|
47
|
+
node bin/aurora.js update-clients
|
|
48
|
+
node bin/aurora.js status
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Running `aurora` without a subcommand opens an interactive client selector. Use
|
|
52
|
+
Up/Down (or `j`/`k`) and Enter to launch Claude or Codex through Aurora.
|
|
53
|
+
|
|
54
|
+
The launcher stores shared local state under `~/.aurora` and starts a local
|
|
55
|
+
sidecar at `127.0.0.1:17878`. Official clients talk to the sidecar; the sidecar
|
|
56
|
+
injects the selected Aurora key/model and forwards runtime traffic to Aurora
|
|
57
|
+
Gateway.
|
|
58
|
+
|
|
59
|
+
The Aurora desktop client is the product path for model/key selection. Its local
|
|
60
|
+
runtime workbench writes `~/.aurora/agent-state.json`; `aurora-claude` and
|
|
61
|
+
`aurora-codex` only consume that local runtime state and route official client
|
|
62
|
+
traffic through the sidecar. The clients are launched with the selected Aurora
|
|
63
|
+
model alias, and the sidecar enforces the same selected alias when forwarding
|
|
64
|
+
runtime requests.
|
|
65
|
+
`aurora-codex` also writes `~/.aurora/clients/codex/config.toml` and
|
|
66
|
+
`auth.json` before launch so Codex uses the Aurora sidecar provider instead of
|
|
67
|
+
the OpenAI login flow.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { installOfficialClients, isGlobalNpmLifecycle, officialClientStatuses } from "../packages/clients/src/index.js";
|
|
3
|
+
|
|
4
|
+
if (!process.env.AURORA_SKIP_OFFICIAL_CLIENT_INSTALL && isGlobalNpmLifecycle()) {
|
|
5
|
+
try {
|
|
6
|
+
await installOfficialClients();
|
|
7
|
+
} catch (error) {
|
|
8
|
+
console.error(`[aurora-code] official client install failed: ${error.message}`);
|
|
9
|
+
console.error("[aurora-code] run `aurora install-clients` after installation.");
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const statuses = officialClientStatuses();
|
|
14
|
+
const missing = statuses.filter((status) => !status.installed);
|
|
15
|
+
|
|
16
|
+
for (const status of statuses) {
|
|
17
|
+
const version = status.version ? ` ${status.version}` : "";
|
|
18
|
+
const marker = status.installed ? "installed" : "missing";
|
|
19
|
+
console.error(`[aurora-code] ${status.name}${version}: ${marker}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (missing.length) {
|
|
23
|
+
console.error("[aurora-code] run `aurora install-clients` to install official standalone commands.");
|
|
24
|
+
}
|
package/bin/aurora.js
CHANGED
|
@@ -1,384 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
import { runAuroraCLI } from "../packages/cli/src/index.js";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
createReadStream,
|
|
7
|
-
createWriteStream,
|
|
8
|
-
existsSync,
|
|
9
|
-
mkdirSync,
|
|
10
|
-
readFileSync,
|
|
11
|
-
realpathSync,
|
|
12
|
-
rmSync,
|
|
13
|
-
} from "fs";
|
|
14
|
-
import { createRequire } from "node:module";
|
|
15
|
-
import { createHash } from "node:crypto";
|
|
16
|
-
import { get as httpsGet } from "node:https";
|
|
17
|
-
import { homedir, tmpdir } from "node:os";
|
|
18
|
-
import path from "path";
|
|
19
|
-
import { fileURLToPath } from "url";
|
|
20
|
-
|
|
21
|
-
// __dirname equivalent in ESM
|
|
22
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
23
|
-
const __dirname = path.dirname(__filename);
|
|
24
|
-
const require = createRequire(import.meta.url);
|
|
25
|
-
const packageRoot = path.join(__dirname, "..");
|
|
26
|
-
const packageVersion = require(path.join(packageRoot, "package.json")).version;
|
|
27
|
-
const downloadBaseUrl = "https://downloads.auroramos.com";
|
|
28
|
-
const terminalTitle = "aurora";
|
|
29
|
-
|
|
30
|
-
process.title = terminalTitle;
|
|
31
|
-
|
|
32
|
-
function writeTerminalTitle(title) {
|
|
33
|
-
if (!process.stdout.isTTY) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const sanitized = title.replace(/[\x00-\x1f\x7f\x9b\x9c]/g, "").trim();
|
|
37
|
-
if (!sanitized) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
process.stdout.write(`\x1b]0;${sanitized}\x07`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const PLATFORM_PACKAGE_BY_TARGET = {
|
|
44
|
-
"x86_64-unknown-linux-gnu": "@auroraflow/code-linux-x64",
|
|
45
|
-
"aarch64-unknown-linux-gnu": "@auroraflow/code-linux-arm64",
|
|
46
|
-
"x86_64-apple-darwin": "@auroraflow/code-darwin-x64",
|
|
47
|
-
"aarch64-apple-darwin": "@auroraflow/code-darwin-arm64",
|
|
48
|
-
"x86_64-pc-windows-msvc": "@auroraflow/code-win32-x64",
|
|
49
|
-
"aarch64-pc-windows-msvc": "@auroraflow/code-win32-arm64",
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const { platform, arch } = process;
|
|
53
|
-
|
|
54
|
-
let targetTriple = null;
|
|
55
|
-
switch (platform) {
|
|
56
|
-
case "linux":
|
|
57
|
-
case "android":
|
|
58
|
-
switch (arch) {
|
|
59
|
-
case "x64":
|
|
60
|
-
targetTriple = "x86_64-unknown-linux-gnu";
|
|
61
|
-
break;
|
|
62
|
-
case "arm64":
|
|
63
|
-
targetTriple = "aarch64-unknown-linux-gnu";
|
|
64
|
-
break;
|
|
65
|
-
default:
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
break;
|
|
69
|
-
case "darwin":
|
|
70
|
-
switch (arch) {
|
|
71
|
-
case "x64":
|
|
72
|
-
targetTriple = "x86_64-apple-darwin";
|
|
73
|
-
break;
|
|
74
|
-
case "arm64":
|
|
75
|
-
targetTriple = "aarch64-apple-darwin";
|
|
76
|
-
break;
|
|
77
|
-
default:
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
break;
|
|
81
|
-
case "win32":
|
|
82
|
-
switch (arch) {
|
|
83
|
-
case "x64":
|
|
84
|
-
targetTriple = "x86_64-pc-windows-msvc";
|
|
85
|
-
break;
|
|
86
|
-
case "arm64":
|
|
87
|
-
targetTriple = "aarch64-pc-windows-msvc";
|
|
88
|
-
break;
|
|
89
|
-
default:
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
break;
|
|
93
|
-
default:
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (!targetTriple) {
|
|
98
|
-
throw new Error(`Unsupported platform: ${platform} (${arch})`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const platformPackage = PLATFORM_PACKAGE_BY_TARGET[targetTriple];
|
|
102
|
-
if (!platformPackage) {
|
|
103
|
-
throw new Error(`Unsupported target triple: ${targetTriple}`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const auroraBinaryName = process.platform === "win32" ? "aurora.exe" : "aurora";
|
|
107
|
-
const localVendorRoot = path.join(__dirname, "..", "vendor");
|
|
108
|
-
const packageBinaryPath = (vendorRoot) =>
|
|
109
|
-
path.join(vendorRoot, targetTriple, "bin", auroraBinaryName);
|
|
110
|
-
const legacyBinaryPath = (vendorRoot) =>
|
|
111
|
-
path.join(vendorRoot, targetTriple, "codex", process.platform === "win32" ? "codex.exe" : "codex");
|
|
112
|
-
|
|
113
|
-
function resolveNativePackage(vendorRoot) {
|
|
114
|
-
const packageRoot = path.join(vendorRoot, targetTriple);
|
|
115
|
-
const binaryPath = packageBinaryPath(vendorRoot);
|
|
116
|
-
if (existsSync(binaryPath)) {
|
|
117
|
-
return {
|
|
118
|
-
binaryPath,
|
|
119
|
-
pathDir: path.join(packageRoot, "aurora-path"),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const legacyPath = legacyBinaryPath(vendorRoot);
|
|
124
|
-
if (existsSync(legacyPath)) {
|
|
125
|
-
return {
|
|
126
|
-
binaryPath: legacyPath,
|
|
127
|
-
pathDir: path.join(packageRoot, "path"),
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function resolvePlatformNativePackage() {
|
|
135
|
-
try {
|
|
136
|
-
const packageJsonPath = require.resolve(`${platformPackage}/package.json`, {
|
|
137
|
-
paths: [packageRoot],
|
|
138
|
-
});
|
|
139
|
-
return resolveNativePackage(path.join(path.dirname(packageJsonPath), "vendor"));
|
|
140
|
-
} catch {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
let nativePackage =
|
|
146
|
-
resolvePlatformNativePackage() || resolveNativePackage(localVendorRoot);
|
|
147
|
-
|
|
148
|
-
async function downloadFile(url, destination) {
|
|
149
|
-
await new Promise((resolve, reject) => {
|
|
150
|
-
const file = createWriteStream(destination);
|
|
151
|
-
const request = httpsGet(url, (response) => {
|
|
152
|
-
if (
|
|
153
|
-
response.statusCode >= 300 &&
|
|
154
|
-
response.statusCode < 400 &&
|
|
155
|
-
response.headers.location
|
|
156
|
-
) {
|
|
157
|
-
file.close();
|
|
158
|
-
rmSync(destination, { force: true });
|
|
159
|
-
downloadFile(response.headers.location, destination)
|
|
160
|
-
.then(resolve)
|
|
161
|
-
.catch(reject);
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (response.statusCode !== 200) {
|
|
166
|
-
file.close();
|
|
167
|
-
rmSync(destination, { force: true });
|
|
168
|
-
reject(new Error(`Download failed with HTTP ${response.statusCode}`));
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
response.pipe(file);
|
|
173
|
-
file.on("finish", () => {
|
|
174
|
-
file.close(resolve);
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
request.on("error", (err) => {
|
|
178
|
-
file.close();
|
|
179
|
-
rmSync(destination, { force: true });
|
|
180
|
-
reject(err);
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async function sha256File(filePath) {
|
|
186
|
-
return await new Promise((resolve, reject) => {
|
|
187
|
-
const hash = createHash("sha256");
|
|
188
|
-
const stream = createReadStream(filePath);
|
|
189
|
-
stream.on("data", (chunk) => hash.update(chunk));
|
|
190
|
-
stream.on("error", reject);
|
|
191
|
-
stream.on("end", () => resolve(hash.digest("hex")));
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
async function verifySha256(archivePath, checksumPath) {
|
|
196
|
-
const checksumText = readFileSync(checksumPath, "utf8").trim();
|
|
197
|
-
const expected = checksumText.split(/\s+/)[0];
|
|
198
|
-
const actual = await sha256File(archivePath);
|
|
199
|
-
if (!expected || actual !== expected) {
|
|
200
|
-
throw new Error(
|
|
201
|
-
`Aurora Code native binary checksum mismatch for ${targetTriple}.`,
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async function installNativePackage() {
|
|
207
|
-
const archiveUrl =
|
|
208
|
-
`${downloadBaseUrl}/aurora-code/${packageVersion}/${targetTriple}.tar.xz`;
|
|
209
|
-
const checksumUrl = `${archiveUrl}.sha256`;
|
|
210
|
-
const targetDir = path.join(localVendorRoot, targetTriple);
|
|
211
|
-
const archivePath = path.join(
|
|
212
|
-
tmpdir(),
|
|
213
|
-
`aurora-code-${packageVersion}-${targetTriple}.tar.xz`,
|
|
214
|
-
);
|
|
215
|
-
const checksumPath = `${archivePath}.sha256`;
|
|
216
|
-
|
|
217
|
-
// eslint-disable-next-line no-console
|
|
218
|
-
console.error(`Downloading Aurora Code native binary from ${archiveUrl}`);
|
|
219
|
-
mkdirSync(localVendorRoot, { recursive: true });
|
|
220
|
-
rmSync(targetDir, { recursive: true, force: true });
|
|
221
|
-
await downloadFile(archiveUrl, archivePath);
|
|
222
|
-
await downloadFile(checksumUrl, checksumPath);
|
|
223
|
-
await verifySha256(archivePath, checksumPath);
|
|
224
|
-
mkdirSync(targetDir, { recursive: true });
|
|
225
|
-
|
|
226
|
-
const tar = spawn("tar", ["-xJf", archivePath, "-C", targetDir], {
|
|
227
|
-
stdio: "inherit",
|
|
228
|
-
});
|
|
229
|
-
const exitCode = await new Promise((resolve) => {
|
|
230
|
-
tar.on("exit", (code) => resolve(code ?? 1));
|
|
231
|
-
tar.on("error", () => resolve(1));
|
|
232
|
-
});
|
|
233
|
-
rmSync(archivePath, { force: true });
|
|
234
|
-
rmSync(checksumPath, { force: true });
|
|
235
|
-
if (exitCode !== 0) {
|
|
236
|
-
rmSync(targetDir, { recursive: true, force: true });
|
|
237
|
-
throw new Error("Failed to extract Aurora Code native binary.");
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return resolveNativePackage(localVendorRoot);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (!nativePackage) {
|
|
244
|
-
nativePackage = await installNativePackage();
|
|
245
|
-
if (!nativePackage) {
|
|
246
|
-
const packageManager = detectPackageManager();
|
|
247
|
-
const updateCommand =
|
|
248
|
-
packageManager === "bun"
|
|
249
|
-
? "bun install -g @auroraflow/code@latest"
|
|
250
|
-
: "npm install -g @auroraflow/code@latest";
|
|
251
|
-
throw new Error(
|
|
252
|
-
`Missing native binary for ${targetTriple}. Reinstall Aurora Code: ${updateCommand}`,
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const { binaryPath, pathDir } = nativePackage;
|
|
258
|
-
|
|
259
|
-
// Use an asynchronous spawn instead of spawnSync so that Node is able to
|
|
260
|
-
// respond to signals (e.g. Ctrl-C / SIGINT) while the native binary is
|
|
261
|
-
// executing. This allows us to forward those signals to the child process
|
|
262
|
-
// and guarantees that when either the child terminates or the parent
|
|
263
|
-
// receives a fatal signal, both processes exit in a predictable manner.
|
|
264
|
-
|
|
265
|
-
function getUpdatedPath(newDirs) {
|
|
266
|
-
const pathSep = process.platform === "win32" ? ";" : ":";
|
|
267
|
-
const existingPath = process.env.PATH || "";
|
|
268
|
-
const updatedPath = [
|
|
269
|
-
...newDirs,
|
|
270
|
-
...existingPath.split(pathSep).filter(Boolean),
|
|
271
|
-
].join(pathSep);
|
|
272
|
-
return updatedPath;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Use heuristics to detect the package manager that was used to install Aurora Code
|
|
277
|
-
* in order to give the user a hint about how to update it.
|
|
278
|
-
*/
|
|
279
|
-
function detectPackageManager() {
|
|
280
|
-
const userAgent = process.env.npm_config_user_agent || "";
|
|
281
|
-
if (/\bbun\//.test(userAgent)) {
|
|
282
|
-
return "bun";
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const execPath = process.env.npm_execpath || "";
|
|
286
|
-
if (execPath.includes("bun")) {
|
|
287
|
-
return "bun";
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (
|
|
291
|
-
__dirname.includes(".bun/install/global") ||
|
|
292
|
-
__dirname.includes(".bun\\install\\global")
|
|
293
|
-
) {
|
|
294
|
-
return "bun";
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
return userAgent ? "npm" : null;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const additionalDirs = [];
|
|
301
|
-
if (existsSync(pathDir)) {
|
|
302
|
-
additionalDirs.push(pathDir);
|
|
303
|
-
}
|
|
304
|
-
const updatedPath = getUpdatedPath(additionalDirs);
|
|
305
|
-
|
|
306
|
-
const env = { ...process.env, PATH: updatedPath };
|
|
307
|
-
const auroraHome =
|
|
308
|
-
env.AURORA_HOME && env.AURORA_HOME.trim()
|
|
309
|
-
? env.AURORA_HOME
|
|
310
|
-
: path.join(homedir(), ".aurora");
|
|
311
|
-
env.AURORA_HOME = auroraHome;
|
|
312
|
-
env.CODEX_HOME = auroraHome;
|
|
313
|
-
const packageManagerEnvVar =
|
|
314
|
-
detectPackageManager() === "bun"
|
|
315
|
-
? "AURORA_MANAGED_BY_BUN"
|
|
316
|
-
: "AURORA_MANAGED_BY_NPM";
|
|
317
|
-
env[packageManagerEnvVar] = "1";
|
|
318
|
-
env.AURORA_MANAGED_PACKAGE_ROOT = realpathSync(path.join(__dirname, ".."));
|
|
319
|
-
// Rust install diagnostics still understand the upstream variable names.
|
|
320
|
-
// Set both so Aurora-packaged launches are detected across the inherited core.
|
|
321
|
-
if (packageManagerEnvVar === "AURORA_MANAGED_BY_BUN") {
|
|
322
|
-
env.CODEX_MANAGED_BY_BUN = "1";
|
|
323
|
-
} else {
|
|
324
|
-
env.CODEX_MANAGED_BY_NPM = "1";
|
|
325
|
-
}
|
|
326
|
-
env.CODEX_MANAGED_PACKAGE_ROOT = env.AURORA_MANAGED_PACKAGE_ROOT;
|
|
327
|
-
|
|
328
|
-
writeTerminalTitle(terminalTitle);
|
|
329
|
-
|
|
330
|
-
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
331
|
-
stdio: "inherit",
|
|
332
|
-
env,
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
child.on("error", (err) => {
|
|
336
|
-
// Typically triggered when the binary is missing or not executable.
|
|
337
|
-
// Re-throwing here will terminate the parent with a non-zero exit code
|
|
338
|
-
// while still printing a helpful stack trace.
|
|
339
|
-
// eslint-disable-next-line no-console
|
|
340
|
-
console.error(err);
|
|
341
|
-
process.exit(1);
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
// Forward common termination signals to the child so that it shuts down
|
|
345
|
-
// gracefully. In the handler we temporarily disable the default behavior of
|
|
346
|
-
// exiting immediately; once the child has been signaled we simply wait for
|
|
347
|
-
// its exit event which will in turn terminate the parent (see below).
|
|
348
|
-
const forwardSignal = (signal) => {
|
|
349
|
-
if (child.killed) {
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
try {
|
|
353
|
-
child.kill(signal);
|
|
354
|
-
} catch {
|
|
355
|
-
/* ignore */
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
["SIGINT", "SIGTERM", "SIGHUP"].forEach((sig) => {
|
|
360
|
-
process.on(sig, () => forwardSignal(sig));
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
// When the child exits, mirror its termination reason in the parent so that
|
|
364
|
-
// shell scripts and other tooling observe the correct exit status.
|
|
365
|
-
// Wrap the lifetime of the child process in a Promise so that we can await
|
|
366
|
-
// its termination in a structured way. The Promise resolves with an object
|
|
367
|
-
// describing how the child exited: either via exit code or due to a signal.
|
|
368
|
-
const childResult = await new Promise((resolve) => {
|
|
369
|
-
child.on("exit", (code, signal) => {
|
|
370
|
-
if (signal) {
|
|
371
|
-
resolve({ type: "signal", signal });
|
|
372
|
-
} else {
|
|
373
|
-
resolve({ type: "code", exitCode: code ?? 1 });
|
|
374
|
-
}
|
|
375
|
-
});
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
if (childResult.type === "signal") {
|
|
379
|
-
// Re-emit the same signal so that the parent terminates with the expected
|
|
380
|
-
// semantics (this also sets the correct exit code of 128 + n).
|
|
381
|
-
process.kill(process.pid, childResult.signal);
|
|
382
|
-
} else {
|
|
383
|
-
process.exit(childResult.exitCode);
|
|
384
|
-
}
|
|
4
|
+
await runAuroraCLI(process.argv.slice(2));
|