@runtypelabs/cli 2.35.1 → 2.35.2

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 (2) hide show
  1. package/dist/index.js +506 -457
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -17162,7 +17162,7 @@ var BuiltInToolIdPrefix = {
17162
17162
  PLATFORM: "platform"
17163
17163
  };
17164
17164
 
17165
- // ../shared/dist/chunk-NWSU7U4C.mjs
17165
+ // ../shared/dist/chunk-3LDIAPYZ.mjs
17166
17166
  function sanitizeToolNameForAiSdk(name) {
17167
17167
  return name.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase().replace(/_+/g, "_").replace(/^_|_$/g, "");
17168
17168
  }
@@ -17551,7 +17551,7 @@ var recordCollectionSchemaSchema = external_exports.strictObject({
17551
17551
  additionalProperties: external_exports.boolean().optional()
17552
17552
  }).superRefine((schema, ctx) => addSemanticIssues(schema, ctx));
17553
17553
 
17554
- // ../shared/dist/chunk-CUYPH2YF.mjs
17554
+ // ../shared/dist/chunk-WN6ECZUE.mjs
17555
17555
  var MCPServerCategory = {
17556
17556
  COMMUNICATION: "communication",
17557
17557
  PRODUCTIVITY: "productivity",
@@ -17573,7 +17573,11 @@ var subagentExecutionConfigSchema = external_exports.object({
17573
17573
  var subagentRunHandleSchema = external_exports.object({
17574
17574
  kind: external_exports.literal("subagent_run"),
17575
17575
  runId: external_exports.string(),
17576
- agentType: external_exports.enum(["runtype", "claude_managed"]),
17576
+ /**
17577
+ * Which durable lane the child executes on. `'durable'` is the ADR 0020
17578
+ * session DO; `'runtype'` is the in-process detached-run DO.
17579
+ */
17580
+ agentType: external_exports.enum(["runtype", "claude_managed", "durable"]),
17577
17581
  status: external_exports.enum(["queued", "running"]),
17578
17582
  startedAt: external_exports.string()
17579
17583
  });
@@ -21214,7 +21218,7 @@ var UNIFIED_SSE_EVENT_TYPES = _unifiedTuple([
21214
21218
  "custom"
21215
21219
  ]);
21216
21220
 
21217
- // ../shared/dist/chunk-FYZWAHYL.mjs
21221
+ // ../shared/dist/chunk-5XPR3WY2.mjs
21218
21222
  var mediaAnnotationsSchema = external_exports.object({
21219
21223
  audience: external_exports.array(external_exports.enum(["user", "assistant"])).optional()
21220
21224
  });
@@ -21223,7 +21227,9 @@ var mediaContentPartSchema = external_exports.union([
21223
21227
  type: external_exports.literal("media"),
21224
21228
  data: external_exports.string(),
21225
21229
  mediaType: external_exports.string(),
21226
- annotations: mediaAnnotationsSchema.optional()
21230
+ annotations: mediaAnnotationsSchema.optional(),
21231
+ /** Tool-result media handle (`MediaResultRef`); present once the bytes were stored. */
21232
+ ref: external_exports.object({ uri: external_exports.string(), assetId: external_exports.string(), sizeBytes: external_exports.number() }).optional()
21227
21233
  }),
21228
21234
  external_exports.object({
21229
21235
  type: external_exports.literal("image-url"),
@@ -22491,7 +22497,8 @@ var AGENT_CONTENT_CONFIG_KEYS = {
22491
22497
  temporal: true,
22492
22498
  memory: true,
22493
22499
  sandbox: true,
22494
- tenancyStrategy: true
22500
+ tenancyStrategy: true,
22501
+ durability: true
22495
22502
  };
22496
22503
  var AGENT_CONTENT_CONFIG_KEY_LIST = Object.keys(AGENT_CONTENT_CONFIG_KEYS).sort();
22497
22504
  function stripTrailingChars(value, char) {
@@ -22820,6 +22827,474 @@ var MAX_MESSAGE_CONTENT_BYTES = 1024 * 1024;
22820
22827
  var MAX_MESSAGES_TOTAL_BYTES = 32 * 1024 * 1024;
22821
22828
  var encoder = new TextEncoder();
22822
22829
  var UNEVALUATED_VERDICT = Object.freeze({ status: "unevaluated" });
22830
+ var tenancyAssuranceLevelSchema = external_exports.enum(["anonymous", "asserted", "verified"]);
22831
+ var tenancyStrategyPresetSchema = external_exports.enum([
22832
+ "internal",
22833
+ "tenant-isolated",
22834
+ "end-user-isolated"
22835
+ ]);
22836
+ var tenancyAssuranceFloorSchema = external_exports.enum(["asserted", "verified"]);
22837
+ var tenancyStrategySchema = external_exports.object({
22838
+ preset: tenancyStrategyPresetSchema,
22839
+ assuranceFloor: external_exports.object({
22840
+ tenant: tenancyAssuranceFloorSchema.optional(),
22841
+ endUser: tenancyAssuranceFloorSchema.optional()
22842
+ }).strict().optional()
22843
+ }).strict();
22844
+ var MCP_HTTP_HEADER_NAME_PATTERN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
22845
+ function isValidMCPHTTPHeaderValue(value) {
22846
+ for (let index = 0; index < value.length; index += 1) {
22847
+ const code = value.charCodeAt(index);
22848
+ if (code === 9 || code >= 32 && code <= 126 || code >= 128 && code <= 255) {
22849
+ continue;
22850
+ }
22851
+ return false;
22852
+ }
22853
+ return true;
22854
+ }
22855
+ var INCOMPATIBLE_HEADERS_AUTH_FIELDS = [
22856
+ "headerName",
22857
+ "token",
22858
+ "username",
22859
+ "password",
22860
+ "tokenSecretName",
22861
+ "usernameSecretName",
22862
+ "passwordSecretName",
22863
+ "oauth2"
22864
+ ];
22865
+ function validateMCPHeadersAuth(auth) {
22866
+ if (!auth) return { valid: true };
22867
+ if (auth.type !== "headers") {
22868
+ if (auth.headers !== void 0) {
22869
+ return {
22870
+ valid: false,
22871
+ code: "headers_wrong_type",
22872
+ message: "The headers field is only valid with auth type 'headers'",
22873
+ path: ["headers"]
22874
+ };
22875
+ }
22876
+ return { valid: true };
22877
+ }
22878
+ for (const field of INCOMPATIBLE_HEADERS_AUTH_FIELDS) {
22879
+ if (auth[field] !== void 0) {
22880
+ return {
22881
+ valid: false,
22882
+ code: "incompatible_auth_field",
22883
+ message: `Auth type 'headers' cannot also set ${field}`,
22884
+ path: [field]
22885
+ };
22886
+ }
22887
+ }
22888
+ if (typeof auth.headers !== "object" || auth.headers === null || Array.isArray(auth.headers) || Object.keys(auth.headers).length === 0) {
22889
+ return {
22890
+ valid: false,
22891
+ code: "headers_required",
22892
+ message: "Auth type 'headers' requires a non-empty headers record",
22893
+ path: ["headers"]
22894
+ };
22895
+ }
22896
+ const normalizedNames = /* @__PURE__ */ new Set();
22897
+ for (const [name, value] of Object.entries(auth.headers)) {
22898
+ if (!MCP_HTTP_HEADER_NAME_PATTERN.test(name)) {
22899
+ return {
22900
+ valid: false,
22901
+ code: "invalid_header_name",
22902
+ message: `Invalid HTTP header name "${name}"`,
22903
+ path: ["headers", name]
22904
+ };
22905
+ }
22906
+ if (typeof value !== "string") {
22907
+ return {
22908
+ valid: false,
22909
+ code: "invalid_header_value",
22910
+ message: `Header "${name}" must have a string value`,
22911
+ path: ["headers", name]
22912
+ };
22913
+ }
22914
+ if (!isValidMCPHTTPHeaderValue(value)) {
22915
+ return {
22916
+ valid: false,
22917
+ code: "invalid_header_value",
22918
+ message: `Header "${name}" contains characters that are not valid in an HTTP header value`,
22919
+ path: ["headers", name]
22920
+ };
22921
+ }
22922
+ const normalizedName = name.toLowerCase();
22923
+ if (normalizedNames.has(normalizedName)) {
22924
+ return {
22925
+ valid: false,
22926
+ code: "duplicate_header_name",
22927
+ message: `Header name "${name}" is duplicated case-insensitively`,
22928
+ path: ["headers", name]
22929
+ };
22930
+ }
22931
+ normalizedNames.add(normalizedName);
22932
+ }
22933
+ return { valid: true };
22934
+ }
22935
+ var REASONING_BUDGET_BOUNDS = {
22936
+ /** Anthropic extended thinking (`thinking: { type: 'enabled', budgetTokens }`). */
22937
+ budgetTokens: { min: 1e3, max: 1e5 },
22938
+ /** Gemini 2.5 thinking budget (`thinkingConfig.thinkingBudget`). */
22939
+ thinkingBudget: { min: 1024, max: 65536 }
22940
+ };
22941
+ var reasoningConfigSchema = external_exports.union([
22942
+ external_exports.boolean(),
22943
+ external_exports.object({
22944
+ enabled: external_exports.boolean(),
22945
+ // OpenAI GPT-5 and o-series
22946
+ reasoningEffort: external_exports.enum(["minimal", "low", "medium", "high", "xhigh"]).optional(),
22947
+ reasoningSummary: external_exports.enum(["auto", "detailed"]).optional(),
22948
+ // Anthropic Claude
22949
+ budgetTokens: external_exports.number().int().min(REASONING_BUDGET_BOUNDS.budgetTokens.min).max(REASONING_BUDGET_BOUNDS.budgetTokens.max).optional(),
22950
+ // Anthropic ADAPTIVE thinking (Claude 4.6 and later, including the Claude 5 family): maps to output_config.effort.
22951
+ // Free-form because the accepted ladder is per-model catalog data
22952
+ // (`ModelReasoningOptions.effort`) and carries rungs outside the
22953
+ // `reasoningEffort` union, such as 'max'. The save-time check is the flow
22954
+ // validator's REASONING_KNOB_UNSUPPORTED advisory, not this schema: a
22955
+ // hand-kept enum here would reject a rung the model added upstream.
22956
+ effort: external_exports.string().min(1).max(32).optional(),
22957
+ // Google Gemini
22958
+ thinkingBudget: external_exports.number().int().min(REASONING_BUDGET_BOUNDS.thinkingBudget.min).max(REASONING_BUDGET_BOUNDS.thinkingBudget.max).optional(),
22959
+ // Gemini 3+ level mode; mutually exclusive with thinkingBudget per model.
22960
+ thinkingLevel: external_exports.string().min(1).max(32).optional(),
22961
+ includeThoughts: external_exports.boolean().optional()
22962
+ })
22963
+ ]);
22964
+ var samplingConfigSchema = {
22965
+ topP: external_exports.number().min(0).max(1).optional(),
22966
+ topK: external_exports.number().int().min(1).max(500).optional(),
22967
+ frequencyPenalty: external_exports.number().min(-2).max(2).optional(),
22968
+ presencePenalty: external_exports.number().min(-2).max(2).optional(),
22969
+ seed: external_exports.number().int().optional()
22970
+ };
22971
+ var errorHandlingSchema = external_exports.object({
22972
+ onError: external_exports.enum(["fail", "continue", "fallback"]),
22973
+ fallbacks: external_exports.array(
22974
+ external_exports.discriminatedUnion("type", [
22975
+ external_exports.object({
22976
+ type: external_exports.literal("retry"),
22977
+ delay: external_exports.number().int().min(0).max(6e4).optional()
22978
+ }),
22979
+ external_exports.object({
22980
+ type: external_exports.literal("model"),
22981
+ model: external_exports.string(),
22982
+ temperature: external_exports.number().min(0).max(2).optional(),
22983
+ maxTokens: external_exports.number().int().min(1).optional(),
22984
+ delay: external_exports.number().int().min(0).max(6e4).optional()
22985
+ }),
22986
+ external_exports.object({
22987
+ type: external_exports.literal("message"),
22988
+ message: external_exports.string(),
22989
+ delay: external_exports.number().int().min(0).max(6e4).optional()
22990
+ })
22991
+ ])
22992
+ ).optional(),
22993
+ // Conditions that activate the fallback chain. Mirrors PromptErrorHandling.triggers;
22994
+ // defaults to error-only when omitted.
22995
+ triggers: external_exports.array(external_exports.object({ type: external_exports.enum(["error", "empty-output"]) })).optional()
22996
+ }).optional();
22997
+ var artifactConfigSchema = external_exports.object({
22998
+ enabled: external_exports.literal(true),
22999
+ types: external_exports.array(external_exports.enum(["markdown", "component"])).min(1)
23000
+ });
23001
+ var temporalConfigSchema = external_exports.object({
23002
+ injectElapsed: external_exports.boolean().optional(),
23003
+ elapsedThresholdSeconds: external_exports.number().int().min(0).optional(),
23004
+ groundNow: external_exports.boolean().optional(),
23005
+ timezone: external_exports.string().optional()
23006
+ });
23007
+ var memoryConfigSchema = external_exports.object({
23008
+ enabled: external_exports.boolean(),
23009
+ profileTemplate: external_exports.string().optional(),
23010
+ // When omitted and `enabled` is true, treated as `true` (smart default): a
23011
+ // Markdown memory summary is woven into the agent's system prompt on each
23012
+ // turn so the agent always has the user in context — without the model having
23013
+ // to call `recall_memory` first. (The summary is cached per profile so the
23014
+ // synthesis cost is paid once, not on every turn.) Set false to skip
23015
+ // injection (focused task agents that don't benefit from a profile overview).
23016
+ // Resolved via `shouldInjectMemorySummary` so the default lives in one place.
23017
+ injectSummary: external_exports.boolean().optional()
23018
+ });
23019
+ var sandboxNetworkAccessSchema = external_exports.union([
23020
+ external_exports.enum(["none", "essentials", "open"]),
23021
+ external_exports.object({
23022
+ profile: external_exports.enum(["none", "essentials", "open"]).optional(),
23023
+ allow: external_exports.array(external_exports.string()).optional()
23024
+ })
23025
+ ]);
23026
+ var sandboxConfigSchema = external_exports.object({
23027
+ enabled: external_exports.boolean(),
23028
+ // INERT except `'runtype-sandbox'`: the agent-sandbox runtime
23029
+ // (`SandboxToolService`) REJECTS any provider other than `'runtype-sandbox'`
23030
+ // with a throw at the first sandbox tool call — `'daytona'` is NOT honored on
23031
+ // this path (Phase 3 "Daytona parity" is unshipped). Kept parseable (not
23032
+ // narrowed to `['runtype-sandbox']`) so a stored/imported `'daytona'` config
23033
+ // does not fail agent-config parse, and so this schema stays aligned with the
23034
+ // FPO public-types mirror + MCP snapshot that still list it. Selecting
23035
+ // `'daytona'` is an author-time no-op that surfaces as a runtime error.
23036
+ // (`quickjs` / `cloudflare-worker` are code-eval only, no shell — never valid.)
23037
+ provider: external_exports.enum(["runtype-sandbox", "daytona"]).optional(),
23038
+ // `'ephemeral'` and `'conversation'` (the default) are implemented.
23039
+ // `'named'` is parseable but NOT yet implemented: the runtime silently
23040
+ // degrades `'named'` to `'ephemeral'` (with a debug log) — no durable
23041
+ // cross-conversation workspace exists yet (Phase 3). Kept parseable so a
23042
+ // stored `'named'` config still loads; it just behaves as `'ephemeral'`.
23043
+ persistence: external_exports.enum(["ephemeral", "conversation", "named"]).optional(),
23044
+ // INERT on the agent sandbox path: `instanceType` is NOT honored — the agent
23045
+ // sandbox always provisions `standard-4` (the blanket default fixed by
23046
+ // apps/sandbox/wrangler.toml `[[containers]]`) regardless of this value (the
23047
+ // value is read for the transform-data/deploy sandbox billing paths, not for
23048
+ // the agent builtin tools). Kept parseable for forward-compat + mirror
23049
+ // alignment; treat it as a no-op author-time hint until the agent path wires
23050
+ // per-plan container sizing.
23051
+ instanceType: external_exports.enum(["standard-1", "standard-2", "standard-3", "standard-4"]).optional(),
23052
+ networkAccess: sandboxNetworkAccessSchema.optional(),
23053
+ ttl: external_exports.enum(["5m", "1h", "24h", "unlimited"]).optional(),
23054
+ sleepAfter: external_exports.enum(["5m", "15m", "30m", "1h"]).optional(),
23055
+ // Operator-authored bootstrap commands. The API runs this batch once after
23056
+ // enforcing the sandbox's network policy and before the first model-authored
23057
+ // sandbox verb. Commands run in order from /workspace and must be foreground,
23058
+ // self-contained, and safe to retry after an interrupted container runtime;
23059
+ // the credential-bearing exec supervisor deliberately reaps every descendant
23060
+ // before a command returns, so setup cannot launch a daemon meant to outlive
23061
+ // it. Trusted Durable Object state plus a run-scoped memo prevents the batch
23062
+ // from being repeated for the same provisioned workspace. Changing the
23063
+ // commands or managed-secret KEY bindings creates a fresh sandbox identity;
23064
+ // rotating a value under the same key does not rerun setup.
23065
+ setupCommands: external_exports.array(external_exports.string().min(1, "setup commands must not be empty")).optional(),
23066
+ // Credential environment available ONLY to the operator-authored setup batch
23067
+ // above — never to a model-authored `bash` command. Keys are env var names;
23068
+ // values are MANAGED SECRET KEYS (e.g. `GITHUB_CLONE_TOKEN`), never raw
23069
+ // credential values. The API resolves them immediately before setup and
23070
+ // delivers them out-of-band over `cloudflareSandboxExecWithSecretEnv`, so the
23071
+ // values never appear in command strings, model-facing tool schemas, logs, or
23072
+ // spill files. Like `networkAccess`, both fields are operator Definition: the
23073
+ // model cannot author setup, name a managed secret, or grant itself one.
23074
+ //
23075
+ // TRUST BOUNDARY — read before configuring this. Every process started by a
23076
+ // credentialed setup batch can read the injected values. Keep setup authored
23077
+ // and reviewed by the operator; do not run model-, attacker-, or
23078
+ // supply-chain-authored code (for example an install script) while credentials
23079
+ // are present, and never persist a raw credential into /workspace for later
23080
+ // model access. The secret supervisor freezes pre-existing processes, reaps
23081
+ // every setup descendant, and destroys the sandbox fail-closed if cleanup
23082
+ // fails, but output redaction remains defense-in-depth rather than permission
23083
+ // to echo or transform a credential.
23084
+ // Therefore:
23085
+ // - Prefer `credentialProxies` (phantom tokens, swapped at the egress
23086
+ // proxy) for any HTTP(S) protocol it supports — the real credential
23087
+ // never enters the container at all.
23088
+ // - Scope the secret as narrowly as the provider allows (read-only,
23089
+ // single-repo) and pair it with a tight `networkAccess` profile.
23090
+ // - Keep credentialed setup separate from later uncredentialed dependency
23091
+ // installation and model-authored work.
23092
+ // Name shape and the 32-entry cap mirror the sandbox worker's
23093
+ // `validateSecretEnv`; `RUNTYPE_SECRET_COMMAND` is the worker's reserved
23094
+ // control-channel variable.
23095
+ secretEnv: external_exports.record(
23096
+ external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "must be a valid environment variable name").refine((name) => name !== "RUNTYPE_SECRET_COMMAND", {
23097
+ message: "RUNTYPE_SECRET_COMMAND is reserved"
23098
+ }),
23099
+ external_exports.string().min(1, "must be a managed secret key")
23100
+ ).refine((record2) => Object.keys(record2).length <= 32, {
23101
+ message: "secretEnv supports at most 32 variables"
23102
+ }).optional()
23103
+ // NOTE: a `requireApprovalForBash` knob was forward-declared here for Phase 3
23104
+ // but never wired to any runtime gate, so it was REMOVED from the public
23105
+ // schema rather than ship a misleading, inert control (post-Fable handoff 05,
23106
+ // F3). To gate `bash` today use the generic `tools.approval` config, which
23107
+ // matches the tool by name. Re-add the dedicated knob only with its wiring.
23108
+ });
23109
+ var agentDurabilityConfigSchema = external_exports.object({
23110
+ watchLeaseMs: external_exports.number().int().min(1e4).max(18e5).nullable().optional(),
23111
+ maxBudgetMs: external_exports.number().int().min(1e3).max(864e5).nullable().optional(),
23112
+ forced: external_exports.enum(["durable", "in_process"]).optional()
23113
+ });
23114
+ var DEFAULT_TURN_MAX_BUDGET_MS = 30 * 60 * 1e3;
23115
+ var agentRuntimeConfigSchema = external_exports.object({
23116
+ model: external_exports.string().optional(),
23117
+ systemPrompt: external_exports.string().optional(),
23118
+ temperature: external_exports.number().min(0).max(2).optional(),
23119
+ // Maximum output tokens (the model call's `maxOutputTokens`). A sibling of
23120
+ // the sampling params: a static generation budget that belongs on the saved
23121
+ // agent definition. Notably load-bearing for "thinking" default models that
23122
+ // share reasoning + answer tokens in one output budget (Moonshot requires
23123
+ // `>= 16k` or the visible answer can truncate to nothing after a long
23124
+ // reasoning trace) — the Product Generator pins `24000` for exactly this.
23125
+ // `buildVirtualFlow` already maps this onto the prompt step (defaulting to
23126
+ // 16384 when unset), so saving it here is all that's required for it to take
23127
+ // effect at execution time.
23128
+ maxTokens: external_exports.number().int().min(1).optional(),
23129
+ ...samplingConfigSchema,
23130
+ // Unified tools configuration (nested under 'tools').
23131
+ //
23132
+ // This is the **createAgent / FPO-v2 create-form** projection of the canonical
23133
+ // `agentToolsConfigSchema` (`tool-types.ts`). It is kept separate on purpose —
23134
+ // it carries create-time constraints (`.int().min().max()`), a create-form
23135
+ // `runtimeTools.toolType` enum (`advisor`/`search` instead of the canonical
23136
+ // `RuntimeToolDefinition` union), and does NOT yet accept `toolSearch`.
23137
+ // Collapsing it onto the canonical leaves would change createAgent validation,
23138
+ // so the two are pinned by review + the planning doc rather than a shared
23139
+ // import. Adding `toolSearch` here (to match the canonical schema + the runtime
23140
+ // wire form) is a tracked follow-up.
23141
+ tools: external_exports.object({
23142
+ toolIds: external_exports.array(external_exports.string()).optional(),
23143
+ toolConfigs: external_exports.record(external_exports.string(), external_exports.record(external_exports.string(), external_exports.unknown())).optional(),
23144
+ runtimeTools: external_exports.array(
23145
+ external_exports.object({
23146
+ name: external_exports.string(),
23147
+ description: external_exports.string(),
23148
+ toolType: external_exports.enum([
23149
+ "flow",
23150
+ "custom",
23151
+ "external",
23152
+ "local",
23153
+ "advisor",
23154
+ "subagent",
23155
+ "search"
23156
+ ]),
23157
+ parametersSchema: external_exports.record(external_exports.string(), external_exports.unknown()),
23158
+ config: external_exports.record(external_exports.string(), external_exports.unknown())
23159
+ })
23160
+ ).optional(),
23161
+ mcpServers: external_exports.array(
23162
+ external_exports.object({
23163
+ id: external_exports.string(),
23164
+ name: external_exports.string().optional(),
23165
+ url: external_exports.string(),
23166
+ auth: external_exports.object({
23167
+ type: external_exports.enum(["api_key", "bearer", "basic", "custom_header", "headers", "none"]),
23168
+ headerName: external_exports.string().optional(),
23169
+ token: external_exports.string().optional(),
23170
+ username: external_exports.string().optional(),
23171
+ password: external_exports.string().optional(),
23172
+ // For `type: 'headers'`: arbitrary HTTP header name → value
23173
+ // templates. The shared refinement below enforces the exclusive shape.
23174
+ headers: external_exports.record(external_exports.string(), external_exports.string()).optional()
23175
+ }).superRefine((auth, ctx) => {
23176
+ const validation = validateMCPHeadersAuth(auth);
23177
+ if (!validation.valid) {
23178
+ ctx.addIssue({
23179
+ code: "custom",
23180
+ path: validation.path,
23181
+ message: validation.message
23182
+ });
23183
+ }
23184
+ }).optional(),
23185
+ allowedTools: external_exports.array(external_exports.string()).optional(),
23186
+ timeout: external_exports.number().optional(),
23187
+ transport: external_exports.enum(["streamable_http", "rest"]).optional(),
23188
+ enabled: external_exports.boolean().optional()
23189
+ })
23190
+ ).optional(),
23191
+ maxToolCalls: external_exports.number().int().min(1).max(100).optional(),
23192
+ toolCallStrategy: external_exports.enum(["auto", "required", "none"]).optional(),
23193
+ approval: external_exports.object({
23194
+ require: external_exports.union([external_exports.array(external_exports.string()), external_exports.boolean()]),
23195
+ timeout: external_exports.number().optional(),
23196
+ /** Opt out of agent-supplied approval reasons (`_approvalReason`
23197
+ * schema injection). Default: true. Mirrors approvalConfigSchema
23198
+ * in tool-types.ts. */
23199
+ requestReason: external_exports.boolean().optional(),
23200
+ /** Persistent "always" choices offered at the approval prompt.
23201
+ * Mirrors approvalConfigSchema.choices in tool-types.ts. */
23202
+ choices: external_exports.object({
23203
+ alwaysAllow: external_exports.boolean().optional(),
23204
+ alwaysDeny: external_exports.boolean().optional()
23205
+ }).optional()
23206
+ }).optional(),
23207
+ perToolLimits: external_exports.record(
23208
+ external_exports.string(),
23209
+ external_exports.object({
23210
+ maxCalls: external_exports.number().optional(),
23211
+ required: external_exports.boolean().optional()
23212
+ })
23213
+ ).optional(),
23214
+ subagentConfig: external_exports.object({
23215
+ toolPool: external_exports.array(external_exports.string()),
23216
+ defaultMaxTurns: external_exports.number().int().min(1).max(100).optional(),
23217
+ maxTurnsLimit: external_exports.number().int().min(1).max(100).optional(),
23218
+ maxSpawnsPerRun: external_exports.number().int().min(1).max(50).optional(),
23219
+ defaultModel: external_exports.string().optional(),
23220
+ allowNesting: external_exports.boolean().optional(),
23221
+ // Max must stay <= the dispatch `options.stepTimeoutMs` cap
23222
+ // (600_000 — `api-schemas/dispatch.ts`): `resolveSubagentTimeouts`
23223
+ // (apps/api subagent dispatch) stamps the child flow's
23224
+ // `stepTimeoutMs` from the subagent's effective timeout. Keep the
23225
+ // two bounds in lockstep or 600s subagents break at the smaller cap.
23226
+ defaultTimeoutMs: external_exports.number().int().min(1e3).max(6e5).optional(),
23227
+ executionModes: external_exports.array(external_exports.enum(["attached", "detached"])).min(1).optional(),
23228
+ defaultExecutionMode: external_exports.enum(["attached", "detached"]).optional(),
23229
+ defaultNotify: external_exports.enum(["none", "narrate", "react"]).optional(),
23230
+ detachedMaxBudgetMs: external_exports.number().int().min(1e3).max(864e5).optional(),
23231
+ detachedNoProgressBudgetMs: external_exports.number().int().min(1e3).max(864e5).optional()
23232
+ }).optional(),
23233
+ codeModeConfig: external_exports.object({
23234
+ toolPool: external_exports.array(external_exports.string()),
23235
+ description: external_exports.string().optional(),
23236
+ timeoutMs: external_exports.number().int().min(1e3).max(6e5).optional()
23237
+ }).optional()
23238
+ }).optional(),
23239
+ artifacts: artifactConfigSchema.optional(),
23240
+ reasoning: reasoningConfigSchema.optional(),
23241
+ advisor: external_exports.object({
23242
+ model: external_exports.string(),
23243
+ systemPrompt: external_exports.string().optional()
23244
+ }).optional().nullable(),
23245
+ loopConfig: external_exports.object({
23246
+ maxTurns: external_exports.number().int().min(1).max(100).optional(),
23247
+ maxCost: external_exports.number().min(0).optional(),
23248
+ enableReflection: external_exports.boolean().optional(),
23249
+ reflectionInterval: external_exports.number().int().min(1).max(50).optional()
23250
+ }).optional(),
23251
+ voice: external_exports.object({
23252
+ enabled: external_exports.boolean().optional(),
23253
+ provider: external_exports.string().optional(),
23254
+ interruptionMode: external_exports.enum(["none", "cancel", "barge-in"]).optional(),
23255
+ elevenLabs: external_exports.object({
23256
+ voiceId: external_exports.string().optional(),
23257
+ modelId: external_exports.string().optional(),
23258
+ stability: external_exports.number().min(0).max(1).optional(),
23259
+ similarity: external_exports.number().min(0).max(1).optional()
23260
+ }).optional()
23261
+ }).optional(),
23262
+ errorHandling: errorHandlingSchema,
23263
+ loggingPolicy: external_exports.enum(["default", "on", "off"]).optional(),
23264
+ // Opt-in PII redaction for tail-log and telemetry payloads. `'default'`
23265
+ // defers to a lower layer (surface/product) or the resolver default (off).
23266
+ // Mirrors `loggingPolicy`.
23267
+ piiRedaction: external_exports.enum(["default", "off", "redact"]).optional(),
23268
+ // Opt-in temporal awareness. `injectElapsed` turns on the automatic
23269
+ // "time has passed" decorator (a `<temporal_context>` block prepended to
23270
+ // the user turn at dispatch, gated on turn ≥ 2 and a gap ≥
23271
+ // `elapsedThresholdSeconds`). `groundNow` additionally surfaces the current
23272
+ // datetime in that block. `timezone` is the agent's DEFAULT IANA zone —
23273
+ // the layered tool/decorator resolution overrides it per-conversation.
23274
+ temporal: temporalConfigSchema.optional(),
23275
+ // Long-term memory (Cloudflare Agent Memory). Single-sourced as
23276
+ // `memoryConfigSchema` (below) and reused by the update-agent, dispatch
23277
+ // inline-agent, and FPO agent schemas so the four surfaces never drift —
23278
+ // mirroring how `temporalConfigSchema` is shared.
23279
+ memory: memoryConfigSchema.optional(),
23280
+ // Agent Sandbox (Linux computer). When enabled, the agent gets the sandbox
23281
+ // builtin tools + system-prompt frame at dispatch. Single-sourced as
23282
+ // `sandboxConfigSchema` (above), mirroring `memory`. The live machine is agent
23283
+ // state; this block is the operator Definition that enables it.
23284
+ sandbox: sandboxConfigSchema.optional(),
23285
+ // Tenancy Strategy (ADR 0012) — per-resource opt-in to tenant/end-user
23286
+ // isolation. Part of the Definition (validated + persisted + content-hashed
23287
+ // here so `ensure` tracks it). Absent → platform-global default (no behavior
23288
+ // change); present → the execution pipeline expands it and enforces the
23289
+ // lock-down gate pre-engine. Single-sourced as `tenancyStrategySchema` in
23290
+ // `./tenancy-strategy`; the expansion + gate logic lives in apps/api.
23291
+ tenancyStrategy: tenancyStrategySchema.optional(),
23292
+ // Durable-turn knobs (ADR 0020). Single-sourced as
23293
+ // `agentDurabilityConfigSchema` (above), mirroring `memory` / `sandbox`.
23294
+ // Durability is the platform default; this block only tunes the turn and
23295
+ // carries the per-agent lane pin.
23296
+ durability: agentDurabilityConfigSchema.optional()
23297
+ }).strict();
22823
23298
  var contextFallbackSchema = external_exports.union([
22824
23299
  external_exports.object({ type: external_exports.literal("retry"), delay: external_exports.number().optional() }),
22825
23300
  external_exports.object({
@@ -23534,7 +24009,21 @@ var promptConfigSchema = external_exports.object({
23534
24009
  enabled: external_exports.literal(true),
23535
24010
  types: external_exports.array(external_exports.enum(["markdown", "component"])).min(1)
23536
24011
  }).optional(),
23537
- reasoning: external_exports.boolean().optional(),
24012
+ // The canonical `reasoningConfigSchema` from `agent-runtime-config-schema.ts`,
24013
+ // whose union already leads with `z.boolean()` — so this is the boolean-first
24014
+ // union, not a second wrapper around one.
24015
+ //
24016
+ // This field was `z.boolean().optional()` until the object form was found to
24017
+ // be unsaveable: the flow editor's reasoning dials write the full
24018
+ // `ReasoningConfig` ({enabled, reasoningEffort | effort | thinkingLevel |
24019
+ // budgetTokens | thinkingBudget | reasoningSummary | includeThoughts}), the
24020
+ // engine has always honored it (`typeof flowPrompt.reasoning === 'object'` in
24021
+ // `apps/api/src/lib/flow-execution/prompt-executor.ts`, mirrored by the
24022
+ // runtime port), and an agent has always accepted it — only flow create /
24023
+ // update rejected it, with SCHEMA_VALIDATION_FAILED "expected boolean,
24024
+ // received object". Sharing ONE schema with the agent plane is what keeps the
24025
+ // two from drifting apart again.
24026
+ reasoning: reasoningConfigSchema.optional(),
23538
24027
  previousMessages: promptPreviousMessagesSchema.optional(),
23539
24028
  streamOutput: external_exports.boolean().optional(),
23540
24029
  errorHandling: promptErrorHandlingConfigSchema.optional(),
@@ -28943,97 +29432,6 @@ var runtimeHostDependencySchema = external_exports.union([
28943
29432
  backgroundRunCoordinatorDependencySchema,
28944
29433
  unknownHostDependencySchema
28945
29434
  ]);
28946
- var MCP_HTTP_HEADER_NAME_PATTERN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
28947
- function isValidMCPHTTPHeaderValue(value) {
28948
- for (let index = 0; index < value.length; index += 1) {
28949
- const code = value.charCodeAt(index);
28950
- if (code === 9 || code >= 32 && code <= 126 || code >= 128 && code <= 255) {
28951
- continue;
28952
- }
28953
- return false;
28954
- }
28955
- return true;
28956
- }
28957
- var INCOMPATIBLE_HEADERS_AUTH_FIELDS = [
28958
- "headerName",
28959
- "token",
28960
- "username",
28961
- "password",
28962
- "tokenSecretName",
28963
- "usernameSecretName",
28964
- "passwordSecretName",
28965
- "oauth2"
28966
- ];
28967
- function validateMCPHeadersAuth(auth) {
28968
- if (!auth) return { valid: true };
28969
- if (auth.type !== "headers") {
28970
- if (auth.headers !== void 0) {
28971
- return {
28972
- valid: false,
28973
- code: "headers_wrong_type",
28974
- message: "The headers field is only valid with auth type 'headers'",
28975
- path: ["headers"]
28976
- };
28977
- }
28978
- return { valid: true };
28979
- }
28980
- for (const field of INCOMPATIBLE_HEADERS_AUTH_FIELDS) {
28981
- if (auth[field] !== void 0) {
28982
- return {
28983
- valid: false,
28984
- code: "incompatible_auth_field",
28985
- message: `Auth type 'headers' cannot also set ${field}`,
28986
- path: [field]
28987
- };
28988
- }
28989
- }
28990
- if (typeof auth.headers !== "object" || auth.headers === null || Array.isArray(auth.headers) || Object.keys(auth.headers).length === 0) {
28991
- return {
28992
- valid: false,
28993
- code: "headers_required",
28994
- message: "Auth type 'headers' requires a non-empty headers record",
28995
- path: ["headers"]
28996
- };
28997
- }
28998
- const normalizedNames = /* @__PURE__ */ new Set();
28999
- for (const [name, value] of Object.entries(auth.headers)) {
29000
- if (!MCP_HTTP_HEADER_NAME_PATTERN.test(name)) {
29001
- return {
29002
- valid: false,
29003
- code: "invalid_header_name",
29004
- message: `Invalid HTTP header name "${name}"`,
29005
- path: ["headers", name]
29006
- };
29007
- }
29008
- if (typeof value !== "string") {
29009
- return {
29010
- valid: false,
29011
- code: "invalid_header_value",
29012
- message: `Header "${name}" must have a string value`,
29013
- path: ["headers", name]
29014
- };
29015
- }
29016
- if (!isValidMCPHTTPHeaderValue(value)) {
29017
- return {
29018
- valid: false,
29019
- code: "invalid_header_value",
29020
- message: `Header "${name}" contains characters that are not valid in an HTTP header value`,
29021
- path: ["headers", name]
29022
- };
29023
- }
29024
- const normalizedName = name.toLowerCase();
29025
- if (normalizedNames.has(normalizedName)) {
29026
- return {
29027
- valid: false,
29028
- code: "duplicate_header_name",
29029
- message: `Header name "${name}" is duplicated case-insensitively`,
29030
- path: ["headers", name]
29031
- };
29032
- }
29033
- normalizedNames.add(normalizedName);
29034
- }
29035
- return { valid: true };
29036
- }
29037
29435
  var SKILL_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
29038
29436
  var EMIT_ARTIFACT_MARKDOWN_TOOL_ID = "emit_artifact_markdown";
29039
29437
  var EMIT_ARTIFACT_COMPONENT_TOOL_ID = "emit_artifact_component";
@@ -29533,357 +29931,6 @@ var SLACK_MANIFEST_BOT_SCOPES = [
29533
29931
  ...SLACK_REQUIRED_BOT_SCOPES,
29534
29932
  ...SLACK_OPTIONAL_BOT_SCOPES
29535
29933
  ];
29536
- var tenancyAssuranceLevelSchema = external_exports.enum(["anonymous", "asserted", "verified"]);
29537
- var tenancyStrategyPresetSchema = external_exports.enum([
29538
- "internal",
29539
- "tenant-isolated",
29540
- "end-user-isolated"
29541
- ]);
29542
- var tenancyAssuranceFloorSchema = external_exports.enum(["asserted", "verified"]);
29543
- var tenancyStrategySchema = external_exports.object({
29544
- preset: tenancyStrategyPresetSchema,
29545
- assuranceFloor: external_exports.object({
29546
- tenant: tenancyAssuranceFloorSchema.optional(),
29547
- endUser: tenancyAssuranceFloorSchema.optional()
29548
- }).strict().optional()
29549
- }).strict();
29550
- var reasoningConfigSchema = external_exports.union([
29551
- external_exports.boolean(),
29552
- external_exports.object({
29553
- enabled: external_exports.boolean(),
29554
- // OpenAI GPT-5 and o-series
29555
- reasoningEffort: external_exports.enum(["minimal", "low", "medium", "high", "xhigh"]).optional(),
29556
- reasoningSummary: external_exports.enum(["auto", "detailed"]).optional(),
29557
- // Anthropic Claude
29558
- budgetTokens: external_exports.number().int().min(1e3).max(1e5).optional(),
29559
- // Google Gemini
29560
- thinkingBudget: external_exports.number().int().min(1024).max(65536).optional(),
29561
- includeThoughts: external_exports.boolean().optional()
29562
- })
29563
- ]);
29564
- var samplingConfigSchema = {
29565
- topP: external_exports.number().min(0).max(1).optional(),
29566
- topK: external_exports.number().int().min(1).max(500).optional(),
29567
- frequencyPenalty: external_exports.number().min(-2).max(2).optional(),
29568
- presencePenalty: external_exports.number().min(-2).max(2).optional(),
29569
- seed: external_exports.number().int().optional()
29570
- };
29571
- var errorHandlingSchema = external_exports.object({
29572
- onError: external_exports.enum(["fail", "continue", "fallback"]),
29573
- fallbacks: external_exports.array(
29574
- external_exports.discriminatedUnion("type", [
29575
- external_exports.object({
29576
- type: external_exports.literal("retry"),
29577
- delay: external_exports.number().int().min(0).max(6e4).optional()
29578
- }),
29579
- external_exports.object({
29580
- type: external_exports.literal("model"),
29581
- model: external_exports.string(),
29582
- temperature: external_exports.number().min(0).max(2).optional(),
29583
- maxTokens: external_exports.number().int().min(1).optional(),
29584
- delay: external_exports.number().int().min(0).max(6e4).optional()
29585
- }),
29586
- external_exports.object({
29587
- type: external_exports.literal("message"),
29588
- message: external_exports.string(),
29589
- delay: external_exports.number().int().min(0).max(6e4).optional()
29590
- })
29591
- ])
29592
- ).optional(),
29593
- // Conditions that activate the fallback chain. Mirrors PromptErrorHandling.triggers;
29594
- // defaults to error-only when omitted.
29595
- triggers: external_exports.array(external_exports.object({ type: external_exports.enum(["error", "empty-output"]) })).optional()
29596
- }).optional();
29597
- var artifactConfigSchema = external_exports.object({
29598
- enabled: external_exports.literal(true),
29599
- types: external_exports.array(external_exports.enum(["markdown", "component"])).min(1)
29600
- });
29601
- var temporalConfigSchema = external_exports.object({
29602
- injectElapsed: external_exports.boolean().optional(),
29603
- elapsedThresholdSeconds: external_exports.number().int().min(0).optional(),
29604
- groundNow: external_exports.boolean().optional(),
29605
- timezone: external_exports.string().optional()
29606
- });
29607
- var memoryConfigSchema = external_exports.object({
29608
- enabled: external_exports.boolean(),
29609
- profileTemplate: external_exports.string().optional(),
29610
- // When omitted and `enabled` is true, treated as `true` (smart default): a
29611
- // Markdown memory summary is woven into the agent's system prompt on each
29612
- // turn so the agent always has the user in context — without the model having
29613
- // to call `recall_memory` first. (The summary is cached per profile so the
29614
- // synthesis cost is paid once, not on every turn.) Set false to skip
29615
- // injection (focused task agents that don't benefit from a profile overview).
29616
- // Resolved via `shouldInjectMemorySummary` so the default lives in one place.
29617
- injectSummary: external_exports.boolean().optional()
29618
- });
29619
- var sandboxNetworkAccessSchema = external_exports.union([
29620
- external_exports.enum(["none", "essentials", "open"]),
29621
- external_exports.object({
29622
- profile: external_exports.enum(["none", "essentials", "open"]).optional(),
29623
- allow: external_exports.array(external_exports.string()).optional()
29624
- })
29625
- ]);
29626
- var sandboxConfigSchema = external_exports.object({
29627
- enabled: external_exports.boolean(),
29628
- // INERT except `'runtype-sandbox'`: the agent-sandbox runtime
29629
- // (`SandboxToolService`) REJECTS any provider other than `'runtype-sandbox'`
29630
- // with a throw at the first sandbox tool call — `'daytona'` is NOT honored on
29631
- // this path (Phase 3 "Daytona parity" is unshipped). Kept parseable (not
29632
- // narrowed to `['runtype-sandbox']`) so a stored/imported `'daytona'` config
29633
- // does not fail agent-config parse, and so this schema stays aligned with the
29634
- // FPO public-types mirror + MCP snapshot that still list it. Selecting
29635
- // `'daytona'` is an author-time no-op that surfaces as a runtime error.
29636
- // (`quickjs` / `cloudflare-worker` are code-eval only, no shell — never valid.)
29637
- provider: external_exports.enum(["runtype-sandbox", "daytona"]).optional(),
29638
- // `'ephemeral'` and `'conversation'` (the default) are implemented.
29639
- // `'named'` is parseable but NOT yet implemented: the runtime silently
29640
- // degrades `'named'` to `'ephemeral'` (with a debug log) — no durable
29641
- // cross-conversation workspace exists yet (Phase 3). Kept parseable so a
29642
- // stored `'named'` config still loads; it just behaves as `'ephemeral'`.
29643
- persistence: external_exports.enum(["ephemeral", "conversation", "named"]).optional(),
29644
- // INERT on the agent sandbox path: `instanceType` is NOT honored — the agent
29645
- // sandbox always provisions `standard-4` (the blanket default fixed by
29646
- // apps/sandbox/wrangler.toml `[[containers]]`) regardless of this value (the
29647
- // value is read for the transform-data/deploy sandbox billing paths, not for
29648
- // the agent builtin tools). Kept parseable for forward-compat + mirror
29649
- // alignment; treat it as a no-op author-time hint until the agent path wires
29650
- // per-plan container sizing.
29651
- instanceType: external_exports.enum(["standard-1", "standard-2", "standard-3", "standard-4"]).optional(),
29652
- networkAccess: sandboxNetworkAccessSchema.optional(),
29653
- ttl: external_exports.enum(["5m", "1h", "24h", "unlimited"]).optional(),
29654
- sleepAfter: external_exports.enum(["5m", "15m", "30m", "1h"]).optional(),
29655
- // Operator-authored bootstrap commands. The API runs this batch once after
29656
- // enforcing the sandbox's network policy and before the first model-authored
29657
- // sandbox verb. Commands run in order from /workspace and must be foreground,
29658
- // self-contained, and safe to retry after an interrupted container runtime;
29659
- // the credential-bearing exec supervisor deliberately reaps every descendant
29660
- // before a command returns, so setup cannot launch a daemon meant to outlive
29661
- // it. Trusted Durable Object state plus a run-scoped memo prevents the batch
29662
- // from being repeated for the same provisioned workspace. Changing the
29663
- // commands or managed-secret KEY bindings creates a fresh sandbox identity;
29664
- // rotating a value under the same key does not rerun setup.
29665
- setupCommands: external_exports.array(external_exports.string().min(1, "setup commands must not be empty")).optional(),
29666
- // Credential environment available ONLY to the operator-authored setup batch
29667
- // above — never to a model-authored `bash` command. Keys are env var names;
29668
- // values are MANAGED SECRET KEYS (e.g. `GITHUB_CLONE_TOKEN`), never raw
29669
- // credential values. The API resolves them immediately before setup and
29670
- // delivers them out-of-band over `cloudflareSandboxExecWithSecretEnv`, so the
29671
- // values never appear in command strings, model-facing tool schemas, logs, or
29672
- // spill files. Like `networkAccess`, both fields are operator Definition: the
29673
- // model cannot author setup, name a managed secret, or grant itself one.
29674
- //
29675
- // TRUST BOUNDARY — read before configuring this. Every process started by a
29676
- // credentialed setup batch can read the injected values. Keep setup authored
29677
- // and reviewed by the operator; do not run model-, attacker-, or
29678
- // supply-chain-authored code (for example an install script) while credentials
29679
- // are present, and never persist a raw credential into /workspace for later
29680
- // model access. The secret supervisor freezes pre-existing processes, reaps
29681
- // every setup descendant, and destroys the sandbox fail-closed if cleanup
29682
- // fails, but output redaction remains defense-in-depth rather than permission
29683
- // to echo or transform a credential.
29684
- // Therefore:
29685
- // - Prefer `credentialProxies` (phantom tokens, swapped at the egress
29686
- // proxy) for any HTTP(S) protocol it supports — the real credential
29687
- // never enters the container at all.
29688
- // - Scope the secret as narrowly as the provider allows (read-only,
29689
- // single-repo) and pair it with a tight `networkAccess` profile.
29690
- // - Keep credentialed setup separate from later uncredentialed dependency
29691
- // installation and model-authored work.
29692
- // Name shape and the 32-entry cap mirror the sandbox worker's
29693
- // `validateSecretEnv`; `RUNTYPE_SECRET_COMMAND` is the worker's reserved
29694
- // control-channel variable.
29695
- secretEnv: external_exports.record(
29696
- external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "must be a valid environment variable name").refine((name) => name !== "RUNTYPE_SECRET_COMMAND", {
29697
- message: "RUNTYPE_SECRET_COMMAND is reserved"
29698
- }),
29699
- external_exports.string().min(1, "must be a managed secret key")
29700
- ).refine((record2) => Object.keys(record2).length <= 32, {
29701
- message: "secretEnv supports at most 32 variables"
29702
- }).optional()
29703
- // NOTE: a `requireApprovalForBash` knob was forward-declared here for Phase 3
29704
- // but never wired to any runtime gate, so it was REMOVED from the public
29705
- // schema rather than ship a misleading, inert control (post-Fable handoff 05,
29706
- // F3). To gate `bash` today use the generic `tools.approval` config, which
29707
- // matches the tool by name. Re-add the dedicated knob only with its wiring.
29708
- });
29709
- var agentRuntimeConfigSchema = external_exports.object({
29710
- model: external_exports.string().optional(),
29711
- systemPrompt: external_exports.string().optional(),
29712
- temperature: external_exports.number().min(0).max(2).optional(),
29713
- // Maximum output tokens (the model call's `maxOutputTokens`). A sibling of
29714
- // the sampling params: a static generation budget that belongs on the saved
29715
- // agent definition. Notably load-bearing for "thinking" default models that
29716
- // share reasoning + answer tokens in one output budget (Moonshot requires
29717
- // `>= 16k` or the visible answer can truncate to nothing after a long
29718
- // reasoning trace) — the Product Generator pins `24000` for exactly this.
29719
- // `buildVirtualFlow` already maps this onto the prompt step (defaulting to
29720
- // 16384 when unset), so saving it here is all that's required for it to take
29721
- // effect at execution time.
29722
- maxTokens: external_exports.number().int().min(1).optional(),
29723
- ...samplingConfigSchema,
29724
- // Unified tools configuration (nested under 'tools').
29725
- //
29726
- // This is the **createAgent / FPO-v2 create-form** projection of the canonical
29727
- // `agentToolsConfigSchema` (`tool-types.ts`). It is kept separate on purpose —
29728
- // it carries create-time constraints (`.int().min().max()`), a create-form
29729
- // `runtimeTools.toolType` enum (`advisor`/`search` instead of the canonical
29730
- // `RuntimeToolDefinition` union), and does NOT yet accept `toolSearch`.
29731
- // Collapsing it onto the canonical leaves would change createAgent validation,
29732
- // so the two are pinned by review + the planning doc rather than a shared
29733
- // import. Adding `toolSearch` here (to match the canonical schema + the runtime
29734
- // wire form) is a tracked follow-up.
29735
- tools: external_exports.object({
29736
- toolIds: external_exports.array(external_exports.string()).optional(),
29737
- toolConfigs: external_exports.record(external_exports.string(), external_exports.record(external_exports.string(), external_exports.unknown())).optional(),
29738
- runtimeTools: external_exports.array(
29739
- external_exports.object({
29740
- name: external_exports.string(),
29741
- description: external_exports.string(),
29742
- toolType: external_exports.enum([
29743
- "flow",
29744
- "custom",
29745
- "external",
29746
- "local",
29747
- "advisor",
29748
- "subagent",
29749
- "search"
29750
- ]),
29751
- parametersSchema: external_exports.record(external_exports.string(), external_exports.unknown()),
29752
- config: external_exports.record(external_exports.string(), external_exports.unknown())
29753
- })
29754
- ).optional(),
29755
- mcpServers: external_exports.array(
29756
- external_exports.object({
29757
- id: external_exports.string(),
29758
- name: external_exports.string().optional(),
29759
- url: external_exports.string(),
29760
- auth: external_exports.object({
29761
- type: external_exports.enum(["api_key", "bearer", "basic", "custom_header", "headers", "none"]),
29762
- headerName: external_exports.string().optional(),
29763
- token: external_exports.string().optional(),
29764
- username: external_exports.string().optional(),
29765
- password: external_exports.string().optional(),
29766
- // For `type: 'headers'`: arbitrary HTTP header name → value
29767
- // templates. The shared refinement below enforces the exclusive shape.
29768
- headers: external_exports.record(external_exports.string(), external_exports.string()).optional()
29769
- }).superRefine((auth, ctx) => {
29770
- const validation = validateMCPHeadersAuth(auth);
29771
- if (!validation.valid) {
29772
- ctx.addIssue({
29773
- code: "custom",
29774
- path: validation.path,
29775
- message: validation.message
29776
- });
29777
- }
29778
- }).optional(),
29779
- allowedTools: external_exports.array(external_exports.string()).optional(),
29780
- timeout: external_exports.number().optional(),
29781
- transport: external_exports.enum(["streamable_http", "rest"]).optional(),
29782
- enabled: external_exports.boolean().optional()
29783
- })
29784
- ).optional(),
29785
- maxToolCalls: external_exports.number().int().min(1).max(100).optional(),
29786
- toolCallStrategy: external_exports.enum(["auto", "required", "none"]).optional(),
29787
- approval: external_exports.object({
29788
- require: external_exports.union([external_exports.array(external_exports.string()), external_exports.boolean()]),
29789
- timeout: external_exports.number().optional(),
29790
- /** Opt out of agent-supplied approval reasons (`_approvalReason`
29791
- * schema injection). Default: true. Mirrors approvalConfigSchema
29792
- * in tool-types.ts. */
29793
- requestReason: external_exports.boolean().optional(),
29794
- /** Persistent "always" choices offered at the approval prompt.
29795
- * Mirrors approvalConfigSchema.choices in tool-types.ts. */
29796
- choices: external_exports.object({
29797
- alwaysAllow: external_exports.boolean().optional(),
29798
- alwaysDeny: external_exports.boolean().optional()
29799
- }).optional()
29800
- }).optional(),
29801
- perToolLimits: external_exports.record(
29802
- external_exports.string(),
29803
- external_exports.object({
29804
- maxCalls: external_exports.number().optional(),
29805
- required: external_exports.boolean().optional()
29806
- })
29807
- ).optional(),
29808
- subagentConfig: external_exports.object({
29809
- toolPool: external_exports.array(external_exports.string()),
29810
- defaultMaxTurns: external_exports.number().int().min(1).max(100).optional(),
29811
- maxTurnsLimit: external_exports.number().int().min(1).max(100).optional(),
29812
- maxSpawnsPerRun: external_exports.number().int().min(1).max(50).optional(),
29813
- defaultModel: external_exports.string().optional(),
29814
- allowNesting: external_exports.boolean().optional(),
29815
- // Max must stay <= the dispatch `options.stepTimeoutMs` cap
29816
- // (600_000 — `api-schemas/dispatch.ts`): `resolveSubagentTimeouts`
29817
- // (apps/api subagent dispatch) stamps the child flow's
29818
- // `stepTimeoutMs` from the subagent's effective timeout. Keep the
29819
- // two bounds in lockstep or 600s subagents break at the smaller cap.
29820
- defaultTimeoutMs: external_exports.number().int().min(1e3).max(6e5).optional(),
29821
- executionModes: external_exports.array(external_exports.enum(["attached", "detached"])).min(1).optional(),
29822
- defaultExecutionMode: external_exports.enum(["attached", "detached"]).optional(),
29823
- defaultNotify: external_exports.enum(["none", "narrate", "react"]).optional(),
29824
- detachedMaxBudgetMs: external_exports.number().int().min(1e3).max(864e5).optional(),
29825
- detachedNoProgressBudgetMs: external_exports.number().int().min(1e3).max(864e5).optional()
29826
- }).optional(),
29827
- codeModeConfig: external_exports.object({
29828
- toolPool: external_exports.array(external_exports.string()),
29829
- description: external_exports.string().optional(),
29830
- timeoutMs: external_exports.number().int().min(1e3).max(6e5).optional()
29831
- }).optional()
29832
- }).optional(),
29833
- artifacts: artifactConfigSchema.optional(),
29834
- reasoning: reasoningConfigSchema.optional(),
29835
- advisor: external_exports.object({
29836
- model: external_exports.string(),
29837
- systemPrompt: external_exports.string().optional()
29838
- }).optional().nullable(),
29839
- loopConfig: external_exports.object({
29840
- maxTurns: external_exports.number().int().min(1).max(100).optional(),
29841
- maxCost: external_exports.number().min(0).optional(),
29842
- enableReflection: external_exports.boolean().optional(),
29843
- reflectionInterval: external_exports.number().int().min(1).max(50).optional()
29844
- }).optional(),
29845
- voice: external_exports.object({
29846
- enabled: external_exports.boolean().optional(),
29847
- provider: external_exports.string().optional(),
29848
- interruptionMode: external_exports.enum(["none", "cancel", "barge-in"]).optional(),
29849
- elevenLabs: external_exports.object({
29850
- voiceId: external_exports.string().optional(),
29851
- modelId: external_exports.string().optional(),
29852
- stability: external_exports.number().min(0).max(1).optional(),
29853
- similarity: external_exports.number().min(0).max(1).optional()
29854
- }).optional()
29855
- }).optional(),
29856
- errorHandling: errorHandlingSchema,
29857
- loggingPolicy: external_exports.enum(["default", "on", "off"]).optional(),
29858
- // Opt-in PII redaction for tail-log and telemetry payloads. `'default'`
29859
- // defers to a lower layer (surface/product) or the resolver default (off).
29860
- // Mirrors `loggingPolicy`.
29861
- piiRedaction: external_exports.enum(["default", "off", "redact"]).optional(),
29862
- // Opt-in temporal awareness. `injectElapsed` turns on the automatic
29863
- // "time has passed" decorator (a `<temporal_context>` block prepended to
29864
- // the user turn at dispatch, gated on turn ≥ 2 and a gap ≥
29865
- // `elapsedThresholdSeconds`). `groundNow` additionally surfaces the current
29866
- // datetime in that block. `timezone` is the agent's DEFAULT IANA zone —
29867
- // the layered tool/decorator resolution overrides it per-conversation.
29868
- temporal: temporalConfigSchema.optional(),
29869
- // Long-term memory (Cloudflare Agent Memory). Single-sourced as
29870
- // `memoryConfigSchema` (below) and reused by the update-agent, dispatch
29871
- // inline-agent, and FPO agent schemas so the four surfaces never drift —
29872
- // mirroring how `temporalConfigSchema` is shared.
29873
- memory: memoryConfigSchema.optional(),
29874
- // Agent Sandbox (Linux computer). When enabled, the agent gets the sandbox
29875
- // builtin tools + system-prompt frame at dispatch. Single-sourced as
29876
- // `sandboxConfigSchema` (above), mirroring `memory`. The live machine is agent
29877
- // state; this block is the operator Definition that enables it.
29878
- sandbox: sandboxConfigSchema.optional(),
29879
- // Tenancy Strategy (ADR 0012) — per-resource opt-in to tenant/end-user
29880
- // isolation. Part of the Definition (validated + persisted + content-hashed
29881
- // here so `ensure` tracks it). Absent → platform-global default (no behavior
29882
- // change); present → the execution pipeline expands it and enforces the
29883
- // lock-down gate pre-engine. Single-sourced as `tenancyStrategySchema` in
29884
- // `./tenancy-strategy`; the expansion + gate logic lives in apps/api.
29885
- tenancyStrategy: tenancyStrategySchema.optional()
29886
- }).strict();
29887
29934
  var identityAdapterKindSchema = external_exports.enum(["oidc-jwt", "session", "custom"]);
29888
29935
  var ASYMMETRIC_JWT_ALGORITHMS = [
29889
29936
  "RS256",
@@ -30117,7 +30164,12 @@ var agentReasoningConfigSchema = external_exports.object({
30117
30164
  reasoningEffort: external_exports.enum(["minimal", "low", "medium", "high", "xhigh"]).optional(),
30118
30165
  reasoningSummary: external_exports.enum(["auto", "detailed"]).optional(),
30119
30166
  budgetTokens: external_exports.number().int().min(1e3).max(1e5).optional(),
30167
+ // Anthropic adaptive thinking / Gemini 3+ level mode. Free-form for the same
30168
+ // per-model catalog-ladder reason as `reasoningConfigSchema` in
30169
+ // `agent-runtime-config-schema.ts`; kept in lockstep with it.
30170
+ effort: external_exports.string().min(1).max(32).optional(),
30120
30171
  thinkingBudget: external_exports.number().int().min(1024).max(65536).optional(),
30172
+ thinkingLevel: external_exports.string().min(1).max(32).optional(),
30121
30173
  includeThoughts: external_exports.boolean().optional()
30122
30174
  });
30123
30175
  var agentVoiceConfigSchema = external_exports.object({
@@ -32459,7 +32511,7 @@ var DispatchRequestEnvelopeSchema = external_exports.object({
32459
32511
  */
32460
32512
  clientToolsPolicy: ClientToolsPolicySchema.optional(),
32461
32513
  secrets: external_exports.record(external_exports.string(), external_exports.string()).optional().describe(
32462
- "Per-request credentials for agent/external-tool execution. Ignored when `flow` is the hosted target; FLOW credentials must use managed {{secret:NAME}} references."
32514
+ "Retired. A NON-EMPTY map on an agent dispatch is rejected with 400 RUNTIME_AGENT_TRANSIENT_SECRETS_UNSUPPORTED, unless the deprecated `options.useRuntimePackage: false` opt-out routes the run to the legacy engine, which still honors it for single-turn (non-loop) agents until that engine is removed. An empty map is accepted and does nothing. Ignored on flow dispatches. Store credentials as managed secrets and reference them as {{secret:NAME}}. The field is kept on the wire for compatibility only."
32463
32515
  ),
32464
32516
  credentialProxies: external_exports.array(credentialProxyConfigSchema).max(10).optional(),
32465
32517
  inputs: external_exports.record(external_exports.string(), external_exports.any()).optional().refine(
@@ -32502,7 +32554,7 @@ var DispatchRequestEnvelopeSchema = external_exports.object({
32502
32554
  debugMode: external_exports.boolean().optional().default(false),
32503
32555
  loggingPolicy: external_exports.enum(["default", "on", "off"]).optional(),
32504
32556
  useRuntimePackage: external_exports.boolean().optional().describe(
32505
- "Compatibility execution-lane OPT-OUT. For FLOW dispatches the field is accepted but ignored: eligible flows always use the @runtypelabs/runtime lane, while ineligible flows still fold to legacy silently. For AGENT dispatches, an eligible agent now uses the @runtypelabs/runtime lane by DEFAULT when this field is omitted; only an explicit `false` forces the legacy engine. Definitions the runtime lane cannot execute faithfully still fold to legacy on their own."
32557
+ "Execution-lane selector. `false` is DEPRECATED: the legacy agent engine is being retired, an agent dispatch that sends `false` still runs on it today with RFC 9745 `Deprecation` + `X-API-Deprecation-Warning` response headers, and a later release rejects it. Omitted (the default) runs an eligible agent on the @runtypelabs/runtime lane and folds a definition the lane cannot execute faithfully to legacy on its own; `true` is the strict opt-in that turns such a fold into a 400 instead. For FLOW dispatches the field is accepted but ignored: eligible flows always use the runtime lane, while ineligible flows still fold to legacy silently."
32506
32558
  ),
32507
32559
  /** Route prompt model calls through an attached dashboard browser. */
32508
32560
  localInference: LocalInferenceSelectionSchema.optional(),
@@ -53354,18 +53406,15 @@ agentsCommand.command("execute <id>").description("Execute an agent").requiredOp
53354
53406
  const apiKey = await ensureAuth();
53355
53407
  if (!apiKey) return;
53356
53408
  const client = createCliClient(apiKey);
53409
+ const messages = [{ role: "user", content: options.message }];
53357
53410
  const payload = {
53358
- messages: [{ role: "user", content: options.message }],
53411
+ messages,
53359
53412
  streamResponse: options.stream
53360
53413
  };
53361
53414
  if (options.stream) {
53362
53415
  console.log(chalk25.gray("Starting agent..."));
53363
53416
  try {
53364
- const response = await client.requestStream(`/agents/${id}/execute`, {
53365
- method: "POST",
53366
- body: JSON.stringify(payload),
53367
- headers: { Accept: "text/event-stream" }
53368
- });
53417
+ const response = await client.agents.executeStream(id, { messages });
53369
53418
  const callbacks = {
53370
53419
  onStepDelta: (chunk) => {
53371
53420
  process.stdout.write(chunk);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/cli",
3
- "version": "2.35.1",
3
+ "version": "2.35.2",
4
4
  "description": "Command-line interface for Runtype AI platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,8 +26,8 @@
26
26
  "react": "^19.2.8",
27
27
  "rosie-skills": "0.8.1",
28
28
  "yaml": "^2.9.0",
29
- "@runtypelabs/sdk": "9.2.1",
30
29
  "@runtypelabs/ink-components": "0.3.7",
30
+ "@runtypelabs/sdk": "9.3.0",
31
31
  "@runtypelabs/terminal-animations": "0.2.4"
32
32
  },
33
33
  "devDependencies": {
@@ -43,7 +43,7 @@
43
43
  "tsx": "^4.7.1",
44
44
  "typescript": "^6.0.3",
45
45
  "vitest": "^4.1.0",
46
- "@runtypelabs/shared": "3.34.2"
46
+ "@runtypelabs/shared": "3.35.0"
47
47
  },
48
48
  "engines": {
49
49
  "node": ">=22.12.0"