@aexhq/sdk 0.40.6 → 0.40.7
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 +159 -159
- package/dist/_contracts/stable.d.ts +10 -5
- package/dist/_contracts/stable.js +10 -5
- package/dist/client.js +5 -11
- package/dist/client.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/authentication.md +125 -125
- package/docs/billing.md +118 -118
- package/docs/concepts/agent-tools.md +66 -66
- package/docs/concepts/composition.md +37 -37
- package/docs/concepts/providers-and-runtimes.md +54 -54
- package/docs/concepts/runs.md +49 -49
- package/docs/concepts/subagents.md +88 -88
- package/docs/credentials.md +125 -125
- package/docs/defaults.md +64 -64
- package/docs/errors.md +196 -196
- package/docs/events.md +243 -243
- package/docs/limits-and-quotas.md +144 -144
- package/docs/limits.md +50 -50
- package/docs/mcp.md +44 -44
- package/docs/networking.md +163 -163
- package/docs/outputs.md +267 -267
- package/docs/public-surface.json +77 -77
- package/docs/quickstart.md +119 -119
- package/docs/release.md +38 -38
- package/docs/retries.md +129 -129
- package/docs/run-config.md +58 -58
- package/docs/run-record.md +55 -55
- package/docs/secrets.md +125 -125
- package/docs/testing.md +35 -35
- package/docs/vision-skills.md +91 -91
- package/docs/webhooks.md +127 -127
- package/examples/feature-tour.ts +282 -282
- package/examples/spike-settle-latency.ts +125 -125
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,159 +1,159 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: aex
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# @aexhq/sdk
|
|
6
|
-
|
|
7
|
-
aex is an agent execution platform for launching autonomous agents from a simple TypeScript SDK and CLI.
|
|
8
|
-
|
|
9
|
-
The package ships:
|
|
10
|
-
|
|
11
|
-
- `Aex` for sessions, one-shot runs, inspect, download, cancel, and delete.
|
|
12
|
-
- `sessions` / `openSession()` for durable, resumable agent sessions.
|
|
13
|
-
- Typed run primitives: `Models`, `Providers`, `Sizes`, `Skill`, `Tool` / `Tools`, `AgentsMd`, `File`, `McpServer`, and `Secret`.
|
|
14
|
-
- A bundled `aex` CLI with the same run, status, events, outputs, download, cancel, delete, and whoami operations.
|
|
15
|
-
|
|
16
|
-
## Install
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm i @aexhq/sdk
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
This installs the TypeScript SDK exports and the bundled `aex` CLI. The CLI
|
|
23
|
-
ships inside the package — invoke it with `npx aex …` after a local install, or
|
|
24
|
-
`npm i -g @aexhq/sdk` to put a bare `aex` on your PATH. Set both credentials
|
|
25
|
-
before running the examples: `AEX_API_KEY` authenticates to aex, and
|
|
26
|
-
`ANTHROPIC_API_KEY` is your BYOK provider key for Claude.
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
export AEX_API_KEY="<your-aex-api-key>"
|
|
30
|
-
export ANTHROPIC_API_KEY="<your-anthropic-api-key>"
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## First Session
|
|
34
|
-
|
|
35
|
-
```ts
|
|
36
|
-
import { Aex, Models, Sizes } from "@aexhq/sdk";
|
|
37
|
-
|
|
38
|
-
const aex = new Aex(process.env.AEX_API_KEY!);
|
|
39
|
-
|
|
40
|
-
const session = await aex.openSession({
|
|
41
|
-
model: Models.CLAUDE_HAIKU_4_5,
|
|
42
|
-
system: "You are a concise engineering assistant.",
|
|
43
|
-
runtime: Sizes.SHARED_0_25X_1GB,
|
|
44
|
-
// Default is "3m"; set it explicitly when you want a different idle window.
|
|
45
|
-
overrides: { idleTtl: "3m" },
|
|
46
|
-
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// done() awaits settle by default, so status is the terminal outcome
|
|
50
|
-
// ("succeeded"), and costUsd/usage are populated.
|
|
51
|
-
const first = await session.send("Summarize this repo.").done();
|
|
52
|
-
console.log(first.status, first.costUsd, first.text);
|
|
53
|
-
|
|
54
|
-
const resumed = await aex.openSession(session.id);
|
|
55
|
-
await resumed.send("Continue with the follow-up validation.").done();
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Need a one-shot convenience? `run()` opens a session, sends `message` as one
|
|
59
|
-
turn, and returns the collected result. The returned `runId` is the session id,
|
|
60
|
-
so it can be resumed later with `openSession(runId)`.
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
const result = await aex.run({
|
|
64
|
-
model: Models.CLAUDE_HAIKU_4_5,
|
|
65
|
-
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! },
|
|
66
|
-
message: "Write the report and save outputs."
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
console.log(result.runId, result.status, result.text);
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
For multiple providers, include each BYOK key in `apiKeys`:
|
|
73
|
-
|
|
74
|
-
```ts
|
|
75
|
-
await aex.run({
|
|
76
|
-
model: Models.CLAUDE_HAIKU_4_5,
|
|
77
|
-
apiKeys: {
|
|
78
|
-
anthropic: process.env.ANTHROPIC_API_KEY!,
|
|
79
|
-
openai: process.env.OPENAI_API_KEY!
|
|
80
|
-
},
|
|
81
|
-
message: "Delegate research to a subagent."
|
|
82
|
-
});
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
The same request can run from the bundled CLI (`npx aex` on a local install):
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
npx aex run \
|
|
89
|
-
--api-key "$AEX_API_KEY" \
|
|
90
|
-
--anthropic-api-key "$ANTHROPIC_API_KEY" \
|
|
91
|
-
--model claude-haiku-4-5 \
|
|
92
|
-
--prompt "Write the report and save outputs." \
|
|
93
|
-
--follow
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## CLI: login, discovery, typed errors
|
|
97
|
-
|
|
98
|
-
Stop re-passing `--api-key` on every command — log in once and the token (plus
|
|
99
|
-
your default `--aex-url`) is persisted to a `0600` config file
|
|
100
|
-
(`$XDG_CONFIG_HOME/aex/config.json` or `~/.config/aex/config.json`; `%APPDATA%\aex\config.json`
|
|
101
|
-
on Windows). An explicit `--api-key` flag always overrides the stored one.
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
npx aex login --api-key "$AEX_API_KEY" [--aex-url https://api.aex.dev]
|
|
105
|
-
npx aex whoami # no --api-key needed after login
|
|
106
|
-
npx aex whoami --json # machine-readable workspace + scopes + limits
|
|
107
|
-
npx aex auth status # show the resolved config (the token value is never printed)
|
|
108
|
-
npx aex logout # clear the stored token
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
Discover the closed sets the platform accepts — no token, no network (human table
|
|
112
|
-
by default, machine JSON under `--json`). Per-verb `--help` is also key-free:
|
|
113
|
-
|
|
114
|
-
```bash
|
|
115
|
-
npx aex models list # canonical models + their default provider
|
|
116
|
-
npx aex providers list # providers + the models each serves
|
|
117
|
-
npx aex tools list # complete builtin tool set
|
|
118
|
-
npx aex runtime-sizes list # managed runtime presets (cpus / memory / default)
|
|
119
|
-
npx aex run --help # flags for one verb (no API key required)
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Errors are typed and actionable. Every `openSession()` / `run()` config-validation
|
|
123
|
-
failure throws a `RunConfigValidationError` (`err.code === "RUN_CONFIG_INVALID"`)
|
|
124
|
-
you can `catch` by code; CLI failures print a JSON envelope carrying the HTTP
|
|
125
|
-
`status`, a one-line `remedy`, and the `runId` where known, and a wrong `--model`,
|
|
126
|
-
`--provider`, or `--runtime-size` gets a "did you mean?" suggestion.
|
|
127
|
-
|
|
128
|
-
## Continue with sessions
|
|
129
|
-
|
|
130
|
-
Use sessions for conversational flows. `run()` is the one-shot convenience; a
|
|
131
|
-
`SessionHandle` is the lower-level surface when you want multiple turns,
|
|
132
|
-
streaming, messages, events, outputs, or downloads.
|
|
133
|
-
|
|
134
|
-
```ts
|
|
135
|
-
const session = await aex.openSession(result.runId);
|
|
136
|
-
const next = await session.send("Turn this into a checklist.").done();
|
|
137
|
-
console.log(next.text);
|
|
138
|
-
|
|
139
|
-
const messages = await session.messages().list();
|
|
140
|
-
const outputs = await aex.sessions.outputs(session.id).list();
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## Feature Areas
|
|
144
|
-
|
|
145
|
-
- **Agent runtime:** managed autonomous runs with filesystem read/edit, grep/glob/head/tail, open web fetch/search, background commands, code execution, git, and subagents.
|
|
146
|
-
- **Durable infrastructure:** run records, status, wait/cancel/delete, idempotency, typed events, output capture, downloads, timeouts, and runtime sizes.
|
|
147
|
-
- **Agent composition:** skills, files, AGENTS.md, remote MCP servers, environment variables, packages, and networking controls.
|
|
148
|
-
- **Subagents:** typed parent/child lineage for async child runs, output handoff, and bounded agent delegation.
|
|
149
|
-
- **Models and providers:** Anthropic, DeepSeek, OpenAI, Gemini, Mistral, OpenRouter, Doubao, and Doubao China behind one submission shape.
|
|
150
|
-
- **Typed control surface:** strongly typed SDK inputs, CLI parity, BYOK provider keys, workspace secrets, redaction, and output modes.
|
|
151
|
-
|
|
152
|
-
## Docs
|
|
153
|
-
|
|
154
|
-
- [Quickstart](docs/quickstart.md)
|
|
155
|
-
- [Run configuration](docs/run-config.md)
|
|
156
|
-
- [Composition](docs/concepts/composition.md)
|
|
157
|
-
- [Secrets](docs/secrets.md)
|
|
158
|
-
- [Limits](docs/limits.md)
|
|
159
|
-
- [Provider/runtime capabilities](docs/provider-runtime-capabilities.md)
|
|
1
|
+
---
|
|
2
|
+
title: aex
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# @aexhq/sdk
|
|
6
|
+
|
|
7
|
+
aex is an agent execution platform for launching autonomous agents from a simple TypeScript SDK and CLI.
|
|
8
|
+
|
|
9
|
+
The package ships:
|
|
10
|
+
|
|
11
|
+
- `Aex` for sessions, one-shot runs, inspect, download, cancel, and delete.
|
|
12
|
+
- `sessions` / `openSession()` for durable, resumable agent sessions.
|
|
13
|
+
- Typed run primitives: `Models`, `Providers`, `Sizes`, `Skill`, `Tool` / `Tools`, `AgentsMd`, `File`, `McpServer`, and `Secret`.
|
|
14
|
+
- A bundled `aex` CLI with the same run, status, events, outputs, download, cancel, delete, and whoami operations.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm i @aexhq/sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This installs the TypeScript SDK exports and the bundled `aex` CLI. The CLI
|
|
23
|
+
ships inside the package — invoke it with `npx aex …` after a local install, or
|
|
24
|
+
`npm i -g @aexhq/sdk` to put a bare `aex` on your PATH. Set both credentials
|
|
25
|
+
before running the examples: `AEX_API_KEY` authenticates to aex, and
|
|
26
|
+
`ANTHROPIC_API_KEY` is your BYOK provider key for Claude.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
export AEX_API_KEY="<your-aex-api-key>"
|
|
30
|
+
export ANTHROPIC_API_KEY="<your-anthropic-api-key>"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## First Session
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { Aex, Models, Sizes } from "@aexhq/sdk";
|
|
37
|
+
|
|
38
|
+
const aex = new Aex(process.env.AEX_API_KEY!);
|
|
39
|
+
|
|
40
|
+
const session = await aex.openSession({
|
|
41
|
+
model: Models.CLAUDE_HAIKU_4_5,
|
|
42
|
+
system: "You are a concise engineering assistant.",
|
|
43
|
+
runtime: Sizes.SHARED_0_25X_1GB,
|
|
44
|
+
// Default is "3m"; set it explicitly when you want a different idle window.
|
|
45
|
+
overrides: { idleTtl: "3m" },
|
|
46
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// done() awaits settle by default, so status is the terminal outcome
|
|
50
|
+
// ("succeeded"), and costUsd/usage are populated.
|
|
51
|
+
const first = await session.send("Summarize this repo.").done();
|
|
52
|
+
console.log(first.status, first.costUsd, first.text);
|
|
53
|
+
|
|
54
|
+
const resumed = await aex.openSession(session.id);
|
|
55
|
+
await resumed.send("Continue with the follow-up validation.").done();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Need a one-shot convenience? `run()` opens a session, sends `message` as one
|
|
59
|
+
turn, and returns the collected result. The returned `runId` is the session id,
|
|
60
|
+
so it can be resumed later with `openSession(runId)`.
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
const result = await aex.run({
|
|
64
|
+
model: Models.CLAUDE_HAIKU_4_5,
|
|
65
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! },
|
|
66
|
+
message: "Write the report and save outputs."
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
console.log(result.runId, result.status, result.text);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For multiple providers, include each BYOK key in `apiKeys`:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
await aex.run({
|
|
76
|
+
model: Models.CLAUDE_HAIKU_4_5,
|
|
77
|
+
apiKeys: {
|
|
78
|
+
anthropic: process.env.ANTHROPIC_API_KEY!,
|
|
79
|
+
openai: process.env.OPENAI_API_KEY!
|
|
80
|
+
},
|
|
81
|
+
message: "Delegate research to a subagent."
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The same request can run from the bundled CLI (`npx aex` on a local install):
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx aex run \
|
|
89
|
+
--api-key "$AEX_API_KEY" \
|
|
90
|
+
--anthropic-api-key "$ANTHROPIC_API_KEY" \
|
|
91
|
+
--model claude-haiku-4-5 \
|
|
92
|
+
--prompt "Write the report and save outputs." \
|
|
93
|
+
--follow
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## CLI: login, discovery, typed errors
|
|
97
|
+
|
|
98
|
+
Stop re-passing `--api-key` on every command — log in once and the token (plus
|
|
99
|
+
your default `--aex-url`) is persisted to a `0600` config file
|
|
100
|
+
(`$XDG_CONFIG_HOME/aex/config.json` or `~/.config/aex/config.json`; `%APPDATA%\aex\config.json`
|
|
101
|
+
on Windows). An explicit `--api-key` flag always overrides the stored one.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx aex login --api-key "$AEX_API_KEY" [--aex-url https://api.aex.dev]
|
|
105
|
+
npx aex whoami # no --api-key needed after login
|
|
106
|
+
npx aex whoami --json # machine-readable workspace + scopes + limits
|
|
107
|
+
npx aex auth status # show the resolved config (the token value is never printed)
|
|
108
|
+
npx aex logout # clear the stored token
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Discover the closed sets the platform accepts — no token, no network (human table
|
|
112
|
+
by default, machine JSON under `--json`). Per-verb `--help` is also key-free:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npx aex models list # canonical models + their default provider
|
|
116
|
+
npx aex providers list # providers + the models each serves
|
|
117
|
+
npx aex tools list # complete builtin tool set
|
|
118
|
+
npx aex runtime-sizes list # managed runtime presets (cpus / memory / default)
|
|
119
|
+
npx aex run --help # flags for one verb (no API key required)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Errors are typed and actionable. Every `openSession()` / `run()` config-validation
|
|
123
|
+
failure throws a `RunConfigValidationError` (`err.code === "RUN_CONFIG_INVALID"`)
|
|
124
|
+
you can `catch` by code; CLI failures print a JSON envelope carrying the HTTP
|
|
125
|
+
`status`, a one-line `remedy`, and the `runId` where known, and a wrong `--model`,
|
|
126
|
+
`--provider`, or `--runtime-size` gets a "did you mean?" suggestion.
|
|
127
|
+
|
|
128
|
+
## Continue with sessions
|
|
129
|
+
|
|
130
|
+
Use sessions for conversational flows. `run()` is the one-shot convenience; a
|
|
131
|
+
`SessionHandle` is the lower-level surface when you want multiple turns,
|
|
132
|
+
streaming, messages, events, outputs, or downloads.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const session = await aex.openSession(result.runId);
|
|
136
|
+
const next = await session.send("Turn this into a checklist.").done();
|
|
137
|
+
console.log(next.text);
|
|
138
|
+
|
|
139
|
+
const messages = await session.messages().list();
|
|
140
|
+
const outputs = await aex.sessions.outputs(session.id).list();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Feature Areas
|
|
144
|
+
|
|
145
|
+
- **Agent runtime:** managed autonomous runs with filesystem read/edit, grep/glob/head/tail, open web fetch/search, background commands, code execution, git, and subagents.
|
|
146
|
+
- **Durable infrastructure:** run records, status, wait/cancel/delete, idempotency, typed events, output capture, downloads, timeouts, and runtime sizes.
|
|
147
|
+
- **Agent composition:** skills, files, AGENTS.md, remote MCP servers, environment variables, packages, and networking controls.
|
|
148
|
+
- **Subagents:** typed parent/child lineage for async child runs, output handoff, and bounded agent delegation.
|
|
149
|
+
- **Models and providers:** Anthropic, DeepSeek, OpenAI, Gemini, Mistral, OpenRouter, Doubao, and Doubao China behind one submission shape.
|
|
150
|
+
- **Typed control surface:** strongly typed SDK inputs, CLI parity, BYOK provider keys, workspace secrets, redaction, and output modes.
|
|
151
|
+
|
|
152
|
+
## Docs
|
|
153
|
+
|
|
154
|
+
- [Quickstart](docs/quickstart.md)
|
|
155
|
+
- [Run configuration](docs/run-config.md)
|
|
156
|
+
- [Composition](docs/concepts/composition.md)
|
|
157
|
+
- [Secrets](docs/secrets.md)
|
|
158
|
+
- [Limits](docs/limits.md)
|
|
159
|
+
- [Provider/runtime capabilities](docs/provider-runtime-capabilities.md)
|
|
@@ -22,18 +22,23 @@
|
|
|
22
22
|
* exact default API plane.
|
|
23
23
|
*/
|
|
24
24
|
export declare const AEX_DEFAULT_BASE_URL = "https://api.aex.dev";
|
|
25
|
+
/**
|
|
26
|
+
* Canonical hosted dev API plane URL. Used when a self-describing dev API key is
|
|
27
|
+
* passed with no explicit `baseUrl`.
|
|
28
|
+
*/
|
|
29
|
+
export declare const AEX_DEV_BASE_URL = "https://dev-api.aex.dev";
|
|
25
30
|
/**
|
|
26
31
|
* Plane → API base URL. When the SDK constructor is given no explicit `baseUrl`
|
|
27
32
|
* it DERIVES the target from the API key's embedded plane (see
|
|
28
33
|
* {@link import("./api-key.js").parseApiKey}) rather than blindly defaulting to
|
|
29
|
-
* prod — so a dev key
|
|
34
|
+
* prod — so a dev key routes to `dev-api.aex.dev` and a prd key routes to
|
|
35
|
+
* `api.aex.dev`.
|
|
30
36
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* — but the plane-mismatch guard (dev key + prd baseUrl) still fires.
|
|
37
|
+
* The plane-mismatch guard still fires when a key is pointed at the wrong
|
|
38
|
+
* canonical host (for example, a dev key with `baseUrl=https://api.aex.dev`).
|
|
34
39
|
*/
|
|
35
40
|
export declare const PLANE_BASE_URLS: {
|
|
36
|
-
readonly dev:
|
|
41
|
+
readonly dev: "https://dev-api.aex.dev";
|
|
37
42
|
readonly prd: "https://api.aex.dev";
|
|
38
43
|
};
|
|
39
44
|
export declare function stableStringify(value: unknown): string;
|
|
@@ -23,18 +23,23 @@ import { createHash } from "node:crypto";
|
|
|
23
23
|
* exact default API plane.
|
|
24
24
|
*/
|
|
25
25
|
export const AEX_DEFAULT_BASE_URL = "https://api.aex.dev";
|
|
26
|
+
/**
|
|
27
|
+
* Canonical hosted dev API plane URL. Used when a self-describing dev API key is
|
|
28
|
+
* passed with no explicit `baseUrl`.
|
|
29
|
+
*/
|
|
30
|
+
export const AEX_DEV_BASE_URL = "https://dev-api.aex.dev";
|
|
26
31
|
/**
|
|
27
32
|
* Plane → API base URL. When the SDK constructor is given no explicit `baseUrl`
|
|
28
33
|
* it DERIVES the target from the API key's embedded plane (see
|
|
29
34
|
* {@link import("./api-key.js").parseApiKey}) rather than blindly defaulting to
|
|
30
|
-
* prod — so a dev key
|
|
35
|
+
* prod — so a dev key routes to `dev-api.aex.dev` and a prd key routes to
|
|
36
|
+
* `api.aex.dev`.
|
|
31
37
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* — but the plane-mismatch guard (dev key + prd baseUrl) still fires.
|
|
38
|
+
* The plane-mismatch guard still fires when a key is pointed at the wrong
|
|
39
|
+
* canonical host (for example, a dev key with `baseUrl=https://api.aex.dev`).
|
|
35
40
|
*/
|
|
36
41
|
export const PLANE_BASE_URLS = {
|
|
37
|
-
dev:
|
|
42
|
+
dev: AEX_DEV_BASE_URL,
|
|
38
43
|
prd: AEX_DEFAULT_BASE_URL
|
|
39
44
|
};
|
|
40
45
|
export function stableStringify(value) {
|
package/dist/client.js
CHANGED
|
@@ -1766,11 +1766,9 @@ export class Aex {
|
|
|
1766
1766
|
* Resolve the effective `baseUrl` from a self-describing API key (ZERO-network):
|
|
1767
1767
|
* - key omitted-of-shape (opaque/legacy): return the caller's `baseUrl`
|
|
1768
1768
|
* unchanged (HttpClient falls back to the prd default).
|
|
1769
|
-
* - `baseUrl` omitted: DERIVE it from the key's plane
|
|
1770
|
-
* host (dev) requires an explicit `baseUrl` — throw with that guidance.
|
|
1769
|
+
* - `baseUrl` omitted: DERIVE it from the key's plane.
|
|
1771
1770
|
* - `baseUrl` supplied but its plane DISAGREES with the key's plane: throw
|
|
1772
|
-
* {@link CredentialValidationError} BEFORE any request
|
|
1773
|
-
* against the prd default → bare token_invalid` trap).
|
|
1771
|
+
* {@link CredentialValidationError} BEFORE any request.
|
|
1774
1772
|
*/
|
|
1775
1773
|
function resolveBaseUrlForKey(apiKey, baseUrl) {
|
|
1776
1774
|
const parsed = parseApiKey(apiKey);
|
|
@@ -1778,15 +1776,11 @@ function resolveBaseUrlForKey(apiKey, baseUrl) {
|
|
|
1778
1776
|
return baseUrl;
|
|
1779
1777
|
const planeUrl = PLANE_BASE_URLS[parsed.plane];
|
|
1780
1778
|
if (baseUrl === undefined) {
|
|
1781
|
-
if (planeUrl === null) {
|
|
1782
|
-
throw new CredentialValidationError(`Aex: this API key is for the ${parsed.plane} plane, which has no default host — pass baseUrl explicitly.`, { plane: parsed.plane });
|
|
1783
|
-
}
|
|
1784
1779
|
return planeUrl;
|
|
1785
1780
|
}
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
throw new CredentialValidationError(`Aex: this API key is for the ${parsed.plane} plane but baseUrl targets the prd plane (${PLANE_BASE_URLS.prd}) — ` +
|
|
1781
|
+
const canonicalPlane = baseUrl === PLANE_BASE_URLS.dev ? "dev" : baseUrl === PLANE_BASE_URLS.prd ? "prd" : undefined;
|
|
1782
|
+
if (canonicalPlane !== undefined && canonicalPlane !== parsed.plane) {
|
|
1783
|
+
throw new CredentialValidationError(`Aex: this API key is for the ${parsed.plane} plane but baseUrl targets the ${canonicalPlane} plane (${baseUrl}) — ` +
|
|
1790
1784
|
`pass the ${parsed.plane} plane baseUrl, or omit baseUrl to auto-route.`, { plane: parsed.plane, baseUrl });
|
|
1791
1785
|
}
|
|
1792
1786
|
return baseUrl;
|