@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 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 never silently 401s against `api.aex.dev`.
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
- * `prd` is {@link AEX_DEFAULT_BASE_URL}. `dev` is `null`: the dev plane has no
32
- * stable public hostname yet, so a dev key still requires an explicit `baseUrl`
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: null;
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 never silently 401s against `api.aex.dev`.
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
- * `prd` is {@link AEX_DEFAULT_BASE_URL}. `dev` is `null`: the dev plane has no
33
- * stable public hostname yet, so a dev key still requires an explicit `baseUrl`
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: null,
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; a plane with no default
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 (the exact `dev key
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
- // The only client-detectable mismatch: a non-prd key pointed at the canonical
1787
- // prd host (dev has no canonical host to compare a prd key against).
1788
- if (baseUrl === PLANE_BASE_URLS.prd && parsed.plane !== "prd") {
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;