@aexhq/sdk 0.33.1 → 0.34.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 +19 -27
- package/dist/_contracts/operations.d.ts +2 -54
- package/dist/_contracts/operations.js +2 -87
- package/dist/_contracts/run-config.d.ts +19 -13
- package/dist/_contracts/run-config.js +6 -33
- package/dist/_contracts/run-unit.d.ts +1 -33
- package/dist/_contracts/run-unit.js +2 -21
- package/dist/_contracts/runtime-sizes.d.ts +2 -2
- package/dist/_contracts/runtime-sizes.js +2 -2
- package/dist/_contracts/status.d.ts +2 -2
- package/dist/_contracts/status.js +3 -0
- package/dist/_contracts/submission.d.ts +22 -18
- package/dist/_contracts/submission.js +60 -42
- package/dist/agents-md.d.ts +5 -5
- package/dist/agents-md.js +7 -7
- package/dist/agents-md.js.map +1 -1
- package/dist/asset-upload.d.ts +4 -4
- package/dist/asset-upload.js +4 -4
- package/dist/bundle.d.ts +2 -2
- package/dist/bundle.js +2 -2
- package/dist/cli.mjs +354 -12982
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +218 -386
- package/dist/client.js +347 -645
- package/dist/client.js.map +1 -1
- package/dist/data-tools.d.ts +25 -22
- package/dist/data-tools.js +75 -62
- package/dist/data-tools.js.map +1 -1
- package/dist/fetch-archive.js +16 -16
- package/dist/fetch-archive.js.map +1 -1
- package/dist/file.d.ts +5 -5
- package/dist/file.js +7 -7
- package/dist/file.js.map +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.js +14 -13
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.d.ts +4 -4
- package/dist/mcp-server.js +4 -4
- package/dist/proxy-endpoint.d.ts +4 -4
- package/dist/proxy-endpoint.js +1 -1
- package/dist/secret.d.ts +8 -8
- package/dist/secret.js +8 -8
- package/dist/secret.js.map +1 -1
- package/dist/skill-tool.d.ts +102 -0
- package/dist/skill-tool.js +190 -0
- package/dist/skill-tool.js.map +1 -0
- package/dist/tool.d.ts +1 -1
- package/dist/tool.js +3 -3
- package/dist/tool.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/cleanup.md +3 -3
- package/docs/concepts/agent-tools.md +6 -25
- package/docs/concepts/composition.md +15 -12
- package/docs/concepts/providers-and-runtimes.md +3 -3
- package/docs/concepts/runs.md +27 -22
- package/docs/credentials.md +52 -84
- package/docs/defaults.md +6 -6
- package/docs/events.md +65 -44
- package/docs/limits-and-quotas.md +3 -4
- package/docs/mcp.md +3 -3
- package/docs/networking.md +8 -8
- package/docs/outputs.md +44 -40
- package/docs/provider-runtime-capabilities.md +1 -1
- package/docs/public-surface.json +2 -2
- package/docs/quickstart.md +20 -10
- package/docs/run-config.md +12 -14
- package/docs/run-record.md +8 -8
- package/docs/secrets.md +16 -26
- package/docs/skills.md +55 -110
- package/docs/vision-skills.md +29 -40
- package/examples/chat-corpus.ts +8 -9
- package/package.json +1 -1
- package/dist/skill.d.ts +0 -149
- package/dist/skill.js +0 -198
- package/dist/skill.js.map +0 -1
package/docs/outputs.md
CHANGED
|
@@ -4,42 +4,48 @@ title: Outputs
|
|
|
4
4
|
|
|
5
5
|
# Outputs
|
|
6
6
|
|
|
7
|
-
Every
|
|
7
|
+
Every session produces durable metadata (status, events, snapshots, cleanup state) and an outputs namespace. By default, managed runs capture every regular file the agent creates or modifies in the container: the runner snapshots the filesystem just before the agent starts, rescans it when the agent exits, and uploads the delta. There is no default or official output directory. Use `outputs.allowedDirs` only when you want to narrow capture to specific roots, and `outputs.deniedDirs` to subtract noise. `session.download()` returns the public session record — metadata, typed events, and captured output bytes — as a zip; the per-namespace verbs (`session.outputs().download()` / `session.events().download()` / `session.downloadMetadata()`) return one slice each.
|
|
8
|
+
|
|
9
|
+
The output verbs below hang off the session's `outputs()` accessor
|
|
10
|
+
(`session.outputs().list()`, `.read()`, `.download()`, …). Reach a handle from a
|
|
11
|
+
live session (`openSession` / `run`) or reopen one later with
|
|
12
|
+
`aex.openSession(sessionId)`; the client also exposes cross-session reads under
|
|
13
|
+
`aex.sessions.*`.
|
|
8
14
|
|
|
9
15
|
## Quickstart
|
|
10
16
|
|
|
11
17
|
```ts
|
|
12
18
|
import { Models } from "@aexhq/sdk";
|
|
13
19
|
|
|
14
|
-
const
|
|
20
|
+
const session = await aex.openSession({
|
|
15
21
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
16
|
-
|
|
17
|
-
secrets: { apiKeys: { anthropic: apiKey } }
|
|
22
|
+
apiKeys: { anthropic: apiKey }
|
|
18
23
|
});
|
|
19
24
|
|
|
20
|
-
await
|
|
21
|
-
await
|
|
25
|
+
await session.send("Produce a report and save it as a file.").done();
|
|
26
|
+
await session.wait();
|
|
27
|
+
await session.download({ to: "./session.zip" });
|
|
22
28
|
```
|
|
23
29
|
|
|
24
30
|
```bash
|
|
25
|
-
aex download <
|
|
31
|
+
aex download <session-id> --out ./session.zip --api-token …
|
|
26
32
|
```
|
|
27
33
|
|
|
28
34
|
## The three namespaces
|
|
29
35
|
|
|
30
|
-
A
|
|
36
|
+
A session's downloadable content is organised into three logical namespaces, each with a matching verb. Every zip is assembled **client-side** from the public read endpoints (session record + `session.events().list()` + `session.outputs().list()` + per-output `/download`) — there is no server-side archive route.
|
|
31
37
|
|
|
32
38
|
| Namespace | What it holds | Verb | CLI |
|
|
33
39
|
| --- | --- | --- | --- |
|
|
34
|
-
| `outputs` | The
|
|
35
|
-
| `events` | Typed event-channel records (`events.jsonl`). | `
|
|
36
|
-
| `metadata` | The
|
|
40
|
+
| `outputs` | The session's real deliverables. | `session.outputs().download()` | `download <id> --only outputs` |
|
|
41
|
+
| `events` | Typed event-channel records (`events.jsonl`). | `session.events().download()` | `download <id> --only events` |
|
|
42
|
+
| `metadata` | The session record (`run.json`). | `session.downloadMetadata()` | `download <id> --only metadata` |
|
|
37
43
|
|
|
38
44
|
Platform diagnostics are stored outside the public archive under `runs/<runId>/internal/logs/` for internal/admin access only. They are not exposed by the SDK download helpers or the public CLI.
|
|
39
45
|
|
|
40
|
-
## What `download()` returns
|
|
46
|
+
## What `session.download()` returns
|
|
41
47
|
|
|
42
|
-
`download(
|
|
48
|
+
`session.download()` is the **whole-session** verb — it bundles the public namespaces as top-level folders. It is distinct from `session.outputs().download(selector)`, which fetches a single file. Layout:
|
|
43
49
|
|
|
44
50
|
```
|
|
45
51
|
metadata/run.json # run record (status, runId, timestamps, snapshot)
|
|
@@ -60,30 +66,29 @@ manifest.json # RunRecordManifestV1
|
|
|
60
66
|
| `outputs[]` | `{ id, filename, sizeBytes?, contentType? }` — one row per file successfully written under `outputs/`. |
|
|
61
67
|
| `errors[]` | `{ namespace, id, filename, message }` — per-artifact byte fetches that failed during assembly. Best-effort: a failure records an entry here and is skipped from the tree rather than aborting the whole zip. |
|
|
62
68
|
|
|
63
|
-
The single-namespace verbs return the same per-file bytes at the zip root (e.g. `
|
|
69
|
+
The single-namespace verbs return the same per-file bytes at the zip root (e.g. `session.outputs().download()` -> `report.txt` + a `manifest.json`; `session.events().download()` -> `events.jsonl`).
|
|
64
70
|
|
|
65
71
|
## Downloading one output
|
|
66
72
|
|
|
67
|
-
`
|
|
73
|
+
`session.outputs().download(selector)` returns a `Uint8Array`. Omit the selector to download the whole outputs namespace as a zip; pass an output from `session.outputs().list()`, an `{ id }`, or a path selector against the listed `Output.filename` values to download one file:
|
|
68
74
|
|
|
69
75
|
```ts
|
|
70
|
-
const allOutputs = await
|
|
71
|
-
await
|
|
76
|
+
const allOutputs = await session.outputs().download();
|
|
77
|
+
await session.outputs().download(undefined, { to: "./outputs.zip" });
|
|
72
78
|
|
|
73
|
-
const report = await
|
|
79
|
+
const report = await session.outputs().download({ path: "reports/report.txt" });
|
|
74
80
|
console.log(new TextDecoder().decode(report));
|
|
75
81
|
|
|
76
|
-
const looseReport = await
|
|
82
|
+
const looseReport = await session.outputs().download({ path: "report.txt", match: "suffix" });
|
|
77
83
|
console.log(looseReport.byteLength);
|
|
78
84
|
```
|
|
79
85
|
|
|
80
86
|
## Reading one output as text
|
|
81
87
|
|
|
82
|
-
`
|
|
88
|
+
`session.outputs().read(selector, options?)` reads ONE output file as byte-capped, decoded UTF-8 text. It streams the file and stops at `options.maxBytes` (default 50 KB, ceiling 10 MB), so a large deliverable never fully buffers — this is the read built for handing a session's output to an LLM tool. Select the file by `{ path }` (suffix-matchable) or `{ id }`. To read from a session id without a live handle, use `aex.sessions.outputs(sessionId).read(selector, options?)` — the same accessor, addressed by id.
|
|
83
89
|
|
|
84
90
|
```ts
|
|
85
|
-
const { text, truncated, totalBytes } = await
|
|
86
|
-
runId,
|
|
91
|
+
const { text, truncated, totalBytes } = await session.outputs().read(
|
|
87
92
|
{ path: "report.md", match: "suffix" },
|
|
88
93
|
{ maxBytes: 50_000, grep: "error" }
|
|
89
94
|
);
|
|
@@ -97,25 +102,25 @@ Check `truncated` before treating `text` as complete. Pass `options.grep` (a sub
|
|
|
97
102
|
|
|
98
103
|
### Chatting over a workspace's outputs
|
|
99
104
|
|
|
100
|
-
`createDataTools(client)` packages the read surface (`
|
|
105
|
+
`createDataTools(client)` packages the read surface (`sessions.list` + `sessions.outputs(id).list` + `sessions.outputs(id).read`) as a vendor-neutral LLM tool set (`{ tools, instructions, execute }`) so you can build a search-then-fetch chat over your sessions and their outputs in a few lines on top of the public SDK. The `tools` are plain JSON-Schema definitions (the shape every major LLM tool API accepts); `execute(name, input)` dispatches a tool call against the workspace-scoped client. See the runnable `examples/data-chat/` example.
|
|
101
106
|
|
|
102
107
|
## Finding outputs
|
|
103
108
|
|
|
104
|
-
`
|
|
109
|
+
`session.outputs().list(query?)` can filter the captured output list client-side. Use `session.outputs().find(query)` when you want discovery to be explicit, or `session.outputs().findOne(query)` when exactly one file is expected:
|
|
105
110
|
|
|
106
111
|
```ts
|
|
107
|
-
const images = await
|
|
108
|
-
const jsonReports = await
|
|
112
|
+
const images = await session.outputs().find({ type: "image" });
|
|
113
|
+
const jsonReports = await session.outputs().list({
|
|
109
114
|
dir: "reports",
|
|
110
115
|
extension: ".json"
|
|
111
116
|
});
|
|
112
117
|
|
|
113
|
-
const report = await
|
|
118
|
+
const report = await session.outputs().findOne({
|
|
114
119
|
filename: "summary.json",
|
|
115
120
|
contentType: "application/json"
|
|
116
121
|
});
|
|
117
122
|
if (report) {
|
|
118
|
-
const bytes = await
|
|
123
|
+
const bytes = await session.outputs().download(report);
|
|
119
124
|
}
|
|
120
125
|
```
|
|
121
126
|
|
|
@@ -130,15 +135,14 @@ Query fields compose with AND semantics:
|
|
|
130
135
|
| `contentType` | Exact content type or a prefix wildcard such as `image/*`. |
|
|
131
136
|
| `type` | High-level type: `text`, `json`, `image`, `audio`, `video`, `pdf`, `archive`, `binary`, or `unknown`. |
|
|
132
137
|
|
|
133
|
-
`
|
|
138
|
+
`session.outputs().findOne(query)` returns `null` when nothing matches and throws `RunStateError` when the query matches more than one output.
|
|
134
139
|
|
|
135
140
|
## Temporary output links
|
|
136
141
|
|
|
137
|
-
Use `
|
|
142
|
+
Use `session.outputs().link(selectorOrQuery, options?)` when another process, browser, media tag, or downloader needs a direct artifact URL instead of bytes buffered through the SDK.
|
|
138
143
|
|
|
139
144
|
```ts
|
|
140
|
-
const link = await
|
|
141
|
-
runId,
|
|
145
|
+
const link = await session.outputs().link(
|
|
142
146
|
{ path: "reports/summary.json" },
|
|
143
147
|
{ expiresIn: "15m" }
|
|
144
148
|
);
|
|
@@ -150,16 +154,16 @@ Selectors can be an output id, an `Output` object, a path selector, or an `Outpu
|
|
|
150
154
|
|
|
151
155
|
The returned URL is a reusable bearer URL until it expires. Anyone who has it can read that artifact during the TTL. aex does not promise one-time use or early revocation for these direct artifact URLs.
|
|
152
156
|
|
|
153
|
-
For large files, `
|
|
157
|
+
For large files, `session.outputs().fetch()` mints the same temporary URL and returns the `Response` from fetching it directly, without adding the SDK API token to that second request:
|
|
154
158
|
|
|
155
159
|
```ts
|
|
156
|
-
const response = await
|
|
160
|
+
const response = await session.outputs().fetch({ type: "video", filename: /clip\.mp4$/ });
|
|
157
161
|
const stream = response.body;
|
|
158
162
|
```
|
|
159
163
|
|
|
160
164
|
## Lifecycle behaviour
|
|
161
165
|
|
|
162
|
-
`download()` works at any
|
|
166
|
+
`session.download()` works at any session state — it reads whatever the public endpoints currently expose, so the zip reflects the session as of the call:
|
|
163
167
|
|
|
164
168
|
| Run state | Behaviour |
|
|
165
169
|
| --- | --- |
|
|
@@ -170,8 +174,8 @@ const stream = response.body;
|
|
|
170
174
|
## `outputs.allowedDirs` — override capture roots
|
|
171
175
|
|
|
172
176
|
```ts
|
|
173
|
-
aex.
|
|
174
|
-
/* ...
|
|
177
|
+
aex.openSession({
|
|
178
|
+
/* ... */
|
|
175
179
|
outputs: {
|
|
176
180
|
allowedDirs: ["/workspace/reports", "/workspace/state"]
|
|
177
181
|
}
|
|
@@ -195,8 +199,8 @@ Runtime notes:
|
|
|
195
199
|
## `outputs.deniedDirs` — subtract noise
|
|
196
200
|
|
|
197
201
|
```ts
|
|
198
|
-
aex.
|
|
199
|
-
/* ...
|
|
202
|
+
aex.openSession({
|
|
203
|
+
/* ... */
|
|
200
204
|
outputs: {
|
|
201
205
|
deniedDirs: ["node_modules", "/var/cache", "*.tmp"]
|
|
202
206
|
}
|
|
@@ -227,7 +231,7 @@ Metadata still gets the full treatment. aex captures every regular file the run
|
|
|
227
231
|
|
|
228
232
|
## Mid-session download semantics
|
|
229
233
|
|
|
230
|
-
Mid-session calls are **best-effort and side-effect-free**: they expose whatever artifacts have already been uploaded. Files written by the agent are normally uploaded near terminal, after the filesystem diff. If you need the full output set, wait for the
|
|
234
|
+
Mid-session calls are **best-effort and side-effect-free**: they expose whatever artifacts have already been uploaded. Files written by the agent are normally uploaded near terminal, after the filesystem diff. If you need the full output set, wait for the session to park and call `session.download()` again.
|
|
231
235
|
|
|
232
236
|
## Safety
|
|
233
237
|
|
|
@@ -40,7 +40,7 @@ All new submissions run on the managed runtime. Public support is expressed as s
|
|
|
40
40
|
|
|
41
41
|
## Skills
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
Skills are supplied as load-tools in the `tools` array. Build one with `Tools.fromSkillDir` or `Tools.fromSkillUrl`; each normalizes to an asset that the platform snapshots into durable run asset storage.
|
|
44
44
|
|
|
45
45
|
Notes:
|
|
46
46
|
|
package/docs/public-surface.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"brand": "aex",
|
|
3
3
|
"productName": "Agent Executor",
|
|
4
4
|
"oneLine": "aex is an agent execution platform for launching autonomous agents from a simple TypeScript SDK and CLI.",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Open durable agent sessions, send turns, stream events, capture outputs, and compose agents with skills, files, MCP, proxy endpoints, and subagents across the managed runtime.",
|
|
6
6
|
"alpha": {
|
|
7
7
|
"label": "Alpha testing",
|
|
8
8
|
"description": "Access is limited to invited testers while we harden the hosted runtime, dashboard, and SDK workflows."
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"slug": "agent-runtime",
|
|
50
50
|
"href": "/docs/features/#agent-runtime",
|
|
51
51
|
"title": "Agent runtime",
|
|
52
|
-
"description": "Managed autonomous runs with filesystem read/edit, grep/glob/head/tail, open web fetch/search
|
|
52
|
+
"description": "Managed autonomous runs with filesystem read/edit, grep/glob/head/tail, open web fetch/search, background commands, code execution, git, and subagents."
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"slug": "durable-infrastructure",
|
package/docs/quickstart.md
CHANGED
|
@@ -65,26 +65,36 @@ const result = await aex.run({
|
|
|
65
65
|
console.log(result.runId, result.status, result.text);
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
## 5.
|
|
68
|
+
## 5. Session control: stream, wait, download
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
Sessions are the low-level API. The handle a session gives you can do everything
|
|
71
|
+
to itself — stream its events, wait for it to park, and download its record:
|
|
72
72
|
|
|
73
73
|
```ts
|
|
74
|
-
const
|
|
74
|
+
const session = await aex.openSession({
|
|
75
75
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
76
|
-
|
|
77
|
-
prompt: "Write a short report and save it as a file."
|
|
76
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
78
77
|
});
|
|
79
78
|
|
|
80
|
-
|
|
79
|
+
// A turn streams its own events; iterate them, then collect the result.
|
|
80
|
+
const turn = session.send("Write a short report and save it as a file.");
|
|
81
|
+
for await (const event of turn) {
|
|
81
82
|
console.log(event.type);
|
|
82
83
|
}
|
|
84
|
+
await turn.done();
|
|
85
|
+
|
|
86
|
+
// Reads/streams/downloads are grouped into accessor sub-resources:
|
|
87
|
+
// session.messages() / events() / outputs() / webhooks(). Grab the last
|
|
88
|
+
// assistant message (an AssistantTextEntry; use ?.text for the string).
|
|
89
|
+
const lastText = (await session.messages().last())?.text;
|
|
90
|
+
console.log(lastText);
|
|
83
91
|
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
// Poll the record until the session parks (idle / suspended / error).
|
|
93
|
+
const record = await session.wait();
|
|
94
|
+
console.log(record.status);
|
|
86
95
|
|
|
87
|
-
|
|
96
|
+
// Download the whole session record (metadata, events, outputs) as a zip.
|
|
97
|
+
await session.download({ to: "./session.zip" });
|
|
88
98
|
```
|
|
89
99
|
|
|
90
100
|
The same run from the bundled CLI:
|
package/docs/run-config.md
CHANGED
|
@@ -4,28 +4,26 @@ title: Run configuration
|
|
|
4
4
|
|
|
5
5
|
# Run configuration
|
|
6
6
|
|
|
7
|
-
A run config is the credential-free subset of
|
|
7
|
+
A run config is the credential-free subset of the session options (`openSession` / `run`) that you can keep in code or load from a JSON file. It is not a platform object, saved definition, DSL, trigger, or persistent agent profile. aex only stores the immutable session record created when the session lands.
|
|
8
8
|
|
|
9
9
|
Allowed fields:
|
|
10
10
|
|
|
11
11
|
- `model` - required.
|
|
12
|
-
- `prompt` - required, string or array of strings.
|
|
13
12
|
- `system` - optional system message.
|
|
14
|
-
- `
|
|
15
|
-
- `
|
|
16
|
-
- `
|
|
17
|
-
- `
|
|
18
|
-
- `timeout` - optional run deadline duration string such as `"30m"` or `"2h"`.
|
|
19
|
-
- `proxyEndpoints` - array of `PlatformProxyEndpoint`; endpoint-level `retry` is allowed here and remains declaration-based.
|
|
13
|
+
- `mcpServers` - array of `McpServerRef`; headers are split into the vaulted secrets channel server-side.
|
|
14
|
+
- `environment` - `{ networking?, packages?, variables? }`. Networking is open by default; set `networking.mode` to `limited` only when you want an allowlist. `variables` are merged into the in-container `RUNTIME.env` / `RUNTIME.json` mounts. (Run secrets go in `environment.secrets`, which carries live `Secret` instances and is not part of a shareable config.)
|
|
15
|
+
- `runtime` - optional managed-runtime preset. Prefer `Sizes` in TypeScript.
|
|
16
|
+
- `proxyEndpoints` - array of `ProxyEndpoint` instances; endpoint-level `retry` is allowed here and remains declaration-based.
|
|
20
17
|
- `metadata` - non-secret structured metadata.
|
|
18
|
+
- `overrides` - `{ idleTtl?, timeout?, maxSpendUsd? }`. `timeout` is an optional session deadline (e.g. `"30m"`, `"2h"`); `maxSpendUsd` stops the session once its spend would exceed the cap (see [Limits & quotas](limits-and-quotas.md)).
|
|
21
19
|
|
|
22
|
-
`agentsMd`, `files`, `outputs`, `tools`, `includeBuiltinTools`,
|
|
20
|
+
`message` (the one-shot `run` input), `agentsMd`, `files`, `outputs`, `tools`, `includeBuiltinTools`, and `outputMode` are `openSession` / `run` options, not reusable run-config fields. They carry the turn input, bytes, capture behavior, or agent tool/output controls that belong on a concrete call. Skill bundles are `tools` entries built with `Tools.fromSkillDir(...)` / `Tools.fromSkillUrl(...)`, so they too are SDK-code options rather than config fields. Subagents run in-process; there is no `limits` / `parentRunId` option.
|
|
23
21
|
|
|
24
|
-
Secrets never live in run config. Pass
|
|
22
|
+
Secrets never live in run config. Pass provider keys through the top-level `apiKeys` map (and run secrets through `environment.secrets`) in the SDK, or the equivalent host-mode flags (`--anthropic-api-key`, `--mcp-auth`, `--proxy-auth`) in the CLI. See [Secrets](secrets.md) for secret lifecycles and [Credentials](credentials.md) for the proxy endpoint policy/auth split and retry fields.
|
|
25
23
|
|
|
26
24
|
## Reuse in code
|
|
27
25
|
|
|
28
|
-
Use an ordinary function when you want reusable typed parameters. aex does not store or execute this function; it only receives the
|
|
26
|
+
Use an ordinary function when you want reusable typed parameters. aex does not store or execute this function; it only receives the parameters you pass.
|
|
29
27
|
|
|
30
28
|
```ts
|
|
31
29
|
import { Models } from "@aexhq/sdk";
|
|
@@ -34,13 +32,13 @@ function summarise(topic: string) {
|
|
|
34
32
|
return {
|
|
35
33
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
36
34
|
system: "You are a concise automation agent.",
|
|
37
|
-
|
|
35
|
+
message: `Write a short answer about ${topic}.`
|
|
38
36
|
};
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
await aex.
|
|
39
|
+
await aex.run({
|
|
42
40
|
...summarise("agent-first SDK design"),
|
|
43
|
-
|
|
41
|
+
apiKeys: { anthropic: apiKey }
|
|
44
42
|
});
|
|
45
43
|
```
|
|
46
44
|
|
package/docs/run-record.md
CHANGED
|
@@ -4,28 +4,28 @@ title: Run record
|
|
|
4
4
|
|
|
5
5
|
# Run record
|
|
6
6
|
|
|
7
|
-
The run record is the durable product primitive for one
|
|
7
|
+
The run record is the durable product primitive for one session. It is the public-safe bundle of status metadata, the non-secret submission snapshot when available, typed events, captured outputs, and manifest entries for custody and cost telemetry.
|
|
8
8
|
|
|
9
|
-
## Listing
|
|
9
|
+
## Listing sessions
|
|
10
10
|
|
|
11
|
-
`aex.
|
|
11
|
+
`aex.sessions.list(query?)` enumerates the sessions in this workspace, most-recent first, one page at a time. The workspace is derived server-side from the API token, so this only ever returns your own sessions. It is the workspace-wide discovery entry point: combine it with `aex.sessions.outputs(id).list()` / `.read(...)` (see [Outputs](outputs.md)) to reach any session's deliverables.
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
14
|
let cursor: string | undefined;
|
|
15
15
|
do {
|
|
16
|
-
const page = await aex.
|
|
17
|
-
for (const
|
|
18
|
-
console.log(
|
|
16
|
+
const page = await aex.sessions.list({ status: "idle", limit: 25, cursor });
|
|
17
|
+
for (const session of page.sessions) {
|
|
18
|
+
console.log(session.id, session.status, session.createdAt, session.costUsd);
|
|
19
19
|
}
|
|
20
20
|
cursor = page.nextCursor;
|
|
21
21
|
} while (cursor);
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
`query` fields are all optional: `status` (single
|
|
24
|
+
`query` fields are all optional: `status` (single session status, e.g. `"idle"`), `since` (ISO-8601 lower bound on `createdAt`), `limit` (defaults to 25, clamped to `[1, 100]`), and `cursor` (the opaque keyset cursor from a prior page's `nextCursor` — absent on the last page). Each page row is a public-safe `SessionSummary` (`id`, `status`, `createdAt`, `updatedAt`, and `costUsd` once settled); it deliberately omits the submission snapshot (model / system / env). Use `aex.sessions.get(id)` for status / timing / cost on one session, or `session.unit()` on a handle for the full self-contained record including the parsed submission.
|
|
25
25
|
|
|
26
26
|
## Downloading a run record
|
|
27
27
|
|
|
28
|
-
`
|
|
28
|
+
`session.download()` and `aex download <session-id>` return a zip with this layout:
|
|
29
29
|
|
|
30
30
|
```text
|
|
31
31
|
manifest.json
|
package/docs/secrets.md
CHANGED
|
@@ -16,14 +16,14 @@ provider key, such as `ANTHROPIC_API_KEY` for Claude.
|
|
|
16
16
|
### TypeScript
|
|
17
17
|
|
|
18
18
|
```ts
|
|
19
|
-
import {
|
|
19
|
+
import { Aex, Models } from "@aexhq/sdk";
|
|
20
20
|
|
|
21
|
-
const aex = new
|
|
21
|
+
const aex = new Aex({ apiToken: process.env.AEX_API_TOKEN! });
|
|
22
22
|
|
|
23
|
-
await aex.
|
|
23
|
+
await aex.run({
|
|
24
24
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
message: "Write a short report and save it as a file.",
|
|
26
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
27
27
|
});
|
|
28
28
|
```
|
|
29
29
|
|
|
@@ -43,20 +43,20 @@ Use `Secret.value(...).upload(...)` when you start with an ephemeral value and
|
|
|
43
43
|
want to persist it as a named workspace secret for later runs.
|
|
44
44
|
|
|
45
45
|
```ts
|
|
46
|
-
import {
|
|
46
|
+
import { Aex, Models, Providers, Secret } from "@aexhq/sdk";
|
|
47
47
|
|
|
48
|
-
const aex = new
|
|
48
|
+
const aex = new Aex({ apiToken: process.env.AEX_API_TOKEN! });
|
|
49
49
|
|
|
50
50
|
const githubToken = await Secret.value(process.env.GITHUB_TOKEN!).upload(aex, {
|
|
51
51
|
name: "github-token"
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
await aex.
|
|
54
|
+
await aex.run({
|
|
55
55
|
provider: Providers.ANTHROPIC,
|
|
56
56
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
message: "Inspect the repository issues.",
|
|
58
|
+
environment: { secrets: { GITHUB_TOKEN: githubToken } },
|
|
59
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
60
60
|
});
|
|
61
61
|
```
|
|
62
62
|
|
|
@@ -86,16 +86,6 @@ const secrets = await aex.secrets.list();
|
|
|
86
86
|
const metadata = await aex.secrets.get("serper-api-key");
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
## Get A Secret Value
|
|
90
|
-
|
|
91
|
-
Use `get_value` only when the value is intentionally needed outside a run. It is
|
|
92
|
-
the explicit audited value-read path.
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
const secretValue = await aex.secrets.get_value("serper-api-key");
|
|
96
|
-
console.log(secretValue.value);
|
|
97
|
-
```
|
|
98
|
-
|
|
99
89
|
## Inject A Workspace Secret Into A Run
|
|
100
90
|
|
|
101
91
|
Reference workspace secrets with `Secret.ref(name)`. The value resolves
|
|
@@ -104,14 +94,14 @@ server-side and is injected as the named environment variable.
|
|
|
104
94
|
```ts
|
|
105
95
|
import { Models, Providers, Secret } from "@aexhq/sdk";
|
|
106
96
|
|
|
107
|
-
await aex.
|
|
97
|
+
await aex.run({
|
|
108
98
|
provider: Providers.ANTHROPIC,
|
|
109
99
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
SERPER_API_KEY: Secret.ref("serper-api-key")
|
|
100
|
+
message: "Use SERPER_API_KEY for web search.",
|
|
101
|
+
environment: {
|
|
102
|
+
secrets: { SERPER_API_KEY: Secret.ref("serper-api-key") }
|
|
113
103
|
},
|
|
114
|
-
|
|
104
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
115
105
|
});
|
|
116
106
|
```
|
|
117
107
|
|