@matterailab/orbcode 0.1.14 โ 0.2.0
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 +13 -13
- package/dist/auth/auth.js +2 -2
- package/dist/config/settings.js +10 -10
- package/dist/core/hooks.js +6 -6
- package/dist/headless.js +4 -4
- package/dist/index.js +2 -2
- package/dist/ui/App.js +1 -1
- package/dist/ui/LoginView.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -130,10 +130,10 @@ Fallbacks & overrides:
|
|
|
130
130
|
- **settings.json key**: set `apiKey` in `~/.orbcode/settings.json` (or a
|
|
131
131
|
project's `.orbcode/settings.json`) to skip login. The login screen itself is
|
|
132
132
|
browser-redirect only.
|
|
133
|
-
- **Env token**: set `
|
|
133
|
+
- **Env token**: set `MATTERAI_TOKEN` to skip login entirely (takes precedence
|
|
134
134
|
over everything).
|
|
135
|
-
- **Dev endpoints**: `
|
|
136
|
-
and `
|
|
135
|
+
- **Dev endpoints**: `MATTERAI_BACKEND_URL` (default `https://api.matterai.so`)
|
|
136
|
+
and `MATTERAI_APP_URL` (default `https://app.matterai.so`) override where the
|
|
137
137
|
device flow points โ useful against a local backend/webapp.
|
|
138
138
|
- Tokens are MatterAI JWTs. A token whose payload has `env: "development"`
|
|
139
139
|
automatically routes API calls to `http://localhost:3000`, matching the
|
|
@@ -346,13 +346,13 @@ and `--resume <id>`.
|
|
|
346
346
|
|
|
347
347
|
| env var | effect |
|
|
348
348
|
| --------------------- | ----------------------------------------------------------------- |
|
|
349
|
-
| `
|
|
350
|
-
| `
|
|
351
|
-
| `
|
|
352
|
-
| `
|
|
353
|
-
| `
|
|
354
|
-
| `
|
|
355
|
-
| `
|
|
349
|
+
| `MATTERAI_TOKEN` | auth token (overrides everything) |
|
|
350
|
+
| `MATTERAI_API_KEY` | same as `apiKey` in settings.json |
|
|
351
|
+
| `MATTERAI_BASE_URL` | same as `baseUrl` in settings.json |
|
|
352
|
+
| `MATTERAI_MODEL` | model override (what `--model` sets internally) |
|
|
353
|
+
| `MATTERAI_CONFIG_DIR` | config directory (default `~/.orbcode`) |
|
|
354
|
+
| `MATTERAI_BACKEND_URL` | device-auth backend (default `https://api.matterai.so`) |
|
|
355
|
+
| `MATTERAI_APP_URL` | webapp for the authorize page (default `https://app.matterai.so`) |
|
|
356
356
|
|
|
357
357
|
`autoApproveEdits` / `autoApproveSafeCommands` set the session defaults for the
|
|
358
358
|
approval prompts (dangerous commands still always prompt); shift+tab cycles
|
|
@@ -365,7 +365,7 @@ them to **block** dangerous actions, **auto-approve** trusted ones, **rewrite**
|
|
|
365
365
|
tool inputs, **inject context** into the model, **format code** after edits,
|
|
366
366
|
**notify** you, or **keep the agent working** until a condition is met. They use
|
|
367
367
|
the **same contract as Claude Code's hooks**, so scripts written for it work
|
|
368
|
-
here (just use `$
|
|
368
|
+
here (just use `$MATTERAI_PROJECT_DIR` and OrbCode's tool names).
|
|
369
369
|
|
|
370
370
|
> ๐ **This is the overview. The complete, example-driven reference โ
|
|
371
371
|
> per-event input/output, a copy-paste cookbook, debugging, and security โ is in
|
|
@@ -588,8 +588,8 @@ node test-device-auth.mjs # device-auth polling flow against a local mock
|
|
|
588
588
|
command runs `dist/`, and the version is read from `package.json` at runtime.
|
|
589
589
|
- **Stale link after the rename** โ `npm unlink -g orbitalcode && npm link`.
|
|
590
590
|
- **Login times out** โ the device code lives 10 minutes; press Enter to retry,
|
|
591
|
-
or paste a token manually. Against a local stack, set `
|
|
592
|
-
and `
|
|
591
|
+
or paste a token manually. Against a local stack, set `MATTERAI_BACKEND_URL`
|
|
592
|
+
and `MATTERAI_APP_URL`.
|
|
593
593
|
- **401 on chat** โ token expired: `/logout` then `/login`.
|
|
594
594
|
- **Keyboard input does nothing** โ OrbCode needs a real TTY (raw mode); it
|
|
595
595
|
won't accept piped stdin. Use `-p` for non-interactive runs.
|
package/dist/auth/auth.js
CHANGED
|
@@ -32,10 +32,10 @@ export function getSignInUrl() {
|
|
|
32
32
|
return `${APP_URL}/authentication/sign-in?loginType=extension&source=cli`;
|
|
33
33
|
}
|
|
34
34
|
function deviceAuthBaseUrl() {
|
|
35
|
-
return process.env.
|
|
35
|
+
return process.env.MATTERAI_BACKEND_URL || DEFAULT_BACKEND_URL;
|
|
36
36
|
}
|
|
37
37
|
function deviceAuthAppUrl() {
|
|
38
|
-
return process.env.
|
|
38
|
+
return process.env.MATTERAI_APP_URL || APP_URL;
|
|
39
39
|
}
|
|
40
40
|
export async function startDeviceAuth() {
|
|
41
41
|
const response = await fetch(`${deviceAuthBaseUrl()}/orbcode/auth/start`, {
|
package/dist/config/settings.js
CHANGED
|
@@ -20,7 +20,7 @@ const SETTINGS_KEYS = [
|
|
|
20
20
|
"env",
|
|
21
21
|
];
|
|
22
22
|
export function getConfigDir() {
|
|
23
|
-
return process.env.
|
|
23
|
+
return process.env.MATTERAI_CONFIG_DIR || path.join(os.homedir(), ".orbcode");
|
|
24
24
|
}
|
|
25
25
|
function getConfigPath() {
|
|
26
26
|
return path.join(getConfigDir(), "config.json");
|
|
@@ -76,7 +76,7 @@ function isProjectHooksTrusted(cwd, hash) {
|
|
|
76
76
|
// stdin is not a TTY (so a stray export in a shell rc file can't silently
|
|
77
77
|
// disable the trust gate for interactive sessions). A non-TTY check keeps
|
|
78
78
|
// the gate meaningful in the TUI while still letting CI opt in.
|
|
79
|
-
if (process.env.
|
|
79
|
+
if (process.env.MATTERAI_TRUST_PROJECT_HOOKS === "1" && !process.stdin.isTTY)
|
|
80
80
|
return true;
|
|
81
81
|
const store = readJson(getTrustStorePath());
|
|
82
82
|
return Boolean(store && store[cwd] === hash);
|
|
@@ -179,23 +179,23 @@ export function loadSettings() {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
// Environment variables take precedence over all files.
|
|
182
|
-
if (process.env.
|
|
183
|
-
settings.baseUrl = process.env.
|
|
184
|
-
if (process.env.
|
|
185
|
-
settings.apiKey = process.env.
|
|
186
|
-
if (process.env.
|
|
187
|
-
settings.model = process.env.
|
|
182
|
+
if (process.env.MATTERAI_BASE_URL)
|
|
183
|
+
settings.baseUrl = process.env.MATTERAI_BASE_URL;
|
|
184
|
+
if (process.env.MATTERAI_API_KEY)
|
|
185
|
+
settings.apiKey = process.env.MATTERAI_API_KEY;
|
|
186
|
+
if (process.env.MATTERAI_MODEL)
|
|
187
|
+
settings.model = process.env.MATTERAI_MODEL;
|
|
188
188
|
if (!isValidAxonModel(settings.model)) {
|
|
189
189
|
settings.model = DEFAULT_MODEL_ID;
|
|
190
190
|
}
|
|
191
191
|
return settings;
|
|
192
192
|
}
|
|
193
193
|
/**
|
|
194
|
-
* Effective credential:
|
|
194
|
+
* Effective credential: MATTERAI_TOKEN env > apiKey (settings.json / env) >
|
|
195
195
|
* stored login token.
|
|
196
196
|
*/
|
|
197
197
|
export function getAuthToken(settings) {
|
|
198
|
-
return process.env.
|
|
198
|
+
return process.env.MATTERAI_TOKEN || settings.apiKey || settings.token;
|
|
199
199
|
}
|
|
200
200
|
/** Persist app state to config.json. settings.json-only fields are skipped. */
|
|
201
201
|
export function saveSettings(settings) {
|
package/dist/core/hooks.js
CHANGED
|
@@ -260,11 +260,11 @@ function capContext(text) {
|
|
|
260
260
|
}
|
|
261
261
|
/** Keys always stripped from the hook environment (OrbCode credentials/config). */
|
|
262
262
|
const HOOK_ENV_REDACT_EXACT = new Set([
|
|
263
|
-
"
|
|
264
|
-
"
|
|
265
|
-
"
|
|
266
|
-
"
|
|
267
|
-
"
|
|
263
|
+
"MATTERAI_TOKEN",
|
|
264
|
+
"MATTERAI_API_KEY",
|
|
265
|
+
"MATTERAI_CONFIG_DIR",
|
|
266
|
+
"MATTERAI_BACKEND_URL",
|
|
267
|
+
"MATTERAI_APP_URL",
|
|
268
268
|
]);
|
|
269
269
|
/** Pattern for credential-like env var names (TOKEN, KEY, SECRET, โฆ) so
|
|
270
270
|
* third-party secrets (GITHUB_TOKEN, AWS_SECRET_ACCESS_KEY, โฆ) are redacted
|
|
@@ -274,7 +274,7 @@ const HOOK_ENV_REDACT_PATTERN = /(?:^|_)(TOKEN|KEY|SECRET|PASSWORD|PASSWD|CREDEN
|
|
|
274
274
|
* (so PATH, HOME, npx, git, โฆ all work) minus anything that looks like a
|
|
275
275
|
* credential โ hooks must never see the user's API token. */
|
|
276
276
|
function buildHookEnv(cwd) {
|
|
277
|
-
const env = {
|
|
277
|
+
const env = { MATTERAI_PROJECT_DIR: cwd };
|
|
278
278
|
for (const [key, value] of Object.entries(process.env)) {
|
|
279
279
|
if (value === undefined)
|
|
280
280
|
continue;
|
package/dist/headless.js
CHANGED
|
@@ -4,9 +4,9 @@ import { Agent } from "./core/agent.js";
|
|
|
4
4
|
/** Non-interactive `orbcode -p "prompt"` mode: prints the final response to stdout. */
|
|
5
5
|
export async function runHeadless(prompt, yolo) {
|
|
6
6
|
const settings = loadSettings();
|
|
7
|
-
// An unknown --model (or
|
|
7
|
+
// An unknown --model (or MATTERAI_MODEL) silently resolves to the default; say
|
|
8
8
|
// so on stderr instead of quietly running a different model than requested.
|
|
9
|
-
const requestedModel = process.env.
|
|
9
|
+
const requestedModel = process.env.MATTERAI_MODEL;
|
|
10
10
|
if (requestedModel && !isValidAxonModel(requestedModel)) {
|
|
11
11
|
process.stderr.write(`warning: unknown model "${requestedModel}"; using "${settings.model}". ` +
|
|
12
12
|
`Add it under "customModels" in settings.json (with a "provider") to use it.\n`);
|
|
@@ -18,7 +18,7 @@ export async function runHeadless(prompt, yolo) {
|
|
|
18
18
|
// so they don't need a MatterAI login. Only gate on the token when the
|
|
19
19
|
// selected model actually goes through the MatterAI gateway.
|
|
20
20
|
if (!token && !usesAiSdk(getModel(settings.model))) {
|
|
21
|
-
console.error("Not signed in. Run `orbcode login`, set
|
|
21
|
+
console.error("Not signed in. Run `orbcode login`, set MATTERAI_TOKEN, or put an apiKey in settings.json.");
|
|
22
22
|
process.exit(1);
|
|
23
23
|
}
|
|
24
24
|
// There's no interactive trust prompt in headless mode, so untrusted project
|
|
@@ -26,7 +26,7 @@ export async function runHeadless(prompt, yolo) {
|
|
|
26
26
|
const pendingHooks = getPendingProjectHooks();
|
|
27
27
|
if (pendingHooks) {
|
|
28
28
|
process.stderr.write(`note: ${pendingHooks.commands.length} project hook(s) in .orbcode/settings.json are untrusted and were skipped. ` +
|
|
29
|
-
`Trust them in an interactive session, or set
|
|
29
|
+
`Trust them in an interactive session, or set MATTERAI_TRUST_PROJECT_HOOKS=1.\n`);
|
|
30
30
|
}
|
|
31
31
|
let exitCode = 0;
|
|
32
32
|
// Only the final content is printed: either the attempt_completion result
|
package/dist/index.js
CHANGED
|
@@ -88,9 +88,9 @@ async function main() {
|
|
|
88
88
|
}
|
|
89
89
|
const model = takeFlagValue(args, "model") ?? takeFlagValue(args, "m");
|
|
90
90
|
if (model) {
|
|
91
|
-
// loadSettings() treats
|
|
91
|
+
// loadSettings() treats MATTERAI_MODEL as the highest-precedence override,
|
|
92
92
|
// so the flag reaches both the TUI and headless mode without plumbing.
|
|
93
|
-
process.env.
|
|
93
|
+
process.env.MATTERAI_MODEL = model;
|
|
94
94
|
}
|
|
95
95
|
let initialSession;
|
|
96
96
|
const resumeId = takeFlagValue(args, "resume") ?? takeFlagValue(args, "r");
|
package/dist/ui/App.js
CHANGED
|
@@ -523,7 +523,7 @@ export function App({ initialView, initialPrompt, initialSession, updateCheck, }
|
|
|
523
523
|
`Version ${VERSION}`,
|
|
524
524
|
`Model ${model.name} (${model.id})`,
|
|
525
525
|
`Directory ${process.cwd()}`,
|
|
526
|
-
`Account ${getAuthToken(settings) ? (settings.apiKey || process.env.
|
|
526
|
+
`Account ${getAuthToken(settings) ? (settings.apiKey || process.env.MATTERAI_TOKEN ? "API key" : "signed in") : "signed out"}${settings.organizationId ? ` ยท org ${settings.organizationId}` : ""}`,
|
|
527
527
|
`Gateway ${settings.baseUrl ?? "MatterAI (default)"}`,
|
|
528
528
|
`Context ${contextTokens.toLocaleString()} / ${model.contextWindow.toLocaleString()} tokens (${contextPct}%)`,
|
|
529
529
|
`Cost $${totalCost.toFixed(4)} this session`,
|
package/dist/ui/LoginView.js
CHANGED
|
@@ -78,5 +78,5 @@ export function LoginView({ onLogin }) {
|
|
|
78
78
|
void beginBrowserLogin();
|
|
79
79
|
}
|
|
80
80
|
});
|
|
81
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: COLORS.primary, paddingX: 1, children: [_jsxs(Text, { bold: true, color: COLORS.primary, children: ["Sign in to ", PRODUCT_NAME] }), phase === "waiting" ? (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, children: _jsx(Spinner, { label: "Waiting for authorization in your browser" }) }), _jsx(Text, { dimColor: true, children: "Approve the \"Authorize OrbCode CLI\" dialog at:" }), _jsxs(Text, { dimColor: true, children: [" ", authorizeUrl] }), _jsx(Text, { dimColor: true, children: "Esc to cancel" })] })) : (_jsxs(Text, { children: ["Press ", _jsx(Text, { bold: true, children: "Enter" }), " to open MatterAI in your browser and authorize OrbCode CLI."] })), phase === "starting" && _jsx(Text, { color: COLORS.thinking, children: "Contacting sign-in service\u2026" }), phase === "verifying" && _jsx(Text, { color: COLORS.thinking, children: "Verifying\u2026" }), error && _jsxs(Text, { color: COLORS.error, children: ["\u2717 ", error] }), _jsx(Text, { dimColor: true, children: "To use a token instead, set apiKey in ~/.orbcode/settings.json or the
|
|
81
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: COLORS.primary, paddingX: 1, children: [_jsxs(Text, { bold: true, color: COLORS.primary, children: ["Sign in to ", PRODUCT_NAME] }), phase === "waiting" ? (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, children: _jsx(Spinner, { label: "Waiting for authorization in your browser" }) }), _jsx(Text, { dimColor: true, children: "Approve the \"Authorize OrbCode CLI\" dialog at:" }), _jsxs(Text, { dimColor: true, children: [" ", authorizeUrl] }), _jsx(Text, { dimColor: true, children: "Esc to cancel" })] })) : (_jsxs(Text, { children: ["Press ", _jsx(Text, { bold: true, children: "Enter" }), " to open MatterAI in your browser and authorize OrbCode CLI."] })), phase === "starting" && _jsx(Text, { color: COLORS.thinking, children: "Contacting sign-in service\u2026" }), phase === "verifying" && _jsx(Text, { color: COLORS.thinking, children: "Verifying\u2026" }), error && _jsxs(Text, { color: COLORS.error, children: ["\u2717 ", error] }), _jsx(Text, { dimColor: true, children: "To use a token instead, set apiKey in ~/.orbcode/settings.json or the MATTERAI_TOKEN env var." })] }));
|
|
82
82
|
}
|