@rnbsolucoes/axion-code 0.1.3
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 +207 -0
- package/npm/bin/axion.mjs +297 -0
- package/npm/releases/linux-x64/axion-code +0 -0
- package/npm/releases/win32-x64/axion-code.exe +0 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Axion Code
|
|
2
|
+
|
|
3
|
+
Axion Code is the Go-first CLI agent harness for the Axion ecosystem. It brings
|
|
4
|
+
the Axion Agent runtime to the terminal with PREVC + A workflow state, Mythos
|
|
5
|
+
execution discipline, provider/model management, persistent sessions, shared
|
|
6
|
+
Axion Desktop configuration, native dotcontext support, and a Claude Code-style
|
|
7
|
+
TUI focused on agentic coding workflows.
|
|
8
|
+
|
|
9
|
+
This MVP follows the PREVC-P documentation package in `.context/`:
|
|
10
|
+
|
|
11
|
+
- Go core;
|
|
12
|
+
- PREVC + A / Mythos event rail;
|
|
13
|
+
- JSONL protocol for `run --json`;
|
|
14
|
+
- SQLite-first shared user session store;
|
|
15
|
+
- Claude Code-style terminal TUI powered by Bubble Tea;
|
|
16
|
+
- full-width chat layout with initial brand splash;
|
|
17
|
+
- provider catalog/profile foundation with mock and OpenRouter adapters;
|
|
18
|
+
- interactive slash palette and provider/model/permission menus;
|
|
19
|
+
- Axion Desktop fallback provider presets, including OpenAI-compatible and Anthropic-compatible endpoints;
|
|
20
|
+
- shared Axion Desktop/CLI provider, model and permission stores under `%USERPROFILE%\.axion`;
|
|
21
|
+
- Pi Agent assets in inspect/import-only mode;
|
|
22
|
+
- MCP probe/list/read-only posture.
|
|
23
|
+
|
|
24
|
+
## MVP Commands
|
|
25
|
+
|
|
26
|
+
```powershell
|
|
27
|
+
axion-code
|
|
28
|
+
axion-code ask "Explique este projeto"
|
|
29
|
+
axion-code ask --provider openrouter --model google/gemini-2.5-flash-lite "Responda em uma linha"
|
|
30
|
+
axion-code run --json
|
|
31
|
+
axion-code doctor --json
|
|
32
|
+
axion-code session list --json
|
|
33
|
+
axion-code provider list --json
|
|
34
|
+
axion-code provider profile init
|
|
35
|
+
axion-code provider profile list --json
|
|
36
|
+
axion-code provider profile add or-free --catalog openrouter --model openrouter/free --credential-ref env:OPENROUTER_API_KEY
|
|
37
|
+
axion-code provider profile set or-free
|
|
38
|
+
axion-code provider profile delete or-free
|
|
39
|
+
axion-code provider profile active
|
|
40
|
+
axion-code provider model list openrouter --json
|
|
41
|
+
axion-code provider test openrouter google/gemini-2.5-flash-lite
|
|
42
|
+
axion-code permission list --json
|
|
43
|
+
axion-code permission set full_permission
|
|
44
|
+
axion-code graphics doctor
|
|
45
|
+
axion-code graphics logo
|
|
46
|
+
axion-code graphics logo --mode sixel --width 180
|
|
47
|
+
axion-code mcp list --json
|
|
48
|
+
axion-code package inspect <path>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
Official install, after the package is published to the public npm registry:
|
|
54
|
+
|
|
55
|
+
```powershell
|
|
56
|
+
npm install -g @rnbsolucoes/axion-code
|
|
57
|
+
axion
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The GitHub source repository can remain private. The npm package is intentionally
|
|
61
|
+
published as a small installer/runtime package: it contains the Node wrapper,
|
|
62
|
+
platform binaries under `npm/releases`, and documentation, but it does not ship
|
|
63
|
+
the Go source tree (`cmd/`, `internal/`, `go.mod`, `go.sum`).
|
|
64
|
+
|
|
65
|
+
Private GitHub install is not the recommended distribution path. Commands like
|
|
66
|
+
`npm install -g rnbsolucoes/Axion-CLI` use Git access and may require SSH keys or
|
|
67
|
+
credentials on every machine. Use the scoped npm package instead.
|
|
68
|
+
|
|
69
|
+
Development install from the current local clone:
|
|
70
|
+
|
|
71
|
+
```powershell
|
|
72
|
+
npm install -g .
|
|
73
|
+
axion
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If an older local `axion.ps1` shim already exists, replace it once:
|
|
77
|
+
|
|
78
|
+
```powershell
|
|
79
|
+
npm install -g . --force
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The npm package exposes both `axion` and `axion-code`. It does not use a
|
|
83
|
+
`postinstall` hook. On first run, the wrapper copies the packaged binary for the
|
|
84
|
+
current platform into the local Axion Code bin directory and then executes it. In
|
|
85
|
+
a source clone only, if no packaged binary exists, the wrapper can build from Go
|
|
86
|
+
as a development fallback.
|
|
87
|
+
|
|
88
|
+
Requirements:
|
|
89
|
+
|
|
90
|
+
- Node.js 18+ for the npm wrapper.
|
|
91
|
+
- End users do not need Go when installing from npm.
|
|
92
|
+
- Development source builds need Go 1.26+ on `PATH`, `AXION_GO`, or the Codex
|
|
93
|
+
bundled Go toolchain at `%USERPROFILE%\.codex\toolchains\go1.26.4\go\bin\go.exe`.
|
|
94
|
+
|
|
95
|
+
For this development machine, if an older PowerShell shim still points directly
|
|
96
|
+
to `%LOCALAPPDATA%\AxionCode\bin\axion-code.exe`, rebuild the local binary:
|
|
97
|
+
|
|
98
|
+
```powershell
|
|
99
|
+
go build -o "$env:LOCALAPPDATA\AxionCode\bin\axion-code.exe" ./cmd/axion-code
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Publish
|
|
103
|
+
|
|
104
|
+
Build the npm package binaries before publishing:
|
|
105
|
+
|
|
106
|
+
```powershell
|
|
107
|
+
npm run build:npm-binaries:release
|
|
108
|
+
npm pack --dry-run
|
|
109
|
+
npm publish --access public
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The npm account or organization must own the `@rnbsolucoes` scope. Scoped public
|
|
113
|
+
packages must be published with public access on the first publish.
|
|
114
|
+
The current release build targets Windows x64 and Linux x64. Add more targets by
|
|
115
|
+
running `node npm/build-package-binaries.mjs --targets=all` or a comma-separated
|
|
116
|
+
target list when those platforms are ready.
|
|
117
|
+
|
|
118
|
+
## Update
|
|
119
|
+
|
|
120
|
+
Check for a newer version:
|
|
121
|
+
|
|
122
|
+
```powershell
|
|
123
|
+
axion update --check
|
|
124
|
+
axion version --check
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Update the installed CLI. This is the official update alias and must remain the
|
|
128
|
+
single command users run whenever a new Axion Code binary/package is released:
|
|
129
|
+
|
|
130
|
+
```powershell
|
|
131
|
+
axion update
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The npm wrapper checks the public npm registry first and falls back to the GitHub
|
|
135
|
+
package metadata only when available. If a newer version exists, the initial
|
|
136
|
+
Axion Code splash shows the update notice and hides it after the first
|
|
137
|
+
interaction.
|
|
138
|
+
|
|
139
|
+
Without npm:
|
|
140
|
+
|
|
141
|
+
```powershell
|
|
142
|
+
go build -o "$env:LOCALAPPDATA\AxionCode\bin\axion-code.exe" ./cmd/axion-code
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Provider and model configuration is shared with Axion Desktop:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
%USERPROFILE%\.axion\harness\providers.json
|
|
149
|
+
%USERPROFILE%\.axion\harness\active_profile
|
|
150
|
+
%USERPROFILE%\.axion\axion-mode.json
|
|
151
|
+
%USERPROFILE%\.axion\sessions\axion.db
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
OpenRouter uses `OPENROUTER_API_KEY` from the environment or a `secret:<NAME>` reference stored in `C:\Israel\Pesoal\secrets.env` (override for tests: `AXION_SECRETS_ENV`). Provider profile config stores only references, never the key value.
|
|
155
|
+
|
|
156
|
+
For test/dev isolation, set `AXION_HOME` to a temporary folder. In normal use, leave it unset so Desktop and CLI remain two surfaces of the same Axion harness.
|
|
157
|
+
|
|
158
|
+
The interactive TUI supports:
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
/ inline slash palette
|
|
162
|
+
/provider
|
|
163
|
+
/provider set <profile-id>
|
|
164
|
+
/model
|
|
165
|
+
/permission
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Slash palette behavior: `↑/↓` selects, `Tab` completes the selected command, `Enter` executes the selected command, `Esc` closes active menus/wizards.
|
|
169
|
+
|
|
170
|
+
`/model` pulls the active provider's `/models` endpoint when credentials are configured. Reasoning and fast-mode steps appear only when the selected model metadata exposes those parameters.
|
|
171
|
+
|
|
172
|
+
Provider menu actions:
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
Register provider
|
|
176
|
+
Edit provider
|
|
177
|
+
Set provider
|
|
178
|
+
Delete provider
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
For a profile-backed OpenRouter session:
|
|
182
|
+
|
|
183
|
+
```powershell
|
|
184
|
+
axion provider profile add or-free --catalog openrouter --model openrouter/free --credential-ref env:OPENROUTER_API_KEY
|
|
185
|
+
axion provider profile set or-free
|
|
186
|
+
axion
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Build
|
|
190
|
+
|
|
191
|
+
```powershell
|
|
192
|
+
go test -count=1 ./...
|
|
193
|
+
go build ./cmd/axion-code
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
If Go is not on PATH, use a verified local Go toolchain and keep generated binaries out of git.
|
|
197
|
+
|
|
198
|
+
## Current Limits
|
|
199
|
+
|
|
200
|
+
This is a functional direction MVP, not the full harness:
|
|
201
|
+
|
|
202
|
+
- no provider streaming yet; current provider profile foundation is non-streaming;
|
|
203
|
+
- terminal logo uses Sixel when available and falls back to width-bounded ANSI/block rendering;
|
|
204
|
+
- initial chat splash shows the Axion logo and system name until the first interaction;
|
|
205
|
+
- no tool execution yet;
|
|
206
|
+
- no executable Pi RPC bridge yet;
|
|
207
|
+
- no MCP transport execution yet.
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import https from "node:https";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const root = resolve(here, "..", "..");
|
|
10
|
+
const isWindows = process.platform === "win32";
|
|
11
|
+
const exeName = isWindows ? "axion-code.exe" : "axion-code";
|
|
12
|
+
const platformKey = `${process.platform}-${process.arch}`;
|
|
13
|
+
const packagedExePath = join(root, "npm", "releases", platformKey, exeName);
|
|
14
|
+
const binDir = isWindows
|
|
15
|
+
? join(process.env.LOCALAPPDATA || join(process.env.USERPROFILE || root, "AppData", "Local"), "AxionCode", "bin")
|
|
16
|
+
: join(process.env.HOME || root, ".local", "share", "axion-code", "bin");
|
|
17
|
+
const exePath = join(binDir, exeName);
|
|
18
|
+
const markerPath = join(binDir, ".axion-code-package-version");
|
|
19
|
+
const updateCachePath = join(binDir, ".axion-code-update.json");
|
|
20
|
+
const packageJSON = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
21
|
+
const updateSource = packageJSON.name;
|
|
22
|
+
const githubSource = "github:rnbsolucoes/Axion-CLI";
|
|
23
|
+
const updatePackageURL = "https://raw.githubusercontent.com/rnbsolucoes/Axion-CLI/main/package.json";
|
|
24
|
+
const npmRegistryURL = "https://registry.npmjs.org/@rnbsolucoes%2Faxion-code/latest";
|
|
25
|
+
const updateCommand = "axion update";
|
|
26
|
+
const updateCacheTTL = 12 * 60 * 60 * 1000;
|
|
27
|
+
|
|
28
|
+
function findGo() {
|
|
29
|
+
if (process.env.AXION_GO) {
|
|
30
|
+
return process.env.AXION_GO;
|
|
31
|
+
}
|
|
32
|
+
if (isWindows && process.env.USERPROFILE) {
|
|
33
|
+
const bundled = join(process.env.USERPROFILE, ".codex", "toolchains", "go1.26.4", "go", "bin", "go.exe");
|
|
34
|
+
if (existsSync(bundled)) {
|
|
35
|
+
return bundled;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return "go";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function sourceAvailable() {
|
|
42
|
+
return existsSync(join(root, "go.mod")) && existsSync(join(root, "cmd", "axion-code"));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function installPackagedBinary() {
|
|
46
|
+
if (!existsSync(packagedExePath)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
copyFileSync(packagedExePath, exePath);
|
|
50
|
+
if (!isWindows) {
|
|
51
|
+
chmodSync(exePath, 0o755);
|
|
52
|
+
}
|
|
53
|
+
writeFileSync(markerPath, `${packageJSON.version}\n`, "utf8");
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function buildFromSource() {
|
|
58
|
+
const go = findGo();
|
|
59
|
+
const result = spawnSync(go, ["build", "-o", exePath, "./cmd/axion-code"], {
|
|
60
|
+
cwd: root,
|
|
61
|
+
stdio: "inherit",
|
|
62
|
+
shell: false
|
|
63
|
+
});
|
|
64
|
+
if (result.status !== 0) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
writeFileSync(markerPath, `${packageJSON.version}\n`, "utf8");
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function ensureBinary() {
|
|
72
|
+
const marker = existsSync(markerPath) ? readFileSync(markerPath, "utf8").trim() : "";
|
|
73
|
+
if (existsSync(exePath) && marker === packageJSON.version) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
mkdirSync(binDir, { recursive: true });
|
|
77
|
+
if (installPackagedBinary()) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (sourceAvailable() && buildFromSource()) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
console.error("");
|
|
84
|
+
console.error(`Axion Code binary for ${platformKey} was not found in this package.`);
|
|
85
|
+
console.error("If you are using a source clone, install Go 1.26+ on PATH or set AXION_GO and run:");
|
|
86
|
+
console.error(" npm run install:local");
|
|
87
|
+
console.error("If you installed from npm, update to a package that includes your platform binary.");
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function semverParts(value) {
|
|
92
|
+
return String(value || "")
|
|
93
|
+
.trim()
|
|
94
|
+
.split(/[+-]/)[0]
|
|
95
|
+
.split(".")
|
|
96
|
+
.slice(0, 3)
|
|
97
|
+
.map((part) => Number.parseInt(part, 10) || 0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function compareVersions(a, b) {
|
|
101
|
+
const aa = semverParts(a);
|
|
102
|
+
const bb = semverParts(b);
|
|
103
|
+
for (let i = 0; i < 3; i += 1) {
|
|
104
|
+
if ((aa[i] || 0) > (bb[i] || 0)) return 1;
|
|
105
|
+
if ((aa[i] || 0) < (bb[i] || 0)) return -1;
|
|
106
|
+
}
|
|
107
|
+
return String(a || "").localeCompare(String(b || ""));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function readJSON(path) {
|
|
111
|
+
try {
|
|
112
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
113
|
+
} catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function writeJSON(path, value) {
|
|
119
|
+
try {
|
|
120
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
121
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
|
122
|
+
} catch {
|
|
123
|
+
// Update metadata is advisory; failing to cache must not block startup.
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function fetchJSON(url, timeoutMs = 1800) {
|
|
128
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
129
|
+
const headers = { "User-Agent": `Axion-Code/${packageJSON.version}` };
|
|
130
|
+
if (url.includes("githubusercontent.com")) {
|
|
131
|
+
const token = process.env.GH_TOKEN || process.env.GITHUB_TOKEN || "";
|
|
132
|
+
if (token) {
|
|
133
|
+
headers.Authorization = `Bearer ${token}`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const req = https.get(url, { headers }, (res) => {
|
|
137
|
+
if (res.statusCode !== 200) {
|
|
138
|
+
res.resume();
|
|
139
|
+
rejectPromise(new Error(`status ${res.statusCode}`));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
let body = "";
|
|
143
|
+
res.setEncoding("utf8");
|
|
144
|
+
res.on("data", (chunk) => {
|
|
145
|
+
body += chunk;
|
|
146
|
+
if (body.length > 128 * 1024) {
|
|
147
|
+
req.destroy(new Error("version payload too large"));
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
res.on("end", () => {
|
|
151
|
+
try {
|
|
152
|
+
resolvePromise(JSON.parse(body));
|
|
153
|
+
} catch (error) {
|
|
154
|
+
rejectPromise(error);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
req.setTimeout(timeoutMs, () => req.destroy(new Error("version check timeout")));
|
|
159
|
+
req.on("error", rejectPromise);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function fetchLatestPackage() {
|
|
164
|
+
const errors = [];
|
|
165
|
+
for (const candidate of [
|
|
166
|
+
{ url: npmRegistryURL, source: packageJSON.name },
|
|
167
|
+
{ url: updatePackageURL, source: githubSource }
|
|
168
|
+
]) {
|
|
169
|
+
try {
|
|
170
|
+
const remote = await fetchJSON(candidate.url);
|
|
171
|
+
const latestVersion = String(remote.version || "").trim();
|
|
172
|
+
if (latestVersion) {
|
|
173
|
+
return { latestVersion, source: candidate.source };
|
|
174
|
+
}
|
|
175
|
+
errors.push(`${candidate.url}: missing version`);
|
|
176
|
+
} catch (error) {
|
|
177
|
+
errors.push(`${candidate.url}: ${error.message}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
throw new Error(errors.join("; "));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function readUpdateInfo({ force = false } = {}) {
|
|
184
|
+
const cached = readJSON(updateCachePath);
|
|
185
|
+
const now = Date.now();
|
|
186
|
+
if (!force && cached?.latestVersion && now - Number(cached.checkedAt || 0) < updateCacheTTL) {
|
|
187
|
+
return {
|
|
188
|
+
currentVersion: packageJSON.version,
|
|
189
|
+
latestVersion: cached.latestVersion,
|
|
190
|
+
updateAvailable: compareVersions(cached.latestVersion, packageJSON.version) > 0,
|
|
191
|
+
source: updateSource,
|
|
192
|
+
checkedAt: cached.checkedAt,
|
|
193
|
+
fromCache: true
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const remote = await fetchLatestPackage();
|
|
198
|
+
const latestVersion = remote.latestVersion;
|
|
199
|
+
const info = {
|
|
200
|
+
currentVersion: packageJSON.version,
|
|
201
|
+
latestVersion,
|
|
202
|
+
updateAvailable: latestVersion ? compareVersions(latestVersion, packageJSON.version) > 0 : false,
|
|
203
|
+
source: remote.source || updateSource,
|
|
204
|
+
checkedAt: now,
|
|
205
|
+
fromCache: false
|
|
206
|
+
};
|
|
207
|
+
if (latestVersion) {
|
|
208
|
+
writeJSON(updateCachePath, { latestVersion, checkedAt: now, source: info.source });
|
|
209
|
+
}
|
|
210
|
+
return info;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
return {
|
|
213
|
+
currentVersion: packageJSON.version,
|
|
214
|
+
latestVersion: cached?.latestVersion || "",
|
|
215
|
+
updateAvailable: cached?.latestVersion ? compareVersions(cached.latestVersion, packageJSON.version) > 0 : false,
|
|
216
|
+
source: cached?.source || updateSource,
|
|
217
|
+
checkedAt: cached?.checkedAt || 0,
|
|
218
|
+
fromCache: Boolean(cached?.latestVersion),
|
|
219
|
+
error: error.message
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async function updateCommandHandler(args) {
|
|
225
|
+
const checkOnly = args.includes("--check");
|
|
226
|
+
const asJSON = args.includes("--json");
|
|
227
|
+
const info = await readUpdateInfo({ force: true });
|
|
228
|
+
if (checkOnly) {
|
|
229
|
+
if (asJSON) {
|
|
230
|
+
console.log(JSON.stringify({
|
|
231
|
+
current: info.currentVersion,
|
|
232
|
+
latest: info.latestVersion || undefined,
|
|
233
|
+
update_available: info.updateAvailable,
|
|
234
|
+
source: info.source,
|
|
235
|
+
command: updateCommand,
|
|
236
|
+
checked: Boolean(info.latestVersion),
|
|
237
|
+
error: info.error || undefined
|
|
238
|
+
}));
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (info.updateAvailable) {
|
|
242
|
+
console.log(`Update available: ${info.currentVersion} -> ${info.latestVersion}`);
|
|
243
|
+
console.log(`Run: ${updateCommand}`);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (info.latestVersion) {
|
|
247
|
+
console.log(`Axion Code ${info.currentVersion} is up to date.`);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
console.log(`Axion Code ${info.currentVersion}. Could not check latest version.`);
|
|
251
|
+
if (info.error) {
|
|
252
|
+
console.error(`Version check warning: ${info.error}`);
|
|
253
|
+
}
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const source = info.source === packageJSON.name ? packageJSON.name : updateSource;
|
|
257
|
+
console.log(`Updating Axion Code from ${source}...`);
|
|
258
|
+
const result = spawnSync("npm", ["install", "-g", source], {
|
|
259
|
+
stdio: "inherit",
|
|
260
|
+
shell: false
|
|
261
|
+
});
|
|
262
|
+
if (result.error) {
|
|
263
|
+
console.error(result.error.message);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
if (result.status !== 0) {
|
|
267
|
+
process.exit(result.status || 1);
|
|
268
|
+
}
|
|
269
|
+
console.log("Axion Code update completed. Run axion again.");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const args = process.argv.slice(2);
|
|
273
|
+
if (args[0] === "update") {
|
|
274
|
+
await updateCommandHandler(args.slice(1));
|
|
275
|
+
process.exit(0);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const updateInfo = await readUpdateInfo();
|
|
279
|
+
ensureBinary();
|
|
280
|
+
const run = spawnSync(exePath, process.argv.slice(2), {
|
|
281
|
+
stdio: "inherit",
|
|
282
|
+
shell: false,
|
|
283
|
+
env: {
|
|
284
|
+
...process.env,
|
|
285
|
+
AXION_CODE_VERSION: packageJSON.version,
|
|
286
|
+
AXION_CODE_LATEST_VERSION: updateInfo.latestVersion || "",
|
|
287
|
+
AXION_CODE_UPDATE_AVAILABLE: updateInfo.updateAvailable ? "1" : "0",
|
|
288
|
+
AXION_CODE_UPDATE_COMMAND: updateCommand,
|
|
289
|
+
AXION_CODE_UPDATE_SOURCE: updateSource
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (run.error) {
|
|
294
|
+
console.error(run.error.message);
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
process.exit(run.status ?? 0);
|
|
Binary file
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rnbsolucoes/axion-code",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Axion Code CLI harness for the Axion ecosystem.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/rnbsolucoes/Axion-CLI.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/rnbsolucoes/Axion-CLI#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/rnbsolucoes/Axion-CLI/issues"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public",
|
|
16
|
+
"registry": "https://registry.npmjs.org/"
|
|
17
|
+
},
|
|
18
|
+
"bin": {
|
|
19
|
+
"axion": "npm/bin/axion.mjs",
|
|
20
|
+
"axion-code": "npm/bin/axion.mjs"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "go build -o dist/axion-code ./cmd/axion-code",
|
|
24
|
+
"build:npm-binaries": "node npm/build-package-binaries.mjs",
|
|
25
|
+
"build:npm-binaries:release": "node npm/build-package-binaries.mjs --targets=win32-x64,linux-x64",
|
|
26
|
+
"install:local": "node npm/install-local.mjs",
|
|
27
|
+
"test": "go test -count=1 ./..."
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"npm/bin",
|
|
34
|
+
"npm/releases",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"keywords": [
|
|
38
|
+
"axion",
|
|
39
|
+
"cli",
|
|
40
|
+
"agent",
|
|
41
|
+
"prevc",
|
|
42
|
+
"harness"
|
|
43
|
+
]
|
|
44
|
+
}
|