@aexhq/sdk 0.16.0 → 0.17.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 +11 -8
- package/dist/_contracts/index.d.ts +2 -0
- package/dist/_contracts/index.js +2 -0
- package/dist/_contracts/internal.d.ts +2 -0
- package/dist/_contracts/internal.js +2 -0
- package/dist/_contracts/managed-key.d.ts +3 -2
- package/dist/_contracts/models.d.ts +113 -0
- package/dist/_contracts/models.js +127 -0
- package/dist/_contracts/post-hook.d.ts +28 -0
- package/dist/_contracts/post-hook.js +68 -0
- package/dist/_contracts/run-config.d.ts +15 -17
- package/dist/_contracts/run-config.js +17 -19
- package/dist/_contracts/run-unit.d.ts +4 -4
- package/dist/_contracts/run-unit.js +17 -6
- package/dist/_contracts/submission.d.ts +46 -12
- package/dist/_contracts/submission.js +40 -4
- package/dist/cli.mjs +201 -35
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +28 -13
- package/dist/client.js +19 -2
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/cleanup.md +3 -1
- package/docs/credentials.md +3 -3
- package/docs/outputs.md +3 -1
- package/docs/provider-runtime-capabilities.md +1 -1
- package/docs/quickstart.md +17 -7
- package/docs/run-config.md +12 -7
- package/docs/skills.md +102 -117
- package/docs/testing.md +9 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,7 +9,8 @@ aex is a TypeScript-first SDK + CLI for running autonomous agent sessions across
|
|
|
9
9
|
```ts
|
|
10
10
|
import {
|
|
11
11
|
AgentExecutor, // the only client class — submits durable runs to aex
|
|
12
|
-
|
|
12
|
+
RunModels, // closed public model id constants
|
|
13
|
+
Skill, // local, URL, and catalog skill bundles normalized to assets
|
|
13
14
|
McpServer, // MCP server declarations (headers split into secrets server-side)
|
|
14
15
|
ProxyEndpoint, // per-run managed HTTP proxy endpoint
|
|
15
16
|
AgentsMd, // AGENTS.md / CLAUDE.md uploads
|
|
@@ -55,15 +56,15 @@ The aex URL defaults to `https://api.aex.dev`. Set `--aex-url` on the CLI or `ba
|
|
|
55
56
|
## Quickstart (SDK)
|
|
56
57
|
|
|
57
58
|
```ts
|
|
58
|
-
import { AgentExecutor } from "@aexhq/sdk";
|
|
59
|
+
import { AgentExecutor, RunModels } from "@aexhq/sdk";
|
|
59
60
|
|
|
60
61
|
const aex = new AgentExecutor({
|
|
61
|
-
apiToken: process.env.AEX_API_TOKEN
|
|
62
|
+
apiToken: process.env.AEX_API_TOKEN!,
|
|
62
63
|
// baseUrl defaults to https://api.aex.dev - set it for local or staging planes.
|
|
63
64
|
});
|
|
64
65
|
|
|
65
66
|
const runId = await aex.submitRun({
|
|
66
|
-
model:
|
|
67
|
+
model: RunModels.CLAUDE_HAIKU_4_5,
|
|
67
68
|
system: "You are a concise automation agent.",
|
|
68
69
|
prompt: "Write a short answer about agent-first SDK design.",
|
|
69
70
|
secrets: { apiKey: process.env.ANTHROPIC_API_KEY! }
|
|
@@ -87,9 +88,9 @@ Reusable, credential-free configs can be ordinary functions:
|
|
|
87
88
|
```ts
|
|
88
89
|
function summarise(topic: string) {
|
|
89
90
|
return {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
model: RunModels.CLAUDE_HAIKU_4_5,
|
|
92
|
+
system: "You are a concise automation agent.",
|
|
93
|
+
prompt: `Write a short answer about ${topic}.`
|
|
93
94
|
};
|
|
94
95
|
}
|
|
95
96
|
|
|
@@ -127,7 +128,9 @@ aex run \
|
|
|
127
128
|
--follow
|
|
128
129
|
```
|
|
129
130
|
|
|
130
|
-
`--config` accepts a plain run-config JSON file for a single run request: `{ model, system?, prompt, skills?, mcpServers?, environment?, proxyEndpoints?, metadata? }`. There is no saved-definition product or interpolation DSL — build the JSON at the call site.
|
|
131
|
+
`--config` accepts a plain run-config JSON file for a single run request: `{ model, system?, prompt, skills?, mcpServers?, environment?, runtimeSize?, timeout?, postHook?, proxyEndpoints?, metadata? }`. There is no saved-definition product or interpolation DSL — build the JSON at the call site. SDK code should use `RunModels`; config JSON is validated against the same `RUN_MODELS` allowlist.
|
|
132
|
+
|
|
133
|
+
Runtime controls: omit `builtins` to use the default `["developer"]` toolkit, pass `builtins: []` to disable builtins for a pure-MCP run, use `outputMode: "stream"` for per-token assistant text, prefer `RuntimeSizes` for `runtimeSize`, and use `postHook` to run a verifier command after the agent exits successfully.
|
|
131
134
|
|
|
132
135
|
## Test commands
|
|
133
136
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./proxy-protocol.js";
|
|
2
2
|
export * from "./provider-support.js";
|
|
3
|
+
export * from "./models.js";
|
|
3
4
|
export * from "./status.js";
|
|
4
5
|
export * from "./submission.js";
|
|
5
6
|
export * from "./runtime-sizes.js";
|
|
7
|
+
export * from "./post-hook.js";
|
|
6
8
|
export * from "./runner-event.js";
|
|
7
9
|
export * from "./event-envelope.js";
|
|
8
10
|
export * from "./connection-ticket.js";
|
package/dist/_contracts/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./proxy-protocol.js";
|
|
2
2
|
export * from "./provider-support.js";
|
|
3
|
+
export * from "./models.js";
|
|
3
4
|
export * from "./status.js";
|
|
4
5
|
export * from "./submission.js";
|
|
5
6
|
export * from "./runtime-sizes.js";
|
|
7
|
+
export * from "./post-hook.js";
|
|
6
8
|
export * from "./runner-event.js";
|
|
7
9
|
export * from "./event-envelope.js";
|
|
8
10
|
export * from "./connection-ticket.js";
|
|
@@ -4,5 +4,7 @@
|
|
|
4
4
|
// of validator code. NOT part of the public `@aexhq/contracts` surface — do
|
|
5
5
|
// NOT add this to the package `index`; consumers reach it via the explicit
|
|
6
6
|
// `@aexhq/contracts/internal` subpath.
|
|
7
|
+
export * from "./models.js";
|
|
8
|
+
export * from "./post-hook.js";
|
|
7
9
|
export * from "./submission.js";
|
|
8
10
|
//# sourceMappingURL=internal.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RunProvider, RuntimeKind } from "./submission.js";
|
|
2
|
+
import type { RunModel } from "./models.js";
|
|
2
3
|
export declare const CREDENTIAL_MODES: readonly ["byok", "managed"];
|
|
3
4
|
export type CredentialMode = (typeof CREDENTIAL_MODES)[number];
|
|
4
5
|
export declare const DEFAULT_CREDENTIAL_MODE: CredentialMode;
|
|
@@ -31,7 +32,7 @@ export interface ManagedKeyPolicyV1 {
|
|
|
31
32
|
readonly billingRequired: true;
|
|
32
33
|
readonly providers: readonly RunProvider[];
|
|
33
34
|
readonly runtimes: readonly RuntimeKind[];
|
|
34
|
-
readonly models?: readonly
|
|
35
|
+
readonly models?: readonly RunModel[];
|
|
35
36
|
readonly features: ManagedKeyFeaturePolicyV1;
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
@@ -75,7 +76,7 @@ export interface ManagedCredentialResolutionInput {
|
|
|
75
76
|
readonly runId: string;
|
|
76
77
|
readonly provider: RunProvider;
|
|
77
78
|
readonly runtime: RuntimeKind;
|
|
78
|
-
readonly model:
|
|
79
|
+
readonly model: RunModel;
|
|
79
80
|
readonly policy: ManagedKeyPolicyV1;
|
|
80
81
|
}
|
|
81
82
|
export interface ManagedCredentialLease {
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { RunProvider } from "./submission.js";
|
|
2
|
+
/**
|
|
3
|
+
* Closed set of model ids accepted by the public run-submission schema.
|
|
4
|
+
*
|
|
5
|
+
* The provider-proxy still sends the model id through to the selected upstream
|
|
6
|
+
* provider, but callers cannot submit arbitrary strings. Additions belong here
|
|
7
|
+
* first so SDK types, CLI validation, docs examples, and platform parsing move
|
|
8
|
+
* together.
|
|
9
|
+
*/
|
|
10
|
+
export declare const RUN_MODELS: readonly ["claude-haiku-4-5", "claude-3-5-haiku-latest", "claude-3-5-sonnet-latest", "deepseek-v4-flash", "deepseek-v4-pro", "deepseek-chat", "deepseek-reasoner", "gpt-4.1", "gpt-4o-mini", "gemini-2.0-flash", "gemini-2.5-flash", "mistral-large-latest", "mistral-small-latest"];
|
|
11
|
+
export type RunModel = (typeof RUN_MODELS)[number];
|
|
12
|
+
/**
|
|
13
|
+
* Symbol-style accessors for the closed model set. Prefer these over raw
|
|
14
|
+
* strings so an invalid token is a compile error, not a runtime 400 — e.g.
|
|
15
|
+
* `Models.CLAUDE_HAIKU_4_5`. The upstream provider is a pure function of the
|
|
16
|
+
* model ({@link providerForModel}), so picking a model fully determines
|
|
17
|
+
* routing; callers never pass `provider` separately.
|
|
18
|
+
*/
|
|
19
|
+
export declare const Models: {
|
|
20
|
+
/** Claude Haiku 4.5 — Anthropic. */
|
|
21
|
+
readonly CLAUDE_HAIKU_4_5: "claude-haiku-4-5";
|
|
22
|
+
/** Claude 3.5 Haiku (latest) — Anthropic. */
|
|
23
|
+
readonly CLAUDE_3_5_HAIKU_LATEST: "claude-3-5-haiku-latest";
|
|
24
|
+
/** Claude 3.5 Sonnet (latest) — Anthropic. */
|
|
25
|
+
readonly CLAUDE_3_5_SONNET_LATEST: "claude-3-5-sonnet-latest";
|
|
26
|
+
/** DeepSeek V4 Flash — DeepSeek (non-thinking, fast). */
|
|
27
|
+
readonly DEEPSEEK_V4_FLASH: "deepseek-v4-flash";
|
|
28
|
+
/** DeepSeek V4 Pro — DeepSeek (reasoning-heavy). */
|
|
29
|
+
readonly DEEPSEEK_V4_PRO: "deepseek-v4-pro";
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Legacy alias DeepSeek routes to `deepseek-v4-flash` (non-thinking).
|
|
32
|
+
* DeepSeek removes this name on 2026-07-24 15:59 UTC — migrate to
|
|
33
|
+
* {@link Models.DEEPSEEK_V4_FLASH}.
|
|
34
|
+
*/
|
|
35
|
+
readonly DEEPSEEK_CHAT: "deepseek-chat";
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Legacy alias DeepSeek routes to `deepseek-v4-flash` (thinking).
|
|
38
|
+
* DeepSeek removes this name on 2026-07-24 15:59 UTC — migrate to
|
|
39
|
+
* {@link Models.DEEPSEEK_V4_FLASH} (or {@link Models.DEEPSEEK_V4_PRO} for
|
|
40
|
+
* heavier reasoning).
|
|
41
|
+
*/
|
|
42
|
+
readonly DEEPSEEK_REASONER: "deepseek-reasoner";
|
|
43
|
+
/** GPT-4.1 — OpenAI. */
|
|
44
|
+
readonly GPT_4_1: "gpt-4.1";
|
|
45
|
+
/** GPT-4o mini — OpenAI. */
|
|
46
|
+
readonly GPT_4O_MINI: "gpt-4o-mini";
|
|
47
|
+
/** Gemini 2.0 Flash — Gemini. */
|
|
48
|
+
readonly GEMINI_2_0_FLASH: "gemini-2.0-flash";
|
|
49
|
+
/** Gemini 2.5 Flash — Gemini. */
|
|
50
|
+
readonly GEMINI_2_5_FLASH: "gemini-2.5-flash";
|
|
51
|
+
/** Mistral Large (latest) — Mistral. */
|
|
52
|
+
readonly MISTRAL_LARGE_LATEST: "mistral-large-latest";
|
|
53
|
+
/** Mistral Small (latest) — Mistral. */
|
|
54
|
+
readonly MISTRAL_SMALL_LATEST: "mistral-small-latest";
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Back-compat alias for {@link Models}. Existing imports of `RunModels`
|
|
58
|
+
* keep working; new code should prefer `Models`.
|
|
59
|
+
*/
|
|
60
|
+
export declare const RunModels: {
|
|
61
|
+
/** Claude Haiku 4.5 — Anthropic. */
|
|
62
|
+
readonly CLAUDE_HAIKU_4_5: "claude-haiku-4-5";
|
|
63
|
+
/** Claude 3.5 Haiku (latest) — Anthropic. */
|
|
64
|
+
readonly CLAUDE_3_5_HAIKU_LATEST: "claude-3-5-haiku-latest";
|
|
65
|
+
/** Claude 3.5 Sonnet (latest) — Anthropic. */
|
|
66
|
+
readonly CLAUDE_3_5_SONNET_LATEST: "claude-3-5-sonnet-latest";
|
|
67
|
+
/** DeepSeek V4 Flash — DeepSeek (non-thinking, fast). */
|
|
68
|
+
readonly DEEPSEEK_V4_FLASH: "deepseek-v4-flash";
|
|
69
|
+
/** DeepSeek V4 Pro — DeepSeek (reasoning-heavy). */
|
|
70
|
+
readonly DEEPSEEK_V4_PRO: "deepseek-v4-pro";
|
|
71
|
+
/**
|
|
72
|
+
* @deprecated Legacy alias DeepSeek routes to `deepseek-v4-flash` (non-thinking).
|
|
73
|
+
* DeepSeek removes this name on 2026-07-24 15:59 UTC — migrate to
|
|
74
|
+
* {@link Models.DEEPSEEK_V4_FLASH}.
|
|
75
|
+
*/
|
|
76
|
+
readonly DEEPSEEK_CHAT: "deepseek-chat";
|
|
77
|
+
/**
|
|
78
|
+
* @deprecated Legacy alias DeepSeek routes to `deepseek-v4-flash` (thinking).
|
|
79
|
+
* DeepSeek removes this name on 2026-07-24 15:59 UTC — migrate to
|
|
80
|
+
* {@link Models.DEEPSEEK_V4_FLASH} (or {@link Models.DEEPSEEK_V4_PRO} for
|
|
81
|
+
* heavier reasoning).
|
|
82
|
+
*/
|
|
83
|
+
readonly DEEPSEEK_REASONER: "deepseek-reasoner";
|
|
84
|
+
/** GPT-4.1 — OpenAI. */
|
|
85
|
+
readonly GPT_4_1: "gpt-4.1";
|
|
86
|
+
/** GPT-4o mini — OpenAI. */
|
|
87
|
+
readonly GPT_4O_MINI: "gpt-4o-mini";
|
|
88
|
+
/** Gemini 2.0 Flash — Gemini. */
|
|
89
|
+
readonly GEMINI_2_0_FLASH: "gemini-2.0-flash";
|
|
90
|
+
/** Gemini 2.5 Flash — Gemini. */
|
|
91
|
+
readonly GEMINI_2_5_FLASH: "gemini-2.5-flash";
|
|
92
|
+
/** Mistral Large (latest) — Mistral. */
|
|
93
|
+
readonly MISTRAL_LARGE_LATEST: "mistral-large-latest";
|
|
94
|
+
/** Mistral Small (latest) — Mistral. */
|
|
95
|
+
readonly MISTRAL_SMALL_LATEST: "mistral-small-latest";
|
|
96
|
+
};
|
|
97
|
+
export declare const RUN_MODELS_BY_PROVIDER: {
|
|
98
|
+
readonly anthropic: readonly ["claude-haiku-4-5", "claude-3-5-haiku-latest", "claude-3-5-sonnet-latest"];
|
|
99
|
+
readonly deepseek: readonly ["deepseek-v4-flash", "deepseek-v4-pro", "deepseek-chat", "deepseek-reasoner"];
|
|
100
|
+
readonly openai: readonly ["gpt-4.1", "gpt-4o-mini"];
|
|
101
|
+
readonly gemini: readonly ["gemini-2.0-flash", "gemini-2.5-flash"];
|
|
102
|
+
readonly mistral: readonly ["mistral-large-latest", "mistral-small-latest"];
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Resolve the upstream provider for a model id. Returns `undefined` when the
|
|
106
|
+
* input is not a known {@link RunModel} (so the SDK can fall back to the
|
|
107
|
+
* default and let the server reject the model). Total over the closed model
|
|
108
|
+
* set, so any `RunModel` resolves.
|
|
109
|
+
*/
|
|
110
|
+
export declare function providerForModel(model: string): RunProvider | undefined;
|
|
111
|
+
export declare function isRunModel(input: unknown): input is RunModel;
|
|
112
|
+
export declare function parseRunModel(input: unknown, field?: string): RunModel;
|
|
113
|
+
export declare function assertRunModelMatchesProvider(provider: RunProvider, model: RunModel, field?: string): void;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Closed set of model ids accepted by the public run-submission schema.
|
|
3
|
+
*
|
|
4
|
+
* The provider-proxy still sends the model id through to the selected upstream
|
|
5
|
+
* provider, but callers cannot submit arbitrary strings. Additions belong here
|
|
6
|
+
* first so SDK types, CLI validation, docs examples, and platform parsing move
|
|
7
|
+
* together.
|
|
8
|
+
*/
|
|
9
|
+
export const RUN_MODELS = [
|
|
10
|
+
"claude-haiku-4-5",
|
|
11
|
+
"claude-3-5-haiku-latest",
|
|
12
|
+
"claude-3-5-sonnet-latest",
|
|
13
|
+
"deepseek-v4-flash",
|
|
14
|
+
"deepseek-v4-pro",
|
|
15
|
+
"deepseek-chat",
|
|
16
|
+
"deepseek-reasoner",
|
|
17
|
+
"gpt-4.1",
|
|
18
|
+
"gpt-4o-mini",
|
|
19
|
+
"gemini-2.0-flash",
|
|
20
|
+
"gemini-2.5-flash",
|
|
21
|
+
"mistral-large-latest",
|
|
22
|
+
"mistral-small-latest"
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Symbol-style accessors for the closed model set. Prefer these over raw
|
|
26
|
+
* strings so an invalid token is a compile error, not a runtime 400 — e.g.
|
|
27
|
+
* `Models.CLAUDE_HAIKU_4_5`. The upstream provider is a pure function of the
|
|
28
|
+
* model ({@link providerForModel}), so picking a model fully determines
|
|
29
|
+
* routing; callers never pass `provider` separately.
|
|
30
|
+
*/
|
|
31
|
+
export const Models = {
|
|
32
|
+
/** Claude Haiku 4.5 — Anthropic. */
|
|
33
|
+
CLAUDE_HAIKU_4_5: "claude-haiku-4-5",
|
|
34
|
+
/** Claude 3.5 Haiku (latest) — Anthropic. */
|
|
35
|
+
CLAUDE_3_5_HAIKU_LATEST: "claude-3-5-haiku-latest",
|
|
36
|
+
/** Claude 3.5 Sonnet (latest) — Anthropic. */
|
|
37
|
+
CLAUDE_3_5_SONNET_LATEST: "claude-3-5-sonnet-latest",
|
|
38
|
+
/** DeepSeek V4 Flash — DeepSeek (non-thinking, fast). */
|
|
39
|
+
DEEPSEEK_V4_FLASH: "deepseek-v4-flash",
|
|
40
|
+
/** DeepSeek V4 Pro — DeepSeek (reasoning-heavy). */
|
|
41
|
+
DEEPSEEK_V4_PRO: "deepseek-v4-pro",
|
|
42
|
+
/**
|
|
43
|
+
* @deprecated Legacy alias DeepSeek routes to `deepseek-v4-flash` (non-thinking).
|
|
44
|
+
* DeepSeek removes this name on 2026-07-24 15:59 UTC — migrate to
|
|
45
|
+
* {@link Models.DEEPSEEK_V4_FLASH}.
|
|
46
|
+
*/
|
|
47
|
+
DEEPSEEK_CHAT: "deepseek-chat",
|
|
48
|
+
/**
|
|
49
|
+
* @deprecated Legacy alias DeepSeek routes to `deepseek-v4-flash` (thinking).
|
|
50
|
+
* DeepSeek removes this name on 2026-07-24 15:59 UTC — migrate to
|
|
51
|
+
* {@link Models.DEEPSEEK_V4_FLASH} (or {@link Models.DEEPSEEK_V4_PRO} for
|
|
52
|
+
* heavier reasoning).
|
|
53
|
+
*/
|
|
54
|
+
DEEPSEEK_REASONER: "deepseek-reasoner",
|
|
55
|
+
/** GPT-4.1 — OpenAI. */
|
|
56
|
+
GPT_4_1: "gpt-4.1",
|
|
57
|
+
/** GPT-4o mini — OpenAI. */
|
|
58
|
+
GPT_4O_MINI: "gpt-4o-mini",
|
|
59
|
+
/** Gemini 2.0 Flash — Gemini. */
|
|
60
|
+
GEMINI_2_0_FLASH: "gemini-2.0-flash",
|
|
61
|
+
/** Gemini 2.5 Flash — Gemini. */
|
|
62
|
+
GEMINI_2_5_FLASH: "gemini-2.5-flash",
|
|
63
|
+
/** Mistral Large (latest) — Mistral. */
|
|
64
|
+
MISTRAL_LARGE_LATEST: "mistral-large-latest",
|
|
65
|
+
/** Mistral Small (latest) — Mistral. */
|
|
66
|
+
MISTRAL_SMALL_LATEST: "mistral-small-latest"
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Back-compat alias for {@link Models}. Existing imports of `RunModels`
|
|
70
|
+
* keep working; new code should prefer `Models`.
|
|
71
|
+
*/
|
|
72
|
+
export const RunModels = Models;
|
|
73
|
+
export const RUN_MODELS_BY_PROVIDER = {
|
|
74
|
+
anthropic: [
|
|
75
|
+
Models.CLAUDE_HAIKU_4_5,
|
|
76
|
+
Models.CLAUDE_3_5_HAIKU_LATEST,
|
|
77
|
+
Models.CLAUDE_3_5_SONNET_LATEST
|
|
78
|
+
],
|
|
79
|
+
deepseek: [
|
|
80
|
+
Models.DEEPSEEK_V4_FLASH,
|
|
81
|
+
Models.DEEPSEEK_V4_PRO,
|
|
82
|
+
Models.DEEPSEEK_CHAT,
|
|
83
|
+
Models.DEEPSEEK_REASONER
|
|
84
|
+
],
|
|
85
|
+
openai: [Models.GPT_4_1, Models.GPT_4O_MINI],
|
|
86
|
+
gemini: [Models.GEMINI_2_0_FLASH, Models.GEMINI_2_5_FLASH],
|
|
87
|
+
mistral: [Models.MISTRAL_LARGE_LATEST, Models.MISTRAL_SMALL_LATEST]
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Reverse index: every model id → its single upstream provider. Derived from
|
|
91
|
+
* {@link RUN_MODELS_BY_PROVIDER} so the two never drift; each model appears
|
|
92
|
+
* under exactly one provider.
|
|
93
|
+
*/
|
|
94
|
+
const PROVIDER_BY_MODEL = (() => {
|
|
95
|
+
const map = {};
|
|
96
|
+
for (const [provider, models] of Object.entries(RUN_MODELS_BY_PROVIDER)) {
|
|
97
|
+
for (const model of models) {
|
|
98
|
+
map[model] = provider;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return map;
|
|
102
|
+
})();
|
|
103
|
+
/**
|
|
104
|
+
* Resolve the upstream provider for a model id. Returns `undefined` when the
|
|
105
|
+
* input is not a known {@link RunModel} (so the SDK can fall back to the
|
|
106
|
+
* default and let the server reject the model). Total over the closed model
|
|
107
|
+
* set, so any `RunModel` resolves.
|
|
108
|
+
*/
|
|
109
|
+
export function providerForModel(model) {
|
|
110
|
+
return PROVIDER_BY_MODEL[model];
|
|
111
|
+
}
|
|
112
|
+
export function isRunModel(input) {
|
|
113
|
+
return typeof input === "string" && RUN_MODELS.includes(input);
|
|
114
|
+
}
|
|
115
|
+
export function parseRunModel(input, field = "submission.model") {
|
|
116
|
+
if (!isRunModel(input)) {
|
|
117
|
+
throw new Error(`${field} must be one of: ${RUN_MODELS.join(", ")}`);
|
|
118
|
+
}
|
|
119
|
+
return input;
|
|
120
|
+
}
|
|
121
|
+
export function assertRunModelMatchesProvider(provider, model, field = "submission.model") {
|
|
122
|
+
if (!RUN_MODELS_BY_PROVIDER[provider].includes(model)) {
|
|
123
|
+
throw new Error(`${field} ${JSON.stringify(model)} is not supported for provider ${provider}; ` +
|
|
124
|
+
`expected one of: ${RUN_MODELS_BY_PROVIDER[provider].join(", ")}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Default post-agent-run hook timeout (5 minutes). */
|
|
2
|
+
export declare const DEFAULT_POST_HOOK_TIMEOUT_MS: number;
|
|
3
|
+
/** Default number of repair turns after a failing hook. */
|
|
4
|
+
export declare const DEFAULT_POST_HOOK_MAX_TURNS = 10;
|
|
5
|
+
/**
|
|
6
|
+
* Customer-facing post-agent-run verifier shape. The SDK and run-config JSON
|
|
7
|
+
* send this form on the wire; the server parser normalizes it to
|
|
8
|
+
* {@link PlatformPostHook}.
|
|
9
|
+
*/
|
|
10
|
+
export interface PlatformPostHookInput {
|
|
11
|
+
readonly command: string;
|
|
12
|
+
readonly timeout?: string;
|
|
13
|
+
readonly maxTurns?: number;
|
|
14
|
+
readonly maxChars?: number | null;
|
|
15
|
+
}
|
|
16
|
+
/** Parsed post-agent-run verifier carried through dispatch to the runner. */
|
|
17
|
+
export interface PlatformPostHook {
|
|
18
|
+
readonly command: string;
|
|
19
|
+
readonly timeoutMs: number;
|
|
20
|
+
readonly maxTurns: number;
|
|
21
|
+
readonly maxChars: number | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse the public `postHook` option. An omitted hook, null hook, or hook with
|
|
25
|
+
* an empty/whitespace-only command is treated as omitted so callers can pre-fill
|
|
26
|
+
* configs without enabling the verifier accidentally.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parsePostHook(input: unknown, path?: string): PlatformPostHook | undefined;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { parseDurationToMs } from "./runtime-sizes.js";
|
|
2
|
+
/** Default post-agent-run hook timeout (5 minutes). */
|
|
3
|
+
export const DEFAULT_POST_HOOK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
4
|
+
/** Default number of repair turns after a failing hook. */
|
|
5
|
+
export const DEFAULT_POST_HOOK_MAX_TURNS = 10;
|
|
6
|
+
/**
|
|
7
|
+
* Parse the public `postHook` option. An omitted hook, null hook, or hook with
|
|
8
|
+
* an empty/whitespace-only command is treated as omitted so callers can pre-fill
|
|
9
|
+
* configs without enabling the verifier accidentally.
|
|
10
|
+
*/
|
|
11
|
+
export function parsePostHook(input, path = "postHook") {
|
|
12
|
+
if (input === undefined || input === null) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const value = requirePostHookRecord(input, path);
|
|
16
|
+
const allowed = new Set(["command", "timeout", "maxTurns", "maxChars"]);
|
|
17
|
+
for (const key of Object.keys(value)) {
|
|
18
|
+
if (!allowed.has(key)) {
|
|
19
|
+
throw new Error(`${path}.${key} is not an allowed field; permitted: command, timeout, maxTurns, maxChars`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (typeof value.command !== "string") {
|
|
23
|
+
throw new Error(`${path}.command must be a string`);
|
|
24
|
+
}
|
|
25
|
+
if (value.command.trim().length === 0) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const timeoutMs = parsePostHookTimeout(value.timeout, `${path}.timeout`);
|
|
29
|
+
const maxTurns = parseNonNegativeInteger(value.maxTurns, `${path}.maxTurns`, DEFAULT_POST_HOOK_MAX_TURNS);
|
|
30
|
+
const maxChars = value.maxChars === null
|
|
31
|
+
? null
|
|
32
|
+
: parseNonNegativeInteger(value.maxChars, `${path}.maxChars`, null);
|
|
33
|
+
return {
|
|
34
|
+
command: value.command,
|
|
35
|
+
timeoutMs,
|
|
36
|
+
maxTurns,
|
|
37
|
+
maxChars
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function parsePostHookTimeout(input, path) {
|
|
41
|
+
if (input === undefined) {
|
|
42
|
+
return DEFAULT_POST_HOOK_TIMEOUT_MS;
|
|
43
|
+
}
|
|
44
|
+
if (typeof input !== "string") {
|
|
45
|
+
throw new Error(`${path} must be a duration string (e.g. "5m", "30s"); got ${JSON.stringify(input)}`);
|
|
46
|
+
}
|
|
47
|
+
const ms = parseDurationToMs(input);
|
|
48
|
+
if (ms <= 0) {
|
|
49
|
+
throw new Error(`${path} must be greater than 0ms; got ${ms}ms`);
|
|
50
|
+
}
|
|
51
|
+
return ms;
|
|
52
|
+
}
|
|
53
|
+
function parseNonNegativeInteger(input, path, defaultValue) {
|
|
54
|
+
if (input === undefined) {
|
|
55
|
+
return defaultValue;
|
|
56
|
+
}
|
|
57
|
+
if (typeof input !== "number" || !Number.isSafeInteger(input) || input < 0) {
|
|
58
|
+
throw new Error(`${path} must be a non-negative integer`);
|
|
59
|
+
}
|
|
60
|
+
return input;
|
|
61
|
+
}
|
|
62
|
+
function requirePostHookRecord(input, path) {
|
|
63
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
64
|
+
throw new Error(`${path} must be an object`);
|
|
65
|
+
}
|
|
66
|
+
return input;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=post-hook.js.map
|
|
@@ -3,17 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Public composition concepts:
|
|
5
5
|
*
|
|
6
|
-
* - `SkillRef` is the wire-level reference to a skill
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* terminal). The three shapes are discriminated by `kind` so
|
|
12
|
-
* consumers branch mechanically and providers can never accidentally
|
|
13
|
-
* be looked up in `skill_bundles`. Transient refs do NOT round-trip
|
|
14
|
-
* through JSON (bytes can't be serialised back); `parseRunRequestConfig`
|
|
15
|
-
* therefore rejects them while the BFF multipart submission parser
|
|
16
|
-
* accepts them.
|
|
6
|
+
* - `SkillRef` is the wire-level reference to a skill. Public run
|
|
7
|
+
* configs use storage-neutral `kind:"asset"` refs produced by the SDK
|
|
8
|
+
* upload path or by workspace catalog records. Provider skill refs remain
|
|
9
|
+
* in the parser for wire compatibility, but the managed runtime rejects
|
|
10
|
+
* them at submission time.
|
|
17
11
|
*
|
|
18
12
|
* - `McpServerRef` is the non-secret part of an MCP server declaration:
|
|
19
13
|
* `name` and `url`. Bearer / cookie / per-request headers travel in
|
|
@@ -37,7 +31,9 @@
|
|
|
37
31
|
* boundary.
|
|
38
32
|
*/
|
|
39
33
|
import type { JsonValue, PlatformProxyEndpoint, PlatformEnvironment } from "./submission.js";
|
|
34
|
+
import { type RunModel } from "./models.js";
|
|
40
35
|
import type { RuntimeSize } from "./runtime-sizes.js";
|
|
36
|
+
import { type PlatformPostHookInput } from "./post-hook.js";
|
|
41
37
|
/**
|
|
42
38
|
* Mirrors the server-side CHECK constraint
|
|
43
39
|
* `skill_bundles_id_format_chk = check (id ~ '^skl_[A-Za-z0-9_-]{8,128}$')`
|
|
@@ -62,10 +58,9 @@ export declare const SKILL_BUNDLE_LIMITS: {
|
|
|
62
58
|
/** Compressed (.zip) ceiling. */
|
|
63
59
|
readonly maxCompressedBytes: number;
|
|
64
60
|
/**
|
|
65
|
-
* Hard ceiling for the direct-to-storage
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* limit; objects above this would need S3 multipart, which is out of scope.
|
|
61
|
+
* Hard ceiling for the direct-to-storage upload path. Bytes never transit the
|
|
62
|
+
* hosted API, so its memory/request-payload limits do not cap accepted
|
|
63
|
+
* bundles; objects above this product cap are rejected before upload.
|
|
69
64
|
*/
|
|
70
65
|
readonly maxBytes: number;
|
|
71
66
|
/** Sum of uncompressed file sizes. */
|
|
@@ -259,7 +254,7 @@ export declare function rejectStdioMcpShape(record: Record<string, unknown>): vo
|
|
|
259
254
|
* into the normal `submitRun` request.
|
|
260
255
|
*/
|
|
261
256
|
export interface RunRequestConfig {
|
|
262
|
-
readonly model:
|
|
257
|
+
readonly model: RunModel;
|
|
263
258
|
readonly system?: string;
|
|
264
259
|
readonly prompt: string | readonly string[];
|
|
265
260
|
readonly skills?: readonly SkillRef[];
|
|
@@ -269,6 +264,8 @@ export interface RunRequestConfig {
|
|
|
269
264
|
readonly runtimeSize?: RuntimeSize;
|
|
270
265
|
/** Run deadline as a duration string (`"1h"`, `"30m"`); bounded [1m, 6h] server-side. */
|
|
271
266
|
readonly timeout?: string;
|
|
267
|
+
/** Post-agent-run verifier command. Empty command is treated as omitted. */
|
|
268
|
+
readonly postHook?: PlatformPostHookInput;
|
|
272
269
|
readonly proxyEndpoints?: readonly PlatformProxyEndpoint[];
|
|
273
270
|
readonly metadata?: Readonly<Record<string, JsonValue>>;
|
|
274
271
|
}
|
|
@@ -290,7 +287,7 @@ export declare function parseRunRequestConfig(input: unknown): RunRequestConfig;
|
|
|
290
287
|
* the audit log don't have to re-handle two shapes.
|
|
291
288
|
*/
|
|
292
289
|
export interface NormalisedRunRequestConfig {
|
|
293
|
-
readonly model:
|
|
290
|
+
readonly model: RunModel;
|
|
294
291
|
readonly system?: string;
|
|
295
292
|
readonly prompt: readonly string[];
|
|
296
293
|
readonly skills: readonly SkillRef[];
|
|
@@ -298,6 +295,7 @@ export interface NormalisedRunRequestConfig {
|
|
|
298
295
|
readonly environment?: PlatformEnvironment;
|
|
299
296
|
readonly proxyEndpoints?: readonly PlatformProxyEndpoint[];
|
|
300
297
|
readonly metadata?: Readonly<Record<string, JsonValue>>;
|
|
298
|
+
readonly postHook?: PlatformPostHookInput;
|
|
301
299
|
/**
|
|
302
300
|
* MCP servers whose run-config entry carried `headers`. Keyed by the `name`
|
|
303
301
|
* that appears in `mcpServers` so the BFF can pair them up.
|
|
@@ -3,17 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Public composition concepts:
|
|
5
5
|
*
|
|
6
|
-
* - `SkillRef` is the wire-level reference to a skill
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* terminal). The three shapes are discriminated by `kind` so
|
|
12
|
-
* consumers branch mechanically and providers can never accidentally
|
|
13
|
-
* be looked up in `skill_bundles`. Transient refs do NOT round-trip
|
|
14
|
-
* through JSON (bytes can't be serialised back); `parseRunRequestConfig`
|
|
15
|
-
* therefore rejects them while the BFF multipart submission parser
|
|
16
|
-
* accepts them.
|
|
6
|
+
* - `SkillRef` is the wire-level reference to a skill. Public run
|
|
7
|
+
* configs use storage-neutral `kind:"asset"` refs produced by the SDK
|
|
8
|
+
* upload path or by workspace catalog records. Provider skill refs remain
|
|
9
|
+
* in the parser for wire compatibility, but the managed runtime rejects
|
|
10
|
+
* them at submission time.
|
|
17
11
|
*
|
|
18
12
|
* - `McpServerRef` is the non-secret part of an MCP server declaration:
|
|
19
13
|
* `name` and `url`. Bearer / cookie / per-request headers travel in
|
|
@@ -36,6 +30,8 @@
|
|
|
36
30
|
* Keep this as the public source of truth for the SDK/CLI composition
|
|
37
31
|
* boundary.
|
|
38
32
|
*/
|
|
33
|
+
import { parseRunModel } from "./models.js";
|
|
34
|
+
import { parsePostHook } from "./post-hook.js";
|
|
39
35
|
// ---------------------------------------------------------------------------
|
|
40
36
|
// Skill ID + name format
|
|
41
37
|
// ---------------------------------------------------------------------------
|
|
@@ -66,10 +62,9 @@ export const SKILL_BUNDLE_LIMITS = {
|
|
|
66
62
|
/** Compressed (.zip) ceiling. */
|
|
67
63
|
maxCompressedBytes: 10 * 1024 * 1024,
|
|
68
64
|
/**
|
|
69
|
-
* Hard ceiling for the direct-to-storage
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* limit; objects above this would need S3 multipart, which is out of scope.
|
|
65
|
+
* Hard ceiling for the direct-to-storage upload path. Bytes never transit the
|
|
66
|
+
* hosted API, so its memory/request-payload limits do not cap accepted
|
|
67
|
+
* bundles; objects above this product cap are rejected before upload.
|
|
73
68
|
*/
|
|
74
69
|
maxBytes: 2 * 1024 * 1024 * 1024,
|
|
75
70
|
/** Sum of uncompressed file sizes. */
|
|
@@ -609,6 +604,7 @@ export function parseRunRequestConfig(input) {
|
|
|
609
604
|
"environment",
|
|
610
605
|
"runtimeSize",
|
|
611
606
|
"timeout",
|
|
607
|
+
"postHook",
|
|
612
608
|
"proxyEndpoints",
|
|
613
609
|
"metadata"
|
|
614
610
|
]);
|
|
@@ -617,10 +613,7 @@ export function parseRunRequestConfig(input) {
|
|
|
617
613
|
throw new Error(`run request config contains unexpected field: ${key}`);
|
|
618
614
|
}
|
|
619
615
|
}
|
|
620
|
-
const model = record.model;
|
|
621
|
-
if (typeof model !== "string" || model.length === 0) {
|
|
622
|
-
throw new Error("run request config model must be a non-empty string");
|
|
623
|
-
}
|
|
616
|
+
const model = parseRunModel(record.model, "run request config model");
|
|
624
617
|
const system = record.system;
|
|
625
618
|
if (system !== undefined && typeof system !== "string") {
|
|
626
619
|
throw new Error("run request config system, when provided, must be a string");
|
|
@@ -628,6 +621,7 @@ export function parseRunRequestConfig(input) {
|
|
|
628
621
|
const prompt = parseRunRequestConfigPrompt(record.prompt);
|
|
629
622
|
const skills = parseRunRequestConfigSkills(record.skills);
|
|
630
623
|
const mcpServers = parseRunRequestConfigMcpServers(record.mcpServers);
|
|
624
|
+
const postHook = parsePostHook(record.postHook, "run request config postHook");
|
|
631
625
|
return {
|
|
632
626
|
model,
|
|
633
627
|
...(system !== undefined ? { system } : {}),
|
|
@@ -647,6 +641,9 @@ export function parseRunRequestConfig(input) {
|
|
|
647
641
|
...(record.timeout !== undefined
|
|
648
642
|
? { timeout: record.timeout }
|
|
649
643
|
: {}),
|
|
644
|
+
...(postHook !== undefined
|
|
645
|
+
? { postHook: record.postHook }
|
|
646
|
+
: {}),
|
|
650
647
|
...(record.proxyEndpoints !== undefined
|
|
651
648
|
? { proxyEndpoints: record.proxyEndpoints }
|
|
652
649
|
: {}),
|
|
@@ -724,6 +721,7 @@ export function normaliseRunRequestConfig(config) {
|
|
|
724
721
|
...(config.environment !== undefined ? { environment: config.environment } : {}),
|
|
725
722
|
...(config.proxyEndpoints !== undefined ? { proxyEndpoints: config.proxyEndpoints } : {}),
|
|
726
723
|
...(config.metadata !== undefined ? { metadata: config.metadata } : {}),
|
|
724
|
+
...(config.postHook !== undefined ? { postHook: config.postHook } : {}),
|
|
727
725
|
mcpServerSecrets
|
|
728
726
|
};
|
|
729
727
|
}
|
|
@@ -185,9 +185,9 @@ export interface RunUnit {
|
|
|
185
185
|
* submission. Never throws on minor unknown keys so we can
|
|
186
186
|
* forward-compat with worker-side enrichment.
|
|
187
187
|
*
|
|
188
|
-
* Returns a typed shape even for malformed snapshots
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
188
|
+
* Returns a typed shape even for malformed snapshots by falling back to the
|
|
189
|
+
* default public model and empty collection defaults, because the dashboard
|
|
190
|
+
* must still render *something* for a buggy historical row rather than 500ing
|
|
191
|
+
* the whole detail page.
|
|
192
192
|
*/
|
|
193
193
|
export declare function parseRunUnitSubmission(input: unknown): RunUnitSubmission;
|