@matterailab/orbcode 0.1.3 → 0.1.4

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 CHANGED
@@ -144,12 +144,13 @@ The two Axon models are built in; `/model` opens a scroll-and-select picker
144
144
  (`/model <id>` still selects directly). Additional models can be declared via
145
145
  `customModels` in settings.json. The choice persists across sessions.
146
146
 
147
- | id | context | max output | pricing |
148
- |---------------------|---------|------------|--------------------------|
149
- | `axon-code-2-5-pro` | 400k | 64k | $2/M in · $6/M out |
150
- | `axon-code-2-5-mini`| 400k | 64k | free |
147
+ | id | context | max output | pricing |
148
+ | ---------------------- | ------- | ---------- | ------------------ |
149
+ | `axon-eido-3-code-pro` | 400k | 64k | $3/M in · $9/M out |
150
+ | `axon-code-2-5-pro` | 400k | 64k | $2/M in · $6/M out |
151
+ | `axon-code-2-5-mini` | 400k | 64k | free |
151
152
 
152
- `axon-code-2-5-pro` is the default. Both support native JSON tool calls and
153
+ `axon-code-2-5-pro` is the default. All three support native JSON tool calls and
153
154
  image input. Cost comes from the API's usage chunks (`is_byok`-aware) and is
154
155
  shown in the status bar.
155
156
 
@@ -196,35 +197,35 @@ shown in the status bar.
196
197
 
197
198
  ## Slash commands
198
199
 
199
- | command | action |
200
- |------------|--------|
201
- | `/help` | list commands |
202
- | `/model` | scrollable model picker (`/model pro` / `/model mini` / full id selects directly) |
203
- | `/clear` | clear the screen only, like the terminal's `clear` — the conversation and context continue |
204
- | `/new` | start a fresh conversation/session with a clean slate |
205
- | `/resume` | pick a previous session for this directory and continue it (screen is cleared, conversation replayed) |
206
- | `/analytics` | open the MatterAI analytics dashboard (app.matterai.so/orbital) in the browser |
207
- | `/compact` | summarize the conversation and replace history with the summary |
208
- | `/tasks` | print the current task list |
209
- | `/status` | version, model, account, gateway, context usage, cost, approval modes |
210
- | `/cost` | show session cost and fetch account balance |
211
- | `/init` | analyze the codebase and create/improve `AGENTS.md` |
212
- | `/login` | start the browser sign-in flow |
213
- | `/logout` | remove the saved token |
214
- | `/version` | print the CLI version |
215
- | `/exit` | quit |
200
+ | command | action |
201
+ | ------------ | ----------------------------------------------------------------------------------------------------- |
202
+ | `/help` | list commands |
203
+ | `/model` | scrollable model picker (`/model pro` / `/model mini` / full id selects directly) |
204
+ | `/clear` | clear the screen only, like the terminal's `clear` — the conversation and context continue |
205
+ | `/new` | start a fresh conversation/session with a clean slate |
206
+ | `/resume` | pick a previous session for this directory and continue it (screen is cleared, conversation replayed) |
207
+ | `/analytics` | open the MatterAI analytics dashboard (app.matterai.so/orbital) in the browser |
208
+ | `/compact` | summarize the conversation and replace history with the summary |
209
+ | `/tasks` | print the current task list |
210
+ | `/status` | version, model, account, gateway, context usage, cost, approval modes |
211
+ | `/cost` | show session cost and fetch account balance |
212
+ | `/init` | analyze the codebase and create/improve `AGENTS.md` |
213
+ | `/login` | start the browser sign-in flow |
214
+ | `/logout` | remove the saved token |
215
+ | `/version` | print the CLI version |
216
+ | `/exit` | quit |
216
217
 
217
218
  ## Keyboard shortcuts
218
219
 
219
- | key | action |
220
- |-----|--------|
221
- | `Esc` | interrupt the running turn (or cancel login polling / close a menu) |
222
- | `Ctrl+C` | quit |
223
- | `Ctrl+O` | toggle thinking display for the whole transcript (past turns included) |
224
- | `Shift+Tab` | cycle approval mode: ask → accept edits → auto-approve |
225
- | `↑` / `↓` | input history, or navigate any open menu |
226
- | `Ctrl+A` / `Ctrl+E` | start / end of line |
227
- | `Ctrl+U` | clear the input line |
220
+ | key | action |
221
+ | ------------------- | ---------------------------------------------------------------------- |
222
+ | `Esc` | interrupt the running turn (or cancel login polling / close a menu) |
223
+ | `Ctrl+C` | quit |
224
+ | `Ctrl+O` | toggle thinking display for the whole transcript (past turns included) |
225
+ | `Shift+Tab` | cycle approval mode: ask → accept edits → auto-approve |
226
+ | `↑` / `↓` | input history, or navigate any open menu |
227
+ | `Ctrl+A` / `Ctrl+E` | start / end of line |
228
+ | `Ctrl+U` | clear the input line |
228
229
 
229
230
  ## Approvals & safety
230
231
 
@@ -267,22 +268,22 @@ Two kinds of files under `~/.orbcode/`:
267
268
 
268
269
  ```json
269
270
  {
270
- "apiKey": "<token used instead of logging in>",
271
- "baseUrl": "https://my-gateway.example.com/v1",
272
- "model": "my-custom-model",
273
- "autoApproveEdits": false,
274
- "autoApproveSafeCommands": false,
275
- "customModels": [
276
- {
277
- "id": "my-custom-model",
278
- "name": "My Custom Model",
279
- "contextWindow": 128000,
280
- "maxOutputTokens": 32000,
281
- "inputPrice": 0.000001,
282
- "outputPrice": 0.000002
283
- }
284
- ],
285
- "env": { "MY_VAR": "value" }
271
+ "apiKey": "<token used instead of logging in>",
272
+ "baseUrl": "https://my-gateway.example.com/v1",
273
+ "model": "my-custom-model",
274
+ "autoApproveEdits": false,
275
+ "autoApproveSafeCommands": false,
276
+ "customModels": [
277
+ {
278
+ "id": "my-custom-model",
279
+ "name": "My Custom Model",
280
+ "contextWindow": 128000,
281
+ "maxOutputTokens": 32000,
282
+ "inputPrice": 0.000001,
283
+ "outputPrice": 0.000002
284
+ }
285
+ ],
286
+ "env": { "MY_VAR": "value" }
286
287
  }
287
288
  ```
288
289
 
@@ -295,15 +296,15 @@ config.json.
295
296
  Sessions are stored in `~/.orbcode/sessions/<id>.json` and power `/resume`
296
297
  and `--resume <id>`.
297
298
 
298
- | env var | effect |
299
- |---------|--------|
300
- | `ORBCODE_TOKEN` | auth token (overrides everything) |
301
- | `ORBCODE_API_KEY` | same as `apiKey` in settings.json |
302
- | `ORBCODE_BASE_URL` | same as `baseUrl` in settings.json |
303
- | `ORBCODE_MODEL` | model override (what `--model` sets internally) |
304
- | `ORBCODE_CONFIG_DIR` | config directory (default `~/.orbcode`) |
305
- | `ORBCODE_BACKEND_URL` | device-auth backend (default `https://api.matterai.so`) |
306
- | `ORBCODE_APP_URL` | webapp for the authorize page (default `https://app.matterai.so`) |
299
+ | env var | effect |
300
+ | --------------------- | ----------------------------------------------------------------- |
301
+ | `ORBCODE_TOKEN` | auth token (overrides everything) |
302
+ | `ORBCODE_API_KEY` | same as `apiKey` in settings.json |
303
+ | `ORBCODE_BASE_URL` | same as `baseUrl` in settings.json |
304
+ | `ORBCODE_MODEL` | model override (what `--model` sets internally) |
305
+ | `ORBCODE_CONFIG_DIR` | config directory (default `~/.orbcode`) |
306
+ | `ORBCODE_BACKEND_URL` | device-auth backend (default `https://api.matterai.so`) |
307
+ | `ORBCODE_APP_URL` | webapp for the authorize page (default `https://app.matterai.so`) |
307
308
 
308
309
  `autoApproveEdits` / `autoApproveSafeCommands` set the session defaults for the
309
310
  approval prompts (dangerous commands still always prompt); shift+tab cycles
@@ -365,19 +366,19 @@ reset date — the same data as the extension's profile view.
365
366
 
366
367
  Active in the CLI (schemas byte-identical to the extension's `native-tools`):
367
368
 
368
- | tool | executor notes |
369
- |------|----------------|
370
- | `read_file` | line-numbered output (`LINE\|content`, 6-char pad), 1000-line cap, offset/limit |
371
- | `file_edit` | single replacement; unique-match enforcement; `replace_all`; empty `old_string` = whole file |
372
- | `multi_file_edit` | batched edits grouped per file, per-edit OK/FAILED results |
373
- | `file_write` | creates parent dirs, full-content writes |
374
- | `list_files` | optional recursive, ignores node_modules/.git/build dirs, 800-entry cap |
375
- | `search_files` | JS regex search with glob `file_pattern` (picomatch), 300-match cap, binary skip |
376
- | `execute_command` | user's shell, 120s timeout, 30k output cap, optional cwd |
377
- | `web_search` / `web_fetch` | proxied through the MatterAI backend with your token |
378
- | `update_todo_list` | drives the TUI todo panel |
379
- | `ask_followup_question` | interactive menu in the TUI |
380
- | `attempt_completion` | ends the turn with a completion card |
369
+ | tool | executor notes |
370
+ | -------------------------- | -------------------------------------------------------------------------------------------- |
371
+ | `read_file` | line-numbered output (`LINE\|content`, 6-char pad), 1000-line cap, offset/limit |
372
+ | `file_edit` | single replacement; unique-match enforcement; `replace_all`; empty `old_string` = whole file |
373
+ | `multi_file_edit` | batched edits grouped per file, per-edit OK/FAILED results |
374
+ | `file_write` | creates parent dirs, full-content writes |
375
+ | `list_files` | optional recursive, ignores node_modules/.git/build dirs, 800-entry cap |
376
+ | `search_files` | JS regex search with glob `file_pattern` (picomatch), 300-match cap, binary skip |
377
+ | `execute_command` | user's shell, 120s timeout, 30k output cap, optional cwd |
378
+ | `web_search` / `web_fetch` | proxied through the MatterAI backend with your token |
379
+ | `update_todo_list` | drives the TUI todo panel |
380
+ | `ask_followup_question` | interactive menu in the TUI |
381
+ | `attempt_completion` | ends the turn with a completion card |
381
382
 
382
383
  Present in `tools/schemas/` but **inactive** (need IDE services): `codebase_search`,
383
384
  `lsp`, `list_code_definition_names`, `use_skill`, `check_past_chat_memories`,
@@ -417,6 +418,7 @@ Source-of-truth rule: behavior is **ported from the Orbital extension repo**
417
418
  schemas byte-identical rather than editing them here.
418
419
 
419
420
  Backend/web pieces of the device-auth flow live in:
421
+
420
422
  - `gravity-console-backend` → `src/controller/orbcodeAuthController.ts`
421
423
  (+ OAuth state in `router.ts`, callbacks in `authController.ts`)
422
424
  - `gravity-console-webapp` → authorize dialog in `src/App.js`, sign-in q-p
@@ -21,6 +21,17 @@ export const AXON_MODELS = {
21
21
  outputPrice: 0.000006,
22
22
  free: false,
23
23
  },
24
+ "axon-eido-3-code-pro": {
25
+ id: "axon-eido-3-code-pro",
26
+ name: "Axon Eido 3 Pro",
27
+ description: "Axon Eido 3 Pro is the frontier Axon Code model for coding tasks, long running agents and general intelligence, fine-tuned on open source models.",
28
+ contextWindow: 400000,
29
+ maxOutputTokens: 64000,
30
+ supportsImages: true,
31
+ inputPrice: 0.000003,
32
+ outputPrice: 0.000009,
33
+ free: false,
34
+ },
24
35
  };
25
36
  export const DEFAULT_MODEL_ID = "axon-code-2-5-pro";
26
37
  /** Add user-defined models (from settings.json) to the registry. */
package/dist/auth/auth.js CHANGED
@@ -78,7 +78,10 @@ export async function pollDeviceAuth(devicecode) {
78
78
  export async function fetchProfile(token) {
79
79
  const url = getUrlFromToken("https://api.matterai.so/axoncode/profile", token);
80
80
  const response = await fetch(url, {
81
- headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
81
+ headers: {
82
+ Authorization: `Bearer ${token}`,
83
+ "Content-Type": "application/json",
84
+ },
82
85
  });
83
86
  if (!response.ok) {
84
87
  throw new Error(`Profile request failed (${response.status}). Your token may be invalid or expired.`);
@@ -150,7 +153,9 @@ export async function fetchTaskTitle(taskId, token, maxRetries = 3, retryDelayMs
150
153
  export async function fetchBalance(token, organizationId) {
151
154
  try {
152
155
  const url = getUrlFromToken("https://api.matterai.so/api/profile/balance", token);
153
- const headers = { Authorization: `Bearer ${token}` };
156
+ const headers = {
157
+ Authorization: `Bearer ${token}`,
158
+ };
154
159
  if (organizationId)
155
160
  headers["X-KiloCode-OrganizationId"] = organizationId;
156
161
  const response = await fetch(url, { headers });
package/dist/ui/App.js CHANGED
@@ -41,6 +41,28 @@ function setTerminalTitle(title) {
41
41
  process.stdout.write(`\x1b]0;${title}\x07`);
42
42
  }
43
43
  }
44
+ function formatRelativeTime(isoStr) {
45
+ if (!isoStr)
46
+ return "???";
47
+ const now = Date.now();
48
+ const target = new Date(isoStr).getTime();
49
+ if (Number.isNaN(target))
50
+ return "???";
51
+ const diff = target - now;
52
+ if (diff <= 0)
53
+ return "now";
54
+ const sec = Math.floor(diff / 1000);
55
+ const min = Math.floor(sec / 60);
56
+ const hrs = Math.floor(min / 60);
57
+ const days = Math.floor(hrs / 24);
58
+ if (days >= 1)
59
+ return `in ${days} day${days > 1 ? "s" : ""}`;
60
+ if (hrs >= 1)
61
+ return `in ${hrs}h ${min % 60}m`;
62
+ if (min >= 1)
63
+ return `in ${min}m`;
64
+ return "soon";
65
+ }
44
66
  /** Human lines for the /status and /cost usage block (extension profile data). */
45
67
  function usageLines(profile) {
46
68
  const lines = [];
@@ -52,8 +74,22 @@ function usageLines(profile) {
52
74
  if (typeof profile.remainingReviews === "number") {
53
75
  lines.push(`Reviews ${profile.remainingReviews} remaining`);
54
76
  }
55
- if (profile.creditsResetDate)
77
+ if (profile.tieredUsage) {
78
+ const ws = [
79
+ ["5hr", "5-Hour", profile.tieredUsage.fiveHour],
80
+ ["wk", "Weekly", profile.tieredUsage.weekly],
81
+ ["mo", "Monthly", profile.tieredUsage.monthly],
82
+ ];
83
+ for (const [short, label, w] of ws) {
84
+ const remaining = Math.max(0, w.remaining || 0);
85
+ const pct = Math.max(0, Math.min(100, w.percentage || 0));
86
+ const reset = formatRelativeTime(w.resetsAt);
87
+ lines.push(`${label.padEnd(12)} ${remaining.toFixed(1)}/${w.limit.toFixed(1)} left (${pct}% used) · Resets ${reset}`);
88
+ }
89
+ }
90
+ else if (profile.creditsResetDate) {
56
91
  lines.push(`Resets ${profile.creditsResetDate}`);
92
+ }
57
93
  return lines;
58
94
  }
59
95
  const INIT_PROMPT = `Analyze this codebase and create an AGENTS.md file containing:
@@ -139,7 +175,7 @@ export function App({ initialView, initialPrompt, initialSession, }) {
139
175
  if (!token)
140
176
  return;
141
177
  fetchProfile(token)
142
- .then((profile) => setUsage({ plan: profile.plan, usagePercentage: profile.usagePercentage }))
178
+ .then((profile) => setUsage({ plan: profile.plan, usagePercentage: profile.usagePercentage, tieredUsage: profile.tieredUsage }))
143
179
  .catch(() => { });
144
180
  }, []);
145
181
  const agentRef = useRef(null);
@@ -227,6 +263,10 @@ export function App({ initialView, initialPrompt, initialSession, }) {
227
263
  case "usage":
228
264
  setContextTokens(event.inputTokens + event.outputTokens);
229
265
  setTotalCost(event.totalCost);
266
+ // A usage chunk arrives once per LLM response, so the plan/usage
267
+ // shown below the chat box stays current mid-turn, not only
268
+ // after the turn finishes.
269
+ refreshUsage();
230
270
  break;
231
271
  case "completion":
232
272
  pushRow({ kind: "completion", text: event.result });
@@ -324,11 +364,20 @@ export function App({ initialView, initialPrompt, initialSession, }) {
324
364
  if (arg && isValidAxonModel(arg)) {
325
365
  switchModel(arg);
326
366
  }
327
- else if (arg && isValidAxonModel(`axon-code-2-5-${arg}`)) {
328
- switchModel(`axon-code-2-5-${arg}`);
329
- }
330
367
  else if (arg) {
331
- pushRow({ kind: "error", text: `Unknown model "${arg}". Available: ${ids.join(", ")}` });
368
+ // Allow short suffixes like "pro" or "mini" to resolve to the
369
+ // latest matching registered id, so /model pro keeps working
370
+ // as new model generations are added.
371
+ const matches = ids
372
+ .filter((id) => id.endsWith(`-${arg}`))
373
+ .sort()
374
+ .reverse();
375
+ if (matches.length > 0) {
376
+ switchModel(matches[0]);
377
+ }
378
+ else {
379
+ pushRow({ kind: "error", text: `Unknown model "${arg}". Available: ${ids.join(", ")}` });
380
+ }
332
381
  }
333
382
  else {
334
383
  setModelPickerOpen(true);
@@ -539,7 +588,7 @@ export function App({ initialView, initialPrompt, initialSession, }) {
539
588
  saveSettings(updated);
540
589
  agentRef.current = null;
541
590
  setView("chat");
542
- setUsage({ plan: profile.plan, usagePercentage: profile.usagePercentage });
591
+ setUsage({ plan: profile.plan, usagePercentage: profile.usagePercentage, tieredUsage: profile.tieredUsage });
543
592
  const who = profile.user?.name || profile.user?.email;
544
593
  pushRow({ kind: "info", text: `Signed in${who ? ` as ${who}` : ""}. Ready when you are.` });
545
594
  }, [pushRow]);
@@ -558,7 +607,7 @@ export function App({ initialView, initialPrompt, initialSession, }) {
558
607
  pushRow({ kind: "user", text: answer });
559
608
  pendingFollowup.resolve(answer);
560
609
  setPendingFollowup(null);
561
- } }) })), busy && !pendingApproval && !pendingFollowup && !streamingText && (_jsx(Box, { marginTop: 1, children: _jsx(Spinner, { label: busyLabel }) })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(InputBox, { active: inputActive, slashCommands: SLASH_COMMANDS, onSubmit: handleSubmit }), _jsx(StatusBar, { modelId: settings.model, contextTokens: contextTokens, totalCost: totalCost, state: busy ? busyLabel : "", approvalMode: approvalMode, busy: busy, title: sessionTitle, plan: usage?.plan, usagePercentage: usage?.usagePercentage })] })] }))] }));
610
+ } }) })), busy && !pendingApproval && !pendingFollowup && !streamingText && (_jsx(Box, { marginTop: 1, children: _jsx(Spinner, { label: busyLabel }) })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(InputBox, { active: inputActive, slashCommands: SLASH_COMMANDS, onSubmit: handleSubmit }), _jsx(StatusBar, { modelId: settings.model, contextTokens: contextTokens, totalCost: totalCost, state: busy ? busyLabel : "", approvalMode: approvalMode, busy: busy, title: sessionTitle, plan: usage?.plan, usagePercentage: usage?.usagePercentage, tieredUsage: usage?.tieredUsage })] })] }))] }));
562
611
  }
563
612
  function tail(text, lines) {
564
613
  const all = text.split("\n").filter((l) => l.trim());
@@ -7,12 +7,51 @@ const MODE_LABELS = {
7
7
  edits: "⏵⏵ accept edits on",
8
8
  auto: "⏵⏵⏵ auto-approve on",
9
9
  };
10
+ function formatRelativeTime(isoStr) {
11
+ if (!isoStr)
12
+ return "???";
13
+ const now = Date.now();
14
+ const target = new Date(isoStr).getTime();
15
+ if (Number.isNaN(target))
16
+ return "???";
17
+ const diff = target - now;
18
+ if (diff <= 0)
19
+ return "now";
20
+ const sec = Math.floor(diff / 1000);
21
+ const min = Math.floor(sec / 60);
22
+ const hrs = Math.floor(min / 60);
23
+ const days = Math.floor(hrs / 24);
24
+ if (days >= 1)
25
+ return `${days}d`;
26
+ if (hrs >= 1)
27
+ return `${hrs}h${min % 60 > 0 ? ` ${min % 60}m` : ""}`;
28
+ if (min >= 1)
29
+ return `${min}m`;
30
+ return "soon";
31
+ }
10
32
  function truncate(text, max) {
11
33
  return text.length > max ? text.slice(0, max - 1) + "…" : text;
12
34
  }
13
- export function StatusBar({ modelId, contextTokens, totalCost, state, approvalMode, busy, title, plan, usagePercentage, }) {
35
+ /**
36
+ * Picks the most constrained window (highest percentage used) and returns a
37
+ * compact string like "5hr 12% · resets in 3h 15m".
38
+ */
39
+ function mostConstrainedSummary(tu) {
40
+ const windows = [
41
+ ["5hr", tu.fiveHour.percentage, tu.fiveHour.resetsAt],
42
+ ["wk", tu.weekly.percentage, tu.weekly.resetsAt],
43
+ ["mo", tu.monthly.percentage, tu.monthly.resetsAt],
44
+ ];
45
+ const [label, pct, resetsAt] = windows.reduce((best, cur) => cur[1] >= best[1] ? cur : best);
46
+ return `${label} ${Math.round(pct)}% · resets ${formatRelativeTime(resetsAt)}`;
47
+ }
48
+ export function StatusBar({ modelId, contextTokens, totalCost, state, approvalMode, busy, title, plan, usagePercentage, tieredUsage, }) {
14
49
  const model = getModel(modelId);
15
50
  const contextPct = Math.min(100, Math.round((contextTokens / model.contextWindow) * 100));
16
- const remaining = typeof usagePercentage === "number" ? Math.max(0, Math.round(100 - usagePercentage)) : undefined;
17
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsxs(Text, { dimColor: true, children: [_jsx(Text, { color: approvalMode === "ask" ? undefined : COLORS.warning, children: MODE_LABELS[approvalMode] }), " (shift+tab to cycle)", busy && " · esc to interrupt", state ? _jsxs(Text, { color: COLORS.thinking, children: [" \u00B7 ", state] }) : null] }), _jsxs(Text, { dimColor: true, children: [title ? `${truncate(title, 32)} · ` : "", model.name, " \u00B7 ctx ", contextTokens.toLocaleString(), " (", contextPct, "%)", model.free ? " · free" : ` · $${totalCost.toFixed(4)}`] })] }), (plan || remaining !== undefined) && (_jsx(Box, { justifyContent: "flex-end", children: _jsxs(Text, { dimColor: true, children: [plan ? `${plan} plan` : "", plan && remaining !== undefined ? " · " : "", remaining !== undefined ? (_jsxs(Text, { color: remaining <= 10 ? COLORS.error : undefined, children: [remaining, "% usage remaining"] })) : null] }) }))] }));
51
+ const constrainedLine = tieredUsage
52
+ ? mostConstrainedSummary(tieredUsage)
53
+ : typeof usagePercentage === "number"
54
+ ? `${Math.round(usagePercentage)}% used`
55
+ : null;
56
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsxs(Text, { dimColor: true, children: [_jsx(Text, { color: approvalMode === "ask" ? undefined : COLORS.warning, children: MODE_LABELS[approvalMode] }), " (shift+tab to cycle)", busy && " · esc to interrupt", state ? _jsxs(Text, { color: COLORS.thinking, children: [" \u00B7 ", state] }) : null] }), _jsxs(Text, { dimColor: true, children: [title ? `${truncate(title, 32)} · ` : "", model.name, " \u00B7 ctx ", contextTokens.toLocaleString(), " (", contextPct, "%)", model.free ? " · free" : ` · $${totalCost.toFixed(4)}`] })] }), (plan || constrainedLine) && (_jsx(Box, { justifyContent: "flex-end", children: _jsxs(Text, { dimColor: true, children: [plan && constrainedLine ? " · " : "", constrainedLine] }) }))] }));
18
57
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterailab/orbcode",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "OrbCode CLI — agentic coding in your terminal, powered by Axon models by MatterAI",
5
5
  "type": "module",
6
6
  "bin": {