@aexhq/sdk 0.18.1 → 0.20.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 +2 -2
- package/dist/_contracts/models.d.ts +133 -38
- package/dist/_contracts/models.js +114 -69
- package/dist/_contracts/operations.d.ts +17 -1
- package/dist/_contracts/operations.js +50 -0
- package/dist/_contracts/provider-support.d.ts +68 -0
- package/dist/_contracts/provider-support.js +28 -0
- package/dist/_contracts/run-config.d.ts +1 -1
- package/dist/_contracts/run-cost.d.ts +27 -0
- package/dist/_contracts/run-cost.js +34 -1
- package/dist/_contracts/runtime-types.d.ts +32 -0
- package/dist/_contracts/submission.d.ts +58 -2
- package/dist/_contracts/submission.js +106 -7
- package/dist/agents-md.d.ts +3 -3
- package/dist/agents-md.js +6 -6
- package/dist/agents-md.js.map +1 -1
- package/dist/cli.mjs +116 -86
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +90 -10
- package/dist/client.js +121 -40
- package/dist/client.js.map +1 -1
- package/dist/fetch-archive.js +1 -1
- package/dist/file.d.ts +3 -3
- package/dist/file.js +6 -6
- package/dist/file.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/proxy-endpoint.d.ts +2 -2
- package/dist/proxy-endpoint.js +1 -1
- package/dist/secret.d.ts +102 -0
- package/dist/secret.js +148 -0
- package/dist/secret.js.map +1 -0
- package/dist/skill.d.ts +8 -8
- package/dist/skill.js +10 -10
- package/dist/skill.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/cleanup.md +1 -1
- package/docs/credentials.md +4 -4
- package/docs/events.md +2 -2
- package/docs/outputs.md +3 -3
- package/docs/provider-runtime-capabilities.md +23 -1
- package/docs/quickstart.md +7 -7
- package/docs/run-config.md +4 -4
- package/docs/skills.md +4 -4
- package/package.json +2 -2
|
@@ -109,6 +109,34 @@ export const PROVIDER_PUBLIC_SUPPORT = {
|
|
|
109
109
|
runtimeEvidence: {
|
|
110
110
|
managed: COMMON_EVIDENCE
|
|
111
111
|
}
|
|
112
|
+
},
|
|
113
|
+
// Doubao (ByteDance) via the official Ark API — international BytePlus gateway.
|
|
114
|
+
// Wired + parser/routing-verified but not yet proven against a live BytePlus
|
|
115
|
+
// account, so `live-unverified`. Promote to `supported` (and swap COMMON_EVIDENCE
|
|
116
|
+
// for a DOUBAO_MANAGED_EVIDENCE pointer to live-sdk-doubao.test.ts) once the
|
|
117
|
+
// live run passes.
|
|
118
|
+
doubao: {
|
|
119
|
+
displayName: "Doubao",
|
|
120
|
+
status: "live-unverified",
|
|
121
|
+
docsAnchor: "doubao",
|
|
122
|
+
docs: COMMON_DOCS,
|
|
123
|
+
evidence: COMMON_EVIDENCE,
|
|
124
|
+
runtimeEvidence: {
|
|
125
|
+
managed: COMMON_EVIDENCE
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
// Doubao (ByteDance) via the official Ark API — China Volcengine gateway.
|
|
129
|
+
// Same wiring as `doubao`; additionally gated on CF Worker egress reaching the
|
|
130
|
+
// Beijing host (see apps/egress-probe). `live-unverified` until proven live.
|
|
131
|
+
"doubao-cn": {
|
|
132
|
+
displayName: "Doubao (China)",
|
|
133
|
+
status: "live-unverified",
|
|
134
|
+
docsAnchor: "doubao-cn",
|
|
135
|
+
docs: COMMON_DOCS,
|
|
136
|
+
evidence: COMMON_EVIDENCE,
|
|
137
|
+
runtimeEvidence: {
|
|
138
|
+
managed: COMMON_EVIDENCE
|
|
139
|
+
}
|
|
112
140
|
}
|
|
113
141
|
};
|
|
114
142
|
export function providerPublicSupport(provider) {
|
|
@@ -251,7 +251,7 @@ export declare function rejectStdioMcpShape(record: Record<string, unknown>): vo
|
|
|
251
251
|
/**
|
|
252
252
|
* Plain JSON accepted by `aex run --config <path>`. This is not a
|
|
253
253
|
* platform object; it is only the non-secret run parameters that the CLI folds
|
|
254
|
-
* into the normal `
|
|
254
|
+
* into the normal `submit` request.
|
|
255
255
|
*/
|
|
256
256
|
export interface RunRequestConfig {
|
|
257
257
|
readonly model: RunModel;
|
|
@@ -92,6 +92,21 @@ export interface RunCostManagedKeyBudgetTelemetry {
|
|
|
92
92
|
readonly chargedCreditUnits?: number;
|
|
93
93
|
readonly releasedCreditUnits?: number;
|
|
94
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* The basis for a {@link RunCostTelemetry.billedCostUsd}: an honest marker of
|
|
97
|
+
* whether the figure is a settle-time ESTIMATE or has been RECONCILED against
|
|
98
|
+
* authoritative actuals. Deliberately carries NO rate-card version or unit
|
|
99
|
+
* rates — the platform's public-safe convention treats `rateCard`/`margin` as
|
|
100
|
+
* private tokens (run-cost.test.ts privateCostFieldPattern), so the version the
|
|
101
|
+
* figure was derived under stays internal (recorded only in the platform's
|
|
102
|
+
* internal raw-usage export).
|
|
103
|
+
*/
|
|
104
|
+
export declare const RUN_COST_BASIS_STATUSES: readonly ["estimated", "reconciled"];
|
|
105
|
+
export type RunCostBasisStatus = (typeof RUN_COST_BASIS_STATUSES)[number];
|
|
106
|
+
export interface RunCostBasis {
|
|
107
|
+
readonly currency: "USD";
|
|
108
|
+
readonly status: RunCostBasisStatus;
|
|
109
|
+
}
|
|
95
110
|
export interface RunCostTelemetry {
|
|
96
111
|
readonly schemaVersion: typeof RUN_COST_TELEMETRY_SCHEMA_VERSION;
|
|
97
112
|
readonly runId?: string;
|
|
@@ -108,6 +123,18 @@ export interface RunCostTelemetry {
|
|
|
108
123
|
readonly storage?: RunCostStorageTelemetry;
|
|
109
124
|
readonly proxy?: RunCostProxyTelemetry;
|
|
110
125
|
readonly managedKey?: RunCostManagedKeyBudgetTelemetry;
|
|
126
|
+
/**
|
|
127
|
+
* Customer-facing AEX cost of serving this run, USD — a REPORTED ESTIMATE,
|
|
128
|
+
* not a charge (telemetry/showback only; no invoicing or credit deduction).
|
|
129
|
+
* = rawCostUsd × marginMultiplier (margin currently a global 1.0). EXCLUDES
|
|
130
|
+
* the customer's BYOK provider spend. The raw (pre-margin) figure is kept
|
|
131
|
+
* internal and never appears on this public-safe shape. A plain number, so it
|
|
132
|
+
* passes the run-record public-safe archive scan. Absent when the run incurred
|
|
133
|
+
* no priced AEX usage.
|
|
134
|
+
*/
|
|
135
|
+
readonly billedCostUsd?: number;
|
|
136
|
+
/** Currency + estimate/reconciled basis for {@link billedCostUsd}. */
|
|
137
|
+
readonly costBasis?: RunCostBasis;
|
|
111
138
|
}
|
|
112
139
|
export type RunCostTelemetryInput = Omit<RunCostTelemetry, "schemaVersion">;
|
|
113
140
|
export interface RunCostTelemetryFromUsageSamplesInput {
|
|
@@ -96,6 +96,16 @@ const RUN_USAGE_SAMPLE_METRIC_UNITS = {
|
|
|
96
96
|
"managed_key.charged_credit_units": "credit_unit",
|
|
97
97
|
"managed_key.released_credit_units": "credit_unit"
|
|
98
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* The basis for a {@link RunCostTelemetry.billedCostUsd}: an honest marker of
|
|
101
|
+
* whether the figure is a settle-time ESTIMATE or has been RECONCILED against
|
|
102
|
+
* authoritative actuals. Deliberately carries NO rate-card version or unit
|
|
103
|
+
* rates — the platform's public-safe convention treats `rateCard`/`margin` as
|
|
104
|
+
* private tokens (run-cost.test.ts privateCostFieldPattern), so the version the
|
|
105
|
+
* figure was derived under stays internal (recorded only in the platform's
|
|
106
|
+
* internal raw-usage export).
|
|
107
|
+
*/
|
|
108
|
+
export const RUN_COST_BASIS_STATUSES = ["estimated", "reconciled"];
|
|
99
109
|
export function buildRunUsageSample(input) {
|
|
100
110
|
const metric = normalizeUsageSampleMetric(input.metric);
|
|
101
111
|
const expectedUnit = RUN_USAGE_SAMPLE_METRIC_UNITS[metric];
|
|
@@ -134,7 +144,9 @@ export function buildRunCostTelemetry(input) {
|
|
|
134
144
|
...(input.providerUsage ? { providerUsage: input.providerUsage.map(normalizeProviderUsage) } : {}),
|
|
135
145
|
...(input.storage ? { storage: normalizeStorage(input.storage) } : {}),
|
|
136
146
|
...(input.proxy ? { proxy: normalizeProxy(input.proxy) } : {}),
|
|
137
|
-
...(input.managedKey ? { managedKey: normalizeManagedKey(input.managedKey) } : {})
|
|
147
|
+
...(input.managedKey ? { managedKey: normalizeManagedKey(input.managedKey) } : {}),
|
|
148
|
+
...(input.billedCostUsd !== undefined ? { billedCostUsd: nonNegativeFinite(input.billedCostUsd, "billedCostUsd") } : {}),
|
|
149
|
+
...(input.costBasis ? { costBasis: normalizeCostBasis(input.costBasis) } : {})
|
|
138
150
|
});
|
|
139
151
|
}
|
|
140
152
|
export function buildRunCostTelemetryFromUsageSamples(input) {
|
|
@@ -318,6 +330,11 @@ export function mergeRunCostTelemetry(base, next) {
|
|
|
318
330
|
const storage = sumStorage(base.storage, patch.storage);
|
|
319
331
|
const proxy = sumProxy(base.proxy, patch.proxy);
|
|
320
332
|
const managedKey = mergeManagedKey(base.managedKey, patch.managedKey);
|
|
333
|
+
// Derived cost fields are LAST-WRITER-WINS (a re-derivation supersedes the
|
|
334
|
+
// prior estimate), not summed — they are projections of the whole sample set,
|
|
335
|
+
// not additive metrics.
|
|
336
|
+
const billedCostUsd = patch.billedCostUsd ?? base.billedCostUsd;
|
|
337
|
+
const costBasis = patch.costBasis ?? base.costBasis;
|
|
321
338
|
if (runId)
|
|
322
339
|
merged.runId = runId;
|
|
323
340
|
if (provider)
|
|
@@ -346,6 +363,10 @@ export function mergeRunCostTelemetry(base, next) {
|
|
|
346
363
|
merged.proxy = proxy;
|
|
347
364
|
if (managedKey)
|
|
348
365
|
merged.managedKey = managedKey;
|
|
366
|
+
if (billedCostUsd !== undefined)
|
|
367
|
+
merged.billedCostUsd = billedCostUsd;
|
|
368
|
+
if (costBasis)
|
|
369
|
+
merged.costBasis = costBasis;
|
|
349
370
|
return buildRunCostTelemetry(merged);
|
|
350
371
|
}
|
|
351
372
|
function normalizeDurations(input) {
|
|
@@ -470,6 +491,18 @@ function normalizeSummaryStatus(input) {
|
|
|
470
491
|
}
|
|
471
492
|
return input;
|
|
472
493
|
}
|
|
494
|
+
function normalizeCostBasis(input) {
|
|
495
|
+
if (!input || typeof input !== "object") {
|
|
496
|
+
throw new Error("run cost basis must be an object");
|
|
497
|
+
}
|
|
498
|
+
if (input.currency !== "USD") {
|
|
499
|
+
throw new Error(`run cost basis currency ${String(input.currency)} is not supported`);
|
|
500
|
+
}
|
|
501
|
+
if (!isStringIn(input.status, RUN_COST_BASIS_STATUSES)) {
|
|
502
|
+
throw new Error(`run cost basis status ${String(input.status)} is not supported`);
|
|
503
|
+
}
|
|
504
|
+
return Object.freeze({ currency: "USD", status: input.status });
|
|
505
|
+
}
|
|
473
506
|
function addProviderUsage(usageByKey, input, sample, field) {
|
|
474
507
|
const provider = sample.provider ?? input.provider;
|
|
475
508
|
if (!provider) {
|
|
@@ -210,3 +210,35 @@ export interface FileRecord {
|
|
|
210
210
|
readonly deletedAt?: string | null;
|
|
211
211
|
readonly [key: string]: unknown;
|
|
212
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Wire-level record for a workspace secret as returned by the BFF.
|
|
215
|
+
*
|
|
216
|
+
* Workspace secrets share the lifecycle SEMANTIC of skills/files: a
|
|
217
|
+
* `Secret.value(...)` is per-run and gone at terminal; PROMOTING it (or
|
|
218
|
+
* `aex.secrets.set`) persists a named, searchable workspace secret. The
|
|
219
|
+
* identity is the `name` (the handle a `Secret.ref` points at); the value
|
|
220
|
+
* rotates under that stable name, bumping `version`.
|
|
221
|
+
*
|
|
222
|
+
* This record is METADATA ONLY — it never carries the secret value. The value
|
|
223
|
+
* is write-only on create/rotate and readable solely via the audited
|
|
224
|
+
* {@link SecretReveal} path.
|
|
225
|
+
*/
|
|
226
|
+
export interface SecretRecord {
|
|
227
|
+
readonly id: string;
|
|
228
|
+
readonly name: string;
|
|
229
|
+
readonly version: number;
|
|
230
|
+
readonly state: "ready";
|
|
231
|
+
readonly createdAt?: string;
|
|
232
|
+
readonly updatedAt?: string;
|
|
233
|
+
readonly deletedAt?: string | null;
|
|
234
|
+
readonly [key: string]: unknown;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Value-bearing result of an audited `aex.secrets.reveal`. The ONLY wire shape
|
|
238
|
+
* that carries a workspace secret value back to the caller. Reveal is a logged
|
|
239
|
+
* action (POST, not GET) so a value read is always attributable.
|
|
240
|
+
*/
|
|
241
|
+
export interface SecretReveal {
|
|
242
|
+
readonly name: string;
|
|
243
|
+
readonly value: string;
|
|
244
|
+
}
|
|
@@ -105,7 +105,7 @@ export declare function packageInstallString(pkg: PlatformPackage): string;
|
|
|
105
105
|
* runtime; provider selection only decides which upstream model route
|
|
106
106
|
* the managed provider-proxy uses.
|
|
107
107
|
*/
|
|
108
|
-
export declare const RUN_PROVIDERS: readonly ["anthropic", "deepseek", "openai", "gemini", "mistral", "openrouter"];
|
|
108
|
+
export declare const RUN_PROVIDERS: readonly ["anthropic", "deepseek", "openai", "gemini", "mistral", "openrouter", "doubao", "doubao-cn"];
|
|
109
109
|
export type RunProvider = (typeof RUN_PROVIDERS)[number];
|
|
110
110
|
export declare const DEFAULT_RUN_PROVIDER: RunProvider;
|
|
111
111
|
/**
|
|
@@ -133,6 +133,10 @@ export declare const Providers: {
|
|
|
133
133
|
readonly MISTRAL: "mistral";
|
|
134
134
|
/** OpenRouter — OpenAI-compatible aggregator routing to many upstream models. */
|
|
135
135
|
readonly OPENROUTER: "openrouter";
|
|
136
|
+
/** Doubao (ByteDance) via the official international BytePlus ModelArk gateway. */
|
|
137
|
+
readonly DOUBAO: "doubao";
|
|
138
|
+
/** Doubao (ByteDance) via the official China Volcengine Ark gateway. */
|
|
139
|
+
readonly DOUBAO_CN: "doubao-cn";
|
|
136
140
|
};
|
|
137
141
|
/**
|
|
138
142
|
* Customer-facing runtime selector. Optional on the wire; absent resolves
|
|
@@ -194,6 +198,15 @@ export interface PlatformInlineSecrets {
|
|
|
194
198
|
readonly apiKey?: string;
|
|
195
199
|
readonly mcpServers?: readonly PlatformMcpServerSecret[];
|
|
196
200
|
readonly proxyEndpointAuth?: readonly PlatformProxyEndpointAuth[];
|
|
201
|
+
/**
|
|
202
|
+
* Per-run env-var secret VALUES, keyed by env name. Each entry pairs with a
|
|
203
|
+
* `submission.secretEnv[<envName>] = { ephemeral: true }` declaration. Lives
|
|
204
|
+
* in the secrets channel so it is vaulted and excluded from the idempotency
|
|
205
|
+
* hash; the runtime injects it as the named env var and it is deleted at the
|
|
206
|
+
* run's terminal. Workspace `{ ref }` bindings resolve server-side and never
|
|
207
|
+
* appear here.
|
|
208
|
+
*/
|
|
209
|
+
readonly envSecrets?: Readonly<Record<string, string>>;
|
|
197
210
|
}
|
|
198
211
|
/**
|
|
199
212
|
* Per-run named HTTP proxy endpoint. The `authShape` describes how the
|
|
@@ -219,6 +232,21 @@ export interface PlatformProxyEndpoint {
|
|
|
219
232
|
readonly retry?: ProxyRetryPolicy;
|
|
220
233
|
}
|
|
221
234
|
export declare const SECRETS_KEY = "secrets";
|
|
235
|
+
/** POSIX-style env var name a `secretEnv` entry binds to (e.g. `SERPER_API_KEY`). */
|
|
236
|
+
export declare const SECRET_ENV_NAME_PATTERN: RegExp;
|
|
237
|
+
/** Workspace secret handle a `secretEnv` ref points at (and the name `secret.upload` persists to). */
|
|
238
|
+
export declare const SECRET_HANDLE_PATTERN: RegExp;
|
|
239
|
+
/**
|
|
240
|
+
* One `submission.secretEnv` entry — VALUE-FREE, so it rides the (hashed)
|
|
241
|
+
* submission safely. `{ ref }` resolves a workspace secret server-side;
|
|
242
|
+
* `{ ephemeral: true }` pairs with a `secrets.envSecrets[<envName>]` value
|
|
243
|
+
* (per-run, vaulted, deleted at the run's terminal).
|
|
244
|
+
*/
|
|
245
|
+
export type PlatformSecretEnvEntry = {
|
|
246
|
+
readonly ref: string;
|
|
247
|
+
} | {
|
|
248
|
+
readonly ephemeral: true;
|
|
249
|
+
};
|
|
222
250
|
export declare const PROXY_ENDPOINT_NAME_PATTERN: RegExp;
|
|
223
251
|
export declare const RESERVED_PROXY_ENDPOINT_NAMES: Set<string>;
|
|
224
252
|
export declare const deniedSecretFields: Set<string>;
|
|
@@ -228,6 +256,16 @@ export declare function parseProxyMethods(input: unknown, field: string): readon
|
|
|
228
256
|
export declare function parseProxyPathPrefixes(input: unknown, field: string): readonly string[];
|
|
229
257
|
export declare function parseProxyAllowedHeaders(input: unknown, field: string, authShape: ProxyAuthShape): readonly string[] | undefined;
|
|
230
258
|
export declare function crossValidateProxyEndpointsAndAuth(endpoints: readonly PlatformProxyEndpoint[] | undefined, auth: readonly PlatformProxyEndpointAuth[] | undefined): void;
|
|
259
|
+
/**
|
|
260
|
+
* Cross-check `submission.secretEnv` declarations against `secrets.envSecrets`
|
|
261
|
+
* values. Mirrors {@link crossValidateProxyEndpointsAndAuth}:
|
|
262
|
+
*
|
|
263
|
+
* - `{ ephemeral: true }` MUST have a matching `secrets.envSecrets` value.
|
|
264
|
+
* - `{ ref }` MUST NOT supply a value (the value lives in the workspace store).
|
|
265
|
+
* - every `secrets.envSecrets` value MUST have a matching `{ ephemeral: true }`
|
|
266
|
+
* declaration (no orphan values that would never be injected).
|
|
267
|
+
*/
|
|
268
|
+
export declare function crossValidateSecretEnvAndValues(secretEnv: Readonly<Record<string, PlatformSecretEnvEntry>> | undefined, envSecrets: Readonly<Record<string, string>> | undefined): void;
|
|
231
269
|
export declare function parseInlineSecrets(input: unknown): PlatformInlineSecrets;
|
|
232
270
|
/**
|
|
233
271
|
* The proxy body-redactor refuses to mask any derived target string shorter
|
|
@@ -263,6 +301,15 @@ export interface PlatformSubmission {
|
|
|
263
301
|
readonly agentsMd: readonly AgentsMdRef[];
|
|
264
302
|
readonly files: readonly FileRef[];
|
|
265
303
|
readonly mcpServers: readonly McpServerRef[];
|
|
304
|
+
/**
|
|
305
|
+
* Env-var secret bindings — VALUE-FREE declarations keyed by env name. Each
|
|
306
|
+
* value is `{ ref }` (resolve a workspace secret server-side) or
|
|
307
|
+
* `{ ephemeral: true }` (value supplied in `secrets.envSecrets`, vaulted and
|
|
308
|
+
* deleted at terminal). The runtime injects the resolved value as the named
|
|
309
|
+
* env var. Lifecycle parity with skills/files: per-run by default, persisted
|
|
310
|
+
* only when promoted to the workspace store.
|
|
311
|
+
*/
|
|
312
|
+
readonly secretEnv?: Readonly<Record<string, PlatformSecretEnvEntry>>;
|
|
266
313
|
readonly environment?: PlatformEnvironment;
|
|
267
314
|
readonly securityProfile?: RuntimeSecurityProfileName;
|
|
268
315
|
readonly metadata?: Record<string, JsonValue>;
|
|
@@ -369,6 +416,15 @@ export interface PlatformRunSubmissionRequest {
|
|
|
369
416
|
* for repair until this budget is exhausted.
|
|
370
417
|
*/
|
|
371
418
|
readonly postHook?: PlatformPostHook;
|
|
419
|
+
/**
|
|
420
|
+
* Lineage parent (agent-session §9). When present the server admits this
|
|
421
|
+
* run as a CHILD of `parentRunId`: it walks the parent's lineage, enforces
|
|
422
|
+
* the max-subagent-depth + per-root concurrency caps, and persists
|
|
423
|
+
* `parent_run_id` + a server-derived `depth`. The client may name a parent
|
|
424
|
+
* but NEVER the depth — depth is computed server-side from the parent row,
|
|
425
|
+
* so a forged value cannot bypass the cap.
|
|
426
|
+
*/
|
|
427
|
+
readonly parentRunId?: string;
|
|
372
428
|
}
|
|
373
429
|
/**
|
|
374
430
|
* Wire shape posted by the SDK and CLI. `workspaceId` is **omitted by
|
|
@@ -466,7 +522,7 @@ export declare class RuntimeValidationError extends Error {
|
|
|
466
522
|
}
|
|
467
523
|
/**
|
|
468
524
|
* Walk the parsed submission and collect features that the active managed
|
|
469
|
-
* runtime cannot serve. Provider-hosted skill refs (`
|
|
525
|
+
* runtime cannot serve. Provider-hosted skill refs (`kind:"provider"`) are
|
|
470
526
|
* rejected now that new submissions only dispatch through managed runs.
|
|
471
527
|
*/
|
|
472
528
|
export declare function collectManagedUnsupportedFeatures(req: PlatformRunSubmissionRequest): string[];
|
|
@@ -80,7 +80,9 @@ export const RUN_PROVIDERS = [
|
|
|
80
80
|
"openai",
|
|
81
81
|
"gemini",
|
|
82
82
|
"mistral",
|
|
83
|
-
"openrouter"
|
|
83
|
+
"openrouter",
|
|
84
|
+
"doubao",
|
|
85
|
+
"doubao-cn"
|
|
84
86
|
];
|
|
85
87
|
export const DEFAULT_RUN_PROVIDER = "anthropic";
|
|
86
88
|
/**
|
|
@@ -107,7 +109,11 @@ export const Providers = {
|
|
|
107
109
|
/** Mistral. */
|
|
108
110
|
MISTRAL: "mistral",
|
|
109
111
|
/** OpenRouter — OpenAI-compatible aggregator routing to many upstream models. */
|
|
110
|
-
OPENROUTER: "openrouter"
|
|
112
|
+
OPENROUTER: "openrouter",
|
|
113
|
+
/** Doubao (ByteDance) via the official international BytePlus ModelArk gateway. */
|
|
114
|
+
DOUBAO: "doubao",
|
|
115
|
+
/** Doubao (ByteDance) via the official China Volcengine Ark gateway. */
|
|
116
|
+
DOUBAO_CN: "doubao-cn"
|
|
111
117
|
};
|
|
112
118
|
/**
|
|
113
119
|
* Customer-facing runtime selector. Optional on the wire; absent resolves
|
|
@@ -126,6 +132,10 @@ export function checkRuntimeSupported(provider, runtime) {
|
|
|
126
132
|
return { ok: true };
|
|
127
133
|
}
|
|
128
134
|
export const SECRETS_KEY = "secrets";
|
|
135
|
+
/** POSIX-style env var name a `secretEnv` entry binds to (e.g. `SERPER_API_KEY`). */
|
|
136
|
+
export const SECRET_ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
|
|
137
|
+
/** Workspace secret handle a `secretEnv` ref points at (and the name `secret.upload` persists to). */
|
|
138
|
+
export const SECRET_HANDLE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
129
139
|
export const PROXY_ENDPOINT_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
130
140
|
export const RESERVED_PROXY_ENDPOINT_NAMES = new Set(["proxy", "aex", "internal", "admin"]);
|
|
131
141
|
/**
|
|
@@ -633,9 +643,40 @@ export function crossValidateProxyEndpointsAndAuth(endpoints, auth) {
|
|
|
633
643
|
}
|
|
634
644
|
}
|
|
635
645
|
}
|
|
646
|
+
/**
|
|
647
|
+
* Cross-check `submission.secretEnv` declarations against `secrets.envSecrets`
|
|
648
|
+
* values. Mirrors {@link crossValidateProxyEndpointsAndAuth}:
|
|
649
|
+
*
|
|
650
|
+
* - `{ ephemeral: true }` MUST have a matching `secrets.envSecrets` value.
|
|
651
|
+
* - `{ ref }` MUST NOT supply a value (the value lives in the workspace store).
|
|
652
|
+
* - every `secrets.envSecrets` value MUST have a matching `{ ephemeral: true }`
|
|
653
|
+
* declaration (no orphan values that would never be injected).
|
|
654
|
+
*/
|
|
655
|
+
export function crossValidateSecretEnvAndValues(secretEnv, envSecrets) {
|
|
656
|
+
const declarations = secretEnv ?? {};
|
|
657
|
+
const values = envSecrets ?? {};
|
|
658
|
+
for (const [envName, entry] of Object.entries(declarations)) {
|
|
659
|
+
const hasValue = Object.prototype.hasOwnProperty.call(values, envName);
|
|
660
|
+
if ("ref" in entry) {
|
|
661
|
+
if (hasValue) {
|
|
662
|
+
throw new Error(`submission.secretEnv[${envName}] is a workspace ref and must not supply a value in secrets.envSecrets[${envName}]; the value resolves server-side`);
|
|
663
|
+
}
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
if (!hasValue) {
|
|
667
|
+
throw new Error(`submission.secretEnv[${envName}] is ephemeral but has no matching secrets.envSecrets[${envName}] value`);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
for (const envName of Object.keys(values)) {
|
|
671
|
+
const entry = declarations[envName];
|
|
672
|
+
if (!entry || !("ephemeral" in entry)) {
|
|
673
|
+
throw new Error(`secrets.envSecrets[${envName}] has no matching submission.secretEnv[${envName}] ephemeral declaration`);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
636
677
|
export function parseInlineSecrets(input) {
|
|
637
678
|
const value = requireRecord(input, "secrets");
|
|
638
|
-
const allowedTopLevel = new Set(["apiKey", "mcpServers", "proxyEndpointAuth"]);
|
|
679
|
+
const allowedTopLevel = new Set(["apiKey", "mcpServers", "proxyEndpointAuth", "envSecrets"]);
|
|
639
680
|
for (const key of Object.keys(value)) {
|
|
640
681
|
if (key.startsWith("__aex_")) {
|
|
641
682
|
// Platform-internal namespace (e.g. __aex_proxy_token). The BFF
|
|
@@ -651,12 +692,30 @@ export function parseInlineSecrets(input) {
|
|
|
651
692
|
const apiKey = value.apiKey !== undefined ? requireString(value.apiKey, "secrets.apiKey") : undefined;
|
|
652
693
|
const mcpServers = parseMcpServerSecrets(value.mcpServers);
|
|
653
694
|
const proxyEndpointAuth = parseProxyEndpointAuth(value.proxyEndpointAuth);
|
|
695
|
+
const envSecrets = parseEnvSecrets(value.envSecrets);
|
|
654
696
|
return {
|
|
655
697
|
...(apiKey !== undefined ? { apiKey } : {}),
|
|
656
698
|
...(mcpServers ? { mcpServers } : {}),
|
|
657
|
-
...(proxyEndpointAuth ? { proxyEndpointAuth } : {})
|
|
699
|
+
...(proxyEndpointAuth ? { proxyEndpointAuth } : {}),
|
|
700
|
+
...(envSecrets ? { envSecrets } : {})
|
|
658
701
|
};
|
|
659
702
|
}
|
|
703
|
+
function parseEnvSecrets(input) {
|
|
704
|
+
if (input === undefined || input === null)
|
|
705
|
+
return undefined;
|
|
706
|
+
const value = requireRecord(input, "secrets.envSecrets");
|
|
707
|
+
const out = {};
|
|
708
|
+
for (const [envName, entry] of Object.entries(value)) {
|
|
709
|
+
if (!SECRET_ENV_NAME_PATTERN.test(envName)) {
|
|
710
|
+
throw new Error(`secrets.envSecrets key "${envName}" must be a valid env var name matching ${SECRET_ENV_NAME_PATTERN.source}`);
|
|
711
|
+
}
|
|
712
|
+
if (typeof entry !== "string" || entry.length === 0) {
|
|
713
|
+
throw new Error(`secrets.envSecrets.${envName} must be a non-empty string`);
|
|
714
|
+
}
|
|
715
|
+
out[envName] = entry;
|
|
716
|
+
}
|
|
717
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
718
|
+
}
|
|
660
719
|
function parseMcpServerSecrets(input) {
|
|
661
720
|
if (input === undefined) {
|
|
662
721
|
return undefined;
|
|
@@ -917,6 +976,7 @@ export function parseRunSubmissionRequest(input, options = {}) {
|
|
|
917
976
|
"timeout",
|
|
918
977
|
"postHook",
|
|
919
978
|
"proxyEndpoints",
|
|
979
|
+
"parentRunId",
|
|
920
980
|
SECRETS_KEY
|
|
921
981
|
]);
|
|
922
982
|
for (const key of Object.keys(value)) {
|
|
@@ -949,6 +1009,9 @@ export function parseRunSubmissionRequest(input, options = {}) {
|
|
|
949
1009
|
}
|
|
950
1010
|
const runtimeSize = parseRuntimeSize(value.runtimeSize);
|
|
951
1011
|
const timeoutMs = parseRunTimeout(value.timeout);
|
|
1012
|
+
// Lineage parent only. `depth` is NEVER accepted from the wire — the server
|
|
1013
|
+
// derives it from the parent row (a forged depth must not bypass the cap).
|
|
1014
|
+
const parentRunId = optionalString(value.parentRunId, "submission.parentRunId");
|
|
952
1015
|
const postHook = parsePostHook(value.postHook, "submission.postHook");
|
|
953
1016
|
const proxyEndpoints = parseProxyEndpoints(value.proxyEndpoints);
|
|
954
1017
|
const secrets = parseInlineSecrets(value.secrets);
|
|
@@ -956,6 +1019,7 @@ export function parseRunSubmissionRequest(input, options = {}) {
|
|
|
956
1019
|
crossValidateProxyEndpointsAndAuth(proxyEndpoints, secrets.proxyEndpointAuth);
|
|
957
1020
|
const submission = parseSubmission(value.submission);
|
|
958
1021
|
assertRunModelMatchesProvider(provider, submission.model);
|
|
1022
|
+
crossValidateSecretEnvAndValues(submission.secretEnv, secrets.envSecrets);
|
|
959
1023
|
// mcpServers names must agree across the submission half and the
|
|
960
1024
|
// secrets half — every secrets.mcpServers[i].name MUST resolve to a
|
|
961
1025
|
// submission.mcpServers entry (no orphan secrets) AND the URL must
|
|
@@ -999,6 +1063,7 @@ export function parseRunSubmissionRequest(input, options = {}) {
|
|
|
999
1063
|
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
1000
1064
|
...(postHook !== undefined ? { postHook } : {}),
|
|
1001
1065
|
...(proxyEndpoints ? { proxyEndpoints } : {}),
|
|
1066
|
+
...(parentRunId !== undefined ? { parentRunId } : {}),
|
|
1002
1067
|
secrets
|
|
1003
1068
|
};
|
|
1004
1069
|
}
|
|
@@ -1051,6 +1116,7 @@ export function parseSubmission(input) {
|
|
|
1051
1116
|
"agentsMd",
|
|
1052
1117
|
"files",
|
|
1053
1118
|
"mcpServers",
|
|
1119
|
+
"secretEnv",
|
|
1054
1120
|
"environment",
|
|
1055
1121
|
"securityProfile",
|
|
1056
1122
|
"metadata",
|
|
@@ -1071,6 +1137,7 @@ export function parseSubmission(input) {
|
|
|
1071
1137
|
const agentsMd = parseAgentsMd(value.agentsMd);
|
|
1072
1138
|
const files = parseFiles(value.files);
|
|
1073
1139
|
const mcpServers = parseMcpServers(value.mcpServers);
|
|
1140
|
+
const secretEnv = parseSecretEnv(value.secretEnv);
|
|
1074
1141
|
const environment = parseEnvironment(value.environment);
|
|
1075
1142
|
const securityProfile = parseRuntimeSecurityProfile(value.securityProfile);
|
|
1076
1143
|
const metadata = optionalJsonRecord(value.metadata, "submission.metadata");
|
|
@@ -1086,6 +1153,7 @@ export function parseSubmission(input) {
|
|
|
1086
1153
|
agentsMd,
|
|
1087
1154
|
files,
|
|
1088
1155
|
mcpServers,
|
|
1156
|
+
...(secretEnv ? { secretEnv } : {}),
|
|
1089
1157
|
...(environment ? { environment } : {}),
|
|
1090
1158
|
...(securityProfile ? { securityProfile } : {}),
|
|
1091
1159
|
...(metadata ? { metadata } : {}),
|
|
@@ -1095,6 +1163,37 @@ export function parseSubmission(input) {
|
|
|
1095
1163
|
...(platform ? { platform } : {})
|
|
1096
1164
|
};
|
|
1097
1165
|
}
|
|
1166
|
+
function parseSecretEnv(input) {
|
|
1167
|
+
if (input === undefined || input === null)
|
|
1168
|
+
return undefined;
|
|
1169
|
+
const value = requireRecord(input, "submission.secretEnv");
|
|
1170
|
+
const out = {};
|
|
1171
|
+
for (const [envName, entry] of Object.entries(value)) {
|
|
1172
|
+
if (!SECRET_ENV_NAME_PATTERN.test(envName)) {
|
|
1173
|
+
throw new Error(`submission.secretEnv key "${envName}" must be a valid env var name matching ${SECRET_ENV_NAME_PATTERN.source}`);
|
|
1174
|
+
}
|
|
1175
|
+
const path = `submission.secretEnv.${envName}`;
|
|
1176
|
+
const record = requireRecord(entry, path);
|
|
1177
|
+
const keys = Object.keys(record);
|
|
1178
|
+
if (keys.length !== 1 || (!("ref" in record) && !("ephemeral" in record))) {
|
|
1179
|
+
throw new Error(`${path} must be exactly one of { ref } or { ephemeral: true }`);
|
|
1180
|
+
}
|
|
1181
|
+
if ("ref" in record) {
|
|
1182
|
+
const handle = requireString(record.ref, `${path}.ref`);
|
|
1183
|
+
if (!SECRET_HANDLE_PATTERN.test(handle)) {
|
|
1184
|
+
throw new Error(`${path}.ref handle must match ${SECRET_HANDLE_PATTERN.source}`);
|
|
1185
|
+
}
|
|
1186
|
+
out[envName] = { ref: handle };
|
|
1187
|
+
}
|
|
1188
|
+
else {
|
|
1189
|
+
if (record.ephemeral !== true) {
|
|
1190
|
+
throw new Error(`${path}.ephemeral must be the literal true`);
|
|
1191
|
+
}
|
|
1192
|
+
out[envName] = { ephemeral: true };
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
1196
|
+
}
|
|
1098
1197
|
function parsePlatformConfig(input) {
|
|
1099
1198
|
if (input === undefined || input === null)
|
|
1100
1199
|
return undefined;
|
|
@@ -1478,15 +1577,15 @@ export class RuntimeValidationError extends Error {
|
|
|
1478
1577
|
}
|
|
1479
1578
|
/**
|
|
1480
1579
|
* Walk the parsed submission and collect features that the active managed
|
|
1481
|
-
* runtime cannot serve. Provider-hosted skill refs (`
|
|
1580
|
+
* runtime cannot serve. Provider-hosted skill refs (`kind:"provider"`) are
|
|
1482
1581
|
* rejected now that new submissions only dispatch through managed runs.
|
|
1483
1582
|
*/
|
|
1484
1583
|
export function collectManagedUnsupportedFeatures(req) {
|
|
1485
1584
|
const features = [];
|
|
1486
1585
|
for (const skill of req.submission.skills) {
|
|
1487
1586
|
if (skill.kind === "provider") {
|
|
1488
|
-
const versionSuffix = skill.version ?
|
|
1489
|
-
features.push(`
|
|
1587
|
+
const versionSuffix = skill.version ? `@${skill.version}` : "";
|
|
1588
|
+
features.push(`provider skill "${skill.vendor}/${skill.skillId}${versionSuffix}" (kind:"provider")`);
|
|
1490
1589
|
}
|
|
1491
1590
|
}
|
|
1492
1591
|
return features;
|
package/dist/agents-md.d.ts
CHANGED
|
@@ -5,9 +5,9 @@ import type { AgentsMdRef } from "./_contracts/index.js";
|
|
|
5
5
|
* behaviour).
|
|
6
6
|
*
|
|
7
7
|
* const rules = await AgentsMd.fromContent("# Be helpful", { name: "rules" });
|
|
8
|
-
* await client.
|
|
8
|
+
* await client.submit({ agentsMd: [rules], ... });
|
|
9
9
|
*
|
|
10
|
-
* `client.
|
|
10
|
+
* `client.submit` materializes the bytes to the hosted asset store before
|
|
11
11
|
* the run lands. Asset deduplication handles repeated uploads automatically.
|
|
12
12
|
*/
|
|
13
13
|
export declare class AgentsMd {
|
|
@@ -30,7 +30,7 @@ export declare class AgentsMd {
|
|
|
30
30
|
}): Promise<AgentsMd>;
|
|
31
31
|
/**
|
|
32
32
|
* Internal: yield the draft's zipped bytes + metadata so
|
|
33
|
-
* `client.
|
|
33
|
+
* `client.submit` can upload it as an asset.
|
|
34
34
|
*/
|
|
35
35
|
_takeDraftBundle(): {
|
|
36
36
|
name: string;
|
package/dist/agents-md.js
CHANGED
|
@@ -7,9 +7,9 @@ import { strToU8, zipSync } from "fflate";
|
|
|
7
7
|
* behaviour).
|
|
8
8
|
*
|
|
9
9
|
* const rules = await AgentsMd.fromContent("# Be helpful", { name: "rules" });
|
|
10
|
-
* await client.
|
|
10
|
+
* await client.submit({ agentsMd: [rules], ... });
|
|
11
11
|
*
|
|
12
|
-
* `client.
|
|
12
|
+
* `client.submit` materializes the bytes to the hosted asset store before
|
|
13
13
|
* the run lands. Asset deduplication handles repeated uploads automatically.
|
|
14
14
|
*/
|
|
15
15
|
export class AgentsMd {
|
|
@@ -53,12 +53,12 @@ export class AgentsMd {
|
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* Internal: yield the draft's zipped bytes + metadata so
|
|
56
|
-
* `client.
|
|
56
|
+
* `client.submit` can upload it as an asset.
|
|
57
57
|
*/
|
|
58
58
|
_takeDraftBundle() {
|
|
59
59
|
if (this.#consumed) {
|
|
60
|
-
throw new Error("AgentsMd: cannot reuse a consumed AgentsMd in
|
|
61
|
-
"via AgentsMd.fromContent(...) / AgentsMd.fromPath(...) per
|
|
60
|
+
throw new Error("AgentsMd: cannot reuse a consumed AgentsMd in submit. Build a fresh one " +
|
|
61
|
+
"via AgentsMd.fromContent(...) / AgentsMd.fromPath(...) per submit call.");
|
|
62
62
|
}
|
|
63
63
|
if (this.#ref.kind !== "draft" || !this.#zipBytes) {
|
|
64
64
|
return undefined;
|
|
@@ -73,7 +73,7 @@ export class AgentsMd {
|
|
|
73
73
|
toJSON() {
|
|
74
74
|
if (this.#ref.kind === "draft") {
|
|
75
75
|
throw new Error("AgentsMd: draft AgentsMd cannot be JSON-serialised — it only becomes a wire " +
|
|
76
|
-
"ref when client.
|
|
76
|
+
"ref when client.submit uploads the bytes as an asset.");
|
|
77
77
|
}
|
|
78
78
|
return this.#ref;
|
|
79
79
|
}
|
package/dist/agents-md.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-md.js","sourceRoot":"","sources":["../src/agents-md.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAE1C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,QAAQ;IACV,IAAI,CAAiC;IACrC,SAAS,CAAyB;IAC3C,SAAS,GAAG,KAAK,CAAC;IAElB,YAAY,GAAmC,EAAE,QAAqB;QACpE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;IACvD,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,IAA+B;QACvE,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACjF,MAAM,IAAI,KAAK,CAAC,yCAAyC,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7F,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAqB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC;QAC9E,OAAO,IAAI,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,6DAA6D;IAC7D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAA+B;QACjE,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACH,gBAAgB;QACd,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,
|
|
1
|
+
{"version":3,"file":"agents-md.js","sourceRoot":"","sources":["../src/agents-md.ts"],"names":[],"mappings":"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"}
|