From 678237e86d40f9d87911c526690f7ff7c37ebcf2 Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:37:54 +0100 Subject: [PATCH 01/10] feature: lifecycle hooks --- src/lib/river/server.ts | 8 ++++++- src/lib/river/types.ts | 32 +++++++++++++++++++++++++++- src/routes/examples/river/+server.ts | 15 ++++++++++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/lib/river/server.ts b/src/lib/river/server.ts index 74e4d35..b6e9be1 100644 --- a/src/lib/river/server.ts +++ b/src/lib/river/server.ts @@ -70,7 +70,7 @@ const createServerSideAgentRunner: ServerSideAgentRunner = (router) => { }; }; -const createServerEndpointHandler: ServerEndpointHandler = (router) => { +const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { const runner = createServerSideAgentRunner(router); return { POST: async (event) => { @@ -95,10 +95,14 @@ const createServerEndpointHandler: ServerEndpointHandler = (router) => { const error = new RiverError('Invalid body', bodyResult.error); return new Response(JSON.stringify(error), { status: 400 }); } + const { agentId, input } = bodyResult.data; const stream = new ReadableStream({ async start(streamController) { // TODO: make it so that you can do some wait until and piping shit in here + + await hooks?.beforeAgentRun?.({ event, agentId, input, abortController }); + try { await runner.runAgent({ agentId: bodyResult.data.agentId, @@ -114,10 +118,12 @@ const createServerEndpointHandler: ServerEndpointHandler = (router) => { } } finally { streamController.close(); + await hooks?.afterAgentRun?.({ event, agentId, input }); } }, cancel(reason) { abortController.abort(reason); + hooks?.onAbort?.({ event, agentId, input, reason }); } }); diff --git a/src/lib/river/types.ts b/src/lib/river/types.ts index 83aefed..8000692 100644 --- a/src/lib/river/types.ts +++ b/src/lib/river/types.ts @@ -77,9 +77,39 @@ type ServerSideAgentRunner = ( }; type ServerEndpointHandler = ( - router: DecoratedAgentRouter + router: DecoratedAgentRouter, + hooks: LifecycleHooks ) => { POST: (event: RequestEvent) => Promise }; +type LifecycleHooks = { + beforeAgentRun?: (ctx: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + abortController: AbortController; + // potential future add for passing through the start time of the lifecycle? + // startAt: number; + }) => void | Promise; + afterAgentRun?: (ctx: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + // metrics: { totalChunks: number; durationMs: number }; + }) => void | Promise; + onError?: (ctx: { + event: RequestEvent; + error: RiverError; + agentId: K; + input: InferRiverAgentInputType; + }) => void | Promise; + onAbort?: (ctx: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + reason?: unknown; + }) => void; +}; + // CLIENT CALLER SECTION type OnCompleteCallback = (data: { totalChunks: number; duration: number }) => void | Promise; type OnErrorCallback = (error: RiverError) => void | Promise; diff --git a/src/routes/examples/river/+server.ts b/src/routes/examples/river/+server.ts index 53ed8bd..f0af842 100644 --- a/src/routes/examples/river/+server.ts +++ b/src/routes/examples/river/+server.ts @@ -3,4 +3,17 @@ import { exampleRouter } from './router.js'; // in the real world this should probably be in src/routes/api/river/+server.ts -export const { POST } = RIVER_SERVER.createServerEndpointHandler(exampleRouter); +export const { POST } = RIVER_SERVER.createServerEndpointHandler(exampleRouter, { + beforeAgentRun: async ({ event, input, agentId, abortController }) => { + console.log('[HOOK] - beforeAgentRun', event.route.id, agentId, input); + }, + afterAgentRun: async ({ event, input, agentId }) => { + console.log('[HOOK] - afterAgentRun', { agentId }); + }, + onAbort: ({ event, input, agentId, reason }) => { + console.log('[HOOK] - onAbort', { reason }); + }, + onError: async ({ event, input, agentId, error }) => { + console.log('[HOOK] - onError', { error }); + } +}); From f522709aa6d2a21665cddbdabc66f71b52eb2418 Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:05:18 +0100 Subject: [PATCH 02/10] fix: `onError` hook not being invoked --- src/lib/river/server.ts | 5 +++++ src/lib/river/types.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/river/server.ts b/src/lib/river/server.ts index b6e9be1..3f79362 100644 --- a/src/lib/river/server.ts +++ b/src/lib/river/server.ts @@ -115,6 +115,11 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { streamController.close(); } else { streamController.error(error); + const riverErr = + error instanceof RiverError + ? error + : new RiverError(`[RIVER:${agentId}] - Run Failed`, error); + await hooks?.onError?.({ event, agentId, input, error: riverErr }); } } finally { streamController.close(); diff --git a/src/lib/river/types.ts b/src/lib/river/types.ts index 8000692..8222997 100644 --- a/src/lib/river/types.ts +++ b/src/lib/river/types.ts @@ -78,7 +78,7 @@ type ServerSideAgentRunner = ( type ServerEndpointHandler = ( router: DecoratedAgentRouter, - hooks: LifecycleHooks + hooks?: LifecycleHooks ) => { POST: (event: RequestEvent) => Promise }; type LifecycleHooks = { From 403ccfa056614635e1d44c8a1efec19c2c5748a9 Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:33:11 +0100 Subject: [PATCH 03/10] choice between passing `function` or effect-style try catch for per hook error handling --- src/lib/river/server.ts | 47 ++++++++++++++++++++++++---- src/lib/river/types.ts | 28 +++++++++++------ src/routes/examples/river/+server.ts | 13 ++++++-- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/lib/river/server.ts b/src/lib/river/server.ts index 3f79362..6e8150c 100644 --- a/src/lib/river/server.ts +++ b/src/lib/river/server.ts @@ -1,8 +1,10 @@ import z from 'zod'; import type { + AgentRouter, CreateAgentRouter, CreateAiSdkRiverAgent, CreateCustomRiverAgent, + LifecycleHooks, ServerEndpointHandler, ServerSideAgentRunner } from './types.js'; @@ -101,7 +103,19 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { async start(streamController) { // TODO: make it so that you can do some wait until and piping shit in here - await hooks?.beforeAgentRun?.({ event, agentId, input, abortController }); + const defaultErrorHandler = async (error: unknown) => { + if (hooks?.onError) { + const riverErr = + error instanceof RiverError + ? error + : new RiverError(`[RIVER:${agentId}] - Run Failed`, error); + await safeCall(hooks.onError, { event, agentId, input, riverErr }); + } else { + console.error('Unhandled error during agent run:', error); + } + }; + + await safeCall(hooks?.beforeAgentRun, { event, agentId, input, abortController }); try { await runner.runAgent({ @@ -115,11 +129,8 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { streamController.close(); } else { streamController.error(error); - const riverErr = - error instanceof RiverError - ? error - : new RiverError(`[RIVER:${agentId}] - Run Failed`, error); - await hooks?.onError?.({ event, agentId, input, error: riverErr }); + + await defaultErrorHandler(error); } } finally { streamController.close(); @@ -137,6 +148,30 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { }; }; +async function safeCall>( + hook: LifecycleHooks[K] | undefined, + args: any, // can improve typing per hook later + globalOnError?: (err: unknown) => Promise +) { + if (!hook) return; + + try { + if (typeof hook === 'function') { + await hook(args); + } else { + await hook.try(args); + } + } catch (err) { + if (hook && typeof hook !== 'function' && hook.catch) { + await hook.catch(err, { ...args }); + } else if (globalOnError) { + await globalOnError(err); + } else { + console.error('Unhandled hook error:', err); + } + } +} + export const RIVER_SERVER = { createAgentRouter, createAiSdkAgent, diff --git a/src/lib/river/types.ts b/src/lib/river/types.ts index 8222997..28cf617 100644 --- a/src/lib/river/types.ts +++ b/src/lib/river/types.ts @@ -81,15 +81,25 @@ type ServerEndpointHandler = ( hooks?: LifecycleHooks ) => { POST: (event: RequestEvent) => Promise }; -type LifecycleHooks = { - beforeAgentRun?: (ctx: { - event: RequestEvent; - agentId: K; - input: InferRiverAgentInputType; - abortController: AbortController; - // potential future add for passing through the start time of the lifecycle? - // startAt: number; - }) => void | Promise; +export type HookWithError = { + try: (args: T) => Promise | void; + catch: (error: unknown, args: T) => Promise | void; +}; + +export type LifecycleHooks = { + beforeAgentRun?: + | HookWithError<{ + event: RequestEvent; + agentId: keyof T; + input: InferRiverAgentInputType; + abortController: AbortController; + }> + | ((args: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + abortController: AbortController; + }) => Promise | void); afterAgentRun?: (ctx: { event: RequestEvent; agentId: K; diff --git a/src/routes/examples/river/+server.ts b/src/routes/examples/river/+server.ts index f0af842..ccc8af3 100644 --- a/src/routes/examples/river/+server.ts +++ b/src/routes/examples/river/+server.ts @@ -1,11 +1,18 @@ -import { RIVER_SERVER } from '$lib/index.js'; +import { RIVER_SERVER, RiverError } from '$lib/index.js'; import { exampleRouter } from './router.js'; // in the real world this should probably be in src/routes/api/river/+server.ts export const { POST } = RIVER_SERVER.createServerEndpointHandler(exampleRouter, { - beforeAgentRun: async ({ event, input, agentId, abortController }) => { - console.log('[HOOK] - beforeAgentRun', event.route.id, agentId, input); + beforeAgentRun: { + try: ({ input }) => { + console.log('[HOOK] - beforeAgentRun', { input }); + throw new RiverError('Example Throw'); + }, + catch: (error, { input }) => { + // Allows for per hook error handling + console.error('[HOOK ERROR] - beforeAgentRun', error); + } }, afterAgentRun: async ({ event, input, agentId }) => { console.log('[HOOK] - afterAgentRun', { agentId }); From 725609448e5b46e33f90bf503e8cdbd3b581aff6 Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:39:44 +0100 Subject: [PATCH 04/10] finished updating types with `HookWithError` --- src/lib/river/types.ts | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/lib/river/types.ts b/src/lib/river/types.ts index 28cf617..49e5360 100644 --- a/src/lib/river/types.ts +++ b/src/lib/river/types.ts @@ -100,24 +100,36 @@ export type LifecycleHooks = { input: InferRiverAgentInputType; abortController: AbortController; }) => Promise | void); - afterAgentRun?: (ctx: { - event: RequestEvent; - agentId: K; - input: InferRiverAgentInputType; - // metrics: { totalChunks: number; durationMs: number }; - }) => void | Promise; + afterAgentRun?: + | HookWithError<{ + event: RequestEvent; + agentId: keyof T; + input: InferRiverAgentInputType; + }> + | ((ctx: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + }) => void | Promise); + onAbort?: + | HookWithError<{ + event: RequestEvent; + agentId: T; + input: InferRiverAgentInputType; + reason?: unknown; + }> + | ((ctx: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + reason?: unknown; + }) => void); onError?: (ctx: { event: RequestEvent; error: RiverError; agentId: K; input: InferRiverAgentInputType; }) => void | Promise; - onAbort?: (ctx: { - event: RequestEvent; - agentId: K; - input: InferRiverAgentInputType; - reason?: unknown; - }) => void; }; // CLIENT CALLER SECTION From 6b66e1cf361849293feb06ed1ece1ae9ca24b1df Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:51:44 +0100 Subject: [PATCH 05/10] forgot to convert `onAbort` to `safeCall` function --- src/lib/river/server.ts | 4 ++-- src/lib/river/types.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/river/server.ts b/src/lib/river/server.ts index 6e8150c..6daa1b6 100644 --- a/src/lib/river/server.ts +++ b/src/lib/river/server.ts @@ -134,12 +134,12 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { } } finally { streamController.close(); - await hooks?.afterAgentRun?.({ event, agentId, input }); + await safeCall(hooks?.afterAgentRun, { event, agentId, input }); } }, cancel(reason) { abortController.abort(reason); - hooks?.onAbort?.({ event, agentId, input, reason }); + safeCall(hooks?.onAbort, { event, agentId, input, reason }); } }); diff --git a/src/lib/river/types.ts b/src/lib/river/types.ts index 49e5360..c08e1bc 100644 --- a/src/lib/river/types.ts +++ b/src/lib/river/types.ts @@ -114,7 +114,7 @@ export type LifecycleHooks = { onAbort?: | HookWithError<{ event: RequestEvent; - agentId: T; + agentId: keyof T; input: InferRiverAgentInputType; reason?: unknown; }> From 523da9b87628df1970dda7123f35456822a0e5e5 Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 19:44:03 +0100 Subject: [PATCH 06/10] `safeCall` for defaultErrorHandler --- src/lib/river/server.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/lib/river/server.ts b/src/lib/river/server.ts index 6daa1b6..f8e25eb 100644 --- a/src/lib/river/server.ts +++ b/src/lib/river/server.ts @@ -103,15 +103,15 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { async start(streamController) { // TODO: make it so that you can do some wait until and piping shit in here - const defaultErrorHandler = async (error: unknown) => { + const defaultErrorHandler = async (err: unknown) => { if (hooks?.onError) { - const riverErr = - error instanceof RiverError - ? error - : new RiverError(`[RIVER:${agentId}] - Run Failed`, error); - await safeCall(hooks.onError, { event, agentId, input, riverErr }); + const error = + err instanceof RiverError + ? err + : new RiverError(`[RIVER:${agentId}] - Run Failed`, err); + await safeCall(hooks.onError, { event, agentId, input, error }); } else { - console.error('Unhandled error during agent run:', error); + console.error('Unhandled error during agent run:', err); } }; @@ -139,6 +139,7 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { }, cancel(reason) { abortController.abort(reason); + safeCall(hooks?.onAbort, { event, agentId, input, reason }); } }); From 7ab592fc6d04ea7b46e3a74c6758fcb042c68bb0 Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 20:37:20 +0100 Subject: [PATCH 07/10] type safe args on `safeCall` --- src/lib/river/server.ts | 7 ++++--- src/lib/river/types.ts | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lib/river/server.ts b/src/lib/river/server.ts index f8e25eb..3b3ece0 100644 --- a/src/lib/river/server.ts +++ b/src/lib/river/server.ts @@ -4,6 +4,7 @@ import type { CreateAgentRouter, CreateAiSdkRiverAgent, CreateCustomRiverAgent, + HookForSafeCall, LifecycleHooks, ServerEndpointHandler, ServerSideAgentRunner @@ -149,9 +150,9 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { }; }; -async function safeCall>( - hook: LifecycleHooks[K] | undefined, - args: any, // can improve typing per hook later +async function safeCall( + hook: HookForSafeCall | undefined, + args: T, globalOnError?: (err: unknown) => Promise ) { if (!hook) return; diff --git a/src/lib/river/types.ts b/src/lib/river/types.ts index c08e1bc..126a178 100644 --- a/src/lib/river/types.ts +++ b/src/lib/river/types.ts @@ -86,6 +86,13 @@ export type HookWithError = { catch: (error: unknown, args: T) => Promise | void; }; +export type HookForSafeCall = + | ((args: T) => Promise | void) + | { + try: (args: T) => Promise | void; + catch: (error: unknown, args: T) => Promise | void; + }; + export type LifecycleHooks = { beforeAgentRun?: | HookWithError<{ From 57f3c190fb7f777a92cda4821c1bc07615cd7938 Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 21:14:52 +0100 Subject: [PATCH 08/10] renamed `safeCall` to `callServerHook` --- src/lib/river/server.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/river/server.ts b/src/lib/river/server.ts index 3b3ece0..ffaf697 100644 --- a/src/lib/river/server.ts +++ b/src/lib/river/server.ts @@ -110,13 +110,13 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { err instanceof RiverError ? err : new RiverError(`[RIVER:${agentId}] - Run Failed`, err); - await safeCall(hooks.onError, { event, agentId, input, error }); + await callServerHook(hooks.onError, { event, agentId, input, error }); } else { console.error('Unhandled error during agent run:', err); } }; - await safeCall(hooks?.beforeAgentRun, { event, agentId, input, abortController }); + await callServerHook(hooks?.beforeAgentRun, { event, agentId, input, abortController }); try { await runner.runAgent({ @@ -135,13 +135,13 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { } } finally { streamController.close(); - await safeCall(hooks?.afterAgentRun, { event, agentId, input }); + await callServerHook(hooks?.afterAgentRun, { event, agentId, input }); } }, cancel(reason) { abortController.abort(reason); - safeCall(hooks?.onAbort, { event, agentId, input, reason }); + callServerHook(hooks?.onAbort, { event, agentId, input, reason }); } }); @@ -150,7 +150,7 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { }; }; -async function safeCall( +async function callServerHook( hook: HookForSafeCall | undefined, args: T, globalOnError?: (err: unknown) => Promise From e7a16bf5ceecb2f7523a2b1db2a9372729f887dd Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 23:33:37 +0100 Subject: [PATCH 09/10] fix type narrowing in application lifecycle hooks --- src/lib/river/types.ts | 85 ++++++++++++++-------------- src/routes/examples/river/+server.ts | 10 +++- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/src/lib/river/types.ts b/src/lib/river/types.ts index 126a178..d303a7a 100644 --- a/src/lib/river/types.ts +++ b/src/lib/river/types.ts @@ -81,62 +81,58 @@ type ServerEndpointHandler = ( hooks?: LifecycleHooks ) => { POST: (event: RequestEvent) => Promise }; -export type HookWithError = { +type HookWithError = { try: (args: T) => Promise | void; catch: (error: unknown, args: T) => Promise | void; }; -export type HookForSafeCall = +type HookForSafeCall = | ((args: T) => Promise | void) | { try: (args: T) => Promise | void; catch: (error: unknown, args: T) => Promise | void; }; -export type LifecycleHooks = { - beforeAgentRun?: - | HookWithError<{ - event: RequestEvent; - agentId: keyof T; - input: InferRiverAgentInputType; - abortController: AbortController; - }> - | ((args: { - event: RequestEvent; - agentId: K; - input: InferRiverAgentInputType; - abortController: AbortController; - }) => Promise | void); - afterAgentRun?: - | HookWithError<{ - event: RequestEvent; - agentId: keyof T; - input: InferRiverAgentInputType; - }> - | ((ctx: { - event: RequestEvent; - agentId: K; - input: InferRiverAgentInputType; - }) => void | Promise); - onAbort?: - | HookWithError<{ - event: RequestEvent; - agentId: keyof T; - input: InferRiverAgentInputType; - reason?: unknown; - }> - | ((ctx: { - event: RequestEvent; - agentId: K; - input: InferRiverAgentInputType; - reason?: unknown; - }) => void); - onError?: (ctx: { +type AllBeforeAgentRunArgs = { + [K in keyof T]: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + abortController: AbortController; + }; +}[keyof T]; + +type AllAfterAgentRunArgs = { + [K in keyof T]: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + }; +}[keyof T]; + +type AllOnAbortArgs = { + [K in keyof T]: { + event: RequestEvent; + agentId: K; + input: InferRiverAgentInputType; + reason?: unknown; + }; +}[keyof T]; + +type AllOnErrorArgs = { + [K in keyof T]: { event: RequestEvent; error: RiverError; agentId: K; input: InferRiverAgentInputType; - }) => void | Promise; + }; +}[keyof T]; + +type LifecycleHooks = { + beforeAgentRun?: HookForSafeCall>; + afterAgentRun?: HookForSafeCall>; + onAbort?: HookForSafeCall>; + onError?: (ctx: AllOnErrorArgs) => void | Promise; }; // CLIENT CALLER SECTION @@ -186,5 +182,8 @@ export type { ServerSideAgentRunner, ServerEndpointHandler, ClientSideCaller, - AgentRouter + AgentRouter, + LifecycleHooks, + HookWithError, + HookForSafeCall }; diff --git a/src/routes/examples/river/+server.ts b/src/routes/examples/river/+server.ts index ccc8af3..5952b10 100644 --- a/src/routes/examples/river/+server.ts +++ b/src/routes/examples/river/+server.ts @@ -1,12 +1,17 @@ import { RIVER_SERVER, RiverError } from '$lib/index.js'; +import { z } from 'zod/mini'; import { exampleRouter } from './router.js'; // in the real world this should probably be in src/routes/api/river/+server.ts export const { POST } = RIVER_SERVER.createServerEndpointHandler(exampleRouter, { beforeAgentRun: { - try: ({ input }) => { + try: ({ input, agentId }) => { console.log('[HOOK] - beforeAgentRun', { input }); + if (agentId === 'exampleCustomAgent') { + // With support for type narrowing + console.log('Narrowed Input', input); + } throw new RiverError('Example Throw'); }, catch: (error, { input }) => { @@ -15,6 +20,9 @@ export const { POST } = RIVER_SERVER.createServerEndpointHandler(exampleRouter, } }, afterAgentRun: async ({ event, input, agentId }) => { + if (agentId === 'chatAgent') { + input; + } console.log('[HOOK] - afterAgentRun', { agentId }); }, onAbort: ({ event, input, agentId, reason }) => { From b1fceb2ca338384da21345ebaa3ddbfb43e761a8 Mon Sep 17 00:00:00 2001 From: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Date: Mon, 6 Oct 2025 23:48:07 +0100 Subject: [PATCH 10/10] cleanup unneeded types after type narrowing --- src/lib/river/server.ts | 4 ++-- src/lib/river/types.ts | 16 +++++----------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/lib/river/server.ts b/src/lib/river/server.ts index ffaf697..13e1ec3 100644 --- a/src/lib/river/server.ts +++ b/src/lib/river/server.ts @@ -4,7 +4,7 @@ import type { CreateAgentRouter, CreateAiSdkRiverAgent, CreateCustomRiverAgent, - HookForSafeCall, + ServerHook, LifecycleHooks, ServerEndpointHandler, ServerSideAgentRunner @@ -151,7 +151,7 @@ const createServerEndpointHandler: ServerEndpointHandler = (router, hooks) => { }; async function callServerHook( - hook: HookForSafeCall | undefined, + hook: ServerHook | undefined, args: T, globalOnError?: (err: unknown) => Promise ) { diff --git a/src/lib/river/types.ts b/src/lib/river/types.ts index d303a7a..6310160 100644 --- a/src/lib/river/types.ts +++ b/src/lib/river/types.ts @@ -81,12 +81,7 @@ type ServerEndpointHandler = ( hooks?: LifecycleHooks ) => { POST: (event: RequestEvent) => Promise }; -type HookWithError = { - try: (args: T) => Promise | void; - catch: (error: unknown, args: T) => Promise | void; -}; - -type HookForSafeCall = +type ServerHook = | ((args: T) => Promise | void) | { try: (args: T) => Promise | void; @@ -129,9 +124,9 @@ type AllOnErrorArgs = { }[keyof T]; type LifecycleHooks = { - beforeAgentRun?: HookForSafeCall>; - afterAgentRun?: HookForSafeCall>; - onAbort?: HookForSafeCall>; + beforeAgentRun?: ServerHook>; + afterAgentRun?: ServerHook>; + onAbort?: ServerHook>; onError?: (ctx: AllOnErrorArgs) => void | Promise; }; @@ -184,6 +179,5 @@ export type { ClientSideCaller, AgentRouter, LifecycleHooks, - HookWithError, - HookForSafeCall + ServerHook };