Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2f220cc
fix(security): bound SDK streams and enforce event identity
HAYDEN-OAI Aug 18, 2026
8283fd4
fix(security): validate retained streaming identities and event payloads
HAYDEN-OAI Aug 19, 2026
d0ed2b4
fix(security): stabilize streamed event routing and host backing storage
HAYDEN-OAI Aug 19, 2026
4f2c2f9
fix(security): guard cross-realm collections and inherited stream rou…
HAYDEN-OAI Aug 19, 2026
5498320
fix(security): bind streaming parser configuration and binary queues
HAYDEN-OAI Aug 19, 2026
2cd10b7
fix(security): bind streamed events and fail closed on opaque payloads
HAYDEN-OAI Aug 19, 2026
266cd10
fix(streaming): scope JSON budgets to parseable tool calls
HAYDEN-OAI Aug 19, 2026
4903a36
fix(security): bound retained event descriptors and capture tool deltas
HAYDEN-OAI Aug 19, 2026
057b4e6
Harden buffered event prototypes and stream routing identities
HAYDEN-OAI Aug 19, 2026
1ad4b05
Support cross-realm native Error stacks on Node 22
HAYDEN-OAI Aug 19, 2026
be87d1f
Harden cross-realm buffering and streaming parser boundaries
HAYDEN-OAI Aug 19, 2026
2c99abc
fix: harden streamed snapshot identity and retained storage
HAYDEN-OAI Aug 19, 2026
6bafad1
fix: constrain proxy queues and cumulative streaming work
HAYDEN-OAI Aug 19, 2026
acd97e7
fix: bind structured chat snapshot parser frames
HAYDEN-OAI Aug 19, 2026
de9c49c
fix: preserve validated streaming parser and event snapshots
HAYDEN-OAI Aug 19, 2026
3969716
fix: preserve buffered API errors with response headers
HAYDEN-OAI Aug 19, 2026
06d4b1c
fix: bind streamed tool parsing to actual wire contract
HAYDEN-OAI Aug 19, 2026
6f26d1a
fix(streaming): bind parsers to serialized owner and response format
HAYDEN-OAI Aug 19, 2026
929ded3
fix(streaming): bind validated tool collections and array budgets
HAYDEN-OAI Aug 19, 2026
b18e1a6
fix(streaming): bind parser schemas and preserve buffered dates
HAYDEN-OAI Aug 19, 2026
836c27c
fix: preserve streaming parser ownership and shared event accounting
HAYDEN-OAI Aug 20, 2026
dd41cae
merge: preserve hardened streaming contracts with main
HAYDEN-OAI Aug 20, 2026
a5a1cf1
fix: capture tool-call accessors once on older Node runtimes
HAYDEN-OAI Aug 20, 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
49 changes: 48 additions & 1 deletion src/internal/request-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,58 @@ export type RequestOptions = {
export type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit };
export type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent;

interface JSONRequestBodyObserver {
value(holder: object, key: string, value: unknown): void;
complete(): void;
}

const jsonRequestBodyObservers = new WeakMap<object, Set<JSONRequestBodyObserver>>();

/** Observes values produced by the actual JSON request serializer without changing them. */
export function observeJSONRequestBody(body: object, observer: JSONRequestBodyObserver): () => void {
let observers = jsonRequestBodyObservers.get(body);
if (!observers) {
observers = new Set();
jsonRequestBodyObservers.set(body, observers);
}
observers.add(observer);

return () => {
const active = jsonRequestBodyObservers.get(body);
if (!active) {
return;
}
active.delete(observer);
if (active.size === 0) {
jsonRequestBodyObservers.delete(body);
}
};
}

export const FallbackEncoder: RequestEncoder = ({ headers, body }) => {
const observers =
typeof body === 'object' && body !== null ? jsonRequestBodyObservers.get(body) : undefined;
let encoded: string;

if (!observers || observers.size === 0) {
encoded = JSON.stringify(body);
} else {
const active = [...observers];
encoded = JSON.stringify(body, function (this: object, key: string, value: unknown): unknown {
for (const observer of active) {
observer.value(this, key, value);
}
return value;
});
for (const observer of active) {
observer.complete();
}
}

return {
bodyHeaders: {
'content-type': 'application/json',
},
body: JSON.stringify(body),
body: encoded,
};
};
Loading
Loading