@runtypelabs/sdk 9.3.0 → 9.3.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.
- package/CHANGELOG.md +3457 -0
- package/dist/index.cjs +28 -85
- package/dist/index.d.cts +130 -631
- package/dist/index.d.ts +130 -631
- package/dist/index.mjs +28 -85
- package/package.json +1 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,3457 @@
|
|
|
1
|
+
# @runtypelabs/sdk
|
|
2
|
+
|
|
3
|
+
## 9.3.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ccd07e2: Report a truncated agent turn as a failure instead of a clean completion. When a model turn ends with the provider finish reason `length` while a tool call's arguments are still streaming, the agent loop now stops with the loop-level `stopReason: 'length'` and `success: false` — previously the run reported `success: true` / `stopReason: 'complete'` with an empty output and an unpaired tool start that was only discoverable by pairing trace events. `decideLoopContinuation` gains the matching `length_cutoff` reason on both the runtime and its api twin, and the cutoff verdict outranks `max_cost` so a run that trips both is still reported as failed.
|
|
8
|
+
|
|
9
|
+
The cutoff is attributed per tool call, not per turn. A turn that runs a multi-step authored flow ends on its LAST prompt step's stop reason, so each unpaired `tool_start` is stamped with the stop reason of the step that owned it: an early step that truncated mid tool call fails the run even when a later step ends cleanly, and an unpaired start from a clean step no longer fails a run whose last step merely truncated its text.
|
|
10
|
+
|
|
11
|
+
Every `tool_start` the loop leaves in flight at turn end is now closed by a synthesized failed `tool_complete`, under any stop reason rather than only the cutoff — an unpaired start was previously discarded when the next turn began. The cutoff close-out names the output-token limit; any other unresolved start reports that the turn ended first.
|
|
12
|
+
|
|
13
|
+
The loop-level stop reason and any salvaged reply are now observable: `execution_error` carries an optional `stopReason` and an optional `finalOutput` (both loose, like `execution_complete`'s), emitted by both the runtime emitter and the api's legacy translator. The buffered `/v1/dispatch` agent envelope reports the same verdict that `agent_executions.stop_reason` persists instead of hard-coding `error`, the SDK's `execution_error` → `agent_complete` fold forwards it rather than flattening it to `error`, and both durable readers project a failure terminal through one shared helper. A cut-off run still spends its final-reply elicitation turn, and a messaging surface delivers that salvaged sentence instead of the surface's generic error message while still recording the run as failed. The run's span no longer reports status OK.
|
|
14
|
+
|
|
15
|
+
MIGRATION: this changes the default verdict for an existing agent whose turns are truncated mid tool call — a run that used to report `success: true` with empty output now reports `success: false` with `stopReason: 'length'`. The fix is to raise the agent's `maxTokens`. To pin the old verdict while you do, set the new `loopConfig.treatLengthCutoffAsFailure` to `false`; it defaults to `true`, and the synthesized failed `tool_complete` close-outs are emitted either way.
|
|
16
|
+
|
|
17
|
+
- 8ab7d4a: Apply flow and agent version snapshots to the live execution rows atomically when publishing from any API surface.
|
|
18
|
+
|
|
19
|
+
## 9.3.1
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- 95e48e6: Address the /review findings on the legacy agent-loop retirement (#7824). No
|
|
24
|
+
behavior changes beyond three consolidated error bodies and the deletion of code
|
|
25
|
+
the retirement left unreachable; the rest is documentation and message text that
|
|
26
|
+
still described the deleted engine as a live destination.
|
|
27
|
+
- **One parity-fold refusal for three hosts.** `/v1/dispatch`,
|
|
28
|
+
`/v1/agents/:id/execute` and the Product API answered the same defect with
|
|
29
|
+
three different bodies, one of which told the author to "dispatch it via POST
|
|
30
|
+
/v1/dispatch (which routes folded definitions to the legacy engine)" — a dead
|
|
31
|
+
end now that lane returns a 400 of its own. All three share
|
|
32
|
+
`parityFoldRefusal()`, so the response is `400
|
|
33
|
+
RUNTIME_AGENT_PARITY_FOLD_UNSUPPORTED` with the fold classes as evidence.
|
|
34
|
+
- **Remediation text no longer prescribes the retired opt-out.** The agent-save
|
|
35
|
+
advisory, the admission reason strings, the runtime-package gate messages, the
|
|
36
|
+
`dispatch` request-schema descriptions (public spec + SDK cores + MCP tool
|
|
37
|
+
inputs), the client SDK JSDoc, two knowledge fragments and two Fern docs pages
|
|
38
|
+
now describe the terminal answer and append `LEGACY_LANE_NO_BRIDGE_REMEDY`.
|
|
39
|
+
- **Internal census truthfulness.** Three log lines said "internal execution runs
|
|
40
|
+
on the legacy engine" while the census already reported `refused`; they now
|
|
41
|
+
agree.
|
|
42
|
+
- **Deletion residue removed:** the unsatisfiable local-inference guard in
|
|
43
|
+
`/v1/dispatch` and its `LOCAL_INFERENCE_UNAVAILABLE` export,
|
|
44
|
+
`lib/virtual-agent-summary.ts`, and five knip-verified dead modules
|
|
45
|
+
(`scripts/test-loop-standalone.ts`, which imported the deleted agent executor
|
|
46
|
+
and was therefore broken, `services/webhook-doc-crawler.ts`,
|
|
47
|
+
`lib/agent-memory/cf-types-compat.ts`, `lib/constants/record-limits.ts`,
|
|
48
|
+
`lib/email/index.ts`).
|
|
49
|
+
|
|
50
|
+
## 9.3.0
|
|
51
|
+
|
|
52
|
+
### Minor Changes
|
|
53
|
+
|
|
54
|
+
- 6bfcfa0: Durable-by-default agent turns (ADR 0020): the `runtype_managed` agentType is deleted and durability becomes the default property of every agent turn, decided once at admission by the pure `turn-durability-policy` (outs: parity fold, Flagship `enable-durable-agent-turns` rule, per-agent `config.durability.forced` pin). The session DO adopts the `SessionEventStore` ledger with post-engine filters before journaling and single relay-owned SSE `id:` lines, gains a bounded recovery engine (incident record, budgets, sealed terminal reasons, recover-on-any-wake, sub-turn continuation with orphaned-tool repair), a 7-day parked-turn TTL with a resume-vs-expiry CAS, and two-phase fenced claim/start concurrency (`reject` / `supersede` / `queue` + `coalesce`, admission `idempotencyKey`) with every rejectable check ahead of the daily-quota reservation. Harness knobs move to `config.durability { watchLeaseMs, maxBudgetMs, forced }`.
|
|
55
|
+
|
|
56
|
+
### Patch Changes
|
|
57
|
+
|
|
58
|
+
- 20f2a28: Deprecate the `options.useRuntimePackage: false` legacy execution-lane opt-out on `/v1/dispatch`. The legacy agent engine is being retired: an agent dispatch that still sends `false` runs on it for one more release and its response now carries RFC 9745 `Deprecation` and `X-API-Deprecation-Warning` headers; a later release rejects `false`. The value is deprecated, not the field: omitting it selects the runtime lane, and `true` remains the strict opt-in that fails loudly instead of folding to legacy. The OpenAPI spec, SDK types and MCP `dispatch` tool input describe the new contract, every API remediation that still names the opt-out calls it a deprecated bridge, and the dashboard's agent test chat no longer sends `false` (it was forcing every dashboard agent test onto the legacy engine).
|
|
59
|
+
- 9ac677d: Carry the Anthropic adaptive-thinking effort and the Gemini thinking level all the way to the model request.
|
|
60
|
+
|
|
61
|
+
`buildReasoningOptions` mapped a flat `ReasoningConfig` onto `anthropic: { budgetTokens }` and `google: { thinkingBudget, includeThoughts }` only, while `buildReasoningProviderOptions` reads `effort` in the Anthropic adaptive branch and `thinkingLevel` in the Google branch. On Claude 4.6 and later, including the Claude 5 family that left the model with no working reasoning dial at all: adaptive thinking discards `budgetTokens`, and the effort it does accept was never mapped. Gemini 3 level mode had the same shape.
|
|
62
|
+
|
|
63
|
+
`ReasoningConfig` gains `effort` and `thinkingLevel` (plain strings, because the accepted rungs are per-model catalog data that already exceeds the fixed `reasoningEffort` union), the agent config and FPO agent schemas accept them, the execution contract and the model-gateway wire schema carry them, and both prompt executors map them into their own provider bucket. Neither is cross-filled from `reasoningEffort`, which is the OpenAI ladder. The api and runtime mappings move together and are pinned by three new cases in the shared prompt-executor parity corpus.
|
|
64
|
+
|
|
65
|
+
- 9ac677d: Expose per-model reasoning knobs on the model-configuration surfaces, and warn at save time when a reasoning config asks for a knob the model does not accept.
|
|
66
|
+
|
|
67
|
+
`GET /v1/model-configs` and `GET /v1/model-configs/grouped` now carry the catalog-sourced `reasoningCapability.options` (`toggle` / `effort` ladder / `budgetTokens` range), `anthropicThinkingMode` and `builtInReasoning`, so a client can render the dials a model actually has instead of a per-provider guess. The committed OpenAPI spec and the generated SDK types are regenerated for the new fields.
|
|
68
|
+
|
|
69
|
+
The model-advisory pass gains one non-blocking code, `REASONING_KNOB_UNSUPPORTED` (warning, never error): an effort level outside the model's published ladder, a `budgetTokens` on an Anthropic model the executor drives in adaptive thinking mode (which carries no token budget and drops the value before the request), or a thinking budget outside the model's published range. The effort check reads only the carrier the executor actually reads for that provider, so a level stranded on a field the request never carries (a Gemini row that stored its thinking level under the OpenAI effort field) is no longer reported as unsupported. It stays silent whenever the catalog makes no claim about the model, on the boolean `reasoning: true` form, on an explicit `enabled: false`, and on disabled steps.
|
|
70
|
+
|
|
71
|
+
- e1111dc: Retire dispatch-transient `secrets` on agent dispatches.
|
|
72
|
+
|
|
73
|
+
An agent dispatch that carries a NON-EMPTY request-scoped `secrets` map is now
|
|
74
|
+
answered with a terminal 400 `RUNTIME_AGENT_TRANSIENT_SECRETS_UNSUPPORTED`.
|
|
75
|
+
Previously only an explicit `options.useRuntimePackage: true` was refused; a
|
|
76
|
+
caller who never set the option was folded onto the legacy agent engine so the
|
|
77
|
+
field could keep working. An empty map is still accepted and does nothing, and
|
|
78
|
+
the deprecated `options.useRuntimePackage: false` opt-out still routes the run
|
|
79
|
+
to the legacy engine, which honors the map for single-turn agents until that
|
|
80
|
+
engine is removed. Dispatch-transient secrets are retired
|
|
81
|
+
platform-wide (D-080, amended 2026-08-27), the census counted zero occurrences
|
|
82
|
+
in 30 days on both the fold line and the refusal line, and the fold was routing
|
|
83
|
+
callers onto an engine being deleted to honor a contract being deleted. Store
|
|
84
|
+
the value as a managed secret and reference it as `{{secret:NAME}}`.
|
|
85
|
+
|
|
86
|
+
The remediation is terminal: it no longer prescribes the deprecated
|
|
87
|
+
`options.useRuntimePackage: false` bridge. The wire field stays on the dispatch
|
|
88
|
+
schema for compatibility, with its description (and the regenerated OpenAPI
|
|
89
|
+
spec, SDK types and MCP `dispatch` input schema) rewritten to say retired. Flow
|
|
90
|
+
dispatches are unchanged: they have always accepted and ignored the field.
|
|
91
|
+
|
|
92
|
+
- 6bfcfa0: Add the `runtype_managed` agent execution mode (slice 0: mode plumbing). A new `agentType` value classifies agents onto a durable self-hosted session harness (staging-only, flag-gated via the env-pinned `enable-runtype-managed` Flagship gate plus the fail-closed `runtype-managed-agents` Schematic flag). This slice lands the classification, the `agents.runtype_managed_config` column and route schemas, and loud rejections at every execution surface so the mode can never silently degrade into the in-request loop; the session DO harness and entry-surface wiring land in follow-up slices. Design: `docs/features/planning/2026-07-31-runtype-managed-harness.md`.
|
|
93
|
+
|
|
94
|
+
## 9.2.1
|
|
95
|
+
|
|
96
|
+
### Patch Changes
|
|
97
|
+
|
|
98
|
+
- a370a11: Surface the model credit promo (ADR 0021) everywhere models are listed, not only in the dashboard picker.
|
|
99
|
+
- Every model-listing route (`GET /v1/model-configs`, `/v1/model-configs/grouped`, `/v1/model-configs/available`) now stamps `creditPromoMultiplier` (e.g. `0.1`) and a plain-language `creditPromoLabel` (e.g. `"90% off"`, `null` when undiscounted) on each row, computed server-side from the same eligibility rule the billing seam uses and gated on platform-key custody. Routed families (`runtype:deepseek-v4-flash`) resolve through the routing table to their Workers AI primary, so a discounted route is advertised even when the id says nothing about Workers AI. MCP (`list_available_models`, `list_model_configs`, `list_model_configs_grouped`), the SDK and the CLI all read the same fields.
|
|
100
|
+
- Dashboard: Settings → Models rows and the Add Model dialog show the callout next to the model name; the Add Model dialog gains a "Discounted" filter that appears only while a promo is active. The model picker prefers the server label and falls back to the shared predicate.
|
|
101
|
+
|
|
102
|
+
## 9.2.0
|
|
103
|
+
|
|
104
|
+
### Minor Changes
|
|
105
|
+
|
|
106
|
+
- d129b45: Add bounded Flow loops and durable asynchronous execution handles with pollable status results.
|
|
107
|
+
- 005b795: First-party MCP catalog tools now cross the dashboard assistant's dispatch as name-only `runtype-mcp` catalog refs that the api hydrates from its own copy of the catalog, instead of full browser-supplied manifests. `clientTools[]` accepts `{ name, catalog: 'runtype-mcp' }` beside the existing `InlineClientTool` shape on `POST /v1/dispatch` and `POST /v1/agents/:id/execute`; an unknown ref is a 400, never a silent drop. Because the catalog no longer crosses the browser, the per-string `parametersSchema` cap returns from a provisional 8KB to 2KB (runtypelabs/core#7617).
|
|
108
|
+
|
|
109
|
+
No entry is exempt from the byte caps. The catalog clears 2KB on its own merits after the description rewrite (longest string 1894 bytes), and the host proxy collapses first-party tools to refs before dispatch, so a browser bundle loaded before this ships keeps working rather than sending manifests the new cap rejects.
|
|
110
|
+
|
|
111
|
+
`@runtypelabs/sdk` gains `CatalogClientToolRef` / `ClientToolEntry` / `isCatalogClientToolRef`, and `dispatch()` forwards a ref instead of throwing on its absent `parametersSchema`.
|
|
112
|
+
|
|
113
|
+
MCP tool and parameter descriptions were rewritten to be terse and factual; the flow step `config` description dropped from 4.4KB to under 2KB, with its uncovered caveats (send-email `html`, vector-search qualifiers, `loop`, recordFilter operators) moved into the `generate-flow` build instructions.
|
|
114
|
+
|
|
115
|
+
- 235751c: Report exact raw Runtype-funded provider and hosted-tool cost separately from blended execution cost.
|
|
116
|
+
- dd54ba0: Allow detached Flow dispatches to run with 30-minute Flow and step budgets, and expose those controls on MCP and Code Mode `run_flow` helpers.
|
|
117
|
+
- b2ac8a0: Harden durable asynchronous execution authorization, encrypted storage, native Claude Managed status polling, and SDK surface parity.
|
|
118
|
+
- dae3030: Add the agent key request contract and MCP tools. `@runtypelabs/shared` owns the
|
|
119
|
+
wire contract and the canonical `runtype.api-key/v1` key-file format that the
|
|
120
|
+
CLI writer and dashboard download both emit. The MCP server gains
|
|
121
|
+
`request_api_key`, `claim_api_key`, and `cancel_api_key_request`: filing a
|
|
122
|
+
request generates its own PKCE verifier and raises the approval page through URL
|
|
123
|
+
elicitation where the client supports it, and redemption defaults to storing the
|
|
124
|
+
minted key as a Runtype secret so only a `{{secret:KEY}}` reference reaches the
|
|
125
|
+
conversation. The secret-intake URL-elicitation helpers are generalized into a
|
|
126
|
+
reusable handoff helper that both flows now share, with unchanged secret-intake
|
|
127
|
+
behavior. The SDK gains the matching request/get/claim/cancel methods.
|
|
128
|
+
- c5a5baf: Exported runtime artifacts now DECLARE their host dependencies instead of being rejected for them (D-116).
|
|
129
|
+
|
|
130
|
+
`GET /v1/flows/{id}/export-runtime` no longer answers `422 DURABLE_FLOW_EXPORT_UNSUPPORTED` for a flow carrying a durable-class step (`wait-until` / `crawl`). That code is retired. Both export responses — flow and agent — now carry an additive `hostDependencies` array naming the runtime seams the artifact needs a host to wire before it can run everything it describes:
|
|
131
|
+
- `durable-pause-host` (`ExecuteFlowOptions.onDurablePause`, with `ExecuteAgentOptions.onDurablePause` as the agent-lane sibling) for durable-class steps anywhere in the artifact's executable closure;
|
|
132
|
+
- `background-run-coordinator` (`RuntimeToolExecutorDeps.backgroundRunCoordinator`) for a detached-capable `tools.subagentConfig` pool or a detached inline subagent tool.
|
|
133
|
+
|
|
134
|
+
Each entry carries the seam name, the reason, and the sites that caused it with full closure provenance (`ownerKind` / `ownerId` / `ownerName`), so a site living in an embedded agent, a capability, or an inline tool's backing definition is findable. The array is always present and empty when nothing needs wiring. The shape is a discriminated union on `kind` declared once in `@runtypelabs/shared` (`runtimeHostDependencySchema`); consumers should render `interface` and `reason` for a `kind` they do not recognise rather than failing.
|
|
135
|
+
|
|
136
|
+
The Workers-for-Platforms artifact lane is unchanged: a durable-class step is still a permanent `durable_steps_hosted_only` ineligibility reason there, because Cloudflare Workflows cannot live in a WfP dispatch namespace and that host is not the customer's to wire.
|
|
137
|
+
|
|
138
|
+
### Patch Changes
|
|
139
|
+
|
|
140
|
+
- b216c6a: Follow-ups to the D-107 durable-flow export rejection (#7634).
|
|
141
|
+
|
|
142
|
+
Each entry in the `422` `durableSteps` array now carries provenance — `ownerKind` (`flow` / `agent` / `capability` / `inline-tool`) plus `ownerId` and `ownerName` where they exist — and the rejection message names the carrier. The check covers a flow's whole executable closure, so a bare `stepId` routinely named a step that appears nowhere in the flow the caller is editing.
|
|
143
|
+
|
|
144
|
+
The closure walk also got three correctness fixes: a nested flow's own embedded agent registry is swept (previously only the root flow's was, so an agent reachable only through a flow-tool backing flow was never inspected); an agent capability's `tool` payload is descended like any other inline runtime tool (previously only `flow` and `subAgent` were); and the fixed ten-hop closure recursion bound — which failed OPEN, exporting a durable step found past it — is replaced by a worklist with an identity visited-set that terminates without ever declining to look.
|
|
145
|
+
|
|
146
|
+
`MAX_CONDITIONAL_NESTING_DEPTH` is now exported from `@runtypelabs/shared`, so the export gate imports the validator's own cap instead of restating it, and `isDurableStepType` replaces the last two hand-restated `wait-until` / `crawl` literal pairs.
|
|
147
|
+
|
|
148
|
+
- edefa3c: Enforce single-config delegated external Agent evals and correlate their synthetic step and tool traces with the public runtime execution ID.
|
|
149
|
+
- f95b02e: A messaging human takeover now lapses and the agent resumes after the surface's `interventionMode.takeoverIdleTimeoutMinutes` (default 24 hours, `0` disables) with no operator send. The lapse is evaluated at the dispatch gate on the next inbound, applied as a compare-and-set on the observed `takeoverAt`, and logged as `conversation_takeover_lapsed`. Closing or reopening a conversation (`PUT /v1/messaging/conversations/{id}` status changes, `closeConversation`, the `/new` reset) now clears the takeover so a reopened thread never inherits a stale mute. Every `agent_mode` writer lives in `apps/api/src/services/messaging-takeover.ts`.
|
|
150
|
+
- f5250b6: Make saved external-agent authentication credentials write-only on agent
|
|
151
|
+
management responses. Create, update, detail, and agent-card refresh responses
|
|
152
|
+
now return `<redacted>` instead of plaintext, while safe same-auth-type PUT
|
|
153
|
+
round trips preserve the sealed credential and cross-host repoints still require
|
|
154
|
+
the caller to resend the real credential. Clients that copy an agent read into
|
|
155
|
+
a create request must now inject the original credential from their secret
|
|
156
|
+
manager instead of treating the read response as a credential export.
|
|
157
|
+
- e305a29: Key a sandbox's injected egress state by execution owner instead of holding it
|
|
158
|
+
DO-level, so concurrent code-execution steps sharing one sandbox id can no
|
|
159
|
+
longer clobber or prematurely clear each other's credentials.
|
|
160
|
+
|
|
161
|
+
`reuseSandboxId` is an author-supplied string, and a constant collapses every
|
|
162
|
+
concurrent execution of a flow, for one organization, onto one sandbox id. The
|
|
163
|
+
injected API token, credential-proxy rules and `networkAccess` posture were
|
|
164
|
+
plain instance fields on `CloudflareSandboxDO`, so the last writer won: a step
|
|
165
|
+
could run under another step's egress posture and another user's token, and a
|
|
166
|
+
sibling's cleanup cleared credentials a live step was still using.
|
|
167
|
+
|
|
168
|
+
Each execution now holds one grant keyed by its containment owner id and
|
|
169
|
+
releases only its own on the way out. A grant that asks for a different API
|
|
170
|
+
token or a different `networkAccess` than a live sibling is refused and its
|
|
171
|
+
step fails with an actionable error, since a shared container has no honest
|
|
172
|
+
merge for a container-wide posture; an omitted dimension resolves against the
|
|
173
|
+
ambient layer rather than inheriting a sibling's, so an execution that asked
|
|
174
|
+
for the fail-closed default never gains a neighbour's open egress. Every
|
|
175
|
+
execution takes a grant, including one that injects nothing — it has a posture
|
|
176
|
+
too, and leaving it uncounted would let it run under a sibling's broader
|
|
177
|
+
egress. Identical
|
|
178
|
+
credential-proxy rules compose — phantom tokens are persisted per secret, so
|
|
179
|
+
concurrent runs of one flow legitimately present the same phantom, and only a
|
|
180
|
+
phantom resolving to a different rule is refused. Grants carry their
|
|
181
|
+
execution's containment deadline, so an abandoned step stops refusing siblings
|
|
182
|
+
once its own budget lapses. The long-lived callers whose credentials
|
|
183
|
+
deliberately outlive one call (`deployWithPreview`, the agent tool lane's
|
|
184
|
+
`setNetworkAccess`) keep an ambient layer that a scoped release now restores
|
|
185
|
+
rather than wipes.
|
|
186
|
+
|
|
187
|
+
- 2783291: Finished the Slack OAuth install server-side, so a headless caller no longer needs the dashboard popup to complete setup. `POST /v1/oauth/slack/start` now accepts an optional `surfaceId`, validates that the surface exists and belongs to the caller before minting the encrypted state blob (400 on a malformed id, 404 on a missing or foreign one), and carries the id across the redirect; the callback then stamps the claim result onto that surface's inbound config (`integrationId`, `teamId`, `teamName`, `appId`, `botUserId`) and activates it — the same write the dashboard wizard performs client-side today. Stamping is idempotent, re-checks ownership at callback time, and never fails the OAuth: a surface deleted mid-handshake is logged and the install still completes, and a failed claim leaves the surface untouched. State blobs minted before the field existed keep parsing, and `SlackOAuthStartRequest` in the TypeScript SDK carries the new optional field. Separately, `POST /v1/integrations/slack/install` now enforces the `INTEGRATIONS:WRITE` API-key scope that every sibling integrations mutation route already required; it was missing.
|
|
188
|
+
|
|
189
|
+
## 9.1.1
|
|
190
|
+
|
|
191
|
+
### Patch Changes
|
|
192
|
+
|
|
193
|
+
- 7aea953: Follow-ups to the #6049 §D10 wire fixes: the AG-UI translator synthesizes a `TOOL_CALL_START` for complete-only tool frames (the MCP discovery connection pseudo-tool) so strict AG-UI clients no longer see an orphan `TOOL_CALL_END`; the AG-UI runtime tee redacts the discovery pseudo-tool's raw connection-failure text on end-user streams; the SDK's `agent_tool_complete` event carries the frame's `error` field so complete-only failures stay diagnosable; the terminal error `code`/`details.errorName` invariant is folded into one `terminalErrorFields` helper.
|
|
194
|
+
- 9c9eb47: Close the #6049 §D5 agent-lifecycle re-audit (D-111..D-115).
|
|
195
|
+
- `execution_start` on the resume leg of a paused agent run now carries `resumed: true` (D-113). Consumers keep run-level state across a start that carries the flag; the SDK forwards it on `AgentStartEvent.resumed` and `executeWithLocalTools` fires `onAgentStart` once per session instead of once per leg.
|
|
196
|
+
- Terminal `execution_error.code` is a stable vocabulary on the runtime flow lane too (D-115): a generic throw reports `EXECUTION_FAILED` with the class name on `details.errorName` instead of leaking `Error` / `TypeError` as the code. `StepTimeoutError` and the `AbortError` / `TimeoutError` pair still pass through by name; structured codes keep precedence. `FlowLifecycleComplete.error.details` carries the same observability host-side.
|
|
197
|
+
- Pins for the ratified pause sequence (D-111), the agent-kind shape on external / Claude Managed lanes (D-112), and the abort terminal (D-114).
|
|
198
|
+
|
|
199
|
+
## 9.1.0
|
|
200
|
+
|
|
201
|
+
### Minor Changes
|
|
202
|
+
|
|
203
|
+
- ccdc5f6: Expose the first-class record/conversation `ownerId` on every client surface (#3395)
|
|
204
|
+
- **CLI**: `records list`, `records create`, and `records export` take `--owner-id`; `records update` takes `--owner-id` plus `--clear-owner` (an explicit `null`, which clears the stored owner — omitting both leaves it untouched). `conversations list` takes `--owner-id`. `records get`/`update` render the owner, and the CSV export gains an `ownerId` column.
|
|
205
|
+
- **SDK**: `CreateRecordRequest.ownerId` and `CreateConversationRequest.ownerId` / `UpdateConversationRequest.ownerId` accept `string | null`, so `records.update()` and `conversations.update()` can clear an owner.
|
|
206
|
+
- **MCP**: `create_record` / `create_conversation` accept `owner_id`; `update_record` / `update_conversation` accept a nullable `owner_id` where `null` clears the owner.
|
|
207
|
+
- **Code Mode MCP**: the `listRecords` / `createRecord` / `updateRecord` / `listConversations` / `createConversation` / `updateConversation` method docs describe `ownerId` and its null-clears semantics.
|
|
208
|
+
|
|
209
|
+
- ccdc5f6: Promote conversation/record `ownerId` to a dedicated indexed column (#3395)
|
|
210
|
+
- Adds `records.owner_id` (B-tree indexed) via migration `0148`, backfilling every existing row whose `metadata.ownerId` is a non-empty string.
|
|
211
|
+
- Converges every write seam onto the column — conversations create/update, records create/update (`POST/PUT /v1/records`), and dispatch `resolveRecord`. One precedence rule (`resolveRecordOwner`): a top-level `ownerId` wins over a nested `metadata.ownerId`, a legacy string nested value is promoted into the column, and the nested key is never persisted again. Update requests accept `ownerId: null` to clear the owner; omitting the field leaves it untouched.
|
|
212
|
+
- Conversation and record responses source the first-class `ownerId` from the column (`GET /v1/records` list/detail and the CSV export now return it) and strip a residual nested copy from the echoed metadata when the column is set.
|
|
213
|
+
- Extends the `?ownerId=` filter to `GET /v1/records` (and the CSV export), backed by plain index equality instead of JSONB extraction. The record-filter DSL (`recordFilter` on `retrieve-record` / `update-record` / `list-records` steps, schedule `record_filter`, `POST /v1/records/preview-filter`) treats `ownerId` as a top-level column on both execution lanes.
|
|
214
|
+
- Adds the `{{_record.ownerId}}` system variable (#7549) on both execution lanes, sourced from the column; the key is omitted (never `undefined`) when a record has no owner.
|
|
215
|
+
|
|
216
|
+
Behavior note: records written after deploy carry the owner only in the column, so `{{_record.metadata.ownerId}}` no longer resolves for them. Use `{{_record.ownerId}}` instead.
|
|
217
|
+
|
|
218
|
+
### Patch Changes
|
|
219
|
+
|
|
220
|
+
- b4c1858: `/v1/dispatch` agent loops now run on the `@runtypelabs/runtime` lane BY DEFAULT (legacy-engine retirement program, D-109 M1).
|
|
221
|
+
|
|
222
|
+
`options.useRuntimePackage` becomes an opt-OUT: an eligible agent dispatch that omits the field selects the runtime lane instead of the legacy engine. An explicit `false` still selects legacy verbatim, and every existing fold — `claude_managed` / no agent input, the parity-fold classes, and the unchanged request/definition support gates (`authoredDefinitionSupportIssue`) — still routes ineligible definitions to legacy.
|
|
223
|
+
|
|
224
|
+
Compatibility: a request that reaches the runtime lane through the new DEFAULT and then hits a support gate degrades to a legacy execution rather than returning HTTP 400. An explicit `useRuntimePackage: true` keeps rejecting exactly as before. Local agent inference no longer requires the explicit opt-in (it is refused only for an explicit opt-out).
|
|
225
|
+
|
|
226
|
+
- cf8dd74: Expose per-unit execution-engine attribution on the batch/eval read surfaces (#6106). `FlowStepResultSchema` (flow/record/batch step results), the eval results per-step rows, the eval run-scores per-case rows, and the schedules batch/run per-record results gain a nullable `executionEngine` ('runtime' | 'legacy'; null for rows written before attribution shipped or units that never executed), mapped verbatim from the persisted column. `GET /v1/batch/status/{id}` gains `executionEngineSummary` ('runtime' | 'legacy' | 'mixed' | null), derived at read time by aggregating the batch's per-record values — never inferred from IDs, sources, or models. SDK types regenerate from the updated spec.
|
|
227
|
+
- 901ee20: Return the per-execution metrics `record_results` already stores from `GET /v1/records/{id}/results`, and render them on a conversation turn.
|
|
228
|
+
|
|
229
|
+
`record_results` persists `total_tokens`, `model_used`, `execution_time_ms` and `estimated_cost` on every row the executor writes, but the handler's projection selected nine columns and none of them were these. The product Activity view is the only consumer that reads a conversation's turns, so a turn rendered with no latency, cost, tokens or model while an agent run beside it in the same merged list showed all four. Nothing failed and nothing logged: the fields were simply never on the wire, and a response schema that did not declare them agreed with the omission.
|
|
230
|
+
|
|
231
|
+
The projection and `RecordResultSchema` now carry all four, so they reach the OpenAPI spec and the generated TypeScript, Python, Ruby and Java SDK types. `estimatedCost` is declared as a string because `estimated_cost` is a `decimal(10,6)` column that reaches the wire unparsed, matching how `analytics.ts` already returns it.
|
|
232
|
+
|
|
233
|
+
The Activity turn pane renders them through the same `MetricCard` the run pane uses, so the two item kinds no longer read as different depths of detail. A turn carrying none of the four renders no metric block rather than four empty tiles. A new api-side contract test asserts set equality between the schema's fields and the query's projection, so neither half can drift from the other again.
|
|
234
|
+
|
|
235
|
+
- 86212a3: Make runs and conversations navigable instead of something you jump between.
|
|
236
|
+
|
|
237
|
+
Agent editor: closing the Test Agent sheet now routes to the run it produced,
|
|
238
|
+
detected by row identity rather than timestamps so it never depends on
|
|
239
|
+
client/server clock agreement, and never hijacks navigation when no run was
|
|
240
|
+
dispatched. The active tab and selected run round-trip through the URL
|
|
241
|
+
(`?tab=runs&run=…`), so a run can be linked, opened in a new tab, and reached
|
|
242
|
+
with the Back button. The Runs tab carries a run count and a failure dot, the
|
|
243
|
+
runs list gets keyboard triage, the per-run rail became a duration waterfall
|
|
244
|
+
instead of a second flat copy of the tool calls, and a stale run id renders a
|
|
245
|
+
recovery state rather than an endless skeleton.
|
|
246
|
+
|
|
247
|
+
Products: conversations are no longer reachable only from a hover-revealed icon
|
|
248
|
+
on a canvas node. A product-level Activity view lists runs and conversations
|
|
249
|
+
across every surface with a surface filter, surface nodes carry an activity and
|
|
250
|
+
failure signal, and the product header's stats link into Activity pre-filtered.
|
|
251
|
+
|
|
252
|
+
API: `agent_executions` gains a nullable `conversation_id`, exposed on the
|
|
253
|
+
executions list and detail responses, so consumers can group a multi-turn
|
|
254
|
+
thread's runs without a per-run log query. It is the run's own thread, distinct
|
|
255
|
+
from the existing `parent_conversation_id` (subagent lineage), and stays null on
|
|
256
|
+
stateless surfaces (webhook, schedule, eval, one-shot API) rather than being
|
|
257
|
+
synthesized from the execution id.
|
|
258
|
+
|
|
259
|
+
- 840934b: Force managed external-agent skill orchestration through Runtime at every whole-agent production entrance, including dispatch, internal jobs, webhook, messaging, client chat, voice, evals, nested agents, and surface overrides. Managed execution now fails closed rather than degrading to direct A2A delegation when Runtime is unavailable.
|
|
260
|
+
|
|
261
|
+
## 9.0.0
|
|
262
|
+
|
|
263
|
+
### Major Changes
|
|
264
|
+
|
|
265
|
+
- b01026e: Repair foreign-key drift across environments, separate asset storage identity from canonical ownership without breaking rollback Workers, and preserve organization-owned tools and skills when their creating user is deleted.
|
|
266
|
+
|
|
267
|
+
### Patch Changes
|
|
268
|
+
|
|
269
|
+
- 7a5cf94: Persist the post-approval assistant turn on `POST /v1/client/resume`
|
|
270
|
+
|
|
271
|
+
A client-tool (WebMCP) pause is a terminal success, so the pausing
|
|
272
|
+
`/v1/client/chat` turn wrote its assistant message with the gated calls still in
|
|
273
|
+
`state: 'call'` and finished, while the resume that carried the approved tool
|
|
274
|
+
outputs wrote nothing at all. Everything the model produced after the approval
|
|
275
|
+
only reached the conversation record when a later chat turn happened to re-send
|
|
276
|
+
the browser's own copy of it, so a conversation whose last turn was an approval
|
|
277
|
+
lost its final answer outright.
|
|
278
|
+
|
|
279
|
+
Resume now claims the conversation's active-turn slot when it is free (never
|
|
280
|
+
taking it back from a newer chat turn the visitor started instead of approving),
|
|
281
|
+
assembles the leg's assistant text from its own stream, resolves the
|
|
282
|
+
stored `toolInvocations` from the submitted `toolOutputs`, and persists both
|
|
283
|
+
under the same compare-and-swap guard — on completion, on a re-pause, and on the
|
|
284
|
+
buffered (`streamResponse: false`) path. A client's later echo of that message
|
|
285
|
+
is deduplicated, and the request accepts an optional `assistantMessageId` so a
|
|
286
|
+
client that mints the id locally gets exact id dedupe.
|
|
287
|
+
|
|
288
|
+
## 8.0.3
|
|
289
|
+
|
|
290
|
+
### Patch Changes
|
|
291
|
+
|
|
292
|
+
- e154387: Surface managed Telegram bot creation failures instead of spinning silently. The status endpoint now runs a KV-cached manager-webhook health probe once a request has been pending for over two minutes and returns a `diagnostic: 'manager_webhook_unhealthy'` hint (new optional enum field in the SDK types); the verdict is derived from the delivery-blocking verify checks only, so a stale Telegram `last_error_date` cannot flip it. The Create New Bot wizard shows a slow-progress notice after 90 seconds, a misconfiguration notice when the diagnostic fires, and offers a one-click fallback to manual bot connection. Manual installs for a surface now cancel that surface's abandoned managed-bot requests, retrying after a poll timeout cancels the timed-out request, and initiate logs a traceable success line.
|
|
293
|
+
|
|
294
|
+
## 8.0.2
|
|
295
|
+
|
|
296
|
+
### Patch Changes
|
|
297
|
+
|
|
298
|
+
- 3b4f69c: Normalize package authorship and copyright metadata.
|
|
299
|
+
|
|
300
|
+
The `author` field reads `Runtype` rather than `Runtype Labs` across every
|
|
301
|
+
workspace package that set it, and the copyright holder in each license file is
|
|
302
|
+
now `Runtype, Inc` — replacing `Travrse Labs, Inc` in the CLI and the four Fern
|
|
303
|
+
SDKs, and the `Runtype Labs` that the new `flue-otel` license was written with.
|
|
304
|
+
|
|
305
|
+
Metadata only: no source, dependency, or behavior change.
|
|
306
|
+
|
|
307
|
+
## 8.0.1
|
|
308
|
+
|
|
309
|
+
### Patch Changes
|
|
310
|
+
|
|
311
|
+
- 047a57b: Serve `finalOutput` on the agent-executions list by default, with a `view=compact` opt-out.
|
|
312
|
+
|
|
313
|
+
`GET /v1/agents/{id}/executions` now accepts the shared `view=full|compact`
|
|
314
|
+
collection-representation parameter and defaults to `full`, which carries each
|
|
315
|
+
run's `finalOutput`. The route also serves the `?executionId=` single-row
|
|
316
|
+
lookup, so callers reading a run's result off it previously got `stopReason`
|
|
317
|
+
and `totalTokens` with no output and read the intact row as data loss.
|
|
318
|
+
`view=compact` restores the historical lightweight projection (and applies the
|
|
319
|
+
standard 100-character string preview). The per-iteration blobs
|
|
320
|
+
(`iterationDetails`, `loopConfig`) stay detail-endpoint-only in both views.
|
|
321
|
+
|
|
322
|
+
The MCP `list_agent_executions` tool gains the same `view` parameter and
|
|
323
|
+
defaults to `compact`, matching every other MCP list tool; `view` is threaded
|
|
324
|
+
through both `RuntypeClient` implementations and the Code Mode executor so an
|
|
325
|
+
explicit `full` actually reaches the API. The dashboard runs list asks for
|
|
326
|
+
`compact` explicitly since it renders only row titles and status.
|
|
327
|
+
|
|
328
|
+
## 8.0.0
|
|
329
|
+
|
|
330
|
+
### Major Changes
|
|
331
|
+
|
|
332
|
+
- 93387f9: Add the expand-first organization model-configuration foundation: canonical organization-owned storage, creator-safe lifecycle, rollback-compatible reads and runtime settings, stale legacy-write containment, and nullable ownership/provenance fields in model-config responses. The nullable `userId` response contract is a breaking schema change required before canonical organization rows can be activated.
|
|
333
|
+
- 8847973: Remove the dormant `@runtypelabs/guardrails` library and the entire skill-spector scanning feature (the `@runtypelabs/skill-spector` package, the `apps/skill-spector` scanner worker, and the API/dashboard wiring) from the codebase. The advisory `POST /v1/skills/scan` endpoint and the `enableSkillScanner` profile-features flag are removed; the TypeScript SDK drops `skills.scan()` and the `SkillScan*` verdict types; the dashboard drops the skill "Security scan" affordance.
|
|
334
|
+
|
|
335
|
+
### Minor Changes
|
|
336
|
+
|
|
337
|
+
- 7d284c9: Activate organization-owned model configurations with conflict-preserving migration, shared teammate CRUD, fail-closed runtime resolution, creator-independent lifecycle, transactional audit events, rollback aliases, and a dashboard recovery state for conflicting legacy settings.
|
|
338
|
+
- 3ea4dd2: Migrate organization Amazon Bedrock credentials to shared organization connections with explicit BYOK custody across REST, TypeScript SDK, MCP, and Code Mode; deterministic structured-credential runtime resolution; lifecycle preservation; audit attribution; and storage-only mixed-version aliases that cannot silently select execution custody.
|
|
339
|
+
- 59e5efa: Move organization OpenAI-compatible credentials and typed endpoint metadata to shared organization connections with explicit BYOK authority, exact model discovery and sync, creator-independent lifecycle, rollback-safe endpoint mirroring, and consistent REST, SDK, MCP, Code Mode, dashboard, runtime, status, telemetry, and audit behavior.
|
|
340
|
+
- 60e39b1: Migrate organization Mixlayer model credentials to shared organization connections with explicit BYOK or platform-managed custody across REST, TypeScript SDK, MCP, Code Mode, and the dashboard; deterministic runtime and status resolution; lifecycle preservation; audit attribution; and canonical mixlayer policy identity for legacy Modelsocket-compatible execution.
|
|
341
|
+
- 553da9d: Migrate organization Tinfoil model credentials to shared organization connections with explicit BYOK custody across REST, TypeScript SDK, MCP, and Code Mode; deterministic runtime and status resolution; lifecycle preservation; audit attribution; and storage-only mixed-version aliases that cannot silently select execution custody.
|
|
342
|
+
- a2c4ec7: Migrate organization Together.ai credentials to shared organization connections with explicit BYOK custody across REST, TypeScript SDK, MCP, Code Mode, and the dashboard; deterministic runtime and status resolution; creator-independent lifecycle; transactional audit attribution; and guarded dedicated-endpoint routing that cannot redirect the organization credential outside Together.ai.
|
|
343
|
+
- 6671abd: Move Vercel AI Gateway credentials to organization-owned connections with explicit shared BYOK or Platform authority, durable actor audit, creator-independent lifecycle, typed custom gateway settings, and consistent SDK, MCP, Code Mode, dashboard, runtime, and billing attribution.
|
|
344
|
+
- f3aef36: Migrate Vertex AI and Vertex AI (Claude) credentials to independent organization-owned connections with explicit BYOK custody, creator-independent lifecycle, transactional actor audit, and provider-scoped service-account resolution across REST, SDK, MCP, Code Mode, dashboard, legacy execution, and hosted runtime.
|
|
345
|
+
|
|
346
|
+
### Patch Changes
|
|
347
|
+
|
|
348
|
+
- af59a67: Agent-lane consumers scope terminal semantics to their own execution, so a relayed flow-as-tool child no longer supplies the run's terminal, final text, or response body.
|
|
349
|
+
|
|
350
|
+
A flow tool relays its nested flow onto the parent agent's stream, and that child always completes before the parent's `tool_complete`. Consumers reading "this run's terminal / final text / reported error" now filter by the owning `executionId` (`ownExecutionFrames` / `isOwnExecutionFrame`). Fixes an HTTP 500 on non-streaming `/v1/agents/{id}/execute` (`tool_complete after terminal execution_complete`), a voice turn that failed closed on a nested `success: false`, a duplicate AG-UI terminal callback, a Product API capability returning a nested flow step's payload as its `data`/`message`, and an SDK `onAgentComplete(success:false)` firing mid-run for a nested failure the agent recovered from.
|
|
351
|
+
|
|
352
|
+
- c29f1ce: Prepare Linear and GitHub built-in integrations for organization-owned credential authority with previous-Worker guards, owner-native credential preservation, and forward-compatible runtime/status resolution.
|
|
353
|
+
- 4776fa0: Retain external OTLP spans, span events, and LogRecords in the append-only
|
|
354
|
+
customer Logs tier on both the standalone ingest worker and API fallback lane.
|
|
355
|
+
The projection resolves tenant attribution before retention, applies the
|
|
356
|
+
agent's logging and PII-redaction policies, scrubs credential-shaped content,
|
|
357
|
+
and records bounded-row truncation explicitly. Logs and trace readers collapse
|
|
358
|
+
at-least-once retries by kind-specific identities and rebuild the exported span
|
|
359
|
+
parent/child tree without double-counting envelope metrics. OTLP LogRecords are
|
|
360
|
+
now decoded for protobuf and JSON exports; metrics remain acknowledged without
|
|
361
|
+
storage. JSON `/v1/executions/ingest` runs remain a compatibility path and now
|
|
362
|
+
return an explicit trace-availability reason instead of looking like a
|
|
363
|
+
successful empty trace. MCP execution-id inputs clarify that they accept the
|
|
364
|
+
runtime `execution_id`, not the `aex_...` database row ID.
|
|
365
|
+
|
|
366
|
+
## 7.3.1
|
|
367
|
+
|
|
368
|
+
### Patch Changes
|
|
369
|
+
|
|
370
|
+
- 5df5995: Migrate organization Braintrust tracing to organization-owned observability connections with shared control/runtime resolution, bound secret custody, legacy promotion, lifecycle resilience, and actor-attributed audit events.
|
|
371
|
+
- 1419c72: chore: update model configs from models.dev/Vercel/Mixlayer APIs
|
|
372
|
+
|
|
373
|
+
Adds 3 runtime models (`gemini-3.7-flash`, `google/gemini-3.7-flash`,
|
|
374
|
+
`alibaba/qwen3.8-2.4t-a95b`); no models were removed and no pricing changed.
|
|
375
|
+
|
|
376
|
+
Also swaps the account default in `DEFAULT_MODELS_FOR_NEW_ACCOUNTS` from
|
|
377
|
+
`gemini-3.6-flash` to `gemini-3.7-flash` in the fast Gemini flash-tier slot:
|
|
378
|
+
same 1M context, same reasoning/tool-use/vision/audio-input capability tags,
|
|
379
|
+
same google→vercel routing, at half the blended cost (0.00225 vs 0.0045 per
|
|
380
|
+
1k tokens). This moves `DEFAULT_MODEL_ID`, which is the OpenAPI `model`
|
|
381
|
+
default on the prompt-create/update routes, so the spec and SDK types are
|
|
382
|
+
regenerated. `EVAL_JUDGE_MODEL` and `PRODUCT_GENERATOR_MODEL` are
|
|
383
|
+
intentionally untouched.
|
|
384
|
+
|
|
385
|
+
- 948ceed: Migrate organization Anthropic credentials to shared organization connections with explicit custody policy, deterministic runtime resolution, lifecycle preservation, audit attribution, and mixed-version compatibility.
|
|
386
|
+
- c56a67e: Migrate organization Google model credentials to shared organization connections with explicit custody policy across REST, TypeScript SDK, MCP, and Code Mode; deterministic runtime and status resolution; lifecycle preservation; audit attribution; and storage-only mixed-version aliases that cannot silently select execution custody.
|
|
387
|
+
- 212bd10: Migrate organization OpenAI credentials to shared organization connections with explicit custody policy, deterministic runtime resolution, audit attribution, legacy model-config compatibility, and a provider-agnostic mixed-version guard for later provider activations.
|
|
388
|
+
- 5ae8a9c: Migrate organization xAI model credentials to shared organization connections with explicit custody policy across REST, TypeScript SDK, MCP, and Code Mode; deterministic runtime and status resolution; lifecycle preservation; audit attribution; and storage-only mixed-version aliases that cannot silently select execution custody.
|
|
389
|
+
|
|
390
|
+
## 7.3.0
|
|
391
|
+
|
|
392
|
+
### Minor Changes
|
|
393
|
+
|
|
394
|
+
- d1ba834: Add a uniform `view=compact` representation to collection endpoints, cap long string previews at 100 characters, default MCP list tools to compact responses, and fix agent type filtering.
|
|
395
|
+
|
|
396
|
+
## 7.2.1
|
|
397
|
+
|
|
398
|
+
### Patch Changes
|
|
399
|
+
|
|
400
|
+
- 083846c: External agents can speak Runtype's unified stream (`protocol: 'runtype-stream'`).
|
|
401
|
+
|
|
402
|
+
`agents.externalConfig` gains one additive field, `protocol`. Absent and `'a2a'`
|
|
403
|
+
both mean today's A2A JSON-RPC behavior byte-for-byte — the column is JSONB, so
|
|
404
|
+
no migration and no backfill. `'runtype-stream'` means the endpoint answers
|
|
405
|
+
`POST {endpoint}` with a `text/event-stream` in the 35-event unified vocabulary,
|
|
406
|
+
the same wire Runtype's own engines emit. `framework` also gains `'flue'`, a
|
|
407
|
+
reporting hint that nothing branches on.
|
|
408
|
+
|
|
409
|
+
**This fixes a live correctness bug, not just a feature.** Everything that runs
|
|
410
|
+
an external agent through `executeAgentInternal` — plain agent batches,
|
|
411
|
+
schedules, messaging channels, webhook surfaces — got `{ success, responseText,
|
|
412
|
+
error }` and wrote no `tool_executions` rows, so anything reading a run's trace
|
|
413
|
+
saw an EMPTY one. Every trace grader (`called_tool`, `tool_order`,
|
|
414
|
+
`max_tool_calls`, `used_no_tools`) therefore failed in a way that looked like the
|
|
415
|
+
agent misbehaving. On the new protocol the structure survives the boundary and
|
|
416
|
+
the rows are written.
|
|
417
|
+
- `ExternalAgentProxy.executeUnifiedStream` is a fourth method on the existing
|
|
418
|
+
proxy, so all outbound external-agent I/O keeps one home: the same
|
|
419
|
+
`UrlValidationService` (SSRF on a customer-supplied endpoint), the same
|
|
420
|
+
`buildAuthHeaders` (exactly one place materializes the sealed credential), the
|
|
421
|
+
same `timeoutMs` / `retryCount` fields. Retries cover the CONNECT phase only —
|
|
422
|
+
once a frame has been forwarded the request is not replayable.
|
|
423
|
+
- The request body is the full `messages` history rather than the A2A lane's
|
|
424
|
+
last message as one text part, so adopting the protocol also fixes that
|
|
425
|
+
truncation. It is deliberately the dispatch body `examples/flue-persona`
|
|
426
|
+
already accepts, which makes that example the executable reference
|
|
427
|
+
implementation of the server side.
|
|
428
|
+
- `executeExternalAgentUnified` (`agent-executor.ts`) folds the terminal frame
|
|
429
|
+
into the usual result shape; `InternalAgentExecutionParams` gains an optional
|
|
430
|
+
`stream`, and the external branch tees the caller's sink with
|
|
431
|
+
`createAgentToolSSETap`. The tap needed no changes — it already reads the
|
|
432
|
+
native unified tool vocabulary — which is what makes tool rows, and therefore
|
|
433
|
+
batch trace grading, start working.
|
|
434
|
+
- A terminal frame's `totalCost` is returned but never persisted as Runtype
|
|
435
|
+
cost. It is the customer's assertion about their own provider spend, and
|
|
436
|
+
`aggregateExecutionCost` has no provenance predicate yet.
|
|
437
|
+
|
|
438
|
+
**Validation is a trust boundary here.** The stream is customer-authored input
|
|
439
|
+
on the path that writes DB rows, so every frame goes through
|
|
440
|
+
`unifiedSSEEventSchema` (non-conforming frames are dropped, as the AG-UI edge
|
|
441
|
+
does) and the run goes through the shared structural validator
|
|
442
|
+
(`packages/shared/src/utils/unified-sse-conformance.ts`) — no private copy, so
|
|
443
|
+
producer and consumer are held to identical rules. A structural violation (a
|
|
444
|
+
`tool_complete` for a call that never started, a second `execution_start`, a
|
|
445
|
+
frame after the terminal, a hole in `seq`) is never forwarded and fails the
|
|
446
|
+
dispatch, and event/byte/frame caps plus the configured timeout bound every
|
|
447
|
+
hostile shape. That validator now also exposes `createConformanceTracker`, an
|
|
448
|
+
incremental form for exactly this consumer; the whole-array
|
|
449
|
+
`findConformanceViolations` is implemented in terms of it so the two can never
|
|
450
|
+
disagree.
|
|
451
|
+
|
|
452
|
+
Not included, and unchanged: the synchronous `/eval/run` path still rejects a
|
|
453
|
+
non-`runtype` agent target with `AGENT_TYPE_RUN_UNSUPPORTED` (its message is
|
|
454
|
+
narrowed to name the surfaces that do work). Direct dispatch for unified
|
|
455
|
+
external agents there is the next phase.
|
|
456
|
+
|
|
457
|
+
## 7.2.0
|
|
458
|
+
|
|
459
|
+
### Minor Changes
|
|
460
|
+
|
|
461
|
+
- 6ae01b5: Canonicalize the "Managed in code" provenance indicator across the dashboard and expose flow provenance through the API.
|
|
462
|
+
|
|
463
|
+
One shared dashboard module now owns the badge, the save-overwrite confirmation dialog, and the predicate, which delegates to `isManagedByCodeSource` in `@runtypelabs/shared`. This fixes terraform-managed tools, which previously showed no badge and skipped the overwrite warning because the tools surface hardcoded a check against the `sdk` source.
|
|
464
|
+
|
|
465
|
+
Flows gain provenance end to end: `lastModifiedSource` is now returned on the flow list and detail responses (and by create/update), and the flow editor renders the badge and gates Save behind the confirmation dialog, matching agents. The flows index badges code-managed rows.
|
|
466
|
+
|
|
467
|
+
## 7.1.0
|
|
468
|
+
|
|
469
|
+
### Minor Changes
|
|
470
|
+
|
|
471
|
+
- 27d0b95: Add an additive optional `stepErrorCount` to `execution_complete`: the count of top-level steps that completed carrying a non-null `error`, **including continue-on-error swallows**.
|
|
472
|
+
|
|
473
|
+
It is a **sibling** of the failure counters, never a replacement. `stepErrorCount` is deliberately the LARGER set: a step that swallowed its error under the default `errorHandling: 'continue'` reports `success: true` and still carries the reason on its top-level `error`, so it contributes to `stepErrorCount` but not to `failedSteps` or to the flow's `success` verdict. Collapsing the two onto one predicate would either redefine `success` (counting swallows as failures) or undercount errors.
|
|
474
|
+
- Emitted on `execution_complete` (unified SSE) by both the API-owned lane and the `@runtypelabs/runtime` FLOW lane, and carried inside the terminal event of the buffered JSON dispatch body.
|
|
475
|
+
- Persisted with the execution's `flow_complete` telemetry event, so a run's swallowed-error count is queryable after the fact.
|
|
476
|
+
- Threaded through the runtime's `RuntimeFlowProgress` and the persisted resume state, so a paused/resumed flow keeps an accurate count across legs.
|
|
477
|
+
- Optional and additive: absent (not `undefined`) when a producer has no counter, so existing clients and parsers are unaffected.
|
|
478
|
+
|
|
479
|
+
Documented boundary: the two dispatch-seam swallows (`generate-embedding`, `vector-search`) carry their reason on `metadata.error` with no top-level `error`, so they land in neither counter — `stepErrorCount` counts exactly what `step_complete.error` puts on the wire.
|
|
480
|
+
|
|
481
|
+
### Patch Changes
|
|
482
|
+
|
|
483
|
+
- 8d85ce9: Forward the A2A conversation handles on an `await` pause, so a paused external-agent run stays correlatable off the buffered response and the SDK callback.
|
|
484
|
+
|
|
485
|
+
Follow-up to #6845 (#6103 §B3), where the external-agent `input-required` pause moved from `approval_start` onto the `await` rail. Two consumers still only read the handles off `approval_start`:
|
|
486
|
+
- **API** — the buffered (`streamResponse: false`) dispatch response forwarded `externalAgent` only from an `approval_start` terminal, so a non-streaming A2A pause returned `status: 'paused'` with no `externalAgent` at all. The `await` terminal's context is now forwarded the same way. Resume was never affected (it routes off the persisted checkpoint), but the response shape regressed for exactly the lane that PR retargeted.
|
|
487
|
+
- **SDK** — the unified `await` → `agent_await` mapping dropped `awaitReason`, `elicitation`, and `externalAgent`, while the same adapter already forwards `externalAgent` on `execution_complete`. An `onAgentPaused` consumer could not tell an A2A elicitation from a client-tool wait, nor see the `contextId` / `taskId` to resume the conversation with. `AgentPausedEvent` gains the three optional fields, typed against the canonical wire schemas: a new exported `AgentElicitation` (and `AgentElicitationRequest`) restates `unifiedElicitationSchema` in full — both `mode` values, the required `message`, plus `requestedSchema`, `url`, `serverName`, `pauseCount`, and multi-request `requests` — and `externalAgent` reuses the existing exported `ExternalAgentContext`. Previously these fields were reachable only as `unknown` through an index signature, so consumers had to cast to render a form, follow a `url`-mode auth prompt, or preserve the pause-count binding.
|
|
488
|
+
|
|
489
|
+
- cdff95a: A2A runtime parity for the external-agent client (#6103 §B3).
|
|
490
|
+
|
|
491
|
+
**Runtime** — "speaking A2A" is now a first-class feature of the runtime package. A new `engine/a2a/` module owns the wire protocol for both A2A clients: 0.3/1.0 negotiation off `cachedAgentCard.protocolVersion` (method names, `a2a-version` header, roles, part oneofs, `TASK_STATE` normalization), endpoint preference for the cached card, and immediate-reply result normalization (a `{ result: { message } }` reply is a completed task carrying the message text, not an empty output). The external-agent client (`external-agent.ts`) and the A2A tool path (`runA2A`) now share it, so the two clients agree on the wire. Transient send failures retry (`retryCount ?? 3`, 100ms ×2, no retry on abort / URL-validation / JSON-RPC error), and per-agent `timeoutMs` bounds each attempt while the engine wall clock still bounds the whole run.
|
|
492
|
+
|
|
493
|
+
The external-agent `input-required` / `auth-required` pause is now a resumable await instead of an `approval_start`. It emits the unified `await` frame with `awaitReason: 'a2a_input_required'` / `'a2a_auth_required'`, the peer's question on the existing elicitation payload, and a new additive optional `externalAgent: { contextId, taskId }` field (wire shape reused from `approval_start`/`execution_complete`). A resumable external-mode checkpoint (`kind: 'external-agent'`, keyed at pinned iteration 0, overwrite-on-re-pause) is persisted through the same store as loop checkpoints; a resume re-enters external mode and sends the user's reply as the next message on the checkpoint's `contextId`. No checkpoint is written when the peer assigned no `contextId`. The new `external_input_required` stop reason maps to the paused status so usage is not double-counted. `awaitReason` remains UX context only — nothing branches on it; the tool/skill approval fold is unchanged.
|
|
494
|
+
|
|
495
|
+
**API** — the runtime export pipeline now carries per-agent `timeoutMs`/`retryCount` through to the runtime lane, and the paused-status mapping understands the new stop reason.
|
|
496
|
+
|
|
497
|
+
**Shared / SDK** — the additive `await.externalAgent` field is added to the unified SSE schema (open optional field) and regenerated into the TypeScript SDK types and OpenAPI spec.
|
|
498
|
+
|
|
499
|
+
## 7.0.0
|
|
500
|
+
|
|
501
|
+
### Major Changes
|
|
502
|
+
|
|
503
|
+
- dda50f3: Retire the legacy eval override channels. `overrides` is the only spelling the wire accepts: `stepOverrides` (with its `'*'` key), `claudeManagedOverride`, `advisorOverride`, and the four scalar surface-eval `*Override` fields no longer parse.
|
|
504
|
+
|
|
505
|
+
**Breaking**, and the major lands on `@runtypelabs/sdk` alone because that is the only package anything resolves by range: it declared `stepOverrides` and `claudeManagedOverride` as accepted input on `runVirtualEval` and no longer does. The API takes a minor — its wire contract breaks too, but the package is private, so its version is changelog and deploy metadata rather than a contract a dependent resolves. What tells an API caller about the break is this entry and the 400 itself, not a version number they never read.
|
|
506
|
+
|
|
507
|
+
A request still using a retired spelling gets a 400 naming the `overrides.*` field that replaced it. That rejection is the point rather than a side effect — the eval request schemas are `.passthrough()`, so merely undeclaring a field would leave it silently ignored, and an ignored override is recorded and scored exactly like an applied one. Failing loudly is what keeps an unmigrated caller from being graded as a baseline it never asked for.
|
|
508
|
+
|
|
509
|
+
Migration is a rename in every case:
|
|
510
|
+
|
|
511
|
+
| Retired | Replacement |
|
|
512
|
+
| -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
513
|
+
| `stepOverrides['*']` | `overrides.agent` or `overrides.flow`, whichever matches the target |
|
|
514
|
+
| `stepOverrides[stepId]` | `overrides.steps[stepId]` |
|
|
515
|
+
| `claudeManagedOverride` | `overrides.claudeManaged` |
|
|
516
|
+
| `advisorOverride` | `overrides.advisor` |
|
|
517
|
+
| `temperatureOverride` / `maxTokensOverride` / `responseFormatOverride` / `reasoningOverride` | `overrides.flow.temperature` / `.maxTokens` / `.responseFormat` / `.reasoning` |
|
|
518
|
+
|
|
519
|
+
Splitting `'*'` into `agent` / `flow` is what makes the target-illegal case a 400 instead of a drop: the one key used to mean "the agent under test" on one target kind and "every prompt step" on the other, so it could never be checked.
|
|
520
|
+
|
|
521
|
+
`options.modelOverride` is unaffected — it is a dispatch knob, not an eval override channel, and keeps its existing lowest precedence beneath the caller's own `overrides.flow`.
|
|
522
|
+
|
|
523
|
+
In-flight batches are unaffected and the deploy needs no coordination. The plan expected this deletion to require a versioned Durable Object drain or a no-batches deploy window, which holds only while "what a caller may send" and "what persisted state may contain" are the same type. They are now separate: `evalOverridesInputFromExecutionConfig` folds the state shape for internal execution metadata and pre-carrier `batchState`, and a request cannot reach it. `'*'` therefore survives inside execution metadata on purpose — it is still how the flow engine spells "every prompt step", which no wire change touches.
|
|
524
|
+
|
|
525
|
+
A data migration (`0130_backfill_eval_config_canonical_overrides`) rewrites the historical `batch_executions.eval_config` audit snapshots into the same canonical shape, so one spelling remains in the system. It cannot change what any run does: nothing executes from that column — the batch Durable Object restores `evalConfig` from its own state, never from Postgres — and every read of it is display or reporting. The Runs-list reader now understands both shapes, so it labels runs correctly whether or not the migration has run.
|
|
526
|
+
|
|
527
|
+
### Minor Changes
|
|
528
|
+
|
|
529
|
+
- a634b53: Eval overrides now travel on one canonical `overrides` request field
|
|
530
|
+
|
|
531
|
+
`overrides` previously carried only the per-sub-agent targets, which had no
|
|
532
|
+
legacy channel and no first-party producer. It now carries every channel —
|
|
533
|
+
`agent` / `flow` / `steps` / `claudeManaged` / `advisor` beside `subagents` /
|
|
534
|
+
`subagentDefaults` — and the dashboard, the SDK, the MCP tool inputs and the
|
|
535
|
+
OpenAPI examples all emit it.
|
|
536
|
+
|
|
537
|
+
Four new submit-time 400s replace what were silently-scored no-ops: setting
|
|
538
|
+
both the canonical and the legacy spelling of one channel, `overrides.agent` on
|
|
539
|
+
a flow target (or `overrides.flow` on an agent target), and an `overrides.steps`
|
|
540
|
+
key naming no step of the target. The unreachable-`agentId` rejection now
|
|
541
|
+
applies on every eval lane, `/eval/stream` included.
|
|
542
|
+
|
|
543
|
+
The legacy `stepOverrides` (with its `'*'` key), `claudeManagedOverride` and
|
|
544
|
+
`advisorOverride` fields still parse and still resolve identically; they are
|
|
545
|
+
deleted in a later phase.
|
|
546
|
+
|
|
547
|
+
### Patch Changes
|
|
548
|
+
|
|
549
|
+
- 836fc82: Phase 0 of the Persona visitor conversation-history contract. Everything here is additive: `flow` on init, `flowId` on summaries and query parameters, and the stored `metadata.flow_id` key all stay as compatibility aliases through the rolling-deploy window.
|
|
550
|
+
|
|
551
|
+
**Durable handles.** `POST /v1/client/init` now returns `conversationId` from every successful branch (fresh mint, legacy `sessionId` replay, `conversationId` resume) plus a canonical top-level `targetId` from the chat-capable ones. A widget persists the conversation, not the short-lived session. `targetId` is not the identity function on what the caller configured: an agent-only client token resolves its agent to that agent's primary flow before storing, so a widget filtering by the configured agent id would have got an empty history and, on delete-all, would have deleted nothing while reporting success. The four target shapes are pinned against the record's stored `flow_id`.
|
|
552
|
+
|
|
553
|
+
**`targetId` filter symmetry.** Both `GET` and `DELETE /v1/client/conversations` take it; a target-scoped UI can no longer clear conversations it never showed the visitor. Supplying `targetId` and `flowId` with different values is a 400 rather than a guess.
|
|
554
|
+
|
|
555
|
+
**Display projections.** A stored message's `content` is the model channel, which for anything richer than a plain text turn is not what the person read. Messages now carry an optional `displayContent` alongside it, plus `displayAvailable` on the read path; execution reads only `content`. Absent and empty-string projections are distinct states. Without a projection, stored content stands in only when it is plainly render-safe, so opaque model-only structure is withheld rather than handed to a renderer.
|
|
556
|
+
|
|
557
|
+
A terminal assistant turn is the hard case: its visible text is only computable in the browser after the stream closes, and if the visitor leaves right then no later request exists to carry it. `PATCH /v1/client/conversations/{id}/display-projections` is that channel. Projection-only (it cannot create a message or move content, role, ordering, timestamps, count, ownership, or title), all-or-nothing per batch, idempotent, bound to the session's own conversation, and bounded for a `keepalive` request. The write compare-and-swaps on `conversationRevision`: unlike the two chat-path writers, this route is not serialized by the active-turn CAS, so an unguarded rewrite of the transcript array could delete a turn persisted between its read and its write. A re-sent chat turn repairs a lost finalization.
|
|
558
|
+
|
|
559
|
+
**`conversationRevision`.** An opaque equality-only change token on init, detail, and the finalization response. It moves on every transcript mutation including a projection change, which deliberately leaves `updatedAt` alone so a closing tab cannot reorder a history list.
|
|
560
|
+
|
|
561
|
+
**Authoritative continuation.** `/v1/client/chat` executes the stored transcript merged with genuinely new message ids instead of the client's own array. A second device's turns can no longer be dropped by a stale or truncated local view; stored content wins for ids the record already holds.
|
|
562
|
+
|
|
563
|
+
**Identity acknowledgement (privacy-critical).** Identity admission is gated per owner, and with the gate off a supplied proof was accepted and ignored, so a request asking for verified cross-device scope ran silently at browser scope. A widget could not tell the difference, which is unacceptable for a verified erase. Every visitor grant now reports `identityStatus` (`not_provided` | `admitted` | `ignored`) and every history response carries `X-History-Identity-Status`. Init still succeeds with `ignored` so chat degrades gracefully; a history route handed such a proof now fails 503 `identity_proof_not_admitted` before any visitor-scoped read or mutation runs, pinned by DB-mutation counts on every destructive route. A rejected proof stays a 401 and is never reported as `ignored`.
|
|
564
|
+
|
|
565
|
+
**Previews.** Summaries carry a plain-text `preview` of the newest visitor-visible message, bounded to 140 Unicode code points, derived from the display projection and never falling through to opaque content.
|
|
566
|
+
|
|
567
|
+
Also pins the zero-message first-page-load ownership claim Persona's bootstrap depends on, and adds a generated wire fixture (`apps/api/tests/fixtures/client-conversation-history-wire.json`) for the Persona repo to pin its message mapper against.
|
|
568
|
+
|
|
569
|
+
## 6.6.3
|
|
570
|
+
|
|
571
|
+
### Patch Changes
|
|
572
|
+
|
|
573
|
+
- f59e62b: Add per-visitor conversation history to the public client surface, so an embedded Persona widget can show a visitor their own past conversations with no backend on the host site.
|
|
574
|
+
|
|
575
|
+
History-capable clients opt in with `visitorHistory: true` on `POST /v1/client/init`. The API then mints (or resumes) a durable anonymous visitor for that browser and returns a `visitor` grant alongside the session. The raw visitor secret is returned only when minted, is stored only as a SHA-256 hash, and is namespaced per client token so a secret from one site is inert on another. Legacy clients that do not opt in keep the previous response shape and do not create discarded visitors.
|
|
576
|
+
|
|
577
|
+
New session-authed, visitor-scoped routes:
|
|
578
|
+
- `GET /v1/client/conversations` (cursor-paginated, optional `flowId` filter)
|
|
579
|
+
- `GET /v1/client/conversations/{id}`
|
|
580
|
+
- `DELETE /v1/client/conversations/{id}`
|
|
581
|
+
- `DELETE /v1/client/conversations`
|
|
582
|
+
- `POST /v1/client/visitor/reset`
|
|
583
|
+
|
|
584
|
+
Each requires both a live `sessionId` and the `X-Visitor-Token` secret: a bare client token is public and site-wide, and a bare `sessionId` is a low-entropy TypeID, so neither alone can read history. A conversation the caller does not own answers 404 rather than 403, so the routes cannot be used to enumerate other visitors' conversations.
|
|
585
|
+
|
|
586
|
+
`POST /v1/client/init` also accepts a visitor-authorized `conversationId`, mutually exclusive with legacy `sessionId`, so a conversation selected from server history can be resumed without a browser-local conversation-to-session map. Out-of-scope conversations answer 404.
|
|
587
|
+
|
|
588
|
+
Conversations can be titled server-side from their opening exchange, replacing the timestamp placeholder, so embedders no longer need to keep local message snippets just to render a history list. This ships dark behind `enable-conversation-titles`: titling sends the opening exchange to a model from a different provider than the surface's agent, and there is no per-surface way to decline that yet, so it stays off in production until the `conversationTitles` config lands (`docs/features/planning/2026-08-08-conversation-title-configuration.md`). The flag doubles as an operator kill switch for a platform-run model call on a public surface.
|
|
589
|
+
|
|
590
|
+
`POST /v1/client/init` also accepts an optional `identityProof`. When the Identity Exchange gate is on, it is verified once against the token owner's registered integrations and projected to a durable `eu_*`, which binds the browser's visitor to that person. An invalid proof is rejected 401 and nothing is bound; an absent proof leaves the session anonymous, unchanged.
|
|
591
|
+
|
|
592
|
+
Binding an end user is the anonymous-to-identified merge: the visitor's existing conversations come along (no rows move — ownership is read through the link). Cross-device reads require a fresh admitted identity proof on that request; a stored visitor binding alone never widens authorization beyond the exact browser. Sibling resolution is scoped to the client token, so one identity on two sites remains two histories, and an unbound visitor resolves to itself alone rather than unioning on a null end user. A second person signing in on a browser that is already bound gets a fresh visitor instead of inheriting the first person's history.
|
|
593
|
+
|
|
594
|
+
Visitor ownership is tracked on a new `records.client_visitor_id` column and a new `client_visitors` table, deliberately separate from the `end_users` (`eu_*`) tenancy plane: an `eu_*` is an admitted, verified identity that doubles as an authorization key for end-user-private record reads, so an anonymous browser-held secret must not mint into it. Keeping the planes separate also leaves the verified `identityProof` path untouched.
|
|
595
|
+
|
|
596
|
+
- 308c44c: Stop every consumer surface from claiming execution-count caps that no longer exist (remove-execution-caps Slice 3).
|
|
597
|
+
|
|
598
|
+
Slice 2 removed execution-count caps from enforcement. This makes the dashboard, the REST responses, and the docs agree with that: a card-on-file account is never bounded by execution count, and the only remaining bound is the code-owned protective daily ceiling for accounts with no payment method, framed as "add a payment method to remove", never "upgrade your plan".
|
|
599
|
+
- `ExecutionStats` gains `executionCapReason` (`'no_card_ceiling' | null`), the single signal a surface may branch on. The neutral fallbacks (rate-limit block, spend-cap block, DO fail-open, failed display read) no longer report a ceiling-shaped limit.
|
|
600
|
+
- `GET /usage-limits` and `/usage-limits/daily` expose `executionCapReason` and always key the payload under `daily`; `inSlowMode` / `isOverage` / `overageCount` / `periodType` stay on the wire but are documented as inert.
|
|
601
|
+
- `GET /v1/billing/status` gains `usage.executionsToday` (`executionsThisMonth` is a deprecated alias carrying the same daily count); `isApproachingLimits` / `isOverLimits` are documented as always `false`.
|
|
602
|
+
- Dashboard: usage banners render only for a no-card account, the slow-mode modal is deleted (it had no producer), and the dev billing tester models the carded/no-card matrix instead of retired plan pools.
|
|
603
|
+
- CLI: `runtype billing status` and `runtype auth whoami` read `executionsToday` instead of `executionsUsed` / `executionsLimit`, which the API has never returned, so both printed "Executions: 0" against a live API. They now show a plain count (no invented denominator) and say "unavailable" when the usage read failed.
|
|
604
|
+
|
|
605
|
+
## 6.6.2
|
|
606
|
+
|
|
607
|
+
### Patch Changes
|
|
608
|
+
|
|
609
|
+
- 941f500: Warn at authoring time when an approval-requiring agent is bound to an
|
|
610
|
+
unattended surface (slice 1 of the unanswerable-approval-surfaces plan; no
|
|
611
|
+
execution behavior change). Adds the shared surface-attendance registry (an
|
|
612
|
+
`approvalAnswerable` trait on `SurfaceTraits` with polarity-explicit helpers
|
|
613
|
+
`isApprovalAnswerableSurfaceType` / `isApprovalUnanswerableSurfaceType`) and a
|
|
614
|
+
new advisory code `APPROVAL_UNANSWERABLE_ON_SURFACE` (warning severity, never
|
|
615
|
+
blocking) emitted from the product validator, the surface-item add/update
|
|
616
|
+
response envelopes (REST and, via passthrough, MCP `add_surface_item` — the
|
|
617
|
+
SDK response types gain an optional `warnings` array), and the agent-save
|
|
618
|
+
`_warnings` when an update arms approval on an agent already bound to
|
|
619
|
+
unattended surfaces. The dashboard channel and surface config panels show the
|
|
620
|
+
same warning inline. The webhook DO and messaging trigger now read their
|
|
621
|
+
(unchanged, `false`) attendance fact from the shared registry instead of
|
|
622
|
+
omitting it per call site.
|
|
623
|
+
|
|
624
|
+
## 6.6.1
|
|
625
|
+
|
|
626
|
+
### Patch Changes
|
|
627
|
+
|
|
628
|
+
- 5ad8bac: Add a runnable end-user usage acceptance lab, align client-token SDK types with agent-scoped surface tokens, support explicit local-test hosted identity, make magic-link OAuth continuation work across email-opened tabs, and make empty-ledger/dashboard deep-link paths testable end to end.
|
|
629
|
+
- 58f5a8a: Remove surfaces as a billing dimension entirely.
|
|
630
|
+
|
|
631
|
+
Surfaces (the deployed-channel objects on products: chat, api, mcp, slack,
|
|
632
|
+
etc.) no longer count against any plan limit or appear in any billing surface:
|
|
633
|
+
- Surface create / environment-change no longer consults the Schematic
|
|
634
|
+
`production-surfaces` / `development-surfaces` entitlement flags; surfaces are
|
|
635
|
+
unlimited on every plan.
|
|
636
|
+
- Surface counts are no longer synced to Schematic as `production_surface_count`
|
|
637
|
+
/ `development_surface_count` company traits.
|
|
638
|
+
- `BillingConfig` drops the `productionSurfaceLimit` / `developmentSurfaceLimit`
|
|
639
|
+
fields; `/v1/billing/status` drops the surface limit + usage fields and the
|
|
640
|
+
surface component of `isApproachingLimits` / `isOverLimits`.
|
|
641
|
+
- The 402 `PRODUCTION_SURFACE_LIMIT` / `DEVELOPMENT_SURFACE_LIMIT` responses are
|
|
642
|
+
removed from the surface create / update / ensure routes (and their OpenAPI
|
|
643
|
+
contracts), so the surface-limit error handling in the dashboard is dead code.
|
|
644
|
+
|
|
645
|
+
Surfaces remain fully functional as a product concept; only the billing and
|
|
646
|
+
entitlement machinery is removed. The Schematic-side flags/features/traits
|
|
647
|
+
become unused and can be deleted from the Schematic dashboard separately.
|
|
648
|
+
|
|
649
|
+
- e12b556: Add an org-scoped, non-admin read endpoint `GET /v1/executions/{executionId}/journal`
|
|
650
|
+
that returns the durable `flow_execution_events` journal rows for an execution the
|
|
651
|
+
caller owns, redacted and in replay order (API-key/Clerk authenticated, ownership-scoped,
|
|
652
|
+
`FLOWS:READ`/`AGENTS:READ` scoped for API keys, 404 on unowned/missing ids, `truncated`
|
|
653
|
+
flag when the 1000-event cap is hit). This is a strictly-narrower read surface than the
|
|
654
|
+
admin trace bundle and is what the runtime-parity B-17 gate reads from the normal
|
|
655
|
+
`api.runtype-staging.com` surface.
|
|
656
|
+
- e23af15: Add a dedicated `ScheduleEntitlementErrorSchema` OpenAPI component for the
|
|
657
|
+
schedule 402 responses (create/update/resume). The runtime bodies already
|
|
658
|
+
return `message`, `code`, and `upgradeUrl`, but the routes referenced the
|
|
659
|
+
generic `ErrorSchema` (which declares only `error` + `details`), so
|
|
660
|
+
generated SDK types hid the upgrade path. The new schema extends
|
|
661
|
+
`ErrorSchema` with the three fields and is registered as
|
|
662
|
+
`#/components/schemas/ScheduleEntitlementError`. Regenerates the OpenAPI
|
|
663
|
+
spec and all SDK cores (TS/Python/PHP/Ruby/Java).
|
|
664
|
+
|
|
665
|
+
Addresses Greptile P1 on PR #6490.
|
|
666
|
+
|
|
667
|
+
## 6.6.0
|
|
668
|
+
|
|
669
|
+
### Minor Changes
|
|
670
|
+
|
|
671
|
+
- bcf78f5: Add typed record collections end to end (Records→Collections plan §5.1/§5.2). The SDK gains an augmentable `RecordCollections` map, a `CollectionMeta<S>` helper, and `client.records.from(slug)` — a typed scope whose `.list/.get/.create/.update` pin the record `type` to the slug and type `metadata` for that collection (`.get`/`.update` guard against cross-collection ids). A new authed `GET /v1/collections/types.d.ts` endpoint hand-emits a `.d.ts` (one interface per schematized collection plus a `declare module '@runtypelabs/sdk'` augmentation, with `// skipped:` markers for rows whose stored schema no longer parses) from the constrained schema dialect. `runtype records typegen [-o <file>]` fetches it (commit and diff-check the output in CI to catch collection-schema drift). The typegen endpoint is fanned out across surfaces: the `get_collection_types` MCP tool (standard + code-mode `getCollectionTypegen`) and the CLI.
|
|
672
|
+
|
|
673
|
+
## 6.5.1
|
|
674
|
+
|
|
675
|
+
### Patch Changes
|
|
676
|
+
|
|
677
|
+
- 22ab25a: Widen the SSE `agent_tool_start` toolType union to include `data_connection` and `search`, matching what both engines already emit on the wire.
|
|
678
|
+
|
|
679
|
+
## 6.5.0
|
|
680
|
+
|
|
681
|
+
### Minor Changes
|
|
682
|
+
|
|
683
|
+
- 9dca3bc: Add the agent state events to every wire layer (agent state IR, slice 2).
|
|
684
|
+
|
|
685
|
+
State change is now expressible on the wire as RFC-6902 JSON Patch over an open JSON
|
|
686
|
+
document, in all three declared contracts: the internal engine IR gains
|
|
687
|
+
`agent_state_snapshot` / `agent_state_delta`, the public unified vocabulary grows from
|
|
688
|
+
33 to 35 events with `state_snapshot` / `state_delta`, and the AG-UI union gains
|
|
689
|
+
`STATE_SNAPSHOT` / `STATE_DELTA` under the spec's own field names. Both emitters
|
|
690
|
+
(`AgentEventEmitter`, `UnifiedEventEmitter`) can produce them, the API edge translator
|
|
691
|
+
projects internal onto unified, and the AG-UI translator projects unified onto the
|
|
692
|
+
protocol events.
|
|
693
|
+
|
|
694
|
+
The JSON-Patch shape moves to `@runtypelabs/shared` (`json-patch.ts`) so all three
|
|
695
|
+
schemas type against one definition; `packages/runtime/src/engine/state-channel.ts`
|
|
696
|
+
re-exports it and keeps the apply/diff behavior.
|
|
697
|
+
|
|
698
|
+
State events are deliberately block-neutral: unlike media, approval, and tool frames
|
|
699
|
+
they do not seal an open text channel, because state is rendered out-of-band and a
|
|
700
|
+
mid-turn write must not split the assistant's message. Both producers agree, pinned by
|
|
701
|
+
the runtime/unified parity gate.
|
|
702
|
+
|
|
703
|
+
The generated SDK types and Python SDK follow the OpenAPI spec, so `ExecutionStreamEvent`
|
|
704
|
+
now includes both new variants.
|
|
705
|
+
|
|
706
|
+
Still inert: nothing seeds a state channel and no run emits these yet. The reserved
|
|
707
|
+
state-write tool, seeding, and exposing state to the model land in the next increment.
|
|
708
|
+
|
|
709
|
+
- e76a310: Add feature-gated product usage analytics grouped by durable end-user identity. UsageTracker Durable Objects now retain exact, idempotent daily execution and platform-spend rollups for 93 days; the authenticated analytics API verifies product and tenant ownership, hydrates customer-facing identity labels, and reports attributed versus unattributed coverage.
|
|
710
|
+
|
|
711
|
+
Expose the breakdown through the TypeScript SDK and a lazy-loaded Usage settings subview with product, tenant, period, and sort filters, top-user metrics, unattributed-usage guidance, and formula-safe CSV export.
|
|
712
|
+
|
|
713
|
+
### Patch Changes
|
|
714
|
+
|
|
715
|
+
- eab2128: Pin first-party dispatch helpers to the response mode selected by their JSON or streaming transport.
|
|
716
|
+
- 25412dc: Run flow-definition record batches and isolated step tests through the hosted
|
|
717
|
+
runtime, fail closed when a definition needs unsupported continuation behavior,
|
|
718
|
+
and submit large record sets to the batch processor instead of returning a
|
|
719
|
+
scheduled handle without enqueuing work. Preserve the prior temporal snapshot
|
|
720
|
+
during isolated step replays while stamping a fresh execution-start timestamp,
|
|
721
|
+
retain record execution history, and pin scheduled batches to the admitted
|
|
722
|
+
definition.
|
|
723
|
+
- 7ab031f: Authorize Product surface keys with immutable capability target IDs across API, MCP, A2A, AG-UI, and webhook execution paths.
|
|
724
|
+
- eab2128: Document and normalize buffered continuation responses across dispatch,
|
|
725
|
+
saved-agent, and client routes, preserving failures and chained approvals across
|
|
726
|
+
legacy and runtime continuations.
|
|
727
|
+
|
|
728
|
+
## 6.4.0
|
|
729
|
+
|
|
730
|
+
### Minor Changes
|
|
731
|
+
|
|
732
|
+
- c576866: Add operator-authored `sandbox.setupCommands` plus a `sandbox.secretEnv` map on the
|
|
733
|
+
agent Definition (env var name → managed secret KEY). Setup runs once after network
|
|
734
|
+
policy enforcement and before the model's first sandbox verb. The API resolves
|
|
735
|
+
credential values only for setup and delivers them out-of-band over the
|
|
736
|
+
`cloudflareSandboxExecWithSecretEnv` RPC, so they never appear in command strings,
|
|
737
|
+
model-facing tool schemas, logs, or spill files.
|
|
738
|
+
|
|
739
|
+
Model-authored `bash` always uses the plain credential-less RPC, even when its
|
|
740
|
+
command references a configured variable. A run-scoped memo plus trusted Durable
|
|
741
|
+
Object claim/completion state keeps setup once-only across parallel and sequential
|
|
742
|
+
tool calls. A setup-definition fingerprint versions the sandbox identity, so
|
|
743
|
+
configuration changes get a fresh machine rather than reinjecting credentials
|
|
744
|
+
into an existing model-tainted one. Failed or interrupted setup remains retryable.
|
|
745
|
+
|
|
746
|
+
Credentialed setup must remain operator-authored, foreground, and self-contained:
|
|
747
|
+
the secret supervisor freezes pre-existing processes and reaps every descendant on
|
|
748
|
+
return. Prefer `credentialProxies` (phantom tokens) when the target protocol
|
|
749
|
+
supports them.
|
|
750
|
+
|
|
751
|
+
- 9e19bc0: Surface inbound webhook health in the API and dashboard.
|
|
752
|
+
|
|
753
|
+
Rejected inbound webhooks were invisible: a Slack surface whose signing secret no longer matches returns 401 before any execution starts, so nothing reached the logs and the channel simply looked idle. The API has recorded per-surface delivery and failure history in `product_surfaces.webhook_health` all along, but never served it.
|
|
754
|
+
|
|
755
|
+
Surface responses now carry a `webhookHealth` projection (`lastDeliveryAt` plus the most recent rejections), and the dashboard keeps it refreshed while the product editor is open: the channel node shows a red "Rejecting events" dot, and the channel edit panel explains the specific failure and names the field to fix (for a Slack signature mismatch, the Signing Secret rather than the similar-looking Client Secret). Derivation and copy are single-sourced in `@runtypelabs/shared`.
|
|
756
|
+
|
|
757
|
+
### Patch Changes
|
|
758
|
+
|
|
759
|
+
- ad943b9: Align public dispatch request types and clients with the canonical API schema.
|
|
760
|
+
- 15f3980: Document and type buffered dispatch responses, and honor `streamResponse: false` on the runtime-agent lane.
|
|
761
|
+
- 41a2650: Redact protected tool parameter values from debug streams, customer logs, approvals, and persisted tool executions while preserving protected-field attribution.
|
|
762
|
+
- 050c834: Retire legacy dispatch-scoped `{{secrets.key}}` values for hosted FLOW
|
|
763
|
+
execution. Hosted flows continue accepting the `secrets` field for wire
|
|
764
|
+
compatibility, but the pipeline strips it before either runtime or legacy
|
|
765
|
+
execution; use managed `{{secret:NAME}}` references for flow credentials.
|
|
766
|
+
- 17382d8: Retire the per-request legacy engine override for flow dispatches while
|
|
767
|
+
continuing to accept the compatibility field for existing clients and agent
|
|
768
|
+
runtime selection.
|
|
769
|
+
- 17382d8: Run eligible buffered JSON flow dispatches through `@runtypelabs/runtime`, using
|
|
770
|
+
the same structured runtime completion and unified events as the streaming path.
|
|
771
|
+
Explicit `useRuntimePackage: false` and runtime-ineligible requests continue to
|
|
772
|
+
use the legacy engine.
|
|
773
|
+
|
|
774
|
+
## 6.3.6
|
|
775
|
+
|
|
776
|
+
### Patch Changes
|
|
777
|
+
|
|
778
|
+
- 19e0d21: Remove the remaining backtracking ambiguity from the artifact-reference
|
|
779
|
+
`savedToPattern` in `extractArtifactReferencesFromMessages`, closing CodeQL
|
|
780
|
+
alert #320 (`js/polynomial-redos`).
|
|
781
|
+
|
|
782
|
+
An earlier fix stopped the capture's _first_ character from accepting
|
|
783
|
+
whitespace, which removed the overlap with the preceding `\s+`. It left a second
|
|
784
|
+
overlap in place: the capture body `[^—\]\n]*?` accepts tabs and spaces, and so
|
|
785
|
+
did the `\s+—` alternative in the trailing group, so the two still shared split
|
|
786
|
+
points across a whitespace run.
|
|
787
|
+
|
|
788
|
+
The trailing group now lists its terminators bare (`—`, `]`, `\n`, `$`). Because
|
|
789
|
+
the capture class excludes exactly those terminators, the two are disjoint,
|
|
790
|
+
exactly one parse exists at each position, and the polynomial behavior is gone
|
|
791
|
+
structurally rather than merely bounded.
|
|
792
|
+
|
|
793
|
+
Behavior is unchanged: dropping `\s+` only moves whitespace that sits before a
|
|
794
|
+
`—` from the separator into the capture, and the capture is already `.trim()`ed
|
|
795
|
+
at the use site. Verified equivalent across 16 input shapes, and pinned by two
|
|
796
|
+
new tests covering whitespace around the separator and a 200k-character
|
|
797
|
+
whitespace run.
|
|
798
|
+
|
|
799
|
+
## 6.3.5
|
|
800
|
+
|
|
801
|
+
### Patch Changes
|
|
802
|
+
|
|
803
|
+
- 6784100: Eliminate ReDoS on externally-influenced inputs
|
|
804
|
+
|
|
805
|
+
Five regexes that ran over third-party or tenant-authored text combined an
|
|
806
|
+
unbounded/lazy class with an overlapping quantifier, making them quadratic on a
|
|
807
|
+
hostile input. Each is now linear, with behavior preserved:
|
|
808
|
+
- **skill-spector** hostname extraction stripped delimiters with a single `/g`
|
|
809
|
+
alternation of two anchored branches (the global scan retried the `$` branch at
|
|
810
|
+
every position). Split into two separately anchored, non-global replaces, plus a
|
|
811
|
+
token-length cap — the manifest under scan is hostile by design.
|
|
812
|
+
- **sdk** artifact-reference extraction let `\s+` overlap a whitespace-accepting
|
|
813
|
+
lazy class; the capture's first character now excludes whitespace.
|
|
814
|
+
- **api** `store-vector` unwrapped `config.vectorsSource` with a regex whose `\s*`
|
|
815
|
+
overlapped `[^}]+?`. It now calls the shared, regex-free
|
|
816
|
+
`unwrapVectorSourceTemplate`, which also converges the api with the runtime's
|
|
817
|
+
previously private twin.
|
|
818
|
+
- **shared** `Link` header parsing widened `[^>]*` to `[^<>]*` so an unterminated
|
|
819
|
+
`<` fails at the next `<`.
|
|
820
|
+
- **model-execution** parameter-rejection classification now bounds the scanned
|
|
821
|
+
provider error body before matching, covering all five patterns.
|
|
822
|
+
|
|
823
|
+
- d3bb1ed: Apply security overrides for dev/build tooling (batch 1), resolving 29 Dependabot
|
|
824
|
+
alerts. Adds bounded `overrides` entries for `@tootallnate/once`, `ajv`,
|
|
825
|
+
`minimatch`, `path-to-regexp`, `smol-toml`, `rollup`, `@babel/core`, `js-yaml`,
|
|
826
|
+
`brace-expansion`, `undici` (<6 only) and `sharp`, and bumps the
|
|
827
|
+
`vercel-functions-hello` example's `vercel` devDependency 44 -> 58 so
|
|
828
|
+
`@vercel/fun` stops pinning `tar@6.2.1` (which no `tar` override could clear).
|
|
829
|
+
|
|
830
|
+
No runtime source changed; this is a lockfile/root-config change. Notable
|
|
831
|
+
resolution shifts: `sharp` 0.34.5 -> 0.35.2 (prebuilt binary set swap, verified
|
|
832
|
+
against the marketing Next.js build), `rollup` 4.57.0 -> 4.62.0, and `tar@6.2.1`
|
|
833
|
+
removed from the tree entirely. `undici@7.28.0` is deliberately untouched for
|
|
834
|
+
miniflare / wrangler / `@cloudflare/vitest-pool-workers`.
|
|
835
|
+
|
|
836
|
+
- 13b718f: Apply security overrides for runtime-reachable dependencies (batch 2). Adds bounded
|
|
837
|
+
`overrides` entries for `fast-uri`, `form-data` (3.x and 4.x), `lodash`, `uuid` (13.x),
|
|
838
|
+
`basic-ftp`, `defu`, `flatted`, `body-parser` (2.x), `js-yaml` (4.x),
|
|
839
|
+
`brace-expansion` (5.x), `ip-address` (10.x) and `dompurify`.
|
|
840
|
+
|
|
841
|
+
Unlike batch 1 these are reachable from shipped code, not just dev/build tooling:
|
|
842
|
+
`fast-uri` sits under `ajv` in the API worker's MCP/schema path, `form-data` and
|
|
843
|
+
`uuid` are pulled in by the API, runtime and sandbox dependency trees, `js-yaml` 4.x
|
|
844
|
+
reaches `@runtypelabs/cli`, and `brace-expansion` 5.x reaches
|
|
845
|
+
`@runtypelabs/model-execution`. The `dompurify` entry drops the vulnerable 3.3.3 copy
|
|
846
|
+
that `posthog-js` pulled in and consolidates on 3.4.12, the version
|
|
847
|
+
`@runtypelabs/persona` already ships in the same tree.
|
|
848
|
+
|
|
849
|
+
No runtime source changed; this is a lockfile/root-config change. Every override
|
|
850
|
+
carries a deliberate upper bound, since a bare `>=X` override resolves to the newest
|
|
851
|
+
match across all majors. Verified: no downgrades anywhere in the lockfile.
|
|
852
|
+
|
|
853
|
+
## 6.3.4
|
|
854
|
+
|
|
855
|
+
### Patch Changes
|
|
856
|
+
|
|
857
|
+
- 400c1f1: Tighten the batch results header and surface failed steps at the batch level
|
|
858
|
+
- Batch and scheduled-run results responses gain a `summary.recordsWithFailedSteps` count. It is batch-wide rather than page-scoped and ignores the status filter, so it stays correct on a paginated batch. The batch's own `failedRecords` cannot express this: a record whose flow ran to the end counts as completed even when a step inside it failed.
|
|
859
|
+
- The results sheet header collapses from three rows to two. Identity (title, copyable batch ID, duration, and the new "N with failed steps" signal) shares the title row with refresh and close, so the close button no longer drifts down beside the filters; the segmented status filter and record lookup get their own row.
|
|
860
|
+
- The record lookup is now an `ExpandingSearch` that costs an icon until used, instead of a permanently open text input.
|
|
861
|
+
- Dropped the title count badge when the segmented control is present, since its "All" segment already states the count.
|
|
862
|
+
- The batch sheet no longer routes through `ExecutionFilterBar`, which removes a "Clear" button that was always lit: the sheet seeds a `from` date that the batch endpoint never sends, so the bar read as actively filtered when nothing was applied.
|
|
863
|
+
|
|
864
|
+
- 400c1f1: Batch results screen redesign: honest per-record status and less chrome
|
|
865
|
+
- Batch and scheduled-run results endpoints now include a per-record step rollup (`stepCount`, `failedStepCount`, `durationMs`) so the results list can answer "did it work end to end, and how fast" without per-record fetches.
|
|
866
|
+
- Batch result rows are titled by record name (never "Unknown") and show duration plus a step summary; a completed record with failed steps renders as "Completed with errors" (amber) instead of a clean green "Completed", with the failed count spelled out in text.
|
|
867
|
+
- The batch results sheet gets a segmented status filter with counts (All / Completed / Failed / Running) driven by the batch summary, a copyable batch ID chip instead of an ID embedded in the title, a "Duration" label once the batch finishes, no $0.00 cost display, and a pagination footer only when there is something to page.
|
|
868
|
+
- The record detail panel leads with the run output, auto-expands failed steps with the error inline, quiets successful steps to icon-only status, and drops badges that repeated the header.
|
|
869
|
+
|
|
870
|
+
- 93a3c5b: Hosted Google OAuth connect flow with automatic token refresh. Google Workspace moves off the paste-a-token path onto `organization_integrations`: a "Connect Google" popup flow (`POST /v1/oauth/google/start` + public callback) captures tokens server-side, and a new token broker transparently refreshes access tokens (5-minute skew, optimistic version-gated writes) for every Google tool call. `invalid_grant` surfaces as a "Needs reconnection" badge instead of silent hourly credential death. BYO OAuth client supported per connect, with the deployment's authorized redirect URI shown as a copy field in both BYO panels (served by `GET /v1/oauth/google/config` so it is always the exact string the authorize call sends); the Runtype-provided platform client additionally ships behind the `enable-google-platform-oauth-client` Flagship gate (fail-closed off in production, on in staging/dev) on top of its `GOOGLE_OAUTH_CLIENT_ID`/`GOOGLE_OAUTH_CLIENT_SECRET` env requirement, so BYO is the only path until that rollout completes. The legacy pasted-token path is removed in the same change (a census found no stored `google-workspace` credentials in any environment): `POST`/`DELETE /v1/integrations/google/credentials` now reject with a pointer to the connect flow, and Google tool failures report their real cause instead of degrading into a generic "not configured" error.
|
|
871
|
+
|
|
872
|
+
## 6.3.3
|
|
873
|
+
|
|
874
|
+
### Patch Changes
|
|
875
|
+
|
|
876
|
+
- 844b742: Slack setup: replace the broken manifest deep link with a copy-and-paste flow. Slack's redesigned create-app modal silently ignores the `manifest_json` URL parameter, so `createAppUrl` now points at the plain app-creation page and the setup wizard has users copy the manifest and paste it into Slack's "From a manifest" option.
|
|
877
|
+
|
|
878
|
+
## 6.3.2
|
|
879
|
+
|
|
880
|
+
### Patch Changes
|
|
881
|
+
|
|
882
|
+
- f0ec44b: Realign the outer agent loop to terminate on natural model yield. The loop now
|
|
883
|
+
continues only for mechanical reasons: the turn was cut off by the inner tool
|
|
884
|
+
budget (`max_tool_calls`), the tool surface expanded that turn (skill load or
|
|
885
|
+
`tool_search` discovery), or the turn died on a provider error (retry path,
|
|
886
|
+
bounded by the consecutive-error abort). A turn the model ends itself
|
|
887
|
+
(`end_turn`) terminates the loop with `stopReason: 'complete'` regardless of
|
|
888
|
+
output length, tool count, or wording, so conversational agents with
|
|
889
|
+
`maxTurns > 1` no longer re-run tools and answer themselves after asking the
|
|
890
|
+
user a question. `maxTurns` is now a pure safety cap. Removes the
|
|
891
|
+
`"Continue working on the task."` nudge on terminating turns and the
|
|
892
|
+
four-signal `detectAutoComplete` text heuristics (the text-only signal
|
|
893
|
+
survives only as the fallback for providers that report no stop reason).
|
|
894
|
+
Breaking-internal: `@runtypelabs/runtime` no longer exports
|
|
895
|
+
`detectAutoComplete` / `AutoCompleteSignal`; use `decideLoopContinuation` and
|
|
896
|
+
its types instead.
|
|
897
|
+
|
|
898
|
+
## 6.3.1
|
|
899
|
+
|
|
900
|
+
### Patch Changes
|
|
901
|
+
|
|
902
|
+
- d547ab3: Fix client-chat dispatch of a locked-down (tenancy-strategy) agent failing every admitted turn: the `client_conversation` record is created at session init, before any identity proof exists, so it was un-stamped and the execution's scoped record read excluded it ("Record ... not found or not accessible"). The pipeline now claims the session-authorized conversation record into the resolved tenant/end-user scope pre-engine (idempotent claim-or-match), and rejects a cross-scope conversation with a 403 `conversation_scope_mismatch` instead of ever widening the read.
|
|
903
|
+
- c065bb9: Restore debug-tier cost and token fidelity dropped by the unified SSE cutover: the edge translator now forwards the flow-level `totalTokensUsed` scalar onto `execution_complete` and per-tool `toolCost` onto flow-family `tool_complete`. FilteredStream still strips both from user-facing streams; debug/SDK streams see them again, fixing the dashboard live execution timeline's per-tool cost display.
|
|
904
|
+
|
|
905
|
+
## 6.3.0
|
|
906
|
+
|
|
907
|
+
### Minor Changes
|
|
908
|
+
|
|
909
|
+
- 20737ee: Make the 33-event `ExecutionStreamEvent` vocabulary the platform's only public
|
|
910
|
+
execution stream. Remove request-, Persona-version-, and Flagship-based wire
|
|
911
|
+
format negotiation; translate API-owned engine frames unconditionally; expose
|
|
912
|
+
unified events in non-streaming JSON responses; and remove the public
|
|
913
|
+
`FlowSSEEvent` OpenAPI component.
|
|
914
|
+
|
|
915
|
+
Update the TypeScript and Python SDKs, dashboard, examples, smoke tests, and
|
|
916
|
+
internal tools to consume unified streams. The TypeScript SDK keeps its stable
|
|
917
|
+
flow and agent callback presentation shapes by translating the unified wire
|
|
918
|
+
client-side, while obsolete stream-format helper calls are source-compatible
|
|
919
|
+
no-ops. Preserve external-agent resume handles and flow completion counts on
|
|
920
|
+
the unified contract.
|
|
921
|
+
|
|
922
|
+
### Patch Changes
|
|
923
|
+
|
|
924
|
+
- 401acbd: Authored `toolMocks` on manual eval cases: a hand-written case can now carry its own `toolMocks` array without ever having been captured from a real run — `POST /eval/ensure`, `defineEval`, and the MCP eval-case tools all accept it. On a suite with `recordedToolMode: 'continue'`, `toolMocks` presence (captured or authored) is what triggers serving recorded results instead of dispatching the real tool, so an eval case can now get a `toolType: 'local'` tool past its first call (which otherwise pauses the run forever) without a captured checkpoint. `checkpoint` stays capture-only — it is execution-state (where a run was forked from), not something an author writes by hand, and `/eval/ensure` continues to reject it. Authored-mocks replay keeps the same agent (virtual-flow) target restriction as captured checkpoint cases; a flow-target suite skips the case as a gradeable failure instead of running it. The suite-run batch path (`POST /eval/suites/:id/run` above the sync case ceiling) now rejects a continue-mode case carrying `toolMocks` (`REPLAY_MODE_CASES_UNSUPPORTED_ON_BATCH`) instead of silently running it with mocks unserved; the code-mode MCP spec overlay and SDK output validation (a mock must include an explicit `output` key) round out the surface. A `ToolMock`'s `output` field is now correctly marked required in the generated OpenAPI spec and TS SDK types (a bare `z.unknown()` had rendered it as optional despite the server always requiring it, letting a caller construct an output-less mock the server then rejected with an opaque error).
|
|
925
|
+
- cb8cb9e: Per-case eval graders: eval cases now carry an optional `graders` array that REPLACES the suite-level graders for that case (null ⇒ use the suite graders). `POST /eval/ensure` decomposes divergent per-case `expect` arrays into a suite default plus per-case overrides instead of rejecting them with a 400; both run paths (sync `/eval/run` and the batch scoring pass) score each case against its own effective grader array, and `graderIndex` now indexes into that per-case array. The suite CRUD case schemas, `/eval/ensure` pull round-trip, and the MCP eval-case tool inputs all carry the field.
|
|
926
|
+
- 7f77e9f: Surface responses now embed the canonical public endpoint URL. The API computes `endpoint` server-side (via its own base-URL authority) on surface list, get, create, and update responses, and on surfaces embedded in the product GET: the URL for MCP, API, A2A, AG-UI, webhook, and chat surfaces, or null for channel-based types (Slack, email, schedule). The dashboard's snippet generators, endpoint listings, and onboarding steps now prefer `surface.endpoint` over client-side URL construction, which survives only as a fallback for cached payloads that predate the field.
|
|
927
|
+
|
|
928
|
+
## 6.2.1
|
|
929
|
+
|
|
930
|
+
### Patch Changes
|
|
931
|
+
|
|
932
|
+
- 68a503e: Add `orgName` to the `GET /v1/users/profile` response: the display name of the caller's active organization, resolved from the Clerk-synced organizations table. Null for personal accounts. Lets API-key and SDK consumers resolve their org identity without a Clerk session.
|
|
933
|
+
|
|
934
|
+
## 6.2.0
|
|
935
|
+
|
|
936
|
+
### Minor Changes
|
|
937
|
+
|
|
938
|
+
- b967727: Remove the dead product-generation sessions surface: the `/v1/products/generation/sessions` CRUD endpoints (create, list, get, update, delete, append-event) and their `product_generation_sessions` / `product_generation_session_events` tables. This surface was orphaned legacy from the March 2026 three-agent generator design and had zero consumers (dashboard, worker, CLI, SDK, or API callers); both tables held zero rows in staging and production. A drop migration removes the tables; the OpenAPI spec and generated TypeScript/Python SDK types no longer expose the routes.
|
|
939
|
+
|
|
940
|
+
### Patch Changes
|
|
941
|
+
|
|
942
|
+
- 2c8cf42: Secrets gain a first-class `docsUrl` ("where to get this key"). New nullable `docs_url` column on secrets with https-only validation (`secretDocsUrlSchema`) at every write path (REST create/update with null-clears, intake submit, MCP `create_secret`/`update_secret` via `docs_url`), plus a hand-curated provider-docs registry (`SECRET_PROVIDER_DOCS`, 15 providers) mapping well-known key names to official console pages. Intake manifest items resolve `docsUrl` server-side with binding > secret row > registry precedence, each candidate gated by the new `isSafeDocsUrl` guard; the dashboard gates all "Get key" anchors on the same guard (hardening for pre-gate rows) and manual mode shows a registry-driven "Get key" button as the user types a known key name. FPO `setupInstructions.docsUrl` validation tightened to https-only.
|
|
943
|
+
- 2c8cf42: Secret intake sources accept an optional `description` so MCP agents can hand users a self-explanatory configuration link. `secretRequirementSourceSchema` gains the field; `buildConfigurationUrl` carries it (with `key`) into the intake screen query string; focused (`source=secret`) manifest items fall back to the caller-supplied description when the secret does not exist yet; the dashboard renders it on focused cards and forwards it from the URL. The MCP `get_secret_intake_manifest` / `submit_secret_intake` source and `create_secret.description` now guide agents to write descriptions that state the key's general, account-wide purpose and where to obtain the value. Secret values never travel in URLs.
|
|
944
|
+
|
|
945
|
+
## 6.1.4
|
|
946
|
+
|
|
947
|
+
### Patch Changes
|
|
948
|
+
|
|
949
|
+
- 843b702: Remove the `enable-agent-skills` Flagship rollout flag now that Agent Skills is fully enabled in production. The feature is unconditionally on: the admin/control-plane gate, the legacy-flow and resume-reattach skill-loading gates, the `propose_skill` execution guard, and the dashboard Skills nav/route gating are all removed. `GET /v1/users/profile` still returns `features.enableAgentSkills`, now hardcoded to `true` for wire compatibility with deployed SPA bundles and the published SDK.
|
|
950
|
+
|
|
951
|
+
## 6.1.3
|
|
952
|
+
|
|
953
|
+
### Patch Changes
|
|
954
|
+
|
|
955
|
+
- 1acada7: Accept inline `config.flow` flow tools at the dispatch boundary when the caller opts into the runtime execution lane (`options.useRuntimePackage: true`). The dispatch validator previously rejected any flow tool without a `flowId`/`toolId` reference, and the tools normalizer silently stripped `config.flow` — together 400-ing the rt-seam staging smoke templates and rolling back the staging deploy. Inline flows remain rejected (clean 400 with an actionable message) on the legacy lane, which cannot execute them. `flowName`-only references are accepted on the runtime lane (resolved `flowName ?? flowId` by the runtime tool executor); the SDK's mirrored `FlowToolConfig`/`RuntimeFlowToolConfig` types gained the same `flow`/`flowName` fields.
|
|
956
|
+
- db2cf06: Make monetary usage delivery idempotent, normalize live billing webhooks and customer notifications, and rebuild Billing and Usage around explicit collection, credit, analytics, and enforcement sources.
|
|
957
|
+
|
|
958
|
+
## 6.1.2
|
|
959
|
+
|
|
960
|
+
### Patch Changes
|
|
961
|
+
|
|
962
|
+
- 158223e: Launch Runtown as a disposable, standalone, staging-only Cloudflare app for navigating a real Runtype product as a third-person 3D town. A Flagship-gated dashboard command opens the experiment, which signs in with Clerk, calls the user API directly, adapts Pica's first-run tour to the product architecture, and deep-links back to canonical dashboard editors. Runtown has no production Worker, route, release dispatch, or production-access path while the experiment is being evaluated.
|
|
963
|
+
|
|
964
|
+
Add account-and-product-scoped Durable Object multiplayer with anonymous travelers, authoritative movement guards, short-lived tickets, and opt-in HRTF nearby dialogue cues that never transmit questions, generated answers, transcripts, or generated audio. Preserve the richer architecture characters, grounded streamed narration, enterable buildings, live execution traffic, quests, configuration health, and spatial voice while isolating all game code and deployment lifecycle from the dashboard.
|
|
965
|
+
|
|
966
|
+
- 3abba4d: Preserve debug step costs and inline Claude Managed agent IDs in unified SSE streams while migrating smoke coverage to the default vocabulary.
|
|
967
|
+
|
|
968
|
+
## 6.1.1
|
|
969
|
+
|
|
970
|
+
### Patch Changes
|
|
971
|
+
|
|
972
|
+
- 40cb003: Generated OpenAPI types for the flow export-runtime response now declare the
|
|
973
|
+
ADR 0014 fields (`agents` Embedded Agent Registry and `dependencyRefs`), so
|
|
974
|
+
typed SDK consumers get first-class access instead of reaching through
|
|
975
|
+
untyped extras.
|
|
976
|
+
|
|
977
|
+
## 6.1.0
|
|
978
|
+
|
|
979
|
+
### Minor Changes
|
|
980
|
+
|
|
981
|
+
- cfacf11: feat: record collections on every non-REST surface
|
|
982
|
+
|
|
983
|
+
Fans the `/v1/collections` REST API (Records→Collections Phase 1) out to the
|
|
984
|
+
remaining surfaces, closing the Phase 1 acceptance loop — create → infer →
|
|
985
|
+
warn → validate-existing → enforce → 422 works identically via REST, SDK, MCP,
|
|
986
|
+
and CLI:
|
|
987
|
+
- **MCP** (`@runtypelabs/mcp` + the api-internal client): seven tools —
|
|
988
|
+
`list_collections`, `get_collection`, `create_collection`,
|
|
989
|
+
`update_collection`, `delete_collection`, `infer_collection_schema`,
|
|
990
|
+
`validate_collection_records` — with
|
|
991
|
+
read-only/destructive annotations, next-step hints, and collections-domain
|
|
992
|
+
error recovery hints.
|
|
993
|
+
- **Code Mode MCP**: matching `runtype.listCollections(...)` /
|
|
994
|
+
`getCollection` / `createCollection` / `updateCollection` /
|
|
995
|
+
`deleteCollection` / `inferCollectionSchema` / `validateExistingRecords`
|
|
996
|
+
executor methods with overlay docs and examples.
|
|
997
|
+
- **SDK**: `client.collections` endpoint class
|
|
998
|
+
(list/get/create/update/delete/inferSchema/validateExisting) with response
|
|
999
|
+
types derived from the generated OpenAPI spec.
|
|
1000
|
+
- **CLI**: `runtype collections list|get|create|update|delete|infer|validate`,
|
|
1001
|
+
including `--schema-file` round-tripping and the infer → update adoption
|
|
1002
|
+
flow.
|
|
1003
|
+
- **Docs**: new user-guide page "Defining a schema" plus a collections section
|
|
1004
|
+
in the MCP server integration guide.
|
|
1005
|
+
|
|
1006
|
+
The dashboard assistant deliberately excludes the new tools
|
|
1007
|
+
(`phase2:collections`) until the Collections UI ships.
|
|
1008
|
+
|
|
1009
|
+
- cd1133f: Add a Slack "Add to Slack" OAuth install flow. The Slack setup wizard now
|
|
1010
|
+
captures the bot token server-side via a real OAuth v2 handshake instead of
|
|
1011
|
+
asking the user to hand-copy the App ID, install the app, and paste the
|
|
1012
|
+
`xoxb-` bot token. The user pastes only the three App Credentials (Client ID,
|
|
1013
|
+
Client Secret, Signing Secret) from one Slack page and clicks "Add to Slack".
|
|
1014
|
+
- New authenticated `POST /v1/oauth/slack/start` returns the Slack authorize
|
|
1015
|
+
URL, storing the client + signing secret in a short-lived (10 min),
|
|
1016
|
+
one-time-use, AES-256-GCM-encrypted KV state blob.
|
|
1017
|
+
- New public `GET /v1/oauth/slack/callback` exchanges the code, claims the
|
|
1018
|
+
pending integration, and posts non-secret metadata back to the dashboard
|
|
1019
|
+
opener. The bot token never transits the browser.
|
|
1020
|
+
- The generated Slack app manifest now includes `oauth_config.redirect_urls`.
|
|
1021
|
+
- New `integrations.startSlackOAuth` SDK method.
|
|
1022
|
+
|
|
1023
|
+
### Patch Changes
|
|
1024
|
+
|
|
1025
|
+
- c26556c: Add record collections: customer-defined data models for Records. New `record_collections` entity (slug = record type by convention) owning an optional constrained-dialect JSON Schema, with `/v1/collections` CRUD, append-only schema version history, additive-vs-breaking evolution gating, infer-schema-from-data proposals, and validate-existing dry runs. Validation mode defaults to `off`, so registering a collection changes no existing behavior; write-seam enforcement lands in a follow-up.
|
|
1026
|
+
- 2c315c5: Enforce collection schema validation at every record write seam (Records→Collections Phase 1 PR 2). When a record's type matches a collection whose validationMode is `warn` or `enforce` with a non-null schema, the write's metadata is validated: `enforce` rejects with a 422 `schema_validation_failed` envelope carrying stable field-level codes (`REQUIRED_FIELD_MISSING`, `INVALID_TYPE`, `INVALID_ENUM_VALUE`, …); `warn` proceeds, surfaces `schemaWarnings` on the response, and stamps the new nullable `records.schema_valid` column. Covered seams: POST/PUT /v1/records, bulk-edit (post-merge), CSV import (per-row), the upsert-record/update-record context steps (step errorHandling contract), the builtin record agent tools, the dispatch record-create path, and the conversations routes. `recordFilter` gains a `schemaValid` top-level pseudo-field (`isTrue`/`isFalse`/`isSet`/`isNotSet`) so filters can target nonconforming or unevaluated rows. Unregistered types see zero behavior change.
|
|
1027
|
+
- 644e057: Generate the Slack app manifest API-side so it always carries absolute URLs. The Slack setup wizard built the manifest in the browser from the SPA's API base, which is the relative `/api` proxy path on staging/preview, so the manifest ended up with relative URLs (`/api/v1/messaging/webhooks/slack/...`) that Slack rejects (`Input must match regex pattern: ^https?:\/\/`). A new authed endpoint `POST /v1/integrations/slack/manifest` builds the manifest from the API's true public origin; its OAuth redirect URL now reuses the same helper as the OAuth start route so the manifest's `redirect_urls` and the handshake's `redirect_uri` can never drift. Also fixes two Slack schema issues (empty `suggested_prompts`, unsanitized bot `display_name`), makes the manual webhook URL shown for surfaces absolute, and derives the OAuth-callback postMessage origin from the manifest so completion no longer breaks on relative API bases.
|
|
1028
|
+
|
|
1029
|
+
## 6.0.2
|
|
1030
|
+
|
|
1031
|
+
### Patch Changes
|
|
1032
|
+
|
|
1033
|
+
- a948051: `POST /v1/client/resume` now accepts an optional refreshed `clientTools[]` + `clientToolsFingerprint` snapshot (same diff-only / send-once protocol as `/v1/client/chat`, including the 409 `client_tools_resend_required` handshake). The refreshed set is re-validated and re-gated against the surface's `behavior.webmcp` policy, then replaces the run's persisted clientTools so page tools registered after a mid-run navigation become callable on the next model turn — letting a WebMCP browser agent complete cross-page tasks (search → navigate → read product → add to cart) in a single user turn. Omitting both fields keeps the existing frozen-at-dispatch behavior.
|
|
1034
|
+
|
|
1035
|
+
## 6.0.1
|
|
1036
|
+
|
|
1037
|
+
### Patch Changes
|
|
1038
|
+
|
|
1039
|
+
- 4b4bbe9: Fix and prune the `paginate-api` flow step.
|
|
1040
|
+
- **`link_header` pagination now actually advances pages.** Previously the loop rebuilt the base URL every iteration and discarded the `rel="next"` URL parsed from the response `Link` header, so it either looped on page one or never followed the next link. The next URL is now threaded through the loop and fetched directly, so link-header APIs (e.g. GitHub) paginate correctly.
|
|
1041
|
+
- **Removed the unused `oauth2` auth type.** The `oauth2` value is dropped from the `authType` enum and the `oauth2TokenUrl` / `oauth2ClientId` / `oauth2ClientSecret` / `oauth2Scopes` fields are removed from `authConfig`. The executor never implemented OAuth2 (it only logged a warning), and zero stored flows use it.
|
|
1042
|
+
- **Removed the unused `entityIdPath` field.** It was never read by the executor.
|
|
1043
|
+
- Fixed the hidden `api-data-sync` dashboard template, which used a non-schema `pagination: { type, pageSize, maxPages }` shape; it now uses the schema fields (`paginationType`, `pageSize`, `maxPages`).
|
|
1044
|
+
|
|
1045
|
+
- 9a3dd1a: Narrow the `send-event` flow step's `provider` to PostHog only. The step never shipped a Google Analytics, Amplitude, or Segment implementation (those enum values threw at dispatch), so `provider` now accepts `'posthog'` alone; a flow that stored a removed value fails validation with an actionable message pointing at the API Call step for other analytics services. The SDK's `SendEventStepConfig.provider` type is narrowed to `'posthog'` to match. The PostHog capture request now goes through the executor's fetch seam, adding SSRF protection; that seam also defaults the Runtype User-Agent for every shared HTTP step (fetch-url, paginate-api, api-call, wait-until, send-event).
|
|
1046
|
+
- aab02e1: Remove dead flow-step config surface that was accepted by validation but never read by either execution engine. Each field below was verified unused in the api and runtime executors with zero stored production usage; removing them makes the schemas honest about what the platform actually does. A flow that stored one of these fields keeps running — the value was already ignored — it simply no longer appears in the schema, SDK types, or generated artifacts.
|
|
1047
|
+
- **`update-record.updatesTemplate`** — removed from the schema and the runtime executor branch that implemented it. Use `updates` (per-value `{{template}}` substitution) instead. Dropping it keeps update targets' field names statically knowable. A config still carrying the field now fails loudly rather than silently applying an empty patch: the shared normalizer (which runs on the API execution and validation paths) throws a `NormalizationError`, and the runtime executor (which bypasses normalization) throws its own equivalent guard.
|
|
1048
|
+
- **`generate-embedding` inline vector store** — removed the `vectorStore` sub-config and the `storeInRecord` flag. This step only produces an embedding vector into `outputVariable`; persisting it is the separate `store-vector` step's job (the inline store was never wired to an executor). The false "stores the embedding in a vector DB" doc comment is corrected.
|
|
1049
|
+
- **`pinecone` vector backend** — dropped from the `vector-search` and `store-vector` provider/destination enums (plus the now-unreachable `pineconeConfig` sub-configs and dashboard affordances). Pinecone was never implemented — it only ever threw "not yet implemented". The `vector-search` executor now throws an actionable error on an unknown provider instead of silently falling through to the pgvector path.
|
|
1050
|
+
- **`execute-agent.variables`** — removed from the schema and normalizer; nothing read it.
|
|
1051
|
+
- **`upsert-record.metadataMapping`** — removed from the schema and normalizer; nothing read it.
|
|
1052
|
+
- **`api-call.requestTemplate`** — removed from the schema and normalizer; it was dropped at the api-call → fetch-url seam.
|
|
1053
|
+
- **`retrieve-record.fields`** — removed from the schema (UI-only, never read).
|
|
1054
|
+
- **`fetch-url` `responseType: 'xml'`** — removed from the enum, the executor branch, and the SDK type. It only ever aliased `text` (there was never XML parsing). The schema stays strict so new authoring is rejected, but because the normalizer runs on the API execution path a legacy stored flow keeps working: `normalizeFetchUrlConfig` remaps a stored `'xml'` to `'text'` before the enum check (and the runtime executor's default branch already returns text), so immutable `flow_versions` still execute.
|
|
1055
|
+
|
|
1056
|
+
The removed SDK builder fields (`GenerateEmbeddingVectorStoreConfig`, `StoreVectorPineconeConfig`, and the corresponding `flow-builder` config properties) and the shared type aliases are dropped in the same change.
|
|
1057
|
+
|
|
1058
|
+
- ebb401b: Sibling-parity fixes for two flow step types (additive, no behavior change for existing flows):
|
|
1059
|
+
- **tool-call `timeout`**: the config field existed but was passed as an ignored `_timeout` parameter and never enforced. It is now enforced via `Promise.race` inside `executeToolById`. A timeout fails the step respecting its `onError` contract (throws for `fail`/`retry`, returns the continue output for `continue`). Enforcement applies only when `timeout` is set, so flows that omit it keep their prior unbounded behavior.
|
|
1060
|
+
- **send-stream `outputVariable` / `errorHandling` / `defaultValue`**: send-stream previously accepted only `{ message }`. It now supports an optional `outputVariable` (defaults to `"message"`, so the flows that omit it are unaffected) plus the standard `errorHandling` / `defaultValue` continue-on-error fields shared by sibling steps. The streaming orchestrator resolves the effective output key so a custom output variable still streams. The SDK `SendStreamStepConfig` exposes the new fields; the dashboard step-card UI for `outputVariable` is deferred to a follow-up (its closest sibling, send-event, also omits it).
|
|
1061
|
+
|
|
1062
|
+
## 6.0.0
|
|
1063
|
+
|
|
1064
|
+
### Major Changes
|
|
1065
|
+
|
|
1066
|
+
- 51ab2d1: Remove the `fetch-github` flow step from validation, execution, SDKs, generated schemas, and dashboard surfaces. The step was never surfaced in the UI, ignored half of its own config fields, and depended on an external repomix ingestor service. Use `api-call` for single GitHub API requests, `transform-data` with a container sandbox (`daytona` / `runtype-sandbox`) to clone and work on repositories, or the GitHub MCP server for agent-driven GitHub work.
|
|
1067
|
+
- a27eea9: Remove the non-functional `send-text` flow step from validation, SDKs, generated schemas, and dashboard surfaces.
|
|
1068
|
+
|
|
1069
|
+
### Minor Changes
|
|
1070
|
+
|
|
1071
|
+
- 5f08625: feat: product and surface setup readiness
|
|
1072
|
+
|
|
1073
|
+
Adds a net-new readiness primitive that answers "what's left to make this product (or surface) live?" with structured, headless-first next steps. A pure `@runtypelabs/shared` core composes pending secrets with each surface's remaining install steps, and every step names the best available way to satisfy it — an MCP tool to call now, a REST call from a coding harness, or a dashboard deep link when a browser is genuinely required (OAuth, DNS, keypair).
|
|
1074
|
+
- `GET /v1/products/{id}/setup` and `GET /v1/products/{id}/surfaces/{surfaceId}/setup` (public API).
|
|
1075
|
+
- `get_product_setup` and `get_surface_setup` read-only MCP tools, plus code-mode `getProductSetup` / `getSurfaceSetup`.
|
|
1076
|
+
|
|
1077
|
+
### Patch Changes
|
|
1078
|
+
|
|
1079
|
+
- 5cff576: Enforce full-workspace ESLint coverage for published TypeScript packages.
|
|
1080
|
+
- 9ab9197: Persist flow descriptions and use the generated flow request contract across the SDK and dashboard.
|
|
1081
|
+
|
|
1082
|
+
## 5.15.0
|
|
1083
|
+
|
|
1084
|
+
### Minor Changes
|
|
1085
|
+
|
|
1086
|
+
- 6aac451: feat: add a multi-header auth type (`type: 'headers'`) for custom MCP servers. Servers can now send an arbitrary non-empty record of legal HTTP headers, with `{{secret:NAME}}` references resolved through the scoped secret store and registered with the per-execution leak guard. Support spans API discovery and saved-server CRUD, runtime discovery and dispatch, FPO/agent/SDK contracts, and runtime export. The dashboard exposes the uncommon configuration through a progressively disclosed **Advanced authentication** editor while keeping stored values encrypted and opaque until the user supplies a complete replacement set.
|
|
1087
|
+
|
|
1088
|
+
## 5.14.3
|
|
1089
|
+
|
|
1090
|
+
### Patch Changes
|
|
1091
|
+
|
|
1092
|
+
- 29ce53f: Finish hiding pre-GA Runtype Apps from public SDK/docs/CLI surfaces and keep app-only client sessions fail-closed behind the feature flag.
|
|
1093
|
+
- 5d828d9: Use Schematic-accepted platform spend as the canonical billing-month spend display across Billing and Usage.
|
|
1094
|
+
|
|
1095
|
+
## 5.14.2
|
|
1096
|
+
|
|
1097
|
+
### Patch Changes
|
|
1098
|
+
|
|
1099
|
+
- b00dea7: Hide pre-GA Runtype Apps surfaces from public tool catalogs, docs, schemas, skills indexes, SDK generation, and unauthenticated CLI help; keep runtime/tool access fail-closed behind the feature flag.
|
|
1100
|
+
|
|
1101
|
+
## 5.14.1
|
|
1102
|
+
|
|
1103
|
+
### Patch Changes
|
|
1104
|
+
|
|
1105
|
+
- 0d4b1b8: Default Usage analytics to the current billing month and add spend analytics period presets.
|
|
1106
|
+
|
|
1107
|
+
## 5.14.0
|
|
1108
|
+
|
|
1109
|
+
### Minor Changes
|
|
1110
|
+
|
|
1111
|
+
- facb5d9: Add Massive Web Render as a web-scraping provider alongside Firecrawl. Includes the `builtin:massive` agent tool, a `massive` fetch method on the fetch-url flow step (format, geotargeting, delay, and cache options), a `PLATFORM_MASSIVE_KEY` platform key with BYOK support via Settings > Integrations, cost tracking (`massive:render`), and SDK/dashboard surfaces. The whole feature ships behind the `enable-massive-web-render` Flagship flag (fail-closed in production): tool execution, the fetch-url step branch, built-in tool listings, and the dashboard surfaces (via `features.enableMassiveWebRender` on the user profile) all gate on it.
|
|
1112
|
+
|
|
1113
|
+
## 5.13.0
|
|
1114
|
+
|
|
1115
|
+
### Minor Changes
|
|
1116
|
+
|
|
1117
|
+
- 89dbb72: FPO expressiveness: evals, skills, and Claude Managed agents are now first-class in the Full Product Object schema.
|
|
1118
|
+
- New optional top-level `evals[]` section (suites with graders, cases, recorded-tool replay config) targeting a capability; assembly materializes suites + cases with `origin: 'fpo'`, and ensure-fpo converges suite-level fields while preserving user-added (non-FPO-origin) cases.
|
|
1119
|
+
- New optional top-level `skills[]` section (content, trust level, capability refs, inline tools, `bindTo` agent capabilities); materialized via the skill service and bound to agent-backed capabilities. `mcpServers` is rejected at the schema per the v1 write invariant.
|
|
1120
|
+
- `agentClaudeManagedConfigSchema` widened to the canonical surface: `setupMode` ('create' | 'connect'), `mcpServers`, `customTools` (materialized into `agent_capabilities` with FPO-local capability ids rewritten to real product capability ids), and `anthropicAgentVersion` coerced to number (legacy string input still accepted). ensure-fpo no longer rejects inline `claude_managed` / `external` agents.
|
|
1121
|
+
- `pull-fpo` now reconstructs `secrets` (declarations from product secret bindings), `schedules`, `evals` (shape-compatible cases only, with skip warnings for captured checkpoint/toolMock cases), `skills` (via agent skill bindings), and Claude Managed agent configs. Records remain unreconstructed (account-scoped, not product-attributable) with an explicit warning.
|
|
1122
|
+
- Mirror-drift fixes: public FPO types gain the `ag-ui` / `hosted-page` / `chrome_extension` surface types; FPO flow steps accept top-level `when`; the flat agent schema's error handling gains `message` fallbacks + `triggers` and its runtime-tool type enum gains `advisor` / `search`, matching v2.
|
|
1123
|
+
- `computeFpoContentHash` covers the new sections with absent-key omission, so hashes of existing FPOs without `evals`/`skills` are unchanged (all three lockstep copies updated).
|
|
1124
|
+
|
|
1125
|
+
## 5.12.1
|
|
1126
|
+
|
|
1127
|
+
### Patch Changes
|
|
1128
|
+
|
|
1129
|
+
- b2badd2: Retire the `usage-based-pricing` feature flag now that the rollout is complete across all environments. The trial-expiry and auto-topup-failed spend-gate branches, the card-entry slow-mode 429 messaging (`/settings/billing/portal` CTA), the `X-Runtype-Billing-Status` advisory header, and the billing lifecycle emails are now unconditional. The `features.usageBasedPricing` field is removed from `GET /v1/users/profile`, and the dashboard renders the card-centric billing copy unconditionally.
|
|
1130
|
+
|
|
1131
|
+
## 5.12.0
|
|
1132
|
+
|
|
1133
|
+
### Minor Changes
|
|
1134
|
+
|
|
1135
|
+
- 9a527cd: Evals E6: feedback-triggered eval proposals and judge calibration.
|
|
1136
|
+
|
|
1137
|
+
Real end-user feedback now feeds the eval proposal queue automatically: a thumbs-down, NPS of 6 or below, or CSAT of 2 or below on a Flow conversation proposes a regression case forked just before the poorly rated reply (a left comment pre-fills the expected answer), and a thumbs-up or NPS of 9 or above proposes a golden case whose endorsed reply becomes the expectation. The on-write hook is non-blocking, dedups per conversation moment, targets the Flow's default (or only) suite, and writes through the governed E5 proposal seam so the per-suite daily cap and review-required governance apply unchanged.
|
|
1138
|
+
|
|
1139
|
+
Judge calibration lands the humanVerdict loop: POST /eval/scores/{scoreId}/review records a lightweight 👍/👎 review of an AI-grader verdict (run-results outcomes now carry `scoreId` and `humanVerdict`), and the suite detail exposes `judgeAgreement`, surfaced on the suite page as a plain "Agrees with you N of M times" trust display. Parity: SDK `evals.reviewScore` + `PersistedGraderOutcome`, MCP `review_eval_score`, code-mode `reviewEvalScore`, and dashboard 👍/👎 buttons with a tune-your-criteria hint on disagreement.
|
|
1140
|
+
|
|
1141
|
+
### Patch Changes
|
|
1142
|
+
|
|
1143
|
+
- 2821ddb: Evals E5: eval case proposal queue, definition-seeded generation, and the coverage meter. New `eval_case_proposals` table plus REST endpoints (`GET /v1/eval/suites/{id}/proposals`, accept/reject, `POST /v1/eval/suites/{id}/generate-cases`, `GET /v1/eval/suites/{id}/coverage`). Machine-generated cases never enter a suite directly: generation fans the target definition out over an explicit diversity matrix (category × persona), filters candidates for gradeability, and writes proposals that require an affirmative accept (verbatim or edited, with provenance backlink and audit trail — same governance stance as skill proposals). The coverage meter reports which target tools and instruction clauses the suite's cases and graders already exercise (structural tool inventory + a cached, definition-hash-invalidated LLM clause pass), with per-gap targeted generation. Ships with the suite-page review queue and coverage UI, SDK methods (`suites.listProposals/acceptProposal/rejectProposal/generateCases/getCoverage`), and MCP tools (`list_eval_proposals`, `resolve_eval_proposal`, `generate_eval_cases`, `get_eval_coverage`).
|
|
1144
|
+
- ec895c9: Prompt-caching auto-demotion loop plus two caching-ops levers.
|
|
1145
|
+
- **Auto-demotion**: workloads that persistently pay the Anthropic 1.25× cache-write premium without landing reads (≥20 stamped requests in a 24h window with a <5% read rate) are automatically suppressed from stamping for 24h via a KV entry consulted upstream of `computeCachePlan`. Counters are folded inline at the usage-emit site (no cron), fail-open everywhere, keyed by tenant + agent/flow@version, with a structured `prompt-cache demotion` log charted on the Grafana prompt-cache dashboard. `CACHE_AUTO_DEMOTION_DISABLED='true'` is the ops kill switch.
|
|
1146
|
+
- **Gateway cache-pinning kill switch**: `CF_GATEWAY_CACHE_PINNING_DISABLED='true'` restores Vercel-gateway Anthropic failover for cache-bearing requests without turning off caching.
|
|
1147
|
+
- **Per-batch canary opt-out**: `options.skipCacheWarm` on batch submission skips the serial prompt-cache warm canary and fans out immediately (REST, SDK `BatchOptions`, MCP `submit_batch`).
|
|
1148
|
+
|
|
1149
|
+
## 5.11.0
|
|
1150
|
+
|
|
1151
|
+
### Minor Changes
|
|
1152
|
+
|
|
1153
|
+
- 8f998e7: Add optional offset pagination to `GET /v1/client-tokens` (`limit` 1-200 + `offset`), mirroring the `/client-tokens/:id/conversations` sibling. When `limit` is provided the response includes a `pagination` object (`limit`, `offset`, `hasMore`); when omitted the full list and legacy envelope are returned unchanged, so existing callers keep working. The listing order gains a deterministic `id` tiebreak. The params are threaded through the SDK `clientTokens.list()`, the MCP `list_client_tokens` tool, and the Code Mode `listClientTokens(params)` method.
|
|
1154
|
+
- 9a47ef1: Prompt caching slice 3 — determinism guards + implicit-provider hygiene + escape hatch.
|
|
1155
|
+
- **Determinism (prompt-cache hit rate):** freeze `_execution.timestamp` / `_now` once per execution instead of per loop iteration (both the api agent loop and the runtime port), so temporal system-prompt bytes stay identical across turns and don't bust the cache prefix. Weighted provider selection (`selectProviderByWeight`) is now sticky per conversation — a deterministic hash of `conversationId ?? executionId` replaces `Math.random()`, so a multi-provider family never flips providers mid-conversation onto a cold cache.
|
|
1156
|
+
- **Implicit / routing-key providers:** OpenAI-family routes now carry a platform-derived `promptCacheKey` (`providerOptions.openai.promptCacheKey`) sharded per conversation — a cross-tenant routing-namespace hygiene fix and a hit-rate improvement; scope keys are derived from platform-owned identifiers only, never caller-supplied on platform keys. DeepSeek's `prompt_cache_hit_tokens` / `prompt_cache_miss_tokens` usage shape is now normalized by `normalizeCacheUsage`. No new family's billing discount is flipped on (hygiene only).
|
|
1157
|
+
- **Escape hatch:** `options.cache: false` on dispatch / execute-agent (and the `.strict()` MCP tool mirrors) disables prompt caching per request, overriding the rollout flag — for eval/batch fan-outs and workloads that must never share provider cache state.
|
|
1158
|
+
- New byte-prefix parity corpus (`prompt-cache-parity/`) driven by both prompt-executor ports pins the actual product outcome (hit rate): turn N is a strict byte-prefix of turn N+1, boundary sets are identical across executors, and no stray timestamp bytes appear when the template has no temporal references.
|
|
1159
|
+
|
|
1160
|
+
### Patch Changes
|
|
1161
|
+
|
|
1162
|
+
- e6b97e1: Regenerated OpenAPI types for the hosted end-user identity endpoints (`/v1/end-user-auth/*`): request/response schemas and the `rt_eu_`-prefixed access-token description.
|
|
1163
|
+
- e88000e: Trace→eval capture UI (E3 UI increment): "Add to eval" from a log trace, fork picker, replayability badge, and the next-step divergence diff.
|
|
1164
|
+
- **Add to eval** — an agent execution's log detail panel gains an "Add to eval" action that forks the run into a `saved_from_run` test case. The dialog picks an agent-target eval (or creates the agent's default one), lets the user choose which recorded action becomes the graded next step (fork picker), and reports whether the case is fully replayable after saving.
|
|
1165
|
+
- **Capture preview endpoint** — new `GET /v1/eval/executions/{executionId}/capture-preview` dry-runs the capture (same ownership-scoped reader and message math as the write path) and returns the recorded actions plus the fork index each maps to, so the fork picker never re-derives the seed math client-side.
|
|
1166
|
+
- **Replayability badge** — captured cases in the suite view show a "Replayable" / "Partial replay" badge derived from whether any recorded tool output was truncated at capture.
|
|
1167
|
+
- **Divergence diff** — the run-results page shows, for a captured case run in next-step mode, the recorded next action beside the new run's next action ("used to call `lookup_account`, now calls `issue_refund`"), before the grader chips. This is backed by a new persisted `eval_case_scores.next_step_tool_calls` column (a migration) written by the next-step run path and read back through `GET /v1/eval/runs/{runId}/scores`; the `NextStepToolCall` shape is added to `@runtypelabs/shared` and surfaced on the SDK's `EvalRunScores` cases.
|
|
1168
|
+
|
|
1169
|
+
- 3ac490c: Evals E4 — recorded-tool replay ("continue past the first action"). A new
|
|
1170
|
+
`RecordedToolExecutor` (runtime) serves a captured case's `toolMocks` by tool
|
|
1171
|
+
name and never performs I/O, so a replayed checkpoint case can run past its
|
|
1172
|
+
first action to grade what the agent does after a tool result comes back. The
|
|
1173
|
+
match/policy/error-shaping logic lives in one shared pure core
|
|
1174
|
+
(`resolveRecordedToolOutcome`) consumed by both the runtime executor and the
|
|
1175
|
+
api eval-run chokepoint, pinned by a cross-import parity suite.
|
|
1176
|
+
|
|
1177
|
+
Adds a per-suite replay config on `eval_suites`: `recordedToolMode`
|
|
1178
|
+
(`next_step` default | `continue`) and `recordedToolUnmatchedPolicy` (`fail`
|
|
1179
|
+
default | `stub`), surfaced through the suite create/update/ensure REST routes,
|
|
1180
|
+
the SDK `defineEval`, and a dashboard "Replay mode" control. Editing a mock's
|
|
1181
|
+
`output` turns any recorded case into a counterfactual for free. The
|
|
1182
|
+
recorded-tool config is included in the eval content hash only when non-default,
|
|
1183
|
+
so existing (default) suites keep their hashes.
|
|
1184
|
+
|
|
1185
|
+
- d7780b7: Prompt caching slice 5 — read-only observability + author advisory + breakpoint-budget tail.
|
|
1186
|
+
|
|
1187
|
+
`@runtypelabs/shared`: add the non-blocking `CACHE_VOLATILE_SYSTEM_PROMPT` flow-validation advisory (a `recommendation`) — a prompt step whose system prompt embeds a per-run temporal variable (`{{_now}}`, `{{_execution.*}}`, `{{_schedule.*}}`) re-renders its cacheable prefix every run, so automatic prompt caching can't land a cross-request hit; the advisory names the offending roots and suggests moving them into the user prompt. Its volatile-root rule mirrors the cache planner in `@runtypelabs/model-execution` (duplicated because `shared` cannot import that package). Adds a nine-turn byte-prefix parity fixture exercising the new reserve breakpoint.
|
|
1188
|
+
|
|
1189
|
+
`@runtypelabs/model-execution`: add the reserve breakpoint (budget #4) to Anthropic-family cache stamping — when a within-turn tool loop grows the gap between the system boundary and the moving last-message boundary past 15 content blocks, one intermediate history breakpoint is added at the block-count midpoint so neither gap exceeds Anthropic's cache lookback. Total stays within the 4-breakpoint budget.
|
|
1190
|
+
|
|
1191
|
+
`@runtypelabs/api`: surface prompt-cache read/write token counts (`cacheReadTokens` / `cacheWriteTokens`, from `flow_step_results`) in the `GET /flows/{id}/step-results` response, and add a debug-only `cache` block (`{ strategy, boundaries, prefixTokens, read, write }`) to prompt `step_complete` telemetry under `debugMode`.
|
|
1192
|
+
|
|
1193
|
+
`@runtypelabs/dashboard-spa`: render cache read/write token rows in the step-detail view.
|
|
1194
|
+
|
|
1195
|
+
`@runtypelabs/sdk`: regenerated OpenAPI types for the new step-result fields.
|
|
1196
|
+
|
|
1197
|
+
## 5.10.0
|
|
1198
|
+
|
|
1199
|
+
### Minor Changes
|
|
1200
|
+
|
|
1201
|
+
- 36d84c1: feat(evals): criteria decomposition for AI graders (E2 slice 3). New `POST /eval/graders/decompose` splits one plain-language AI-grader criterion carrying several obligations into focused, independently judgeable sub-checks; each accepted sub-check becomes a plain `kind: 'ai'` grader row, indistinguishable at scoring time from a hand-typed one. SDK: `Runtype.evals.decomposeCriteria(criteria)`. The decomposer is a versioned platform prompt (`@runtypelabs/shared` `eval-criteria-decomposition.ts`) sharing the judge flow's model pair and metering path; a failed decomposition surfaces as a visible error, never a silent no-op.
|
|
1202
|
+
- e769fbf: Add trace→eval capture (evals Extension 2, increment 1): `POST /eval/suites/:id/cases/from-execution` forks a real agent run into a test case — it freezes the run's conversation history up to a fork point, attaches every recorded tool result as an editable mock, and saves the case with origin `saved_from_run` (the first writer for that origin). Capture is a copy, never a replay: the endpoint reads persisted rows and writes a case row; it executes nothing. The next-step run mode and the recorded-tool executor are later increments.
|
|
1203
|
+
|
|
1204
|
+
New additive JSONB keys inside `eval_cases.input` (no migration): `checkpoint` (`{ sourceExecutionId?, sourceConversationId?, forkMessageIndex }`) and `toolMocks` (`Array<{ toolName, input?, output, isError?, sourceToolExecutionId?, truncated? }>`), with `caseCheckpointSchema` / `toolMockSchema` in `@runtypelabs/shared`. A mock captured from a failed call is stamped `isError: true` so a future replay serves it as a failure. The SDK gains `Runtype.evals.suites.addCaseFromExecution(...)`.
|
|
1205
|
+
|
|
1206
|
+
Per a tool-output fidelity audit, capture sources the full-fidelity persisted `tool_executions.output_result` (uncapped) rather than the R2 log-trace tree (which truncates tool outputs at emit), runs its own secret scrub over the reconstructed history + mocks (`input_messages` is raw at rest), and caps each mock output — a truncated capture marks the case non-fully-replayable via the response's `replayable` flag.
|
|
1207
|
+
|
|
1208
|
+
The captured case shape (`checkpoint`/`toolMocks` and tool-call/tool-result message turns) round-trips through `addCases`/`updateCase` without a validation error. A captured case is a next-step replay case; because that run mode does not exist yet, the synchronous run path skips such a case with a clear gradeable failure instead of feeding its frozen history to dispatch (the batch path already rejects `messages`-input cases). The endpoint is also exposed through the Code-Mode MCP as `captureEvalCaseFromExecution`.
|
|
1209
|
+
|
|
1210
|
+
### Patch Changes
|
|
1211
|
+
|
|
1212
|
+
- 5d07273: Consolidate the duplicated content-hash primitives (`isPlainObject`, canonical `normalizeValue`, and the SHA-256 hex encoder) used by `products.ensure`, `tools.ensure`, `skills.ensure`, `surfaces.ensure`, and `products.ensureFpo` into a single internal `content-hash.ts` module. No behavior change — content hashes for all `*.ensure()` surfaces are byte-identical before and after. `flows-ensure.ts` and `evals-ensure.ts` keep their own local normalizers (they intentionally preserve `null` values, unlike the canonical normalizer) but now share the same `isPlainObject` and hex-encoding helpers.
|
|
1213
|
+
|
|
1214
|
+
## 5.9.0
|
|
1215
|
+
|
|
1216
|
+
### Minor Changes
|
|
1217
|
+
|
|
1218
|
+
- e85c67e: Custom judge flows for AI graders (E2, `judgeFlowId`): an AI grader can now name one of the evaluating account's own flows as its judge instead of the platform judge prompt, via `judge(criteria, { judgeFlowId })` in the SDK or `judgeFlowId` on the grader config. The flow is executed through the normal flow pipeline in the customer's own account (so judge spend bills them and is metered once, by the pipeline) under a fixed contract: it receives the four platform judge variables (`criteria`, `caseName`, `expected`, `transcript`) as inputs, and its final output must be the platform verdict JSON (`reasoning` / `verdict` / `evidence`), parsed by the same validator as the platform judge so the verdict contract never varies by judge implementation. Contract validation is run-time: a miswired judge flow (missing, inaccessible, failing, or returning malformed output) resolves to an `insufficient_evidence` outcome with a visible grader error naming the problem, so it can neither fail nor silently pass cases. `judgePromptVersion` is not stamped into these scores' grader snapshots (the platform prompt did not produce them); the snapshot's `judgeFlowId` is the provenance.
|
|
1219
|
+
- f5ad9c0: Trajectory judge core (E1): the AI grader now evaluates the whole run, not just the final output. The judge is the new Runtype-owned "Runtype Eval Judge" system flow (config as code in `@runtypelabs/shared`, converged per environment via `scripts/ensure-eval-judge-flow.ts` like the Flow Generator): the builder's criteria is embedded as a variable inside a hand-crafted eval-expert system prompt, graded by `gemini-3.5-flash` with a cross-provider `nemotron-3-ultra-550b-a55b` fallback, and rendered in-process by the grader executor so judge spend bills the evaluating customer. The judge receives an indexed transcript of the run's steps and tool calls (with inputs/outputs, truncated and capped) and returns a binary verdict (`pass` / `fail` / `insufficient_evidence`) with critique-before-verdict reasoning and clickable evidence citations, instead of a 1-5 score. `insufficient_evidence` renders as a warning and never fails a case. Existing `threshold`/`.atLeast()` SDK semantics are preserved by mapping pass/fail to 5/1 internally, and the judge-prompt version is stamped into each score's `grader_snapshot` so historical scores stay interpretable. The batch scoring path now threads tool inputs/outputs from `tool_executions` into the grading trace, `eval_case_scores` gains `verdict`/`evidence` columns, and the run-results page shows insufficient-evidence badges plus evidence chips that deep-link into the case's trace section.
|
|
1220
|
+
|
|
1221
|
+
### Patch Changes
|
|
1222
|
+
|
|
1223
|
+
- ae6f98e: Degrade gracefully when R2 SQL fails on the logs read path. When the historical (R2 SQL) leg of a merged GET /v1/logs or /v1/logs/stats query fails (e.g. the Iceberg manifest scan limit, error 40020), the request now serves hot-tier (recent) entries and counts with a new optional `degraded: true` field on the response data instead of failing the whole request with a 500. Degraded stats responses are never cached. The dashboard logs page shows a "historical logs temporarily unavailable" banner when the flag is set.
|
|
1224
|
+
|
|
1225
|
+
## 5.8.1
|
|
1226
|
+
|
|
1227
|
+
### Patch Changes
|
|
1228
|
+
|
|
1229
|
+
- 9087295: Add abuse limits to the Runtype Apps records data plane (`/v1/client/records`).
|
|
1230
|
+
- **Per-app record cap**: creates are blocked once an app holds 10,000 records
|
|
1231
|
+
across all its namespaces (counted by the per-app storage-type prefix within
|
|
1232
|
+
the owner scope), returning `403` with a hint. This bounds unmetered writes
|
|
1233
|
+
from the anonymous, freely-mintable data plane into the owner's `records`
|
|
1234
|
+
table.
|
|
1235
|
+
- **Write rate limiting** (`POST`/`PUT`/`DELETE`): a native Cloudflare Workers
|
|
1236
|
+
rate-limit binding (`RATE_LIMIT_APP_DATA`) keyed per app (the real backstop)
|
|
1237
|
+
and per session, 100 writes / 10s. Rejections return `429` with `Retry-After`.
|
|
1238
|
+
Fails open (no limiting) when the binding is unconfigured so the data plane
|
|
1239
|
+
never breaks.
|
|
1240
|
+
- Documents both limits in the deploying-apps guide and the `build-runtype-app`
|
|
1241
|
+
skill; adds the `429` response to the write routes in the OpenAPI spec.
|
|
1242
|
+
|
|
1243
|
+
- 7007359: Add optional optimistic concurrency to `PUT /v1/client/records/:id` (the Runtype
|
|
1244
|
+
Apps data plane) so concurrent anonymous sessions stop silently clobbering each
|
|
1245
|
+
other. The flagship use case for apps (collaborative surfaces like a shared retro
|
|
1246
|
+
board) is exactly concurrent writers, and PUT is a full metadata replace, so the
|
|
1247
|
+
default last-write-wins behavior loses updates.
|
|
1248
|
+
- New optional request field `expectedUpdatedAt` (the `updatedAt` from the
|
|
1249
|
+
caller's last read). When provided, the update is a compare-and-set: the
|
|
1250
|
+
equality is folded into the UPDATE's `WHERE` clause (closing the TOCTOU race),
|
|
1251
|
+
with a fresh pre-check for a friendly error. On a mismatch the API returns
|
|
1252
|
+
`409` with the **current** record in the body (`{ error, hint, record }`) so
|
|
1253
|
+
the client can rebase and retry.
|
|
1254
|
+
- The comparison is millisecond-precision-robust: the `records.updated_at`
|
|
1255
|
+
Postgres `timestamp` stores microseconds, but the token the caller holds is a
|
|
1256
|
+
millisecond ISO string (`Date.toISOString()`), so both the JS pre-check and the
|
|
1257
|
+
SQL guard (`date_trunc('milliseconds', updated_at)`) compare on the
|
|
1258
|
+
ms-truncated value.
|
|
1259
|
+
- Omitting `expectedUpdatedAt` preserves the existing last-write-wins behavior
|
|
1260
|
+
exactly — fully backward compatible.
|
|
1261
|
+
|
|
1262
|
+
Also updates the `build-runtype-app` agent skill and the deploying-apps developer
|
|
1263
|
+
guide with the new field.
|
|
1264
|
+
|
|
1265
|
+
- ee51039: feat(evals): "Save as test case" moment (Beginner-First Evals §6.1)
|
|
1266
|
+
|
|
1267
|
+
After a test run completes in the RunFlowSheet Test tab, a "Save as test case"
|
|
1268
|
+
button captures the run's input and output into a pre-filled, editable eval
|
|
1269
|
+
case dialog, targeting the flow's default eval suite (auto-created on first
|
|
1270
|
+
save, named "<Flow name> eval"). Saved cases are tagged `origin: 'saved_from_run'`.
|
|
1271
|
+
- `POST /v1/eval/suites` and `POST /v1/eval/suites/{id}/cases` accept an
|
|
1272
|
+
optional, server-validated `origin` field on each case (`manual` |
|
|
1273
|
+
`saved_from_run` | `generated` | `imported` | `fpo`), previously hardcoded
|
|
1274
|
+
to `'manual'` on every write path.
|
|
1275
|
+
- Adds the missing `createEvalSuite` method to the dashboard's browser API
|
|
1276
|
+
client and an `ensureDefaultEvalSuiteForFlow` helper (find-or-create the
|
|
1277
|
+
flow's default suite).
|
|
1278
|
+
- `EvalCaseDialog` gains `initialValues`/`origin` props so the save-as-test-case
|
|
1279
|
+
flow can reuse its existing input/expected shaping instead of a new form.
|
|
1280
|
+
|
|
1281
|
+
- db60b0c: Score-over-time chart on the eval suite page, a Score column in the eval comparison view for suite-linked runs, and a server-side `evalSuiteId` filter on `GET /v1/eval/batches` (the suite page's run history no longer truncates to a client-side slice of the org-wide runs list). `GET /v1/eval/group/{groupId}` batches now include `evalSuiteId` and `suiteScore`.
|
|
1282
|
+
- 40874d8: Add pagination to the Evals page's Runs tab and to the suite detail page's
|
|
1283
|
+
runs list. Both previously fetched a single `limit: 100` page and rendered it
|
|
1284
|
+
with client-side search only, so an active org's older runs (or a suite past
|
|
1285
|
+
its first 100 org-wide runs) were silently invisible with no way to page.
|
|
1286
|
+
`GET /v1/eval/batches` is offset-based, so the pagination footer paginates by
|
|
1287
|
+
offset (50/page on the Runs tab, 25/page on the suite page). The endpoint now
|
|
1288
|
+
returns `hasMore` (matching the convention already used by `/v1/flows`,
|
|
1289
|
+
`/v1/client/conversations`, `/v1/schedules`, …) instead of the client
|
|
1290
|
+
inferring it from page fullness. Also drops the dead cursor plumbing in
|
|
1291
|
+
`useEvalBatches` / `listEvalBatches` (the API never returned
|
|
1292
|
+
`cursor`/`nextCursor`/`prevCursor`), and fixes two follow-on bugs found in
|
|
1293
|
+
review: the suite detail page's pagination footer stayed hidden when a
|
|
1294
|
+
full-page offset landed on an empty page (stranding the user with no way
|
|
1295
|
+
back), and running a suite from the Evals tab while `runsOffset` was
|
|
1296
|
+
non-zero refetched at the stale offset instead of surfacing the new run on
|
|
1297
|
+
page 1.
|
|
1298
|
+
- 41b296a: Add the Runtype Apps records data plane (`/v1/client/records`). A deployed
|
|
1299
|
+
app's browser JS can now persist data using its origin-locked client token,
|
|
1300
|
+
governed entirely by the manifest's `data[]` namespace grants:
|
|
1301
|
+
- `GET /v1/client/records?namespace=…` (cursor-paginated list), `POST /v1/client/records`,
|
|
1302
|
+
`GET/PUT/DELETE /v1/client/records/:id` — all session-authed with the session
|
|
1303
|
+
from `POST /v1/client/init`.
|
|
1304
|
+
- Authorization is manifest-driven and evaluated per request: the session's
|
|
1305
|
+
client token resolves to its app, and the requested namespace must appear in
|
|
1306
|
+
the **active** version's `manifest.data[]`. Mutating verbs require
|
|
1307
|
+
`read-write`; an un-granted namespace is never accessible (out-of-namespace
|
|
1308
|
+
records 404 to avoid leaking existence).
|
|
1309
|
+
- Rows live in the existing `records` table (`type` = namespace) under the app
|
|
1310
|
+
owner's tenant, stamped with server-controlled `appId` / `versionId` /
|
|
1311
|
+
`clientSessionId` provenance (reserved `_app` metadata key, stripped from
|
|
1312
|
+
caller input and never echoed). Metadata is capped at 64 KB.
|
|
1313
|
+
- `POST /v1/client/init` now mints a session for data-only app tokens (a
|
|
1314
|
+
manifest that declares record namespaces but no flows/agents). The init
|
|
1315
|
+
response carries an `app` object instead of `flow` for these sessions; `flow`
|
|
1316
|
+
is now optional.
|
|
1317
|
+
|
|
1318
|
+
Also updates the `build-runtype-app` agent skill and the deploying-apps
|
|
1319
|
+
developer/user guides with the data API and an end-to-end example.
|
|
1320
|
+
|
|
1321
|
+
## 5.8.0
|
|
1322
|
+
|
|
1323
|
+
### Minor Changes
|
|
1324
|
+
|
|
1325
|
+
- 4c17349: Eval score persistence (Beginner-First Evals Phase 1, PR-A): grader scores now have a durable home.
|
|
1326
|
+
- **Saved-suite runs of `POST /v1/eval/run` persist by default**: the run gets a `batchExecutions` anchor row (`executionType='eval'`, `evalSuiteId` set) and one `eval_case_scores` row per (case, grader) — the data source for run history, baselines, and score-over-time. Pass `virtual: true` to keep a run ephemeral; inline `definition` runs stay ephemeral always. The response (and SDK `RunEvalResult`) gains `runId`.
|
|
1327
|
+
- **Suite-linked batch runs are scored at completion**: `completeBatch()` now grades a run with `batchExecutions.evalSuiteId` set from its persisted step results — including trace-grader coverage rebuilt from `flowStepResults` + `tool_executions` (closing the deferred batch-trace gap). Idempotent and non-fatal; dormant until a producer links batches to suites.
|
|
1328
|
+
- **New read endpoint `GET /v1/eval/runs/{batchId}/scores`** returning per-case grader outcomes in the same shape as the sync run response.
|
|
1329
|
+
- **Four new AI grader presets**: Stays on task, Same language, Refuses when it should, No personal data (mirrored in the SDK `judges.*` builders).
|
|
1330
|
+
- CLI `runtype eval run` prints the persisted run id.
|
|
1331
|
+
|
|
1332
|
+
- f89cb41: Eval suite CRUD + suite runs + Evals index restructure (Beginner-First Evals Phase 1, PR-B).
|
|
1333
|
+
- **New `/v1/eval/suites` REST family**: create/list/get/update/delete suites, add/edit/delete test cases, and `POST /v1/eval/suites/{id}/run`. List/get include case counts and each suite's latest run + score. Suites within the synchronous case limit run inline and return the scored result; larger suites queue a durable run whose grader scoring fires in `completeBatch()` (activating the previously dormant batch scoring pass) via inline records stamped with `_evalCaseId`.
|
|
1334
|
+
- **Two-writers provenance**: Definition edits (name, description, graders) from the dashboard/API stamp `lastModifiedSource` and a graders change invalidates the config-as-code `contentHash` so the next `ensure` re-converges; case mutations deliberately leave provenance untouched (cases are server-authoritative data and survive unchanged-probe deploys).
|
|
1335
|
+
- **`GET /v1/eval/batches`** gains an `origin` filter (`suite` | `adhoc`) and returns `evalSuiteId`, `requestSource`, and a `suiteScore` summary per run.
|
|
1336
|
+
- **Dashboard `/evals` restructure**: the index is now Evals (suites) as the primary tab — name, target, case count, latest score, last run, Run/Delete actions, and a "Managed in code" badge for ensure-converged suites — with Runs as a secondary tab carrying an origin badge + filter, a Score column for suite runs, and "Ad-hoc comparison" labeling for suite-less runs. "Compare configs" is an action on run groups.
|
|
1337
|
+
- **SDK**: `client.evals.suites.*` namespace (create/list/get/update/delete/run/addCases/updateCase/deleteCase) plus a generic `patch` helper on `RuntypeClient`.
|
|
1338
|
+
- **Code-Mode MCP**: `createEvalSuite`, `listEvalSuites`, `getEvalSuite`, `updateEvalSuite`, `deleteEvalSuite`, `runEvalSuite`, `addEvalCases`, `updateEvalCase`, `deleteEvalCase`.
|
|
1339
|
+
|
|
1340
|
+
- fa6d18a: feat(flow-steps): add `get-record` and `list-records` step types, deprecate `retrieve-record`
|
|
1341
|
+
|
|
1342
|
+
`retrieve-record` derives its return shape (single object vs. array) from the lookup method, which is unintuitive and a common source of `{{var.field}}` resolving to `undefined`. Cardinality is now a property of the step **type**: `get-record` always returns a single record object (fails if no match), `list-records` always returns an array (newest-first, `limit` default 50 / max 1000, `onEmpty: 'succeed' | 'fail'`).
|
|
1343
|
+
- **Engine (api + runtime)**: `retrieve-record` is resolved to its successor by a single pure alias (`resolveRetrieveRecordAlias`) at the normalizer seam, so both legacy executors are removed and saved / published / inline flows execute through the new `get-record` / `list-records` executors with behavior preserved (query mode → `list-records` with `limit: 1000` + `onEmpty: 'fail'`; id mode → `get-record`). SSE step events emit the resolved type for aliased steps.
|
|
1344
|
+
- **Validation**: `validate_flow` emits a non-blocking `DEPRECATED_STEP_TYPE` warning for `retrieve-record` naming the successor its config resolves to, and the array/object-access warning code was renamed `RETRIEVE_RECORD_ARRAY_OBJECT_ACCESS` → `LIST_RECORDS_OBJECT_ACCESS`.
|
|
1345
|
+
- **MCP**: `create_flow` / `update_flow` / `validate_flow` step-config guidance now documents both new types and marks `retrieve-record` as deprecated.
|
|
1346
|
+
- **Client SDK**: `FlowBuilder`/`RuntypeFlowBuilder` gain `getRecord()` and `listRecords()` methods (plus `GetRecordStepConfig` / `ListRecordsStepConfig` types); `retrieveRecord()` is marked `@deprecated` but continues to work unchanged.
|
|
1347
|
+
- **react-flow**: `get-record` and `list-records` are added to `FlowStepType` with display labels ("Get record" / "List records").
|
|
1348
|
+
|
|
1349
|
+
`retrieve-record` is still accepted everywhere for backward compatibility — this is additive, no breaking changes.
|
|
1350
|
+
|
|
1351
|
+
### Patch Changes
|
|
1352
|
+
|
|
1353
|
+
- 1422e92: Add fire-and-forget dispatch for Claude Managed agents via the RFC 7240
|
|
1354
|
+
`Prefer: respond-async` request header. On the durable lane (a saved agent
|
|
1355
|
+
invoked with a `conversationId`), the turn runs headlessly in the session DO
|
|
1356
|
+
with full durability (seq log + `session_turns` row + watchdog alarm) and the
|
|
1357
|
+
request returns `202 { executionId, status, conversationId }` plus a
|
|
1358
|
+
`Preference-Applied: respond-async` header instead of streaming. Clients
|
|
1359
|
+
reconnect via `GET /agents/:id/executions/:executionId/events` or poll
|
|
1360
|
+
`GET /agents/:id/runs`. Requesting async on the in-request/virtual lane (no
|
|
1361
|
+
durable owner to outlive the request) returns `400 ASYNC_REQUIRES_DURABLE_LANE`.
|
|
1362
|
+
Honored on both `/v1/agents/:id/execute` and saved-agent `/v1/dispatch`. The
|
|
1363
|
+
202 response + `AsyncDispatchHandle` schema are documented in the OpenAPI spec
|
|
1364
|
+
and flow through to the generated TypeScript and Python SDKs.
|
|
1365
|
+
- d0df6a8: Durable Claude Managed sessions: two reliability fixes for the session DO.
|
|
1366
|
+
1. Watchdog re-arm on settle: `runTurn`'s finally now mirrors `alarm()`'s
|
|
1367
|
+
guard — it re-arms the watchdog when any durable `running` turn row remains
|
|
1368
|
+
(an orphan stranded by a mid-turn DO eviction) instead of unconditionally
|
|
1369
|
+
disarming. Previously a new turn settling inside the watchdog window
|
|
1370
|
+
deleted the alarm out from under the orphaned turn, stranding it `running`
|
|
1371
|
+
forever with no interrupted run row and no terminal frame.
|
|
1372
|
+
2. Sub-frame-granular reconnect cursor: the legacy-to-unified translation is
|
|
1373
|
+
1-to-many (one durable log row can fan out into several unified events), and
|
|
1374
|
+
every sub-frame previously carried the same row seq as its SSE `id:`, so a
|
|
1375
|
+
mid-row disconnect skipped the rest of the row on reconnect (worst case the
|
|
1376
|
+
terminal `execution_complete`). Intermediate sub-frames now carry a
|
|
1377
|
+
composite `<rowSeq>.<subIndex>` id and the row's final sub-frame keeps the
|
|
1378
|
+
plain row seq, so a reconnect with the last seen id (passed verbatim as
|
|
1379
|
+
`?after=`) resumes with exactly the not-yet-applied sub-frames. Plain-seq
|
|
1380
|
+
cursors keep their existing semantics; the id stays opaque to Persona.
|
|
1381
|
+
|
|
1382
|
+
- de60a30: End-user credential registration (multi-tenancy V1, inc 5) — connect leg. Adds
|
|
1383
|
+
`POST /v1/end-user-integrations/{provider}/connect`: an end user attaches their
|
|
1384
|
+
own third-party account (GitHub first) so a Runtype agent can act on their behalf
|
|
1385
|
+
later.
|
|
1386
|
+
- **Auth model:** builder-authenticated (api-key / clerk, the same credential
|
|
1387
|
+
that consumes the resulting secret via builder-mediated dispatch). The
|
|
1388
|
+
end-user identity comes ONLY from a verified Identity-Exchange proof
|
|
1389
|
+
(`verifyExchangeProof`), never a body-asserted id. Registration admits
|
|
1390
|
+
`verified` end-user assurance ONLY.
|
|
1391
|
+
- **Flow:** verify the proof against the builder-owner's configured identity
|
|
1392
|
+
integrations → project a durable `eu_*` (Option 1: `integration_id = NULL`, so
|
|
1393
|
+
the stored secret reconciles with the builder-mediated dispatch path) → bind a
|
|
1394
|
+
single-use, KV-backed `state` → return the connector's authorize URL.
|
|
1395
|
+
- **Connector seam:** a new `OAuthConnector` registry (`services/end-user-oauth`)
|
|
1396
|
+
with GitHub as the first provider (GitHub was previously PAT/App-paste only —
|
|
1397
|
+
this is the first real OAuth-redirect connector). Adding a provider is a
|
|
1398
|
+
registry entry, not a new route.
|
|
1399
|
+
- Orchestration + security invariants live in
|
|
1400
|
+
`services/end-user-oauth/connect-service.ts` (thin route adapter over it),
|
|
1401
|
+
unit-tested with the verifier injected.
|
|
1402
|
+
|
|
1403
|
+
Connect leg only — the OAuth callback (token exchange → `eu_*`-scoped secret) and
|
|
1404
|
+
GitHub OAuth App credential provisioning (add `GITHUB_OAUTH_CLIENT_ID` /
|
|
1405
|
+
`GITHUB_OAUTH_CLIENT_SECRET` to `wrangler.toml` `required`) land in the follow-up.
|
|
1406
|
+
Until provisioned, the connector reports "not configured" and connect returns 501.
|
|
1407
|
+
|
|
1408
|
+
- 9736850: Fix non-streaming agent execution masking an approval pause. When a Quick-Agent's
|
|
1409
|
+
tool call tripped the approval gate (`config.tools.approval.require`), the flow
|
|
1410
|
+
paused but the non-streaming (`streamResponse: false`) `POST /v1/agents/{id}/execute`
|
|
1411
|
+
and `POST /v1/dispatch` agent paths branched only on `execResult.success` (which
|
|
1412
|
+
is `true` on a pause), so they persisted the `agent_executions` row as `completed`
|
|
1413
|
+
(stopReason `complete`, `completedAt` stamped) and returned a bare success
|
|
1414
|
+
envelope — a JSON caller could never discover or resolve the pending approval.
|
|
1415
|
+
|
|
1416
|
+
Both paths now mirror the streaming path's paused persistence and the dispatch
|
|
1417
|
+
JSON payload's paused status: the row is persisted as `paused` (stopReason
|
|
1418
|
+
`paused`, no `completedAt`) and the response carries `status: 'paused'` with a
|
|
1419
|
+
`pausedReason` object. `pausedReason` threads the approval discriminators
|
|
1420
|
+
(`awaitReason: 'approval_required'` + `approvalId`) so a caller can resolve the
|
|
1421
|
+
gate via `POST /v1/agents/{id}/approve`. The wire shape is single-sourced in
|
|
1422
|
+
`buildPausedReason` so the several producers can't drift.
|
|
1423
|
+
|
|
1424
|
+
`@runtypelabs/sdk` (packages/client): `AgentExecuteResponse` gains `'paused'` on
|
|
1425
|
+
`stopReason` plus optional `status` and `pausedReason` fields, and
|
|
1426
|
+
`AgentsEndpoint.runTask()` now stops the session loop on a `paused` result
|
|
1427
|
+
instead of re-sending.
|
|
1428
|
+
|
|
1429
|
+
Verified live on staging.
|
|
1430
|
+
|
|
1431
|
+
- 8f13a37: Add policy-gated PII redaction at the log/telemetry chokepoints. A new
|
|
1432
|
+
`resolvePiiRedactionPolicy` resolver (mirroring `resolveLoggingPolicy`, default
|
|
1433
|
+
`off`) is threaded from agent/flow, surface, and product config through the
|
|
1434
|
+
execution engine into the two customer-data chokepoints: `prepareCustomerTailData`
|
|
1435
|
+
(customer tail logs → dashboard, R2, hot-tier DO, live tail, Sentry/Grafana) and
|
|
1436
|
+
`ExecutionTelemetryService.sendBatch` (R2 telemetry pipelines). When the resolved
|
|
1437
|
+
policy is `redact`, customer-supplied (UGC) fields are masked via the shared PII
|
|
1438
|
+
primitive; system fields are never touched. Opt-in and flag-free — no behavior
|
|
1439
|
+
change unless a config layer sets `piiRedaction: 'redact'`.
|
|
1440
|
+
|
|
1441
|
+
The agent `piiRedaction` config is a first-class field on every write surface:
|
|
1442
|
+
the SDK agent content-hash (`@runtypelabs/sdk`) includes it so an agent that only
|
|
1443
|
+
changes its redaction policy produces a new content hash, and the MCP
|
|
1444
|
+
`create_agent` / `update_agent` tools (`@runtypelabs/mcp`) accept `piiRedaction`
|
|
1445
|
+
(and the previously-missing `loggingPolicy`) so it round-trips through the agent
|
|
1446
|
+
tool surface.
|
|
1447
|
+
|
|
1448
|
+
- 9002f51: Security: agent sandbox container egress now fails closed. The sandbox DO's outbound enforcement treats an unset in-memory network-access profile as `off` for raw pass-through egress (previously it fell through to unrestricted egress, so a background process that outlived a DO eviction escaped the operator's `essentials`/`none` profile). The credentialed proxy paths (per-execution api token and phantom-token credential-proxy rules) remain reachable under the unset default because their state is equally in-memory and dies with the same eviction; an explicit `off`/allowlist profile still gates all paths. The container executor forwards an explicit `on` and deploy pins its historical open posture explicitly. The flow validator's `SANDBOX_NETWORK_ACCESS_DISABLED` warning now also fires for `runtype-sandbox`/`cloudflare-sandbox` transform steps that call `fetch()` without `networkAccess`. The inert `requireApprovalForBash` sandbox config knob is removed from the public schema until its approval wiring exists (use the generic `tools.approval` config to gate `bash` by name); the `open` egress profile's flag-only gating and the org-shared `conversationId` container keying are documented as accepted risks.
|
|
1449
|
+
- 4520c60: Fix the subagent HITL resume model's three design gaps (runtime). (1) Exactly-once pre-gate side effects: resume is a full child re-run (the Anthropic session is archived on pause), so a non-idempotent child tool call made before the gated one used to re-execute on approve-resume (child does `create_ticket` then gated `send_email` → two tickets). `runSubagent` now records every child tool result in a `SubagentReplayJournal` that rides out on `ApprovalRequiredError.replayJournal`; passed back on resume via `ApprovalConfig.subagentReplayJournal`, matching re-issued calls (same tool name + same canonical parameters) are answered from the journal instead of executing again. (2) Boundary-scoped, parameter-bound approval grants: the gate previously matched `approvedTools` by bare tool name, so approving the child's `send_email` pre-approved the parent's and every sibling subagent's same-named tool for the whole execution — and a child re-run could re-issue the approved tool with different parameters than the human reviewed. Grants now resolve against the approval boundary (`ApprovalRequiredError.approvalScope`, e.g. `subagent:delegate_email`) and the recommended one-shot resume grant is the param-bound `ApprovalRequiredError.approvalKey`, which re-prompts when the re-issued call's parameters drift from what the human saw; bare-name grants keep working for the top-level agent's own tools but no longer bleed into children (bare-name denials stay effective at every boundary, the fail-closed direction). (3) Parent-visible approval correlation: `agent_approval_start.toolCallId` for a subagent pause is the muted child's tool_use id, which never appeared on the parent stream — the `subagent` attribution block now carries `parentToolCallId`, the subagent tool call's id whose `agent_tool_start` the client already saw (additive optional field on the shared SSE schemas and the regenerated OpenAPI spec / SDK types). Also: `ExecuteAgentOptions.onApprovalRequired` hands `executeAgent` consumers the full pause object (the SSE frame intentionally omits the resume-critical `approvalKey` / `approvalScope` / `replayJournal`), and the skill capability-load gate resolves grants through the same boundary-scoped + param-bound matcher so the pause's `approvalKey` satisfies it on resume and a top-level skill grant does not bleed into a subagent child's same-named skill load.
|
|
1450
|
+
- 49d599f: Fix chat surfaces created via REST/MCP silently disabling WebMCP: surface write paths (REST create/update and the config-as-code ensure service) now inject the `type` discriminant into the persisted behavior JSONB (callers passing legacy `config` or a `behavior` without `type` previously stored it verbatim), the canonical surface content hash normalizes behavior with the injected discriminant on both the shared and SDK copies so ensure converges without phantom diffs, and `readSurfaceWebMCPPolicy` accepts the surface row's `type` column as the authoritative discriminant so legacy rows written without one still resolve their WebMCP policy.
|
|
1451
|
+
- 9cbdba8: Carry per-request tenancy identity (`tenant` / `endUser`, multi-tenancy V1) through
|
|
1452
|
+
the MCP and Code-Mode execution surfaces so multi-tenant dispatch/execute reaches
|
|
1453
|
+
parity with the REST routes + generated SDKs:
|
|
1454
|
+
- MCP `dispatch` tool gains optional `tenant` / `end_user` inputs (snake_case,
|
|
1455
|
+
mapped to camelCase on the wire); the `.strict()` schema previously rejected them.
|
|
1456
|
+
- MCP `execute_agent` tool gains the same optional `tenant` / `end_user` inputs,
|
|
1457
|
+
threaded through both `RuntypeClient.executeAgent` implementations (the
|
|
1458
|
+
hand-written HTTP client and the api-internal client), whose closed body objects
|
|
1459
|
+
previously dropped them.
|
|
1460
|
+
- Code-Mode MCP `executeAgent` becomes a pass-through like `dispatch` (its closed
|
|
1461
|
+
destructure dropped `tenant`/`endUser`; it also now sends the
|
|
1462
|
+
`streamResponse: false` key the execute route actually reads, instead of the
|
|
1463
|
+
ignored `stream: false`), and the overlay docs show tenant/endUser on
|
|
1464
|
+
`executeAgent` and `dispatch`.
|
|
1465
|
+
- TS SDK `CreateSecretRequest` is now derived from the generated OpenAPI types
|
|
1466
|
+
instead of a drifted hand-written interface, picking up `productTenantId` /
|
|
1467
|
+
`endUserId`.
|
|
1468
|
+
|
|
1469
|
+
Omit `tenant` / `endUser` for the unchanged org-level default.
|
|
1470
|
+
|
|
1471
|
+
- b82d8f1: Usage-based-pricing slice 1b-ii: propagate the platform-key spend-block
|
|
1472
|
+
`blockReason` discriminant (`credit_exhausted | trial_expired |
|
|
1473
|
+
auto_topup_failed`) onto the public wire and render differentiated dashboard
|
|
1474
|
+
paywall copy keyed off it.
|
|
1475
|
+
- Wire: `blockReason` is now an optional field on the `execution_error`
|
|
1476
|
+
(unified) and `flow_error` (legacy) SSE event schemas, forwarded through both
|
|
1477
|
+
legacy→unified mapper branches, every `flow_error` / `dispatch_error` emitter,
|
|
1478
|
+
the REST error envelope, and the buffered non-streaming payload. Regenerated
|
|
1479
|
+
OpenAPI + Python SDK + client types follow.
|
|
1480
|
+
- Dashboard: a shared `getSpendBlockCopy` helper maps the reason to card-centric
|
|
1481
|
+
copy (out of credit / trial ended / payment failed), consumed by the streaming
|
|
1482
|
+
execution-error surface, the REST 402 handler, and the usage banner. All spend
|
|
1483
|
+
and slow-mode CTAs route to the credit-card entry page
|
|
1484
|
+
(`/settings/billing/portal`); hardcoded "Upgrade to Startup" / "Upgrade to
|
|
1485
|
+
Team" strings are replaced with "Add a payment method".
|
|
1486
|
+
|
|
1487
|
+
Additive and behavior-neutral: `blockReason` is only populated on an already
|
|
1488
|
+
flag-gated (`usage-based-pricing`) spend block, and the paywall copy falls open
|
|
1489
|
+
to generic "add a payment method" copy for an absent or unrecognized reason.
|
|
1490
|
+
|
|
1491
|
+
- edae98b: Usage-based pricing slice 4 (dashboard): expose the `usage-based-pricing` flag to the SPA as `features.usageBasedPricing` on `GET /v1/users/profile`, and gate the card-centric billing surfaces on it. With the flag on, the SlowModeModal CTA and the BYOK card copy become "Add a payment method" (routing to the credit-card entry page), and the usage alert banner differentiates the force-upgrade reasons (out of credit vs trial ended vs payment failed) by mirroring the API spend gate's subscription/trial precedence, including a new trial-expired alert. Flag off (the production default) renders today's UI byte-identically; the flip per cohort is the launch lever.
|
|
1492
|
+
|
|
1493
|
+
## 5.7.0
|
|
1494
|
+
|
|
1495
|
+
### Minor Changes
|
|
1496
|
+
|
|
1497
|
+
- fd2e18e: Durable Claude Managed sessions (slice 4a): durable run record + deliverables persistence.
|
|
1498
|
+
|
|
1499
|
+
The Postgres half of the durable-sessions §8 Q1 split — the raw SSE event log stays in DO-SQLite; Postgres carries only a per-turn summary plus deliverable pointers.
|
|
1500
|
+
- New tables `managed_agent_runs` (one row per managed turn, written at settle with status / final text / token usage / cost / the seq ceiling) and `managed_agent_outputs` (one pointer row per swept `/mnt/session/outputs/` file; the bytes already live in asset storage). Run rows are idempotent on `execution_id`; deliverable rows dedupe on `(run_id, anthropic_file_id)`.
|
|
1501
|
+
- `ClaudeManagedSessionDO` writes both at turn settle (success or failure) in the same `finally` as the lease — best-effort, so a persistence failure never fails the run. The shared `onSessionOutput` sweep callback gains an `onDeliverableSwept` hook the DO uses to collect deliverable pointers during the turn.
|
|
1502
|
+
- New read routes `GET /v1/agents/{id}/runs?conversationId=` and `GET /v1/agents/{id}/runs/{runId}` (agent ownership + AGENTS:READ, the same trust level as the events reconnect route) — the queryable execution record and "deliverables tab" backbone managed turns lacked.
|
|
1503
|
+
|
|
1504
|
+
Adds `managed-agent-run-store.ts` mirroring the session store. No webhook or headless behavior yet (slices 4b/4c).
|
|
1505
|
+
|
|
1506
|
+
## 5.6.0
|
|
1507
|
+
|
|
1508
|
+
### Minor Changes
|
|
1509
|
+
|
|
1510
|
+
- 78e6f0e: feat(evals): grader severity (`gate`/`soft`) + functional `--strict`, and inline `evals:` on `flows.ensure` (code-colocated evals increment 5)
|
|
1511
|
+
- **Severity.** Every grader now carries an optional `severity: 'gate' | 'soft'` (absent ⇒ `gate`, the historical hard-gate behavior). A `soft` grader miss is tracked-but-not-failing — reported per-outcome but it does not fail the case unless the run is strict. `casePassed(outcomes, { strict })` in `@runtypelabs/shared` owns the aggregation; `EvalScoringService.scoreRun` threads a `strict` flag and stamps each outcome's severity.
|
|
1512
|
+
- **`runtype eval --strict` is now functional** (previously a stub): it sends `strict: true` to `POST /v1/eval/run`, and the server-computed severity-aware `passed` drives the exit code (a soft miss alone exits `0` without `--strict`, `1` with it; a gate miss always exits `1`). The CLI also surfaces soft misses on passing cases as warnings.
|
|
1513
|
+
- **SDK chainable severity handles.** Grader builders (`contains(...)`, `judge(...)`, `calledTool(...)`, …) return a `Gradeable` with `.gate()` / `.soft()` handles (and `.atLeast(n)` on AI graders to set the 1-5 judge cutoff). The handles are non-enumerable, so a grader still serializes byte-identically to its plain wire shape and the content hash of an un-annotated grader is unchanged.
|
|
1514
|
+
- **Inline `evals:` on `flows.ensure`.** `defineFlow({ ..., evals: [...] })` attaches eval suites that converge with the flow; an inline eval that omits `target` defaults to the enclosing flow. This is SDK-orchestrated and honors the eval-endpoints-only rule — the flow converges through `/flows/ensure` (its `{ name, steps }` wire shape and content hash are unchanged; `evals` is never sent there) and each inline suite converges through the existing `/eval/ensure`. `Runtype.flows.ensure(...)` returns the per-suite converge outcomes under `evals`.
|
|
1515
|
+
|
|
1516
|
+
## 5.5.0
|
|
1517
|
+
|
|
1518
|
+
### Minor Changes
|
|
1519
|
+
|
|
1520
|
+
- edf1724: Code-colocated evals increment 4: trace graders — deterministic, free assertions
|
|
1521
|
+
over a run's execution trace (which tools/steps ran, in what order, whether it
|
|
1522
|
+
completed, what it cost), not just its final output text.
|
|
1523
|
+
|
|
1524
|
+
New `CheckGrader` kinds scored by the pure `runCheck` engine: `called_tool`
|
|
1525
|
+
(with optional `input` / `output` / `isError` / `times` filters),
|
|
1526
|
+
`not_called_tool`, `used_no_tools`, `max_tool_calls`, `tool_order` (ordered
|
|
1527
|
+
subsequence), `ran_step`, `step_order`, `completed`, and `cost`. `GradingTarget`
|
|
1528
|
+
gains an optional `trace` ({ toolCalls, steps, completed, costUsd }); trace
|
|
1529
|
+
checks fail gracefully with a clear reason when no trace was captured.
|
|
1530
|
+
|
|
1531
|
+
The synchronous `POST /v1/eval/run` path now populates `trace` per case: steps
|
|
1532
|
+
and cost come from the `FlowExecutionResult`, and tool calls are captured
|
|
1533
|
+
in-memory from the run's SSE tool events (the same mechanism the virtual-agent
|
|
1534
|
+
tool-persistence tap uses), so trace graders work end-to-end without persisting
|
|
1535
|
+
anything. Batch scoring (`/eval/submit`) is unchanged and still does not wire
|
|
1536
|
+
trace graders — they are fully exercisable via `/eval/run`.
|
|
1537
|
+
|
|
1538
|
+
The SDK gains trace-grader builders: `calledTool(name, opts?)`,
|
|
1539
|
+
`notCalledTool(name)`, `usedNoTools()`, `maxToolCalls(max)`, `toolOrder(tools)`,
|
|
1540
|
+
`ranStep(name)`, `stepOrder(steps)`, `completed()`, and `cost(maxUsd)`.
|
|
1541
|
+
`defineEval` now accepts these kinds (previously rejected as "not available
|
|
1542
|
+
yet").
|
|
1543
|
+
|
|
1544
|
+
## 5.4.0
|
|
1545
|
+
|
|
1546
|
+
### Minor Changes
|
|
1547
|
+
|
|
1548
|
+
- 0cd1d82: Add `defineEval` — the pure authoring layer for code-colocated evals. Define the evals for a flow or agent right next to its `defineFlow` / `flows.ensure` definition, using grader builders (`contains`, `regex`, `jsonField`, `length`, `latency`, `noError`, `matchesExpected`, `judge`, and the `judges.*` presets) that emit the canonical `GraderConfig` wire shapes. `defineEval` validates and normalizes a definition (target + cases + per-case graders, with suite-level `graders` merged into each case) into an environment-portable `EvalDefinition`, and `computeEvalContentHash` provides the hash-first basis for future `evals.ensure` convergence. Pure and local (no I/O), mirroring the `defineFlow` precedent. The converge endpoint, `runtype eval` CLI, and trace/severity grader extensions land in follow-up increments (see `docs/features/planning/2026-06-24-code-colocated-evals.md`).
|
|
1549
|
+
- a7b06ce: Code-colocated evals increment 3: the `runtype eval run` CI gate plus the
|
|
1550
|
+
synchronous run+score endpoint behind it.
|
|
1551
|
+
|
|
1552
|
+
New `POST /v1/eval/run` runs every case of an eval suite (a saved suite by id, or
|
|
1553
|
+
an inline `--virtual` definition) against its target flow/saved-agent, grades the
|
|
1554
|
+
outputs with the suite graders via `EvalScoringService`, and returns the suite
|
|
1555
|
+
score + per-case grader outcomes in one response. Synchronous and ephemeral — no
|
|
1556
|
+
batch is created and no `eval_case_scores` are persisted (AI-grader spend is
|
|
1557
|
+
still metered); bounded by a per-run case ceiling, with a per-case timeout.
|
|
1558
|
+
`claude_managed` agents and inline/virtual agent targets are rejected with an
|
|
1559
|
+
actionable error.
|
|
1560
|
+
|
|
1561
|
+
The SDK gains `client.evals.runSuite({ suiteId } | { definition })` (and the
|
|
1562
|
+
`runEvalSuite` helper) returning the typed `RunEvalResult`.
|
|
1563
|
+
|
|
1564
|
+
The CLI gains `runtype eval run [idOrDirPrefix]`: it discovers `**/*.eval.ts`,
|
|
1565
|
+
loads each `defineEval(...)` default export via jiti, `ensure`s the suite (or runs
|
|
1566
|
+
it inline with `--virtual`), runs it, and maps the result to eve-style exit codes
|
|
1567
|
+
(`0` pass / `1` gate failure / `2` config error). Supports `--junit <path>`,
|
|
1568
|
+
`--url <api>`, `--cwd <dir>`, and a `--strict` stub (grader severity lands in a
|
|
1569
|
+
later increment).
|
|
1570
|
+
|
|
1571
|
+
- 17f7b6b: Add the code-colocated eval converge surface (increment 2): `POST /v1/eval/ensure`
|
|
1572
|
+
- `GET /v1/eval/pull`, the `client.evals.ensure(def)` / `client.evals.pull(name)`
|
|
1573
|
+
SDK methods, and the canonical `computeEvalContentHash` in `@runtypelabs/shared`.
|
|
1574
|
+
|
|
1575
|
+
`evals.ensure` is the deploy-time, non-executing converge for `defineEval` suites
|
|
1576
|
+
— the eval sibling of `flows.ensure`. It is hash-first (the steady state is one
|
|
1577
|
+
tiny probe), upserts an eval suite + replaces its cases, and returns
|
|
1578
|
+
`unchanged | created | updated | definitionRequired` with the server-computed
|
|
1579
|
+
content hash. Suite identity is the suite name (defaults to `flow:<name>` /
|
|
1580
|
+
`agent:<name>`) + account scope; the target flow/agent is resolved by name and
|
|
1581
|
+
fails loudly on a missing or ambiguous match. Every write stamps
|
|
1582
|
+
`last_modified_source = 'sdk'` for the deferred external-edit conflict guard.
|
|
1583
|
+
|
|
1584
|
+
Lean v2 scope: hash-first idempotency only. Per-case divergent graders, dry-run /
|
|
1585
|
+
plan, 409 conflict codes, and version snapshots are deferred to later increments;
|
|
1586
|
+
`virtual: true` suites are rejected (ephemeral, nothing durable to converge).
|
|
1587
|
+
Adds `EVALS:*` / `EVALS:READ` / `EVALS:WRITE` API-key scopes.
|
|
1588
|
+
|
|
1589
|
+
## 5.3.1
|
|
1590
|
+
|
|
1591
|
+
### Patch Changes
|
|
1592
|
+
|
|
1593
|
+
- 2260366: Switch the flow generator and product generator to GLM 5.2 (`glm-5.2`).
|
|
1594
|
+
- The flow generator's `FLOW_GENERATION_MODEL_ID` now points at `glm-5.2`.
|
|
1595
|
+
- The product generator is now a **single fixed model**: the `product-generator-model` Flagship flag (and its allowlist, profile plumbing, and dashboard-side resolution) has been removed entirely. `@runtypelabs/shared` now exports a single `PRODUCT_GENERATOR_MODEL = 'glm-5.2'` constant used by both the converged agent definition and the dashboard generate route. The `features.productGeneratorModel` field is dropped from `GET /v1/users/profile`.
|
|
1596
|
+
|
|
1597
|
+
## 5.3.0
|
|
1598
|
+
|
|
1599
|
+
### Minor Changes
|
|
1600
|
+
|
|
1601
|
+
- 83d57ad: Add the `_tenant` system variable and the `ResolvedTenancyContext` spine (multi-tenancy V1, increment 1)
|
|
1602
|
+
|
|
1603
|
+
Dispatch and `agents/:id/execute` now accept an optional top-level `tenant: { id, ... }`
|
|
1604
|
+
object, exposed in templates as `{{_tenant.*}}` — the Product Tenant scope (the
|
|
1605
|
+
builder's customer _inside_ a Product), nested under the Builder Org (`_user`) and
|
|
1606
|
+
above the End User (`_endUser`). It is threaded exactly like `_endUser`: additive,
|
|
1607
|
+
caller-asserted, and keyed to nothing yet (the trust boundary, identity projection,
|
|
1608
|
+
and scoped memory/records/secrets land in later increments).
|
|
1609
|
+
|
|
1610
|
+
Internally, `runExecutionPipeline` now computes a `ResolvedTenancyContext` once at the
|
|
1611
|
+
execution seam (a thin, pure projection of the caller + dispatch identity) and attaches
|
|
1612
|
+
it to `executionMetadata.resolvedTenancy` as the forward-stated dependency root later
|
|
1613
|
+
increments read scope from. Every existing execution behaves identically.
|
|
1614
|
+
|
|
1615
|
+
- 9ed5154: Multi-tenancy V1 (increment 4): Tenancy Strategy + lock-down gate (ADR 0012).
|
|
1616
|
+
A resource can now declare a `tenancyStrategy` on its Definition (an archetype
|
|
1617
|
+
preset — `internal` / `tenant-isolated` / `end-user-isolated` — expanding into
|
|
1618
|
+
two orthogonal axes, data scope × credential authority, plus a per-scope
|
|
1619
|
+
assurance floor). At the execution-pipeline seam the strategy is expanded
|
|
1620
|
+
(populating `dataScope` / `credentialAuthority` on `ResolvedTenancyContext`) and
|
|
1621
|
+
a **lock-down gate** runs **pre-engine**: a locked-down resource is rejected
|
|
1622
|
+
(403) when the resolved tenancy lacks a required scope or sits below the declared
|
|
1623
|
+
assurance floor — never silently run against the global scope. This is the first
|
|
1624
|
+
consumer of increment 3's graded `assurance`, so a web-embedded `client-token`
|
|
1625
|
+
dispatch of an `end-user-isolated` agent correctly **fails closed** (graded
|
|
1626
|
+
`anonymous`) until an Identity Exchange can raise it to `verified`.
|
|
1627
|
+
|
|
1628
|
+
Scope is the **agent** resource (authorable via the agent create/update/ensure
|
|
1629
|
+
config, the FPO inline-agent config, and the SDK — content-hashed so `ensure`
|
|
1630
|
+
tracks it). Enforcement is at the pipeline seam (single-turn agent dispatch /
|
|
1631
|
+
`:id/execute` / product-chat / client-token). The multi-turn loop executor and
|
|
1632
|
+
the background schedule/eval executor — neither of which resolves per-execution
|
|
1633
|
+
tenancy yet — apply a **fail-closed** backstop: a locked-down agent is refused
|
|
1634
|
+
there rather than run global. Resources with no strategy behave identically to
|
|
1635
|
+
today (the headline invariant). Flow-resource strategies, the config-bearing
|
|
1636
|
+
tenant overlay, elicitation surfaces, full loop/background enforcement, and
|
|
1637
|
+
ResumeState scope persistence are forward-stated follow-ups (the scoped-data
|
|
1638
|
+
increment).
|
|
1639
|
+
|
|
1640
|
+
## 5.2.3
|
|
1641
|
+
|
|
1642
|
+
### Patch Changes
|
|
1643
|
+
|
|
1644
|
+
- 346f947: Run workspace type-checking on the TypeScript 7 native compiler (`tsgo`, from `@typescript/native-preview`). The per-package `typecheck` / `type-check` scripts now invoke `tsgo --noEmit` instead of `tsc --noEmit` (~5x faster across the workspace). This is a type-check-only change: `typescript` stays pinned at `^6.0.3` for builds, lint, and codegen — whose compiler-API consumers (tsup `.d.ts` emit, typescript-eslint, ts-morph) are not stable on the 7.x API until ~7.1 — so no package's runtime behavior or emitted types change. The `typecheck:native` benchmark harness is updated to stay version-agnostic (it derives the `tsc` baseline for `--compare`), `@typescript/native-preview` is bumped to the latest tracked build, and the orphaned `@runtypelabs/system-product-generator` package's stray `typescript@^5.9.3` pin is aligned to `^6.0.3`.
|
|
1645
|
+
|
|
1646
|
+
## 5.2.2
|
|
1647
|
+
|
|
1648
|
+
### Patch Changes
|
|
1649
|
+
|
|
1650
|
+
- c09b0af: Agent Sandbox (Phase 1): give a hosted agent a Linux computer via five `builtin`
|
|
1651
|
+
tools — `bash`, `read_file`, `write_file`, `edit_file`, `expose_port` — injected
|
|
1652
|
+
at dispatch when `agent.config.sandbox.enabled` and the `enable-agent-sandbox`
|
|
1653
|
+
Flagship flag is on. The agent acts as if it is already inside the machine; the
|
|
1654
|
+
container is provisioned lazily on the first sandbox tool call. Phase 1 ships the
|
|
1655
|
+
`runtype-sandbox` provider with `ephemeral` persistence behind the flag.
|
|
1656
|
+
|
|
1657
|
+
The egress posture defaults to a curated, versioned, single-sourced `essentials`
|
|
1658
|
+
network profile (language registries, OS mirrors, GitHub) enforced at the single
|
|
1659
|
+
DO egress proxy — bounded, not open. The runtime is untouched: the tools route
|
|
1660
|
+
through the existing injected `ToolExecutor`, and all
|
|
1661
|
+
provisioning/network/billing lives API-side (ADR 0010). `bash`/`read_file`/etc.
|
|
1662
|
+
do not appear in tool discovery (injected, not catalog-selected).
|
|
1663
|
+
|
|
1664
|
+
## 5.2.1
|
|
1665
|
+
|
|
1666
|
+
### Patch Changes
|
|
1667
|
+
|
|
1668
|
+
- 9a77df1: Subagent HITL approval propagation (runtime Claude Managed path). When a Claude Managed subagent's child agent calls a tool that requires approval, the runtime now pauses for a human instead of swallowing the request into an opaque subagent tool failure. The Claude Managed bridge no longer converts a child tool's `ApprovalRequiredError` into an `is_error` result — it re-raises it; `runSubagent` forwards the parent's approval policy (`require` / `approvedTools` / `deniedTools`) into the child and enriches the propagating error with subagent attribution, so the parent agent loop emits a single `agent_approval_start`. The `agent_approval_start` / `approval_start` SSE events gain an optional `subagent` attribution object (`toolName`, `agentName`) so an approval UI can render "subagent X wants to run tool Y". On resume the parent re-dispatches the subagent with the now-approved tool, which proceeds. Attribution is UX context only — no code branches on it. (api virtual-flow / Claude Managed subagent paths are tracked as a gated follow-up.)
|
|
1669
|
+
|
|
1670
|
+
## 5.2.0
|
|
1671
|
+
|
|
1672
|
+
### Minor Changes
|
|
1673
|
+
|
|
1674
|
+
- 049bcf9: Surface nested flow-as-tool attribution on the unified SSE stream via `text_start.parentToolCallId` and `reasoning_start.parentToolCallId`.
|
|
1675
|
+
|
|
1676
|
+
When a flow runs as a tool, the server enriches its streamed prompt text and reasoning with the parent model tool-call id (`toolContext.toolId`). The unified (Persona 4.0) translator previously dropped that enrichment, so the nested flow's text and thinking were flattened into the parent execution's channels with no way to attribute them. The unified `text_start` and `reasoning_start` events now carry an optional `parentToolCallId` (matching `tool_start.toolCallId`): a consumer maps a block's `id` to its `parentToolCallId` and routes the nested streamed text/thinking into the parent tool's row instead of the top-level assistant message. Additive and optional — top-level (non-nested) text/reasoning omits the field.
|
|
1677
|
+
|
|
1678
|
+
## 5.1.0
|
|
1679
|
+
|
|
1680
|
+
### Minor Changes
|
|
1681
|
+
|
|
1682
|
+
- 82d897c: Two follow-ups to the unified SSE cutover:
|
|
1683
|
+
|
|
1684
|
+
**Single public SSE schema name.** Rename the OpenAPI component `UnifiedSSEEvent`
|
|
1685
|
+
→ `ExecutionStreamEvent` (and the SDK's canonical `UnifiedStreamEvent` type →
|
|
1686
|
+
`ExecutionStreamEvent`), so the published spec / Fern API reference / SDK types
|
|
1687
|
+
expose a single, neutrally-named SSE event union with no "unified vs legacy"
|
|
1688
|
+
framing. The internal Zod source keeps its `unified*` names; `DispatchEvent` /
|
|
1689
|
+
`AgentStreamEvent` remain deprecated aliases of the renamed type, and the
|
|
1690
|
+
legacy `FlowSSEEvent` component stays registered (no route reference) so the
|
|
1691
|
+
SDK's FlowBuilder convenience types keep resolving.
|
|
1692
|
+
|
|
1693
|
+
**Per-step token usage in the unified stream.** Add an optional `tokensUsed`
|
|
1694
|
+
field to the unified `step_complete` event and forward it through the edge
|
|
1695
|
+
translator, restoring the per-step token count on surfaces that moved to the
|
|
1696
|
+
unified vocabulary (e.g. the dashboard flow-builder test-step result).
|
|
1697
|
+
|
|
1698
|
+
### Patch Changes
|
|
1699
|
+
|
|
1700
|
+
- 97a3431: Normalize remaining dashboard dispatch SSE consumers and flow-tool execution streams for the unified SSE default.
|
|
1701
|
+
|
|
1702
|
+
## 5.0.0
|
|
1703
|
+
|
|
1704
|
+
### Major Changes
|
|
1705
|
+
|
|
1706
|
+
- 44779c1: Remove phantom prompt-execution surfaces that targeted server routes which never existed (`POST /prompts/{id}/run` and `POST /prompts/{id}/run-on-record`): drops `prompts.run()` / `PromptRunner` / `PromptRunOptions` and `PromptsEndpoint.runOnRecord()`. These methods always 404'd; use `dispatch()` to execute a prompt step instead.
|
|
1707
|
+
|
|
1708
|
+
## 4.21.0
|
|
1709
|
+
|
|
1710
|
+
### Minor Changes
|
|
1711
|
+
|
|
1712
|
+
- b43088f: Make the unified SSE event vocabulary the default for streaming responses.
|
|
1713
|
+
|
|
1714
|
+
Every execution stream (`/v1/dispatch`, `/v1/agents/{id}/execute`, the client
|
|
1715
|
+
chat/resume routes, and the dispatch resume/approve routes) now emits the
|
|
1716
|
+
unified 33-event vocabulary by default. The OpenAPI spec and generated SDK types
|
|
1717
|
+
document the unified `UnifiedSSEEvent` union only; the legacy `AgentSSEEvent` /
|
|
1718
|
+
`DispatchSSEEvent` components are removed (`FlowSSEEvent` is retained solely for
|
|
1719
|
+
the not-yet-ported eval stream).
|
|
1720
|
+
|
|
1721
|
+
The wire vocabulary is resolved per request by `resolveSseEventFormat`:
|
|
1722
|
+
1. an explicit `?events=unified` / `?events=legacy` query param wins;
|
|
1723
|
+
2. otherwise the `X-Persona-Version` header negotiates (v4.0+ → unified, an older
|
|
1724
|
+
announced version → legacy, so deployed pre-4.0 widgets are protected);
|
|
1725
|
+
3. otherwise the new `default-sse-event-format` Cloudflare Flagship flag (enum
|
|
1726
|
+
`unified` | `legacy`, code default `unified`) decides — targetable by
|
|
1727
|
+
environment, organization, user, or surface so a cohort can be rolled back to
|
|
1728
|
+
the legacy vocabulary during the surgical rollout.
|
|
1729
|
+
|
|
1730
|
+
The engine continues to emit legacy frames internally; they are translated to
|
|
1731
|
+
the unified vocabulary at the stream edge.
|
|
1732
|
+
|
|
1733
|
+
### Patch Changes
|
|
1734
|
+
|
|
1735
|
+
- 4bef8db: Port the Python SDK (`runtype-sdk`) to consume the unified SSE event vocabulary
|
|
1736
|
+
as its only wire format. Every streaming request opts into `?events=unified` and
|
|
1737
|
+
the SDK parses the unified 33-event vocabulary natively (no legacy parsers, no
|
|
1738
|
+
translation layer). The hand-written event models, the SSE dispatch, the
|
|
1739
|
+
local-tool pause/resume collector, and the `FlowResult` / `FlowSummary`
|
|
1740
|
+
accumulation are all rewritten to the unified events.
|
|
1741
|
+
|
|
1742
|
+
This is a breaking change to the Python SDK's streaming surface (`runtype-sdk`
|
|
1743
|
+
4.0.0): the legacy `agent_*` / `flow_*` event models are replaced by the unified
|
|
1744
|
+
models (`UnifiedEvent` union), `StreamCallbacks` exposes one callback per unified
|
|
1745
|
+
event type (and is the single surface for flow + agent, with `AgentStreamCallbacks`
|
|
1746
|
+
as an alias), and `FlowSummary.execution_time` becomes `duration_ms`. The npm
|
|
1747
|
+
`@runtypelabs/sdk` (TypeScript SDK) is unchanged; this entry exists to record the
|
|
1748
|
+
Python SDK change in the release pipeline.
|
|
1749
|
+
|
|
1750
|
+
- 2b788c7: Port the TS SDK's hand-written SSE runtime parsers to the unified 33-event
|
|
1751
|
+
vocabulary. The dispatch and agent execution streams (`/dispatch`,
|
|
1752
|
+
`/dispatch/resume`, `/agents/{id}/execute`, `/agents/{id}/resume`) now request
|
|
1753
|
+
`?events=unified` and reverse-translate the unified frames back to the SDK's
|
|
1754
|
+
existing legacy event shapes, so the public `StreamCallbacks` /
|
|
1755
|
+
`AgentStreamCallbacks` surface is unchanged. The translators are tolerant of a
|
|
1756
|
+
legacy stream too (pass-through), keeping the SDK safe during the server-side
|
|
1757
|
+
rollout. Still-legacy producers (`/prompts/{id}/run`, the eval stream,
|
|
1758
|
+
`/tools/{id}/execute`) are untouched.
|
|
1759
|
+
|
|
1760
|
+
## 4.20.0
|
|
1761
|
+
|
|
1762
|
+
### Minor Changes
|
|
1763
|
+
|
|
1764
|
+
- 3fdf801: FPO config-as-code PR3 — `pull-fpo` + `prune`, closing the whole-FPO round-trip.
|
|
1765
|
+
- **`GET /v1/products/pull-fpo?name=…`** (SDK `products.pullFpo(name)`) reconstructs
|
|
1766
|
+
a self-contained Full Product Object from the live product graph — the absorb-drift
|
|
1767
|
+
direction of `ensure-fpo`. It composes the existing per-entity pulls (product,
|
|
1768
|
+
backing flows/agents, surfaces) and mints deterministic FPO-local ids, so feeding
|
|
1769
|
+
the result back into `ensure-fpo` converges to `unchanged`. records/schedules/secrets
|
|
1770
|
+
are not reconstructed and `tools` is emitted empty (tool refs are portable
|
|
1771
|
+
`tool:<name>`); per-pull caveats are surfaced in `warnings`.
|
|
1772
|
+
- **`prune` (opt-in)** on `POST /v1/products/ensure-fpo` (SDK `ensureFpo(fpo, { prune })`):
|
|
1773
|
+
after the converge passes, removes product-scoped `product_capabilities` / `product_surfaces`
|
|
1774
|
+
(and their `product_surface_items`) absent from the FPO. Account-scoped flows/agents/tools/records
|
|
1775
|
+
are NEVER touched; `createPolicy: 'skip'` entities are kept. Adds a `pruned` per-entity
|
|
1776
|
+
result; with `dryRun`, would-be removals are reported as `pruned` plan rows without deleting.
|
|
1777
|
+
|
|
1778
|
+
## 4.19.2
|
|
1779
|
+
|
|
1780
|
+
### Patch Changes
|
|
1781
|
+
|
|
1782
|
+
- d5b9f87: Normalize client identity + version advertisement across all Runtype SDKs/clients.
|
|
1783
|
+
|
|
1784
|
+
Every first-party client now sends a consistent `X-Runtype-Client: <kind>` header
|
|
1785
|
+
plus a `runtype-<kind>/<version>` `User-Agent`, so the API can attribute traffic by
|
|
1786
|
+
client and version (`detectActorSource` in `audit-log.ts`):
|
|
1787
|
+
- **JS/TS SDK (`@runtypelabs/sdk`)**: previously sent no attribution at all — now
|
|
1788
|
+
defaults to `X-Runtype-Client: sdk` + `User-Agent: runtype-sdk/<version> (typescript)`
|
|
1789
|
+
(version inlined at build via tsup `define`). Caller-supplied headers still override,
|
|
1790
|
+
so the CLI's `runtype-cli/<version>` wrapping is unaffected.
|
|
1791
|
+
- **Python SDK**: now sends `X-Runtype-Client: sdk` + `User-Agent: runtype-sdk/<version> (python)`
|
|
1792
|
+
on both the ergonomic client and the generated `.api` surface. The version is resolved
|
|
1793
|
+
from installed distribution metadata via `importlib.metadata` (single source: `pyproject.toml`).
|
|
1794
|
+
- **MCP (`@runtypelabs/mcp`)**: now advertises `X-Runtype-Client: mcp` +
|
|
1795
|
+
`User-Agent: runtype-mcp/<version>` (the headers were previously gated on a client
|
|
1796
|
+
kind that no call site ever set, so the MCP server sent no attribution at all).
|
|
1797
|
+
- **Code Mode MCP**: now versions its proxy `User-Agent` (`Runtype-CodeMode/<version>`),
|
|
1798
|
+
keeping the exact prefix casing the Analytics Engine dashboard filters on.
|
|
1799
|
+
|
|
1800
|
+
The `runtype-sdk/` prefix is shared by both SDKs (it's what the API parses); the
|
|
1801
|
+
TypeScript vs Python distinction rides in the standard User-Agent comment
|
|
1802
|
+
(`(typescript)` / `(python)`). The CLI already advertised identity + version and is
|
|
1803
|
+
unchanged.
|
|
1804
|
+
|
|
1805
|
+
- 6d5ba51: Harden WebMCP page-tool handling against indirect prompt injection (Chrome WebMCP security guidance / OWASP LLM01):
|
|
1806
|
+
- **Spotlight untrusted tool output.** Output from `origin: 'webmcp'` page tools (and any tool a page flags with the new `untrustedContentHint`) is now wrapped in a randomized-nonce delimiter envelope before the model reads it, so the model treats contaminated third-party data as data, not instructions. Verbatim output is unchanged in ResumeState, `{{toolName_result}}` variables, and the SSE stream.
|
|
1807
|
+
- **Cap untrusted output size** at 64KB (truncated with a visible marker) to prevent context/token-exhaustion via an unbounded page-tool result.
|
|
1808
|
+
- **Cap `clientTools[]` descriptions at 2KB** to close the malicious-manifest / tool-poisoning vector (hidden instructions in an oversized description).
|
|
1809
|
+
- **Add `untrustedContentHint`** to the inline client-tool wire schema so a page can mark an `sdk`-origin tool's output as untrusted.
|
|
1810
|
+
- Strengthen the dashboard assistant's safety prompt to recognize the spotlight envelope and treat tool names/descriptions as untrusted data.
|
|
1811
|
+
|
|
1812
|
+
## 4.19.1
|
|
1813
|
+
|
|
1814
|
+
### Patch Changes
|
|
1815
|
+
|
|
1816
|
+
- cd7b402: Refresh default models for new accounts. The global default model is now
|
|
1817
|
+
`kimi-k2.6` (a reasoning + tool-use + vision model already trusted as the
|
|
1818
|
+
product-generator default) instead of the tagless 9B `qwen/qwen3.5-9b`. Bumped
|
|
1819
|
+
flagship tiers to the current generation and dropped the superseded versions:
|
|
1820
|
+
`gpt-5.4` → `gpt-5.5`, `claude-opus-4-6` → `claude-opus-4-8`, `qwen/qwen3.5-9b`
|
|
1821
|
+
→ `qwen/qwen3.6-27b`, `qwen3.5-plus` → `qwen3.6-plus`, and added
|
|
1822
|
+
`gemini-3.5-flash` and `nemotron-3-ultra-550b-a55b`. Dropped the grok tiers and
|
|
1823
|
+
`nemotron-3-120b-a12b` from the auto-enabled set. Cheaper tiers with no newer
|
|
1824
|
+
equivalent (`gpt-5.4-mini`, `gpt-5.4-nano`, `gemini-3-1-flash-lite`,
|
|
1825
|
+
`gemini-3.1-pro`, `claude-sonnet-4-6`) are unchanged.
|
|
1826
|
+
|
|
1827
|
+
Kept in sync with the new default: the `prompts.model` column default (migration
|
|
1828
|
+
`0077`), the agent-facing model-selection guidance in `knowledge-fragments.ts`,
|
|
1829
|
+
and the regenerated OpenAPI spec / SDK types (the `create_prompt` / `update_prompt`
|
|
1830
|
+
`model` default).
|
|
1831
|
+
|
|
1832
|
+
## 4.19.0
|
|
1833
|
+
|
|
1834
|
+
### Minor Changes
|
|
1835
|
+
|
|
1836
|
+
- 9efb803: Marathon playbooks: opt-in `fallbackOnEmpty` to recover from empty (text-less)
|
|
1837
|
+
model output.
|
|
1838
|
+
|
|
1839
|
+
Set `fallbackOnEmpty: true` on a milestone (or at the playbook top level as a
|
|
1840
|
+
default) to make that milestone's `fallbackModels` chain also fire when the model
|
|
1841
|
+
finishes successfully but returns no visible text — the "thinking model spends its
|
|
1842
|
+
whole budget reasoning and answers nothing" failure — instead of only on errors.
|
|
1843
|
+
It attaches the execution engine's existing `empty-output` fallback trigger to the
|
|
1844
|
+
agent `errorHandling` the marathon writes. Off by default (never automatic) and
|
|
1845
|
+
only effective when `fallbackModels` is configured; the playbook loader warns when
|
|
1846
|
+
it is enabled without a fallback chain. No API change.
|
|
1847
|
+
|
|
1848
|
+
- 9efb803: Marathon: support per-session `maxTokens` and `temperature` overrides for the
|
|
1849
|
+
**primary** model, settable from the CLI (`--max-tokens` / `--temperature`) and
|
|
1850
|
+
in playbooks (per-milestone fields plus top-level defaults).
|
|
1851
|
+
- API: `POST /v1/agents/:id/execute` now accepts request-level `temperature` and
|
|
1852
|
+
`maxTokens`, merged into the agent config before `buildVirtualFlow` (mirrors the
|
|
1853
|
+
existing `model` / `systemPrompt` overrides). Out-of-range values are ignored.
|
|
1854
|
+
- SDK: `RunTaskOptions`, `AgentExecuteRequest`, and `WorkflowMilestoneConfig` gain
|
|
1855
|
+
optional `temperature` / `maxTokens`; the marathon runner threads them into each
|
|
1856
|
+
session's execute request.
|
|
1857
|
+
- CLI: resolves both per phase with precedence per-milestone playbook value >
|
|
1858
|
+
global CLI flag > playbook top-level default.
|
|
1859
|
+
|
|
1860
|
+
Previously only a fallback model could carry a `maxTokens`, so a "thinking"
|
|
1861
|
+
primary model that spent its budget reasoning could return no tool call and stall
|
|
1862
|
+
the run with nothing to show.
|
|
1863
|
+
|
|
1864
|
+
### Patch Changes
|
|
1865
|
+
|
|
1866
|
+
- e96edad: feat(products): ensure-fpo PR2 — converge surfaces, records, schedules, secrets, and capability-as-tool composition
|
|
1867
|
+
|
|
1868
|
+
Extends `POST /v1/products/ensure-fpo` (and SDK `products.ensureFpo()`) beyond the PR1 product → capability-backing graph to converge the rest of the Full Product Object:
|
|
1869
|
+
- **Surfaces + surface items**: each `fpo.surfaces[]` converges via the product-scoped surface-ensure service (behavior `{ type, ...config }`), and route → `product_surface_items` join rows reconcile against the converged capabilities. Integration-backed types (slack/telegram/discord) reserve a pending integration once, on first create only (idempotent; `inbound` stored raw and excluded from the content hash).
|
|
1870
|
+
- **Records**: `fpo.records[]` reconcile by tenant `(type, name)` with merged metadata (mirrors the assembler's `onConflictDoUpdate`).
|
|
1871
|
+
- **Schedules**: `fpo.schedules[]` reconcile by `(owner, backing flow/agent, triggerType)` with update-in-place (never orphan — an orphaned schedule keeps firing). A within-FPO duplicate `(capabilityId, triggerType)` guard keeps the identity unambiguous.
|
|
1872
|
+
- **Secrets**: tool `auth.setupRequired` secret bindings + product-level `fpo.secrets[]` materialize via the (now shared) assembler helpers. The route additionally requires `SECRETS:WRITE` — but only when the FPO actually carries secrets, so secret-free callers keep working with `PRODUCTS:WRITE` alone.
|
|
1873
|
+
- **Capability-as-tool composition**: `capability:<id>` toolIds and `capabilityToolRefs[]` now materialize as flow-backed tools (converged by name via tool-ensure) with the agent ref rewritten to the portable `tool:<name>` form before the agent converges. The PR1 rejection guard is removed. Backing converges in two passes (flows then agents) so a composition target resolves regardless of FPO order.
|
|
1874
|
+
|
|
1875
|
+
The per-entity report (`entities[]`) gains `tool` / `surface` / `record` / `schedule` kinds. Still NON-atomic and self-healing on re-run; whole-FPO fast-probe, `pull-fpo`, and `prune` remain deferred to PR3.
|
|
1876
|
+
|
|
1877
|
+
## 4.18.0
|
|
1878
|
+
|
|
1879
|
+
### Minor Changes
|
|
1880
|
+
|
|
1881
|
+
- 266280e: Add whole-FPO config-as-code converge: `POST /v1/products/ensure-fpo` + `products.ensureFpo()`.
|
|
1882
|
+
|
|
1883
|
+
Converges an entire Full Product Object (the nested product graph) in one shot by fanning out to the
|
|
1884
|
+
existing per-entity ensure services in dependency order (product → capability backing flows/agents →
|
|
1885
|
+
capability link rows), threading FPO-local refs to real identities and returning a per-entity report.
|
|
1886
|
+
NON-atomic by design: a per-entity failure is reported (not thrown) and a re-run self-heals.
|
|
1887
|
+
|
|
1888
|
+
This first release converges product + capability backing flows/agents + capability links. Surfaces,
|
|
1889
|
+
records, schedules, `fpo.tools` secret bindings, capability-as-tool composition, the whole-FPO
|
|
1890
|
+
hash-only fast-probe, `pull-fpo`, and opt-in `prune` are deliberately deferred to follow-ups (such
|
|
1891
|
+
capabilities are reported as `failed`/`skipped` in the per-entity report). Adds the canonical
|
|
1892
|
+
`computeFpoContentHash` to `@runtypelabs/shared` (with an inlined SDK copy pinned by a shared parity
|
|
1893
|
+
corpus).
|
|
1894
|
+
|
|
1895
|
+
## 4.17.1
|
|
1896
|
+
|
|
1897
|
+
### Patch Changes
|
|
1898
|
+
|
|
1899
|
+
- 408e8f4: Enable conditional revalidation (instant-lists part 4) for the Agents list, the
|
|
1900
|
+
root deferred from part 3. The canonical first page of `GET /agents` now supports
|
|
1901
|
+
HTTP conditional GET: it returns a weak `ETag` and `304 Not Modified` when the
|
|
1902
|
+
caller's `If-None-Match` still matches, skipping the page query. The dashboard
|
|
1903
|
+
sends the prior ETag when warming/revalidating the Agents list, so a navigation or
|
|
1904
|
+
reload where nothing changed costs a single `304` with no body and keeps the warm
|
|
1905
|
+
seed on screen.
|
|
1906
|
+
|
|
1907
|
+
The agents list `lastRunAt` is a correlated `MAX(agent_executions.created_at)` per
|
|
1908
|
+
agent rather than an `agents` column, so the change token folds that cross-table
|
|
1909
|
+
max in (via a new additive `freshnessExpressions` option on the shared
|
|
1910
|
+
`evaluateListConditional` helper). This means a new agent run busts the cache and
|
|
1911
|
+
the "Last run" cell never goes stale behind a `304` — a deliberate trade that
|
|
1912
|
+
lowers the `304` hit rate for actively-running accounts in exchange for
|
|
1913
|
+
correctness. See `docs/features/planning/2026-06-14-list-conditional-revalidation.md`.
|
|
1914
|
+
|
|
1915
|
+
- fee4239: Extend conditional revalidation (instant-lists part 3) to the Records, Tools, and
|
|
1916
|
+
Schedules lists. The canonical first page of `GET /records`, `GET /tools`, and
|
|
1917
|
+
`GET /schedules` now supports HTTP conditional GET: each returns a weak `ETag`
|
|
1918
|
+
(`COUNT` + `MAX(updated_at, ...)`) and `304 Not Modified` when the caller's
|
|
1919
|
+
`If-None-Match` still matches, skipping the page query entirely. The dashboard
|
|
1920
|
+
sends the prior ETag when warming/revalidating these lists, so a navigation or
|
|
1921
|
+
reload where nothing changed costs a single `304` with no body and keeps the warm
|
|
1922
|
+
seed on screen. Schedules folds `next_run_at`/`last_run_at` into the freshness MAX
|
|
1923
|
+
(the scheduler writes them without bumping `updated_at`); records/tools need no
|
|
1924
|
+
extra freshness columns. The conditional path is gated to the truly unfiltered
|
|
1925
|
+
canonical page on both sides — any filter/search/cursor or non-default page size
|
|
1926
|
+
falls back to a plain GET.
|
|
1927
|
+
|
|
1928
|
+
The Agents list is intentionally deferred to a follow-up: its `lastRunAt` is a
|
|
1929
|
+
correlated subquery over the executions table rather than an `agents` column, so a
|
|
1930
|
+
token over `agents` alone would 304 after a new run and leave "Last run" stale.
|
|
1931
|
+
See `docs/features/planning/2026-06-14-list-conditional-revalidation.md`.
|
|
1932
|
+
|
|
1933
|
+
## 4.17.0
|
|
1934
|
+
|
|
1935
|
+
### Minor Changes
|
|
1936
|
+
|
|
1937
|
+
- 83e5921: Conditional revalidation for the Flows list (instant-lists part 2). The canonical
|
|
1938
|
+
first page of `GET /flows` now supports HTTP conditional GET: it returns a weak
|
|
1939
|
+
`ETag` (`COUNT` + `MAX(updated_at)`) and `304 Not Modified` when the caller's
|
|
1940
|
+
`If-None-Match` still matches, skipping the page query entirely. The dashboard
|
|
1941
|
+
sends the prior ETag when warming/revalidating the Flows list, so a navigation or
|
|
1942
|
+
reload where nothing changed costs a single `304` with no body and keeps the warm
|
|
1943
|
+
seed on screen. Adds `RuntypeClient.getConditional()` to the SDK. Other primary
|
|
1944
|
+
lists and detail-shell seeding are fast-follows (see
|
|
1945
|
+
`docs/features/planning/2026-06-14-list-conditional-revalidation.md`).
|
|
1946
|
+
|
|
1947
|
+
## 4.16.0
|
|
1948
|
+
|
|
1949
|
+
### Minor Changes
|
|
1950
|
+
|
|
1951
|
+
- 46624dc: Add config-as-code `ensure` for skills (admin/control plane). New `POST /v1/skills/ensure` (idempotent hash-first converge: create the skill or append a new version when the canonical manifest hash differs; `release: 'publish'` publishes the converged version) and `GET /v1/skills/pull` (canonical definition + provenance, the absorb-drift direction). Identity is name + account scope; the content hash (`computeSkillContentHash`) covers the manifest with the frontmatter `name` excluded. Ensure is the admin-plane `create_skill` path — API scopes only (`SKILLS:WRITE`/`SKILLS:*`), no review queue, no proposal row — distinct from the deployed-agent `propose_skill` data plane. Adds `configHash` / `lastModifiedSource` / `lastSdkSyncAt` provenance columns on `skills`, a `skill_ensure_locks` scoped-name serialization table, and the SDK surface `defineSkill` + `skills.ensure()` / `skills.pull()`.
|
|
1952
|
+
- 845d81b: Add config-as-code `ensure` / `pull` for surfaces. New product-scoped endpoints
|
|
1953
|
+
`POST /v1/products/{id}/surfaces/ensure` and `GET /v1/products/{id}/surfaces/pull`
|
|
1954
|
+
idempotently converge a repo-defined surface onto a product (identity is
|
|
1955
|
+
productId + name) using the shared hash-first ensure protocol — hash-only probe,
|
|
1956
|
+
`definitionRequired` miss, 422 content-hash-mismatch, 409 conflict, and `dryRun`
|
|
1957
|
+
planning. Surfaces have no version snapshots (release `none`), so there is no
|
|
1958
|
+
publish option. The SDK gains `Runtype.surfaces.ensure(productId, def)` /
|
|
1959
|
+
`Runtype.surfaces.pull(productId, name)` and `defineSurface`. Credentials in
|
|
1960
|
+
`inbound` / `outbound` are sealed before write and the content hash is computed
|
|
1961
|
+
over the plaintext form so probes stay stable across pulls.
|
|
1962
|
+
- 45aaaa7: Add cross-session "Always allow" persisted tool-approval grants. A remembered tool
|
|
1963
|
+
approval now persists server-side, keyed to (owner, agent, end-user) with an
|
|
1964
|
+
account-level fallback, so the human-in-the-loop prompt is skipped automatically on
|
|
1965
|
+
future dispatches for that tool. Enabled per-agent via `approval.choices.alwaysAllow`
|
|
1966
|
+
(default off) and revocable from the dashboard. Skill-load approvals
|
|
1967
|
+
(`toolType === 'skill'`) are excluded, and a grant only short-circuits the approval
|
|
1968
|
+
prompt — tool resolution, ownership scoping, and secret access are unaffected
|
|
1969
|
+
(approval ≠ authorization).
|
|
1970
|
+
- 3396ef1: Tighten context-step `errorHandling` validation to object-only (errorHandling v2, leg 4)
|
|
1971
|
+
|
|
1972
|
+
Flow create / update / ensure / validate now reject the legacy bare-string
|
|
1973
|
+
`errorHandling` shorthand (`'fail' | 'continue' | 'default'`) on context steps,
|
|
1974
|
+
along with the deprecated `'default'` onError alias. Clients must send the object
|
|
1975
|
+
form `{ onError: 'fail' | 'continue' | 'fallback' }` (which the dashboard, SDK,
|
|
1976
|
+
templates, and AI generators have emitted since the leg-2 convergence).
|
|
1977
|
+
|
|
1978
|
+
This is a deliberate, low-risk breaking change to the flow-authoring contract:
|
|
1979
|
+
30-day production telemetry (`Flow ErrorHandling Written`) showed inbound
|
|
1980
|
+
string-form context writes came 100% from one internal smoke-test account, with
|
|
1981
|
+
zero organic customer traffic.
|
|
1982
|
+
|
|
1983
|
+
The SDK (`@runtypelabs/sdk`) context-step builders now type `errorHandling` as the
|
|
1984
|
+
object form only (`ContextErrorHandling`), so the now-rejected bare-string form is
|
|
1985
|
+
caught at compile time instead of surfacing as a runtime 400. Prompt-step builders
|
|
1986
|
+
still accept the string shorthand.
|
|
1987
|
+
|
|
1988
|
+
The runtime is unchanged: the replay normalizer still tolerates the string and
|
|
1989
|
+
`'default'` forms, so immutable historical flow versions keep executing, and
|
|
1990
|
+
`/dispatch` (which does not run this validator) is unaffected. Prompt-step
|
|
1991
|
+
`errorHandling` uses its own richer schema and is out of scope.
|
|
1992
|
+
|
|
1993
|
+
- f9b537d: Add Agent Skill scan verdicts (warnings vs errors).
|
|
1994
|
+
|
|
1995
|
+
Introduces a deterministic two-tier verdict layer over SkillSpector findings: a
|
|
1996
|
+
`warning` when a skill _appears_ malicious (low–medium confidence) and an
|
|
1997
|
+
`error` when it is high-confidence malicious or matches an always-block category
|
|
1998
|
+
(credential exfiltration, prompt injection, MCP tool poisoning, data
|
|
1999
|
+
exfiltration, privilege escalation).
|
|
2000
|
+
- `@runtypelabs/shared`: `deriveSkillScanVerdict()` + the confidence × severity
|
|
2001
|
+
matrix, hard-block categories, and the scanner-Worker RPC contract types
|
|
2002
|
+
(`SkillScanRequest` / `SkillScanResponse`). Pure and single-sourced so the API,
|
|
2003
|
+
dashboard, and scanner Worker share identical thresholds.
|
|
2004
|
+
- New `runtype-skill-spector` Worker app wraps `@runtypelabs/skill-spector` in
|
|
2005
|
+
its own bundle (off the API's bundle budget) and exposes a `scanSkill` RPC.
|
|
2006
|
+
- `@runtypelabs/api`: `scanSkillManifest()` client that serializes a manifest to
|
|
2007
|
+
its canonical SKILL.md, calls the scanner over the optional
|
|
2008
|
+
`SKILL_SPECTOR_SCAN` binding, and fails closed when the scanner is
|
|
2009
|
+
unavailable. Includes a `dev:bun` in-process stub for parity.
|
|
2010
|
+
- `@runtypelabs/api`: `POST /v1/skills/scan` ("scan before save", no persist/
|
|
2011
|
+
gate) + the `scanSkillManifest` client over the optional `SKILL_SPECTOR_SCAN`
|
|
2012
|
+
binding (staging-bound; fails closed when absent). Dev:bun in-process stub.
|
|
2013
|
+
- `@runtypelabs/sdk`: `skills.scan(markdown)` returning the verdict.
|
|
2014
|
+
- `@runtypelabs/dashboard-spa`: a "Security scan" affordance + verdict banner
|
|
2015
|
+
(green clean / amber suspicious / red blocked, with a findings list) in the
|
|
2016
|
+
skill editor.
|
|
2017
|
+
|
|
2018
|
+
Publish/bind gating and scan persistence remain sequenced follow-ups, and the
|
|
2019
|
+
production scanner binding is added once the production scanner Worker is
|
|
2020
|
+
deployed (worker-first ordering).
|
|
2021
|
+
|
|
2022
|
+
## 4.15.0
|
|
2023
|
+
|
|
2024
|
+
### Minor Changes
|
|
2025
|
+
|
|
2026
|
+
- 0dcd669: Add config-as-code `ensure`/`pull` for products. `POST /v1/products/ensure` idempotently converges a repo-defined product (create-or-update by name + account scope, hash-first probe protocol) and `GET /v1/products/pull` returns the canonical definition + provenance (the absorb-drift direction). The SDK gains `Runtype.products.ensure`/`Runtype.products.pull` plus `defineProduct`, mirroring the tool ensure surface.
|
|
2027
|
+
|
|
2028
|
+
Scope (v1): the converge covers the top-level product record only — `description`, `icon`, and the `spec` (ProductSpec: identity / stack / internal docs). The canonical content hash (`computeProductContentHash` in `@runtypelabs/shared`) excludes `name` (identity) and `canvas` (architecture-viewer UI layout state). Nested capabilities/surfaces/tools/records/schedules are not converged. Like tools, products have no version snapshots, so there is no publish option.
|
|
2029
|
+
|
|
2030
|
+
Adds `config_hash` / `last_modified_source` / `last_sdk_sync_at` provenance columns to `products` and a `product_ensure_locks` table for scoped-name serialization (migration `0071`).
|
|
2031
|
+
|
|
2032
|
+
## 4.14.0
|
|
2033
|
+
|
|
2034
|
+
### Minor Changes
|
|
2035
|
+
|
|
2036
|
+
- fec3688: feat(api): per-turn systemPrompt + clientTools on POST /v1/agents/:id/execute
|
|
2037
|
+
|
|
2038
|
+
Unblocks config-as-code migration (ADR 0003) for agents whose defining state is
|
|
2039
|
+
per-turn dynamic — the Dev Mode and Dashboard assistants rebuild their system
|
|
2040
|
+
prompt every turn (embedding the flow being edited / page context) and the
|
|
2041
|
+
Dashboard assistant's entire tool surface arrives as browser `clientTools[]`.
|
|
2042
|
+
They can now be referenced by saved-agent id instead of dispatched fully inline.
|
|
2043
|
+
- **`systemPrompt` override** (#4398): optional request-level override, applied to
|
|
2044
|
+
the loaded agent config before `buildVirtualFlow` (covers both the loop and
|
|
2045
|
+
non-loop paths), mirroring the existing `model` / `reasoning` overrides.
|
|
2046
|
+
Request-scoped, never persisted. Trusted-server-proxy-only.
|
|
2047
|
+
- **`clientTools` passthrough** (#4399): optional request-level WebMCP / SDK local
|
|
2048
|
+
tools, admitted through the SAME seam dispatch uses and threaded via
|
|
2049
|
+
`executionMetadata.clientTools` (api prompt-executor merge, precedence
|
|
2050
|
+
`saved < runtimeTools < clientTools`; stays off the runtime package).
|
|
2051
|
+
- **Shared admission seam**: extracted `admitApiKeyClientTools` in
|
|
2052
|
+
`runtime-tools-utils.ts`. `POST /v1/dispatch` is refactored onto it
|
|
2053
|
+
(behavior-preserving), pinned by a `.claude/review/touchpoints.yaml` row.
|
|
2054
|
+
- **SDK parity**: `AgentExecuteRequest` (`@runtypelabs/sdk`) gains `systemPrompt`,
|
|
2055
|
+
`clientTools`, and `clientToolsPolicy`, mirroring its existing `model` /
|
|
2056
|
+
`reasoning` overrides and the `DispatchRequest` contract.
|
|
2057
|
+
|
|
2058
|
+
Also adds `maxTokens` to the `FpoAgentRuntimeConfig` public type snapshot (the v2
|
|
2059
|
+
inline-agent `config` mirror), with a new `FpoAgentRuntimeConfig ↔
|
|
2060
|
+
agentRuntimeConfigSchema` parity guard so the hand-maintained mirror can no longer
|
|
2061
|
+
drift silently. Docs: `guide-runtime-tools.mdx` updated — `clientTools[]` /
|
|
2062
|
+
`clientToolsPolicy` are now accepted on both `/v1/dispatch` and
|
|
2063
|
+
`/v1/agents/:id/execute`.
|
|
2064
|
+
|
|
2065
|
+
- 26c393c: feat(agents): make `maxTokens` a savable agent config field
|
|
2066
|
+
|
|
2067
|
+
`maxTokens` is now part of the canonical agent runtime config surface
|
|
2068
|
+
(`agentRuntimeConfigSchema`), so it can be set via `createAgent`, `updateAgent`,
|
|
2069
|
+
and the config-as-code `ensure` protocol (`defineAgent({ maxTokens })`), persisted
|
|
2070
|
+
on the agent row, and included in the content hash. Previously it was an unknown
|
|
2071
|
+
key, silently stripped on write — agents that need a fixed output budget (e.g. the
|
|
2072
|
+
Product Generator pinning `24000` for a "thinking" default model) could not save it.
|
|
2073
|
+
|
|
2074
|
+
The execution wiring already consumed `config.maxTokens` (mapped onto the virtual
|
|
2075
|
+
flow's prompt step, defaulting to `16384` when unset), so saving it is all that was
|
|
2076
|
+
required for it to take effect. No per-request route override is added — a fixed
|
|
2077
|
+
token budget is a static property of the agent definition.
|
|
2078
|
+
|
|
2079
|
+
## 4.13.1
|
|
2080
|
+
|
|
2081
|
+
### Patch Changes
|
|
2082
|
+
|
|
2083
|
+
- 8bffeb2: Internal, tenant-scoped asset offload for inbound conversation media.
|
|
2084
|
+
|
|
2085
|
+
Large inline media (base64 images / file attachments) on inbound conversation
|
|
2086
|
+
message writes can now be offloaded to internal, tenant-scoped R2 storage and
|
|
2087
|
+
replaced with a small `asset_ref` reference in the persisted JSONB, then
|
|
2088
|
+
rehydrated back to bytes at model-execution time. Internal assets are resolved
|
|
2089
|
+
**server-side only**, gated on the authenticated caller's tenant — they are never
|
|
2090
|
+
exposed via a public or signed URL.
|
|
2091
|
+
- `AssetStorageService` gains a `visibility: 'internal'` mode and a
|
|
2092
|
+
tenant-checked `getInternal()` getter; `assets.public_url` is now nullable.
|
|
2093
|
+
- New authenticated, tenant-scoped serve route `GET /v1/internal-assets/{assetId}`.
|
|
2094
|
+
- Offload-on-write is gated behind the `enable-asset-offload` flag (off in
|
|
2095
|
+
production by default). Rehydration is always-on and a no-op when no references
|
|
2096
|
+
are present, so toggling the flag never strands data.
|
|
2097
|
+
- Shared offload/rehydrate primitives live in `@runtypelabs/model-execution`
|
|
2098
|
+
(`offloadInlineMediaInMessages`, `rehydrateAssetReferences`,
|
|
2099
|
+
`AssetReferenceContent`) and are wired into both the api and runtime prompt
|
|
2100
|
+
executors from the single shared implementation (no api↔runtime drift).
|
|
2101
|
+
|
|
2102
|
+
## 4.13.0
|
|
2103
|
+
|
|
2104
|
+
### Minor Changes
|
|
2105
|
+
|
|
2106
|
+
- 04db6c7: Generalize config-as-code name-based resolution from tools to **agents and
|
|
2107
|
+
flows**: reference a saved agent or flow from a portable `defineAgent` /
|
|
2108
|
+
`defineFlow` definition by name with the new `agent:<name>` and `flow:<name>`
|
|
2109
|
+
forms — the agent/flow analogue of the shipped `tool:<name>`.
|
|
2110
|
+
|
|
2111
|
+
Three reference sites are covered:
|
|
2112
|
+
- an `execute-agent` flow step's `config.agentId` → `agent:<name>`
|
|
2113
|
+
- a saved subagent runtime tool's `config.agentId` → `agent:<name>`
|
|
2114
|
+
- a flow-as-tool runtime tool's `config.flowId` → `flow:<name>`
|
|
2115
|
+
|
|
2116
|
+
The name is canonical (hashed and persisted), and resolves to a concrete row at
|
|
2117
|
+
execute time, every dispatch — ownership-scoped, oldest-wins on duplicate names —
|
|
2118
|
+
so the same definition converges to the same content hash across environments
|
|
2119
|
+
even though the underlying agent/flow ids differ. All three surfaces already
|
|
2120
|
+
loaded the **live row** by id at execution (no published-version indirection), so
|
|
2121
|
+
name resolution loads the same live row.
|
|
2122
|
+
|
|
2123
|
+
Highlights:
|
|
2124
|
+
- Reserved `agent:` / `flow:` reference prefixes with
|
|
2125
|
+
`isNamedAgentRef` / `parseNamedAgentRef` / `formatNamedAgentRef` (and the flow
|
|
2126
|
+
trio) in `@runtypelabs/shared`. They coexist with the `{{flow:X}}` template
|
|
2127
|
+
**variable** namespace, which is a separate grammar (only meaningful inside
|
|
2128
|
+
`{{…}}`).
|
|
2129
|
+
- **Ensure/validation time** (including `dryRun`): an `agent:<name>` / `flow:<name>`
|
|
2130
|
+
that resolves to zero rows (missing) or more than one (ambiguous) is a hard
|
|
2131
|
+
`400` per reference path (`AGENT_NOT_FOUND` / `AGENT_NAME_AMBIGUOUS` /
|
|
2132
|
+
`FLOW_NOT_FOUND` / `FLOW_NAME_AMBIGUOUS`) via the flow-validator account-scoped
|
|
2133
|
+
pass.
|
|
2134
|
+
- **Execution time**: names resolve oldest-wins with a structured warn for
|
|
2135
|
+
missing/ambiguous; a turn is never failed over reference quality. Wired into the
|
|
2136
|
+
execute-agent step handler, subagent dispatch, and the flow-as-tool executor.
|
|
2137
|
+
- Raw `agent_…` / `flow_…` ids stay rejected on the ensure surface. This also
|
|
2138
|
+
**closes a pre-existing portability hole**: the agent and flow ensure scans now
|
|
2139
|
+
cover saved-subagent / flow-as-tool runtime-tool refs and an `execute-agent`
|
|
2140
|
+
step's top-level `config.agentId`, none of which were scanned before.
|
|
2141
|
+
- `pull` reverse-maps raw `agent_…` / `flow_…` references to their name forms so a
|
|
2142
|
+
dashboard-built definition round-trips; references that can't safely round-trip
|
|
2143
|
+
(deleted, or name-shadowed by an older same-named row) are left as raw ids and
|
|
2144
|
+
reported in the existing `warnings` field.
|
|
2145
|
+
|
|
2146
|
+
Note: agents and flows have no "active/callable" gate (unlike tools), so
|
|
2147
|
+
resolution is over all rows in scope and ambiguity is simply "≥2 rows share the
|
|
2148
|
+
name". See `docs/features/planning/2026-06-13-ensure-name-based-agent-flow-resolution.md`.
|
|
2149
|
+
|
|
2150
|
+
- 7ea7ece: Layer 3 of the variable-namespace re-architecture: a prompt dispatched to the model with a surviving `{{...}}` token is now an observable signal, not just a buried server log.
|
|
2151
|
+
- A new optional `unresolvedVariables: string[]` field on the `step_complete` SSE event (canonical Zod in `sse-event-schemas.ts`, flowing to the OpenAPI spec + generated TS/Python SDK types). Prompt steps populate it (and telemetry) when template substitution left any reference unresolved — sourced from the engine's `missingVariables`, which already includes unknown-namespace tokens. Non-fatal: the step still runs.
|
|
2152
|
+
- The api prompt-executor's previously warn-only "missing variables" path now threads the unresolved names onto the wire + telemetry, and logs a clearer message.
|
|
2153
|
+
- The portable runtime engine emits the same field on its own `step_complete` (threaded through `PromptStepResult` → `StepLifecycleComplete` → the flow-stream emitter) and warns to the console — api↔runtime parity, not just the api.
|
|
2154
|
+
|
|
2155
|
+
This is the execute-time catch-all that surfaces the original `{{flow:topic}}` foot-gun on the first dispatch regardless of static coverage.
|
|
2156
|
+
|
|
2157
|
+
### Patch Changes
|
|
2158
|
+
|
|
2159
|
+
- 3a162cc: Marathon ledger unification (increment 3): gate provider-native compaction prediction on the masked send view.
|
|
2160
|
+
|
|
2161
|
+
`buildNativeCompactionEvent` previously decided whether to announce a provider-native (Anthropic-side) compaction by comparing `breakdown.estimatedInputTokens` — the **true pre-mask** conversation size — against the auto-compact threshold. But provider-native compaction is performed by Anthropic, which only ever sees the **masked send view** (hot-tail offload has already shrunk old tool outputs before the request leaves the SDK). Gating on the larger pre-mask size made the SDK emit `start`/`complete` compaction lifecycle events for compactions the provider never performed.
|
|
2162
|
+
|
|
2163
|
+
The predictor now gates on `breakdown.sendEstimatedInputTokens ?? breakdown.estimatedInputTokens` (the send view's size, falling back to the true size when no masking reduction happened — the two are equal then). The event payload still reports the true pre-mask numbers (`estimatedTokens` / `beforeTokens`) for honest accounting display.
|
|
2164
|
+
|
|
2165
|
+
SDK-only; no wire-contract or behavior change for `summary_fallback` compaction. (Anchoring the provider-native summary in the durable ledger and fixing the latent compaction-summary leak in `stream-helpers.ts` are deferred to a follow-up increment — see the planning doc.)
|
|
2166
|
+
|
|
2167
|
+
- ee6f248: Harden record metadata key normalization (P0.6). Keys that normalize to a reserved prototype name (`constructor`, `prototype`, `__proto__`) or to an empty string are now rejected at every write seam (create, update, bulk-edit, CSV import) with a `METADATA_RESERVED_KEY` 400 (CSV reports the offending row and continues). Collision renames that were previously silent are now surfaced as `warnings: [{ code: 'KEY_RENAMED', from, to }]` on the create/update/bulk-edit/CSV responses. Also fixes a latent false-collision bug where the collision check traversed `Object.prototype` (now built on a null-prototype accumulator). The SDK's `records.create()` / `records.update()` now return `RecordWriteResponse` and `BulkEditResponse` carries an optional `warnings` field so typed consumers can read the rename notices.
|
|
2168
|
+
|
|
2169
|
+
## 4.12.0
|
|
2170
|
+
|
|
2171
|
+
### Minor Changes
|
|
2172
|
+
|
|
2173
|
+
- d895f91: Add name-based tool resolution to the config-as-code (`ensure`) surface:
|
|
2174
|
+
reference a saved tool from a portable `defineAgent` / `defineFlow` definition by
|
|
2175
|
+
its name with the new `tool:<name>` form (e.g.
|
|
2176
|
+
`toolIds: ['builtin:web-search', 'tool:My Scraper']`).
|
|
2177
|
+
|
|
2178
|
+
The name is canonical: it is what gets hashed and persisted, and it resolves to a
|
|
2179
|
+
concrete tool row at execute time, every dispatch (ownership-scoped, oldest-wins
|
|
2180
|
+
on duplicate names) — so the same definition converges to the same content hash
|
|
2181
|
+
across environments even though the underlying tool ids differ. Raw `tool_…` ids
|
|
2182
|
+
stay rejected on the ensure surface (they are environment-bound); the rejection
|
|
2183
|
+
message now points at `tool:<name>`.
|
|
2184
|
+
|
|
2185
|
+
Highlights:
|
|
2186
|
+
- `tool:` is a reserved tool-ref prefix; `separateToolIds` gains a `namedToolIds`
|
|
2187
|
+
bucket. Helpers `isNamedToolRef` / `parseNamedToolRef` / `formatNamedToolRef`
|
|
2188
|
+
live in `@runtypelabs/shared`.
|
|
2189
|
+
- **Ensure/validation time** (including `dryRun`): a `tool:<name>` that resolves
|
|
2190
|
+
to zero tools (missing) or more than one (ambiguous) is a hard `400` per
|
|
2191
|
+
reference path — the breakage surfaces at converge time in CI, not as a silent
|
|
2192
|
+
dispatch-time drop. Agent path in `agent-ensure-service`; flow path via the
|
|
2193
|
+
flow-validator account-scoped pass (which also fixes a pre-existing gap: the
|
|
2194
|
+
flow ensure scan now covers a `tool-call` step's top-level `config.toolId`).
|
|
2195
|
+
- **Execution time**: names resolve oldest-wins with a structured warn for
|
|
2196
|
+
missing/ambiguous; a turn is never failed over reference quality. Wired into
|
|
2197
|
+
the prompt-executor, code-step tool resolver, and tool-call executor.
|
|
2198
|
+
- `requiresApproval` accepts the `tool:<name>` form (matching the saved tool's
|
|
2199
|
+
name; the decision is still made on tool name + parameters only).
|
|
2200
|
+
- `pull` reverse-maps raw `tool_…` references to `tool:<name>` so a
|
|
2201
|
+
dashboard-built definition round-trips; references that can't safely round-trip
|
|
2202
|
+
(deleted, or name-shadowed by an older same-named tool) are left as raw ids and
|
|
2203
|
+
reported in a new `warnings` field on the pull response.
|
|
2204
|
+
|
|
2205
|
+
Note: named resolution is ownership-scoped (org-shared via `ownershipFilter`),
|
|
2206
|
+
intentionally broader than the legacy by-id custom-tool load in the
|
|
2207
|
+
prompt-executor (`eq(userId)`) — see the planning doc's open question #3. The
|
|
2208
|
+
by-id load's narrower scoping is left unchanged here to avoid a broad
|
|
2209
|
+
behavior change.
|
|
2210
|
+
|
|
2211
|
+
- 2392c5e: Hide the Agents Subdomains surface (`/v1/agents-subdomains`) from the published
|
|
2212
|
+
schema surface until GA. The routes stay mounted and runtime-gated by the
|
|
2213
|
+
`enable-agents-subdomains` Flagship flag, but they are now excluded from the
|
|
2214
|
+
public OpenAPI spec, the generated TypeScript SDK types, the Python SDK, and
|
|
2215
|
+
Fern docs.
|
|
2216
|
+
|
|
2217
|
+
This adds a build-time, declarative hidden-surface list
|
|
2218
|
+
(`HIDDEN_PUBLIC_PATH_PREFIXES` in `apps/api/src/lib/openapi/registry.ts`) that
|
|
2219
|
+
the OpenAPI generator applies only to the PUBLIC document (the same code path as
|
|
2220
|
+
`INTERNAL_TAG`, but keyed by path prefix so a whole feature can be hidden with
|
|
2221
|
+
one entry). The internal/admin spec still records the surface. Because the
|
|
2222
|
+
generator is deterministic and CI-drift-gated, hiding cannot depend on the
|
|
2223
|
+
runtime flag; this is a static exclusion that leaves runtime behavior unchanged.
|
|
2224
|
+
|
|
2225
|
+
Two customer-facing surfaces that the build-time spec exclusion can't reach are
|
|
2226
|
+
also gated at runtime by the same flag:
|
|
2227
|
+
- `GET /v1/api-keys/options` (which feeds the dashboard API-key scope picker) now
|
|
2228
|
+
omits the `AGENTS_SUBDOMAINS:*` / `:READ` / `:WRITE` scopes when the flag is off
|
|
2229
|
+
for the caller, so the feature isn't advertised there.
|
|
2230
|
+
- OAuth-minted MCP keys no longer include `AGENTS_SUBDOMAINS:*` until GA.
|
|
2231
|
+
|
|
2232
|
+
To un-hide the surface when it's ready, remove its entry from
|
|
2233
|
+
`HIDDEN_PUBLIC_PATH_PREFIXES`, regenerate the spec + SDKs, re-add
|
|
2234
|
+
`AGENTS_SUBDOMAINS:*` to `MCP_OAUTH_PERMISSIONS`, and drop the
|
|
2235
|
+
`AGENTS_SUBDOMAINS` entry from `KNOWN_EXCLUDED` in
|
|
2236
|
+
`tests/mcp-oauth-minted-scope.test.ts`. (The `/v1/api-keys/options` picker
|
|
2237
|
+
un-hides automatically once the flag is on.)
|
|
2238
|
+
|
|
2239
|
+
- 4cfef88: Marathon ledger unification (increment 1): route SDK hot-tail tool-output offloads through one artifact store.
|
|
2240
|
+
- SDK: new `offloadRecorder` option on `RunTaskOptions` (and exported `RunTaskOffloadRecorder` type). When supplied, `offloadToolResult` delegates persistence to the recorder and splices its reference into the send view instead of writing to the unledgered `.runtype/marathons/<slug>/tool-outputs/` fallback. The SDK still owns the offload decision (its inline threshold); the recorder owns storage. Declining (returning `undefined`/throwing) falls back to the built-in store, so non-marathon and browser consumers are unchanged.
|
|
2241
|
+
- CLI: supplies a recorder backed by the existing content-addressed ledger store (`offloadToolOutput`), so the 500–100k char band becomes a first-class ledger citizen (content-addressed `art_<sha256>`, hashed, `read_offloaded_output`-resolvable, deduped, on-timeline) instead of a separate unledgered store.
|
|
2242
|
+
- CLI: fix the per-offload `loadTreeLog` reload — `recordOffloadedArtifact` now appends through a shared head accessor (`getOrLoadTreeLogSync`) so artifact entries land on-chain at the live head instead of as sibling stubs off a stale, disk-reloaded head, and offload cost is O(1) rather than O(tree-log size).
|
|
2243
|
+
|
|
2244
|
+
- 04dc52c: Plan-tiered preview TTL and preview expiry extension.
|
|
2245
|
+
|
|
2246
|
+
`publish_page` preview pages now expire based on the account's plan instead of a uniform 7 days: the new `htmlPreviewTtlSeconds` billing entitlement (Schematic feature "HTML Preview TTL Seconds") is resolved at publish time, with -1 meaning permanent (no expiry) and a fail-closed 7-day default when unset or unreachable. The TTL is snapshotted at upload, so plan changes never retroactively expire existing URLs.
|
|
2247
|
+
|
|
2248
|
+
New `POST /v1/assets/:assetId/extend` endpoint re-ups a preview page's expiry to the caller's current plan TTL at the same URL — including previews that have already expired (expired pages keep their stored content; only serving is blocked). Exposed through the Runtype MCP server as the `extend_asset_expiry` tool, gated by the new `ASSETS:WRITE` API-key scope.
|
|
2249
|
+
|
|
2250
|
+
Callers can also choose a custom lifetime: `publish_page` accepts an optional `expiresInSeconds` parameter and the extend endpoint an optional `{ expiresInSeconds }` body (`expires_in_seconds` on the MCP tool). The plan TTL is a hard ceiling — shorter lifetimes are honored, longer requests are clamped, and permanence can never be requested (only granted by a permanent-plan entitlement).
|
|
2251
|
+
|
|
2252
|
+
- 6f6dd80: Extend config-as-code `ensure`/`pull` to the **tools** entity. Adds `POST /v1/tools/ensure` (idempotent, hash-first create-or-update by name + ownership) and `GET /v1/tools/pull` (round-trippable canonical definition + provenance), built on the shared `ensure-protocol` decision core used by agents and flows.
|
|
2253
|
+
- **SDK**: `defineTool`, `Runtype.tools.ensure(def, opts)`, and `Runtype.tools.pull(name)` with `expectNoChanges` drift gating and `onConflict` handling. The inlined content hash is parity-pinned against `@runtypelabs/shared` via a shared fixture corpus.
|
|
2254
|
+
- **Shared**: `computeToolContentHash` / `normalizeToolDefinition` over `{ toolType, description, parametersSchema, config }` (name is identity, excluded from the hash).
|
|
2255
|
+
- **Provenance**: `ensure` writes stamp `lastModifiedSource: 'sdk'` on the tool. Both dashboards render a "Managed in code" badge and a save-warning dialog when editing a code-managed tool.
|
|
2256
|
+
|
|
2257
|
+
Tools have no version snapshots, so (unlike agents/flows) there is no `release: 'publish'` option and no `versionId` in the response.
|
|
2258
|
+
|
|
2259
|
+
### Patch Changes
|
|
2260
|
+
|
|
2261
|
+
- cf9eae0: Add the Runtype Apps index page to the dashboard (SPA): a Tier-1 list view to create apps, manage details (name, description, visibility), suspend/resume, delete, and browse version history with activate/rollback. The nav entry and route are gated behind the `enable-runtype-apps` flag via a new `features.enableRuntypeApps` field on `GET /v1/users/profile` (fail-closed in production), so a flag-off account never sees Apps. Regenerated OpenAPI spec and SDK types follow the new profile field.
|
|
2262
|
+
- 6c475fe: Close record-tool surface-parity gaps (P0.7): expose already-existing `/v1/records` API capabilities on the client surfaces that lacked them.
|
|
2263
|
+
- MCP: add the `delete_record` tool (input schema, schema-map registration, destructive tool definition, execution handler, and `deleteRecord` on the `RuntypeClient` interface + both implementers).
|
|
2264
|
+
- Code-Mode MCP: add `deleteRecord(id)` → `DELETE /v1/records/:id` to the executor and code-spec overlay.
|
|
2265
|
+
- SDK: add `records.getStepResults(id, params?)` → `GET /v1/records/:id/step-results` and `records.getCosts(id)` → `GET /v1/records/:id/costs` to `RecordsEndpoint`.
|
|
2266
|
+
- CLI: add `records results <id>` and `records costs <id>` subcommands routed through the SDK.
|
|
2267
|
+
|
|
2268
|
+
## 4.11.0
|
|
2269
|
+
|
|
2270
|
+
### Minor Changes
|
|
2271
|
+
|
|
2272
|
+
- e7a7c22: Default marathon workflow adopts the stall-policy and write-rule primitives (Phase 2). The default workflow now ships `stallPolicy: { nudgeAfter: 1, escalateModelAfter: 2, stopAfter: 3 }`, so a session that ends without any tool calls gets a corrective nudge on the very next session, a second actionless session signals model escalation (consumed when a fallback model is configured), and the run stalls on the third as before. The research and planning guards become trace-aware: once the plan file is written, product writes unlock in the same session instead of being blocked until the phase advances between sessions, confined by the same write-target rules execution enforces (modify allowlist, creation `outputRoot`), now shared via one helper. Creation tasks are also told about the `outputRoot` confinement in the planning instructions and execution tool guidance instead of discovering it through blocked writes.
|
|
2273
|
+
- e7a7c22: Add workflow stall policy and richer marathon playbooks. WorkflowDefinition gains an optional `stallPolicy` (`nudgeAfter` / `escalateModelAfter` / `stopAfter`) keyed on the consecutive-empty-sessions counter, so narration-only sessions trigger a recovery nudge, a model-escalation signal (`state.stallEscalationRequested`), or a configurable stall threshold instead of silently dying after 3 empty sessions. Playbooks can now declare per-milestone `recovery` messages (triggered on the same stall counter), `transitionSummary` strings, and a top-level `stallPolicy`; policy blocks also compile into model-facing tool guidance so enforced constraints (write globs, outputRoot, plan-first) are stated to the model instead of silently blocking it. The CLI consumes the escalation signal by restarting the marathon on the milestone's next `fallbackModels` entry, and surfaces playbook authoring warnings (e.g. no milestone sets `canAcceptCompletion: true`) at load time. Default (non-playbook) marathon behavior is unchanged.
|
|
2274
|
+
- e7a7c22: TypeScript playbooks. Marathon playbooks can now be `.ts`/`.mts` modules, loaded at runtime via jiti (no Node version or transpile-step requirements) from the same search paths as YAML/JSON. Every workflow config behavior slot (instructions, tool guidance, completion criteria, recovery, transition summaries, intercepts, force-end-turn, accept-completion, classify/bootstrap/candidate-block) now accepts a plain function in addition to inline data and hook references, so TypeScript playbooks express custom logic directly without registry ceremony; `definePlaybook(...)` is exported from the SDK as optional type-inference sugar. A module playbook's default export is either a config object or a factory receiving the injected `{ registerWorkflowHook }` API for named-hook registration. Load failures, missing default exports, and non-config exports fail with actionable errors naming the playbook path.
|
|
2275
|
+
- e7a7c22: Workflow hook registry and the default marathon workflow as data (Phase 3). The SDK gains a named hook registry (`registerWorkflowHook` with a reserved `builtin:` namespace, slot-kind validation, and actionable load-time errors) and an environment-free `compileWorkflowConfig` that turns declarative workflow configs into `WorkflowDefinition`s, with glob matching injected via deps. The default workflow's behaviors (classification, bootstrap discovery, per-phase instructions/guards/recovery/completion heuristics) are now registered as `builtin:*` hooks and composed by an exported `defaultWorkflowConfig` compiled through the same function — so playbooks and the default share one compile path and a user playbook can reuse or override any slice of the default by hook name. The CLI playbook loader delegates compilation to the SDK and adds: hook references in every behavior slot (`instructions: builtin:research-instructions`, `completionCriteria: { type: acme:my-completion }`), per-milestone `intercept`/`forceEndTurn` slots, and a `plugins:` field that loads JS modules (confined to the playbook's directory) which register custom hooks via an injected `registerWorkflowHook` API. `loadPlaybook` is now async. Compiled output for the default workflow is behavior-identical (pinned by the existing workflow test suite).
|
|
2276
|
+
|
|
2277
|
+
### Patch Changes
|
|
2278
|
+
|
|
2279
|
+
- 713e743: Add the `chrome_extension` product surface type: a downloadable Manifest V3 Chrome extension that embeds the product's agent (vendored Persona widget) in the browser side panel with packaged browser tools (read page, fill forms, navigate tabs) executed through the native WebMCP client-tool loop. The dashboard assembles the ZIP client-side, pins a stable extension ID via the manifest `key` field, and converges the surface's client token allowlist and `behavior.webmcp` policy on download. The WebMCP surface-policy gate now admits `chrome_extension` behaviors alongside `chat`.
|
|
2280
|
+
|
|
2281
|
+
## 4.10.0
|
|
2282
|
+
|
|
2283
|
+
### Minor Changes
|
|
2284
|
+
|
|
2285
|
+
- ad2dd30: Agent config-as-code: `POST /v1/agents/ensure` (non-executing, hash-first idempotent converge with dryRun planning, onConflict/release policies, and 409/422 conflict detection), `GET /v1/agents/pull` (canonical definition + provenance), SDK `defineAgent` + `client.agents.ensure/pull`, shared `computeAgentContentHash` canonical serializer, and `configHash`/`lastModifiedSource` provenance columns on agents (all non-ensure write paths now stamp their source).
|
|
2286
|
+
- 90a4707: Enrich `GET /v1/skill-proposals` listings with the underlying skill + proposed
|
|
2287
|
+
version manifest. Each item now carries two additive, optional fields —
|
|
2288
|
+
`skill: { id, name, description, status } | null` and
|
|
2289
|
+
`version: { id, versionNumber, manifest: { frontmatter, runtype, body } } | null`
|
|
2290
|
+
— so the review queue can show reviewers WHAT they are approving. A skill body is
|
|
2291
|
+
instructions injected into another agent's context, and the `runtype` block
|
|
2292
|
+
carries the proposed capability bindings (flows, agents, tools, MCP servers,
|
|
2293
|
+
inline tools) — the most security-relevant part of an approval decision — so
|
|
2294
|
+
blind approval defeated review-by-default governance. Both fields are `null` only when the underlying
|
|
2295
|
+
skill/version row was deleted out from under the proposal (the listing degrades
|
|
2296
|
+
gracefully via a LEFT JOIN rather than 500-ing), and are entirely absent on
|
|
2297
|
+
older API servers — consumers must tolerate them being `undefined`. The SDK's
|
|
2298
|
+
`SkillProposal` interface gains the matching optional `skill?` / `version?`
|
|
2299
|
+
fields.
|
|
2300
|
+
- 7027149: Flow config-as-code: `POST /v1/flows/ensure` (non-executing, hash-first idempotent converge with dryRun planning, onConflict/release policies, and 409/422 conflict detection) and `GET /v1/flows/pull` (canonical definition + provenance), built on a generic ensure decision core shared with the agent ensure service. SDK gains `defineFlow` + `client.flows.ensure/pull`; `flows.upsert()` is unchanged and documented as the execute-flavored sibling (save-and-run) of the deploy-time ensure verb. The dashboards' flow integration-code generators add an "Ensure Flow (config-as-code)" example (defineFlow + flows.ensure snippet and the `/v1/flows/ensure` HTTP request) alongside the existing upsert example, whose copy now distinguishes save-and-run from converge. Adds the `flow_ensure_locks` scoped-name serialization table and a flow content-hash parity fixture corpus shared by the SDK and `@runtypelabs/shared`.
|
|
2301
|
+
- f07ceb8: Add marathon context-ledger artifact plumbing, derive tool-result context views without mutating saved history, and enable session context recall by default.
|
|
2302
|
+
- 7d398a2: Mid-session hard abort for marathon (Esc Esc). The SDK's `runTask` and `executeWithLocalTools` accept an `abortSignal` that cancels the in-flight SSE stream and ends the run gracefully (cost and tokens preserved, state persisted, status `paused`/resumable). In the marathon TUI, pressing Esc twice while the agent works interrupts the turn, restores any queued steering messages and composer draft into the checkpoint input, and lands at a "stopped" checkpoint where Enter exits or new instructions continue the task.
|
|
2303
|
+
- 92c6ae3: Marathon context ledger: window-base compaction and persistence fixes.
|
|
2304
|
+
|
|
2305
|
+
SDK: compaction now records a send-window base (`RunTaskState.contextWindowBaseIndex`). After a compaction, sessions send `[stored summary, messages since base, continuation]` and only re-compact when that window itself re-crosses the threshold — previously every post-threshold session re-summarized the whole task and dropped all recent raw turns from the send. The persist path appends exactly the new continuation message per session, fixing duplicated (and fidelity-degraded) history once replay trimming made the send view shorter than the source. Send-view derivation no longer deep-clones the full history per send, and hot-tail offload skips rewriting files that already exist. Offload reference markers now live in a shared `offload-markers` module with locale-pinned size formatting.
|
|
2306
|
+
|
|
2307
|
+
CLI: tree-log delta checkpoints no longer re-embed compaction summary text on every save (summary ledger entries are the durable copy; materialization and `/tree` navigation rebuild them from the chain). Repeated offloads of identical output record one artifact entry. `read_offloaded_output` verifies content against the recorded sha256 and warns on mismatch. Tools rebuilt after a `/tools` or sandbox checkpoint change keep their offload wrapping. The unused artifact GC stub (which would have deleted still-readable legacy offload files) was removed.
|
|
2308
|
+
|
|
2309
|
+
- 518018a: Replace Helicone with [models.dev](https://models.dev) as the build-time source of model metadata. The auto-generated catalog now carries real `contextLength`, `maxOutputTokens`, modalities, capability flags, knowledge cutoff, release date, and cached-token pricing — replacing the previous name-pattern estimates. Vercel AI Gateway stays authoritative for pricing.
|
|
2310
|
+
|
|
2311
|
+
New optional `ModelConfig` fields (all surfaced via `@runtypelabs/shared`): `knowledgeCutoff`, `releaseDate`, `inputModalities`, `outputModalities`, `supportsVision`, `supportsToolUse`, `supportsReasoning`, `inputCacheReadCostPer1kTokens`, `inputCacheWriteCostPer1kTokens`. These populate only on the verbose lazy-loaded catalog (`apps/api/src/lib/model-catalog/generated-metadata.ts`, a separate Wrangler module); the hot-path `generated-configs.ts` tuple format is unchanged so the main Workers bundle does not grow.
|
|
2312
|
+
|
|
2313
|
+
The `pnpm update-models` script also gains a disappearance classifier that aborts when a `DEFAULT_MODELS_FOR_NEW_ACCOUNTS` entry vanishes from upstream without being in `RETIRED_MODELS` / `DEPRECATED_MODELS`, preventing silent breakage of new-account onboarding.
|
|
2314
|
+
|
|
2315
|
+
Tag vocabulary is normalized on `'tool-use'` for tool-calling capability (matching Vercel AI Gateway passthrough tags and the model-advisory validator), and the dashboard "tools" capability filter now matches it. The `'playground'` tag (previously emitted from Helicone's `show_in_playground`) is no longer generated — no consumer read it.
|
|
2316
|
+
|
|
2317
|
+
- 6ecce93: Runtype Apps increment 1, PR 3: agent + developer deploy surfaces. Adds six MCP tools (`create_app`, `deploy_app_version`, `activate_app_version`, `list_apps`, `get_app`, `delete_app`) on both MCP servers (standard + Code Mode `runtype.*` methods), an SDK `client.apps` endpoint (incl. raw-zip `uploadVersion` and JSON `uploadVersionFiles`), a `runtype apps` CLI command family (`create`, `deploy <dir>`, `list`, `versions`, `activate`, `delete`), a JSON `{ files, filesBase64 }` upload variant on `POST /v1/apps/:id/versions` (the API zips server-side for surfaces that cannot stream binary bodies), and the `build-runtype-app` agent skill.
|
|
2318
|
+
- c7bad37: Cursor pagination for the Agent Skills list. `GET /v1/skills` now accepts `cursor`, `limit`, `direction`, and `includeCount` query params and returns the standard `pagination` envelope alongside `data` (additive; the status filter still works with cursors). The TypeScript SDK adds `skills.listPage()` for the full `{ data, pagination }` envelope while `skills.list()` keeps returning the plain array, and the dashboard Skills tab pages through skills with the standard cursor pagination footer.
|
|
2319
|
+
- 6e53e7f: Use typed model capability flags instead of tag/name heuristics. `GET /v1/model-configs/grouped` now returns `supportsVision`, `supportsToolUse`, and `supportsReasoning` per group (derived from the typed ModelConfig flags populated by the models.dev pipeline, with capability tags as fallback for tag-only sources, OR-merged across a group's provider entries). The dashboard add-model capability filters and the settings page tools/reasoning filters read these flags (tags remain a fallback), replacing the hand-coded provider/model-name heuristics. The model-advisory `MODEL_CAPABILITY_MISMATCH` checks also accept the typed flags.
|
|
2320
|
+
|
|
2321
|
+
### Patch Changes
|
|
2322
|
+
|
|
2323
|
+
- df3a66d: Dashboard provenance guardrail for config-as-code agents: agents whose live config was last converged from a code definition (`lastModifiedSource: 'sdk'`, stamped only by `POST /v1/agents/ensure`) now show a "Managed in code" badge in the agent editor and edit slide-over, and saving dashboard edits to such an agent asks for confirmation first (the next deploy may overwrite the edit). Also documents the existing `lastModifiedSource` and `configHash` response fields in the agent detail/mutation OpenAPI schemas (they were already on the wire via the row spread).
|
|
2324
|
+
- 2bb37c4: Skill proposal review enrichment: `GET /v1/skill-proposals` now resolves the manifest's capability IDs (flows, agents, tools) to tenant-scoped names via `resolvedCapabilityNames`, and resolves the proposing execution to the authoring agent via `proposingAgent`. IDs that do not resolve inside the reviewer's account are surfaced with a null name as a review signal instead of being dropped. The dashboard proposals queue renders the named capability grants inline (with a "Not found in this account" flag for unresolved IDs) and shows the proposing agent's name in place of the raw execution typeid.
|
|
2325
|
+
- 4e3999f: Dashboard SPA build-time cuts and hygiene: skip the duplicate shared build during Workers Builds installs (SKIP_PREPARE=1), env-gate tsup .d.ts generation (TSUP_SKIP_DTS=1, set by the SPA build:cf scripts), disable Vite's gzip-size report pass, switch shiki to the fine-grained core bundle with the JavaScript regex engine and an explicit grammar set in both dashboards (~274 fewer emitted chunks, no oniguruma wasm), restore the SPA ESLint baseline to the legacy dashboard's effective rule set, wire up the SPA vitest suite, and make the SDK's stream-utils import style consistent to silence Rollup's mixed static/dynamic import warning.
|
|
2326
|
+
|
|
2327
|
+
## 4.9.0
|
|
2328
|
+
|
|
2329
|
+
### Minor Changes
|
|
2330
|
+
|
|
2331
|
+
- 96ec88a: Mid-run steering queue for marathon (Pi-style): press Enter while the agent is working to open a composer and queue a steering message. Queued steers end the in-flight session at the next local-tool pause and are delivered at the start of the next session; Tab toggles delivery to "after all work" (follow-up). `runTask` gains additive `getQueuedUserMessages` / `hasQueuedUserMessages` options.
|
|
2332
|
+
|
|
2333
|
+
## 4.8.1
|
|
2334
|
+
|
|
2335
|
+
### Patch Changes
|
|
2336
|
+
|
|
2337
|
+
- 15b4a2f: Add a native Granola integration. Connect Granola from Settings > Integrations by pasting a `grn_` API key (verified live against Granola's public API before storage). Agents, flows, and transform-data code steps gain five read-only `builtin:granola:*` tools (list/get meeting notes, transcript, folders, and bounded client-side search). Ships a "New Granola Meeting Notes" flow template that pairs with a schedule to poll for new or updated notes using the `{{_schedule.lastRunAt}}` cursor with overlap. SDK types regenerated for the new `/v1/integrations/granola/install` endpoint.
|
|
2338
|
+
|
|
2339
|
+
Granola credential resolution is explicit-only: each `builtin:granola:*` tool instance must name its credential in `toolConfigs[toolId]` (`GranolaToolConfig`) as either `apiKey` (a `{{secret:NAME}}` reference to a secret holding a `grn_` API key, enabling per-tenant keys; literal keys are rejected) or `integrationId` (pin one connected workspace, the explicit way to use the account's connected Granola). There is no silent fallback to the org's workspace, so adding a Granola tool can never unintentionally expose the whole org's meeting corpus.
|
|
2340
|
+
|
|
2341
|
+
- 698edda: Regenerated OpenAPI types: the GET /v1/logs/stats response schema now documents the existing cachedAt field (string when served from the 30s stats cache, null for fresh responses).
|
|
2342
|
+
|
|
2343
|
+
## 4.8.0
|
|
2344
|
+
|
|
2345
|
+
### Minor Changes
|
|
2346
|
+
|
|
2347
|
+
- 8aeda2c: Add internal builder docs to the FPO/template model
|
|
2348
|
+
|
|
2349
|
+
Templates and products can now carry non-user-facing builder documentation that
|
|
2350
|
+
captures intent: why a template is shaped the way it is, design choices, best
|
|
2351
|
+
practices, and implementation notes.
|
|
2352
|
+
- New shared `internalDocsSchema` (`content` markdown body, `tags` for indexing,
|
|
2353
|
+
and a forward-compatible `resources` array seeding a broader template
|
|
2354
|
+
knowledge/resource system). Added to the FPO `product` object and the
|
|
2355
|
+
FPO-template top level.
|
|
2356
|
+
- Persisted on `products.spec.internalDocs` and accepted by the products
|
|
2357
|
+
create/update routes (`null` clears it).
|
|
2358
|
+
- Editable from the product edit panel in the architecture viewer. The field is
|
|
2359
|
+
intentionally excluded from the agent-facing public type snapshots, so it is
|
|
2360
|
+
not exposed in end-user surfaces by default.
|
|
2361
|
+
|
|
2362
|
+
### Patch Changes
|
|
2363
|
+
|
|
2364
|
+
- 982da6c: Agent-supplied approval reasons. When a tool call requires approval, the engine now injects a reserved optional `_approvalReason` parameter into the model-visible tool schema so the agent can justify the call. The value is stripped before the tool executes and surfaced to the approver as `reason` on `agent_approval_start` / `step_await` events, in Slack/Telegram approval prompts, and in the dashboard approval card. Enabled by default for approval-gated tools; opt out with `tools.approval.requestReason: false`. Tools that already define `_approvalReason` in their own schema are left untouched.
|
|
2365
|
+
|
|
2366
|
+
## 4.7.1
|
|
2367
|
+
|
|
2368
|
+
### Patch Changes
|
|
2369
|
+
|
|
2370
|
+
- 2c12987: Close six SSE contract-field gaps surfaced by a new drift audit (same class as `step_complete.stopReason`): fields emitted on the public wire (and read by consumers) that the canonical SSE schema omitted, so the public OpenAPI components and generated SDK types under-represented the stream. All additions are optional, so existing frames still validate.
|
|
2371
|
+
- `step_start.outputVariable` — the step output-variable name the dashboard reads to unwrap the `{ [outputVariable]: <rendered> }` envelope at render time.
|
|
2372
|
+
- `flow_complete.flowName` — emitted by the API raw-write paths; now declared for wire-superset parity with `flow_start`.
|
|
2373
|
+
- `agent_error` / `agent_reflection` / `agent_skill_loaded` / `agent_skill_proposed` `.timestamp` — the runtime `AgentEventEmitter` injects an ISO timestamp on these events; reconciled into the shared schema per the runtime↔shared wire-contract rule.
|
|
2374
|
+
|
|
2375
|
+
Regenerates the public/internal OpenAPI spec and the generated TS + Python SDK types. Adds a `contract-field-drift-hunter` agent that audits the API surface for this drift class.
|
|
2376
|
+
|
|
2377
|
+
## 4.7.0
|
|
2378
|
+
|
|
2379
|
+
### Minor Changes
|
|
2380
|
+
|
|
2381
|
+
- 5d3eada: Harden flows Dev Mode SDK code generation against drift by deriving parser and completions from SDK metadata and adding SDK builder coverage for all generated step methods.
|
|
2382
|
+
- 6730e12: Complete the public SSE/OpenAPI contract for Persona Runtype streams (#3975):
|
|
2383
|
+
- Add the optional `stopReason` field (`end_turn` | `max_tool_calls` | `length` | `content_filter` | `error` | `unknown`) to the canonical `step_complete` SSE schema, so the public `FlowSSEEvent` component and generated SDK types document the model finish reason that prompt steps already emit on the wire.
|
|
2384
|
+
- Re-export stable public stream-event aliases (`DispatchEvent`, `FlowStreamEvent`, `AgentStreamEvent`, `StreamEventOf`) from the SDK barrel, tied to the generated OpenAPI components so they drift only with the public spec.
|
|
2385
|
+
- Add public OpenAPI coverage for the remaining browser client-token runtime endpoints — `POST /v1/client/init`, `POST /v1/client/resume` (SSE), and `POST /v1/client/feedback` — reusing the runtime validation schemas so the docs and implementation cannot drift.
|
|
2386
|
+
|
|
2387
|
+
### Patch Changes
|
|
2388
|
+
|
|
2389
|
+
- 6efd928: Fix a race in `/client/chat` interrupt handling where a slower, older request could reclaim the active turn slot from a newer interrupting turn. `markClientChatTurnStarted` now claims the slot with a compare-and-swap on the turn's arrival timestamp (captured at request entry), so a stale request whose write lands late can no longer restore its turn id and defeat the interrupt.
|
|
2390
|
+
|
|
2391
|
+
## 4.6.1
|
|
2392
|
+
|
|
2393
|
+
### Patch Changes
|
|
2394
|
+
|
|
2395
|
+
- cf15960: Improve dashboard responsiveness with persisted safe query caching, lazy analytics loading, optimistic list actions, and batched product editor context loading.
|
|
2396
|
+
|
|
2397
|
+
## 4.6.0
|
|
2398
|
+
|
|
2399
|
+
### Minor Changes
|
|
2400
|
+
|
|
2401
|
+
- e7eefe0: Agent memory: thread `endUser` identity through the dispatch / agent-execute / SDK surface so templates like `{{_endUser.id}}` resolve for per-end-user memory sharding (distinct from `_user`, the Runtype account holder). `endUser` is exposed as `{{_endUser.*}}` in template variables on both the agent and flow execution paths, and is carried into the memory profile resolution so multi-tenant SaaS callers can shard long-term memory per end-user. Also persists agent `config.memory` on create/update and adds the agent-editor memory config state plumbing.
|
|
2402
|
+
|
|
2403
|
+
## 4.5.0
|
|
2404
|
+
|
|
2405
|
+
### Minor Changes
|
|
2406
|
+
|
|
2407
|
+
- 55eb091: Add agent self-service coverage for OpenAI-compatible (BYOK) model endpoints across MCP, the SDK, and Code Mode. Agents can now connect a custom OpenAI-compatible endpoint, discover its models, and register them without the dashboard.
|
|
2408
|
+
- **MCP**: new `create_provider_key`, `list_provider_keys`, `update_provider_key`, `delete_provider_key`, `discover_provider_models`, and `sync_provider_models` tools, plus `create_model_config` extended to accept `provider: "generic-openai"` with a `base_url` and custom-model pricing/display fields (and normalizing the bare endpoint model id to the routed `generic-openai:` form the API expects). Mirrored across both MCP servers (`RuntypeApiClient` and `RuntypeInternalClient`) and Code Mode (`runtype.createProviderKey`, `discoverProviderModels`, `syncProviderModels`, etc.).
|
|
2409
|
+
- **SDK**: new `client.providerKeys` endpoint (`create`, `list`, `update`, `delete`, `discoverModels`, `discoverModelsForKey`, `syncModels`); `CreateModelConfigRequest`/`CreateProviderKeyRequest`/`UpdateProviderKeyRequest` extended for `generic-openai`.
|
|
2410
|
+
- These wrap existing BYOK-gated REST routes, so callers without the entitlement receive `402 BYOK_NOT_AVAILABLE`. Documentation updated for connecting an OpenAI-compatible endpoint via the API, MCP, and SDK.
|
|
2411
|
+
|
|
2412
|
+
### Patch Changes
|
|
2413
|
+
|
|
2414
|
+
- 3f65083: Derive the `provider` enum on `CreateProviderKeyRequest` and `CreateModelConfigRequest` from the generated OpenAPI types instead of hand-maintaining the unions. This fixes a real drift: the hand-written unions accepted `'huggingface'` (which the API rejects) and omitted valid providers such as `vertex`, `vertex-anthropic`, `bedrock`, `tinfoil`, `braintrust`, `weaviate`, `vectorize`, `browser-rendering`, plus `model`/`runtime`/`mock`/`modelsocket` for model configs. Type-only change; no runtime behavior change.
|
|
2415
|
+
|
|
2416
|
+
## 4.4.0
|
|
2417
|
+
|
|
2418
|
+
### Minor Changes
|
|
2419
|
+
|
|
2420
|
+
- 59fd1b6: Remove the no-op `parallelCalls` tool-config flag (and the unused
|
|
2421
|
+
`parallelToolCalls` field on `ToolsConfig`).
|
|
2422
|
+
|
|
2423
|
+
`parallelCalls` was accepted and plumbed through the dispatch schema, SDK,
|
|
2424
|
+
MCP tool inputs, FPO schema, OpenAPI spec, config-merge, and runtime export,
|
|
2425
|
+
but it was never applied at the provider level — no executor ever passed a
|
|
2426
|
+
parallel-tool-use option to the model. Parallel tool calls therefore always
|
|
2427
|
+
used (and continue to use) each provider's default, which is parallel-enabled
|
|
2428
|
+
for current Claude/OpenAI/etc. models. Removing the dead config makes the
|
|
2429
|
+
surface honest: it no longer implies you can toggle a behavior that the
|
|
2430
|
+
platform never actually controlled.
|
|
2431
|
+
|
|
2432
|
+
Backward compatible at runtime: request schemas strip unknown keys, so an
|
|
2433
|
+
older client that still sends `parallelCalls` is accepted unchanged (the key
|
|
2434
|
+
is ignored, exactly as before). The only change is type-level — the field is
|
|
2435
|
+
gone from the SDK and API types.
|
|
2436
|
+
|
|
2437
|
+
## 4.3.0
|
|
2438
|
+
|
|
2439
|
+
### Minor Changes
|
|
2440
|
+
|
|
2441
|
+
- e133753: Add the optional `clientToolsPolicy` field to the SDK's `DispatchRequest` type.
|
|
2442
|
+
|
|
2443
|
+
Follow-up to allowing WebMCP `clientTools[]` on `/dispatch`: typed
|
|
2444
|
+
`@runtypelabs/sdk` callers can now pass `clientToolsPolicy.allowlist` to
|
|
2445
|
+
self-restrict which `origin: 'webmcp'` client tools are admitted, matching the
|
|
2446
|
+
shared `DispatchRequestSchema`.
|
|
2447
|
+
|
|
2448
|
+
### Patch Changes
|
|
2449
|
+
|
|
2450
|
+
- 26401de: WebMCP: make parallel calls to the same local tool individually addressable on resume (core#3878, follow-on to #3870).
|
|
2451
|
+
|
|
2452
|
+
When a single model turn calls the same local tool more than once in parallel (the common "add A and B to my cart" case), the `flow_await` / `agent_await` / `step_await` events now carry a unique per-call `toolCallId` (the provider `tool_use` id). The `/resume` `toolOutputs` map can be keyed by that `toolCallId` so a client can resolve every pending call of one paused execution in a single resume, including multiple calls to the same tool. Keying by tool name still works (legacy contract; collapses same-tool parallel calls onto one slot). Resolution remains tolerant: outputs can arrive in any order across one or more `/resume` requests, and missing siblings re-pause.
|
|
2453
|
+
|
|
2454
|
+
## 4.2.0
|
|
2455
|
+
|
|
2456
|
+
### Minor Changes
|
|
2457
|
+
|
|
2458
|
+
- 52091ac: Bump `@daytonaio/sdk` to `^0.184.0` and let the Daytona deploy path tag sandboxes with labels + opt into server-side reaping.
|
|
2459
|
+
- **`@runtypelabs/sandbox`:** upgraded `@daytonaio/sdk` (`^0.27.1` → `^0.184.0`). Existing call sites (`create`/`get`/`delete`/`codeRun`/`executeCommand`/`getPreviewLink`/`setAutostopInterval`) remain compatible; we don't use the now-async-iterator `list()`. `DaytonaDeployOptions` gains optional `labels`, `autoStopInterval`, and `autoDeleteInterval`. Labels are applied at sandbox creation (new sandboxes only); `autoStopInterval` defaults to the existing 120 minutes; `autoDeleteInterval` (via `setAutoDeleteInterval`) is opt-in so callers can have leaked sandboxes self-reap.
|
|
2460
|
+
- **`@runtypelabs/api`:** `POST /api/tools/sandbox/deploy` now accepts optional `labels`, `autoStopInterval`, and `autoDeleteInterval` and forwards them to the Daytona executor. Default behavior is unchanged when they're omitted. The executor guards both intervals with `Number.isFinite` so a non-number from the untyped request body falls back to the default instead of silently leaving the sandbox with no auto-stop.
|
|
2461
|
+
- **`@runtypelabs/sdk`:** `DeploySandboxRequest` gains the same three optional fields so SDK/CLI callers can pass them in lockstep with the REST route.
|
|
2462
|
+
|
|
2463
|
+
This lets CI tag its Daytona sandboxes (e.g. `source: 'runtype-ci'`) for traceability and gives them a short auto-stop + immediate auto-delete so a killed run can't leak a live sandbox.
|
|
2464
|
+
|
|
2465
|
+
- 0aa81ed: `runWithLocalTools` now resolves parallel local tool calls in a single pause/resume cycle (core#3870 follow-up).
|
|
2466
|
+
|
|
2467
|
+
When a model turn requests several local (client-side / WebMCP) tool calls at once — e.g. "search for X **and** add SKU Y" — the server emits a `flow_await`/`step_await` per call and its `/resume` accepts every output in one request. The SDK previously processed only the last paused tool per cycle (last-writer-wins), so N parallel calls took N pause/resume round-trips. Both `RuntypeClient.runWithLocalTools` and the FlowBuilder's `runWithLocalTools` now collect the whole batch (keyed by tool name, merging `flow_await` + `step_await`), execute every handler concurrently, and resume once with all `toolOutputs`. Single-tool turns are unchanged; the merge of partial `flow_await`/`step_await` context is preserved.
|
|
2468
|
+
|
|
2469
|
+
## 4.1.0
|
|
2470
|
+
|
|
2471
|
+
### Minor Changes
|
|
2472
|
+
|
|
2473
|
+
- 88d04d6: Add `FlowBuilder.validate()` to the SDK (#10, slice 3 of the end-to-end
|
|
2474
|
+
type-safety initiative — the SDK-facing consumer of the shared flow validator).
|
|
2475
|
+
|
|
2476
|
+
`new FlowBuilder()…validate(client)` (and the bound `runtype.flow(name)…validate()`
|
|
2477
|
+
/ `Runtype.flows.virtual()…validate()`) POSTs the prospective flow to the public
|
|
2478
|
+
validation endpoint (`POST /v1/public/flows/validate`) WITHOUT creating it, and
|
|
2479
|
+
returns the same `errors` / `warnings` / `recommendations` envelope the API,
|
|
2480
|
+
dashboard, and MCP `validate_flow` tool use. Structural issues, the upsert-record
|
|
2481
|
+
JSON foot-gun, undeclared-variable warnings, and sub-optimal model selections now
|
|
2482
|
+
surface at author time rather than at dispatch time. Authentication is optional;
|
|
2483
|
+
an authenticated client additionally runs account-scoped checks (referenced
|
|
2484
|
+
tools / flows / agents must exist + be owned), reported via `result.context`.
|
|
2485
|
+
|
|
2486
|
+
Implemented as the API-backed option (slice-3 option a), so the SDK stays
|
|
2487
|
+
**zero-dependency**: `validate()` reuses the client's existing `post<T>` transport
|
|
2488
|
+
(no new HTTP plumbing). The return type (`FlowValidationResult`) and `FlowValidationIssue`
|
|
2489
|
+
are **spec-derived** from `components['schemas']` in the generated OpenAPI types, so
|
|
2490
|
+
they cannot drift from the API contract. New public exports: `FlowValidationResult`,
|
|
2491
|
+
`FlowValidationIssue`, `FlowValidationClient`.
|
|
2492
|
+
|
|
2493
|
+
The `@runtypelabs/shared` bump is the regenerated `generated-sdk-reference.ts`
|
|
2494
|
+
(the SDK reference auto-extracts the public API surface, so the two new `validate`
|
|
2495
|
+
methods land in the MCP `runtype://types/sdk-reference` resource).
|
|
2496
|
+
|
|
2497
|
+
- ac87cbe: Type `DispatchRequest.flow.steps` instead of `Array<any>`.
|
|
2498
|
+
|
|
2499
|
+
`flow.steps` is now `FlowStepDefinition[]`, a step shape derived from the
|
|
2500
|
+
OpenAPI spec's `POST /v1/flows` request body, so its `type` discriminant is the
|
|
2501
|
+
canonical `FlowStepType` union (the 26 `FLOW_STEP_TYPES` from
|
|
2502
|
+
`@runtypelabs/shared`) rather than `any`. A malformed step — an unknown `type`,
|
|
2503
|
+
or a non-object element — is now a compile error in `dispatch()` payloads and
|
|
2504
|
+
the FlowBuilders. Two new public types are exported: `FlowStepType` and
|
|
2505
|
+
`FlowStepDefinition`.
|
|
2506
|
+
|
|
2507
|
+
Because the type is spec-derived, it cannot drift from the API:
|
|
2508
|
+
`pnpm generate:types` regenerates the underlying SDK types from the committed
|
|
2509
|
+
spec and `generate:types:check` fails CI on drift. A new compile-time guard
|
|
2510
|
+
(`flow-step-definition.type-assert.ts`, type-checked but not shipped) pins the
|
|
2511
|
+
"malformed step is a compile error" contract so a future regression toward
|
|
2512
|
+
`any` breaks the build.
|
|
2513
|
+
|
|
2514
|
+
Step `config` is still `unknown` at this layer (the API keeps step config loose
|
|
2515
|
+
at the schema layer and validates it imperatively for rich, field-level agent
|
|
2516
|
+
feedback). Compile-time per-type `config` typing — and typing the dispatch
|
|
2517
|
+
request body directly in the spec — is the remaining follow-up (#12(a) of the
|
|
2518
|
+
end-to-end type-safety initiative).
|
|
2519
|
+
|
|
2520
|
+
Dashboard (`patch`): three call sites that assemble dispatch payloads from
|
|
2521
|
+
dynamically-typed flow data (`product-generator-agent.ts`, `ai-flow-assistant-flow.ts`,
|
|
2522
|
+
`useStandaloneDispatchExecution.ts`) were updated to assert the SDK's narrowed
|
|
2523
|
+
step shape at the wire boundary — type-only adjustments, no behavior change.
|
|
2524
|
+
|
|
2525
|
+
Classified **minor**, not major: the runtime/wire contract is byte-identical
|
|
2526
|
+
(this is a compile-time-only tightening), `any` was an eslint-disabled escape
|
|
2527
|
+
hatch rather than a real contract, every valid step payload still compiles, and
|
|
2528
|
+
the primary consumers (`FlowBuilder` / `RuntypeFlowBuilder`) produce conforming
|
|
2529
|
+
steps. Only step literals that were already invalid per the API contract (a
|
|
2530
|
+
non-canonical `type`, a non-object element) become compile errors — the
|
|
2531
|
+
intended safety improvement.
|
|
2532
|
+
|
|
2533
|
+
### Patch Changes
|
|
2534
|
+
|
|
2535
|
+
- 2711b97: Fix `flows.create()` step type: `CreateFlowRequest.flowSteps[].type` now uses the
|
|
2536
|
+
spec-derived `FlowStepType` (the full canonical `FLOW_STEP_TYPES` set) instead of a
|
|
2537
|
+
stale hand-written 5-value literal (`'prompt' | 'context' | 'condition' | 'output' |
|
|
2538
|
+
'email'`, 4 of which were never real step types). Real step types like
|
|
2539
|
+
`'transform-data'` and `'conditional'` are now accepted, and the type is pinned by a
|
|
2540
|
+
compile-time assertion so it cannot drift from the API spec again.
|
|
2541
|
+
- 84ab7da: Consolidate the three `validate()` implementations (`FlowBuilder`,
|
|
2542
|
+
`ClientFlowBuilder`, `RuntypeFlowBuilder`) onto a single shared
|
|
2543
|
+
`validateInlineFlow()` helper. The saved-flow-by-id guard, the
|
|
2544
|
+
`POST /public/flows/validate` path, and the `{ name, steps }` body shape were
|
|
2545
|
+
duplicated verbatim across `flow-builder.ts` and `flows-namespace.ts`; they now
|
|
2546
|
+
share one implementation, so the validation contract can no longer drift between
|
|
2547
|
+
the two surfaces. Behavior is identical — error messages are byte-for-byte the
|
|
2548
|
+
same (each caller passes its own surface-specific remediation hint). Internal
|
|
2549
|
+
refactor only; no public API change.
|
|
2550
|
+
|
|
2551
|
+
## 4.0.4
|
|
2552
|
+
|
|
2553
|
+
### Patch Changes
|
|
2554
|
+
|
|
2555
|
+
- 2e3a776: Begin the converge-then-tighten path toward strict validation of steps nested
|
|
2556
|
+
inside `conditional` branches (the last unmigrated step type, #6 capstone).
|
|
2557
|
+
|
|
2558
|
+
Leg 1 (non-breaking, measure-first):
|
|
2559
|
+
- `setVariableConfigSchema` now accepts `value: null`, aligning the schema with
|
|
2560
|
+
the runtime normalizer and executor (which already permit it). Clearing a
|
|
2561
|
+
variable (`value: null`) is a legitimate idiom, commonly the else-branch of a
|
|
2562
|
+
conditional. The SDK's `SetVariableStepConfig.value` type is widened to match.
|
|
2563
|
+
- New read-only `Flow NestedStep Shape Written` PostHog event counts legacy
|
|
2564
|
+
markers (snake_case configs, `set-variable value:null`, legacy `true_steps` /
|
|
2565
|
+
`false_steps` branch keys, lenient envelopes, unknown types) on steps nested
|
|
2566
|
+
inside conditional branches per flow write. This is the decay watch that gates
|
|
2567
|
+
the eventual strict recursive-union tighten — no behavior change to what is
|
|
2568
|
+
persisted or validated.
|
|
2569
|
+
|
|
2570
|
+
See `docs/features/planning/2026-06-04-conditional-nested-step-strict-validation.md`.
|
|
2571
|
+
|
|
2572
|
+
## 4.0.3
|
|
2573
|
+
|
|
2574
|
+
### Patch Changes
|
|
2575
|
+
|
|
2576
|
+
- 8f11ab5: Normalize the generic REST request-validation error envelope. Every `.openapi()`
|
|
2577
|
+
route now returns the same coded `{ code, message, path, suggestion? }` detail
|
|
2578
|
+
shape (stable Runtype codes like `MISSING_REQUIRED_FIELD`, `INVALID_ENUM`,
|
|
2579
|
+
`OUT_OF_RANGE`) instead of raw Zod issues, so REST/SDK callers get the same
|
|
2580
|
+
enriched, machine-readable feedback that MCP previously had to reconstruct via
|
|
2581
|
+
`enrichErrorForAgent`. The four `defaultHook` sites (shared `createOpenAPIApp()`
|
|
2582
|
+
factory plus the hand-rolled product-api / quick-start / product-chat mappers)
|
|
2583
|
+
now route through a single shared `validationErrorResponse` helper. The MCP
|
|
2584
|
+
client now forwards the new `code` and `suggestion` fields through
|
|
2585
|
+
`enrichErrorForAgent`, so MCP-surface agents receive the same coded feedback.
|
|
2586
|
+
- edf2b2a: Register the OpenAPI error envelope and four other high-duplication schemas as
|
|
2587
|
+
shared `#/components/schemas/*` components, so routes emit one-line `$ref`s
|
|
2588
|
+
instead of inlining the full object at every use site:
|
|
2589
|
+
- `Error` — the 4xx/5xx error envelope (~1,291 copies → 1 definition)
|
|
2590
|
+
- `Pagination` — the cursor envelope on every paginated list response (12×)
|
|
2591
|
+
- `FlowValidationResult` / `FlowValidationIssue` — the flow-validation envelope
|
|
2592
|
+
and its issue item (the issue appeared 36× = 12 results × 3 arrays)
|
|
2593
|
+
- `RecordFilterCondition` — the record-filter `field/op/value` clause (12×)
|
|
2594
|
+
|
|
2595
|
+
Net: the committed spec artifacts shrink ~98k lines and the generated SDK types
|
|
2596
|
+
shrink ~14k lines, exposing reusable `components['schemas']['*']` types.
|
|
2597
|
+
Representation-only: runtime request/response bodies and documented shapes are
|
|
2598
|
+
byte-identical (verified zero semantic diffs across all 1,773 public + 2,004
|
|
2599
|
+
internal resolved schemas).
|
|
2600
|
+
|
|
2601
|
+
## 4.0.2
|
|
2602
|
+
|
|
2603
|
+
### Patch Changes
|
|
2604
|
+
|
|
2605
|
+
- d4ca2dd: Correct `createExternalTool` JSDoc to stop documenting `{{_internal.auth_token}}`, `{{_internal.user_id}}`, and `{{_internal.org_id}}` as available auth variables. These `_internal.*` variables are never populated at runtime and are actively blocked by the execution engine; the docs now point users to secret references (`{{secret:NAME}}`) for credentials.
|
|
2606
|
+
|
|
2607
|
+
## 4.0.1
|
|
2608
|
+
|
|
2609
|
+
### Patch Changes
|
|
2610
|
+
|
|
2611
|
+
- a7cb0d9: Add a `slow` fallback trigger: a per-model-call total wall-clock duration cap that fails a slow-but-not-stalled model call over to its configured fallback model. A model that streams continuously but slowly (e.g. ~24 tok/s) never trips the existing TTFT/idle stall watchdogs (an idle timer resets on every chunk), so a step can now opt in with `errorHandling.triggers: [{ type: 'slow', afterMs }]` (suggested default 45s) plus a `model` fallback.
|
|
2612
|
+
|
|
2613
|
+
The cap aborts-and-falls-over **only while the partial work is safely discardable**, gated two ways: it disarms permanently the moment a tool chunk passes (a side effect may have fired — re-running could double it), and, in a streaming-to-client dispatch, the moment a delta is flushed live (falling over would double-emit). In a non-streaming (`streamResponse: false`) dispatch the buffered partial is discardable, so the cap can fire mid-generation — the case it exists for. A duration-cap abort skips the same-model retry and routes straight to the configured fallback (a slow model is likely slow again).
|
|
2614
|
+
|
|
2615
|
+
`withModelCallResilience` gains optional `maxDurationMs` / `streamingToClient` / `isToolChunk` (off by default — fully opt-in, zero change to existing calls) and a `duration_cap` `ModelStreamStallError` phase. The runtime honors the trigger too, but with no Layer-2 fallback chain a cap abort surfaces as a clean `StepExecutionError`. The flow validator rejects a `slow` trigger with a non-positive `afterMs` (`SLOW_TRIGGER_INVALID_AFTER_MS`), and the error-handling editor preserves a saved slow trigger's `afterMs` across save.
|
|
2616
|
+
|
|
2617
|
+
## 4.0.0
|
|
2618
|
+
|
|
2619
|
+
### Major Changes
|
|
2620
|
+
|
|
2621
|
+
- 55d5817: SDK: alias four more entity types to the generated OpenAPI types, and remove a dead endpoint.
|
|
2622
|
+
|
|
2623
|
+
**Breaking (types only — runtime behavior unchanged):** `Surface`, `ScheduleRun`, `ProviderApiKey`, and `BuiltInTool` now re-export from the committed OpenAPI spec instead of hand-mirrored interfaces, so they reflect what the API actually returns:
|
|
2624
|
+
- `ProviderApiKey.id` is now `string` (was `number`); `provider` widens from a literal union to `string`; `keyPreview`/`lastUsedAt` become `| null`; gains optional `settings`.
|
|
2625
|
+
- `BuiltInTool.category` widens from a literal union to `string`; gains optional `modelCompatibility`; `parametersSchema` is an opaque object.
|
|
2626
|
+
- `ScheduleRun` gains `totalRecords`/`processedRecords`/`failedRecords` and drops its `[key: string]: unknown` index signature.
|
|
2627
|
+
- `Surface.inbound` is now a typed (Slack) object rather than `Record<string, unknown>`.
|
|
2628
|
+
|
|
2629
|
+
Consumers reading dropped/renamed fields were already getting `undefined` at runtime; the types now match the wire.
|
|
2630
|
+
|
|
2631
|
+
**Breaking:** removed `tools.getExecutions()` and the exported `ToolExecution` type. They called `GET /tools/{id}/executions`, which has **no route handler** and 404s in production. The never-mounted dashboard `ToolExecutionHistory` component and its API test (which asserted the nonexistent route) are removed alongside.
|
|
2632
|
+
|
|
2633
|
+
- 89b107f: feat(sdk): alias Flow/FlowStep/Tool from the OpenAPI spec; fix flow + tool response-schema drift
|
|
2634
|
+
|
|
2635
|
+
Continues the OpenAPI codegen swap (after #3645/#3665). Three coupled changes that all touch `entities.ts` + the regenerated spec + SDK `types.ts`:
|
|
2636
|
+
- **Flow phantom fix (API spec accuracy):** the flow `GET`/`LIST`/`POST` response schemas advertised a `status` field the handlers stopped returning (removed in #3404), and the shared detail schema carried a `draftVersionId` that only the `PUT` handler returns. Removed `status` everywhere and split a dedicated `UpdatedFlowResponseSchema` (`FlowDetailSchema.extend({ draftVersionId })`) for the update route so `GET`/`POST` no longer promise it.
|
|
2637
|
+
- **Tool schema split:** `GET /v1/tools/{id}` never attaches `validation` (only create/update/convert do, when custom-tool code produces warnings). Split `ToolDetailSchema` (base, GET) from `ToolWithValidationSchema` (create/update/convert).
|
|
2638
|
+
- **SDK aliases:** `Flow`, `FlowStep`, and `Tool` are now `paths[...]`-derived from the generated spec instead of hand-written interfaces. Added a `FlowListItem` alias for the lighter `GET /v1/flows` list item and retyped `flows.list()` to `PaginationResponse<FlowListItem>` (it was incorrectly typed as the detail shape). `FlowListItem` is named to avoid colliding with the flow-execution `FlowSummary` already exported by `flow-builder.ts`.
|
|
2639
|
+
|
|
2640
|
+
This is a **major** bump for `@runtypelabs/sdk` because the generated shapes are looser/more accurate than the old interfaces: the GET flow detail no longer carries `status`/`description`, flow steps have optional `name`/`order`/`enabled`/`config`, the tool GET shape drops `validation`, and tool `config`/`parametersSchema` are typed as the JSONB records the API actually returns. Dashboard and CLI consumers are updated in lockstep.
|
|
2641
|
+
|
|
2642
|
+
- e1a4368: Alias the SDK `RuntypeRecord` type to the generated OpenAPI contract (PR3 of the
|
|
2643
|
+
OpenAPI codegen swap, following #3665 / #3670).
|
|
2644
|
+
|
|
2645
|
+
`RuntypeRecord` is now derived from `GET /v1/records/{id}` and a new
|
|
2646
|
+
`RecordListItem` type from `GET /v1/records`, replacing the hand-written
|
|
2647
|
+
interface that had drifted from what the API actually returns:
|
|
2648
|
+
- **`availableFields` is list-only.** It is computed per-row from metadata keys
|
|
2649
|
+
and returned only when `includeFields=true`, so it now lives on
|
|
2650
|
+
`RecordListItem` (returned by `records.list()` / `records.getExample()`), not
|
|
2651
|
+
on the GET/create/update `RuntypeRecord`. Mirrors the `FlowListItem` split.
|
|
2652
|
+
- **`metadataSchema` typing corrected.** The hand-written `keyMapping` /
|
|
2653
|
+
`keyTypes` / `sizeKb` / `keyCount` / `updatedAt` fields never existed on the
|
|
2654
|
+
wire — the trigger-computed JSONB summary is returned verbatim with snake_case
|
|
2655
|
+
keys. It is now typed as `{ keys: string[] }` (the only field consumers read)
|
|
2656
|
+
plus a catchall for the remaining computed fields.
|
|
2657
|
+
- **`metadataLabels`** tightened from `Record<string, unknown>` to
|
|
2658
|
+
`Record<string, string>` (its real shape).
|
|
2659
|
+
|
|
2660
|
+
API-side, the records list response schema now documents `availableFields` via a
|
|
2661
|
+
`RecordListItemSchema`, and `RecordSchema` accurately describes the
|
|
2662
|
+
`metadataSchema` / `metadataLabels` shapes.
|
|
2663
|
+
|
|
2664
|
+
### Minor Changes
|
|
2665
|
+
|
|
2666
|
+
- a0b30f3: Add `Runtype.skills.*` — a hand-written SDK resource for the Agent Skills admin/control plane. Covers `create`, `get`, `list`, `update` (append draft version), `delete`, `listVersions`, `publishVersion`, `import`, `bind`, `unbind`, `listBindings`, plus a nested `skills.proposals` review queue (`list`, `approve`, `reject`). The deployed-agent `propose_skill` data plane is intentionally not exposed. Also adds generic `put`/`delete` request helpers to `RuntypeClient` (the skills surface uses real `PUT`/`DELETE` verbs).
|
|
2667
|
+
|
|
2668
|
+
### Patch Changes
|
|
2669
|
+
|
|
2670
|
+
- c3536a2: Upgrade A2A (Agent-to-Agent) protocol support to spec v1.0.
|
|
2671
|
+
|
|
2672
|
+
**Surface (we expose agents as A2A): 1.0 only.** The agent card now advertises
|
|
2673
|
+
`supportedInterfaces[]` + `securitySchemes`, the JSON-RPC endpoint uses
|
|
2674
|
+
PascalCase methods (`SendMessage`/`SendStreamingMessage`/`GetTask`/`CancelTask`/
|
|
2675
|
+
`SubscribeToTask`, plus the new `ListTasks`), Parts use the unified 1.0 oneof
|
|
2676
|
+
(`text`/`raw`/`url`/`data`, `mediaType`, no `kind`), task states are
|
|
2677
|
+
SCREAMING*SNAKE (`TASK_STATE*\*`), streaming events are `StreamResponse`
|
|
2678
|
+
wrappers (`statusUpdate`/`artifactUpdate`, no `final`), and errors use the
|
|
2679
|
+
`google.rpc.Status`form. Wire encoding is centralized in a new`apps/api/src/lib/a2a-wire/v10.ts` serializer. (No production A2A surface had
|
|
2680
|
+
ever been invoked, so the hard cut breaks no existing consumer.)
|
|
2681
|
+
|
|
2682
|
+
**Import / federation (we consume external A2A agents): supports both 0.3 and
|
|
2683
|
+
1.0.** External agent cards are parsed against a dual-version schema; an
|
|
2684
|
+
interface selector prefers a 1.0 JSON-RPC interface and falls back to the 0.3
|
|
2685
|
+
top-level `url`. The external-agent proxy and the `runA2A` runtime tool emit
|
|
2686
|
+
the envelope matching the negotiated version (`A2AToolConfig.protocolVersion`,
|
|
2687
|
+
default 0.3).
|
|
2688
|
+
|
|
2689
|
+
- 8fefe6f: Agent Skills (admin plane): expose the `enable-agent-skills` flag to clients via `GET /v1/users/profile` (`features.enableAgentSkills`) so the dashboard can gate its Skills nav, and add a dedicated `GET /v1/skills/{id}/versions` endpoint for listing a skill's version history. Regenerated the public/internal OpenAPI artifacts and the SDK's generated types.
|
|
2690
|
+
- aa97266: Add an `empty-output` fallback trigger and terminal `message` fallback to prompt/agent error handling. Fallbacks can now fire when a model finishes successfully but returns no visible text (the "thinking" model reasoning-spiral failure), not just on error. `errorHandling.triggers` is an array (`error` | `empty-output`, defaulting to `[{type:'error'}]`), and a `{type:'message', message}` fallback yields a graceful author-controlled reply when retries/model swaps still come back empty. The product generator agent opts in (retry → reliable non-thinking model → synthesized message) so Kimi K2.6 empty answers no longer surface as blank chat bubbles.
|
|
2691
|
+
|
|
2692
|
+
The error-handling editor (used by both flow prompt steps and now the agent editor sidebar) exposes the new options: toggles for which conditions run the fallback chain (errors / empty replies) and a "Fixed message" fallback type. Agents gain a dedicated "Error handling" section that reuses the same modal.
|
|
2693
|
+
|
|
2694
|
+
The SDK's inlined error-handling types gain `MessageFallback`, the `triggers` field on `PromptErrorHandling`, and `FallbackTrigger`; the `FallbacksExhaustedEvent` type is corrected to match the wire event (`fallback_exhausted`, optional `finalError`, new `reason`).
|
|
2695
|
+
|
|
2696
|
+
- 42979fc: Add a `product-generator-model` Flagship string flag that selects which model the dashboard's product generator dispatches with (`kimi-k2.6` default, `claude-sonnet-4-6`, `gpt-5.5`, `claude-opus-4-8`). The flag is evaluated per user/org by the API and surfaced via `GET /v1/users/profile` as `features.productGeneratorModel`; the dashboard resolves it before dispatch and falls back to `kimi-k2.6` on any lookup failure.
|
|
2697
|
+
- af80a8a: Add Agent Skills — versioned, loadable context bundles (Anthropic SKILL.md +
|
|
2698
|
+
a `runtype:` capability extension) that deployed Runtype agents load on demand.
|
|
2699
|
+
- Two-plane governance: admin/control authoring (REST/SDK/MCP, scopes-only) vs
|
|
2700
|
+
deployed-agent self-authoring via `propose_skill` (review-by-default, with a
|
|
2701
|
+
human-set, agent-unreachable auto-publish opt-out scoped to the proposing
|
|
2702
|
+
agent).
|
|
2703
|
+
- Runtime: `skill:<slug>` virtual tools, stateless `runSkill` (body-as-result +
|
|
2704
|
+
capability activation through the existing tool-discovery channel), the
|
|
2705
|
+
capability-load approval gate reusing `ApprovalRequiredError`, and the
|
|
2706
|
+
`agent_skill_loaded` / `agent_skill_proposed` SSE events.
|
|
2707
|
+
- v1 capability scope: `flowIds`/`agentIds`/`toolIds`/`inlineTools`
|
|
2708
|
+
(`mcpServers` rejected at write, still parsed losslessly on import).
|
|
2709
|
+
|
|
2710
|
+
## 3.0.0
|
|
2711
|
+
|
|
2712
|
+
### Major Changes
|
|
2713
|
+
|
|
2714
|
+
- 53bfe49: Generate SDK types from the committed OpenAPI 3.2 spec via `openapi-typescript`, replacing hand-mirrored types. Adds `pnpm generate:types` (+ `:check` drift gate, wired into CI).
|
|
2715
|
+
|
|
2716
|
+
**Breaking (types only — runtime behavior unchanged):** several public types now reflect what the API actually returns, so over-declared fields are removed and some become optional:
|
|
2717
|
+
- `StreamEvent` and its members derive from the spec's `FlowSSEEvent` union — fields the API may omit (e.g. `StepCompleteEvent.name`, `executionTime`) are now optional, and the deprecated fallback event aliases (`FallbackFailEvent`, `FallbackSuccessEvent`, `FallbacksInitiatedEvent`) map onto the canonical discriminants (`fallback_exhausted`, `fallback_complete`, `fallback_start`).
|
|
2718
|
+
- Entity types re-export from the spec: `Prompt` (drops `isStreamed`/`tools`/`inputVariables`), `UserProfile` (drops `firstName`/`lastName`/`preferences.defaultModel`), `IntegrationTool` (`parametersSchema` → `parameters`), plus `Secret`, `Conversation`, `ConversationListItem`, `AgentVersionDetail`, `FlowVersionDetail`, `Integration`, `ModelUsageDetail`, `Schedule`.
|
|
2719
|
+
|
|
2720
|
+
Consumers reading removed fields were already getting `undefined` at runtime (the API never returned them); the types now match reality.
|
|
2721
|
+
|
|
2722
|
+
## 2.2.0
|
|
2723
|
+
|
|
2724
|
+
### Minor Changes
|
|
2725
|
+
|
|
2726
|
+
- f676234: Add typed SDK endpoint classes for resources the client previously lacked: `secrets`, `schedules` (CRUD + pause/resume/run-now + runs/stats), `surfaces`, `conversations`, `logs` (query/stats/trace), `agentVersions`, `flowVersions`, `integrations`, and `billing`. Each is exposed as a typed property on `RuntypeClient`, bringing the SDK closer to parity with the API surface used by the CLI.
|
|
2727
|
+
|
|
2728
|
+
### Patch Changes
|
|
2729
|
+
|
|
2730
|
+
- 75c7cbd: CLI consistency polish: standardize output and pagination flags, bump Node engine
|
|
2731
|
+
- Unify the `--json` flag description to `Output as JSON` across commands and the
|
|
2732
|
+
root program (semantically distinct variants on `tail`, `agents task`, and
|
|
2733
|
+
`persona init` are intentionally preserved).
|
|
2734
|
+
- Standardize pagination flags on list commands whose API supports cursor
|
|
2735
|
+
pagination: `--limit <n>` + `--cursor <cursor>`, with an actionable
|
|
2736
|
+
"fetch the next page with `--cursor …`" hint when more results exist.
|
|
2737
|
+
- Added to: `flows`, `prompts`, `records`, `agents`, `schedules`,
|
|
2738
|
+
`conversations`, `tools`, `products`.
|
|
2739
|
+
- `--limit` has no forced default — when omitted, the API's own page size
|
|
2740
|
+
applies (avoids silently shrinking existing default result counts).
|
|
2741
|
+
- `conversations`/`tools` previously printed a dead-end "pass ?limit and
|
|
2742
|
+
?cursor" hint without exposing the flags; they now work.
|
|
2743
|
+
- Add shared `buildListParams` / `printNextCursorHint` helpers in `lib/output.ts`
|
|
2744
|
+
(normalizing the `nextCursor`/`cursor` and `hasMore`/`hasNextPage` response
|
|
2745
|
+
variants) and adopt them in `surfaces` and `logs`, replacing hand-rolled query
|
|
2746
|
+
builders and inline hints (also fixes a `surfaces` hint that rendered a trailing
|
|
2747
|
+
space when no cursor was present).
|
|
2748
|
+
- Bump `engines.node` from `>=18.0.0` to `>=22.0.0` for `@runtypelabs/cli`,
|
|
2749
|
+
`@runtypelabs/sdk`, `@runtypelabs/ink-components`, and
|
|
2750
|
+
`@runtypelabs/terminal-animations`. Node 18 is EOL; 22 is the current LTS. (The
|
|
2751
|
+
repo root requires `>=24`, but these are published/consumer-installed packages,
|
|
2752
|
+
so the floor is held at the current LTS rather than the dev-toolchain version.)
|
|
2753
|
+
|
|
2754
|
+
- 3b357cc: Route all CLI API access through the SDK client instead of a hand-rolled raw HTTP client. Every command now constructs a configured `@runtypelabs/sdk` client via `createCliClient`, using typed endpoint methods (e.g. `client.flows.list()`) where available and the SDK's generic methods elsewhere. This makes the SDK the CLI's single source of truth for the API surface, so the CLI stops drifting behind the API, and a new `runtype/cli-use-sdk` lint rule prevents reintroducing a parallel raw client. The CLI client disables request timeouts by default for long-running executions via the SDK's new `timeout: null` support. Also fixes two latent bugs surfaced during the migration: `flows run --no-stream` now correctly requests a non-streamed response (`options.streamResponse`), and `flows get` displays the step count from the actual `flowSteps`/`stepCount` response fields.
|
|
2755
|
+
|
|
2756
|
+
## 2.1.1
|
|
2757
|
+
|
|
2758
|
+
### Patch Changes
|
|
2759
|
+
|
|
2760
|
+
- 3b6779b: Migrate WebMCP polyfill from navigator.modelContext to document.modelContext per Chrome 150 spec change (WebML CG Issue 173 / PR #184)
|
|
2761
|
+
|
|
2762
|
+
## 2.1.0
|
|
2763
|
+
|
|
2764
|
+
### Minor Changes
|
|
2765
|
+
|
|
2766
|
+
- 7d37b2f: Add `dispatch.clientTools[]` — a per-dispatch wire field for client-executed
|
|
2767
|
+
tools (WebMCP page tools and SDK locals).
|
|
2768
|
+
- Server validates the envelope (`webmcp:` prefix is server-applied,
|
|
2769
|
+
~64KB budget, duplicate / regex / shape checks) and merges into the
|
|
2770
|
+
prompt-step tool set with precedence `saved < runtimeTools < clientTools`.
|
|
2771
|
+
- SDK extends `runWithLocalTools` with `{ scope?: 'turn' | 'session' }`.
|
|
2772
|
+
Default `'session'` is back-compat. `'turn'` auto-builds
|
|
2773
|
+
`dispatch.clientTools[]` from the handler map.
|
|
2774
|
+
- Surface model gains an opt-in `chat.webmcp.{enabled, allowlist,
|
|
2775
|
+
requireConfirmFor}` block. Default off; dashboard UI is Phase 4.
|
|
2776
|
+
|
|
2777
|
+
Complementary to in-engine `resolveTools`
|
|
2778
|
+
(`packages/runtime/src/engine/agent-engine.ts:687`): `resolveTools` is
|
|
2779
|
+
per-iteration inside one agent loop; `clientTools[]` is the wire-side
|
|
2780
|
+
counterpart that arrives per-dispatch.
|
|
2781
|
+
|
|
2782
|
+
## 2.0.1
|
|
2783
|
+
|
|
2784
|
+
### Patch Changes
|
|
2785
|
+
|
|
2786
|
+
- 89dc476: Preserve reasoning content (Anthropic extended-thinking signatures, Gemini thought signatures) across the platform-key proxy round-trip. Previously, when the runtime ran multi-round tool loops over `keys.mode: "platform"`, the assistant's round-1 `ReasoningPart` was silently dropped on round 2's POST body — breaking Anthropic extended thinking because the model requires its signed thinking block to ride alongside subsequent `tool_use` content. Now:
|
|
2787
|
+
- `StreamChunk.reasoningProviderOptions` carries the signature on the `reason_complete` SSE chunk. The capture lives in a single shared helper (`buildReasonCompleteChunk` in `stream-helpers.ts`) used by `processStandardStreamEvent` and the four hand-written executors (cloudflare-gateway, mixlayer, togetherai, workers-ai).
|
|
2788
|
+
- `MessageContent` gains a `reasoning` variant at every schema site: model-execution, runtime, shared dispatch, shared feedback-types, shared runtime-proxy (newly extracted), the api dispatch / schedules / client routes (consolidated onto the shared `MessageContentSchema`), the MCP `execute_agent` tool input, the public `DispatchChatMessage` agent-facing type snapshot, and the runtime's exported `PromptMessage` interface.
|
|
2789
|
+
- The runtime-proxy schema moved from `apps/api/src/routes/runtime-proxy.ts` to `@runtypelabs/shared/api-schemas/runtime-proxy.ts` so the cross-package parity test can validate proxy ↔ runtime ↔ dispatch in one place.
|
|
2790
|
+
- `PlatformKeyProxyLanguageModel`'s `translateNonSystemMessage` and `translateChunkToV2Parts` now emit reasoning parts in both directions, with provider signatures verbatim.
|
|
2791
|
+
- `buildMessagesArray` reconstructs assistant messages with reasoning **before** tool-call (Anthropic ordering rule); `applyTemplateToContent` skips template substitution on reasoning text (would invalidate the signed payload); `SecretLeakGuard.scrubValue` is applied to reasoning text to prevent secrets in chain-of-thought leaking through the proxy.
|
|
2792
|
+
- Tool-call and tool-result `providerOptions` (Anthropic `cache_control`, Gemini `thought_signature`) now round-trip through the proxy schema.
|
|
2793
|
+
- The dispatch route's pre-validation message filter (`hasNonEmptyMessageContent`) accepts `reasoning` (and `file`) variants so legitimate multi-modal turns are no longer silently dropped before Zod validation runs.
|
|
2794
|
+
|
|
2795
|
+
## 2.0.0
|
|
2796
|
+
|
|
2797
|
+
### Major Changes
|
|
2798
|
+
|
|
2799
|
+
- dc704fb: Remove the unused `status` lifecycle field from Flows and Agents (Option A from the status-field planning doc). The field gated nothing at runtime — dispatch always ran the live config row — and conflated lifecycle and draft/publish concerns. Dropped the `flows.status` and `agents.status` columns (and their now-redundant indexes), removed `status` from the REST list/create/update routes, the SDK `Flow` type, the MCP create/update agent + flow tools and list filters, the FPO agent schema, and the dashboard status pill/selectors.
|
|
2800
|
+
|
|
2801
|
+
Breaking: API responses for flows/agents no longer include `status`; the create/update endpoints and MCP tools no longer accept it; `Flow.status` is removed from `@runtypelabs/sdk`. Surface status, product status, and execution/run status are unaffected. Draft vs. published is now owned entirely by the versioning system.
|
|
2802
|
+
|
|
2803
|
+
### Minor Changes
|
|
2804
|
+
|
|
2805
|
+
- fed76a8: Add a first-class `ownerId` field to conversations and dispatch records. `POST`/`PUT /v1/conversations` and dispatch `record` inputs accept a top-level `ownerId` (stored as `metadata.ownerId`, overriding any nested value); `GET /v1/conversations?ownerId=<id>` filters the list server-side by owner; and conversation responses echo `ownerId` as a top-level field. The SDK's `DispatchRequest.record` gains an `ownerId` field. Enables multi-tenant apps to scope conversations per end-user under a single shared API key.
|
|
2806
|
+
- 102e70b: CSV record upload now supports a constant type. `POST /records/upload-csv` accepts a new optional `typeValue` form field; when set, every imported record receives that type and the header lookup for `typeColumn` is skipped. The dashboard upload dialog gains a "From column" / "Constant" toggle on the Type field, defaulting to "Constant" when no type-like column is auto-detected. The SDK (`records.uploadCsv`) and dashboard API client (`uploadRecordsCsv`) gain a matching optional `typeValue` parameter; `typeValue` takes precedence when both `typeColumn` and `typeValue` are supplied.
|
|
2807
|
+
- 95df762: Make flow step IDs stable across saves and let "Test step" replay against unsaved edits. Previously every `PUT /v1/flows/:id` regenerated all step IDs, which broke the dashboard "Test step" modal (stale id → 404) and orphaned prior `flow_step_results`. Step IDs supplied by the client are now preserved; the server only mints an ID when none is provided. Duplicate IDs within a flow are rejected. `POST /v1/dispatch/test-step` accepts an optional inline `step` config so the dashboard can iterate on unsaved edits without saving the flow first.
|
|
2808
|
+
|
|
2809
|
+
### Patch Changes
|
|
2810
|
+
|
|
2811
|
+
- cd6d918: Address code-review findings on the Claude Managed eval adapter:
|
|
2812
|
+
- Surface eval streaming path now passes `billing` to `adapter.runOnVariant` so platform-key token spend is recorded in Schematic instead of running free.
|
|
2813
|
+
- Eval variant agents are now created with `PLATFORM_ANTHROPIC_KEY` when available so the daily orphan sweeper can reach them regardless of which user spawned the eval. The resolved key is persisted on the `EvalVariantHandle` so archive paths (including the batch DO's terminal cleanup) succeed even when the underlying agent row was deleted mid-batch.
|
|
2814
|
+
- SDK `EvalEndpoint.runVirtualEval` type signature now exposes `agentId` and per-config `claudeManagedOverride` so SDK callers can target Claude Managed agents without casting.
|
|
2815
|
+
- `/eval/stream` route now uses the shared `loadAndGateClaudeManagedAgent` helper instead of re-inlining the six-gate check.
|
|
2816
|
+
- The `claudeManagedOverride` Zod schema in product-surface-eval is extracted to a single constant shared between the realtime and batch request schemas.
|
|
2817
|
+
- `CLAUDE_MANAGED_SYNTHETIC_STEP_ID` is now imported from `agent-internal-executor` in `virtual-eval-executor` and `product-surface-eval` instead of being redeclared / hardcoded.
|
|
2818
|
+
|
|
2819
|
+
## 1.24.2
|
|
2820
|
+
|
|
2821
|
+
### Patch Changes
|
|
2822
|
+
|
|
2823
|
+
- bade11f: External A2A agent enhancements: per-call `skillId` override, A2A 0.3.0 `contextId` threading, and caller-supplied `metadata` merge.
|
|
2824
|
+
|
|
2825
|
+
`ExecuteAgentOptions.externalAgent?: { skillId?; contextId?; metadata? }` — pass a per-call skill override (wins over the cached agent card resolution), a conversation handle to resume an existing A2A conversation, and arbitrary metadata that merges into `params.metadata` alongside the reserved `skill` / `system` keys.
|
|
2826
|
+
|
|
2827
|
+
`AgentCompleteEvent.externalAgent?: { contextId?; taskId? }` and `AgentApprovalStartEvent.externalAgent?: { contextId?; taskId? }` are new optional fields on the wire that surface the upstream-assigned conversation handle and task id. Callers persist `contextId` and pass it back on the next `executeAgent` call to resume the same conversation. Mirrored in `@runtypelabs/shared`'s `sse-parser` types in lockstep so Persona clients can type-check the new fields. Fully additive — the api emitter leaves the field unset and existing parsers ignore unknown fields.
|
|
2828
|
+
|
|
2829
|
+
`runExternalAgentTurn` and `runExternalAgentTurnStreaming` accept an optional 6th `invokeOptions` parameter; `RunExternalAgentTurnResult` gains an optional `contextId?: string` on both `'completed'` and `'paused'` variants.
|
|
2830
|
+
|
|
2831
|
+
`@runtypelabs/sdk` — the SDK's local copies of `AgentApprovalStartEvent` and `AgentCompleteEvent` in `endpoints.ts` gain the same optional `externalAgent` field so callers using `agents.executeWithCallbacks` / `agents.executeWithLocalTools` can access the conversation handle type-safely without casting.
|
|
2832
|
+
|
|
2833
|
+
- 6fbe4ed: Consolidate the `{ contextId?: string; taskId?: string }` shape — previously declared inline 6 times across `@runtypelabs/shared`, `@runtypelabs/runtime`, and `@runtypelabs/sdk` — into a named `ExternalAgentContext` interface. `shared` is the canonical source; the runtime re-exports it; the SDK keeps a structurally identical local copy to preserve its zero-production-dep posture. New type-level parity test pins the consolidated shape across all three surfaces and both variants of `RunExternalAgentTurnResult` via `expectTypeOf`. No wire-format change; the shape is bit-for-bit identical.
|
|
2834
|
+
|
|
2835
|
+
## 1.24.1
|
|
2836
|
+
|
|
2837
|
+
### Patch Changes
|
|
2838
|
+
|
|
2839
|
+
- d659976: Fix persisted flow protocol 422 detection — check statusCode instead of message string
|
|
2840
|
+
- 0442e36: Harden persisted flow 422 detection to handle both error types, add unit tests
|
|
2841
|
+
|
|
2842
|
+
## 1.24.0
|
|
2843
|
+
|
|
2844
|
+
### Minor Changes
|
|
2845
|
+
|
|
2846
|
+
- 761dd74: Add persisted flow protocol (APQ-style) for zero-overhead upsert execution
|
|
2847
|
+
|
|
2848
|
+
SDK now sends only a flow name + content hash on upsert dispatch. If the API recognizes the hash, it executes immediately with no comparison or write overhead. On first deploy or code change, the API responds with FLOW_DEFINITION_REQUIRED and the SDK retries once with the full definition. This eliminates sending the full flow definition over the wire on every execution for the common case (steady-state deployment).
|
|
2849
|
+
|
|
2850
|
+
## 1.23.0
|
|
2851
|
+
|
|
2852
|
+
### Minor Changes
|
|
2853
|
+
|
|
2854
|
+
- 96b2f28: Bulk Edit Records dialog now uses the same record-filter chip builder as the records list, schedules, and per-step record queries. The filter picks fields from the live record schema (with type-aware operators, sample values, and nested AND/OR groups) instead of the hand-rolled equals/contains/etc. select trio.
|
|
2855
|
+
|
|
2856
|
+
The `POST /v1/records/bulk-edit` endpoint, the `bulk_edit_records` MCP tool, and the Code-Mode `bulkEditRecords` spec all accept an optional `recordFilter` (the record-filter DSL) on the request body. The legacy `conditions` shape is still supported for backward compatibility.
|
|
2857
|
+
|
|
2858
|
+
- 5b7e3fe: Add Phase 2 runtime export API endpoints: `GET /v1/flows/:id/export-runtime` and `GET /v1/agents/:id/export-runtime`. These endpoints return fully-resolved, self-contained JSON definitions that the `@runtypelabs/runtime` package can consume at boot with no live database queries needed at execution time.
|
|
2859
|
+
|
|
2860
|
+
Key features:
|
|
2861
|
+
- Flow steps inlined in execution order
|
|
2862
|
+
- Agent capabilities resolved recursively (up to 3 levels of nested sub-agents)
|
|
2863
|
+
- MCP server credentials sanitized — raw tokens replaced with secret-name references, `{{secret:NAME}}` references preserved
|
|
2864
|
+
- External agent credentials unsealed before export
|
|
2865
|
+
- Built-in tool IDs resolved to inline `InlineRuntimeTool` definitions
|
|
2866
|
+
- DB-backed tool TypeIDs fetched and inlined as `InlineToolDefinition` entries
|
|
2867
|
+
|
|
2868
|
+
## 1.22.0
|
|
2869
|
+
|
|
2870
|
+
### Minor Changes
|
|
2871
|
+
|
|
2872
|
+
- de7f600: Add computed `keyStatus` enum to model API responses. The server now resolves per-user key availability at response time, returning `"platform"` (works out of the box), `"custom"` (user brought their own key), or `"needs_setup"` (user action required). This replaces the static `supportsCustomKey: boolean` which was always `true` and provided no useful signal to agents or consumers.
|
|
2873
|
+
|
|
2874
|
+
## 1.21.3
|
|
2875
|
+
|
|
2876
|
+
### Patch Changes
|
|
2877
|
+
|
|
2878
|
+
- 569e7d5: Rename model field `requiresApiKey` to `supportsCustomKey` to clarify that models are available by default via platform keys and custom API keys are optional (BYOK). Rename embedding model field `requiresApiKey` string to `customKeyProvider` for consistency.
|
|
2879
|
+
|
|
2880
|
+
## 1.21.2
|
|
2881
|
+
|
|
2882
|
+
### Patch Changes
|
|
2883
|
+
|
|
2884
|
+
- b3a580e: Consolidate SDK builder and product surface skill config types around canonical shared contracts.
|
|
2885
|
+
|
|
2886
|
+
## 1.21.1
|
|
2887
|
+
|
|
2888
|
+
### Patch Changes
|
|
2889
|
+
|
|
2890
|
+
- c5e0c1d: Consolidate entity types into single source of truth in packages/shared
|
|
2891
|
+
- Define canonical API response entity types (Agent, Surface, SurfaceItem, SurfaceKey, Product, Capability, ApiKey, UserModelConfig) in packages/shared/src/types/entities.ts
|
|
2892
|
+
- Update packages/shared/src/types/client-types.ts with comprehensive Flow, FlowStep, RuntypeRecord types matching actual API response shapes
|
|
2893
|
+
- Update dashboard product types to re-export from @runtypelabs/shared instead of maintaining independent definitions
|
|
2894
|
+
- Remove dead packages/types package (zero imports across codebase, stale column references)
|
|
2895
|
+
- Remove dead convertKeysToCamelCase/convertKeysToSnakeCase code from SDK transform.ts (pass-through since API uses native camelCase)
|
|
2896
|
+
- Use SurfaceBehavior discriminated union from shared for Surface.behavior typing
|
|
2897
|
+
|
|
2898
|
+
## 1.21.0
|
|
2899
|
+
|
|
2900
|
+
### Minor Changes
|
|
2901
|
+
|
|
2902
|
+
- 5190fd0: Add type-driven SDK code generation metadata registry that prevents silent drift between SDK config interfaces and the dashboard code generator
|
|
2903
|
+
|
|
2904
|
+
## 1.20.0
|
|
2905
|
+
|
|
2906
|
+
### Minor Changes
|
|
2907
|
+
|
|
2908
|
+
- f777029: Linear-style chip+popover record filter builder (`RecordFilterChips`), unified across the schedules page and the `retrieve-record` flow step card. Same `RecordFilter` wire shape — drop-in for the existing builder.
|
|
2909
|
+
|
|
2910
|
+
Each chip is split into independent segments (`field | op | value | X`) with per-segment popovers. The value popover for set-membership / equality on string fields now renders a contextual list of distinct field values with per-value match counts (Linear-style), backed by a new `GET /v1/records/field-values?type=&field=` endpoint. Free-text fallback preserved via "Use 'X'" search row.
|
|
2911
|
+
|
|
2912
|
+
**Schedule UI unification**: dropped the three-way `Record Target` mode selector (`All records of a type` / `Specific record IDs` / `Records matching a filter`). The chip filter is now the single way to target records, since:
|
|
2913
|
+
- `id`, `name`, `createdAt`, `updatedAt` are now reachable as top-level columns in the filter compiler — `id is one of [...]` covers what `Specific record IDs` used to do.
|
|
2914
|
+
- A filter with type only and no chips covers what `All records of a type` used to do.
|
|
2915
|
+
|
|
2916
|
+
A "Paste IDs" button drops a pre-filled `id is one of [...]` chip for power users with a list to paste; the value picker also bulk-adds when you paste a comma- or newline-separated list into its search input. Old saved schedules still load (and their `recordType` / `recordIds` are normalized into a chip filter on edit) — the executor's resolver still understands all three legacy fields, so existing schedules keep running unchanged.
|
|
2917
|
+
|
|
2918
|
+
**`retrieve-record` step now accepts a `recordFilter`**: in query mode, the step card renders the same `RecordFilterChips` UI, replacing the `where type is X / and name contains Y` two-row form. The new `config.recordFilter` is validated via `recordFilterSchema`, normalized through the shared normalizer, and AND-ed into the executor's where clause (with `{{template}}` substitution applied to chip values before compilation). Legacy `recordType` / `recordName` keep working — old saved steps load by normalizing into chips, and the executor still falls back to the legacy fields when no `recordFilter` is set.
|
|
2919
|
+
|
|
2920
|
+
**`update-record` step gets the same treatment**: a new "Find record" radio at the top of the step card lets users target by context (`_record`, the existing default), by ID, or by chip filter. When a filter is set, the executor compiles it with templates substituted and takes the first match (ordered by `updatedAt desc`). Filter validation is enforced at validate-time via a new `updateRecordConfigSchema`. Same backward-compatibility story: legacy `recordType` / `recordName` keep working until the user edits.
|
|
2921
|
+
|
|
2922
|
+
**MCP discoverability**: the `create-flow` / `update-flow` / `validate-flow` MCP tool descriptions now document `recordFilter` as a valid `config` shape for `retrieve-record` and `update-record`, including the operator allowlist and reachable top-level columns. New `RecordFilter`, `RecordFilterCondition`, `RecordFilterGroup`, `RecordFilterOperator`, `RetrieveRecordConfig`, and `UpdateRecordConfig` types are added to `runtype://types/flow-steps` so agent clients see the shape directly. `flow-step-type-metadata.ts` config-hints lines now mention `recordFilter` for both steps. The runtime passthrough already worked (config is forwarded as an opaque object); this slice makes it discoverable.
|
|
2923
|
+
|
|
2924
|
+
Also fix two bugs surfaced by the new UI:
|
|
2925
|
+
- **`/v1/records/preview-filter` 500 on `is one of` / `is not one of`**: drizzle's `sql` template expanded `${array}` as a row constructor `($1, $2)`, so `= ANY(${list})` compiled to `text = ANY(($1, $2))` and Postgres rejected it as `text = record`. Switched both `in` and `notIn` to the `IN (${list})` form, which compiles to the correct `text IN ($1, $2)`. Pinned with a regression test.
|
|
2926
|
+
- **Trailing comma vanished while typing in the multi-value input**: every keystroke re-rendered from the parsed array, eating the comma. Now holds the raw typed text in local state and keeps the parsed array in sync on every keystroke so Apply still reads a fresh value.
|
|
2927
|
+
|
|
2928
|
+
## 1.19.1
|
|
2929
|
+
|
|
2930
|
+
### Patch Changes
|
|
2931
|
+
|
|
2932
|
+
- 7712f0d: Expose flowTimeoutMs/stepTimeoutMs in dispatch options, add timeout abort smoke test, and fix partial token accounting on aborted prompt steps
|
|
2933
|
+
|
|
2934
|
+
## 1.19.0
|
|
2935
|
+
|
|
2936
|
+
### Minor Changes
|
|
2937
|
+
|
|
2938
|
+
- e6d59df: Add per-step `when` predicate for conditional step execution. Any step can carry
|
|
2939
|
+
a JS expression evaluated at runtime; if falsy the step is skipped with its
|
|
2940
|
+
outputVariable set to null and a `step_skip` SSE event emitted. Default-skip-on-
|
|
2941
|
+
throw; opt into fail-loud via `errorHandling.onError: 'fail'`.
|
|
2942
|
+
|
|
2943
|
+
## 1.18.1
|
|
2944
|
+
|
|
2945
|
+
### Patch Changes
|
|
2946
|
+
|
|
2947
|
+
- 778a8be: Fix flow tools failing when referenced via saved tool ID instead of direct flowId
|
|
2948
|
+
|
|
2949
|
+
When a saved tool with `toolType: 'flow'` was added as an agent capability, the dashboard and API built the runtime tool config with `config.toolId` (the saved tool's database ID) instead of `config.flowId` (the ID of the flow to execute). This caused validation to fail with "Flow tool missing flowId".
|
|
2950
|
+
- Dashboard now resolves saved tool config to extract the actual `flowId`
|
|
2951
|
+
- API executor resolves `config.toolId` → saved tool → `flowId` at execution time
|
|
2952
|
+
- Validation accepts either `flowId` or `toolId` for flow tools
|
|
2953
|
+
- Added end-to-end smoke test for flow-as-tool on agents
|
|
2954
|
+
|
|
2955
|
+
## 1.18.0
|
|
2956
|
+
|
|
2957
|
+
### Minor Changes
|
|
2958
|
+
|
|
2959
|
+
- 7070cfb: Remove `chunk` from the SDK's `step_delta` event shape, the
|
|
2960
|
+
`StepChunkEvent` alias, and the `onStepChunk` callback. Customers migrate
|
|
2961
|
+
to `text` and `onStepDelta`. Bruno API examples and the dashboard's
|
|
2962
|
+
generated SDK code now use the new field/callback names. The shared
|
|
2963
|
+
flow-execution streaming hook drops its unrelated `data.content` legacy
|
|
2964
|
+
reader. Runtime: `StepDeltaEventData` adds optional `partId? /
|
|
2965
|
+
messageId? / toolId?` fields to match the api's canonical
|
|
2966
|
+
`StepDeltaData` per the api-parity-for-ports rule.
|
|
2967
|
+
|
|
2968
|
+
### Patch Changes
|
|
2969
|
+
|
|
2970
|
+
- e886078: Add first-class `agent_media` SSE events for multimodal tool output, aligned with AI SDK standards. Media types use AI SDK v3/v4 content-part shapes (`media`, `image-url`, `file-url`) and tools wire up `toModelOutput` so models receive native multimodal content. Messaging surfaces (Telegram, Slack) collect and deliver media natively via channel adapters.
|
|
2971
|
+
- e6fcbe6: Add media visibility control for agent_media SSE events
|
|
2972
|
+
|
|
2973
|
+
Two-layer visibility system: MCP `annotations.audience` on content parts (spec compliance) and tool-level `mediaVisibility` config via `toolConfigs`. Tools can now return media to the model for reasoning without it being shown to the user. Default behavior unchanged — all existing tools continue to show media to both audiences.
|
|
2974
|
+
|
|
2975
|
+
- 94261ac: Restore browser tools and add dedicated Browser category with namespaced tool IDs
|
|
2976
|
+
- Unhide all 16 browser tools (7 quick-action + 9 session) that were hidden pending staging validation
|
|
2977
|
+
- Add `BROWSER` category to separate browser tools from generic web scraping
|
|
2978
|
+
- Rename tool IDs from `browser-*` to `browser:*` namespace format (e.g. `builtin:browser:screenshot`)
|
|
2979
|
+
- Add alias support for backward compatibility with legacy `browser-*` IDs
|
|
2980
|
+
- Add Browser ToolGroupCard in the dashboard tools sheet
|
|
2981
|
+
|
|
2982
|
+
- 91db7b9: Add typed agent approval stream events and callbacks to the TypeScript SDK.
|
|
2983
|
+
|
|
2984
|
+
## 1.17.1
|
|
2985
|
+
|
|
2986
|
+
### Patch Changes
|
|
2987
|
+
|
|
2988
|
+
- 28f126c: Thread AI SDK `finishReason` through the model-execution stream into dispatch `step_complete` SSE events as a new `stopReason` field, and — for parity — onto `agent_turn_complete` on both the API agent-loop path (`/agents/:id/execute`, `/dispatch`, `/product-chat`, `/mcp-capability`) and the self-hosted runtime. Clients can now distinguish a model invocation that ended naturally (`end_turn`) from one that was capped mid-loop by `stopWhen` (`max_tool_calls`), plus `length`, `content_filter`, `error`, and `unknown`. Fixes the empty-chat-bubble symptom in the dashboard when a virtual-agent tool call hits `maxToolCalls: 1`: the follow-up model invocation was cut off silently and the UI had no way to explain why.
|
|
2989
|
+
|
|
2990
|
+
`@runtypelabs/runtime` mirrors the feature end-to-end: `PromptStepResult.stopReason` exposes the per-step value, `FlowEngineResult.lastStopReason` surfaces the last-prompt-step reason of a flow run, and `AgentTurnCompleteEventData.stopReason` lands on the `agent_turn_complete` SSE event so self-hosted Persona clients see the same signal as the hosted API. `StepStopReason` and `mapFinishReasonToStopReason` are now re-exported from the runtime barrel so external consumers can type-annotate the new field.
|
|
2991
|
+
|
|
2992
|
+
`@runtypelabs/sdk` gains `stopReason` on its `AgentTurnCompleteEvent` interface — the public SDK surface was missing the field even though the wire carried it.
|
|
2993
|
+
|
|
2994
|
+
**Bug fixes pulled in alongside the feature**:
|
|
2995
|
+
- `collectUsageWithTimeout` (and the three inline variants in `cloudflare-gateway-executor`, `workers-ai-executor`, `mixlayer-executor`) no longer discard an already-resolved `finishReason` when the usage race times out. Previously `Promise.all` rejected the whole await when the usage arm rejected, losing `finishReason: 'tool-calls'` that had arrived at t=0 — re-creating the empty-bubble symptom for providers with slow usage accounting. Switched to `Promise.allSettled` so the two arms resolve independently.
|
|
2996
|
+
|
|
2997
|
+
**Python SDK** (`packages/python-sdk`, versioned separately): `StepCompleteEvent` gains an optional `stop_reason` field with `AliasChoices('stop_reason', 'stopReason')`, plus a new `StepStopReason` Literal type. Full agent-loop event modeling (`agent_turn_complete`, etc.) in the Python SDK is out of scope — it doesn't model agent events today.
|
|
2998
|
+
|
|
2999
|
+
## 1.17.0
|
|
3000
|
+
|
|
3001
|
+
### Minor Changes
|
|
3002
|
+
|
|
3003
|
+
- 060278a: Add Subagent tool authoring UI and SDK builder methods.
|
|
3004
|
+
|
|
3005
|
+
Dashboard: `subagent` is now selectable in the Create Tool dialog. The tool
|
|
3006
|
+
detail page exposes an agent picker (from `/v1/agents`), an allowed-tools
|
|
3007
|
+
multiselect drawn from the selected agent's configured tools, an output
|
|
3008
|
+
format radio (`text` / `json` / `last_message`), and optional `maxTurns`,
|
|
3009
|
+
`timeoutMs`, `taskTemplate`, and `inheritMessages` controls. Tools list
|
|
3010
|
+
renders a Bot icon + "Subagent" badge for the new type.
|
|
3011
|
+
|
|
3012
|
+
SDK: `FlowBuilder` gains `.withSubagentTool(name, opts)` (attach a subagent
|
|
3013
|
+
runtime tool to the most recent prompt step) and `.withSubagents(opts)`
|
|
3014
|
+
(enable agent-driven dynamic spawning via the synthesized `spawn_subagent`
|
|
3015
|
+
tool). `Tool`, `ToolConfig`, `RuntimeTool`, and `ToolsConfig` types are
|
|
3016
|
+
extended with `'subagent'` and the new `SubagentToolConfig` /
|
|
3017
|
+
`RuntimeSubagentToolConfig` / `AgentSubagentConfig` shapes.
|
|
3018
|
+
|
|
3019
|
+
The API trust boundary (tool-pool intersection, leak guard propagation,
|
|
3020
|
+
recursion depth, per-run spawn ceiling) is unchanged — this PR is a
|
|
3021
|
+
UX-only veneer over the already-shipped API engine.
|
|
3022
|
+
|
|
3023
|
+
## 1.16.0
|
|
3024
|
+
|
|
3025
|
+
### Minor Changes
|
|
3026
|
+
|
|
3027
|
+
- 23b42c8: Add sampling config parameters (topP, topK, frequencyPenalty, presencePenalty, seed) for model execution
|
|
3028
|
+
|
|
3029
|
+
Adds end-to-end support for five new sampling parameters across the platform:
|
|
3030
|
+
- API: ExecutionOptions, all model executors, prompt executor, agent executor, dispatch/flow-steps validation
|
|
3031
|
+
- Dashboard: New SamplingParameterControl component, model selector, prompt card, agent editor
|
|
3032
|
+
- SDK: Prompt step builders, prompt run options, eval overrides, agent execute request, and shared dispatch/eval override types
|
|
3033
|
+
- All params default to undefined (use model default) with no fallback values
|
|
3034
|
+
- Qwen 3.5 open-weight models routed through Mixlayer still apply their specialized defaults when these fields are unset, but any explicitly configured sampling value takes precedence over those Qwen fallbacks
|
|
3035
|
+
|
|
3036
|
+
## 1.15.3
|
|
3037
|
+
|
|
3038
|
+
### Patch Changes
|
|
3039
|
+
|
|
3040
|
+
- 60dbf93: Improve `deploy_sandbox` on the Cloudflare Sandbox provider: auto-create parent directories when writing nested `files` entries, reject reserved port 3000 up front with a clear message, default to port 8080, and return a `stage` field plus captured stdout/stderr in `output` on failure for easier debugging.
|
|
3041
|
+
|
|
3042
|
+
## 1.15.2
|
|
3043
|
+
|
|
3044
|
+
### Patch Changes
|
|
3045
|
+
|
|
3046
|
+
- 64dfdb5: Replace stale model references in user-facing examples, JSDoc, templates, and builtin-tool compatibility lists. After the tranche-2 model curation, several example and documentation sites still referenced models that had been filtered from the generated catalog (`gpt-3.5-turbo`, `gpt-4-turbo`, `o1`, `o1-mini`, `claude-3-5-sonnet`, `claude-3-opus`, `gemini-1.5-flash`, `gemini-2.0-flash`, `gemini-pro`, `grok-3`, `grok-3-mini`). Users copying those examples would receive model-not-found errors.
|
|
3047
|
+
|
|
3048
|
+
Touched:
|
|
3049
|
+
- `apps/dashboard/lib/constants/vector-flow-templates.ts` — user-facing vector flow template (`gpt-3.5-turbo` → `gpt-5-nano`)
|
|
3050
|
+
- `apps/dashboard/lib/api-request-generator.ts` — dashboard-generated API example payloads (eval comparison pair → `claude-sonnet-4-6`, `gemini-3-flash`)
|
|
3051
|
+
- `apps/dashboard/lib/sdk-completions.ts` — SDK autocompletion options for the `model` field (OpenAI + Anthropic + Google current)
|
|
3052
|
+
- `apps/dashboard/lib/sdk-code-generator.ts` — SDK eval-comparison example (`gpt-5.4`, `claude-opus-4-6`, `gemini-3.1-pro`)
|
|
3053
|
+
- `packages/mcp/src/core/tools.ts` — `run_prompt` / `execute_agent` MCP tool schema descriptions (example model triplet in the `model` arg description)
|
|
3054
|
+
- `packages/client/src/runtype.ts`, `evals-namespace.ts`, `eval-builder.ts` — five JSDoc `@example` blocks that showed `compareModels` usage with `claude-3-opus` / `gpt-4o` / `gemini-pro`
|
|
3055
|
+
- `packages/shared/src/product-generation/knowledge-fragments.ts` — rewrote the xAI Live Search compatibility paragraph to drop grok-3 advice (grok-3 is no longer in the catalog)
|
|
3056
|
+
- `packages/shared/src/builtin-tools-registry.ts` — `modelCompatibility` lists for DALL-E, OpenAI web search, Anthropic web search/fetch, and xAI Live Search: removed filtered-out models and added current ones
|
|
3057
|
+
|
|
3058
|
+
No runtime behavior changes — this is all documentation, example code, and compatibility-list hygiene.
|
|
3059
|
+
|
|
3060
|
+
## 1.15.1
|
|
3061
|
+
|
|
3062
|
+
### Patch Changes
|
|
3063
|
+
|
|
3064
|
+
- ca82595: Fix Cloudflare Sandbox deploy/cleanup routes overflowing the SDK's 63-char sandbox ID limit
|
|
3065
|
+
|
|
3066
|
+
The `@cloudflare/sandbox` SDK's `sanitizeSandboxId()` throws a `SecurityError` when the ID exceeds 63 chars (DNS subdomain limit). The prior scoping format — `${user.orgId || user.userId}_cf-sandbox-${uuid}` — produced ~76-char IDs with Clerk-style org/user IDs, so every call to `/tools/sandbox/cf-sandbox/deploy` threw before reaching the inner try/catch and returned a generic 500 `Failed to deploy Cloudflare Sandbox`. Replace the direct prefix with a 12-hex-char SHA-256 tenant hash so scoped IDs land under 50 chars, and lowercase the result to avoid the SDK's case-insensitivity warning on preview hostnames. The SDK client now appends `details` to error messages when the API returns a `{ error, details }` shape, so future failures like this aren't hidden behind the top-level label.
|
|
3067
|
+
|
|
3068
|
+
## 1.15.0
|
|
3069
|
+
|
|
3070
|
+
### Minor Changes
|
|
3071
|
+
|
|
3072
|
+
- 2820927: Replace the `cloudflare-shell` sandbox provider with `cloudflare-sandbox`, backed by `@cloudflare/sandbox`.
|
|
3073
|
+
- `sandboxProvider` on transform-data steps and custom runtime tools accepts `'cloudflare-sandbox'` instead of `'cloudflare-shell'`.
|
|
3074
|
+
- New `CloudflareSandboxDO` container-backed Durable Object replaces `ShellSandboxDO`. Each sandbox is a full Linux computer (Node 22, Python 3.12, pnpm, tsx, uv, git) with snapshot-backed persistence, preview URLs, and Active-CPU pricing.
|
|
3075
|
+
- New routes: `POST /tools/sandbox/cf-sandbox/deploy` and `DELETE /tools/sandbox/cf-sandbox/:sandboxId`. The old `cf-shell` routes are removed.
|
|
3076
|
+
- SDK: `deployCfShell` / `cleanupCfShell` renamed to `deployCfSandbox` / `cleanupCfSandbox`. `DeployCfShellRequest` / `DeployCfShellResponse` renamed to `DeployCfSandboxRequest` / `DeployCfSandboxResponse`.
|
|
3077
|
+
- CLI: `createDeployCfShellLocalTool` / `cleanupCfShellWorkers` renamed to `createDeployCfSandboxLocalTool` / `cleanupCfSandboxes`. Python is now a supported language for Cloudflare Sandbox.
|
|
3078
|
+
- Infrastructure: wrangler migration `v7` drops `ShellSandboxDO` and adds `CloudflareSandboxDO`. `SHELL_STORAGE` R2 binding renamed to `SANDBOX_STORAGE`. Requires Workers Paid + Containers add-on on the Cloudflare account.
|
|
3079
|
+
|
|
3080
|
+
Breaking change: any caller passing `sandboxProvider: 'cloudflare-shell'` must switch to `'cloudflare-sandbox'`. There was no production usage of the old provider, so the impact is limited to internal testing.
|
|
3081
|
+
|
|
3082
|
+
## 1.14.1
|
|
3083
|
+
|
|
3084
|
+
### Patch Changes
|
|
3085
|
+
|
|
3086
|
+
- 799f8db: Extend `BuiltInTool` category union for commerce and artifact tools; type `IntegrationToolsCombobox` for minimal tool rows used by built-in groupings.
|
|
3087
|
+
|
|
3088
|
+
## 1.14.0
|
|
3089
|
+
|
|
3090
|
+
### Minor Changes
|
|
3091
|
+
|
|
3092
|
+
- 040c7e8: Add body template support for external tools. External tool configs now accept an optional `body` field with `{{variable}}` interpolation, enabling control over the exact JSON body structure sent to APIs. When absent, behavior is unchanged (remaining parameters auto-serialized).
|
|
3093
|
+
|
|
3094
|
+
## 1.13.3
|
|
3095
|
+
|
|
3096
|
+
### Patch Changes
|
|
3097
|
+
|
|
3098
|
+
- e10c4d4: Fix marathon tasks completing prematurely by preventing auto-waive from forcing plan-written and best-candidate-verified gates open, and routing stopReason=complete through workflow canAcceptCompletion gates.
|
|
3099
|
+
|
|
3100
|
+
## 1.13.2
|
|
3101
|
+
|
|
3102
|
+
### Patch Changes
|
|
3103
|
+
|
|
3104
|
+
- 7f727ab: feat: add record management built-in tools for agents
|
|
3105
|
+
|
|
3106
|
+
Adds 5 new built-in tools (runtype_record_upsert, runtype_record_batch_upsert, runtype_record_get, runtype_record_list, runtype_record_delete) that enable agents to create, read, update, and delete Runtype records during execution. Tools appear as a grouped "Record Management" section in the tool picker with a select-all checkbox.
|
|
3107
|
+
|
|
3108
|
+
- 19b9c08: fix(sdk): refine marathon task agent workflow phase handling and resume copy
|
|
3109
|
+
|
|
3110
|
+
Align `TASK_COMPLETE` checks with the workflow phase at session start when the phase transitions mid-turn. Treat non-default execute phases as execution-like for local tool trace bookkeeping. Distinguish forced-compaction and continuation guardrails for in-progress (saved) tasks versus completed tasks.
|
|
3111
|
+
|
|
3112
|
+
## 1.13.1
|
|
3113
|
+
|
|
3114
|
+
### Patch Changes
|
|
3115
|
+
|
|
3116
|
+
- d73361a: Disable source maps in published packages to reduce npm package size
|
|
3117
|
+
|
|
3118
|
+
## 1.13.0
|
|
3119
|
+
|
|
3120
|
+
### Minor Changes
|
|
3121
|
+
|
|
3122
|
+
- 2de3530: Add `deployCfShell` and `cleanupCfShell` methods to the Tools endpoint
|
|
3123
|
+
|
|
3124
|
+
## 1.12.0
|
|
3125
|
+
|
|
3126
|
+
### Minor Changes
|
|
3127
|
+
|
|
3128
|
+
- 62c2f83: Add Cloudflare Shell as a new sandbox provider for Marathon CLI
|
|
3129
|
+
|
|
3130
|
+
Introduces `cloudflare-shell` as an alternative to Daytona for agent code execution in Marathon. Uses `@cloudflare/worker-bundler` for runtime TypeScript compilation and npm dependency resolution, and `@cloudflare/shell` for virtual filesystem persistence backed by SQLite + R2.
|
|
3131
|
+
|
|
3132
|
+
Key features:
|
|
3133
|
+
- JavaScript and TypeScript execution with npm dependencies
|
|
3134
|
+
- Virtual filesystem persistence via `@cloudflare/shell` Workspace
|
|
3135
|
+
- Deploy-with-preview via persistent Dynamic Workers
|
|
3136
|
+
- No API key required (uses existing Cloudflare Workers infrastructure)
|
|
3137
|
+
- ~1-5ms startup vs ~100-500ms for Daytona
|
|
3138
|
+
|
|
3139
|
+
Usage: `runtype task "your task" --sandbox cloudflare-shell`
|
|
3140
|
+
|
|
3141
|
+
## 1.11.0
|
|
3142
|
+
|
|
3143
|
+
### Minor Changes
|
|
3144
|
+
|
|
3145
|
+
- cc9ff7a: Add Orthogonal-backed platform tools with hierarchical `platform:orthogonal:company:tool` ID format, catalog generation, managed execution, and spend tracking via DO + Analytics Engine.
|
|
3146
|
+
|
|
3147
|
+
## 1.10.2
|
|
3148
|
+
|
|
3149
|
+
### Patch Changes
|
|
3150
|
+
|
|
3151
|
+
- 9e3fee1: Fix marathon session reliability: resolve completion deadlocks (verification auto-waive, premature TASK_COMPLETE), fix write loops and stall detection, retain accumulated cost across checkpoint restarts, retry server-side network errors in session loop, and add 'o' key to open files from Files tab or open agent in dashboard
|
|
3152
|
+
|
|
3153
|
+
## 1.10.1
|
|
3154
|
+
|
|
3155
|
+
### Patch Changes
|
|
3156
|
+
|
|
3157
|
+
- ce76184: Fix the SDK package entrypoints to emit stable ESM and CommonJS bundles for workspace consumers.
|
|
3158
|
+
|
|
3159
|
+
## 1.10.0
|
|
3160
|
+
|
|
3161
|
+
### Minor Changes
|
|
3162
|
+
|
|
3163
|
+
- 190adf8: Add agent fallback-model and playbook policy support across the API, CLI, and SDK.
|
|
3164
|
+
|
|
3165
|
+
Improve marathon task execution with safer verification handling, creation-task output constraints, and better recovery when verification is repeatedly blocked.
|
|
3166
|
+
|
|
3167
|
+
## 1.9.2
|
|
3168
|
+
|
|
3169
|
+
### Patch Changes
|
|
3170
|
+
|
|
3171
|
+
- bd08d42: Wire streamed tool input through the API, SDK, and Marathon CLI, keep local tools active through client-side execution, and enable Anthropic eager input streaming behind a feature flag.
|
|
3172
|
+
|
|
3173
|
+
## 1.9.1
|
|
3174
|
+
|
|
3175
|
+
### Patch Changes
|
|
3176
|
+
|
|
3177
|
+
- 8494865: Wire streamed tool input through the API, SDK, and Marathon CLI, keep local tools active through client-side execution, and enable Anthropic eager input streaming behind a feature flag.
|
|
3178
|
+
- f49d2d6: Improve Marathon build-and-serve workflow routing for prompts that ask the agent to create a runnable web app, serve it, and verify routes.
|
|
3179
|
+
|
|
3180
|
+
## 1.9.0
|
|
3181
|
+
|
|
3182
|
+
### Minor Changes
|
|
3183
|
+
|
|
3184
|
+
- 152019b: Add a first-class Cloudflare Browser Rendering `crawl` flow step with synchronous execution, settings-based credentials, per-page platform billing, and editor/SDK authoring support.
|
|
3185
|
+
|
|
3186
|
+
### Patch Changes
|
|
3187
|
+
|
|
3188
|
+
- b6d2ceb: Fix Marathon history replay so local tool call/result pairs stay valid when continuation history is trimmed or resumed. This prevents Anthropic and Claude runs from failing on orphaned `tool_result` messages during Marathon continuation.
|
|
3189
|
+
|
|
3190
|
+
## 1.8.2
|
|
3191
|
+
|
|
3192
|
+
### Patch Changes
|
|
3193
|
+
|
|
3194
|
+
- c7229a9: Make marathon web research tasks honor the existing `external` workflow variant end-to-end. External prompts now steer agents toward built-in web tools, block repo discovery during research, and stop injecting repo-editing guidance into session context for website-focused runs.
|
|
3195
|
+
- c7229a9: Make marathon external research tasks write their final findings to a workspace markdown file before completion. External runs now default that artifact path to `<task-slug>.md`, require `write_file` to that path, and do not accept `TASK_COMPLETE` until the markdown report has been saved.
|
|
3196
|
+
|
|
3197
|
+
## 1.8.1
|
|
3198
|
+
|
|
3199
|
+
### Patch Changes
|
|
3200
|
+
|
|
3201
|
+
- 4ec90b5: Fix `--compact-threshold` parsing to remove ambiguous bare-ratio format. The flag now accepts only two formats: percent (e.g. `--compact-threshold 80%`) and absolute token count (e.g. `--compact-threshold 120000`). Bare decimal values like `0.8` are no longer interpreted as ratios. Also ensure provider-native compaction lifecycle cleanup fires even when session execution throws, preventing a stuck compaction indicator in the TUI.
|
|
3202
|
+
- 4ec90b5: Add provider-aware marathon context management with model-budget-aware compaction thresholds, compaction lifecycle telemetry, structured compact summaries, CLI controls for compaction strategy and instructions, and tool-output guardrails that surface or offload oversized local tool results.
|
|
3203
|
+
|
|
3204
|
+
## 1.8.0
|
|
3205
|
+
|
|
3206
|
+
### Minor Changes
|
|
3207
|
+
|
|
3208
|
+
- 564d33c: Add --tools flag to marathon command for enabling built-in tools (exa, firecrawl, dalle, web search, etc.) during agent runs
|
|
3209
|
+
|
|
3210
|
+
## 1.7.3
|
|
3211
|
+
|
|
3212
|
+
### Patch Changes
|
|
3213
|
+
|
|
3214
|
+
- f9b1333: Switch SDK build from tsc (CommonJS) to tsup (dual ESM + CJS) to fix named export errors when consumed by ESM packages like the CLI on Node.js v24+
|
|
3215
|
+
|
|
3216
|
+
## 1.7.2
|
|
3217
|
+
|
|
3218
|
+
### Patch Changes
|
|
3219
|
+
|
|
3220
|
+
- cb689ac: Improve marathon safety and verification by checkpointing original files before writes, adding rollback and guarded verification tools, and requiring successful verification before completion.
|
|
3221
|
+
- cb689ac: Fix marathon resume and execution-state handling so resumed or restarted runs keep their workflow phase, advance cleanly from planning into execution, avoid reusing the wrong local-tool results across resume cycles, and stop reporting errored runs as completed.
|
|
3222
|
+
- cb689ac: Tighten marathon execution target tracking by trimming candidate paths, ignoring scratch-file writes as targets, blocking planning/execution writes to undeclared files, sanitizing poisoned saved marathon state on resume, and surfacing clearer rate-limit details when marathon hits a 429.
|
|
3223
|
+
- cb689ac: Harden marathon repo-editing runs by requiring stronger UX-task research, preserving existing functionality during execution, preferring tool-trace memory over freeform narration, and blocking completion until the edited target is re-read after writes.
|
|
3224
|
+
- cb689ac: Fix marathon execution loops by only advancing after a successful write to the exact plan path, ignoring `.runtype` artifact candidates, and blocking redundant execution-phase discovery until the current target read fails.
|
|
3225
|
+
|
|
3226
|
+
## 1.7.1
|
|
3227
|
+
|
|
3228
|
+
### Patch Changes
|
|
3229
|
+
|
|
3230
|
+
- 458711d: refactor: remove modelsocket provider, consolidate onto mixlayer
|
|
3231
|
+
|
|
3232
|
+
Removes the redundant `modelsocket` provider and consolidates all model routing onto `mixlayer`. Both providers were backed by the same Mixlayer infrastructure (`https://models.mixlayer.ai`) and shared the same API key. This simplifies the codebase and removes the `modelsocket` npm dependency.
|
|
3233
|
+
|
|
3234
|
+
Key changes:
|
|
3235
|
+
- Rewrites `/chat` endpoint from proprietary WebSocket SDK to AI SDK `streamText()`
|
|
3236
|
+
- Adds backward compatibility: stored `modelsocket` references transparently resolve to `mixlayer`
|
|
3237
|
+
- Includes database migration to convert existing `modelsocket` records to `mixlayer`
|
|
3238
|
+
- Removes `modelsocket-executor.ts` and related test files
|
|
3239
|
+
- Updates all dashboard UI, routing, and config files
|
|
3240
|
+
- Keeps `modelsocketKey` field name and `MODELSOCKET_*` env vars for infrastructure compatibility
|
|
3241
|
+
|
|
3242
|
+
## 1.7.0
|
|
3243
|
+
|
|
3244
|
+
### Minor Changes
|
|
3245
|
+
|
|
3246
|
+
- 3531abb: Make Cloudflare Worker the default sandbox provider for transform-data steps, soft-deprecating QuickJS as legacy
|
|
3247
|
+
|
|
3248
|
+
## 1.6.0
|
|
3249
|
+
|
|
3250
|
+
### Minor Changes
|
|
3251
|
+
|
|
3252
|
+
- 57ca1e0: Add Cloudflare Worker-Loader sandbox provider for transform-data steps
|
|
3253
|
+
- Add cloudflare-worker as third sandbox provider option
|
|
3254
|
+
- Full async/await support with V8 isolate sandboxing
|
|
3255
|
+
- Helper function injection and console output capture
|
|
3256
|
+
- Network isolation and configurable timeout
|
|
3257
|
+
- Zero cost (in-process, no external API calls)
|
|
3258
|
+
- Runtime-aware AI code generation: magic button and flow generator now produce code matching the selected runtime's constraints (sync-only for QuickJS, helpers.\* namespace for Cloudflare Worker, fetch/npm for Daytona)
|
|
3259
|
+
|
|
3260
|
+
## 1.5.1
|
|
3261
|
+
|
|
3262
|
+
### Patch Changes
|
|
3263
|
+
|
|
3264
|
+
- 077b0ff: Internal maintenance: update comments and rename imports for clarity
|
|
3265
|
+
|
|
3266
|
+
## 1.5.0
|
|
3267
|
+
|
|
3268
|
+
### Minor Changes
|
|
3269
|
+
|
|
3270
|
+
- a96ce5d: Rename `maxIterations` to `maxTurns` in agent loop configuration and SSE event types to align with industry conventions (OpenAI, Anthropic, Vercel AI SDK). The `stopReason` value `max_iterations` is now `max_turns`.
|
|
3271
|
+
|
|
3272
|
+
### Patch Changes
|
|
3273
|
+
|
|
3274
|
+
- 8505d96: Add 'timeout' to agent loop stop reason types for wall-clock timeout guard
|
|
3275
|
+
|
|
3276
|
+
## 1.4.0
|
|
3277
|
+
|
|
3278
|
+
### Minor Changes
|
|
3279
|
+
|
|
3280
|
+
- ed4d85a: Unify SSE event naming across the platform
|
|
3281
|
+
- Rename `step_chunk` to `step_delta` (aligns with Anthropic/OpenAI/Vercel convention)
|
|
3282
|
+
- Rename `flow_paused` to `flow_await`, `step_waiting_local` to `step_await`, `agent_paused` to `agent_await`
|
|
3283
|
+
- Consolidate fallback events: merge `fallbacks_initiated` into `fallback_start`, unify `fallback_success`/`fallback_fail` into `fallback_complete`, rename `fallbacks_exhausted` to `fallback_exhausted`
|
|
3284
|
+
- Add structured TypeScript interfaces for tool events (`ToolStartEventData`, `ToolCompleteEventData`, `ToolErrorEventData`)
|
|
3285
|
+
- Formalize `tool_error` as a first-class event type with `emitToolError()` method
|
|
3286
|
+
|
|
3287
|
+
All renames use dual-emit for backwards compatibility: the API sends both the new and legacy event names during the transition period. SDK consumers accept both names.
|
|
3288
|
+
|
|
3289
|
+
## 1.3.0
|
|
3290
|
+
|
|
3291
|
+
### Minor Changes
|
|
3292
|
+
|
|
3293
|
+
- ffab49e: Add marathon continuation support: RunTaskContinuation type, previousMessages/continuationMessage/compact options, costByModel tracking, and compact summary for resume
|
|
3294
|
+
|
|
3295
|
+
## 1.2.1
|
|
3296
|
+
|
|
3297
|
+
### Patch Changes
|
|
3298
|
+
|
|
3299
|
+
- 0e5a64a: Add `markdownIfAvailable` support for fetch-url steps so SDK consumers can explicitly control markdown-first text fetching behavior.
|
|
3300
|
+
|
|
3301
|
+
## 1.2.0
|
|
3302
|
+
|
|
3303
|
+
### Minor Changes
|
|
3304
|
+
|
|
3305
|
+
- b0bada9: Add `end_turn` stop reason to distinguish "turn ended" from "task completed." Non-loop agents now return `end_turn` instead of `complete`, enabling multi-session marathon execution to continue across sessions. SDK includes client-side stop-phrase detection as a fallback for non-loop agents.
|
|
3306
|
+
|
|
3307
|
+
## 1.1.0
|
|
3308
|
+
|
|
3309
|
+
### Minor Changes
|
|
3310
|
+
|
|
3311
|
+
- ebe3c6b: Add `agents.runTask()` method for multi-session long-task agent execution with automatic state management, streaming support, cost tracking, and optional dashboard progress sync via records.
|
|
3312
|
+
|
|
3313
|
+
## 1.0.2
|
|
3314
|
+
|
|
3315
|
+
### Patch Changes
|
|
3316
|
+
|
|
3317
|
+
- aa97d84: Remove `embedCode` from `CreateClientTokenResponse`. The API no longer returns embed snippets (dashboard uses persona's generateCodeSnippet instead). Aligns SDK types with API.
|
|
3318
|
+
|
|
3319
|
+
## 1.0.1
|
|
3320
|
+
|
|
3321
|
+
### Patch Changes
|
|
3322
|
+
|
|
3323
|
+
- de81f99: Remove unused `promptId`, `contextTemplateId`, `prompt`, and `contextTemplate` fields from the `FlowStep` type. These fields were never functional at runtime and have been removed from the API.
|
|
3324
|
+
|
|
3325
|
+
## 1.0.0
|
|
3326
|
+
|
|
3327
|
+
### Major Changes
|
|
3328
|
+
|
|
3329
|
+
- 065de96: BREAKING: Normalize SSE stream events for consistency.
|
|
3330
|
+
|
|
3331
|
+
## Changes
|
|
3332
|
+
|
|
3333
|
+
### 1. Standardize on `result` field
|
|
3334
|
+
|
|
3335
|
+
Previously, prompt steps used `result` while context steps used `output`. Now all step types consistently use `result`.
|
|
3336
|
+
- Removed `output` field from `StepCompleteEvent` type
|
|
3337
|
+
- Removed fallback logic (`event.result ?? event.output`) from stream handlers
|
|
3338
|
+
|
|
3339
|
+
### 2. Rename `executionType` to `stepType`
|
|
3340
|
+
|
|
3341
|
+
Renamed the field from `executionType` to `stepType` to better align with industry conventions (Zapier, n8n, LangGraph) and clarify that it describes the type of step, not how it executes.
|
|
3342
|
+
|
|
3343
|
+
### 3. Expand `stepType` values
|
|
3344
|
+
|
|
3345
|
+
Previously, `executionType` was limited to `'prompt' | 'context'`. Now `stepType` provides the specific step type like `'prompt'`, `'transform-data'`, `'api-call'`, `'send-email'`, etc.
|
|
3346
|
+
|
|
3347
|
+
This is more useful for:
|
|
3348
|
+
- Filtering specific step types
|
|
3349
|
+
- Building step-type-specific UI
|
|
3350
|
+
- Consumer control logic
|
|
3351
|
+
- Future agent execution types
|
|
3352
|
+
|
|
3353
|
+
### 4. User-facing visibility
|
|
3354
|
+
|
|
3355
|
+
`stepType` is now visible in user-facing mode (debugMode: false) for `step_chunk`, `step_complete`, and `step_error` events, allowing consumers to use it for control logic.
|
|
3356
|
+
|
|
3357
|
+
## Migration
|
|
3358
|
+
1. Change `event.output` to `event.result`
|
|
3359
|
+
2. Change `event.executionType` to `event.stepType`
|
|
3360
|
+
3. If checking `stepType === 'context'`, update to check for specific types or use `stepType !== 'prompt'`
|
|
3361
|
+
|
|
3362
|
+
## 0.5.0
|
|
3363
|
+
|
|
3364
|
+
### Minor Changes
|
|
3365
|
+
|
|
3366
|
+
- 0140d17: Add `withInputs()` method to FlowBuilder for top-level input variables
|
|
3367
|
+
|
|
3368
|
+
You can now pass input variables directly accessible as `{{varName}}` in templates without needing the `_record.metadata` prefix:
|
|
3369
|
+
|
|
3370
|
+
```typescript
|
|
3371
|
+
const result = await new FlowBuilder()
|
|
3372
|
+
.useExistingFlow('flow_abc123')
|
|
3373
|
+
.withInputs({
|
|
3374
|
+
customerName: 'Acme Corp',
|
|
3375
|
+
topic: 'Q4 sales',
|
|
3376
|
+
})
|
|
3377
|
+
.run(apiClient, { streamResponse: true })
|
|
3378
|
+
```
|
|
3379
|
+
|
|
3380
|
+
The `inputs` field is also available directly on `DispatchRequest` for API calls.
|
|
3381
|
+
|
|
3382
|
+
## 0.4.0
|
|
3383
|
+
|
|
3384
|
+
### Minor Changes
|
|
3385
|
+
|
|
3386
|
+
- cf6fcdc: Add strongly-typed JSON types to replace `any` usage across the SDK. This includes:
|
|
3387
|
+
- `JsonValue`, `JsonObject`, `JsonPrimitive`, `JsonArray` types for type-safe JSON handling
|
|
3388
|
+
- `Metadata`, `StepOutput`, `ToolArgs`, `ToolResult` semantic type aliases
|
|
3389
|
+
- Type guards: `isJsonValue()`, `isJsonObject()`, `isJsonPrimitive()`, `isJsonArray()`
|
|
3390
|
+
- Updated all interfaces to use proper types instead of `any`:
|
|
3391
|
+
- `FlowStep.config` now uses `JsonObject`
|
|
3392
|
+
- `RuntypeRecord.metadata` now uses `Metadata`
|
|
3393
|
+
- `ModelConfig.settings` now uses `JsonObject`
|
|
3394
|
+
- Tool-related types (`parametersSchema`, `inputParameters`, `outputResult`) now use `JSONSchema`, `JsonObject`, `JsonValue`
|
|
3395
|
+
- Request/response types updated throughout
|
|
3396
|
+
|
|
3397
|
+
These changes improve TypeScript type safety while maintaining backward compatibility - existing code that passes plain objects will continue to work.
|
|
3398
|
+
|
|
3399
|
+
## 0.3.0
|
|
3400
|
+
|
|
3401
|
+
### Minor Changes
|
|
3402
|
+
|
|
3403
|
+
- 9ec83bd: Add ReasoningConfig type for fine-grained control over AI reasoning/extended thinking
|
|
3404
|
+
- New `ReasoningConfig` interface supports GPT-5, Claude 4, and Gemini 2.5 reasoning options
|
|
3405
|
+
- `reasoning` field on prompt steps now accepts `boolean | ReasoningConfig`
|
|
3406
|
+
- GPT-5 users can configure `reasoningEffort` and `reasoningSummary` for streaming
|
|
3407
|
+
- Claude users can set `budgetTokens` for extended thinking
|
|
3408
|
+
- Google users can configure `thinkingBudget` and `includeThoughts`
|
|
3409
|
+
|
|
3410
|
+
Example usage:
|
|
3411
|
+
|
|
3412
|
+
```typescript
|
|
3413
|
+
.prompt({
|
|
3414
|
+
name: 'Analyze',
|
|
3415
|
+
model: 'gpt-5',
|
|
3416
|
+
userPrompt: 'Analyze this data',
|
|
3417
|
+
reasoning: {
|
|
3418
|
+
enabled: true,
|
|
3419
|
+
reasoningEffort: 'high',
|
|
3420
|
+
reasoningSummary: 'detailed'
|
|
3421
|
+
}
|
|
3422
|
+
})
|
|
3423
|
+
```
|
|
3424
|
+
|
|
3425
|
+
- a63f268: Migrate SDK to native camelCase API convention
|
|
3426
|
+
- Transform functions (`transformRequest`, `transformResponse`, `transformQueryParams`) are now pass-through since the API uses native camelCase
|
|
3427
|
+
- Added TypeScript utility types for compile-time case conversion: `ToCamelCase`, `ToSnakeCase`, `SnakeToCamelString`, `CamelToSnakeString`
|
|
3428
|
+
- No changes to the SDK's external API surface - existing code continues to work
|
|
3429
|
+
|
|
3430
|
+
## 0.2.1
|
|
3431
|
+
|
|
3432
|
+
### Patch Changes
|
|
3433
|
+
|
|
3434
|
+
- 8506aa1: Remove private @runtypelabs/shared dependency from all public packages by inlining types and constants. This fixes npm installation errors where users couldn't install packages due to the unpublished internal shared package dependency.
|
|
3435
|
+
|
|
3436
|
+
## 0.2.0
|
|
3437
|
+
|
|
3438
|
+
### Minor Changes
|
|
3439
|
+
|
|
3440
|
+
- Remove `includeDistance` option from `VectorSearchStepConfig` interface. Distance/similarity scores are now always included in vector search results when available.
|
|
3441
|
+
- 06ac26d: Add SDK support for error handling fallbacks and client token management
|
|
3442
|
+
|
|
3443
|
+
TypeScript SDK (@runtypelabs/sdk):
|
|
3444
|
+
- Add error handling types to step configs (PromptErrorHandling, ContextErrorHandling)
|
|
3445
|
+
- Add support for fallback chains with retry and model fallbacks
|
|
3446
|
+
- Add fallback SSE event types (fallbacks_initiated, fallback_start, fallback_success, fallback_fail, fallbacks_exhausted)
|
|
3447
|
+
- Add ClientTokensEndpoint for client token CRUD operations
|
|
3448
|
+
- Re-export error handling and client token types from shared lib
|
|
3449
|
+
|
|
3450
|
+
MCP Server (@runtypelabs/mcp-server):
|
|
3451
|
+
- Add client token management tools: list_client_tokens, get_client_token, create_client_token, update_client_token, delete_client_token, regenerate_client_token
|
|
3452
|
+
|
|
3453
|
+
## 0.1.3
|
|
3454
|
+
|
|
3455
|
+
### Patch Changes
|
|
3456
|
+
|
|
3457
|
+
- 2eb58c6: Add official npm package badge to README
|