Skip to content
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c3cc795
chore(core): add @standard-schema/spec dependency
AlemTuzlak May 6, 2026
18df213
feat(core): add AgentValidator interface and defaultEventValidator
AlemTuzlak May 6, 2026
2a124f4
fix(core): tighten AgentValidator guards and add fromStandardSchema t…
AlemTuzlak May 6, 2026
6cd0583
feat(core): add hand-written static types for messages, tools, run input
AlemTuzlak May 6, 2026
2d870b8
refactor(core): extract BaseMessageFields, document types-static.ts p…
AlemTuzlak May 6, 2026
0c1dbfc
feat(core): add hand-written static types for events
AlemTuzlak May 6, 2026
827d65b
fix(core): correct RunFinishedInterruptOutcome.interrupts to Interrupt[]
AlemTuzlak May 6, 2026
201eb74
feat(core): add hand-written static types for capabilities
AlemTuzlak May 6, 2026
0106c81
docs(core): port JSDoc from capabilities.ts to capabilities-static.ts
AlemTuzlak May 6, 2026
d64cc65
refactor(core): drop schema.parse from event factories, inline defaults
AlemTuzlak May 6, 2026
394bc69
refactor(core): use AGUIError in createRunFinishedInterruptEvent guard
AlemTuzlak May 6, 2026
87e75e4
refactor(client,proto): route runtime event validation through AgentV…
AlemTuzlak May 6, 2026
ca58179
refactor(client,proto): include path in validator error messages, doc…
AlemTuzlak May 6, 2026
908f9d5
refactor(core)!: remove zod schemas, expose only types and validator …
AlemTuzlak May 6, 2026
e3dffed
test(core): assert defaultEventValidator preserves forward-compat tol…
AlemTuzlak May 6, 2026
83510a4
docs(core): update stale comments in *-static.ts now that zod is removed
AlemTuzlak May 6, 2026
bf99721
chore(core)!: remove zod runtime dependency
AlemTuzlak May 6, 2026
a065541
chore: migrate external schema consumers off @ag-ui/core schemas
AlemTuzlak May 6, 2026
21dd0e9
docs(core): update event-validation guidance to reflect AgentValidato…
AlemTuzlak May 6, 2026
b715285
chore(core): bump to 0.1.0 with zod removal changelog entry
AlemTuzlak May 6, 2026
1006a5f
test(core): tighten validator.test.ts casts to satisfy strict tsc
AlemTuzlak May 6, 2026
53d7de4
refactor(core): collapse *-static.ts scaffolding back into surface files
AlemTuzlak May 6, 2026
b243a15
refactor(core): restore @ag-ui/core/schemas subpath; drop defaultEven…
AlemTuzlak May 6, 2026
2618efe
chore(core): tighten zod peer range to ^3.24.0 and add types conditions
AlemTuzlak May 6, 2026
7c7d0a7
test(core): restore schema tests, redirected to @ag-ui/core/schemas s…
AlemTuzlak May 6, 2026
cd1d2aa
chore(core): widen zod peer range to ^3.24.0 || ^4.0.0
AlemTuzlak May 6, 2026
95e7b24
refactor: revert client/proto to EventSchemas.parse, drop AgentValidator
AlemTuzlak May 6, 2026
3b4a06f
docs: 0.1.0 migration guide + jscodeshift codemod for *Schema imports
AlemTuzlak May 6, 2026
4988162
fix(codemods): use jscodeshift paths() API for the schemas merge site
AlemTuzlak May 6, 2026
07f33b3
fix(core): resolve typecheck errors in schema-type-equality and modul…
AlemTuzlak May 6, 2026
320496f
fix(codemod,packages): address load-bearing CR findings
AlemTuzlak May 6, 2026
1026d89
fix(codemod): preserve aliases and separate type/value declarations
AlemTuzlak May 6, 2026
eede4f7
fix(codemods): use shell:true and mkdtempSync for cross-platform robu…
AlemTuzlak May 6, 2026
742661b
chore: revert tsconfig changes and move codemods to repo root
AlemTuzlak May 6, 2026
1634966
chore: sync pnpm-lock.yaml after removing @standard-schema/spec dep
AlemTuzlak May 6, 2026
db8f1aa
fix(core): add passthrough index signature to BaseEvent
AlemTuzlak May 6, 2026
b6b7ccf
refactor(core): drop defensive casts, align Tool/RunAgentInput types …
AlemTuzlak May 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 45 additions & 37 deletions docs/sdk/js/core/events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -589,43 +589,51 @@ The following event types are deprecated:
See [Reasoning Migration](/concepts/reasoning#migration-from-thinking-events)
for detailed migration guidance.

## Event Schemas

The SDK uses Zod schemas to validate events:

```typescript
const EventSchemas = z.discriminatedUnion("type", [
TextMessageStartEventSchema,
TextMessageContentEventSchema,
TextMessageEndEventSchema,
ToolCallStartEventSchema,
ToolCallArgsEventSchema,
ToolCallEndEventSchema,
ToolCallResultEventSchema,
StateSnapshotEventSchema,
StateDeltaEventSchema,
MessagesSnapshotEventSchema,
ActivitySnapshotEventSchema,
ActivityDeltaEventSchema,
RawEventSchema,
CustomEventSchema,
RunStartedEventSchema,
RunFinishedEventSchema,
RunErrorEventSchema,
StepStartedEventSchema,
StepFinishedEventSchema,
ReasoningStartEventSchema,
ReasoningMessageStartEventSchema,
ReasoningMessageContentEventSchema,
ReasoningMessageEndEventSchema,
ReasoningMessageChunkEventSchema,
ReasoningEndEventSchema,
ReasoningEncryptedValueEventSchema,
])
```

This allows for runtime validation of events and provides TypeScript type
inference.
## Event validation

`@ag-ui/core` ships TypeScript types for every event but does not bundle a runtime
schema validator in its main entry. Consumers that need to validate untrusted event
streams (for example, when parsing wire data over HTTP) plug in an `AgentValidator` —
a pluggable interface based on [Standard Schema](https://github.com/standard-schema/standard-schema).

The `@ag-ui/core/schemas` subpath exports a ready-made `zodValidator` backed by zod.
Install zod explicitly to use it (zod is an optional peer dependency):

```typescript
import { zodValidator } from "@ag-ui/core/schemas";
import { EventType } from "@ag-ui/core";

const result = zodValidator.validateEvent({
type: EventType.TEXT_MESSAGE_START,
messageId: "msg-1",
// role defaults to "assistant" when omitted
});

if (result.success) {
// result.value is typed as { type: EventType; [k: string]: unknown }
console.log(result.value);
} else {
console.error("Invalid event:", result.issues);
}
```

For a custom validator backed by zod, valibot, arktype, or any library that implements
the Standard Schema spec:

```typescript
import { fromStandardSchema, type AgentValidator } from "@ag-ui/core";
import { z } from "zod";

const myEventSchema = z.object({ type: z.string() }).passthrough();

const myValidator: AgentValidator = {
validateEvent: fromStandardSchema(myEventSchema),
};
```

The HTTP transform in `@ag-ui/client` and the protobuf decoder in `@ag-ui/proto`
both accept an optional validator argument and default to `zodValidator` from
`@ag-ui/core/schemas`, preserving full runtime validation with no additional setup.

### ToolCallChunkEvent

Expand Down
2 changes: 1 addition & 1 deletion docs/sdk/js/core/multimodal-inputs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ description:
multimodal content parts.

```typescript
import { UserMessage } from "@ag-ui/core"
import type { UserMessage } from "@ag-ui/core"

const message: UserMessage = {
id: "user-1",
Expand Down
3 changes: 2 additions & 1 deletion integrations/adk-middleware/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"@arethetypeswrong/cli": "^0.17.4",
"tsdown": "^0.20.1",
"typescript": "^5.3.3",
"vitest": "^4.0.18"
"vitest": "^4.0.18",
"zod": "^3.24.0"
},
"exports": {
".": {
Expand Down
3 changes: 2 additions & 1 deletion integrations/adk-middleware/typescript/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HttpAgent } from "@ag-ui/client";
import { AgentCapabilities, AgentCapabilitiesSchema } from "@ag-ui/core";
import type { AgentCapabilities } from "@ag-ui/core";
import { AgentCapabilitiesSchema } from "@ag-ui/core/schemas";

export class ADKAgent extends HttpAgent {
/**
Expand Down
59 changes: 46 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions sdks/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ For more information visit the [official documentation](https://docs.ag-ui.com/)
## Multimodal user messages

```ts
import { UserMessageSchema } from "@ag-ui/core";
import type { UserMessage } from "@ag-ui/core";

const message = UserMessageSchema.parse({
const message: UserMessage = {
id: "user-123",
role: "user" as const,
role: "user",
content: [
{ type: "text", text: "Please describe this image" },
{
Expand All @@ -23,7 +23,7 @@ const message = UserMessageSchema.parse({
},
},
],
});
};

console.log(message);
// { id: "user-123", role: "user", content: [...] }
Expand Down
27 changes: 17 additions & 10 deletions sdks/typescript/packages/client/src/transform/http.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { BaseEvent, EventSchemas } from "@ag-ui/core";
import { BaseEvent, EventType, type AgentValidator } from "@ag-ui/core";
import { zodValidator } from "@ag-ui/core/schemas";
import { Subject, ReplaySubject, Observable } from "rxjs";
import { HttpEvent, HttpEventType } from "../run/http-request";
import { parseSSEStream } from "./sse";
import { parseProtoStream } from "./proto";
import * as proto from "@ag-ui/proto";
import { EventType } from "@ag-ui/core";
import { type DebugLoggerInput, resolveDebugLogger } from "@/debug-logger";

/**
Expand All @@ -13,6 +13,7 @@ import { type DebugLoggerInput, resolveDebugLogger } from "@/debug-logger";
export const transformHttpEventStream = (
source$: Observable<HttpEvent>,
debugLogger?: DebugLoggerInput,
validator: AgentValidator = zodValidator,
): Observable<BaseEvent> => {
const log = resolveDebugLogger(debugLogger);
const eventSubject = new Subject<BaseEvent>();
Expand Down Expand Up @@ -51,16 +52,22 @@ export const transformHttpEventStream = (
// Use SSE JSON parser for all other cases
parseSSEStream(bufferSubject, log).subscribe({
next: (json) => {
try {
const parsedEvent = EventSchemas.parse(json);
log?.event("HTTP", "Event validated:", parsedEvent, {
type: parsedEvent.type,
const result = validator.validateEvent(json);
if (result.success) {
log?.event("HTTP", "Event validated:", result.value, {
type: result.value.type,
valid: true,
});
eventSubject.next(parsedEvent as BaseEvent);
} catch (err) {
log?.event("HTTP", "Event invalid:", { json, error: String(err) });
eventSubject.error(err);
eventSubject.next(result.value as BaseEvent);
} else {
log?.event("HTTP", "Event invalid:", { json, issues: result.issues });
eventSubject.error(
new Error(
`Invalid event: ${result.issues
.map((i) => (i.path?.length ? `[${i.path.join(".")}] ${i.message}` : i.message))
.join("; ")}`,
),
);
}
},
error: (err) => {
Expand Down
1 change: 1 addition & 0 deletions sdks/typescript/packages/client/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default mergeConfig(
resolve: {
alias: {
"@/": path.resolve(__dirname, "./src") + "/",
"@ag-ui/core/schemas": path.resolve(__dirname, "../core/src/schemas.ts"),
"@ag-ui/core": path.resolve(__dirname, "../core/src/index.ts"),
"@ag-ui/proto": path.resolve(__dirname, "../proto/src/index.ts"),
"@ag-ui/encoder": path.resolve(__dirname, "../encoder/src/index.ts"),
Expand Down
Loading
Loading