@aexhq/sdk 0.34.0 → 0.36.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.
Files changed (63) hide show
  1. package/README.md +16 -15
  2. package/dist/_contracts/index.d.ts +3 -4
  3. package/dist/_contracts/index.js +1 -4
  4. package/dist/_contracts/operations.d.ts +2 -1
  5. package/dist/_contracts/operations.js +10 -0
  6. package/dist/_contracts/run-config.d.ts +1 -3
  7. package/dist/_contracts/run-config.js +2 -7
  8. package/dist/_contracts/run-trace.d.ts +0 -86
  9. package/dist/_contracts/run-trace.js +1 -184
  10. package/dist/_contracts/run-unit.d.ts +2 -25
  11. package/dist/_contracts/run-unit.js +1 -2
  12. package/dist/_contracts/runtime-manifest.d.ts +1 -1
  13. package/dist/_contracts/runtime-security-profile.d.ts +0 -2
  14. package/dist/_contracts/runtime-security-profile.js +0 -9
  15. package/dist/_contracts/runtime-types.d.ts +25 -4
  16. package/dist/_contracts/stable.d.ts +1 -1
  17. package/dist/_contracts/stable.js +1 -1
  18. package/dist/_contracts/submission.d.ts +62 -95
  19. package/dist/_contracts/submission.js +59 -482
  20. package/dist/cli.mjs +99 -442
  21. package/dist/cli.mjs.sha256 +1 -1
  22. package/dist/client.d.ts +49 -25
  23. package/dist/client.js +341 -70
  24. package/dist/client.js.map +1 -1
  25. package/dist/index.d.ts +9 -15
  26. package/dist/index.js +11 -17
  27. package/dist/index.js.map +1 -1
  28. package/dist/retry.d.ts +162 -0
  29. package/dist/retry.js +320 -0
  30. package/dist/retry.js.map +1 -0
  31. package/dist/secret.d.ts +2 -2
  32. package/dist/secret.js +1 -1
  33. package/dist/version.d.ts +1 -1
  34. package/dist/version.js +1 -1
  35. package/docs/concepts/composition.md +8 -14
  36. package/docs/credentials.md +59 -101
  37. package/docs/defaults.md +0 -8
  38. package/docs/events.md +8 -9
  39. package/docs/limits-and-quotas.md +1 -4
  40. package/docs/limits.md +2 -6
  41. package/docs/mcp.md +4 -5
  42. package/docs/networking.md +6 -16
  43. package/docs/outputs.md +0 -4
  44. package/docs/public-surface.json +3 -3
  45. package/docs/quickstart.md +3 -7
  46. package/docs/retries.md +129 -0
  47. package/docs/run-config.md +6 -3
  48. package/docs/secrets.md +1 -1
  49. package/docs/skills.md +3 -3
  50. package/docs/vision-skills.md +52 -101
  51. package/examples/feature-tour.ts +284 -0
  52. package/package.json +1 -1
  53. package/dist/_contracts/proxy-protocol.d.ts +0 -305
  54. package/dist/_contracts/proxy-protocol.js +0 -297
  55. package/dist/_contracts/proxy-validation.d.ts +0 -19
  56. package/dist/_contracts/proxy-validation.js +0 -51
  57. package/dist/data-tools.d.ts +0 -82
  58. package/dist/data-tools.js +0 -251
  59. package/dist/data-tools.js.map +0 -1
  60. package/dist/proxy-endpoint.d.ts +0 -131
  61. package/dist/proxy-endpoint.js +0 -144
  62. package/dist/proxy-endpoint.js.map +0 -1
  63. package/examples/chat-corpus.ts +0 -84
package/dist/cli.mjs CHANGED
@@ -10,34 +10,6 @@ import { readFile, writeFile, readdir, stat, mkdir, chmod, rm } from "node:fs/pr
10
10
  import { resolve as resolvePath4, join, dirname as dirname2 } from "node:path";
11
11
  import { homedir } from "node:os";
12
12
 
13
- // ../contracts/dist/proxy-protocol.js
14
- var PROXY_PROTOCOL_VERSION_V2 = "2";
15
- var PROXY_PROTOCOL_HEADER = "x-aex-proxy-protocol";
16
- var PROXY_RESP_STATUS_HEADER = "x-aex-proxy-status";
17
- var PROXY_RESP_MODE_HEADER = "x-aex-proxy-effective-mode";
18
- var PROXY_RESP_TRUNCATED_HEADER = "x-aex-proxy-truncated";
19
- var PROXY_RESP_UPSTREAM_HEADERS_HEADER = "x-aex-proxy-upstream-headers";
20
- var PROXY_METHOD_HEADER = "x-aex-method";
21
- var PROXY_PATH_HEADER = "x-aex-path";
22
- var PROXY_QUERY_HEADER = "x-aex-query";
23
- var PROXY_HEADERS_HEADER = "x-aex-headers";
24
- var PROXY_RESPONSE_MODE_HEADER = "x-aex-response-mode";
25
- var PROXY_RESPONSE_MODES = ["status_only", "headers_only", "full"];
26
- var PROXY_ENDPOINT_DEFAULTS = {
27
- allowHeaders: [],
28
- responseMode: "headers_only",
29
- // 10 MiB. The body is buffered in the hosted API to enforce this cap, while the
30
- // launch default fits practical multimodal/tool POSTs without every endpoint
31
- // needing an override.
32
- maxRequestBytes: 10 * 1024 * 1024,
33
- // Unlimited (0). The request body is buffered to enforce its cap, so that
34
- // stays finite; the response is streamed, so it does not need one.
35
- maxResponseBytes: 0,
36
- // 5 minutes. Long-running upstream tool/model calls should not fail under a
37
- // development-oriented 10s ceiling; endpoints can still set a smaller value.
38
- timeoutMs: 5 * 60 * 1e3
39
- };
40
-
41
13
  // ../contracts/dist/provider-support.js
42
14
  var COMMON_DOCS = [
43
15
  { label: "Secrets", href: "secrets.md" },
@@ -392,7 +364,6 @@ function parseRunRequestConfig(input) {
392
364
  "environment",
393
365
  "runtimeSize",
394
366
  "timeout",
395
- "proxyEndpoints",
396
367
  "metadata"
397
368
  ]);
398
369
  for (const key of Object.keys(record)) {
@@ -412,14 +383,13 @@ function parseRunRequestConfig(input) {
412
383
  ...system !== void 0 ? { system } : {},
413
384
  prompt,
414
385
  ...mcpServers !== void 0 ? { mcpServers } : {},
415
- // environment / proxyEndpoints / metadata: passed through
416
- // as-is — the BFF revalidates them via `parseRunSubmissionRequest`,
386
+ // environment / metadata: passed through as-is — the BFF revalidates
387
+ // them via `parseRunSubmissionRequest`,
417
388
  // so duplicating the heavyweight parsers here would mean two sources
418
389
  // of truth. The CLI surfaces structural errors at submission time.
419
390
  ...record.environment !== void 0 ? { environment: record.environment } : {},
420
391
  ...record.runtimeSize !== void 0 ? { runtimeSize: record.runtimeSize } : {},
421
392
  ...record.timeout !== void 0 ? { timeout: record.timeout } : {},
422
- ...record.proxyEndpoints !== void 0 ? { proxyEndpoints: record.proxyEndpoints } : {},
423
393
  ...record.metadata !== void 0 ? { metadata: record.metadata } : {}
424
394
  };
425
395
  }
@@ -489,7 +459,6 @@ var RUNTIME_SECURITY_PROFILE_CONFIG = Object.freeze({
489
459
  allowOpenNetworking: false,
490
460
  allowRuntimePackages: false,
491
461
  allowCustomerEnvVars: true,
492
- allowProxyEndpoints: true,
493
462
  allowMcpServers: true
494
463
  }),
495
464
  standard: Object.freeze({
@@ -498,7 +467,6 @@ var RUNTIME_SECURITY_PROFILE_CONFIG = Object.freeze({
498
467
  allowOpenNetworking: true,
499
468
  allowRuntimePackages: true,
500
469
  allowCustomerEnvVars: true,
501
- allowProxyEndpoints: true,
502
470
  allowMcpServers: true
503
471
  }),
504
472
  developer: Object.freeze({
@@ -507,7 +475,6 @@ var RUNTIME_SECURITY_PROFILE_CONFIG = Object.freeze({
507
475
  allowOpenNetworking: true,
508
476
  allowRuntimePackages: true,
509
477
  allowCustomerEnvVars: true,
510
- allowProxyEndpoints: true,
511
478
  allowMcpServers: true
512
479
  })
513
480
  });
@@ -524,9 +491,6 @@ var RUN_PROVIDERS = [
524
491
  "doubao-cn"
525
492
  ];
526
493
  var DEFAULT_RUN_PROVIDER = "anthropic";
527
- var MIN_REDACTION_TARGET_BYTES = 4;
528
- var MIN_PROXY_SECRET_BYTES = 8;
529
- var _MIN_PROXY_SECRET_BYTES_OK = MIN_PROXY_SECRET_BYTES >= MIN_REDACTION_TARGET_BYTES;
530
494
  var BUILTIN_TOOL_NAMES = [
531
495
  "bash",
532
496
  "read_file",
@@ -1400,6 +1364,7 @@ __export(operations_exports, {
1400
1364
  listRuns: () => listRuns,
1401
1365
  listSecrets: () => listSecrets,
1402
1366
  listSessionEvents: () => listSessionEvents,
1367
+ listSessionMessages: () => listSessionMessages,
1403
1368
  listSessionOutputs: () => listSessionOutputs,
1404
1369
  listSessions: () => listSessions,
1405
1370
  normalizeOutputLinkExpiresIn: () => normalizeOutputLinkExpiresIn,
@@ -2188,6 +2153,16 @@ async function sendSessionMessage(http, sessionId, request, options) {
2188
2153
  body: JSON.stringify(request)
2189
2154
  });
2190
2155
  }
2156
+ async function listSessionMessages(http, sessionId, query) {
2157
+ const params = {};
2158
+ if (query?.limit !== void 0)
2159
+ params.limit = String(query.limit);
2160
+ if (query?.cursor !== void 0)
2161
+ params.cursor = query.cursor;
2162
+ if (query?.since !== void 0)
2163
+ params.since = query.since;
2164
+ return http.request(`/api/sessions/${encodeURIComponent(sessionId)}/messages`, {}, params);
2165
+ }
2191
2166
  async function suspendSession(http, sessionId, options) {
2192
2167
  const headers = idempotencyHeaders(options);
2193
2168
  return http.request(`/api/sessions/${encodeURIComponent(sessionId)}/suspend`, { method: "POST", ...headers ? { headers } : {} });
@@ -2800,34 +2775,8 @@ async function uploadWorkspaceAsset(http, input) {
2800
2775
  });
2801
2776
  }
2802
2777
 
2803
- // ../contracts/dist/proxy-validation.js
2804
- function validateProxyAuth(endpoints, auth) {
2805
- const authList = auth ?? [];
2806
- const endpointNames = new Set(endpoints.map((e) => e.name));
2807
- const authNames = /* @__PURE__ */ new Set();
2808
- for (const entry of authList) {
2809
- if (authNames.has(entry.name)) {
2810
- throw new Error(`secrets.proxyEndpointAuth contains duplicate name '${entry.name}'`);
2811
- }
2812
- authNames.add(entry.name);
2813
- if (!endpointNames.has(entry.name)) {
2814
- throw new Error(`secrets.proxyEndpointAuth[].name='${entry.name}' has no matching proxyEndpoints[].name`);
2815
- }
2816
- }
2817
- for (const endpoint of endpoints) {
2818
- const match = authList.find((a) => a.name === endpoint.name);
2819
- if (!match) {
2820
- throw new Error(`proxyEndpoints[].name='${endpoint.name}' is missing a matching secrets.proxyEndpointAuth entry`);
2821
- }
2822
- if (match.value.type !== endpoint.authShape.type) {
2823
- throw new Error(`secrets.proxyEndpointAuth[name='${endpoint.name}'].value.type='${match.value.type}' does not match proxyEndpoints[name='${endpoint.name}'].authShape.type='${endpoint.authShape.type}'`);
2824
- }
2825
- }
2826
- }
2827
-
2828
2778
  // dist/internal.js
2829
2779
  var AEX_INDEX_PATH = "/mnt/session/uploads/aex/index.json";
2830
- var AEX_RUN_TOKEN_PATH = "/mnt/session/uploads/aex/run-token";
2831
2780
 
2832
2781
  // dist/host/common.js
2833
2782
  var SUCCESS = { code: 0 };
@@ -2986,7 +2935,7 @@ async function refuseInsideManagedRun(io2, verb) {
2986
2935
  try {
2987
2936
  await io2.readFile(AEX_INDEX_PATH);
2988
2937
  io2.stderr(`\`aex ${verb}\` is a host command and cannot run inside a managed run container.
2989
- Use \`aex proxy ...\` to call your declared upstream endpoints from inside the run.
2938
+ Make HTTP calls from your code and pass credentials through secrets.
2990
2939
  `);
2991
2940
  return true;
2992
2941
  } catch (err2) {
@@ -3171,285 +3120,6 @@ async function runOutputsSyncCmd(io2, dirs) {
3171
3120
  return SUCCESS;
3172
3121
  }
3173
3122
 
3174
- // dist/proxy.js
3175
- function parseProxyFlags(rest) {
3176
- let endpointName = null;
3177
- let method = "GET";
3178
- let path = "/";
3179
- let query = null;
3180
- const headers = /* @__PURE__ */ new Map();
3181
- let dataSpec = null;
3182
- let responseMode = null;
3183
- let showHelp = false;
3184
- for (let i2 = 0; i2 < rest.length; i2++) {
3185
- const arg = rest[i2];
3186
- if (arg === "--help" || arg === "-h") {
3187
- showHelp = true;
3188
- continue;
3189
- }
3190
- if (arg === "--method") {
3191
- method = expect(rest, ++i2, "--method");
3192
- continue;
3193
- }
3194
- if (arg === "--path") {
3195
- path = expect(rest, ++i2, "--path");
3196
- continue;
3197
- }
3198
- if (arg === "--query") {
3199
- query = expect(rest, ++i2, "--query");
3200
- continue;
3201
- }
3202
- if (arg === "--header") {
3203
- const kv = expect(rest, ++i2, "--header");
3204
- const eq = kv.indexOf("=");
3205
- if (eq <= 0)
3206
- return { ok: false, reason: "--header must be in the form KEY=VALUE" };
3207
- headers.set(kv.slice(0, eq).toLowerCase(), kv.slice(eq + 1));
3208
- continue;
3209
- }
3210
- if (arg === "--data") {
3211
- dataSpec = expect(rest, ++i2, "--data");
3212
- continue;
3213
- }
3214
- if (arg === "--response-mode") {
3215
- responseMode = expect(rest, ++i2, "--response-mode");
3216
- continue;
3217
- }
3218
- if (arg.startsWith("--")) {
3219
- return { ok: false, reason: `unknown flag: ${arg}` };
3220
- }
3221
- if (endpointName === null) {
3222
- endpointName = arg;
3223
- continue;
3224
- }
3225
- return { ok: false, reason: `unexpected positional argument: ${arg}` };
3226
- }
3227
- return { ok: true, flags: { endpointName, method, path, query, headers, dataSpec, responseMode, showHelp } };
3228
- }
3229
- function expect(arr, idx, flag) {
3230
- const v = arr[idx];
3231
- if (v === void 0) {
3232
- throw new CliUsageError(`${flag} requires a value`);
3233
- }
3234
- return v;
3235
- }
3236
- var CliUsageError = class extends Error {
3237
- };
3238
- async function printProxyHelp(io2) {
3239
- io2.stdout("aex proxy \u2014 call an upstream HTTP endpoint via the managed proxy.\n\n");
3240
- io2.stdout("Usage:\n");
3241
- io2.stdout(" aex proxy <endpoint-name> [flags]\n\n");
3242
- io2.stdout("Flags:\n");
3243
- io2.stdout(" --method <verb> HTTP method (default: GET)\n");
3244
- io2.stdout(" --path <path> Caller-supplied path; must match policy prefixes\n");
3245
- io2.stdout(` --query <json> JSON object of query parameters (e.g. '{"q":"x"}')
3246
- `);
3247
- io2.stdout(" --header K=V Add a caller header (repeatable)\n");
3248
- io2.stdout(" --data <value> Request body. Use '-' for stdin, '@<file>' for file content\n");
3249
- io2.stdout(" --response-mode <mode> status_only | headers_only | full (may only narrow policy)\n");
3250
- io2.stdout(" --help Show this message\n\n");
3251
- const manifest = await tryReadManifest(io2);
3252
- if (manifest && manifest.endpoints.length > 0) {
3253
- io2.stdout("Declared endpoints:\n");
3254
- for (const ep of manifest.endpoints) {
3255
- io2.stdout(` \u2022 ${formatProxyEndpointSummary(ep)}
3256
- `);
3257
- }
3258
- }
3259
- return SUCCESS;
3260
- }
3261
- function formatProxyEndpointSummary(ep) {
3262
- const retry = ep.retry ? `, retry=${ep.retry.maxAttempts}x ${ep.retry.retryOnMethods.join("/")} ${ep.retry.retryOnStatuses.join("/")} delay=${ep.retry.initialDelayMs}-${ep.retry.maxDelayMs}ms jitter=${ep.retry.jitter}${ep.retry.respectRetryAfter ? " retry-after" : ""}` : "";
3263
- return `${ep.name}: ${ep.allowMethods.join(",")} ${ep.allowPathPrefixes.join(",")} (mode=${ep.responseMode}${retry})`;
3264
- }
3265
- async function runProxy(io2, rest) {
3266
- let parsed;
3267
- try {
3268
- parsed = parseProxyFlags(rest);
3269
- } catch (err2) {
3270
- if (err2 instanceof CliUsageError) {
3271
- io2.stderr(`${err2.message}
3272
- `);
3273
- return USAGE_ERR;
3274
- }
3275
- throw err2;
3276
- }
3277
- if (!parsed.ok) {
3278
- io2.stderr(`${parsed.reason}
3279
- `);
3280
- return USAGE_ERR;
3281
- }
3282
- const f = parsed.flags;
3283
- if (f.showHelp) {
3284
- return await printProxyHelp(io2);
3285
- }
3286
- if (!f.endpointName) {
3287
- io2.stderr("missing endpoint-name\n");
3288
- io2.stderr("usage: aex proxy <endpoint-name> [flags]\n");
3289
- return USAGE_ERR;
3290
- }
3291
- if (f.responseMode && !PROXY_RESPONSE_MODES.includes(f.responseMode)) {
3292
- io2.stderr(`--response-mode must be one of: ${PROXY_RESPONSE_MODES.join(", ")}
3293
- `);
3294
- return USAGE_ERR;
3295
- }
3296
- const manifest = await tryReadManifest(io2);
3297
- if (!manifest) {
3298
- emitError(io2, {
3299
- error: "internal_error",
3300
- message: "manifest not mounted; this CLI must run inside an aex-managed run"
3301
- });
3302
- return RUNTIME_ERR;
3303
- }
3304
- if (!manifest.proxyBaseUrl) {
3305
- emitError(io2, {
3306
- error: "endpoint_not_found",
3307
- message: "this run has no proxy endpoints declared",
3308
- endpointName: f.endpointName
3309
- });
3310
- return RUNTIME_ERR;
3311
- }
3312
- let token;
3313
- try {
3314
- token = (await io2.readFile(AEX_RUN_TOKEN_PATH)).trim();
3315
- } catch {
3316
- emitError(io2, {
3317
- error: "unauthorized",
3318
- message: "run token file missing; this run has no proxy bearer"
3319
- });
3320
- return RUNTIME_ERR;
3321
- }
3322
- if (!token) {
3323
- emitError(io2, { error: "unauthorized", message: "run token is empty" });
3324
- return RUNTIME_ERR;
3325
- }
3326
- let body;
3327
- if (f.dataSpec !== null) {
3328
- try {
3329
- body = await resolveBody(io2, f.dataSpec);
3330
- } catch (err2) {
3331
- io2.stderr(`failed to read request body: ${err2.message}
3332
- `);
3333
- return RUNTIME_ERR;
3334
- }
3335
- }
3336
- const url = `${manifest.proxyBaseUrl.replace(/\/+$/, "")}/${encodeURIComponent(f.endpointName)}`;
3337
- const requestHeaders = new Headers();
3338
- requestHeaders.set("authorization", `Bearer ${token}`);
3339
- requestHeaders.set(PROXY_PROTOCOL_HEADER, PROXY_PROTOCOL_VERSION_V2);
3340
- requestHeaders.set(PROXY_METHOD_HEADER, f.method.toUpperCase());
3341
- requestHeaders.set(PROXY_PATH_HEADER, f.path);
3342
- if (f.query) {
3343
- requestHeaders.set(PROXY_QUERY_HEADER, f.query);
3344
- }
3345
- if (f.headers.size > 0) {
3346
- requestHeaders.set(PROXY_HEADERS_HEADER, JSON.stringify(Object.fromEntries(f.headers)));
3347
- }
3348
- if (f.responseMode) {
3349
- requestHeaders.set(PROXY_RESPONSE_MODE_HEADER, f.responseMode);
3350
- }
3351
- if (body !== void 0) {
3352
- requestHeaders.set("content-length", String(body.byteLength));
3353
- }
3354
- const init = {
3355
- method: "POST",
3356
- headers: requestHeaders,
3357
- redirect: "manual"
3358
- };
3359
- if (body !== void 0) {
3360
- init.body = body;
3361
- }
3362
- let response;
3363
- try {
3364
- response = await io2.fetchImpl(url, init);
3365
- } catch (err2) {
3366
- emitError(io2, {
3367
- error: "upstream_error",
3368
- message: `proxy request failed: ${err2.message}`,
3369
- endpointName: f.endpointName
3370
- });
3371
- return RUNTIME_ERR;
3372
- }
3373
- if (response.headers.get(PROXY_RESP_STATUS_HEADER) !== null) {
3374
- const envelope = await readStreamedEnvelope(response, f.endpointName);
3375
- io2.stdout(JSON.stringify(envelope) + "\n");
3376
- return SUCCESS;
3377
- }
3378
- const text = await response.text();
3379
- let parsedBody;
3380
- try {
3381
- parsedBody = text ? JSON.parse(text) : {};
3382
- } catch {
3383
- const snippet = text.slice(0, 200).replace(/\s+/g, " ").trim();
3384
- emitError(io2, {
3385
- error: "internal_error",
3386
- message: `proxy returned non-JSON response (HTTP ${response.status}, body=${JSON.stringify(snippet)})`,
3387
- endpointName: f.endpointName
3388
- });
3389
- return RUNTIME_ERR;
3390
- }
3391
- if (!response.ok) {
3392
- io2.stderr(JSON.stringify(parsedBody) + "\n");
3393
- return RUNTIME_ERR;
3394
- }
3395
- io2.stdout(JSON.stringify(parsedBody) + "\n");
3396
- return SUCCESS;
3397
- }
3398
- async function resolveBody(io2, spec) {
3399
- if (spec === "-") {
3400
- const data = await io2.readFile("/dev/stdin");
3401
- return new Uint8Array(Buffer.from(data, "utf8"));
3402
- }
3403
- if (spec.startsWith("@")) {
3404
- const path = spec.slice(1);
3405
- if (!path)
3406
- throw new Error("--data @<file> requires a path");
3407
- const data = await io2.readFile(path);
3408
- return new Uint8Array(Buffer.from(data, "utf8"));
3409
- }
3410
- return new Uint8Array(Buffer.from(spec, "utf8"));
3411
- }
3412
- function emitError(io2, body) {
3413
- io2.stderr(JSON.stringify(body) + "\n");
3414
- }
3415
- async function readStreamedEnvelope(response, endpointName) {
3416
- const effectiveResponseMode = response.headers.get(PROXY_RESP_MODE_HEADER) ?? "headers_only";
3417
- const upstreamStatus = Number.parseInt(response.headers.get(PROXY_RESP_STATUS_HEADER) ?? "0", 10);
3418
- let upstreamHeaders = {};
3419
- const rawHeaders = response.headers.get(PROXY_RESP_UPSTREAM_HEADERS_HEADER);
3420
- if (rawHeaders) {
3421
- try {
3422
- const parsed = JSON.parse(rawHeaders);
3423
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
3424
- upstreamHeaders = parsed;
3425
- }
3426
- } catch {
3427
- }
3428
- }
3429
- const truncatedRaw = response.headers.get(PROXY_RESP_TRUNCATED_HEADER);
3430
- const bytes = new Uint8Array(await response.arrayBuffer());
3431
- return {
3432
- endpointName,
3433
- upstreamStatus,
3434
- upstreamHeaders,
3435
- effectiveResponseMode,
3436
- // The streamed path can't echo the request-side clamp decision (it
3437
- // isn't carried back); the effective mode is authoritative for the
3438
- // agent and matches what v1 surfaced for an un-clamped call.
3439
- modeClamped: false,
3440
- ...effectiveResponseMode === "full" && bytes.byteLength > 0 ? { upstreamBodyBase64: Buffer.from(bytes).toString("base64") } : {},
3441
- ...truncatedRaw === "true" ? { truncated: true } : {}
3442
- };
3443
- }
3444
- async function tryReadManifest(io2) {
3445
- try {
3446
- const raw = await io2.readFile(AEX_INDEX_PATH);
3447
- return JSON.parse(raw);
3448
- } catch {
3449
- return null;
3450
- }
3451
- }
3452
-
3453
3123
  // dist/host/run-cmd.js
3454
3124
  import { resolve as resolvePath } from "node:path";
3455
3125
  var DEFAULT_SESSION_IDLE_TTL = "3m";
@@ -3616,6 +3286,10 @@ async function runRunCmd(io2, argv) {
3616
3286
  return USAGE_ERR;
3617
3287
  }
3618
3288
  rest = proxyAuthFlags.remaining;
3289
+ if (proxyEndpointFlags.values.length > 0 || Object.keys(proxyAuthFlags.entries).length > 0) {
3290
+ io2.stderr("--proxy-endpoint and --proxy-auth are no longer supported; make HTTP calls from your code and pass credentials via secrets.\n");
3291
+ return USAGE_ERR;
3292
+ }
3619
3293
  const positional = rest.filter((a) => !a.startsWith("--"));
3620
3294
  const unknownFlags = rest.filter((a) => a.startsWith("--"));
3621
3295
  if (unknownFlags.length > 0) {
@@ -3727,35 +3401,6 @@ async function runRunCmd(io2, argv) {
3727
3401
  for (const name of mcpHeaderBag.keys()) {
3728
3402
  if (!mcpServersForSubmission.some((m) => m.name === name)) {
3729
3403
  io2.stderr(`--mcp-auth ${name}: no matching --mcp / mcpServers entry declared
3730
- `);
3731
- return USAGE_ERR;
3732
- }
3733
- }
3734
- let proxyEndpoints = runConfig.proxyEndpoints ?? [];
3735
- if (proxyEndpointFlags.values.length > 0) {
3736
- try {
3737
- proxyEndpoints = proxyEndpointFlags.values.map((raw, i2) => parseJsonOrThrow(raw, `--proxy-endpoint[${i2}]`));
3738
- } catch (err2) {
3739
- io2.stderr(`${err2.message}
3740
- `);
3741
- return USAGE_ERR;
3742
- }
3743
- }
3744
- const proxyAuth = [];
3745
- for (const [name, spec] of Object.entries(proxyAuthFlags.entries)) {
3746
- const parsed = parseProxyAuth(spec);
3747
- if (!parsed.ok) {
3748
- io2.stderr(`--proxy-auth ${name}: ${parsed.reason}
3749
- `);
3750
- return USAGE_ERR;
3751
- }
3752
- proxyAuth.push({ name, value: parsed.value });
3753
- }
3754
- if (proxyEndpoints.length > 0) {
3755
- try {
3756
- validateProxyAuth(proxyEndpoints, proxyAuth);
3757
- } catch (err2) {
3758
- io2.stderr(`proxy auth validation failed: ${err2.message}
3759
3404
  `);
3760
3405
  return USAGE_ERR;
3761
3406
  }
@@ -3774,8 +3419,7 @@ async function runRunCmd(io2, argv) {
3774
3419
  const hasAdditionalProviderKeys = Object.keys(providerKeyValues).some((p) => p !== provider);
3775
3420
  const secrets = {
3776
3421
  apiKeys: hasAdditionalProviderKeys ? providerKeyValues : { [provider]: providerKeyValues[provider] },
3777
- ...mcpServerSecrets.length > 0 ? { mcpServers: mcpServerSecrets } : {},
3778
- ...proxyAuth.length > 0 ? { proxyEndpointAuth: proxyAuth } : {}
3422
+ ...mcpServerSecrets.length > 0 ? { mcpServers: mcpServerSecrets } : {}
3779
3423
  };
3780
3424
  const request = {
3781
3425
  provider,
@@ -3784,8 +3428,7 @@ async function runRunCmd(io2, argv) {
3784
3428
  retention: { idleTtl: DEFAULT_SESSION_IDLE_TTL },
3785
3429
  ...runtimeSizeFlag.value ? { runtimeSize: runtimeSizeFlag.value } : runConfig.runtimeSize ? { runtimeSize: runConfig.runtimeSize } : {},
3786
3430
  ...runTimeoutFlag.value ? { timeout: runTimeoutFlag.value } : runConfig.timeout ? { timeout: runConfig.timeout } : {},
3787
- ...webhookFlag.value ? { webhook: { url: webhookFlag.value } } : {},
3788
- ...proxyEndpoints.length > 0 ? { proxyEndpoints } : {}
3431
+ ...webhookFlag.value ? { webhook: { url: webhookFlag.value } } : {}
3789
3432
  };
3790
3433
  const createKey = idempotency.value ?? generateIdempotencyKey();
3791
3434
  const messageKey = `${createKey}:message`;
@@ -3864,47 +3507,6 @@ async function runRunCmd(io2, argv) {
3864
3507
  return RUNTIME_ERR;
3865
3508
  }
3866
3509
  }
3867
- function parseProxyAuth(spec) {
3868
- const idx = spec.indexOf(":");
3869
- if (idx <= 0) {
3870
- return { ok: false, reason: `expected '<type>:<value>' (got: ${spec})` };
3871
- }
3872
- const type = spec.slice(0, idx);
3873
- const restValue = spec.slice(idx + 1);
3874
- switch (type) {
3875
- case "bearer":
3876
- if (!restValue)
3877
- return { ok: false, reason: "bearer requires a token value" };
3878
- return { ok: true, value: { type: "bearer", token: restValue } };
3879
- case "header":
3880
- if (!restValue)
3881
- return { ok: false, reason: "header requires a value" };
3882
- return { ok: true, value: { type: "header", value: restValue } };
3883
- case "query":
3884
- if (!restValue)
3885
- return { ok: false, reason: "query requires a value" };
3886
- return { ok: true, value: { type: "query", value: restValue } };
3887
- case "basic": {
3888
- const sep = restValue.indexOf(":");
3889
- if (sep <= 0 || sep >= restValue.length - 1) {
3890
- return { ok: false, reason: "basic requires <username>:<password>" };
3891
- }
3892
- return {
3893
- ok: true,
3894
- value: { type: "basic", username: restValue.slice(0, sep), password: restValue.slice(sep + 1) }
3895
- };
3896
- }
3897
- default:
3898
- return { ok: false, reason: `unknown auth type '${type}' (expected bearer|basic|header|query)` };
3899
- }
3900
- }
3901
- function parseJsonOrThrow(raw, label) {
3902
- try {
3903
- return JSON.parse(raw);
3904
- } catch (err2) {
3905
- throw new Error(`${label} is not valid JSON: ${err2.message}`);
3906
- }
3907
- }
3908
3510
  function stripMcpHeadersForParsing(input) {
3909
3511
  const mcpHeaders = /* @__PURE__ */ new Map();
3910
3512
  if (input === null || typeof input !== "object" || Array.isArray(input)) {
@@ -4400,6 +4002,82 @@ async function runWhoamiCmd(io2, argv) {
4400
4002
  }
4401
4003
  }
4402
4004
 
4005
+ // dist/host/redeem.js
4006
+ function messageForStatus(status2, serverMessage) {
4007
+ switch (status2) {
4008
+ case 404:
4009
+ return "coupon code not found";
4010
+ case 403:
4011
+ return "this coupon can't be redeemed by this workspace";
4012
+ case 409:
4013
+ return "coupon already redeemed";
4014
+ case 400:
4015
+ return serverMessage ? `invalid input: ${serverMessage}` : "invalid input";
4016
+ case 401:
4017
+ return "not authorized \u2014 check --api-token, or run `aex login`";
4018
+ default:
4019
+ return serverMessage ? `redeem failed: ${serverMessage}` : `redeem failed (HTTP ${status2})`;
4020
+ }
4021
+ }
4022
+ async function runRedeemCmd(io2, argv) {
4023
+ if (await refuseInsideManagedRun(io2, "redeem"))
4024
+ return USAGE_ERR;
4025
+ const common = await resolveCommonHostFlags(io2, argv);
4026
+ if (!common.ok) {
4027
+ io2.stderr(`${common.reason}
4028
+ `);
4029
+ return USAGE_ERR;
4030
+ }
4031
+ const positional = common.rest.filter((arg) => !arg.startsWith("--"));
4032
+ if (positional.length !== 1) {
4033
+ io2.stderr("usage: aex redeem <code> [common flags]\n");
4034
+ return USAGE_ERR;
4035
+ }
4036
+ const code = positional[0];
4037
+ const base = common.flags.aexUrl.replace(/\/+$/, "");
4038
+ const url = `${base}/billing/redeem`;
4039
+ let response;
4040
+ try {
4041
+ response = await io2.fetchImpl(url, {
4042
+ method: "POST",
4043
+ headers: {
4044
+ accept: "application/json",
4045
+ "content-type": "application/json",
4046
+ authorization: `Bearer ${common.flags.apiToken}`
4047
+ },
4048
+ body: JSON.stringify({ code })
4049
+ });
4050
+ } catch (err2) {
4051
+ io2.stderr(`redeem failed: ${err2 instanceof Error ? err2.message : String(err2)}
4052
+ `);
4053
+ return RUNTIME_ERR;
4054
+ }
4055
+ if (common.flags.debug) {
4056
+ io2.stderr(`[aex] POST /billing/redeem -> ${response.status}
4057
+ `);
4058
+ }
4059
+ const text = await response.text();
4060
+ let body = {};
4061
+ try {
4062
+ if (text.length > 0)
4063
+ body = JSON.parse(text);
4064
+ } catch {
4065
+ body = {};
4066
+ }
4067
+ if (!response.ok) {
4068
+ const serverMessage = body && typeof body === "object" && typeof body.message === "string" ? body.message : void 0;
4069
+ io2.stderr(`${messageForStatus(response.status, serverMessage)}
4070
+ `);
4071
+ return RUNTIME_ERR;
4072
+ }
4073
+ const ok = body;
4074
+ const amountUsd = typeof ok.amountUsd === "number" ? ok.amountUsd : 0;
4075
+ const newBalanceUsd = typeof ok.newBalanceUsd === "number" ? ok.newBalanceUsd : 0;
4076
+ io2.stdout(`Redeemed $${amountUsd.toFixed(2)}. New balance: $${newBalanceUsd.toFixed(2)}.
4077
+ `);
4078
+ return SUCCESS;
4079
+ }
4080
+
4403
4081
  // dist/host/debug.js
4404
4082
  import { dirname, resolve as resolvePath3 } from "node:path";
4405
4083
  function status(source, state, opts = {}) {
@@ -5649,8 +5327,6 @@ async function dispatch(io2, args) {
5649
5327
  const sub = args[0];
5650
5328
  const rest = args.slice(1);
5651
5329
  switch (sub) {
5652
- case "proxy":
5653
- return runProxy(io2, rest);
5654
5330
  case "run":
5655
5331
  return runRunCmd(io2, rest);
5656
5332
  case "status":
@@ -5680,6 +5356,8 @@ async function dispatch(io2, args) {
5680
5356
  return runDeleteAssetCmd(io2, rest);
5681
5357
  case "whoami":
5682
5358
  return runWhoamiCmd(io2, rest);
5359
+ case "redeem":
5360
+ return runRedeemCmd(io2, rest);
5683
5361
  case "login":
5684
5362
  return runLoginCmd(io2, rest);
5685
5363
  case "logout":
@@ -5704,26 +5382,6 @@ async function dispatch(io2, args) {
5704
5382
  }
5705
5383
  }
5706
5384
  async function printGlobalHelp(io2) {
5707
- const manifest = await tryReadManifest(io2);
5708
- if (manifest) {
5709
- io2.stdout("aex \u2014 in-container CLI for managed run sessions\n\n");
5710
- io2.stdout("Usage:\n");
5711
- io2.stdout(" aex proxy <endpoint-name> [flags]\n");
5712
- io2.stdout(" aex proxy --help\n\n");
5713
- if (manifest.endpoints.length === 0) {
5714
- io2.stdout("This run declared no proxy endpoints.\n");
5715
- } else {
5716
- io2.stdout("Declared proxy endpoints for this run:\n");
5717
- for (const ep of manifest.endpoints) {
5718
- io2.stdout(` \u2022 ${formatProxyEndpointSummary(ep)}
5719
- `);
5720
- }
5721
- }
5722
- io2.stdout(`
5723
- Protocol version: ${manifest.protocolVersion}
5724
- `);
5725
- return SUCCESS;
5726
- }
5727
5385
  io2.stdout("aex \u2014 unified CLI for the aex platform (mirrors the SDK 1:1)\n\n");
5728
5386
  io2.stdout("Usage:\n");
5729
5387
  io2.stdout(" aex run --config <run.json> --<provider>-api-key K --api-token T [flags]\n");
@@ -5740,6 +5398,7 @@ Protocol version: ${manifest.protocolVersion}
5740
5398
  io2.stdout(" aex delete <session-id> --api-token T\n");
5741
5399
  io2.stdout(" aex delete-asset <assetId|hash> --api-token T\n");
5742
5400
  io2.stdout(" aex whoami --api-token T\n");
5401
+ io2.stdout(" aex redeem <code> --api-token T Redeem a coupon code into the workspace prepaid balance\n");
5743
5402
  io2.stdout(" aex login --api-token T [--aex-url U] Persist token + url (then other verbs need no --api-token)\n");
5744
5403
  io2.stdout(" aex logout Clear the stored token\n");
5745
5404
  io2.stdout(" aex auth status Show the resolved config (token never printed)\n");
@@ -5767,8 +5426,6 @@ Protocol version: ${manifest.protocolVersion}
5767
5426
  io2.stdout(" --mcp name=url MCP server entry (repeatable)\n");
5768
5427
  io2.stdout(" --mcp-auth name=Hdr:Val Auth header on the matching --mcp; routed into vaulted secrets (repeatable)\n");
5769
5428
  io2.stdout(" --metadata key=value Submission metadata entry (repeatable)\n");
5770
- io2.stdout(" --proxy-endpoint '<json>' PlatformProxyEndpoint JSON (repeatable)\n");
5771
- io2.stdout(" --proxy-auth name=<spec> bearer:tok | basic:u:p | header:v | query:v (repeatable)\n");
5772
5429
  io2.stdout(" --runtime-size <size> managed runtime preset\n");
5773
5430
  io2.stdout(" --run-timeout <dur> Server-side run deadline (e.g. 1h); distinct from --timeout\n");
5774
5431
  io2.stdout(" --idempotency-key <key> Optional; defaults to a fresh UUID\n");