@aexhq/sdk 0.35.0 → 0.37.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 +17 -16
- package/dist/_contracts/event-envelope.d.ts +22 -1
- package/dist/_contracts/event-envelope.js +26 -2
- package/dist/_contracts/event-stream-client.js +7 -1
- package/dist/_contracts/index.d.ts +3 -4
- package/dist/_contracts/index.js +1 -4
- package/dist/_contracts/operations.d.ts +31 -1
- package/dist/_contracts/operations.js +64 -1
- package/dist/_contracts/run-config.d.ts +2 -4
- package/dist/_contracts/run-config.js +2 -7
- package/dist/_contracts/run-trace.d.ts +0 -86
- package/dist/_contracts/run-trace.js +1 -184
- package/dist/_contracts/run-unit.d.ts +14 -25
- package/dist/_contracts/run-unit.js +56 -2
- package/dist/_contracts/runtime-manifest.d.ts +1 -1
- package/dist/_contracts/runtime-security-profile.d.ts +0 -2
- package/dist/_contracts/runtime-security-profile.js +0 -9
- package/dist/_contracts/runtime-sizes.d.ts +2 -2
- package/dist/_contracts/runtime-sizes.js +5 -5
- package/dist/_contracts/runtime-types.d.ts +123 -4
- package/dist/_contracts/stable.d.ts +1 -1
- package/dist/_contracts/stable.js +1 -1
- package/dist/_contracts/submission.d.ts +8 -76
- package/dist/_contracts/submission.js +5 -472
- package/dist/cli.mjs +574 -511
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +69 -25
- package/dist/client.js +338 -68
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +8 -16
- package/dist/index.js +5 -17
- package/dist/index.js.map +1 -1
- package/dist/secret.d.ts +2 -2
- package/dist/secret.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/authentication.md +92 -0
- package/docs/billing.md +112 -0
- package/docs/concepts/agent-tools.md +4 -4
- package/docs/concepts/composition.md +8 -14
- package/docs/concepts/providers-and-runtimes.md +4 -1
- package/docs/concepts/runs.md +2 -1
- package/docs/concepts/subagents.md +85 -0
- package/docs/credentials.md +78 -96
- package/docs/defaults.md +9 -15
- package/docs/errors.md +132 -0
- package/docs/events.md +44 -32
- package/docs/limits-and-quotas.md +30 -17
- package/docs/limits.md +4 -8
- package/docs/mcp.md +5 -6
- package/docs/networking.md +75 -59
- package/docs/outputs.md +4 -7
- package/docs/public-surface.json +4 -4
- package/docs/quickstart.md +12 -13
- package/docs/run-config.md +7 -4
- package/docs/secrets.md +6 -1
- package/docs/skills.md +3 -3
- package/docs/vision-skills.md +52 -101
- package/docs/webhooks.md +132 -0
- package/examples/feature-tour.ts +4 -21
- package/package.json +1 -1
- package/dist/_contracts/proxy-protocol.d.ts +0 -305
- package/dist/_contracts/proxy-protocol.js +0 -297
- package/dist/_contracts/proxy-validation.d.ts +0 -19
- package/dist/_contracts/proxy-validation.js +0 -51
- package/dist/data-tools.d.ts +0 -82
- package/dist/data-tools.js +0 -251
- package/dist/data-tools.js.map +0 -1
- package/dist/proxy-endpoint.d.ts +0 -131
- package/dist/proxy-endpoint.js +0 -144
- package/dist/proxy-endpoint.js.map +0 -1
- package/examples/chat-corpus.ts +0 -84
package/docs/secrets.md
CHANGED
|
@@ -88,6 +88,11 @@ const metadata = await aex.secrets.get("serper-api-key");
|
|
|
88
88
|
|
|
89
89
|
## Inject A Workspace Secret Into A Run
|
|
90
90
|
|
|
91
|
+
> **Availability note:** workspace-secret `Secret.ref(...)` injection requires
|
|
92
|
+
> the next platform deploy — on the current hosted plane the referenced
|
|
93
|
+
> variable can resolve empty inside the run. Per-run `Secret.value(...)`
|
|
94
|
+
> secrets are unaffected. This note will be removed once the deploy lands.
|
|
95
|
+
|
|
91
96
|
Reference workspace secrets with `Secret.ref(name)`. The value resolves
|
|
92
97
|
server-side and is injected as the named environment variable.
|
|
93
98
|
|
|
@@ -111,5 +116,5 @@ await aex.run({
|
|
|
111
116
|
await aex.secrets.delete("serper-api-key");
|
|
112
117
|
```
|
|
113
118
|
|
|
114
|
-
The CLI supports per-run provider
|
|
119
|
+
The CLI supports per-run provider and MCP credentials. Workspace secret
|
|
115
120
|
administration is exposed through the SDK.
|
package/docs/skills.md
CHANGED
|
@@ -72,9 +72,9 @@ files into the workspace under `/workspace/skills/<name>/`. So the `SKILL.md` bo
|
|
|
72
72
|
and every supporting file are on disk from the first turn; the load-tool call is
|
|
73
73
|
how that body enters the model's context, not how the files get written.
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
Skills that call external HTTP APIs should read credentials from
|
|
76
|
+
`environment.secrets` and use the normal client for that service. See
|
|
77
|
+
[Credentials](credentials.md) for the secret model.
|
|
78
78
|
|
|
79
79
|
Run-scoped asset copies are part of the run record and are removed by run deletion
|
|
80
80
|
or retention cleanup.
|
package/docs/vision-skills.md
CHANGED
|
@@ -1,73 +1,57 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Call a vision
|
|
2
|
+
title: Call a vision API from a skill
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# Call a vision
|
|
5
|
+
# Call a vision API from a skill
|
|
6
6
|
|
|
7
|
-
aex has no built-in vision tool. The agent's `provider
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
managed proxy**, with the key supplied on a `ProxyEndpoint.bearer(...)` instance.
|
|
12
|
-
The raw key never enters the container.
|
|
7
|
+
aex has no built-in vision tool. The agent's `provider` / `model` selects the
|
|
8
|
+
reasoning model for the run; if a skill needs image understanding mid-run, ship a
|
|
9
|
+
skill that calls the vision provider with normal HTTP and pass that provider key
|
|
10
|
+
as a runtime secret.
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
large enough to need a raised `maxRequestBytes`.
|
|
12
|
+
The runnable example lives at [`examples/vision-skill/`](../../../examples/vision-skill).
|
|
13
|
+
It captions a frame with ByteDance Doubao Seed Vision (Ark) and returns a
|
|
14
|
+
per-noun "does the frame depict X?" verdict.
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
[`examples/vision-skill/`](../../../examples/vision-skill) (`SKILL.md`,
|
|
21
|
-
`caption_frame.py`, `verify_frame.py`, `run_with_vision_skill.mjs`). It
|
|
22
|
-
captions a frame with ByteDance Doubao Seed Vision (Ark) and returns a per-noun
|
|
23
|
-
"does the frame depict X?" verdict. Everything below is taken from it.
|
|
24
|
-
|
|
25
|
-
## 1. Declare the model endpoint as a proxy endpoint
|
|
26
|
-
|
|
27
|
-
The vision provider's API is just an HTTPS host. Declare it with
|
|
28
|
-
`ProxyEndpoint.bearer(...)`, which carries the key on the instance. The two
|
|
29
|
-
model-specific settings are `responseMode: "full"` (so the skill gets the upstream
|
|
30
|
-
JSON back) and a raised `maxRequestBytes` (so the base64 image fits):
|
|
16
|
+
## Submit the run
|
|
31
17
|
|
|
32
18
|
```ts
|
|
33
|
-
import { Aex, Models,
|
|
19
|
+
import { Aex, Models, Secret, Tools } from "@aexhq/sdk";
|
|
34
20
|
|
|
35
21
|
const aex = new Aex({ apiToken: process.env.AEX_API_TOKEN! });
|
|
36
22
|
|
|
37
|
-
const
|
|
38
|
-
name: "doubao-ark",
|
|
39
|
-
baseUrl: "https://ark.ap-southeast.bytepluses.com", // intl BytePlus gateway
|
|
40
|
-
token: process.env.DOUBAO_API_KEY!,
|
|
41
|
-
allowMethods: ["POST"],
|
|
42
|
-
allowPathPrefixes: ["/api/v3/chat/completions"],
|
|
43
|
-
maxRequestBytes: 2_000_000, // base64 image POSTs — see note below
|
|
44
|
-
responseMode: "full",
|
|
45
|
-
timeoutMs: 60_000
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
await aex.run({
|
|
23
|
+
const result = await aex.run({
|
|
49
24
|
model: Models.CLAUDE_HAIKU_4_5,
|
|
50
|
-
message: "
|
|
25
|
+
message: "Read skills/frame-vision-gate/SKILL.md, then caption and verify the frame.",
|
|
51
26
|
tools: [await Tools.fromSkillDir("./vision-skill", { name: "frame-vision-gate" })],
|
|
52
|
-
|
|
27
|
+
environment: {
|
|
28
|
+
secrets: {
|
|
29
|
+
DOUBAO_API_KEY: Secret.value(process.env.DOUBAO_API_KEY!)
|
|
30
|
+
},
|
|
31
|
+
networking: {
|
|
32
|
+
mode: "limited",
|
|
33
|
+
allowedHosts: ["ark.ap-southeast.bytepluses.com"]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
53
36
|
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
54
37
|
});
|
|
38
|
+
|
|
39
|
+
console.log(result.runId, result.text);
|
|
55
40
|
```
|
|
56
41
|
|
|
57
|
-
`Tools.fromSkillDir("./vision-skill",
|
|
58
|
-
|
|
59
|
-
repo,
|
|
60
|
-
OpenAI-compatible endpoint, or any other OpenAI-chat-shaped vision API — only
|
|
61
|
-
`baseUrl` and the path prefix change.
|
|
42
|
+
`Tools.fromSkillDir("./vision-skill", ...)` is resolved relative to the process
|
|
43
|
+
CWD. Run the script from the directory that contains `vision-skill/` (in this
|
|
44
|
+
repo, `examples/`).
|
|
62
45
|
|
|
63
|
-
##
|
|
46
|
+
## Call the provider from the skill
|
|
64
47
|
|
|
65
|
-
Inside the run, the skill
|
|
66
|
-
|
|
67
|
-
|
|
48
|
+
Inside the run, the skill reads `DOUBAO_API_KEY` and makes an
|
|
49
|
+
OpenAI-compatible chat-completions request with Python's standard HTTP client.
|
|
50
|
+
The image is base64-inlined as a data URL in the request body:
|
|
68
51
|
|
|
69
52
|
```python
|
|
70
|
-
import base64, json
|
|
53
|
+
import base64, json, os, urllib.request
|
|
54
|
+
|
|
71
55
|
b64 = base64.b64encode(open("/workspace/files/frame.jpg", "rb").read()).decode()
|
|
72
56
|
request_body = {
|
|
73
57
|
"model": "doubao-seed-1-6-vision-250815",
|
|
@@ -81,63 +65,30 @@ request_body = {
|
|
|
81
65
|
]}
|
|
82
66
|
]
|
|
83
67
|
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Write the body to a file and hand it to the mounted CLI with `--data @<file>`
|
|
87
|
-
(the mount has no execute bit, so invoke through `bun`; see `credentials.md`):
|
|
88
68
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"--path", "/api/v3/chat/completions",
|
|
98
|
-
"--header", "content-type=application/json",
|
|
99
|
-
"--data", f"@{body_path}",
|
|
100
|
-
"--response-mode", "full"],
|
|
101
|
-
capture_output=True, text=True, timeout=90,
|
|
69
|
+
req = urllib.request.Request(
|
|
70
|
+
"https://ark.ap-southeast.bytepluses.com/api/v3/chat/completions",
|
|
71
|
+
data=json.dumps(request_body).encode("utf-8"),
|
|
72
|
+
headers={
|
|
73
|
+
"Authorization": f"Bearer {os.environ['DOUBAO_API_KEY']}",
|
|
74
|
+
"Content-Type": "application/json"
|
|
75
|
+
},
|
|
76
|
+
method="POST",
|
|
102
77
|
)
|
|
103
78
|
```
|
|
104
79
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
```python
|
|
110
|
-
envelope = json.loads(result.stdout)
|
|
111
|
-
if "error" in envelope:
|
|
112
|
-
raise RuntimeError(f"proxy error: {envelope['error']}: {envelope['message']}")
|
|
113
|
-
upstream = json.loads(base64.b64decode(envelope["upstreamBodyBase64"]).decode())
|
|
114
|
-
content = upstream["choices"][0]["message"]["content"] # the model's JSON answer
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
The key is injected by the hosted proxy on the outbound call; it never appears on disk in
|
|
118
|
-
the container or in the model's context.
|
|
119
|
-
|
|
120
|
-
## `maxRequestBytes` and timeout defaults
|
|
80
|
+
The same pattern works for OpenAI, Gemini's OpenAI-compatible endpoint, or any
|
|
81
|
+
other HTTPS model API. Put the key in `environment.secrets`, allow-list the host
|
|
82
|
+
when using limited networking, and use the provider's normal SDK or HTTP API.
|
|
121
83
|
|
|
122
|
-
|
|
123
|
-
is **5 minutes**. That fits typical base64 image/model POSTs without extra
|
|
124
|
-
configuration. If a body does exceed the cap, the proxy rejects it before any
|
|
125
|
-
upstream call with an explicit error naming the observed size, the configured
|
|
126
|
-
cap, and how to raise it:
|
|
84
|
+
## Payload size
|
|
127
85
|
|
|
128
|
-
|
|
129
|
-
|
|
86
|
+
Base64 images are larger than their source files. Scale frames before captioning
|
|
87
|
+
when possible, for example:
|
|
130
88
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
## Notes
|
|
89
|
+
```bash
|
|
90
|
+
ffmpeg -i source.mp4 -vf fps=1,scale=960:-1 frame_%03d.jpg
|
|
91
|
+
```
|
|
136
92
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- **Keyless model hosts.** If the upstream takes no credential, declare the
|
|
140
|
-
endpoint with `ProxyEndpoint.none(...)` (see `credentials.md`).
|
|
141
|
-
- **Response size.** `responseMode: "full"` is required to read the model's reply
|
|
142
|
-
back. Leave `maxResponseBytes` at its default (`0` = unlimited, streamed) unless
|
|
143
|
-
you want a truncation cap.
|
|
93
|
+
This keeps upload size and model cost bounded without losing the signal most
|
|
94
|
+
vision models need.
|
package/docs/webhooks.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Webhooks
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Webhooks
|
|
6
|
+
|
|
7
|
+
aex can notify your endpoint when a run finishes. Webhooks are **per-run**: you
|
|
8
|
+
pass a callback URL with the submission, and the platform delivers exactly one
|
|
9
|
+
`run.finished` event to it when the run reaches its terminal state.
|
|
10
|
+
|
|
11
|
+
> **Availability note:** terminal webhook delivery for session-based runs
|
|
12
|
+
> requires the next platform deploy — on the current hosted plane a session
|
|
13
|
+
> run's webhook may not fire. This note will be removed once the deploy lands.
|
|
14
|
+
|
|
15
|
+
## Register a callback
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { Aex, Models } from "@aexhq/sdk";
|
|
19
|
+
|
|
20
|
+
const aex = new Aex(process.env.AEX_API_TOKEN!);
|
|
21
|
+
|
|
22
|
+
const session = await aex.openSession({
|
|
23
|
+
model: Models.CLAUDE_HAIKU_4_5,
|
|
24
|
+
webhook: { url: "https://hooks.example.com/aex" },
|
|
25
|
+
apiKeys: { anthropic: process.env.ANTHROPIC_API_KEY! }
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
aex run \
|
|
31
|
+
--api-token "$AEX_API_TOKEN" \
|
|
32
|
+
--anthropic-api-key "$ANTHROPIC_API_KEY" \
|
|
33
|
+
--model claude-haiku-4-5 \
|
|
34
|
+
--prompt "Write the report." \
|
|
35
|
+
--webhook https://hooks.example.com/aex
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The URL must be `https`. The callback URL is an operational concern, not part
|
|
39
|
+
of the submission fingerprint: retrying the same submission with the same
|
|
40
|
+
idempotency key but a different callback URL never conflicts.
|
|
41
|
+
|
|
42
|
+
## What gets delivered
|
|
43
|
+
|
|
44
|
+
One POST carrying the terminal `run.finished` event, sent at the
|
|
45
|
+
settle-consistent barrier — when you receive it, the run record is already
|
|
46
|
+
terminal and its outputs are complete and readable. The body is built once at
|
|
47
|
+
settle, frozen, and re-sent byte-identical on every retry or manual redelivery:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"specversion": "1.0",
|
|
52
|
+
"id": "<delivery id — matches the webhook-id header>",
|
|
53
|
+
"source": "aex",
|
|
54
|
+
"type": "run.finished",
|
|
55
|
+
"subject": "<the run id>",
|
|
56
|
+
"time": "2026-07-02T12:34:56.000Z",
|
|
57
|
+
"data": {
|
|
58
|
+
"runId": "<the run id>",
|
|
59
|
+
"status": "succeeded",
|
|
60
|
+
"terminalAt": "2026-07-02T12:34:56.000Z",
|
|
61
|
+
"reason": null,
|
|
62
|
+
"failureClass": null,
|
|
63
|
+
"costTelemetry": { "billedCostUsd": 0.42 }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`reason` / `failureClass` carry the failure detail on non-success terminals;
|
|
69
|
+
`costTelemetry` is present when the billed cost is known.
|
|
70
|
+
|
|
71
|
+
## Verify deliveries
|
|
72
|
+
|
|
73
|
+
Deliveries are signed [Standard Webhooks](https://www.standardwebhooks.com/)
|
|
74
|
+
style: HMAC-SHA256 over `` `${webhook-id}.${webhook-timestamp}.${rawBody}` ``,
|
|
75
|
+
sent in three headers — `webhook-id` (stable across retries; your dedupe key),
|
|
76
|
+
`webhook-timestamp` (unix seconds), and `webhook-signature` (a space-delimited
|
|
77
|
+
list of `v1,<base64>` entries).
|
|
78
|
+
|
|
79
|
+
The signing key is a per-workspace secret. Reveal it (it is created on first
|
|
80
|
+
use) with either surface:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
aex webhooks secret --api-token "$AEX_API_TOKEN" # prints whsec_...
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const { whsec } = await aex.webhookSigningSecret();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Verify inbound requests with the exported `verifyAexWebhook` — pure Web Crypto,
|
|
91
|
+
identical under Bun and Node, and interoperable with the `standardwebhooks`
|
|
92
|
+
reference library:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { verifyAexWebhook } from "@aexhq/sdk";
|
|
96
|
+
|
|
97
|
+
// In your HTTP handler — use the EXACT raw body bytes, never re-serialize.
|
|
98
|
+
const ok = await verifyAexWebhook({
|
|
99
|
+
rawBody,
|
|
100
|
+
headers: request.headers,
|
|
101
|
+
secret: process.env.AEX_WEBHOOK_SECRET! // the whsec_... value
|
|
102
|
+
});
|
|
103
|
+
if (!ok) return new Response("bad signature", { status: 401 });
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`verifyAexWebhook` rejects stale timestamps (default tolerance 300 seconds) and
|
|
107
|
+
compares signatures constant-time. It accepts every `v1` entry in the signature
|
|
108
|
+
list, so it is already rotation-ready — but **server-side rotation of the
|
|
109
|
+
signing secret is not available yet**: `aex webhooks secret` reveals or creates
|
|
110
|
+
the one workspace secret and there is no rotate endpoint today. If your secret
|
|
111
|
+
is compromised, contact <support@aex.dev>.
|
|
112
|
+
|
|
113
|
+
## Delivery ledger and redelivery
|
|
114
|
+
|
|
115
|
+
Each run keeps a delivery ledger — attempts, last status code, and last error:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const deliveries = await session.webhooks().list();
|
|
119
|
+
await session.webhooks().redeliver(deliveries[0]!.id);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
aex deliveries <session-id> --api-token "$AEX_API_TOKEN"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Redelivery re-sends the frozen payload with the **same** `webhook-id`, so a
|
|
127
|
+
consumer that dedupes on `webhook-id` handles retries, redeliveries, and
|
|
128
|
+
at-least-once delivery uniformly. An empty ledger means the run carried no
|
|
129
|
+
`webhook` or has not reached a terminal state yet.
|
|
130
|
+
|
|
131
|
+
For the terminal-event mechanics behind delivery timing, see
|
|
132
|
+
[Events](events.md).
|
package/examples/feature-tour.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* SDK feature tour: one managed session that uses typed model/runtime constants,
|
|
3
3
|
* inline AGENTS.md guidance, uploaded files, a custom tool bundle, selected
|
|
4
4
|
* built-in tools, runtime env vars/secrets, streamed events, output reads, and
|
|
5
|
-
*
|
|
5
|
+
* a follow-up session turn.
|
|
6
6
|
*
|
|
7
7
|
* Run from the repository root after building the workspace package:
|
|
8
8
|
*
|
|
@@ -20,13 +20,11 @@ import {
|
|
|
20
20
|
AgentsMd,
|
|
21
21
|
Aex,
|
|
22
22
|
BuiltinTools,
|
|
23
|
-
createCorpusTools,
|
|
24
23
|
File,
|
|
25
24
|
isRateLimited,
|
|
26
25
|
isTextMessage,
|
|
27
26
|
McpServer,
|
|
28
27
|
Models,
|
|
29
|
-
ProxyEndpoint,
|
|
30
28
|
Providers,
|
|
31
29
|
Secret,
|
|
32
30
|
Sizes,
|
|
@@ -132,17 +130,6 @@ const environmentSecrets = demoRuntimeSecret
|
|
|
132
130
|
? { DEMO_RUNTIME_SECRET: Secret.value(demoRuntimeSecret) }
|
|
133
131
|
: undefined;
|
|
134
132
|
|
|
135
|
-
const proxyEndpoints = [
|
|
136
|
-
ProxyEndpoint.none({
|
|
137
|
-
name: "httpbin",
|
|
138
|
-
baseUrl: "https://httpbin.org",
|
|
139
|
-
allowMethods: ["GET"],
|
|
140
|
-
allowPathPrefixes: ["/json"],
|
|
141
|
-
responseMode: "full",
|
|
142
|
-
timeoutMs: 10_000
|
|
143
|
-
})
|
|
144
|
-
];
|
|
145
|
-
|
|
146
133
|
console.log("creating feature-tour session...");
|
|
147
134
|
console.log(`optional mcp: ${mcpServers.length > 0 ? "enabled" : "disabled"}`);
|
|
148
135
|
console.log(`optional runtime secret: ${environmentSecrets ? "enabled" : "disabled"}`);
|
|
@@ -165,7 +152,6 @@ const session = await aex.openSession({
|
|
|
165
152
|
BuiltinTools.code_execution,
|
|
166
153
|
metricLookup
|
|
167
154
|
],
|
|
168
|
-
proxyEndpoints,
|
|
169
155
|
mcpServers,
|
|
170
156
|
environment: {
|
|
171
157
|
networking: { mode: "open" },
|
|
@@ -201,8 +187,7 @@ const prompt = [
|
|
|
201
187
|
"Analyze the attached quarterly metrics.",
|
|
202
188
|
"Call metric_lookup for atlas, beacon, and cinder.",
|
|
203
189
|
"Create /workspace/outputs/feature-tour-report.md with a short table, a ranking by q2_revenue_usd, and two risks.",
|
|
204
|
-
"Create /workspace/outputs/summary.json with keys topProduct, totalQ2RevenueUsd, highestActivationProduct, and riskCount."
|
|
205
|
-
"Mention whether the httpbin proxy endpoint is declared, but do not call it unless you need to."
|
|
190
|
+
"Create /workspace/outputs/summary.json with keys topProduct, totalQ2RevenueUsd, highestActivationProduct, and riskCount."
|
|
206
191
|
].join(" ");
|
|
207
192
|
|
|
208
193
|
const firstTurn = session.send(prompt);
|
|
@@ -272,10 +257,8 @@ if (report) {
|
|
|
272
257
|
console.log(reportPreview.text || "(no risk lines found)");
|
|
273
258
|
}
|
|
274
259
|
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
console.log("corpus-scoped list_outputs result:");
|
|
278
|
-
console.log(JSON.stringify(corpusOutputs, null, 2));
|
|
260
|
+
const reopenedOutputs = await aex.sessions.outputs(session.id).list();
|
|
261
|
+
console.log(`outputs via aex.sessions.outputs(...): ${reopenedOutputs.length}`);
|
|
279
262
|
|
|
280
263
|
if (downloadPath) {
|
|
281
264
|
const bytes = await session.download({ to: downloadPath });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aexhq/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"description": "TypeScript SDK for running autonomous agent sessions across providers (Anthropic, OpenAI, DeepSeek, Gemini, Mistral) behind one interface.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|