@rnbsolucoes/axion-code 0.1.3 → 0.1.6
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 +101 -5
- package/npm/bin/axion.mjs +66 -9
- package/npm/releases/linux-x64/axion-code +0 -0
- package/npm/releases/win32-x64/axion-code.exe +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,9 @@ This MVP follows the PREVC-P documentation package in `.context/`:
|
|
|
19
19
|
- Axion Desktop fallback provider presets, including OpenAI-compatible and Anthropic-compatible endpoints;
|
|
20
20
|
- shared Axion Desktop/CLI provider, model and permission stores under `%USERPROFILE%\.axion`;
|
|
21
21
|
- Pi Agent assets in inspect/import-only mode;
|
|
22
|
-
- MCP
|
|
22
|
+
- native dotcontext and MCP management posture;
|
|
23
|
+
- plan-scoped PREVC + A learning consolidation through `/learn`;
|
|
24
|
+
- shared plugin and native isolated subagent catalogs.
|
|
23
25
|
|
|
24
26
|
## MVP Commands
|
|
25
27
|
|
|
@@ -29,6 +31,8 @@ axion-code ask "Explique este projeto"
|
|
|
29
31
|
axion-code ask --provider openrouter --model google/gemini-2.5-flash-lite "Responda em uma linha"
|
|
30
32
|
axion-code run --json
|
|
31
33
|
axion-code doctor --json
|
|
34
|
+
axion-code init --json
|
|
35
|
+
axion-code init --project --json
|
|
32
36
|
axion-code session list --json
|
|
33
37
|
axion-code provider list --json
|
|
34
38
|
axion-code provider profile init
|
|
@@ -45,6 +49,15 @@ axion-code graphics doctor
|
|
|
45
49
|
axion-code graphics logo
|
|
46
50
|
axion-code graphics logo --mode sixel --width 180
|
|
47
51
|
axion-code mcp list --json
|
|
52
|
+
axion-code mcp add sample --command node --arg server.js
|
|
53
|
+
axion-code mcp enable sample
|
|
54
|
+
axion-code mcp disable sample
|
|
55
|
+
axion-code mcp remove sample
|
|
56
|
+
axion-code mcp import .\mcp-servers.json
|
|
57
|
+
axion-code plugins list --json
|
|
58
|
+
axion-code agents list --json
|
|
59
|
+
axion-code agents run bug-hunter "review this login flow"
|
|
60
|
+
axion-code learn --json
|
|
48
61
|
axion-code package inspect <path>
|
|
49
62
|
```
|
|
50
63
|
|
|
@@ -142,33 +155,115 @@ Without npm:
|
|
|
142
155
|
go build -o "$env:LOCALAPPDATA\AxionCode\bin\axion-code.exe" ./cmd/axion-code
|
|
143
156
|
```
|
|
144
157
|
|
|
145
|
-
Provider
|
|
158
|
+
Provider catalog/configuration is shared with Axion Desktop, while the active
|
|
159
|
+
Axion Code selection is isolated:
|
|
146
160
|
|
|
147
161
|
```text
|
|
148
162
|
%USERPROFILE%\.axion\harness\providers.json
|
|
149
|
-
%USERPROFILE%\.axion\harness\active_profile
|
|
163
|
+
%USERPROFILE%\.axion\harness\active_profile # Axion Desktop active profile
|
|
164
|
+
%USERPROFILE%\.axion\harness\active_profile_cli # Axion Code active profile
|
|
165
|
+
%USERPROFILE%\.axion\harness\selection_cli.json # Axion Code active model/params
|
|
150
166
|
%USERPROFILE%\.axion\axion-mode.json
|
|
151
167
|
%USERPROFILE%\.axion\sessions\axion.db
|
|
168
|
+
%USERPROFILE%\.axion\mcp-servers.json
|
|
169
|
+
%USERPROFILE%\.axion\plugins.json
|
|
170
|
+
%USERPROFILE%\.axion\sub-agents.json
|
|
152
171
|
```
|
|
153
172
|
|
|
154
173
|
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
174
|
|
|
156
|
-
For test/dev isolation, set `AXION_HOME` to a temporary folder. In normal use,
|
|
175
|
+
For test/dev isolation, set `AXION_HOME` to a temporary folder. In normal use,
|
|
176
|
+
leave it unset so Desktop and CLI share the same provider catalog while keeping
|
|
177
|
+
their active provider/model selections independent.
|
|
178
|
+
|
|
179
|
+
## Project Bootstrap
|
|
180
|
+
|
|
181
|
+
`axion-code init --json` bootstraps the shared user-level Axion home used by
|
|
182
|
+
Axion Desktop and Axion Code. It creates missing files under
|
|
183
|
+
`%USERPROFILE%\.axion` without overwriting Desktop-owned provider/model state.
|
|
184
|
+
|
|
185
|
+
`axion-code init --project --json` bootstraps the current workspace. The same
|
|
186
|
+
operation is available inside the TUI with `/init`. It creates only missing
|
|
187
|
+
project scaffolding:
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
.brv/ local operational memory and PREVC + A learning buffers
|
|
191
|
+
.context/ workflow, plans, tasks, context snapshots and PREVC evidence
|
|
192
|
+
.docs/ project documents, specs, reports and handoff material
|
|
193
|
+
AGENTS.md project-scoped instructions
|
|
194
|
+
CLAUDE.md Claude-compatible project instructions
|
|
195
|
+
.gitignore ignored local runtime, secrets, cache and build-output patterns
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
If a legacy `docs/` directory exists and `.docs/` does not, project bootstrap
|
|
199
|
+
renames `docs/` to `.docs/`. If both exist, Axion Code leaves both untouched and
|
|
200
|
+
does not attempt an automatic merge.
|
|
201
|
+
|
|
202
|
+
Instruction layering is explicit: shared `%USERPROFILE%\.axion\AGENTS.md`
|
|
203
|
+
contains global Axion Code agent rules, while the workspace root `AGENTS.md`
|
|
204
|
+
contains project-specific rules. Provider runtime prompts read both layers when
|
|
205
|
+
present, plus `CLAUDE.md` as a compatibility surface.
|
|
157
206
|
|
|
158
207
|
The interactive TUI supports:
|
|
159
208
|
|
|
160
209
|
```text
|
|
161
210
|
/ inline slash palette
|
|
211
|
+
/init
|
|
162
212
|
/provider
|
|
163
213
|
/provider set <profile-id>
|
|
164
214
|
/model
|
|
165
215
|
/permission
|
|
216
|
+
/mcp
|
|
217
|
+
/learn
|
|
218
|
+
/plugins
|
|
219
|
+
/agents
|
|
220
|
+
/agents run <id> <prompt>
|
|
166
221
|
```
|
|
167
222
|
|
|
168
223
|
Slash palette behavior: `↑/↓` selects, `Tab` completes the selected command, `Enter` executes the selected command, `Esc` closes active menus/wizards.
|
|
169
224
|
|
|
170
225
|
`/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
226
|
|
|
227
|
+
`/learn` consolidates plan-scoped learning from `.brv/plans/<plan-id>` and `.context/learning-candidates*.md`, filters low-signal material, deduplicates by content hash/summary and promotes relevant notes into native dotcontext at `<workspace>/.axion/context`.
|
|
228
|
+
|
|
229
|
+
When the active plan comes from `.context/plans/*.md`, `/task add`, `/task done`
|
|
230
|
+
and `/task progress` update the Markdown plan file directly. Axion Code rewrites
|
|
231
|
+
only the target task line marker/progress and keeps the rest of the document
|
|
232
|
+
unchanged.
|
|
233
|
+
|
|
234
|
+
`/mcp` opens an inline MCP list. Enabled servers can be disabled, disabled servers can be enabled, and non-native servers can be uninstalled while preserving valid `mcp-servers.json` formatting.
|
|
235
|
+
|
|
236
|
+
`/agents` lists the native isolated subagents. `/agents run <id> <prompt>` calls one with an isolated prompt while inheriting the active provider/model from the main agent. The subagent returns findings/action feedback instead of joining the main context by default.
|
|
237
|
+
|
|
238
|
+
## MCP, Plugins And Subagents
|
|
239
|
+
|
|
240
|
+
MCP import files use the same JSON array shape as `%USERPROFILE%\.axion\mcp-servers.json`:
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
[
|
|
244
|
+
{
|
|
245
|
+
"id": "context7",
|
|
246
|
+
"name": "Context7",
|
|
247
|
+
"transport": "stdio",
|
|
248
|
+
"command": "npx",
|
|
249
|
+
"args": ["-y", "@upstash/context7-mcp"],
|
|
250
|
+
"enabled": false,
|
|
251
|
+
"read_only": true
|
|
252
|
+
}
|
|
253
|
+
]
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
`axion mcp import <file.json>` merges by `id`, preserves `native` protection for built-ins, writes formatted JSON, and rejects entries without `id` or without the required `command`/`url` for the selected transport. Native MCPs such as `dotcontext` cannot be removed, only disabled.
|
|
257
|
+
|
|
258
|
+
Plugins are read from the same shared Axion Desktop file, `%USERPROFILE%\.axion\plugins.json`. The CLI can list, enable, disable and remove plugin records, but executable plugin installation remains intentionally gated for the next trust-policy cycle.
|
|
259
|
+
|
|
260
|
+
Subagents are stored in `%USERPROFILE%\.axion\sub-agents.json`. The initial catalog has 15 native entries:
|
|
261
|
+
|
|
262
|
+
- Programming: `code-reviewer`, `bug-hunter`, `security-reviewer`, `performance-reviewer`, `frontend-ux-reviewer`.
|
|
263
|
+
- Professional: `product-strategist`, `business-analyst`, `financial-analyst`, `legal-policy-reviewer`, `marketing-strategist`, `sales-ops-analyst`, `customer-success-advisor`, `data-analyst`, `operations-advisor`, `hr-talent-advisor`.
|
|
264
|
+
|
|
265
|
+
Execution contract: subagents inherit the active provider/model, receive an isolated prompt containing only their role and the requested task, do not access the main hidden context unless explicitly included in the prompt, and return findings/evidence/actions back to the main timeline.
|
|
266
|
+
|
|
172
267
|
Provider menu actions:
|
|
173
268
|
|
|
174
269
|
```text
|
|
@@ -204,4 +299,5 @@ This is a functional direction MVP, not the full harness:
|
|
|
204
299
|
- initial chat splash shows the Axion logo and system name until the first interaction;
|
|
205
300
|
- no tool execution yet;
|
|
206
301
|
- no executable Pi RPC bridge yet;
|
|
207
|
-
- no MCP transport execution yet
|
|
302
|
+
- no MCP transport execution yet;
|
|
303
|
+
- native subagent execution is prompt-isolated and provider/model-inherited; richer multi-subagent orchestration, streaming and budget telemetry remain next-cycle items.
|
package/npm/bin/axion.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import https from "node:https";
|
|
5
5
|
import { dirname, join, resolve } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
@@ -42,15 +42,49 @@ function sourceAvailable() {
|
|
|
42
42
|
return existsSync(join(root, "go.mod")) && existsSync(join(root, "cmd", "axion-code"));
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
function sleep(ms) {
|
|
46
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function markerMatches(expectedMarker) {
|
|
50
|
+
try {
|
|
51
|
+
return existsSync(exePath) && readFileSync(markerPath, "utf8").trim() === expectedMarker;
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function copyPackagedBinaryWithRetry(expectedMarker) {
|
|
58
|
+
for (let attempt = 0; attempt < 8; attempt += 1) {
|
|
59
|
+
try {
|
|
60
|
+
copyFileSync(packagedExePath, exePath);
|
|
61
|
+
return;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
const retryable = error && (error.code === "EBUSY" || error.code === "EPERM");
|
|
64
|
+
if (!retryable) {
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
if (markerMatches(expectedMarker)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (attempt === 7) {
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
sleep(75 * (attempt + 1));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
45
78
|
function installPackagedBinary() {
|
|
46
79
|
if (!existsSync(packagedExePath)) {
|
|
47
80
|
return false;
|
|
48
81
|
}
|
|
49
|
-
|
|
82
|
+
const marker = packagedBinaryMarker();
|
|
83
|
+
copyPackagedBinaryWithRetry(marker);
|
|
50
84
|
if (!isWindows) {
|
|
51
85
|
chmodSync(exePath, 0o755);
|
|
52
86
|
}
|
|
53
|
-
writeFileSync(markerPath, `${
|
|
87
|
+
writeFileSync(markerPath, `${marker}\n`, "utf8");
|
|
54
88
|
return true;
|
|
55
89
|
}
|
|
56
90
|
|
|
@@ -64,13 +98,14 @@ function buildFromSource() {
|
|
|
64
98
|
if (result.status !== 0) {
|
|
65
99
|
return false;
|
|
66
100
|
}
|
|
67
|
-
writeFileSync(markerPath, `${
|
|
101
|
+
writeFileSync(markerPath, `${sourceBinaryMarker()}\n`, "utf8");
|
|
68
102
|
return true;
|
|
69
103
|
}
|
|
70
104
|
|
|
71
105
|
function ensureBinary() {
|
|
72
106
|
const marker = existsSync(markerPath) ? readFileSync(markerPath, "utf8").trim() : "";
|
|
73
|
-
|
|
107
|
+
const desiredMarker = existsSync(packagedExePath) ? packagedBinaryMarker() : sourceBinaryMarker();
|
|
108
|
+
if (existsSync(exePath) && marker === desiredMarker) {
|
|
74
109
|
return;
|
|
75
110
|
}
|
|
76
111
|
mkdirSync(binDir, { recursive: true });
|
|
@@ -88,6 +123,19 @@ function ensureBinary() {
|
|
|
88
123
|
process.exit(1);
|
|
89
124
|
}
|
|
90
125
|
|
|
126
|
+
function packagedBinaryMarker() {
|
|
127
|
+
try {
|
|
128
|
+
const stat = statSync(packagedExePath);
|
|
129
|
+
return `${packageJSON.version}|${platformKey}|pkg|${stat.size}|${Math.trunc(stat.mtimeMs)}`;
|
|
130
|
+
} catch {
|
|
131
|
+
return `${packageJSON.version}|${platformKey}|pkg`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function sourceBinaryMarker() {
|
|
136
|
+
return `${packageJSON.version}|${platformKey}|source`;
|
|
137
|
+
}
|
|
138
|
+
|
|
91
139
|
function semverParts(value) {
|
|
92
140
|
return String(value || "")
|
|
93
141
|
.trim()
|
|
@@ -183,7 +231,12 @@ async function fetchLatestPackage() {
|
|
|
183
231
|
async function readUpdateInfo({ force = false } = {}) {
|
|
184
232
|
const cached = readJSON(updateCachePath);
|
|
185
233
|
const now = Date.now();
|
|
186
|
-
if (
|
|
234
|
+
if (
|
|
235
|
+
!force &&
|
|
236
|
+
cached?.latestVersion &&
|
|
237
|
+
compareVersions(cached.latestVersion, packageJSON.version) >= 0 &&
|
|
238
|
+
now - Number(cached.checkedAt || 0) < updateCacheTTL
|
|
239
|
+
) {
|
|
187
240
|
return {
|
|
188
241
|
currentVersion: packageJSON.version,
|
|
189
242
|
latestVersion: cached.latestVersion,
|
|
@@ -209,13 +262,17 @@ async function readUpdateInfo({ force = false } = {}) {
|
|
|
209
262
|
}
|
|
210
263
|
return info;
|
|
211
264
|
} catch (error) {
|
|
265
|
+
const usableCachedVersion =
|
|
266
|
+
cached?.latestVersion && compareVersions(cached.latestVersion, packageJSON.version) >= 0
|
|
267
|
+
? cached.latestVersion
|
|
268
|
+
: "";
|
|
212
269
|
return {
|
|
213
270
|
currentVersion: packageJSON.version,
|
|
214
|
-
latestVersion:
|
|
215
|
-
updateAvailable:
|
|
271
|
+
latestVersion: usableCachedVersion,
|
|
272
|
+
updateAvailable: usableCachedVersion ? compareVersions(usableCachedVersion, packageJSON.version) > 0 : false,
|
|
216
273
|
source: cached?.source || updateSource,
|
|
217
274
|
checkedAt: cached?.checkedAt || 0,
|
|
218
|
-
fromCache: Boolean(
|
|
275
|
+
fromCache: Boolean(usableCachedVersion),
|
|
219
276
|
error: error.message
|
|
220
277
|
};
|
|
221
278
|
}
|
|
Binary file
|
|
Binary file
|